insert {} around if, for, etc.

This commit is contained in:
Brenton Bostick 2023-04-13 08:21:15 -04:00
parent 8e0ecc88f7
commit 5e69b82759
54 changed files with 1687 additions and 768 deletions

View file

@ -136,8 +136,9 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
if (_rp) { if (_rp) {
for (;;) { for (;;) {
if (!len) if (!len) {
return; return;
}
--len; --len;
_r[_rp++] = *(in++); _r[_rp++] = *(in++);
if (_rp == 16) { if (_rp == 16) {
@ -160,8 +161,9 @@ void AES::GMAC::update(const void *const data, unsigned int len) noexcept
_y[0] = y0; _y[0] = y0;
_y[1] = y1; _y[1] = y1;
for (unsigned int i = 0; i < len; ++i) for (unsigned int i = 0; i < len; ++i) {
_r[i] = in[i]; _r[i] = in[i];
}
_rp = len; // len is always less than 16 here _rp = len; // len is always less than 16 here
} }
@ -187,8 +189,9 @@ void AES::GMAC::finish(uint8_t tag[16]) noexcept
uint64_t y1 = _y[1]; uint64_t y1 = _y[1];
if (_rp) { if (_rp) {
while (_rp < 16) while (_rp < 16) {
_r[_rp++] = 0; _r[_rp++] = 0;
}
y0 ^= Utils::loadMachineEndian< uint64_t >(_r); y0 ^= Utils::loadMachineEndian< uint64_t >(_r);
y1 ^= Utils::loadMachineEndian< uint64_t >(_r + 8); y1 ^= Utils::loadMachineEndian< uint64_t >(_r + 8);
s_gfmul(h0, h1, y0, y1); s_gfmul(h0, h1, y0, y1);
@ -247,8 +250,9 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
_aes.p_encryptSW(reinterpret_cast<const uint8_t *>(_ctr), reinterpret_cast<uint8_t *>(keyStream)); _aes.p_encryptSW(reinterpret_cast<const uint8_t *>(_ctr), reinterpret_cast<uint8_t *>(keyStream));
reinterpret_cast<uint32_t *>(_ctr)[3] = Utils::hton(++ctr); reinterpret_cast<uint32_t *>(_ctr)[3] = Utils::hton(++ctr);
uint8_t *outblk = out + (totalLen - 16); uint8_t *outblk = out + (totalLen - 16);
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i) {
outblk[i] ^= reinterpret_cast<uint8_t *>(keyStream)[i]; outblk[i] ^= reinterpret_cast<uint8_t *>(keyStream)[i];
}
break; break;
} }
} }
@ -442,10 +446,11 @@ void AES::CTR::finish() noexcept
const unsigned int rem = _len & 15U; const unsigned int rem = _len & 15U;
if (rem) { if (rem) {
_aes.encrypt(_ctr, tmp); _aes.encrypt(_ctr, tmp);
for (unsigned int i = 0, j = _len - rem; i < rem; ++i) for (unsigned int i = 0, j = _len - rem; i < rem; ++i) {
_out[j + i] ^= tmp[i]; _out[j + i] ^= tmp[i];
} }
} }
}
// Software AES and AES key expansion --------------------------------------------------------------------------------- // Software AES and AES key expansion ---------------------------------------------------------------------------------
@ -497,8 +502,9 @@ void AES::p_initSW(const uint8_t *key) noexcept
rk[9] = rk[1] ^ rk[8]; rk[9] = rk[1] ^ rk[8];
rk[10] = rk[2] ^ rk[9]; rk[10] = rk[2] ^ rk[9];
rk[11] = rk[3] ^ rk[10]; rk[11] = rk[3] ^ rk[10];
if (++i == 7) if (++i == 7) {
break; break;
}
temp = rk[11]; temp = rk[11];
rk[12] = rk[4] ^ (Te2_r(temp >> 24U) & 0xff000000U) ^ (Te3_r((temp >> 16U) & 0xffU) & 0x00ff0000U) ^ (Te0[(temp >> 8U) & 0xffU] & 0x0000ff00U) ^ (Te1_r((temp) & 0xffU) & 0x000000ffU); rk[12] = rk[4] ^ (Te2_r(temp >> 24U) & 0xff000000U) ^ (Te3_r((temp >> 16U) & 0xffU) & 0x00ff0000U) ^ (Te0[(temp >> 8U) & 0xffU] & 0x0000ff00U) ^ (Te1_r((temp) & 0xffU) & 0x000000ffU);
rk[13] = rk[5] ^ rk[12]; rk[13] = rk[5] ^ rk[12];
@ -511,8 +517,9 @@ void AES::p_initSW(const uint8_t *key) noexcept
p_k.sw.h[0] = Utils::ntoh(p_k.sw.h[0]); p_k.sw.h[0] = Utils::ntoh(p_k.sw.h[0]);
p_k.sw.h[1] = Utils::ntoh(p_k.sw.h[1]); p_k.sw.h[1] = Utils::ntoh(p_k.sw.h[1]);
for (int i = 0; i < 60; ++i) for (int i = 0; i < 60; ++i) {
p_k.sw.dk[i] = p_k.sw.ek[i]; p_k.sw.dk[i] = p_k.sw.ek[i];
}
rk = p_k.sw.dk; rk = p_k.sw.dk;
for (int i = 0, j = 56; i < j; i += 4, j -= 4) { for (int i = 0, j = 56; i < j; i += 4, j -= 4) {

View file

@ -197,8 +197,9 @@ public:
*reinterpret_cast<uint32_t *>(_iv + 8) = *reinterpret_cast<const uint64_t *>(iv + 8); *reinterpret_cast<uint32_t *>(_iv + 8) = *reinterpret_cast<const uint64_t *>(iv + 8);
*reinterpret_cast<uint32_t *>(_iv + 12) = 0x01000000; // 0x00000001 in big-endian byte order *reinterpret_cast<uint32_t *>(_iv + 12) = 0x01000000; // 0x00000001 in big-endian byte order
#else #else
for(int i=0;i<12;++i) for(int i=0;i<12;++i) {
_iv[i] = iv[i]; _iv[i] = iv[i];
}
_iv[12] = 0; _iv[12] = 0;
_iv[13] = 0; _iv[13] = 0;
_iv[14] = 0; _iv[14] = 0;
@ -373,9 +374,10 @@ public:
// End of AAD is padded to a multiple of 16 bytes to ensure unique encoding. // End of AAD is padded to a multiple of 16 bytes to ensure unique encoding.
len &= 0xfU; len &= 0xfU;
if (len != 0) if (len != 0) {
_gmac.update(Utils::ZERO256, 16 - len); _gmac.update(Utils::ZERO256, 16 - len);
} }
}
/** /**
* First pass plaintext input function * First pass plaintext input function
@ -495,9 +497,10 @@ public:
{ {
_gmac.update(aad, len); _gmac.update(aad, len);
len &= 0xfU; len &= 0xfU;
if (len != 0) if (len != 0) {
_gmac.update(Utils::ZERO256, 16 - len); _gmac.update(Utils::ZERO256, 16 - len);
} }
}
/** /**
* Feed ciphertext into the decryptor * Feed ciphertext into the decryptor

View file

@ -228,8 +228,9 @@ void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
// Handle anything left over from a previous run that wasn't a multiple of 16 bytes. // Handle anything left over from a previous run that wasn't a multiple of 16 bytes.
if (_rp) { if (_rp) {
for (;;) { for (;;) {
if (!len) if (!len) {
return; return;
}
--len; --len;
_r[_rp++] = *(in++); _r[_rp++] = *(in++);
if (_rp == 16) { if (_rp == 16) {
@ -281,8 +282,9 @@ void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
_mm_storeu_si128(reinterpret_cast<__m128i *>(_y), y); _mm_storeu_si128(reinterpret_cast<__m128i *>(_y), y);
// Any overflow is cached for a later run or finish(). // Any overflow is cached for a later run or finish().
for (unsigned int i = 0; i < len; ++i) for (unsigned int i = 0; i < len; ++i) {
_r[i] = in[i]; _r[i] = in[i];
}
_rp = len; // len is always less than 16 here _rp = len; // len is always less than 16 here
} }
@ -295,8 +297,9 @@ void AES::GMAC::p_aesNIFinish(uint8_t tag[16]) noexcept
// Handle any remaining bytes, padding the last block with zeroes. // Handle any remaining bytes, padding the last block with zeroes.
if (_rp) { if (_rp) {
while (_rp < 16) while (_rp < 16) {
_r[_rp++] = 0; _r[_rp++] = 0;
}
y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i *>(_r)))); y = p_gmacPCLMUL128(_aes.p_k.ni.h[0], _mm_xor_si128(y, _mm_loadu_si128(reinterpret_cast<__m128i *>(_r))));
} }
@ -552,8 +555,9 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
// Any remaining input is placed in _out. This will be picked up and crypted // Any remaining input is placed in _out. This will be picked up and crypted
// on subsequent calls to crypt() or finish() as it'll mean _len will not be // on subsequent calls to crypt() or finish() as it'll mean _len will not be
// an even multiple of 16. // an even multiple of 16.
for (unsigned int i = 0; i < len; ++i) for (unsigned int i = 0; i < len; ++i) {
out[i] = in[i]; out[i] = in[i];
}
_ctr[1] = Utils::hton(c1); _ctr[1] = Utils::hton(c1);
} }

View file

@ -56,8 +56,9 @@ void AES::GMAC::p_armUpdate(const uint8_t *in, unsigned int len) noexcept
if (_rp) { if (_rp) {
for(;;) { for(;;) {
if (!len) if (!len) {
return; return;
}
--len; --len;
_r[_rp++] = *(in++); _r[_rp++] = *(in++);
if (_rp == 16) { if (_rp == 16) {
@ -75,8 +76,9 @@ void AES::GMAC::p_armUpdate(const uint8_t *in, unsigned int len) noexcept
vst1q_u8(reinterpret_cast<uint8_t *>(_y), y); vst1q_u8(reinterpret_cast<uint8_t *>(_y), y);
for (unsigned int i = 0; i < len; ++i) for (unsigned int i = 0; i < len; ++i) {
_r[i] = in[i]; _r[i] = in[i];
}
_rp = len; // len is always less than 16 here _rp = len; // len is always less than 16 here
} }
@ -87,8 +89,9 @@ void AES::GMAC::p_armFinish(uint8_t tag[16]) noexcept
const uint8x16_t h = _aes.p_k.neon.h; const uint8x16_t h = _aes.p_k.neon.h;
if (_rp) { if (_rp) {
while (_rp < 16) while (_rp < 16) {
_r[_rp++] = 0; _r[_rp++] = 0;
}
y = s_clmul_armneon_crypto(h, y, _r); y = s_clmul_armneon_crypto(h, y, _r);
} }
@ -255,8 +258,9 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
in += 64; in += 64;
dd = (uint8x16_t)vaddq_u32((uint32x4_t)dd, four); dd = (uint8x16_t)vaddq_u32((uint32x4_t)dd, four);
if (unlikely(len < 64)) if (unlikely(len < 64)) {
break; break;
}
dd1 = (uint8x16_t)vaddq_u32((uint32x4_t)dd1, four); dd1 = (uint8x16_t)vaddq_u32((uint32x4_t)dd1, four);
dd2 = (uint8x16_t)vaddq_u32((uint32x4_t)dd2, four); dd2 = (uint8x16_t)vaddq_u32((uint32x4_t)dd2, four);
dd3 = (uint8x16_t)vaddq_u32((uint32x4_t)dd3, four); dd3 = (uint8x16_t)vaddq_u32((uint32x4_t)dd3, four);
@ -290,8 +294,9 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
// Any remaining input is placed in _out. This will be picked up and crypted // Any remaining input is placed in _out. This will be picked up and crypted
// on subsequent calls to crypt() or finish() as it'll mean _len will not be // on subsequent calls to crypt() or finish() as it'll mean _len will not be
// an even multiple of 16. // an even multiple of 16.
for (unsigned int i = 0; i < len; ++i) for (unsigned int i = 0; i < len; ++i) {
out[i] = in[i]; out[i] = in[i];
}
vst1q_u8(reinterpret_cast<uint8_t *>(_ctr), vrev32q_u8(dd)); vst1q_u8(reinterpret_cast<uint8_t *>(_ctr), vrev32q_u8(dd));
} }
@ -327,12 +332,14 @@ void AES::p_init_armneon_crypto(const uint8_t *key) noexcept
w[i] = w[i - ZT_INIT_ARMNEON_CRYPTO_NK] ^ t; w[i] = w[i - ZT_INIT_ARMNEON_CRYPTO_NK] ^ t;
} }
for (unsigned int i=0;i<(ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));++i) for (unsigned int i=0;i<(ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));++i) {
w[i] = Utils::hton(w[i]); w[i] = Utils::hton(w[i]);
}
p_k.neon.dk[0] = p_k.neon.ek[14]; p_k.neon.dk[0] = p_k.neon.ek[14];
for (int i=1;i<14;++i) for (int i=1;i<14;++i) {
p_k.neon.dk[i] = vaesimcq_u8(p_k.neon.ek[14 - i]); p_k.neon.dk[i] = vaesimcq_u8(p_k.neon.ek[14 - i]);
}
p_k.neon.dk[14] = p_k.neon.ek[0]; p_k.neon.dk[14] = p_k.neon.ek[0];
p_encrypt_armneon_crypto(Utils::ZERO256, h); p_encrypt_armneon_crypto(Utils::ZERO256, h);

View file

@ -71,8 +71,9 @@ public:
*/ */
inline void copyTo(void *const bits,const unsigned int len) const inline void copyTo(void *const bits,const unsigned int len) const
{ {
if (len < ZT_ADDRESS_LENGTH) if (len < ZT_ADDRESS_LENGTH) {
return; return;
}
unsigned char *b = (unsigned char *)bits; unsigned char *b = (unsigned char *)bits;
*(b++) = (unsigned char)((_a >> 32) & 0xff); *(b++) = (unsigned char)((_a >> 32) & 0xff);
*(b++) = (unsigned char)((_a >> 24) & 0xff); *(b++) = (unsigned char)((_a >> 24) & 0xff);

View file

@ -81,8 +81,9 @@ public:
Buffer(unsigned int l) Buffer(unsigned int l)
{ {
if (l > C) if (l > C) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
_l = l; _l = l;
} }
@ -100,8 +101,9 @@ public:
template<unsigned int C2> template<unsigned int C2>
inline Buffer &operator=(const Buffer<C2> &b) inline Buffer &operator=(const Buffer<C2> &b)
{ {
if (unlikely(b._l > C)) if (unlikely(b._l > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
if (C2 == C) { if (C2 == C) {
memcpy(this,&b,sizeof(Buffer<C>)); memcpy(this,&b,sizeof(Buffer<C>));
} else { } else {
@ -112,23 +114,26 @@ public:
inline void copyFrom(const void *b,unsigned int l) inline void copyFrom(const void *b,unsigned int l)
{ {
if (unlikely(l > C)) if (unlikely(l > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
memcpy(_b,b,l); memcpy(_b,b,l);
_l = l; _l = l;
} }
unsigned char operator[](const unsigned int i) const unsigned char operator[](const unsigned int i) const
{ {
if (unlikely(i >= _l)) if (unlikely(i >= _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
return (unsigned char)_b[i]; return (unsigned char)_b[i];
} }
unsigned char &operator[](const unsigned int i) unsigned char &operator[](const unsigned int i)
{ {
if (unlikely(i >= _l)) if (unlikely(i >= _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
return ((unsigned char *)_b)[i]; return ((unsigned char *)_b)[i];
} }
@ -147,14 +152,16 @@ public:
*/ */
unsigned char *field(unsigned int i,unsigned int l) unsigned char *field(unsigned int i,unsigned int l)
{ {
if (unlikely((i + l) > _l)) if (unlikely((i + l) > _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
return (unsigned char *)(_b + i); return (unsigned char *)(_b + i);
} }
const unsigned char *field(unsigned int i,unsigned int l) const const unsigned char *field(unsigned int i,unsigned int l) const
{ {
if (unlikely((i + l) > _l)) if (unlikely((i + l) > _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
return (const unsigned char *)(_b + i); return (const unsigned char *)(_b + i);
} }
@ -168,12 +175,14 @@ public:
template<typename T> template<typename T>
inline void setAt(unsigned int i,const T v) inline void setAt(unsigned int i,const T v)
{ {
if (unlikely((i + sizeof(T)) > _l)) if (unlikely((i + sizeof(T)) > _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
uint8_t *p = reinterpret_cast<uint8_t *>(_b + i); uint8_t *p = reinterpret_cast<uint8_t *>(_b + i);
for(unsigned int x=1;x<=sizeof(T);++x) for(unsigned int x=1;x<=sizeof(T);++x) {
*(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x))); *(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x)));
}
#else #else
T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + i); T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + i);
*p = Utils::hton(v); *p = Utils::hton(v);
@ -190,8 +199,9 @@ public:
template<typename T> template<typename T>
inline T at(unsigned int i) const inline T at(unsigned int i) const
{ {
if (unlikely((i + sizeof(T)) > _l)) if (unlikely((i + sizeof(T)) > _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
T v = 0; T v = 0;
const uint8_t *p = reinterpret_cast<const uint8_t *>(_b + i); const uint8_t *p = reinterpret_cast<const uint8_t *>(_b + i);
@ -216,12 +226,14 @@ public:
template<typename T> template<typename T>
inline void append(const T v) inline void append(const T v)
{ {
if (unlikely((_l + sizeof(T)) > C)) if (unlikely((_l + sizeof(T)) > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l); uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l);
for(unsigned int x=1;x<=sizeof(T);++x) for(unsigned int x=1;x<=sizeof(T);++x) {
*(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x))); *(p++) = (uint8_t)(v >> (8 * (sizeof(T) - x)));
}
#else #else
T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + _l); T *const ZT_VAR_MAY_ALIAS p = reinterpret_cast<T *>(_b + _l);
*p = Utils::hton(v); *p = Utils::hton(v);
@ -238,11 +250,13 @@ public:
*/ */
inline void append(unsigned char c,unsigned int n) inline void append(unsigned char c,unsigned int n)
{ {
if (unlikely((_l + n) > C)) if (unlikely((_l + n) > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
for(unsigned int i=0;i<n;++i) }
for(unsigned int i=0;i<n;++i) {
_b[_l++] = (char)c; _b[_l++] = (char)c;
} }
}
/** /**
* Append secure random bytes * Append secure random bytes
@ -251,8 +265,9 @@ public:
*/ */
inline void appendRandom(unsigned int n) inline void appendRandom(unsigned int n)
{ {
if (unlikely((_l + n) > C)) if (unlikely((_l + n) > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
Utils::getSecureRandom(_b + _l,n); Utils::getSecureRandom(_b + _l,n);
_l += n; _l += n;
} }
@ -266,8 +281,9 @@ public:
*/ */
inline void append(const void *b,unsigned int l) inline void append(const void *b,unsigned int l)
{ {
if (unlikely((_l + l) > C)) if (unlikely((_l + l) > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
memcpy(_b + _l,b,l); memcpy(_b + _l,b,l);
_l += l; _l += l;
} }
@ -281,12 +297,14 @@ public:
inline void appendCString(const char *s) inline void appendCString(const char *s)
{ {
for(;;) { for(;;) {
if (unlikely(_l >= C)) if (unlikely(_l >= C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
if (!(_b[_l++] = *(s++))) }
if (!(_b[_l++] = *(s++))) {
break; break;
} }
} }
}
/** /**
* Append a buffer * Append a buffer
@ -313,8 +331,9 @@ public:
*/ */
inline char *appendField(unsigned int l) inline char *appendField(unsigned int l)
{ {
if (unlikely((_l + l) > C)) if (unlikely((_l + l) > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
char *r = _b + _l; char *r = _b + _l;
_l += l; _l += l;
return r; return r;
@ -330,8 +349,9 @@ public:
*/ */
inline void addSize(unsigned int i) inline void addSize(unsigned int i)
{ {
if (unlikely((i + _l) > C)) if (unlikely((i + _l) > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
_l += i; _l += i;
} }
@ -345,8 +365,9 @@ public:
*/ */
inline void setSize(const unsigned int i) inline void setSize(const unsigned int i)
{ {
if (unlikely(i > C)) if (unlikely(i > C)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
_l = i; _l = i;
} }
@ -358,10 +379,12 @@ public:
*/ */
inline void behead(const unsigned int at) inline void behead(const unsigned int at)
{ {
if (!at) if (!at) {
return; return;
if (unlikely(at > _l)) }
if (unlikely(at > _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
::memmove(_b,_b + at,_l -= at); ::memmove(_b,_b + at,_l -= at);
} }
@ -375,8 +398,9 @@ public:
inline void erase(const unsigned int at,const unsigned int length) inline void erase(const unsigned int at,const unsigned int length)
{ {
const unsigned int endr = at + length; const unsigned int endr = at + length;
if (unlikely(endr > _l)) if (unlikely(endr > _l)) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
::memmove(_b + at,_b + endr,_l - endr); ::memmove(_b + at,_b + endr,_l - endr);
_l -= length; _l -= length;
} }

View file

@ -731,7 +731,9 @@ static void crypto_scalarmult(u8 *mypublic, const u8 *secret, const u8 *basepoin
uint8_t e[32]; uint8_t e[32];
int i; int i;
for (i = 0; i < 32; ++i) e[i] = secret[i]; for (i = 0; i < 32; ++i) {
e[i] = secret[i];
}
e[0] &= 248; e[0] &= 248;
e[31] &= 127; e[31] &= 127;
e[31] |= 64; e[31] |= 64;
@ -873,22 +875,26 @@ static inline void fe25519_freeze(fe25519 *r)
{ {
int i; int i;
crypto_uint32 m = equal(r->v[31],127); crypto_uint32 m = equal(r->v[31],127);
for(i=30;i>0;i--) for(i=30;i>0;i--) {
m &= equal(r->v[i],255); m &= equal(r->v[i],255);
}
m &= ge(r->v[0],237); m &= ge(r->v[0],237);
m = -m; m = -m;
r->v[31] -= m&127; r->v[31] -= m&127;
for(i=30;i>0;i--) for(i=30;i>0;i--) {
r->v[i] -= m&255; r->v[i] -= m&255;
}
r->v[0] -= m&237; r->v[0] -= m&237;
} }
static inline void fe25519_unpack(fe25519 *r, const unsigned char x[32]) static inline void fe25519_unpack(fe25519 *r, const unsigned char x[32])
{ {
int i; int i;
for(i=0;i<32;i++) r->v[i] = x[i]; for(i=0;i<32;i++) {
r->v[i] = x[i];
}
r->v[31] &= 127; r->v[31] &= 127;
} }
@ -898,9 +904,10 @@ static inline void fe25519_pack(unsigned char r[32], const fe25519 *x)
int i; int i;
fe25519 y = *x; fe25519 y = *x;
fe25519_freeze(&y); fe25519_freeze(&y);
for(i=0;i<32;i++) for(i=0;i<32;i++) {
r[i] = y.v[i]; r[i] = y.v[i];
} }
}
static inline int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) static inline int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
{ {
@ -909,8 +916,11 @@ static inline int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
fe25519 t2 = *y; fe25519 t2 = *y;
fe25519_freeze(&t1); fe25519_freeze(&t1);
fe25519_freeze(&t2); fe25519_freeze(&t2);
for(i=0;i<32;i++) for(i=0;i<32;i++) {
if(t1.v[i] != t2.v[i]) return 0; if (t1.v[i] != t2.v[i]) {
return 0;
}
}
return 1; return 1;
} }
@ -919,7 +929,9 @@ static inline void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
int i; int i;
crypto_uint32 mask = b; crypto_uint32 mask = b;
mask = -mask; mask = -mask;
for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]); for(i=0;i<32;i++) {
r->v[i] ^= mask & (x->v[i] ^ r->v[i]);
}
} }
static inline unsigned char fe25519_getparity(const fe25519 *x) static inline unsigned char fe25519_getparity(const fe25519 *x)
@ -933,20 +945,26 @@ static inline void fe25519_setone(fe25519 *r)
{ {
int i; int i;
r->v[0] = 1; r->v[0] = 1;
for(i=1;i<32;i++) r->v[i]=0; for(i=1;i<32;i++) {
r->v[i]=0;
}
} }
static inline void fe25519_setzero(fe25519 *r) static inline void fe25519_setzero(fe25519 *r)
{ {
int i; int i;
for(i=0;i<32;i++) r->v[i]=0; for(i=0;i<32;i++) {
r->v[i]=0;
}
} }
static inline void fe25519_neg(fe25519 *r, const fe25519 *x) static inline void fe25519_neg(fe25519 *r, const fe25519 *x)
{ {
fe25519 t; fe25519 t;
int i; int i;
for(i=0;i<32;i++) t.v[i]=x->v[i]; for(i=0;i<32;i++) {
t.v[i]=x->v[i];
}
fe25519_setzero(r); fe25519_setzero(r);
fe25519_sub(r, r, &t); fe25519_sub(r, r, &t);
} }
@ -954,7 +972,9 @@ static inline void fe25519_neg(fe25519 *r, const fe25519 *x)
static inline void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) static inline void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
{ {
int i; int i;
for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; for(i=0;i<32;i++) {
r->v[i] = x->v[i] + y->v[i];
}
reduce_add_sub(r); reduce_add_sub(r);
} }
@ -964,8 +984,12 @@ static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
crypto_uint32 t[32]; crypto_uint32 t[32];
t[0] = x->v[0] + 0x1da; t[0] = x->v[0] + 0x1da;
t[31] = x->v[31] + 0xfe; t[31] = x->v[31] + 0xfe;
for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe; for(i=1;i<31;i++) {
for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i]; t[i] = x->v[i] + 0x1fe;
}
for(i=0;i<32;i++) {
r->v[i] = t[i] - y->v[i];
}
reduce_add_sub(r); reduce_add_sub(r);
} }
@ -973,14 +997,19 @@ static inline void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
{ {
int i,j; int i,j;
crypto_uint32 t[63]; crypto_uint32 t[63];
for(i=0;i<63;i++)t[i] = 0; for(i=0;i<63;i++) {
t[i] = 0;
}
for(i=0;i<32;i++) for(i=0;i<32;i++) {
for(j=0;j<32;j++) for(j=0;j<32;j++) {
t[i+j] += x->v[i] * y->v[j]; t[i+j] += x->v[i] * y->v[j];
}
}
for(i=32;i<63;i++) for(i=32;i<63;i++) {
r->v[i-32] = t[i-32] + times38(t[i]); r->v[i-32] = t[i-32] + times38(t[i]);
}
r->v[31] = t[31]; /* result now in r[0]...r[31] */ r->v[31] = t[31]; /* result now in r[0]...r[31] */
reduce_mul(r); reduce_mul(r);
@ -1139,9 +1168,10 @@ static inline void reduce_add_sub(sc25519 *r)
pb = b; pb = b;
} }
mask = b - 1; mask = b - 1;
for(i=0;i<32;i++) for(i=0;i<32;i++) {
r->v[i] ^= mask & (r->v[i] ^ t[i]); r->v[i] ^= mask & (r->v[i] ^ t[i]);
} }
}
/* Reduce coefficients of x before calling barrett_reduce */ /* Reduce coefficients of x before calling barrett_reduce */
static inline void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) static inline void barrett_reduce(sc25519 *r, const crypto_uint32 x[64])
@ -1156,21 +1186,35 @@ static inline void barrett_reduce(sc25519 *r, const crypto_uint32 x[64])
crypto_uint32 pb = 0; crypto_uint32 pb = 0;
crypto_uint32 b; crypto_uint32 b;
for (i = 0;i < 66;++i) q2[i] = 0; for (i = 0;i < 66;++i) {
for (i = 0;i < 33;++i) r2[i] = 0; q2[i] = 0;
}
for (i = 0;i < 33;++i) {
r2[i] = 0;
}
for(i=0;i<33;i++) for(i=0;i<33;i++) {
for(j=0;j<33;j++) for(j=0;j<33;j++) {
if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; if(i+j >= 31) {
q2[i+j] += mu[i]*x[j+31];
}
}
}
carry = q2[31] >> 8; carry = q2[31] >> 8;
q2[32] += carry; q2[32] += carry;
carry = q2[32] >> 8; carry = q2[32] >> 8;
q2[33] += carry; q2[33] += carry;
for(i=0;i<33;i++)r1[i] = x[i]; for(i=0;i<33;i++) {
for(i=0;i<32;i++) r1[i] = x[i];
for(j=0;j<33;j++) }
if(i+j < 33) r2[i+j] += m[i]*q3[j]; for(i=0;i<32;i++) {
for(j=0;j<33;j++) {
if(i+j < 33) {
r2[i+j] += m[i]*q3[j];
}
}
}
for(i=0;i<32;i++) { for(i=0;i<32;i++) {
carry = r2[i] >> 8; carry = r2[i] >> 8;
@ -1197,8 +1241,12 @@ static inline void sc25519_from32bytes(sc25519 *r, const unsigned char x[32])
{ {
int i; int i;
crypto_uint32 t[64]; crypto_uint32 t[64];
for(i=0;i<32;i++) t[i] = x[i]; for(i=0;i<32;i++) {
for(i=32;i<64;++i) t[i] = 0; t[i] = x[i];
}
for(i=32;i<64;++i) {
t[i] = 0;
}
barrett_reduce(r, t); barrett_reduce(r, t);
} }
@ -1206,20 +1254,26 @@ static inline void sc25519_from64bytes(sc25519 *r, const unsigned char x[64])
{ {
int i; int i;
crypto_uint32 t[64]; crypto_uint32 t[64];
for(i=0;i<64;i++) t[i] = x[i]; for(i=0;i<64;i++) {
t[i] = x[i];
}
barrett_reduce(r, t); barrett_reduce(r, t);
} }
static inline void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) static inline void sc25519_to32bytes(unsigned char r[32], const sc25519 *x)
{ {
int i; int i;
for(i=0;i<32;i++) r[i] = x->v[i]; for(i=0;i<32;i++) {
r[i] = x->v[i];
}
} }
static inline void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) static inline void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y)
{ {
int i, carry; int i, carry;
for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; for(i=0;i<32;i++) {
r->v[i] = x->v[i] + y->v[i];
}
for(i=0;i<31;i++) { for(i=0;i<31;i++) {
carry = r->v[i] >> 8; carry = r->v[i] >> 8;
r->v[i+1] += carry; r->v[i+1] += carry;
@ -1232,11 +1286,15 @@ static inline void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y)
{ {
int i,j,carry; int i,j,carry;
crypto_uint32 t[64]; crypto_uint32 t[64];
for(i=0;i<64;i++)t[i] = 0; for(i=0;i<64;i++) {
t[i] = 0;
}
for(i=0;i<32;i++) for(i=0;i<32;i++) {
for(j=0;j<32;j++) for(j=0;j<32;j++) {
t[i+j] += x->v[i] * y->v[j]; t[i+j] += x->v[i] * y->v[j];
}
}
for(i=0;i<63;i++) { for(i=0;i<63;i++) {
carry = t[i] >> 8; carry = t[i] >> 8;
@ -2329,18 +2387,21 @@ static inline int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p
/* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */ /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */
fe25519_square(&chk, &r->x); fe25519_square(&chk, &r->x);
fe25519_mul(&chk, &chk, &den); fe25519_mul(&chk, &chk, &den);
if (!fe25519_iseq_vartime(&chk, &num)) if (!fe25519_iseq_vartime(&chk, &num)) {
fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1); fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1);
}
/* 4. Now we have one of the two square roots, except if input was not a square */ /* 4. Now we have one of the two square roots, except if input was not a square */
fe25519_square(&chk, &r->x); fe25519_square(&chk, &r->x);
fe25519_mul(&chk, &chk, &den); fe25519_mul(&chk, &chk, &den);
if (!fe25519_iseq_vartime(&chk, &num)) if (!fe25519_iseq_vartime(&chk, &num)) {
return -1; return -1;
}
/* 5. Choose the desired square root according to parity: */ /* 5. Choose the desired square root according to parity: */
if(fe25519_getparity(&r->x) != (1-par)) if(fe25519_getparity(&r->x) != (1-par)) {
fe25519_neg(&r->x, &r->x); fe25519_neg(&r->x, &r->x);
}
fe25519_mul(&r->t, &r->x, &r->y); fe25519_mul(&r->t, &r->x, &r->y);
return 0; return 0;
@ -2395,8 +2456,11 @@ static inline void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge2551
p1p1_to_p3(r, &tp1p1); p1p1_to_p3(r, &tp1p1);
add_p1p1(&tp1p1, r, &pre[b[i]]); add_p1p1(&tp1p1, r, &pre[b[i]]);
} }
if(i != 0) p1p1_to_p2((ge25519_p2 *)r, &tp1p1); if (i != 0) {
else p1p1_to_p3(r, &tp1p1); p1p1_to_p2((ge25519_p2 *)r, &tp1p1);
} else {
p1p1_to_p3(r, &tp1p1);
}
} }
} }
@ -2420,9 +2484,15 @@ static inline void get_hram(unsigned char *hram, const unsigned char *sm, const
{ {
unsigned long long i; unsigned long long i;
for (i = 0;i < 32;++i) playground[i] = sm[i]; for (i = 0;i < 32;++i) {
for (i = 32;i < 64;++i) playground[i] = pk[i-32]; playground[i] = sm[i];
for (i = 64;i < smlen;++i) playground[i] = sm[i]; }
for (i = 32;i < 64;++i) {
playground[i] = pk[i-32];
}
for (i = 64;i < smlen;++i) {
playground[i] = sm[i];
}
ZeroTier::SHA512(hram,playground,(unsigned int)smlen); ZeroTier::SHA512(hram,playground,(unsigned int)smlen);
} }
@ -2476,10 +2546,12 @@ void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPubli
extsk[31] &= 127; extsk[31] &= 127;
extsk[31] |= 64; extsk[31] |= 64;
for(unsigned int i=0;i<32;i++) for(unsigned int i=0;i<32;i++) {
sig[32 + i] = extsk[32 + i]; sig[32 + i] = extsk[32 + i];
for(unsigned int i=0;i<32;i++) }
for(unsigned int i=0;i<32;i++) {
sig[64 + i] = digest[i]; sig[64 + i] = digest[i];
}
SHA512(hmg,sig + 32,64); SHA512(hmg,sig + 32,64);
@ -2489,8 +2561,9 @@ void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPubli
ge25519_pack(r, &ger); ge25519_pack(r, &ger);
/* Computation of s */ /* Computation of s */
for(unsigned int i=0;i<32;i++) for(unsigned int i=0;i<32;i++) {
sig[i] = r[i]; sig[i] = r[i];
}
get_hram(hram,sig,myPublic.data + 32,sig,96); get_hram(hram,sig,myPublic.data + 32,sig,96);
@ -2501,8 +2574,9 @@ void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPubli
sc25519_add(&scs, &scs, &sck); sc25519_add(&scs, &scs, &sck);
sc25519_to32bytes(s,&scs); /* cat s */ sc25519_to32bytes(s,&scs); /* cat s */
for(unsigned int i=0;i<32;i++) for(unsigned int i=0;i<32;i++) {
sig[32 + i] = s[i]; sig[32 + i] = s[i];
}
#endif #endif
} }
@ -2511,8 +2585,9 @@ bool C25519::verify(const C25519::Public &their,const void *msg,unsigned int len
const unsigned char *const sig = (const unsigned char *)signature; const unsigned char *const sig = (const unsigned char *)signature;
unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg) unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg)
SHA512(digest,msg,len); SHA512(digest,msg,len);
if (!Utils::secureEq(sig + 64,digest,32)) if (!Utils::secureEq(sig + 64,digest,32)) {
return false; return false;
}
unsigned char t2[32]; unsigned char t2[32];
ge25519 get1, get2; ge25519 get1, get2;
@ -2520,8 +2595,9 @@ bool C25519::verify(const C25519::Public &their,const void *msg,unsigned int len
unsigned char hram[crypto_hash_sha512_BYTES]; unsigned char hram[crypto_hash_sha512_BYTES];
unsigned char m[96]; unsigned char m[96];
if (ge25519_unpackneg_vartime(&get1,their.data + 32)) if (ge25519_unpackneg_vartime(&get1,their.data + 32)) {
return false; return false;
}
get_hram(hram,sig,their.data + 32,m,96); get_hram(hram,sig,their.data + 32,m,96);

View file

@ -25,27 +25,31 @@ int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
{ {
try { try {
// There must be at least one entry, and sanity check for bad chain max length // There must be at least one entry, and sanity check for bad chain max length
if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
return -1; return -1;
}
// Validate all entries in chain of custody // Validate all entries in chain of custody
Buffer<(sizeof(Capability) * 2)> tmp; Buffer<(sizeof(Capability) * 2)> tmp;
this->serialize(tmp,true); this->serialize(tmp,true);
for(unsigned int c=0;c<_maxCustodyChainLength;++c) { for(unsigned int c=0;c<_maxCustodyChainLength;++c) {
if (c == 0) { if (c == 0) {
if ((!_custody[c].to)||(!_custody[c].from)||(_custody[c].from != Network::controllerFor(_nwid))) if ((!_custody[c].to)||(!_custody[c].from)||(_custody[c].from != Network::controllerFor(_nwid))) {
return -1; // the first entry must be present and from the network's controller return -1; // the first entry must be present and from the network's controller
}
} else { } else {
if (!_custody[c].to) if (!_custody[c].to) {
return 0; // all previous entries were valid, so we are valid return 0; // all previous entries were valid, so we are valid
else if ((!_custody[c].from)||(_custody[c].from != _custody[c-1].to)) } else if ((!_custody[c].from)||(_custody[c].from != _custody[c-1].to)) {
return -1; // otherwise if we have another entry it must be from the previous holder in the chain return -1; // otherwise if we have another entry it must be from the previous holder in the chain
} }
}
const Identity id(RR->topology->getIdentity(tPtr,_custody[c].from)); const Identity id(RR->topology->getIdentity(tPtr,_custody[c].from));
if (id) { if (id) {
if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature)) if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature)) {
return -1; return -1;
}
} else { } else {
RR->sw->requestWhois(tPtr,RR->node->now(),_custody[c].from); RR->sw->requestWhois(tPtr,RR->node->now(),_custody[c].from);
return 1; return 1;

View file

@ -85,9 +85,10 @@ public:
_maxCustodyChainLength((mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1), _maxCustodyChainLength((mccl > 0) ? ((mccl < ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) ? mccl : (unsigned int)ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH) : 1),
_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES) _ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES)
{ {
if (_ruleCount > 0) if (_ruleCount > 0) {
memcpy(_rules,rules,sizeof(ZT_VirtualNetworkRule) * _ruleCount); memcpy(_rules,rules,sizeof(ZT_VirtualNetworkRule) * _ruleCount);
} }
}
/** /**
* @return Rules -- see ruleCount() for size of array * @return Rules -- see ruleCount() for size of array
@ -121,9 +122,11 @@ public:
{ {
Address i2; Address i2;
for(unsigned int i=0;i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH;++i) { for(unsigned int i=0;i<ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH;++i) {
if (!_custody[i].to) if (!_custody[i].to) {
return i2; return i2;
else i2 = _custody[i].to; } else {
i2 = _custody[i].to;
}
} }
return i2; return i2;
} }
@ -380,7 +383,9 @@ public:
template<unsigned int C> template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const inline void serialize(Buffer<C> &b,const bool forSign = false) const
{ {
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
// These are the same between Tag and Capability // These are the same between Tag and Capability
b.append(_nwid); b.append(_nwid);
@ -409,7 +414,9 @@ public:
// This is the size of any additional fields, currently 0. // This is the size of any additional fields, currently 0.
b.append((uint16_t)0); b.append((uint16_t)0);
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
} }
template<unsigned int C> template<unsigned int C>
@ -428,27 +435,32 @@ public:
const unsigned int rc = b.template at<uint16_t>(p); const unsigned int rc = b.template at<uint16_t>(p);
p += 2; p += 2;
if (rc > ZT_MAX_CAPABILITY_RULES) if (rc > ZT_MAX_CAPABILITY_RULES) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
deserializeRules(b,p,_rules,_ruleCount,rc); deserializeRules(b,p,_rules,_ruleCount,rc);
_maxCustodyChainLength = (unsigned int)b[p++]; _maxCustodyChainLength = (unsigned int)b[p++];
if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) if ((_maxCustodyChainLength < 1)||(_maxCustodyChainLength > ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
for(unsigned int i=0;;++i) { for(unsigned int i=0;;++i) {
const Address to(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); const Address to(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
p += ZT_ADDRESS_LENGTH; p += ZT_ADDRESS_LENGTH;
if (!to) if (!to) {
break; break;
if ((i >= _maxCustodyChainLength)||(i >= ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) }
if ((i >= _maxCustodyChainLength)||(i >= ZT_MAX_CAPABILITY_CUSTODY_CHAIN_LENGTH)) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
_custody[i].to = to; _custody[i].to = to;
_custody[i].from.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); _custody[i].from.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
p += ZT_ADDRESS_LENGTH; p += ZT_ADDRESS_LENGTH;
if (b[p++] == 1) { if (b[p++] == 1) {
if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
}
p += 2; p += 2;
memcpy(_custody[i].signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); memcpy(_custody[i].signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
p += ZT_C25519_SIGNATURE_LEN; p += ZT_C25519_SIGNATURE_LEN;
@ -458,8 +470,9 @@ public:
} }
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
if (p > b.size()) if (p > b.size()) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
return (p - startAt); return (p - startAt);
} }

View file

@ -48,26 +48,31 @@ CertificateOfMembership::CertificateOfMembership(uint64_t timestamp,uint64_t tim
bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other, const Identity &otherIdentity) const bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other, const Identity &otherIdentity) const
{ {
if ((_qualifierCount == 0)||(other._qualifierCount == 0)) if ((_qualifierCount == 0)||(other._qualifierCount == 0)) {
return false; return false;
}
std::map< uint64_t, uint64_t > otherFields; std::map< uint64_t, uint64_t > otherFields;
for(unsigned int i=0;i<other._qualifierCount;++i) for(unsigned int i=0;i<other._qualifierCount;++i) {
otherFields[other._qualifiers[i].id] = other._qualifiers[i].value; otherFields[other._qualifiers[i].id] = other._qualifiers[i].value;
}
bool fullIdentityVerification = false; bool fullIdentityVerification = false;
for(unsigned int i=0;i<_qualifierCount;++i) { for(unsigned int i=0;i<_qualifierCount;++i) {
const uint64_t qid = _qualifiers[i].id; const uint64_t qid = _qualifiers[i].id;
if ((qid >= 3)&&(qid <= 6)) if ((qid >= 3)&&(qid <= 6)) {
fullIdentityVerification = true; fullIdentityVerification = true;
}
std::map< uint64_t, uint64_t >::iterator otherQ(otherFields.find(qid)); std::map< uint64_t, uint64_t >::iterator otherQ(otherFields.find(qid));
if (otherQ == otherFields.end()) if (otherQ == otherFields.end()) {
return false; return false;
}
const uint64_t a = _qualifiers[i].value; const uint64_t a = _qualifiers[i].value;
const uint64_t b = otherQ->second; const uint64_t b = otherQ->second;
if (((a >= b) ? (a - b) : (b - a)) > _qualifiers[i].maxDelta) if (((a >= b) ? (a - b) : (b - a)) > _qualifiers[i].maxDelta) {
return false; return false;
} }
}
// If this COM has a full hash of its identity, assume the other must have this as well. // If this COM has a full hash of its identity, assume the other must have this as well.
// Otherwise we are on a controller that does not incorporate these. // Otherwise we are on a controller that does not incorporate these.
@ -76,12 +81,14 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other, c
otherIdentity.publicKeyHash(idHash); otherIdentity.publicKeyHash(idHash);
for(unsigned long i=0;i<4;++i) { for(unsigned long i=0;i<4;++i) {
std::map< uint64_t, uint64_t >::iterator otherQ(otherFields.find((uint64_t)(i + 3))); std::map< uint64_t, uint64_t >::iterator otherQ(otherFields.find((uint64_t)(i + 3)));
if (otherQ == otherFields.end()) if (otherQ == otherFields.end()) {
return false; return false;
if (otherQ->second != Utils::ntoh(idHash[i])) }
if (otherQ->second != Utils::ntoh(idHash[i])) {
return false; return false;
} }
} }
}
return true; return true;
} }
@ -108,8 +115,9 @@ bool CertificateOfMembership::sign(const Identity &with)
int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) const int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) const
{ {
if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)) if ((!_signedBy)||(_signedBy != Network::controllerFor(networkId()))||(_qualifierCount > ZT_NETWORK_COM_MAX_QUALIFIERS)) {
return -1; return -1;
}
const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) { if (!id) {

View file

@ -142,9 +142,10 @@ public:
inline int64_t timestamp() const inline int64_t timestamp() const
{ {
for(unsigned int i=0;i<_qualifierCount;++i) { for(unsigned int i=0;i<_qualifierCount;++i) {
if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP) if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP) {
return _qualifiers[i].value; return _qualifiers[i].value;
} }
}
return 0; return 0;
} }
@ -154,9 +155,10 @@ public:
inline Address issuedTo() const inline Address issuedTo() const
{ {
for(unsigned int i=0;i<_qualifierCount;++i) { for(unsigned int i=0;i<_qualifierCount;++i) {
if (_qualifiers[i].id == COM_RESERVED_ID_ISSUED_TO) if (_qualifiers[i].id == COM_RESERVED_ID_ISSUED_TO) {
return Address(_qualifiers[i].value); return Address(_qualifiers[i].value);
} }
}
return Address(); return Address();
} }
@ -166,9 +168,10 @@ public:
inline uint64_t networkId() const inline uint64_t networkId() const
{ {
for(unsigned int i=0;i<_qualifierCount;++i) { for(unsigned int i=0;i<_qualifierCount;++i) {
if (_qualifiers[i].id == COM_RESERVED_ID_NETWORK_ID) if (_qualifiers[i].id == COM_RESERVED_ID_NETWORK_ID) {
return _qualifiers[i].value; return _qualifiers[i].value;
} }
}
return 0ULL; return 0ULL;
} }
@ -226,9 +229,10 @@ public:
b.append(_qualifiers[i].maxDelta); b.append(_qualifiers[i].maxDelta);
} }
_signedBy.appendTo(b); _signedBy.appendTo(b);
if (_signedBy) if (_signedBy) {
b.append(_signature.data,ZT_C25519_SIGNATURE_LEN); b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
} }
}
template<unsigned int C> template<unsigned int C>
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0) inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
@ -238,17 +242,20 @@ public:
_qualifierCount = 0; _qualifierCount = 0;
_signedBy.zero(); _signedBy.zero();
if (b[p++] != 1) if (b[p++] != 1) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
}
unsigned int numq = b.template at<uint16_t>(p); unsigned int numq = b.template at<uint16_t>(p);
p += sizeof(uint16_t); p += sizeof(uint16_t);
uint64_t lastId = 0; uint64_t lastId = 0;
for(unsigned int i=0;i<numq;++i) { for(unsigned int i=0;i<numq;++i) {
const uint64_t qid = b.template at<uint64_t>(p); const uint64_t qid = b.template at<uint64_t>(p);
if (qid < lastId) if (qid < lastId) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING;
else lastId = qid; } else {
lastId = qid;
}
if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) { if (_qualifierCount < ZT_NETWORK_COM_MAX_QUALIFIERS) {
_qualifiers[_qualifierCount].id = qid; _qualifiers[_qualifierCount].id = qid;
_qualifiers[_qualifierCount].value = b.template at<uint64_t>(p + 8); _qualifiers[_qualifierCount].value = b.template at<uint64_t>(p + 8);
@ -273,16 +280,19 @@ public:
inline bool operator==(const CertificateOfMembership &c) const inline bool operator==(const CertificateOfMembership &c) const
{ {
if (_signedBy != c._signedBy) if (_signedBy != c._signedBy) {
return false; return false;
if (_qualifierCount != c._qualifierCount) }
if (_qualifierCount != c._qualifierCount) {
return false; return false;
}
for(unsigned int i=0;i<_qualifierCount;++i) { for(unsigned int i=0;i<_qualifierCount;++i) {
const _Qualifier &a = _qualifiers[i]; const _Qualifier &a = _qualifiers[i];
const _Qualifier &b = c._qualifiers[i]; const _Qualifier &b = c._qualifiers[i];
if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta)) if ((a.id != b.id)||(a.value != b.value)||(a.maxDelta != b.maxDelta)) {
return false; return false;
} }
}
return (memcmp(_signature.data,c._signature.data,ZT_C25519_SIGNATURE_LEN) == 0); return (memcmp(_signature.data,c._signature.data,ZT_C25519_SIGNATURE_LEN) == 0);
} }
inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); } inline bool operator!=(const CertificateOfMembership &c) const { return (!(*this == c)); }

View file

@ -23,8 +23,9 @@ namespace ZeroTier {
int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) const int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) const
{ {
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) {
return -1; return -1;
}
const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) { if (!id) {
RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy); RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
@ -45,14 +46,16 @@ bool CertificateOfOwnership::_owns(const CertificateOfOwnership::Thing &t,const
if (_thingTypes[i] == (uint8_t)t) { if (_thingTypes[i] == (uint8_t)t) {
unsigned int k = 0; unsigned int k = 0;
while (k < l) { while (k < l) {
if (reinterpret_cast<const uint8_t *>(v)[k] != _thingValues[i][k]) if (reinterpret_cast<const uint8_t *>(v)[k] != _thingValues[i][k]) {
break; break;
}
++k; ++k;
} }
if (k == l) if (k == l) {
return true; return true;
} }
} }
}
return false; return false;
} }

View file

@ -80,10 +80,12 @@ public:
inline bool owns(const InetAddress &ip) const inline bool owns(const InetAddress &ip) const
{ {
if (ip.ss_family == AF_INET) if (ip.ss_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.ss_family == AF_INET6) }
if (ip.ss_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; return false;
} }
@ -96,7 +98,9 @@ public:
inline void addThing(const InetAddress &ip) inline void addThing(const InetAddress &ip)
{ {
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
return;
}
if (ip.ss_family == AF_INET) { if (ip.ss_family == AF_INET) {
_thingTypes[_thingCount] = THING_IPV4_ADDRESS; _thingTypes[_thingCount] = THING_IPV4_ADDRESS;
memcpy(_thingValues[_thingCount],&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4); memcpy(_thingValues[_thingCount],&(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr),4);
@ -110,7 +114,9 @@ public:
inline void addThing(const MAC &mac) inline void addThing(const MAC &mac)
{ {
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) {
return;
}
_thingTypes[_thingCount] = THING_MAC_ADDRESS; _thingTypes[_thingCount] = THING_MAC_ADDRESS;
mac.copyTo(_thingValues[_thingCount],6); mac.copyTo(_thingValues[_thingCount],6);
++_thingCount; ++_thingCount;
@ -142,7 +148,9 @@ public:
template<unsigned int C> template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const inline void serialize(Buffer<C> &b,const bool forSign = false) const
{ {
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
b.append(_networkId); b.append(_networkId);
b.append(_ts); b.append(_ts);
@ -164,7 +172,9 @@ public:
b.append((uint16_t)0); // length of additional fields, currently 0 b.append((uint16_t)0); // length of additional fields, currently 0
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
} }
template<unsigned int C> template<unsigned int C>
@ -197,8 +207,9 @@ public:
_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); _signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
p += ZT_ADDRESS_LENGTH; p += ZT_ADDRESS_LENGTH;
if (b[p++] == 1) { if (b[p++] == 1) {
if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
}
p += 2; p += 2;
memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
p += ZT_C25519_SIGNATURE_LEN; p += ZT_C25519_SIGNATURE_LEN;
@ -207,8 +218,9 @@ public:
} }
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
if (p > b.size()) if (p > b.size()) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
return (p - startAt); return (p - startAt);
} }

View file

@ -55,10 +55,14 @@ public:
{ {
for(unsigned int i=0;i<C;++i) { for(unsigned int i=0;i<C;++i) {
if ((s)&&(i < len)) { if ((s)&&(i < len)) {
if (!(_d[i] = *s)) if (!(_d[i] = *s)) {
s = (const char *)0; s = (const char *)0;
else ++s; } else {
} else _d[i] = (char)0; ++s;
}
} else {
_d[i] = (char)0;
}
} }
_d[C - 1] = (char)0; _d[C - 1] = (char)0;
} }
@ -82,10 +86,14 @@ public:
{ {
for(unsigned int i=0;i<C;++i) { for(unsigned int i=0;i<C;++i) {
if (s) { if (s) {
if (!(_d[i] = *s)) if (!(_d[i] = *s)) {
s = (const char *)0; s = (const char *)0;
else ++s; } else {
} else _d[i] = (char)0; ++s;
}
} else {
_d[i] = (char)0;
}
} }
_d[C - 1] = (char)0; _d[C - 1] = (char)0;
return (!s); return (!s);
@ -105,9 +113,10 @@ public:
inline unsigned int sizeBytes() const inline unsigned int sizeBytes() const
{ {
for(unsigned int i=0;i<C;++i) { for(unsigned int i=0;i<C;++i) {
if (!_d[i]) if (!_d[i]) {
return i; return i;
} }
}
return C-1; return C-1;
} }
@ -141,14 +150,16 @@ public:
bool esc; bool esc;
int j; int j;
if (!destlen) // sanity check if (!destlen) { // sanity check
return -1; return -1;
}
while (*p) { while (*p) {
k = key; k = key;
while ((*k)&&(*p)) { while ((*k)&&(*p)) {
if (*p != *k) if (*p != *k) {
break; break;
}
++k; ++k;
if (++p == eof) { if (++p == eof) {
dest[0] = (char)0; dest[0] = (char)0;
@ -212,8 +223,9 @@ public:
dest[0] = (char)0; dest[0] = (char)0;
return -1; return -1;
} }
} else {
break;
} }
else break;
} }
} }
@ -252,8 +264,9 @@ public:
bool getB(const char *key,bool dfl = false) const bool getB(const char *key,bool dfl = false) const
{ {
char tmp[4]; char tmp[4];
if (this->get(key,tmp,sizeof(tmp)) >= 0) if (this->get(key,tmp,sizeof(tmp)) >= 0) {
return ((*tmp == '1')||(*tmp == 't')||(*tmp == 'T')); return ((*tmp == '1')||(*tmp == 't')||(*tmp == 'T'));
}
return dfl; return dfl;
} }
@ -267,8 +280,9 @@ public:
inline uint64_t getUI(const char *key,uint64_t dfl = 0) const inline uint64_t getUI(const char *key,uint64_t dfl = 0) const
{ {
char tmp[128]; char tmp[128];
if (this->get(key,tmp,sizeof(tmp)) >= 1) if (this->get(key,tmp,sizeof(tmp)) >= 1) {
return Utils::hexStrToU64(tmp); return Utils::hexStrToU64(tmp);
}
return dfl; return dfl;
} }
@ -282,8 +296,9 @@ public:
inline int64_t getI(const char *key,int64_t dfl = 0) const inline int64_t getI(const char *key,int64_t dfl = 0) const
{ {
char tmp[128]; char tmp[128];
if (this->get(key,tmp,sizeof(tmp)) >= 1) if (this->get(key,tmp,sizeof(tmp)) >= 1) {
return Utils::hexStrTo64(tmp); return Utils::hexStrTo64(tmp);
}
return dfl; return dfl;
} }

View file

@ -81,8 +81,9 @@ public:
return true; return true;
} }
++_idx; ++_idx;
if (_idx >= _ht->_bc) if (_idx >= _ht->_bc) {
return false; return false;
}
_b = _ht->_t[_idx]; _b = _ht->_t[_idx];
} }
} }
@ -102,21 +103,25 @@ public:
_bc(bc), _bc(bc),
_s(0) _s(0)
{ {
if (!_t) if (!_t) {
throw ZT_EXCEPTION_OUT_OF_MEMORY; throw ZT_EXCEPTION_OUT_OF_MEMORY;
for(unsigned long i=0;i<bc;++i) }
for(unsigned long i=0;i<bc;++i) {
_t[i] = (_Bucket *)0; _t[i] = (_Bucket *)0;
} }
}
Hashtable(const Hashtable<K,V> &ht) : Hashtable(const Hashtable<K,V> &ht) :
_t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * ht._bc))), _t(reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * ht._bc))),
_bc(ht._bc), _bc(ht._bc),
_s(ht._s) _s(ht._s)
{ {
if (!_t) if (!_t) {
throw ZT_EXCEPTION_OUT_OF_MEMORY; throw ZT_EXCEPTION_OUT_OF_MEMORY;
for(unsigned long i=0;i<_bc;++i) }
for(unsigned long i=0;i<_bc;++i) {
_t[i] = (_Bucket *)0; _t[i] = (_Bucket *)0;
}
for(unsigned long i=0;i<_bc;++i) { for(unsigned long i=0;i<_bc;++i) {
const _Bucket *b = ht._t[i]; const _Bucket *b = ht._t[i];
while (b) { while (b) {
@ -234,8 +239,9 @@ public:
{ {
_Bucket *b = _t[_hc(k) % _bc]; _Bucket *b = _t[_hc(k) % _bc];
while (b) { while (b) {
if (b->k == k) if (b->k == k) {
return &(b->v); return &(b->v);
}
b = b->next; b = b->next;
} }
return (V *)0; return (V *)0;
@ -268,8 +274,9 @@ public:
{ {
_Bucket *b = _t[_hc(k) % _bc]; _Bucket *b = _t[_hc(k) % _bc];
while (b) { while (b) {
if (b->k == k) if (b->k == k) {
return true; return true;
}
b = b->next; b = b->next;
} }
return false; return false;
@ -286,9 +293,11 @@ public:
_Bucket *b = _t[bidx]; _Bucket *b = _t[bidx];
while (b) { while (b) {
if (b->k == k) { if (b->k == k) {
if (lastb) if (lastb) {
lastb->next = b->next; lastb->next = b->next;
else _t[bidx] = b->next; } else {
_t[bidx] = b->next;
}
delete b; delete b;
--_s; --_s;
return true; return true;
@ -341,8 +350,9 @@ public:
_Bucket *b = _t[bidx]; _Bucket *b = _t[bidx];
while (b) { while (b) {
if (b->k == k) if (b->k == k) {
return b->v; return b->v;
}
b = b->next; b = b->next;
} }
@ -396,8 +406,9 @@ private:
const unsigned long nc = _bc * 2; const unsigned long nc = _bc * 2;
_Bucket **nt = reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * nc)); _Bucket **nt = reinterpret_cast<_Bucket **>(::malloc(sizeof(_Bucket *) * nc));
if (nt) { if (nt) {
for(unsigned long i=0;i<nc;++i) for(unsigned long i=0;i<nc;++i) {
nt[i] = (_Bucket *)0; nt[i] = (_Bucket *)0;
}
for(unsigned long i=0;i<_bc;++i) { for(unsigned long i=0;i<_bc;++i) {
_Bucket *b = _t[i]; _Bucket *b = _t[i];
while (b) { while (b) {

View file

@ -93,8 +93,9 @@ void Identity::generate()
} while (_address.isReserved()); } while (_address.isReserved());
_publicKey = kp.pub; _publicKey = kp.pub;
if (!_privateKey) if (!_privateKey) {
_privateKey = new C25519::Private(); _privateKey = new C25519::Private();
}
*_privateKey = kp.priv; *_privateKey = kp.priv;
delete [] genmem; delete [] genmem;
@ -102,8 +103,9 @@ void Identity::generate()
bool Identity::locallyValidate() const bool Identity::locallyValidate() const
{ {
if (_address.isReserved()) if (_address.isReserved()) {
return false; return false;
}
unsigned char digest[64]; unsigned char digest[64];
char *genmem = new char[ZT_IDENTITY_GEN_MEMORY]; char *genmem = new char[ZT_IDENTITY_GEN_MEMORY];

View file

@ -56,9 +56,10 @@ public:
Identity(const char *str) : Identity(const char *str) :
_privateKey((C25519::Private *)0) _privateKey((C25519::Private *)0)
{ {
if (!fromString(str)) if (!fromString(str)) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
} }
}
template<unsigned int C> template<unsigned int C>
Identity(const Buffer<C> &b,unsigned int startAt = 0) : Identity(const Buffer<C> &b,unsigned int startAt = 0) :
@ -80,8 +81,9 @@ public:
_address = id._address; _address = id._address;
_publicKey = id._publicKey; _publicKey = id._publicKey;
if (id._privateKey) { if (id._privateKey) {
if (!_privateKey) if (!_privateKey) {
_privateKey = new C25519::Private(); _privateKey = new C25519::Private();
}
*_privateKey = *(id._privateKey); *_privateKey = *(id._privateKey);
} else { } else {
delete _privateKey; delete _privateKey;
@ -144,8 +146,9 @@ public:
*/ */
inline C25519::Signature sign(const void *data,unsigned int len) const inline C25519::Signature sign(const void *data,unsigned int len) const
{ {
if (_privateKey) if (_privateKey) {
return C25519::sign(*_privateKey,_publicKey,data,len); return C25519::sign(*_privateKey,_publicKey,data,len);
}
throw ZT_EXCEPTION_PRIVATE_KEY_REQUIRED; throw ZT_EXCEPTION_PRIVATE_KEY_REQUIRED;
} }
@ -160,8 +163,9 @@ public:
*/ */
inline bool verify(const void *data,unsigned int len,const void *signature,unsigned int siglen) const inline bool verify(const void *data,unsigned int len,const void *signature,unsigned int siglen) const
{ {
if (siglen != ZT_C25519_SIGNATURE_LEN) if (siglen != ZT_C25519_SIGNATURE_LEN) {
return false; return false;
}
return C25519::verify(_publicKey,data,len,signature); return C25519::verify(_publicKey,data,len,signature);
} }
@ -217,7 +221,9 @@ public:
if ((_privateKey)&&(includePrivate)) { if ((_privateKey)&&(includePrivate)) {
b.append((unsigned char)ZT_C25519_PRIVATE_KEY_LEN); b.append((unsigned char)ZT_C25519_PRIVATE_KEY_LEN);
b.append(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN); b.append(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN);
} else b.append((unsigned char)0); } else {
b.append((unsigned char)0);
}
} }
/** /**
@ -243,16 +249,18 @@ public:
_address.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); _address.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
p += ZT_ADDRESS_LENGTH; p += ZT_ADDRESS_LENGTH;
if (b[p++] != 0) if (b[p++] != 0) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
}
memcpy(_publicKey.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN); memcpy(_publicKey.data,b.field(p,ZT_C25519_PUBLIC_KEY_LEN),ZT_C25519_PUBLIC_KEY_LEN);
p += ZT_C25519_PUBLIC_KEY_LEN; p += ZT_C25519_PUBLIC_KEY_LEN;
unsigned int privateKeyLength = (unsigned int)b[p++]; unsigned int privateKeyLength = (unsigned int)b[p++];
if (privateKeyLength) { if (privateKeyLength) {
if (privateKeyLength != ZT_C25519_PRIVATE_KEY_LEN) if (privateKeyLength != ZT_C25519_PRIVATE_KEY_LEN) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
}
_privateKey = new C25519::Private(); _privateKey = new C25519::Private();
memcpy(_privateKey->data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN); memcpy(_privateKey->data,b.field(p,ZT_C25519_PRIVATE_KEY_LEN),ZT_C25519_PRIVATE_KEY_LEN);
p += ZT_C25519_PRIVATE_KEY_LEN; p += ZT_C25519_PRIVATE_KEY_LEN;
@ -293,9 +301,11 @@ public:
{ {
C25519::Pair pair; C25519::Pair pair;
pair.pub = _publicKey; pair.pub = _publicKey;
if (_privateKey) if (_privateKey) {
pair.priv = *_privateKey; pair.priv = *_privateKey;
else memset(pair.priv.data,0,ZT_C25519_PRIVATE_KEY_LEN); } else {
memset(pair.priv.data,0,ZT_C25519_PRIVATE_KEY_LEN);
}
return pair; return pair;
} }

View file

@ -186,9 +186,10 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
// Object not found, currently only meaningful from network controllers. // Object not found, currently only meaningful from network controllers.
if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) {
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
if ((network)&&(network->controller() == peer->address())) if ((network)&&(network->controller() == peer->address())) {
network->setNotFound(tPtr); network->setNotFound(tPtr);
} }
}
Metrics::pkt_error_obj_not_found_in++; Metrics::pkt_error_obj_not_found_in++;
break; break;
@ -198,9 +199,10 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
// that the queried node does not support acting as a controller. // that the queried node does not support acting as a controller.
if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) {
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
if ((network)&&(network->controller() == peer->address())) if ((network)&&(network->controller() == peer->address())) {
network->setNotFound(tPtr); network->setNotFound(tPtr);
} }
}
Metrics::pkt_error_unsupported_op_in++; Metrics::pkt_error_unsupported_op_in++;
break; break;
@ -395,8 +397,9 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
// Identity is different from the one we already have -- address collision // Identity is different from the one we already have -- address collision
// Check rate limits // Check rate limits
if (!RR->node->rateGateIdentityVerification(now,_path->address())) if (!RR->node->rateGateIdentityVerification(now,_path->address())) {
return true; return true;
}
uint8_t key[ZT_SYMMETRIC_KEY_SIZE]; uint8_t key[ZT_SYMMETRIC_KEY_SIZE];
if (RR->identity.agree(id,key)) { if (RR->identity.agree(id,key)) {
@ -466,9 +469,10 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
InetAddress externalSurfaceAddress; InetAddress externalSurfaceAddress;
if (ptr < size()) { if (ptr < size()) {
ptr += externalSurfaceAddress.deserialize(*this,ptr); ptr += externalSurfaceAddress.deserialize(*this,ptr);
if ((externalSurfaceAddress)&&(hops() == 0)) if ((externalSurfaceAddress)&&(hops() == 0)) {
RR->sa->iam(tPtr,id.address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now); RR->sa->iam(tPtr,id.address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(id),now);
} }
}
// Get primary planet world ID and world timestamp if present // Get primary planet world ID and world timestamp if present
uint64_t planetWorldId = 0; uint64_t planetWorldId = 0;
@ -490,8 +494,9 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
const unsigned int numMoons = at<uint16_t>(ptr); const unsigned int numMoons = at<uint16_t>(ptr);
ptr += 2; ptr += 2;
for(unsigned int i=0;i<numMoons;++i) { for(unsigned int i=0;i<numMoons;++i) {
if ((World::Type)(*this)[ptr++] == World::TYPE_MOON) if ((World::Type)(*this)[ptr++] == World::TYPE_MOON) {
moonIdsAndTimestamps.push_back(std::pair<uint64_t,uint64_t>(at<uint64_t>(ptr),at<uint64_t>(ptr + 8))); moonIdsAndTimestamps.push_back(std::pair<uint64_t,uint64_t>(at<uint64_t>(ptr),at<uint64_t>(ptr + 8)));
}
ptr += 16; ptr += 16;
} }
} }
@ -550,8 +555,9 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
for(std::vector<World>::const_iterator m(moons.begin());m!=moons.end();++m) { for(std::vector<World>::const_iterator m(moons.begin());m!=moons.end();++m) {
for(std::vector< std::pair<uint64_t,uint64_t> >::const_iterator i(moonIdsAndTimestamps.begin());i!=moonIdsAndTimestamps.end();++i) { for(std::vector< std::pair<uint64_t,uint64_t> >::const_iterator i(moonIdsAndTimestamps.begin());i!=moonIdsAndTimestamps.end();++i) {
if (i->first == m->id()) { if (i->first == m->id()) {
if (m->timestamp() > i->second) if (m->timestamp() > i->second) {
m->serialize(outp,false); m->serialize(outp,false);
}
break; break;
} }
} }
@ -576,8 +582,9 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
const uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID); const uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID);
uint64_t networkId = 0; uint64_t networkId = 0;
if (!RR->node->expectingReplyTo(inRePacketId)) if (!RR->node->expectingReplyTo(inRePacketId)) {
return true; return true;
}
switch(inReVerb) { switch(inReVerb) {
@ -587,15 +594,17 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION]; const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION];
const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION]; const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION];
const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO__OK__IDX_REVISION); const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO__OK__IDX_REVISION);
if (vProto < ZT_PROTO_VERSION_MIN) if (vProto < ZT_PROTO_VERSION_MIN) {
return true; return true;
}
InetAddress externalSurfaceAddress; InetAddress externalSurfaceAddress;
unsigned int ptr = ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2; unsigned int ptr = ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2;
// Get reported external surface address if present // Get reported external surface address if present
if (ptr < size()) if (ptr < size()) {
ptr += externalSurfaceAddress.deserialize(*this,ptr); ptr += externalSurfaceAddress.deserialize(*this,ptr);
}
// Handle planet or moon updates if present // Handle planet or moon updates if present
if ((ptr + 2) <= size()) { if ((ptr + 2) <= size()) {
@ -622,8 +631,9 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
if ((externalSurfaceAddress)&&(hops() == 0)) if ((externalSurfaceAddress)&&(hops() == 0)) {
RR->sa->iam(tPtr,peer->address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now()); RR->sa->iam(tPtr,peer->address(),_path->localSocket(),_path->address(),externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now());
}
} break; } break;
case Packet::VERB_WHOIS: case Packet::VERB_WHOIS:
@ -636,8 +646,9 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
case Packet::VERB_NETWORK_CONFIG_REQUEST: { case Packet::VERB_NETWORK_CONFIG_REQUEST: {
networkId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_PAYLOAD); networkId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_PAYLOAD);
const SharedPtr<Network> network(RR->node->network(networkId)); const SharedPtr<Network> network(RR->node->network(networkId));
if (network) if (network) {
network->handleConfigChunk(tPtr,packetId(),source(),*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD); network->handleConfigChunk(tPtr,packetId(),source(),*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD);
}
} break; } break;
case Packet::VERB_MULTICAST_GATHER: { case Packet::VERB_MULTICAST_GATHER: {
@ -662,9 +673,10 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP
if ((flags & 0x01) != 0) { // deprecated but still used by older peers if ((flags & 0x01) != 0) { // deprecated but still used by older peers
CertificateOfMembership com; CertificateOfMembership com;
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS); offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS);
if (com) if (com) {
network->addCredential(tPtr,com); network->addCredential(tPtr,com);
} }
}
if ((flags & 0x02) != 0) { if ((flags & 0x02) != 0) {
// OK(MULTICAST_FRAME) includes implicit gather results // OK(MULTICAST_FRAME) includes implicit gather results
@ -753,8 +765,9 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,void *tPtr,const
// Returns true if packet appears valid; pos and proto will be set // Returns true if packet appears valid; pos and proto will be set
static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto) static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto)
{ {
if (frameLen < 40) if (frameLen < 40) {
return false; return false;
}
pos = 40; pos = 40;
proto = frameData[6]; proto = frameData[6];
while (pos <= frameLen) { while (pos <= frameLen) {
@ -763,8 +776,9 @@ static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsig
case 43: // routing case 43: // routing
case 60: // destination options case 60: // destination options
case 135: // mobility options case 135: // mobility options
if ((pos + 8) > frameLen) if ((pos + 8) > frameLen) {
return false; // invalid! return false; // invalid!
}
proto = frameData[pos]; proto = frameData[pos];
pos += ((unsigned int)frameData[pos + 1] * 8) + 8; pos += ((unsigned int)frameData[pos + 1] * 8) + 8;
break; break;
@ -859,9 +873,10 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,void *tPtr,const Shar
const MAC sourceMac(peer->address(),nwid); const MAC sourceMac(peer->address(),nwid);
const unsigned int frameLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD; const unsigned int frameLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD;
const uint8_t *const frameData = reinterpret_cast<const uint8_t *>(data()) + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD; const uint8_t *const frameData = reinterpret_cast<const uint8_t *>(data()) + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD;
if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),sourceMac,network->mac(),frameData,frameLen,etherType,0) > 0) if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),sourceMac,network->mac(),frameData,frameLen,etherType,0) > 0) {
RR->node->putFrame(tPtr,nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen); RR->node->putFrame(tPtr,nwid,network->userPtr(),sourceMac,network->mac(),etherType,0,(const void *)frameData,frameLen);
} }
}
} else { } else {
_sendErrorNeedCredentials(RR,tPtr,peer,nwid); _sendErrorNeedCredentials(RR,tPtr,peer,nwid);
return false; return false;
@ -884,9 +899,10 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const
if ((flags & 0x01) != 0) { // inline COM with EXT_FRAME is deprecated but still used with old peers if ((flags & 0x01) != 0) { // inline COM with EXT_FRAME is deprecated but still used with old peers
CertificateOfMembership com; CertificateOfMembership com;
comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM); comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM);
if (com) if (com) {
network->addCredential(tPtr,com); network->addCredential(tPtr,com);
} }
}
if (!network->gate(tPtr,peer)) { if (!network->gate(tPtr,peer)) {
RR->t->incomingNetworkAccessDenied(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,true); RR->t->incomingNetworkAccessDenied(tPtr,network,_path,packetId(),size(),peer->address(),Packet::VERB_EXT_FRAME,true);
@ -967,8 +983,9 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK); Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
outp.append((unsigned char)Packet::VERB_ECHO); outp.append((unsigned char)Packet::VERB_ECHO);
outp.append((uint64_t)pid); outp.append((uint64_t)pid);
if (size() > ZT_PACKET_IDX_PAYLOAD) if (size() > ZT_PACKET_IDX_PAYLOAD) {
outp.append(reinterpret_cast<const unsigned char *>(data()) + ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD); outp.append(reinterpret_cast<const unsigned char *>(data()) + ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD);
}
outp.armor(peer->key(),true,peer->aesKeysIfSupported()); outp.armor(peer->key(),true,peer->aesKeysIfSupported());
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now); peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
@ -991,14 +1008,17 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,c
if (nwid != lastNwid) { if (nwid != lastNwid) {
lastNwid = nwid; lastNwid = nwid;
SharedPtr<Network> network(RR->node->network(nwid)); SharedPtr<Network> network(RR->node->network(nwid));
if (network) if (network) {
authorized = network->gate(tPtr,peer); authorized = network->gate(tPtr,peer);
if (!authorized) }
if (!authorized) {
authorized = ((RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address()))); authorized = ((RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address())));
} }
if (authorized) }
if (authorized) {
RR->mc->add(tPtr,now,nwid,MulticastGroup(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14)),peer->address()); RR->mc->add(tPtr,now,nwid,MulticastGroup(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14)),peer->address());
} }
}
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,false,0,ZT_QOS_NO_FLOW); peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,false,0,ZT_QOS_NO_FLOW);
return true; return true;
@ -1045,8 +1065,9 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t
p += 2; p += 2;
for(unsigned int i=0;i<numCapabilities;++i) { for(unsigned int i=0;i<numCapabilities;++i) {
p += cap.deserialize(*this,p); p += cap.deserialize(*this,p);
if ((!network)||(network->id() != cap.networkId())) if ((!network)||(network->id() != cap.networkId())) {
network = RR->node->network(cap.networkId()); network = RR->node->network(cap.networkId());
}
if (network) { if (network) {
switch (network->addCredential(tPtr,cap)) { switch (network->addCredential(tPtr,cap)) {
case Membership::ADD_REJECTED: case Membership::ADD_REJECTED:
@ -1061,14 +1082,17 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t
} }
} }
if (p >= size()) return true; if (p >= size()) {
return true;
}
const unsigned int numTags = at<uint16_t>(p); const unsigned int numTags = at<uint16_t>(p);
p += 2; p += 2;
for(unsigned int i=0;i<numTags;++i) { for(unsigned int i=0;i<numTags;++i) {
p += tag.deserialize(*this,p); p += tag.deserialize(*this,p);
if ((!network)||(network->id() != tag.networkId())) if ((!network)||(network->id() != tag.networkId())) {
network = RR->node->network(tag.networkId()); network = RR->node->network(tag.networkId());
}
if (network) { if (network) {
switch (network->addCredential(tPtr,tag)) { switch (network->addCredential(tPtr,tag)) {
case Membership::ADD_REJECTED: case Membership::ADD_REJECTED:
@ -1083,14 +1107,17 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t
} }
} }
if (p >= size()) return true; if (p >= size()) {
return true;
}
const unsigned int numRevocations = at<uint16_t>(p); const unsigned int numRevocations = at<uint16_t>(p);
p += 2; p += 2;
for(unsigned int i=0;i<numRevocations;++i) { for(unsigned int i=0;i<numRevocations;++i) {
p += revocation.deserialize(*this,p); p += revocation.deserialize(*this,p);
if ((!network)||(network->id() != revocation.networkId())) if ((!network)||(network->id() != revocation.networkId())) {
network = RR->node->network(revocation.networkId()); network = RR->node->network(revocation.networkId());
}
if (network) { if (network) {
switch(network->addCredential(tPtr,peer->address(),revocation)) { switch(network->addCredential(tPtr,peer->address(),revocation)) {
case Membership::ADD_REJECTED: case Membership::ADD_REJECTED:
@ -1105,14 +1132,17 @@ bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,void *t
} }
} }
if (p >= size()) return true; if (p >= size()) {
return true;
}
const unsigned int numCoos = at<uint16_t>(p); const unsigned int numCoos = at<uint16_t>(p);
p += 2; p += 2;
for(unsigned int i=0;i<numCoos;++i) { for(unsigned int i=0;i<numCoos;++i) {
p += coo.deserialize(*this,p); p += coo.deserialize(*this,p);
if ((!network)||(network->id() != coo.networkId())) if ((!network)||(network->id() != coo.networkId())) {
network = RR->node->network(coo.networkId()); network = RR->node->network(coo.networkId());
}
if (network) { if (network) {
switch(network->addCredential(tPtr,coo)) { switch(network->addCredential(tPtr,coo)) {
case Membership::ADD_REJECTED: case Membership::ADD_REJECTED:
@ -1198,8 +1228,9 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
try { try {
CertificateOfMembership com; CertificateOfMembership com;
com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM); com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM);
if ((com)&&(network)) if ((com)&&(network)) {
network->addCredential(tPtr,com); network->addCredential(tPtr,com);
}
} catch ( ... ) {} // discard invalid COMs } catch ( ... ) {} // discard invalid COMs
} }
@ -1240,9 +1271,10 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
// This is deprecated but may still be sent by old peers // This is deprecated but may still be sent by old peers
CertificateOfMembership com; CertificateOfMembership com;
offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM); offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM);
if (com) if (com) {
network->addCredential(tPtr,com); network->addCredential(tPtr,com);
} }
}
if (!network->gate(tPtr,peer)) { if (!network->gate(tPtr,peer)) {
_sendErrorNeedCredentials(RR,tPtr,peer,nwid); _sendErrorNeedCredentials(RR,tPtr,peer,nwid);
@ -1287,8 +1319,9 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
const uint8_t *const frameData = (const uint8_t *)field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen); const uint8_t *const frameData = (const uint8_t *)field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,frameLen);
if ((flags & 0x08)&&(network->config().isMulticastReplicator(RR->identity.address()))) if ((flags & 0x08)&&(network->config().isMulticastReplicator(RR->identity.address()))) {
RR->mc->send(tPtr,RR->node->now(),network,peer->address(),to,from,etherType,frameData,frameLen); RR->mc->send(tPtr,RR->node->now(),network,peer->address(),to,from,etherType,frameData,frameLen);
}
if (from != MAC(peer->address(),nwid)) { if (from != MAC(peer->address(),nwid)) {
if (network->config().permitsBridging(peer->address())) { if (network->config().permitsBridging(peer->address())) {
@ -1300,9 +1333,10 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
} }
} }
if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),from,to.mac(),frameData,frameLen,etherType,0) > 0) if (network->filterIncomingPacket(tPtr,peer,RR->identity.address(),from,to.mac(),frameData,frameLen,etherType,0) > 0) {
RR->node->putFrame(tPtr,nwid,network->userPtr(),from,to.mac(),etherType,0,(const void *)frameData,frameLen); RR->node->putFrame(tPtr,nwid,network->userPtr(),from,to.mac(),etherType,0,(const void *)frameData,frameLen);
} }
}
if (gatherLimit) { if (gatherLimit) {
Packet outp(source(),RR->identity.address(),Packet::VERB_OK); Packet outp(source(),RR->identity.address(),Packet::VERB_OK);

View file

@ -62,26 +62,42 @@ InetAddress::IpScope InetAddress::ipScope() const
case 0x38: case 0x38:
return IP_SCOPE_PSEUDOPRIVATE; // 56.0.0.0/8 (US Postal Service) return IP_SCOPE_PSEUDOPRIVATE; // 56.0.0.0/8 (US Postal Service)
case 0x64: case 0x64:
if ((ip & 0xffc00000) == 0x64400000) return IP_SCOPE_PRIVATE; // 100.64.0.0/10 if ((ip & 0xffc00000) == 0x64400000) {
return IP_SCOPE_PRIVATE; // 100.64.0.0/10
}
break; break;
case 0x7f: case 0x7f:
return IP_SCOPE_LOOPBACK; // 127.0.0.0/8 return IP_SCOPE_LOOPBACK; // 127.0.0.0/8
case 0xa9: case 0xa9:
if ((ip & 0xffff0000) == 0xa9fe0000) return IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16 if ((ip & 0xffff0000) == 0xa9fe0000) {
return IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
}
break; break;
case 0xac: case 0xac:
if ((ip & 0xfff00000) == 0xac100000) return IP_SCOPE_PRIVATE; // 172.16.0.0/12 if ((ip & 0xfff00000) == 0xac100000) {
return IP_SCOPE_PRIVATE; // 172.16.0.0/12
}
break; break;
case 0xc0: case 0xc0:
if ((ip & 0xffff0000) == 0xc0a80000) return IP_SCOPE_PRIVATE; // 192.168.0.0/16 if ((ip & 0xffff0000) == 0xc0a80000) {
if ((ip & 0xffffff00) == 0xc0000200) return IP_SCOPE_PRIVATE; // 192.0.2.0/24 return IP_SCOPE_PRIVATE; // 192.168.0.0/16
}
if ((ip & 0xffffff00) == 0xc0000200) {
return IP_SCOPE_PRIVATE; // 192.0.2.0/24
}
break; break;
case 0xc6: case 0xc6:
if ((ip & 0xfffe0000) == 0xc6120000) return IP_SCOPE_PRIVATE; // 198.18.0.0/15 if ((ip & 0xfffe0000) == 0xc6120000) {
if ((ip & 0xffffff00) == 0xc6336400) return IP_SCOPE_PRIVATE; // 198.51.100.0/24 return IP_SCOPE_PRIVATE; // 198.18.0.0/15
}
if ((ip & 0xffffff00) == 0xc6336400) {
return IP_SCOPE_PRIVATE; // 198.51.100.0/24
}
break; break;
case 0xcb: case 0xcb:
if ((ip & 0xffffff00) == 0xcb007100) return IP_SCOPE_PRIVATE; // 203.0.113.0/24 if ((ip & 0xffffff00) == 0xcb007100) {
return IP_SCOPE_PRIVATE; // 203.0.113.0/24
}
break; break;
case 0xff: case 0xff:
return IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable) return IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable)
@ -98,21 +114,35 @@ InetAddress::IpScope InetAddress::ipScope() const
case AF_INET6: { case AF_INET6: {
const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr); const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
if ((ip[0] & 0xf0) == 0xf0) { if ((ip[0] & 0xf0) == 0xf0) {
if (ip[0] == 0xff) return IP_SCOPE_MULTICAST; // ff00::/8 if (ip[0] == 0xff) {
return IP_SCOPE_MULTICAST; // ff00::/8
}
if ((ip[0] == 0xfe)&&((ip[1] & 0xc0) == 0x80)) { if ((ip[0] == 0xfe)&&((ip[1] & 0xc0) == 0x80)) {
unsigned int k = 2; unsigned int k = 2;
while ((!ip[k])&&(k < 15)) ++k; while ((!ip[k])&&(k < 15)) {
if ((k == 15)&&(ip[15] == 0x01)) ++k;
return IP_SCOPE_LOOPBACK; // fe80::1/128 }
else return IP_SCOPE_LINK_LOCAL; // fe80::/10 if ((k == 15)&&(ip[15] == 0x01)) {
return IP_SCOPE_LOOPBACK; // fe80::1/128
} else {
return IP_SCOPE_LINK_LOCAL; // fe80::/10
}
}
if ((ip[0] & 0xfe) == 0xfc) {
return IP_SCOPE_PRIVATE; // fc00::/7
} }
if ((ip[0] & 0xfe) == 0xfc) return IP_SCOPE_PRIVATE; // fc00::/7
} }
unsigned int k = 0; unsigned int k = 0;
while ((!ip[k])&&(k < 15)) ++k; while ((!ip[k])&&(k < 15)) {
++k;
}
if (k == 15) { // all 0's except last byte if (k == 15) { // all 0's except last byte
if (ip[15] == 0x01) return IP_SCOPE_LOOPBACK; // ::1/128 if (ip[15] == 0x01) {
if (ip[15] == 0x00) return IP_SCOPE_NONE; // ::/128 return IP_SCOPE_LOOPBACK; // ::1/128
}
if (ip[15] == 0x00) {
return IP_SCOPE_NONE; // ::/128
}
} }
return IP_SCOPE_GLOBAL; return IP_SCOPE_GLOBAL;
} break; } break;
@ -142,7 +172,9 @@ char *InetAddress::toString(char buf[64]) const
{ {
char *p = toIpString(buf); char *p = toIpString(buf);
if (*p) { if (*p) {
while (*p) ++p; while (*p) {
++p;
}
*(p++) = '/'; *(p++) = '/';
Utils::decimal(port(),p); Utils::decimal(port(),p);
} }
@ -178,14 +210,17 @@ bool InetAddress::fromString(const char *ipSlashPort)
memset(this,0,sizeof(InetAddress)); memset(this,0,sizeof(InetAddress));
if (!*ipSlashPort) if (!*ipSlashPort) {
return true; return true;
if (!Utils::scopy(buf,sizeof(buf),ipSlashPort)) }
if (!Utils::scopy(buf,sizeof(buf),ipSlashPort)) {
return false; return false;
}
char *portAt = buf; char *portAt = buf;
while ((*portAt)&&(*portAt != '/')) while ((*portAt)&&(*portAt != '/')) {
++portAt; ++portAt;
}
unsigned int port = 0; unsigned int port = 0;
if (*portAt) { if (*portAt) {
*(portAt++) = (char)0; *(portAt++) = (char)0;
@ -273,9 +308,10 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const
const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_addr.s6_addr); const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_addr.s6_addr);
const uint8_t *b = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr); const uint8_t *b = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
for(unsigned int i=0;i<16;++i) { for(unsigned int i=0;i<16;++i) {
if ((a[i] & m[i]) != (b[i] & n[i])) if ((a[i] & m[i]) != (b[i] & n[i])) {
return false; return false;
} }
}
return true; return true;
} }
} }
@ -289,8 +325,9 @@ bool InetAddress::containsAddress(const InetAddress &addr) const
switch(ss_family) { switch(ss_family) {
case AF_INET: { case AF_INET: {
const unsigned int bits = netmaskBits(); const unsigned int bits = netmaskBits();
if (bits == 0) if (bits == 0) {
return true; return true;
}
return ( (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(&addr)->sin_addr.s_addr) >> (32 - bits)) == (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) >> (32 - bits)) ); return ( (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(&addr)->sin_addr.s_addr) >> (32 - bits)) == (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) >> (32 - bits)) );
} }
case AF_INET6: { case AF_INET6: {
@ -299,9 +336,10 @@ bool InetAddress::containsAddress(const InetAddress &addr) const
const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_addr.s6_addr); const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_addr.s6_addr);
const uint8_t *b = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr); const uint8_t *b = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
for(unsigned int i=0;i<16;++i) { for(unsigned int i=0;i<16;++i) {
if ((a[i] & m[i]) != b[i]) if ((a[i] & m[i]) != b[i]) {
return false; return false;
} }
}
return true; return true;
} }
} }
@ -314,27 +352,33 @@ bool InetAddress::isNetwork() const
switch(ss_family) { switch(ss_family) {
case AF_INET: { case AF_INET: {
unsigned int bits = netmaskBits(); unsigned int bits = netmaskBits();
if (bits <= 0) if (bits <= 0) {
return false; return false;
if (bits >= 32) }
if (bits >= 32) {
return false; return false;
}
uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr); uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
return ((ip & (0xffffffff >> bits)) == 0); return ((ip & (0xffffffff >> bits)) == 0);
} }
case AF_INET6: { case AF_INET6: {
unsigned int bits = netmaskBits(); unsigned int bits = netmaskBits();
if (bits <= 0) if (bits <= 0) {
return false; return false;
if (bits >= 128) }
if (bits >= 128) {
return false; return false;
}
const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr); const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
unsigned int p = bits / 8; unsigned int p = bits / 8;
if ((ip[p++] & (0xff >> (bits % 8))) != 0) if ((ip[p++] & (0xff >> (bits % 8))) != 0) {
return false; return false;
}
while (p < 16) { while (p < 16) {
if (ip[p++]) if (ip[p++]) {
return false; return false;
} }
}
return true; return true;
} }
} }
@ -366,33 +410,35 @@ bool InetAddress::operator==(const InetAddress &a) const
bool InetAddress::operator<(const InetAddress &a) const bool InetAddress::operator<(const InetAddress &a) const
{ {
if (ss_family < a.ss_family) if (ss_family < a.ss_family) {
return true; return true;
else if (ss_family == a.ss_family) { } else if (ss_family == a.ss_family) {
switch(ss_family) { switch(ss_family) {
case AF_INET: case AF_INET:
if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_port < reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port) if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_port < reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port) {
return true; return true;
else if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_port == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port) { } else if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_port == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_port) {
if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr < reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr) if (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr < reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr) {
return true; return true;
} }
}
break; break;
case AF_INET6: case AF_INET6:
if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port) if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port) {
return true; return true;
else if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port) { } else if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_port) {
if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo) if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo) {
return true; return true;
else if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo) { } else if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_flowinfo == reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_flowinfo) {
if (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) < 0) if (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) < 0) {
return true; return true;
else if (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0) { } else if (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0) {
if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_scope_id < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_scope_id) if (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_scope_id < reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_scope_id) {
return true; return true;
} }
} }
} }
}
break; break;
default: default:
return (memcmp(this,&a,sizeof(InetAddress)) < 0); return (memcmp(this,&a,sizeof(InetAddress)) < 0);

View file

@ -94,29 +94,33 @@ struct InetAddress : public sockaddr_storage
inline InetAddress &operator=(const InetAddress &a) inline InetAddress &operator=(const InetAddress &a)
{ {
if (&a != this) if (&a != this) {
memcpy(this,&a,sizeof(InetAddress)); memcpy(this,&a,sizeof(InetAddress));
}
return *this; return *this;
} }
inline InetAddress &operator=(const InetAddress *a) inline InetAddress &operator=(const InetAddress *a)
{ {
if (a != this) if (a != this) {
memcpy(this,a,sizeof(InetAddress)); memcpy(this,a,sizeof(InetAddress));
}
return *this; return *this;
} }
inline InetAddress &operator=(const struct sockaddr_storage &ss) inline InetAddress &operator=(const struct sockaddr_storage &ss)
{ {
if (reinterpret_cast<const InetAddress *>(&ss) != this) if (reinterpret_cast<const InetAddress *>(&ss) != this) {
memcpy(this,&ss,sizeof(InetAddress)); memcpy(this,&ss,sizeof(InetAddress));
}
return *this; return *this;
} }
inline InetAddress &operator=(const struct sockaddr_storage *ss) inline InetAddress &operator=(const struct sockaddr_storage *ss)
{ {
if (reinterpret_cast<const InetAddress *>(ss) != this) if (reinterpret_cast<const InetAddress *>(ss) != this) {
memcpy(this,ss,sizeof(InetAddress)); memcpy(this,ss,sizeof(InetAddress));
}
return *this; return *this;
} }
@ -230,9 +234,10 @@ struct InetAddress : public sockaddr_storage
case AF_INET6: case AF_INET6:
const uint8_t *ipb = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr); const uint8_t *ipb = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
for(int i=0;i<16;++i) { for(int i=0;i<16;++i) {
if (ipb[i]) if (ipb[i]) {
return false; return false;
} }
}
return (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == 0); return (reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port == 0);
} }
return false; return false;
@ -398,10 +403,12 @@ struct InetAddress : public sockaddr_storage
inline bool ipsEqual(const InetAddress &a) const inline bool ipsEqual(const InetAddress &a) const
{ {
if (ss_family == a.ss_family) { if (ss_family == a.ss_family) {
if (ss_family == AF_INET) if (ss_family == AF_INET) {
return (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr); return (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr);
if (ss_family == AF_INET6) }
if (ss_family == AF_INET6) {
return (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0); return (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr,16) == 0);
}
return (memcmp(this,&a,sizeof(InetAddress)) == 0); return (memcmp(this,&a,sizeof(InetAddress)) == 0);
} }
return false; return false;
@ -418,10 +425,12 @@ struct InetAddress : public sockaddr_storage
inline bool ipsEqual2(const InetAddress &a) const inline bool ipsEqual2(const InetAddress &a) const
{ {
if (ss_family == a.ss_family) { if (ss_family == a.ss_family) {
if (ss_family == AF_INET) if (ss_family == AF_INET) {
return (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr); return (reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr == reinterpret_cast<const struct sockaddr_in *>(&a)->sin_addr.s_addr);
if (ss_family == AF_INET6) }
if (ss_family == AF_INET6) {
return (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr, 8) == 0); return (memcmp(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr, reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr, 8) == 0);
}
return (memcmp(this,&a,sizeof(InetAddress)) == 0); return (memcmp(this,&a,sizeof(InetAddress)) == 0);
} }
return false; return false;
@ -434,14 +443,16 @@ struct InetAddress : public sockaddr_storage
} else if (ss_family == AF_INET6) { } else if (ss_family == AF_INET6) {
unsigned long tmp = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port; unsigned long tmp = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port;
const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr); const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
for(long i=0;i<16;++i) for(long i=0;i<16;++i) {
reinterpret_cast<uint8_t *>(&tmp)[i % sizeof(tmp)] ^= a[i]; reinterpret_cast<uint8_t *>(&tmp)[i % sizeof(tmp)] ^= a[i];
}
return tmp; return tmp;
} else { } else {
unsigned long tmp = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port; unsigned long tmp = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port;
const uint8_t *a = reinterpret_cast<const uint8_t *>(this); const uint8_t *a = reinterpret_cast<const uint8_t *>(this);
for(long i=0;i<(long)sizeof(InetAddress);++i) for(long i=0;i<(long)sizeof(InetAddress);++i) {
reinterpret_cast<uint8_t *>(&tmp)[i % sizeof(tmp)] ^= a[i]; reinterpret_cast<uint8_t *>(&tmp)[i % sizeof(tmp)] ^= a[i];
}
return tmp; return tmp;
} }
} }
@ -478,9 +489,10 @@ struct InetAddress : public sockaddr_storage
while ((ip0 >> 31) == (ip1 >> 31)) { while ((ip0 >> 31) == (ip1 >> 31)) {
ip0 <<= 1; ip0 <<= 1;
ip1 <<= 1; ip1 <<= 1;
if (++c == 32) if (++c == 32) {
break; break;
} }
}
} break; } break;
case AF_INET6: { case AF_INET6: {
const uint8_t *ip0 = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr); const uint8_t *ip0 = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
@ -493,8 +505,9 @@ struct InetAddress : public sockaddr_storage
uint8_t ip1b = ip1[i]; uint8_t ip1b = ip1[i];
uint8_t bit = 0x80; uint8_t bit = 0x80;
while (bit != 0) { while (bit != 0) {
if ((ip0b & bit) != (ip1b & bit)) if ((ip0b & bit) != (ip1b & bit)) {
break; break;
}
++c; ++c;
bit >>= 1; bit >>= 1;
} }

View file

@ -90,8 +90,9 @@ public:
*/ */
inline void copyTo(void *buf,unsigned int len) const inline void copyTo(void *buf,unsigned int len) const
{ {
if (len < 6) if (len < 6) {
return; return;
}
unsigned char *b = (unsigned char *)buf; unsigned char *b = (unsigned char *)buf;
*(b++) = (unsigned char)((_m >> 40) & 0xff); *(b++) = (unsigned char)((_m >> 40) & 0xff);
*(b++) = (unsigned char)((_m >> 32) & 0xff); *(b++) = (unsigned char)((_m >> 32) & 0xff);

View file

@ -39,18 +39,21 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
{ {
const Capability *sendCaps[ZT_MAX_NETWORK_CAPABILITIES]; const Capability *sendCaps[ZT_MAX_NETWORK_CAPABILITIES];
unsigned int sendCapCount = 0; unsigned int sendCapCount = 0;
for(unsigned int c=0;c<nconf.capabilityCount;++c) for(unsigned int c=0;c<nconf.capabilityCount;++c) {
sendCaps[sendCapCount++] = &(nconf.capabilities[c]); sendCaps[sendCapCount++] = &(nconf.capabilities[c]);
}
const Tag *sendTags[ZT_MAX_NETWORK_TAGS]; const Tag *sendTags[ZT_MAX_NETWORK_TAGS];
unsigned int sendTagCount = 0; unsigned int sendTagCount = 0;
for(unsigned int t=0;t<nconf.tagCount;++t) for(unsigned int t=0;t<nconf.tagCount;++t) {
sendTags[sendTagCount++] = &(nconf.tags[t]); sendTags[sendTagCount++] = &(nconf.tags[t]);
}
const CertificateOfOwnership *sendCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]; const CertificateOfOwnership *sendCoos[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
unsigned int sendCooCount = 0; unsigned int sendCooCount = 0;
for(unsigned int c=0;c<nconf.certificateOfOwnershipCount;++c) for(unsigned int c=0;c<nconf.certificateOfOwnershipCount;++c) {
sendCoos[sendCooCount++] = &(nconf.certificatesOfOwnership[c]); sendCoos[sendCooCount++] = &(nconf.certificatesOfOwnership[c]);
}
unsigned int capPtr = 0; unsigned int capPtr = 0;
unsigned int tagPtr = 0; unsigned int tagPtr = 0;
@ -115,8 +118,9 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
RR->t->credentialRejected(tPtr,com,"old"); RR->t->credentialRejected(tPtr,com,"old");
return ADD_REJECTED; return ADD_REJECTED;
} }
if (_com == com) if (_com == com) {
return ADD_ACCEPTED_REDUNDANT; return ADD_ACCEPTED_REDUNDANT;
}
switch(com.verify(RR,tPtr)) { switch(com.verify(RR,tPtr)) {
default: default:
@ -141,9 +145,10 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remot
RR->t->credentialRejected(tPtr,cred,"old"); RR->t->credentialRejected(tPtr,cred,"old");
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
} }
if (*rc == cred) if (*rc == cred) {
return Membership::ADD_ACCEPTED_REDUNDANT; return Membership::ADD_ACCEPTED_REDUNDANT;
} }
}
const int64_t *const rt = revocations.get(Membership::credentialKey(C::credentialType(),cred.id())); const int64_t *const rt = revocations.get(Membership::credentialKey(C::credentialType(),cred.id()));
if ((rt)&&(*rt >= cred.timestamp())) { if ((rt)&&(*rt >= cred.timestamp())) {
@ -156,8 +161,9 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remot
RR->t->credentialRejected(tPtr,cred,"invalid"); RR->t->credentialRejected(tPtr,cred,"invalid");
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
case 0: case 0:
if (!rc) if (!rc) {
rc = &(remoteCreds[cred.id()]); rc = &(remoteCreds[cred.id()]);
}
*rc = cred; *rc = cred;
return Membership::ADD_ACCEPTED_NEW; return Membership::ADD_ACCEPTED_NEW;
case 1: case 1:

View file

@ -115,9 +115,10 @@ public:
CertificateOfOwnership *v = (CertificateOfOwnership *)0; CertificateOfOwnership *v = (CertificateOfOwnership *)0;
Hashtable< uint32_t,CertificateOfOwnership >::Iterator i(*(const_cast< Hashtable< uint32_t,CertificateOfOwnership> *>(&_remoteCoos))); Hashtable< uint32_t,CertificateOfOwnership >::Iterator i(*(const_cast< Hashtable< uint32_t,CertificateOfOwnership> *>(&_remoteCoos)));
while (i.next(k,v)) { while (i.next(k,v)) {
if (_isCredentialTimestampValid(nconf,*v)&&(v->owns(r))) if (_isCredentialTimestampValid(nconf,*v)&&(v->owns(r))) {
return true; return true;
} }
}
return _isV6NDPEmulated(nconf,r); return _isV6NDPEmulated(nconf,r);
} }
@ -187,8 +188,9 @@ private:
break; break;
} }
} }
if (prefixMatches) if (prefixMatches) {
return true; return true;
}
break; break;
} }
} }
@ -203,8 +205,9 @@ private:
break; break;
} }
} }
if (prefixMatches) if (prefixMatches) {
return true; return true;
}
break; break;
} }
} }
@ -230,10 +233,11 @@ private:
C *v = (C *)0; C *v = (C *)0;
typename Hashtable<uint32_t,C>::Iterator i(remoteCreds); typename Hashtable<uint32_t,C>::Iterator i(remoteCreds);
while (i.next(k,v)) { while (i.next(k,v)) {
if (!_isCredentialTimestampValid(nconf,*v)) if (!_isCredentialTimestampValid(nconf,*v)) {
remoteCreds.erase(*k); remoteCreds.erase(*k);
} }
} }
}
// Last time we pushed MULTICAST_LIKE(s) // Last time we pushed MULTICAST_LIKE(s)
int64_t _lastUpdatedMulticast; int64_t _lastUpdatedMulticast;
@ -271,9 +275,10 @@ public:
inline Capability *next() inline Capability *next()
{ {
while (_hti.next(_k,_c)) { while (_hti.next(_k,_c)) {
if (_m._isCredentialTimestampValid(_nconf,*_c)) if (_m._isCredentialTimestampValid(_nconf,*_c)) {
return _c; return _c;
} }
}
return (Capability *)0; return (Capability *)0;
} }

View file

@ -92,10 +92,11 @@ public:
inline bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); } inline bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); }
inline bool operator<(const MulticastGroup &g) const inline bool operator<(const MulticastGroup &g) const
{ {
if (_mac < g._mac) if (_mac < g._mac) {
return true; return true;
else if (_mac == g._mac) } else if (_mac == g._mac) {
return (_adi < g._adi); return (_adi < g._adi);
}
return false; return false;
} }
inline bool operator>(const MulticastGroup &g) const { return (g < *this); } inline bool operator>(const MulticastGroup &g) const { return (g < *this); }

View file

@ -69,10 +69,11 @@ unsigned int Multicaster::gather(const Address &queryingPeer,uint64_t nwid,const
unsigned int added = 0,i,k,rptr,totalKnown = 0; unsigned int added = 0,i,k,rptr,totalKnown = 0;
uint64_t a,picked[(ZT_PROTO_MAX_PACKET_LENGTH / 5) + 2]; uint64_t a,picked[(ZT_PROTO_MAX_PACKET_LENGTH / 5) + 2];
if (!limit) if (!limit) {
return 0; return 0;
else if (limit > 0xffff) } else if (limit > 0xffff) {
limit = 0xffff; limit = 0xffff;
}
const unsigned int totalAt = appendTo.size(); const unsigned int totalAt = appendTo.size();
appendTo.addSize(4); // sizeof(uint32_t) appendTo.addSize(4); // sizeof(uint32_t)
@ -133,13 +134,15 @@ std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup
std::vector<Address> ls; std::vector<Address> ls;
Mutex::Lock _l(_groups_m); Mutex::Lock _l(_groups_m);
const MulticastGroupStatus *s = _groups.get(Multicaster::Key(nwid,mg)); const MulticastGroupStatus *s = _groups.get(Multicaster::Key(nwid,mg));
if (!s) if (!s) {
return ls; return ls;
}
for(std::vector<MulticastGroupMember>::const_reverse_iterator m(s->members.rbegin());m!=s->members.rend();++m) { for(std::vector<MulticastGroupMember>::const_reverse_iterator m(s->members.rbegin());m!=s->members.rend();++m) {
ls.push_back(m->address); ls.push_back(m->address);
if (ls.size() >= limit) if (ls.size() >= limit) {
break; break;
} }
}
return ls; return ls;
} }
@ -193,7 +196,9 @@ void Multicaster::send(
outp.append((uint32_t)mg.adi()); outp.append((uint32_t)mg.adi());
outp.append((uint16_t)etherType); outp.append((uint16_t)etherType);
outp.append(data,len); outp.append(data,len);
if (!network->config().disableCompression()) outp.compress(); if (!network->config().disableCompression()) {
outp.compress();
}
outp.armor(bestMulticastReplicator->key(),true,bestMulticastReplicator->aesKeysIfSupported()); outp.armor(bestMulticastReplicator->key(),true,bestMulticastReplicator->aesKeysIfSupported());
bestMulticastReplicatorPath->send(RR,tPtr,outp.data(),outp.size(),now); bestMulticastReplicatorPath->send(RR,tPtr,outp.data(),outp.size(),now);
return; return;
@ -208,12 +213,14 @@ void Multicaster::send(
if (!gs.members.empty()) { if (!gs.members.empty()) {
// Allocate a memory buffer if group is monstrous // Allocate a memory buffer if group is monstrous
if (gs.members.size() > (sizeof(idxbuf) / sizeof(unsigned long))) if (gs.members.size() > (sizeof(idxbuf) / sizeof(unsigned long))) {
indexes = new unsigned long[gs.members.size()]; indexes = new unsigned long[gs.members.size()];
}
// Generate a random permutation of member indexes // Generate a random permutation of member indexes
for(unsigned long i=0;i<gs.members.size();++i) for(unsigned long i=0;i<gs.members.size();++i) {
indexes[i] = i; indexes[i] = i;
}
for(unsigned long i=(unsigned long)gs.members.size()-1;i>0;--i) { for(unsigned long i=(unsigned long)gs.members.size()-1;i>0;--i) {
unsigned long j = (unsigned long)RR->node->prng() % (i + 1); unsigned long j = (unsigned long)RR->node->prng() % (i + 1);
unsigned long tmp = indexes[j]; unsigned long tmp = indexes[j];
@ -248,10 +255,11 @@ void Multicaster::send(
for(unsigned int i=0;i<activeBridgeCount;++i) { for(unsigned int i=0;i<activeBridgeCount;++i) {
if ((activeBridges[i] != RR->identity.address())&&(activeBridges[i] != origin)) { if ((activeBridges[i] != RR->identity.address())&&(activeBridges[i] != origin)) {
out.sendOnly(RR,tPtr,activeBridges[i]); // optimization: don't use dedup log if it's a one-pass send out.sendOnly(RR,tPtr,activeBridges[i]); // optimization: don't use dedup log if it's a one-pass send
if (++count >= limit) if (++count >= limit) {
break; break;
} }
} }
}
unsigned long idx = 0; unsigned long idx = 0;
while ((count < limit)&&(idx < gs.members.size())) { while ((count < limit)&&(idx < gs.members.size())) {
@ -276,16 +284,18 @@ void Multicaster::send(
unsigned int numExplicitGatherPeers = 0; unsigned int numExplicitGatherPeers = 0;
SharedPtr<Peer> bestRoot(RR->topology->getUpstreamPeer()); SharedPtr<Peer> bestRoot(RR->topology->getUpstreamPeer());
if (bestRoot) if (bestRoot) {
explicitGatherPeers[numExplicitGatherPeers++] = bestRoot->address(); explicitGatherPeers[numExplicitGatherPeers++] = bestRoot->address();
}
explicitGatherPeers[numExplicitGatherPeers++] = network->controller(); explicitGatherPeers[numExplicitGatherPeers++] = network->controller();
Address ac[ZT_MAX_NETWORK_SPECIALISTS]; Address ac[ZT_MAX_NETWORK_SPECIALISTS];
const unsigned int accnt = network->config().alwaysContactAddresses(ac); const unsigned int accnt = network->config().alwaysContactAddresses(ac);
unsigned int shuffled[ZT_MAX_NETWORK_SPECIALISTS]; unsigned int shuffled[ZT_MAX_NETWORK_SPECIALISTS];
for(unsigned int i=0;i<accnt;++i) for(unsigned int i=0;i<accnt;++i) {
shuffled[i] = i; shuffled[i] = i;
}
for(unsigned int i=0,k=accnt>>1;i<k;++i) { for(unsigned int i=0,k=accnt>>1;i<k;++i) {
const uint64_t x = RR->node->prng(); const uint64_t x = RR->node->prng();
const unsigned int x1 = shuffled[(unsigned int)x % accnt]; const unsigned int x1 = shuffled[(unsigned int)x % accnt];
@ -296,18 +306,20 @@ void Multicaster::send(
} }
for(unsigned int i=0;i<accnt;++i) { for(unsigned int i=0;i<accnt;++i) {
explicitGatherPeers[numExplicitGatherPeers++] = ac[shuffled[i]]; explicitGatherPeers[numExplicitGatherPeers++] = ac[shuffled[i]];
if (numExplicitGatherPeers == 16) if (numExplicitGatherPeers == 16) {
break; break;
} }
}
std::vector<Address> anchors(network->config().anchors()); std::vector<Address> anchors(network->config().anchors());
for(std::vector<Address>::const_iterator a(anchors.begin());a!=anchors.end();++a) { for(std::vector<Address>::const_iterator a(anchors.begin());a!=anchors.end();++a) {
if (*a != RR->identity.address()) { if (*a != RR->identity.address()) {
explicitGatherPeers[numExplicitGatherPeers++] = *a; explicitGatherPeers[numExplicitGatherPeers++] = *a;
if (numExplicitGatherPeers == 16) if (numExplicitGatherPeers == 16) {
break; break;
} }
} }
}
for(unsigned int k=0;k<numExplicitGatherPeers;++k) { for(unsigned int k=0;k<numExplicitGatherPeers;++k) {
const CertificateOfMembership *com = (network) ? ((network->config().com) ? &(network->config().com) : (const CertificateOfMembership *)0) : (const CertificateOfMembership *)0; const CertificateOfMembership *com = (network) ? ((network->config().com) ? &(network->config().com) : (const CertificateOfMembership *)0) : (const CertificateOfMembership *)0;
@ -317,8 +329,9 @@ void Multicaster::send(
mg.mac().appendTo(outp); mg.mac().appendTo(outp);
outp.append((uint32_t)mg.adi()); outp.append((uint32_t)mg.adi());
outp.append((uint32_t)gatherLimit); outp.append((uint32_t)gatherLimit);
if (com) if (com) {
com->serialize(outp); com->serialize(outp);
}
RR->node->expectReplyTo(outp.packetId()); RR->node->expectReplyTo(outp.packetId());
RR->sw->send(tPtr,outp,true); RR->sw->send(tPtr,outp,true);
} }
@ -340,18 +353,20 @@ void Multicaster::send(
data, data,
len); len);
if (origin) if (origin) {
out.logAsSent(origin); out.logAsSent(origin);
}
unsigned int count = 0; unsigned int count = 0;
for(unsigned int i=0;i<activeBridgeCount;++i) { for(unsigned int i=0;i<activeBridgeCount;++i) {
if (activeBridges[i] != RR->identity.address()) { if (activeBridges[i] != RR->identity.address()) {
out.sendAndLog(RR,tPtr,activeBridges[i]); out.sendAndLog(RR,tPtr,activeBridges[i]);
if (++count >= limit) if (++count >= limit) {
break; break;
} }
} }
}
unsigned long idx = 0; unsigned long idx = 0;
while ((count < limit)&&(idx < gs.members.size())) { while ((count < limit)&&(idx < gs.members.size())) {
@ -365,9 +380,10 @@ void Multicaster::send(
} catch ( ... ) {} // this is a sanity check to catch any failures and make sure indexes[] still gets deleted } catch ( ... ) {} // this is a sanity check to catch any failures and make sure indexes[] still gets deleted
// Free allocated memory buffer if any // Free allocated memory buffer if any
if (indexes != idxbuf) if (indexes != idxbuf) {
delete [] indexes; delete [] indexes;
} }
}
void Multicaster::clean(int64_t now) void Multicaster::clean(int64_t now)
{ {
@ -377,9 +393,11 @@ void Multicaster::clean(int64_t now)
Hashtable<Multicaster::Key,MulticastGroupStatus>::Iterator mm(_groups); Hashtable<Multicaster::Key,MulticastGroupStatus>::Iterator mm(_groups);
while (mm.next(k,s)) { while (mm.next(k,s)) {
for(std::list<OutboundMulticast>::iterator tx(s->txQueue.begin());tx!=s->txQueue.end();) { for(std::list<OutboundMulticast>::iterator tx(s->txQueue.begin());tx!=s->txQueue.end();) {
if ((tx->expired(now))||(tx->atLimit())) if ((tx->expired(now))||(tx->atLimit())) {
s->txQueue.erase(tx++); s->txQueue.erase(tx++);
else ++tx; } else {
++tx;
}
} }
unsigned long count = 0; unsigned long count = 0;
@ -411,8 +429,9 @@ void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup
// assumes _groups_m is locked // assumes _groups_m is locked
// Do not add self -- even if someone else returns it // Do not add self -- even if someone else returns it
if (member == RR->identity.address()) if (member == RR->identity.address()) {
return; return;
}
std::vector<MulticastGroupMember>::iterator m(std::lower_bound(gs.members.begin(),gs.members.end(),member)); std::vector<MulticastGroupMember>::iterator m(std::lower_bound(gs.members.begin(),gs.members.end(),member));
if (m != gs.members.end()) { if (m != gs.members.end()) {
@ -426,13 +445,15 @@ void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup
} }
for(std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) { for(std::list<OutboundMulticast>::iterator tx(gs.txQueue.begin());tx!=gs.txQueue.end();) {
if (tx->atLimit()) if (tx->atLimit()) {
gs.txQueue.erase(tx++); gs.txQueue.erase(tx++);
else { } else {
tx->sendIfNew(RR,tPtr,member); tx->sendIfNew(RR,tPtr,member);
if (tx->atLimit()) if (tx->atLimit()) {
gs.txQueue.erase(tx++); gs.txQueue.erase(tx++);
else ++tx; } else {
++tx;
}
} }
} }
} }

View file

@ -42,8 +42,9 @@ namespace {
// Returns true if packet appears valid; pos and proto will be set // Returns true if packet appears valid; pos and proto will be set
static inline bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto) static inline bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto)
{ {
if (frameLen < 40) if (frameLen < 40) {
return false; return false;
}
pos = 40; pos = 40;
proto = frameData[6]; proto = frameData[6];
while (pos <= frameLen) { while (pos <= frameLen) {
@ -52,8 +53,9 @@ static inline bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLe
case 43: // routing case 43: // routing
case 60: // destination options case 60: // destination options
case 135: // mobility options case 135: // mobility options
if ((pos + 8) > frameLen) if ((pos + 8) > frameLen) {
return false; // invalid! return false; // invalid!
}
proto = frameData[pos]; proto = frameData[pos];
pos += ((unsigned int)frameData[pos + 1] * 8) + 8; pos += ((unsigned int)frameData[pos + 1] * 8) + 8;
break; break;
@ -165,8 +167,9 @@ static _doZtFilterResult _doZtFilter(
case ZT_NETWORK_RULE_ACTION_TEE: case ZT_NETWORK_RULE_ACTION_TEE:
case ZT_NETWORK_RULE_ACTION_WATCH: case ZT_NETWORK_RULE_ACTION_WATCH:
case ZT_NETWORK_RULE_ACTION_REDIRECT: case ZT_NETWORK_RULE_ACTION_REDIRECT:
if (RR->identity.address() == rules[rn].v.fwd.address) if (RR->identity.address() == rules[rn].v.fwd.address) {
superAccept = true; superAccept = true;
}
break; break;
default: default:
break; break;
@ -342,7 +345,9 @@ static _doZtFilterResult _doZtFilter(
case 0x84: // SCTP case 0x84: // SCTP
case 0x88: // UDPLite case 0x88: // UDPLite
if (frameLen > (pos + 4)) { if (frameLen > (pos + 4)) {
if (rt == ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE) pos += 2; if (rt == ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE) {
pos += 2;
}
p = (int)frameData[pos++] << 8; p = (int)frameData[pos++] << 8;
p |= (int)frameData[pos]; p |= (int)frameData[pos];
} }
@ -358,8 +363,12 @@ static _doZtFilterResult _doZtFilter(
break; break;
case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: { case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: {
uint64_t cf = (inbound) ? ZT_RULE_PACKET_CHARACTERISTICS_INBOUND : 0ULL; uint64_t cf = (inbound) ? ZT_RULE_PACKET_CHARACTERISTICS_INBOUND : 0ULL;
if (macDest.isMulticast()) cf |= ZT_RULE_PACKET_CHARACTERISTICS_MULTICAST; if (macDest.isMulticast()) {
if (macDest.isBroadcast()) cf |= ZT_RULE_PACKET_CHARACTERISTICS_BROADCAST; cf |= ZT_RULE_PACKET_CHARACTERISTICS_MULTICAST;
}
if (macDest.isBroadcast()) {
cf |= ZT_RULE_PACKET_CHARACTERISTICS_BROADCAST;
}
if (ownershipVerificationMask == 1) { if (ownershipVerificationMask == 1) {
ownershipVerificationMask = 0; ownershipVerificationMask = 0;
InetAddress src; InetAddress src;
@ -386,20 +395,24 @@ static _doZtFilterResult _doZtFilter(
} }
if (inbound) { if (inbound) {
if (membership) { if (membership) {
if ((src)&&(membership->hasCertificateOfOwnershipFor<InetAddress>(nconf,src))) if ((src)&&(membership->hasCertificateOfOwnershipFor<InetAddress>(nconf,src))) {
ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED; ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED;
if (membership->hasCertificateOfOwnershipFor<MAC>(nconf,macSource)) }
if (membership->hasCertificateOfOwnershipFor<MAC>(nconf,macSource)) {
ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED; ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED;
} }
}
} else { } else {
for(unsigned int i=0;i<nconf.certificateOfOwnershipCount;++i) { for(unsigned int i=0;i<nconf.certificateOfOwnershipCount;++i) {
if ((src)&&(nconf.certificatesOfOwnership[i].owns(src))) if ((src)&&(nconf.certificatesOfOwnership[i].owns(src))) {
ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED; ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_IP_AUTHENTICATED;
if (nconf.certificatesOfOwnership[i].owns(macSource)) }
if (nconf.certificatesOfOwnership[i].owns(macSource)) {
ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED; ownershipVerificationMask |= ZT_RULE_PACKET_CHARACTERISTICS_SENDER_MAC_AUTHENTICATED;
} }
} }
} }
}
cf |= ownershipVerificationMask; cf |= ownershipVerificationMask;
if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)&&(frameData[9] == 0x06)) { if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)&&(frameData[9] == 0x06)) {
const unsigned int headerLen = 4 * (frameData[0] & 0xf); const unsigned int headerLen = 4 * (frameData[0] & 0xf);
@ -528,9 +541,11 @@ static _doZtFilterResult _doZtFilter(
rrl.log(rn,thisRuleMatches,thisSetMatches); rrl.log(rn,thisRuleMatches,thisSetMatches);
if ((rules[rn].t & 0x40)) if ((rules[rn].t & 0x40)) {
thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1)); thisSetMatches |= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
else thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1)); } else {
thisSetMatches &= (thisRuleMatches ^ ((rules[rn].t >> 7) & 1));
}
} }
return DOZTFILTER_NO_MATCH; return DOZTFILTER_NO_MATCH;
@ -552,8 +567,9 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u
_netconfFailure(NETCONF_FAILURE_NONE), _netconfFailure(NETCONF_FAILURE_NONE),
_portError(0) _portError(0)
{ {
for(int i=0;i<ZT_NETWORK_MAX_INCOMING_UPDATES;++i) for(int i=0;i<ZT_NETWORK_MAX_INCOMING_UPDATES;++i) {
_incomingConfigChunks[i].ts = 0; _incomingConfigChunks[i].ts = 0;
}
if (nconf) { if (nconf) {
this->setConfiguration(tPtr,*nconf,false); this->setConfiguration(tPtr,*nconf,false);
@ -581,9 +597,10 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u
} catch ( ... ) {} } catch ( ... ) {}
delete dict; delete dict;
if (!got) if (!got) {
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,"\n",1); RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,"\n",1);
} }
}
if (!_portInitialized) { if (!_portInitialized) {
ZT_VirtualNetworkConfig ctmp; ZT_VirtualNetworkConfig ctmp;
@ -665,14 +682,16 @@ bool Network::filterOutgoingPacket(
break; break;
} }
if (accept) if (accept) {
break; break;
} }
}
} break; } break;
case DOZTFILTER_DROP: case DOZTFILTER_DROP:
if (_config.remoteTraceTarget) if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); RR->t->networkFilter(tPtr,*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,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()
@ -709,17 +728,20 @@ bool Network::filterOutgoingPacket(
outp.compress(); outp.compress();
RR->sw->send(tPtr,outp,true); RR->sw->send(tPtr,outp,true);
if (_config.remoteTraceTarget) if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0);
}
return false; // DROP locally, since we redirected return false; // DROP locally, since we redirected
} else { } else {
if (_config.remoteTraceTarget) if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,1); RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,1);
}
return true; return true;
} }
} else { } else {
if (_config.remoteTraceTarget) if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0); RR->t->networkFilter(tPtr,*this,rrl,(localCapabilityIndex >= 0) ? &crrl : (Trace::RuleResultLog *)0,(localCapabilityIndex >= 0) ? &(_config.capabilities[localCapabilityIndex]) : (Capability *)0,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,noTee,false,0);
}
return false; return false;
} }
} }
@ -789,8 +811,9 @@ int Network::filterIncomingPacket(
} break; } break;
case DOZTFILTER_DROP: case DOZTFILTER_DROP:
if (_config.remoteTraceTarget) if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,0); RR->t->networkFilter(tPtr,*this,rrl,(Trace::RuleResultLog *)0,(Capability *)0,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,0);
}
return 0; // DROP return 0; // DROP
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()
@ -826,24 +849,27 @@ int Network::filterIncomingPacket(
outp.compress(); outp.compress();
RR->sw->send(tPtr,outp,true); RR->sw->send(tPtr,outp,true);
if (_config.remoteTraceTarget) if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(c) ? &crrl : (Trace::RuleResultLog *)0,c,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,0); RR->t->networkFilter(tPtr,*this,rrl,(c) ? &crrl : (Trace::RuleResultLog *)0,c,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,0);
}
return 0; // DROP locally, since we redirected return 0; // DROP locally, since we redirected
} }
} }
if (_config.remoteTraceTarget) if (_config.remoteTraceTarget) {
RR->t->networkFilter(tPtr,*this,rrl,(c) ? &crrl : (Trace::RuleResultLog *)0,c,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,accept); RR->t->networkFilter(tPtr,*this,rrl,(c) ? &crrl : (Trace::RuleResultLog *)0,c,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,false,true,accept);
}
return accept; return accept;
} }
bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)) {
return true; return true;
else if (includeBridgedGroups) } else if (includeBridgedGroups) {
return _multicastGroupsBehindMe.contains(mg); return _multicastGroupsBehindMe.contains(mg);
}
return false; return false;
} }
@ -860,14 +886,16 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
std::vector<MulticastGroup>::iterator i(std::lower_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg)); std::vector<MulticastGroup>::iterator i(std::lower_bound(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg));
if ( (i != _myMulticastGroups.end()) && (*i == mg) ) if ( (i != _myMulticastGroups.end()) && (*i == mg) ) {
_myMulticastGroups.erase(i); _myMulticastGroups.erase(i);
} }
}
uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr) uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr)
{ {
if (_destroyed) if (_destroyed) {
return 0; return 0;
}
const unsigned int start = ptr; const unsigned int start = ptr;
@ -894,15 +922,18 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
chunkIndex = chunk.at<uint32_t>(ptr); chunkIndex = chunk.at<uint32_t>(ptr);
ptr += 4; ptr += 4;
if (((chunkIndex + chunkLen) > totalLength)||(totalLength >= ZT_NETWORKCONFIG_DICT_CAPACITY)) // >= since we need room for a null at the end if (((chunkIndex + chunkLen) > totalLength)||(totalLength >= ZT_NETWORKCONFIG_DICT_CAPACITY)) { // >= since we need room for a null at the end
return 0; return 0;
if ((chunk[ptr] != 1)||(chunk.at<uint16_t>(ptr + 1) != ZT_C25519_SIGNATURE_LEN)) }
if ((chunk[ptr] != 1)||(chunk.at<uint16_t>(ptr + 1) != ZT_C25519_SIGNATURE_LEN)) {
return 0; return 0;
}
const uint8_t *sig = reinterpret_cast<const uint8_t *>(chunk.field(ptr + 3,ZT_C25519_SIGNATURE_LEN)); const uint8_t *sig = reinterpret_cast<const uint8_t *>(chunk.field(ptr + 3,ZT_C25519_SIGNATURE_LEN));
// We can use the signature, which is unique per chunk, to get a per-chunk ID for local deduplication use // We can use the signature, which is unique per chunk, to get a per-chunk ID for local deduplication use
for(unsigned int i=0;i<16;++i) for(unsigned int i=0;i<16;++i) {
reinterpret_cast<uint8_t *>(&chunkId)[i & 7] ^= sig[i]; reinterpret_cast<uint8_t *>(&chunkId)[i & 7] ^= sig[i];
}
// Find existing or new slot for this update and check if this is a duplicate chunk // Find existing or new slot for this update and check if this is a duplicate chunk
for(int i=0;i<ZT_NETWORK_MAX_INCOMING_UPDATES;++i) { for(int i=0;i<ZT_NETWORK_MAX_INCOMING_UPDATES;++i) {
@ -910,9 +941,10 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
c = &(_incomingConfigChunks[i]); c = &(_incomingConfigChunks[i]);
for(unsigned long j=0;j<c->haveChunks;++j) { for(unsigned long j=0;j<c->haveChunks;++j) {
if (c->haveChunkIds[j] == chunkId) if (c->haveChunkIds[j] == chunkId) {
return 0; return 0;
} }
}
break; break;
} else if ((!c)||(_incomingConfigChunks[i].ts < c->ts)) { } else if ((!c)||(_incomingConfigChunks[i].ts < c->ts)) {
@ -922,10 +954,12 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
// If it's not a duplicate, check chunk signature // If it's not a duplicate, check chunk signature
const Identity controllerId(RR->topology->getIdentity(tPtr,controller())); const Identity controllerId(RR->topology->getIdentity(tPtr,controller()));
if (!controllerId) // we should always have the controller identity by now, otherwise how would we have queried it the first time? if (!controllerId) { // we should always have the controller identity by now, otherwise how would we have queried it the first time?
return 0; return 0;
if (!controllerId.verify(chunk.field(start,ptr - start),ptr - start,sig,ZT_C25519_SIGNATURE_LEN)) }
if (!controllerId.verify(chunk.field(start,ptr - start),ptr - start,sig,ZT_C25519_SIGNATURE_LEN)) {
return 0; return 0;
}
// New properly verified chunks can be flooded "virally" through the network // New properly verified chunks can be flooded "virally" through the network
if (fastPropagate) { if (fastPropagate) {
@ -947,13 +981,15 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
totalLength = chunkLen; totalLength = chunkLen;
chunkIndex = 0; chunkIndex = 0;
if (totalLength >= ZT_NETWORKCONFIG_DICT_CAPACITY) if (totalLength >= ZT_NETWORKCONFIG_DICT_CAPACITY) {
return 0; return 0;
}
for(int i=0;i<ZT_NETWORK_MAX_INCOMING_UPDATES;++i) { for(int i=0;i<ZT_NETWORK_MAX_INCOMING_UPDATES;++i) {
if ((!c)||(_incomingConfigChunks[i].ts < c->ts)) if ((!c)||(_incomingConfigChunks[i].ts < c->ts)) {
c = &(_incomingConfigChunks[i]); c = &(_incomingConfigChunks[i]);
} }
}
} else { } else {
// Single-chunk unsigned legacy configs are only allowed from the controller itself // Single-chunk unsigned legacy configs are only allowed from the controller itself
return 0; return 0;
@ -966,8 +1002,9 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
c->haveChunks = 0; c->haveChunks = 0;
c->haveBytes = 0; c->haveBytes = 0;
} }
if (c->haveChunks >= ZT_NETWORK_MAX_UPDATE_CHUNKS) if (c->haveChunks >= ZT_NETWORK_MAX_UPDATE_CHUNKS) {
return false; return false;
}
c->haveChunkIds[c->haveChunks++] = chunkId; c->haveChunkIds[c->haveChunks++] = chunkId;
memcpy(c->data.unsafeData() + chunkIndex,chunkData,chunkLen); memcpy(c->data.unsafeData() + chunkIndex,chunkData,chunkLen);
@ -1002,15 +1039,18 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk) int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToDisk)
{ {
if (_destroyed) if (_destroyed) {
return 0; return 0;
}
// _lock is NOT locked when this is called // _lock is NOT locked when this is called
try { try {
if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id)) if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id)) {
return 0; // invalid config that is not for us or not for this network return 0; // invalid config that is not for us or not for this network
if (_config == nconf) }
if (_config == nconf) {
return 1; // OK config, but duplicate of what we already have return 1; // OK config, but duplicate of what we already have
}
ZT_VirtualNetworkConfig ctmp; ZT_VirtualNetworkConfig ctmp;
bool oldPortInitialized; bool oldPortInitialized;
@ -1050,8 +1090,9 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
void Network::requestConfiguration(void *tPtr) void Network::requestConfiguration(void *tPtr)
{ {
if (_destroyed) if (_destroyed) {
return; return;
}
if ((_id >> 56) == 0xff) { if ((_id >> 56) == 0xff) {
if ((_id & 0xffffff) == 0) { if ((_id & 0xffffff) == 0) {
@ -1152,8 +1193,9 @@ void Network::requestConfiguration(void *tPtr)
nconf->staticIpCount = 2; nconf->staticIpCount = 2;
nconf->ruleCount = 1; nconf->ruleCount = 1;
if (networkHub != 0) if (networkHub != 0) {
nconf->specialists[0] = networkHub; nconf->specialists[0] = networkHub;
}
nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,myAddress); nconf->staticIps[0] = InetAddress::makeIpv66plane(_id,myAddress);
nconf->staticIps[1].set(ipv4,4,8); nconf->staticIps[1].set(ipv4,4,8);
@ -1169,7 +1211,9 @@ void Network::requestConfiguration(void *tPtr)
nconf->name[4] = 'c'; nconf->name[4] = 'c';
nconf->name[5] = '-'; nconf->name[5] = '-';
unsigned long nn = 6; unsigned long nn = 6;
while ((nconf->name[nn] = v4ascii[nn - 6])) ++nn; while ((nconf->name[nn] = v4ascii[nn - 6])) {
++nn;
}
nconf->name[nn++] = '.'; nconf->name[nn++] = '.';
nconf->name[nn++] = '0'; nconf->name[nn++] = '0';
nconf->name[nn++] = '.'; nconf->name[nn++] = '.';
@ -1241,8 +1285,9 @@ bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer)
// comRevocationThreshold = m->comRevocationThreshold(); // comRevocationThreshold = m->comRevocationThreshold();
//} //}
if ( (_config.isPublic()) || ((m)&&(m->isAllowedOnNetwork(_config, peer->identity()))) ) { if ( (_config.isPublic()) || ((m)&&(m->isAllowedOnNetwork(_config, peer->identity()))) ) {
if (!m) if (!m) {
m = &(_membership(peer->address())); m = &(_membership(peer->address()));
}
if (m->multicastLikeGate(now)) { if (m->multicastLikeGate(now)) {
_announceMulticastGroupsTo(tPtr,peer->address(),_allMulticastGroups()); _announceMulticastGroupsTo(tPtr,peer->address(),_allMulticastGroups());
} }
@ -1267,27 +1312,31 @@ void Network::clean()
const int64_t now = RR->node->now(); const int64_t now = RR->node->now();
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
if (_destroyed) if (_destroyed) {
return; return;
}
{ {
Hashtable< MulticastGroup,uint64_t >::Iterator i(_multicastGroupsBehindMe); Hashtable< MulticastGroup,uint64_t >::Iterator i(_multicastGroupsBehindMe);
MulticastGroup *mg = (MulticastGroup *)0; MulticastGroup *mg = (MulticastGroup *)0;
uint64_t *ts = (uint64_t *)0; uint64_t *ts = (uint64_t *)0;
while (i.next(mg,ts)) { while (i.next(mg,ts)) {
if ((now - *ts) > (ZT_MULTICAST_LIKE_EXPIRE * 2)) if ((now - *ts) > (ZT_MULTICAST_LIKE_EXPIRE * 2)) {
_multicastGroupsBehindMe.erase(*mg); _multicastGroupsBehindMe.erase(*mg);
} }
} }
}
{ {
Address *a = (Address *)0; Address *a = (Address *)0;
Membership *m = (Membership *)0; Membership *m = (Membership *)0;
Hashtable<Address,Membership>::Iterator i(_memberships); Hashtable<Address,Membership>::Iterator i(_memberships);
while (i.next(a,m)) { while (i.next(a,m)) {
if (!RR->topology->getPeerNoCache(*a)) if (!RR->topology->getPeerNoCache(*a)) {
_memberships.erase(*a); _memberships.erase(*a);
else m->clean(now,_config); } else {
m->clean(now,_config);
}
} }
} }
} }
@ -1322,34 +1371,38 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
{ {
Hashtable<MAC,Address>::Iterator i(_remoteBridgeRoutes); Hashtable<MAC,Address>::Iterator i(_remoteBridgeRoutes);
while (i.next(m,a)) { while (i.next(m,a)) {
if (*a == maxAddr) if (*a == maxAddr) {
_remoteBridgeRoutes.erase(*m); _remoteBridgeRoutes.erase(*m);
} }
} }
} }
} }
}
void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now) void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size(); const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size();
_multicastGroupsBehindMe.set(mg,now); _multicastGroupsBehindMe.set(mg,now);
if (tmp != _multicastGroupsBehindMe.size()) if (tmp != _multicastGroupsBehindMe.size()) {
_sendUpdatesToMembers(tPtr,&mg); _sendUpdatesToMembers(tPtr,&mg);
} }
}
Membership::AddCredentialResult Network::addCredential(void *tPtr,const CertificateOfMembership &com) Membership::AddCredentialResult Network::addCredential(void *tPtr,const CertificateOfMembership &com)
{ {
if (com.networkId() != _id) if (com.networkId() != _id) {
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
}
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
return _membership(com.issuedTo()).addCredential(RR,tPtr,_config,com); return _membership(com.issuedTo()).addCredential(RR,tPtr,_config,com);
} }
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev) Membership::AddCredentialResult Network::addCredential(void *tPtr,const Address &sentFrom,const Revocation &rev)
{ {
if (rev.networkId() != _id) if (rev.networkId() != _id) {
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
}
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
Membership &m = _membership(rev.target()); Membership &m = _membership(rev.target());
@ -1386,8 +1439,9 @@ void Network::destroy()
ZT_VirtualNetworkStatus Network::_status() const ZT_VirtualNetworkStatus Network::_status() const
{ {
// assumes _lock is locked // assumes _lock is locked
if (_portError) if (_portError) {
return ZT_NETWORK_STATUS_PORT_ERROR; return ZT_NETWORK_STATUS_PORT_ERROR;
}
switch(_netconfFailure) { switch(_netconfFailure) {
case NETCONF_FAILURE_ACCESS_DENIED: case NETCONF_FAILURE_ACCESS_DENIED:
return ZT_NETWORK_STATUS_ACCESS_DENIED; return ZT_NETWORK_STATUS_ACCESS_DENIED;
@ -1407,9 +1461,11 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
// assumes _lock is locked // assumes _lock is locked
ec->nwid = _id; ec->nwid = _id;
ec->mac = _mac.toInt(); ec->mac = _mac.toInt();
if (_config) if (_config) {
Utils::scopy(ec->name,sizeof(ec->name),_config.name); Utils::scopy(ec->name,sizeof(ec->name),_config.name);
else ec->name[0] = (char)0; } else {
ec->name[0] = (char)0;
}
ec->status = _status(); ec->status = _status();
ec->type = (_config) ? (_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE; ec->type = (_config) ? (_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE;
ec->mtu = (_config) ? _config.mtu : ZT_DEFAULT_MTU; ec->mtu = (_config) ? _config.mtu : ZT_DEFAULT_MTU;
@ -1466,24 +1522,29 @@ void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMu
const int64_t now = RR->node->now(); const int64_t now = RR->node->now();
std::vector<MulticastGroup> groups; std::vector<MulticastGroup> groups;
if (newMulticastGroup) if (newMulticastGroup) {
groups.push_back(*newMulticastGroup); groups.push_back(*newMulticastGroup);
else groups = _allMulticastGroups(); } else {
groups = _allMulticastGroups();
}
std::vector<Address> alwaysAnnounceTo; std::vector<Address> alwaysAnnounceTo;
if ((newMulticastGroup)||((now - _lastAnnouncedMulticastGroupsUpstream) >= ZT_MULTICAST_ANNOUNCE_PERIOD)) { if ((newMulticastGroup)||((now - _lastAnnouncedMulticastGroupsUpstream) >= ZT_MULTICAST_ANNOUNCE_PERIOD)) {
if (!newMulticastGroup) if (!newMulticastGroup) {
_lastAnnouncedMulticastGroupsUpstream = now; _lastAnnouncedMulticastGroupsUpstream = now;
}
alwaysAnnounceTo = _config.alwaysContactAddresses(); alwaysAnnounceTo = _config.alwaysContactAddresses();
if (std::find(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),controller()) == alwaysAnnounceTo.end()) if (std::find(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),controller()) == alwaysAnnounceTo.end()) {
alwaysAnnounceTo.push_back(controller()); alwaysAnnounceTo.push_back(controller());
}
const std::vector<Address> upstreams(RR->topology->upstreamAddresses()); const std::vector<Address> upstreams(RR->topology->upstreamAddresses());
for(std::vector<Address>::const_iterator a(upstreams.begin());a!=upstreams.end();++a) { for(std::vector<Address>::const_iterator a(upstreams.begin());a!=upstreams.end();++a) {
if (std::find(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),*a) == alwaysAnnounceTo.end()) if (std::find(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),*a) == alwaysAnnounceTo.end()) {
alwaysAnnounceTo.push_back(*a); alwaysAnnounceTo.push_back(*a);
} }
}
std::sort(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end()); std::sort(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end());
for(std::vector<Address>::const_iterator a(alwaysAnnounceTo.begin());a!=alwaysAnnounceTo.end();++a) { for(std::vector<Address>::const_iterator a(alwaysAnnounceTo.begin());a!=alwaysAnnounceTo.end();++a) {
@ -1511,12 +1572,13 @@ void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMu
while (i.next(a,m)) { while (i.next(a,m)) {
const Identity remoteIdentity(RR->topology->getIdentity(tPtr, *a)); const Identity remoteIdentity(RR->topology->getIdentity(tPtr, *a));
if (remoteIdentity) { if (remoteIdentity) {
if ( ( m->multicastLikeGate(now) || (newMulticastGroup) ) && (m->isAllowedOnNetwork(_config, remoteIdentity)) && (!std::binary_search(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),*a)) ) if ( ( m->multicastLikeGate(now) || (newMulticastGroup) ) && (m->isAllowedOnNetwork(_config, remoteIdentity)) && (!std::binary_search(alwaysAnnounceTo.begin(),alwaysAnnounceTo.end(),*a)) ) {
_announceMulticastGroupsTo(tPtr,*a,groups); _announceMulticastGroupsTo(tPtr,*a,groups);
} }
} }
} }
} }
}
void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups) void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups)
{ {
@ -1551,8 +1613,9 @@ std::vector<MulticastGroup> Network::_allMulticastGroups() const
mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1); mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1);
mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end()); mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end());
_multicastGroupsBehindMe.appendKeys(mgs); _multicastGroupsBehindMe.appendKeys(mgs);
if ((_config)&&(_config.enableBroadcast())) if ((_config)&&(_config.enableBroadcast())) {
mgs.push_back(Network::BROADCAST); mgs.push_back(Network::BROADCAST);
}
std::sort(mgs.begin(),mgs.end()); std::sort(mgs.begin(),mgs.end());
mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end()); mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end());
return mgs; return mgs;

View file

@ -332,8 +332,9 @@ public:
*/ */
inline Membership::AddCredentialResult addCredential(void *tPtr,const Capability &cap) inline Membership::AddCredentialResult addCredential(void *tPtr,const Capability &cap)
{ {
if (cap.networkId() != _id) if (cap.networkId() != _id) {
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
}
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
return _membership(cap.issuedTo()).addCredential(RR,tPtr,_config,cap); return _membership(cap.issuedTo()).addCredential(RR,tPtr,_config,cap);
} }
@ -343,8 +344,9 @@ public:
*/ */
inline Membership::AddCredentialResult addCredential(void *tPtr,const Tag &tag) inline Membership::AddCredentialResult addCredential(void *tPtr,const Tag &tag)
{ {
if (tag.networkId() != _id) if (tag.networkId() != _id) {
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
}
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
return _membership(tag.issuedTo()).addCredential(RR,tPtr,_config,tag); return _membership(tag.issuedTo()).addCredential(RR,tPtr,_config,tag);
} }
@ -359,8 +361,9 @@ public:
*/ */
inline Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfOwnership &coo) inline Membership::AddCredentialResult addCredential(void *tPtr,const CertificateOfOwnership &coo)
{ {
if (coo.networkId() != _id) if (coo.networkId() != _id) {
return Membership::ADD_REJECTED; return Membership::ADD_REJECTED;
}
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
return _membership(coo.issuedTo()).addCredential(RR,tPtr,_config,coo); return _membership(coo.issuedTo()).addCredential(RR,tPtr,_config,coo);
} }
@ -377,9 +380,10 @@ public:
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
Membership &m = _membership(to); Membership &m = _membership(to);
const int64_t lastPushed = m.lastPushedCredentials(); const int64_t lastPushed = m.lastPushedCredentials();
if ((lastPushed < _lastConfigUpdate)||((now - lastPushed) > ZT_PEER_CREDENTIALS_REQUEST_RATE_LIMIT)) if ((lastPushed < _lastConfigUpdate)||((now - lastPushed) > ZT_PEER_CREDENTIALS_REQUEST_RATE_LIMIT)) {
m.pushCredentials(RR,tPtr,now,to,_config); m.pushCredentials(RR,tPtr,now,to,_config);
} }
}
/** /**
* Push credentials if we haven't done so in a very long time * Push credentials if we haven't done so in a very long time
@ -393,9 +397,10 @@ public:
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
Membership &m = _membership(to); Membership &m = _membership(to);
const int64_t lastPushed = m.lastPushedCredentials(); const int64_t lastPushed = m.lastPushedCredentials();
if ((lastPushed < _lastConfigUpdate)||((now - lastPushed) > ZT_PEER_ACTIVITY_TIMEOUT)) if ((lastPushed < _lastConfigUpdate)||((now - lastPushed) > ZT_PEER_ACTIVITY_TIMEOUT)) {
m.pushCredentials(RR,tPtr,now,to,_config); m.pushCredentials(RR,tPtr,now,to,_config);
} }
}
/** /**
* Destroy this network * Destroy this network

View file

@ -29,48 +29,84 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
// Try to put the more human-readable fields first // Try to put the more human-readable fields first
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION)) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,this->networkId)) return false; return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,this->timestamp)) return false; }
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID,this->networkId)) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision)) return false; return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString(tmp2))) return false; }
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET,this->remoteTraceTarget.toString(tmp2))) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,this->timestamp)) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL,(uint64_t)this->remoteTraceLevel)) return false; return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags)) return false; }
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta)) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) return false; return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) return false; }
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU,(uint64_t)this->mtu)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString(tmp2))) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET,this->remoteTraceTarget.toString(tmp2))) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL,(uint64_t)this->remoteTraceLevel)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MTU,(uint64_t)this->mtu)) {
return false;
}
#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF #ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
if (includeLegacy) { if (includeLegacy) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST_OLD,this->enableBroadcast())) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST_OLD,this->enableBroadcast())) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD,this->isPrivate())) return false; return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD,this->isPrivate())) {
return false;
}
std::string v4s; std::string v4s;
for(unsigned int i=0;i<staticIpCount;++i) { for(unsigned int i=0;i<staticIpCount;++i) {
if (this->staticIps[i].ss_family == AF_INET) { if (this->staticIps[i].ss_family == AF_INET) {
if (v4s.length() > 0) if (v4s.length() > 0) {
v4s.push_back(','); v4s.push_back(',');
}
char buf[64]; char buf[64];
v4s.append(this->staticIps[i].toString(buf)); v4s.append(this->staticIps[i].toString(buf));
} }
} }
if (v4s.length() > 0) { if (v4s.length() > 0) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD,v4s.c_str())) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD,v4s.c_str())) {
return false;
}
} }
std::string v6s; std::string v6s;
for(unsigned int i=0;i<staticIpCount;++i) { for(unsigned int i=0;i<staticIpCount;++i) {
if (this->staticIps[i].ss_family == AF_INET6) { if (this->staticIps[i].ss_family == AF_INET6) {
if (v6s.length() > 0) if (v6s.length() > 0) {
v6s.push_back(','); v6s.push_back(',');
}
char buf[64]; char buf[64];
v6s.append(this->staticIps[i].toString(buf)); v6s.append(this->staticIps[i].toString(buf));
} }
} }
if (v6s.length() > 0) { if (v6s.length() > 0) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD,v6s.c_str())) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD,v6s.c_str())) {
return false;
}
} }
std::string ets; std::string ets;
@ -82,8 +118,9 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
et = rules[i].v.etherType; et = rules[i].v.etherType;
} else if (rt == ZT_NETWORK_RULE_ACTION_ACCEPT) { } else if (rt == ZT_NETWORK_RULE_ACTION_ACCEPT) {
if (((int)lastrt < 32)||(lastrt == ZT_NETWORK_RULE_MATCH_ETHERTYPE)) { if (((int)lastrt < 32)||(lastrt == ZT_NETWORK_RULE_MATCH_ETHERTYPE)) {
if (ets.length() > 0) if (ets.length() > 0) {
ets.push_back(','); ets.push_back(',');
}
char tmp2[16] = {0}; char tmp2[16] = {0};
ets.append(Utils::hex((uint16_t)et,tmp2)); ets.append(Utils::hex((uint16_t)et,tmp2));
} }
@ -92,24 +129,31 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
lastrt = rt; lastrt = rt;
} }
if (ets.length() > 0) { if (ets.length() > 0) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES_OLD,ets.c_str())) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES_OLD,ets.c_str())) {
return false;
}
} }
if (this->com) { if (this->com) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD,this->com.toString().c_str())) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD,this->com.toString().c_str())) {
return false;
}
} }
std::string ab; std::string ab;
for(unsigned int i=0;i<this->specialistCount;++i) { for(unsigned int i=0;i<this->specialistCount;++i) {
if ((this->specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) { if ((this->specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) {
if (ab.length() > 0) if (ab.length() > 0) {
ab.push_back(','); ab.push_back(',');
}
char tmp2[16] = {0}; char tmp2[16] = {0};
ab.append(Address(this->specialists[i]).toString(tmp2)); ab.append(Address(this->specialists[i]).toString(tmp2));
} }
} }
if (ab.length() > 0) { if (ab.length() > 0) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES_OLD,ab.c_str())) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES_OLD,ab.c_str())) {
return false;
}
} }
} }
#endif // ZT_SUPPORT_OLD_STYLE_NETCONF #endif // ZT_SUPPORT_OLD_STYLE_NETCONF
@ -119,35 +163,49 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
if (this->com) { if (this->com) {
tmp->clear(); tmp->clear();
this->com.serialize(*tmp); this->com.serialize(*tmp);
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) {
return false;
}
} }
tmp->clear(); tmp->clear();
for(unsigned int i=0;i<this->capabilityCount;++i) for(unsigned int i=0;i<this->capabilityCount;++i) {
this->capabilities[i].serialize(*tmp); this->capabilities[i].serialize(*tmp);
}
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) {
return false;
}
} }
tmp->clear(); tmp->clear();
for(unsigned int i=0;i<this->tagCount;++i) for(unsigned int i=0;i<this->tagCount;++i) {
this->tags[i].serialize(*tmp); this->tags[i].serialize(*tmp);
}
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS,*tmp)) {
return false;
}
} }
tmp->clear(); tmp->clear();
for(unsigned int i=0;i<this->certificateOfOwnershipCount;++i) for(unsigned int i=0;i<this->certificateOfOwnershipCount;++i) {
this->certificatesOfOwnership[i].serialize(*tmp); this->certificatesOfOwnership[i].serialize(*tmp);
}
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) {
return false;
}
} }
tmp->clear(); tmp->clear();
for(unsigned int i=0;i<this->specialistCount;++i) for(unsigned int i=0;i<this->specialistCount;++i) {
tmp->append((uint64_t)this->specialists[i]); tmp->append((uint64_t)this->specialists[i]);
}
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) {
return false;
}
} }
tmp->clear(); tmp->clear();
@ -158,50 +216,83 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
tmp->append((uint16_t)this->routes[i].metric); tmp->append((uint16_t)this->routes[i].metric);
} }
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ROUTES,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ROUTES,*tmp)) {
return false;
}
} }
tmp->clear(); tmp->clear();
for(unsigned int i=0;i<this->staticIpCount;++i) for(unsigned int i=0;i<this->staticIpCount;++i) {
this->staticIps[i].serialize(*tmp); this->staticIps[i].serialize(*tmp);
}
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS,*tmp)) {
return false;
}
} }
if (this->ruleCount) { if (this->ruleCount) {
tmp->clear(); tmp->clear();
Capability::serializeRules(*tmp,rules,ruleCount); Capability::serializeRules(*tmp,rules,ruleCount);
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_RULES,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_RULES,*tmp)) {
return false;
}
} }
} }
tmp->clear(); tmp->clear();
DNS::serializeDNS(*tmp, &dns); DNS::serializeDNS(*tmp, &dns);
if (tmp->size()) { if (tmp->size()) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_DNS,*tmp)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_DNS,*tmp)) {
return false;
}
} }
if (this->ssoVersion == 0) { if (this->ssoVersion == 0) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_ENABLED, this->ssoEnabled)) return false; return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_ENABLED, this->ssoEnabled)) {
return false;
}
if (this->ssoEnabled) { if (this->ssoEnabled) {
if (this->authenticationURL[0]) { if (this->authenticationURL[0]) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL)) {
return false;
}
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_EXPIRY_TIME, this->authenticationExpiryTime)) {
return false;
} }
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_EXPIRY_TIME, this->authenticationExpiryTime)) return false;
} }
} else if(this->ssoVersion == 1) { } else if(this->ssoVersion == 1) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_VERSION, this->ssoVersion)) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_ENABLED, this->ssoEnabled)) return false; return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_ENABLED, this->ssoEnabled)) {
return false;
}
//if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL)) return false; //if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_AUTHENTICATION_URL, this->authenticationURL)) return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUER_URL, this->issuerURL)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUER_URL, this->issuerURL)) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CENTRAL_ENDPOINT_URL, this->centralAuthURL)) return false; return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NONCE, this->ssoNonce)) return false; }
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATE, this->ssoState)) return false; if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CENTRAL_ENDPOINT_URL, this->centralAuthURL)) {
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CLIENT_ID, this->ssoClientID)) return false; return false;
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_PROVIDER, this->ssoProvider)) return false; }
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NONCE, this->ssoNonce)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATE, this->ssoState)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CLIENT_ID, this->ssoClientID)) {
return false;
}
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SSO_PROVIDER, this->ssoProvider)) {
return false;
}
} }
delete tmp; delete tmp;
@ -241,39 +332,47 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name,sizeof(this->name)); d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name,sizeof(this->name));
this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU,ZT_DEFAULT_MTU); this->mtu = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MTU,ZT_DEFAULT_MTU);
if (this->mtu < 1280) if (this->mtu < 1280) {
this->mtu = 1280; // minimum MTU allowed by IPv6 standard and others this->mtu = 1280; // minimum MTU allowed by IPv6 standard and others
else if (this->mtu > ZT_MAX_MTU) } else if (this->mtu > ZT_MAX_MTU) {
this->mtu = ZT_MAX_MTU; this->mtu = ZT_MAX_MTU;
}
if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION,0) < 6) { if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION,0) < 6) {
#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF #ifdef ZT_SUPPORT_OLD_STYLE_NETCONF
char tmp2[1024] = {0}; char tmp2[1024] = {0};
// Decode legacy fields if version is old // Decode legacy fields if version is old
if (d.getB(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST_OLD)) if (d.getB(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST_OLD)) {
this->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST; this->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST;
}
this->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; // always enable for old-style netconf this->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION; // always enable for old-style netconf
this->type = (d.getB(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD,true)) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC; this->type = (d.getB(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD,true)) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC;
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD,tmp2,sizeof(tmp2)) > 0) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD,tmp2,sizeof(tmp2)) > 0) {
char *saveptr = (char *)0; char *saveptr = (char *)0;
for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) { for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
if (this->staticIpCount >= ZT_MAX_ZT_ASSIGNED_ADDRESSES) break; if (this->staticIpCount >= ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
break;
}
InetAddress ip(f); InetAddress ip(f);
if (!ip.isNetwork()) if (!ip.isNetwork()) {
this->staticIps[this->staticIpCount++] = ip; this->staticIps[this->staticIpCount++] = ip;
} }
} }
}
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD,tmp2,sizeof(tmp2)) > 0) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD,tmp2,sizeof(tmp2)) > 0) {
char *saveptr = (char *)0; char *saveptr = (char *)0;
for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) { for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
if (this->staticIpCount >= ZT_MAX_ZT_ASSIGNED_ADDRESSES) break; if (this->staticIpCount >= ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
break;
}
InetAddress ip(f); InetAddress ip(f);
if (!ip.isNetwork()) if (!ip.isNetwork()) {
this->staticIps[this->staticIpCount++] = ip; this->staticIps[this->staticIpCount++] = ip;
} }
} }
}
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD,tmp2,sizeof(tmp2)) > 0) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD,tmp2,sizeof(tmp2)) > 0) {
this->com.fromString(tmp2); this->com.fromString(tmp2);
@ -283,7 +382,9 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
char *saveptr = (char *)0; char *saveptr = (char *)0;
for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) { for(char *f=Utils::stok(tmp2,",",&saveptr);(f);f=Utils::stok((char *)0,",",&saveptr)) {
unsigned int et = Utils::hexStrToUInt(f) & 0xffff; unsigned int et = Utils::hexStrToUInt(f) & 0xffff;
if ((this->ruleCount + 2) > ZT_MAX_NETWORK_RULES) break; if ((this->ruleCount + 2) > ZT_MAX_NETWORK_RULES) {
break;
}
if (et > 0) { if (et > 0) {
this->rules[this->ruleCount].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE; this->rules[this->ruleCount].t = (uint8_t)ZT_NETWORK_RULE_MATCH_ETHERTYPE;
this->rules[this->ruleCount].v.etherType = (uint16_t)et; this->rules[this->ruleCount].v.etherType = (uint16_t)et;
@ -311,8 +412,9 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,0); this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,0);
this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)ZT_NETWORK_TYPE_PRIVATE); this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)ZT_NETWORK_TYPE_PRIVATE);
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) if (d.get(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) {
this->com.deserialize(*tmp,0); this->com.deserialize(*tmp,0);
}
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) {
try { try {
@ -341,9 +443,9 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) {
unsigned int p = 0; unsigned int p = 0;
while (p < tmp->size()) { while (p < tmp->size()) {
if (certificateOfOwnershipCount < ZT_MAX_CERTIFICATES_OF_OWNERSHIP) if (certificateOfOwnershipCount < ZT_MAX_CERTIFICATES_OF_OWNERSHIP) {
p += certificatesOfOwnership[certificateOfOwnershipCount++].deserialize(*tmp,p); p += certificatesOfOwnership[certificateOfOwnershipCount++].deserialize(*tmp,p);
else { } else {
CertificateOfOwnership foo; CertificateOfOwnership foo;
p += foo.deserialize(*tmp,p); p += foo.deserialize(*tmp,p);
} }
@ -353,8 +455,9 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) { if (d.get(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) {
unsigned int p = 0; unsigned int p = 0;
while ((p + 8) <= tmp->size()) { while ((p + 8) <= tmp->size()) {
if (specialistCount < ZT_MAX_NETWORK_SPECIALISTS) if (specialistCount < ZT_MAX_NETWORK_SPECIALISTS) {
this->specialists[this->specialistCount++] = tmp->at<uint64_t>(p); this->specialists[this->specialistCount++] = tmp->at<uint64_t>(p);
}
p += 8; p += 8;
} }
} }

View file

@ -356,9 +356,10 @@ public:
{ {
std::vector<Address> r; std::vector<Address> r;
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) {
r.push_back(Address(specialists[i])); r.push_back(Address(specialists[i]));
} }
}
return r; return r;
} }
@ -366,18 +367,20 @@ public:
{ {
unsigned int c = 0; unsigned int c = 0;
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) {
ab[c++] = specialists[i]; ab[c++] = specialists[i];
} }
}
return c; return c;
} }
inline bool isActiveBridge(const Address &a) const inline bool isActiveBridge(const Address &a) const
{ {
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if (((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)&&(a == specialists[i])) if (((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)&&(a == specialists[i])) {
return true; return true;
} }
}
return false; return false;
} }
@ -385,9 +388,10 @@ public:
{ {
std::vector<Address> r; std::vector<Address> r;
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR) != 0) if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR) != 0) {
r.push_back(Address(specialists[i])); r.push_back(Address(specialists[i]));
} }
}
return r; return r;
} }
@ -395,9 +399,10 @@ public:
{ {
std::vector<Address> r; std::vector<Address> r;
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0) if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0) {
r.push_back(Address(specialists[i])); r.push_back(Address(specialists[i]));
} }
}
return r; return r;
} }
@ -405,18 +410,20 @@ public:
{ {
unsigned int c = 0; unsigned int c = 0;
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0) if ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0) {
mr[c++] = specialists[i]; mr[c++] = specialists[i];
} }
}
return c; return c;
} }
inline bool isMulticastReplicator(const Address &a) const inline bool isMulticastReplicator(const Address &a) const
{ {
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if (((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0)&&(a == specialists[i])) if (((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0)&&(a == specialists[i])) {
return true; return true;
} }
}
return false; return false;
} }
@ -424,9 +431,10 @@ public:
{ {
std::vector<Address> r; std::vector<Address> r;
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) {
r.push_back(Address(specialists[i])); r.push_back(Address(specialists[i]));
} }
}
return r; return r;
} }
@ -434,9 +442,10 @@ public:
{ {
unsigned int c = 0; unsigned int c = 0;
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) if ((specialists[i] & (ZT_NETWORKCONFIG_SPECIALIST_TYPE_ANCHOR | ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR)) != 0) {
ac[c++] = specialists[i]; ac[c++] = specialists[i];
} }
}
return c; return c;
} }
@ -456,9 +465,10 @@ public:
inline bool permitsBridging(const Address &fromPeer) const inline bool permitsBridging(const Address &fromPeer) const
{ {
for(unsigned int i=0;i<specialistCount;++i) { for(unsigned int i=0;i<specialistCount;++i) {
if ((fromPeer == specialists[i])&&((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)) if ((fromPeer == specialists[i])&&((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)) {
return true; return true;
} }
}
return false; return false;
} }
@ -495,18 +505,20 @@ public:
const Capability *capability(const uint32_t id) const const Capability *capability(const uint32_t id) const
{ {
for(unsigned int i=0;i<capabilityCount;++i) { for(unsigned int i=0;i<capabilityCount;++i) {
if (capabilities[i].id() == id) if (capabilities[i].id() == id) {
return &(capabilities[i]); return &(capabilities[i]);
} }
}
return (Capability *)0; return (Capability *)0;
} }
const Tag *tag(const uint32_t id) const const Tag *tag(const uint32_t id) const
{ {
for(unsigned int i=0;i<tagCount;++i) { for(unsigned int i=0;i<tagCount;++i) {
if (tags[i].id() == id) if (tags[i].id() == id) {
return &(tags[i]); return &(tags[i]);
} }
}
return (Tag *)0; return (Tag *)0;
} }

View file

@ -54,8 +54,9 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
_lastMemoizedTraceSettings(0), _lastMemoizedTraceSettings(0),
_lowBandwidthMode(false) _lowBandwidthMode(false)
{ {
if (callbacks->version != 0) if (callbacks->version != 0) {
throw ZT_EXCEPTION_INVALID_ARGUMENT; throw ZT_EXCEPTION_INVALID_ARGUMENT;
}
memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks)); memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks));
// Initialize non-cryptographic PRNG from a good random source // Initialize non-cryptographic PRNG from a good random source
@ -96,10 +97,11 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
idtmp[1] = 0; idtmp[1] = 0;
n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1);
if ((n > 0)&&(n < (int)sizeof(RR->publicIdentityStr))&&(n < (int)sizeof(tmp))) { if ((n > 0)&&(n < (int)sizeof(RR->publicIdentityStr))&&(n < (int)sizeof(tmp))) {
if (memcmp(tmp,RR->publicIdentityStr,n)) if (memcmp(tmp,RR->publicIdentityStr,n)) {
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
} }
} }
}
char *m = (char *)0; char *m = (char *)0;
try { try {
@ -111,10 +113,13 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
const unsigned long bc = sizeof(Bond) + (((sizeof(Bond) & 0xf) != 0) ? (16 - (sizeof(Bond) & 0xf)) : 0); const unsigned long bc = sizeof(Bond) + (((sizeof(Bond) & 0xf) != 0) ? (16 - (sizeof(Bond) & 0xf)) : 0);
m = reinterpret_cast<char *>(::malloc(16 + ts + sws + mcs + topologys + sas + bc)); m = reinterpret_cast<char *>(::malloc(16 + ts + sws + mcs + topologys + sas + bc));
if (!m) if (!m) {
throw std::bad_alloc(); throw std::bad_alloc();
}
RR->rtmem = m; RR->rtmem = m;
while (((uintptr_t)m & 0xf) != 0) ++m; while (((uintptr_t)m & 0xf) != 0) {
++m;
}
RR->t = new (m) Trace(RR); RR->t = new (m) Trace(RR);
m += ts; m += ts;
@ -128,12 +133,24 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
m += sas; m += sas;
RR->bc = new (m) Bond(RR); RR->bc = new (m) Bond(RR);
} catch ( ... ) { } catch ( ... ) {
if (RR->sa) RR->sa->~SelfAwareness(); if (RR->sa) {
if (RR->topology) RR->topology->~Topology(); RR->sa->~SelfAwareness();
if (RR->mc) RR->mc->~Multicaster(); }
if (RR->sw) RR->sw->~Switch(); if (RR->topology) {
if (RR->t) RR->t->~Trace(); RR->topology->~Topology();
if (RR->bc) RR->bc->~Bond(); }
if (RR->mc) {
RR->mc->~Multicaster();
}
if (RR->sw) {
RR->sw->~Switch();
}
if (RR->t) {
RR->t->~Trace();
}
if (RR->bc) {
RR->bc->~Bond();
}
::free(m); ::free(m);
throw; throw;
} }
@ -147,12 +164,24 @@ Node::~Node()
Mutex::Lock _l(_networks_m); Mutex::Lock _l(_networks_m);
_networks.clear(); // destroy all networks before shutdown _networks.clear(); // destroy all networks before shutdown
} }
if (RR->sa) RR->sa->~SelfAwareness(); if (RR->sa) {
if (RR->topology) RR->topology->~Topology(); RR->sa->~SelfAwareness();
if (RR->mc) RR->mc->~Multicaster(); }
if (RR->sw) RR->sw->~Switch(); if (RR->topology) {
if (RR->t) RR->t->~Trace(); RR->topology->~Topology();
if (RR->bc) RR->bc->~Bond(); }
if (RR->mc) {
RR->mc->~Multicaster();
}
if (RR->sw) {
RR->sw->~Switch();
}
if (RR->t) {
RR->t->~Trace();
}
if (RR->bc) {
RR->bc->~Bond();
}
::free(RR->rtmem); ::free(RR->rtmem);
} }
@ -187,7 +216,9 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
if (nw) { if (nw) {
RR->sw->onLocalEthernet(tptr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength); RR->sw->onLocalEthernet(tptr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
} }
// Closure used to ping upstream and active/online peers // Closure used to ping upstream and active/online peers
@ -242,9 +273,10 @@ public:
if ((!contacted)&&(_bestCurrentUpstream)) { if ((!contacted)&&(_bestCurrentUpstream)) {
const SharedPtr<Path> up(_bestCurrentUpstream->getAppropriatePath(_now,true)); const SharedPtr<Path> up(_bestCurrentUpstream->getAppropriatePath(_now,true));
if (up) if (up) {
p->sendHELLO(_tPtr,up->localSocket(),up->address(),_now); p->sendHELLO(_tPtr,up->localSocket(),up->address(),_now);
} }
}
_alwaysContact.erase(p->address()); // after this we'll WHOIS all upstreams that remain _alwaysContact.erase(p->address()); // after this we'll WHOIS all upstreams that remain
} else if (p->isActive(_now)) { } else if (p->isActive(_now)) {
@ -302,10 +334,11 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0; std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
while (i.next(upstreamAddress,upstreamStableEndpoints)) { while (i.next(upstreamAddress,upstreamStableEndpoints)) {
SharedPtr<Peer> p(RR->topology->getPeerNoCache(*upstreamAddress)); SharedPtr<Peer> p(RR->topology->getPeerNoCache(*upstreamAddress));
if (p) if (p) {
lastReceivedFromUpstream = std::max(p->lastReceive(),lastReceivedFromUpstream); lastReceivedFromUpstream = std::max(p->lastReceive(),lastReceivedFromUpstream);
} }
} }
}
// Clean up any old local controller auth memorizations. // Clean up any old local controller auth memorizations.
{ {
@ -314,9 +347,10 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
_LocalControllerAuth *k = (_LocalControllerAuth *)0; _LocalControllerAuth *k = (_LocalControllerAuth *)0;
int64_t *v = (int64_t *)0; int64_t *v = (int64_t *)0;
while (i.next(k,v)) { while (i.next(k,v)) {
if ((*v - now) > (ZT_NETWORK_AUTOCONF_DELAY * 3)) if ((*v - now) > (ZT_NETWORK_AUTOCONF_DELAY * 3)) {
_localControllerAuthorizations.erase(*k); _localControllerAuthorizations.erase(*k);
} }
}
_localControllerAuthorizations_m.unlock(); _localControllerAuthorizations_m.unlock();
} }
@ -344,9 +378,10 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
Hashtable< Address,std::vector<InetAddress> >::Iterator i(alwaysContact); Hashtable< Address,std::vector<InetAddress> >::Iterator i(alwaysContact);
Address *upstreamAddress = (Address *)0; Address *upstreamAddress = (Address *)0;
std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0; std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
while (i.next(upstreamAddress,upstreamStableEndpoints)) while (i.next(upstreamAddress,upstreamStableEndpoints)) {
RR->sw->requestWhois(tptr,now,*upstreamAddress); RR->sw->requestWhois(tptr,now,*upstreamAddress);
} }
}
// Refresh network config or broadcast network updates to members as needed // Refresh network config or broadcast network updates to members as needed
for(std::vector< std::pair< SharedPtr<Network>,bool > >::const_iterator n(networkConfigNeeded.begin());n!=networkConfigNeeded.end();++n) { for(std::vector< std::pair< SharedPtr<Network>,bool > >::const_iterator n(networkConfigNeeded.begin());n!=networkConfigNeeded.end();++n) {
@ -361,8 +396,9 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
// Update online status, post status change as event // Update online status, post status change as event
const bool oldOnline = _online; const bool oldOnline = _online;
_online = (((now - lastReceivedFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amUpstream())); _online = (((now - lastReceivedFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amUpstream()));
if (oldOnline != _online) if (oldOnline != _online) {
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
}
} catch ( ... ) { } catch ( ... ) {
return ZT_RESULT_FATAL_ERROR_INTERNAL; return ZT_RESULT_FATAL_ERROR_INTERNAL;
} }
@ -399,8 +435,9 @@ ZT_ResultCode Node::join(uint64_t nwid,void *uptr,void *tptr)
{ {
Mutex::Lock _l(_networks_m); Mutex::Lock _l(_networks_m);
SharedPtr<Network> &nw = _networks[nwid]; SharedPtr<Network> &nw = _networks[nwid];
if (!nw) if (!nw) {
nw = SharedPtr<Network>(new Network(RR,tptr,nwid,uptr,(const NetworkConfig *)0)); nw = SharedPtr<Network>(new Network(RR,tptr,nwid,uptr,(const NetworkConfig *)0));
}
return ZT_RESULT_OK; return ZT_RESULT_OK;
} }
@ -412,17 +449,20 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr)
Mutex::Lock _l(_networks_m); Mutex::Lock _l(_networks_m);
SharedPtr<Network> *nw = _networks.get(nwid); SharedPtr<Network> *nw = _networks.get(nwid);
RR->sw->removeNetworkQoSControlBlock(nwid); RR->sw->removeNetworkQoSControlBlock(nwid);
if (!nw) if (!nw) {
return ZT_RESULT_OK; return ZT_RESULT_OK;
if (uptr) }
if (uptr) {
*uptr = (*nw)->userPtr(); *uptr = (*nw)->userPtr();
}
(*nw)->externalConfig(&ctmp); (*nw)->externalConfig(&ctmp);
(*nw)->destroy(); (*nw)->destroy();
nUserPtr = (*nw)->userPtr(); nUserPtr = (*nw)->userPtr();
} }
if (nUserPtr) if (nUserPtr) {
RR->node->configureVirtualNetworkPort(tptr,nwid,nUserPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp); RR->node->configureVirtualNetworkPort(tptr,nwid,nUserPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
}
{ {
Mutex::Lock _l(_networks_m); Mutex::Lock _l(_networks_m);
@ -443,7 +483,9 @@ ZT_ResultCode Node::multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multica
if (nw) { if (nw) {
nw->multicastSubscribe(tptr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff))); nw->multicastSubscribe(tptr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
} }
ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi) ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
@ -452,7 +494,9 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
if (nw) { if (nw) {
nw->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff))); nw->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
return ZT_RESULT_OK; return ZT_RESULT_OK;
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } else {
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
} }
ZT_ResultCode Node::orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed) ZT_ResultCode Node::orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed)
@ -486,8 +530,9 @@ ZT_PeerList *Node::peers() const
std::sort(peers.begin(),peers.end()); std::sort(peers.begin(),peers.end());
char *buf = (char *)::malloc(sizeof(ZT_PeerList) + (sizeof(ZT_Peer) * peers.size())); char *buf = (char *)::malloc(sizeof(ZT_PeerList) + (sizeof(ZT_Peer) * peers.size()));
if (!buf) if (!buf) {
return (ZT_PeerList *)0; return (ZT_PeerList *)0;
}
ZT_PeerList *pl = (ZT_PeerList *)buf; ZT_PeerList *pl = (ZT_PeerList *)buf;
pl->peers = (ZT_Peer *)(buf + sizeof(ZT_PeerList)); pl->peers = (ZT_Peer *)(buf + sizeof(ZT_PeerList));
@ -506,8 +551,9 @@ ZT_PeerList *Node::peers() const
p->versionRev = -1; p->versionRev = -1;
} }
p->latency = pi->second->latency(_now); p->latency = pi->second->latency(_now);
if (p->latency >= 0xffff) if (p->latency >= 0xffff) {
p->latency = -1; p->latency = -1;
}
p->role = RR->topology->role(pi->second->identity().address()); p->role = RR->topology->role(pi->second->identity().address());
std::vector< SharedPtr<Path> > paths(pi->second->paths(_now)); std::vector< SharedPtr<Path> > paths(pi->second->paths(_now));
@ -567,8 +613,9 @@ ZT_VirtualNetworkList *Node::networks() const
Mutex::Lock _l(_networks_m); Mutex::Lock _l(_networks_m);
char *buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * _networks.size())); char *buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * _networks.size()));
if (!buf) if (!buf) {
return (ZT_VirtualNetworkList *)0; return (ZT_VirtualNetworkList *)0;
}
ZT_VirtualNetworkList *nl = (ZT_VirtualNetworkList *)buf; ZT_VirtualNetworkList *nl = (ZT_VirtualNetworkList *)buf;
nl->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList)); nl->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList));
@ -576,17 +623,19 @@ ZT_VirtualNetworkList *Node::networks() const
Hashtable< uint64_t,SharedPtr<Network> >::Iterator i(*const_cast< Hashtable< uint64_t,SharedPtr<Network> > *>(&_networks)); Hashtable< uint64_t,SharedPtr<Network> >::Iterator i(*const_cast< Hashtable< uint64_t,SharedPtr<Network> > *>(&_networks));
uint64_t *k = (uint64_t *)0; uint64_t *k = (uint64_t *)0;
SharedPtr<Network> *v = (SharedPtr<Network> *)0; SharedPtr<Network> *v = (SharedPtr<Network> *)0;
while (i.next(k,v)) while (i.next(k,v)) {
(*v)->externalConfig(&(nl->networks[nl->networkCount++])); (*v)->externalConfig(&(nl->networks[nl->networkCount++]));
}
return nl; return nl;
} }
void Node::freeQueryResult(void *qr) void Node::freeQueryResult(void *qr)
{ {
if (qr) if (qr) {
::free(qr); ::free(qr);
} }
}
int Node::addLocalInterfaceAddress(const struct sockaddr_storage *addr) int Node::addLocalInterfaceAddress(const struct sockaddr_storage *addr)
{ {
@ -624,9 +673,10 @@ int Node::sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *d
void Node::setNetconfMaster(void *networkControllerInstance) void Node::setNetconfMaster(void *networkControllerInstance)
{ {
RR->localNetworkController = reinterpret_cast<NetworkController *>(networkControllerInstance); RR->localNetworkController = reinterpret_cast<NetworkController *>(networkControllerInstance);
if (networkControllerInstance) if (networkControllerInstance) {
RR->localNetworkController->init(RR->identity, this); RR->localNetworkController->init(RR->identity, this);
} }
}
/****************************************************************************/ /****************************************************************************/
/* Node methods used only within node/ */ /* Node methods used only within node/ */
@ -634,11 +684,13 @@ void Node::setNetconfMaster(void *networkControllerInstance)
bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress) bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress)
{ {
if (!Path::isAddressValidForPath(remoteAddress)) if (!Path::isAddressValidForPath(remoteAddress)) {
return false; return false;
}
if (RR->topology->isProhibitedEndpoint(ztaddr,remoteAddress)) if (RR->topology->isProhibitedEndpoint(ztaddr,remoteAddress)) {
return false; return false;
}
{ {
Mutex::Lock _l(_networks_m); Mutex::Lock _l(_networks_m);
@ -648,12 +700,13 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,cons
while (i.next(k,v)) { while (i.next(k,v)) {
if ((*v)->hasConfig()) { if ((*v)->hasConfig()) {
for(unsigned int k=0;k<(*v)->config().staticIpCount;++k) { for(unsigned int k=0;k<(*v)->config().staticIpCount;++k) {
if ((*v)->config().staticIps[k].containsAddress(remoteAddress)) if ((*v)->config().staticIps[k].containsAddress(remoteAddress)) {
return false; return false;
} }
} }
} }
} }
}
return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),localSocket,reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0) : true); return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),localSocket,reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0) : true);
} }
@ -694,14 +747,18 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
if (destination == RR->identity.address()) { if (destination == RR->identity.address()) {
SharedPtr<Network> n(network(nwid)); SharedPtr<Network> n(network(nwid));
if (!n) return; if (!n) {
return;
}
n->setConfiguration((void *)0,nc,true); n->setConfiguration((void *)0,nc,true);
} else { } else {
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>(); Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
try { try {
if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) { if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) {
uint64_t configUpdateId = prng(); uint64_t configUpdateId = prng();
if (!configUpdateId) ++configUpdateId; if (!configUpdateId) {
++configUpdateId;
}
const unsigned int totalSize = dconf->sizeBytes(); const unsigned int totalSize = dconf->sizeBytes();
unsigned int chunkIndex = 0; unsigned int chunkIndex = 0;
@ -745,7 +802,9 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
{ {
if (destination == RR->identity.address()) { if (destination == RR->identity.address()) {
SharedPtr<Network> n(network(rev.networkId())); SharedPtr<Network> n(network(rev.networkId()));
if (!n) return; if (!n) {
return;
}
n->addCredential((void *)0,RR->identity.address(),rev); n->addCredential((void *)0,RR->identity.address(),rev);
} else { } else {
Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS); Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
@ -763,7 +822,9 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
{ {
if (destination == RR->identity.address()) { if (destination == RR->identity.address()) {
SharedPtr<Network> n(network(nwid)); SharedPtr<Network> n(network(nwid));
if (!n) return; if (!n) {
return;
}
switch(errorCode) { switch(errorCode) {
case NetworkController::NC_ERROR_OBJECT_NOT_FOUND: case NetworkController::NC_ERROR_OBJECT_NOT_FOUND:
case NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR: case NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR:
@ -1045,9 +1106,15 @@ enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const stru
void ZT_version(int *major,int *minor,int *revision) void ZT_version(int *major,int *minor,int *revision)
{ {
if (major) *major = ZEROTIER_ONE_VERSION_MAJOR; if (major) {
if (minor) *minor = ZEROTIER_ONE_VERSION_MINOR; *major = ZEROTIER_ONE_VERSION_MAJOR;
if (revision) *revision = ZEROTIER_ONE_VERSION_REVISION; }
if (minor) {
*minor = ZEROTIER_ONE_VERSION_MINOR;
}
if (revision) {
*revision = ZEROTIER_ONE_VERSION_REVISION;
}
} }
} // extern "C" } // extern "C"

View file

@ -138,8 +138,9 @@ public:
{ {
Mutex::Lock _l(_networks_m); Mutex::Lock _l(_networks_m);
const SharedPtr<Network> *n = _networks.get(nwid); const SharedPtr<Network> *n = _networks.get(nwid);
if (n) if (n) {
return *n; return *n;
}
return SharedPtr<Network>(); return SharedPtr<Network>();
} }
@ -156,8 +157,9 @@ public:
Hashtable< uint64_t,SharedPtr<Network> >::Iterator i(*const_cast< Hashtable< uint64_t,SharedPtr<Network> > * >(&_networks)); Hashtable< uint64_t,SharedPtr<Network> >::Iterator i(*const_cast< Hashtable< uint64_t,SharedPtr<Network> > * >(&_networks));
uint64_t *k = (uint64_t *)0; uint64_t *k = (uint64_t *)0;
SharedPtr<Network> *v = (SharedPtr<Network> *)0; SharedPtr<Network> *v = (SharedPtr<Network> *)0;
while (i.next(k,v)) while (i.next(k,v)) {
nw.push_back(*v); nw.push_back(*v);
}
return nw; return nw;
} }
@ -223,9 +225,10 @@ public:
const uint32_t pid2 = (uint32_t)(packetId >> 32); const uint32_t pid2 = (uint32_t)(packetId >> 32);
const unsigned long bucket = (unsigned long)(pid2 & ZT_EXPECTING_REPLIES_BUCKET_MASK1); const unsigned long bucket = (unsigned long)(pid2 & ZT_EXPECTING_REPLIES_BUCKET_MASK1);
for(unsigned long i=0;i<=ZT_EXPECTING_REPLIES_BUCKET_MASK2;++i) { for(unsigned long i=0;i<=ZT_EXPECTING_REPLIES_BUCKET_MASK2;++i) {
if (_expectingRepliesTo[bucket][i] == pid2) if (_expectingRepliesTo[bucket][i] == pid2) {
return true; return true;
} }
}
return false; return false;
} }
@ -258,8 +261,9 @@ public:
_localControllerAuthorizations_m.lock(); _localControllerAuthorizations_m.lock();
const int64_t *const at = _localControllerAuthorizations.get(_LocalControllerAuth(nwid,addr)); const int64_t *const at = _localControllerAuthorizations.get(_LocalControllerAuth(nwid,addr));
_localControllerAuthorizations_m.unlock(); _localControllerAuthorizations_m.unlock();
if (at) if (at) {
return ((now - *at) < (ZT_NETWORK_AUTOCONF_DELAY * 3)); return ((now - *at) < (ZT_NETWORK_AUTOCONF_DELAY * 3));
}
return false; return false;
} }

View file

@ -50,20 +50,27 @@ void OutboundMulticast::init(
_frameLen = (len < ZT_MAX_MTU) ? len : ZT_MAX_MTU; _frameLen = (len < ZT_MAX_MTU) ? len : ZT_MAX_MTU;
_etherType = etherType; _etherType = etherType;
if (gatherLimit) flags |= 0x02; if (gatherLimit) {
flags |= 0x02;
}
_packet.setSource(RR->identity.address()); _packet.setSource(RR->identity.address());
_packet.setVerb(Packet::VERB_MULTICAST_FRAME); _packet.setVerb(Packet::VERB_MULTICAST_FRAME);
_packet.append((uint64_t)nwid); _packet.append((uint64_t)nwid);
_packet.append(flags); _packet.append(flags);
if (gatherLimit) _packet.append((uint32_t)gatherLimit); if (gatherLimit) {
if (src) src.appendTo(_packet); _packet.append((uint32_t)gatherLimit);
}
if (src) {
src.appendTo(_packet);
}
dest.mac().appendTo(_packet); dest.mac().appendTo(_packet);
_packet.append((uint32_t)dest.adi()); _packet.append((uint32_t)dest.adi());
_packet.append((uint16_t)etherType); _packet.append((uint16_t)etherType);
_packet.append(payload,_frameLen); _packet.append(payload,_frameLen);
if (!disableCompression) if (!disableCompression) {
_packet.compress(); _packet.compress();
}
memcpy(_frameData,payload,_frameLen); memcpy(_frameData,payload,_frameLen);
} }

View file

@ -418,7 +418,9 @@ static inline unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE
if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) {
pIn+=2; pMatch+=2; pIn+=2; pMatch+=2;
} }
if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++; if ((pIn<pInLimit) && (*pMatch == *pIn)) {
pIn++;
}
return (unsigned)(pIn - pStart); return (unsigned)(pIn - pStart);
} }
@ -438,26 +440,30 @@ static inline int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize
static inline U32 LZ4_hash4(U32 sequence, tableType_t const tableType) static inline U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
{ {
if (tableType == byU16) if (tableType == byU16) {
return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
else } else {
return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
} }
}
static inline U32 LZ4_hash5(U64 sequence, tableType_t const tableType) static inline U32 LZ4_hash5(U64 sequence, tableType_t const tableType)
{ {
static const U64 prime5bytes = 889523592379ULL; static const U64 prime5bytes = 889523592379ULL;
static const U64 prime8bytes = 11400714785074694791ULL; static const U64 prime8bytes = 11400714785074694791ULL;
const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
if (LZ4_isLittleEndian()) if (LZ4_isLittleEndian()) {
return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
else } else {
return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
} }
}
FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType)
{ {
if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); if ((sizeof(reg_t)==8) && (tableType != byU16)) {
return LZ4_hash5(LZ4_read_ARCH(p), tableType);
}
return LZ4_hash4(LZ4_read32(p), tableType); return LZ4_hash4(LZ4_read32(p), tableType);
} }
@ -537,7 +543,9 @@ FORCE_INLINE int LZ4_compress_generic(
U32 forwardH; U32 forwardH;
/* Init conditions */ /* Init conditions */
if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported inputSize, too large (or negative) */ if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) {
return 0; /* Unsupported inputSize, too large (or negative) */
}
switch(dict) { switch(dict) {
case noDict: case noDict:
default: default:
@ -553,8 +561,12 @@ FORCE_INLINE int LZ4_compress_generic(
lowLimit = (const BYTE*)source; lowLimit = (const BYTE*)source;
break; break;
} }
if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) {
if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ return 0; /* Size too large (not within 64K limit) */
}
if (inputSize<LZ4_minLength) {
goto _last_literals; /* Input too small, no compression (all literals) */
}
/* First Byte */ /* First Byte */
LZ4_putPosition(ip, cctx->hashTable, tableType, base); LZ4_putPosition(ip, cctx->hashTable, tableType, base);
@ -578,7 +590,9 @@ FORCE_INLINE int LZ4_compress_generic(
forwardIp += step; forwardIp += step;
step = (searchMatchNb++ >> LZ4_skipTrigger); step = (searchMatchNb++ >> LZ4_skipTrigger);
if (unlikely(forwardIp > mflimit)) goto _last_literals; if (unlikely(forwardIp > mflimit)) {
goto _last_literals;
}
match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base);
if (dict==usingExtDict) { if (dict==usingExtDict) {
@ -609,15 +623,19 @@ FORCE_INLINE int LZ4_compress_generic(
unsigned const litLength = (unsigned)(ip - anchor); unsigned const litLength = (unsigned)(ip - anchor);
token = op++; token = op++;
if ((outputLimited) && /* Check output buffer overflow */ if ((outputLimited) && /* Check output buffer overflow */
(unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) {
return 0; return 0;
}
if (litLength >= RUN_MASK) { if (litLength >= RUN_MASK) {
int len = (int)litLength-RUN_MASK; int len = (int)litLength-RUN_MASK;
*token = (RUN_MASK<<ML_BITS); *token = (RUN_MASK<<ML_BITS);
for(; len >= 255 ; len-=255) *op++ = 255; for(; len >= 255 ; len-=255) {
*op++ = (BYTE)len; *op++ = 255;
}
*op++ = (BYTE)len;
} else {
*token = (BYTE)(litLength<<ML_BITS);
} }
else *token = (BYTE)(litLength<<ML_BITS);
/* Copy Literals */ /* Copy Literals */
LZ4_wildCopy(op, anchor, op+litLength); LZ4_wildCopy(op, anchor, op+litLength);
@ -637,7 +655,9 @@ _next_match:
const BYTE* limit; const BYTE* limit;
match += refDelta; match += refDelta;
limit = ip + (dictEnd-match); limit = ip + (dictEnd-match);
if (limit > matchlimit) limit = matchlimit; if (limit > matchlimit) {
limit = matchlimit;
}
matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
ip += MINMATCH + matchCode; ip += MINMATCH + matchCode;
if (ip==limit) { if (ip==limit) {
@ -651,8 +671,9 @@ _next_match:
} }
if ( outputLimited && /* Check output buffer overflow */ if ( outputLimited && /* Check output buffer overflow */
(unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) ) (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) ) {
return 0; return 0;
}
if (matchCode >= ML_MASK) { if (matchCode >= ML_MASK) {
*token += ML_MASK; *token += ML_MASK;
matchCode -= ML_MASK; matchCode -= ML_MASK;
@ -664,14 +685,17 @@ _next_match:
} }
op += matchCode / 255; op += matchCode / 255;
*op++ = (BYTE)(matchCode % 255); *op++ = (BYTE)(matchCode % 255);
} else } else {
*token += (BYTE)(matchCode); *token += (BYTE)(matchCode);
} }
}
anchor = ip; anchor = ip;
/* Test end of chunk */ /* Test end of chunk */
if (ip > mflimit) break; if (ip > mflimit) {
break;
}
/* Fill table */ /* Fill table */
LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); LZ4_putPosition(ip-2, cctx->hashTable, tableType, base);
@ -705,12 +729,15 @@ _last_literals:
{ {
size_t const lastRun = (size_t)(iend - anchor); size_t const lastRun = (size_t)(iend - anchor);
if ( (outputLimited) && /* Check output buffer overflow */ if ( (outputLimited) && /* Check output buffer overflow */
((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) ) ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) ) {
return 0; return 0;
}
if (lastRun >= RUN_MASK) { if (lastRun >= RUN_MASK) {
size_t accumulator = lastRun - RUN_MASK; size_t accumulator = lastRun - RUN_MASK;
*op++ = RUN_MASK << ML_BITS; *op++ = RUN_MASK << ML_BITS;
for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; for(; accumulator >= 255 ; accumulator-=255) {
*op++ = 255;
}
*op++ = (BYTE) accumulator; *op++ = (BYTE) accumulator;
} else { } else {
*op++ = (BYTE)(lastRun<<ML_BITS); *op++ = (BYTE)(lastRun<<ML_BITS);
@ -730,17 +757,19 @@ static inline int LZ4_compress_fast_extState(void* state, const char* source, ch
//if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; //if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
if (maxOutputSize >= LZ4_compressBound(inputSize)) { if (maxOutputSize >= LZ4_compressBound(inputSize)) {
if (inputSize < LZ4_64Klimit) if (inputSize < LZ4_64Klimit) {
return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
else
return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
} else { } else {
if (inputSize < LZ4_64Klimit) return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
}
} else {
if (inputSize < LZ4_64Klimit) {
return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
else } else {
return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
} }
} }
}
static inline int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) static inline int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
{ {
@ -798,9 +827,15 @@ FORCE_INLINE int LZ4_decompress_generic(
/* Special cases */ /* Special cases */
if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ if ((partialDecoding) && (oexit > oend-MFLIMIT)) {
if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */
if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); }
if ((endOnInput) && (unlikely(outputSize==0))) {
return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
}
if ((!endOnInput) && (unlikely(outputSize==0))) {
return (*ip==0?1:-1);
}
/* Main Loop : decode sequences */ /* Main Loop : decode sequences */
while (1) { while (1) {
@ -816,8 +851,12 @@ FORCE_INLINE int LZ4_decompress_generic(
s = *ip++; s = *ip++;
length += s; length += s;
} while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) & (s==255) ); } while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) & (s==255) );
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) goto _output_error; /* overflow detection */ if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) {
if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) goto _output_error; /* overflow detection */ goto _output_error; /* overflow detection */
}
if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) {
goto _output_error; /* overflow detection */
}
} }
/* copy literals */ /* copy literals */
@ -825,11 +864,19 @@ FORCE_INLINE int LZ4_decompress_generic(
if ( ((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) if ( ((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
|| ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) { || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) {
if (partialDecoding) { if (partialDecoding) {
if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ if (cpy > oend) {
if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ goto _output_error; /* Error : write attempt beyond end of output buffer */
}
if ((endOnInput) && (ip+length > iend)) {
goto _output_error; /* Error : read attempt beyond end of input buffer */
}
} else { } else {
if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ if ((!endOnInput) && (cpy != oend)) {
if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ goto _output_error; /* Error : block decoding must stop exactly there */
}
if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) {
goto _output_error; /* Error : input must be consumed */
}
} }
memcpy(op, ip, length); memcpy(op, ip, length);
ip += length; ip += length;
@ -844,7 +891,9 @@ FORCE_INLINE int LZ4_decompress_generic(
offset = LZ4_readLE16(ip); offset = LZ4_readLE16(ip);
ip += 2; ip += 2;
match = op - offset; match = op - offset;
if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside buffers */ if ((checkOffset) && (unlikely(match < lowLimit))) {
goto _output_error; /* Error : offset outside buffers */
}
LZ4_write32(op, (U32)offset); /* costs ~1%; silence an msan warning when offset==0 */ LZ4_write32(op, (U32)offset); /* costs ~1%; silence an msan warning when offset==0 */
/* get matchlength */ /* get matchlength */
@ -853,16 +902,22 @@ FORCE_INLINE int LZ4_decompress_generic(
unsigned s; unsigned s;
do { do {
s = *ip++; s = *ip++;
if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; if ((endOnInput) && (ip > iend-LASTLITERALS)) {
goto _output_error;
}
length += s; length += s;
} while (s==255); } while (s==255);
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) {
goto _output_error; /* overflow detection */
}
} }
length += MINMATCH; length += MINMATCH;
/* check external dictionary */ /* check external dictionary */
if ((dict==usingExtDict) && (match < lowPrefix)) { if ((dict==usingExtDict) && (match < lowPrefix)) {
if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ if (unlikely(op+length > oend-LASTLITERALS)) {
goto _output_error; /* doesn't respect parsing restriction */
}
if (length <= (size_t)(lowPrefix-match)) { if (length <= (size_t)(lowPrefix-match)) {
/* match can be copied as a single segment from external dictionary */ /* match can be copied as a single segment from external dictionary */
@ -877,7 +932,9 @@ FORCE_INLINE int LZ4_decompress_generic(
if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */ if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */
BYTE* const endOfMatch = op + restSize; BYTE* const endOfMatch = op + restSize;
const BYTE* copyFrom = lowPrefix; const BYTE* copyFrom = lowPrefix;
while (op < endOfMatch) *op++ = *copyFrom++; while (op < endOfMatch) {
*op++ = *copyFrom++;
}
} else { } else {
memcpy(op, lowPrefix, restSize); memcpy(op, lowPrefix, restSize);
op += restSize; op += restSize;
@ -905,26 +962,32 @@ FORCE_INLINE int LZ4_decompress_generic(
if (unlikely(cpy>oend-12)) { if (unlikely(cpy>oend-12)) {
BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1); BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1);
if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ if (cpy > oend-LASTLITERALS) {
goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
}
if (op < oCopyLimit) { if (op < oCopyLimit) {
LZ4_wildCopy(op, match, oCopyLimit); LZ4_wildCopy(op, match, oCopyLimit);
match += oCopyLimit - op; match += oCopyLimit - op;
op = oCopyLimit; op = oCopyLimit;
} }
while (op<cpy) *op++ = *match++; while (op<cpy) {
*op++ = *match++;
}
} else { } else {
LZ4_copy8(op, match); LZ4_copy8(op, match);
if (length>16) LZ4_wildCopy(op+8, match+8, cpy); if (length>16) {
LZ4_wildCopy(op+8, match+8, cpy);
}
} }
op=cpy; /* correction */ op=cpy; /* correction */
} }
/* end of decoding */ /* end of decoding */
if (endOnInput) if (endOnInput) {
return (int) (((char*)op)-dest); /* Nb of output bytes decoded */ return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
else } else {
return (int) (((const char*)ip)-source); /* Nb of input bytes read */ return (int) (((const char*)ip)-source); /* Nb of input bytes read */
}
/* Overflow error detected */ /* Overflow error detected */
_output_error: _output_error:
return (int) (-(((const char*)ip)-source))-1; return (int) (-(((const char*)ip)-source))-1;
@ -993,8 +1056,9 @@ void Packet::armor(const void *key,bool encryptPayload,const AES aesKeys[2])
uint8_t *const payload = data + ZT_PACKET_IDX_VERB; uint8_t *const payload = data + ZT_PACKET_IDX_VERB;
const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB; const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB;
if (encryptPayload) if (encryptPayload) {
s20.crypt12(payload,payload,payloadLen); s20.crypt12(payload,payload,payloadLen);
}
uint64_t mac[2]; uint64_t mac[2];
Poly1305::compute(mac,payload,payloadLen,macKey); Poly1305::compute(mac,payload,payloadLen,macKey);
@ -1039,14 +1103,17 @@ bool Packet::dearmor(const void *key,const AES aesKeys[2])
uint64_t mac[2]; uint64_t mac[2];
Poly1305::compute(mac,payload,payloadLen,keyStream); Poly1305::compute(mac,payload,payloadLen,keyStream);
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8)) if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8)) {
return false; return false;
}
#else #else
if ((*reinterpret_cast<const uint64_t *>(data + ZT_PACKET_IDX_MAC)) != mac[0]) // also secure, constant time if ((*reinterpret_cast<const uint64_t *>(data + ZT_PACKET_IDX_MAC)) != mac[0]) { // also secure, constant time
return false; return false;
}
#endif #endif
if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) {
Salsa20::memxor(data + ZT_PACKET_IDX_VERB,reinterpret_cast<const uint8_t *>(keyStream + 8),payloadLen); Salsa20::memxor(data + ZT_PACKET_IDX_VERB,reinterpret_cast<const uint8_t *>(keyStream + 8),payloadLen);
}
} else { } else {
Salsa20 s20(mangledKey,data + ZT_PACKET_IDX_IV); Salsa20 s20(mangledKey,data + ZT_PACKET_IDX_IV);
uint64_t macKey[4]; uint64_t macKey[4];
@ -1054,15 +1121,18 @@ bool Packet::dearmor(const void *key,const AES aesKeys[2])
uint64_t mac[2]; uint64_t mac[2];
Poly1305::compute(mac,payload,payloadLen,macKey); Poly1305::compute(mac,payload,payloadLen,macKey);
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8)) if (!Utils::secureEq(mac,data + ZT_PACKET_IDX_MAC,8)) {
return false; return false;
}
#else #else
if ((*reinterpret_cast<const uint64_t *>(data + ZT_PACKET_IDX_MAC)) != mac[0]) // also secure, constant time if ((*reinterpret_cast<const uint64_t *>(data + ZT_PACKET_IDX_MAC)) != mac[0]) { // also secure, constant time
return false; return false;
}
#endif #endif
if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) {
s20.crypt12(payload,payload,payloadLen); s20.crypt12(payload,payload,payloadLen);
} }
}
return true; return true;
} }
@ -1073,7 +1143,9 @@ void Packet::cryptField(const void *key,unsigned int start,unsigned int len)
{ {
uint8_t *const data = reinterpret_cast<uint8_t *>(unsafeData()); uint8_t *const data = reinterpret_cast<uint8_t *>(unsafeData());
uint8_t iv[8]; uint8_t iv[8];
for(int i=0;i<8;++i) iv[i] = data[i]; for(int i=0;i<8;++i) {
iv[i] = data[i];
}
iv[7] &= 0xf8; // mask off least significant 3 bits of packet ID / IV since this is unset when this function gets called iv[7] &= 0xf8; // mask off least significant 3 bits of packet ID / IV since this is unset when this function gets called
Salsa20 s20(key,iv); Salsa20 s20(key,iv);
s20.crypt12(data + start,data + start,len); s20.crypt12(data + start,data + start,len);

View file

@ -461,8 +461,9 @@ public:
*/ */
inline void init(const Packet &p,unsigned int fragStart,unsigned int fragLen,unsigned int fragNo,unsigned int fragTotal) inline void init(const Packet &p,unsigned int fragStart,unsigned int fragLen,unsigned int fragNo,unsigned int fragTotal)
{ {
if ((fragStart + fragLen) > p.size()) if ((fragStart + fragLen) > p.size()) {
throw ZT_EXCEPTION_OUT_OF_BOUNDS; throw ZT_EXCEPTION_OUT_OF_BOUNDS;
}
setSize(fragLen + ZT_PROTO_MIN_FRAGMENT_LENGTH); setSize(fragLen + ZT_PROTO_MIN_FRAGMENT_LENGTH);
// NOTE: this copies both the IV/packet ID and the destination address. // NOTE: this copies both the IV/packet ID and the destination address.
@ -1217,9 +1218,11 @@ public:
*/ */
inline void setFragmented(bool f) inline void setFragmented(bool f)
{ {
if (f) if (f) {
(*this)[ZT_PACKET_IDX_FLAGS] |= (char)ZT_PROTO_FLAG_FRAGMENTED; (*this)[ZT_PACKET_IDX_FLAGS] |= (char)ZT_PROTO_FLAG_FRAGMENTED;
else (*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_FRAGMENTED); } else {
(*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_FRAGMENTED);
}
} }
/** /**
@ -1265,9 +1268,11 @@ public:
unsigned char &b = (*this)[ZT_PACKET_IDX_FLAGS]; unsigned char &b = (*this)[ZT_PACKET_IDX_FLAGS];
b = (b & 0xc7) | (unsigned char)((c << 3) & 0x38); // bits: FFCCCHHH b = (b & 0xc7) | (unsigned char)((c << 3) & 0x38); // bits: FFCCCHHH
// Set DEPRECATED "encrypted" flag -- used by pre-1.0.3 peers // Set DEPRECATED "encrypted" flag -- used by pre-1.0.3 peers
if (c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) if (c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012) {
b |= ZT_PROTO_FLAG_ENCRYPTED; b |= ZT_PROTO_FLAG_ENCRYPTED;
else b &= (~ZT_PROTO_FLAG_ENCRYPTED); } else {
b &= (~ZT_PROTO_FLAG_ENCRYPTED);
}
} }
/** /**
@ -1405,8 +1410,9 @@ private:
// IV and source/destination addresses. Using the addresses divides the // IV and source/destination addresses. Using the addresses divides the
// key space into two halves-- A->B and B->A (since order will change). // key space into two halves-- A->B and B->A (since order will change).
for(unsigned int i=0;i<18;++i) // 8 + (ZT_ADDRESS_LENGTH * 2) == 18 for(unsigned int i=0;i<18;++i) { // 8 + (ZT_ADDRESS_LENGTH * 2) == 18
out[i] = in[i] ^ d[i]; out[i] = in[i] ^ d[i];
}
// Flags, but with hop count masked off. Hop count is altered by forwarding // Flags, but with hop count masked off. Hop count is altered by forwarding
// nodes. It's one of the only parts of a packet modifiable by people // nodes. It's one of the only parts of a packet modifiable by people
@ -1419,9 +1425,10 @@ private:
out[20] = in[20] ^ (unsigned char)((size() >> 8) & 0xff); // little endian out[20] = in[20] ^ (unsigned char)((size() >> 8) & 0xff); // little endian
// Rest of raw key is used unchanged // Rest of raw key is used unchanged
for(unsigned int i=21;i<32;++i) for(unsigned int i=21;i<32;++i) {
out[i] = in[i]; out[i] = in[i];
} }
}
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -229,9 +229,10 @@ public:
// tunnels due to very spotty performance and low MTU issues over // tunnels due to very spotty performance and low MTU issues over
// these IPv6 tunnel links. // these IPv6 tunnel links.
const uint8_t *ipd = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr); const uint8_t *ipd = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&a)->sin6_addr.s6_addr);
if ((ipd[0] == 0x20)&&(ipd[1] == 0x01)&&(ipd[2] == 0x04)&&(ipd[3] == 0x70)) if ((ipd[0] == 0x20)&&(ipd[1] == 0x01)&&(ipd[2] == 0x04)&&(ipd[3] == 0x70)) {
return false; return false;
} }
}
return true; return true;
default: default:
return false; return false;

View file

@ -52,8 +52,9 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
_localMultipathSupported(false), _localMultipathSupported(false),
_lastComputedAggregateMeanLatency(0) _lastComputedAggregateMeanLatency(0)
{ {
if (!myIdentity.agree(peerIdentity,_key)) if (!myIdentity.agree(peerIdentity,_key)) {
throw ZT_EXCEPTION_INVALID_ARGUMENT; throw ZT_EXCEPTION_INVALID_ARGUMENT;
}
uint8_t ktmp[ZT_SYMMETRIC_KEY_SIZE]; uint8_t ktmp[ZT_SYMMETRIC_KEY_SIZE];
KBKDFHMACSHA384(_key,ZT_KBKDF_LABEL_AES_GMAC_SIV_K0,0,0,ktmp); KBKDFHMACSHA384(_key,ZT_KBKDF_LABEL_AES_GMAC_SIV_K0,0,0,ktmp);
@ -267,7 +268,9 @@ SharedPtr<Path> Peer::getAppropriatePath(int64_t now, bool includeExpired, int32
bestPath = i; bestPath = i;
} }
} }
} else break; } else {
break;
}
} }
if (bestPath != ZT_MAX_PEER_NETWORK_PATHS) { if (bestPath != ZT_MAX_PEER_NETWORK_PATHS) {
return _paths[bestPath].p; return _paths[bestPath].p;
@ -316,7 +319,9 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
} }
break; break;
} }
} else break; } else {
break;
}
} }
Mutex::Lock _l2(other->_paths_m); Mutex::Lock _l2(other->_paths_m);
@ -339,7 +344,9 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
} }
break; break;
} }
} else break; } else {
break;
}
} }
unsigned int mine = ZT_MAX_PEER_NETWORK_PATHS; unsigned int mine = ZT_MAX_PEER_NETWORK_PATHS;
@ -569,7 +576,9 @@ void Peer::clusterRedirect(void *tPtr,const SharedPtr<Path> &originatingPath,con
newPriority = _paths[i].priority; newPriority = _paths[i].priority;
break; break;
} }
} else break; } else {
break;
}
} }
newPriority += 2; newPriority += 2;
@ -579,8 +588,9 @@ void Peer::clusterRedirect(void *tPtr,const SharedPtr<Path> &originatingPath,con
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 (_paths[i].p) { if (_paths[i].p) {
if ((_paths[i].priority >= newPriority)&&(!_paths[i].p->address().ipsEqual2(remoteAddress))) { if ((_paths[i].priority >= newPriority)&&(!_paths[i].p->address().ipsEqual2(remoteAddress))) {
if (i != j) if (i != j) {
_paths[j] = _paths[i]; _paths[j] = _paths[i];
}
++j; ++j;
} }
} }
@ -610,7 +620,9 @@ void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddres
_paths[i].p->sent(now); _paths[i].p->sent(now);
_paths[i].lr = 0; // path will not be used unless it speaks again _paths[i].lr = 0; // path will not be used unless it speaks again
} }
} else break; } else {
break;
}
} }
} }

View file

@ -119,9 +119,12 @@ public:
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_m);
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 (_paths[i].p) { if (_paths[i].p) {
if (((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION)&&(_paths[i].p->address() == addr)) if (((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION)&&(_paths[i].p->address() == addr)) {
return true; return true;
} else break; }
} else {
break;
}
} }
return false; return false;
} }
@ -139,8 +142,9 @@ public:
inline bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force) inline bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force)
{ {
SharedPtr<Path> bp(getAppropriatePath(now,force)); SharedPtr<Path> bp(getAppropriatePath(now,force));
if (bp) if (bp) {
return bp->send(RR,tPtr,data,len,now); return bp->send(RR,tPtr,data,len,now);
}
return false; return false;
} }
@ -281,7 +285,9 @@ public:
std::vector< SharedPtr<Path> > pp; std::vector< SharedPtr<Path> > pp;
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_m);
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 (!_paths[i].p) break; if (!_paths[i].p) {
break;
}
pp.push_back(_paths[i].p); pp.push_back(_paths[i].p);
} }
return pp; return pp;
@ -334,11 +340,13 @@ public:
inline unsigned int relayQuality(const int64_t now) inline unsigned int relayQuality(const int64_t now)
{ {
const uint64_t tsr = now - _lastReceive; const uint64_t tsr = now - _lastReceive;
if (tsr >= ZT_PEER_ACTIVITY_TIMEOUT) if (tsr >= ZT_PEER_ACTIVITY_TIMEOUT) {
return (~(unsigned int)0); return (~(unsigned int)0);
}
unsigned int l = latency(now); unsigned int l = latency(now);
if (!l) if (!l) {
l = 0xffff; l = 0xffff;
}
return (l * (((unsigned int)tsr / (ZT_PEER_PING_PERIOD + 1000)) + 1)); return (l * (((unsigned int)tsr / (ZT_PEER_PING_PERIOD + 1000)) + 1));
} }
@ -380,9 +388,11 @@ public:
*/ */
inline bool rateGatePushDirectPaths(const int64_t now) inline bool rateGatePushDirectPaths(const int64_t now)
{ {
if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME) if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME) {
++_directPathPushCutoffCount; ++_directPathPushCutoffCount;
else _directPathPushCutoffCount = 0; } else {
_directPathPushCutoffCount = 0;
}
_lastDirectPathPushReceive = now; _lastDirectPathPushReceive = now;
return (_directPathPushCutoffCount < ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT); return (_directPathPushCutoffCount < ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT);
} }
@ -444,28 +454,33 @@ public:
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_m);
unsigned int pc = 0; unsigned int pc = 0;
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 (_paths[i].p) if (_paths[i].p) {
++pc; ++pc;
else break; } else {
break;
}
} }
b.append((uint16_t)pc); b.append((uint16_t)pc);
for(unsigned int i=0;i<pc;++i) for(unsigned int i=0;i<pc;++i) {
_paths[i].p->address().serialize(b); _paths[i].p->address().serialize(b);
} }
} }
}
template<unsigned int C> template<unsigned int C>
inline static SharedPtr<Peer> deserializeFromCache(int64_t now,void *tPtr,Buffer<C> &b,const RuntimeEnvironment *renv) inline static SharedPtr<Peer> deserializeFromCache(int64_t now,void *tPtr,Buffer<C> &b,const RuntimeEnvironment *renv)
{ {
try { try {
unsigned int ptr = 0; unsigned int ptr = 0;
if (b[ptr++] != 2) if (b[ptr++] != 2) {
return SharedPtr<Peer>(); return SharedPtr<Peer>();
}
Identity id; Identity id;
ptr += id.deserialize(b,ptr); ptr += id.deserialize(b,ptr);
if (!id) if (!id) {
return SharedPtr<Peer>(); return SharedPtr<Peer>();
}
SharedPtr<Peer> p(new Peer(renv,renv->identity,id)); SharedPtr<Peer> p(new Peer(renv,renv->identity,id));
@ -487,8 +502,9 @@ public:
InetAddress inaddr; InetAddress inaddr;
try { try {
ptr += inaddr.deserialize(b,ptr); ptr += inaddr.deserialize(b,ptr);
if (inaddr) if (inaddr) {
p->attemptToContactAt(tPtr,-1,inaddr,now,true); p->attemptToContactAt(tPtr,-1,inaddr,now,true);
}
} catch ( ... ) { } catch ( ... ) {
break; break;
} }

View file

@ -192,8 +192,9 @@ static inline void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
if (st->leftover) { if (st->leftover) {
size_t i = st->leftover; size_t i = st->leftover;
st->buffer[i] = 1; st->buffer[i] = 1;
for (i = i + 1; i < poly1305_block_size; i++) for (i = i + 1; i < poly1305_block_size; i++) {
st->buffer[i] = 0; st->buffer[i] = 0;
}
st->final = 1; st->final = 1;
poly1305_blocks(st, st->buffer, poly1305_block_size); poly1305_blocks(st, st->buffer, poly1305_block_size);
} }
@ -391,8 +392,9 @@ poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
if (st->leftover) { if (st->leftover) {
size_t i = st->leftover; size_t i = st->leftover;
st->buffer[i++] = 1; st->buffer[i++] = 1;
for (; i < poly1305_block_size; i++) for (; i < poly1305_block_size; i++) {
st->buffer[i] = 0; st->buffer[i] = 0;
}
st->final = 1; st->final = 1;
poly1305_blocks(st, st->buffer, poly1305_block_size); poly1305_blocks(st, st->buffer, poly1305_block_size);
} }
@ -477,15 +479,18 @@ static inline void poly1305_update(poly1305_context *ctx, const unsigned char *m
/* handle leftover */ /* handle leftover */
if (st->leftover) { if (st->leftover) {
size_t want = (poly1305_block_size - st->leftover); size_t want = (poly1305_block_size - st->leftover);
if (want > bytes) if (want > bytes) {
want = bytes; want = bytes;
for (i = 0; i < want; i++) }
for (i = 0; i < want; i++) {
st->buffer[st->leftover + i] = m[i]; st->buffer[st->leftover + i] = m[i];
}
bytes -= want; bytes -= want;
m += want; m += want;
st->leftover += want; st->leftover += want;
if (st->leftover < poly1305_block_size) if (st->leftover < poly1305_block_size) {
return; return;
}
poly1305_blocks(st, st->buffer, poly1305_block_size); poly1305_blocks(st, st->buffer, poly1305_block_size);
st->leftover = 0; st->leftover = 0;
} }
@ -500,8 +505,9 @@ static inline void poly1305_update(poly1305_context *ctx, const unsigned char *m
/* store leftover */ /* store leftover */
if (bytes) { if (bytes) {
for (i = 0; i < bytes; i++) for (i = 0; i < bytes; i++) {
st->buffer[st->leftover + i] = m[i]; st->buffer[st->leftover + i] = m[i];
}
st->leftover += bytes; st->leftover += bytes;
} }
} }

View file

@ -23,8 +23,9 @@ namespace ZeroTier {
int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const
{ {
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) {
return -1; return -1;
}
const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) { if (!id) {
RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy); RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);

View file

@ -118,7 +118,9 @@ public:
template<unsigned int C> template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const inline void serialize(Buffer<C> &b,const bool forSign = false) const
{ {
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
b.append((uint32_t)0); // 4 unused bytes, currently set to 0 b.append((uint32_t)0); // 4 unused bytes, currently set to 0
b.append(_id); b.append(_id);
@ -140,7 +142,9 @@ public:
// This is the size of any additional fields, currently 0. // This is the size of any additional fields, currently 0.
b.append((uint16_t)0); b.append((uint16_t)0);
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
} }
template<unsigned int C> template<unsigned int C>
@ -173,14 +177,17 @@ public:
p += 2; p += 2;
memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
p += ZT_C25519_SIGNATURE_LEN; p += ZT_C25519_SIGNATURE_LEN;
} else throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; } else {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
}
} else { } else {
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
} }
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
if (p > b.size()) if (p > b.size()) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
return (p - startAt); return (p - startAt);
} }

View file

@ -58,12 +58,15 @@ static ZT_INLINE void sha512_compress(sha512_state *const md,uint8_t *const buf)
uint64_t S[8], W[80], t0, t1; uint64_t S[8], W[80], t0, t1;
int i; int i;
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) {
S[i] = md->state[i]; S[i] = md->state[i];
for (i = 0; i < 16; i++) }
for (i = 0; i < 16; i++) {
LOAD64H(W[i], buf + (8*i)); LOAD64H(W[i], buf + (8*i));
for (i = 16; i < 80; i++) }
for (i = 16; i < 80; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
#define RND(a,b,c,d,e,f,g,h,i) \ #define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
@ -82,9 +85,10 @@ static ZT_INLINE void sha512_compress(sha512_state *const md,uint8_t *const buf)
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
} }
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) {
md->state[i] = md->state[i] + S[i]; md->state[i] = md->state[i] + S[i];
} }
}
static ZT_INLINE void sha384_init(sha512_state *const md) static ZT_INLINE void sha384_init(sha512_state *const md)
{ {

View file

@ -121,8 +121,9 @@ void Salsa20::crypt12(const void *in,void *out,unsigned int bytes)
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
#endif #endif
if (!bytes) if (!bytes) {
return; return;
}
#ifndef ZT_SALSA20_SSE #ifndef ZT_SALSA20_SSE
j0 = _state.i[0]; j0 = _state.i[0];
@ -145,8 +146,9 @@ void Salsa20::crypt12(const void *in,void *out,unsigned int bytes)
for (;;) { for (;;) {
if (bytes < 64) { if (bytes < 64) {
for (i = 0;i < bytes;++i) for (i = 0;i < bytes;++i) {
tmp[i] = m[i]; tmp[i] = m[i];
}
m = tmp; m = tmp;
ctarget = c; ctarget = c;
c = tmp; c = tmp;
@ -589,9 +591,10 @@ void Salsa20::crypt12(const void *in,void *out,unsigned int bytes)
if (bytes <= 64) { if (bytes <= 64) {
if (bytes < 64) { if (bytes < 64) {
for (i = 0;i < bytes;++i) for (i = 0;i < bytes;++i) {
ctarget[i] = c[i]; ctarget[i] = c[i];
} }
}
#ifndef ZT_SALSA20_SSE #ifndef ZT_SALSA20_SSE
_state.i[8] = j8; _state.i[8] = j8;
@ -620,8 +623,9 @@ void Salsa20::crypt20(const void *in,void *out,unsigned int bytes)
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
#endif #endif
if (!bytes) if (!bytes) {
return; return;
}
#ifndef ZT_SALSA20_SSE #ifndef ZT_SALSA20_SSE
j0 = _state.i[0]; j0 = _state.i[0];
@ -644,8 +648,9 @@ void Salsa20::crypt20(const void *in,void *out,unsigned int bytes)
for (;;) { for (;;) {
if (bytes < 64) { if (bytes < 64) {
for (i = 0;i < bytes;++i) for (i = 0;i < bytes;++i) {
tmp[i] = m[i]; tmp[i] = m[i];
}
m = tmp; m = tmp;
ctarget = c; ctarget = c;
c = tmp; c = tmp;
@ -1320,9 +1325,10 @@ void Salsa20::crypt20(const void *in,void *out,unsigned int bytes)
if (bytes <= 64) { if (bytes <= 64) {
if (bytes < 64) { if (bytes < 64) {
for (i = 0;i < bytes;++i) for (i = 0;i < bytes;++i) {
ctarget[i] = c[i]; ctarget[i] = c[i];
} }
}
#ifndef ZT_SALSA20_SSE #ifndef ZT_SALSA20_SSE
_state.i[8] = j8; _state.i[8] = j8;

View file

@ -61,8 +61,9 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
{ {
const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
if ((scope != reporterPhysicalAddress.ipScope())||(scope == InetAddress::IP_SCOPE_NONE)||(scope == InetAddress::IP_SCOPE_LOOPBACK)||(scope == InetAddress::IP_SCOPE_MULTICAST)) if ((scope != reporterPhysicalAddress.ipScope())||(scope == InetAddress::IP_SCOPE_NONE)||(scope == InetAddress::IP_SCOPE_LOOPBACK)||(scope == InetAddress::IP_SCOPE_MULTICAST)) {
return; return;
}
Mutex::Lock _l(_phy_m); Mutex::Lock _l(_phy_m);
PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,receivedOnLocalSocket,reporterPhysicalAddress,scope)]; PhySurfaceEntry &entry = _phy[PhySurfaceKey(reporter,receivedOnLocalSocket,reporterPhysicalAddress,scope)];
@ -83,10 +84,11 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
PhySurfaceKey *k = (PhySurfaceKey *)0; PhySurfaceKey *k = (PhySurfaceKey *)0;
PhySurfaceEntry *e = (PhySurfaceEntry *)0; PhySurfaceEntry *e = (PhySurfaceEntry *)0;
while (i.next(k,e)) { while (i.next(k,e)) {
if ((k->reporterPhysicalAddress != reporterPhysicalAddress)&&(k->scope == scope)) if ((k->reporterPhysicalAddress != reporterPhysicalAddress)&&(k->scope == scope)) {
_phy.erase(*k); _phy.erase(*k);
} }
} }
}
// Reset all paths within this scope and address family // Reset all paths within this scope and address family
_ResetWithinScope rset(tPtr,now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope); _ResetWithinScope rset(tPtr,now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope);
@ -121,9 +123,10 @@ void SelfAwareness::clean(int64_t now)
PhySurfaceKey *k = (PhySurfaceKey *)0; PhySurfaceKey *k = (PhySurfaceKey *)0;
PhySurfaceEntry *e = (PhySurfaceEntry *)0; PhySurfaceEntry *e = (PhySurfaceEntry *)0;
while (i.next(k,e)) { while (i.next(k,e)) {
if ((now - e->ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) if ((now - e->ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) {
_phy.erase(*k); _phy.erase(*k);
} }
} }
}
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -37,19 +37,21 @@ public:
~SharedPtr() ~SharedPtr()
{ {
if (_ptr) { if (_ptr) {
if (--_ptr->__refCount <= 0) if (--_ptr->__refCount <= 0) {
delete _ptr; delete _ptr;
} }
} }
}
inline SharedPtr &operator=(const SharedPtr &sp) inline SharedPtr &operator=(const SharedPtr &sp)
{ {
if (_ptr != sp._ptr) { if (_ptr != sp._ptr) {
T *p = sp._getAndInc(); T *p = sp._getAndInc();
if (_ptr) { if (_ptr) {
if (--_ptr->__refCount <= 0) if (--_ptr->__refCount <= 0) {
delete _ptr; delete _ptr;
} }
}
_ptr = p; _ptr = p;
} }
return *this; return *this;
@ -97,8 +99,9 @@ public:
inline void zero() inline void zero()
{ {
if (_ptr) { if (_ptr) {
if (--_ptr->__refCount <= 0) if (--_ptr->__refCount <= 0) {
delete _ptr; delete _ptr;
}
_ptr = (T *)0; _ptr = (T *)0;
} }
} }
@ -108,8 +111,9 @@ public:
*/ */
inline int references() inline int references()
{ {
if (_ptr) if (_ptr) {
return _ptr->__refCount.load(); return _ptr->__refCount.load();
}
return 0; return 0;
} }
@ -123,8 +127,9 @@ public:
private: private:
inline T *_getAndInc() const inline T *_getAndInc() const
{ {
if (_ptr) if (_ptr) {
++_ptr->__refCount; ++_ptr->__refCount;
}
return _ptr; return _ptr;
} }
T *_ptr; T *_ptr;

View file

@ -46,8 +46,9 @@ Switch::Switch(const RuntimeEnvironment *renv) :
// Returns true if packet appears valid; pos and proto will be set // Returns true if packet appears valid; pos and proto will be set
static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto) static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto)
{ {
if (frameLen < 40) if (frameLen < 40) {
return false; return false;
}
pos = 40; pos = 40;
proto = frameData[6]; proto = frameData[6];
while (pos <= frameLen) { while (pos <= frameLen) {
@ -56,8 +57,9 @@ static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsig
case 43: // routing case 43: // routing
case 60: // destination options case 60: // destination options
case 135: // mobility options case 135: // mobility options
if ((pos + 8) > frameLen) if ((pos + 8) > frameLen) {
return false; // invalid! return false; // invalid!
}
proto = frameData[pos]; proto = frameData[pos];
pos += ((unsigned int)frameData[pos + 1] * 8) + 8; pos += ((unsigned int)frameData[pos + 1] * 8) + 8;
break; break;
@ -88,10 +90,12 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
* locate peers with versions <1.0.4. */ * locate peers with versions <1.0.4. */
const Address beaconAddr(reinterpret_cast<const char *>(data) + 8,5); const Address beaconAddr(reinterpret_cast<const char *>(data) + 8,5);
if (beaconAddr == RR->identity.address()) if (beaconAddr == RR->identity.address()) {
return; return;
if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localSocket,fromAddr)) }
if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localSocket,fromAddr)) {
return; return;
}
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,beaconAddr)); const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,beaconAddr));
if (peer) { // we'll only respond to beacons from known peers if (peer) { // we'll only respond to beacons from known peers
if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses
@ -110,8 +114,9 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
const Address destination(fragment.destination()); const Address destination(fragment.destination());
if (destination != RR->identity.address()) { if (destination != RR->identity.address()) {
if ( (!RR->topology->amUpstream()) && (!path->trustEstablished(now)) ) if ( (!RR->topology->amUpstream()) && (!path->trustEstablished(now)) ) {
return; return;
}
if (fragment.hops() < ZT_RELAY_MAX_HOPS) { if (fragment.hops() < ZT_RELAY_MAX_HOPS) {
fragment.incrementHops(); fragment.incrementHops();
@ -122,10 +127,11 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
if ((!relayTo)||(!relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,false))) { if ((!relayTo)||(!relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,false))) {
// Don't know peer or no direct path -- so relay via someone upstream // Don't know peer or no direct path -- so relay via someone upstream
relayTo = RR->topology->getUpstreamPeer(); relayTo = RR->topology->getUpstreamPeer();
if (relayTo) if (relayTo) {
relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,true); relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,true);
} }
} }
}
} else { } else {
// Fragment looks like ours // Fragment looks like ours
const uint64_t fragmentPacketId = fragment.packetId(); const uint64_t fragmentPacketId = fragment.packetId();
@ -159,8 +165,9 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
if (Utils::countBits(rq->haveFragments |= (1 << fragmentNumber)) == totalFragments) { if (Utils::countBits(rq->haveFragments |= (1 << fragmentNumber)) == totalFragments) {
// We have all fragments -- assemble and process full Packet // We have all fragments -- assemble and process full Packet
for(unsigned int f=1;f<totalFragments;++f) for(unsigned int f=1;f<totalFragments;++f) {
rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength()); rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength());
}
if (rq->frag0.tryDecode(RR,tPtr,flowId)) { if (rq->frag0.tryDecode(RR,tPtr,flowId)) {
rq->timestamp = 0; // packet decoded, free entry rq->timestamp = 0; // packet decoded, free entry
@ -179,12 +186,14 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
const Address destination(reinterpret_cast<const uint8_t *>(data) + 8,ZT_ADDRESS_LENGTH); const Address destination(reinterpret_cast<const uint8_t *>(data) + 8,ZT_ADDRESS_LENGTH);
const Address source(reinterpret_cast<const uint8_t *>(data) + 13,ZT_ADDRESS_LENGTH); const Address source(reinterpret_cast<const uint8_t *>(data) + 13,ZT_ADDRESS_LENGTH);
if (source == RR->identity.address()) if (source == RR->identity.address()) {
return; return;
}
if (destination != RR->identity.address()) { if (destination != RR->identity.address()) {
if ( (!RR->topology->amUpstream()) && (!path->trustEstablished(now)) && (source != RR->identity.address()) ) if ( (!RR->topology->amUpstream()) && (!path->trustEstablished(now)) && (source != RR->identity.address()) ) {
return; return;
}
Packet packet(data,len); Packet packet(data,len);
@ -194,20 +203,22 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
if ((relayTo)&&(relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,false))) { if ((relayTo)&&(relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,false))) {
if ((source != RR->identity.address())&&(_shouldUnite(now,source,destination))) { if ((source != RR->identity.address())&&(_shouldUnite(now,source,destination))) {
const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(tPtr,source)); const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(tPtr,source));
if (sourcePeer) if (sourcePeer) {
relayTo->introduce(tPtr,now,sourcePeer); relayTo->introduce(tPtr,now,sourcePeer);
} }
}
} else { } else {
relayTo = RR->topology->getUpstreamPeer(); relayTo = RR->topology->getUpstreamPeer();
if ((relayTo)&&(relayTo->address() != source)) { if ((relayTo)&&(relayTo->address() != source)) {
if (relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true)) { if (relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true)) {
const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(tPtr,source)); const SharedPtr<Peer> sourcePeer(RR->topology->getPeer(tPtr,source));
if (sourcePeer) if (sourcePeer) {
relayTo->introduce(tPtr,now,sourcePeer); relayTo->introduce(tPtr,now,sourcePeer);
} }
} }
} }
} }
}
} else if ((reinterpret_cast<const uint8_t *>(data)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0) { } else if ((reinterpret_cast<const uint8_t *>(data)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_FRAGMENTED) != 0) {
// Packet is the head of a fragmented packet series // Packet is the head of a fragmented packet series
@ -241,8 +252,9 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
// We have all fragments -- assemble and process full Packet // We have all fragments -- assemble and process full Packet
rq->frag0.init(data,len,path,now); rq->frag0.init(data,len,path,now);
for(unsigned int f=1;f<rq->totalFragments;++f) for(unsigned int f=1;f<rq->totalFragments;++f) {
rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength()); rq->frag0.append(rq->frags[f - 1].payload(),rq->frags[f - 1].payloadLength());
}
if (rq->frag0.tryDecode(RR,tPtr,flowId)) { if (rq->frag0.tryDecode(RR,tPtr,flowId)) {
rq->timestamp = 0; // packet decoded, free entry rq->timestamp = 0; // packet decoded, free entry
@ -278,8 +290,9 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{ {
if (!network->hasConfig()) if (!network->hasConfig()) {
return; return;
}
// Check if this packet is from someone other than the tap -- i.e. bridged in // Check if this packet is from someone other than the tap -- i.e. bridged in
bool fromBridged; bool fromBridged;
@ -402,8 +415,9 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
if ((sipNetmaskBits == 88)&&(my6[0] == 0xfd)&&(my6[9] == 0x99)&&(my6[10] == 0x93)) { // ZT-RFC4193 /88 ??? if ((sipNetmaskBits == 88)&&(my6[0] == 0xfd)&&(my6[9] == 0x99)&&(my6[10] == 0x93)) { // ZT-RFC4193 /88 ???
unsigned int ptr = 0; unsigned int ptr = 0;
while (ptr != 11) { while (ptr != 11) {
if (pkt6[ptr] != my6[ptr]) if (pkt6[ptr] != my6[ptr]) {
break; break;
}
++ptr; ++ptr;
} }
if (ptr == 11) { // prefix match! if (ptr == 11) { // prefix match!
@ -415,8 +429,9 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
if ( (my6[0] == 0xfc) && (my6[1] == (uint8_t)((nwid32 >> 24) & 0xff)) && (my6[2] == (uint8_t)((nwid32 >> 16) & 0xff)) && (my6[3] == (uint8_t)((nwid32 >> 8) & 0xff)) && (my6[4] == (uint8_t)(nwid32 & 0xff))) { if ( (my6[0] == 0xfc) && (my6[1] == (uint8_t)((nwid32 >> 24) & 0xff)) && (my6[2] == (uint8_t)((nwid32 >> 16) & 0xff)) && (my6[3] == (uint8_t)((nwid32 >> 8) & 0xff)) && (my6[4] == (uint8_t)(nwid32 & 0xff))) {
unsigned int ptr = 0; unsigned int ptr = 0;
while (ptr != 5) { while (ptr != 5) {
if (pkt6[ptr] != my6[ptr]) if (pkt6[ptr] != my6[ptr]) {
break; break;
}
++ptr; ++ptr;
} }
if (ptr == 5) { // prefix match! if (ptr == 5) { // prefix match!
@ -440,8 +455,12 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
adv[5] = 0x20; adv[5] = 0x20;
adv[6] = 0x3a; adv[6] = 0x3a;
adv[7] = 0xff; adv[7] = 0xff;
for(int i=0;i<16;++i) adv[8 + i] = pkt6[i]; for(int i=0;i<16;++i) {
for(int i=0;i<16;++i) adv[24 + i] = my6[i]; adv[8 + i] = pkt6[i];
}
for(int i=0;i<16;++i) {
adv[24 + i] = my6[i];
}
adv[40] = 0x88; adv[40] = 0x88;
adv[41] = 0x00; adv[41] = 0x00;
adv[42] = 0x00; adv[42] = 0x00;
@ -450,7 +469,9 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
adv[45] = 0x00; adv[45] = 0x00;
adv[46] = 0x00; adv[46] = 0x00;
adv[47] = 0x00; adv[47] = 0x00;
for(int i=0;i<16;++i) adv[48 + i] = pkt6[i]; for(int i=0;i<16;++i) {
adv[48 + i] = pkt6[i];
}
adv[64] = 0x02; adv[64] = 0x02;
adv[65] = 0x01; adv[65] = 0x01;
adv[66] = peerMac[0]; adv[66] = peerMac[0];
@ -462,7 +483,9 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
uint16_t pseudo_[36]; uint16_t pseudo_[36];
uint8_t *const pseudo = reinterpret_cast<uint8_t *>(pseudo_); uint8_t *const pseudo = reinterpret_cast<uint8_t *>(pseudo_);
for(int i=0;i<32;++i) pseudo[i] = adv[8 + i]; for(int i=0;i<32;++i) {
pseudo[i] = adv[8 + i];
}
pseudo[32] = 0x00; pseudo[32] = 0x00;
pseudo[33] = 0x00; pseudo[33] = 0x00;
pseudo[34] = 0x00; pseudo[34] = 0x00;
@ -471,10 +494,16 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
pseudo[37] = 0x00; pseudo[37] = 0x00;
pseudo[38] = 0x00; pseudo[38] = 0x00;
pseudo[39] = 0x3a; pseudo[39] = 0x3a;
for(int i=0;i<32;++i) pseudo[40 + i] = adv[40 + i]; for(int i=0;i<32;++i) {
pseudo[40 + i] = adv[40 + i];
}
uint32_t checksum = 0; uint32_t checksum = 0;
for(int i=0;i<36;++i) checksum += Utils::hton(pseudo_[i]); for(int i=0;i<36;++i) {
while ((checksum >> 16)) checksum = (checksum & 0xffff) + (checksum >> 16); checksum += Utils::hton(pseudo_[i]);
}
while ((checksum >> 16)) {
checksum = (checksum & 0xffff) + (checksum >> 16);
}
checksum = ~checksum; checksum = ~checksum;
adv[42] = (checksum >> 8) & 0xff; adv[42] = (checksum >> 8) & 0xff;
adv[43] = checksum & 0xff; adv[43] = checksum & 0xff;
@ -495,8 +524,9 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
* Note that some OSes, most notably Linux, do this for you by learning * Note that some OSes, most notably Linux, do this for you by learning
* multicast addresses on bridge interfaces and subscribing each slave. * multicast addresses on bridge interfaces and subscribing each slave.
* But in that case this does no harm, as the sets are just merged. */ * But in that case this does no harm, as the sets are just merged. */
if (fromBridged) if (fromBridged) {
network->learnBridgedMulticastGroup(tPtr,multicastGroup,RR->node->now()); network->learnBridgedMulticastGroup(tPtr,multicastGroup,RR->node->now());
}
// First pass sets noTee to false, but noTee is set to true in OutboundMulticast to prevent duplicates. // First pass sets noTee to false, but noTee is set to true in OutboundMulticast to prevent duplicates.
if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId,qosBucket)) { if (!network->filterOutgoingPacket(tPtr,false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId,qosBucket)) {
@ -585,12 +615,15 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
} else { } else {
// Otherwise pick a random set of them // Otherwise pick a random set of them
while (numBridges < ZT_MAX_BRIDGE_SPAM) { while (numBridges < ZT_MAX_BRIDGE_SPAM) {
if (ab == activeBridges.end()) if (ab == activeBridges.end()) {
ab = activeBridges.begin(); ab = activeBridges.begin();
}
if (((unsigned long)RR->node->prng() % (unsigned long)activeBridges.size()) == 0) { if (((unsigned long)RR->node->prng() % (unsigned long)activeBridges.size()) == 0) {
bridges[numBridges++] = *ab; bridges[numBridges++] = *ab;
++ab; ++ab;
} else ++ab; } else {
++ab;
}
} }
} }
} }
@ -886,22 +919,26 @@ void Switch::send(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
} }
_txQueue.push_back(TXQueueEntry(dest,RR->node->now(),packet,encrypt,flowId)); _txQueue.push_back(TXQueueEntry(dest,RR->node->now(),packet,encrypt,flowId));
} }
if (!RR->topology->getPeer(tPtr,dest)) if (!RR->topology->getPeer(tPtr,dest)) {
requestWhois(tPtr,RR->node->now(),dest); requestWhois(tPtr,RR->node->now(),dest);
} }
} }
}
void Switch::requestWhois(void *tPtr,const int64_t now,const Address &addr) void Switch::requestWhois(void *tPtr,const int64_t now,const Address &addr)
{ {
if (addr == RR->identity.address()) if (addr == RR->identity.address()) {
return; return;
}
{ {
Mutex::Lock _l(_lastSentWhoisRequest_m); Mutex::Lock _l(_lastSentWhoisRequest_m);
int64_t &last = _lastSentWhoisRequest[addr]; int64_t &last = _lastSentWhoisRequest[addr];
if ((now - last) < ZT_WHOIS_RETRY_DELAY) if ((now - last) < ZT_WHOIS_RETRY_DELAY) {
return; return;
else last = now; } else {
last = now;
}
} }
const SharedPtr<Peer> upstream(RR->topology->getUpstreamPeer()); const SharedPtr<Peer> upstream(RR->topology->getUpstreamPeer());
@ -925,10 +962,11 @@ void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
RXQueueEntry *const rq = &(_rxQueue[ptr]); RXQueueEntry *const rq = &(_rxQueue[ptr]);
Mutex::Lock rql(rq->lock); Mutex::Lock rql(rq->lock);
if ((rq->timestamp)&&(rq->complete)) { if ((rq->timestamp)&&(rq->complete)) {
if ((rq->frag0.tryDecode(RR,tPtr,rq->flowId))||((now - rq->timestamp) > ZT_RECEIVE_QUEUE_TIMEOUT)) if ((rq->frag0.tryDecode(RR,tPtr,rq->flowId))||((now - rq->timestamp) > ZT_RECEIVE_QUEUE_TIMEOUT)) {
rq->timestamp = 0; rq->timestamp = 0;
} }
} }
}
{ {
Mutex::Lock _l(_txQueue_m); Mutex::Lock _l(_txQueue_m);
@ -949,8 +987,9 @@ void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
unsigned long Switch::doTimerTasks(void *tPtr,int64_t now) unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
{ {
const uint64_t timeSinceLastCheck = now - _lastCheckedQueues; const uint64_t timeSinceLastCheck = now - _lastCheckedQueues;
if (timeSinceLastCheck < ZT_WHOIS_RETRY_DELAY) if (timeSinceLastCheck < ZT_WHOIS_RETRY_DELAY) {
return (unsigned long)(ZT_WHOIS_RETRY_DELAY - timeSinceLastCheck); return (unsigned long)(ZT_WHOIS_RETRY_DELAY - timeSinceLastCheck);
}
_lastCheckedQueues = now; _lastCheckedQueues = now;
std::vector<Address> needWhois; std::vector<Address> needWhois;
@ -963,14 +1002,16 @@ unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
} else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) { } else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) {
_txQueue.erase(txi++); _txQueue.erase(txi++);
} else { } else {
if (!RR->topology->getPeer(tPtr,txi->dest)) if (!RR->topology->getPeer(tPtr,txi->dest)) {
needWhois.push_back(txi->dest); needWhois.push_back(txi->dest);
}
++txi; ++txi;
} }
} }
} }
for(std::vector<Address>::const_iterator i(needWhois.begin());i!=needWhois.end();++i) for(std::vector<Address>::const_iterator i(needWhois.begin());i!=needWhois.end();++i) {
requestWhois(tPtr,now,*i); requestWhois(tPtr,now,*i);
}
for(unsigned int ptr=0;ptr<ZT_RX_QUEUE_SIZE;++ptr) { for(unsigned int ptr=0;ptr<ZT_RX_QUEUE_SIZE;++ptr) {
RXQueueEntry *const rq = &(_rxQueue[ptr]); RXQueueEntry *const rq = &(_rxQueue[ptr]);
@ -980,11 +1021,12 @@ unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
rq->timestamp = 0; rq->timestamp = 0;
} else { } else {
const Address src(rq->frag0.source()); const Address src(rq->frag0.source());
if (!RR->topology->getPeer(tPtr,src)) if (!RR->topology->getPeer(tPtr,src)) {
requestWhois(tPtr,now,src); requestWhois(tPtr,now,src);
} }
} }
} }
}
{ {
Mutex::Lock _l(_lastUniteAttempt_m); Mutex::Lock _l(_lastUniteAttempt_m);
@ -992,10 +1034,11 @@ unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
_LastUniteKey *k = (_LastUniteKey *)0; _LastUniteKey *k = (_LastUniteKey *)0;
uint64_t *v = (uint64_t *)0; uint64_t *v = (uint64_t *)0;
while (i.next(k,v)) { while (i.next(k,v)) {
if ((now - *v) >= (ZT_MIN_UNITE_INTERVAL * 8)) if ((now - *v) >= (ZT_MIN_UNITE_INTERVAL * 8)) {
_lastUniteAttempt.erase(*k); _lastUniteAttempt.erase(*k);
} }
} }
}
{ {
Mutex::Lock _l(_lastSentWhoisRequest_m); Mutex::Lock _l(_lastSentWhoisRequest_m);
@ -1003,10 +1046,11 @@ unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
Address *a = (Address *)0; Address *a = (Address *)0;
int64_t *ts = (int64_t *)0; int64_t *ts = (int64_t *)0;
while (i.next(a,ts)) { while (i.next(a,ts)) {
if ((now - *ts) > (ZT_WHOIS_RETRY_DELAY * 2)) if ((now - *ts) > (ZT_WHOIS_RETRY_DELAY * 2)) {
_lastSentWhoisRequest.erase(*a); _lastSentWhoisRequest.erase(*a);
} }
} }
}
return ZT_WHOIS_RETRY_DELAY; return ZT_WHOIS_RETRY_DELAY;
} }
@ -1047,10 +1091,11 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt,int32_t flowId)
peer->tryMemorizedPath(tPtr,now); // periodically attempt memorized or statically defined paths, if any are known peer->tryMemorizedPath(tPtr,now); // periodically attempt memorized or statically defined paths, if any are known
const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer()); const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
if ( (!relay) || (!(viaPath = relay->getAppropriatePath(now,false,flowId))) ) { if ( (!relay) || (!(viaPath = relay->getAppropriatePath(now,false,flowId))) ) {
if (!(viaPath = peer->getAppropriatePath(now,true,flowId))) if (!(viaPath = peer->getAppropriatePath(now,true,flowId))) {
return false; return false;
} }
} }
}
if (viaPath) { if (viaPath) {
uint16_t userSpecifiedMtu = viaPath->mtu(); uint16_t userSpecifiedMtu = viaPath->mtu();
_sendViaSpecificPath(tPtr,peer,viaPath,userSpecifiedMtu,now,packet,encrypt,flowId); _sendViaSpecificPath(tPtr,peer,viaPath,userSpecifiedMtu,now,packet,encrypt,flowId);
@ -1090,8 +1135,9 @@ void Switch::_sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path
unsigned int fragStart = chunkSize; unsigned int fragStart = chunkSize;
unsigned int remaining = packet.size() - chunkSize; unsigned int remaining = packet.size() - chunkSize;
unsigned int fragsRemaining = (remaining / (mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH)); unsigned int fragsRemaining = (remaining / (mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH));
if ((fragsRemaining * (mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH)) < remaining) if ((fragsRemaining * (mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH)) < remaining) {
++fragsRemaining; ++fragsRemaining;
}
const unsigned int totalFragments = fragsRemaining + 1; const unsigned int totalFragments = fragsRemaining + 1;
for(unsigned int fno=1;fno<totalFragments;++fno) { for(unsigned int fno=1;fno<totalFragments;++fno) {

View file

@ -241,9 +241,10 @@ private:
const unsigned int current = static_cast<unsigned int>(_rxQueuePtr.load()); const unsigned int current = static_cast<unsigned int>(_rxQueuePtr.load());
for(unsigned int k=1;k<=ZT_RX_QUEUE_SIZE;++k) { for(unsigned int k=1;k<=ZT_RX_QUEUE_SIZE;++k) {
RXQueueEntry *rq = &(_rxQueue[(current - k) % ZT_RX_QUEUE_SIZE]); RXQueueEntry *rq = &(_rxQueue[(current - k) % ZT_RX_QUEUE_SIZE]);
if ((rq->packetId == packetId)&&(rq->timestamp)) if ((rq->packetId == packetId)&&(rq->timestamp)) {
return rq; return rq;
} }
}
++_rxQueuePtr; ++_rxQueuePtr;
return &(_rxQueue[static_cast<unsigned int>(current) % ZT_RX_QUEUE_SIZE]); return &(_rxQueue[static_cast<unsigned int>(current) % ZT_RX_QUEUE_SIZE]);
} }

View file

@ -23,8 +23,9 @@ namespace ZeroTier {
int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const
{ {
if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) if ((!_signedBy)||(_signedBy != Network::controllerFor(_networkId))) {
return -1; return -1;
}
const Identity id(RR->topology->getIdentity(tPtr,_signedBy)); const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) { if (!id) {
RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy); RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);

View file

@ -116,7 +116,9 @@ public:
template<unsigned int C> template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const inline void serialize(Buffer<C> &b,const bool forSign = false) const
{ {
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
b.append(_networkId); b.append(_networkId);
b.append(_ts); b.append(_ts);
@ -133,7 +135,9 @@ public:
b.append((uint16_t)0); // length of additional fields, currently 0 b.append((uint16_t)0); // length of additional fields, currently 0
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
} }
template<unsigned int C> template<unsigned int C>
@ -158,8 +162,9 @@ public:
_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); _signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
p += ZT_ADDRESS_LENGTH; p += ZT_ADDRESS_LENGTH;
if (b[p++] == 1) { if (b[p++] == 1) {
if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) if (b.template at<uint16_t>(p) != ZT_C25519_SIGNATURE_LEN) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
}
p += 2; p += 2;
memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
p += ZT_C25519_SIGNATURE_LEN; p += ZT_C25519_SIGNATURE_LEN;
@ -168,8 +173,9 @@ public:
} }
p += 2 + b.template at<uint16_t>(p); p += 2 + b.template at<uint16_t>(p);
if (p > b.size()) if (p > b.size()) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
return (p - startAt); return (p - startAt);
} }

View file

@ -56,9 +56,10 @@ Topology::~Topology()
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers); Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
Address *a = (Address *)0; Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0; SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
while (i.next(a,p)) while (i.next(a,p)) {
_savePeer((void *)0,*p); _savePeer((void *)0,*p);
} }
}
SharedPtr<Peer> Topology::addPeer(void *tPtr,const SharedPtr<Peer> &peer) SharedPtr<Peer> Topology::addPeer(void *tPtr,const SharedPtr<Peer> &peer)
{ {
@ -66,8 +67,9 @@ SharedPtr<Peer> Topology::addPeer(void *tPtr,const SharedPtr<Peer> &peer)
{ {
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_m);
SharedPtr<Peer> &hp = _peers[peer->address()]; SharedPtr<Peer> &hp = _peers[peer->address()];
if (!hp) if (!hp) {
hp = peer; hp = peer;
}
np = hp; np = hp;
} }
return np; return np;
@ -75,15 +77,17 @@ SharedPtr<Peer> Topology::addPeer(void *tPtr,const SharedPtr<Peer> &peer)
SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta) SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta)
{ {
if (zta == RR->identity.address()) if (zta == RR->identity.address()) {
return SharedPtr<Peer>(); return SharedPtr<Peer>();
}
{ {
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_m);
const SharedPtr<Peer> *const ap = _peers.get(zta); const SharedPtr<Peer> *const ap = _peers.get(zta);
if (ap) if (ap) {
return *ap; return *ap;
} }
}
try { try {
Buffer<ZT_PEER_MAX_SERIALIZED_STATE_SIZE> buf; Buffer<ZT_PEER_MAX_SERIALIZED_STATE_SIZE> buf;
@ -95,8 +99,9 @@ SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta)
buf.setSize(len); buf.setSize(len);
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_m);
SharedPtr<Peer> &ap = _peers[zta]; SharedPtr<Peer> &ap = _peers[zta];
if (ap) if (ap) {
return ap; return ap;
}
ap = Peer::deserializeFromCache(RR->node->now(),tPtr,buf,RR); ap = Peer::deserializeFromCache(RR->node->now(),tPtr,buf,RR);
if (!ap) { if (!ap) {
_peers.erase(zta); _peers.erase(zta);
@ -115,9 +120,10 @@ Identity Topology::getIdentity(void *tPtr,const Address &zta)
} else { } else {
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_m);
const SharedPtr<Peer> *const ap = _peers.get(zta); const SharedPtr<Peer> *const ap = _peers.get(zta);
if (ap) if (ap) {
return (*ap)->identity(); return (*ap)->identity();
} }
}
return Identity(); return Identity();
} }
@ -141,8 +147,9 @@ SharedPtr<Peer> Topology::getUpstreamPeer()
} }
} }
if (!best) if (!best) {
return SharedPtr<Peer>(); return SharedPtr<Peer>();
}
return *best; return *best;
} }
@ -155,12 +162,14 @@ bool Topology::isUpstream(const Identity &id) const
bool Topology::shouldAcceptWorldUpdateFrom(const Address &addr) const bool Topology::shouldAcceptWorldUpdateFrom(const Address &addr) const
{ {
Mutex::Lock _l(_upstreams_m); Mutex::Lock _l(_upstreams_m);
if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),addr) != _upstreamAddresses.end()) if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),addr) != _upstreamAddresses.end()) {
return true; return true;
}
for(std::vector< std::pair< uint64_t,Address> >::const_iterator s(_moonSeeds.begin());s!=_moonSeeds.end();++s) { for(std::vector< std::pair< uint64_t,Address> >::const_iterator s(_moonSeeds.begin());s!=_moonSeeds.end();++s) {
if (s->second == addr) if (s->second == addr) {
return true; return true;
} }
}
return false; return false;
} }
@ -169,9 +178,10 @@ ZT_PeerRole Topology::role(const Address &ztaddr) const
Mutex::Lock _l(_upstreams_m); Mutex::Lock _l(_upstreams_m);
if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) { if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) {
for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) {
if (i->identity.address() == ztaddr) if (i->identity.address() == ztaddr) {
return ZT_PEER_ROLE_PLANET; return ZT_PEER_ROLE_PLANET;
} }
}
return ZT_PEER_ROLE_MOON; return ZT_PEER_ROLE_MOON;
} }
return ZT_PEER_ROLE_LEAF; return ZT_PEER_ROLE_LEAF;
@ -186,26 +196,30 @@ bool Topology::isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipa
if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) { if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),ztaddr) != _upstreamAddresses.end()) {
for(std::vector<World::Root>::const_iterator r(_planet.roots().begin());r!=_planet.roots().end();++r) { for(std::vector<World::Root>::const_iterator r(_planet.roots().begin());r!=_planet.roots().end();++r) {
if (r->identity.address() == ztaddr) { if (r->identity.address() == ztaddr) {
if (r->stableEndpoints.empty()) if (r->stableEndpoints.empty()) {
return false; // no stable endpoints specified, so allow dynamic paths return false; // no stable endpoints specified, so allow dynamic paths
}
for(std::vector<InetAddress>::const_iterator e(r->stableEndpoints.begin());e!=r->stableEndpoints.end();++e) { for(std::vector<InetAddress>::const_iterator e(r->stableEndpoints.begin());e!=r->stableEndpoints.end();++e) {
if (ipaddr.ipsEqual(*e)) if (ipaddr.ipsEqual(*e)) {
return false; return false;
} }
} }
} }
}
for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) { for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) {
for(std::vector<World::Root>::const_iterator r(m->roots().begin());r!=m->roots().end();++r) { for(std::vector<World::Root>::const_iterator r(m->roots().begin());r!=m->roots().end();++r) {
if (r->identity.address() == ztaddr) { if (r->identity.address() == ztaddr) {
if (r->stableEndpoints.empty()) if (r->stableEndpoints.empty()) {
return false; // no stable endpoints specified, so allow dynamic paths return false; // no stable endpoints specified, so allow dynamic paths
}
for(std::vector<InetAddress>::const_iterator e(r->stableEndpoints.begin());e!=r->stableEndpoints.end();++e) { for(std::vector<InetAddress>::const_iterator e(r->stableEndpoints.begin());e!=r->stableEndpoints.end();++e) {
if (ipaddr.ipsEqual(*e)) if (ipaddr.ipsEqual(*e)) {
return false; return false;
} }
} }
} }
} }
}
return true; return true;
} }
@ -214,8 +228,9 @@ bool Topology::isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipa
bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew) bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
{ {
if ((newWorld.type() != World::TYPE_PLANET)&&(newWorld.type() != World::TYPE_MOON)) if ((newWorld.type() != World::TYPE_PLANET)&&(newWorld.type() != World::TYPE_MOON)) {
return false; return false;
}
Mutex::Lock _l2(_peers_m); Mutex::Lock _l2(_peers_m);
Mutex::Lock _l1(_upstreams_m); Mutex::Lock _l1(_upstreams_m);
@ -238,9 +253,11 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
} }
if (existing) { if (existing) {
if (existing->shouldBeReplacedBy(newWorld)) if (existing->shouldBeReplacedBy(newWorld)) {
*existing = newWorld; *existing = newWorld;
else return false; } else {
return false;
}
} else if (newWorld.type() == World::TYPE_MOON) { } else if (newWorld.type() == World::TYPE_MOON) {
if (alwaysAcceptNew) { if (alwaysAcceptNew) {
_moons.push_back(newWorld); _moons.push_back(newWorld);
@ -256,13 +273,15 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
break; break;
} }
} }
if (existing) if (existing) {
break; break;
} }
} }
} }
if (!existing) }
if (!existing) {
return false; return false;
}
} else { } else {
return false; return false;
} }
@ -301,10 +320,11 @@ void Topology::addMoon(void *tPtr,const uint64_t id,const Address &seed)
if (seed) { if (seed) {
Mutex::Lock _l(_upstreams_m); Mutex::Lock _l(_upstreams_m);
if (std::find(_moonSeeds.begin(),_moonSeeds.end(),std::pair<uint64_t,Address>(id,seed)) == _moonSeeds.end()) if (std::find(_moonSeeds.begin(),_moonSeeds.end(),std::pair<uint64_t,Address>(id,seed)) == _moonSeeds.end()) {
_moonSeeds.push_back(std::pair<uint64_t,Address>(id,seed)); _moonSeeds.push_back(std::pair<uint64_t,Address>(id,seed));
} }
} }
}
void Topology::removeMoon(void *tPtr,const uint64_t id) void Topology::removeMoon(void *tPtr,const uint64_t id)
{ {
@ -326,9 +346,10 @@ void Topology::removeMoon(void *tPtr,const uint64_t id)
std::vector< std::pair<uint64_t,Address> > cm; std::vector< std::pair<uint64_t,Address> > cm;
for(std::vector< std::pair<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) { for(std::vector< std::pair<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) {
if (m->first != id) if (m->first != id) {
cm.push_back(*m); cm.push_back(*m);
} }
}
_moonSeeds.swap(cm); _moonSeeds.swap(cm);
_memoizeUpstreams(tPtr); _memoizeUpstreams(tPtr);
@ -356,11 +377,12 @@ void Topology::doPeriodicTasks(void *tPtr,int64_t now)
Path::HashKey *k = (Path::HashKey *)0; Path::HashKey *k = (Path::HashKey *)0;
SharedPtr<Path> *p = (SharedPtr<Path> *)0; SharedPtr<Path> *p = (SharedPtr<Path> *)0;
while (i.next(k,p)) { while (i.next(k,p)) {
if (p->references() <= 1) if (p->references() <= 1) {
_paths.erase(*k); _paths.erase(*k);
} }
} }
} }
}
void Topology::_memoizeUpstreams(void *tPtr) void Topology::_memoizeUpstreams(void *tPtr)
{ {
@ -388,11 +410,12 @@ void Topology::_memoizeUpstreams(void *tPtr)
} else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) { } else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) {
_upstreamAddresses.push_back(i->identity.address()); _upstreamAddresses.push_back(i->identity.address());
SharedPtr<Peer> &hp = _peers[i->identity.address()]; SharedPtr<Peer> &hp = _peers[i->identity.address()];
if (!hp) if (!hp) {
hp = new Peer(RR,RR->identity,i->identity); hp = new Peer(RR,RR->identity,i->identity);
} }
} }
} }
}
std::sort(_upstreamAddresses.begin(),_upstreamAddresses.end()); std::sort(_upstreamAddresses.begin(),_upstreamAddresses.end());
} }

View file

@ -89,8 +89,9 @@ public:
{ {
Mutex::Lock _l(_peers_m); Mutex::Lock _l(_peers_m);
const SharedPtr<Peer> *const ap = _peers.get(zta); const SharedPtr<Peer> *const ap = _peers.get(zta);
if (ap) if (ap) {
return *ap; return *ap;
}
return SharedPtr<Peer>(); return SharedPtr<Peer>();
} }
@ -105,8 +106,9 @@ public:
{ {
Mutex::Lock _l(_paths_m); Mutex::Lock _l(_paths_m);
SharedPtr<Path> &p = _paths[Path::HashKey(l,r)]; SharedPtr<Path> &p = _paths[Path::HashKey(l,r)];
if (!p) if (!p) {
p.set(new Path(l,r)); p.set(new Path(l,r));
}
return p; return p;
} }
@ -163,25 +165,28 @@ public:
if (i->identity != RR->identity) { if (i->identity != RR->identity) {
std::vector<InetAddress> &ips = eps[i->identity.address()]; std::vector<InetAddress> &ips = eps[i->identity.address()];
for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) { for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
if (std::find(ips.begin(),ips.end(),*j) == ips.end()) if (std::find(ips.begin(),ips.end(),*j) == ips.end()) {
ips.push_back(*j); ips.push_back(*j);
} }
} }
} }
}
for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) { for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) {
for(std::vector<World::Root>::const_iterator i(m->roots().begin());i!=m->roots().end();++i) { for(std::vector<World::Root>::const_iterator i(m->roots().begin());i!=m->roots().end();++i) {
if (i->identity != RR->identity) { if (i->identity != RR->identity) {
std::vector<InetAddress> &ips = eps[i->identity.address()]; std::vector<InetAddress> &ips = eps[i->identity.address()];
for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) { for(std::vector<InetAddress>::const_iterator j(i->stableEndpoints.begin());j!=i->stableEndpoints.end();++j) {
if (std::find(ips.begin(),ips.end(),*j) == ips.end()) if (std::find(ips.begin(),ips.end(),*j) == ips.end()) {
ips.push_back(*j); ips.push_back(*j);
} }
} }
} }
} }
for(std::vector< std::pair<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) }
for(std::vector< std::pair<uint64_t,Address> >::const_iterator m(_moonSeeds.begin());m!=_moonSeeds.end();++m) {
eps[m->second]; eps[m->second];
} }
}
/** /**
* @return Vector of active upstream addresses (including roots) * @return Vector of active upstream addresses (including roots)
@ -209,9 +214,10 @@ public:
Mutex::Lock _l(_upstreams_m); Mutex::Lock _l(_upstreams_m);
std::vector<uint64_t> mw; std::vector<uint64_t> mw;
for(std::vector< std::pair<uint64_t,Address> >::const_iterator s(_moonSeeds.begin());s!=_moonSeeds.end();++s) { for(std::vector< std::pair<uint64_t,Address> >::const_iterator s(_moonSeeds.begin());s!=_moonSeeds.end();++s) {
if (std::find(mw.begin(),mw.end(),s->first) == mw.end()) if (std::find(mw.begin(),mw.end(),s->first) == mw.end()) {
mw.push_back(s->first); mw.push_back(s->first);
} }
}
return mw; return mw;
} }
@ -287,9 +293,10 @@ public:
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0; SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
while (i.next(a,p)) { while (i.next(a,p)) {
const SharedPtr<Path> pp((*p)->getAppropriatePath(now,false)); const SharedPtr<Path> pp((*p)->getAppropriatePath(now,false));
if (pp) if (pp) {
++cnt; ++cnt;
} }
}
return cnt; return cnt;
} }
@ -354,9 +361,10 @@ public:
inline unsigned int getOutboundPathMtu(const InetAddress &physicalAddress) inline unsigned int getOutboundPathMtu(const InetAddress &physicalAddress)
{ {
for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) { for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) {
return _physicalPathConfig[i].second.mtu; return _physicalPathConfig[i].second.mtu;
} }
}
return ZT_DEFAULT_PHYSMTU; return ZT_DEFAULT_PHYSMTU;
} }
@ -369,9 +377,10 @@ public:
inline uint64_t getOutboundPathTrust(const InetAddress &physicalAddress) inline uint64_t getOutboundPathTrust(const InetAddress &physicalAddress)
{ {
for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) { for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) {
return _physicalPathConfig[i].second.trustedPathId; return _physicalPathConfig[i].second.trustedPathId;
} }
}
return 0; return 0;
} }
@ -384,9 +393,10 @@ public:
inline bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId) inline bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId)
{ {
for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) { for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
if ((_physicalPathConfig[i].second.trustedPathId == trustedPathId)&&(_physicalPathConfig[i].first.containsAddress(physicalAddress))) if ((_physicalPathConfig[i].second.trustedPathId == trustedPathId)&&(_physicalPathConfig[i].first.containsAddress(physicalAddress))) {
return true; return true;
} }
}
return false; return false;
} }
@ -399,18 +409,20 @@ public:
_numConfiguredPhysicalPaths = 0; _numConfiguredPhysicalPaths = 0;
} else { } else {
std::map<InetAddress,ZT_PhysicalPathConfiguration> cpaths; std::map<InetAddress,ZT_PhysicalPathConfiguration> cpaths;
for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second; cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second;
}
if (pathConfig) { if (pathConfig) {
ZT_PhysicalPathConfiguration pc(*pathConfig); ZT_PhysicalPathConfiguration pc(*pathConfig);
if (pc.mtu <= 0) if (pc.mtu <= 0) {
pc.mtu = ZT_DEFAULT_PHYSMTU; pc.mtu = ZT_DEFAULT_PHYSMTU;
else if (pc.mtu < ZT_MIN_PHYSMTU) } else if (pc.mtu < ZT_MIN_PHYSMTU) {
pc.mtu = ZT_MIN_PHYSMTU; pc.mtu = ZT_MIN_PHYSMTU;
else if (pc.mtu > ZT_MAX_PHYSMTU) } else if (pc.mtu > ZT_MAX_PHYSMTU) {
pc.mtu = ZT_MAX_PHYSMTU; pc.mtu = ZT_MAX_PHYSMTU;
}
cpaths[*(reinterpret_cast<const InetAddress *>(pathNetwork))] = pc; cpaths[*(reinterpret_cast<const InetAddress *>(pathNetwork))] = pc;
} else { } else {

View file

@ -59,15 +59,18 @@ void Trace::resettingPathsInScope(void *const tPtr,const Address &reporter,const
d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR,myPhysicalAddress.toString(tmp)); d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_PHYADDR,myPhysicalAddress.toString(tmp));
d.add(ZT_REMOTE_TRACE_FIELD__IP_SCOPE,(uint64_t)scope); d.add(ZT_REMOTE_TRACE_FIELD__IP_SCOPE,(uint64_t)scope);
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
}
_spamToAllNetworks(tPtr,d,Trace::LEVEL_NORMAL); _spamToAllNetworks(tPtr,d,Trace::LEVEL_NORMAL);
} }
void Trace::peerConfirmingUnknownPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &path,const uint64_t packetId,const Packet::Verb verb) void Trace::peerConfirmingUnknownPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &path,const uint64_t packetId,const Packet::Verb verb)
{ {
char tmp[128]; char tmp[128];
if (!path) return; // sanity check if (!path) {
return; // sanity check
}
ZT_LOCAL_TRACE(tPtr,RR,"trying unknown path %s to %.10llx (packet %.16llx verb %d local socket %lld network %.16llx)",path->address().toString(tmp),peer.address().toInt(),packetId,verb,path->localSocket(),networkId); ZT_LOCAL_TRACE(tPtr,RR,"trying unknown path %s to %.10llx (packet %.16llx verb %d local socket %lld network %.16llx)",path->address().toString(tmp),peer.address().toInt(),packetId,verb,path->localSocket(),networkId);
@ -82,20 +85,23 @@ void Trace::peerConfirmingUnknownPath(void *const tPtr,const uint64_t networkId,
d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S); d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_CONFIRMING_UNKNOWN_PATH_S);
d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId); d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb); d.add(ZT_REMOTE_TRACE_FIELD__PACKET_VERB,(uint64_t)verb);
if (networkId) if (networkId) {
d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId); d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId);
}
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address()); d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address());
if (path) { if (path) {
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp)); d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
} }
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if (byn.first) }
if (byn.first) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::bondStateMessage(void *const tPtr,char *msg) void Trace::bondStateMessage(void *const tPtr,char *msg)
{ {
@ -105,7 +111,9 @@ void Trace::bondStateMessage(void *const tPtr,char *msg)
void Trace::peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath,const uint64_t packetId) void Trace::peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath,const uint64_t packetId)
{ {
char tmp[128]; char tmp[128];
if (!newPath) return; // sanity check if (!newPath) {
return; // sanity check
}
ZT_LOCAL_TRACE(tPtr,RR,"learned new path %s to %.10llx (packet %.16llx local socket %lld network %.16llx)",newPath->address().toString(tmp),peer.address().toInt(),packetId,newPath->localSocket(),networkId); ZT_LOCAL_TRACE(tPtr,RR,"learned new path %s to %.10llx (packet %.16llx local socket %lld network %.16llx)",newPath->address().toString(tmp),peer.address().toInt(),packetId,newPath->localSocket(),networkId);
@ -119,23 +127,28 @@ void Trace::peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &p
Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d; Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S); d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_LEARNED_NEW_PATH_S);
d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId); d.add(ZT_REMOTE_TRACE_FIELD__PACKET_ID,packetId);
if (networkId) if (networkId) {
d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, networkId); d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID, networkId);
}
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address()); d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address());
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,newPath->address().toString(tmp)); d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,newPath->address().toString(tmp));
d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,newPath->localSocket()); d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,newPath->localSocket());
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if (byn.first) }
if (byn.first) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::peerRedirected(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath) void Trace::peerRedirected(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &newPath)
{ {
char tmp[128]; char tmp[128];
if (!newPath) return; // sanity check if (!newPath) {
return; // sanity check
}
ZT_LOCAL_TRACE(tPtr,RR,"explicit redirect from %.10llx to path %s",peer.address().toInt(),newPath->address().toString(tmp)); ZT_LOCAL_TRACE(tPtr,RR,"explicit redirect from %.10llx to path %s",peer.address().toInt(),newPath->address().toString(tmp));
@ -148,25 +161,30 @@ void Trace::peerRedirected(void *const tPtr,const uint64_t networkId,Peer &peer,
if ((_globalTarget)||(byn.first)) { if ((_globalTarget)||(byn.first)) {
Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d; Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S); d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__PEER_REDIRECTED_S);
if (networkId) if (networkId) {
d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId); d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,networkId);
}
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address()); d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,peer.address());
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,newPath->address().toString(tmp)); d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,newPath->address().toString(tmp));
d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,newPath->localSocket()); d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,newPath->localSocket());
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if (byn.first) }
if (byn.first) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const MAC &sourceMac,const MAC &destMac,const unsigned int etherType,const unsigned int vlanId,const unsigned int frameLen,const char *reason) void Trace::outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const MAC &sourceMac,const MAC &destMac,const unsigned int etherType,const unsigned int vlanId,const unsigned int frameLen,const char *reason)
{ {
#ifdef ZT_TRACE #ifdef ZT_TRACE
char tmp[128],tmp2[128]; char tmp[128],tmp2[128];
#endif #endif
if (!network) return; // sanity check if (!network) {
return; // sanity check
}
ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DROP frame %s -> %s etherType %.4x size %u (%s)",network->id(),sourceMac.toString(tmp),destMac.toString(tmp2),etherType,frameLen,(reason) ? reason : "unknown reason"); ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DROP frame %s -> %s etherType %.4x size %u (%s)",network->id(),sourceMac.toString(tmp),destMac.toString(tmp2),etherType,frameLen,(reason) ? reason : "unknown reason");
@ -182,20 +200,25 @@ void Trace::outgoingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network
d.add(ZT_REMOTE_TRACE_FIELD__ETHERTYPE,(uint64_t)etherType); d.add(ZT_REMOTE_TRACE_FIELD__ETHERTYPE,(uint64_t)etherType);
d.add(ZT_REMOTE_TRACE_FIELD__VLAN_ID,(uint64_t)vlanId); d.add(ZT_REMOTE_TRACE_FIELD__VLAN_ID,(uint64_t)vlanId);
d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH,(uint64_t)frameLen); d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH,(uint64_t)frameLen);
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) }
if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::incomingNetworkAccessDenied(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested) void Trace::incomingNetworkAccessDenied(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,bool credentialsRequested)
{ {
char tmp[128]; char tmp[128];
if (!network) return; // sanity check if (!network) {
return; // sanity check
}
ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DENIED packet from %.10llx(%s) verb %d size %u%s",network->id(),source.toInt(),(path) ? (path->address().toString(tmp)) : "???",(int)verb,packetLength,credentialsRequested ? " (credentials requested)" : " (credentials not requested)"); ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DENIED packet from %.10llx(%s) verb %d size %u%s",network->id(),source.toInt(),(path) ? (path->address().toString(tmp)) : "???",(int)verb,packetLength,credentialsRequested ? " (credentials requested)" : " (credentials not requested)");
@ -214,17 +237,21 @@ void Trace::incomingNetworkAccessDenied(void *const tPtr,const SharedPtr<Network
} }
d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network->id()); d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network->id());
if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) }
if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac,const char *reason) void Trace::incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network> &network,const SharedPtr<Path> &path,const uint64_t packetId,const unsigned int packetLength,const Address &source,const Packet::Verb verb,const MAC &sourceMac,const MAC &destMac,const char *reason)
{ {
char tmp[128]; char tmp[128];
if (!network) return; // sanity check if (!network) {
return; // sanity check
}
ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DROPPED frame from %.10llx(%s) verb %d size %u",network->id(),source.toInt(),(path) ? (path->address().toString(tmp)) : "???",(int)verb,packetLength); ZT_LOCAL_TRACE(tPtr,RR,"%.16llx DROPPED frame from %.10llx(%s) verb %d size %u",network->id(),source.toInt(),(path) ? (path->address().toString(tmp)) : "???",(int)verb,packetLength);
@ -244,15 +271,18 @@ void Trace::incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network
d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network->id()); d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,network->id());
d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC,sourceMac.toInt()); d.add(ZT_REMOTE_TRACE_FIELD__SOURCE_MAC,sourceMac.toInt());
d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC,destMac.toInt()); d.add(ZT_REMOTE_TRACE_FIELD__DEST_MAC,destMac.toInt());
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_VERBOSE)) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) }
if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_VERBOSE)) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const char *reason) void Trace::incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const char *reason)
{ {
@ -270,8 +300,9 @@ void Trace::incomingPacketMessageAuthenticationFailure(void *const tPtr,const Sh
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp)); d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
} }
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
} }
@ -294,8 +325,9 @@ void Trace::incomingPacketInvalid(void *const tPtr,const SharedPtr<Path> &path,c
d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
} }
d.add(ZT_REMOTE_TRACE_FIELD__PACKET_HOPS,(uint64_t)hops); d.add(ZT_REMOTE_TRACE_FIELD__PACKET_HOPS,(uint64_t)hops);
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
} }
@ -316,8 +348,9 @@ void Trace::incomingPacketDroppedHELLO(void *const tPtr,const SharedPtr<Path> &p
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp)); d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket()); d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
} }
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
} }
@ -370,20 +403,25 @@ void Trace::networkFilter(
d.add(ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_INBOUND,inbound ? "1" : "0"); d.add(ZT_REMOTE_TRACE_FIELD__FILTER_FLAG_INBOUND,inbound ? "1" : "0");
d.add(ZT_REMOTE_TRACE_FIELD__FILTER_RESULT,(int64_t)accept); d.add(ZT_REMOTE_TRACE_FIELD__FILTER_RESULT,(int64_t)accept);
d.add(ZT_REMOTE_TRACE_FIELD__FILTER_BASE_RULE_LOG,(const char *)primaryRuleSetLog.data(),(int)primaryRuleSetLog.sizeBytes()); d.add(ZT_REMOTE_TRACE_FIELD__FILTER_BASE_RULE_LOG,(const char *)primaryRuleSetLog.data(),(int)primaryRuleSetLog.sizeBytes());
if (matchingCapabilityRuleSetLog) if (matchingCapabilityRuleSetLog) {
d.add(ZT_REMOTE_TRACE_FIELD__FILTER_CAP_RULE_LOG,(const char *)matchingCapabilityRuleSetLog->data(),(int)matchingCapabilityRuleSetLog->sizeBytes()); d.add(ZT_REMOTE_TRACE_FIELD__FILTER_CAP_RULE_LOG,(const char *)matchingCapabilityRuleSetLog->data(),(int)matchingCapabilityRuleSetLog->sizeBytes());
if (matchingCapability) }
if (matchingCapability) {
d.add(ZT_REMOTE_TRACE_FIELD__FILTER_CAP_ID,(uint64_t)matchingCapability->id()); d.add(ZT_REMOTE_TRACE_FIELD__FILTER_CAP_ID,(uint64_t)matchingCapability->id());
}
d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH,(uint64_t)frameLen); d.add(ZT_REMOTE_TRACE_FIELD__FRAME_LENGTH,(uint64_t)frameLen);
if (frameLen > 0) if (frameLen > 0) {
d.add(ZT_REMOTE_TRACE_FIELD__FRAME_DATA,(const char *)frameData,(frameLen > 256) ? (int)256 : (int)frameLen); d.add(ZT_REMOTE_TRACE_FIELD__FRAME_DATA,(const char *)frameData,(frameLen > 256) ? (int)256 : (int)frameLen);
}
if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_RULES)) if ((_globalTarget)&&((int)_globalLevel >= (int)Trace::LEVEL_RULES)) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_RULES)) }
if ((byn.first)&&((int)byn.second >= (int)Trace::LEVEL_RULES)) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::credentialRejected(void *const tPtr,const CertificateOfMembership &c,const char *reason) void Trace::credentialRejected(void *const tPtr,const CertificateOfMembership &c,const char *reason)
{ {
@ -401,15 +439,18 @@ void Trace::credentialRejected(void *const tPtr,const CertificateOfMembership &c
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if (byn.first) }
if (byn.first) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason) void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c,const char *reason)
{ {
@ -427,15 +468,18 @@ void Trace::credentialRejected(void *const tPtr,const CertificateOfOwnership &c,
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if (byn.first) }
if (byn.first) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::credentialRejected(void *const tPtr,const Capability &c,const char *reason) void Trace::credentialRejected(void *const tPtr,const Capability &c,const char *reason)
{ {
@ -453,15 +497,18 @@ void Trace::credentialRejected(void *const tPtr,const Capability &c,const char *
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if (byn.first) }
if (byn.first) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason) void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason)
{ {
@ -480,15 +527,18 @@ void Trace::credentialRejected(void *const tPtr,const Tag &c,const char *reason)
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value());
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
}
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if (byn.first) }
if (byn.first) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *reason) void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *reason)
{ {
@ -505,15 +555,18 @@ void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target()); d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target());
if (reason) if (reason) {
d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason); d.add(ZT_REMOTE_TRACE_FIELD__REASON, reason);
}
if (_globalTarget) if (_globalTarget) {
_send(tPtr,d,_globalTarget); _send(tPtr,d,_globalTarget);
if (byn.first) }
if (byn.first) {
_send(tPtr,d,byn.first); _send(tPtr,d,byn.first);
} }
} }
}
void Trace::updateMemoizedSettings() void Trace::updateMemoizedSettings()
{ {
@ -549,9 +602,10 @@ void Trace::_spamToAllNetworks(void *const tPtr,const Dictionary<ZT_MAX_REMOTE_T
uint64_t *k = (uint64_t *)0; uint64_t *k = (uint64_t *)0;
std::pair<Address,Trace::Level> *v = (std::pair<Address,Trace::Level> *)0; std::pair<Address,Trace::Level> *v = (std::pair<Address,Trace::Level> *)0;
while (i.next(k,v)) { while (i.next(k,v)) {
if ((v)&&(v->first)&&((int)v->second >= (int)level)) if ((v)&&(v->first)&&((int)v->second >= (int)level)) {
_send(tPtr,d,v->first); _send(tPtr,d,v->first);
} }
} }
}
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -188,18 +188,22 @@ const Utils::CPUIDRegisters Utils::CPUID;
static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len) static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len)
{ {
volatile uint8_t *const end = ptr + len; volatile uint8_t *const end = ptr + len;
while (ptr != end) *(ptr++) = (uint8_t)0; while (ptr != end) {
*(ptr++) = (uint8_t)0;
}
} }
static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t *,unsigned int) = _Utils_doBurn; static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t *,unsigned int) = _Utils_doBurn;
void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); } void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); }
static unsigned long _Utils_itoa(unsigned long n,char *s) static unsigned long _Utils_itoa(unsigned long n,char *s)
{ {
if (n == 0) if (n == 0) {
return 0; return 0;
}
unsigned long pos = _Utils_itoa(n / 10,s); unsigned long pos = _Utils_itoa(n / 10,s);
if (pos >= 22) // sanity check, should be impossible if (pos >= 22) { // sanity check, should be impossible
pos = 22; pos = 22;
}
s[pos] = '0' + (char)(n % 10); s[pos] = '0' + (char)(n % 10);
return pos + 1; return pos + 1;
} }
@ -288,7 +292,9 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
exit(1); exit(1);
return; return;
} }
} else break; } else {
break;
}
} }
randomPtr = 0; randomPtr = 0;
s20.crypt12(randomBuf,randomBuf,sizeof(randomBuf)); s20.crypt12(randomBuf,randomBuf,sizeof(randomBuf));

View file

@ -128,8 +128,9 @@ public:
static inline bool secureEq(const void *a,const void *b,unsigned int len) static inline bool secureEq(const void *a,const void *b,unsigned int len)
{ {
uint8_t diff = 0; uint8_t diff = 0;
for(unsigned int i=0;i<len;++i) for(unsigned int i=0;i<len;++i) {
diff |= ( (reinterpret_cast<const uint8_t *>(a))[i] ^ (reinterpret_cast<const uint8_t *>(b))[i] ); diff |= ( (reinterpret_cast<const uint8_t *>(a))[i] ^ (reinterpret_cast<const uint8_t *>(b))[i] );
}
return (diff == 0); return (diff == 0);
} }
@ -232,26 +233,32 @@ public:
unsigned int l = 0; unsigned int l = 0;
while (l < buflen) { while (l < buflen) {
uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++)); uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
if (!hc) break; if (!hc) {
break;
}
uint8_t c = 0; uint8_t c = 0;
if ((hc >= 48)&&(hc <= 57)) // 0..9 if ((hc >= 48)&&(hc <= 57)) { // 0..9
c = hc - 48; c = hc - 48;
else if ((hc >= 97)&&(hc <= 102)) // a..f } else if ((hc >= 97)&&(hc <= 102)) { // a..f
c = hc - 87; c = hc - 87;
else if ((hc >= 65)&&(hc <= 70)) // A..F } else if ((hc >= 65)&&(hc <= 70)) { // A..F
c = hc - 55; c = hc - 55;
}
hc = *(reinterpret_cast<const uint8_t *>(h++)); hc = *(reinterpret_cast<const uint8_t *>(h++));
if (!hc) break; if (!hc) {
break;
}
c <<= 4; c <<= 4;
if ((hc >= 48)&&(hc <= 57)) if ((hc >= 48)&&(hc <= 57)) {
c |= hc - 48; c |= hc - 48;
else if ((hc >= 97)&&(hc <= 102)) } else if ((hc >= 97)&&(hc <= 102)) {
c |= hc - 87; c |= hc - 87;
else if ((hc >= 65)&&(hc <= 70)) } else if ((hc >= 65)&&(hc <= 70)) {
c |= hc - 55; c |= hc - 55;
}
reinterpret_cast<uint8_t *>(buf)[l++] = c; reinterpret_cast<uint8_t *>(buf)[l++] = c;
} }
@ -263,29 +270,39 @@ public:
unsigned int l = 0; unsigned int l = 0;
const char *hend = h + hlen; const char *hend = h + hlen;
while (l < buflen) { while (l < buflen) {
if (h == hend) break; if (h == hend) {
break;
}
uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++)); uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
if (!hc) break; if (!hc) {
break;
}
uint8_t c = 0; uint8_t c = 0;
if ((hc >= 48)&&(hc <= 57)) if ((hc >= 48)&&(hc <= 57)) {
c = hc - 48; c = hc - 48;
else if ((hc >= 97)&&(hc <= 102)) } else if ((hc >= 97)&&(hc <= 102)) {
c = hc - 87; c = hc - 87;
else if ((hc >= 65)&&(hc <= 70)) } else if ((hc >= 65)&&(hc <= 70)) {
c = hc - 55; c = hc - 55;
}
if (h == hend) break; if (h == hend) {
break;
}
hc = *(reinterpret_cast<const uint8_t *>(h++)); hc = *(reinterpret_cast<const uint8_t *>(h++));
if (!hc) break; if (!hc) {
break;
}
c <<= 4; c <<= 4;
if ((hc >= 48)&&(hc <= 57)) if ((hc >= 48)&&(hc <= 57)) {
c |= hc - 48; c |= hc - 48;
else if ((hc >= 97)&&(hc <= 102)) } else if ((hc >= 97)&&(hc <= 102)) {
c |= hc - 87; c |= hc - 87;
else if ((hc >= 65)&&(hc <= 70)) } else if ((hc >= 65)&&(hc <= 70)) {
c |= hc - 55; c |= hc - 55;
}
reinterpret_cast<uint8_t *>(buf)[l++] = c; reinterpret_cast<uint8_t *>(buf)[l++] = c;
} }
@ -382,8 +399,9 @@ public:
*/ */
static inline bool scopy(char *dest,unsigned int len,const char *src) static inline bool scopy(char *dest,unsigned int len,const char *src)
{ {
if (!len) if (!len) {
return false; // sanity check return false; // sanity check
}
if (!src) { if (!src) {
*dest = (char)0; *dest = (char)0;
return true; return true;
@ -435,9 +453,10 @@ public:
static inline bool isZero(const void *p,unsigned int len) static inline bool isZero(const void *p,unsigned int len)
{ {
for(unsigned int i=0;i<len;++i) { for(unsigned int i=0;i<len;++i) {
if (((const unsigned char *)p)[i]) if (((const unsigned char *)p)[i]) {
return false; return false;
} }
}
return true; return true;
} }
@ -660,8 +679,9 @@ public:
{ {
#ifdef ZT_NO_UNALIGNED_ACCESS #ifdef ZT_NO_UNALIGNED_ACCESS
I tmp; I tmp;
for(int i=0;i<(int)sizeof(I);++i) for(int i=0;i<(int)sizeof(I);++i) {
reinterpret_cast<uint8_t *>(&tmp)[i] = reinterpret_cast<const uint8_t *>(p)[i]; reinterpret_cast<uint8_t *>(&tmp)[i] = reinterpret_cast<const uint8_t *>(p)[i];
}
return tmp; return tmp;
#else #else
return *reinterpret_cast<const I *>(p); return *reinterpret_cast<const I *>(p);
@ -679,8 +699,9 @@ public:
static ZT_INLINE void storeMachineEndian(void *const p, const I i) noexcept static ZT_INLINE void storeMachineEndian(void *const 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) {
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k]; reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
}
#else #else
*reinterpret_cast<I *>(p) = i; *reinterpret_cast<I *>(p) = i;
#endif #endif

View file

@ -148,8 +148,9 @@ public:
*/ */
inline bool shouldBeReplacedBy(const World &update) inline bool shouldBeReplacedBy(const World &update)
{ {
if ((_id == 0)||(_type == TYPE_NULL)) if ((_id == 0)||(_type == TYPE_NULL)) {
return true; return true;
}
if ((_id == update._id)&&(_ts < update._ts)&&(_type == update._type)) { if ((_id == update._id)&&(_ts < update._ts)&&(_type == update._type)) {
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp; Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> tmp;
update.serialize(tmp,true); update.serialize(tmp,true);
@ -166,25 +167,32 @@ public:
template<unsigned int C> template<unsigned int C>
inline void serialize(Buffer<C> &b,bool forSign = false) const inline void serialize(Buffer<C> &b,bool forSign = false) const
{ {
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL); if (forSign) {
b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
b.append((uint8_t)_type); b.append((uint8_t)_type);
b.append((uint64_t)_id); b.append((uint64_t)_id);
b.append((uint64_t)_ts); b.append((uint64_t)_ts);
b.append(_updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN); b.append(_updatesMustBeSignedBy.data,ZT_C25519_PUBLIC_KEY_LEN);
if (!forSign) if (!forSign) {
b.append(_signature.data,ZT_C25519_SIGNATURE_LEN); b.append(_signature.data,ZT_C25519_SIGNATURE_LEN);
}
b.append((uint8_t)_roots.size()); b.append((uint8_t)_roots.size());
for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) { for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
r->identity.serialize(b); r->identity.serialize(b);
b.append((uint8_t)r->stableEndpoints.size()); b.append((uint8_t)r->stableEndpoints.size());
for(std::vector<InetAddress>::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep) for(std::vector<InetAddress>::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep) {
ep->serialize(b); ep->serialize(b);
} }
if (_type == TYPE_MOON) }
if (_type == TYPE_MOON) {
b.append((uint16_t)0); // no attached dictionary (for future use) b.append((uint16_t)0); // no attached dictionary (for future use)
}
if (forSign) b.append((uint64_t)0xf7f7f7f7f7f7f7f7ULL); if (forSign) {
b.append((uint64_t)0xf7f7f7f7f7f7f7f7ULL);
}
} }
template<unsigned int C> template<unsigned int C>
@ -217,22 +225,25 @@ public:
memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN); memcpy(_signature.data,b.field(p,ZT_C25519_SIGNATURE_LEN),ZT_C25519_SIGNATURE_LEN);
p += ZT_C25519_SIGNATURE_LEN; p += ZT_C25519_SIGNATURE_LEN;
const unsigned int numRoots = (unsigned int)b[p++]; const unsigned int numRoots = (unsigned int)b[p++];
if (numRoots > ZT_WORLD_MAX_ROOTS) if (numRoots > ZT_WORLD_MAX_ROOTS) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
for(unsigned int k=0;k<numRoots;++k) { for(unsigned int k=0;k<numRoots;++k) {
_roots.push_back(Root()); _roots.push_back(Root());
Root &r = _roots.back(); Root &r = _roots.back();
p += r.identity.deserialize(b,p); p += r.identity.deserialize(b,p);
unsigned int numStableEndpoints = b[p++]; unsigned int numStableEndpoints = b[p++];
if (numStableEndpoints > ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT) if (numStableEndpoints > ZT_WORLD_MAX_STABLE_ENDPOINTS_PER_ROOT) {
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW; throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
}
for(unsigned int kk=0;kk<numStableEndpoints;++kk) { for(unsigned int kk=0;kk<numStableEndpoints;++kk) {
r.stableEndpoints.push_back(InetAddress()); r.stableEndpoints.push_back(InetAddress());
p += r.stableEndpoints.back().deserialize(b,p); p += r.stableEndpoints.back().deserialize(b,p);
} }
} }
if (_type == TYPE_MOON) if (_type == TYPE_MOON) {
p += b.template at<uint16_t>(p) + 2; p += b.template at<uint16_t>(p) + 2;
}
return (p - startAt); return (p - startAt);
} }