mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
ZeroTier standard .clang-format -- switch to spaces, match indentation of Rust, mostly based on LLVM format.
This commit is contained in:
parent
2698dab696
commit
12e7546ebc
111 changed files with 31629 additions and 26070 deletions
|
@ -57,7 +57,7 @@ SpacesInCStyleCastParentheses: 'false'
|
|||
SpacesInContainerLiterals: 'true'
|
||||
SpacesInParentheses: 'false'
|
||||
SpacesInSquareBrackets: 'false'
|
||||
UseTab: ForIndentation
|
||||
UseTab: 'false'
|
||||
|
||||
---
|
||||
Language: Cpp
|
||||
|
|
230
core/AES.cpp
230
core/AES.cpp
|
@ -11,9 +11,10 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif
|
||||
|
@ -40,12 +41,21 @@ namespace {
|
|||
uint32_t y1t_##N = (y)&0x22222222U; \
|
||||
uint32_t y2t_##N = (y)&0x44444444U; \
|
||||
uint32_t y3t_##N = (y)&0x88888888U; \
|
||||
uint64_t z0t_##N = (((uint64_t)x0t_##N * y0t_##N) ^ ((uint64_t)x1t_##N * y3t_##N) ^ ((uint64_t)x2t_##N * y2t_##N) ^ ((uint64_t)x3t_##N * y1t_##N)) & 0x1111111111111111ULL; \
|
||||
uint64_t z1t_##N = (((uint64_t)x0t_##N * y1t_##N) ^ ((uint64_t)x1t_##N * y0t_##N) ^ ((uint64_t)x2t_##N * y3t_##N) ^ ((uint64_t)x3t_##N * y2t_##N)) & 0x2222222222222222ULL; \
|
||||
uint64_t z2t_##N = (((uint64_t)x0t_##N * y2t_##N) ^ ((uint64_t)x1t_##N * y1t_##N) ^ ((uint64_t)x2t_##N * y0t_##N) ^ ((uint64_t)x3t_##N * y3t_##N)) & 0x4444444444444444ULL; \
|
||||
uint64_t z0t_##N = (((uint64_t)x0t_##N * y0t_##N) ^ ((uint64_t)x1t_##N * y3t_##N) ^ ((uint64_t)x2t_##N * y2t_##N) \
|
||||
^ ((uint64_t)x3t_##N * y1t_##N)) \
|
||||
& 0x1111111111111111ULL; \
|
||||
uint64_t z1t_##N = (((uint64_t)x0t_##N * y1t_##N) ^ ((uint64_t)x1t_##N * y0t_##N) ^ ((uint64_t)x2t_##N * y3t_##N) \
|
||||
^ ((uint64_t)x3t_##N * y2t_##N)) \
|
||||
& 0x2222222222222222ULL; \
|
||||
uint64_t z2t_##N = (((uint64_t)x0t_##N * y2t_##N) ^ ((uint64_t)x1t_##N * y1t_##N) ^ ((uint64_t)x2t_##N * y0t_##N) \
|
||||
^ ((uint64_t)x3t_##N * y3t_##N)) \
|
||||
& 0x4444444444444444ULL; \
|
||||
z0t_##N |= z1t_##N; \
|
||||
z2t_##N |= z0t_##N; \
|
||||
uint64_t zt_##N = z2t_##N | ((((uint64_t)x0t_##N * y3t_##N) ^ ((uint64_t)x1t_##N * y2t_##N) ^ ((uint64_t)x2t_##N * y1t_##N) ^ ((uint64_t)x3t_##N * y0t_##N)) & 0x8888888888888888ULL); \
|
||||
uint64_t zt_##N = z2t_##N \
|
||||
| ((((uint64_t)x0t_##N * y3t_##N) ^ ((uint64_t)x1t_##N * y2t_##N) \
|
||||
^ ((uint64_t)x2t_##N * y1t_##N) ^ ((uint64_t)x3t_##N * y0t_##N)) \
|
||||
& 0x8888888888888888ULL); \
|
||||
(rh) = (uint32_t)(zt_##N >> 32U); \
|
||||
(rl) = (uint32_t)zt_##N;
|
||||
|
||||
|
@ -330,16 +340,21 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
t1 = Te0[s1 >> 24U] ^ Te1_r((s2 >> 16U) & m8) ^ Te2_r((s3 >> 8U) & m8) ^ Te3_r(s0 & m8) ^ rk[53];
|
||||
t2 = Te0[s2 >> 24U] ^ Te1_r((s3 >> 16U) & m8) ^ Te2_r((s0 >> 8U) & m8) ^ Te3_r(s1 & m8) ^ rk[54];
|
||||
t3 = Te0[s3 >> 24U] ^ Te1_r((s0 >> 16U) & m8) ^ Te2_r((s1 >> 8U) & m8) ^ Te3_r(s2 & m8) ^ rk[55];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8) ^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8) ^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8) ^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8) ^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
|
||||
*reinterpret_cast<uint64_t*>(out) = in0 ^ Utils::hton(((uint64_t)s0 << 32U) | (uint64_t)s1);
|
||||
*reinterpret_cast<uint64_t*>(out + 8) = in1 ^ Utils::hton(((uint64_t)s2 << 32U) | (uint64_t)s3);
|
||||
out += 16;
|
||||
} while ((len -= 16) >= 16);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
do {
|
||||
uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
|
||||
s0 = ctr0rk0;
|
||||
|
@ -399,10 +414,14 @@ void AES::CTR::crypt(const void *const input, unsigned int len) noexcept
|
|||
t1 = Te0[s1 >> 24U] ^ Te1_r((s2 >> 16U) & m8) ^ Te2_r((s3 >> 8U) & m8) ^ Te3_r(s0 & m8) ^ rk[53];
|
||||
t2 = Te0[s2 >> 24U] ^ Te1_r((s3 >> 16U) & m8) ^ Te2_r((s0 >> 8U) & m8) ^ Te3_r(s1 & m8) ^ rk[54];
|
||||
t3 = Te0[s3 >> 24U] ^ Te1_r((s0 >> 16U) & m8) ^ Te2_r((s1 >> 8U) & m8) ^ Te3_r(s2 & m8) ^ rk[55];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8) ^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8) ^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8) ^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8) ^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
|
||||
out[0] = in[0] ^ (uint8_t)(s0 >> 24U);
|
||||
out[1] = in[1] ^ (uint8_t)(s0 >> 16U);
|
||||
|
@ -449,35 +468,118 @@ void AES::CTR::finish() noexcept
|
|||
|
||||
// Software AES and AES key expansion ---------------------------------------------------------------------------------
|
||||
|
||||
const uint32_t AES::Te0[256] = {0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153,
|
||||
0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
|
||||
0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba,
|
||||
0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
|
||||
0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437,
|
||||
0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
|
||||
0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878,
|
||||
0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a};
|
||||
const uint32_t AES::Te4[256] = {0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030, 0x01010101, 0x67676767, 0x2b2b2b2b, 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676, 0xcacacaca, 0x82828282, 0xc9c9c9c9, 0x7d7d7d7d, 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2, 0xafafafaf, 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0, 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626, 0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, 0x71717171, 0xd8d8d8d8, 0x31313131,
|
||||
0x15151515, 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, 0x18181818, 0x96969696, 0x05050505, 0x9a9a9a9a, 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, 0xebebebeb, 0x27272727, 0xb2b2b2b2, 0x75757575,
|
||||
0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0, 0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484, 0x53535353, 0xd1d1d1d1, 0x00000000, 0xedededed, 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, 0x6a6a6a6a, 0xcbcbcbcb, 0xbebebebe, 0x39393939, 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf, 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa, 0xfbfbfbfb, 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f, 0x50505050, 0x3c3c3c3c, 0x9f9f9f9f,
|
||||
0xa8a8a8a8, 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, 0x92929292, 0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, 0x10101010, 0xffffffff, 0xf3f3f3f3, 0xd2d2d2d2,
|
||||
0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, 0x5f5f5f5f, 0x97979797, 0x44444444, 0x17171717, 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373, 0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, 0x46464646, 0xeeeeeeee, 0xb8b8b8b8, 0x14141414, 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb, 0xe0e0e0e0, 0x32323232, 0x3a3a3a3a, 0x0a0a0a0a, 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac, 0x62626262, 0x91919191, 0x95959595, 0xe4e4e4e4,
|
||||
0x79797979, 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d, 0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, 0x65656565, 0x7a7a7a7a, 0xaeaeaeae, 0x08080808,
|
||||
0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, 0x1c1c1c1c, 0xa6a6a6a6, 0xb4b4b4b4, 0xc6c6c6c6, 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b, 0x8a8a8a8a, 0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e, 0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e, 0xe1e1e1e1, 0xf8f8f8f8, 0x98989898, 0x11111111, 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, 0x9b9b9b9b, 0x1e1e1e1e, 0x87878787, 0xe9e9e9e9, 0xcececece, 0x55555555, 0x28282828,
|
||||
0xdfdfdfdf, 0x8c8c8c8c, 0xa1a1a1a1, 0x89898989, 0x0d0d0d0d, 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f, 0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616};
|
||||
const uint32_t AES::Td0[256] = {0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c,
|
||||
0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
|
||||
0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1,
|
||||
0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
|
||||
0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e,
|
||||
0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
|
||||
0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14,
|
||||
0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742};
|
||||
const uint8_t AES::Td4[256] = {0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d,
|
||||
0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c,
|
||||
0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
|
||||
const uint32_t AES::rcon[15] = {0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000};
|
||||
const uint32_t AES::Te0[256] = {
|
||||
0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050,
|
||||
0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d,
|
||||
0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd,
|
||||
0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a,
|
||||
0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193,
|
||||
0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1,
|
||||
0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd,
|
||||
0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
|
||||
0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5,
|
||||
0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46,
|
||||
0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5,
|
||||
0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81,
|
||||
0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad,
|
||||
0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a,
|
||||
0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc,
|
||||
0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
|
||||
0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca,
|
||||
0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256,
|
||||
0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef,
|
||||
0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7,
|
||||
0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af,
|
||||
0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1,
|
||||
0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86,
|
||||
0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
|
||||
0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138,
|
||||
0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22,
|
||||
0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980,
|
||||
0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11,
|
||||
0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a
|
||||
};
|
||||
const uint32_t AES::Te4[256] = {
|
||||
0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030,
|
||||
0x01010101, 0x67676767, 0x2b2b2b2b, 0xfefefefe, 0xd7d7d7d7, 0xabababab, 0x76767676, 0xcacacaca, 0x82828282,
|
||||
0xc9c9c9c9, 0x7d7d7d7d, 0xfafafafa, 0x59595959, 0x47474747, 0xf0f0f0f0, 0xadadadad, 0xd4d4d4d4, 0xa2a2a2a2,
|
||||
0xafafafaf, 0x9c9c9c9c, 0xa4a4a4a4, 0x72727272, 0xc0c0c0c0, 0xb7b7b7b7, 0xfdfdfdfd, 0x93939393, 0x26262626,
|
||||
0x36363636, 0x3f3f3f3f, 0xf7f7f7f7, 0xcccccccc, 0x34343434, 0xa5a5a5a5, 0xe5e5e5e5, 0xf1f1f1f1, 0x71717171,
|
||||
0xd8d8d8d8, 0x31313131, 0x15151515, 0x04040404, 0xc7c7c7c7, 0x23232323, 0xc3c3c3c3, 0x18181818, 0x96969696,
|
||||
0x05050505, 0x9a9a9a9a, 0x07070707, 0x12121212, 0x80808080, 0xe2e2e2e2, 0xebebebeb, 0x27272727, 0xb2b2b2b2,
|
||||
0x75757575, 0x09090909, 0x83838383, 0x2c2c2c2c, 0x1a1a1a1a, 0x1b1b1b1b, 0x6e6e6e6e, 0x5a5a5a5a, 0xa0a0a0a0,
|
||||
0x52525252, 0x3b3b3b3b, 0xd6d6d6d6, 0xb3b3b3b3, 0x29292929, 0xe3e3e3e3, 0x2f2f2f2f, 0x84848484, 0x53535353,
|
||||
0xd1d1d1d1, 0x00000000, 0xedededed, 0x20202020, 0xfcfcfcfc, 0xb1b1b1b1, 0x5b5b5b5b, 0x6a6a6a6a, 0xcbcbcbcb,
|
||||
0xbebebebe, 0x39393939, 0x4a4a4a4a, 0x4c4c4c4c, 0x58585858, 0xcfcfcfcf, 0xd0d0d0d0, 0xefefefef, 0xaaaaaaaa,
|
||||
0xfbfbfbfb, 0x43434343, 0x4d4d4d4d, 0x33333333, 0x85858585, 0x45454545, 0xf9f9f9f9, 0x02020202, 0x7f7f7f7f,
|
||||
0x50505050, 0x3c3c3c3c, 0x9f9f9f9f, 0xa8a8a8a8, 0x51515151, 0xa3a3a3a3, 0x40404040, 0x8f8f8f8f, 0x92929292,
|
||||
0x9d9d9d9d, 0x38383838, 0xf5f5f5f5, 0xbcbcbcbc, 0xb6b6b6b6, 0xdadadada, 0x21212121, 0x10101010, 0xffffffff,
|
||||
0xf3f3f3f3, 0xd2d2d2d2, 0xcdcdcdcd, 0x0c0c0c0c, 0x13131313, 0xecececec, 0x5f5f5f5f, 0x97979797, 0x44444444,
|
||||
0x17171717, 0xc4c4c4c4, 0xa7a7a7a7, 0x7e7e7e7e, 0x3d3d3d3d, 0x64646464, 0x5d5d5d5d, 0x19191919, 0x73737373,
|
||||
0x60606060, 0x81818181, 0x4f4f4f4f, 0xdcdcdcdc, 0x22222222, 0x2a2a2a2a, 0x90909090, 0x88888888, 0x46464646,
|
||||
0xeeeeeeee, 0xb8b8b8b8, 0x14141414, 0xdededede, 0x5e5e5e5e, 0x0b0b0b0b, 0xdbdbdbdb, 0xe0e0e0e0, 0x32323232,
|
||||
0x3a3a3a3a, 0x0a0a0a0a, 0x49494949, 0x06060606, 0x24242424, 0x5c5c5c5c, 0xc2c2c2c2, 0xd3d3d3d3, 0xacacacac,
|
||||
0x62626262, 0x91919191, 0x95959595, 0xe4e4e4e4, 0x79797979, 0xe7e7e7e7, 0xc8c8c8c8, 0x37373737, 0x6d6d6d6d,
|
||||
0x8d8d8d8d, 0xd5d5d5d5, 0x4e4e4e4e, 0xa9a9a9a9, 0x6c6c6c6c, 0x56565656, 0xf4f4f4f4, 0xeaeaeaea, 0x65656565,
|
||||
0x7a7a7a7a, 0xaeaeaeae, 0x08080808, 0xbabababa, 0x78787878, 0x25252525, 0x2e2e2e2e, 0x1c1c1c1c, 0xa6a6a6a6,
|
||||
0xb4b4b4b4, 0xc6c6c6c6, 0xe8e8e8e8, 0xdddddddd, 0x74747474, 0x1f1f1f1f, 0x4b4b4b4b, 0xbdbdbdbd, 0x8b8b8b8b,
|
||||
0x8a8a8a8a, 0x70707070, 0x3e3e3e3e, 0xb5b5b5b5, 0x66666666, 0x48484848, 0x03030303, 0xf6f6f6f6, 0x0e0e0e0e,
|
||||
0x61616161, 0x35353535, 0x57575757, 0xb9b9b9b9, 0x86868686, 0xc1c1c1c1, 0x1d1d1d1d, 0x9e9e9e9e, 0xe1e1e1e1,
|
||||
0xf8f8f8f8, 0x98989898, 0x11111111, 0x69696969, 0xd9d9d9d9, 0x8e8e8e8e, 0x94949494, 0x9b9b9b9b, 0x1e1e1e1e,
|
||||
0x87878787, 0xe9e9e9e9, 0xcececece, 0x55555555, 0x28282828, 0xdfdfdfdf, 0x8c8c8c8c, 0xa1a1a1a1, 0x89898989,
|
||||
0x0d0d0d0d, 0xbfbfbfbf, 0xe6e6e6e6, 0x42424242, 0x68686868, 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f,
|
||||
0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616
|
||||
};
|
||||
const uint32_t AES::Td0[256] = {
|
||||
0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55,
|
||||
0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67,
|
||||
0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb,
|
||||
0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd,
|
||||
0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0,
|
||||
0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2,
|
||||
0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba,
|
||||
0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a,
|
||||
0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9,
|
||||
0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997,
|
||||
0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9,
|
||||
0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927,
|
||||
0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f,
|
||||
0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad,
|
||||
0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5,
|
||||
0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
|
||||
0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c,
|
||||
0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1,
|
||||
0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b,
|
||||
0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3,
|
||||
0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65,
|
||||
0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331,
|
||||
0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e,
|
||||
0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f,
|
||||
0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c,
|
||||
0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f,
|
||||
0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c,
|
||||
0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190,
|
||||
0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742
|
||||
};
|
||||
const uint8_t AES::Td4[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39,
|
||||
0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2,
|
||||
0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76,
|
||||
0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc,
|
||||
0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d,
|
||||
0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c,
|
||||
0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f,
|
||||
0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
|
||||
0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62,
|
||||
0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd,
|
||||
0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60,
|
||||
0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
|
||||
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,
|
||||
0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
||||
};
|
||||
const uint32_t AES::rcon[15] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
|
||||
0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
|
||||
0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000 };
|
||||
|
||||
void AES::p_initSW(const uint8_t* key) noexcept
|
||||
{
|
||||
|
@ -493,14 +595,16 @@ void AES::p_initSW(const uint8_t *key) noexcept
|
|||
rk[7] = Utils::loadBigEndian<uint32_t>(key + 28);
|
||||
for (int i = 0;;) {
|
||||
uint32_t temp = rk[7];
|
||||
rk[8] = rk[0] ^ (Te2_r((temp >> 16U) & 0xffU) & 0xff000000U) ^ (Te3_r((temp >> 8U) & 0xffU) & 0x00ff0000U) ^ (Te0[(temp) & 0xffU] & 0x0000ff00U) ^ (Te1_r(temp >> 24U) & 0x000000ffU) ^ rcon[i];
|
||||
rk[8] = rk[0] ^ (Te2_r((temp >> 16U) & 0xffU) & 0xff000000U) ^ (Te3_r((temp >> 8U) & 0xffU) & 0x00ff0000U)
|
||||
^ (Te0[(temp)&0xffU] & 0x0000ff00U) ^ (Te1_r(temp >> 24U) & 0x000000ffU) ^ rcon[i];
|
||||
rk[9] = rk[1] ^ rk[8];
|
||||
rk[10] = rk[2] ^ rk[9];
|
||||
rk[11] = rk[3] ^ rk[10];
|
||||
if (++i == 7)
|
||||
break;
|
||||
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[14] = rk[6] ^ rk[13];
|
||||
rk[15] = rk[7] ^ rk[14];
|
||||
|
@ -531,10 +635,14 @@ void AES::p_initSW(const uint8_t *key) noexcept
|
|||
}
|
||||
for (int i = 1; i < 14; ++i) {
|
||||
rk += 4;
|
||||
rk[0] = Td0[Te4[(rk[0] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[0] >> 16U) & 0xffU] & 0xffU) ^ Td2_r(Te4[(rk[0] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[0]) & 0xffU] & 0xffU);
|
||||
rk[1] = Td0[Te4[(rk[1] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[1] >> 16U) & 0xffU] & 0xffU) ^ Td2_r(Te4[(rk[1] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[1]) & 0xffU] & 0xffU);
|
||||
rk[2] = Td0[Te4[(rk[2] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[2] >> 16U) & 0xffU] & 0xffU) ^ Td2_r(Te4[(rk[2] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[2]) & 0xffU] & 0xffU);
|
||||
rk[3] = Td0[Te4[(rk[3] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[3] >> 16U) & 0xffU] & 0xffU) ^ Td2_r(Te4[(rk[3] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[3]) & 0xffU] & 0xffU);
|
||||
rk[0] = Td0[Te4[(rk[0] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[0] >> 16U) & 0xffU] & 0xffU)
|
||||
^ Td2_r(Te4[(rk[0] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[0]) & 0xffU] & 0xffU);
|
||||
rk[1] = Td0[Te4[(rk[1] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[1] >> 16U) & 0xffU] & 0xffU)
|
||||
^ Td2_r(Te4[(rk[1] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[1]) & 0xffU] & 0xffU);
|
||||
rk[2] = Td0[Te4[(rk[2] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[2] >> 16U) & 0xffU] & 0xffU)
|
||||
^ Td2_r(Te4[(rk[2] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[2]) & 0xffU] & 0xffU);
|
||||
rk[3] = Td0[Te4[(rk[3] >> 24U)] & 0xffU] ^ Td1_r(Te4[(rk[3] >> 16U) & 0xffU] & 0xffU)
|
||||
^ Td2_r(Te4[(rk[3] >> 8U) & 0xffU] & 0xffU) ^ Td3_r(Te4[(rk[3]) & 0xffU] & 0xffU);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -603,10 +711,14 @@ void AES::p_encryptSW(const uint8_t *in, uint8_t *out) const noexcept
|
|||
t1 = Te0[s1 >> 24U] ^ Te1_r((s2 >> 16U) & m8) ^ Te2_r((s3 >> 8U) & m8) ^ Te3_r(s0 & m8) ^ rk[53];
|
||||
t2 = Te0[s2 >> 24U] ^ Te1_r((s3 >> 16U) & m8) ^ Te2_r((s0 >> 8U) & m8) ^ Te3_r(s1 & m8) ^ rk[54];
|
||||
t3 = Te0[s3 >> 24U] ^ Te1_r((s0 >> 16U) & m8) ^ Te2_r((s1 >> 8U) & m8) ^ Te3_r(s2 & m8) ^ rk[55];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8) ^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8) ^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8) ^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8) ^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
s0 = (Te2_r(t0 >> 24U) & m8_24) ^ (Te3_r((t1 >> 16U) & m8) & m8_16) ^ (Te0[(t2 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t3 & m8) & m8) ^ rk[56];
|
||||
s1 = (Te2_r(t1 >> 24U) & m8_24) ^ (Te3_r((t2 >> 16U) & m8) & m8_16) ^ (Te0[(t3 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t0 & m8) & m8) ^ rk[57];
|
||||
s2 = (Te2_r(t2 >> 24U) & m8_24) ^ (Te3_r((t3 >> 16U) & m8) & m8_16) ^ (Te0[(t0 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t1 & m8) & m8) ^ rk[58];
|
||||
s3 = (Te2_r(t3 >> 24U) & m8_24) ^ (Te3_r((t0 >> 16U) & m8) & m8_16) ^ (Te0[(t1 >> 8U) & m8] & m8_8)
|
||||
^ (Te1_r(t2 & m8) & m8) ^ rk[59];
|
||||
|
||||
Utils::storeBigEndian<uint32_t>(out, s0);
|
||||
Utils::storeBigEndian<uint32_t>(out + 4, s1);
|
||||
|
@ -676,10 +788,14 @@ void AES::p_decryptSW(const uint8_t *in, uint8_t *out) const noexcept
|
|||
t1 = Td0[s1 >> 24U] ^ Td1_r((s0 >> 16U) & m8) ^ Td2_r((s3 >> 8U) & m8) ^ Td3_r(s2 & m8) ^ rk[53];
|
||||
t2 = Td0[s2 >> 24U] ^ Td1_r((s1 >> 16U) & m8) ^ Td2_r((s0 >> 8U) & m8) ^ Td3_r(s3 & m8) ^ rk[54];
|
||||
t3 = Td0[s3 >> 24U] ^ Td1_r((s2 >> 16U) & m8) ^ Td2_r((s1 >> 8U) & m8) ^ Td3_r(s0 & m8) ^ rk[55];
|
||||
s0 = (Td4[t0 >> 24U] << 24U) ^ (Td4[(t3 >> 16U) & m8] << 16U) ^ (Td4[(t2 >> 8U) & m8] << 8U) ^ (Td4[(t1) & m8]) ^ rk[56];
|
||||
s1 = (Td4[t1 >> 24U] << 24U) ^ (Td4[(t0 >> 16U) & m8] << 16U) ^ (Td4[(t3 >> 8U) & m8] << 8U) ^ (Td4[(t2) & m8]) ^ rk[57];
|
||||
s2 = (Td4[t2 >> 24U] << 24U) ^ (Td4[(t1 >> 16U) & m8] << 16U) ^ (Td4[(t0 >> 8U) & m8] << 8U) ^ (Td4[(t3) & m8]) ^ rk[58];
|
||||
s3 = (Td4[t3 >> 24U] << 24U) ^ (Td4[(t2 >> 16U) & m8] << 16U) ^ (Td4[(t1 >> 8U) & m8] << 8U) ^ (Td4[(t0) & m8]) ^ rk[59];
|
||||
s0 = (Td4[t0 >> 24U] << 24U) ^ (Td4[(t3 >> 16U) & m8] << 16U) ^ (Td4[(t2 >> 8U) & m8] << 8U) ^ (Td4[(t1)&m8])
|
||||
^ rk[56];
|
||||
s1 = (Td4[t1 >> 24U] << 24U) ^ (Td4[(t0 >> 16U) & m8] << 16U) ^ (Td4[(t3 >> 8U) & m8] << 8U) ^ (Td4[(t2)&m8])
|
||||
^ rk[57];
|
||||
s2 = (Td4[t2 >> 24U] << 24U) ^ (Td4[(t1 >> 16U) & m8] << 16U) ^ (Td4[(t0 >> 8U) & m8] << 8U) ^ (Td4[(t3)&m8])
|
||||
^ rk[58];
|
||||
s3 = (Td4[t3 >> 24U] << 24U) ^ (Td4[(t2 >> 16U) & m8] << 16U) ^ (Td4[(t1 >> 8U) & m8] << 8U) ^ (Td4[(t0)&m8])
|
||||
^ rk[59];
|
||||
|
||||
Utils::storeBigEndian<uint32_t>(out, s0);
|
||||
Utils::storeBigEndian<uint32_t>(out + 4, s1);
|
||||
|
|
72
core/AES.hpp
72
core/AES.hpp
|
@ -15,8 +15,8 @@
|
|||
#define ZT_AES_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
// Uncomment to disable all hardware acceleration (usually for testing)
|
||||
//#define ZT_AES_NO_ACCEL
|
||||
|
@ -40,8 +40,7 @@ namespace ZeroTier {
|
|||
* This includes hardware acceleration for certain processors. The software
|
||||
* mode is fallback and is significantly slower.
|
||||
*/
|
||||
class AES
|
||||
{
|
||||
class AES {
|
||||
public:
|
||||
/**
|
||||
* @return True if this system has hardware AES acceleration
|
||||
|
@ -64,7 +63,8 @@ public:
|
|||
* Create an un-initialized AES instance (must call init() before use)
|
||||
*/
|
||||
ZT_INLINE AES() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an AES instance with the given key
|
||||
|
@ -72,10 +72,14 @@ public:
|
|||
* @param key 256-bit key
|
||||
*/
|
||||
explicit ZT_INLINE AES(const void* const key) noexcept
|
||||
{ this->init(key); }
|
||||
{
|
||||
this->init(key);
|
||||
}
|
||||
|
||||
ZT_INLINE ~AES()
|
||||
{ Utils::burn(&p_k, sizeof(p_k)); }
|
||||
{
|
||||
Utils::burn(&p_k, sizeof(p_k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set (or re-set) this AES256 cipher's key
|
||||
|
@ -151,8 +155,7 @@ public:
|
|||
/**
|
||||
* Streaming GMAC calculator
|
||||
*/
|
||||
class GMAC
|
||||
{
|
||||
class GMAC {
|
||||
friend class GMACSIVEncryptor;
|
||||
friend class GMACSIVDecryptor;
|
||||
|
||||
|
@ -179,7 +182,8 @@ public:
|
|||
* @param aes Keyed AES instance to use
|
||||
*/
|
||||
ZT_INLINE GMAC(const AES& aes) : _aes(aes)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset and initialize for a new GMAC calculation
|
||||
|
@ -251,14 +255,14 @@ public:
|
|||
* We will never encrypt more than a tiny fraction of 2^32 blocks, so this is left out as
|
||||
* an optimization.
|
||||
*/
|
||||
class CTR
|
||||
{
|
||||
class CTR {
|
||||
friend class GMACSIVEncryptor;
|
||||
friend class GMACSIVDecryptor;
|
||||
|
||||
public:
|
||||
ZT_INLINE CTR(const AES& aes) noexcept : _aes(aes)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this CTR instance to encrypt a new stream
|
||||
|
@ -327,8 +331,7 @@ public:
|
|||
* This supports encryption of a maximum of 2^31 bytes of data per
|
||||
* call to init().
|
||||
*/
|
||||
class GMACSIVEncryptor
|
||||
{
|
||||
class GMACSIVEncryptor {
|
||||
public:
|
||||
/**
|
||||
* Create a new AES-GMAC-SIV encryptor keyed with the provided AES instances
|
||||
|
@ -336,10 +339,11 @@ public:
|
|||
* @param k0 First of two AES instances keyed with K0
|
||||
* @param k1 Second of two AES instances keyed with K1
|
||||
*/
|
||||
ZT_INLINE GMACSIVEncryptor(const AES &k0, const AES &k1) noexcept :
|
||||
_gmac(k0),
|
||||
_ctr(k1)
|
||||
{}
|
||||
ZT_INLINE GMACSIVEncryptor(const AES& k0, const AES& k1) noexcept
|
||||
: _gmac(k0)
|
||||
, _ctr(k1)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize AES-GMAC-SIV
|
||||
|
@ -386,7 +390,9 @@ public:
|
|||
* @param len Length of plaintext chunk
|
||||
*/
|
||||
ZT_INLINE void update1(const void* const input, const unsigned int len) noexcept
|
||||
{ _gmac.update(input, len); }
|
||||
{
|
||||
_gmac.update(input, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish first pass, compute CTR IV, initialize second pass.
|
||||
|
@ -429,7 +435,9 @@ public:
|
|||
* @param len Length of plaintext chunk
|
||||
*/
|
||||
ZT_INLINE void update2(const void* const input, const unsigned int len) noexcept
|
||||
{ _ctr.crypt(input, len); }
|
||||
{
|
||||
_ctr.crypt(input, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish second pass and return a pointer to the opaque 128-bit IV+MAC block
|
||||
|
@ -457,13 +465,13 @@ public:
|
|||
*
|
||||
* GMAC-SIV decryption is single-pass. AAD (if any) must be processed first.
|
||||
*/
|
||||
class GMACSIVDecryptor
|
||||
{
|
||||
class GMACSIVDecryptor {
|
||||
public:
|
||||
ZT_INLINE GMACSIVDecryptor(const AES &k0, const AES &k1) noexcept:
|
||||
_ctr(k1),
|
||||
_gmac(k0)
|
||||
{}
|
||||
ZT_INLINE GMACSIVDecryptor(const AES& k0, const AES& k1) noexcept
|
||||
: _ctr(k1)
|
||||
, _gmac(k0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize decryptor for a new message
|
||||
|
@ -550,11 +558,9 @@ private:
|
|||
void p_encryptSW(const uint8_t* in, uint8_t* out) const noexcept;
|
||||
void p_decryptSW(const uint8_t* in, uint8_t* out) const noexcept;
|
||||
|
||||
union
|
||||
{
|
||||
union {
|
||||
#ifdef ZT_AES_AESNI
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
__m128i k[28];
|
||||
__m128i h[4]; // h, hh, hhh, hhhh
|
||||
__m128i h2[4]; // _mm_xor_si128(_mm_shuffle_epi32(h, 78), h), etc.
|
||||
|
@ -562,8 +568,7 @@ private:
|
|||
#endif
|
||||
|
||||
#ifdef ZT_AES_NEON
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint64_t hsw[2]; // in case it has AES but not PMULL, not sure if that ever happens
|
||||
uint8x16_t ek[15];
|
||||
uint8x16_t dk[15];
|
||||
|
@ -571,8 +576,7 @@ private:
|
|||
} neon;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint64_t h[2];
|
||||
uint32_t ek[60];
|
||||
uint32_t dk[60];
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
// AES for X64 AES-NI extensions (no 32-bit X86 support). Supports AVX2 and
|
||||
// AVX512 VAES for performance in excess of 10GiB/sec/core on newer chips.
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Constants.hpp"
|
||||
|
||||
#ifdef ZT_AES_AESNI
|
||||
|
||||
|
@ -32,7 +32,8 @@ const __m128i s_sseSwapBytes = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|
|||
#ifdef __GNUC__
|
||||
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,pclmul")))
|
||||
#endif
|
||||
__m128i p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
|
||||
__m128i
|
||||
p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
|
||||
{
|
||||
y = _mm_shuffle_epi8(y, s_sseSwapBytes);
|
||||
__m128i t1 = _mm_clmulepi64_si128(h, y, 0x00);
|
||||
|
@ -46,10 +47,16 @@ __m128i p_gmacPCLMUL128(const __m128i h, __m128i y) noexcept
|
|||
t4 = _mm_xor_si128(t4, t2);
|
||||
__m128i t5 = _mm_srli_epi32(t1, 31);
|
||||
t1 = _mm_or_si128(_mm_slli_epi32(t1, 1), _mm_slli_si128(t5, 4));
|
||||
t4 = _mm_or_si128(_mm_or_si128(_mm_slli_epi32(t4, 1), _mm_slli_si128(_mm_srli_epi32(t4, 31), 4)), _mm_srli_si128(t5, 12));
|
||||
t4 = _mm_or_si128(
|
||||
_mm_or_si128(_mm_slli_epi32(t4, 1), _mm_slli_si128(_mm_srli_epi32(t4, 31), 4)),
|
||||
_mm_srli_si128(t5, 12));
|
||||
t5 = _mm_xor_si128(_mm_xor_si128(_mm_slli_epi32(t1, 31), _mm_slli_epi32(t1, 30)), _mm_slli_epi32(t1, 25));
|
||||
t1 = _mm_xor_si128(t1, _mm_slli_si128(t5, 12));
|
||||
t4 = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(t4, _mm_srli_si128(t5, 4)), t1), _mm_srli_epi32(t1, 2)), _mm_srli_epi32(t1, 7)), _mm_srli_epi32(t1, 1));
|
||||
t4 = _mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(t4, _mm_srli_si128(t5, 4)), t1), _mm_srli_epi32(t1, 2)),
|
||||
_mm_srli_epi32(t1, 7)),
|
||||
_mm_srli_epi32(t1, 1));
|
||||
return _mm_shuffle_epi8(t4, s_sseSwapBytes);
|
||||
}
|
||||
|
||||
|
@ -85,10 +92,14 @@ void p_aesCtrInnerVAES512(unsigned int &len, const uint64_t c0, uint64_t &c1, co
|
|||
do {
|
||||
__m512i p0 = _mm512_loadu_si512(reinterpret_cast<const __m512i*>(in));
|
||||
__m512i d0 = _mm512_set_epi64(
|
||||
(long long)Utils::hton(c1 + 3ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1 + 2ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1 + 1ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1), (long long)c0);
|
||||
(long long)Utils::hton(c1 + 3ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1 + 2ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1 + 1ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1),
|
||||
(long long)c0);
|
||||
c1 += 4;
|
||||
in += 64;
|
||||
len -= 64;
|
||||
|
@ -138,11 +149,15 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
|
|||
__m256i p0 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in));
|
||||
__m256i p1 = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(in + 32));
|
||||
__m256i d0 = _mm256_set_epi64x(
|
||||
(long long)Utils::hton(c1 + 1ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1), (long long)c0);
|
||||
(long long)Utils::hton(c1 + 1ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1),
|
||||
(long long)c0);
|
||||
__m256i d1 = _mm256_set_epi64x(
|
||||
(long long)Utils::hton(c1 + 3ULL), (long long)c0,
|
||||
(long long)Utils::hton(c1 + 2ULL), (long long)c0);
|
||||
(long long)Utils::hton(c1 + 3ULL),
|
||||
(long long)c0,
|
||||
(long long)Utils::hton(c1 + 2ULL),
|
||||
(long long)c0);
|
||||
c1 += 4;
|
||||
in += 64;
|
||||
len -= 64;
|
||||
|
@ -187,7 +202,8 @@ void p_aesCtrInnerVAES256(unsigned int &len, const uint64_t c0, uint64_t &c1, co
|
|||
#ifdef __GNUC__
|
||||
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
|
||||
#endif
|
||||
__m128i p_init256_1_aesni(__m128i a, __m128i b) noexcept
|
||||
__m128i
|
||||
p_init256_1_aesni(__m128i a, __m128i b) noexcept
|
||||
{
|
||||
__m128i x, y;
|
||||
b = _mm_shuffle_epi32(b, 0xff);
|
||||
|
@ -204,7 +220,8 @@ __m128i p_init256_1_aesni(__m128i a, __m128i b) noexcept
|
|||
#ifdef __GNUC__
|
||||
__attribute__((__target__("ssse3,sse4,sse4.1,sse4.2,aes,pclmul")))
|
||||
#endif
|
||||
__m128i p_init256_2_aesni(__m128i a, __m128i b) noexcept
|
||||
__m128i
|
||||
p_init256_2_aesni(__m128i a, __m128i b) noexcept
|
||||
{
|
||||
__m128i x, y, z;
|
||||
y = _mm_aeskeygenassist_si128(a, 0x00);
|
||||
|
@ -236,7 +253,9 @@ void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
|
|||
--len;
|
||||
_r[_rp++] = *(in++);
|
||||
if (_rp == 16) {
|
||||
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))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -260,17 +279,37 @@ void AES::GMAC::p_aesNIUpdate(const uint8_t *in, unsigned int len) noexcept
|
|||
__m128i d3 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 32)), sb);
|
||||
__m128i d4 = _mm_shuffle_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 48)), sb);
|
||||
in += 64;
|
||||
__m128i a = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x00), _mm_clmulepi64_si128(hhh, d2, 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x00), _mm_clmulepi64_si128(h, d4, 0x00)));
|
||||
__m128i b = _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x11), _mm_clmulepi64_si128(hhh, d2, 0x11)), _mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x11), _mm_clmulepi64_si128(h, d4, 0x11)));
|
||||
__m128i c = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(hhhh2, _mm_xor_si128(_mm_shuffle_epi32(d1, 78), d1), 0x00), _mm_clmulepi64_si128(hhh2, _mm_xor_si128(_mm_shuffle_epi32(d2, 78), d2), 0x00)), _mm_xor_si128(_mm_clmulepi64_si128(hh2, _mm_xor_si128(_mm_shuffle_epi32(d3, 78), d3), 0x00), _mm_clmulepi64_si128(h2, _mm_xor_si128(_mm_shuffle_epi32(d4, 78), d4), 0x00))), _mm_xor_si128(a, b));
|
||||
__m128i a = _mm_xor_si128(
|
||||
_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x00), _mm_clmulepi64_si128(hhh, d2, 0x00)),
|
||||
_mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x00), _mm_clmulepi64_si128(h, d4, 0x00)));
|
||||
__m128i b = _mm_xor_si128(
|
||||
_mm_xor_si128(_mm_clmulepi64_si128(hhhh, d1, 0x11), _mm_clmulepi64_si128(hhh, d2, 0x11)),
|
||||
_mm_xor_si128(_mm_clmulepi64_si128(hh, d3, 0x11), _mm_clmulepi64_si128(h, d4, 0x11)));
|
||||
__m128i c = _mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
_mm_clmulepi64_si128(hhhh2, _mm_xor_si128(_mm_shuffle_epi32(d1, 78), d1), 0x00),
|
||||
_mm_clmulepi64_si128(hhh2, _mm_xor_si128(_mm_shuffle_epi32(d2, 78), d2), 0x00)),
|
||||
_mm_xor_si128(
|
||||
_mm_clmulepi64_si128(hh2, _mm_xor_si128(_mm_shuffle_epi32(d3, 78), d3), 0x00),
|
||||
_mm_clmulepi64_si128(h2, _mm_xor_si128(_mm_shuffle_epi32(d4, 78), d4), 0x00))),
|
||||
_mm_xor_si128(a, b));
|
||||
a = _mm_xor_si128(_mm_slli_si128(c, 8), a);
|
||||
b = _mm_xor_si128(_mm_srli_si128(c, 8), b);
|
||||
c = _mm_srli_epi32(a, 31);
|
||||
a = _mm_or_si128(_mm_slli_epi32(a, 1), _mm_slli_si128(c, 4));
|
||||
b = _mm_or_si128(_mm_or_si128(_mm_slli_epi32(b, 1), _mm_slli_si128(_mm_srli_epi32(b, 31), 4)), _mm_srli_si128(c, 12));
|
||||
b = _mm_or_si128(
|
||||
_mm_or_si128(_mm_slli_epi32(b, 1), _mm_slli_si128(_mm_srli_epi32(b, 31), 4)),
|
||||
_mm_srli_si128(c, 12));
|
||||
c = _mm_xor_si128(_mm_slli_epi32(a, 31), _mm_xor_si128(_mm_slli_epi32(a, 30), _mm_slli_epi32(a, 25)));
|
||||
a = _mm_xor_si128(a, _mm_slli_si128(c, 12));
|
||||
b = _mm_xor_si128(b, _mm_xor_si128(a, _mm_xor_si128(_mm_xor_si128(_mm_srli_epi32(a, 1), _mm_srli_si128(c, 4)), _mm_xor_si128(_mm_srli_epi32(a, 2), _mm_srli_epi32(a, 7)))));
|
||||
b = _mm_xor_si128(
|
||||
b,
|
||||
_mm_xor_si128(
|
||||
a,
|
||||
_mm_xor_si128(
|
||||
_mm_xor_si128(_mm_srli_epi32(a, 1), _mm_srli_si128(c, 4)),
|
||||
_mm_xor_si128(_mm_srli_epi32(a, 2), _mm_srli_epi32(a, 7)))));
|
||||
y = _mm_shuffle_epi8(b, sb);
|
||||
} while (likely(in != end64));
|
||||
}
|
||||
|
@ -427,12 +466,12 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
_len = totalLen + len;
|
||||
|
||||
if (likely(len >= 64)) {
|
||||
|
||||
#if defined(ZT_AES_VAES512) && defined(ZT_AES_VAES256)
|
||||
if (Utils::CPUID.vaes) {
|
||||
if (Utils::CPUID.avx512f) {
|
||||
p_aesCtrInnerVAES512(len, _ctr[0], c1, in, out, k);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p_aesCtrInnerVAES256(len, _ctr[0], c1, in, out, k);
|
||||
}
|
||||
goto skip_conventional_aesni_64;
|
||||
|
@ -516,9 +555,15 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
d2 = _mm_aesenc_si128(d2, k13);
|
||||
d3 = _mm_aesenc_si128(d3, k13);
|
||||
d0 = _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in)));
|
||||
d1 = _mm_xor_si128(_mm_aesenclast_si128(d1, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 16)));
|
||||
d2 = _mm_xor_si128(_mm_aesenclast_si128(d2, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 32)));
|
||||
d3 = _mm_xor_si128(_mm_aesenclast_si128(d3, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in + 48)));
|
||||
d1 = _mm_xor_si128(
|
||||
_mm_aesenclast_si128(d1, k14),
|
||||
_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 16)));
|
||||
d2 = _mm_xor_si128(
|
||||
_mm_aesenclast_si128(d2, k14),
|
||||
_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 32)));
|
||||
d3 = _mm_xor_si128(
|
||||
_mm_aesenclast_si128(d3, k14),
|
||||
_mm_loadu_si128(reinterpret_cast<const __m128i*>(in + 48)));
|
||||
in += 64;
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(out), d0);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 16), d1);
|
||||
|
@ -526,7 +571,6 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
_mm_storeu_si128(reinterpret_cast<__m128i*>(out + 48), d3);
|
||||
out += 64;
|
||||
} while (likely(in != eof64));
|
||||
|
||||
}
|
||||
|
||||
skip_conventional_aesni_64:
|
||||
|
@ -546,7 +590,9 @@ void AES::CTR::p_aesNICrypt(const uint8_t *in, uint8_t *out, unsigned int len) n
|
|||
d0 = _mm_aesenc_si128(d0, k11);
|
||||
d0 = _mm_aesenc_si128(d0, k12);
|
||||
d0 = _mm_aesenc_si128(d0, k13);
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(out), _mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i *>(in))));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(out),
|
||||
_mm_xor_si128(_mm_aesenclast_si128(d0, k14), _mm_loadu_si128(reinterpret_cast<const __m128i*>(in))));
|
||||
in += 16;
|
||||
len -= 16;
|
||||
out += 16;
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
|
||||
// AES for ARM crypto extensions and NEON.
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Constants.hpp"
|
||||
|
||||
#ifdef ZT_AES_NEON
|
||||
|
||||
|
@ -298,7 +298,9 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
|
|||
vst1q_u8(reinterpret_cast<uint8_t*>(_ctr), vrev32q_u8(dd));
|
||||
}
|
||||
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_SUBWORD(w) ((uint32_t)s_sbox[w & 0xffU] + ((uint32_t)s_sbox[(w >> 8U) & 0xffU] << 8U) + ((uint32_t)s_sbox[(w >> 16U) & 0xffU] << 16U) + ((uint32_t)s_sbox[(w >> 24U) & 0xffU] << 24U))
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_SUBWORD(w) \
|
||||
((uint32_t)s_sbox[w & 0xffU] + ((uint32_t)s_sbox[(w >> 8U) & 0xffU] << 8U) \
|
||||
+ ((uint32_t)s_sbox[(w >> 16U) & 0xffU] << 16U) + ((uint32_t)s_sbox[(w >> 24U) & 0xffU] << 24U))
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_ROTWORD(w) (((w) << 8U) | ((w) >> 24U))
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_NK 8
|
||||
#define ZT_INIT_ARMNEON_CRYPTO_NB 4
|
||||
|
@ -306,24 +308,42 @@ void AES::CTR::p_armCrypt(const uint8_t *in, uint8_t *out, unsigned int len) noe
|
|||
|
||||
void AES::p_init_armneon_crypto(const uint8_t* key) noexcept
|
||||
{
|
||||
static const uint8_t s_sbox[256] = {0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c,
|
||||
0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea,
|
||||
0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
|
||||
static const uint8_t s_sbox[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82,
|
||||
0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
||||
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96,
|
||||
0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb,
|
||||
0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
|
||||
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff,
|
||||
0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32,
|
||||
0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
|
||||
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
|
||||
0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e,
|
||||
0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
|
||||
0xb0, 0x54, 0xbb, 0x16
|
||||
};
|
||||
|
||||
uint64_t h[2];
|
||||
uint32_t* const w = reinterpret_cast<uint32_t*>(p_k.neon.ek);
|
||||
|
||||
for (unsigned int i = 0; i < ZT_INIT_ARMNEON_CRYPTO_NK; ++i) {
|
||||
const unsigned int j = i * 4;
|
||||
w[i] = ((uint32_t)key[j] << 24U) | ((uint32_t)key[j + 1] << 16U) | ((uint32_t)key[j + 2] << 8U) | (uint32_t)key[j + 3];
|
||||
w[i] = ((uint32_t)key[j] << 24U) | ((uint32_t)key[j + 1] << 16U) | ((uint32_t)key[j + 2] << 8U)
|
||||
| (uint32_t)key[j + 3];
|
||||
}
|
||||
|
||||
for (unsigned int i=ZT_INIT_ARMNEON_CRYPTO_NK;i<(ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));++i) {
|
||||
for (unsigned int i = ZT_INIT_ARMNEON_CRYPTO_NK; i < (ZT_INIT_ARMNEON_CRYPTO_NB * (ZT_INIT_ARMNEON_CRYPTO_NR + 1));
|
||||
++i) {
|
||||
uint32_t t = w[i - 1];
|
||||
const unsigned int imod = i & (ZT_INIT_ARMNEON_CRYPTO_NK - 1);
|
||||
if (imod == 0) {
|
||||
t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(ZT_INIT_ARMNEON_CRYPTO_ROTWORD(t)) ^ rcon[(i - 1) / ZT_INIT_ARMNEON_CRYPTO_NK];
|
||||
} else if (imod == 4) {
|
||||
t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(ZT_INIT_ARMNEON_CRYPTO_ROTWORD(t))
|
||||
^ rcon[(i - 1) / ZT_INIT_ARMNEON_CRYPTO_NK];
|
||||
}
|
||||
else if (imod == 4) {
|
||||
t = ZT_INIT_ARMNEON_CRYPTO_SUBWORD(t);
|
||||
}
|
||||
w[i] = w[i - ZT_INIT_ARMNEON_CRYPTO_NK] ^ t;
|
||||
|
|
114
core/Address.hpp
114
core/Address.hpp
|
@ -15,9 +15,9 @@
|
|||
#define ZT_ADDRESS_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_ADDRESS_STRING_SIZE_MAX (ZT_ADDRESS_LENGTH_HEX + 1)
|
||||
|
||||
|
@ -28,28 +28,37 @@ namespace ZeroTier {
|
|||
*
|
||||
* This is merely a 40-bit short address packed into a uint64_t and wrapped with methods.
|
||||
*/
|
||||
class Address : public TriviallyCopyable
|
||||
{
|
||||
class Address : public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE Address() noexcept : _a(0)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Address(const uint64_t a) noexcept : _a(a)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
explicit ZT_INLINE Address(const uint8_t b[5]) noexcept:
|
||||
_a(((uint64_t)b[0] << 32U) | ((uint64_t)b[1] << 24U) | ((uint64_t)b[2] << 16U) | ((uint64_t)b[3] << 8U) | (uint64_t)b[4])
|
||||
{}
|
||||
explicit ZT_INLINE Address(const uint8_t b[5]) noexcept
|
||||
: _a(((uint64_t)b[0] << 32U) | ((uint64_t)b[1] << 24U) | ((uint64_t)b[2] << 16U) | ((uint64_t)b[3] << 8U)
|
||||
| (uint64_t)b[4])
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Address& operator=(const uint64_t a) noexcept
|
||||
{ _a = a; return *this; }
|
||||
{
|
||||
_a = a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bits Raw address -- 5 bytes, big-endian byte order
|
||||
* @param len Length of array
|
||||
*/
|
||||
ZT_INLINE void setTo(const uint8_t b[5]) noexcept
|
||||
{ _a = ((uint64_t)b[0] << 32U) | ((uint64_t)b[1] << 24U) | ((uint64_t)b[2] << 16U) | ((uint64_t)b[3] << 8U) | (uint64_t)b[4]; }
|
||||
{
|
||||
_a = ((uint64_t)b[0] << 32U) | ((uint64_t)b[1] << 24U) | ((uint64_t)b[2] << 16U) | ((uint64_t)b[3] << 8U)
|
||||
| (uint64_t)b[4];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bits Buffer to hold 5-byte address in big-endian byte order
|
||||
|
@ -69,13 +78,17 @@ public:
|
|||
* @return Integer containing address (0 to 2^40)
|
||||
*/
|
||||
ZT_INLINE uint64_t toInt() const noexcept
|
||||
{ return _a; }
|
||||
{
|
||||
return _a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set address to zero/NIL
|
||||
*/
|
||||
ZT_INLINE void zero() noexcept
|
||||
{ _a = 0; }
|
||||
{
|
||||
_a = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s String with at least 11 characters of space available (10 + terminating NULL)
|
||||
|
@ -116,41 +129,84 @@ public:
|
|||
* @return True if address is reserved and may not be used
|
||||
*/
|
||||
ZT_INLINE bool isReserved() const noexcept
|
||||
{ return ((!_a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX)); }
|
||||
{
|
||||
return ((! _a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX));
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)_a; }
|
||||
{
|
||||
return (unsigned long)_a;
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (_a != 0); }
|
||||
{
|
||||
return (_a != 0);
|
||||
}
|
||||
|
||||
ZT_INLINE operator uint64_t() const noexcept
|
||||
{ return _a; }
|
||||
{
|
||||
return _a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Address& a) const noexcept
|
||||
{ return _a == a._a; }
|
||||
{
|
||||
return _a == a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Address& a) const noexcept
|
||||
{ return _a != a._a; }
|
||||
{
|
||||
return _a != a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const Address& a) const noexcept
|
||||
{ return _a > a._a; }
|
||||
{
|
||||
return _a > a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const Address& a) const noexcept
|
||||
{ return _a < a._a; }
|
||||
{
|
||||
return _a < a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Address& a) const noexcept
|
||||
{ return _a >= a._a; }
|
||||
{
|
||||
return _a >= a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Address& a) const noexcept
|
||||
{ return _a <= a._a; }
|
||||
{
|
||||
return _a <= a._a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const uint64_t a) const noexcept
|
||||
{ return _a == a; }
|
||||
{
|
||||
return _a == a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const uint64_t a) const noexcept
|
||||
{ return _a != a; }
|
||||
{
|
||||
return _a != a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const uint64_t a) const noexcept
|
||||
{ return _a > a; }
|
||||
{
|
||||
return _a > a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const uint64_t a) const noexcept
|
||||
{ return _a < a; }
|
||||
{
|
||||
return _a < a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const uint64_t a) const noexcept
|
||||
{ return _a >= a; }
|
||||
{
|
||||
return _a >= a;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const uint64_t a) const noexcept
|
||||
{ return _a <= a; }
|
||||
{
|
||||
return _a <= a;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t _a;
|
||||
|
|
11
core/Buf.cpp
11
core/Buf.cpp
|
@ -12,6 +12,7 @@
|
|||
/****/
|
||||
|
||||
#include "Buf.hpp"
|
||||
|
||||
#include "Spinlock.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -33,7 +34,8 @@ void *Buf::operator new(std::size_t sz)
|
|||
if (likely(bb != 0)) {
|
||||
b = reinterpret_cast<Buf*>(bb);
|
||||
s_pool.store(b->__nextInPool, std::memory_order_release);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
s_pool.store(0, std::memory_order_release);
|
||||
b = reinterpret_cast<Buf*>(malloc(sz));
|
||||
if (! b)
|
||||
|
@ -56,7 +58,8 @@ void Buf::operator delete(void *ptr)
|
|||
if (s_allocated.load(std::memory_order_relaxed) > ZT_BUF_MAX_POOL_SIZE) {
|
||||
s_allocated.fetch_sub(1, std::memory_order_relaxed);
|
||||
free(ptr);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uintptr_t bb;
|
||||
for (;;) {
|
||||
bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire);
|
||||
|
@ -95,6 +98,8 @@ void Buf::freePool() noexcept
|
|||
}
|
||||
|
||||
long Buf::poolAllocated() noexcept
|
||||
{ return s_allocated.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return s_allocated.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
170
core/Buf.hpp
170
core/Buf.hpp
|
@ -15,16 +15,16 @@
|
|||
#define ZT_BUF_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
// Buffers are 16384 bytes in size because this is the smallest size that can hold any packet
|
||||
// and is a power of two. It needs to be a power of two because masking is significantly faster
|
||||
|
@ -77,8 +77,7 @@ namespace ZeroTier {
|
|||
*
|
||||
* @tparam U Type to overlap with data bytes in data union (can't be larger than ZT_BUF_MEM_SIZE)
|
||||
*/
|
||||
class Buf
|
||||
{
|
||||
class Buf {
|
||||
friend class SharedPtr<Buf>;
|
||||
|
||||
public:
|
||||
|
@ -113,19 +112,30 @@ public:
|
|||
/**
|
||||
* Slice is almost exactly like the built-in slice data structure in Go
|
||||
*/
|
||||
struct Slice : TriviallyCopyable
|
||||
struct Slice : TriviallyCopyable {
|
||||
ZT_INLINE Slice(const SharedPtr<Buf>& b_, const unsigned int s_, const unsigned int e_) noexcept
|
||||
: b(b_)
|
||||
, s(s_)
|
||||
, e(e_)
|
||||
{
|
||||
ZT_INLINE Slice(const SharedPtr< Buf > &b_, const unsigned int s_, const unsigned int e_) noexcept: b(b_), s(s_), e(e_)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE Slice() noexcept: b(), s(0), e(0)
|
||||
{}
|
||||
ZT_INLINE Slice() noexcept
|
||||
: b()
|
||||
, s(0)
|
||||
, e(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (b); }
|
||||
{
|
||||
return (b);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int size() const noexcept
|
||||
{ return (e - s); }
|
||||
{
|
||||
return (e - s);
|
||||
}
|
||||
|
||||
ZT_INLINE void zero() noexcept
|
||||
{
|
||||
|
@ -153,11 +163,11 @@ public:
|
|||
/**
|
||||
* A vector of slices making up a packet that might span more than one buffer.
|
||||
*/
|
||||
class PacketVector : public ZeroTier::FCV< Slice, ZT_MAX_PACKET_FRAGMENTS >
|
||||
{
|
||||
class PacketVector : public ZeroTier::FCV<Slice, ZT_MAX_PACKET_FRAGMENTS> {
|
||||
public:
|
||||
ZT_INLINE PacketVector() : ZeroTier::FCV<Slice, ZT_MAX_PACKET_FRAGMENTS>()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int totalSize() const noexcept
|
||||
{
|
||||
|
@ -182,7 +192,8 @@ public:
|
|||
if (likely((size + rem) <= ZT_BUF_MEM_SIZE)) {
|
||||
Utils::copy(b.unsafeData + size, s->b->unsafeData + start, rem);
|
||||
size += rem;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +232,8 @@ public:
|
|||
copyFunction(b.unsafeData + size, s->b->unsafeData + start, rem);
|
||||
size += rem;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -232,21 +244,23 @@ public:
|
|||
/**
|
||||
* Create a new uninitialized buffer with undefined contents (use clear() to zero if needed)
|
||||
*/
|
||||
ZT_INLINE Buf() noexcept: __nextInPool(0), __refCount(0)
|
||||
{}
|
||||
ZT_INLINE Buf() noexcept
|
||||
: __nextInPool(0)
|
||||
, __refCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new buffer and copy data into it
|
||||
*/
|
||||
ZT_INLINE Buf(const void *const data, const unsigned int len) noexcept:
|
||||
__refCount(0)
|
||||
ZT_INLINE Buf(const void* const data, const unsigned int len) noexcept : __refCount(0)
|
||||
{
|
||||
Utils::copy(unsafeData, data, len);
|
||||
}
|
||||
|
||||
ZT_INLINE Buf(const Buf &b2) noexcept:
|
||||
__nextInPool(0),
|
||||
__refCount(0)
|
||||
ZT_INLINE Buf(const Buf& b2) noexcept
|
||||
: __nextInPool(0)
|
||||
, __refCount(0)
|
||||
{
|
||||
Utils::copy<ZT_BUF_MEM_SIZE>(unsafeData, b2.unsafeData);
|
||||
}
|
||||
|
@ -268,7 +282,9 @@ public:
|
|||
* @return True if iterator has read past the size of the buffer
|
||||
*/
|
||||
static ZT_INLINE bool writeOverflow(const int& ii) noexcept
|
||||
{ return ((ii - ZT_BUF_MEM_SIZE) > 0); }
|
||||
{
|
||||
return ((ii - ZT_BUF_MEM_SIZE) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for overflow beyond the size of the data that should be in the buffer
|
||||
|
@ -281,7 +297,9 @@ public:
|
|||
* @return True if iterator has read past the size of the data
|
||||
*/
|
||||
static ZT_INLINE bool readOverflow(const int& ii, const unsigned int size) noexcept
|
||||
{ return ((ii - (int)size) > 0); }
|
||||
{
|
||||
return ((ii - (int)size) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all memory to zero
|
||||
|
@ -314,9 +332,7 @@ public:
|
|||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
ii += 2;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint16_t)unsafeData[s] << 8U) |
|
||||
(uint16_t)unsafeData[s + 1]);
|
||||
return (((uint16_t)unsafeData[s] << 8U) | (uint16_t)unsafeData[s + 1]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t*>(unsafeData + s));
|
||||
#endif
|
||||
|
@ -334,10 +350,8 @@ public:
|
|||
ii += 4;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint32_t)unsafeData[s] << 24U) |
|
||||
((uint32_t)unsafeData[s + 1] << 16U) |
|
||||
((uint32_t)unsafeData[s + 2] << 8U) |
|
||||
(uint32_t)unsafeData[s + 3]);
|
||||
((uint32_t)unsafeData[s] << 24U) | ((uint32_t)unsafeData[s + 1] << 16U)
|
||||
| ((uint32_t)unsafeData[s + 2] << 8U) | (uint32_t)unsafeData[s + 3]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t*>(unsafeData + s));
|
||||
#endif
|
||||
|
@ -355,14 +369,10 @@ public:
|
|||
ii += 8;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint64_t)unsafeData[s] << 56U) |
|
||||
((uint64_t)unsafeData[s + 1] << 48U) |
|
||||
((uint64_t)unsafeData[s + 2] << 40U) |
|
||||
((uint64_t)unsafeData[s + 3] << 32U) |
|
||||
((uint64_t)unsafeData[s + 4] << 24U) |
|
||||
((uint64_t)unsafeData[s + 5] << 16U) |
|
||||
((uint64_t)unsafeData[s + 6] << 8U) |
|
||||
(uint64_t)unsafeData[s + 7]);
|
||||
((uint64_t)unsafeData[s] << 56U) | ((uint64_t)unsafeData[s + 1] << 48U)
|
||||
| ((uint64_t)unsafeData[s + 2] << 40U) | ((uint64_t)unsafeData[s + 3] << 32U)
|
||||
| ((uint64_t)unsafeData[s + 4] << 24U) | ((uint64_t)unsafeData[s + 5] << 16U)
|
||||
| ((uint64_t)unsafeData[s + 6] << 8U) | (uint64_t)unsafeData[s + 7]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t*>(unsafeData + s));
|
||||
#endif
|
||||
|
@ -383,8 +393,7 @@ public:
|
|||
* @param obj Object to read
|
||||
* @return Bytes read or a negative value on unmarshal error (passed from object) or overflow
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE int rO(int &ii, T &obj) const noexcept
|
||||
template <typename T> ZT_INLINE int rO(int& ii, T& obj) const noexcept
|
||||
{
|
||||
if (likely(ii < ZT_BUF_MEM_SIZE)) {
|
||||
int ms = obj.unmarshal(unsafeData + ii, ZT_BUF_MEM_SIZE - ii);
|
||||
|
@ -490,8 +499,7 @@ public:
|
|||
* @tparam I Static index
|
||||
* @return Value
|
||||
*/
|
||||
template< unsigned int I >
|
||||
ZT_INLINE uint8_t lI8() const noexcept
|
||||
template <unsigned int I> ZT_INLINE uint8_t lI8() const noexcept
|
||||
{
|
||||
static_assert(I < ZT_BUF_MEM_SIZE, "overflow");
|
||||
return unsafeData[I];
|
||||
|
@ -503,14 +511,11 @@ public:
|
|||
* @tparam I Static index
|
||||
* @return Value
|
||||
*/
|
||||
template< unsigned int I >
|
||||
ZT_INLINE uint8_t lI16() const noexcept
|
||||
template <unsigned int I> ZT_INLINE uint8_t lI16() const noexcept
|
||||
{
|
||||
static_assert((I + 1) < ZT_BUF_MEM_SIZE, "overflow");
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint16_t)unsafeData[I] << 8U) |
|
||||
(uint16_t)unsafeData[I + 1]);
|
||||
return (((uint16_t)unsafeData[I] << 8U) | (uint16_t)unsafeData[I + 1]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t*>(unsafeData + I));
|
||||
#endif
|
||||
|
@ -522,16 +527,13 @@ public:
|
|||
* @tparam I Static index
|
||||
* @return Value
|
||||
*/
|
||||
template< unsigned int I >
|
||||
ZT_INLINE uint8_t lI32() const noexcept
|
||||
template <unsigned int I> ZT_INLINE uint8_t lI32() const noexcept
|
||||
{
|
||||
static_assert((I + 3) < ZT_BUF_MEM_SIZE, "overflow");
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint32_t)unsafeData[I] << 24U) |
|
||||
((uint32_t)unsafeData[I + 1] << 16U) |
|
||||
((uint32_t)unsafeData[I + 2] << 8U) |
|
||||
(uint32_t)unsafeData[I + 3]);
|
||||
((uint32_t)unsafeData[I] << 24U) | ((uint32_t)unsafeData[I + 1] << 16U)
|
||||
| ((uint32_t)unsafeData[I + 2] << 8U) | (uint32_t)unsafeData[I + 3]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t*>(unsafeData + I));
|
||||
#endif
|
||||
|
@ -543,20 +545,15 @@ public:
|
|||
* @tparam I Static index
|
||||
* @return Value
|
||||
*/
|
||||
template< unsigned int I >
|
||||
ZT_INLINE uint8_t lI64() const noexcept
|
||||
template <unsigned int I> ZT_INLINE uint8_t lI64() const noexcept
|
||||
{
|
||||
static_assert((I + 7) < ZT_BUF_MEM_SIZE, "overflow");
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint64_t)unsafeData[I] << 56U) |
|
||||
((uint64_t)unsafeData[I + 1] << 48U) |
|
||||
((uint64_t)unsafeData[I + 2] << 40U) |
|
||||
((uint64_t)unsafeData[I + 3] << 32U) |
|
||||
((uint64_t)unsafeData[I + 4] << 24U) |
|
||||
((uint64_t)unsafeData[I + 5] << 16U) |
|
||||
((uint64_t)unsafeData[I + 6] << 8U) |
|
||||
(uint64_t)unsafeData[I + 7]);
|
||||
((uint64_t)unsafeData[I] << 56U) | ((uint64_t)unsafeData[I + 1] << 48U)
|
||||
| ((uint64_t)unsafeData[I + 2] << 40U) | ((uint64_t)unsafeData[I + 3] << 32U)
|
||||
| ((uint64_t)unsafeData[I + 4] << 24U) | ((uint64_t)unsafeData[I + 5] << 16U)
|
||||
| ((uint64_t)unsafeData[I + 6] << 8U) | (uint64_t)unsafeData[I + 7]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t*>(unsafeData + I));
|
||||
#endif
|
||||
|
@ -585,9 +582,7 @@ public:
|
|||
{
|
||||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint16_t)unsafeData[s] << 8U) |
|
||||
(uint16_t)unsafeData[s + 1]);
|
||||
return (((uint16_t)unsafeData[s] << 8U) | (uint16_t)unsafeData[s + 1]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint16_t*>(unsafeData + s));
|
||||
#endif
|
||||
|
@ -605,10 +600,8 @@ public:
|
|||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint32_t)unsafeData[s] << 24U) |
|
||||
((uint32_t)unsafeData[s + 1] << 16U) |
|
||||
((uint32_t)unsafeData[s + 2] << 8U) |
|
||||
(uint32_t)unsafeData[s + 3]);
|
||||
((uint32_t)unsafeData[s] << 24U) | ((uint32_t)unsafeData[s + 1] << 16U)
|
||||
| ((uint32_t)unsafeData[s + 2] << 8U) | (uint32_t)unsafeData[s + 3]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint32_t*>(unsafeData + s));
|
||||
#endif
|
||||
|
@ -626,14 +619,10 @@ public:
|
|||
const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return (
|
||||
((uint64_t)unsafeData[s] << 56U) |
|
||||
((uint64_t)unsafeData[s + 1] << 48U) |
|
||||
((uint64_t)unsafeData[s + 2] << 40U) |
|
||||
((uint64_t)unsafeData[s + 3] << 32U) |
|
||||
((uint64_t)unsafeData[s + 4] << 24U) |
|
||||
((uint64_t)unsafeData[s + 5] << 16U) |
|
||||
((uint64_t)unsafeData[s + 6] << 8U) |
|
||||
(uint64_t)unsafeData[s + 7]);
|
||||
((uint64_t)unsafeData[s] << 56U) | ((uint64_t)unsafeData[s + 1] << 48U)
|
||||
| ((uint64_t)unsafeData[s + 2] << 40U) | ((uint64_t)unsafeData[s + 3] << 32U)
|
||||
| ((uint64_t)unsafeData[s + 4] << 24U) | ((uint64_t)unsafeData[s + 5] << 16U)
|
||||
| ((uint64_t)unsafeData[s + 6] << 8U) | (uint64_t)unsafeData[s + 7]);
|
||||
#else
|
||||
return Utils::ntoh(*reinterpret_cast<const uint64_t*>(unsafeData + s));
|
||||
#endif
|
||||
|
@ -720,15 +709,15 @@ public:
|
|||
* @param ii Index value-result parameter (incremented by size of object)
|
||||
* @param t Object to write
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE void wO(int &ii, T &t) noexcept
|
||||
template <typename T> ZT_INLINE void wO(int& ii, T& t) noexcept
|
||||
{
|
||||
const int s = ii;
|
||||
if (likely((s + T::marshalSizeMax()) <= ZT_BUF_MEM_SIZE)) {
|
||||
int ms = t.marshal(unsafeData + s);
|
||||
if (ms > 0)
|
||||
ii += ms;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ii += T::marshalSizeMax(); // mark as overflowed even if we didn't do anything
|
||||
}
|
||||
}
|
||||
|
@ -747,7 +736,8 @@ public:
|
|||
c = *(s++);
|
||||
wI8(ii, (uint8_t)c);
|
||||
} while (c);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
wI8(ii, 0);
|
||||
}
|
||||
}
|
||||
|
@ -854,7 +844,9 @@ public:
|
|||
* @return Capacity of this buffer (usable size of data.bytes)
|
||||
*/
|
||||
static constexpr unsigned int capacity() noexcept
|
||||
{ return ZT_BUF_MEM_SIZE; }
|
||||
{
|
||||
return ZT_BUF_MEM_SIZE;
|
||||
}
|
||||
|
||||
private:
|
||||
volatile uintptr_t __nextInPool;
|
||||
|
|
3256
core/C25519.cpp
3256
core/C25519.cpp
File diff suppressed because it is too large
Load diff
|
@ -35,18 +35,20 @@ namespace ZeroTier {
|
|||
/**
|
||||
* A combined Curve25519 ECDH and Ed25519 signature engine
|
||||
*/
|
||||
class C25519
|
||||
{
|
||||
class C25519 {
|
||||
public:
|
||||
/**
|
||||
* Generate a set of two 25519 keys: a C25519 ECDH key pair and an Ed25519 EDDSA key pair.
|
||||
*/
|
||||
static void generateCombined(uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE]);
|
||||
static void generateCombined(
|
||||
uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],
|
||||
uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE]);
|
||||
|
||||
/**
|
||||
* Generate a C25519 ECDH key pair only.
|
||||
*/
|
||||
static void generateC25519(uint8_t pub[ZT_C25519_ECDH_PUBLIC_KEY_SIZE],uint8_t priv[ZT_C25519_ECDH_PRIVATE_KEY_SIZE]);
|
||||
static void
|
||||
generateC25519(uint8_t pub[ZT_C25519_ECDH_PUBLIC_KEY_SIZE], uint8_t priv[ZT_C25519_ECDH_PRIVATE_KEY_SIZE]);
|
||||
|
||||
/**
|
||||
* Generate a key pair satisfying a condition
|
||||
|
@ -62,7 +64,10 @@ public:
|
|||
* @tparam F Type of 'cond'
|
||||
*/
|
||||
template <typename F>
|
||||
static ZT_INLINE void generateSatisfying(F cond,uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE])
|
||||
static ZT_INLINE void generateSatisfying(
|
||||
F cond,
|
||||
uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],
|
||||
uint8_t priv[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE])
|
||||
{
|
||||
Utils::getSecureRandom(priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
s_calcPubED(pub, priv); // do Ed25519 key -- bytes 32-63 of pub and priv
|
||||
|
@ -83,7 +88,10 @@ public:
|
|||
* @param their Their public key
|
||||
* @param rawkey Buffer to receive raw (not hashed) agreed upon key
|
||||
*/
|
||||
static void agree(const uint8_t mine[ZT_C25519_ECDH_PRIVATE_KEY_SIZE],const uint8_t their[ZT_C25519_ECDH_PUBLIC_KEY_SIZE],uint8_t rawkey[ZT_C25519_ECDH_SHARED_SECRET_SIZE]);
|
||||
static void agree(
|
||||
const uint8_t mine[ZT_C25519_ECDH_PRIVATE_KEY_SIZE],
|
||||
const uint8_t their[ZT_C25519_ECDH_PUBLIC_KEY_SIZE],
|
||||
uint8_t rawkey[ZT_C25519_ECDH_SHARED_SECRET_SIZE]);
|
||||
|
||||
/**
|
||||
* Sign a message with a sender's key pair
|
||||
|
@ -102,7 +110,12 @@ public:
|
|||
* @param len Length of message in bytes
|
||||
* @param signature Buffer to fill with signature -- MUST be 96 bytes in length
|
||||
*/
|
||||
static void sign(const uint8_t myPrivate[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE],const uint8_t myPublic[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],const void *msg,unsigned int len,void *signature);
|
||||
static void sign(
|
||||
const uint8_t myPrivate[ZT_C25519_COMBINED_PRIVATE_KEY_SIZE],
|
||||
const uint8_t myPublic[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],
|
||||
const void* msg,
|
||||
unsigned int len,
|
||||
void* signature);
|
||||
|
||||
/**
|
||||
* Verify a message's signature
|
||||
|
@ -114,7 +127,12 @@ public:
|
|||
* @param siglen Length of signature in bytes
|
||||
* @return True if signature is valid and the message is authentic and unmodified
|
||||
*/
|
||||
static bool verify(const uint8_t their[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],const void *msg,unsigned int len,const void *signature,unsigned int siglen);
|
||||
static bool verify(
|
||||
const uint8_t their[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE],
|
||||
const void* msg,
|
||||
unsigned int len,
|
||||
const void* signature,
|
||||
unsigned int siglen);
|
||||
|
||||
private:
|
||||
// derive first 32 bytes of kp.pub from first 32 bytes of kp.priv
|
||||
|
|
395
core/CAPI.cpp
395
core/CAPI.cpp
|
@ -11,16 +11,16 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Certificate.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "VL1.hpp"
|
||||
#include "VL2.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "ECC384.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
@ -41,7 +41,8 @@ ZT_MAYBE_UNUSED void *ZT_getBuffer()
|
|||
// wrapped in a SharedPtr<> to be passed into the core.
|
||||
try {
|
||||
return ZT_BUFTOPTR(new ZeroTier::Buf());
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr; // can only happen on out of memory condition
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +53,7 @@ ZT_MAYBE_UNUSED void ZT_freeBuffer(void *b)
|
|||
delete ZT_PTRTOBUF(b);
|
||||
}
|
||||
|
||||
struct p_queryResultBase
|
||||
{
|
||||
struct p_queryResultBase {
|
||||
void (*freeFunction)(const void*);
|
||||
};
|
||||
|
||||
|
@ -90,26 +90,27 @@ ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_new(
|
|||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
*node = reinterpret_cast<ZT_Node*>(new ZeroTier::Node(uptr, callbacks, cc));
|
||||
return ZT_RESULT_OK;
|
||||
} catch (std::bad_alloc &exc) {
|
||||
}
|
||||
catch (std::bad_alloc& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch (std::runtime_error &exc) {
|
||||
}
|
||||
catch (std::runtime_error& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_DATA_STORE_FAILED;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED void ZT_Node_delete(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr)
|
||||
ZT_MAYBE_UNUSED void ZT_Node_delete(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr)
|
||||
{
|
||||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
reinterpret_cast<ZeroTier::Node*>(node)->shutdown(cc);
|
||||
delete (reinterpret_cast<ZeroTier::Node*>(node));
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processWirePacket(
|
||||
|
@ -126,11 +127,16 @@ ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processWirePacket(
|
|||
{
|
||||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK));
|
||||
reinterpret_cast<ZeroTier::Node *>(node)->context().vl1->onRemotePacket(cc, localSocket, *ZeroTier::asInetAddress(remoteAddress), buf, packetLength);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
ZeroTier::SharedPtr<ZeroTier::Buf> buf(
|
||||
(isZtBuffer) ? ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK));
|
||||
reinterpret_cast<ZeroTier::Node*>(node)
|
||||
->context()
|
||||
.vl1->onRemotePacket(cc, localSocket, *ZeroTier::asInetAddress(remoteAddress), buf, packetLength);
|
||||
}
|
||||
catch (std::bad_alloc& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
// "OK" since invalid packets are simply dropped, but the system is still up.
|
||||
// We should never make it here, but if we did that would be the interpretation.
|
||||
}
|
||||
|
@ -157,15 +163,27 @@ ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
|||
const ZeroTier::Context& ctx = reinterpret_cast<ZeroTier::Node*>(node)->context();
|
||||
ZeroTier::SharedPtr<ZeroTier::Network> network(ctx.networks->get(nwid));
|
||||
if (likely(network)) {
|
||||
ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(frameData) : new ZeroTier::Buf(frameData, frameLength & ZT_BUF_MEM_MASK));
|
||||
ctx.vl2->onLocalEthernet(cc, network, ZeroTier::MAC(sourceMac), ZeroTier::MAC(destMac), etherType, vlanId, buf, frameLength);
|
||||
ZeroTier::SharedPtr<ZeroTier::Buf> buf(
|
||||
(isZtBuffer) ? ZT_PTRTOBUF(frameData) : new ZeroTier::Buf(frameData, frameLength & ZT_BUF_MEM_MASK));
|
||||
ctx.vl2->onLocalEthernet(
|
||||
cc,
|
||||
network,
|
||||
ZeroTier::MAC(sourceMac),
|
||||
ZeroTier::MAC(destMac),
|
||||
etherType,
|
||||
vlanId,
|
||||
buf,
|
||||
frameLength);
|
||||
return ZT_RESULT_OK;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
} catch (std::bad_alloc &exc) {
|
||||
}
|
||||
catch (std::bad_alloc& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
@ -180,9 +198,11 @@ ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processBackgroundTasks(
|
|||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->processBackgroundTasks(cc, nextBackgroundTaskDeadline);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
}
|
||||
catch (std::bad_alloc& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
@ -199,27 +219,26 @@ ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_join(
|
|||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->join(nwid, controllerFingerprint, uptr, cc);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
}
|
||||
catch (std::bad_alloc& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_leave(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr,
|
||||
void **uptr,
|
||||
uint64_t nwid)
|
||||
ZT_MAYBE_UNUSED enum ZT_ResultCode
|
||||
ZT_Node_leave(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr, void** uptr, uint64_t nwid)
|
||||
{
|
||||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->leave(nwid, uptr, cc);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
}
|
||||
catch (std::bad_alloc& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
@ -236,9 +255,11 @@ ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_multicastSubscribe(
|
|||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->multicastSubscribe(cc, nwid, multicastGroup, multicastAdi);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
}
|
||||
catch (std::bad_alloc& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
@ -255,55 +276,51 @@ ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_multicastUnsubscribe(
|
|||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->multicastUnsubscribe(cc, nwid, multicastGroup, multicastAdi);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
}
|
||||
catch (std::bad_alloc& exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED uint64_t ZT_Node_address(ZT_Node* node)
|
||||
{ return reinterpret_cast<ZeroTier::Node *>(node)->context().identity.address().toInt(); }
|
||||
{
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->context().identity.address().toInt();
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED const ZT_Identity* ZT_Node_identity(ZT_Node* node)
|
||||
{ return (const ZT_Identity *)(&(reinterpret_cast<ZeroTier::Node *>(node)->identity())); }
|
||||
{
|
||||
return (const ZT_Identity*)(&(reinterpret_cast<ZeroTier::Node*>(node)->identity()));
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED void ZT_Node_status(
|
||||
ZT_Node *node,
|
||||
int64_t,
|
||||
int64_t,
|
||||
void *,
|
||||
ZT_NodeStatus *status)
|
||||
ZT_MAYBE_UNUSED void ZT_Node_status(ZT_Node* node, int64_t, int64_t, void*, ZT_NodeStatus* status)
|
||||
{
|
||||
try {
|
||||
reinterpret_cast<ZeroTier::Node*>(node)->status(status);
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED ZT_PeerList *ZT_Node_peers(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr)
|
||||
ZT_MAYBE_UNUSED ZT_PeerList* ZT_Node_peers(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr)
|
||||
{
|
||||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->peers(cc);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return (ZT_PeerList*)0;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED ZT_VirtualNetworkConfig *ZT_Node_networkConfig(
|
||||
ZT_Node *node,
|
||||
int64_t,
|
||||
int64_t,
|
||||
void *,
|
||||
uint64_t nwid)
|
||||
ZT_MAYBE_UNUSED ZT_VirtualNetworkConfig* ZT_Node_networkConfig(ZT_Node* node, int64_t, int64_t, void*, uint64_t nwid)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->networkConfig(nwid);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return (ZT_VirtualNetworkConfig*)0;
|
||||
}
|
||||
}
|
||||
|
@ -312,19 +329,19 @@ ZT_MAYBE_UNUSED ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node)
|
|||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->networks();
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return (ZT_VirtualNetworkList*)0;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED void ZT_Node_setNetworkUserPtr(
|
||||
ZT_Node *node,
|
||||
uint64_t nwid,
|
||||
void *ptr)
|
||||
ZT_MAYBE_UNUSED void ZT_Node_setNetworkUserPtr(ZT_Node* node, uint64_t nwid, void* ptr)
|
||||
{
|
||||
try {
|
||||
reinterpret_cast<ZeroTier::Node*>(node)->setNetworkUserPtr(nwid, ptr);
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED void ZT_Node_setInterfaceAddresses(
|
||||
|
@ -337,7 +354,9 @@ ZT_MAYBE_UNUSED void ZT_Node_setInterfaceAddresses(
|
|||
{
|
||||
try {
|
||||
reinterpret_cast<ZeroTier::Node*>(node)->setInterfaceAddresses(addrs, addrCount);
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Node_addCertificate(
|
||||
|
@ -353,35 +372,30 @@ ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Node_addCertificate(
|
|||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->addCertificate(cc, localTrust, cert, certData, certSize);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_deleteCertificate(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr,
|
||||
const void *serialNo)
|
||||
ZT_MAYBE_UNUSED enum ZT_ResultCode
|
||||
ZT_Node_deleteCertificate(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr, const void* serialNo)
|
||||
{
|
||||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->deleteCertificate(cc, serialNo);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED ZT_CertificateList *ZT_Node_listCertificates(
|
||||
ZT_Node *node,
|
||||
int64_t,
|
||||
int64_t,
|
||||
void *)
|
||||
ZT_MAYBE_UNUSED ZT_CertificateList* ZT_Node_listCertificates(ZT_Node* node, int64_t, int64_t, void*)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->listCertificates();
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -399,18 +413,19 @@ ZT_MAYBE_UNUSED int ZT_Node_sendUserMessage(
|
|||
try {
|
||||
ZeroTier::CallContext cc(clock, ticks, tptr);
|
||||
return reinterpret_cast<ZeroTier::Node*>(node)->sendUserMessage(cc, dest, typeId, data, len);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED void ZT_Node_setController(
|
||||
ZT_Node *node,
|
||||
void *networkControllerInstance)
|
||||
ZT_MAYBE_UNUSED void ZT_Node_setController(ZT_Node* node, void* networkControllerInstance)
|
||||
{
|
||||
try {
|
||||
reinterpret_cast<ZeroTier::Node*>(node)->setController(networkControllerInstance);
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************************************/
|
||||
|
@ -427,13 +442,16 @@ ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_create(
|
|||
return nullptr;
|
||||
ZeroTier::Locator* loc = new ZeroTier::Locator();
|
||||
for (unsigned int i = 0; i < endpointCount; ++i)
|
||||
loc->add(reinterpret_cast< const ZeroTier::Endpoint * >(endpoints)[i], ZeroTier::Locator::EndpointAttributes::DEFAULT);
|
||||
loc->add(
|
||||
reinterpret_cast<const ZeroTier::Endpoint*>(endpoints)[i],
|
||||
ZeroTier::Locator::EndpointAttributes::DEFAULT);
|
||||
if (! loc->sign(rev, *reinterpret_cast<const ZeroTier::Identity*>(signer))) {
|
||||
delete loc;
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<ZT_Locator*>(loc);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -449,14 +467,13 @@ ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_fromString(const char *str)
|
|||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<ZT_Locator*>(loc);
|
||||
} catch ( ... ) {
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_unmarshal(
|
||||
const void *data,
|
||||
unsigned int len)
|
||||
ZT_MAYBE_UNUSED ZT_Locator* ZT_Locator_unmarshal(const void* data, unsigned int len)
|
||||
{
|
||||
try {
|
||||
if ((! data) || (len == 0))
|
||||
|
@ -467,7 +484,8 @@ ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_unmarshal(
|
|||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<ZT_Locator*>(loc);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -479,10 +497,7 @@ ZT_MAYBE_UNUSED int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigne
|
|||
return reinterpret_cast<const ZeroTier::Locator*>(loc)->marshal(reinterpret_cast<uint8_t*>(buf), false);
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED char *ZT_Locator_toString(
|
||||
const ZT_Locator *loc,
|
||||
char *buf,
|
||||
int capacity)
|
||||
ZT_MAYBE_UNUSED char* ZT_Locator_toString(const ZT_Locator* loc, char* buf, int capacity)
|
||||
{
|
||||
if ((! loc) || (capacity < ZT_LOCATOR_STRING_SIZE_MAX))
|
||||
return nullptr;
|
||||
|
@ -510,14 +525,17 @@ ZT_MAYBE_UNUSED int ZT_Locator_equals(const ZT_Locator *a, const ZT_Locator *b)
|
|||
if (*reinterpret_cast<const ZeroTier::Locator*>(a) == *reinterpret_cast<const ZeroTier::Locator*>(b))
|
||||
return 1;
|
||||
}
|
||||
} else if (!b) {
|
||||
}
|
||||
else if (! b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED unsigned int ZT_Locator_endpointCount(const ZT_Locator* loc)
|
||||
{ return (loc) ? (unsigned int) (reinterpret_cast<const ZeroTier::Locator *>(loc)->endpoints().size()) : 0; }
|
||||
{
|
||||
return (loc) ? (unsigned int)(reinterpret_cast<const ZeroTier::Locator*>(loc)->endpoints().size()) : 0;
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED const ZT_Endpoint* ZT_Locator_endpoint(const ZT_Locator* loc, const unsigned int ep)
|
||||
{
|
||||
|
@ -532,7 +550,9 @@ ZT_MAYBE_UNUSED int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *
|
|||
{
|
||||
if ((! loc) || (! signer))
|
||||
return 0;
|
||||
return reinterpret_cast<const ZeroTier::Locator *>(loc)->verify(*reinterpret_cast<const ZeroTier::Identity *>(signer)) ? 1 : 0;
|
||||
return reinterpret_cast<const ZeroTier::Locator*>(loc)->verify(*reinterpret_cast<const ZeroTier::Identity*>(signer))
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED void ZT_Locator_delete(const ZT_Locator* loc)
|
||||
|
@ -551,7 +571,8 @@ ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type)
|
|||
ZeroTier::Identity* const id = new ZeroTier::Identity();
|
||||
id->generate((ZeroTier::Identity::Type)type);
|
||||
return reinterpret_cast<ZT_Identity*>(id);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -560,8 +581,10 @@ ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_clone(const ZT_Identity *id)
|
|||
{
|
||||
if (id) {
|
||||
try {
|
||||
return reinterpret_cast<ZT_Identity *>(new ZeroTier::Identity(*reinterpret_cast<const ZeroTier::Identity *>(id)));
|
||||
} catch ( ... ) {
|
||||
return reinterpret_cast<ZT_Identity*>(
|
||||
new ZeroTier::Identity(*reinterpret_cast<const ZeroTier::Identity*>(id)));
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +602,8 @@ ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_fromString(const char *idStr)
|
|||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<ZT_Identity*>(id);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -591,7 +615,12 @@ ZT_MAYBE_UNUSED int ZT_Identity_validate(const ZT_Identity *id)
|
|||
return reinterpret_cast<const ZeroTier::Identity*>(id)->locallyValidate() ? 1 : 0;
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned int len, void *signature, unsigned int signatureBufferLength)
|
||||
ZT_MAYBE_UNUSED unsigned int ZT_Identity_sign(
|
||||
const ZT_Identity* id,
|
||||
const void* data,
|
||||
unsigned int len,
|
||||
void* signature,
|
||||
unsigned int signatureBufferLength)
|
||||
{
|
||||
if (! id)
|
||||
return 0;
|
||||
|
@ -600,7 +629,12 @@ ZT_MAYBE_UNUSED unsigned int ZT_Identity_sign(const ZT_Identity *id, const void
|
|||
return reinterpret_cast<const ZeroTier::Identity*>(id)->sign(data, len, signature, signatureBufferLength);
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED int ZT_Identity_verify(const ZT_Identity *id, const void *data, unsigned int len, const void *signature, unsigned int sigLen)
|
||||
ZT_MAYBE_UNUSED int ZT_Identity_verify(
|
||||
const ZT_Identity* id,
|
||||
const void* data,
|
||||
unsigned int len,
|
||||
const void* signature,
|
||||
unsigned int sigLen)
|
||||
{
|
||||
if ((! id) || (! signature) || (! sigLen))
|
||||
return 0;
|
||||
|
@ -649,17 +683,23 @@ ZT_MAYBE_UNUSED int ZT_Identity_compare(const ZT_Identity *a, const ZT_Identity
|
|||
if (b) {
|
||||
if (*reinterpret_cast<const ZeroTier::Identity*>(a) < *reinterpret_cast<const ZeroTier::Identity*>(b)) {
|
||||
return -1;
|
||||
} else if (*reinterpret_cast<const ZeroTier::Identity *>(b) < *reinterpret_cast<const ZeroTier::Identity *>(a)) {
|
||||
}
|
||||
else if (
|
||||
*reinterpret_cast<const ZeroTier::Identity*>(b) < *reinterpret_cast<const ZeroTier::Identity*>(a)) {
|
||||
return 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
} else if (b) {
|
||||
}
|
||||
else if (b) {
|
||||
return -1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -680,8 +720,11 @@ ZT_MAYBE_UNUSED int ZT_Certificate_newKeyPair(
|
|||
int* const privateKeySize)
|
||||
{
|
||||
try {
|
||||
return ZeroTier::Certificate::newKeyPair(type, publicKey, publicKeySize, privateKey, privateKeySize) ? ZT_RESULT_OK : ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
} catch ( ... ) {
|
||||
return ZeroTier::Certificate::newKeyPair(type, publicKey, publicKeySize, privateKey, privateKeySize)
|
||||
? ZT_RESULT_OK
|
||||
: ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
@ -696,15 +739,22 @@ ZT_MAYBE_UNUSED int ZT_Certificate_newCSR(
|
|||
int* const csrSize)
|
||||
{
|
||||
try {
|
||||
if ((!subject) || (!certificatePublicKey) || (certificatePublicKeySize <= 0) || (certificatePublicKeySize > ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE))
|
||||
if ((! subject) || (! certificatePublicKey) || (certificatePublicKeySize <= 0)
|
||||
|| (certificatePublicKeySize > ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE))
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
const ZeroTier::Vector< uint8_t > csrV(ZeroTier::Certificate::createCSR(*subject, certificatePublicKey, (unsigned int)certificatePublicKeySize, uniqueIdPrivateKey, (unsigned int)uniqueIdPrivateKeySize));
|
||||
const ZeroTier::Vector<uint8_t> csrV(ZeroTier::Certificate::createCSR(
|
||||
*subject,
|
||||
certificatePublicKey,
|
||||
(unsigned int)certificatePublicKeySize,
|
||||
uniqueIdPrivateKey,
|
||||
(unsigned int)uniqueIdPrivateKeySize));
|
||||
if (csrV.empty() || ((int)csrV.size() > *csrSize))
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
ZeroTier::Utils::copy(csr, csrV.data(), (unsigned int)csrV.size());
|
||||
*csrSize = (int)csrV.size();
|
||||
return ZT_RESULT_OK;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
@ -719,18 +769,18 @@ ZT_MAYBE_UNUSED ZT_Certificate *ZT_Certificate_sign(
|
|||
ZeroTier::Certificate* const c = new ZeroTier::Certificate(*cert);
|
||||
if (c->sign(issuer, issuerPrivateKey, issuerPrivateKeySize)) {
|
||||
return c;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
delete c;
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Certificate_decode(
|
||||
const ZT_Certificate **decodedCert,
|
||||
const void *cert,
|
||||
int certSize,
|
||||
int verify)
|
||||
ZT_MAYBE_UNUSED enum ZT_CertificateError
|
||||
ZT_Certificate_decode(const ZT_Certificate** decodedCert, const void* cert, int certSize, int verify)
|
||||
{
|
||||
try {
|
||||
if ((! decodedCert) || (! cert) || (certSize <= 0))
|
||||
|
@ -750,15 +800,13 @@ ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Certificate_decode(
|
|||
}
|
||||
*decodedCert = c;
|
||||
return ZT_CERTIFICATE_ERROR_NONE;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED int ZT_Certificate_encode(
|
||||
const ZT_Certificate *cert,
|
||||
void *encoded,
|
||||
int *encodedSize)
|
||||
ZT_MAYBE_UNUSED int ZT_Certificate_encode(const ZT_Certificate* cert, void* encoded, int* encodedSize)
|
||||
{
|
||||
try {
|
||||
if ((! cert) || (! encoded) || (! encodedSize))
|
||||
|
@ -770,20 +818,20 @@ ZT_MAYBE_UNUSED int ZT_Certificate_encode(
|
|||
ZeroTier::Utils::copy(encoded, enc.data(), (unsigned int)enc.size());
|
||||
*encodedSize = (int)enc.size();
|
||||
return ZT_RESULT_OK;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Certificate_verify(
|
||||
const ZT_Certificate *cert,
|
||||
int64_t clock)
|
||||
ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Certificate_verify(const ZT_Certificate* cert, int64_t clock)
|
||||
{
|
||||
try {
|
||||
if (! cert)
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
return ZeroTier::Certificate(*cert).verify(clock, true);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
@ -794,7 +842,8 @@ ZT_MAYBE_UNUSED const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate
|
|||
if (! cert)
|
||||
return nullptr;
|
||||
return (const ZT_Certificate*)(new ZeroTier::Certificate(*cert));
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -804,38 +853,34 @@ ZT_MAYBE_UNUSED void ZT_Certificate_delete(const ZT_Certificate *cert)
|
|||
try {
|
||||
if (cert)
|
||||
delete (const ZeroTier::Certificate*)(cert);
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************************************/
|
||||
|
||||
ZT_MAYBE_UNUSED char *ZT_Endpoint_toString(
|
||||
const ZT_Endpoint *ep,
|
||||
char *buf,
|
||||
int capacity)
|
||||
ZT_MAYBE_UNUSED char* ZT_Endpoint_toString(const ZT_Endpoint* ep, char* buf, int capacity)
|
||||
{
|
||||
if ((! ep) || (! buf) || (capacity < ZT_ENDPOINT_STRING_SIZE_MAX))
|
||||
return nullptr;
|
||||
return reinterpret_cast<const ZeroTier::Endpoint*>(ep)->toString(buf);
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED int ZT_Endpoint_fromString(
|
||||
ZT_Endpoint *ep,
|
||||
const char *str)
|
||||
ZT_MAYBE_UNUSED int ZT_Endpoint_fromString(ZT_Endpoint* ep, const char* str)
|
||||
{
|
||||
if ((! ep) || (! str))
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
return reinterpret_cast<ZeroTier::Endpoint*>(ep)->fromString(str) ? ZT_RESULT_OK : ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED int ZT_Endpoint_fromBytes(
|
||||
ZT_Endpoint *ep,
|
||||
const void *bytes,
|
||||
unsigned int len)
|
||||
ZT_MAYBE_UNUSED int ZT_Endpoint_fromBytes(ZT_Endpoint* ep, const void* bytes, unsigned int len)
|
||||
{
|
||||
if ((! ep) || (! bytes) || (! len))
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
return (reinterpret_cast<ZeroTier::Endpoint *>(ep)->unmarshal(reinterpret_cast<const uint8_t *>(bytes), (int)len) > 0) ? 0 : ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
return (reinterpret_cast<ZeroTier::Endpoint*>(ep)->unmarshal(reinterpret_cast<const uint8_t*>(bytes), (int)len) > 0)
|
||||
? 0
|
||||
: ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/********************************************************************************************************************/
|
||||
|
@ -872,7 +917,8 @@ ZT_MAYBE_UNUSED char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *bu
|
|||
if (likely((cap > 0) && (buf != nullptr))) {
|
||||
if (likely((ia != nullptr) && (cap >= ZT_INETADDRESS_STRING_SIZE_MAX))) {
|
||||
reinterpret_cast<const ZeroTier::InetAddress*>(ia)->toString(buf);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
buf[0] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -893,7 +939,8 @@ ZT_MAYBE_UNUSED void ZT_InetAddress_set(ZT_InetAddress *ia, const void *saddr)
|
|||
(*reinterpret_cast<ZeroTier::InetAddress*>(ia)) = reinterpret_cast<const struct sockaddr*>(saddr);
|
||||
}
|
||||
|
||||
ZT_MAYBE_UNUSED void ZT_InetAddress_setIpBytes(ZT_InetAddress *ia, const void *ipBytes, unsigned int ipLen, unsigned int port)
|
||||
ZT_MAYBE_UNUSED void
|
||||
ZT_InetAddress_setIpBytes(ZT_InetAddress* ia, const void* ipBytes, unsigned int ipLen, unsigned int port)
|
||||
{
|
||||
if (likely(ia != nullptr))
|
||||
reinterpret_cast<ZeroTier::InetAddress*>(ia)->set(ipBytes, ipLen, port);
|
||||
|
@ -938,10 +985,14 @@ ZT_MAYBE_UNUSED unsigned int ZT_InetAddress_ipBytes(const ZT_InetAddress *ia, vo
|
|||
if (ia) {
|
||||
switch (reinterpret_cast<const ZeroTier::InetAddress*>(ia)->as.sa.sa_family) {
|
||||
case AF_INET:
|
||||
ZeroTier::Utils::copy<4>(buf, &(reinterpret_cast<const ZeroTier::InetAddress *>(ia)->as.sa_in.sin_addr.s_addr));
|
||||
ZeroTier::Utils::copy<4>(
|
||||
buf,
|
||||
&(reinterpret_cast<const ZeroTier::InetAddress*>(ia)->as.sa_in.sin_addr.s_addr));
|
||||
return 4;
|
||||
case AF_INET6:
|
||||
ZeroTier::Utils::copy<16>(buf, reinterpret_cast<const ZeroTier::InetAddress *>(ia)->as.sa_in6.sin6_addr.s6_addr);
|
||||
ZeroTier::Utils::copy<16>(
|
||||
buf,
|
||||
reinterpret_cast<const ZeroTier::InetAddress*>(ia)->as.sa_in6.sin6_addr.s6_addr);
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
@ -959,26 +1010,38 @@ ZT_MAYBE_UNUSED int ZT_InetAddress_compare(const ZT_InetAddress *a, const ZT_Ine
|
|||
{
|
||||
if (a) {
|
||||
if (b) {
|
||||
if (*reinterpret_cast<const ZeroTier::InetAddress *>(a) < *reinterpret_cast<const ZeroTier::InetAddress *>(b)) {
|
||||
if (*reinterpret_cast<const ZeroTier::InetAddress*>(a)
|
||||
< *reinterpret_cast<const ZeroTier::InetAddress*>(b)) {
|
||||
return -1;
|
||||
} else if (*reinterpret_cast<const ZeroTier::InetAddress *>(b) < *reinterpret_cast<const ZeroTier::InetAddress *>(a)) {
|
||||
}
|
||||
else if (
|
||||
*reinterpret_cast<const ZeroTier::InetAddress*>(b)
|
||||
< *reinterpret_cast<const ZeroTier::InetAddress*>(a)) {
|
||||
return 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
} else if (b) {
|
||||
}
|
||||
else if (b) {
|
||||
return -1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************************************/
|
||||
|
||||
ZT_MAYBE_UNUSED int ZT_Dictionary_parse(const void *const dict, const unsigned int len, void *const arg, void (*f)(void *, const char *, unsigned int, const void *, unsigned int))
|
||||
ZT_MAYBE_UNUSED int ZT_Dictionary_parse(
|
||||
const void* const dict,
|
||||
const unsigned int len,
|
||||
void* const arg,
|
||||
void (*f)(void*, const char*, unsigned int, const void*, unsigned int))
|
||||
{
|
||||
ZeroTier::Dictionary d;
|
||||
if (d.decode(dict, len)) {
|
||||
|
@ -993,6 +1056,8 @@ ZT_MAYBE_UNUSED int ZT_Dictionary_parse(const void *const dict, const unsigned i
|
|||
/********************************************************************************************************************/
|
||||
|
||||
ZT_MAYBE_UNUSED uint64_t ZT_random()
|
||||
{ return ZeroTier::Utils::random(); }
|
||||
{
|
||||
return ZeroTier::Utils::random();
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -25,14 +25,11 @@ namespace ZeroTier {
|
|||
* graph around from function to function as needed. It's cleaner and probably
|
||||
* faster than passing clock, ticks, and tPtr around everywhere.
|
||||
*/
|
||||
class CallContext
|
||||
{
|
||||
class CallContext {
|
||||
public:
|
||||
ZT_INLINE CallContext(const int64_t c, const int64_t t, void *const p) :
|
||||
clock(c),
|
||||
ticks(t),
|
||||
tPtr(p)
|
||||
{}
|
||||
ZT_INLINE CallContext(const int64_t c, const int64_t t, void* const p) : clock(c), ticks(t), tPtr(p)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Real world time in milliseconds since Unix epoch or -1 if unknown.
|
||||
|
|
|
@ -12,9 +12,10 @@
|
|||
/****/
|
||||
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -23,12 +24,12 @@ CapabilityCredential::CapabilityCredential(
|
|||
const uint64_t nwid,
|
||||
const int64_t timestamp,
|
||||
const ZT_VirtualNetworkRule* const rules,
|
||||
const unsigned int ruleCount) noexcept:
|
||||
m_nwid(nwid),
|
||||
m_timestamp(timestamp),
|
||||
m_id(id),
|
||||
m_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES),
|
||||
m_signatureLength(0)
|
||||
const unsigned int ruleCount) noexcept
|
||||
: m_nwid(nwid)
|
||||
, m_timestamp(timestamp)
|
||||
, m_id(id)
|
||||
, m_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES)
|
||||
, m_signatureLength(0)
|
||||
{
|
||||
Utils::zero<sizeof(m_rules)>(m_rules);
|
||||
if (m_ruleCount > 0)
|
||||
|
@ -153,7 +154,10 @@ int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
return p;
|
||||
}
|
||||
|
||||
int CapabilityCredential::marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept
|
||||
int CapabilityCredential::marshalVirtualNetworkRules(
|
||||
uint8_t* data,
|
||||
const ZT_VirtualNetworkRule* const rules,
|
||||
const unsigned int ruleCount) noexcept
|
||||
{
|
||||
int p = 0;
|
||||
for (unsigned int i = 0; i < ruleCount; ++i) {
|
||||
|
@ -277,7 +281,9 @@ int CapabilityCredential::marshalVirtualNetworkRules(uint8_t *data, const ZT_Vir
|
|||
data[p++] = 19;
|
||||
Utils::storeBigEndian<uint64_t>(data + p, rules[i].v.intRange.start);
|
||||
p += 8;
|
||||
Utils::storeBigEndian<uint64_t>(data + p, rules[i].v.intRange.start + (uint64_t) rules[i].v.intRange.end);
|
||||
Utils::storeBigEndian<uint64_t>(
|
||||
data + p,
|
||||
rules[i].v.intRange.start + (uint64_t)rules[i].v.intRange.end);
|
||||
p += 8;
|
||||
Utils::storeBigEndian<uint16_t>(data + p, rules[i].v.intRange.idx);
|
||||
p += 2;
|
||||
|
@ -288,7 +294,12 @@ int CapabilityCredential::marshalVirtualNetworkRules(uint8_t *data, const ZT_Vir
|
|||
return p;
|
||||
}
|
||||
|
||||
int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data, const int len, ZT_VirtualNetworkRule *const rules, unsigned int &ruleCount, const unsigned int maxRuleCount) noexcept
|
||||
int CapabilityCredential::unmarshalVirtualNetworkRules(
|
||||
const uint8_t* const data,
|
||||
const int len,
|
||||
ZT_VirtualNetworkRule* const rules,
|
||||
unsigned int& ruleCount,
|
||||
const unsigned int maxRuleCount) noexcept
|
||||
{
|
||||
int p = 0;
|
||||
unsigned int rc = 0;
|
||||
|
@ -305,7 +316,8 @@ int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data
|
|||
case ZT_NETWORK_RULE_ACTION_TEE:
|
||||
case ZT_NETWORK_RULE_ACTION_WATCH:
|
||||
case ZT_NETWORK_RULE_ACTION_REDIRECT:
|
||||
if ((p + 14) > len) return -1;
|
||||
if ((p + 14) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.fwd.address = Utils::loadBigEndian<uint64_t>(data + p);
|
||||
p += 8;
|
||||
rules[ruleCount].v.fwd.flags = Utils::loadBigEndian<uint32_t>(data + p);
|
||||
|
@ -315,86 +327,101 @@ int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data
|
|||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
|
||||
case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS:
|
||||
if ((p + ZT_ADDRESS_LENGTH) > len) return -1;
|
||||
if ((p + ZT_ADDRESS_LENGTH) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.zt = Address(data + p).toInt();
|
||||
p += ZT_ADDRESS_LENGTH;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_ID:
|
||||
if ((p + 2) > len) return -1;
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.vlanId = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_PCP:
|
||||
if ((p + 1) > len) return -1;
|
||||
if ((p + 1) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.vlanPcp = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_VLAN_DEI:
|
||||
if ((p + 1) > len) return -1;
|
||||
if ((p + 1) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.vlanDei = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
|
||||
case ZT_NETWORK_RULE_MATCH_MAC_DEST:
|
||||
if ((p + 6) > len) return -1;
|
||||
if ((p + 6) > len)
|
||||
return -1;
|
||||
Utils::copy<6>(rules[ruleCount].v.mac, data + p);
|
||||
p += 6;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
|
||||
case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
|
||||
if ((p + 5) > len) return -1;
|
||||
if ((p + 5) > len)
|
||||
return -1;
|
||||
Utils::copy<4>(&(rules[ruleCount].v.ipv4.ip), data + p);
|
||||
p += 4;
|
||||
rules[ruleCount].v.ipv4.mask = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
|
||||
case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
|
||||
if ((p + 17) > len) return -1;
|
||||
if ((p + 17) > len)
|
||||
return -1;
|
||||
Utils::copy<16>(rules[ruleCount].v.ipv6.ip, data + p);
|
||||
p += 16;
|
||||
rules[ruleCount].v.ipv6.mask = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IP_TOS:
|
||||
if ((p + 3) > len) return -1;
|
||||
if ((p + 3) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.ipTos.mask = data[p++];
|
||||
rules[ruleCount].v.ipTos.value[0] = data[p++];
|
||||
rules[ruleCount].v.ipTos.value[1] = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
|
||||
if ((p + 1) > len) return -1;
|
||||
if ((p + 1) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.ipProtocol = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
|
||||
if ((p + 2) > len) return -1;
|
||||
if ((p + 2) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.etherType = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_ICMP:
|
||||
if ((p + 3) > len) return -1;
|
||||
if ((p + 3) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.icmp.type = data[p++];
|
||||
rules[ruleCount].v.icmp.code = data[p++];
|
||||
rules[ruleCount].v.icmp.flags = data[p++];
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
|
||||
case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
|
||||
if ((p + 4) > len) return -1;
|
||||
if ((p + 4) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.port[0] = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
rules[ruleCount].v.port[1] = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS:
|
||||
if ((p + 8) > len) return -1;
|
||||
if ((p + 8) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.characteristics = Utils::loadBigEndian<uint64_t>(data + p);
|
||||
p += 8;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE:
|
||||
if ((p + 4) > len) return -1;
|
||||
if ((p + 4) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.frameSize[0] = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
rules[ruleCount].v.frameSize[1] = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_RANDOM:
|
||||
if ((p + 4) > len) return -1;
|
||||
if ((p + 4) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.randomProbability = Utils::loadBigEndian<uint32_t>(data + p);
|
||||
p += 4;
|
||||
break;
|
||||
|
@ -405,17 +432,20 @@ int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data
|
|||
case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_SENDER:
|
||||
case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER:
|
||||
if ((p + 4) > len) return -1;
|
||||
if ((p + 4) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.tag.id = Utils::loadBigEndian<uint32_t>(data + p);
|
||||
p += 4;
|
||||
rules[ruleCount].v.tag.value = Utils::loadBigEndian<uint32_t>(data + p);
|
||||
p += 4;
|
||||
break;
|
||||
case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE:
|
||||
if ((p + 19) > len) return -1;
|
||||
if ((p + 19) > len)
|
||||
return -1;
|
||||
rules[ruleCount].v.intRange.start = Utils::loadBigEndian<uint64_t>(data + p);
|
||||
p += 8;
|
||||
rules[ruleCount].v.intRange.end = (uint32_t) (Utils::loadBigEndian<uint64_t>(data + p) - rules[ruleCount].v.intRange.start);
|
||||
rules[ruleCount].v.intRange.end =
|
||||
(uint32_t)(Utils::loadBigEndian<uint64_t>(data + p) - rules[ruleCount].v.intRange.start);
|
||||
p += 8;
|
||||
rules[ruleCount].v.intRange.idx = Utils::loadBigEndian<uint16_t>(data + p);
|
||||
p += 2;
|
||||
|
|
|
@ -14,15 +14,17 @@
|
|||
#ifndef ZT_CAPABILITY_HPP
|
||||
#define ZT_CAPABILITY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX 21
|
||||
#define ZT_CAPABILITY_MARSHAL_SIZE_MAX (8 + 8 + 4 + 1 + 2 + (ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX * ZT_MAX_CAPABILITY_RULES) + 2 + (5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE))
|
||||
#define ZT_CAPABILITY_MARSHAL_SIZE_MAX \
|
||||
(8 + 8 + 4 + 1 + 2 + (ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX * ZT_MAX_CAPABILITY_RULES) + 2 \
|
||||
+ (5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE))
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -46,16 +48,19 @@ class Context;
|
|||
* Note that this is after evaluation of network scope rules and only if
|
||||
* network scope rules do not deliver an explicit match.
|
||||
*/
|
||||
class CapabilityCredential : public Credential
|
||||
{
|
||||
class CapabilityCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_CAPABILITY; }
|
||||
{
|
||||
return ZT_CREDENTIAL_TYPE_CAPABILITY;
|
||||
}
|
||||
|
||||
ZT_INLINE CapabilityCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Capability ID
|
||||
|
@ -76,37 +81,57 @@ public:
|
|||
* @return Rules -- see ruleCount() for size of array
|
||||
*/
|
||||
ZT_INLINE const ZT_VirtualNetworkRule* rules() const noexcept
|
||||
{ return m_rules; }
|
||||
{
|
||||
return m_rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Number of rules in rules()
|
||||
*/
|
||||
ZT_INLINE unsigned int ruleCount() const noexcept
|
||||
{ return m_ruleCount; }
|
||||
{
|
||||
return m_ruleCount;
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_nwid; }
|
||||
{
|
||||
return m_nwid;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_timestamp; }
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_timestamp; }
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& issuedTo() const noexcept
|
||||
{ return m_issuedTo; }
|
||||
{
|
||||
return m_issuedTo;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& signer() const noexcept
|
||||
{ return m_signedBy; }
|
||||
{
|
||||
return m_signedBy;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t* signature() const noexcept
|
||||
{ return m_signature; }
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{ return m_signatureLength; }
|
||||
{
|
||||
return m_signatureLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign this capability and add signature to its chain of custody
|
||||
|
@ -129,10 +154,14 @@ public:
|
|||
* @param RR Runtime environment to provide for peer lookup, etc.
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const noexcept
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_CAPABILITY_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_CAPABILITY_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
@ -145,7 +174,8 @@ public:
|
|||
* @param ruleCount Number of rules
|
||||
* @return Number of bytes written or -1 on error
|
||||
*/
|
||||
static int marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *rules, unsigned int ruleCount) noexcept;
|
||||
static int
|
||||
marshalVirtualNetworkRules(uint8_t* data, const ZT_VirtualNetworkRule* rules, unsigned int ruleCount) noexcept;
|
||||
|
||||
/**
|
||||
* Unmarshal a set of virtual network rules
|
||||
|
@ -157,17 +187,28 @@ public:
|
|||
* @param maxRuleCount Capacity of rules buffer
|
||||
* @return Number of bytes unmarshaled or -1 on error
|
||||
*/
|
||||
static int unmarshalVirtualNetworkRules(const uint8_t *data, int len, ZT_VirtualNetworkRule *rules, unsigned int &ruleCount, unsigned int maxRuleCount) noexcept;
|
||||
static int unmarshalVirtualNetworkRules(
|
||||
const uint8_t* data,
|
||||
int len,
|
||||
ZT_VirtualNetworkRule* rules,
|
||||
unsigned int& ruleCount,
|
||||
unsigned int maxRuleCount) noexcept;
|
||||
|
||||
// Provides natural sort order by ID
|
||||
ZT_INLINE bool operator<(const CapabilityCredential& c) const noexcept
|
||||
{ return (m_id < c.m_id); }
|
||||
{
|
||||
return (m_id < c.m_id);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const CapabilityCredential& c) const noexcept
|
||||
{ return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0); }
|
||||
{
|
||||
return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const CapabilityCredential& c) const noexcept
|
||||
{ return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0); }
|
||||
{
|
||||
return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_nwid;
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
/****/
|
||||
|
||||
#include "Certificate.hpp"
|
||||
#include "SHA512.hpp"
|
||||
|
||||
#include "ECC384.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -24,16 +25,19 @@ Certificate::Certificate() noexcept
|
|||
Utils::zero<sizeof(ZT_Certificate)>(sup);
|
||||
}
|
||||
|
||||
Certificate::Certificate(const ZT_Certificate &apiCert) :
|
||||
Certificate()
|
||||
{ *this = apiCert; }
|
||||
Certificate::Certificate(const ZT_Certificate& apiCert) : Certificate()
|
||||
{
|
||||
*this = apiCert;
|
||||
}
|
||||
|
||||
Certificate::Certificate(const Certificate &cert) :
|
||||
Certificate()
|
||||
{ *this = cert; }
|
||||
Certificate::Certificate(const Certificate& cert) : Certificate()
|
||||
{
|
||||
*this = cert;
|
||||
}
|
||||
|
||||
Certificate::~Certificate()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
Certificate& Certificate::operator=(const ZT_Certificate& cert)
|
||||
{
|
||||
|
@ -51,8 +55,11 @@ Certificate &Certificate::operator=(const ZT_Certificate &cert)
|
|||
for (unsigned int i = 0; i < cert.subject.identityCount; ++i) {
|
||||
if (cert.subject.identities[i].identity) {
|
||||
if (cert.subject.identities[i].locator) {
|
||||
addSubjectIdentity(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity), *reinterpret_cast<const Locator *>(cert.subject.identities[i].locator));
|
||||
} else {
|
||||
addSubjectIdentity(
|
||||
*reinterpret_cast<const Identity*>(cert.subject.identities[i].identity),
|
||||
*reinterpret_cast<const Locator*>(cert.subject.identities[i].locator));
|
||||
}
|
||||
else {
|
||||
addSubjectIdentity(*reinterpret_cast<const Identity*>(cert.subject.identities[i].identity));
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +89,9 @@ Certificate &Certificate::operator=(const ZT_Certificate &cert)
|
|||
Utils::copy<sizeof(ZT_Certificate_Name)>(&(this->subject.name), &(cert.subject.name));
|
||||
|
||||
Utils::copy<sizeof(this->subject.uniqueId)>(this->subject.uniqueId, cert.subject.uniqueId);
|
||||
Utils::copy< sizeof(this->subject.uniqueIdSignature) >(this->subject.uniqueIdSignature, cert.subject.uniqueIdSignature);
|
||||
Utils::copy<sizeof(this->subject.uniqueIdSignature)>(
|
||||
this->subject.uniqueIdSignature,
|
||||
cert.subject.uniqueIdSignature);
|
||||
this->subject.uniqueIdSize = cert.subject.uniqueIdSize;
|
||||
this->subject.uniqueIdSignatureSize = cert.subject.uniqueIdSignatureSize;
|
||||
|
||||
|
@ -241,7 +250,8 @@ bool Certificate::decode(const void *const data, const unsigned int len)
|
|||
return false;
|
||||
if (locatorData.empty()) {
|
||||
this->addSubjectIdentity(id);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Locator loc;
|
||||
if (loc.unmarshal(locatorData.data(), (unsigned int)locatorData.size()) <= 0)
|
||||
return false;
|
||||
|
@ -326,7 +336,10 @@ bool Certificate::decode(const void *const data, const unsigned int len)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Certificate::sign(const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE], const void *const issuerPrivateKey, const unsigned int issuerPrivateKeySize)
|
||||
bool Certificate::sign(
|
||||
const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE],
|
||||
const void* const issuerPrivateKey,
|
||||
const unsigned int issuerPrivateKeySize)
|
||||
{
|
||||
if ((! issuerPrivateKey) || (issuerPrivateKeySize == 0))
|
||||
return false;
|
||||
|
@ -337,13 +350,18 @@ bool Certificate::sign(const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE], const voi
|
|||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384:
|
||||
if (issuerPrivateKeySize == (1 + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_ECC384_PRIVATE_KEY_SIZE)) {
|
||||
Utils::copy<sizeof(this->issuer)>(this->issuer, issuer);
|
||||
Utils::copy< 1 + ZT_ECC384_PUBLIC_KEY_SIZE >(this->issuerPublicKey, issuerPrivateKey); // private is prefixed with public
|
||||
Utils::copy<1 + ZT_ECC384_PUBLIC_KEY_SIZE>(
|
||||
this->issuerPublicKey,
|
||||
issuerPrivateKey); // private is prefixed with public
|
||||
this->issuerPublicKeySize = 1 + ZT_ECC384_PUBLIC_KEY_SIZE;
|
||||
|
||||
const Vector<uint8_t> enc(encode(true));
|
||||
SHA384(this->serialNo, enc.data(), (unsigned int)enc.size());
|
||||
|
||||
ECC384ECDSASign(reinterpret_cast<const uint8_t *>(issuerPrivateKey) + 1 + ZT_ECC384_PUBLIC_KEY_SIZE, this->serialNo, this->signature);
|
||||
ECC384ECDSASign(
|
||||
reinterpret_cast<const uint8_t*>(issuerPrivateKey) + 1 + ZT_ECC384_PUBLIC_KEY_SIZE,
|
||||
this->serialNo,
|
||||
this->signature);
|
||||
this->signatureSize = ZT_ECC384_SIGNATURE_SIZE;
|
||||
|
||||
return true;
|
||||
|
@ -368,15 +386,20 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
if (checkSignatures) {
|
||||
if (!reinterpret_cast<const Identity *>(this->subject.identities[i].identity)->locallyValidate()) {
|
||||
if (! reinterpret_cast<const Identity*>(this->subject.identities[i].identity)
|
||||
->locallyValidate()) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_IDENTITY;
|
||||
}
|
||||
if ((this->subject.identities[i].locator) && (!reinterpret_cast<const Locator *>(this->subject.identities[i].locator)->verify(*reinterpret_cast<const Identity *>(this->subject.identities[i].identity)))) {
|
||||
if ((this->subject.identities[i].locator)
|
||||
&& (! reinterpret_cast<const Locator*>(this->subject.identities[i].locator)
|
||||
->verify(
|
||||
*reinterpret_cast<const Identity*>(this->subject.identities[i].identity)))) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_COMPONENT_SIGNATURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +411,8 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
}
|
||||
|
@ -399,16 +423,19 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
if (! this->subject.updateURLs[i])
|
||||
return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_MISSING_REQUIRED_FIELDS;
|
||||
}
|
||||
}
|
||||
|
||||
if ((this->subject.uniqueIdSize > sizeof(this->subject.uniqueId)) || (this->subject.uniqueIdSignatureSize > sizeof(this->subject.uniqueIdSignature))) {
|
||||
if ((this->subject.uniqueIdSize > sizeof(this->subject.uniqueId))
|
||||
|| (this->subject.uniqueIdSignatureSize > sizeof(this->subject.uniqueIdSignature))) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
if ((this->issuerPublicKeySize > sizeof(this->issuerPublicKey)) || (this->publicKeySize > sizeof(this->publicKey))) {
|
||||
if ((this->issuerPublicKeySize > sizeof(this->issuerPublicKey))
|
||||
|| (this->publicKeySize > sizeof(this->publicKey))) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
|
@ -424,21 +451,25 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
// Signature check fails if main signature is not present or invalid.
|
||||
// Note that the serial number / SHA384 hash is computed on decode(), so
|
||||
// this value is not something we blindly trust from input.
|
||||
if ((this->issuerPublicKeySize > 0) && (this->issuerPublicKeySize <= (unsigned int)sizeof(this->issuerPublicKey))) {
|
||||
if ((this->issuerPublicKeySize > 0)
|
||||
&& (this->issuerPublicKeySize <= (unsigned int)sizeof(this->issuerPublicKey))) {
|
||||
switch (this->issuerPublicKey[0]) {
|
||||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384:
|
||||
if ((this->issuerPublicKeySize == (ZT_ECC384_PUBLIC_KEY_SIZE + 1)) && (this->signatureSize == ZT_ECC384_SIGNATURE_SIZE)) {
|
||||
if ((this->issuerPublicKeySize == (ZT_ECC384_PUBLIC_KEY_SIZE + 1))
|
||||
&& (this->signatureSize == ZT_ECC384_SIGNATURE_SIZE)) {
|
||||
if (! ECC384ECDSAVerify(this->issuerPublicKey + 1, this->serialNo, this->signature)) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE;
|
||||
}
|
||||
|
||||
|
@ -451,7 +482,8 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_NONE:
|
||||
break;
|
||||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384:
|
||||
if ((this->subject.uniqueIdSize == (ZT_ECC384_PUBLIC_KEY_SIZE + 1)) && (this->subject.uniqueIdSignatureSize == ZT_ECC384_SIGNATURE_SIZE)) {
|
||||
if ((this->subject.uniqueIdSize == (ZT_ECC384_PUBLIC_KEY_SIZE + 1))
|
||||
&& (this->subject.uniqueIdSignatureSize == ZT_ECC384_SIGNATURE_SIZE)) {
|
||||
Dictionary d;
|
||||
m_encodeSubject(this->subject, d, true);
|
||||
|
||||
|
@ -459,21 +491,28 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
enc.reserve(1024);
|
||||
d.encode(enc);
|
||||
|
||||
static_assert(ZT_ECC384_SIGNATURE_HASH_SIZE == ZT_SHA384_DIGEST_SIZE, "ECC384 should take 384-bit hash");
|
||||
static_assert(
|
||||
ZT_ECC384_SIGNATURE_HASH_SIZE == ZT_SHA384_DIGEST_SIZE,
|
||||
"ECC384 should take 384-bit hash");
|
||||
uint8_t h[ZT_SHA384_DIGEST_SIZE];
|
||||
SHA384(h, enc.data(), (unsigned int)enc.size());
|
||||
|
||||
if (!ECC384ECDSAVerify(this->subject.uniqueId + 1, h, this->subject.uniqueIdSignature)) {
|
||||
if (! ECC384ECDSAVerify(
|
||||
this->subject.uniqueId + 1,
|
||||
h,
|
||||
this->subject.uniqueIdSignature)) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
|
||||
}
|
||||
}
|
||||
|
@ -483,14 +522,20 @@ ZT_CertificateError Certificate::verify(const int64_t clock, const bool checkSig
|
|||
if (! this->verifyTimeWindow(clock))
|
||||
return ZT_CERTIFICATE_ERROR_OUT_OF_VALID_TIME_WINDOW;
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
return ZT_CERTIFICATE_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool Certificate::newKeyPair(const ZT_CertificatePublicKeyAlgorithm type, uint8_t publicKey[ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE], int *const publicKeySize, uint8_t privateKey[ZT_CERTIFICATE_MAX_PRIVATE_KEY_SIZE], int *const privateKeySize)
|
||||
bool Certificate::newKeyPair(
|
||||
const ZT_CertificatePublicKeyAlgorithm type,
|
||||
uint8_t publicKey[ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE],
|
||||
int* const publicKeySize,
|
||||
uint8_t privateKey[ZT_CERTIFICATE_MAX_PRIVATE_KEY_SIZE],
|
||||
int* const privateKeySize)
|
||||
{
|
||||
switch (type) {
|
||||
case ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384:
|
||||
|
@ -506,7 +551,12 @@ bool Certificate::newKeyPair(const ZT_CertificatePublicKeyAlgorithm type, uint8_
|
|||
return false;
|
||||
}
|
||||
|
||||
Vector< uint8_t > Certificate::createCSR(const ZT_Certificate_Subject &s, const void *const certificatePublicKey, const unsigned int certificatePublicKeySize, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize)
|
||||
Vector<uint8_t> Certificate::createCSR(
|
||||
const ZT_Certificate_Subject& s,
|
||||
const void* const certificatePublicKey,
|
||||
const unsigned int certificatePublicKeySize,
|
||||
const void* uniqueIdPrivate,
|
||||
unsigned int uniqueIdPrivateSize)
|
||||
{
|
||||
Vector<uint8_t> enc;
|
||||
|
||||
|
@ -539,10 +589,16 @@ void Certificate::m_clear()
|
|||
m_extendedAttributes.clear();
|
||||
}
|
||||
|
||||
bool Certificate::m_setSubjectUniqueId(ZT_Certificate_Subject &s, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize)
|
||||
bool Certificate::m_setSubjectUniqueId(
|
||||
ZT_Certificate_Subject& s,
|
||||
const void* uniqueIdPrivate,
|
||||
unsigned int uniqueIdPrivateSize)
|
||||
{
|
||||
if (uniqueIdPrivateSize > 0) {
|
||||
if ((uniqueIdPrivate != nullptr) && (uniqueIdPrivateSize == (1 + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_ECC384_PRIVATE_KEY_SIZE)) && (reinterpret_cast<const uint8_t *>(uniqueIdPrivate)[0] == (uint8_t)ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384)) {
|
||||
if ((uniqueIdPrivate != nullptr)
|
||||
&& (uniqueIdPrivateSize == (1 + ZT_ECC384_PUBLIC_KEY_SIZE + ZT_ECC384_PRIVATE_KEY_SIZE))
|
||||
&& (reinterpret_cast<const uint8_t*>(uniqueIdPrivate)[0]
|
||||
== (uint8_t)ZT_CERTIFICATE_PUBLIC_KEY_ALGORITHM_ECDSA_NIST_P_384)) {
|
||||
Utils::copy<1 + ZT_ECC384_PUBLIC_KEY_SIZE>(s.uniqueId, uniqueIdPrivate);
|
||||
s.uniqueIdSize = 1 + ZT_ECC384_PUBLIC_KEY_SIZE; // private is prefixed with public
|
||||
|
||||
|
@ -554,12 +610,17 @@ bool Certificate::m_setSubjectUniqueId(ZT_Certificate_Subject &s, const void *un
|
|||
uint8_t h[ZT_SHA384_DIGEST_SIZE];
|
||||
SHA384(h, enc.data(), (unsigned int)enc.size());
|
||||
|
||||
ECC384ECDSASign(reinterpret_cast<const uint8_t *>(uniqueIdPrivate) + 1 + ZT_ECC384_PUBLIC_KEY_SIZE, h, s.uniqueIdSignature);
|
||||
ECC384ECDSASign(
|
||||
reinterpret_cast<const uint8_t*>(uniqueIdPrivate) + 1 + ZT_ECC384_PUBLIC_KEY_SIZE,
|
||||
h,
|
||||
s.uniqueIdSignature);
|
||||
s.uniqueIdSignatureSize = ZT_ECC384_SIGNATURE_SIZE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Utils::zero<sizeof(s.uniqueId)>(s.uniqueId);
|
||||
s.uniqueIdSize = 0;
|
||||
Utils::zero<sizeof(s.uniqueIdSignature)>(s.uniqueIdSignature);
|
||||
|
@ -578,9 +639,13 @@ void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d
|
|||
d.add("s.i$", (uint64_t)s.identityCount);
|
||||
for (unsigned int i = 0; i < s.identityCount; ++i) {
|
||||
if (s.identities[i].identity)
|
||||
d.addO(Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.i", i), *reinterpret_cast<const Identity *>(s.identities[i].identity));
|
||||
d.addO(
|
||||
Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.i", i),
|
||||
*reinterpret_cast<const Identity*>(s.identities[i].identity));
|
||||
if (s.identities[i].locator)
|
||||
d.addO(Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.l", i), *reinterpret_cast<const Locator *>(s.identities[i].locator));
|
||||
d.addO(
|
||||
Dictionary::arraySubscript(tmp, sizeof(tmp), "s.i$.l", i),
|
||||
*reinterpret_cast<const Locator*>(s.identities[i].locator));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
#ifndef ZT_CERTIFICATE_HPP
|
||||
#define ZT_CERTIFICATE_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Containers.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -43,8 +43,7 @@ namespace ZeroTier {
|
|||
* field, so these will not work correctly before sign() or decode() is
|
||||
* called.
|
||||
*/
|
||||
class Certificate : public ZT_Certificate
|
||||
{
|
||||
class Certificate : public ZT_Certificate {
|
||||
public:
|
||||
Certificate() noexcept;
|
||||
explicit Certificate(const ZT_Certificate& apiCert);
|
||||
|
@ -63,7 +62,9 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE H384 getSerialNo() const noexcept
|
||||
{ return H384(this->serialNo); }
|
||||
{
|
||||
return H384(this->serialNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subject node/identity without a locator
|
||||
|
@ -109,7 +110,9 @@ public:
|
|||
* @return True on success
|
||||
*/
|
||||
ZT_INLINE bool setSubjectUniqueId(const void* uniqueIdPrivate, unsigned int uniqueIdPrivateSize)
|
||||
{ return m_setSubjectUniqueId(this->subject, uniqueIdPrivate, uniqueIdPrivateSize); }
|
||||
{
|
||||
return m_setSubjectUniqueId(this->subject, uniqueIdPrivate, uniqueIdPrivateSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshal this certificate in binary form
|
||||
|
@ -138,7 +141,10 @@ public:
|
|||
*
|
||||
* @return True on success
|
||||
*/
|
||||
bool sign(const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE], const void *issuerPrivateKey, unsigned int issuerPrivateKeySize);
|
||||
bool sign(
|
||||
const uint8_t issuer[ZT_CERTIFICATE_HASH_SIZE],
|
||||
const void* issuerPrivateKey,
|
||||
unsigned int issuerPrivateKeySize);
|
||||
|
||||
/**
|
||||
* Verify self-contained signatures and validity of certificate structure
|
||||
|
@ -159,7 +165,10 @@ public:
|
|||
* @return True if certificate is not expired or outside window
|
||||
*/
|
||||
ZT_INLINE bool verifyTimeWindow(int64_t clock) const noexcept
|
||||
{ return ((clock >= this->validity[0]) && (clock <= this->validity[1]) && (this->validity[0] <= this->validity[1])); }
|
||||
{
|
||||
return (
|
||||
(clock >= this->validity[0]) && (clock <= this->validity[1]) && (this->validity[0] <= this->validity[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new certificate public/private key pair
|
||||
|
@ -171,7 +180,12 @@ public:
|
|||
* @param privateKeySize Result parameter: set to size of private key
|
||||
* @return True on success
|
||||
*/
|
||||
static bool newKeyPair(const ZT_CertificatePublicKeyAlgorithm type, uint8_t publicKey[ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE], int *const publicKeySize, uint8_t privateKey[ZT_CERTIFICATE_MAX_PRIVATE_KEY_SIZE], int *const privateKeySize);
|
||||
static bool newKeyPair(
|
||||
const ZT_CertificatePublicKeyAlgorithm type,
|
||||
uint8_t publicKey[ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE],
|
||||
int* const publicKeySize,
|
||||
uint8_t privateKey[ZT_CERTIFICATE_MAX_PRIVATE_KEY_SIZE],
|
||||
int* const privateKeySize);
|
||||
|
||||
/**
|
||||
* Create a CSR that encodes the subject of this certificate
|
||||
|
@ -183,32 +197,52 @@ public:
|
|||
* @param uniqueIdPrivateSize Size of unique ID private key
|
||||
* @return Encoded subject (without any unique ID fields) or empty vector on error
|
||||
*/
|
||||
static Vector< uint8_t > createCSR(const ZT_Certificate_Subject &s, const void *certificatePublicKey, unsigned int certificatePublicKeySize, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize);
|
||||
static Vector<uint8_t> createCSR(
|
||||
const ZT_Certificate_Subject& s,
|
||||
const void* certificatePublicKey,
|
||||
unsigned int certificatePublicKeySize,
|
||||
const void* uniqueIdPrivate,
|
||||
unsigned int uniqueIdPrivateSize);
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)Utils::loadMachineEndian< uint32_t >(this->serialNo); }
|
||||
{
|
||||
return (unsigned long)Utils::loadMachineEndian<uint32_t>(this->serialNo);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const ZT_Certificate& c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0; }
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const ZT_Certificate& c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) != 0; }
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) != 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const ZT_Certificate& c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) < 0; }
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) < 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const ZT_Certificate& c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) <= 0; }
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) <= 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const ZT_Certificate& c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) > 0; }
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) > 0;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const ZT_Certificate& c) const noexcept
|
||||
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0; }
|
||||
{
|
||||
return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void m_clear();
|
||||
static bool m_setSubjectUniqueId(ZT_Certificate_Subject &s, const void *uniqueIdPrivate, unsigned int uniqueIdPrivateSize);
|
||||
static bool
|
||||
m_setSubjectUniqueId(ZT_Certificate_Subject& s, const void* uniqueIdPrivate, unsigned int uniqueIdPrivateSize);
|
||||
static void m_encodeSubject(const ZT_Certificate_Subject& s, Dictionary& d, bool omitUniqueIdProofSignature);
|
||||
|
||||
// These hold any identity or locator objects that are owned by and should
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#define ZT_CORE 1
|
||||
|
||||
#include "OS.hpp"
|
||||
#include "zerotier.h"
|
||||
#include "version.h"
|
||||
#include "zerotier.h"
|
||||
|
||||
/**
|
||||
* Length of a ZeroTier address in bytes
|
||||
|
@ -190,7 +190,8 @@
|
|||
#define ZT_PEER_WHOIS_RATE_LIMIT 100
|
||||
|
||||
/**
|
||||
* General rate limit for other kinds of rate-limited packets (HELLO, credential request, etc.) both inbound and outbound
|
||||
* General rate limit for other kinds of rate-limited packets (HELLO, credential request, etc.) both inbound and
|
||||
* outbound
|
||||
*/
|
||||
#define ZT_PEER_GENERAL_RATE_LIMIT 500
|
||||
|
||||
|
|
|
@ -19,111 +19,104 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __CPP11__
|
||||
|
||||
#include <atomic>
|
||||
#include <unordered_map>
|
||||
#include <forward_list>
|
||||
#include <unordered_map>
|
||||
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
template< typename V >
|
||||
class Vector : public std::vector< V >
|
||||
{
|
||||
template <typename V> class Vector : public std::vector<V> {
|
||||
public:
|
||||
ZT_INLINE Vector() :
|
||||
std::vector< V >()
|
||||
{}
|
||||
ZT_INLINE Vector() : std::vector<V>()
|
||||
{
|
||||
}
|
||||
|
||||
template< typename I >
|
||||
ZT_INLINE Vector(I begin, I end) :
|
||||
std::vector< V >(begin, end)
|
||||
{}
|
||||
template <typename I> ZT_INLINE Vector(I begin, I end) : std::vector<V>(begin, end)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template< typename V >
|
||||
class List : public std::list< V >
|
||||
{
|
||||
template <typename V> class List : public std::list<V> {
|
||||
};
|
||||
|
||||
#ifdef __CPP11__
|
||||
|
||||
struct intl_MapHasher
|
||||
struct intl_MapHasher {
|
||||
template <typename O> std::size_t operator()(const O& obj) const noexcept
|
||||
{
|
||||
template< typename O >
|
||||
std::size_t operator()(const O &obj) const noexcept
|
||||
{ return (std::size_t)obj.hashCode(); }
|
||||
return (std::size_t)obj.hashCode();
|
||||
}
|
||||
|
||||
std::size_t operator()(const Vector<uint8_t>& bytes) const noexcept
|
||||
{ return (std::size_t)Utils::fnv1a32(bytes.data(), (unsigned int)bytes.size()); }
|
||||
{
|
||||
return (std::size_t)Utils::fnv1a32(bytes.data(), (unsigned int)bytes.size());
|
||||
}
|
||||
|
||||
std::size_t operator()(const uint64_t i) const noexcept
|
||||
{ return (std::size_t)Utils::hash64(i ^ Utils::s_mapNonce); }
|
||||
{
|
||||
return (std::size_t)Utils::hash64(i ^ Utils::s_mapNonce);
|
||||
}
|
||||
|
||||
std::size_t operator()(const int64_t i) const noexcept
|
||||
{ return (std::size_t)Utils::hash64((uint64_t)i ^ Utils::s_mapNonce); }
|
||||
{
|
||||
return (std::size_t)Utils::hash64((uint64_t)i ^ Utils::s_mapNonce);
|
||||
}
|
||||
|
||||
std::size_t operator()(const uint32_t i) const noexcept
|
||||
{ return (std::size_t)Utils::hash32(i ^ (uint32_t)Utils::s_mapNonce); }
|
||||
{
|
||||
return (std::size_t)Utils::hash32(i ^ (uint32_t)Utils::s_mapNonce);
|
||||
}
|
||||
|
||||
std::size_t operator()(const int32_t i) const noexcept
|
||||
{ return (std::size_t)Utils::hash32((uint32_t)i ^ (uint32_t)Utils::s_mapNonce); }
|
||||
{
|
||||
return (std::size_t)Utils::hash32((uint32_t)i ^ (uint32_t)Utils::s_mapNonce);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename K, typename V> class Map : public std::unordered_map<K, V, intl_MapHasher> {
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
class Map : public std::unordered_map< K, V, intl_MapHasher >
|
||||
{
|
||||
};
|
||||
|
||||
template< typename K, typename V >
|
||||
class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K > >
|
||||
{
|
||||
class MultiMap : public std::unordered_multimap<K, V, intl_MapHasher, std::equal_to<K> > {
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<typename K, typename V>
|
||||
class Map : public std::map< K, V >
|
||||
{};
|
||||
template <typename K, typename V> class Map : public std::map<K, V> {
|
||||
};
|
||||
|
||||
template<typename K, typename V>
|
||||
class MultiMap : public std::multimap< K, V >
|
||||
{};
|
||||
template <typename K, typename V> class MultiMap : public std::multimap<K, V> {
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template< typename K, typename V >
|
||||
class SortedMap : public std::map< K, V >
|
||||
{
|
||||
template <typename K, typename V> class SortedMap : public std::map<K, V> {
|
||||
};
|
||||
|
||||
#ifdef __CPP11__
|
||||
|
||||
template< typename V >
|
||||
class ForwardList : public std::forward_list< V >
|
||||
{
|
||||
template <typename V> class ForwardList : public std::forward_list<V> {
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template< typename V >
|
||||
class ForwardList : public std::list< V >
|
||||
{};
|
||||
template <typename V> class ForwardList : public std::list<V> {
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template< typename V >
|
||||
class Set : public std::set< V, std::less< V > >
|
||||
{
|
||||
template <typename V> class Set : public std::set<V, std::less<V> > {
|
||||
};
|
||||
|
||||
typedef std::string String;
|
||||
|
@ -131,18 +124,23 @@ typedef std::string String;
|
|||
/**
|
||||
* A 384-bit hash
|
||||
*/
|
||||
struct H384
|
||||
{
|
||||
struct H384 {
|
||||
uint64_t data[6];
|
||||
|
||||
ZT_INLINE H384() noexcept
|
||||
{ Utils::zero< sizeof(data) >(data); }
|
||||
{
|
||||
Utils::zero<sizeof(data)>(data);
|
||||
}
|
||||
|
||||
ZT_INLINE H384(const H384& b) noexcept
|
||||
{ Utils::copy< 48 >(data, b.data); }
|
||||
{
|
||||
Utils::copy<48>(data, b.data);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE H384(const void* const d) noexcept
|
||||
{ Utils::copy< 48 >(data, d); }
|
||||
{
|
||||
Utils::copy<48>(data, d);
|
||||
}
|
||||
|
||||
ZT_INLINE H384& operator=(const H384& b) noexcept
|
||||
{
|
||||
|
@ -151,28 +149,47 @@ struct H384
|
|||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)data[0]; }
|
||||
{
|
||||
return (unsigned long)data[0];
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return ((data[0] != 0) && (data[1] != 0) && (data[2] != 0) && (data[3] != 0) && (data[4] != 0) && (data[5] != 0)); }
|
||||
{
|
||||
return (
|
||||
(data[0] != 0) && (data[1] != 0) && (data[2] != 0) && (data[3] != 0) && (data[4] != 0) && (data[5] != 0));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const H384& b) const noexcept
|
||||
{ return ((data[0] == b.data[0]) && (data[1] == b.data[1]) && (data[2] == b.data[2]) && (data[3] == b.data[3]) && (data[4] == b.data[4]) && (data[5] == b.data[5])); }
|
||||
{
|
||||
return (
|
||||
(data[0] == b.data[0]) && (data[1] == b.data[1]) && (data[2] == b.data[2]) && (data[3] == b.data[3])
|
||||
&& (data[4] == b.data[4]) && (data[5] == b.data[5]));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const H384& b) const noexcept
|
||||
{ return !(*this == b); }
|
||||
{
|
||||
return ! (*this == b);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const H384& b) const noexcept
|
||||
{ return std::lexicographical_compare(data, data + 6, b.data, b.data + 6); }
|
||||
{
|
||||
return std::lexicographical_compare(data, data + 6, b.data, b.data + 6);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const H384& b) const noexcept
|
||||
{ return !(b < *this); }
|
||||
{
|
||||
return ! (b < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const H384& b) const noexcept
|
||||
{ return (b < *this); }
|
||||
{
|
||||
return (b < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const H384& b) const noexcept
|
||||
{ return !(*this < b); }
|
||||
{
|
||||
return ! (*this < b);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(H384) == 48, "H384 contains unnecessary padding");
|
||||
|
@ -182,19 +199,23 @@ static_assert(sizeof(H384) == 48, "H384 contains unnecessary padding");
|
|||
*
|
||||
* @tparam S Size in bytes
|
||||
*/
|
||||
template< unsigned long S >
|
||||
struct Blob
|
||||
{
|
||||
template <unsigned long S> struct Blob {
|
||||
uint8_t data[S];
|
||||
|
||||
ZT_INLINE Blob() noexcept
|
||||
{ Utils::zero< S >(data); }
|
||||
{
|
||||
Utils::zero<S>(data);
|
||||
}
|
||||
|
||||
ZT_INLINE Blob(const Blob& b) noexcept
|
||||
{ Utils::copy< S >(data, b.data); }
|
||||
{
|
||||
Utils::copy<S>(data, b.data);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE Blob(const void* const d) noexcept
|
||||
{ Utils::copy< S >(data, d); }
|
||||
{
|
||||
Utils::copy<S>(data, d);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE Blob(const void* const d, const unsigned int l) noexcept
|
||||
{
|
||||
|
@ -211,30 +232,46 @@ struct Blob
|
|||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return Utils::fnv1a32(data, (unsigned int)S); }
|
||||
{
|
||||
return Utils::fnv1a32(data, (unsigned int)S);
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return Utils::allZero(data, (unsigned int)S); }
|
||||
{
|
||||
return Utils::allZero(data, (unsigned int)S);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Blob& b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) == 0); }
|
||||
{
|
||||
return (memcmp(data, b.data, S) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Blob& b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) != 0); }
|
||||
{
|
||||
return (memcmp(data, b.data, S) != 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const Blob& b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) < 0); }
|
||||
{
|
||||
return (memcmp(data, b.data, S) < 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Blob& b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) <= 0); }
|
||||
{
|
||||
return (memcmp(data, b.data, S) <= 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const Blob& b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) > 0); }
|
||||
{
|
||||
return (memcmp(data, b.data, S) > 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Blob& b) const noexcept
|
||||
{ return (memcmp(data, b.data, S) >= 0); }
|
||||
{
|
||||
return (memcmp(data, b.data, S) >= 0);
|
||||
}
|
||||
};
|
||||
|
||||
} // ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
#ifndef ZT_RUNTIMEENVIRONMENT_HPP
|
||||
#define ZT_RUNTIMEENVIRONMENT_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "TinyMap.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "TinyMap.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -38,30 +38,31 @@ class Network;
|
|||
/**
|
||||
* Node instance context
|
||||
*/
|
||||
class Context
|
||||
{
|
||||
class Context {
|
||||
public:
|
||||
ZT_INLINE Context(Node *const n) noexcept:
|
||||
instanceId(Utils::getSecureRandomU64()),
|
||||
node(n),
|
||||
uPtr(nullptr),
|
||||
localNetworkController(nullptr),
|
||||
store(nullptr),
|
||||
networks(nullptr),
|
||||
t(nullptr),
|
||||
expect(nullptr),
|
||||
vl2(nullptr),
|
||||
vl1(nullptr),
|
||||
topology(nullptr),
|
||||
sa(nullptr),
|
||||
ts(nullptr)
|
||||
ZT_INLINE Context(Node* const n) noexcept
|
||||
: instanceId(Utils::getSecureRandomU64())
|
||||
, node(n)
|
||||
, uPtr(nullptr)
|
||||
, localNetworkController(nullptr)
|
||||
, store(nullptr)
|
||||
, networks(nullptr)
|
||||
, t(nullptr)
|
||||
, expect(nullptr)
|
||||
, vl2(nullptr)
|
||||
, vl1(nullptr)
|
||||
, topology(nullptr)
|
||||
, sa(nullptr)
|
||||
, ts(nullptr)
|
||||
{
|
||||
publicIdentityStr[0] = 0;
|
||||
secretIdentityStr[0] = 0;
|
||||
}
|
||||
|
||||
ZT_INLINE ~Context() noexcept
|
||||
{ Utils::burn(secretIdentityStr, sizeof(secretIdentityStr)); }
|
||||
{
|
||||
Utils::burn(secretIdentityStr, sizeof(secretIdentityStr));
|
||||
}
|
||||
|
||||
// Unique ID generated on startup
|
||||
const uint64_t instanceId;
|
||||
|
|
|
@ -11,15 +11,16 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Credential.hpp"
|
||||
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "OwnershipCredential.hpp"
|
||||
#include "RevocationCredential.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "Topology.hpp"
|
||||
|
||||
// These are compile-time asserts to make sure temporary marshal buffers here and
|
||||
|
@ -60,25 +61,43 @@ static ZT_INLINE Credential::VerifyResult p_credVerify(const Context &ctx, const
|
|||
int l = credential.marshal(tmp, true);
|
||||
if (l <= 0)
|
||||
return Credential::VERIFY_BAD_SIGNATURE;
|
||||
return (peer->identity().verify(tmp, (unsigned int)l, credential.signature(), credential.signatureLength()) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE);
|
||||
} catch (...) {}
|
||||
return (
|
||||
peer->identity().verify(tmp, (unsigned int)l, credential.signature(), credential.signatureLength())
|
||||
? Credential::VERIFY_OK
|
||||
: Credential::VERIFY_BAD_SIGNATURE);
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
return Credential::VERIFY_BAD_SIGNATURE;
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const RevocationCredential &credential)
|
||||
{ return p_credVerify(ctx, cc, credential); }
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const RevocationCredential& credential)
|
||||
{
|
||||
return p_credVerify(ctx, cc, credential);
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const TagCredential &credential)
|
||||
{ return p_credVerify(ctx, cc, credential); }
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const TagCredential& credential)
|
||||
{
|
||||
return p_credVerify(ctx, cc, credential);
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const CapabilityCredential &credential)
|
||||
{ return p_credVerify(ctx, cc, credential); }
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const CapabilityCredential& credential)
|
||||
{
|
||||
return p_credVerify(ctx, cc, credential);
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const OwnershipCredential &credential)
|
||||
{ return p_credVerify(ctx, cc, credential); }
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const OwnershipCredential& credential)
|
||||
{
|
||||
return p_credVerify(ctx, cc, credential);
|
||||
}
|
||||
|
||||
Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallContext &cc, const MembershipCredential &credential)
|
||||
Credential::VerifyResult
|
||||
Credential::s_verify(const Context& ctx, const CallContext& cc, const MembershipCredential& credential)
|
||||
{
|
||||
// Sanity check network ID.
|
||||
if ((! credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId)))
|
||||
|
@ -92,7 +111,9 @@ Credential::VerifyResult Credential::s_verify(const Context &ctx, const CallCont
|
|||
// Now verify the controller's signature.
|
||||
uint64_t buf[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX / 8];
|
||||
const unsigned int bufSize = credential.m_fillSigningBuf(buf);
|
||||
return peer->identity().verify(buf, bufSize, credential.m_signature, credential.m_signatureLength) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE;
|
||||
return peer->identity().verify(buf, bufSize, credential.m_signature, credential.m_signatureLength)
|
||||
? Credential::VERIFY_OK
|
||||
: Credential::VERIFY_BAD_SIGNATURE;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
#ifndef ZT_CREDENTIAL_HPP
|
||||
#define ZT_CREDENTIAL_HPP
|
||||
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "CallContext.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -35,18 +35,12 @@ class Context;
|
|||
* All credential verification methods are implemented in Credential.cpp as they share a lot
|
||||
* of common code and logic and grouping them makes auditing easier.
|
||||
*/
|
||||
class Credential : public TriviallyCopyable
|
||||
{
|
||||
class Credential : public TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Result of verify() operations
|
||||
*/
|
||||
enum VerifyResult
|
||||
{
|
||||
VERIFY_OK = 0,
|
||||
VERIFY_BAD_SIGNATURE = 1,
|
||||
VERIFY_NEED_IDENTITY = 2
|
||||
};
|
||||
enum VerifyResult { VERIFY_OK = 0, VERIFY_BAD_SIGNATURE = 1, VERIFY_NEED_IDENTITY = 2 };
|
||||
|
||||
protected:
|
||||
static VerifyResult s_verify(const Context& ctx, const CallContext& cc, const MembershipCredential& credential);
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
#ifndef ZT_DEFRAGMENTER_HPP
|
||||
#define ZT_DEFRAGMENTER_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -40,7 +40,8 @@ namespace ZeroTier {
|
|||
* the ones used throughout the ZeroTier core.
|
||||
*
|
||||
* @tparam MF Maximum number of fragments that each message can possess (default: ZT_MAX_PACKET_FRAGMENTS)
|
||||
* @tparam MFP Maximum number of incoming fragments per path (if paths are specified) (default: ZT_MAX_INCOMING_FRAGMENTS_PER_PATH)
|
||||
* @tparam MFP Maximum number of incoming fragments per path (if paths are specified) (default:
|
||||
* ZT_MAX_INCOMING_FRAGMENTS_PER_PATH)
|
||||
* @tparam GCS Garbage collection target size for the incoming message queue (default: ZT_MAX_PACKET_FRAGMENTS * 2)
|
||||
* @tparam GCT Garbage collection trigger threshold, usually 2X GCS (default: ZT_MAX_PACKET_FRAGMENTS * 4)
|
||||
* @tparam P Type for pointer to a path object (default: SharedPtr<Path>)
|
||||
|
@ -51,14 +52,12 @@ template<
|
|||
unsigned int GCS = (ZT_MAX_PACKET_FRAGMENTS * 2),
|
||||
unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4),
|
||||
typename P = SharedPtr<Path> >
|
||||
class Defragmenter
|
||||
{
|
||||
class Defragmenter {
|
||||
public:
|
||||
/**
|
||||
* Return values from assemble()
|
||||
*/
|
||||
enum ResultCode
|
||||
{
|
||||
enum ResultCode {
|
||||
/**
|
||||
* No error occurred, fragment accepted
|
||||
*/
|
||||
|
@ -97,7 +96,8 @@ public:
|
|||
};
|
||||
|
||||
ZT_INLINE Defragmenter()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a fragment of a multi-part message
|
||||
|
@ -177,7 +177,8 @@ public:
|
|||
ml.writing(); // acquire write lock on _messages
|
||||
for (unsigned long x = 0, y = (messagesByLastUsedTime.size() - GCS); x <= y; ++x)
|
||||
m_messages.erase(messagesByLastUsedTime[x].second);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
@ -190,11 +191,13 @@ public:
|
|||
ml.writing(); // acquire write lock on _messages if not already
|
||||
try {
|
||||
e = &(m_messages[messageId]);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
e->id = messageId;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
e = &(ee->second);
|
||||
}
|
||||
}
|
||||
|
@ -227,10 +230,12 @@ public:
|
|||
try {
|
||||
if (via->m_inboundFragmentedMessages.size() < MFP) {
|
||||
via->m_inboundFragmentedMessages.insert(messageId);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
tooManyPerPath = true;
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
// This would indicate something like bad_alloc thrown by the set. Treat
|
||||
// it as limit exceeded.
|
||||
tooManyPerPath = true;
|
||||
|
@ -298,24 +303,25 @@ public:
|
|||
|
||||
private:
|
||||
// p_E is an entry in the message queue.
|
||||
struct p_E
|
||||
struct p_E {
|
||||
ZT_INLINE p_E() noexcept
|
||||
: id(0)
|
||||
, lastUsed(0)
|
||||
, totalFragmentsExpected(0)
|
||||
, fragmentsReceived(0)
|
||||
{
|
||||
ZT_INLINE p_E() noexcept:
|
||||
id(0),
|
||||
lastUsed(0),
|
||||
totalFragmentsExpected(0),
|
||||
fragmentsReceived(0)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE p_E(const p_E &e) noexcept:
|
||||
id(e.id),
|
||||
lastUsed(e.lastUsed),
|
||||
totalFragmentsExpected(e.totalFragmentsExpected),
|
||||
fragmentsReceived(e.fragmentsReceived),
|
||||
via(e.via),
|
||||
message(e.message),
|
||||
lock()
|
||||
{}
|
||||
ZT_INLINE p_E(const p_E& e) noexcept
|
||||
: id(e.id)
|
||||
, lastUsed(e.lastUsed)
|
||||
, totalFragmentsExpected(e.totalFragmentsExpected)
|
||||
, fragmentsReceived(e.fragmentsReceived)
|
||||
, via(e.via)
|
||||
, message(e.message)
|
||||
, lock()
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~p_E()
|
||||
{
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
namespace ZeroTier {
|
||||
|
||||
Vector<uint8_t>& Dictionary::operator[](const char* const k)
|
||||
{ return m_entries[k]; }
|
||||
{
|
||||
return m_entries[k];
|
||||
}
|
||||
|
||||
const Vector<uint8_t>& Dictionary::operator[](const char* const k) const
|
||||
{
|
||||
|
@ -47,7 +49,8 @@ void Dictionary::add(const char *k, const void *data, unsigned int len)
|
|||
Vector<uint8_t>& e = (*this)[k];
|
||||
if (likely(len != 0)) {
|
||||
e.assign((const uint8_t*)data, (const uint8_t*)data + len);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
e.clear();
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +88,9 @@ char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const
|
|||
}
|
||||
|
||||
void Dictionary::clear()
|
||||
{ m_entries.clear(); }
|
||||
{
|
||||
m_entries.clear();
|
||||
}
|
||||
|
||||
void Dictionary::encode(Vector<uint8_t>& out) const
|
||||
{
|
||||
|
@ -127,24 +132,30 @@ bool Dictionary::decode(const void *data, unsigned int len)
|
|||
v->push_back(c);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (c == (uint8_t)'\n') {
|
||||
k.clear();
|
||||
v = nullptr;
|
||||
} else if (c == 92) { // backslash
|
||||
}
|
||||
else if (c == 92) { // backslash
|
||||
escape = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
v->push_back(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (c == (uint8_t)'=') {
|
||||
v = &m_entries[k];
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
k.push_back(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#ifndef ZT_DICTIONARY_HPP
|
||||
#define ZT_DICTIONARY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -37,16 +37,17 @@ class Identity;
|
|||
* The fastest way to build a dictionary to send is to use the append
|
||||
* static functions, not to populate and then encode a Dictionary.
|
||||
*/
|
||||
class Dictionary
|
||||
{
|
||||
class Dictionary {
|
||||
public:
|
||||
typedef SortedMap<String, Vector<uint8_t> >::const_iterator const_iterator;
|
||||
|
||||
ZT_INLINE Dictionary()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~Dictionary()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
ZT_INLINE void dump() const
|
||||
|
@ -95,13 +96,17 @@ public:
|
|||
* @return Start of key->value pairs
|
||||
*/
|
||||
ZT_INLINE const_iterator begin() const noexcept
|
||||
{ return m_entries.begin(); }
|
||||
{
|
||||
return m_entries.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return End of key->value pairs
|
||||
*/
|
||||
ZT_INLINE const_iterator end() const noexcept
|
||||
{ return m_entries.end(); }
|
||||
{
|
||||
return m_entries.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an integer as a hexadecimal string value
|
||||
|
@ -171,8 +176,7 @@ public:
|
|||
* @param obj Object to unmarshal() into
|
||||
* @return True if unmarshal was successful
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE bool getO(const char *k, T &obj) const
|
||||
template <typename T> ZT_INLINE bool getO(const char* k, T& obj) const
|
||||
{
|
||||
const Vector<uint8_t>& d = (*this)[k];
|
||||
if (d.empty())
|
||||
|
@ -188,8 +192,7 @@ public:
|
|||
* @param obj Object to marshal() into vector
|
||||
* @return True if successful
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE bool addO(const char *k, T &obj)
|
||||
template <typename T> ZT_INLINE bool addO(const char* k, T& obj)
|
||||
{
|
||||
Vector<uint8_t>& d = (*this)[k];
|
||||
d.resize(T::marshalSizeMax());
|
||||
|
@ -211,13 +214,17 @@ public:
|
|||
* @return Number of entries
|
||||
*/
|
||||
ZT_INLINE unsigned int size() const noexcept
|
||||
{ return (unsigned int)m_entries.size(); }
|
||||
{
|
||||
return (unsigned int)m_entries.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if dictionary is not empty
|
||||
*/
|
||||
ZT_INLINE bool empty() const noexcept
|
||||
{ return m_entries.empty(); }
|
||||
{
|
||||
return m_entries.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode to a string in the supplied vector
|
||||
|
@ -245,8 +252,7 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param v Value
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const bool v)
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const bool v)
|
||||
{
|
||||
s_appendKey(out, k);
|
||||
out.push_back((uint8_t)(v ? '1' : '0'));
|
||||
|
@ -260,8 +266,7 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param v Value
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const Address v)
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const Address v)
|
||||
{
|
||||
s_appendKey(out, k);
|
||||
const uint64_t a = v.toInt();
|
||||
|
@ -286,8 +291,7 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param v Value
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const uint64_t v)
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const uint64_t v)
|
||||
{
|
||||
s_appendKey(out, k);
|
||||
char buf[17];
|
||||
|
@ -298,33 +302,40 @@ public:
|
|||
out.push_back((uint8_t)'\n');
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const int64_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const int64_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const uint32_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const uint32_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const int32_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const int32_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const uint16_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const uint16_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const int16_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const int16_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const uint8_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const uint8_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const int8_t v)
|
||||
{ append(out, k, (uint64_t)v); }
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const int8_t v)
|
||||
{
|
||||
append(out, k, (uint64_t)v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a key=value pair to a buffer (vector or FCV)
|
||||
|
@ -333,8 +344,7 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param v Value
|
||||
*/
|
||||
template< typename V >
|
||||
ZT_INLINE static void append(V &out, const char *const k, const char *v)
|
||||
template <typename V> ZT_INLINE static void append(V& out, const char* const k, const char* v)
|
||||
{
|
||||
if ((v) && (*v)) {
|
||||
s_appendKey(out, k);
|
||||
|
@ -368,9 +378,10 @@ public:
|
|||
* @param k Key (must be <= 8 characters)
|
||||
* @param pid Packet ID
|
||||
*/
|
||||
template< typename V >
|
||||
static ZT_INLINE void appendPacketId(V &out, const char *const k, const uint64_t pid)
|
||||
{ append(out, k, &pid, 8); }
|
||||
template <typename V> static ZT_INLINE void appendPacketId(V& out, const char* const k, const uint64_t pid)
|
||||
{
|
||||
append(out, k, &pid, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append key=value with any object implementing the correct marshal interface
|
||||
|
@ -380,8 +391,7 @@ public:
|
|||
* @param v Marshal-able object
|
||||
* @return Bytes appended or negative on error (return value of marshal())
|
||||
*/
|
||||
template< typename V, typename T >
|
||||
static ZT_INLINE int appendObject(V &out, const char *const k, const T &v)
|
||||
template <typename V, typename T> static ZT_INLINE int appendObject(V& out, const char* const k, const T& v)
|
||||
{
|
||||
uint8_t tmp[2048]; // large enough for any current object
|
||||
if (T::marshalSizeMax() > sizeof(tmp))
|
||||
|
@ -403,8 +413,7 @@ public:
|
|||
static char* arraySubscript(char* buf, unsigned int bufSize, const char* name, const unsigned long sub) noexcept;
|
||||
|
||||
private:
|
||||
template< typename V >
|
||||
ZT_INLINE static void s_appendValueByte(V &out, const uint8_t c)
|
||||
template <typename V> ZT_INLINE static void s_appendValueByte(V& out, const uint8_t c)
|
||||
{
|
||||
switch (c) {
|
||||
case 0:
|
||||
|
@ -433,8 +442,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
template< typename V >
|
||||
ZT_INLINE static void s_appendKey(V &out, const char *k)
|
||||
template <typename V> ZT_INLINE static void s_appendKey(V& out, const char* k)
|
||||
{
|
||||
for (;;) {
|
||||
const char c = *(k++);
|
||||
|
|
106
core/ECC384.cpp
106
core/ECC384.cpp
|
@ -2,8 +2,9 @@
|
|||
// https://github.com/esxgx/easy-ecc
|
||||
// This code is under the BSD 2-clause license, not ZeroTier's license
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "ECC384.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -21,25 +22,43 @@ namespace {
|
|||
#define SUPPORTS_INT128 1
|
||||
#else
|
||||
#define SUPPORTS_INT128 0
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint64_t m_low;
|
||||
uint64_t m_high;
|
||||
} uint128_t;
|
||||
#endif
|
||||
|
||||
typedef struct EccPoint
|
||||
{
|
||||
typedef struct EccPoint {
|
||||
uint64_t x[NUM_ECC_DIGITS];
|
||||
uint64_t y[NUM_ECC_DIGITS];
|
||||
} EccPoint;
|
||||
|
||||
#define CONCAT1(a, b) a##b
|
||||
#define CONCAT(a, b) CONCAT1(a, b)
|
||||
#define Curve_P_48 {0x00000000FFFFFFFF, 0xFFFFFFFF00000000, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}
|
||||
#define Curve_B_48 {0x2A85C8EDD3EC2AEF, 0xC656398D8A2ED19D, 0x0314088F5013875A, 0x181D9C6EFE814112, 0x988E056BE3F82D19, 0xB3312FA7E23EE7E4}
|
||||
#define Curve_G_48 {{0x3A545E3872760AB7, 0x5502F25DBF55296C, 0x59F741E082542A38, 0x6E1D3B628BA79B98, 0x8EB1C71EF320AD74, 0xAA87CA22BE8B0537}, {0x7A431D7C90EA0E5F, 0x0A60B1CE1D7E819D, 0xE9DA3113B5F0B8C0, 0xF8F41DBD289A147C, 0x5D9E98BF9292DC29, 0x3617DE4A96262C6F}}
|
||||
#define Curve_N_48 {0xECEC196ACCC52973, 0x581A0DB248B0A77A, 0xC7634D81F4372DDF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}
|
||||
#define Curve_P_48 \
|
||||
{ \
|
||||
0x00000000FFFFFFFF, 0xFFFFFFFF00000000, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, \
|
||||
0xFFFFFFFFFFFFFFFF \
|
||||
}
|
||||
#define Curve_B_48 \
|
||||
{ \
|
||||
0x2A85C8EDD3EC2AEF, 0xC656398D8A2ED19D, 0x0314088F5013875A, 0x181D9C6EFE814112, 0x988E056BE3F82D19, \
|
||||
0xB3312FA7E23EE7E4 \
|
||||
}
|
||||
#define Curve_G_48 \
|
||||
{ \
|
||||
{ 0x3A545E3872760AB7, 0x5502F25DBF55296C, 0x59F741E082542A38, \
|
||||
0x6E1D3B628BA79B98, 0x8EB1C71EF320AD74, 0xAA87CA22BE8B0537 }, \
|
||||
{ \
|
||||
0x7A431D7C90EA0E5F, 0x0A60B1CE1D7E819D, 0xE9DA3113B5F0B8C0, 0xF8F41DBD289A147C, 0x5D9E98BF9292DC29, \
|
||||
0x3617DE4A96262C6F \
|
||||
} \
|
||||
}
|
||||
#define Curve_N_48 \
|
||||
{ \
|
||||
0xECEC196ACCC52973, 0x581A0DB248B0A77A, 0xC7634D81F4372DDF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, \
|
||||
0xFFFFFFFFFFFFFFFF \
|
||||
}
|
||||
const uint64_t curve_p[NUM_ECC_DIGITS] = CONCAT(Curve_P_, ECC_CURVE);
|
||||
const uint64_t curve_b[NUM_ECC_DIGITS] = CONCAT(Curve_B_, ECC_CURVE);
|
||||
const EccPoint curve_G = CONCAT(Curve_G_, ECC_CURVE);
|
||||
|
@ -52,7 +71,9 @@ ZT_INLINE int getRandomNumber(uint64_t *p_vli)
|
|||
}
|
||||
|
||||
ZT_INLINE void vli_clear(uint64_t* p_vli)
|
||||
{ Utils::zero< sizeof(uint64_t) * NUM_ECC_DIGITS >(p_vli); }
|
||||
{
|
||||
Utils::zero<sizeof(uint64_t) * NUM_ECC_DIGITS>(p_vli);
|
||||
}
|
||||
|
||||
ZT_INLINE int vli_isZero(const uint64_t* p_vli)
|
||||
{
|
||||
|
@ -65,7 +86,9 @@ ZT_INLINE int vli_isZero(const uint64_t *p_vli)
|
|||
}
|
||||
|
||||
ZT_INLINE uint64_t vli_testBit(const uint64_t* p_vli, uint p_bit)
|
||||
{ return (p_vli[p_bit / 64] & ((uint64_t)1 << (p_bit % 64))); }
|
||||
{
|
||||
return (p_vli[p_bit / 64] & ((uint64_t)1 << (p_bit % 64)));
|
||||
}
|
||||
|
||||
ZT_INLINE uint vli_numDigits(const uint64_t* p_vli)
|
||||
{
|
||||
|
@ -103,7 +126,8 @@ ZT_INLINE int vli_cmp(const uint64_t *p_left, const uint64_t *p_right)
|
|||
for (int i = NUM_ECC_DIGITS - 1; i >= 0; --i) {
|
||||
if (p_left[i] > p_right[i]) {
|
||||
return 1;
|
||||
} else if (p_left[i] < p_right[i]) {
|
||||
}
|
||||
else if (p_left[i] < p_right[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +435,8 @@ void vli_modInv(uint64_t *p_result, uint64_t *p_input, const uint64_t *p_mod)
|
|||
if (l_carry) {
|
||||
u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
|
||||
}
|
||||
} else if (vli_isEven(b)) {
|
||||
}
|
||||
else if (vli_isEven(b)) {
|
||||
vli_rshift1(b);
|
||||
if (! vli_isEven(v)) {
|
||||
l_carry = vli_add(v, v, p_mod);
|
||||
|
@ -420,7 +445,8 @@ void vli_modInv(uint64_t *p_result, uint64_t *p_input, const uint64_t *p_mod)
|
|||
if (l_carry) {
|
||||
v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
|
||||
}
|
||||
} else if (l_cmpResult > 0) {
|
||||
}
|
||||
else if (l_cmpResult > 0) {
|
||||
vli_sub(a, a, b);
|
||||
vli_rshift1(a);
|
||||
if (vli_cmp(u, v) < 0) {
|
||||
|
@ -434,7 +460,8 @@ void vli_modInv(uint64_t *p_result, uint64_t *p_input, const uint64_t *p_mod)
|
|||
if (l_carry) {
|
||||
u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
vli_sub(b, b, a);
|
||||
vli_rshift1(b);
|
||||
if (vli_cmp(v, u) < 0) {
|
||||
|
@ -455,7 +482,9 @@ void vli_modInv(uint64_t *p_result, uint64_t *p_input, const uint64_t *p_mod)
|
|||
}
|
||||
|
||||
ZT_INLINE int EccPoint_isZero(EccPoint* p_point)
|
||||
{ return (vli_isZero(p_point->x) && vli_isZero(p_point->y)); }
|
||||
{
|
||||
return (vli_isZero(p_point->x) && vli_isZero(p_point->y));
|
||||
}
|
||||
|
||||
void EccPoint_double_jacobian(uint64_t* X1, uint64_t* Y1, uint64_t* Z1)
|
||||
{
|
||||
|
@ -484,7 +513,8 @@ void EccPoint_double_jacobian(uint64_t *X1, uint64_t *Y1, uint64_t *Z1)
|
|||
uint64_t l_carry = vli_add(X1, X1, curve_p);
|
||||
vli_rshift1(X1);
|
||||
X1[NUM_ECC_DIGITS - 1] |= l_carry << 63U;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
vli_rshift1(X1);
|
||||
}
|
||||
/* t1 = 3/2*(x1^2 - z1^4) = B */
|
||||
|
@ -631,8 +661,9 @@ ZT_INLINE void ecc_bytes2native(uint64_t p_native[NUM_ECC_DIGITS], const uint8_t
|
|||
{
|
||||
for (uint i = 0; i < NUM_ECC_DIGITS; ++i) {
|
||||
const uint8_t* p_digit = p_bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
|
||||
p_native[i] = ((uint64_t)p_digit[0] << 56) | ((uint64_t)p_digit[1] << 48) | ((uint64_t)p_digit[2] << 40) | ((uint64_t)p_digit[3] << 32) |
|
||||
((uint64_t)p_digit[4] << 24) | ((uint64_t)p_digit[5] << 16) | ((uint64_t)p_digit[6] << 8) | (uint64_t)p_digit[7];
|
||||
p_native[i] = ((uint64_t)p_digit[0] << 56) | ((uint64_t)p_digit[1] << 48) | ((uint64_t)p_digit[2] << 40)
|
||||
| ((uint64_t)p_digit[3] << 32) | ((uint64_t)p_digit[4] << 24) | ((uint64_t)p_digit[5] << 16)
|
||||
| ((uint64_t)p_digit[6] << 8) | (uint64_t)p_digit[7];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,7 +741,10 @@ ZT_INLINE int ecc_make_key(uint8_t p_publicKey[ECC_BYTES + 1], uint8_t p_private
|
|||
return 1;
|
||||
}
|
||||
|
||||
ZT_INLINE int ecdh_shared_secret(const uint8_t p_publicKey[ECC_BYTES + 1], const uint8_t p_privateKey[ECC_BYTES], uint8_t p_secret[ECC_BYTES])
|
||||
ZT_INLINE int ecdh_shared_secret(
|
||||
const uint8_t p_publicKey[ECC_BYTES + 1],
|
||||
const uint8_t p_privateKey[ECC_BYTES],
|
||||
uint8_t p_secret[ECC_BYTES])
|
||||
{
|
||||
EccPoint l_public;
|
||||
uint64_t l_private[NUM_ECC_DIGITS];
|
||||
|
@ -744,7 +778,8 @@ void vli_modMult(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, const
|
|||
l_productBits = vli_numBits(l_product + NUM_ECC_DIGITS);
|
||||
if (l_productBits) {
|
||||
l_productBits += NUM_ECC_DIGITS * 64;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
l_productBits = vli_numBits(l_product);
|
||||
}
|
||||
|
||||
|
@ -761,7 +796,8 @@ void vli_modMult(uint64_t *p_result, uint64_t *p_left, uint64_t *p_right, const
|
|||
l_bitShift = (l_productBits - l_modBits) % 64;
|
||||
if (l_bitShift) {
|
||||
l_modMultiple[l_digitShift + NUM_ECC_DIGITS] = vli_lshift(l_modMultiple + l_digitShift, p_mod, l_bitShift);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
vli_set(l_modMultiple + l_digitShift, p_mod);
|
||||
}
|
||||
|
||||
|
@ -791,7 +827,8 @@ ZT_INLINE uint umax(uint a, uint b)
|
|||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
ZT_INLINE int ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_hash[ECC_BYTES], uint8_t p_signature[ECC_BYTES * 2])
|
||||
ZT_INLINE int
|
||||
ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_hash[ECC_BYTES], uint8_t p_signature[ECC_BYTES * 2])
|
||||
{
|
||||
uint64_t k[NUM_ECC_DIGITS];
|
||||
uint64_t l_tmp[NUM_ECC_DIGITS];
|
||||
|
@ -833,7 +870,10 @@ ZT_INLINE int ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_
|
|||
return 1;
|
||||
}
|
||||
|
||||
ZT_INLINE int ecdsa_verify(const uint8_t p_publicKey[ECC_BYTES + 1], const uint8_t p_hash[ECC_BYTES], const uint8_t p_signature[ECC_BYTES * 2])
|
||||
ZT_INLINE int ecdsa_verify(
|
||||
const uint8_t p_publicKey[ECC_BYTES + 1],
|
||||
const uint8_t p_hash[ECC_BYTES],
|
||||
const uint8_t p_signature[ECC_BYTES * 2])
|
||||
{
|
||||
uint64_t u1[NUM_ECC_DIGITS], u2[NUM_ECC_DIGITS];
|
||||
uint64_t z[NUM_ECC_DIGITS];
|
||||
|
@ -878,7 +918,8 @@ ZT_INLINE int ecdsa_verify(const uint8_t p_publicKey[ECC_BYTES + 1], const uint8
|
|||
const EccPoint* l_points[4] = { NULL, &curve_G, &l_public, &l_sum };
|
||||
uint l_numBits = umax(vli_numBits(u1), vli_numBits(u2));
|
||||
|
||||
const EccPoint *l_point = l_points[(!!vli_testBit(u1, l_numBits - 1)) | ((!!vli_testBit(u2, l_numBits - 1)) << 1)];
|
||||
const EccPoint* l_point =
|
||||
l_points[(! ! vli_testBit(u1, l_numBits - 1)) | ((! ! vli_testBit(u2, l_numBits - 1)) << 1)];
|
||||
vli_set(rx, l_point->x);
|
||||
vli_set(ry, l_point->y);
|
||||
vli_clear(z);
|
||||
|
@ -922,7 +963,10 @@ void ECC384GenerateKey(uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE], uint8_t priv[ZT_E
|
|||
}
|
||||
}
|
||||
|
||||
void ECC384ECDSASign(const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE], const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE], uint8_t sig[ZT_ECC384_SIGNATURE_SIZE])
|
||||
void ECC384ECDSASign(
|
||||
const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],
|
||||
const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],
|
||||
uint8_t sig[ZT_ECC384_SIGNATURE_SIZE])
|
||||
{
|
||||
if (! ecdsa_sign(priv, hash, sig)) {
|
||||
fprintf(stderr, "FATAL: ecdsa_sign() failed!" ZT_EOL_S);
|
||||
|
@ -930,12 +974,18 @@ void ECC384ECDSASign(const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE], const uint8
|
|||
}
|
||||
}
|
||||
|
||||
bool ECC384ECDSAVerify(const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE], const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE], const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE])
|
||||
bool ECC384ECDSAVerify(
|
||||
const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],
|
||||
const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],
|
||||
const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE])
|
||||
{
|
||||
return (ecdsa_verify(pub, hash, sig) != 0);
|
||||
}
|
||||
|
||||
bool ECC384ECDH(const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE], const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE], uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE])
|
||||
bool ECC384ECDH(
|
||||
const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE],
|
||||
const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE],
|
||||
uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE])
|
||||
{
|
||||
return (ecdh_shared_secret(theirPub, ourPriv, secret) != 0);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,10 @@ void ECC384GenerateKey(uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],uint8_t priv[ZT_EC
|
|||
* @param hash 48-byte hash
|
||||
* @param sig Buffer to receive signature
|
||||
*/
|
||||
void ECC384ECDSASign(const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
|
||||
void ECC384ECDSASign(
|
||||
const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],
|
||||
const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],
|
||||
uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
|
||||
|
||||
/**
|
||||
* Verify a signature
|
||||
|
@ -87,7 +90,10 @@ void ECC384ECDSASign(const uint8_t priv[ZT_ECC384_PRIVATE_KEY_SIZE],const uint8_
|
|||
* @param sig Signature to check
|
||||
* @return True if signature is valid
|
||||
*/
|
||||
bool ECC384ECDSAVerify(const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
|
||||
bool ECC384ECDSAVerify(
|
||||
const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],
|
||||
const uint8_t hash[ZT_ECC384_SIGNATURE_HASH_SIZE],
|
||||
const uint8_t sig[ZT_ECC384_SIGNATURE_SIZE]);
|
||||
|
||||
/**
|
||||
* Perform ECDH key agreement
|
||||
|
@ -99,7 +105,10 @@ bool ECC384ECDSAVerify(const uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_
|
|||
* @param ourPriv Local private key
|
||||
* @param secret Buffer to receive 48-byte secret
|
||||
*/
|
||||
bool ECC384ECDH(const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE],const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE],uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE]);
|
||||
bool ECC384ECDH(
|
||||
const uint8_t theirPub[ZT_ECC384_PUBLIC_KEY_SIZE],
|
||||
const uint8_t ourPriv[ZT_ECC384_PRIVATE_KEY_SIZE],
|
||||
uint8_t secret[ZT_ECC384_SHARED_SECRET_SIZE]);
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
/****/
|
||||
|
||||
#include "Endpoint.hpp"
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -19,30 +20,48 @@ namespace ZeroTier {
|
|||
static ZT_INLINE char s_endpointTypeChar(const ZT_EndpointType t)
|
||||
{
|
||||
switch (t) {
|
||||
default: return '0';
|
||||
case ZT_ENDPOINT_TYPE_ZEROTIER: return 'z';
|
||||
case ZT_ENDPOINT_TYPE_ETHERNET: return 'e';
|
||||
case ZT_ENDPOINT_TYPE_WIFI_DIRECT: return 'd';
|
||||
case ZT_ENDPOINT_TYPE_BLUETOOTH: return 'b';
|
||||
case ZT_ENDPOINT_TYPE_IP: return 'i';
|
||||
case ZT_ENDPOINT_TYPE_IP_UDP: return 'u';
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP: return 't';
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP_WS: return 'w';
|
||||
default:
|
||||
return '0';
|
||||
case ZT_ENDPOINT_TYPE_ZEROTIER:
|
||||
return 'z';
|
||||
case ZT_ENDPOINT_TYPE_ETHERNET:
|
||||
return 'e';
|
||||
case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
|
||||
return 'd';
|
||||
case ZT_ENDPOINT_TYPE_BLUETOOTH:
|
||||
return 'b';
|
||||
case ZT_ENDPOINT_TYPE_IP:
|
||||
return 'i';
|
||||
case ZT_ENDPOINT_TYPE_IP_UDP:
|
||||
return 'u';
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP:
|
||||
return 't';
|
||||
case ZT_ENDPOINT_TYPE_IP_TCP_WS:
|
||||
return 'w';
|
||||
}
|
||||
}
|
||||
|
||||
static ZT_INLINE ZT_EndpointType s_charEndpointType(const char c)
|
||||
{
|
||||
switch (c) {
|
||||
default: return ZT_ENDPOINT_TYPE_NIL;
|
||||
case 'z': return ZT_ENDPOINT_TYPE_ZEROTIER;
|
||||
case 'e': return ZT_ENDPOINT_TYPE_ETHERNET;
|
||||
case 'd': return ZT_ENDPOINT_TYPE_WIFI_DIRECT;
|
||||
case 'b': return ZT_ENDPOINT_TYPE_BLUETOOTH;
|
||||
case 'i': return ZT_ENDPOINT_TYPE_IP;
|
||||
case 'u': return ZT_ENDPOINT_TYPE_IP_UDP;
|
||||
case 't': return ZT_ENDPOINT_TYPE_IP_TCP;
|
||||
case 'w': return ZT_ENDPOINT_TYPE_IP_TCP_WS;
|
||||
default:
|
||||
return ZT_ENDPOINT_TYPE_NIL;
|
||||
case 'z':
|
||||
return ZT_ENDPOINT_TYPE_ZEROTIER;
|
||||
case 'e':
|
||||
return ZT_ENDPOINT_TYPE_ETHERNET;
|
||||
case 'd':
|
||||
return ZT_ENDPOINT_TYPE_WIFI_DIRECT;
|
||||
case 'b':
|
||||
return ZT_ENDPOINT_TYPE_BLUETOOTH;
|
||||
case 'i':
|
||||
return ZT_ENDPOINT_TYPE_IP;
|
||||
case 'u':
|
||||
return ZT_ENDPOINT_TYPE_IP_UDP;
|
||||
case 't':
|
||||
return ZT_ENDPOINT_TYPE_IP_TCP;
|
||||
case 'w':
|
||||
return ZT_ENDPOINT_TYPE_IP_TCP_WS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +103,8 @@ bool Endpoint::fromString(const char *s) noexcept
|
|||
if ((! s) || (! *s)) {
|
||||
// Empty strings are considered NIL endpoints.
|
||||
return true;
|
||||
} else if (s[1] == '/') {
|
||||
}
|
||||
else if (s[1] == '/') {
|
||||
// type/ADDRESS is a fully qualified endpoint.
|
||||
this->type = s_charEndpointType(s[0]);
|
||||
switch (this->type) {
|
||||
|
@ -113,7 +133,8 @@ bool Endpoint::fromString(const char *s) noexcept
|
|||
return false;
|
||||
} break;
|
||||
}
|
||||
} else if (strchr(s, '/') != nullptr) {
|
||||
}
|
||||
else if (strchr(s, '/') != nullptr) {
|
||||
// IP/port is parsed as an IP_UDP endpoint for backward compatibility.
|
||||
this->type = ZT_ENDPOINT_TYPE_IP_UDP;
|
||||
return asInetAddress(this->value.ss).fromString(s);
|
||||
|
|
|
@ -14,24 +14,32 @@
|
|||
#ifndef ZT_ENDPOINT_HPP
|
||||
#define ZT_ENDPOINT_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_ENDPOINT_STRING_SIZE_MAX 256
|
||||
#define ZT_ENDPOINT_MARSHAL_SIZE_MAX 192
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > ZT_INETADDRESS_MARSHAL_SIZE_MAX, "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(ZT_Fingerprint), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(InetAddress), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert(
|
||||
(ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > ZT_INETADDRESS_MARSHAL_SIZE_MAX,
|
||||
"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert(
|
||||
(ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(ZT_Fingerprint),
|
||||
"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert(
|
||||
(ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(InetAddress),
|
||||
"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(MAC), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(Fingerprint), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
static_assert(
|
||||
(ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(Fingerprint),
|
||||
"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
||||
|
||||
/**
|
||||
* Endpoint variant specifying some form of network endpoint.
|
||||
|
@ -42,17 +50,22 @@ static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(Fingerprint), "ZT_ENDP
|
|||
* where InetAddress was used as long as only the UDP type is exchanged
|
||||
* with those nodes.
|
||||
*/
|
||||
class Endpoint : public ZT_Endpoint, public TriviallyCopyable
|
||||
{
|
||||
class Endpoint
|
||||
: public ZT_Endpoint
|
||||
, public TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Create a NIL/empty endpoint
|
||||
*/
|
||||
ZT_INLINE Endpoint() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE Endpoint(const ZT_Endpoint& ep) noexcept
|
||||
{ Utils::copy< sizeof(ZT_Endpoint) >((ZT_Endpoint *)this, &ep); }
|
||||
{
|
||||
Utils::copy<sizeof(ZT_Endpoint)>((ZT_Endpoint*)this, &ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an endpoint for a type that uses an IP
|
||||
|
@ -65,7 +78,8 @@ public:
|
|||
if (inaddr) {
|
||||
this->type = et;
|
||||
Utils::copy<sizeof(struct sockaddr_storage)>(&(this->value.ss), &(inaddr.as.ss));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
memoryZero(this);
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +94,8 @@ public:
|
|||
if (zt_) {
|
||||
this->type = ZT_ENDPOINT_TYPE_ZEROTIER;
|
||||
this->value.fp = zt_;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
memoryZero(this);
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +111,8 @@ public:
|
|||
if (eth_) {
|
||||
this->type = et;
|
||||
this->value.mac = eth_.toInt();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
memoryZero(this);
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +121,9 @@ public:
|
|||
* @return True if endpoint type isn't NIL
|
||||
*/
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return this->type != ZT_ENDPOINT_TYPE_NIL; }
|
||||
{
|
||||
return this->type != ZT_ENDPOINT_TYPE_NIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this endpoint type has an InetAddress address type and thus ip() is valid
|
||||
|
@ -161,7 +179,9 @@ public:
|
|||
* @return InetAddress instance
|
||||
*/
|
||||
ZT_INLINE const InetAddress& ip() const noexcept
|
||||
{ return asInetAddress(this->value.ss); }
|
||||
{
|
||||
return asInetAddress(this->value.ss);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MAC if this is an Ethernet, WiFi direct, or Bluetooth type (undefined otherwise)
|
||||
|
@ -169,7 +189,9 @@ public:
|
|||
* @return Ethernet MAC
|
||||
*/
|
||||
ZT_INLINE MAC eth() const noexcept
|
||||
{ return MAC(this->value.mac); }
|
||||
{
|
||||
return MAC(this->value.mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fingerprint if this is a ZeroTier endpoint type (undefined otherwise)
|
||||
|
@ -177,7 +199,9 @@ public:
|
|||
* @return ZeroTier fingerprint
|
||||
*/
|
||||
ZT_INLINE Fingerprint zt() const noexcept
|
||||
{ return Fingerprint(this->value.fp); }
|
||||
{
|
||||
return Fingerprint(this->value.fp);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{
|
||||
|
@ -209,7 +233,9 @@ public:
|
|||
bool fromString(const char* s) noexcept;
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_ENDPOINT_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept;
|
||||
|
||||
|
@ -218,18 +244,26 @@ public:
|
|||
bool operator==(const Endpoint& ep) const noexcept;
|
||||
|
||||
ZT_INLINE bool operator!=(const Endpoint& ep) const noexcept
|
||||
{ return !((*this) == ep); }
|
||||
{
|
||||
return ! ((*this) == ep);
|
||||
}
|
||||
|
||||
bool operator<(const Endpoint& ep) const noexcept;
|
||||
|
||||
ZT_INLINE bool operator>(const Endpoint& ep) const noexcept
|
||||
{ return (ep < *this); }
|
||||
{
|
||||
return (ep < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Endpoint& ep) const noexcept
|
||||
{ return !(ep < *this); }
|
||||
{
|
||||
return ! (ep < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Endpoint& ep) const noexcept
|
||||
{ return !(*this < ep); }
|
||||
{
|
||||
return ! (*this < ep);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Endpoint) == sizeof(ZT_Endpoint), "size mismatch");
|
||||
|
|
|
@ -36,12 +36,11 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Tracker for expected OK replies to packet IDs of sent packets
|
||||
*/
|
||||
class Expect
|
||||
{
|
||||
class Expect {
|
||||
public:
|
||||
ZT_INLINE Expect() :
|
||||
m_packetIdSent()
|
||||
{}
|
||||
ZT_INLINE Expect() : m_packetIdSent()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by other code when something is sending a packet that could potentially receive an OK response
|
||||
|
@ -50,7 +49,10 @@ public:
|
|||
* @param now Current time
|
||||
*/
|
||||
ZT_INLINE void sending(const uint64_t packetId, const int64_t now) noexcept
|
||||
{ m_packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS] = (uint32_t)(now / ZT_EXPECT_TTL); }
|
||||
{
|
||||
m_packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS] =
|
||||
(uint32_t)(now / ZT_EXPECT_TTL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an OK is expected and if so reset the corresponding bucket.
|
||||
|
@ -64,7 +66,14 @@ public:
|
|||
* @return True if we're expecting a reply (and a reset occurred)
|
||||
*/
|
||||
ZT_INLINE bool expecting(const uint64_t inRePacketId, const int64_t now) noexcept
|
||||
{ return (((now / ZT_EXPECT_TTL) - (int64_t)m_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].exchange(0)) <= 1); }
|
||||
{
|
||||
return (
|
||||
((now / ZT_EXPECT_TTL)
|
||||
- (int64_t)
|
||||
m_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS]
|
||||
.exchange(0))
|
||||
<= 1);
|
||||
}
|
||||
|
||||
private:
|
||||
// Each bucket contains a timestamp in units of the max expect duration.
|
||||
|
|
99
core/FCV.hpp
99
core/FCV.hpp
|
@ -16,8 +16,8 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
|
@ -32,30 +32,28 @@ namespace ZeroTier {
|
|||
* @tparam T Type to contain
|
||||
* @tparam C Maximum capacity of vector
|
||||
*/
|
||||
template< typename T, unsigned int C >
|
||||
class FCV
|
||||
{
|
||||
template <typename T, unsigned int C> class FCV {
|
||||
public:
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
ZT_INLINE FCV() noexcept : _s(0)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE FCV(const FCV& v) : _s(0)
|
||||
{ *this = v; }
|
||||
{
|
||||
*this = v;
|
||||
}
|
||||
|
||||
ZT_INLINE FCV(const T *const contents, const unsigned int len) :
|
||||
_s(len)
|
||||
ZT_INLINE FCV(const T* const contents, const unsigned int len) : _s(len)
|
||||
{
|
||||
const unsigned int l = std::min(len, C);
|
||||
for (unsigned int i = 0; i < l; ++i)
|
||||
new (reinterpret_cast<T*>(_m) + i) T(contents[i]);
|
||||
}
|
||||
|
||||
template< typename I >
|
||||
ZT_INLINE FCV(I i, I end) :
|
||||
_s(0)
|
||||
template <typename I> ZT_INLINE FCV(I i, I end) : _s(0)
|
||||
{
|
||||
while (i != end) {
|
||||
push_back(*i);
|
||||
|
@ -64,7 +62,9 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE ~FCV()
|
||||
{ this->clear(); }
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
ZT_INLINE FCV& operator=(const FCV& v)
|
||||
{
|
||||
|
@ -101,16 +101,24 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE iterator begin() noexcept
|
||||
{ return reinterpret_cast<T *>(_m); }
|
||||
{
|
||||
return reinterpret_cast<T*>(_m);
|
||||
}
|
||||
|
||||
ZT_INLINE iterator end() noexcept
|
||||
{ return reinterpret_cast<T *>(_m) + _s; }
|
||||
{
|
||||
return reinterpret_cast<T*>(_m) + _s;
|
||||
}
|
||||
|
||||
ZT_INLINE const_iterator begin() const noexcept
|
||||
{ return reinterpret_cast<const T *>(_m); }
|
||||
{
|
||||
return reinterpret_cast<const T*>(_m);
|
||||
}
|
||||
|
||||
ZT_INLINE const_iterator end() const noexcept
|
||||
{ return reinterpret_cast<const T *>(_m) + _s; }
|
||||
{
|
||||
return reinterpret_cast<const T*>(_m) + _s;
|
||||
}
|
||||
|
||||
ZT_INLINE T& operator[](const unsigned int i)
|
||||
{
|
||||
|
@ -127,19 +135,29 @@ public:
|
|||
}
|
||||
|
||||
static constexpr unsigned int capacity() noexcept
|
||||
{ return C; }
|
||||
{
|
||||
return C;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int size() const noexcept
|
||||
{ return _s; }
|
||||
{
|
||||
return _s;
|
||||
}
|
||||
|
||||
ZT_INLINE bool empty() const noexcept
|
||||
{ return (_s == 0); }
|
||||
{
|
||||
return (_s == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE T* data() noexcept
|
||||
{ return reinterpret_cast<T *>(_m); }
|
||||
{
|
||||
return reinterpret_cast<T*>(_m);
|
||||
}
|
||||
|
||||
ZT_INLINE const T* data() const noexcept
|
||||
{ return reinterpret_cast<const T *>(_m); }
|
||||
{
|
||||
return reinterpret_cast<const T*>(_m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a value onto the back of this vector
|
||||
|
@ -152,7 +170,8 @@ public:
|
|||
{
|
||||
if (likely(_s < C))
|
||||
new (reinterpret_cast<T*>(_m) + _s++) T(v);
|
||||
else throw Utils::OutOfRangeException;
|
||||
else
|
||||
throw Utils::OutOfRangeException;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,7 +183,8 @@ public:
|
|||
{
|
||||
if (likely(_s < C)) {
|
||||
return *(new (reinterpret_cast<T*>(_m) + _s++) T());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return *(reinterpret_cast<T*>(_m) + (C - 1));
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +198,8 @@ public:
|
|||
{
|
||||
if (likely(_s < C)) {
|
||||
return *(new (reinterpret_cast<T*>(_m) + _s++) T(v));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
T& tmp = *(reinterpret_cast<T*>(_m) + (C - 1));
|
||||
tmp = v;
|
||||
return tmp;
|
||||
|
@ -217,7 +238,9 @@ public:
|
|||
* @param ns New size
|
||||
*/
|
||||
ZT_INLINE void unsafeSetSize(unsigned int ns)
|
||||
{ _s = ns; }
|
||||
{
|
||||
_s = ns;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a bounds checked auto-resizing variant of the [] operator
|
||||
|
@ -249,15 +272,15 @@ public:
|
|||
* @param start Starting iterator
|
||||
* @param end Ending iterator (must be greater than start)
|
||||
*/
|
||||
template< typename X >
|
||||
ZT_INLINE void assign(X start, const X &end)
|
||||
template <typename X> ZT_INLINE void assign(X start, const X& end)
|
||||
{
|
||||
const int l = std::min((int)std::distance(start, end), (int)C);
|
||||
if (l > 0) {
|
||||
this->resize((unsigned int)l);
|
||||
for (int i = 0; i < l; ++i)
|
||||
reinterpret_cast<T*>(_m)[i] = *(start++);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this->clear();
|
||||
}
|
||||
}
|
||||
|
@ -275,19 +298,29 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const FCV& v) const noexcept
|
||||
{ return *this != v; }
|
||||
{
|
||||
return *this != v;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const FCV& v) const noexcept
|
||||
{ return std::lexicographical_compare(begin(), end(), v.begin(), v.end()); }
|
||||
{
|
||||
return std::lexicographical_compare(begin(), end(), v.begin(), v.end());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const FCV& v) const noexcept
|
||||
{ return (v < *this); }
|
||||
{
|
||||
return (v < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const FCV& v) const noexcept
|
||||
{ return v >= *this; }
|
||||
{
|
||||
return v >= *this;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const FCV& v) const noexcept
|
||||
{ return *this >= v; }
|
||||
{
|
||||
return *this >= v;
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
#ifndef ZT_FINGERPRINT_HPP
|
||||
#define ZT_FINGERPRINT_HPP
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_FINGERPRINT_STRING_SIZE_MAX 128
|
||||
|
@ -30,20 +30,27 @@ namespace ZeroTier {
|
|||
* This is the same size as ZT_Fingerprint and should be cast-able back and forth.
|
||||
* This is checked in Tests.cpp.
|
||||
*/
|
||||
class Fingerprint : public ZT_Fingerprint, public TriviallyCopyable
|
||||
{
|
||||
class Fingerprint
|
||||
: public ZT_Fingerprint
|
||||
, public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE Fingerprint() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE Fingerprint(const ZT_Fingerprint& fp) noexcept
|
||||
{ Utils::copy< sizeof(ZT_Fingerprint) >(this, &fp); }
|
||||
{
|
||||
Utils::copy<sizeof(ZT_Fingerprint)>(this, &fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if hash is not all zero (missing/unspecified)
|
||||
*/
|
||||
ZT_INLINE bool haveHash() const noexcept
|
||||
{ return (!Utils::allZero(this->hash, ZT_FINGERPRINT_HASH_SIZE)); }
|
||||
{
|
||||
return (! Utils::allZero(this->hash, ZT_FINGERPRINT_HASH_SIZE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a base32-encoded representation of this fingerprint
|
||||
|
@ -55,7 +62,11 @@ public:
|
|||
Address(this->address).toString(s);
|
||||
if (haveHash()) {
|
||||
s[ZT_ADDRESS_LENGTH_HEX] = '-';
|
||||
Utils::b32e(this->hash, ZT_FINGERPRINT_HASH_SIZE, s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_FINGERPRINT_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
Utils::b32e(
|
||||
this->hash,
|
||||
ZT_FINGERPRINT_HASH_SIZE,
|
||||
s + (ZT_ADDRESS_LENGTH_HEX + 1),
|
||||
ZT_FINGERPRINT_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -84,25 +95,35 @@ public:
|
|||
a[ZT_ADDRESS_LENGTH_HEX] = 0;
|
||||
this->address = Utils::hexStrToU64(a) & ZT_ADDRESS_MASK;
|
||||
if (l > (ZT_ADDRESS_LENGTH_HEX + 1)) {
|
||||
if (Utils::b32d(s + (ZT_ADDRESS_LENGTH_HEX + 1), this->hash, ZT_FINGERPRINT_HASH_SIZE) != ZT_FINGERPRINT_HASH_SIZE)
|
||||
if (Utils::b32d(s + (ZT_ADDRESS_LENGTH_HEX + 1), this->hash, ZT_FINGERPRINT_HASH_SIZE)
|
||||
!= ZT_FINGERPRINT_HASH_SIZE)
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Utils::zero<ZT_FINGERPRINT_HASH_SIZE>(this->hash);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ZT_INLINE void zero() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)this->address; }
|
||||
{
|
||||
return (unsigned long)this->address;
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return this->address != 0; }
|
||||
{
|
||||
return this->address != 0;
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_FINGERPRINT_MARSHAL_SIZE; }
|
||||
{
|
||||
return ZT_FINGERPRINT_MARSHAL_SIZE;
|
||||
}
|
||||
|
||||
ZT_INLINE int marshal(uint8_t data[ZT_FINGERPRINT_MARSHAL_SIZE]) const noexcept
|
||||
{
|
||||
|
@ -121,22 +142,36 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE bool operator==(const ZT_Fingerprint& h) const noexcept
|
||||
{ return ((this->address == h.address) && (memcmp(this->hash, h.hash, ZT_FINGERPRINT_HASH_SIZE) == 0)); }
|
||||
{
|
||||
return ((this->address == h.address) && (memcmp(this->hash, h.hash, ZT_FINGERPRINT_HASH_SIZE) == 0));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const ZT_Fingerprint& h) const noexcept
|
||||
{ return !(*this == h); }
|
||||
{
|
||||
return ! (*this == h);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const ZT_Fingerprint& h) const noexcept
|
||||
{ return ((this->address < h.address) || ((this->address == h.address) && (memcmp(this->hash, h.hash, ZT_FINGERPRINT_HASH_SIZE) < 0))); }
|
||||
{
|
||||
return (
|
||||
(this->address < h.address)
|
||||
|| ((this->address == h.address) && (memcmp(this->hash, h.hash, ZT_FINGERPRINT_HASH_SIZE) < 0)));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const ZT_Fingerprint& h) const noexcept
|
||||
{ return (*reinterpret_cast<const Fingerprint *>(&h) < *this); }
|
||||
{
|
||||
return (*reinterpret_cast<const Fingerprint*>(&h) < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const ZT_Fingerprint& h) const noexcept
|
||||
{ return !(*reinterpret_cast<const Fingerprint *>(&h) < *this); }
|
||||
{
|
||||
return ! (*reinterpret_cast<const Fingerprint*>(&h) < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const ZT_Fingerprint& h) const noexcept
|
||||
{ return !(*this < h); }
|
||||
{
|
||||
return ! (*this < h);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Fingerprint) == sizeof(ZT_Fingerprint), "size mismatch");
|
||||
|
|
|
@ -11,13 +11,14 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Identity.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "MIMC52.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "MIMC52.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
@ -29,7 +30,10 @@ namespace {
|
|||
// This is the memory-intensive hash function used to compute v0 identities from v0 public keys.
|
||||
#define ZT_V0_IDENTITY_GEN_MEMORY 2097152
|
||||
|
||||
void identityV0ProofOfWorkFrankenhash(const void *const restrict c25519CombinedPublicKey, void *const restrict digest, void *const restrict genmem) noexcept
|
||||
void identityV0ProofOfWorkFrankenhash(
|
||||
const void* const restrict c25519CombinedPublicKey,
|
||||
void* const restrict digest,
|
||||
void* const restrict genmem) noexcept
|
||||
{
|
||||
// Digest publicKey[] to obtain initial digest
|
||||
SHA512(digest, c25519CombinedPublicKey, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE);
|
||||
|
@ -56,7 +60,8 @@ void identityV0ProofOfWorkFrankenhash(const void *const restrict c25519CombinedP
|
|||
// Render final digest using genmem as a lookup table
|
||||
for (unsigned long i = 0; i < (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t));) {
|
||||
unsigned long idx1 = (unsigned long)(Utils::ntoh(((uint64_t*)genmem)[i++]) % (64 / sizeof(uint64_t)));
|
||||
unsigned long idx2 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t)));
|
||||
unsigned long idx2 =
|
||||
(unsigned long)(Utils::ntoh(((uint64_t*)genmem)[i++]) % (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t)));
|
||||
uint64_t tmp = ((uint64_t*)genmem)[idx2];
|
||||
((uint64_t*)genmem)[idx2] = ((uint64_t*)digest)[idx1];
|
||||
((uint64_t*)digest)[idx1] = tmp;
|
||||
|
@ -64,10 +69,12 @@ void identityV0ProofOfWorkFrankenhash(const void *const restrict c25519CombinedP
|
|||
}
|
||||
}
|
||||
|
||||
struct identityV0ProofOfWorkCriteria
|
||||
struct identityV0ProofOfWorkCriteria {
|
||||
ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char* restrict sb, char* restrict gm) noexcept
|
||||
: digest(sb)
|
||||
, genmem(gm)
|
||||
{
|
||||
ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *restrict sb, char *restrict gm) noexcept: digest(sb), genmem(gm)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE]) const noexcept
|
||||
{
|
||||
|
@ -108,7 +115,6 @@ bool Identity::generate(const Type t)
|
|||
m_hasPrivate = true;
|
||||
|
||||
switch (t) {
|
||||
|
||||
case C25519: {
|
||||
// Generate C25519/Ed25519 key pair whose hash satisfies a "hashcash" criterion and generate the
|
||||
// address from the last 40 bits of this hash. This is different from the fingerprint hash for V0.
|
||||
|
@ -122,17 +128,19 @@ bool Identity::generate(const Type t)
|
|||
delete[] genmem;
|
||||
m_fp.address = address; // address comes from PoW hash for type 0 identities
|
||||
m_computeHash();
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case P384:
|
||||
for (;;) {
|
||||
C25519::generateCombined(m_pub + 7, m_priv);
|
||||
ECC384GenerateKey(m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
ECC384GenerateKey(
|
||||
m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,
|
||||
m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
|
||||
uint64_t challenge[4];
|
||||
v1ChallengeFromPub(m_pub, challenge);
|
||||
const uint64_t proof = MIMC52::delay(reinterpret_cast<const uint8_t *>(challenge), ZT_IDENTITY_TYPE1_MIMC52_ROUNDS);
|
||||
const uint64_t proof =
|
||||
MIMC52::delay(reinterpret_cast<const uint8_t*>(challenge), ZT_IDENTITY_TYPE1_MIMC52_ROUNDS);
|
||||
m_pub[0] = (uint8_t)(proof >> 48U);
|
||||
m_pub[1] = (uint8_t)(proof >> 40U);
|
||||
m_pub[2] = (uint8_t)(proof >> 32U);
|
||||
|
@ -162,7 +170,6 @@ bool Identity::locallyValidate() const noexcept
|
|||
try {
|
||||
if ((m_fp) && ((! Address(m_fp.address).isReserved()))) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519: {
|
||||
uint8_t digest[64];
|
||||
char* const genmem = (char*)malloc(ZT_V0_IDENTITY_GEN_MEMORY);
|
||||
|
@ -177,13 +184,19 @@ bool Identity::locallyValidate() const noexcept
|
|||
if (Address(m_fp.hash) == m_fp.address) {
|
||||
uint64_t challenge[4];
|
||||
v1ChallengeFromPub(m_pub, challenge);
|
||||
return MIMC52::verify(reinterpret_cast<const uint8_t *>(challenge), ZT_IDENTITY_TYPE1_MIMC52_ROUNDS, ((uint64_t)m_pub[0] << 48U) | ((uint64_t)m_pub[1] << 40U) | ((uint64_t)m_pub[2] << 32U) | ((uint64_t)m_pub[3] << 24U) | ((uint64_t)m_pub[4] << 16U) | ((uint64_t)m_pub[5] << 8U) | (uint64_t)m_pub[6]);
|
||||
return MIMC52::verify(
|
||||
reinterpret_cast<const uint8_t*>(challenge),
|
||||
ZT_IDENTITY_TYPE1_MIMC52_ROUNDS,
|
||||
((uint64_t)m_pub[0] << 48U) | ((uint64_t)m_pub[1] << 40U) | ((uint64_t)m_pub[2] << 32U)
|
||||
| ((uint64_t)m_pub[3] << 24U) | ((uint64_t)m_pub[4] << 16U) | ((uint64_t)m_pub[5] << 8U)
|
||||
| (uint64_t)m_pub[6]);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -191,7 +204,6 @@ void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
|||
{
|
||||
if (m_hasPrivate) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
SHA384(h, m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||
return;
|
||||
|
@ -199,7 +211,6 @@ void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
|||
case P384:
|
||||
SHA384(h, m_pub, sizeof(m_pub), m_priv, sizeof(m_priv));
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
Utils::zero<ZT_FINGERPRINT_HASH_SIZE>(h);
|
||||
|
@ -209,7 +220,6 @@ unsigned int Identity::sign(const void *data, unsigned int len, void *sig, unsig
|
|||
{
|
||||
if (m_hasPrivate) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
|
||||
C25519::sign(m_priv, m_pub, data, len, sig);
|
||||
|
@ -226,7 +236,6 @@ unsigned int Identity::sign(const void *data, unsigned int len, void *sig, unsig
|
|||
return ZT_ECC384_SIGNATURE_SIZE;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -235,7 +244,6 @@ unsigned int Identity::sign(const void *data, unsigned int len, void *sig, unsig
|
|||
bool Identity::verify(const void* data, unsigned int len, const void* sig, unsigned int siglen) const
|
||||
{
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
return C25519::verify(m_pub, data, len, sig, siglen);
|
||||
|
||||
|
@ -246,7 +254,6 @@ bool Identity::verify(const void *data, unsigned int len, const void *sig, unsig
|
|||
return ECC384ECDSAVerify(m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, h, (const uint8_t*)sig);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -262,14 +269,18 @@ bool Identity::agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) con
|
|||
SHA512(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key, h);
|
||||
return true;
|
||||
} else if ((m_type == P384) && (id.m_type == P384)) {
|
||||
}
|
||||
else if ((m_type == P384) && (id.m_type == P384)) {
|
||||
// For another P384 identity we execute DH agreement with BOTH keys and then
|
||||
// hash the results together. For those (cough FIPS cough) who only consider
|
||||
// P384 to be kosher, the C25519 secret can be considered a "salt"
|
||||
// or something. For those who don't trust P384 this means the privacy of
|
||||
// your traffic is also protected by C25519.
|
||||
C25519::agree(m_priv, id.m_pub, rawkey);
|
||||
ECC384ECDH(id.m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
ECC384ECDH(
|
||||
id.m_pub + 7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,
|
||||
m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE,
|
||||
rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||
SHA384(key, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE + ZT_ECC384_SHARED_SECRET_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
@ -301,13 +312,20 @@ char *Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER
|
|||
case P384: {
|
||||
*(p++) = '1';
|
||||
*(p++) = ':';
|
||||
int el = Utils::b32e(m_pub, sizeof(m_pub), p, (int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0) return nullptr;
|
||||
int el =
|
||||
Utils::b32e(m_pub, sizeof(m_pub), p, (int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0)
|
||||
return nullptr;
|
||||
p += el;
|
||||
if ((m_hasPrivate) && (includePrivate)) {
|
||||
*(p++) = ':';
|
||||
el = Utils::b32e(m_priv, sizeof(m_priv), p, (int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0) return nullptr;
|
||||
el = Utils::b32e(
|
||||
m_priv,
|
||||
sizeof(m_priv),
|
||||
p,
|
||||
(int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
||||
if (el <= 0)
|
||||
return nullptr;
|
||||
p += el;
|
||||
}
|
||||
*p = (char)0;
|
||||
|
@ -331,7 +349,6 @@ bool Identity::fromString(const char *str)
|
|||
char* saveptr = nullptr;
|
||||
for (char* f = Utils::stok(tmp, ":", &saveptr); ((f) && (fno < 4)); f = Utils::stok(nullptr, ":", &saveptr)) {
|
||||
switch (fno++) {
|
||||
|
||||
case 0:
|
||||
m_fp.address = Utils::hexStrToU64(f) & ZT_ADDRESS_MASK;
|
||||
if (Address(m_fp.address).isReserved())
|
||||
|
@ -341,18 +358,20 @@ bool Identity::fromString(const char *str)
|
|||
case 1:
|
||||
if ((f[0] == '0') && (! f[1])) {
|
||||
m_type = C25519;
|
||||
} else if ((f[0] == '1') && (!f[1])) {
|
||||
}
|
||||
else if ((f[0] == '1') && (! f[1])) {
|
||||
m_type = P384;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
if (Utils::unhex(f, strlen(f), m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) != ZT_C25519_COMBINED_PUBLIC_KEY_SIZE)
|
||||
if (Utils::unhex(f, strlen(f), m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE)
|
||||
!= ZT_C25519_COMBINED_PUBLIC_KEY_SIZE)
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
@ -360,18 +379,18 @@ bool Identity::fromString(const char *str)
|
|||
if (Utils::b32d(f, m_pub, sizeof(m_pub)) != sizeof(m_pub))
|
||||
return false;
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (strlen(f) > 1) {
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
if (Utils::unhex(f, strlen(f), m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) != ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
if (Utils::unhex(f, strlen(f), m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE)
|
||||
!= ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_hasPrivate = true;
|
||||
}
|
||||
break;
|
||||
|
@ -379,15 +398,14 @@ bool Identity::fromString(const char *str)
|
|||
case P384:
|
||||
if (Utils::b32d(f, m_priv, sizeof(m_priv)) != sizeof(m_priv)) {
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_hasPrivate = true;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,14 +420,16 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], const bool inc
|
|||
{
|
||||
Address(m_fp.address).copyTo(data);
|
||||
switch (m_type) {
|
||||
|
||||
case C25519:
|
||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
|
||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1, m_pub);
|
||||
if ((includePrivate) && (m_hasPrivate)) {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
Utils::copy< ZT_C25519_COMBINED_PRIVATE_KEY_SIZE >(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1, m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(
|
||||
data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1,
|
||||
m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = 0;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1;
|
||||
|
@ -418,13 +438,16 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], const bool inc
|
|||
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1, m_pub);
|
||||
if ((includePrivate) && (m_hasPrivate)) {
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
Utils::copy< ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE >(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1, m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] =
|
||||
ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(
|
||||
data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,
|
||||
m_priv);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1;
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -439,7 +462,6 @@ int Identity::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
|
||||
unsigned int privlen;
|
||||
switch ((m_type = (Type)data[ZT_ADDRESS_LENGTH])) {
|
||||
|
||||
case C25519:
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1))
|
||||
return -1;
|
||||
|
@ -449,12 +471,18 @@ int Identity::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
|
||||
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE];
|
||||
if (privlen == ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE))
|
||||
if (len
|
||||
< (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_C25519_COMBINED_PRIVATE_KEY_SIZE))
|
||||
return -1;
|
||||
m_hasPrivate = true;
|
||||
Utils::copy< ZT_C25519_COMBINED_PRIVATE_KEY_SIZE >(m_priv, data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
} else if (privlen == 0) {
|
||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(
|
||||
m_priv,
|
||||
data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
else if (privlen == 0) {
|
||||
m_hasPrivate = false;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1;
|
||||
}
|
||||
|
@ -473,15 +501,20 @@ int Identity::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
if (privlen == 0) {
|
||||
m_hasPrivate = false;
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1;
|
||||
} else if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
|
||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE))
|
||||
}
|
||||
else if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
|
||||
if (len
|
||||
< (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE))
|
||||
return -1;
|
||||
m_hasPrivate = true;
|
||||
Utils::copy< ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE >(&m_priv, data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(
|
||||
&m_priv,
|
||||
data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1);
|
||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1
|
||||
+ ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
|
|
@ -14,20 +14,21 @@
|
|||
#ifndef ZT_IDENTITY_HPP
|
||||
#define ZT_IDENTITY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_IDENTITY_STRING_BUFFER_LENGTH 1024
|
||||
#define ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE (7 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + ZT_ECC384_PUBLIC_KEY_SIZE)
|
||||
#define ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE (ZT_C25519_COMBINED_PRIVATE_KEY_SIZE + ZT_ECC384_PRIVATE_KEY_SIZE)
|
||||
#define ZT_IDENTITY_MARSHAL_SIZE_MAX (ZT_ADDRESS_LENGTH + 4 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE)
|
||||
#define ZT_IDENTITY_MARSHAL_SIZE_MAX \
|
||||
(ZT_ADDRESS_LENGTH + 4 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE)
|
||||
#define ZT_IDENTITY_TYPE1_MIMC52_ROUNDS 262144
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -44,14 +45,12 @@ namespace ZeroTier {
|
|||
* Type 1 identities are better in many ways but type 0 will remain the default until
|
||||
* 1.x nodes are pretty much dead in the wild.
|
||||
*/
|
||||
class Identity : public TriviallyCopyable
|
||||
{
|
||||
class Identity : public TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Identity type -- numeric values of these enums are protocol constants
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
enum Type {
|
||||
C25519 = ZT_IDENTITY_TYPE_C25519, // Type 0 -- Curve25519 and Ed25519 (1.x and 2.x, default)
|
||||
P384 = ZT_IDENTITY_TYPE_P384 // Type 1 -- NIST P-384 with linked Curve25519/Ed25519 secondaries (2.x+)
|
||||
};
|
||||
|
@ -62,10 +61,14 @@ public:
|
|||
static const Identity NIL;
|
||||
|
||||
ZT_INLINE Identity() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE Identity(const Identity& id) noexcept
|
||||
{ Utils::copy< sizeof(Identity) >(this, &id); }
|
||||
{
|
||||
Utils::copy<sizeof(Identity)>(this, &id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct identity from string
|
||||
|
@ -76,10 +79,14 @@ public:
|
|||
* @param str Identity in canonical string format
|
||||
*/
|
||||
explicit ZT_INLINE Identity(const char* str)
|
||||
{ fromString(str); }
|
||||
{
|
||||
fromString(str);
|
||||
}
|
||||
|
||||
ZT_INLINE ~Identity()
|
||||
{ Utils::burn(reinterpret_cast<void *>(&this->m_priv), sizeof(this->m_priv)); }
|
||||
{
|
||||
Utils::burn(reinterpret_cast<void*>(&this->m_priv), sizeof(this->m_priv));
|
||||
}
|
||||
|
||||
ZT_INLINE Identity& operator=(const Identity& id) noexcept
|
||||
{
|
||||
|
@ -92,13 +99,17 @@ public:
|
|||
* Set identity to NIL value (all zero)
|
||||
*/
|
||||
ZT_INLINE void zero() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Identity type (undefined if identity is null or invalid)
|
||||
*/
|
||||
ZT_INLINE Type type() const noexcept
|
||||
{ return m_type; }
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new identity (address, key pair)
|
||||
|
@ -125,19 +136,25 @@ public:
|
|||
* @return True if this identity contains a private key
|
||||
*/
|
||||
ZT_INLINE bool hasPrivate() const noexcept
|
||||
{ return m_hasPrivate; }
|
||||
{
|
||||
return m_hasPrivate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This identity's address
|
||||
*/
|
||||
ZT_INLINE Address address() const noexcept
|
||||
{ return Address(m_fp.address); }
|
||||
{
|
||||
return Address(m_fp.address);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Full fingerprint of this identity (address plus SHA384 of keys)
|
||||
*/
|
||||
ZT_INLINE const Fingerprint& fingerprint() const noexcept
|
||||
{ return m_fp; }
|
||||
{
|
||||
return m_fp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a hash of this identity's public and private keys.
|
||||
|
@ -224,31 +241,49 @@ public:
|
|||
* @return True if this identity contains something
|
||||
*/
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_fp); }
|
||||
{
|
||||
return (m_fp);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return m_fp.hashCode(); }
|
||||
{
|
||||
return m_fp.hashCode();
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Identity& id) const noexcept
|
||||
{ return (m_fp == id.m_fp); }
|
||||
{
|
||||
return (m_fp == id.m_fp);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Identity& id) const noexcept
|
||||
{ return !(*this == id); }
|
||||
{
|
||||
return ! (*this == id);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const Identity& id) const noexcept
|
||||
{ return (m_fp < id.m_fp); }
|
||||
{
|
||||
return (m_fp < id.m_fp);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const Identity& id) const noexcept
|
||||
{ return (id < *this); }
|
||||
{
|
||||
return (id < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Identity& id) const noexcept
|
||||
{ return !(id < *this); }
|
||||
{
|
||||
return ! (id < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Identity& id) const noexcept
|
||||
{ return !(*this < id); }
|
||||
{
|
||||
return ! (*this < id);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_IDENTITY_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_IDENTITY_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], bool includePrivate = false) const noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
|
|
@ -13,24 +13,31 @@
|
|||
|
||||
#define _WIN32_WINNT 0x06010000
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(sockaddr_storage), "ZT_SOCKADDR_STORAGE_SIZE is incorrect on this platform, must be size of sockaddr_storage");
|
||||
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(InetAddress), "ZT_SOCKADDR_STORAGE_SIZE should equal InetAddress, which should equal size of sockaddr_storage");
|
||||
static_assert(ZT_SOCKADDR_STORAGE_SIZE == sizeof(ZT_InetAddress), "ZT_SOCKADDR_STORAGE_SIZE should equal ZT_InetAddress, which should equal size of sockaddr_storage");
|
||||
static_assert(
|
||||
ZT_SOCKADDR_STORAGE_SIZE == sizeof(sockaddr_storage),
|
||||
"ZT_SOCKADDR_STORAGE_SIZE is incorrect on this platform, must be size of sockaddr_storage");
|
||||
static_assert(
|
||||
ZT_SOCKADDR_STORAGE_SIZE == sizeof(InetAddress),
|
||||
"ZT_SOCKADDR_STORAGE_SIZE should equal InetAddress, which should equal size of sockaddr_storage");
|
||||
static_assert(
|
||||
ZT_SOCKADDR_STORAGE_SIZE == sizeof(ZT_InetAddress),
|
||||
"ZT_SOCKADDR_STORAGE_SIZE should equal ZT_InetAddress, which should equal size of sockaddr_storage");
|
||||
|
||||
const InetAddress InetAddress::LO4((const void*)("\x7f\x00\x00\x01"), 4, 0);
|
||||
const InetAddress InetAddress::LO6((const void *) ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0);
|
||||
const InetAddress
|
||||
InetAddress::LO6((const void*)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0);
|
||||
const InetAddress InetAddress::NIL;
|
||||
|
||||
InetAddress::IpScope InetAddress::ipScope() const noexcept
|
||||
{
|
||||
switch (as.ss.ss_family) {
|
||||
|
||||
case AF_INET: {
|
||||
const uint32_t ip = Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr);
|
||||
switch (ip >> 24U) {
|
||||
|
@ -42,36 +49,46 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
|
|||
return ZT_IP_SCOPE_PRIVATE; // 10.0.0.0/8
|
||||
case 0x15: // return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
||||
case 0x16: // return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
||||
case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense)
|
||||
case 0x19: // return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of
|
||||
// Defense)
|
||||
case 0x1a: // return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA)
|
||||
case 0x1c: // return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North)
|
||||
case 0x1d: // return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA)
|
||||
case 0x1e: // return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
||||
case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
|
||||
case 0x33: // return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of
|
||||
// Social Security)
|
||||
case 0x37: // return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
||||
case 0x38: // 56.0.0.0/8 (US Postal Service)
|
||||
return ZT_IP_SCOPE_PSEUDOPRIVATE;
|
||||
case 0x64:
|
||||
if ((ip & 0xffc00000) == 0x64400000) return ZT_IP_SCOPE_PRIVATE; // 100.64.0.0/10
|
||||
if ((ip & 0xffc00000) == 0x64400000)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 100.64.0.0/10
|
||||
break;
|
||||
case 0x7f:
|
||||
return ZT_IP_SCOPE_LOOPBACK; // 127.0.0.0/8
|
||||
case 0xa9:
|
||||
if ((ip & 0xffff0000) == 0xa9fe0000) return ZT_IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
|
||||
if ((ip & 0xffff0000) == 0xa9fe0000)
|
||||
return ZT_IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
|
||||
break;
|
||||
case 0xac:
|
||||
if ((ip & 0xfff00000) == 0xac100000) return ZT_IP_SCOPE_PRIVATE; // 172.16.0.0/12
|
||||
if ((ip & 0xfff00000) == 0xac100000)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 172.16.0.0/12
|
||||
break;
|
||||
case 0xc0:
|
||||
if ((ip & 0xffff0000) == 0xc0a80000) return ZT_IP_SCOPE_PRIVATE; // 192.168.0.0/16
|
||||
if ((ip & 0xffffff00) == 0xc0000200) return ZT_IP_SCOPE_PRIVATE; // 192.0.2.0/24
|
||||
if ((ip & 0xffff0000) == 0xc0a80000)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 192.168.0.0/16
|
||||
if ((ip & 0xffffff00) == 0xc0000200)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 192.0.2.0/24
|
||||
break;
|
||||
case 0xc6:
|
||||
if ((ip & 0xfffe0000) == 0xc6120000) return ZT_IP_SCOPE_PRIVATE; // 198.18.0.0/15
|
||||
if ((ip & 0xffffff00) == 0xc6336400) return ZT_IP_SCOPE_PRIVATE; // 198.51.100.0/24
|
||||
if ((ip & 0xfffe0000) == 0xc6120000)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 198.18.0.0/15
|
||||
if ((ip & 0xffffff00) == 0xc6336400)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 198.51.100.0/24
|
||||
break;
|
||||
case 0xcb:
|
||||
if ((ip & 0xffffff00) == 0xcb007100) return ZT_IP_SCOPE_PRIVATE; // 203.0.113.0/24
|
||||
if ((ip & 0xffffff00) == 0xcb007100)
|
||||
return ZT_IP_SCOPE_PRIVATE; // 203.0.113.0/24
|
||||
break;
|
||||
case 0xff:
|
||||
return ZT_IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable)
|
||||
|
@ -88,25 +105,31 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
|
|||
case AF_INET6: {
|
||||
const uint8_t* const ip = as.sa_in6.sin6_addr.s6_addr;
|
||||
if ((ip[0] & 0xf0U) == 0xf0) {
|
||||
if (ip[0] == 0xff) return ZT_IP_SCOPE_MULTICAST; // ff00::/8
|
||||
if (ip[0] == 0xff)
|
||||
return ZT_IP_SCOPE_MULTICAST; // ff00::/8
|
||||
if ((ip[0] == 0xfe) && ((ip[1] & 0xc0U) == 0x80)) {
|
||||
unsigned int k = 2;
|
||||
while ((!ip[k]) && (k < 15)) ++k;
|
||||
while ((! ip[k]) && (k < 15))
|
||||
++k;
|
||||
if ((k == 15) && (ip[15] == 0x01))
|
||||
return ZT_IP_SCOPE_LOOPBACK; // fe80::1/128
|
||||
else return ZT_IP_SCOPE_LINK_LOCAL; // fe80::/10
|
||||
else
|
||||
return ZT_IP_SCOPE_LINK_LOCAL; // fe80::/10
|
||||
}
|
||||
if ((ip[0] & 0xfeU) == 0xfc) return ZT_IP_SCOPE_PRIVATE; // fc00::/7
|
||||
if ((ip[0] & 0xfeU) == 0xfc)
|
||||
return ZT_IP_SCOPE_PRIVATE; // fc00::/7
|
||||
}
|
||||
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 (ip[15] == 0x01) return ZT_IP_SCOPE_LOOPBACK; // ::1/128
|
||||
if (ip[15] == 0x00) return ZT_IP_SCOPE_NONE; // ::/128
|
||||
if (ip[15] == 0x01)
|
||||
return ZT_IP_SCOPE_LOOPBACK; // ::1/128
|
||||
if (ip[15] == 0x00)
|
||||
return ZT_IP_SCOPE_NONE; // ::/128
|
||||
}
|
||||
return ZT_IP_SCOPE_GLOBAL;
|
||||
}
|
||||
|
||||
}
|
||||
return ZT_IP_SCOPE_NONE;
|
||||
}
|
||||
|
@ -118,7 +141,8 @@ void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port
|
|||
as.sa_in.sin_family = AF_INET;
|
||||
as.sa_in.sin_port = Utils::hton((uint16_t)port);
|
||||
as.sa_in.sin_addr.s_addr = Utils::loadMachineEndian<uint32_t>(ipBytes);
|
||||
} else if (ipLen == 16) {
|
||||
}
|
||||
else if (ipLen == 16) {
|
||||
as.sa_in6.sin6_family = AF_INET6;
|
||||
as.sa_in6.sin6_port = Utils::hton((uint16_t)port);
|
||||
Utils::copy<16>(as.sa_in6.sin6_addr.s6_addr, ipBytes);
|
||||
|
@ -148,7 +172,8 @@ char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noex
|
|||
{
|
||||
char* p = toIpString(buf);
|
||||
if (*p) {
|
||||
while (*p) ++p;
|
||||
while (*p)
|
||||
++p;
|
||||
*(p++) = '/';
|
||||
Utils::decimal(port(), p);
|
||||
}
|
||||
|
@ -194,7 +219,8 @@ bool InetAddress::fromString(const char *ipSlashPort) noexcept
|
|||
as.sa_in6.sin6_port = Utils::hton((uint16_t)port);
|
||||
inet_pton(AF_INET6, buf, as.sa_in6.sin6_addr.s6_addr);
|
||||
return true;
|
||||
} else if (strchr(buf, '.')) {
|
||||
}
|
||||
else if (strchr(buf, '.')) {
|
||||
as.sa_in.sin_family = AF_INET;
|
||||
as.sa_in.sin_port = Utils::hton((uint16_t)port);
|
||||
inet_pton(AF_INET, buf, &as.sa_in.sin_addr.s_addr);
|
||||
|
@ -215,15 +241,16 @@ InetAddress InetAddress::netmask() const noexcept
|
|||
uint64_t nm[2];
|
||||
const unsigned int bits = netmaskBits();
|
||||
if (bits) {
|
||||
nm[0] = Utils::hton((uint64_t) ((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[0] = Utils::hton(
|
||||
(uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
nm[0] = 0;
|
||||
nm[1] = 0;
|
||||
}
|
||||
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, nm);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -249,11 +276,11 @@ InetAddress InetAddress::network() const noexcept
|
|||
uint64_t nm[2];
|
||||
const unsigned int bits = netmaskBits();
|
||||
Utils::copy<16>(nm, reinterpret_cast<sockaddr_in6*>(&r)->sin6_addr.s6_addr);
|
||||
nm[0] &= Utils::hton((uint64_t) ((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[0] &=
|
||||
Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||
nm[1] &= Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, nm);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -289,9 +316,8 @@ bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
|||
if (bits == 0)
|
||||
return true;
|
||||
return (
|
||||
(Utils::ntoh((uint32_t) addr.as.sa_in.sin_addr.s_addr) >> (32 - bits)) ==
|
||||
(Utils::ntoh((uint32_t) as.sa_in.sin_addr.s_addr) >> (32 - bits))
|
||||
);
|
||||
(Utils::ntoh((uint32_t)addr.as.sa_in.sin_addr.s_addr) >> (32 - bits))
|
||||
== (Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr) >> (32 - bits)));
|
||||
}
|
||||
case AF_INET6: {
|
||||
const InetAddress mask(netmask());
|
||||
|
@ -423,7 +449,8 @@ InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress
|
|||
{
|
||||
InetAddress r;
|
||||
r.as.sa_in6.sin6_family = AF_INET6;
|
||||
r.as.sa_in6.sin6_port = ZT_CONST_TO_BE_UINT16(88); // /88 includes 0xfd + network ID, discriminating by device ID below that
|
||||
r.as.sa_in6.sin6_port =
|
||||
ZT_CONST_TO_BE_UINT16(88); // /88 includes 0xfd + network ID, discriminating by device ID below that
|
||||
r.as.sa_in6.sin6_addr.s6_addr[0] = 0xfd;
|
||||
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56U);
|
||||
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48U);
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#define ZT_INETADDRESS_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -33,8 +33,7 @@ namespace ZeroTier {
|
|||
* sockaddr_storage and used interchangeably. DO NOT change this by e.g.
|
||||
* adding non-static fields, since much code depends on this identity.
|
||||
*/
|
||||
struct InetAddress : public TriviallyCopyable
|
||||
{
|
||||
struct InetAddress : public TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Loopback IPv4 address (no port)
|
||||
|
@ -61,40 +60,64 @@ public:
|
|||
typedef ZT_InetAddress_IpScope IpScope;
|
||||
|
||||
ZT_INLINE InetAddress() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_storage& ss) noexcept
|
||||
{ *this = ss; }
|
||||
{
|
||||
*this = ss;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_storage* const ss) noexcept
|
||||
{ *this = ss; }
|
||||
{
|
||||
*this = ss;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr& sa) noexcept
|
||||
{ *this = sa; }
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr* const sa) noexcept
|
||||
{ *this = sa; }
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in& sa) noexcept
|
||||
{ *this = sa; }
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in* const sa) noexcept
|
||||
{ *this = sa; }
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in6& sa) noexcept
|
||||
{ *this = sa; }
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const sockaddr_in6* const sa) noexcept
|
||||
{ *this = sa; }
|
||||
{
|
||||
*this = sa;
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress(const void* const ipBytes, const unsigned int ipLen, const unsigned int port) noexcept
|
||||
{ this->set(ipBytes, ipLen, port); }
|
||||
{
|
||||
this->set(ipBytes, ipLen, port);
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress(const uint32_t ipv4, const unsigned int port) noexcept
|
||||
{ this->set(&ipv4, 4, port); }
|
||||
{
|
||||
this->set(&ipv4, 4, port);
|
||||
}
|
||||
|
||||
explicit ZT_INLINE InetAddress(const char* const ipSlashPort) noexcept
|
||||
{ this->fromString(ipSlashPort); }
|
||||
{
|
||||
this->fromString(ipSlashPort);
|
||||
}
|
||||
|
||||
ZT_INLINE InetAddress& operator=(const sockaddr_storage& ss) noexcept
|
||||
{
|
||||
|
@ -106,7 +129,8 @@ public:
|
|||
{
|
||||
if (ss)
|
||||
as.ss = *ss;
|
||||
else memoryZero(this);
|
||||
else
|
||||
memoryZero(this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -163,7 +187,9 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE void clear() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IP scope classification (e.g. loopback, link-local, private, global)
|
||||
|
@ -256,7 +282,9 @@ public:
|
|||
* @return Netmask bits
|
||||
*/
|
||||
ZT_INLINE unsigned int netmaskBits() const noexcept
|
||||
{ return port(); }
|
||||
{
|
||||
return port();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if netmask bits is valid for the address type
|
||||
|
@ -282,7 +310,9 @@ public:
|
|||
* @return Gateway metric
|
||||
*/
|
||||
ZT_INLINE unsigned int metric() const noexcept
|
||||
{ return port(); }
|
||||
{
|
||||
return port();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a full netmask as an InetAddress
|
||||
|
@ -328,13 +358,17 @@ public:
|
|||
* @return True if this is an IPv4 address
|
||||
*/
|
||||
ZT_INLINE bool isV4() const noexcept
|
||||
{ return (as.ss.ss_family == AF_INET); }
|
||||
{
|
||||
return (as.ss.ss_family == AF_INET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this is an IPv6 address
|
||||
*/
|
||||
ZT_INLINE bool isV6() const noexcept
|
||||
{ return (as.ss.ss_family == AF_INET6); }
|
||||
{
|
||||
return (as.ss.ss_family == AF_INET6);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return pointer to raw address bytes or NULL if not available
|
||||
|
@ -413,13 +447,14 @@ public:
|
|||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{
|
||||
if (as.ss.ss_family == AF_INET) {
|
||||
return (unsigned long)Utils::hash32(((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce);
|
||||
} else if (as.ss.ss_family == AF_INET6) {
|
||||
return (unsigned long)Utils::hash32(
|
||||
((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce);
|
||||
}
|
||||
else if (as.ss.ss_family == AF_INET6) {
|
||||
return (unsigned long)Utils::hash64(
|
||||
(Utils::loadMachineEndian< uint64_t >(as.sa_in6.sin6_addr.s6_addr) +
|
||||
Utils::loadMachineEndian< uint64_t >(as.sa_in6.sin6_addr.s6_addr + 8) +
|
||||
(uint64_t)as.sa_in6.sin6_port) ^
|
||||
Utils::s_mapNonce);
|
||||
(Utils::loadMachineEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr)
|
||||
+ Utils::loadMachineEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr + 8) + (uint64_t)as.sa_in6.sin6_port)
|
||||
^ Utils::s_mapNonce);
|
||||
}
|
||||
return Utils::fnv1a32(this, sizeof(InetAddress));
|
||||
}
|
||||
|
@ -438,10 +473,14 @@ public:
|
|||
* @return True if address family is non-zero
|
||||
*/
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return (as.ss.ss_family != 0); }
|
||||
{
|
||||
return (as.ss.ss_family != 0);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_INETADDRESS_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_INETADDRESS_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept;
|
||||
|
||||
|
@ -451,9 +490,13 @@ public:
|
|||
{
|
||||
if (as.ss.ss_family == a.as.ss.ss_family) {
|
||||
if (as.ss.ss_family == AF_INET)
|
||||
return ((as.sa_in.sin_port == a.as.sa_in.sin_port) && (as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr));
|
||||
return (
|
||||
(as.sa_in.sin_port == a.as.sa_in.sin_port)
|
||||
&& (as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr));
|
||||
if (as.ss.ss_family == AF_INET6)
|
||||
return ((as.sa_in6.sin6_port == a.as.sa_in6.sin6_port) && (memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 16) == 0));
|
||||
return (
|
||||
(as.sa_in6.sin6_port == a.as.sa_in6.sin6_port)
|
||||
&& (memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 16) == 0));
|
||||
return memcmp(this, &a, sizeof(InetAddress)) == 0;
|
||||
}
|
||||
return false;
|
||||
|
@ -466,7 +509,8 @@ public:
|
|||
const uint16_t p0 = Utils::ntoh((uint16_t)as.sa_in.sin_port);
|
||||
const uint16_t p1 = Utils::ntoh((uint16_t)a.as.sa_in.sin_port);
|
||||
if (p0 == p1)
|
||||
return Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr) < Utils::ntoh((uint32_t)a.as.sa_in.sin_addr.s_addr);
|
||||
return Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr)
|
||||
< Utils::ntoh((uint32_t)a.as.sa_in.sin_addr.s_addr);
|
||||
return p0 < p1;
|
||||
}
|
||||
if (as.ss.ss_family == AF_INET6) {
|
||||
|
@ -482,16 +526,24 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const InetAddress& a) const noexcept
|
||||
{ return !(*this == a); }
|
||||
{
|
||||
return ! (*this == a);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const InetAddress& a) const noexcept
|
||||
{ return (a < *this); }
|
||||
{
|
||||
return (a < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const InetAddress& a) const noexcept
|
||||
{ return !(a < *this); }
|
||||
{
|
||||
return ! (a < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const InetAddress& a) const noexcept
|
||||
{ return !(*this < a); }
|
||||
{
|
||||
return ! (*this < a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute an IPv6 link-local address
|
||||
|
@ -552,8 +604,7 @@ public:
|
|||
/**
|
||||
* Union allowing this to be accessed as a sockaddr of any supported type.
|
||||
*/
|
||||
union
|
||||
{
|
||||
union {
|
||||
sockaddr_storage ss;
|
||||
sockaddr sa;
|
||||
sockaddr_in sa_in;
|
||||
|
@ -562,64 +613,104 @@ public:
|
|||
};
|
||||
|
||||
static ZT_INLINE InetAddress* asInetAddress(sockaddr_in* const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress* asInetAddress(sockaddr_in6* const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress* asInetAddress(sockaddr* const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress* asInetAddress(sockaddr_storage* const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress* asInetAddress(ZT_InetAddress* const p) noexcept
|
||||
{ return reinterpret_cast<InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const sockaddr_in* const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const sockaddr_in6* const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const sockaddr* const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const sockaddr_storage* const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress* asInetAddress(const ZT_InetAddress* const p) noexcept
|
||||
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||
{
|
||||
return reinterpret_cast<const InetAddress*>(p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress& asInetAddress(sockaddr_in& p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress& asInetAddress(sockaddr_in6& p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress& asInetAddress(sockaddr& p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress& asInetAddress(sockaddr_storage& p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE InetAddress& asInetAddress(ZT_InetAddress& p) noexcept
|
||||
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const sockaddr_in& p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const sockaddr_in6& p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const sockaddr& p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const sockaddr_storage& p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
static ZT_INLINE const InetAddress& asInetAddress(const ZT_InetAddress& p) noexcept
|
||||
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||
{
|
||||
return *reinterpret_cast<const InetAddress*>(&p);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
|
|
367
core/LZ4.cpp
367
core/LZ4.cpp
|
@ -37,11 +37,12 @@
|
|||
// original LZ4 license.
|
||||
|
||||
#include "LZ4.hpp"
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FORCE_INLINE __forceinline
|
||||
|
@ -68,8 +69,7 @@ FORCE_INLINE void LZ4_resetStream(LZ4_stream_t *streamPtr);
|
|||
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE - 2)
|
||||
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
uint32_t hashTable[LZ4_HASH_SIZE_U32];
|
||||
uint32_t currentOffset;
|
||||
uint32_t initCheck;
|
||||
|
@ -78,8 +78,7 @@ typedef struct
|
|||
uint32_t dictSize;
|
||||
} LZ4_stream_t_internal;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
const uint8_t* externalDict;
|
||||
size_t extDictSize;
|
||||
const uint8_t* prefixEnd;
|
||||
|
@ -87,15 +86,13 @@ typedef struct
|
|||
} LZ4_streamDecode_t_internal;
|
||||
|
||||
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE - 3)) + 4)
|
||||
union LZ4_stream_u
|
||||
{
|
||||
union LZ4_stream_u {
|
||||
unsigned long long table[LZ4_STREAMSIZE_U64];
|
||||
LZ4_stream_t_internal internal_donotuse;
|
||||
}; /* previously typedef'd to LZ4_stream_t */
|
||||
|
||||
#define LZ4_STREAMDECODESIZE_U64 4
|
||||
union LZ4_streamDecode_u
|
||||
{
|
||||
union LZ4_streamDecode_u {
|
||||
unsigned long long table[LZ4_STREAMDECODESIZE_U64];
|
||||
LZ4_streamDecode_t_internal internal_donotuse;
|
||||
}; /* previously typedef'd to LZ4_streamDecode_t */
|
||||
|
@ -133,39 +130,74 @@ typedef uintptr_t reg_t;
|
|||
|
||||
#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS == 2)
|
||||
FORCE_INLINE U16 LZ4_read16(const void* memPtr)
|
||||
{ return *(const U16 *)memPtr; }
|
||||
{
|
||||
return *(const U16*)memPtr;
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 LZ4_read32(const void* memPtr)
|
||||
{ return *(const U32 *)memPtr; }
|
||||
{
|
||||
return *(const U32*)memPtr;
|
||||
}
|
||||
|
||||
FORCE_INLINE reg_t LZ4_read_ARCH(const void* memPtr)
|
||||
{ return *(const reg_t *)memPtr; }
|
||||
{
|
||||
return *(const reg_t*)memPtr;
|
||||
}
|
||||
|
||||
FORCE_INLINE void LZ4_write16(void* memPtr, U16 value)
|
||||
{ *(U16 *)memPtr = value; }
|
||||
{
|
||||
*(U16*)memPtr = value;
|
||||
}
|
||||
|
||||
FORCE_INLINE void LZ4_write32(void* memPtr, U32 value)
|
||||
{ *(U32 *)memPtr = value; }
|
||||
{
|
||||
*(U32*)memPtr = value;
|
||||
}
|
||||
|
||||
#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS == 1)
|
||||
typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign;
|
||||
FORCE_INLINE U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
FORCE_INLINE U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
FORCE_INLINE reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; }
|
||||
FORCE_INLINE void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
FORCE_INLINE void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
|
||||
typedef union {
|
||||
U16 u16;
|
||||
U32 u32;
|
||||
reg_t uArch;
|
||||
} __attribute__((packed)) unalign;
|
||||
FORCE_INLINE U16 LZ4_read16(const void* ptr)
|
||||
{
|
||||
return ((const unalign*)ptr)->u16;
|
||||
}
|
||||
FORCE_INLINE U32 LZ4_read32(const void* ptr)
|
||||
{
|
||||
return ((const unalign*)ptr)->u32;
|
||||
}
|
||||
FORCE_INLINE reg_t LZ4_read_ARCH(const void* ptr)
|
||||
{
|
||||
return ((const unalign*)ptr)->uArch;
|
||||
}
|
||||
FORCE_INLINE void LZ4_write16(void* memPtr, U16 value)
|
||||
{
|
||||
((unalign*)memPtr)->u16 = value;
|
||||
}
|
||||
FORCE_INLINE void LZ4_write32(void* memPtr, U32 value)
|
||||
{
|
||||
((unalign*)memPtr)->u32 = value;
|
||||
}
|
||||
#else /* safe and portable */
|
||||
FORCE_INLINE U16 LZ4_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; Utils::copy(&val, memPtr, sizeof(val)); return val;
|
||||
U16 val;
|
||||
Utils::copy(&val, memPtr, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
FORCE_INLINE U32 LZ4_read32(const void* memPtr)
|
||||
{
|
||||
U32 val; Utils::copy(&val, memPtr, sizeof(val)); return val;
|
||||
U32 val;
|
||||
Utils::copy(&val, memPtr, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
FORCE_INLINE reg_t LZ4_read_ARCH(const void* memPtr)
|
||||
{
|
||||
reg_t val; Utils::copy(&val, memPtr, sizeof(val)); return val;
|
||||
reg_t val;
|
||||
Utils::copy(&val, memPtr, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
FORCE_INLINE void LZ4_write16(void* memPtr, U16 value)
|
||||
{
|
||||
|
@ -181,7 +213,8 @@ FORCE_INLINE U16 LZ4_readLE16(const void *memPtr)
|
|||
{
|
||||
if (LZ4_isLittleEndian()) {
|
||||
return LZ4_read16(memPtr);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const BYTE* p = (const BYTE*)memPtr;
|
||||
return (U16)((U16)p[0] + (p[1] << 8));
|
||||
}
|
||||
|
@ -191,7 +224,8 @@ FORCE_INLINE void LZ4_writeLE16(void *memPtr, U16 value)
|
|||
{
|
||||
if (LZ4_isLittleEndian()) {
|
||||
LZ4_write16(memPtr, value);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
BYTE* p = (BYTE*)memPtr;
|
||||
p[0] = (BYTE)value;
|
||||
p[1] = (BYTE)(value >> 8);
|
||||
|
@ -212,8 +246,7 @@ FORCE_INLINE void LZ4_wildCopy(void *dstPtr, const void *srcPtr, void *dstEnd)
|
|||
LZ4_copy8(d, s);
|
||||
d += 8;
|
||||
s += 8;
|
||||
}
|
||||
while (d < e);
|
||||
} while (d < e);
|
||||
}
|
||||
|
||||
#define MINMATCH 4
|
||||
|
@ -235,7 +268,8 @@ static const int LZ4_minLength = (MFLIMIT + 1);
|
|||
#define RUN_BITS (8 - ML_BITS)
|
||||
#define RUN_MASK ((1U << RUN_BITS) - 1)
|
||||
|
||||
// #define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
// #define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable
|
||||
// declarations */
|
||||
|
||||
FORCE_INLINE unsigned LZ4_NbCommonBytes(reg_t val)
|
||||
{
|
||||
|
@ -248,10 +282,13 @@ FORCE_INLINE unsigned LZ4_NbCommonBytes(reg_t val)
|
|||
#elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 3))) && ! defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
return (__builtin_ctzll((U64)val) >> 3);
|
||||
#else
|
||||
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
|
||||
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5,
|
||||
3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5,
|
||||
3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
|
||||
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
|
||||
#endif
|
||||
} else /* 32 bits */ {
|
||||
}
|
||||
else /* 32 bits */ {
|
||||
#if defined(_MSC_VER) && ! defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
unsigned long r;
|
||||
_BitScanForward(&r, (U32)val);
|
||||
|
@ -259,11 +296,13 @@ FORCE_INLINE unsigned LZ4_NbCommonBytes(reg_t val)
|
|||
#elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 3))) && ! defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
return (__builtin_ctz((U32)val) >> 3);
|
||||
#else
|
||||
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
|
||||
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1,
|
||||
3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
|
||||
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
|
||||
#endif
|
||||
}
|
||||
} else /* Big Endian CPU */ {
|
||||
}
|
||||
else /* Big Endian CPU */ {
|
||||
if (sizeof(val) == 8) {
|
||||
#if defined(_MSC_VER) && defined(_WIN64) && ! defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
|
@ -273,12 +312,25 @@ FORCE_INLINE unsigned LZ4_NbCommonBytes(reg_t val)
|
|||
return (__builtin_clzll((U64)val) >> 3);
|
||||
#else
|
||||
unsigned r;
|
||||
if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
|
||||
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
|
||||
if (! (val >> 32)) {
|
||||
r = 4;
|
||||
}
|
||||
else {
|
||||
r = 0;
|
||||
val >>= 32;
|
||||
}
|
||||
if (! (val >> 16)) {
|
||||
r += 2;
|
||||
val >>= 8;
|
||||
}
|
||||
else {
|
||||
val >>= 24;
|
||||
}
|
||||
r += (! val);
|
||||
return r;
|
||||
#endif
|
||||
} else /* 32 bits */ {
|
||||
}
|
||||
else /* 32 bits */ {
|
||||
#if defined(_MSC_VER) && ! defined(LZ4_FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse(&r, (unsigned long)val);
|
||||
|
@ -287,7 +339,14 @@ FORCE_INLINE unsigned LZ4_NbCommonBytes(reg_t val)
|
|||
return (__builtin_clz((U32)val) >> 3);
|
||||
#else
|
||||
unsigned r;
|
||||
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
|
||||
if (! (val >> 16)) {
|
||||
r = 2;
|
||||
val >>= 8;
|
||||
}
|
||||
else {
|
||||
r = 0;
|
||||
val >>= 24;
|
||||
}
|
||||
r += (! val);
|
||||
return r;
|
||||
#endif
|
||||
|
@ -319,42 +378,27 @@ FORCE_INLINE unsigned LZ4_count(const BYTE *pIn, const BYTE *pMatch, const BYTE
|
|||
pIn += 2;
|
||||
pMatch += 2;
|
||||
}
|
||||
if ((pIn < pInLimit) && (*pMatch == *pIn)) pIn++;
|
||||
if ((pIn < pInLimit) && (*pMatch == *pIn))
|
||||
pIn++;
|
||||
return (unsigned)(pIn - pStart);
|
||||
}
|
||||
|
||||
static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT - 1));
|
||||
static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
notLimited = 0, limitedOutput = 1
|
||||
} limitedOutput_directive;
|
||||
typedef enum
|
||||
{
|
||||
byPtr, byU32, byU16
|
||||
} tableType_t;
|
||||
typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
|
||||
typedef enum { byPtr, byU32, byU16 } tableType_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
noDict = 0, withPrefix64k, usingExtDict
|
||||
} dict_directive;
|
||||
typedef enum
|
||||
{
|
||||
noDictIssue = 0, dictSmall
|
||||
} dictIssue_directive;
|
||||
typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
|
||||
typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
endOnOutputSize = 0, endOnInputSize = 1
|
||||
} endCondition_directive;
|
||||
typedef enum
|
||||
{
|
||||
full = 0, partial = 1
|
||||
} earlyEnd_directive;
|
||||
typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
|
||||
typedef enum { full = 0, partial = 1 } earlyEnd_directive;
|
||||
|
||||
FORCE_INLINE int LZ4_compressBound(int isize)
|
||||
{ return LZ4_COMPRESSBOUND(isize); }
|
||||
{
|
||||
return LZ4_COMPRESSBOUND(isize);
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
|
||||
{
|
||||
|
@ -377,11 +421,13 @@ FORCE_INLINE U32 LZ4_hash5(U64 sequence, 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);
|
||||
}
|
||||
|
||||
FORCE_INLINE void LZ4_putPositionOnHash(const BYTE *p, U32 h, void *tableBase, tableType_t const tableType, const BYTE *srcBase)
|
||||
FORCE_INLINE void
|
||||
LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
|
||||
{
|
||||
switch (tableType) {
|
||||
case byPtr: {
|
||||
|
@ -460,7 +506,8 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
U32 forwardH;
|
||||
|
||||
/* 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) {
|
||||
case noDict:
|
||||
default:
|
||||
|
@ -476,8 +523,10 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
lowLimit = (const BYTE*)source;
|
||||
break;
|
||||
}
|
||||
if ((tableType == byU16) && (inputSize >= LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
|
||||
if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
|
||||
if ((tableType == byU16) && (inputSize >= LZ4_64Klimit))
|
||||
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 */
|
||||
LZ4_putPosition(ip, cctx->hashTable, tableType, base);
|
||||
|
@ -501,14 +550,16 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
forwardIp += step;
|
||||
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);
|
||||
if (dict == usingExtDict) {
|
||||
if (match < (const BYTE*)source) {
|
||||
refDelta = dictDelta;
|
||||
lowLimit = dictionary;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
refDelta = 0;
|
||||
lowLimit = (const BYTE*)source;
|
||||
}
|
||||
|
@ -537,9 +588,12 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
if (litLength >= RUN_MASK) {
|
||||
int len = (int)litLength - RUN_MASK;
|
||||
*token = (RUN_MASK << ML_BITS);
|
||||
for (; len >= 255; len -= 255) *op++ = 255;
|
||||
for (; len >= 255; len -= 255)
|
||||
*op++ = 255;
|
||||
*op++ = (BYTE)len;
|
||||
} else *token = (BYTE)(litLength << ML_BITS);
|
||||
}
|
||||
else
|
||||
*token = (BYTE)(litLength << ML_BITS);
|
||||
|
||||
/* Copy Literals */
|
||||
LZ4_wildCopy(op, anchor, op + litLength);
|
||||
|
@ -559,7 +613,8 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
const BYTE* limit;
|
||||
match += refDelta;
|
||||
limit = ip + (dictEnd - match);
|
||||
if (limit > matchlimit) limit = matchlimit;
|
||||
if (limit > matchlimit)
|
||||
limit = matchlimit;
|
||||
matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, limit);
|
||||
ip += MINMATCH + matchCode;
|
||||
if (ip == limit) {
|
||||
|
@ -567,7 +622,8 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
matchCode += more;
|
||||
ip += more;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);
|
||||
ip += MINMATCH + matchCode;
|
||||
}
|
||||
|
@ -579,17 +635,20 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
*token += ML_MASK;
|
||||
matchCode -= ML_MASK;
|
||||
LZ4_write32(op, 0xFFFFFFFF);
|
||||
while (matchCode >= 4 * 255) op += 4, LZ4_write32(op, 0xFFFFFFFF), matchCode -= 4 * 255;
|
||||
while (matchCode >= 4 * 255)
|
||||
op += 4, LZ4_write32(op, 0xFFFFFFFF), matchCode -= 4 * 255;
|
||||
op += matchCode / 255;
|
||||
*op++ = (BYTE)(matchCode % 255);
|
||||
} else
|
||||
}
|
||||
else
|
||||
*token += (BYTE)(matchCode);
|
||||
}
|
||||
|
||||
anchor = ip;
|
||||
|
||||
/* Test end of chunk */
|
||||
if (ip > mflimit) break;
|
||||
if (ip > mflimit)
|
||||
break;
|
||||
|
||||
/* Fill table */
|
||||
LZ4_putPosition(ip - 2, cctx->hashTable, tableType, base);
|
||||
|
@ -600,14 +659,14 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
if (match < (const BYTE*)source) {
|
||||
refDelta = dictDelta;
|
||||
lowLimit = dictionary;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
refDelta = 0;
|
||||
lowLimit = (const BYTE*)source;
|
||||
}
|
||||
}
|
||||
LZ4_putPosition(ip, cctx->hashTable, tableType, base);
|
||||
if (((dictIssue == dictSmall) ? (match >= lowRefLimit) : 1)
|
||||
&& (match + MAX_DISTANCE >= ip)
|
||||
if (((dictIssue == dictSmall) ? (match >= lowRefLimit) : 1) && (match + MAX_DISTANCE >= ip)
|
||||
&& (LZ4_read32(match + refDelta) == LZ4_read32(ip))) {
|
||||
token = op++;
|
||||
*token = 0;
|
||||
|
@ -628,9 +687,11 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
if (lastRun >= RUN_MASK) {
|
||||
size_t accumulator = lastRun - RUN_MASK;
|
||||
*op++ = RUN_MASK << ML_BITS;
|
||||
for (; accumulator >= 255; accumulator -= 255) *op++ = 255;
|
||||
for (; accumulator >= 255; accumulator -= 255)
|
||||
*op++ = 255;
|
||||
*op++ = (BYTE)accumulator;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*op++ = (BYTE)(lastRun << ML_BITS);
|
||||
}
|
||||
Utils::copy(op, anchor, lastRun);
|
||||
|
@ -641,7 +702,13 @@ FORCE_INLINE int LZ4_compress_generic(
|
|||
return (int)(((char*)op) - dest);
|
||||
}
|
||||
|
||||
ZT_INLINE int LZ4_compress_fast_extState(void *state, const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
|
||||
ZT_INLINE int LZ4_compress_fast_extState(
|
||||
void* state,
|
||||
const char* source,
|
||||
char* dest,
|
||||
int inputSize,
|
||||
int maxOutputSize,
|
||||
int acceleration)
|
||||
{
|
||||
LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse;
|
||||
LZ4_resetStream((LZ4_stream_t*)state);
|
||||
|
@ -649,14 +716,55 @@ ZT_INLINE int LZ4_compress_fast_extState(void *state, const char *source, char *
|
|||
|
||||
if (maxOutputSize >= LZ4_compressBound(inputSize)) {
|
||||
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 {
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,11 +805,13 @@ FORCE_INLINE int LZ4_decompress_generic(
|
|||
const int safeDecode = (endOnInput == endOnInputSize);
|
||||
const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
|
||||
|
||||
|
||||
/* Special cases */
|
||||
if ((partialDecoding) && (oexit > oend - MFLIMIT)) oexit = oend - MFLIMIT; /* targetOutputSize too high => decode everything */
|
||||
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);
|
||||
if ((partialDecoding) && (oexit > oend - MFLIMIT))
|
||||
oexit = oend - MFLIMIT; /* targetOutputSize too high => decode everything */
|
||||
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 */
|
||||
while (1) {
|
||||
|
@ -717,20 +827,28 @@ FORCE_INLINE int LZ4_decompress_generic(
|
|||
s = *ip++;
|
||||
length += s;
|
||||
} 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)(ip) + length < (uptrval)(ip))) goto _output_error; /* overflow detection */
|
||||
if ((safeDecode) && unlikely((uptrval)(op) + length < (uptrval)(op)))
|
||||
goto _output_error; /* overflow detection */
|
||||
if ((safeDecode) && unlikely((uptrval)(ip) + length < (uptrval)(ip)))
|
||||
goto _output_error; /* overflow detection */
|
||||
}
|
||||
|
||||
/* copy literals */
|
||||
cpy = op + length;
|
||||
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))) {
|
||||
if (partialDecoding) {
|
||||
if (cpy > oend) 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 {
|
||||
if ((!endOnInput) && (cpy != oend)) 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 */
|
||||
if (cpy > oend)
|
||||
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 {
|
||||
if ((! endOnInput) && (cpy != oend))
|
||||
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 */
|
||||
}
|
||||
Utils::copy(op, ip, length);
|
||||
ip += length;
|
||||
|
@ -745,7 +863,8 @@ FORCE_INLINE int LZ4_decompress_generic(
|
|||
offset = LZ4_readLE16(ip);
|
||||
ip += 2;
|
||||
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 */
|
||||
|
||||
/* get matchlength */
|
||||
|
@ -754,22 +873,26 @@ FORCE_INLINE int LZ4_decompress_generic(
|
|||
unsigned s;
|
||||
do {
|
||||
s = *ip++;
|
||||
if ((endOnInput) && (ip > iend - LASTLITERALS)) goto _output_error;
|
||||
if ((endOnInput) && (ip > iend - LASTLITERALS))
|
||||
goto _output_error;
|
||||
length += s;
|
||||
} 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;
|
||||
|
||||
/* check external dictionary */
|
||||
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)) {
|
||||
/* match can be copied as a single segment from external dictionary */
|
||||
memmove(op, dictEnd - (lowPrefix - match), length);
|
||||
op += length;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
/* match encompass external dictionary and current block */
|
||||
size_t const copySize = (size_t)(lowPrefix - match);
|
||||
size_t const restSize = length - copySize;
|
||||
|
@ -778,8 +901,10 @@ FORCE_INLINE int LZ4_decompress_generic(
|
|||
if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */
|
||||
BYTE* const endOfMatch = op + restSize;
|
||||
const BYTE* copyFrom = lowPrefix;
|
||||
while (op < endOfMatch) *op++ = *copyFrom++;
|
||||
} else {
|
||||
while (op < endOfMatch)
|
||||
*op++ = *copyFrom++;
|
||||
}
|
||||
else {
|
||||
Utils::copy(op, lowPrefix, restSize);
|
||||
op += restSize;
|
||||
}
|
||||
|
@ -798,7 +923,8 @@ FORCE_INLINE int LZ4_decompress_generic(
|
|||
match += dec32table[offset];
|
||||
Utils::copy<4>(op + 4, match);
|
||||
match -= dec64;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
LZ4_copy8(op, match);
|
||||
match += 8;
|
||||
}
|
||||
|
@ -806,16 +932,20 @@ FORCE_INLINE int LZ4_decompress_generic(
|
|||
|
||||
if (unlikely(cpy > oend - 12)) {
|
||||
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) {
|
||||
LZ4_wildCopy(op, match, oCopyLimit);
|
||||
match += oCopyLimit - op;
|
||||
op = oCopyLimit;
|
||||
}
|
||||
while (op < cpy) *op++ = *match++;
|
||||
} else {
|
||||
while (op < cpy)
|
||||
*op++ = *match++;
|
||||
}
|
||||
else {
|
||||
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 */
|
||||
}
|
||||
|
@ -852,7 +982,18 @@ int LZ4_compress_fast(const char *source, char *dest, int inputSize, int maxOutp
|
|||
|
||||
int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) noexcept
|
||||
{
|
||||
return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE *)dest, NULL, 0);
|
||||
return LZ4_decompress_generic(
|
||||
source,
|
||||
dest,
|
||||
compressedSize,
|
||||
maxDecompressedSize,
|
||||
endOnInputSize,
|
||||
full,
|
||||
0,
|
||||
noDict,
|
||||
(BYTE*)dest,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -12,16 +12,17 @@
|
|||
/****/
|
||||
|
||||
#include "Locator.hpp"
|
||||
|
||||
#include "Identity.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
const SharedPtr< const Locator::EndpointAttributes > Locator::EndpointAttributes::DEFAULT(new Locator::EndpointAttributes());
|
||||
const SharedPtr<const Locator::EndpointAttributes>
|
||||
Locator::EndpointAttributes::DEFAULT(new Locator::EndpointAttributes());
|
||||
|
||||
Locator::Locator(const char *const str) noexcept :
|
||||
__refCount(0)
|
||||
Locator::Locator(const char* const str) noexcept : __refCount(0)
|
||||
{
|
||||
if (! fromString(str)) {
|
||||
m_revision = 0;
|
||||
|
@ -33,14 +34,18 @@ Locator::Locator(const char *const str) noexcept :
|
|||
|
||||
bool Locator::add(const Endpoint& ep, const SharedPtr<const EndpointAttributes>& a)
|
||||
{
|
||||
for (Vector< std::pair< Endpoint, SharedPtr< const EndpointAttributes > > >::iterator i(m_endpoints.begin());i!=m_endpoints.end();++i) {
|
||||
for (Vector<std::pair<Endpoint, SharedPtr<const EndpointAttributes> > >::iterator i(m_endpoints.begin());
|
||||
i != m_endpoints.end();
|
||||
++i) {
|
||||
if (i->first == ep) {
|
||||
i->second = ((a) && (a->data[0] != 0)) ? a : EndpointAttributes::DEFAULT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_endpoints.size() < ZT_LOCATOR_MAX_ENDPOINTS) {
|
||||
m_endpoints.push_back(std::pair<Endpoint, SharedPtr< const EndpointAttributes > >(ep, ((a) && (a->data[0] != 0)) ? a : EndpointAttributes::DEFAULT));
|
||||
m_endpoints.push_back(std::pair<Endpoint, SharedPtr<const EndpointAttributes> >(
|
||||
ep,
|
||||
((a) && (a->data[0] != 0)) ? a : EndpointAttributes::DEFAULT));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -72,17 +77,25 @@ bool Locator::verify(const Identity &id) const noexcept
|
|||
const unsigned int signlen = marshal(signdata, true);
|
||||
return id.verify(signdata, signlen, m_signature.data(), m_signature.size());
|
||||
}
|
||||
} catch (...) {} // fail verify on any unexpected exception
|
||||
}
|
||||
catch (...) {
|
||||
} // fail verify on any unexpected exception
|
||||
return false;
|
||||
}
|
||||
|
||||
char* Locator::toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept
|
||||
{
|
||||
static_assert(ZT_LOCATOR_STRING_SIZE_MAX > ((((ZT_LOCATOR_MARSHAL_SIZE_MAX / 5) + 1) * 8) + ZT_ADDRESS_LENGTH_HEX + 1), "overflow");
|
||||
static_assert(
|
||||
ZT_LOCATOR_STRING_SIZE_MAX > ((((ZT_LOCATOR_MARSHAL_SIZE_MAX / 5) + 1) * 8) + ZT_ADDRESS_LENGTH_HEX + 1),
|
||||
"overflow");
|
||||
uint8_t bin[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||
m_signer.toString(s);
|
||||
s[ZT_ADDRESS_LENGTH_HEX] = '@';
|
||||
Utils::b32e(bin, marshal(bin, false), s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_LOCATOR_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
Utils::b32e(
|
||||
bin,
|
||||
marshal(bin, false),
|
||||
s + (ZT_ADDRESS_LENGTH_HEX + 1),
|
||||
ZT_LOCATOR_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -107,7 +120,9 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool exclu
|
|||
|
||||
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t)m_endpoints.size());
|
||||
p += 2;
|
||||
for (Vector< std::pair< Endpoint, SharedPtr< const EndpointAttributes > > >::const_iterator e(m_endpoints.begin());e != m_endpoints.end();++e) {
|
||||
for (Vector<std::pair<Endpoint, SharedPtr<const EndpointAttributes> > >::const_iterator e(m_endpoints.begin());
|
||||
e != m_endpoints.end();
|
||||
++e) {
|
||||
int l = e->first.marshal(data + p);
|
||||
if (l <= 0)
|
||||
return -1;
|
||||
|
@ -117,7 +132,8 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool exclu
|
|||
if (l > 0) {
|
||||
Utils::copy(data + p, e->second->data, (unsigned int)l);
|
||||
p += l;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data[p++] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +179,8 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
if (l <= 0) {
|
||||
m_endpoints[i].second = EndpointAttributes::DEFAULT;
|
||||
++p;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_endpoints[i].second.set(new EndpointAttributes());
|
||||
Utils::copy(const_cast<uint8_t*>(m_endpoints[i].second->data), data + p, (unsigned int)l);
|
||||
p += l;
|
||||
|
@ -191,15 +208,20 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept
|
|||
return p;
|
||||
}
|
||||
|
||||
struct p_SortByEndpoint
|
||||
{
|
||||
struct p_SortByEndpoint {
|
||||
// There can't be more than one of the same endpoint, so only need to sort
|
||||
// by endpoint.
|
||||
ZT_INLINE bool operator()(const std::pair< Endpoint, SharedPtr< const Locator::EndpointAttributes > > &a,const std::pair< Endpoint, SharedPtr< const Locator::EndpointAttributes > > &b) const noexcept
|
||||
{ return a.first < b.first; }
|
||||
ZT_INLINE bool operator()(
|
||||
const std::pair<Endpoint, SharedPtr<const Locator::EndpointAttributes> >& a,
|
||||
const std::pair<Endpoint, SharedPtr<const Locator::EndpointAttributes> >& b) const noexcept
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
void Locator::m_sortEndpoints() noexcept
|
||||
{ std::sort(m_endpoints.begin(), m_endpoints.end(), p_SortByEndpoint()); }
|
||||
{
|
||||
std::sort(m_endpoints.begin(), m_endpoints.end(), p_SortByEndpoint());
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
104
core/Locator.hpp
104
core/Locator.hpp
|
@ -15,13 +15,13 @@
|
|||
#define ZT_LOCATOR_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
|
||||
/**
|
||||
* Maximum size of endpoint attributes dictionary plus one byte for size.
|
||||
|
@ -35,7 +35,10 @@
|
|||
*/
|
||||
#define ZT_LOCATOR_MAX_ENDPOINTS 16
|
||||
|
||||
#define ZT_LOCATOR_MARSHAL_SIZE_MAX (8 + ZT_ADDRESS_LENGTH + 2 + (ZT_LOCATOR_MAX_ENDPOINTS * (ZT_ENDPOINT_MARSHAL_SIZE_MAX + ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE)) + 2 + 2 + ZT_SIGNATURE_BUFFER_SIZE)
|
||||
#define ZT_LOCATOR_MARSHAL_SIZE_MAX \
|
||||
(8 + ZT_ADDRESS_LENGTH + 2 \
|
||||
+ (ZT_LOCATOR_MAX_ENDPOINTS * (ZT_ENDPOINT_MARSHAL_SIZE_MAX + ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE)) + 2 + 2 \
|
||||
+ ZT_SIGNATURE_BUFFER_SIZE)
|
||||
|
||||
/**
|
||||
* Maximum size of a string format Locator (this is way larger than needed)
|
||||
|
@ -50,8 +53,7 @@ namespace ZeroTier {
|
|||
* A locator contains long-lived endpoints for a node such as IP/port pairs,
|
||||
* URLs, or other nodes, and is signed by the node it describes.
|
||||
*/
|
||||
class Locator
|
||||
{
|
||||
class Locator {
|
||||
friend class SharedPtr<Locator>;
|
||||
friend class SharedPtr<const Locator>;
|
||||
|
||||
|
@ -62,8 +64,7 @@ public:
|
|||
* This is specified for future use, but there are currently no attributes
|
||||
* defined. A Dictionary is used for serialization for extensibility.
|
||||
*/
|
||||
struct EndpointAttributes
|
||||
{
|
||||
struct EndpointAttributes {
|
||||
friend class SharedPtr<Locator::EndpointAttributes>;
|
||||
friend class SharedPtr<const Locator::EndpointAttributes>;
|
||||
|
||||
|
@ -81,41 +82,56 @@ public:
|
|||
uint8_t data[ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE];
|
||||
|
||||
ZT_INLINE EndpointAttributes() noexcept
|
||||
{ Utils::zero< ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE >(data); }
|
||||
{
|
||||
Utils::zero<ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE>(data);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const EndpointAttributes& a) const noexcept
|
||||
{ return ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) == 0)); }
|
||||
{
|
||||
return ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) == 0));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const EndpointAttributes& a) const noexcept
|
||||
{ return ((data[0] < a.data[0]) || ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) < 0))); }
|
||||
{
|
||||
return ((data[0] < a.data[0]) || ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) < 0)));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const EndpointAttributes& a) const noexcept
|
||||
{ return !(*this == a); }
|
||||
{
|
||||
return ! (*this == a);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const EndpointAttributes& a) const noexcept
|
||||
{ return (a < *this); }
|
||||
{
|
||||
return (a < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const EndpointAttributes& a) const noexcept
|
||||
{ return !(a < *this); }
|
||||
{
|
||||
return ! (a < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const EndpointAttributes& a) const noexcept
|
||||
{ return !(*this < a); }
|
||||
{
|
||||
return ! (*this < a);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<int> __refCount;
|
||||
};
|
||||
|
||||
ZT_INLINE Locator() noexcept:
|
||||
m_revision(0)
|
||||
{}
|
||||
ZT_INLINE Locator() noexcept : m_revision(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Locator(const Locator &l) noexcept:
|
||||
m_revision(l.m_revision),
|
||||
m_signer(l.m_signer),
|
||||
m_endpoints(l.m_endpoints),
|
||||
m_signature(l.m_signature),
|
||||
__refCount(0)
|
||||
{}
|
||||
ZT_INLINE Locator(const Locator& l) noexcept
|
||||
: m_revision(l.m_revision)
|
||||
, m_signer(l.m_signer)
|
||||
, m_endpoints(l.m_endpoints)
|
||||
, m_signature(l.m_signature)
|
||||
, __refCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Locator(const char* const str) noexcept;
|
||||
|
||||
|
@ -123,25 +139,33 @@ public:
|
|||
* @return Timestamp (a.k.a. revision number) set by Location signer
|
||||
*/
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_revision; }
|
||||
{
|
||||
return m_revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ZeroTier address of signer
|
||||
*/
|
||||
ZT_INLINE Address signer() const noexcept
|
||||
{ return m_signer; }
|
||||
{
|
||||
return m_signer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Endpoints specified in locator
|
||||
*/
|
||||
ZT_INLINE const Vector<std::pair<Endpoint, SharedPtr<const EndpointAttributes> > >& endpoints() const noexcept
|
||||
{ return m_endpoints; }
|
||||
{
|
||||
return m_endpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Signature data
|
||||
*/
|
||||
ZT_INLINE const FCV<uint8_t, ZT_SIGNATURE_BUFFER_SIZE>& signature() const noexcept
|
||||
{ return m_signature; }
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an endpoint to this locator
|
||||
|
@ -197,10 +221,14 @@ public:
|
|||
bool fromString(const char* s) noexcept;
|
||||
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return m_revision > 0; }
|
||||
{
|
||||
return m_revision > 0;
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_LOCATOR_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], bool excludeSignature = false) const noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
@ -208,14 +236,16 @@ public:
|
|||
ZT_INLINE bool operator==(const Locator& l) const noexcept
|
||||
{
|
||||
const unsigned long es = (unsigned long)m_endpoints.size();
|
||||
if ((m_revision == l.m_revision) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size()) && (m_signature == l.m_signature)) {
|
||||
if ((m_revision == l.m_revision) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size())
|
||||
&& (m_signature == l.m_signature)) {
|
||||
for (unsigned long i = 0; i < es; ++i) {
|
||||
if (m_endpoints[i].first != l.m_endpoints[i].first)
|
||||
return false;
|
||||
if (! m_endpoints[i].second) {
|
||||
if (l.m_endpoints[i].second)
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((! l.m_endpoints[i].second) || (*(m_endpoints[i].second) != *(l.m_endpoints[i].second)))
|
||||
return false;
|
||||
}
|
||||
|
@ -226,7 +256,9 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Locator& l) const noexcept
|
||||
{ return !(*this == l); }
|
||||
{
|
||||
return ! (*this == l);
|
||||
}
|
||||
|
||||
private:
|
||||
void m_sortEndpoints() noexcept;
|
||||
|
|
137
core/MAC.hpp
137
core/MAC.hpp
|
@ -14,55 +14,70 @@
|
|||
#ifndef ZT_MAC_HPP
|
||||
#define ZT_MAC_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* 48-byte Ethernet MAC address
|
||||
*/
|
||||
class MAC : public TriviallyCopyable
|
||||
{
|
||||
class MAC : public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE MAC() noexcept : m_mac(0ULL)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE MAC(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d, const uint8_t e, const uint8_t f) noexcept:
|
||||
m_mac((((uint64_t)a) << 40U) | (((uint64_t)b) << 32U) | (((uint64_t)c) << 24U) | (((uint64_t)d) << 16U) | (((uint64_t)e) << 8U) | ((uint64_t)f))
|
||||
{}
|
||||
ZT_INLINE
|
||||
MAC(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d, const uint8_t e, const uint8_t f) noexcept
|
||||
: m_mac(
|
||||
(((uint64_t)a) << 40U) | (((uint64_t)b) << 32U) | (((uint64_t)c) << 24U) | (((uint64_t)d) << 16U)
|
||||
| (((uint64_t)e) << 8U) | ((uint64_t)f))
|
||||
{
|
||||
}
|
||||
|
||||
explicit ZT_INLINE MAC(const uint64_t m) noexcept:
|
||||
m_mac(m)
|
||||
{}
|
||||
explicit ZT_INLINE MAC(const uint64_t m) noexcept : m_mac(m)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ZT_INLINE MAC(const uint8_t b[6]) noexcept
|
||||
{ setTo(b); }
|
||||
{
|
||||
setTo(b);
|
||||
}
|
||||
|
||||
ZT_INLINE MAC(const Address& ztaddr, const uint64_t nwid) noexcept
|
||||
{ fromAddress(ztaddr, nwid); }
|
||||
{
|
||||
fromAddress(ztaddr, nwid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MAC in 64-bit integer
|
||||
*/
|
||||
ZT_INLINE uint64_t toInt() const noexcept
|
||||
{ return m_mac; }
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set MAC to zero
|
||||
*/
|
||||
ZT_INLINE void zero() noexcept
|
||||
{ m_mac = 0ULL; }
|
||||
{
|
||||
m_mac = 0ULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bits Raw MAC in big-endian byte order
|
||||
* @param len Length, must be >= 6 or result is zero
|
||||
*/
|
||||
ZT_INLINE void setTo(const uint8_t b[6]) noexcept
|
||||
{ m_mac = ((uint64_t)b[0] << 40U) | ((uint64_t)b[1] << 32U) | ((uint64_t)b[2] << 24U) | ((uint64_t)b[3] << 16U) | ((uint64_t)b[4] << 8U) | (uint64_t)b[5]; }
|
||||
{
|
||||
m_mac = ((uint64_t)b[0] << 40U) | ((uint64_t)b[1] << 32U) | ((uint64_t)b[2] << 24U) | ((uint64_t)b[3] << 16U)
|
||||
| ((uint64_t)b[4] << 8U) | (uint64_t)b[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param buf Destination buffer for MAC in big-endian byte order
|
||||
|
@ -82,13 +97,17 @@ public:
|
|||
* @return True if this is broadcast (all 0xff)
|
||||
*/
|
||||
ZT_INLINE bool isBroadcast() const noexcept
|
||||
{ return m_mac; }
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if this is a multicast MAC
|
||||
*/
|
||||
ZT_INLINE bool isMulticast() const noexcept
|
||||
{ return ((m_mac & 0x010000000000ULL) != 0ULL); }
|
||||
{
|
||||
return ((m_mac & 0x010000000000ULL) != 0ULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this MAC to a MAC derived from an address and a network ID
|
||||
|
@ -118,7 +137,8 @@ public:
|
|||
ZT_INLINE Address toAddress(uint64_t nwid) const noexcept
|
||||
{
|
||||
uint64_t a = m_mac & 0xffffffffffULL; // least significant 40 bits of MAC are formed from address
|
||||
a ^= ((nwid >> 8U) & 0xffU) << 32U; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it
|
||||
a ^= ((nwid >> 8U) & 0xffU)
|
||||
<< 32U; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it
|
||||
a ^= ((nwid >> 16U) & 0xffU) << 24U;
|
||||
a ^= ((nwid >> 24U) & 0xffU) << 16U;
|
||||
a ^= ((nwid >> 32U) & 0xffU) << 8U;
|
||||
|
@ -132,8 +152,10 @@ public:
|
|||
*/
|
||||
static ZT_INLINE unsigned char firstOctetForNetwork(uint64_t nwid) noexcept
|
||||
{
|
||||
const uint8_t a = ((uint8_t)(nwid & 0xfeU) | 0x02U); // locally administered, not multicast, from LSB of network ID
|
||||
return ((a == 0x52) ? 0x32 : a); // blacklist 0x52 since it's used by KVM, libvirt, and other popular virtualization engines... seems de-facto standard on Linux
|
||||
const uint8_t a =
|
||||
((uint8_t)(nwid & 0xfeU) | 0x02U); // locally administered, not multicast, from LSB of network ID
|
||||
return ((a == 0x52) ? 0x32 : a); // blacklist 0x52 since it's used by KVM, libvirt, and other popular
|
||||
// virtualization engines... seems de-facto standard on Linux
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,22 +163,32 @@ public:
|
|||
* @return Byte at said position (address interpreted in big-endian order)
|
||||
*/
|
||||
ZT_INLINE uint8_t operator[](unsigned int i) const noexcept
|
||||
{ return (uint8_t)(m_mac >> (unsigned int)(40 - (i * 8))); }
|
||||
{
|
||||
return (uint8_t)(m_mac >> (unsigned int)(40 - (i * 8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 6, which is the number of bytes in a MAC, for container compliance
|
||||
*/
|
||||
ZT_INLINE unsigned int size() const noexcept
|
||||
{ return 6; }
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)Utils::hash64(m_mac); }
|
||||
{
|
||||
return (unsigned long)Utils::hash64(m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_mac != 0ULL); }
|
||||
{
|
||||
return (m_mac != 0ULL);
|
||||
}
|
||||
|
||||
ZT_INLINE operator uint64_t() const noexcept
|
||||
{ return m_mac; }
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this MAC to a standard format colon-separated hex string
|
||||
|
@ -211,7 +243,8 @@ public:
|
|||
c = (uint64_t)hc - 87;
|
||||
else if ((hc >= 65) && (hc <= 70))
|
||||
c = (uint64_t)hc - 55;
|
||||
else continue;
|
||||
else
|
||||
continue;
|
||||
m_mac = (m_mac << 4U) | c;
|
||||
}
|
||||
m_mac &= 0xffffffffffffULL;
|
||||
|
@ -225,40 +258,64 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE bool operator==(const MAC& m) const noexcept
|
||||
{ return (m_mac == m.m_mac); }
|
||||
{
|
||||
return (m_mac == m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const MAC& m) const noexcept
|
||||
{ return (m_mac != m.m_mac); }
|
||||
{
|
||||
return (m_mac != m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const MAC& m) const noexcept
|
||||
{ return (m_mac < m.m_mac); }
|
||||
{
|
||||
return (m_mac < m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const MAC& m) const noexcept
|
||||
{ return (m_mac <= m.m_mac); }
|
||||
{
|
||||
return (m_mac <= m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const MAC& m) const noexcept
|
||||
{ return (m_mac > m.m_mac); }
|
||||
{
|
||||
return (m_mac > m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const MAC& m) const noexcept
|
||||
{ return (m_mac >= m.m_mac); }
|
||||
{
|
||||
return (m_mac >= m.m_mac);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const uint64_t m) const noexcept
|
||||
{ return (m_mac == m); }
|
||||
{
|
||||
return (m_mac == m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const uint64_t m) const noexcept
|
||||
{ return (m_mac != m); }
|
||||
{
|
||||
return (m_mac != m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const uint64_t m) const noexcept
|
||||
{ return (m_mac < m); }
|
||||
{
|
||||
return (m_mac < m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const uint64_t m) const noexcept
|
||||
{ return (m_mac <= m); }
|
||||
{
|
||||
return (m_mac <= m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const uint64_t m) const noexcept
|
||||
{ return (m_mac > m); }
|
||||
{
|
||||
return (m_mac > m);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const uint64_t m) const noexcept
|
||||
{ return (m_mac >= m); }
|
||||
{
|
||||
return (m_mac >= m);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_mac;
|
||||
|
|
147
core/MIMC52.cpp
147
core/MIMC52.cpp
|
@ -11,37 +11,131 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "MIMC52.hpp"
|
||||
|
||||
#include "AES.hpp"
|
||||
#include "Constants.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
// Largest 1024 primes of form 6k + 5 and less than 2^52. Only the least significant 32
|
||||
// bits need to be here, as the most significant bits are all 1.
|
||||
const uint32_t ZT_MIMC52_PRIMES[1024] = {4294895267, 4294895477, 4294895513, 4294895519, 4294895543, 4294895567, 4294895657, 4294895711, 4294895777, 4294895861, 4294895909, 4294895921, 4294895969, 4294896011, 4294896149, 4294896227, 4294896401, 4294896473, 4294896527, 4294896563, 4294896653, 4294896731, 4294896863, 4294896899, 4294896983, 4294897037, 4294897103, 4294897331, 4294897349, 4294897451, 4294897571, 4294897661, 4294897703, 4294897757, 4294897793, 4294897811, 4294897817, 4294897829, 4294897877, 4294897919, 4294897991, 4294898027, 4294898129, 4294898153, 4294898231, 4294898273,
|
||||
4294898279, 4294898291, 4294898363, 4294898369, 4294898417, 4294898423, 4294898453, 4294898489, 4294898573, 4294898579, 4294898639, 4294898693, 4294898747, 4294898759, 4294898867, 4294898879, 4294898909, 4294898921, 4294898933, 4294899011, 4294899041, 4294899047, 4294899203, 4294899221, 4294899227, 4294899287, 4294899341, 4294899431, 4294899509, 4294899533, 4294899539, 4294899551, 4294899629, 4294899791, 4294899809, 4294899971, 4294900001, 4294900007, 4294900013, 4294900307, 4294900331, 4294900427, 4294900469, 4294900481, 4294900541, 4294900583,
|
||||
4294900781, 4294900853, 4294900931, 4294900991, 4294901033, 4294901087, 4294901159, 4294901267, 4294901393, 4294901411, 4294901489, 4294901657, 4294902011, 4294902071, 4294902101, 4294902107, 4294902353, 4294902377, 4294902599, 4294902647, 4294902743, 4294902869, 4294902977, 4294903067, 4294903103, 4294903259, 4294903289, 4294903397, 4294903421, 4294903493, 4294903577, 4294903631, 4294903637, 4294903733, 4294903799, 4294903823, 4294904003, 4294904033, 4294904081, 4294904129, 4294904279, 4294904297, 4294904303, 4294904333, 4294904351, 4294904381,
|
||||
4294904453, 4294904519, 4294904561, 4294904639, 4294904657, 4294904747, 4294904807, 4294904843, 4294905089, 4294905149, 4294905293, 4294905299, 4294905311, 4294905443, 4294905479, 4294905539, 4294905623, 4294905641, 4294905671, 4294905707, 4294905887, 4294905977, 4294906091, 4294906103, 4294906139, 4294906157, 4294906223, 4294906259, 4294906487, 4294906493, 4294906523, 4294906547, 4294906553, 4294906571, 4294906577, 4294906589, 4294906703, 4294906733, 4294906763, 4294906841, 4294906859, 4294906937, 4294907057, 4294907063, 4294907141, 4294907231,
|
||||
4294907249, 4294907261, 4294907267, 4294907387, 4294907417, 4294907567, 4294907603, 4294907699, 4294907789, 4294907849, 4294907873, 4294907879, 4294908023, 4294908071, 4294908119, 4294908209, 4294908227, 4294908329, 4294908491, 4294908503, 4294908569, 4294908653, 4294908713, 4294908719, 4294908791, 4294908839, 4294908869, 4294908989, 4294909031, 4294909067, 4294909109, 4294909253, 4294909529, 4294909589, 4294909643, 4294909739, 4294909799, 4294909811, 4294909853, 4294910003, 4294910039, 4294910189, 4294910201, 4294910219, 4294910273, 4294910333,
|
||||
4294910369, 4294910393, 4294910471, 4294910549, 4294910651, 4294910669, 4294910681, 4294910711, 4294910753, 4294910801, 4294910981, 4294911053, 4294911143, 4294911227, 4294911239, 4294911359, 4294911383, 4294911407, 4294911521, 4294911551, 4294911611, 4294911641, 4294911689, 4294911719, 4294911869, 4294912109, 4294912133, 4294912151, 4294912187, 4294912223, 4294912331, 4294912439, 4294912607, 4294912703, 4294912859, 4294912871, 4294912907, 4294912961, 4294913003, 4294913111, 4294913309, 4294913333, 4294913357, 4294913399, 4294913411, 4294913459,
|
||||
4294913501, 4294913531, 4294913591, 4294913609, 4294913663, 4294913783, 4294913819, 4294913903, 4294914137, 4294914413, 4294914473, 4294914497, 4294914527, 4294914551, 4294914593, 4294914611, 4294914659, 4294914671, 4294914743, 4294914863, 4294914917, 4294915061, 4294915103, 4294915139, 4294915217, 4294915223, 4294915253, 4294915283, 4294915373, 4294915433, 4294915607, 4294916069, 4294916213, 4294916267, 4294916303, 4294916393, 4294916441, 4294916477, 4294916507, 4294916573, 4294916633, 4294916687, 4294916783, 4294916837, 4294916897, 4294916921,
|
||||
4294917029, 4294917047, 4294917101, 4294917203, 4294917287, 4294917299, 4294917389, 4294917437, 4294917527, 4294917557, 4294917611, 4294917617, 4294917689, 4294917821, 4294917857, 4294917917, 4294917941, 4294918169, 4294918187, 4294918307, 4294918409, 4294918433, 4294918481, 4294918703, 4294918709, 4294918733, 4294918799, 4294918871, 4294919009, 4294919249, 4294919279, 4294919291, 4294919363, 4294919381, 4294919441, 4294919447, 4294919549, 4294919579, 4294919633, 4294919657, 4294919669, 4294919693, 4294919711, 4294920029, 4294920059, 4294920089,
|
||||
4294920197, 4294920239, 4294920257, 4294920263, 4294920269, 4294920341, 4294920353, 4294920407, 4294920503, 4294920599, 4294920647, 4294920743, 4294920803, 4294920809, 4294920881, 4294920899, 4294920983, 4294921043, 4294921139, 4294921151, 4294921181, 4294921229, 4294921289, 4294921331, 4294921343, 4294921391, 4294921469, 4294921709, 4294921721, 4294921823, 4294921847, 4294921889, 4294922057, 4294922171, 4294922201, 4294922237, 4294922309, 4294922399, 4294922447, 4294922507, 4294922513, 4294922549, 4294922609, 4294922663, 4294922861, 4294922933,
|
||||
4294923101, 4294923191, 4294923209, 4294923221, 4294923251, 4294923263, 4294923359, 4294923371, 4294923377, 4294923461, 4294923521, 4294923953, 4294924001, 4294924091, 4294924121, 4294924319, 4294924397, 4294924571, 4294924583, 4294924751, 4294924817, 4294924823, 4294924847, 4294924877, 4294925003, 4294925027, 4294925117, 4294925237, 4294925243, 4294925297, 4294925369, 4294925627, 4294925639, 4294925729, 4294925747, 4294925873, 4294925891, 4294925933, 4294926047, 4294926059, 4294926209, 4294926221, 4294926233, 4294926257, 4294926329, 4294926371,
|
||||
4294926401, 4294926413, 4294926437, 4294926563, 4294926569, 4294926917, 4294926923, 4294926947, 4294926971, 4294927067, 4294927073, 4294927151, 4294927349, 4294927367, 4294927403, 4294927481, 4294927523, 4294927553, 4294927589, 4294927649, 4294927673, 4294927727, 4294927739, 4294927763, 4294927889, 4294928183, 4294928207, 4294928249, 4294928327, 4294928351, 4294928399, 4294928483, 4294928489, 4294928543, 4294928597, 4294928951, 4294928963, 4294928981, 4294929017, 4294929059, 4294929161, 4294929197, 4294929233, 4294929269, 4294929311, 4294929323,
|
||||
4294929341, 4294929383, 4294929401, 4294929497, 4294929509, 4294929581, 4294929707, 4294929743, 4294930043, 4294930121, 4294930193, 4294930223, 4294930349, 4294930403, 4294930571, 4294930613, 4294930721, 4294930751, 4294930877, 4294930931, 4294930961, 4294930967, 4294930973, 4294931021, 4294931051, 4294931057, 4294931063, 4294931219, 4294931273, 4294931339, 4294931423, 4294931441, 4294931453, 4294931567, 4294931639, 4294931717, 4294931897, 4294931969, 4294932023, 4294932053, 4294932239, 4294932299, 4294932443, 4294932671, 4294932677, 4294932731,
|
||||
4294932743, 4294932767, 4294932773, 4294932779, 4294932881, 4294932899, 4294932929, 4294933067, 4294933277, 4294933307, 4294933343, 4294933451, 4294933523, 4294933763, 4294933793, 4294933829, 4294933847, 4294933871, 4294933997, 4294934033, 4294934111, 4294934207, 4294934243, 4294934267, 4294934279, 4294934291, 4294934327, 4294934363, 4294934423, 4294934489, 4294934561, 4294934867, 4294934921, 4294934969, 4294935137, 4294935239, 4294935299, 4294935431, 4294935539, 4294935629, 4294935701, 4294935791, 4294935797, 4294935803, 4294935959, 4294936001,
|
||||
4294936007, 4294936037, 4294936079, 4294936127, 4294936163, 4294936247, 4294936307, 4294936331, 4294936409, 4294936451, 4294936601, 4294936607, 4294936619, 4294936667, 4294936709, 4294936733, 4294936751, 4294936763, 4294936829, 4294936937, 4294936997, 4294937027, 4294937051, 4294937093, 4294937177, 4294937213, 4294937291, 4294937381, 4294937417, 4294937429, 4294937681, 4294937693, 4294937753, 4294937771, 4294937813, 4294937837, 4294937891, 4294937969, 4294938071, 4294938101, 4294938323, 4294938371, 4294938401, 4294938467, 4294938473, 4294938521,
|
||||
4294938599, 4294938731, 4294938779, 4294938833, 4294938899, 4294938977, 4294938983, 4294939067, 4294939127, 4294939223, 4294939277, 4294939331, 4294939337, 4294939391, 4294939457, 4294939559, 4294939673, 4294939691, 4294939901, 4294939991, 4294940087, 4294940093, 4294940189, 4294940213, 4294940417, 4294940657, 4294940699, 4294940753, 4294940801, 4294940873, 4294940951, 4294941047, 4294941143, 4294941161, 4294941227, 4294941281, 4294941377, 4294941509, 4294941551, 4294941701, 4294941731, 4294941767, 4294941911, 4294941923, 4294942043, 4294942139,
|
||||
4294942313, 4294942343, 4294942373, 4294942427, 4294942529, 4294942601, 4294942649, 4294942673, 4294942679, 4294942733, 4294942769, 4294942811, 4294942961, 4294943129, 4294943141, 4294943219, 4294943369, 4294943423, 4294943471, 4294943651, 4294943687, 4294943717, 4294943729, 4294943747, 4294943759, 4294943813, 4294943819, 4294943891, 4294944077, 4294944191, 4294944233, 4294944239, 4294944353, 4294944389, 4294944581, 4294944623, 4294944629, 4294944659, 4294944821, 4294945031, 4294945157, 4294945211, 4294945229, 4294945301, 4294945337, 4294945343,
|
||||
4294945511, 4294945547, 4294945667, 4294945709, 4294945757, 4294945841, 4294945991, 4294946033, 4294946099, 4294946153, 4294946477, 4294946687, 4294946747, 4294946957, 4294946993, 4294947023, 4294947131, 4294947167, 4294947287, 4294947311, 4294947413, 4294947581, 4294947599, 4294947671, 4294947851, 4294947959, 4294948067, 4294948073, 4294948193, 4294948259, 4294948421, 4294948451, 4294948613, 4294948673, 4294948883, 4294949027, 4294949057, 4294949069, 4294949519, 4294949531, 4294949603, 4294949609, 4294949627, 4294949693, 4294949729, 4294949741,
|
||||
4294949807, 4294949921, 4294949939, 4294949981, 4294949993, 4294950083, 4294950173, 4294950197, 4294950251, 4294950287, 4294950317, 4294950323, 4294950329, 4294950581, 4294950593, 4294950617, 4294950629, 4294950713, 4294950929, 4294951151, 4294951163, 4294951169, 4294951379, 4294951583, 4294951613, 4294951853, 4294951907, 4294951913, 4294951937, 4294951961, 4294952063, 4294952183, 4294952393, 4294952543, 4294952549, 4294952597, 4294952627, 4294952687, 4294952723, 4294952729, 4294952789, 4294952819, 4294952873, 4294952891, 4294952903, 4294952969,
|
||||
4294952999, 4294953023, 4294953107, 4294953173, 4294953281, 4294953341, 4294953431, 4294953599, 4294953689, 4294953719, 4294953827, 4294953887, 4294953977, 4294954073, 4294954079, 4294954157, 4294954217, 4294954283, 4294954607, 4294954667, 4294954859, 4294954901, 4294954973, 4294955081, 4294955237, 4294955273, 4294955327, 4294955441, 4294955507, 4294955591, 4294955789, 4294955831, 4294955837, 4294955927, 4294955963, 4294955969, 4294955987, 4294956041, 4294956047, 4294956197, 4294956323, 4294956359, 4294956551, 4294956593, 4294956623, 4294956629,
|
||||
4294956641, 4294956719, 4294956761, 4294956767, 4294956797, 4294956821, 4294956833, 4294957037, 4294957079, 4294957103, 4294957181, 4294957349, 4294957379, 4294957433, 4294957463, 4294957511, 4294957577, 4294957727, 4294957859, 4294957877, 4294958039, 4294958153, 4294958309, 4294958417, 4294958441, 4294958693, 4294958717, 4294958753, 4294958903, 4294958909, 4294959017, 4294959071, 4294959107, 4294959161, 4294959257, 4294959299, 4294959329, 4294959431, 4294959593, 4294959599, 4294959659, 4294959893, 4294959917, 4294959983, 4294960001, 4294960031,
|
||||
4294960061, 4294960079, 4294960097, 4294960271, 4294960283, 4294960349, 4294960367, 4294960421, 4294960529, 4294960541, 4294960583, 4294960613, 4294960673, 4294960691, 4294960697, 4294960787, 4294960919, 4294961003, 4294961039, 4294961153, 4294961159, 4294961171, 4294961321, 4294961411, 4294961471, 4294961507, 4294961537, 4294961669, 4294961717, 4294961741, 4294961873, 4294962059, 4294962137, 4294962167, 4294962263, 4294962281, 4294962311, 4294962341, 4294962413, 4294962521, 4294962563, 4294962761, 4294962893, 4294963103, 4294963163, 4294963223,
|
||||
4294963313, 4294963349, 4294963427, 4294963547, 4294963559, 4294963721, 4294963799, 4294963817, 4294963901, 4294963919, 4294964021, 4294964279, 4294964297, 4294964363, 4294964387, 4294964411, 4294964567, 4294964603, 4294964687, 4294964777, 4294965041, 4294965071, 4294965119, 4294965221, 4294965251, 4294965287, 4294965413, 4294965569, 4294965647, 4294965671, 4294965689, 4294965779, 4294965839, 4294965893, 4294966091, 4294966109, 4294966127, 4294966157, 4294966187, 4294966199, 4294966211, 4294966403, 4294966457, 4294966499, 4294966541, 4294966637,
|
||||
4294966661, 4294966739, 4294966823, 4294966883, 4294966901, 4294966961, 4294967027, 4294967087, 4294967099, 4294967123, 4294967153, 4294967249};
|
||||
const uint32_t ZT_MIMC52_PRIMES[1024] = {
|
||||
4294895267, 4294895477, 4294895513, 4294895519, 4294895543, 4294895567, 4294895657, 4294895711, 4294895777,
|
||||
4294895861, 4294895909, 4294895921, 4294895969, 4294896011, 4294896149, 4294896227, 4294896401, 4294896473,
|
||||
4294896527, 4294896563, 4294896653, 4294896731, 4294896863, 4294896899, 4294896983, 4294897037, 4294897103,
|
||||
4294897331, 4294897349, 4294897451, 4294897571, 4294897661, 4294897703, 4294897757, 4294897793, 4294897811,
|
||||
4294897817, 4294897829, 4294897877, 4294897919, 4294897991, 4294898027, 4294898129, 4294898153, 4294898231,
|
||||
4294898273, 4294898279, 4294898291, 4294898363, 4294898369, 4294898417, 4294898423, 4294898453, 4294898489,
|
||||
4294898573, 4294898579, 4294898639, 4294898693, 4294898747, 4294898759, 4294898867, 4294898879, 4294898909,
|
||||
4294898921, 4294898933, 4294899011, 4294899041, 4294899047, 4294899203, 4294899221, 4294899227, 4294899287,
|
||||
4294899341, 4294899431, 4294899509, 4294899533, 4294899539, 4294899551, 4294899629, 4294899791, 4294899809,
|
||||
4294899971, 4294900001, 4294900007, 4294900013, 4294900307, 4294900331, 4294900427, 4294900469, 4294900481,
|
||||
4294900541, 4294900583, 4294900781, 4294900853, 4294900931, 4294900991, 4294901033, 4294901087, 4294901159,
|
||||
4294901267, 4294901393, 4294901411, 4294901489, 4294901657, 4294902011, 4294902071, 4294902101, 4294902107,
|
||||
4294902353, 4294902377, 4294902599, 4294902647, 4294902743, 4294902869, 4294902977, 4294903067, 4294903103,
|
||||
4294903259, 4294903289, 4294903397, 4294903421, 4294903493, 4294903577, 4294903631, 4294903637, 4294903733,
|
||||
4294903799, 4294903823, 4294904003, 4294904033, 4294904081, 4294904129, 4294904279, 4294904297, 4294904303,
|
||||
4294904333, 4294904351, 4294904381, 4294904453, 4294904519, 4294904561, 4294904639, 4294904657, 4294904747,
|
||||
4294904807, 4294904843, 4294905089, 4294905149, 4294905293, 4294905299, 4294905311, 4294905443, 4294905479,
|
||||
4294905539, 4294905623, 4294905641, 4294905671, 4294905707, 4294905887, 4294905977, 4294906091, 4294906103,
|
||||
4294906139, 4294906157, 4294906223, 4294906259, 4294906487, 4294906493, 4294906523, 4294906547, 4294906553,
|
||||
4294906571, 4294906577, 4294906589, 4294906703, 4294906733, 4294906763, 4294906841, 4294906859, 4294906937,
|
||||
4294907057, 4294907063, 4294907141, 4294907231, 4294907249, 4294907261, 4294907267, 4294907387, 4294907417,
|
||||
4294907567, 4294907603, 4294907699, 4294907789, 4294907849, 4294907873, 4294907879, 4294908023, 4294908071,
|
||||
4294908119, 4294908209, 4294908227, 4294908329, 4294908491, 4294908503, 4294908569, 4294908653, 4294908713,
|
||||
4294908719, 4294908791, 4294908839, 4294908869, 4294908989, 4294909031, 4294909067, 4294909109, 4294909253,
|
||||
4294909529, 4294909589, 4294909643, 4294909739, 4294909799, 4294909811, 4294909853, 4294910003, 4294910039,
|
||||
4294910189, 4294910201, 4294910219, 4294910273, 4294910333, 4294910369, 4294910393, 4294910471, 4294910549,
|
||||
4294910651, 4294910669, 4294910681, 4294910711, 4294910753, 4294910801, 4294910981, 4294911053, 4294911143,
|
||||
4294911227, 4294911239, 4294911359, 4294911383, 4294911407, 4294911521, 4294911551, 4294911611, 4294911641,
|
||||
4294911689, 4294911719, 4294911869, 4294912109, 4294912133, 4294912151, 4294912187, 4294912223, 4294912331,
|
||||
4294912439, 4294912607, 4294912703, 4294912859, 4294912871, 4294912907, 4294912961, 4294913003, 4294913111,
|
||||
4294913309, 4294913333, 4294913357, 4294913399, 4294913411, 4294913459, 4294913501, 4294913531, 4294913591,
|
||||
4294913609, 4294913663, 4294913783, 4294913819, 4294913903, 4294914137, 4294914413, 4294914473, 4294914497,
|
||||
4294914527, 4294914551, 4294914593, 4294914611, 4294914659, 4294914671, 4294914743, 4294914863, 4294914917,
|
||||
4294915061, 4294915103, 4294915139, 4294915217, 4294915223, 4294915253, 4294915283, 4294915373, 4294915433,
|
||||
4294915607, 4294916069, 4294916213, 4294916267, 4294916303, 4294916393, 4294916441, 4294916477, 4294916507,
|
||||
4294916573, 4294916633, 4294916687, 4294916783, 4294916837, 4294916897, 4294916921, 4294917029, 4294917047,
|
||||
4294917101, 4294917203, 4294917287, 4294917299, 4294917389, 4294917437, 4294917527, 4294917557, 4294917611,
|
||||
4294917617, 4294917689, 4294917821, 4294917857, 4294917917, 4294917941, 4294918169, 4294918187, 4294918307,
|
||||
4294918409, 4294918433, 4294918481, 4294918703, 4294918709, 4294918733, 4294918799, 4294918871, 4294919009,
|
||||
4294919249, 4294919279, 4294919291, 4294919363, 4294919381, 4294919441, 4294919447, 4294919549, 4294919579,
|
||||
4294919633, 4294919657, 4294919669, 4294919693, 4294919711, 4294920029, 4294920059, 4294920089, 4294920197,
|
||||
4294920239, 4294920257, 4294920263, 4294920269, 4294920341, 4294920353, 4294920407, 4294920503, 4294920599,
|
||||
4294920647, 4294920743, 4294920803, 4294920809, 4294920881, 4294920899, 4294920983, 4294921043, 4294921139,
|
||||
4294921151, 4294921181, 4294921229, 4294921289, 4294921331, 4294921343, 4294921391, 4294921469, 4294921709,
|
||||
4294921721, 4294921823, 4294921847, 4294921889, 4294922057, 4294922171, 4294922201, 4294922237, 4294922309,
|
||||
4294922399, 4294922447, 4294922507, 4294922513, 4294922549, 4294922609, 4294922663, 4294922861, 4294922933,
|
||||
4294923101, 4294923191, 4294923209, 4294923221, 4294923251, 4294923263, 4294923359, 4294923371, 4294923377,
|
||||
4294923461, 4294923521, 4294923953, 4294924001, 4294924091, 4294924121, 4294924319, 4294924397, 4294924571,
|
||||
4294924583, 4294924751, 4294924817, 4294924823, 4294924847, 4294924877, 4294925003, 4294925027, 4294925117,
|
||||
4294925237, 4294925243, 4294925297, 4294925369, 4294925627, 4294925639, 4294925729, 4294925747, 4294925873,
|
||||
4294925891, 4294925933, 4294926047, 4294926059, 4294926209, 4294926221, 4294926233, 4294926257, 4294926329,
|
||||
4294926371, 4294926401, 4294926413, 4294926437, 4294926563, 4294926569, 4294926917, 4294926923, 4294926947,
|
||||
4294926971, 4294927067, 4294927073, 4294927151, 4294927349, 4294927367, 4294927403, 4294927481, 4294927523,
|
||||
4294927553, 4294927589, 4294927649, 4294927673, 4294927727, 4294927739, 4294927763, 4294927889, 4294928183,
|
||||
4294928207, 4294928249, 4294928327, 4294928351, 4294928399, 4294928483, 4294928489, 4294928543, 4294928597,
|
||||
4294928951, 4294928963, 4294928981, 4294929017, 4294929059, 4294929161, 4294929197, 4294929233, 4294929269,
|
||||
4294929311, 4294929323, 4294929341, 4294929383, 4294929401, 4294929497, 4294929509, 4294929581, 4294929707,
|
||||
4294929743, 4294930043, 4294930121, 4294930193, 4294930223, 4294930349, 4294930403, 4294930571, 4294930613,
|
||||
4294930721, 4294930751, 4294930877, 4294930931, 4294930961, 4294930967, 4294930973, 4294931021, 4294931051,
|
||||
4294931057, 4294931063, 4294931219, 4294931273, 4294931339, 4294931423, 4294931441, 4294931453, 4294931567,
|
||||
4294931639, 4294931717, 4294931897, 4294931969, 4294932023, 4294932053, 4294932239, 4294932299, 4294932443,
|
||||
4294932671, 4294932677, 4294932731, 4294932743, 4294932767, 4294932773, 4294932779, 4294932881, 4294932899,
|
||||
4294932929, 4294933067, 4294933277, 4294933307, 4294933343, 4294933451, 4294933523, 4294933763, 4294933793,
|
||||
4294933829, 4294933847, 4294933871, 4294933997, 4294934033, 4294934111, 4294934207, 4294934243, 4294934267,
|
||||
4294934279, 4294934291, 4294934327, 4294934363, 4294934423, 4294934489, 4294934561, 4294934867, 4294934921,
|
||||
4294934969, 4294935137, 4294935239, 4294935299, 4294935431, 4294935539, 4294935629, 4294935701, 4294935791,
|
||||
4294935797, 4294935803, 4294935959, 4294936001, 4294936007, 4294936037, 4294936079, 4294936127, 4294936163,
|
||||
4294936247, 4294936307, 4294936331, 4294936409, 4294936451, 4294936601, 4294936607, 4294936619, 4294936667,
|
||||
4294936709, 4294936733, 4294936751, 4294936763, 4294936829, 4294936937, 4294936997, 4294937027, 4294937051,
|
||||
4294937093, 4294937177, 4294937213, 4294937291, 4294937381, 4294937417, 4294937429, 4294937681, 4294937693,
|
||||
4294937753, 4294937771, 4294937813, 4294937837, 4294937891, 4294937969, 4294938071, 4294938101, 4294938323,
|
||||
4294938371, 4294938401, 4294938467, 4294938473, 4294938521, 4294938599, 4294938731, 4294938779, 4294938833,
|
||||
4294938899, 4294938977, 4294938983, 4294939067, 4294939127, 4294939223, 4294939277, 4294939331, 4294939337,
|
||||
4294939391, 4294939457, 4294939559, 4294939673, 4294939691, 4294939901, 4294939991, 4294940087, 4294940093,
|
||||
4294940189, 4294940213, 4294940417, 4294940657, 4294940699, 4294940753, 4294940801, 4294940873, 4294940951,
|
||||
4294941047, 4294941143, 4294941161, 4294941227, 4294941281, 4294941377, 4294941509, 4294941551, 4294941701,
|
||||
4294941731, 4294941767, 4294941911, 4294941923, 4294942043, 4294942139, 4294942313, 4294942343, 4294942373,
|
||||
4294942427, 4294942529, 4294942601, 4294942649, 4294942673, 4294942679, 4294942733, 4294942769, 4294942811,
|
||||
4294942961, 4294943129, 4294943141, 4294943219, 4294943369, 4294943423, 4294943471, 4294943651, 4294943687,
|
||||
4294943717, 4294943729, 4294943747, 4294943759, 4294943813, 4294943819, 4294943891, 4294944077, 4294944191,
|
||||
4294944233, 4294944239, 4294944353, 4294944389, 4294944581, 4294944623, 4294944629, 4294944659, 4294944821,
|
||||
4294945031, 4294945157, 4294945211, 4294945229, 4294945301, 4294945337, 4294945343, 4294945511, 4294945547,
|
||||
4294945667, 4294945709, 4294945757, 4294945841, 4294945991, 4294946033, 4294946099, 4294946153, 4294946477,
|
||||
4294946687, 4294946747, 4294946957, 4294946993, 4294947023, 4294947131, 4294947167, 4294947287, 4294947311,
|
||||
4294947413, 4294947581, 4294947599, 4294947671, 4294947851, 4294947959, 4294948067, 4294948073, 4294948193,
|
||||
4294948259, 4294948421, 4294948451, 4294948613, 4294948673, 4294948883, 4294949027, 4294949057, 4294949069,
|
||||
4294949519, 4294949531, 4294949603, 4294949609, 4294949627, 4294949693, 4294949729, 4294949741, 4294949807,
|
||||
4294949921, 4294949939, 4294949981, 4294949993, 4294950083, 4294950173, 4294950197, 4294950251, 4294950287,
|
||||
4294950317, 4294950323, 4294950329, 4294950581, 4294950593, 4294950617, 4294950629, 4294950713, 4294950929,
|
||||
4294951151, 4294951163, 4294951169, 4294951379, 4294951583, 4294951613, 4294951853, 4294951907, 4294951913,
|
||||
4294951937, 4294951961, 4294952063, 4294952183, 4294952393, 4294952543, 4294952549, 4294952597, 4294952627,
|
||||
4294952687, 4294952723, 4294952729, 4294952789, 4294952819, 4294952873, 4294952891, 4294952903, 4294952969,
|
||||
4294952999, 4294953023, 4294953107, 4294953173, 4294953281, 4294953341, 4294953431, 4294953599, 4294953689,
|
||||
4294953719, 4294953827, 4294953887, 4294953977, 4294954073, 4294954079, 4294954157, 4294954217, 4294954283,
|
||||
4294954607, 4294954667, 4294954859, 4294954901, 4294954973, 4294955081, 4294955237, 4294955273, 4294955327,
|
||||
4294955441, 4294955507, 4294955591, 4294955789, 4294955831, 4294955837, 4294955927, 4294955963, 4294955969,
|
||||
4294955987, 4294956041, 4294956047, 4294956197, 4294956323, 4294956359, 4294956551, 4294956593, 4294956623,
|
||||
4294956629, 4294956641, 4294956719, 4294956761, 4294956767, 4294956797, 4294956821, 4294956833, 4294957037,
|
||||
4294957079, 4294957103, 4294957181, 4294957349, 4294957379, 4294957433, 4294957463, 4294957511, 4294957577,
|
||||
4294957727, 4294957859, 4294957877, 4294958039, 4294958153, 4294958309, 4294958417, 4294958441, 4294958693,
|
||||
4294958717, 4294958753, 4294958903, 4294958909, 4294959017, 4294959071, 4294959107, 4294959161, 4294959257,
|
||||
4294959299, 4294959329, 4294959431, 4294959593, 4294959599, 4294959659, 4294959893, 4294959917, 4294959983,
|
||||
4294960001, 4294960031, 4294960061, 4294960079, 4294960097, 4294960271, 4294960283, 4294960349, 4294960367,
|
||||
4294960421, 4294960529, 4294960541, 4294960583, 4294960613, 4294960673, 4294960691, 4294960697, 4294960787,
|
||||
4294960919, 4294961003, 4294961039, 4294961153, 4294961159, 4294961171, 4294961321, 4294961411, 4294961471,
|
||||
4294961507, 4294961537, 4294961669, 4294961717, 4294961741, 4294961873, 4294962059, 4294962137, 4294962167,
|
||||
4294962263, 4294962281, 4294962311, 4294962341, 4294962413, 4294962521, 4294962563, 4294962761, 4294962893,
|
||||
4294963103, 4294963163, 4294963223, 4294963313, 4294963349, 4294963427, 4294963547, 4294963559, 4294963721,
|
||||
4294963799, 4294963817, 4294963901, 4294963919, 4294964021, 4294964279, 4294964297, 4294964363, 4294964387,
|
||||
4294964411, 4294964567, 4294964603, 4294964687, 4294964777, 4294965041, 4294965071, 4294965119, 4294965221,
|
||||
4294965251, 4294965287, 4294965413, 4294965569, 4294965647, 4294965671, 4294965689, 4294965779, 4294965839,
|
||||
4294965893, 4294966091, 4294966109, 4294966127, 4294966157, 4294966187, 4294966199, 4294966211, 4294966403,
|
||||
4294966457, 4294966499, 4294966541, 4294966637, 4294966661, 4294966739, 4294966823, 4294966883, 4294966901,
|
||||
4294966961, 4294967027, 4294967087, 4294967099, 4294967123, 4294967153, 4294967249
|
||||
};
|
||||
|
||||
#ifdef ZT_NO_IEEE_DOUBLE
|
||||
|
||||
|
@ -87,7 +181,8 @@ ZT_INLINE uint64_t modpow52(uint64_t a, uint64_t e, const uint64_t m, const doub
|
|||
}
|
||||
if (likely((e >>= 1U) != 0)) {
|
||||
a = mulmod52(a, a, m, mf);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,6 @@ uint64_t delay(const uint8_t challenge[32], unsigned long rounds);
|
|||
bool verify(const uint8_t challenge[32], unsigned long rounds, uint64_t proof);
|
||||
|
||||
} // namespace MIMC52
|
||||
} // namespcae ZeroTier
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
|
|
164
core/Member.cpp
164
core/Member.cpp
|
@ -11,24 +11,29 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Member.hpp"
|
||||
|
||||
#include "Context.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
Member::Member() :
|
||||
m_comRevocationThreshold(0),
|
||||
m_lastPushedCredentials(0),
|
||||
m_comAgreementLocalTimestamp(0),
|
||||
m_comAgreementRemoteTimestamp(0)
|
||||
Member::Member()
|
||||
: m_comRevocationThreshold(0)
|
||||
, m_lastPushedCredentials(0)
|
||||
, m_comAgreementLocalTimestamp(0)
|
||||
, m_comAgreementRemoteTimestamp(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Member::pushCredentials(const Context &ctx, const CallContext &cc, const SharedPtr< Peer > &to, const NetworkConfig &nconf)
|
||||
void Member::pushCredentials(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const SharedPtr<Peer>& to,
|
||||
const NetworkConfig& nconf)
|
||||
{
|
||||
if (! nconf.com) // sanity check
|
||||
return;
|
||||
|
@ -131,13 +136,29 @@ Member::AddCredentialResult Member::addCredential(
|
|||
{
|
||||
const int64_t newts = com.timestamp();
|
||||
if (newts <= m_comRevocationThreshold) {
|
||||
ctx.t->credentialRejected(cc, 0xd9992121, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0xd9992121,
|
||||
com.networkId(),
|
||||
sourcePeerIdentity,
|
||||
com.id(),
|
||||
com.timestamp(),
|
||||
ZT_CREDENTIAL_TYPE_COM,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
|
||||
const int64_t oldts = m_com.timestamp();
|
||||
if (newts < oldts) {
|
||||
ctx.t->credentialRejected(cc, 0xd9928192, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0xd9928192,
|
||||
com.networkId(),
|
||||
sourcePeerIdentity,
|
||||
com.id(),
|
||||
com.timestamp(),
|
||||
ZT_CREDENTIAL_TYPE_COM,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
if ((newts == oldts) && (m_com == com))
|
||||
|
@ -145,13 +166,29 @@ Member::AddCredentialResult Member::addCredential(
|
|||
|
||||
switch (com.verify(ctx, cc)) {
|
||||
default:
|
||||
ctx.t->credentialRejected(cc, 0x0f198241, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x0f198241,
|
||||
com.networkId(),
|
||||
sourcePeerIdentity,
|
||||
com.id(),
|
||||
com.timestamp(),
|
||||
ZT_CREDENTIAL_TYPE_COM,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return Member::ADD_REJECTED;
|
||||
case Credential::VERIFY_OK:
|
||||
m_com = com;
|
||||
return ADD_ACCEPTED_NEW;
|
||||
case Credential::VERIFY_BAD_SIGNATURE:
|
||||
ctx.t->credentialRejected(cc, 0xbaf0aaaa, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0xbaf0aaaa,
|
||||
com.networkId(),
|
||||
sourcePeerIdentity,
|
||||
com.id(),
|
||||
com.timestamp(),
|
||||
ZT_CREDENTIAL_TYPE_COM,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED);
|
||||
return ADD_REJECTED;
|
||||
case Credential::VERIFY_NEED_IDENTITY:
|
||||
return ADD_DEFERRED_FOR_WHOIS;
|
||||
|
@ -172,22 +209,47 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
|
|||
typename Map<uint32_t, C>::const_iterator rc(remoteCreds.find(cred.id()));
|
||||
if (rc != remoteCreds.end()) {
|
||||
if (rc->second.revision() > cred.revision()) {
|
||||
ctx.t->credentialRejected(cc, 0x40000001, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x40000001,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
cred.id(),
|
||||
cred.revision(),
|
||||
C::credentialType(),
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
|
||||
return Member::ADD_REJECTED;
|
||||
}
|
||||
if (rc->second == cred)
|
||||
return Member::ADD_ACCEPTED_REDUNDANT;
|
||||
}
|
||||
|
||||
typename Map< uint64_t, int64_t >::const_iterator rt(revocations.find(Member::credentialKey(C::credentialType(), cred.id())));
|
||||
typename Map<uint64_t, int64_t>::const_iterator rt(
|
||||
revocations.find(Member::credentialKey(C::credentialType(), cred.id())));
|
||||
if ((rt != revocations.end()) && (rt->second >= cred.revision())) {
|
||||
ctx.t->credentialRejected(cc, 0x24248124, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x24248124,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
cred.id(),
|
||||
cred.revision(),
|
||||
C::credentialType(),
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
|
||||
return Member::ADD_REJECTED;
|
||||
}
|
||||
|
||||
switch (cred.verify(ctx, cc)) {
|
||||
default:
|
||||
ctx.t->credentialRejected(cc, 0x01feba012, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x01feba012,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
cred.id(),
|
||||
cred.revision(),
|
||||
C::credentialType(),
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return Member::ADD_REJECTED;
|
||||
case 0:
|
||||
if (rc == remoteCreds.end())
|
||||
|
@ -198,21 +260,55 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl(
|
|||
}
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag)
|
||||
{ return _addCredImpl< TagCredential >(m_remoteTags, m_revocations, ctx, cc, sourcePeerIdentity, nconf, tag); }
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const TagCredential& tag)
|
||||
{
|
||||
return _addCredImpl<TagCredential>(m_remoteTags, m_revocations, ctx, cc, sourcePeerIdentity, nconf, tag);
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap)
|
||||
{ return _addCredImpl< CapabilityCredential >(m_remoteCaps, m_revocations, ctx, cc, sourcePeerIdentity, nconf, cap); }
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const CapabilityCredential& cap)
|
||||
{
|
||||
return _addCredImpl<CapabilityCredential>(m_remoteCaps, m_revocations, ctx, cc, sourcePeerIdentity, nconf, cap);
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo)
|
||||
{ return _addCredImpl< OwnershipCredential >(m_remoteCoos, m_revocations, ctx, cc, sourcePeerIdentity, nconf, coo); }
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const OwnershipCredential& coo)
|
||||
{
|
||||
return _addCredImpl<OwnershipCredential>(m_remoteCoos, m_revocations, ctx, cc, sourcePeerIdentity, nconf, coo);
|
||||
}
|
||||
|
||||
Member::AddCredentialResult Member::addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev)
|
||||
Member::AddCredentialResult Member::addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const RevocationCredential& rev)
|
||||
{
|
||||
int64_t* rt;
|
||||
switch (rev.verify(ctx, cc)) {
|
||||
default:
|
||||
ctx.t->credentialRejected(cc, 0x938ff009, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x938ff009,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
rev.id(),
|
||||
0,
|
||||
ZT_CREDENTIAL_TYPE_REVOCATION,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return ADD_REJECTED;
|
||||
case 0: {
|
||||
const ZT_CredentialType ct = rev.typeBeingRevoked();
|
||||
|
@ -234,7 +330,15 @@ Member::AddCredentialResult Member::addCredential(const Context &ctx, const Call
|
|||
}
|
||||
return ADD_ACCEPTED_REDUNDANT;
|
||||
default:
|
||||
ctx.t->credentialRejected(cc, 0x0bbbb1a4, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
ctx.t->credentialRejected(
|
||||
cc,
|
||||
0x0bbbb1a4,
|
||||
nconf.networkId,
|
||||
sourcePeerIdentity,
|
||||
rev.id(),
|
||||
0,
|
||||
ZT_CREDENTIAL_TYPE_REVOCATION,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
}
|
||||
|
@ -246,13 +350,9 @@ Member::AddCredentialResult Member::addCredential(const Context &ctx, const Call
|
|||
bool Member::m_isUnspoofableAddress(const NetworkConfig& nconf, const InetAddress& ip) const noexcept
|
||||
{
|
||||
return (
|
||||
ip.isV6() &&
|
||||
nconf.ndpEmulation() &&
|
||||
(
|
||||
(ip == InetAddress::makeIpv66plane(nconf.networkId, m_com.issuedTo().address)) ||
|
||||
(ip == InetAddress::makeIpv6rfc4193(nconf.networkId, m_com.issuedTo().address))
|
||||
)
|
||||
);
|
||||
ip.isV6() && nconf.ndpEmulation()
|
||||
&& ((ip == InetAddress::makeIpv66plane(nconf.networkId, m_com.issuedTo().address))
|
||||
|| (ip == InetAddress::makeIpv6rfc4193(nconf.networkId, m_com.issuedTo().address))));
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
112
core/Member.hpp
112
core/Member.hpp
|
@ -14,14 +14,14 @@
|
|||
#ifndef ZT_MEMBERSHIP_HPP
|
||||
#define ZT_MEMBERSHIP_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "RevocationCredential.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "RevocationCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -36,16 +36,9 @@ class Network;
|
|||
*
|
||||
* This class is not thread safe. It must be locked externally.
|
||||
*/
|
||||
class Member
|
||||
{
|
||||
class Member {
|
||||
public:
|
||||
enum AddCredentialResult
|
||||
{
|
||||
ADD_REJECTED,
|
||||
ADD_ACCEPTED_NEW,
|
||||
ADD_ACCEPTED_REDUNDANT,
|
||||
ADD_DEFERRED_FOR_WHOIS
|
||||
};
|
||||
enum AddCredentialResult { ADD_REJECTED, ADD_ACCEPTED_NEW, ADD_ACCEPTED_REDUNDANT, ADD_DEFERRED_FOR_WHOIS };
|
||||
|
||||
Member();
|
||||
|
||||
|
@ -55,13 +48,16 @@ public:
|
|||
* @param to Peer identity
|
||||
* @param nconf My network config
|
||||
*/
|
||||
void pushCredentials(const Context &ctx, const CallContext &cc, const SharedPtr< Peer > &to, const NetworkConfig &nconf);
|
||||
void
|
||||
pushCredentials(const Context& ctx, const CallContext& cc, const SharedPtr<Peer>& to, const NetworkConfig& nconf);
|
||||
|
||||
/**
|
||||
* @return Time we last pushed credentials to this member
|
||||
*/
|
||||
ZT_INLINE int64_t lastPushedCredentials() const noexcept
|
||||
{ return m_lastPushedCredentials; }
|
||||
{
|
||||
return m_lastPushedCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a remote member's tag (if we have it)
|
||||
|
@ -73,7 +69,9 @@ public:
|
|||
ZT_INLINE const TagCredential* getTag(const NetworkConfig& nconf, const uint32_t id) const noexcept
|
||||
{
|
||||
Map<uint32_t, TagCredential>::const_iterator t(m_remoteTags.find(id));
|
||||
return (((t != m_remoteTags.end()) && (m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second) : (TagCredential *)0);
|
||||
return (
|
||||
((t != m_remoteTags.end()) && (m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second)
|
||||
: (TagCredential*)0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,7 +85,9 @@ public:
|
|||
* Generates a key for internal use in indexing credentials by type and credential ID
|
||||
*/
|
||||
static ZT_INLINE uint64_t credentialKey(const ZT_CredentialType& t, const uint32_t i) noexcept
|
||||
{ return (((uint64_t)t << 32U) | (uint64_t)i); }
|
||||
{
|
||||
return (((uint64_t)t << 32U) | (uint64_t)i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the peer represented by this Membership owns a given address
|
||||
|
@ -97,8 +97,7 @@ public:
|
|||
* @param r Resource to check
|
||||
* @return True if this peer has a certificate of ownership for the given resource
|
||||
*/
|
||||
template< typename T >
|
||||
ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf, const T &r) const noexcept
|
||||
template <typename T> ZT_INLINE bool peerOwnsAddress(const NetworkConfig& nconf, const T& r) const noexcept
|
||||
{
|
||||
if (m_isUnspoofableAddress(nconf, r))
|
||||
return true;
|
||||
|
@ -116,7 +115,8 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool certificateOfMembershipAgress(const MembershipCredential& localCom, const Identity& remoteIdentity)
|
||||
{
|
||||
if ((m_comAgreementLocalTimestamp == localCom.timestamp()) && (m_comAgreementRemoteTimestamp == m_com.timestamp()))
|
||||
if ((m_comAgreementLocalTimestamp == localCom.timestamp())
|
||||
&& (m_comAgreementRemoteTimestamp == m_com.timestamp()))
|
||||
return true;
|
||||
if (m_com.agreesWith(localCom)) {
|
||||
// SECURITY: newer network controllers embed the full fingerprint into the COM. If we are
|
||||
|
@ -129,7 +129,8 @@ public:
|
|||
if (localCom.issuedTo().haveHash()) {
|
||||
if (localCom.issuedTo() != m_com.issuedTo())
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// LEGACY: support networks run by old controllers.
|
||||
if (localCom.issuedTo().address != m_com.issuedTo().address)
|
||||
return false;
|
||||
|
@ -145,18 +146,45 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com);
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag);
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap);
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo);
|
||||
AddCredentialResult addCredential(const Context &ctx, const CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const MembershipCredential& com);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const TagCredential& tag);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const CapabilityCredential& cap);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const OwnershipCredential& coo);
|
||||
AddCredentialResult addCredential(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
const Identity& sourcePeerIdentity,
|
||||
const NetworkConfig& nconf,
|
||||
const RevocationCredential& rev);
|
||||
|
||||
private:
|
||||
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
|
||||
// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
|
||||
// always return true for them. A certificate is not required for these.
|
||||
ZT_INLINE bool m_isUnspoofableAddress(const NetworkConfig& nconf, const MAC& m) const noexcept
|
||||
{ return false; }
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool m_isUnspoofableAddress(const NetworkConfig& nconf, const InetAddress& ip) const noexcept;
|
||||
|
||||
|
@ -166,20 +194,22 @@ private:
|
|||
ZT_INLINE bool m_isCredentialTimestampValid(const NetworkConfig& nconf, const C& remoteCredential) const noexcept
|
||||
{
|
||||
const int64_t ts = remoteCredential.revision();
|
||||
if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) {
|
||||
Map< uint64_t, int64_t >::const_iterator threshold(m_revocations.find(credentialKey(C::credentialType(), remoteCredential.id())));
|
||||
if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts))
|
||||
<= nconf.credentialTimeMaxDelta) {
|
||||
Map<uint64_t, int64_t>::const_iterator threshold(
|
||||
m_revocations.find(credentialKey(C::credentialType(), remoteCredential.id())));
|
||||
return ((threshold == m_revocations.end()) || (ts > threshold->second));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template< typename C >
|
||||
ZT_INLINE void m_cleanCredImpl(const NetworkConfig &nconf, Map< uint32_t, C > &remoteCreds)
|
||||
template <typename C> ZT_INLINE void m_cleanCredImpl(const NetworkConfig& nconf, Map<uint32_t, C>& remoteCreds)
|
||||
{
|
||||
for (typename Map<uint32_t, C>::iterator i(remoteCreds.begin()); i != remoteCreds.end();) {
|
||||
if (! m_isCredentialTimestampValid(nconf, i->second))
|
||||
remoteCreds.erase(i++);
|
||||
else ++i;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,14 +234,14 @@ private:
|
|||
Map<uint32_t, OwnershipCredential> m_remoteCoos;
|
||||
|
||||
public:
|
||||
class CapabilityIterator
|
||||
{
|
||||
class CapabilityIterator {
|
||||
public:
|
||||
ZT_INLINE CapabilityIterator(Member &m, const NetworkConfig &nconf) noexcept:
|
||||
m_hti(m.m_remoteCaps.begin()),
|
||||
m_parent(m),
|
||||
m_nconf(nconf)
|
||||
{}
|
||||
ZT_INLINE CapabilityIterator(Member& m, const NetworkConfig& nconf) noexcept
|
||||
: m_hti(m.m_remoteCaps.begin())
|
||||
, m_parent(m)
|
||||
, m_nconf(nconf)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE CapabilityCredential* next() noexcept
|
||||
{
|
||||
|
|
|
@ -15,13 +15,19 @@
|
|||
|
||||
namespace ZeroTier {
|
||||
|
||||
MembershipCredential::MembershipCredential(const int64_t timestamp, const int64_t timestampMaxDelta, const uint64_t nwid, const Identity &issuedTo) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
m_timestamp(timestamp),
|
||||
m_timestampMaxDelta(timestampMaxDelta),
|
||||
m_networkId(nwid),
|
||||
m_issuedTo(issuedTo.fingerprint()),
|
||||
m_signatureLength(0)
|
||||
{}
|
||||
MembershipCredential::MembershipCredential(
|
||||
const int64_t timestamp,
|
||||
const int64_t timestampMaxDelta,
|
||||
const uint64_t nwid,
|
||||
const Identity& issuedTo) noexcept
|
||||
: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
m_timestamp(timestamp)
|
||||
, m_timestampMaxDelta(timestampMaxDelta)
|
||||
, m_networkId(nwid)
|
||||
, m_issuedTo(issuedTo.fingerprint())
|
||||
, m_signatureLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool MembershipCredential::agreesWith(const MembershipCredential& other) const noexcept
|
||||
{
|
||||
|
@ -31,16 +37,23 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
|||
if (other.m_timestamp > m_timestamp) {
|
||||
if ((other.m_timestamp - m_timestamp) > std::min(m_timestampMaxDelta, other.m_timestampMaxDelta))
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((m_timestamp - other.m_timestamp) > std::min(m_timestampMaxDelta, other.m_timestampMaxDelta))
|
||||
return false;
|
||||
}
|
||||
|
||||
// us <> them
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(m_additionalQualifiers.begin()); i != m_additionalQualifiers.end(); ++i) {
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(
|
||||
m_additionalQualifiers.begin());
|
||||
i != m_additionalQualifiers.end();
|
||||
++i) {
|
||||
if (i->delta != 0xffffffffffffffffULL) {
|
||||
const uint64_t* v2 = nullptr;
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(other.m_additionalQualifiers.begin()); j != other.m_additionalQualifiers.end(); ++i) {
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(
|
||||
other.m_additionalQualifiers.begin());
|
||||
j != other.m_additionalQualifiers.end();
|
||||
++i) {
|
||||
if (j->id == i->id) {
|
||||
v2 = &(j->value);
|
||||
break;
|
||||
|
@ -51,7 +64,8 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
|||
if (*v2 > i->value) {
|
||||
if ((*v2 - i->value) > i->delta)
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((i->value - *v2) > i->delta)
|
||||
return false;
|
||||
}
|
||||
|
@ -59,10 +73,16 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
|||
}
|
||||
|
||||
// them <> us (we need a second pass in case they have qualifiers we don't or vice versa)
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(other.m_additionalQualifiers.begin()); i != other.m_additionalQualifiers.end(); ++i) {
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(
|
||||
other.m_additionalQualifiers.begin());
|
||||
i != other.m_additionalQualifiers.end();
|
||||
++i) {
|
||||
if (i->delta != 0xffffffffffffffffULL) {
|
||||
const uint64_t* v2 = nullptr;
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(m_additionalQualifiers.begin()); j != m_additionalQualifiers.end(); ++i) {
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator j(
|
||||
m_additionalQualifiers.begin());
|
||||
j != m_additionalQualifiers.end();
|
||||
++i) {
|
||||
if (j->id == i->id) {
|
||||
v2 = &(j->value);
|
||||
break;
|
||||
|
@ -73,7 +93,8 @@ bool MembershipCredential::agreesWith(const MembershipCredential &other) const n
|
|||
if (*v2 > i->value) {
|
||||
if ((*v2 - i->value) > i->delta)
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((i->value - *v2) > i->delta)
|
||||
return false;
|
||||
}
|
||||
|
@ -117,12 +138,15 @@ int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_
|
|||
Utils::storeBigEndian<uint16_t>(data + 1, 3);
|
||||
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(data + p, m_issuedTo.hash);
|
||||
p += 48;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// V1 marshal format must shove everything into tuples, resulting in nine.
|
||||
Utils::storeBigEndian<uint16_t>(data + 1, 9);
|
||||
for (int k = 0; k < 6; ++k) {
|
||||
Utils::storeBigEndian<uint64_t>(data + p, (uint64_t)k + 3);
|
||||
Utils::storeMachineEndian< uint64_t >(data + p + 8, Utils::loadMachineEndian< uint64_t >(m_issuedTo.hash + (k * 8)));
|
||||
Utils::storeMachineEndian<uint64_t>(
|
||||
data + p + 8,
|
||||
Utils::loadMachineEndian<uint64_t>(m_issuedTo.hash + (k * 8)));
|
||||
Utils::storeMachineEndian<uint64_t>(data + p + 16, 0xffffffffffffffffULL);
|
||||
p += 24;
|
||||
}
|
||||
|
@ -137,7 +161,8 @@ int MembershipCredential::marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_
|
|||
p += 2;
|
||||
Utils::copy(data + p, m_signature, m_signatureLength);
|
||||
p += (int)m_signatureLength;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// V1 only supports 96-byte signature fields.
|
||||
Utils::copy<96>(data + p, m_signature);
|
||||
p += 96;
|
||||
|
@ -214,7 +239,8 @@ int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
|
|||
m_signatureLength = 96;
|
||||
Utils::copy<96>(m_signature, data + p);
|
||||
return p + 96;
|
||||
} else if (data[0] == 2) {
|
||||
}
|
||||
else if (data[0] == 2) {
|
||||
if ((p + 48) > len)
|
||||
return -1;
|
||||
Utils::copy<48>(m_issuedTo.hash, data + p);
|
||||
|
@ -277,7 +303,10 @@ unsigned int MembershipCredential::m_fillSigningBuf(uint64_t *buf) const noexcep
|
|||
buf[p++] = informational;
|
||||
}
|
||||
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(m_additionalQualifiers.begin()); i != m_additionalQualifiers.end(); ++i) { // NOLINT(modernize-loop-convert)
|
||||
for (FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS>::const_iterator i(
|
||||
m_additionalQualifiers.begin());
|
||||
i != m_additionalQualifiers.end();
|
||||
++i) { // NOLINT(modernize-loop-convert)
|
||||
buf[p++] = Utils::hton(i->id);
|
||||
buf[p++] = Utils::hton(i->value);
|
||||
buf[p++] = Utils::hton(i->delta);
|
||||
|
|
|
@ -14,23 +14,24 @@
|
|||
#ifndef ZT_CERTIFICATEOFMEMBERSHIP_HPP
|
||||
#define ZT_CERTIFICATEOFMEMBERSHIP_HPP
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "FCV.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
// Maximum number of additional tuples beyond the standard always-present three.
|
||||
#define ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS 8
|
||||
|
||||
// version + qualifier count + three required qualifiers + additional qualifiers +
|
||||
#define ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX (1 + 2 + (3 * 3 * 8) + (ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS * 3 * 8) + 144 + 5 + 2 + 96)
|
||||
#define ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX \
|
||||
(1 + 2 + (3 * 3 * 8) + (ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS * 3 * 8) + 144 + 5 + 2 + 96)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -96,19 +97,22 @@ class Context;
|
|||
* order with the fingerprint hash being packed into tuple IDs 3-8 and this buffer is
|
||||
* then signed.
|
||||
*/
|
||||
class MembershipCredential : public Credential
|
||||
{
|
||||
class MembershipCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_COM; }
|
||||
{
|
||||
return ZT_CREDENTIAL_TYPE_COM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty certificate of membership
|
||||
*/
|
||||
ZT_INLINE MembershipCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from required fields common to all networks
|
||||
|
@ -118,46 +122,61 @@ public:
|
|||
* @param nwid Network ID
|
||||
* @param issuedTo Certificate recipient
|
||||
*/
|
||||
MembershipCredential(int64_t timestamp, int64_t timestampMaxDelta, uint64_t nwid, const Identity &issuedTo) noexcept;
|
||||
MembershipCredential(int64_t timestamp, int64_t timestampMaxDelta, uint64_t nwid, const Identity& issuedTo)
|
||||
noexcept;
|
||||
|
||||
/**
|
||||
* @return True if there's something here
|
||||
*/
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_networkId != 0); }
|
||||
{
|
||||
return (m_networkId != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Credential ID, always 0 for COMs
|
||||
*/
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return 0; }
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Timestamp for this cert and maximum delta for timestamp
|
||||
*/
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_timestamp; }
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_timestamp; }
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum allowed difference between timestamps
|
||||
*/
|
||||
ZT_INLINE int64_t timestampMaxDelta() const noexcept
|
||||
{ return m_timestampMaxDelta; }
|
||||
{
|
||||
return m_timestampMaxDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Fingerprint of identity to which this cert was issued
|
||||
*/
|
||||
ZT_INLINE const Fingerprint& issuedTo() const noexcept
|
||||
{ return m_issuedTo; }
|
||||
{
|
||||
return m_issuedTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Network ID for which this cert was issued
|
||||
*/
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_networkId; }
|
||||
{
|
||||
return m_networkId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two certificates for parameter agreement
|
||||
|
@ -189,10 +208,14 @@ public:
|
|||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_MEMBERSHIP_CREDENTIAL_MARSHAL_SIZE_MAX], bool v2 = false) const noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
@ -200,19 +223,28 @@ public:
|
|||
private:
|
||||
unsigned int m_fillSigningBuf(uint64_t* buf) const noexcept;
|
||||
|
||||
struct p_Qualifier
|
||||
struct p_Qualifier {
|
||||
ZT_INLINE p_Qualifier() noexcept
|
||||
: id(0)
|
||||
, value(0)
|
||||
, delta(0)
|
||||
{
|
||||
ZT_INLINE p_Qualifier() noexcept: id(0), value(0), delta(0)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE p_Qualifier(const uint64_t id_, const uint64_t value_, const uint64_t delta_) noexcept: id(id_), value(value_), delta(delta_)
|
||||
{}
|
||||
ZT_INLINE p_Qualifier(const uint64_t id_, const uint64_t value_, const uint64_t delta_) noexcept
|
||||
: id(id_)
|
||||
, value(value_)
|
||||
, delta(delta_)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t id;
|
||||
uint64_t value;
|
||||
uint64_t delta;
|
||||
ZT_INLINE bool operator<(const p_Qualifier& q) const noexcept
|
||||
{ return (id < q.id); } // sort order
|
||||
{
|
||||
return (id < q.id);
|
||||
} // sort order
|
||||
};
|
||||
|
||||
FCV<p_Qualifier, ZT_MEMBERSHIP_CREDENTIAL_MAX_ADDITIONAL_QUALIFIERS> m_additionalQualifiers;
|
||||
|
|
|
@ -34,9 +34,7 @@ namespace ZeroTier {
|
|||
* @tparam TUNIT Unit of time in milliseconds (default: 1000 for one second)
|
||||
* @tparam LSIZE Log size in units of time (default: 10 for 10s worth of data)
|
||||
*/
|
||||
template<int64_t TUNIT = 1000, unsigned long LSIZE = 10>
|
||||
class Meter
|
||||
{
|
||||
template <int64_t TUNIT = 1000, unsigned long LSIZE = 10> class Meter {
|
||||
public:
|
||||
/**
|
||||
* Create and initialize a new meter
|
||||
|
@ -44,7 +42,8 @@ public:
|
|||
* @param now Start time
|
||||
*/
|
||||
ZT_INLINE Meter() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a measurement
|
||||
|
@ -59,8 +58,11 @@ public:
|
|||
// to it.
|
||||
const unsigned long bucket = ((unsigned long)(ts / TUNIT)) % LSIZE;
|
||||
if (unlikely(m_bucket.exchange(bucket, std::memory_order_relaxed) != bucket)) {
|
||||
m_totalExclCounts.fetch_add(m_counts[bucket].exchange(count, std::memory_order_relaxed), std::memory_order_relaxed);
|
||||
} else {
|
||||
m_totalExclCounts.fetch_add(
|
||||
m_counts[bucket].exchange(count, std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
else {
|
||||
m_counts[bucket].fetch_add(count, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#define ZT_MULTICASTGROUP_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -37,14 +37,19 @@ namespace ZeroTier {
|
|||
*
|
||||
* MulticastGroup behaves as an immutable value object.
|
||||
*/
|
||||
class MulticastGroup : public TriviallyCopyable
|
||||
{
|
||||
class MulticastGroup : public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE MulticastGroup() noexcept: m_mac(), m_adi(0)
|
||||
{}
|
||||
ZT_INLINE MulticastGroup() noexcept
|
||||
: m_mac()
|
||||
, m_adi(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE MulticastGroup(const MAC &m, uint32_t a) noexcept: m_mac(m), m_adi(a)
|
||||
{}
|
||||
ZT_INLINE MulticastGroup(const MAC& m, uint32_t a) noexcept
|
||||
: m_mac(m)
|
||||
, m_adi(a)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive the multicast group used for address resolution (ARP/NDP) for an IP
|
||||
|
@ -60,12 +65,14 @@ public:
|
|||
// ADI was added, as well as handling other things that want mindless
|
||||
// Ethernet broadcast to all.
|
||||
return MulticastGroup(MAC(0xffffffffffffULL), Utils::ntoh(*((const uint32_t*)ip.rawIpData())));
|
||||
} else if (ip.isV6()) {
|
||||
}
|
||||
else if (ip.isV6()) {
|
||||
// IPv6 is better designed in this respect. We can compute the IPv6
|
||||
// multicast address directly from the IP address, and it gives us
|
||||
// 24 bits of uniqueness. Collisions aren't likely to be common enough
|
||||
// to care about.
|
||||
const uint8_t *const a = reinterpret_cast<const uint8_t *>(ip.rawIpData()); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||
const uint8_t* const a =
|
||||
reinterpret_cast<const uint8_t*>(ip.rawIpData()); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||
return MulticastGroup(MAC(0x33, 0x33, 0xff, a[13], a[14], a[15]), 0);
|
||||
}
|
||||
return MulticastGroup(); // NOLINT(modernize-return-braced-init-list)
|
||||
|
@ -75,19 +82,28 @@ public:
|
|||
* @return Ethernet MAC portion of multicast group
|
||||
*/
|
||||
ZT_INLINE const MAC& mac() const noexcept
|
||||
{ return m_mac; }
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Additional distinguishing information, which is normally zero except for IPv4 ARP where it's the IPv4 address
|
||||
* @return Additional distinguishing information, which is normally zero except for IPv4 ARP where it's the IPv4
|
||||
* address
|
||||
*/
|
||||
ZT_INLINE uint32_t adi() const
|
||||
{ return m_adi; }
|
||||
{
|
||||
return m_adi;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const MulticastGroup& g) const noexcept
|
||||
{ return ((m_mac == g.m_mac) && (m_adi == g.m_adi)); }
|
||||
{
|
||||
return ((m_mac == g.m_mac) && (m_adi == g.m_adi));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const MulticastGroup& g) const noexcept
|
||||
{ return ((m_mac != g.m_mac) || (m_adi != g.m_adi)); }
|
||||
{
|
||||
return ((m_mac != g.m_mac) || (m_adi != g.m_adi));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const MulticastGroup& g) const noexcept
|
||||
{
|
||||
|
@ -99,16 +115,24 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE bool operator>(const MulticastGroup& g) const noexcept
|
||||
{ return (g < *this); }
|
||||
{
|
||||
return (g < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const MulticastGroup& g) const noexcept
|
||||
{ return !(g < *this); }
|
||||
{
|
||||
return ! (g < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const MulticastGroup& g) const noexcept
|
||||
{ return !(*this < g); }
|
||||
{
|
||||
return ! (*this < g);
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (m_mac.hashCode() + (unsigned long)m_adi); }
|
||||
{
|
||||
return (m_mac.hashCode() + (unsigned long)m_adi);
|
||||
}
|
||||
|
||||
private:
|
||||
MAC m_mac;
|
||||
|
|
218
core/Mutex.hpp
218
core/Mutex.hpp
|
@ -36,33 +36,66 @@ namespace ZeroTier {
|
|||
/**
|
||||
* A simple mutual exclusion lock.
|
||||
*/
|
||||
class Mutex
|
||||
{
|
||||
class Mutex {
|
||||
public:
|
||||
#ifdef ZT_USE_PTHREADS
|
||||
ZT_INLINE Mutex() noexcept { pthread_mutex_init(&_mh,nullptr); }
|
||||
ZT_INLINE ~Mutex() noexcept { pthread_mutex_destroy(&_mh); }
|
||||
ZT_INLINE void lock() const noexcept { pthread_mutex_lock(&((const_cast <Mutex *> (this))->_mh)); }
|
||||
ZT_INLINE void unlock() const noexcept { pthread_mutex_unlock(&((const_cast <Mutex *> (this))->_mh)); }
|
||||
ZT_INLINE Mutex() noexcept
|
||||
{
|
||||
pthread_mutex_init(&_mh, nullptr);
|
||||
}
|
||||
ZT_INLINE ~Mutex() noexcept
|
||||
{
|
||||
pthread_mutex_destroy(&_mh);
|
||||
}
|
||||
ZT_INLINE void lock() const noexcept
|
||||
{
|
||||
pthread_mutex_lock(&((const_cast<Mutex*>(this))->_mh));
|
||||
}
|
||||
ZT_INLINE void unlock() const noexcept
|
||||
{
|
||||
pthread_mutex_unlock(&((const_cast<Mutex*>(this))->_mh));
|
||||
}
|
||||
#else
|
||||
ZT_INLINE Mutex() noexcept : _m() {}
|
||||
ZT_INLINE void lock() const noexcept { const_cast<Mutex *>(this)->_m.lock(); }
|
||||
ZT_INLINE void unlock() const noexcept { const_cast<Mutex *>(this)->_m.unlock(); }
|
||||
ZT_INLINE Mutex() noexcept : _m()
|
||||
{
|
||||
}
|
||||
ZT_INLINE void lock() const noexcept
|
||||
{
|
||||
const_cast<Mutex*>(this)->_m.lock();
|
||||
}
|
||||
ZT_INLINE void unlock() const noexcept
|
||||
{
|
||||
const_cast<Mutex*>(this)->_m.unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
class Lock
|
||||
{
|
||||
class Lock {
|
||||
public:
|
||||
explicit ZT_INLINE Lock(Mutex &m) noexcept : _m(&m) { m.lock(); }
|
||||
explicit ZT_INLINE Lock(const Mutex &m) noexcept : _m(const_cast<Mutex *>(&m)) { _m->lock(); }
|
||||
ZT_INLINE ~Lock() { _m->unlock(); }
|
||||
explicit ZT_INLINE Lock(Mutex& m) noexcept : _m(&m)
|
||||
{
|
||||
m.lock();
|
||||
}
|
||||
explicit ZT_INLINE Lock(const Mutex& m) noexcept : _m(const_cast<Mutex*>(&m))
|
||||
{
|
||||
_m->lock();
|
||||
}
|
||||
ZT_INLINE ~Lock()
|
||||
{
|
||||
_m->unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex* const _m;
|
||||
};
|
||||
|
||||
private:
|
||||
ZT_INLINE Mutex(const Mutex &) noexcept {}
|
||||
ZT_INLINE const Mutex &operator=(const Mutex &) noexcept { return *this; }
|
||||
ZT_INLINE Mutex(const Mutex&) noexcept
|
||||
{
|
||||
}
|
||||
ZT_INLINE const Mutex& operator=(const Mutex&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef ZT_USE_PTHREADS
|
||||
pthread_mutex_t _mh;
|
||||
|
@ -74,33 +107,73 @@ private:
|
|||
/**
|
||||
* A lock allowing multiple threads to read but making all wait on any writing thread.
|
||||
*/
|
||||
class RWMutex
|
||||
{
|
||||
class RWMutex {
|
||||
public:
|
||||
#ifdef ZT_USE_PTHREADS
|
||||
ZT_INLINE RWMutex() noexcept { pthread_rwlock_init(&_mh,nullptr); }
|
||||
ZT_INLINE ~RWMutex() noexcept { pthread_rwlock_destroy(&_mh); }
|
||||
ZT_INLINE void lock() const noexcept { pthread_rwlock_wrlock(&((const_cast <RWMutex *> (this))->_mh)); }
|
||||
ZT_INLINE void rlock() const noexcept { pthread_rwlock_rdlock(&((const_cast <RWMutex *> (this))->_mh)); }
|
||||
ZT_INLINE void unlock() const noexcept { pthread_rwlock_unlock(&((const_cast <RWMutex *> (this))->_mh)); }
|
||||
ZT_INLINE void runlock() const noexcept { pthread_rwlock_unlock(&((const_cast <RWMutex *> (this))->_mh)); }
|
||||
ZT_INLINE RWMutex() noexcept
|
||||
{
|
||||
pthread_rwlock_init(&_mh, nullptr);
|
||||
}
|
||||
ZT_INLINE ~RWMutex() noexcept
|
||||
{
|
||||
pthread_rwlock_destroy(&_mh);
|
||||
}
|
||||
ZT_INLINE void lock() const noexcept
|
||||
{
|
||||
pthread_rwlock_wrlock(&((const_cast<RWMutex*>(this))->_mh));
|
||||
}
|
||||
ZT_INLINE void rlock() const noexcept
|
||||
{
|
||||
pthread_rwlock_rdlock(&((const_cast<RWMutex*>(this))->_mh));
|
||||
}
|
||||
ZT_INLINE void unlock() const noexcept
|
||||
{
|
||||
pthread_rwlock_unlock(&((const_cast<RWMutex*>(this))->_mh));
|
||||
}
|
||||
ZT_INLINE void runlock() const noexcept
|
||||
{
|
||||
pthread_rwlock_unlock(&((const_cast<RWMutex*>(this))->_mh));
|
||||
}
|
||||
#else
|
||||
ZT_INLINE RWMutex() noexcept : _m() {}
|
||||
ZT_INLINE void lock() const noexcept { const_cast<RWMutex *>(this)->_m.lock(); }
|
||||
ZT_INLINE void rlock() const noexcept { const_cast<RWMutex *>(this)->_m.lock_shared(); }
|
||||
ZT_INLINE void unlock() const noexcept { const_cast<RWMutex *>(this)->_m.unlock(); }
|
||||
ZT_INLINE void runlock() const noexcept { const_cast<RWMutex *>(this)->_m.unlock_shared(); }
|
||||
ZT_INLINE RWMutex() noexcept : _m()
|
||||
{
|
||||
}
|
||||
ZT_INLINE void lock() const noexcept
|
||||
{
|
||||
const_cast<RWMutex*>(this)->_m.lock();
|
||||
}
|
||||
ZT_INLINE void rlock() const noexcept
|
||||
{
|
||||
const_cast<RWMutex*>(this)->_m.lock_shared();
|
||||
}
|
||||
ZT_INLINE void unlock() const noexcept
|
||||
{
|
||||
const_cast<RWMutex*>(this)->_m.unlock();
|
||||
}
|
||||
ZT_INLINE void runlock() const noexcept
|
||||
{
|
||||
const_cast<RWMutex*>(this)->_m.unlock_shared();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* RAAI locker that acquires only the read lock (shared read)
|
||||
*/
|
||||
class RLock
|
||||
{
|
||||
class RLock {
|
||||
public:
|
||||
explicit ZT_INLINE RLock(RWMutex &m) noexcept : _m(&m) { m.rlock(); }
|
||||
explicit ZT_INLINE RLock(const RWMutex &m) noexcept : _m(const_cast<RWMutex *>(&m)) { _m->rlock(); }
|
||||
ZT_INLINE ~RLock() { _m->runlock(); }
|
||||
explicit ZT_INLINE RLock(RWMutex& m) noexcept : _m(&m)
|
||||
{
|
||||
m.rlock();
|
||||
}
|
||||
explicit ZT_INLINE RLock(const RWMutex& m) noexcept : _m(const_cast<RWMutex*>(&m))
|
||||
{
|
||||
_m->rlock();
|
||||
}
|
||||
ZT_INLINE ~RLock()
|
||||
{
|
||||
_m->runlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RWMutex* const _m;
|
||||
};
|
||||
|
@ -108,12 +181,21 @@ public:
|
|||
/**
|
||||
* RAAI locker that acquires the write lock (exclusive write, no readers)
|
||||
*/
|
||||
class Lock
|
||||
{
|
||||
class Lock {
|
||||
public:
|
||||
explicit ZT_INLINE Lock(RWMutex &m) noexcept : _m(&m) { m.lock(); }
|
||||
explicit ZT_INLINE Lock(const RWMutex &m) noexcept : _m(const_cast<RWMutex *>(&m)) { _m->lock(); }
|
||||
ZT_INLINE ~Lock() { _m->unlock(); }
|
||||
explicit ZT_INLINE Lock(RWMutex& m) noexcept : _m(&m)
|
||||
{
|
||||
m.lock();
|
||||
}
|
||||
explicit ZT_INLINE Lock(const RWMutex& m) noexcept : _m(const_cast<RWMutex*>(&m))
|
||||
{
|
||||
_m->lock();
|
||||
}
|
||||
ZT_INLINE ~Lock()
|
||||
{
|
||||
_m->unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RWMutex* const _m;
|
||||
};
|
||||
|
@ -127,23 +209,61 @@ public:
|
|||
* transition, meaning protected variable states can change. Code must not assume
|
||||
* that the lock is held constantly if writing() is used to change mode.
|
||||
*/
|
||||
class RMaybeWLock
|
||||
{
|
||||
class RMaybeWLock {
|
||||
public:
|
||||
explicit ZT_INLINE RMaybeWLock(RWMutex &m) noexcept : _m(&m),_w(false) { m.rlock(); }
|
||||
explicit ZT_INLINE RMaybeWLock(const RWMutex &m) noexcept : _m(const_cast<RWMutex *>(&m)),_w(false) { _m->rlock(); }
|
||||
ZT_INLINE void writing() noexcept { if (!_w) { _w = true; _m->runlock(); _m->lock(); } }
|
||||
ZT_INLINE void reading() noexcept { if (_w) { _w = false; _m->unlock(); _m->rlock(); } }
|
||||
ZT_INLINE bool isWriting() const noexcept { return _w; }
|
||||
ZT_INLINE ~RMaybeWLock() { if (_w) _m->unlock(); else _m->runlock(); }
|
||||
explicit ZT_INLINE RMaybeWLock(RWMutex& m) noexcept
|
||||
: _m(&m)
|
||||
, _w(false)
|
||||
{
|
||||
m.rlock();
|
||||
}
|
||||
explicit ZT_INLINE RMaybeWLock(const RWMutex& m) noexcept
|
||||
: _m(const_cast<RWMutex*>(&m))
|
||||
, _w(false)
|
||||
{
|
||||
_m->rlock();
|
||||
}
|
||||
ZT_INLINE void writing() noexcept
|
||||
{
|
||||
if (! _w) {
|
||||
_w = true;
|
||||
_m->runlock();
|
||||
_m->lock();
|
||||
}
|
||||
}
|
||||
ZT_INLINE void reading() noexcept
|
||||
{
|
||||
if (_w) {
|
||||
_w = false;
|
||||
_m->unlock();
|
||||
_m->rlock();
|
||||
}
|
||||
}
|
||||
ZT_INLINE bool isWriting() const noexcept
|
||||
{
|
||||
return _w;
|
||||
}
|
||||
ZT_INLINE ~RMaybeWLock()
|
||||
{
|
||||
if (_w)
|
||||
_m->unlock();
|
||||
else
|
||||
_m->runlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RWMutex* const _m;
|
||||
bool _w;
|
||||
};
|
||||
|
||||
private:
|
||||
ZT_INLINE RWMutex(const RWMutex &) noexcept {}
|
||||
ZT_INLINE const RWMutex &operator=(const RWMutex &) noexcept { return *this; }
|
||||
ZT_INLINE RWMutex(const RWMutex&) noexcept
|
||||
{
|
||||
}
|
||||
ZT_INLINE const RWMutex& operator=(const RWMutex&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef ZT_USE_PTHREADS
|
||||
pthread_rwlock_t _mh;
|
||||
|
|
610
core/Network.cpp
610
core/Network.cpp
File diff suppressed because it is too large
Load diff
106
core/Network.hpp
106
core/Network.hpp
|
@ -14,19 +14,19 @@
|
|||
#ifndef ZT_NETWORK_HPP
|
||||
#define ZT_NETWORK_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "Member.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Member.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
|
||||
#define ZT_NETWORK_MAX_INCOMING_UPDATES 3
|
||||
|
||||
|
@ -39,8 +39,7 @@ class Peer;
|
|||
/**
|
||||
* A virtual LAN
|
||||
*/
|
||||
class Network
|
||||
{
|
||||
class Network {
|
||||
friend class SharedPtr<Network>;
|
||||
|
||||
public:
|
||||
|
@ -53,7 +52,9 @@ public:
|
|||
* Compute primary controller device ID from network ID
|
||||
*/
|
||||
static ZT_INLINE Address controllerFor(uint64_t nwid) noexcept
|
||||
{ return Address(nwid >> 24U); }
|
||||
{
|
||||
return Address(nwid >> 24U);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new network
|
||||
|
@ -77,28 +78,44 @@ public:
|
|||
~Network();
|
||||
|
||||
ZT_INLINE uint64_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE Address controller() const noexcept
|
||||
{ return Address(m_id >> 24U); }
|
||||
{
|
||||
return Address(m_id >> 24U);
|
||||
}
|
||||
|
||||
ZT_INLINE bool multicastEnabled() const noexcept
|
||||
{ return (m_config.multicastLimit > 0); }
|
||||
{
|
||||
return (m_config.multicastLimit > 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool hasConfig() const noexcept
|
||||
{ return (m_config); }
|
||||
{
|
||||
return (m_config);
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t lastConfigUpdate() const noexcept
|
||||
{ return m_lastConfigUpdate; }
|
||||
{
|
||||
return m_lastConfigUpdate;
|
||||
}
|
||||
|
||||
ZT_INLINE ZT_VirtualNetworkStatus status() const noexcept
|
||||
{ return m_status(); }
|
||||
{
|
||||
return m_status();
|
||||
}
|
||||
|
||||
ZT_INLINE const NetworkConfig& config() const noexcept
|
||||
{ return m_config; }
|
||||
{
|
||||
return m_config;
|
||||
}
|
||||
|
||||
ZT_INLINE const MAC& mac() const noexcept
|
||||
{ return m_mac; }
|
||||
{
|
||||
return m_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply filters to an outgoing packet
|
||||
|
@ -209,22 +226,23 @@ public:
|
|||
* @param saveToDisk Save to disk? Used during loading, should usually be true otherwise.
|
||||
* @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new
|
||||
*/
|
||||
int setConfiguration(
|
||||
const CallContext &cc,
|
||||
const NetworkConfig &nconf,
|
||||
bool saveToDisk);
|
||||
int setConfiguration(const CallContext& cc, const NetworkConfig& nconf, bool saveToDisk);
|
||||
|
||||
/**
|
||||
* Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this
|
||||
*/
|
||||
ZT_INLINE void setAccessDenied() noexcept
|
||||
{ _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED; }
|
||||
{
|
||||
_netconfFailure = NETCONF_FAILURE_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set netconf failure to 'not found' -- called by IncomingPacket when controller reports this
|
||||
*/
|
||||
ZT_INLINE void setNotFound() noexcept
|
||||
{ _netconfFailure = NETCONF_FAILURE_NOT_FOUND; }
|
||||
{
|
||||
_netconfFailure = NETCONF_FAILURE_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this peer is permitted to communicate on this network
|
||||
|
@ -276,27 +294,32 @@ public:
|
|||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const MembershipCredential &com);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const MembershipCredential& com);
|
||||
|
||||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const CapabilityCredential &cap);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const CapabilityCredential& cap);
|
||||
|
||||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const TagCredential &tag);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const TagCredential& tag);
|
||||
|
||||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const RevocationCredential &rev);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const RevocationCredential& rev);
|
||||
|
||||
/**
|
||||
* Validate a credential and learn it if it passes certificate and other checks
|
||||
*/
|
||||
Member::AddCredentialResult addCredential(const CallContext &cc, const Identity &sourcePeerIdentity, const OwnershipCredential &coo);
|
||||
Member::AddCredentialResult
|
||||
addCredential(const CallContext& cc, const Identity& sourcePeerIdentity, const OwnershipCredential& coo);
|
||||
|
||||
/**
|
||||
* Push credentials to a peer if timeouts indicate that we should do so
|
||||
|
@ -325,11 +348,11 @@ public:
|
|||
*
|
||||
* @param f Function of (const Address,const Membership)
|
||||
*/
|
||||
template< typename F >
|
||||
ZT_INLINE void eachMember(F f)
|
||||
template <typename F> ZT_INLINE void eachMember(F f)
|
||||
{
|
||||
Mutex::Lock ml(m_memberships_l);
|
||||
for (Map< Address, Member >::iterator i(m_memberships.begin()); i != m_memberships.end(); ++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto)
|
||||
for (Map<Address, Member>::iterator i(m_memberships.begin()); i != m_memberships.end();
|
||||
++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto)
|
||||
if (! f(i->first, i->second))
|
||||
break;
|
||||
}
|
||||
|
@ -339,7 +362,9 @@ public:
|
|||
* @return Externally usable pointer-to-pointer exported via the core API
|
||||
*/
|
||||
ZT_INLINE void** userPtr() noexcept
|
||||
{ return &m_uPtr; }
|
||||
{
|
||||
return &m_uPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
void m_requestConfiguration(const CallContext& cc);
|
||||
|
@ -358,14 +383,15 @@ private:
|
|||
std::atomic<bool> m_destroyed;
|
||||
|
||||
Vector<MulticastGroup> m_myMulticastGroups; // multicast groups that we belong to (according to tap)
|
||||
Map< MulticastGroup, int64_t > m_multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
|
||||
Map< MAC, Address > m_remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
|
||||
Map<MulticastGroup, int64_t> m_multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we
|
||||
// last saw them (if we are a bridge)
|
||||
Map<MAC, Address> m_remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices
|
||||
// behind remote bridges)
|
||||
|
||||
NetworkConfig m_config;
|
||||
std::atomic<int64_t> m_lastConfigUpdate;
|
||||
|
||||
volatile enum
|
||||
{
|
||||
volatile enum {
|
||||
NETCONF_FAILURE_NONE,
|
||||
NETCONF_FAILURE_ACCESS_DENIED,
|
||||
NETCONF_FAILURE_NOT_FOUND,
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include <cstdint>
|
||||
#include "NetworkConfig.hpp"
|
||||
|
||||
#include "Buf.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -32,7 +32,10 @@ bool NetworkConfig::toDictionary(Dictionary &d) const
|
|||
d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA, this->credentialTimeMaxDelta);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION, this->revision);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO, this->issuedTo.toString((char*)tmp));
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH,this->issuedToFingerprintHash,ZT_FINGERPRINT_HASH_SIZE);
|
||||
d.add(
|
||||
ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH,
|
||||
this->issuedToFingerprintHash,
|
||||
ZT_FINGERPRINT_HASH_SIZE);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS, this->flags);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT, (uint64_t)this->multicastLimit);
|
||||
d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE, (uint64_t)this->type);
|
||||
|
@ -102,7 +105,9 @@ bool NetworkConfig::toDictionary(Dictionary &d) const
|
|||
}
|
||||
|
||||
return true;
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -124,7 +129,8 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
|
|||
const Vector<uint8_t>* blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH]);
|
||||
if (blob->size() == ZT_FINGERPRINT_HASH_SIZE) {
|
||||
Utils::copy<ZT_FINGERPRINT_HASH_SIZE>(this->issuedToFingerprintHash, blob->data());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Utils::zero<ZT_FINGERPRINT_HASH_SIZE>(this->issuedToFingerprintHash);
|
||||
}
|
||||
if (! this->issuedTo)
|
||||
|
@ -139,9 +145,11 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
|
|||
|
||||
if (d.getUI(ZT_NETWORKCONFIG_DICT_KEY_VERSION, 0) < 6) {
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
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);
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_COM]);
|
||||
if (! blob->empty()) {
|
||||
|
@ -162,7 +170,9 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
|
|||
if (this->capabilityCount < ZT_MAX_NETWORK_CAPABILITIES)
|
||||
this->capabilities[this->capabilityCount++] = cap;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
std::sort(&(this->capabilities[0]), &(this->capabilities[this->capabilityCount]));
|
||||
}
|
||||
|
||||
|
@ -179,7 +189,9 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
|
|||
if (this->tagCount < ZT_MAX_NETWORK_TAGS)
|
||||
this->tags[this->tagCount++] = tag;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
std::sort(&(this->tags[0]), &(this->tags[this->tagCount]));
|
||||
}
|
||||
|
||||
|
@ -196,8 +208,12 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
|
|||
if (this->certificateOfOwnershipCount < ZT_MAX_CERTIFICATES_OF_OWNERSHIP)
|
||||
this->certificatesOfOwnership[certificateOfOwnershipCount++] = coo;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
std::sort(&(this->certificatesOfOwnership[0]),&(this->certificatesOfOwnership[this->certificateOfOwnershipCount]));
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
std::sort(
|
||||
&(this->certificatesOfOwnership[0]),
|
||||
&(this->certificatesOfOwnership[this->certificateOfOwnershipCount]));
|
||||
}
|
||||
|
||||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS]);
|
||||
|
@ -213,20 +229,24 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
|
|||
if (! blob->empty()) {
|
||||
unsigned int p = 0;
|
||||
while ((p < blob->size()) && (routeCount < ZT_MAX_NETWORK_ROUTES)) {
|
||||
int l = asInetAddress(this->routes[this->routeCount].target).unmarshal(blob->data(),(int)(blob->size() - p));
|
||||
int l = asInetAddress(this->routes[this->routeCount].target)
|
||||
.unmarshal(blob->data(), (int)(blob->size() - p));
|
||||
if (l < 0)
|
||||
return false;
|
||||
p += l;
|
||||
if (p >= blob->size())
|
||||
return false;
|
||||
l = asInetAddress(this->routes[this->routeCount].via).unmarshal(blob->data(),(int)(blob->size() - p));
|
||||
l = asInetAddress(this->routes[this->routeCount].via)
|
||||
.unmarshal(blob->data(), (int)(blob->size() - p));
|
||||
if (l < 0)
|
||||
return false;
|
||||
p += l;
|
||||
if ((p + 4) > blob->size())
|
||||
return false;
|
||||
this->routes[this->routeCount].flags = Utils::loadBigEndian<uint16_t>(blob->data() + p); p += 2;
|
||||
this->routes[this->routeCount].metric = Utils::loadBigEndian<uint16_t>(blob->data() + p); p += 2;
|
||||
this->routes[this->routeCount].flags = Utils::loadBigEndian<uint16_t>(blob->data() + p);
|
||||
p += 2;
|
||||
this->routes[this->routeCount].metric = Utils::loadBigEndian<uint16_t>(blob->data() + p);
|
||||
p += 2;
|
||||
++this->routeCount;
|
||||
}
|
||||
}
|
||||
|
@ -246,13 +266,21 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
|
|||
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_RULES]);
|
||||
if (! blob->empty()) {
|
||||
this->ruleCount = 0;
|
||||
if (CapabilityCredential::unmarshalVirtualNetworkRules(blob->data(), (int)blob->size(), this->rules, this->ruleCount, ZT_MAX_NETWORK_RULES) < 0)
|
||||
if (CapabilityCredential::unmarshalVirtualNetworkRules(
|
||||
blob->data(),
|
||||
(int)blob->size(),
|
||||
this->rules,
|
||||
this->ruleCount,
|
||||
ZT_MAX_NETWORK_RULES)
|
||||
< 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,23 +14,23 @@
|
|||
#ifndef ZT_NETWORKCONFIG_HPP
|
||||
#define ZT_NETWORKCONFIG_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "OwnershipCredential.hpp"
|
||||
#include "CapabilityCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MembershipCredential.hpp"
|
||||
#include "MulticastGroup.hpp"
|
||||
#include "OwnershipCredential.hpp"
|
||||
#include "TagCredential.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -144,10 +144,11 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Network configuration received from network controller nodes
|
||||
*/
|
||||
struct NetworkConfig : TriviallyCopyable
|
||||
{
|
||||
struct NetworkConfig : TriviallyCopyable {
|
||||
ZT_INLINE NetworkConfig() noexcept
|
||||
{ memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
{
|
||||
memoryZero(this);
|
||||
} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
|
||||
/**
|
||||
* Write this network config to a dictionary for transport
|
||||
|
@ -169,25 +170,33 @@ struct NetworkConfig : TriviallyCopyable
|
|||
* @return True if broadcast (ff:ff:ff:ff:ff:ff) address should work on this network
|
||||
*/
|
||||
ZT_INLINE bool enableBroadcast() const noexcept
|
||||
{ return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0); }
|
||||
{
|
||||
return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if IPv6 NDP emulation should be allowed for certain "magic" IPv6 address patterns
|
||||
*/
|
||||
ZT_INLINE bool ndpEmulation() const noexcept
|
||||
{ return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0); }
|
||||
{
|
||||
return ((this->flags & ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Network type is public (no access control)
|
||||
*/
|
||||
ZT_INLINE bool isPublic() const noexcept
|
||||
{ return (this->type == ZT_NETWORK_TYPE_PUBLIC); }
|
||||
{
|
||||
return (this->type == ZT_NETWORK_TYPE_PUBLIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Network type is private (certificate access control)
|
||||
*/
|
||||
ZT_INLINE bool isPrivate() const noexcept
|
||||
{ return (this->type == ZT_NETWORK_TYPE_PRIVATE); }
|
||||
{
|
||||
return (this->type == ZT_NETWORK_TYPE_PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fromPeer Peer attempting to bridge other Ethernet peers onto network
|
||||
|
@ -196,19 +205,26 @@ struct NetworkConfig : TriviallyCopyable
|
|||
ZT_INLINE bool permitsBridging(const Address& fromPeer) const noexcept
|
||||
{
|
||||
for (unsigned int i = 0; i < specialistCount; ++i) {
|
||||
if ((fromPeer.toInt() == (specialists[i] & ZT_ADDRESS_MASK)) && ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0))
|
||||
if ((fromPeer.toInt() == (specialists[i] & ZT_ADDRESS_MASK))
|
||||
&& ((specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (networkId != 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
{
|
||||
return (networkId != 0);
|
||||
} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
ZT_INLINE bool operator==(const NetworkConfig& nc) const noexcept
|
||||
{ return (memcmp(this, &nc, sizeof(NetworkConfig)) == 0); }
|
||||
{
|
||||
return (memcmp(this, &nc, sizeof(NetworkConfig)) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const NetworkConfig& nc) const noexcept
|
||||
{ return (!(*this == nc)); }
|
||||
{
|
||||
return (! (*this == nc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a specialist or mask flags if already present
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#ifndef ZT_NETWORKCONFIGMASTER_HPP
|
||||
#define ZT_NETWORKCONFIGMASTER_HPP
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "RevocationCredential.hpp"
|
||||
#include "Address.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -28,11 +28,9 @@ struct InetAddress;
|
|||
/**
|
||||
* Interface for network controller implementations
|
||||
*/
|
||||
class NetworkController
|
||||
{
|
||||
class NetworkController {
|
||||
public:
|
||||
enum ErrorCode
|
||||
{
|
||||
enum ErrorCode {
|
||||
NC_ERROR_NONE = 0,
|
||||
NC_ERROR_OBJECT_NOT_FOUND = 1,
|
||||
NC_ERROR_ACCESS_DENIED = 2,
|
||||
|
@ -42,19 +40,27 @@ public:
|
|||
/**
|
||||
* Interface for sender used to send pushes and replies
|
||||
*/
|
||||
class Sender
|
||||
{
|
||||
class Sender {
|
||||
public:
|
||||
/**
|
||||
* Send a configuration to a remote peer
|
||||
*
|
||||
* @param nwid Network ID
|
||||
* @param requestPacketId Request packet ID to send OK(NETWORK_CONFIG_REQUEST) or 0 to send NETWORK_CONFIG (push)
|
||||
* @param requestPacketId Request packet ID to send OK(NETWORK_CONFIG_REQUEST) or 0 to send NETWORK_CONFIG
|
||||
* (push)
|
||||
* @param destination Destination peer Address
|
||||
* @param nc Network configuration to send
|
||||
* @param sendLegacyFormatConfig If true, send an old-format network config
|
||||
*/
|
||||
virtual void ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig) = 0;
|
||||
virtual void ncSendConfig(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
const NetworkConfig& nc,
|
||||
bool sendLegacyFormatConfig) = 0;
|
||||
|
||||
/**
|
||||
* Send revocation to a node
|
||||
|
@ -62,7 +68,12 @@ public:
|
|||
* @param destination Destination node address
|
||||
* @param rev Revocation to send
|
||||
*/
|
||||
virtual void ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev) = 0;
|
||||
virtual void ncSendRevocation(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
const Address& destination,
|
||||
const RevocationCredential& rev) = 0;
|
||||
|
||||
/**
|
||||
* Send a network configuration request error
|
||||
|
@ -72,11 +83,22 @@ public:
|
|||
* @param destination Destination peer Address
|
||||
* @param errorCode Error code
|
||||
*/
|
||||
virtual void ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode) = 0;
|
||||
virtual void ncSendError(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
NetworkController::ErrorCode errorCode) = 0;
|
||||
};
|
||||
|
||||
NetworkController() {}
|
||||
virtual ~NetworkController() {}
|
||||
NetworkController()
|
||||
{
|
||||
}
|
||||
virtual ~NetworkController()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this is added to a Node to initialize and supply info
|
||||
|
|
255
core/Node.cpp
255
core/Node.cpp
|
@ -11,39 +11,39 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "Topology.hpp"
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Expect.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Store.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "TrustStore.hpp"
|
||||
#include "VL1.hpp"
|
||||
#include "VL2.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "TrustStore.hpp"
|
||||
#include "Store.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
namespace {
|
||||
|
||||
struct _NodeObjects
|
||||
{
|
||||
ZT_INLINE _NodeObjects(Context &ctx, const CallContext &cc) :
|
||||
networks(),
|
||||
t(ctx),
|
||||
expect(),
|
||||
vl2(ctx),
|
||||
vl1(ctx),
|
||||
topology(ctx, cc),
|
||||
sa(ctx),
|
||||
ts()
|
||||
struct _NodeObjects {
|
||||
ZT_INLINE _NodeObjects(Context& ctx, const CallContext& cc)
|
||||
: networks()
|
||||
, t(ctx)
|
||||
, expect()
|
||||
, vl2(ctx)
|
||||
, vl1(ctx)
|
||||
, topology(ctx, cc)
|
||||
, sa(ctx)
|
||||
, ts()
|
||||
{
|
||||
ctx.networks = &networks;
|
||||
ctx.t = &t;
|
||||
|
@ -67,15 +67,15 @@ struct _NodeObjects
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
Node::Node(void *uPtr, const struct ZT_Node_Callbacks *callbacks, const CallContext &cc) :
|
||||
m_ctx(this),
|
||||
m_store(m_ctx),
|
||||
m_objects(nullptr),
|
||||
m_lastPeerPulse(0),
|
||||
m_lastHousekeepingRun(0),
|
||||
m_lastNetworkHousekeepingRun(0),
|
||||
m_lastTrustStoreUpdate(0),
|
||||
m_online(false)
|
||||
Node::Node(void* uPtr, const struct ZT_Node_Callbacks* callbacks, const CallContext& cc)
|
||||
: m_ctx(this)
|
||||
, m_store(m_ctx)
|
||||
, m_objects(nullptr)
|
||||
, m_lastPeerPulse(0)
|
||||
, m_lastHousekeepingRun(0)
|
||||
, m_lastNetworkHousekeepingRun(0)
|
||||
, m_lastTrustStoreUpdate(0)
|
||||
, m_online(false)
|
||||
{
|
||||
ZT_SPEW("Node starting up!");
|
||||
|
||||
|
@ -99,13 +99,32 @@ Node::Node(void *uPtr, const struct ZT_Node_Callbacks *callbacks, const CallCont
|
|||
m_ctx.identity.generate(Identity::C25519);
|
||||
m_ctx.identity.toString(false, m_ctx.publicIdentityStr);
|
||||
m_ctx.identity.toString(true, m_ctx.secretIdentityStr);
|
||||
m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0, m_ctx.secretIdentityStr, (unsigned int)strlen(m_ctx.secretIdentityStr));
|
||||
m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_ctx.publicIdentityStr, (unsigned int)strlen(m_ctx.publicIdentityStr));
|
||||
m_store.put(
|
||||
cc,
|
||||
ZT_STATE_OBJECT_IDENTITY_SECRET,
|
||||
Utils::ZERO256,
|
||||
0,
|
||||
m_ctx.secretIdentityStr,
|
||||
(unsigned int)strlen(m_ctx.secretIdentityStr));
|
||||
m_store.put(
|
||||
cc,
|
||||
ZT_STATE_OBJECT_IDENTITY_PUBLIC,
|
||||
Utils::ZERO256,
|
||||
0,
|
||||
m_ctx.publicIdentityStr,
|
||||
(unsigned int)strlen(m_ctx.publicIdentityStr));
|
||||
ZT_SPEW("no pre-existing identity found, created %s", m_ctx.identity.toString().c_str());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data = m_store.get(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0);
|
||||
if ((data.empty()) || (memcmp(data.data(), m_ctx.publicIdentityStr, strlen(m_ctx.publicIdentityStr)) != 0))
|
||||
m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_ctx.publicIdentityStr, (unsigned int)strlen(m_ctx.publicIdentityStr));
|
||||
m_store.put(
|
||||
cc,
|
||||
ZT_STATE_OBJECT_IDENTITY_PUBLIC,
|
||||
Utils::ZERO256,
|
||||
0,
|
||||
m_ctx.publicIdentityStr,
|
||||
(unsigned int)strlen(m_ctx.publicIdentityStr));
|
||||
}
|
||||
|
||||
uint8_t localSecretCipherKey[ZT_FINGERPRINT_HASH_SIZE];
|
||||
|
@ -211,7 +230,9 @@ ZT_ResultCode Node::processBackgroundTasks(const CallContext &cc, volatile int64
|
|||
for (Vector<SharedPtr<Peer> >::iterator p(allPeers.begin()); p != allPeers.end(); ++p) {
|
||||
(*p)->pulse(m_ctx, cc);
|
||||
if (! online) {
|
||||
online = ((std::binary_search(rootPeers.begin(), rootPeers.end(), *p) || rootPeers.empty()) && (*p)->directlyConnected());
|
||||
online =
|
||||
((std::binary_search(rootPeers.begin(), rootPeers.end(), *p) || rootPeers.empty())
|
||||
&& (*p)->directlyConnected());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,13 +241,15 @@ ZT_ResultCode Node::processBackgroundTasks(const CallContext &cc, volatile int64
|
|||
|
||||
ZT_SPEW("ranking roots...");
|
||||
m_ctx.topology->rankRoots(cc);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
*nextBackgroundTaskDeadline = cc.ticks + ZT_TIMER_TASK_INTERVAL;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
|
@ -241,7 +264,8 @@ ZT_ResultCode Node::join(uint64_t nwid, const ZT_Fingerprint *controllerFingerpr
|
|||
if (controllerFingerprint) {
|
||||
fp = *controllerFingerprint;
|
||||
ZT_SPEW("joining network %.16llx with controller fingerprint %s", nwid, fp.toString().c_str());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ZT_SPEW("joining network %.16llx", nwid);
|
||||
}
|
||||
|
||||
|
@ -282,34 +306,46 @@ ZT_ResultCode Node::leave(uint64_t nwid, void **uptr, const CallContext &cc)
|
|||
if (uptr)
|
||||
*uptr = *network->userPtr();
|
||||
network->externalConfig(&ctmp);
|
||||
m_ctx.cb.virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this), m_ctx.uPtr, cc.tPtr, nwid, network->userPtr(), ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY, &ctmp);
|
||||
m_ctx.cb.virtualNetworkConfigFunction(
|
||||
reinterpret_cast<ZT_Node*>(this),
|
||||
m_ctx.uPtr,
|
||||
cc.tPtr,
|
||||
nwid,
|
||||
network->userPtr(),
|
||||
ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,
|
||||
&ctmp);
|
||||
network->destroy();
|
||||
return ZT_RESULT_OK;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::multicastSubscribe(const CallContext &cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
|
||||
ZT_ResultCode
|
||||
Node::multicastSubscribe(const CallContext& cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
|
||||
{
|
||||
ZT_SPEW("multicast subscribe to %s:%lu", MAC(multicastGroup).toString().c_str(), multicastAdi);
|
||||
const SharedPtr<Network> nw(m_ctx.networks->get(nwid));
|
||||
if (nw) {
|
||||
nw->multicastSubscribe(cc, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));
|
||||
return ZT_RESULT_OK;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::multicastUnsubscribe(const CallContext &cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
|
||||
ZT_ResultCode
|
||||
Node::multicastUnsubscribe(const CallContext& cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
|
||||
{
|
||||
ZT_SPEW("multicast unsubscribe from %s:%lu", MAC(multicastGroup).toString().c_str(), multicastAdi);
|
||||
const SharedPtr<Network> nw(m_ctx.networks->get(nwid));
|
||||
if (nw) {
|
||||
nw->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));
|
||||
return ZT_RESULT_OK;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
@ -323,8 +359,7 @@ void Node::status(ZT_NodeStatus *status) const
|
|||
status->online = m_online ? 1 : 0;
|
||||
}
|
||||
|
||||
struct p_ZT_PeerListPrivate : public ZT_PeerList
|
||||
{
|
||||
struct p_ZT_PeerListPrivate : public ZT_PeerList {
|
||||
// Actual containers for the memory, hidden from external users.
|
||||
Vector<ZT_Peer> p_peers;
|
||||
ForwardList<Vector<ZT_Path> > p_paths;
|
||||
|
@ -338,10 +373,11 @@ static void p_peerListFreeFunction(const void *pl)
|
|||
delete reinterpret_cast<p_ZT_PeerListPrivate*>(const_cast<void*>(pl));
|
||||
}
|
||||
|
||||
struct p_sortPeerPtrsByAddress
|
||||
{
|
||||
struct p_sortPeerPtrsByAddress {
|
||||
ZT_INLINE bool operator()(const SharedPtr<Peer>& a, const SharedPtr<Peer>& b) const noexcept
|
||||
{ return (a->address() < b->address()); }
|
||||
{
|
||||
return (a->address() < b->address());
|
||||
}
|
||||
};
|
||||
|
||||
ZT_PeerList* Node::peers(const CallContext& cc) const
|
||||
|
@ -371,7 +407,8 @@ ZT_PeerList *Node::peers(const CallContext &cc) const
|
|||
p.versionMinor = (int)vMinor;
|
||||
p.versionRev = (int)vRevision;
|
||||
p.versionProto = (int)vProto;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p.versionMajor = -1;
|
||||
p.versionMinor = -1;
|
||||
p.versionRev = -1;
|
||||
|
@ -401,7 +438,8 @@ ZT_PeerList *Node::peers(const CallContext &cc) const
|
|||
}
|
||||
p.paths = apiPaths.data();
|
||||
p.pathCount = (unsigned int)apiPaths.size();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p.paths = nullptr;
|
||||
p.pathCount = 0;
|
||||
}
|
||||
|
@ -423,7 +461,8 @@ ZT_PeerList *Node::peers(const CallContext &cc) const
|
|||
pl->peerCount = (unsigned long)pl->p_peers.size();
|
||||
|
||||
return pl;
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
delete pl;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -436,7 +475,8 @@ ZT_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const
|
|||
ZT_VirtualNetworkConfig* const nc = (ZT_VirtualNetworkConfig*)::malloc(sizeof(ZT_VirtualNetworkConfig));
|
||||
nw->externalConfig(nc);
|
||||
return nc;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -445,7 +485,8 @@ ZT_VirtualNetworkList *Node::networks() const
|
|||
{
|
||||
Mutex::Lock l(m_allNetworks_l);
|
||||
|
||||
char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * m_allNetworks.size()));
|
||||
char* const buf =
|
||||
(char*)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * m_allNetworks.size()));
|
||||
if (! buf)
|
||||
return nullptr;
|
||||
ZT_VirtualNetworkList* nl = (ZT_VirtualNetworkList*)buf;
|
||||
|
@ -459,9 +500,7 @@ ZT_VirtualNetworkList *Node::networks() const
|
|||
return nl;
|
||||
}
|
||||
|
||||
void Node::setNetworkUserPtr(
|
||||
uint64_t nwid,
|
||||
void *ptr)
|
||||
void Node::setNetworkUserPtr(uint64_t nwid, void* ptr)
|
||||
{
|
||||
SharedPtr<Network> nw(m_ctx.networks->get(nwid));
|
||||
if (nw) {
|
||||
|
@ -471,16 +510,15 @@ void Node::setNetworkUserPtr(
|
|||
}
|
||||
}
|
||||
|
||||
void Node::setInterfaceAddresses(
|
||||
const ZT_InterfaceAddress *addrs,
|
||||
unsigned int addrCount)
|
||||
void Node::setInterfaceAddresses(const ZT_InterfaceAddress* addrs, unsigned int addrCount)
|
||||
{
|
||||
Mutex::Lock _l(m_localInterfaceAddresses_m);
|
||||
m_localInterfaceAddresses.clear();
|
||||
for (unsigned int i = 0; i < addrCount; ++i) {
|
||||
bool dupe = false;
|
||||
for (unsigned int j = 0; j < i; ++j) {
|
||||
if (*(reinterpret_cast<const InetAddress *>(&addrs[j].address)) == *(reinterpret_cast<const InetAddress *>(&addrs[i].address))) {
|
||||
if (*(reinterpret_cast<const InetAddress*>(&addrs[j].address))
|
||||
== *(reinterpret_cast<const InetAddress*>(&addrs[i].address))) {
|
||||
dupe = true;
|
||||
break;
|
||||
}
|
||||
|
@ -500,7 +538,8 @@ ZT_CertificateError Node::addCertificate(
|
|||
Certificate c;
|
||||
if (cert) {
|
||||
c = *cert;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if ((! certData) || (! certSize))
|
||||
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
|
||||
if (! c.decode(certData, certSize))
|
||||
|
@ -509,12 +548,11 @@ ZT_CertificateError Node::addCertificate(
|
|||
m_ctx.ts->add(c, localTrust);
|
||||
m_ctx.ts->update(cc.clock, nullptr);
|
||||
SharedPtr<TrustStore::Entry> ent(m_ctx.ts->get(c.getSerialNo()));
|
||||
return (ent) ? ent->error() : ZT_CERTIFICATE_ERROR_INVALID_FORMAT; // should never be null, but if so it means invalid
|
||||
return (ent) ? ent->error()
|
||||
: ZT_CERTIFICATE_ERROR_INVALID_FORMAT; // should never be null, but if so it means invalid
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::deleteCertificate(
|
||||
const CallContext &cc,
|
||||
const void *serialNo)
|
||||
ZT_ResultCode Node::deleteCertificate(const CallContext& cc, const void* serialNo)
|
||||
{
|
||||
if (! serialNo)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
|
@ -523,8 +561,7 @@ ZT_ResultCode Node::deleteCertificate(
|
|||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
struct p_certificateListInternal
|
||||
{
|
||||
struct p_certificateListInternal {
|
||||
Vector<SharedPtr<TrustStore::Entry> > entries;
|
||||
Vector<const ZT_Certificate*> c;
|
||||
Vector<unsigned int> t;
|
||||
|
@ -533,24 +570,29 @@ struct p_certificateListInternal
|
|||
static void p_freeCertificateList(const void* cl)
|
||||
{
|
||||
if (cl) {
|
||||
reinterpret_cast<const p_certificateListInternal *>(reinterpret_cast<const uint8_t *>(cl) + sizeof(ZT_CertificateList))->~p_certificateListInternal();
|
||||
reinterpret_cast<const p_certificateListInternal*>(
|
||||
reinterpret_cast<const uint8_t*>(cl) + sizeof(ZT_CertificateList))
|
||||
->~p_certificateListInternal();
|
||||
free(const_cast<void*>(cl));
|
||||
}
|
||||
}
|
||||
|
||||
ZT_CertificateList* Node::listCertificates()
|
||||
{
|
||||
ZT_CertificateList *const cl = (ZT_CertificateList *)malloc(sizeof(ZT_CertificateList) + sizeof(p_certificateListInternal));
|
||||
ZT_CertificateList* const cl =
|
||||
(ZT_CertificateList*)malloc(sizeof(ZT_CertificateList) + sizeof(p_certificateListInternal));
|
||||
if (! cl)
|
||||
return nullptr;
|
||||
|
||||
p_certificateListInternal *const clint = reinterpret_cast<p_certificateListInternal *>(reinterpret_cast<uint8_t *>(cl) + sizeof(ZT_CertificateList));
|
||||
p_certificateListInternal* const clint =
|
||||
reinterpret_cast<p_certificateListInternal*>(reinterpret_cast<uint8_t*>(cl) + sizeof(ZT_CertificateList));
|
||||
new (clint) p_certificateListInternal;
|
||||
|
||||
clint->entries = m_ctx.ts->all(false);
|
||||
clint->c.reserve(clint->entries.size());
|
||||
clint->t.reserve(clint->entries.size());
|
||||
for (Vector< SharedPtr< TrustStore::Entry > >::const_iterator i(clint->entries.begin()); i != clint->entries.end(); ++i) {
|
||||
for (Vector<SharedPtr<TrustStore::Entry> >::const_iterator i(clint->entries.begin()); i != clint->entries.end();
|
||||
++i) {
|
||||
clint->c.push_back(&((*i)->certificate()));
|
||||
clint->t.push_back((*i)->localTrust());
|
||||
}
|
||||
|
@ -582,7 +624,9 @@ int Node::sendUserMessage(
|
|||
*/
|
||||
return 1;
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -606,14 +650,16 @@ bool Node::filterPotentialPath(void *tPtr, const Identity &id, int64_t localSock
|
|||
}
|
||||
|
||||
if (m_ctx.cb.pathCheckFunction) {
|
||||
return (m_ctx.cb.pathCheckFunction(
|
||||
return (
|
||||
m_ctx.cb.pathCheckFunction(
|
||||
reinterpret_cast<ZT_Node*>(this),
|
||||
m_ctx.uPtr,
|
||||
tPtr,
|
||||
id.address().toInt(),
|
||||
(const ZT_Identity*)&id,
|
||||
localSocket,
|
||||
reinterpret_cast<const ZT_InetAddress *>(&remoteAddress)) != 0);
|
||||
reinterpret_cast<const ZT_InetAddress*>(&remoteAddress))
|
||||
!= 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -622,21 +668,31 @@ bool Node::filterPotentialPath(void *tPtr, const Identity &id, int64_t localSock
|
|||
bool Node::externalPathLookup(void* tPtr, const Identity& id, int family, InetAddress& addr)
|
||||
{
|
||||
if (m_ctx.cb.pathLookupFunction) {
|
||||
return (m_ctx.cb.pathLookupFunction(
|
||||
return (
|
||||
m_ctx.cb.pathLookupFunction(
|
||||
reinterpret_cast<ZT_Node*>(this),
|
||||
m_ctx.uPtr,
|
||||
tPtr,
|
||||
id.address().toInt(),
|
||||
reinterpret_cast<const ZT_Identity*>(&id),
|
||||
family,
|
||||
reinterpret_cast<ZT_InetAddress *>(&addr)) == ZT_RESULT_OK);
|
||||
reinterpret_cast<ZT_InetAddress*>(&addr))
|
||||
== ZT_RESULT_OK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implementation of NetworkController::Sender ------------------------------------------------------------------------
|
||||
|
||||
void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig)
|
||||
void Node::ncSendConfig(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
const NetworkConfig& nc,
|
||||
bool sendLegacyFormatConfig)
|
||||
{
|
||||
if (destination == m_ctx.identity.address()) {
|
||||
SharedPtr<Network> n(m_ctx.networks->get(nwid));
|
||||
|
@ -644,7 +700,8 @@ void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid,
|
|||
return;
|
||||
CallContext cc(clock, ticks, tPtr);
|
||||
n->setConfiguration(cc, nc, true);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Dictionary dconf;
|
||||
if (nc.toDictionary(dconf)) {
|
||||
uint64_t configUpdateId = Utils::random();
|
||||
|
@ -657,11 +714,10 @@ void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid,
|
|||
/*
|
||||
unsigned int chunkIndex = 0;
|
||||
while (chunkIndex < totalSize) {
|
||||
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH - (ZT_PACKET_IDX_PAYLOAD + 256)));
|
||||
Packet outp(destination,m_ctx.identity.address(),(requestPacketId) ? Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG);
|
||||
if (requestPacketId) {
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH
|
||||
- (ZT_PACKET_IDX_PAYLOAD + 256))); Packet outp(destination,m_ctx.identity.address(),(requestPacketId) ?
|
||||
Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG); if (requestPacketId) { outp.append((unsigned
|
||||
char)Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append(requestPacketId);
|
||||
}
|
||||
|
||||
const unsigned int sigStart = outp.size();
|
||||
|
@ -675,9 +731,8 @@ void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid,
|
|||
outp.append((uint32_t)chunkIndex);
|
||||
|
||||
uint8_t sig[256];
|
||||
const unsigned int siglen = m_ctx.identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart,sig,sizeof(sig));
|
||||
outp.append((uint8_t)1);
|
||||
outp.append((uint16_t)siglen);
|
||||
const unsigned int siglen = m_ctx.identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) +
|
||||
sigStart,outp.size() - sigStart,sig,sizeof(sig)); outp.append((uint8_t)1); outp.append((uint16_t)siglen);
|
||||
outp.append(sig,siglen);
|
||||
|
||||
outp.compress();
|
||||
|
@ -689,7 +744,12 @@ void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid,
|
|||
}
|
||||
}
|
||||
|
||||
void Node::ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev)
|
||||
void Node::ncSendRevocation(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
const Address& destination,
|
||||
const RevocationCredential& rev)
|
||||
{
|
||||
if (destination == m_ctx.identity.address()) {
|
||||
SharedPtr<Network> n(m_ctx.networks->get(rev.networkId()));
|
||||
|
@ -697,7 +757,8 @@ void Node::ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Addr
|
|||
return;
|
||||
CallContext cc(clock, ticks, tPtr);
|
||||
n->addCredential(cc, m_ctx.identity, rev);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
/*
|
||||
Packet outp(destination,m_ctx.identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||
|
@ -712,7 +773,14 @@ void Node::ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Addr
|
|||
}
|
||||
}
|
||||
|
||||
void Node::ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode)
|
||||
void Node::ncSendError(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
NetworkController::ErrorCode errorCode)
|
||||
{
|
||||
if (destination == m_ctx.identity.address()) {
|
||||
SharedPtr<Network> n(m_ctx.networks->get(nwid));
|
||||
|
@ -730,7 +798,8 @@ void Node::ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (requestPacketId) {
|
||||
}
|
||||
else if (requestPacketId) {
|
||||
// TODO
|
||||
/*
|
||||
Packet outp(destination,m_ctx.identity.address(),Packet::VERB_ERROR);
|
||||
|
|
125
core/Node.hpp
125
core/Node.hpp
|
@ -14,19 +14,19 @@
|
|||
#ifndef ZT_NODE_HPP
|
||||
#define ZT_NODE_HPP
|
||||
|
||||
#include "Buf.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Store.hpp"
|
||||
#include "CallContext.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -35,13 +35,18 @@ namespace ZeroTier {
|
|||
*
|
||||
* The pointer returned by ZT_Node_new() is an instance of this class.
|
||||
*/
|
||||
class Node : public NetworkController::Sender
|
||||
{
|
||||
class Node : public NetworkController::Sender {
|
||||
public:
|
||||
// Get rid of alignment warnings on 32-bit Windows
|
||||
#ifdef __WINDOWS__
|
||||
void * operator new(size_t i) { return _mm_malloc(i,16); }
|
||||
void operator delete(void* p) { _mm_free(p); }
|
||||
void* operator new(size_t i)
|
||||
{
|
||||
return _mm_malloc(i, 16);
|
||||
}
|
||||
void operator delete(void* p)
|
||||
{
|
||||
_mm_free(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
Node(void* uPtr, const struct ZT_Node_Callbacks* callbacks, const CallContext& cc);
|
||||
|
@ -50,51 +55,29 @@ public:
|
|||
|
||||
void shutdown(const CallContext& cc);
|
||||
|
||||
ZT_ResultCode processBackgroundTasks(
|
||||
const CallContext &cc,
|
||||
volatile int64_t *nextBackgroundTaskDeadline);
|
||||
ZT_ResultCode processBackgroundTasks(const CallContext& cc, volatile int64_t* nextBackgroundTaskDeadline);
|
||||
|
||||
ZT_ResultCode join(
|
||||
uint64_t nwid,
|
||||
const ZT_Fingerprint *controllerFingerprint,
|
||||
void *uptr,
|
||||
const CallContext &cc);
|
||||
ZT_ResultCode join(uint64_t nwid, const ZT_Fingerprint* controllerFingerprint, void* uptr, const CallContext& cc);
|
||||
|
||||
ZT_ResultCode leave(
|
||||
uint64_t nwid,
|
||||
void **uptr,
|
||||
const CallContext &cc);
|
||||
ZT_ResultCode leave(uint64_t nwid, void** uptr, const CallContext& cc);
|
||||
|
||||
ZT_ResultCode multicastSubscribe(
|
||||
const CallContext &cc,
|
||||
uint64_t nwid,
|
||||
uint64_t multicastGroup,
|
||||
unsigned long multicastAdi);
|
||||
ZT_ResultCode
|
||||
multicastSubscribe(const CallContext& cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi);
|
||||
|
||||
ZT_ResultCode multicastUnsubscribe(
|
||||
const CallContext &cc,
|
||||
uint64_t nwid,
|
||||
uint64_t multicastGroup,
|
||||
unsigned long multicastAdi);
|
||||
ZT_ResultCode
|
||||
multicastUnsubscribe(const CallContext& cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi);
|
||||
|
||||
void status(
|
||||
ZT_NodeStatus *status) const;
|
||||
void status(ZT_NodeStatus* status) const;
|
||||
|
||||
ZT_PeerList *peers(
|
||||
const CallContext &cc) const;
|
||||
ZT_PeerList* peers(const CallContext& cc) const;
|
||||
|
||||
ZT_VirtualNetworkConfig *networkConfig(
|
||||
uint64_t nwid) const;
|
||||
ZT_VirtualNetworkConfig* networkConfig(uint64_t nwid) const;
|
||||
|
||||
ZT_VirtualNetworkList* networks() const;
|
||||
|
||||
void setNetworkUserPtr(
|
||||
uint64_t nwid,
|
||||
void *ptr);
|
||||
void setNetworkUserPtr(uint64_t nwid, void* ptr);
|
||||
|
||||
void setInterfaceAddresses(
|
||||
const ZT_InterfaceAddress *addrs,
|
||||
unsigned int addrCount);
|
||||
void setInterfaceAddresses(const ZT_InterfaceAddress* addrs, unsigned int addrCount);
|
||||
|
||||
ZT_CertificateError addCertificate(
|
||||
const CallContext& cc,
|
||||
|
@ -103,21 +86,13 @@ public:
|
|||
const void* certData,
|
||||
unsigned int certSize);
|
||||
|
||||
ZT_ResultCode deleteCertificate(
|
||||
const CallContext &cc,
|
||||
const void *serialNo);
|
||||
ZT_ResultCode deleteCertificate(const CallContext& cc, const void* serialNo);
|
||||
|
||||
ZT_CertificateList* listCertificates();
|
||||
|
||||
int sendUserMessage(
|
||||
const CallContext &cc,
|
||||
uint64_t dest,
|
||||
uint64_t typeId,
|
||||
const void *data,
|
||||
unsigned int len);
|
||||
int sendUserMessage(const CallContext& cc, uint64_t dest, uint64_t typeId, const void* data, unsigned int len);
|
||||
|
||||
void setController(
|
||||
void *networkControllerInstance);
|
||||
void setController(void* networkControllerInstance);
|
||||
|
||||
/**
|
||||
* Post an event via external callback
|
||||
|
@ -127,8 +102,12 @@ public:
|
|||
* @param md Event data or NULL if none
|
||||
* @param mdSize Size of event data
|
||||
*/
|
||||
ZT_INLINE void postEvent(void *const tPtr, const ZT_Event ev, const void *const md = nullptr, const unsigned int mdSize = 0) noexcept
|
||||
{ m_ctx.cb.eventCallback(reinterpret_cast<ZT_Node *>(this), m_ctx.uPtr, tPtr, ev, md, mdSize); }
|
||||
ZT_INLINE void
|
||||
postEvent(void* const tPtr, const ZT_Event ev, const void* const md = nullptr, const unsigned int mdSize = 0)
|
||||
noexcept
|
||||
{
|
||||
m_ctx.cb.eventCallback(reinterpret_cast<ZT_Node*>(this), m_ctx.uPtr, tPtr, ev, md, mdSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a path should be used for ZeroTier traffic
|
||||
|
@ -155,15 +134,39 @@ public:
|
|||
bool externalPathLookup(void* tPtr, const Identity& id, int family, InetAddress& addr);
|
||||
|
||||
ZT_INLINE const Identity& identity() const noexcept
|
||||
{ return m_ctx.identity; }
|
||||
{
|
||||
return m_ctx.identity;
|
||||
}
|
||||
|
||||
ZT_INLINE const Context& context() const noexcept
|
||||
{ return m_ctx; }
|
||||
{
|
||||
return m_ctx;
|
||||
}
|
||||
|
||||
// Implementation of NetworkController::Sender interface
|
||||
virtual void ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig);
|
||||
virtual void ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev);
|
||||
virtual void ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode);
|
||||
virtual void ncSendConfig(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
const NetworkConfig& nc,
|
||||
bool sendLegacyFormatConfig);
|
||||
virtual void ncSendRevocation(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
const Address& destination,
|
||||
const RevocationCredential& rev);
|
||||
virtual void ncSendError(
|
||||
void* tPtr,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
uint64_t nwid,
|
||||
uint64_t requestPacketId,
|
||||
const Address& destination,
|
||||
NetworkController::ErrorCode errorCode);
|
||||
|
||||
private:
|
||||
Context m_ctx;
|
||||
|
|
25
core/OS.hpp
25
core/OS.hpp
|
@ -17,7 +17,9 @@
|
|||
/* Uncomment this to force a whole lot of debug output. */
|
||||
#define ZT_DEBUG_SPEW
|
||||
|
||||
#if !defined(__GNUC__) && (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__INTEL_COMPILER) || defined(__clang__))
|
||||
#if ! defined(__GNUC__) \
|
||||
&& (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
|
||||
|| defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__INTEL_COMPILER) || defined(__clang__))
|
||||
#define __GNUC__ 3
|
||||
#endif
|
||||
|
||||
|
@ -48,35 +50,39 @@
|
|||
#undef __BSD__
|
||||
#endif
|
||||
|
||||
#include <Shlobj.h>
|
||||
#include <WinSock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <Windows.h>
|
||||
#include <memoryapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <Shlobj.h>
|
||||
#include <sys/param.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#endif /* Microsoft Windows */
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#endif /* NOT Microsoft Windows */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||
#if ( \
|
||||
defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) \
|
||||
|| defined(__AMD64__) || defined(_M_X64))
|
||||
#define ZT_ARCH_X64 1
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#include <immintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#if defined(ZT_ARCH_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386)
|
||||
#if defined(ZT_ARCH_X64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) \
|
||||
|| defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) \
|
||||
|| defined(__I86__) || defined(__INTEL__) || defined(__386)
|
||||
#define ZT_ARCH_X86 1
|
||||
#endif
|
||||
|
||||
|
@ -268,7 +274,8 @@ typedef unsigned uint128_t __attribute__((mode(TI)));
|
|||
#define ZT_VA_ARGS(...) , ##__VA_ARGS__
|
||||
|
||||
#ifdef ZT_DEBUG_SPEW
|
||||
#define ZT_SPEW(f,...) fprintf(stderr,"%s:%d(%s): " f ZT_EOL_S,__FILE__,__LINE__,__FUNCTION__ ZT_VA_ARGS(__VA_ARGS__))
|
||||
#define ZT_SPEW(f, ...) \
|
||||
fprintf(stderr, "%s:%d(%s): " f ZT_EOL_S, __FILE__, __LINE__, __FUNCTION__ ZT_VA_ARGS(__VA_ARGS__))
|
||||
#else
|
||||
#define ZT_SPEW(f, ...)
|
||||
#endif
|
||||
|
|
|
@ -21,11 +21,16 @@ void OwnershipCredential::addThing(const InetAddress &ip)
|
|||
return;
|
||||
if (ip.as.sa.sa_family == AF_INET) {
|
||||
m_thingTypes[m_thingCount] = THING_IPV4_ADDRESS;
|
||||
Utils::copy<4>(m_thingValues[m_thingCount], &(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr));
|
||||
Utils::copy<4>(
|
||||
m_thingValues[m_thingCount],
|
||||
&(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr));
|
||||
++m_thingCount;
|
||||
} else if (ip.as.sa.sa_family == AF_INET6) {
|
||||
}
|
||||
else if (ip.as.sa.sa_family == AF_INET6) {
|
||||
m_thingTypes[m_thingCount] = THING_IPV6_ADDRESS;
|
||||
Utils::copy<16>(m_thingValues[m_thingCount], reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr);
|
||||
Utils::copy<16>(
|
||||
m_thingValues[m_thingCount],
|
||||
reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr);
|
||||
++m_thingCount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
#ifndef ZT_CERTIFICATEOFOWNERSHIP_HPP
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_HPP
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MAC.hpp"
|
||||
|
@ -28,7 +28,9 @@
|
|||
// Maximum size of a thing's value field in bytes
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE 16
|
||||
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX (8 + 8 + 8 + 4 + 2 + ((1 + ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE) * ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) + 5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
|
||||
#define ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX \
|
||||
(8 + 8 + 8 + 4 + 2 + ((1 + ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE) * ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) \
|
||||
+ 5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -40,26 +42,24 @@ class Context;
|
|||
* These are used in conjunction with the rules engine to make IP addresses and
|
||||
* other identifiers un-spoofable.
|
||||
*/
|
||||
class OwnershipCredential : public Credential
|
||||
{
|
||||
class OwnershipCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_COO; }
|
||||
|
||||
enum Thing
|
||||
{
|
||||
THING_NULL = 0,
|
||||
THING_MAC_ADDRESS = 1,
|
||||
THING_IPV4_ADDRESS = 2,
|
||||
THING_IPV6_ADDRESS = 3
|
||||
};
|
||||
return ZT_CREDENTIAL_TYPE_COO;
|
||||
}
|
||||
|
||||
enum Thing { THING_NULL = 0, THING_MAC_ADDRESS = 1, THING_IPV4_ADDRESS = 2, THING_IPV6_ADDRESS = 3 };
|
||||
|
||||
ZT_INLINE OwnershipCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
ZT_INLINE OwnershipCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id) noexcept
|
||||
ZT_INLINE
|
||||
OwnershipCredential(const uint64_t nwid, const int64_t ts, const Address& issuedTo, const uint32_t id) noexcept
|
||||
{
|
||||
memoryZero(this);
|
||||
m_networkId = nwid;
|
||||
|
@ -69,45 +69,74 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_networkId; }
|
||||
{
|
||||
return m_networkId;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_ts; }
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_ts; }
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& issuedTo() const noexcept
|
||||
{ return m_issuedTo; }
|
||||
{
|
||||
return m_issuedTo;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& signer() const noexcept
|
||||
{ return m_signedBy; }
|
||||
{
|
||||
return m_signedBy;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t* signature() const noexcept
|
||||
{ return m_signature; }
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{ return m_signatureLength; }
|
||||
{
|
||||
return m_signatureLength;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int thingCount() const noexcept
|
||||
{ return (unsigned int)m_thingCount; }
|
||||
{
|
||||
return (unsigned int)m_thingCount;
|
||||
}
|
||||
|
||||
ZT_INLINE Thing thingType(const unsigned int i) const noexcept
|
||||
{ return (Thing)m_thingTypes[i]; }
|
||||
{
|
||||
return (Thing)m_thingTypes[i];
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t* thingValue(const unsigned int i) const noexcept
|
||||
{ return m_thingValues[i]; }
|
||||
{
|
||||
return m_thingValues[i];
|
||||
}
|
||||
|
||||
ZT_INLINE bool owns(const InetAddress& ip) const noexcept
|
||||
{
|
||||
if (ip.as.sa.sa_family == AF_INET)
|
||||
return this->_owns(THING_IPV4_ADDRESS, &(reinterpret_cast<const struct sockaddr_in *>(&ip)->sin_addr.s_addr), 4);
|
||||
return this->_owns(
|
||||
THING_IPV4_ADDRESS,
|
||||
&(reinterpret_cast<const struct sockaddr_in*>(&ip)->sin_addr.s_addr),
|
||||
4);
|
||||
else if (ip.as.sa.sa_family == AF_INET6)
|
||||
return this->_owns(THING_IPV6_ADDRESS, reinterpret_cast<const struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr, 16);
|
||||
else return false;
|
||||
return this->_owns(
|
||||
THING_IPV6_ADDRESS,
|
||||
reinterpret_cast<const struct sockaddr_in6*>(&ip)->sin6_addr.s6_addr,
|
||||
16);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_INLINE bool owns(const MAC& mac) const noexcept
|
||||
|
@ -149,23 +178,33 @@ public:
|
|||
* @return Credential verification result: OK, bad signature, or identity needed
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
|
||||
int unmarshal(const uint8_t* data, int len) noexcept;
|
||||
|
||||
// Provides natural sort order by ID
|
||||
ZT_INLINE bool operator<(const OwnershipCredential& coo) const noexcept
|
||||
{ return (m_id < coo.m_id); }
|
||||
{
|
||||
return (m_id < coo.m_id);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const OwnershipCredential& coo) const noexcept
|
||||
{ return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0); }
|
||||
{
|
||||
return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const OwnershipCredential& coo) const noexcept
|
||||
{ return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0); }
|
||||
{
|
||||
return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_INLINE bool _owns(const Thing& t, const void* v, unsigned int l) const noexcept
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
/****/
|
||||
|
||||
#include "Path.hpp"
|
||||
|
||||
#include "Context.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
|
@ -19,7 +20,17 @@ namespace ZeroTier {
|
|||
|
||||
bool Path::send(const Context& ctx, const CallContext& cc, const void* const data, const unsigned int len) noexcept
|
||||
{
|
||||
if (likely(ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, m_localSocket, reinterpret_cast<const ZT_InetAddress *>(&m_addr), data, len, 0) == 0)) {
|
||||
if (likely(
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
m_localSocket,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&m_addr),
|
||||
data,
|
||||
len,
|
||||
0)
|
||||
== 0)) {
|
||||
m_lastOut = cc.ticks;
|
||||
m_outMeter.log(cc.ticks, len);
|
||||
return true;
|
||||
|
|
110
core/Path.hpp
110
core/Path.hpp
|
@ -14,61 +14,63 @@
|
|||
#ifndef ZT_PATH_HPP
|
||||
#define ZT_PATH_HPP
|
||||
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Meter.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Meter.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "CallContext.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class Context;
|
||||
|
||||
template< unsigned int MF, unsigned int MFP, unsigned int GCT, unsigned int GCS, typename P >
|
||||
class Defragmenter;
|
||||
template <unsigned int MF, unsigned int MFP, unsigned int GCT, unsigned int GCS, typename P> class Defragmenter;
|
||||
|
||||
/**
|
||||
* A path across the physical network
|
||||
*/
|
||||
class Path
|
||||
{
|
||||
class Path {
|
||||
friend class SharedPtr<Path>;
|
||||
|
||||
// Allow defragmenter to access fragment-in-flight info stored in Path for performance reasons.
|
||||
template <unsigned int MF, unsigned int MFP, unsigned int GCT, unsigned int GCS, typename P>
|
||||
friend
|
||||
class Defragmenter;
|
||||
friend class Defragmenter;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Map key for paths designed for very fast lookup
|
||||
*/
|
||||
class Key
|
||||
{
|
||||
class Key {
|
||||
public:
|
||||
ZT_INLINE Key() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Key(const InetAddress& ip) noexcept
|
||||
{
|
||||
const unsigned int family = ip.as.sa.sa_family;
|
||||
if (family == AF_INET) {
|
||||
const uint16_t p = (uint16_t)ip.as.sa_in.sin_port;
|
||||
m_hashCode = Utils::hash64((((uint64_t)ip.as.sa_in.sin_addr.s_addr) << 16U) ^ ((uint64_t)p) ^ Utils::s_mapNonce);
|
||||
m_hashCode =
|
||||
Utils::hash64((((uint64_t)ip.as.sa_in.sin_addr.s_addr) << 16U) ^ ((uint64_t)p) ^ Utils::s_mapNonce);
|
||||
m_ipv6Net64 = 0; // 0 for IPv4, never 0 for IPv6
|
||||
m_port = p;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (likely(family == AF_INET6)) {
|
||||
const uint64_t a = Utils::loadMachineEndian< uint64_t >(reinterpret_cast<const uint8_t *>(ip.as.sa_in6.sin6_addr.s6_addr));
|
||||
const uint64_t b = Utils::loadMachineEndian< uint64_t >(reinterpret_cast<const uint8_t *>(ip.as.sa_in6.sin6_addr.s6_addr) + 8);
|
||||
const uint64_t a = Utils::loadMachineEndian<uint64_t>(
|
||||
reinterpret_cast<const uint8_t*>(ip.as.sa_in6.sin6_addr.s6_addr));
|
||||
const uint64_t b = Utils::loadMachineEndian<uint64_t>(
|
||||
reinterpret_cast<const uint8_t*>(ip.as.sa_in6.sin6_addr.s6_addr) + 8);
|
||||
const uint16_t p = ip.as.sa_in6.sin6_port;
|
||||
m_hashCode = Utils::hash64(a ^ b ^ ((uint64_t)p) ^ Utils::s_mapNonce);
|
||||
m_ipv6Net64 = a; // IPv6 /64
|
||||
m_port = p;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// This is not reachable since InetAddress can only be AF_INET or AF_INET6, but implement something.
|
||||
m_hashCode = Utils::fnv1a32(&ip, sizeof(InetAddress));
|
||||
m_ipv6Net64 = 0;
|
||||
|
@ -78,22 +80,30 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)m_hashCode; }
|
||||
{
|
||||
return (unsigned long)m_hashCode;
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const Key& k) const noexcept
|
||||
{ return (m_hashCode == k.m_hashCode) && (m_ipv6Net64 == k.m_ipv6Net64) && (m_port == k.m_port); }
|
||||
{
|
||||
return (m_hashCode == k.m_hashCode) && (m_ipv6Net64 == k.m_ipv6Net64) && (m_port == k.m_port);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const Key& k) const noexcept
|
||||
{ return (!(*this == k)); }
|
||||
{
|
||||
return (! (*this == k));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const Key& k) const noexcept
|
||||
{
|
||||
if (m_hashCode < k.m_hashCode) {
|
||||
return true;
|
||||
} else if (m_hashCode == k.m_hashCode) {
|
||||
}
|
||||
else if (m_hashCode == k.m_hashCode) {
|
||||
if (m_ipv6Net64 < k.m_ipv6Net64) {
|
||||
return true;
|
||||
} else if (m_ipv6Net64 == k.m_ipv6Net64) {
|
||||
}
|
||||
else if (m_ipv6Net64 == k.m_ipv6Net64) {
|
||||
return (m_port < k.m_port);
|
||||
}
|
||||
}
|
||||
|
@ -101,13 +111,19 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE bool operator>(const Key& k) const noexcept
|
||||
{ return (k < *this); }
|
||||
{
|
||||
return (k < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const Key& k) const noexcept
|
||||
{ return !(k < *this); }
|
||||
{
|
||||
return ! (k < *this);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const Key& k) const noexcept
|
||||
{ return !(*this < k); }
|
||||
{
|
||||
return ! (*this < k);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_hashCode;
|
||||
|
@ -115,13 +131,14 @@ public:
|
|||
uint16_t m_port;
|
||||
};
|
||||
|
||||
ZT_INLINE Path(const int64_t l, const InetAddress &r) noexcept:
|
||||
m_localSocket(l),
|
||||
m_lastIn(0),
|
||||
m_lastOut(0),
|
||||
m_latency(-1),
|
||||
m_addr(r)
|
||||
{}
|
||||
ZT_INLINE Path(const int64_t l, const InetAddress& r) noexcept
|
||||
: m_localSocket(l)
|
||||
, m_lastIn(0)
|
||||
, m_lastOut(0)
|
||||
, m_latency(-1)
|
||||
, m_addr(r)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet via this path (last out time is also updated)
|
||||
|
@ -166,7 +183,8 @@ public:
|
|||
const int lat = m_latency.load(std::memory_order_relaxed);
|
||||
if (likely(lat > 0)) {
|
||||
m_latency.store((lat + (int)newMeasurement) >> 1U, std::memory_order_relaxed);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_latency.store((int)newMeasurement, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +193,9 @@ public:
|
|||
* @return Latency in milliseconds or -1 if unknown
|
||||
*/
|
||||
ZT_INLINE int latency() const noexcept
|
||||
{ return m_latency.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return m_latency.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check path aliveness
|
||||
|
@ -183,31 +203,41 @@ public:
|
|||
* @param now Current time
|
||||
*/
|
||||
ZT_INLINE bool alive(const CallContext& cc) const noexcept
|
||||
{ return ((cc.ticks - m_lastIn.load(std::memory_order_relaxed)) < ZT_PATH_ALIVE_TIMEOUT); }
|
||||
{
|
||||
return ((cc.ticks - m_lastIn.load(std::memory_order_relaxed)) < ZT_PATH_ALIVE_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Physical address
|
||||
*/
|
||||
ZT_INLINE const InetAddress& address() const noexcept
|
||||
{ return m_addr; }
|
||||
{
|
||||
return m_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Local socket as specified by external code
|
||||
*/
|
||||
ZT_INLINE int64_t localSocket() const noexcept
|
||||
{ return m_localSocket; }
|
||||
{
|
||||
return m_localSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Last time we received anything
|
||||
*/
|
||||
ZT_INLINE int64_t lastIn() const noexcept
|
||||
{ return m_lastIn.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return m_lastIn.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Last time we sent something
|
||||
*/
|
||||
ZT_INLINE int64_t lastOut() const noexcept
|
||||
{ return m_lastOut.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return m_lastOut.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
private:
|
||||
const int64_t m_localSocket;
|
||||
|
|
252
core/Peer.cpp
252
core/Peer.cpp
|
@ -11,41 +11,45 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Peer.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Expect.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
// An arbitrary byte to send in single byte probes, incremented on each probe.
|
||||
static uint8_t s_arbitraryByte = (uint8_t)Utils::random();
|
||||
|
||||
Peer::Peer() :
|
||||
m_key((uintptr_t)&m_identityKey),
|
||||
m_keyRenegotiationNeeded(false),
|
||||
m_lastReceive(0),
|
||||
m_lastSend(0),
|
||||
m_lastSentHello(0),
|
||||
m_lastWhoisRequestReceived(0),
|
||||
m_lastEchoRequestReceived(0),
|
||||
m_lastProbeReceived(0),
|
||||
m_alivePathCount(0),
|
||||
m_bestPath(0),
|
||||
m_vProto(0),
|
||||
m_vMajor(0),
|
||||
m_vMinor(0),
|
||||
m_vRevision(0)
|
||||
{}
|
||||
Peer::Peer()
|
||||
: m_key((uintptr_t)&m_identityKey)
|
||||
, m_keyRenegotiationNeeded(false)
|
||||
, m_lastReceive(0)
|
||||
, m_lastSend(0)
|
||||
, m_lastSentHello(0)
|
||||
, m_lastWhoisRequestReceived(0)
|
||||
, m_lastEchoRequestReceived(0)
|
||||
, m_lastProbeReceived(0)
|
||||
, m_alivePathCount(0)
|
||||
, m_bestPath(0)
|
||||
, m_vProto(0)
|
||||
, m_vMajor(0)
|
||||
, m_vMinor(0)
|
||||
, m_vRevision(0)
|
||||
{
|
||||
}
|
||||
|
||||
Peer::~Peer()
|
||||
{ Utils::burn(m_helloMacKey, sizeof(m_helloMacKey)); }
|
||||
{
|
||||
Utils::burn(m_helloMacKey, sizeof(m_helloMacKey));
|
||||
}
|
||||
|
||||
bool Peer::init(const Context& ctx, const CallContext& cc, const Identity& peerIdentity)
|
||||
{
|
||||
|
@ -103,10 +107,12 @@ void Peer::received(
|
|||
m_prioritizePaths(cc);
|
||||
if (m_alivePathCount == ZT_MAX_PEER_NETWORK_PATHS) {
|
||||
newPathIdx = ZT_MAX_PEER_NETWORK_PATHS - 1;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
newPathIdx = m_alivePathCount++;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
newPathIdx = m_alivePathCount++;
|
||||
}
|
||||
|
||||
|
@ -120,13 +126,28 @@ void Peer::received(
|
|||
|
||||
m_prioritizePaths(cc);
|
||||
|
||||
ctx.t->learnedNewPath(cc, 0x582fabdd, packetId, m_id, path->address(), (old) ? old->address() : InetAddress());
|
||||
} else {
|
||||
ctx.t->learnedNewPath(
|
||||
cc,
|
||||
0x582fabdd,
|
||||
packetId,
|
||||
m_id,
|
||||
path->address(),
|
||||
(old) ? old->address() : InetAddress());
|
||||
}
|
||||
else {
|
||||
int64_t& lt = m_lastTried[Endpoint(path->address())];
|
||||
if ((cc.ticks - lt) < ZT_PATH_MIN_TRY_INTERVAL) {
|
||||
lt = cc.ticks;
|
||||
path->sent(cc, m_hello(ctx, cc, path->localSocket(), path->address(), false));
|
||||
ctx.t->tryingNewPath(cc, 0xb7747ddd, m_id, path->address(), path->address(), packetId, (uint8_t)verb, m_id);
|
||||
ctx.t->tryingNewPath(
|
||||
cc,
|
||||
0xb7747ddd,
|
||||
m_id,
|
||||
path->address(),
|
||||
path->address(),
|
||||
packetId,
|
||||
(uint8_t)verb,
|
||||
m_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +160,8 @@ void Peer::send(const Context &ctx, const CallContext &cc, const void *data, uns
|
|||
if (likely(via)) {
|
||||
if (likely(via->send(ctx, cc, data, len)))
|
||||
this->sent(cc, len);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const SharedPtr<Peer> root(ctx.topology->root());
|
||||
if (likely((root) && (root.ptr() != this))) {
|
||||
via = root->path(cc);
|
||||
|
@ -163,7 +185,12 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
// Determine if we need a new ephemeral key pair and if a new HELLO needs
|
||||
// to be sent. The latter happens every ZT_PEER_HELLO_INTERVAL or if a new
|
||||
// ephemeral key pair is generated.
|
||||
bool needHello = (((m_vProto >= 20) && (m_keyRenegotiationNeeded || (key == &m_identityKey) || ((cc.ticks - key->timestamp()) >= (ZT_SYMMETRIC_KEY_TTL / 2)) || (key->odometer() > (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2)))) || ((cc.ticks - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL));
|
||||
bool needHello =
|
||||
(((m_vProto >= 20)
|
||||
&& (m_keyRenegotiationNeeded || (key == &m_identityKey)
|
||||
|| ((cc.ticks - key->timestamp()) >= (ZT_SYMMETRIC_KEY_TTL / 2))
|
||||
|| (key->odometer() > (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2))))
|
||||
|| ((cc.ticks - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL));
|
||||
|
||||
// Prioritize paths and more importantly for here forget dead ones.
|
||||
m_prioritizePaths(cc);
|
||||
|
@ -175,13 +202,24 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
// callback (if one was supplied).
|
||||
|
||||
if (m_locator) {
|
||||
for (Vector< std::pair< Endpoint, SharedPtr< const Locator::EndpointAttributes > > >::const_iterator ep(m_locator->endpoints().begin()); ep != m_locator->endpoints().end(); ++ep) {
|
||||
for (Vector<std::pair<Endpoint, SharedPtr<const Locator::EndpointAttributes> > >::const_iterator ep(
|
||||
m_locator->endpoints().begin());
|
||||
ep != m_locator->endpoints().end();
|
||||
++ep) {
|
||||
if (ep->first.type == ZT_ENDPOINT_TYPE_IP_UDP) {
|
||||
if (ctx.node->filterPotentialPath(cc.tPtr, m_id, -1, ep->first.ip())) {
|
||||
int64_t& lt = m_lastTried[ep->first];
|
||||
if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) {
|
||||
lt = cc.ticks;
|
||||
ctx.t->tryingNewPath(cc, 0x84b22322, m_id, ep->first.ip(), InetAddress::NIL, 0, 0, Identity::NIL);
|
||||
ctx.t->tryingNewPath(
|
||||
cc,
|
||||
0x84b22322,
|
||||
m_id,
|
||||
ep->first.ip(),
|
||||
InetAddress::NIL,
|
||||
0,
|
||||
0,
|
||||
Identity::NIL);
|
||||
sent(cc, m_sendProbe(ctx, cc, -1, ep->first.ip(), nullptr, 0));
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +239,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
unsigned int attempts = 0;
|
||||
for (;;) {
|
||||
p_TryQueueItem& qi = m_tryQueue.front();
|
||||
|
@ -219,21 +258,19 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
|
||||
++attempts;
|
||||
if (qi.iteration < 0) {
|
||||
|
||||
// If iteration is less than zero, try to contact the original address.
|
||||
// It may be set to a larger negative value to try multiple times such
|
||||
// as e.g. -3 to try 3 times.
|
||||
sent(cc, m_sendProbe(ctx, cc, -1, qi.target.ip(), nullptr, 0));
|
||||
++qi.iteration;
|
||||
goto requeue_item;
|
||||
|
||||
} else if (qi.target.ip().isV4() && (m_alivePathCount == 0)) {
|
||||
}
|
||||
else if (qi.target.ip().isV4() && (m_alivePathCount == 0)) {
|
||||
// When iteration reaches zero the queue item is dropped unless it's
|
||||
// IPv4 and we have no direct paths. In that case some heavier NAT-t
|
||||
// strategies are attempted.
|
||||
|
||||
if (qi.target.ip().port() < 1024) {
|
||||
|
||||
// If the source port is privileged, we actually scan every possible
|
||||
// privileged port in random order slowly over multiple iterations
|
||||
// of pulse(). This is done in batches of ZT_NAT_T_PORT_SCAN_MAX.
|
||||
|
@ -248,9 +285,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
sent(cc, m_sendProbe(ctx, cc, -1, qi.target.ip(), ports, pn));
|
||||
if (qi.iteration < 1023)
|
||||
goto requeue_item;
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
else {
|
||||
// For un-privileged ports we'll try ZT_NAT_T_PORT_SCAN_MAX ports
|
||||
// beyond the one we were sent to catch some sequentially assigning
|
||||
// symmetric NATs.
|
||||
|
@ -262,7 +298,6 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
sent(cc, m_sendProbe(ctx, cc, -1, tmp, nullptr, 0));
|
||||
if (qi.iteration < ZT_NAT_T_PORT_SCAN_MAX)
|
||||
goto requeue_item;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +307,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
m_tryQueue.pop_front();
|
||||
if (attempts >= std::min((unsigned int)m_tryQueue.size(), (unsigned int)ZT_NAT_T_PORT_SCAN_MAX))
|
||||
break;
|
||||
else continue;
|
||||
else
|
||||
continue;
|
||||
|
||||
// If the code skips here the front item is instead moved to the back.
|
||||
requeue_item:
|
||||
|
@ -280,7 +316,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
m_tryQueue.splice(m_tryQueue.end(), m_tryQueue, m_tryQueue.begin());
|
||||
if (attempts >= std::min((unsigned int)m_tryQueue.size(), (unsigned int)ZT_NAT_T_PORT_SCAN_MAX))
|
||||
break;
|
||||
else continue;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,14 +326,16 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
for (unsigned int i = 0; i < m_alivePathCount; ++i) {
|
||||
if (needHello) {
|
||||
needHello = false;
|
||||
const unsigned int bytes = m_hello(ctx, cc, m_paths[i]->localSocket(), m_paths[i]->address(), m_keyRenegotiationNeeded);
|
||||
const unsigned int bytes =
|
||||
m_hello(ctx, cc, m_paths[i]->localSocket(), m_paths[i]->address(), m_keyRenegotiationNeeded);
|
||||
if (bytes) {
|
||||
m_paths[i]->sent(cc, bytes);
|
||||
sent(cc, bytes);
|
||||
m_lastSentHello = cc.ticks;
|
||||
m_keyRenegotiationNeeded = false;
|
||||
}
|
||||
} else if ((cc.ticks - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) {
|
||||
}
|
||||
else if ((cc.ticks - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) {
|
||||
m_paths[i]->send(ctx, cc, &s_arbitraryByte, 1);
|
||||
++s_arbitraryByte;
|
||||
sent(cc, 1);
|
||||
|
@ -309,7 +348,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
if (root) {
|
||||
const SharedPtr<Path> via(root->path(cc));
|
||||
if (via) {
|
||||
const unsigned int bytes = m_hello(ctx, cc, via->localSocket(), via->address(), m_keyRenegotiationNeeded);
|
||||
const unsigned int bytes =
|
||||
m_hello(ctx, cc, via->localSocket(), via->address(), m_keyRenegotiationNeeded);
|
||||
if (bytes) {
|
||||
via->sent(cc, bytes);
|
||||
root->relayed(cc, bytes);
|
||||
|
@ -325,7 +365,8 @@ void Peer::pulse(const Context &ctx, const CallContext &cc)
|
|||
for (Map<Endpoint, int64_t>::iterator i(m_lastTried.begin()); i != m_lastTried.end();) {
|
||||
if ((cc.ticks - i->second) > (ZT_PATH_MIN_TRY_INTERVAL * 3))
|
||||
m_lastTried.erase(i++);
|
||||
else ++i;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,7 +391,15 @@ void Peer::contact(const Context &ctx, const CallContext &cc, const Endpoint &ep
|
|||
// For IPv4 addresses we send a tiny packet with a low TTL, which helps to
|
||||
// traverse some NAT types. It has no effect otherwise.
|
||||
if (ep.isInetAddr() && ep.ip().isV4()) {
|
||||
ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&ep.ip()), &s_arbitraryByte, 1, 2);
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
-1,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&ep.ip()),
|
||||
&s_arbitraryByte,
|
||||
1,
|
||||
2);
|
||||
++s_arbitraryByte;
|
||||
}
|
||||
|
||||
|
@ -366,16 +415,24 @@ void Peer::contact(const Context &ctx, const CallContext &cc, const Endpoint &ep
|
|||
m_tryQueue.push_back(p_TryQueueItem(ep, -tries));
|
||||
}
|
||||
|
||||
void Peer::resetWithinScope(const Context &ctx, const CallContext &cc, InetAddress::IpScope scope, int inetAddressFamily)
|
||||
void Peer::resetWithinScope(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
InetAddress::IpScope scope,
|
||||
int inetAddressFamily)
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
unsigned int pc = 0;
|
||||
for (unsigned int i = 0; i < m_alivePathCount; ++i) {
|
||||
if ((m_paths[i]) && (((int)m_paths[i]->address().as.sa.sa_family == inetAddressFamily) && (m_paths[i]->address().ipScope() == scope))) {
|
||||
const unsigned int bytes = m_sendProbe(ctx, cc, m_paths[i]->localSocket(), m_paths[i]->address(), nullptr, 0);
|
||||
if ((m_paths[i])
|
||||
&& (((int)m_paths[i]->address().as.sa.sa_family == inetAddressFamily)
|
||||
&& (m_paths[i]->address().ipScope() == scope))) {
|
||||
const unsigned int bytes =
|
||||
m_sendProbe(ctx, cc, m_paths[i]->localSocket(), m_paths[i]->address(), nullptr, 0);
|
||||
m_paths[i]->sent(cc, bytes);
|
||||
sent(cc, bytes);
|
||||
} else if (pc != i) {
|
||||
}
|
||||
else if (pc != i) {
|
||||
m_paths[pc++] = m_paths[i];
|
||||
}
|
||||
}
|
||||
|
@ -430,7 +487,8 @@ int Peer::marshal(const Context &ctx, uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) co
|
|||
if (s <= 0)
|
||||
return s;
|
||||
p += s;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data[p++] = 0;
|
||||
}
|
||||
|
||||
|
@ -465,7 +523,9 @@ int Peer::unmarshal(const Context &ctx, const int64_t ticks, const uint8_t *rest
|
|||
bool identityKeyRestored = false;
|
||||
if (Address(data + 1) == ctx.identity.address()) {
|
||||
uint8_t k[ZT_SYMMETRIC_KEY_SIZE];
|
||||
static_assert(ZT_SYMMETRIC_KEY_SIZE == 48, "marshal() and unmarshal() must be revisited if ZT_SYMMETRIC_KEY_SIZE is changed");
|
||||
static_assert(
|
||||
ZT_SYMMETRIC_KEY_SIZE == 48,
|
||||
"marshal() and unmarshal() must be revisited if ZT_SYMMETRIC_KEY_SIZE is changed");
|
||||
ctx.localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH, k);
|
||||
ctx.localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 16, k + 16);
|
||||
ctx.localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 32, k + 32);
|
||||
|
@ -494,7 +554,8 @@ int Peer::unmarshal(const Context &ctx, const int64_t ticks, const uint8_t *rest
|
|||
if (data[p] == 0) {
|
||||
++p;
|
||||
m_locator.zero();
|
||||
} else if (data[p] == 1) {
|
||||
}
|
||||
else if (data[p] == 1) {
|
||||
++p;
|
||||
Locator* const loc = new Locator();
|
||||
s = loc->unmarshal(data + p, len - p);
|
||||
|
@ -502,7 +563,8 @@ int Peer::unmarshal(const Context &ctx, const int64_t ticks, const uint8_t *rest
|
|||
if (s < 0)
|
||||
return s;
|
||||
p += s;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -523,15 +585,16 @@ int Peer::unmarshal(const Context &ctx, const int64_t ticks, const uint8_t *rest
|
|||
return (p > len) ? -1 : p;
|
||||
}
|
||||
|
||||
struct _PathPriorityComparisonOperator
|
||||
{
|
||||
struct _PathPriorityComparisonOperator {
|
||||
ZT_INLINE bool operator()(const SharedPtr<Path>& a, const SharedPtr<Path>& b) const noexcept
|
||||
{
|
||||
if (a) {
|
||||
if (b)
|
||||
return (a->lastIn() > b->lastIn());
|
||||
else return true;
|
||||
} else {
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -565,7 +628,13 @@ void Peer::m_prioritizePaths(const CallContext &cc)
|
|||
m_bestPath.store((m_alivePathCount != 0) ? (uintptr_t)m_paths[0].ptr() : (uintptr_t)0, std::memory_order_release);
|
||||
}
|
||||
|
||||
unsigned int Peer::m_sendProbe(const Context &ctx, const CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, const unsigned int numPorts)
|
||||
unsigned int Peer::m_sendProbe(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& atAddress,
|
||||
const uint16_t* ports,
|
||||
const unsigned int numPorts)
|
||||
{
|
||||
// Assumes m_lock is locked
|
||||
|
||||
|
@ -574,7 +643,9 @@ unsigned int Peer::m_sendProbe(const Context &ctx, const CallContext &cc, int64_
|
|||
// some future attacker compromises it.
|
||||
|
||||
uint8_t p[ZT_PROTO_MIN_PACKET_LENGTH];
|
||||
Utils::storeMachineEndian< uint64_t >(p + ZT_PROTO_PACKET_ID_INDEX, m_identityKey.nextMessage(ctx.identity.address(), m_id.address()));
|
||||
Utils::storeMachineEndian<uint64_t>(
|
||||
p + ZT_PROTO_PACKET_ID_INDEX,
|
||||
m_identityKey.nextMessage(ctx.identity.address(), m_id.address()));
|
||||
m_id.address().copyTo(p + ZT_PROTO_PACKET_DESTINATION_INDEX);
|
||||
ctx.identity.address().copyTo(p + ZT_PROTO_PACKET_SOURCE_INDEX);
|
||||
p[ZT_PROTO_PACKET_FLAGS_INDEX] = 0;
|
||||
|
@ -586,11 +657,28 @@ unsigned int Peer::m_sendProbe(const Context &ctx, const CallContext &cc, int64_
|
|||
InetAddress tmp(atAddress);
|
||||
for (unsigned int i = 0; i < numPorts; ++i) {
|
||||
tmp.setPort(ports[i]);
|
||||
ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&tmp), p, ZT_PROTO_MIN_PACKET_LENGTH, 0);
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
-1,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&tmp),
|
||||
p,
|
||||
ZT_PROTO_MIN_PACKET_LENGTH,
|
||||
0);
|
||||
}
|
||||
return ZT_PROTO_MIN_PACKET_LENGTH * numPorts;
|
||||
} else {
|
||||
ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, -1, reinterpret_cast<const ZT_InetAddress *>(&atAddress), p, ZT_PROTO_MIN_PACKET_LENGTH, 0);
|
||||
}
|
||||
else {
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
-1,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&atAddress),
|
||||
p,
|
||||
ZT_PROTO_MIN_PACKET_LENGTH,
|
||||
0);
|
||||
return ZT_PROTO_MIN_PACKET_LENGTH;
|
||||
}
|
||||
}
|
||||
|
@ -609,7 +697,12 @@ void Peer::m_deriveSecondaryIdentityKeys() noexcept
|
|||
KBKDFHMACSHA384(m_identityKey.key(), ZT_KBKDF_LABEL_PACKET_HMAC, 0, 0, m_helloMacKey);
|
||||
}
|
||||
|
||||
unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const bool forceNewKey)
|
||||
unsigned int Peer::m_hello(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& atAddress,
|
||||
const bool forceNewKey)
|
||||
{
|
||||
// assumes m_lock is at least locked for reading
|
||||
|
||||
|
@ -635,15 +728,18 @@ unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t lo
|
|||
if (ct <= earliestEphemeralPrivate) {
|
||||
earliestEphemeralPrivate = ct;
|
||||
earliest = m_ephemeralKeysSent + k;
|
||||
} else if (ct >= latestEphemeralPrivate) { // creationTime will be -1 if not initialized
|
||||
}
|
||||
else if (ct >= latestEphemeralPrivate) { // creationTime will be -1 if not initialized
|
||||
latestEphemeralPrivate = ct;
|
||||
latest = m_ephemeralKeysSent + k;
|
||||
}
|
||||
}
|
||||
|
||||
if ((latest != nullptr) && (!forceNewKey) && ((cc.ticks - latest->creationTime) < (ZT_SYMMETRIC_KEY_TTL / 2))) {
|
||||
if ((latest != nullptr) && (! forceNewKey)
|
||||
&& ((cc.ticks - latest->creationTime) < (ZT_SYMMETRIC_KEY_TTL / 2))) {
|
||||
ephemeral = latest;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
earliest->creationTime = cc.ticks;
|
||||
earliest->pub.type = ZT_PROTO_EPHEMERAL_KEY_TYPE_C25519_P384;
|
||||
C25519::generateC25519(earliest->pub.c25519Public, earliest->c25519Private);
|
||||
|
@ -708,12 +804,26 @@ unsigned int Peer::m_hello(const Context &ctx, const CallContext &cc, int64_t lo
|
|||
Protocol::salsa2012DeriveKey(m_identityKey.key(), perPacketKey, outp, ii);
|
||||
Salsa20(perPacketKey, &packetId).crypt12(Utils::ZERO256, polyKey, sizeof(polyKey));
|
||||
Poly1305 p1305(polyKey);
|
||||
p1305.update(outp.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, ii - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START);
|
||||
p1305.update(
|
||||
outp.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,
|
||||
ii - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START);
|
||||
uint64_t polyMac[2];
|
||||
p1305.finish(polyMac);
|
||||
Utils::storeMachineEndian<uint64_t>(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]);
|
||||
|
||||
return (likely(ctx.cb.wirePacketSendFunction(reinterpret_cast<ZT_Node *>(ctx.node), ctx.uPtr, cc.tPtr, localSocket, reinterpret_cast<const ZT_InetAddress *>(&atAddress), outp.unsafeData, ii, 0) == 0)) ? (unsigned int)ii : 0U;
|
||||
return (likely(
|
||||
ctx.cb.wirePacketSendFunction(
|
||||
reinterpret_cast<ZT_Node*>(ctx.node),
|
||||
ctx.uPtr,
|
||||
cc.tPtr,
|
||||
localSocket,
|
||||
reinterpret_cast<const ZT_InetAddress*>(&atAddress),
|
||||
outp.unsafeData,
|
||||
ii,
|
||||
0)
|
||||
== 0))
|
||||
? (unsigned int)ii
|
||||
: 0U;
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
149
core/Peer.hpp
149
core/Peer.hpp
|
@ -14,31 +14,26 @@
|
|||
#ifndef ZT_PEER_HPP
|
||||
#define ZT_PEER_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "SymmetricKey.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_PEER_MARSHAL_SIZE_MAX ( \
|
||||
1 + \
|
||||
ZT_ADDRESS_LENGTH + \
|
||||
ZT_SYMMETRIC_KEY_SIZE + \
|
||||
ZT_IDENTITY_MARSHAL_SIZE_MAX + \
|
||||
1 + ZT_LOCATOR_MARSHAL_SIZE_MAX + \
|
||||
(2 * 4) + \
|
||||
2 )
|
||||
#define ZT_PEER_MARSHAL_SIZE_MAX \
|
||||
(1 + ZT_ADDRESS_LENGTH + ZT_SYMMETRIC_KEY_SIZE + ZT_IDENTITY_MARSHAL_SIZE_MAX + 1 + ZT_LOCATOR_MARSHAL_SIZE_MAX \
|
||||
+ (2 * 4) + 2)
|
||||
|
||||
#define ZT_PEER_DEDUP_BUFFER_SIZE 1024
|
||||
#define ZT_PEER_DEDUP_BUFFER_MASK 1023U
|
||||
|
@ -52,8 +47,7 @@ class Topology;
|
|||
/**
|
||||
* Peer on P2P Network (virtual layer 1)
|
||||
*/
|
||||
class Peer
|
||||
{
|
||||
class Peer {
|
||||
friend class SharedPtr<Peer>;
|
||||
friend class Topology;
|
||||
|
||||
|
@ -80,13 +74,17 @@ public:
|
|||
* @return This peer's ZT address (short for identity().address())
|
||||
*/
|
||||
ZT_INLINE Address address() const noexcept
|
||||
{ return m_id.address(); }
|
||||
{
|
||||
return m_id.address();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This peer's identity
|
||||
*/
|
||||
ZT_INLINE const Identity& identity() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current locator or NULL if no locator is known
|
||||
|
@ -156,7 +154,9 @@ public:
|
|||
* @param bytes Number of bytes relayed
|
||||
*/
|
||||
ZT_INLINE void relayed(const CallContext& cc, const unsigned int bytes) noexcept
|
||||
{ m_relayedMeter.log(cc.ticks, bytes); }
|
||||
{
|
||||
m_relayedMeter.log(cc.ticks, bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current best direct path or NULL if none
|
||||
|
@ -164,7 +164,9 @@ public:
|
|||
* @return Current best path or NULL if there is no direct path
|
||||
*/
|
||||
ZT_INLINE SharedPtr<Path> path(const CallContext& cc) noexcept
|
||||
{ return SharedPtr< Path >(reinterpret_cast<Path *>(m_bestPath.load(std::memory_order_acquire))); }
|
||||
{
|
||||
return SharedPtr<Path>(reinterpret_cast<Path*>(m_bestPath.load(std::memory_order_acquire)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to this peer over a specific path only
|
||||
|
@ -173,7 +175,9 @@ public:
|
|||
* @param len Length in bytes
|
||||
* @param via Path over which to send data (may or may not be an already-learned path for this peer)
|
||||
*/
|
||||
ZT_INLINE void send(const Context &ctx, const CallContext &cc, const void *data, unsigned int len, const SharedPtr< Path > &via) noexcept
|
||||
ZT_INLINE void
|
||||
send(const Context& ctx, const CallContext& cc, const void* data, unsigned int len, const SharedPtr<Path>& via)
|
||||
noexcept
|
||||
{
|
||||
via->send(ctx, cc, data, len);
|
||||
sent(cc, len);
|
||||
|
@ -223,7 +227,9 @@ public:
|
|||
* @return Time of last receive of anything, whether direct or relayed
|
||||
*/
|
||||
ZT_INLINE int64_t lastReceive() const noexcept
|
||||
{ return m_lastReceive.load(std::memory_order_relaxed); }
|
||||
{
|
||||
return m_lastReceive.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Average latency of all direct paths or -1 if no direct paths or unknown
|
||||
|
@ -257,31 +263,41 @@ public:
|
|||
* @return The permanent shared key for this peer computed by simple identity agreement
|
||||
*/
|
||||
ZT_INLINE SymmetricKey& identityKey() noexcept
|
||||
{ return m_identityKey; }
|
||||
{
|
||||
return m_identityKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AES instance for HELLO dictionary / encrypted section encryption/decryption
|
||||
*/
|
||||
ZT_INLINE const AES& identityHelloDictionaryEncryptionCipher() const noexcept
|
||||
{ return m_helloCipher; }
|
||||
{
|
||||
return m_helloCipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Key for HMAC on HELLOs
|
||||
*/
|
||||
ZT_INLINE const uint8_t* identityHelloHmacKey() const noexcept
|
||||
{ return m_helloMacKey; }
|
||||
{
|
||||
return m_helloMacKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw identity key bytes
|
||||
*/
|
||||
ZT_INLINE const uint8_t* rawIdentityKey() const noexcept
|
||||
{ return m_identityKey.key(); }
|
||||
{
|
||||
return m_identityKey.key();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current best key: either the latest ephemeral or the identity key
|
||||
*/
|
||||
ZT_INLINE SymmetricKey& key() noexcept
|
||||
{ return *reinterpret_cast<SymmetricKey *>(m_key.load(std::memory_order_relaxed)); }
|
||||
{
|
||||
return *reinterpret_cast<SymmetricKey*>(m_key.load(std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get keys other than a key we have already tried.
|
||||
|
@ -294,7 +310,9 @@ public:
|
|||
* @param notYetTried All keys known (long lived or session) other than alreadyTried
|
||||
* @return Number of pointers written to notYetTried[]
|
||||
*/
|
||||
ZT_INLINE int getOtherKeys(const SymmetricKey *const alreadyTried, SymmetricKey *notYetTried[ZT_PEER_EPHEMERAL_KEY_COUNT_MAX]) noexcept
|
||||
ZT_INLINE int getOtherKeys(
|
||||
const SymmetricKey* const alreadyTried,
|
||||
SymmetricKey* notYetTried[ZT_PEER_EPHEMERAL_KEY_COUNT_MAX]) noexcept
|
||||
{
|
||||
RWMutex::RLock l(m_lock);
|
||||
int cnt = 0;
|
||||
|
@ -330,7 +348,8 @@ public:
|
|||
* @param vmin Minor version
|
||||
* @param vrev Revision
|
||||
*/
|
||||
ZT_INLINE void setRemoteVersion(unsigned int vproto, unsigned int vmaj, unsigned int vmin, unsigned int vrev) noexcept
|
||||
ZT_INLINE void
|
||||
setRemoteVersion(unsigned int vproto, unsigned int vmaj, unsigned int vmin, unsigned int vrev) noexcept
|
||||
{
|
||||
RWMutex::Lock l(m_lock);
|
||||
m_vProto = (uint16_t)vproto;
|
||||
|
@ -383,7 +402,9 @@ public:
|
|||
void save(const Context& ctx, const CallContext& cc) const;
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_PEER_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_PEER_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(const Context& ctx, uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept;
|
||||
int unmarshal(const Context& ctx, int64_t ticks, const uint8_t* restrict data, int len) noexcept;
|
||||
|
@ -434,25 +455,33 @@ public:
|
|||
* @return True if this is a duplicate
|
||||
*/
|
||||
ZT_INLINE bool deduplicateIncomingPacket(const uint64_t packetId) noexcept
|
||||
{ return m_dedup[Utils::hash32((uint32_t)packetId) & ZT_PEER_DEDUP_BUFFER_MASK].exchange(packetId, std::memory_order_relaxed) == packetId; }
|
||||
{
|
||||
return m_dedup[Utils::hash32((uint32_t)packetId) & ZT_PEER_DEDUP_BUFFER_MASK].exchange(
|
||||
packetId,
|
||||
std::memory_order_relaxed)
|
||||
== packetId;
|
||||
}
|
||||
|
||||
private:
|
||||
struct p_EphemeralPublic
|
||||
{
|
||||
struct p_EphemeralPublic {
|
||||
uint8_t type;
|
||||
uint8_t c25519Public[ZT_C25519_ECDH_PUBLIC_KEY_SIZE];
|
||||
uint8_t p384Public[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
};
|
||||
|
||||
static_assert(sizeof(p_EphemeralPublic) == (1 + ZT_C25519_ECDH_PUBLIC_KEY_SIZE + ZT_ECC384_PUBLIC_KEY_SIZE), "p_EphemeralPublic has extra padding");
|
||||
static_assert(
|
||||
sizeof(p_EphemeralPublic) == (1 + ZT_C25519_ECDH_PUBLIC_KEY_SIZE + ZT_ECC384_PUBLIC_KEY_SIZE),
|
||||
"p_EphemeralPublic has extra padding");
|
||||
|
||||
struct p_EphemeralPrivate
|
||||
{
|
||||
struct p_EphemeralPrivate {
|
||||
ZT_INLINE p_EphemeralPrivate() noexcept : creationTime(-1)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~p_EphemeralPrivate()
|
||||
{ Utils::burn(this, sizeof(p_EphemeralPublic)); }
|
||||
{
|
||||
Utils::burn(this, sizeof(p_EphemeralPublic));
|
||||
}
|
||||
|
||||
int64_t creationTime;
|
||||
uint64_t sha384OfPublic[6];
|
||||
|
@ -461,10 +490,10 @@ private:
|
|||
uint8_t p384Private[ZT_ECC384_PRIVATE_KEY_SIZE];
|
||||
};
|
||||
|
||||
struct p_EphemeralSession
|
||||
{
|
||||
struct p_EphemeralSession {
|
||||
ZT_INLINE p_EphemeralSession() noexcept : established(false)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t sha384OfPeerPublic[6];
|
||||
SymmetricKey key;
|
||||
|
@ -472,9 +501,20 @@ private:
|
|||
};
|
||||
|
||||
void m_prioritizePaths(const CallContext& cc);
|
||||
unsigned int m_sendProbe(const Context &ctx, const CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, unsigned int numPorts);
|
||||
unsigned int m_sendProbe(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& atAddress,
|
||||
const uint16_t* ports,
|
||||
unsigned int numPorts);
|
||||
void m_deriveSecondaryIdentityKeys() noexcept;
|
||||
unsigned int m_hello(const Context &ctx, const CallContext &cc, int64_t localSocket, const InetAddress &atAddress, bool forceNewKey);
|
||||
unsigned int m_hello(
|
||||
const Context& ctx,
|
||||
const CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& atAddress,
|
||||
bool forceNewKey);
|
||||
|
||||
// Guards all fields except those otherwise indicated (and atomics of course).
|
||||
RWMutex m_lock;
|
||||
|
@ -542,17 +582,14 @@ private:
|
|||
// For SharedPtr<>
|
||||
std::atomic<int> __refCount;
|
||||
|
||||
struct p_TryQueueItem
|
||||
struct p_TryQueueItem {
|
||||
ZT_INLINE p_TryQueueItem() : target(), iteration(0)
|
||||
{
|
||||
ZT_INLINE p_TryQueueItem() :
|
||||
target(),
|
||||
iteration(0)
|
||||
{}
|
||||
}
|
||||
|
||||
ZT_INLINE p_TryQueueItem(const Endpoint &t, int iter) :
|
||||
target(t),
|
||||
iteration(iter)
|
||||
{}
|
||||
ZT_INLINE p_TryQueueItem(const Endpoint& t, int iter) : target(t), iteration(iter)
|
||||
{
|
||||
}
|
||||
|
||||
Endpoint target;
|
||||
int iteration;
|
||||
|
|
|
@ -6,8 +6,9 @@ Public domain.
|
|||
|
||||
// Small modifications have been made for ZeroTier, but this code remains in the public domain.
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Poly1305.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
@ -106,15 +107,34 @@ void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size
|
|||
h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit;
|
||||
|
||||
/* h *= r */
|
||||
MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
|
||||
MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
|
||||
MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
|
||||
MUL(d0, h0, r0);
|
||||
MUL(d, h1, s2);
|
||||
ADD(d0, d);
|
||||
MUL(d, h2, s1);
|
||||
ADD(d0, d);
|
||||
MUL(d1, h0, r1);
|
||||
MUL(d, h1, r0);
|
||||
ADD(d1, d);
|
||||
MUL(d, h2, s2);
|
||||
ADD(d1, d);
|
||||
MUL(d2, h0, r2);
|
||||
MUL(d, h1, r1);
|
||||
ADD(d2, d);
|
||||
MUL(d, h2, r0);
|
||||
ADD(d2, d);
|
||||
|
||||
/* (partial) h %= p */
|
||||
unsigned long long c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
|
||||
ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
|
||||
ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff;
|
||||
unsigned long long c = SHR(d0, 44);
|
||||
h0 = LO(d0) & 0xfffffffffff;
|
||||
ADDLO(d1, c);
|
||||
c = SHR(d1, 44);
|
||||
h1 = LO(d1) & 0xfffffffffff;
|
||||
ADDLO(d2, c);
|
||||
c = SHR(d2, 42);
|
||||
h2 = LO(d2) & 0x3ffffffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 44);
|
||||
h0 = h0 & 0xfffffffffff;
|
||||
h1 += c;
|
||||
|
||||
m += poly1305_block_size;
|
||||
|
@ -148,17 +168,32 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx,unsigned char mac[16])
|
|||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
|
||||
c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
c = (h1 >> 44);
|
||||
h1 &= 0xfffffffffff;
|
||||
h2 += c;
|
||||
c = (h2 >> 42);
|
||||
h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 44);
|
||||
h0 &= 0xfffffffffff;
|
||||
h1 += c;
|
||||
c = (h1 >> 44);
|
||||
h1 &= 0xfffffffffff;
|
||||
h2 += c;
|
||||
c = (h2 >> 42);
|
||||
h2 &= 0x3ffffffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 44);
|
||||
h0 &= 0xfffffffffff;
|
||||
h1 += c;
|
||||
|
||||
/* compute h + -p */
|
||||
g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
|
||||
g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
|
||||
g0 = h0 + 5;
|
||||
c = (g0 >> 44);
|
||||
g0 &= 0xfffffffffff;
|
||||
g1 = h1 + c;
|
||||
c = (g1 >> 44);
|
||||
g1 &= 0xfffffffffff;
|
||||
g2 = h2 + c - ((unsigned long long)1 << 42);
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
|
@ -175,9 +210,14 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx,unsigned char mac[16])
|
|||
t0 = st->pad[0];
|
||||
t1 = st->pad[1];
|
||||
|
||||
h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff;
|
||||
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff;
|
||||
h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff;
|
||||
h0 += ((t0)&0xfffffffffff);
|
||||
c = (h0 >> 44);
|
||||
h0 &= 0xfffffffffff;
|
||||
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
|
||||
c = (h1 >> 44);
|
||||
h1 &= 0xfffffffffff;
|
||||
h2 += (((t1 >> 24)) & 0x3ffffffffff) + c;
|
||||
h2 &= 0x3ffffffffff;
|
||||
|
||||
/* mac = h % (2^128) */
|
||||
h0 = ((h0) | (h1 << 44));
|
||||
|
@ -271,19 +311,40 @@ void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size
|
|||
h4 += (U8TO32(m + 12) >> 8) | hibit;
|
||||
|
||||
/* h *= r */
|
||||
unsigned long long d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);
|
||||
unsigned long long d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);
|
||||
unsigned long long d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);
|
||||
unsigned long long d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);
|
||||
unsigned long long d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
|
||||
unsigned long long d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4)
|
||||
+ ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2)
|
||||
+ ((unsigned long long)h4 * s1);
|
||||
unsigned long long d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0)
|
||||
+ ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3)
|
||||
+ ((unsigned long long)h4 * s2);
|
||||
unsigned long long d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1)
|
||||
+ ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4)
|
||||
+ ((unsigned long long)h4 * s3);
|
||||
unsigned long long d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2)
|
||||
+ ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0)
|
||||
+ ((unsigned long long)h4 * s4);
|
||||
unsigned long long d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3)
|
||||
+ ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1)
|
||||
+ ((unsigned long long)h4 * r0);
|
||||
|
||||
/* (partial) h %= p */
|
||||
unsigned long c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff;
|
||||
d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff;
|
||||
d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff;
|
||||
d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff;
|
||||
d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff;
|
||||
h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
|
||||
unsigned long c = (unsigned long)(d0 >> 26);
|
||||
h0 = (unsigned long)d0 & 0x3ffffff;
|
||||
d1 += c;
|
||||
c = (unsigned long)(d1 >> 26);
|
||||
h1 = (unsigned long)d1 & 0x3ffffff;
|
||||
d2 += c;
|
||||
c = (unsigned long)(d2 >> 26);
|
||||
h2 = (unsigned long)d2 & 0x3ffffff;
|
||||
d3 += c;
|
||||
c = (unsigned long)(d3 >> 26);
|
||||
h3 = (unsigned long)d3 & 0x3ffffff;
|
||||
d4 += c;
|
||||
c = (unsigned long)(d4 >> 26);
|
||||
h4 = (unsigned long)d4 & 0x3ffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 26);
|
||||
h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
m += poly1305_block_size;
|
||||
|
@ -322,18 +383,35 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
|
|||
h3 = st->h[3];
|
||||
h4 = st->h[4];
|
||||
|
||||
c = h1 >> 26; h1 = h1 & 0x3ffffff;
|
||||
h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
|
||||
h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
|
||||
h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
|
||||
h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
|
||||
c = h1 >> 26;
|
||||
h1 = h1 & 0x3ffffff;
|
||||
h2 += c;
|
||||
c = h2 >> 26;
|
||||
h2 = h2 & 0x3ffffff;
|
||||
h3 += c;
|
||||
c = h3 >> 26;
|
||||
h3 = h3 & 0x3ffffff;
|
||||
h4 += c;
|
||||
c = h4 >> 26;
|
||||
h4 = h4 & 0x3ffffff;
|
||||
h0 += c * 5;
|
||||
c = h0 >> 26;
|
||||
h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
/* compute h + -p */
|
||||
g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
|
||||
g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
|
||||
g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
|
||||
g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
|
||||
g0 = h0 + 5;
|
||||
c = g0 >> 26;
|
||||
g0 &= 0x3ffffff;
|
||||
g1 = h1 + c;
|
||||
c = g1 >> 26;
|
||||
g1 &= 0x3ffffff;
|
||||
g2 = h2 + c;
|
||||
c = g2 >> 26;
|
||||
g2 &= 0x3ffffff;
|
||||
g3 = h3 + c;
|
||||
c = g3 >> 26;
|
||||
g3 &= 0x3ffffff;
|
||||
g4 = h4 + c - (1 << 26);
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
|
@ -357,10 +435,14 @@ ZT_INLINE void poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
|
|||
h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
|
||||
|
||||
/* mac = (h + pad) % (2^128) */
|
||||
f = (unsigned long long)h0 + st->pad[0] ; h0 = (unsigned long)f;
|
||||
f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f;
|
||||
f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f;
|
||||
f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f;
|
||||
f = (unsigned long long)h0 + st->pad[0];
|
||||
h0 = (unsigned long)f;
|
||||
f = (unsigned long long)h1 + st->pad[1] + (f >> 32);
|
||||
h1 = (unsigned long)f;
|
||||
f = (unsigned long long)h2 + st->pad[2] + (f >> 32);
|
||||
h2 = (unsigned long)f;
|
||||
f = (unsigned long long)h3 + st->pad[3] + (f >> 32);
|
||||
h3 = (unsigned long)f;
|
||||
|
||||
U32TO8(mac + 0, h0);
|
||||
U32TO8(mac + 4, h1);
|
||||
|
@ -433,7 +515,10 @@ void Poly1305::init(const void *key) noexcept
|
|||
|
||||
void Poly1305::update(const void* data, unsigned int len) noexcept
|
||||
{
|
||||
poly1305_update(reinterpret_cast<poly1305_context *>(&ctx),reinterpret_cast<const unsigned char *>(data),(size_t)len);
|
||||
poly1305_update(
|
||||
reinterpret_cast<poly1305_context*>(&ctx),
|
||||
reinterpret_cast<const unsigned char*>(data),
|
||||
(size_t)len);
|
||||
}
|
||||
|
||||
void Poly1305::finish(void* auth) noexcept
|
||||
|
|
|
@ -22,20 +22,23 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Poly1305 one-time MAC calculator
|
||||
*/
|
||||
class Poly1305
|
||||
{
|
||||
class Poly1305 {
|
||||
public:
|
||||
ZT_INLINE Poly1305()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE Poly1305(const void* key)
|
||||
{ this->init(key); }
|
||||
{
|
||||
this->init(key);
|
||||
}
|
||||
|
||||
void init(const void* key) noexcept;
|
||||
void update(const void* data, unsigned int len) noexcept;
|
||||
void finish(void* auth) noexcept;
|
||||
|
||||
static ZT_INLINE void compute(void *const auth, const void *const data, const unsigned int len, const void *const key) noexcept
|
||||
static ZT_INLINE void
|
||||
compute(void* const auth, const void* const data, const unsigned int len, const void* const key) noexcept
|
||||
{
|
||||
Poly1305 p(key);
|
||||
p.update(data, len);
|
||||
|
@ -43,8 +46,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
size_t aligner;
|
||||
unsigned char opaque[136];
|
||||
} ctx;
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
#ifndef ZT_PROTOCOL_HPP
|
||||
#define ZT_PROTOCOL_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "Poly1305.hpp"
|
||||
#include "LZ4.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "LZ4.hpp"
|
||||
#include "Poly1305.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "SymmetricKey.hpp"
|
||||
|
||||
/*
|
||||
|
@ -253,7 +253,9 @@
|
|||
#define ZT_PROTO_HELLO_NODE_META_EPHEMERAL_ACK "E"
|
||||
|
||||
static_assert(ZT_PROTO_MAX_PACKET_LENGTH < ZT_BUF_MEM_SIZE, "maximum packet length won't fit in Buf");
|
||||
static_assert(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START == (ZT_PROTO_MIN_PACKET_LENGTH - 1), "encrypted packet section must start right before protocol verb at one less than minimum packet size");
|
||||
static_assert(
|
||||
ZT_PROTO_PACKET_ENCRYPTED_SECTION_START == (ZT_PROTO_MIN_PACKET_LENGTH - 1),
|
||||
"encrypted packet section must start right before protocol verb at one less than minimum packet size");
|
||||
|
||||
namespace ZeroTier {
|
||||
namespace Protocol {
|
||||
|
@ -261,8 +263,7 @@ namespace Protocol {
|
|||
/**
|
||||
* Packet verb (message type)
|
||||
*/
|
||||
enum Verb
|
||||
{
|
||||
enum Verb {
|
||||
/**
|
||||
* No operation
|
||||
*
|
||||
|
@ -736,8 +737,7 @@ static ZT_INLINE const char *verbName(const Verb v) noexcept
|
|||
/**
|
||||
* Error codes used in ERROR packets.
|
||||
*/
|
||||
enum ErrorCode
|
||||
{
|
||||
enum ErrorCode {
|
||||
/* Invalid request */
|
||||
ERROR_INVALID_REQUEST = 0x01,
|
||||
|
||||
|
@ -766,8 +766,7 @@ enum ErrorCode
|
|||
* This allows the node to know whether this is a normal frame or one generated
|
||||
* by a special tee or redirect type flow rule.
|
||||
*/
|
||||
enum ExtFrameSubtype
|
||||
{
|
||||
enum ExtFrameSubtype {
|
||||
EXT_FRAME_SUBTYPE_NORMAL = 0x0,
|
||||
EXT_FRAME_SUBTYPE_TEE_OUTBOUND = 0x1,
|
||||
EXT_FRAME_SUBTYPE_REDIRECT_OUTBOUND = 0x2,
|
||||
|
@ -780,8 +779,7 @@ enum ExtFrameSubtype
|
|||
/**
|
||||
* EXT_FRAME flags
|
||||
*/
|
||||
enum ExtFrameFlag
|
||||
{
|
||||
enum ExtFrameFlag {
|
||||
/**
|
||||
* A certifiate of membership was included (no longer used but still accepted)
|
||||
*/
|
||||
|
@ -798,8 +796,7 @@ enum ExtFrameFlag
|
|||
/**
|
||||
* NETWORK_CONFIG (or OK(NETWORK_CONFIG_REQUEST)) flags
|
||||
*/
|
||||
enum NetworkConfigFlag
|
||||
{
|
||||
enum NetworkConfigFlag {
|
||||
/**
|
||||
* Indicates that this network config chunk should be fast propagated via rumor mill flooding.
|
||||
*/
|
||||
|
@ -816,7 +813,9 @@ enum NetworkConfigFlag
|
|||
* @param in Input key (32 bytes)
|
||||
* @param out Output buffer (32 bytes)
|
||||
*/
|
||||
static ZT_INLINE void salsa2012DeriveKey(const uint8_t *const in, uint8_t *const out, const Buf &packet, const unsigned int packetSize) noexcept
|
||||
static ZT_INLINE void
|
||||
salsa2012DeriveKey(const uint8_t* const in, uint8_t* const out, const Buf& packet, const unsigned int packetSize)
|
||||
noexcept
|
||||
{
|
||||
// IV and source/destination addresses. Using the addresses divides the
|
||||
// key space into two halves-- A->B and B->A (since order will change).
|
||||
|
@ -824,9 +823,12 @@ static ZT_INLINE void salsa2012DeriveKey(const uint8_t *const in, uint8_t *const
|
|||
for (int i = 0; i < 18; ++i)
|
||||
out[i] = in[i] ^ packet.unsafeData[i];
|
||||
#else
|
||||
*reinterpret_cast<uint64_t *>(out) = *reinterpret_cast<const uint64_t *>(in) ^ *reinterpret_cast<const uint64_t *>(packet.unsafeData);
|
||||
*reinterpret_cast<uint64_t *>(out + 8) = *reinterpret_cast<const uint64_t *>(in + 8) ^ *reinterpret_cast<const uint64_t *>(packet.unsafeData + 8);
|
||||
*reinterpret_cast<uint16_t *>(out + 16) = *reinterpret_cast<const uint16_t *>(in + 16) ^ *reinterpret_cast<const uint16_t *>(packet.unsafeData + 16);
|
||||
*reinterpret_cast<uint64_t*>(out) =
|
||||
*reinterpret_cast<const uint64_t*>(in) ^ *reinterpret_cast<const uint64_t*>(packet.unsafeData);
|
||||
*reinterpret_cast<uint64_t*>(out + 8) =
|
||||
*reinterpret_cast<const uint64_t*>(in + 8) ^ *reinterpret_cast<const uint64_t*>(packet.unsafeData + 8);
|
||||
*reinterpret_cast<uint16_t*>(out + 16) =
|
||||
*reinterpret_cast<const uint16_t*>(in + 16) ^ *reinterpret_cast<const uint16_t*>(packet.unsafeData + 16);
|
||||
#endif
|
||||
|
||||
// Flags, but with hop count masked off. Hop count is altered by forwarding
|
||||
|
@ -859,7 +861,9 @@ static ZT_INLINE void salsa2012DeriveKey(const uint8_t *const in, uint8_t *const
|
|||
* @param verb Protocol verb
|
||||
* @return Index of packet start
|
||||
*/
|
||||
static ZT_INLINE int newPacket(uint8_t pkt[28], const uint64_t packetId, const Address destination, const Address source, const Verb verb) noexcept
|
||||
static ZT_INLINE int
|
||||
newPacket(uint8_t pkt[28], const uint64_t packetId, const Address destination, const Address source, const Verb verb)
|
||||
noexcept
|
||||
{
|
||||
Utils::storeMachineEndian<uint64_t>(pkt + ZT_PROTO_PACKET_ID_INDEX, packetId);
|
||||
destination.copyTo(pkt + ZT_PROTO_PACKET_DESTINATION_INDEX);
|
||||
|
@ -870,8 +874,11 @@ static ZT_INLINE int newPacket(uint8_t pkt[28], const uint64_t packetId, const A
|
|||
return ZT_PROTO_PACKET_VERB_INDEX + 1;
|
||||
}
|
||||
|
||||
static ZT_INLINE int newPacket(Buf &pkt, const uint64_t packetId, const Address destination, const Address source, const Verb verb) noexcept
|
||||
{ return newPacket(pkt.unsafeData, packetId, destination, source, verb); }
|
||||
static ZT_INLINE int
|
||||
newPacket(Buf& pkt, const uint64_t packetId, const Address destination, const Address source, const Verb verb) noexcept
|
||||
{
|
||||
return newPacket(pkt.unsafeData, packetId, destination, source, verb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt and compute packet MAC
|
||||
|
@ -882,7 +889,8 @@ static ZT_INLINE int newPacket(Buf &pkt, const uint64_t packetId, const Address
|
|||
* @param cipherSuite Cipher suite to use for AEAD encryption or just MAC
|
||||
* @return Packet ID of packet (which may change!)
|
||||
*/
|
||||
static ZT_INLINE uint64_t armor(uint8_t *const pkt, const int packetSize, const SymmetricKey &key, const uint8_t cipherSuite) noexcept
|
||||
static ZT_INLINE uint64_t
|
||||
armor(uint8_t* const pkt, const int packetSize, const SymmetricKey& key, const uint8_t cipherSuite) noexcept
|
||||
{
|
||||
// TODO
|
||||
#if 0
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
#ifndef ZT_REVOCATION_HPP
|
||||
#define ZT_REVOCATION_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
/**
|
||||
* Flag: fast propagation via rumor mill algorithm
|
||||
|
@ -35,16 +35,19 @@ class Context;
|
|||
/**
|
||||
* Revocation certificate to instantaneously revoke a COM, capability, or tag
|
||||
*/
|
||||
class RevocationCredential : public Credential
|
||||
{
|
||||
class RevocationCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_REVOCATION; }
|
||||
{
|
||||
return ZT_CREDENTIAL_TYPE_REVOCATION;
|
||||
}
|
||||
|
||||
ZT_INLINE RevocationCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i ID (arbitrary for revocations, currently random)
|
||||
|
@ -55,47 +58,76 @@ public:
|
|||
* @param tgt Target node whose credential(s) are being revoked
|
||||
* @param ct Credential type being revoked
|
||||
*/
|
||||
ZT_INLINE RevocationCredential(const uint32_t i, const uint64_t nwid, const uint32_t cid, const uint64_t thr, const uint64_t fl, const Address &tgt, const ZT_CredentialType ct) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
m_id(i),
|
||||
m_credentialId(cid),
|
||||
m_networkId(nwid),
|
||||
m_threshold(thr),
|
||||
m_flags(fl),
|
||||
m_target(tgt),
|
||||
m_signedBy(),
|
||||
m_type(ct),
|
||||
m_signatureLength(0)
|
||||
{}
|
||||
ZT_INLINE RevocationCredential(
|
||||
const uint32_t i,
|
||||
const uint64_t nwid,
|
||||
const uint32_t cid,
|
||||
const uint64_t thr,
|
||||
const uint64_t fl,
|
||||
const Address& tgt,
|
||||
const ZT_CredentialType ct) noexcept
|
||||
: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
|
||||
m_id(i)
|
||||
, m_credentialId(cid)
|
||||
, m_networkId(nwid)
|
||||
, m_threshold(thr)
|
||||
, m_flags(fl)
|
||||
, m_target(tgt)
|
||||
, m_signedBy()
|
||||
, m_type(ct)
|
||||
, m_signatureLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t credentialId() const noexcept
|
||||
{ return m_credentialId; }
|
||||
{
|
||||
return m_credentialId;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_networkId; }
|
||||
{
|
||||
return m_networkId;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t threshold() const noexcept
|
||||
{ return m_threshold; }
|
||||
{
|
||||
return m_threshold;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& target() const noexcept
|
||||
{ return m_target; }
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& signer() const noexcept
|
||||
{ return m_signedBy; }
|
||||
{
|
||||
return m_signedBy;
|
||||
}
|
||||
|
||||
ZT_INLINE ZT_CredentialType typeBeingRevoked() const noexcept
|
||||
{ return m_type; }
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t* signature() const noexcept
|
||||
{ return m_signature; }
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{ return m_signatureLength; }
|
||||
{
|
||||
return m_signatureLength;
|
||||
}
|
||||
|
||||
ZT_INLINE bool fastPropagate() const noexcept
|
||||
{ return ((m_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); }
|
||||
{
|
||||
return ((m_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signer Signing identity, must have private key
|
||||
|
@ -110,10 +142,14 @@ public:
|
|||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const noexcept
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_REVOCATION_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_REVOCATION_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
|
||||
int unmarshal(const uint8_t* restrict data, int len) noexcept;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// This code is public domain, taken from a PD crypto source file on GitHub.
|
||||
|
||||
#include "SHA512.hpp"
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -16,26 +17,22 @@ struct sha512_state {
|
|||
};
|
||||
|
||||
static const uint64_t K[80] = {
|
||||
0x428a2f98d728ae22ULL,0x7137449123ef65cdULL,0xb5c0fbcfec4d3b2fULL,0xe9b5dba58189dbbcULL,
|
||||
0x3956c25bf348b538ULL,0x59f111f1b605d019ULL,0x923f82a4af194f9bULL,0xab1c5ed5da6d8118ULL,
|
||||
0xd807aa98a3030242ULL,0x12835b0145706fbeULL,0x243185be4ee4b28cULL,0x550c7dc3d5ffb4e2ULL,
|
||||
0x72be5d74f27b896fULL,0x80deb1fe3b1696b1ULL,0x9bdc06a725c71235ULL,0xc19bf174cf692694ULL,
|
||||
0xe49b69c19ef14ad2ULL,0xefbe4786384f25e3ULL,0x0fc19dc68b8cd5b5ULL,0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL,0x4a7484aa6ea6e483ULL,0x5cb0a9dcbd41fbd4ULL,0x76f988da831153b5ULL,
|
||||
0x983e5152ee66dfabULL,0xa831c66d2db43210ULL,0xb00327c898fb213fULL,0xbf597fc7beef0ee4ULL,
|
||||
0xc6e00bf33da88fc2ULL,0xd5a79147930aa725ULL,0x06ca6351e003826fULL,0x142929670a0e6e70ULL,
|
||||
0x27b70a8546d22ffcULL,0x2e1b21385c26c926ULL,0x4d2c6dfc5ac42aedULL,0x53380d139d95b3dfULL,
|
||||
0x650a73548baf63deULL,0x766a0abb3c77b2a8ULL,0x81c2c92e47edaee6ULL,0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL,0xa81a664bbc423001ULL,0xc24b8b70d0f89791ULL,0xc76c51a30654be30ULL,
|
||||
0xd192e819d6ef5218ULL,0xd69906245565a910ULL,0xf40e35855771202aULL,0x106aa07032bbd1b8ULL,
|
||||
0x19a4c116b8d2d0c8ULL,0x1e376c085141ab53ULL,0x2748774cdf8eeb99ULL,0x34b0bcb5e19b48a8ULL,
|
||||
0x391c0cb3c5c95a63ULL,0x4ed8aa4ae3418acbULL,0x5b9cca4f7763e373ULL,0x682e6ff3d6b2b8a3ULL,
|
||||
0x748f82ee5defb2fcULL,0x78a5636f43172f60ULL,0x84c87814a1f0ab72ULL,0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL,0xa4506cebde82bde9ULL,0xbef9a3f7b2c67915ULL,0xc67178f2e372532bULL,
|
||||
0xca273eceea26619cULL,0xd186b8c721c0c207ULL,0xeada7dd6cde0eb1eULL,0xf57d4f7fee6ed178ULL,
|
||||
0x06f067aa72176fbaULL,0x0a637dc5a2c898a6ULL,0x113f9804bef90daeULL,0x1b710b35131c471bULL,
|
||||
0x28db77f523047d84ULL,0x32caab7b40c72493ULL,0x3c9ebe0a15c9bebcULL,0x431d67c49c100d4cULL,
|
||||
0x4cc5d4becb3e42b6ULL,0x597f299cfc657e2aULL,0x5fcb6fab3ad6faecULL,0x6c44198c4a475817ULL
|
||||
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL,
|
||||
0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
||||
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
|
||||
0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL,
|
||||
0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL,
|
||||
0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
|
||||
0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
||||
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL,
|
||||
0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL,
|
||||
0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
||||
0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
|
||||
0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
|
||||
};
|
||||
|
||||
#define STORE64H(x, y) Utils::storeBigEndian<uint64_t>(y, x)
|
||||
|
@ -120,7 +117,8 @@ static void sha512_process(sha512_state *const md,const uint8_t *in,unsigned lon
|
|||
md->length += 128 * 8;
|
||||
in += 128;
|
||||
inlen -= 128;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
unsigned long n = std::min(inlen, (128 - md->curlen));
|
||||
Utils::copy(md->buf + md->curlen, in, n);
|
||||
md->curlen += n;
|
||||
|
@ -248,7 +246,12 @@ void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,const u
|
|||
SHA384(mac, outer, 176);
|
||||
}
|
||||
|
||||
void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const char label,const char context,const uint32_t iter,uint8_t out[ZT_SYMMETRIC_KEY_SIZE])
|
||||
void KBKDFHMACSHA384(
|
||||
const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],
|
||||
const char label,
|
||||
const char context,
|
||||
const uint32_t iter,
|
||||
uint8_t out[ZT_SYMMETRIC_KEY_SIZE])
|
||||
{
|
||||
uint8_t kbkdfMsg[13];
|
||||
|
||||
|
|
|
@ -81,7 +81,12 @@ void HMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],const void *msg,unsigne
|
|||
* @param iter Key iteration for generation of multiple keys for the same label/context
|
||||
* @param out Output to receive derived key
|
||||
*/
|
||||
void KBKDFHMACSHA384(const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],char label,char context,uint32_t iter,uint8_t out[ZT_SYMMETRIC_KEY_SIZE]);
|
||||
void KBKDFHMACSHA384(
|
||||
const uint8_t key[ZT_SYMMETRIC_KEY_SIZE],
|
||||
char label,
|
||||
char context,
|
||||
uint32_t iter,
|
||||
uint8_t out[ZT_SYMMETRIC_KEY_SIZE]);
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
* Since the original was public domain, this is too.
|
||||
*/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#define ROTATE(v, c) (((v) << (c)) | ((v) >> (32 - (c))))
|
||||
#define XOR(v, w) ((v) ^ (w))
|
||||
#define PLUS(v, w) ((uint32_t)((v) + (w)))
|
||||
|
@ -18,8 +19,15 @@
|
|||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
// Slower version that does not use type punning
|
||||
#define U8TO32_LITTLE(p) ( ((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24) )
|
||||
static ZT_INLINE void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); }
|
||||
#define U8TO32_LITTLE(p) \
|
||||
(((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24))
|
||||
static ZT_INLINE void U32TO8_LITTLE(uint8_t* const c, const uint32_t v)
|
||||
{
|
||||
c[0] = (uint8_t)v;
|
||||
c[1] = (uint8_t)(v >> 8);
|
||||
c[2] = (uint8_t)(v >> 16);
|
||||
c[3] = (uint8_t)(v >> 24);
|
||||
}
|
||||
#else
|
||||
// Fast version that just does 32-bit load/store
|
||||
#define U8TO32_LITTLE(p) (*((const uint32_t*)((const void*)(p))))
|
||||
|
@ -32,15 +40,21 @@ static ZT_INLINE void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] =
|
|||
#define U32TO8_LITTLE(c, v) *((uint32_t*)((void*)(c))) = __builtin_bswap32((v))
|
||||
#else // no __GNUC__
|
||||
// Otherwise do it the slow, manual way on BE machines
|
||||
#define U8TO32_LITTLE(p) ( ((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24) )
|
||||
static ZT_INLINE void U32TO8_LITTLE(uint8_t *const c,const uint32_t v) { c[0] = (uint8_t)v; c[1] = (uint8_t)(v >> 8); c[2] = (uint8_t)(v >> 16); c[3] = (uint8_t)(v >> 24); }
|
||||
#define U8TO32_LITTLE(p) \
|
||||
(((uint32_t)(p)[0]) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24))
|
||||
static ZT_INLINE void U32TO8_LITTLE(uint8_t* const c, const uint32_t v)
|
||||
{
|
||||
c[0] = (uint8_t)v;
|
||||
c[1] = (uint8_t)(v >> 8);
|
||||
c[2] = (uint8_t)(v >> 16);
|
||||
c[3] = (uint8_t)(v >> 24);
|
||||
}
|
||||
#endif // __GNUC__ or not
|
||||
#endif // __BYTE_ORDER little or big?
|
||||
#endif // !ZT_SALSA20_SSE
|
||||
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
class _s20sseconsts
|
||||
{
|
||||
class _s20sseconsts {
|
||||
public:
|
||||
_s20sseconsts() noexcept
|
||||
{
|
||||
|
@ -96,8 +110,7 @@ void Salsa20::init(const void *key, const void *iv) noexcept
|
|||
#endif
|
||||
}
|
||||
|
||||
union p_SalsaState
|
||||
{
|
||||
union p_SalsaState {
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
__m128i v[4];
|
||||
#endif // ZT_SALSA20_SSE
|
||||
|
@ -195,10 +208,18 @@ static ZT_INLINE void p_salsaCrypt(p_SalsaState *const state, const uint8_t *m,
|
|||
k02 = _mm_shuffle_epi32(k02, _MM_SHUFFLE(0, 1, 2, 3));
|
||||
k13 = _mm_shuffle_epi32(k13, _MM_SHUFFLE(0, 1, 2, 3));
|
||||
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c), _mm_xor_si128(_mm_unpackhi_epi64(k02, k20), _mm_loadu_si128(reinterpret_cast<const __m128i *>(m))));
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c) + 1, _mm_xor_si128(_mm_unpackhi_epi64(k13, k31), _mm_loadu_si128(reinterpret_cast<const __m128i *>(m) + 1)));
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c) + 2, _mm_xor_si128(_mm_unpacklo_epi64(k20, k02), _mm_loadu_si128(reinterpret_cast<const __m128i *>(m) + 2)));
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(c) + 3, _mm_xor_si128(_mm_unpacklo_epi64(k31, k13), _mm_loadu_si128(reinterpret_cast<const __m128i *>(m) + 3)));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(c),
|
||||
_mm_xor_si128(_mm_unpackhi_epi64(k02, k20), _mm_loadu_si128(reinterpret_cast<const __m128i*>(m))));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(c) + 1,
|
||||
_mm_xor_si128(_mm_unpackhi_epi64(k13, k31), _mm_loadu_si128(reinterpret_cast<const __m128i*>(m) + 1)));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(c) + 2,
|
||||
_mm_xor_si128(_mm_unpacklo_epi64(k20, k02), _mm_loadu_si128(reinterpret_cast<const __m128i*>(m) + 2)));
|
||||
_mm_storeu_si128(
|
||||
reinterpret_cast<__m128i*>(c) + 3,
|
||||
_mm_xor_si128(_mm_unpacklo_epi64(k31, k13), _mm_loadu_si128(reinterpret_cast<const __m128i*>(m) + 3)));
|
||||
|
||||
X0 = X0s;
|
||||
X1 = X1s;
|
||||
|
@ -301,7 +322,8 @@ static ZT_INLINE void p_salsaCrypt(p_SalsaState *const state, const uint8_t *m,
|
|||
bytes -= 64;
|
||||
c += 64;
|
||||
m += 64;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (bytes < 64) {
|
||||
for (unsigned int i = 0; i < bytes; ++i)
|
||||
ctarget[i] = c[i];
|
||||
|
@ -318,12 +340,20 @@ static ZT_INLINE void p_salsaCrypt(p_SalsaState *const state, const uint8_t *m,
|
|||
|
||||
void Salsa20::crypt12(const void* in, void* out, unsigned int bytes) noexcept
|
||||
{
|
||||
p_salsaCrypt< 12 >(reinterpret_cast<p_SalsaState *>(&_state), reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out), bytes);
|
||||
p_salsaCrypt<12>(
|
||||
reinterpret_cast<p_SalsaState*>(&_state),
|
||||
reinterpret_cast<const uint8_t*>(in),
|
||||
reinterpret_cast<uint8_t*>(out),
|
||||
bytes);
|
||||
}
|
||||
|
||||
void Salsa20::crypt20(const void* in, void* out, unsigned int bytes) noexcept
|
||||
{
|
||||
p_salsaCrypt< 20 >(reinterpret_cast<p_SalsaState *>(&_state), reinterpret_cast<const uint8_t *>(in), reinterpret_cast<uint8_t *>(out), bytes);
|
||||
p_salsaCrypt<20>(
|
||||
reinterpret_cast<p_SalsaState*>(&_state),
|
||||
reinterpret_cast<const uint8_t*>(in),
|
||||
reinterpret_cast<uint8_t*>(out),
|
||||
bytes);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
#define ZT_SALSA20_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "TriviallyCopyable.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#ifdef ZT_ARCH_X64
|
||||
#define ZT_SALSA20_SSE 1
|
||||
|
@ -35,30 +35,39 @@ namespace ZeroTier {
|
|||
* a minor optimization done here because ZeroTier messages are
|
||||
* nowhere near this large.
|
||||
*/
|
||||
class Salsa20 : public TriviallyCopyable
|
||||
{
|
||||
class Salsa20 : public TriviallyCopyable {
|
||||
public:
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
|
||||
static constexpr bool accelerated() noexcept
|
||||
{ return true; }
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
static constexpr bool accelerated() noexcept { return false; }
|
||||
static constexpr bool accelerated() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
ZT_INLINE Salsa20() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~Salsa20() noexcept
|
||||
{ Utils::burn(&_state, sizeof(_state)); }
|
||||
{
|
||||
Utils::burn(&_state, sizeof(_state));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key 256-bit (32 byte) key
|
||||
* @param iv 64-bit initialization vector
|
||||
*/
|
||||
ZT_INLINE Salsa20(const void* key, const void* iv) noexcept
|
||||
{ init(key, iv); }
|
||||
{
|
||||
init(key, iv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize cipher
|
||||
|
@ -87,8 +96,7 @@ public:
|
|||
void crypt20(const void* in, void* out, unsigned int bytes) noexcept;
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
union {
|
||||
#ifdef ZT_SALSA20_SSE
|
||||
__m128i v[4];
|
||||
#endif // ZT_SALSA20_SSE
|
||||
|
|
|
@ -24,24 +24,31 @@ namespace ZeroTier {
|
|||
*
|
||||
* This is used in the core to avoid requiring C++11 and because auto_ptr is weird.
|
||||
*/
|
||||
template< typename T >
|
||||
class ScopedPtr : public TriviallyCopyable
|
||||
{
|
||||
template <typename T> class ScopedPtr : public TriviallyCopyable {
|
||||
public:
|
||||
explicit ZT_INLINE ScopedPtr(T* const p) noexcept : m_ptr(p)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~ScopedPtr()
|
||||
{ delete m_ptr; }
|
||||
{
|
||||
delete m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE T* operator->() const noexcept
|
||||
{ return m_ptr; }
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE T& operator*() const noexcept
|
||||
{ return *m_ptr; }
|
||||
{
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE T* ptr() const noexcept
|
||||
{ return m_ptr; }
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE void swap(const ScopedPtr& p) noexcept
|
||||
{
|
||||
|
@ -51,29 +58,43 @@ public:
|
|||
}
|
||||
|
||||
explicit ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_ptr != (T *)0); }
|
||||
{
|
||||
return (m_ptr != (T*)0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const ScopedPtr& p) const noexcept
|
||||
{ return (m_ptr == p.m_ptr); }
|
||||
{
|
||||
return (m_ptr == p.m_ptr);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const ScopedPtr& p) const noexcept
|
||||
{ return (m_ptr != p.m_ptr); }
|
||||
{
|
||||
return (m_ptr != p.m_ptr);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(T* const p) const noexcept
|
||||
{ return (m_ptr == p); }
|
||||
{
|
||||
return (m_ptr == p);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(T* const p) const noexcept
|
||||
{ return (m_ptr != p); }
|
||||
{
|
||||
return (m_ptr != p);
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_INLINE ScopedPtr() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ScopedPtr(const ScopedPtr& p) noexcept : m_ptr(nullptr)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ScopedPtr& operator=(const ScopedPtr& p) noexcept
|
||||
{ return *this; }
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* const m_ptr;
|
||||
};
|
||||
|
@ -81,9 +102,10 @@ private:
|
|||
} // namespace ZeroTier
|
||||
|
||||
namespace std {
|
||||
template< typename T >
|
||||
ZT_INLINE void swap(ZeroTier::ScopedPtr< T > &a, ZeroTier::ScopedPtr< T > &b) noexcept
|
||||
{ a.swap(b); }
|
||||
template <typename T> ZT_INLINE void swap(ZeroTier::ScopedPtr<T>& a, ZeroTier::ScopedPtr<T>& b) noexcept
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,34 +11,44 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
||||
// Entry timeout -- make it fairly long since this is just to prevent stale buildup
|
||||
#define ZT_SELFAWARENESS_ENTRY_TIMEOUT 300000
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
SelfAwareness::SelfAwareness(const Context &ctx) :
|
||||
m_ctx(ctx)
|
||||
{}
|
||||
SelfAwareness::SelfAwareness(const Context& ctx) : m_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void SelfAwareness::iam(const CallContext &cc, const Identity &reporter, const int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted)
|
||||
void SelfAwareness::iam(
|
||||
const CallContext& cc,
|
||||
const Identity& reporter,
|
||||
const int64_t receivedOnLocalSocket,
|
||||
const InetAddress& reporterPhysicalAddress,
|
||||
const InetAddress& myPhysicalAddress,
|
||||
bool trusted)
|
||||
{
|
||||
const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
|
||||
|
||||
if ((scope != reporterPhysicalAddress.ipScope()) || (scope == ZT_IP_SCOPE_NONE) || (scope == ZT_IP_SCOPE_LOOPBACK) || (scope == ZT_IP_SCOPE_MULTICAST))
|
||||
if ((scope != reporterPhysicalAddress.ipScope()) || (scope == ZT_IP_SCOPE_NONE) || (scope == ZT_IP_SCOPE_LOOPBACK)
|
||||
|| (scope == ZT_IP_SCOPE_MULTICAST))
|
||||
return;
|
||||
|
||||
Mutex::Lock l(m_phy_l);
|
||||
p_PhySurfaceEntry &entry = m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)];
|
||||
p_PhySurfaceEntry& entry =
|
||||
m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)];
|
||||
|
||||
if ((trusted) && ((cc.ticks - entry.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress))) {
|
||||
if ((trusted) && ((cc.ticks - entry.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
&& (! entry.mySurface.ipsEqual(myPhysicalAddress))) {
|
||||
// Changes to external surface reported by trusted peers causes path reset in this scope
|
||||
entry.mySurface = myPhysicalAddress;
|
||||
entry.timestampTicks = cc.ticks;
|
||||
|
@ -50,7 +60,8 @@ void SelfAwareness::iam(const CallContext &cc, const Identity &reporter, const i
|
|||
for (Map<p_PhySurfaceKey, p_PhySurfaceEntry>::iterator i(m_phy.begin()); i != m_phy.end();) {
|
||||
if ((i->first.scope == scope) && (i->first.reporterPhysicalAddress != reporterPhysicalAddress))
|
||||
m_phy.erase(i++);
|
||||
else ++i;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
// Reset all paths within this scope and address family
|
||||
|
@ -59,8 +70,16 @@ void SelfAwareness::iam(const CallContext &cc, const Identity &reporter, const i
|
|||
for (Vector<SharedPtr<Peer> >::const_iterator p(peers.begin()); p != peers.end(); ++p)
|
||||
(*p)->resetWithinScope(m_ctx, cc, (InetAddress::IpScope)scope, myPhysicalAddress.as.sa.sa_family);
|
||||
|
||||
m_ctx.t->resettingPathsInScope(cc, 0x9afff100, reporter, reporterPhysicalAddress, entry.mySurface, myPhysicalAddress, scope);
|
||||
} else {
|
||||
m_ctx.t->resettingPathsInScope(
|
||||
cc,
|
||||
0x9afff100,
|
||||
reporter,
|
||||
reporterPhysicalAddress,
|
||||
entry.mySurface,
|
||||
myPhysicalAddress,
|
||||
scope);
|
||||
}
|
||||
else {
|
||||
// Otherwise just update DB to use to determine external surface info
|
||||
entry.mySurface = myPhysicalAddress;
|
||||
entry.timestampTicks = cc.ticks;
|
||||
|
@ -74,7 +93,8 @@ void SelfAwareness::clean(const CallContext &cc)
|
|||
for (Map<p_PhySurfaceKey, p_PhySurfaceEntry>::iterator i(m_phy.begin()); i != m_phy.end();) {
|
||||
if ((cc.ticks - i->second.timestampTicks) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
m_phy.erase(i++);
|
||||
else ++i;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
#ifndef ZT_SELFAWARENESS_HPP
|
||||
#define ZT_SELFAWARENESS_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -31,8 +31,7 @@ class Context;
|
|||
*
|
||||
* Name aside, it shouldn't be capable of achieving sentience.
|
||||
*/
|
||||
class SelfAwareness
|
||||
{
|
||||
class SelfAwareness {
|
||||
public:
|
||||
explicit SelfAwareness(const Context& ctx);
|
||||
|
||||
|
@ -45,7 +44,13 @@ public:
|
|||
* @param myPhysicalAddress Physical address that peer says we have
|
||||
* @param trusted True if this peer is trusted as an authority to inform us of external address changes
|
||||
*/
|
||||
void iam(const CallContext &cc, const Identity &reporter, int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted);
|
||||
void
|
||||
iam(const CallContext& cc,
|
||||
const Identity& reporter,
|
||||
int64_t receivedOnLocalSocket,
|
||||
const InetAddress& reporterPhysicalAddress,
|
||||
const InetAddress& myPhysicalAddress,
|
||||
bool trusted);
|
||||
|
||||
/**
|
||||
* Clean up database periodically
|
||||
|
@ -60,39 +65,56 @@ public:
|
|||
MultiMap<unsigned int, InetAddress> externalAddresses(CallContext& cc) const;
|
||||
|
||||
private:
|
||||
struct p_PhySurfaceKey
|
||||
{
|
||||
struct p_PhySurfaceKey {
|
||||
Address reporter;
|
||||
int64_t receivedOnLocalSocket;
|
||||
InetAddress reporterPhysicalAddress;
|
||||
InetAddress::IpScope scope;
|
||||
|
||||
ZT_INLINE p_PhySurfaceKey() noexcept
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE p_PhySurfaceKey(const Address &r, const int64_t rol, const InetAddress &ra, InetAddress::IpScope s) noexcept: reporter(r), receivedOnLocalSocket(rol), reporterPhysicalAddress(ra), scope(s)
|
||||
{}
|
||||
ZT_INLINE
|
||||
p_PhySurfaceKey(const Address& r, const int64_t rol, const InetAddress& ra, InetAddress::IpScope s) noexcept
|
||||
: reporter(r)
|
||||
, receivedOnLocalSocket(rol)
|
||||
, reporterPhysicalAddress(ra)
|
||||
, scope(s)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return ((unsigned long)reporter.toInt() + (unsigned long)receivedOnLocalSocket + (unsigned long)scope); }
|
||||
{
|
||||
return ((unsigned long)reporter.toInt() + (unsigned long)receivedOnLocalSocket + (unsigned long)scope);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const p_PhySurfaceKey& k) const noexcept
|
||||
{ return ((reporter == k.reporter) && (receivedOnLocalSocket == k.receivedOnLocalSocket) && (reporterPhysicalAddress == k.reporterPhysicalAddress) && (scope == k.scope)); }
|
||||
{
|
||||
return (
|
||||
(reporter == k.reporter) && (receivedOnLocalSocket == k.receivedOnLocalSocket)
|
||||
&& (reporterPhysicalAddress == k.reporterPhysicalAddress) && (scope == k.scope));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const p_PhySurfaceKey& k) const noexcept
|
||||
{ return (!(*this == k)); }
|
||||
{
|
||||
return (! (*this == k));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const p_PhySurfaceKey& k) const noexcept
|
||||
{
|
||||
if (reporter < k.reporter) {
|
||||
return true;
|
||||
} else if (reporter == k.reporter) {
|
||||
}
|
||||
else if (reporter == k.reporter) {
|
||||
if (receivedOnLocalSocket < k.receivedOnLocalSocket) {
|
||||
return true;
|
||||
} else if (receivedOnLocalSocket == k.receivedOnLocalSocket) {
|
||||
}
|
||||
else if (receivedOnLocalSocket == k.receivedOnLocalSocket) {
|
||||
if (reporterPhysicalAddress < k.reporterPhysicalAddress) {
|
||||
return true;
|
||||
} else if (reporterPhysicalAddress == k.reporterPhysicalAddress) {
|
||||
}
|
||||
else if (reporterPhysicalAddress == k.reporterPhysicalAddress) {
|
||||
return scope < k.scope;
|
||||
}
|
||||
}
|
||||
|
@ -101,17 +123,24 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
struct p_PhySurfaceEntry
|
||||
{
|
||||
struct p_PhySurfaceEntry {
|
||||
InetAddress mySurface;
|
||||
int64_t timestampTicks;
|
||||
bool trusted;
|
||||
|
||||
ZT_INLINE p_PhySurfaceEntry() noexcept: mySurface(), timestampTicks(0), trusted(false)
|
||||
{}
|
||||
ZT_INLINE p_PhySurfaceEntry() noexcept
|
||||
: mySurface()
|
||||
, timestampTicks(0)
|
||||
, trusted(false)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE p_PhySurfaceEntry(const InetAddress &a, const int64_t t) noexcept: mySurface(a), timestampTicks(t), trusted(false)
|
||||
{}
|
||||
ZT_INLINE p_PhySurfaceEntry(const InetAddress& a, const int64_t t) noexcept
|
||||
: mySurface(a)
|
||||
, timestampTicks(t)
|
||||
, trusted(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
const Context& m_ctx;
|
||||
|
|
|
@ -25,21 +25,26 @@ namespace ZeroTier {
|
|||
* Classes must have an atomic<int> field called __refCount and set this class
|
||||
* as a friend to be used with this.
|
||||
*/
|
||||
template< typename T >
|
||||
class SharedPtr : public TriviallyCopyable
|
||||
{
|
||||
template <typename T> class SharedPtr : public TriviallyCopyable {
|
||||
public:
|
||||
ZT_INLINE SharedPtr() noexcept : m_ptr(nullptr)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
explicit ZT_INLINE SharedPtr(T* obj) noexcept : m_ptr(obj)
|
||||
{ if (likely(obj != nullptr)) const_cast<std::atomic< int > *>(&(obj->__refCount))->fetch_add(1, std::memory_order_acquire); }
|
||||
{
|
||||
if (likely(obj != nullptr))
|
||||
const_cast<std::atomic<int>*>(&(obj->__refCount))->fetch_add(1, std::memory_order_acquire);
|
||||
}
|
||||
|
||||
ZT_INLINE SharedPtr(const SharedPtr& sp) noexcept : m_ptr(sp.m_acquire())
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~SharedPtr()
|
||||
{ m_release(); }
|
||||
{
|
||||
m_release();
|
||||
}
|
||||
|
||||
ZT_INLINE SharedPtr& operator=(const SharedPtr& sp)
|
||||
{
|
||||
|
@ -90,19 +95,27 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE operator bool() const noexcept
|
||||
{ return (m_ptr != nullptr); }
|
||||
{
|
||||
return (m_ptr != nullptr);
|
||||
}
|
||||
|
||||
ZT_INLINE T& operator*() const noexcept
|
||||
{ return *m_ptr; }
|
||||
{
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
ZT_INLINE T* operator->() const noexcept
|
||||
{ return m_ptr; }
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw pointer to held object
|
||||
*/
|
||||
ZT_INLINE T* ptr() const noexcept
|
||||
{ return m_ptr; }
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this pointer to NULL
|
||||
|
@ -131,34 +144,50 @@ public:
|
|||
T* const ptr = m_ptr;
|
||||
m_ptr = nullptr;
|
||||
return ptr;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept
|
||||
{ return (unsigned long)((uintptr_t)m_ptr + (uintptr_t)Utils::hash32((uint32_t)m_ptr)); }
|
||||
{
|
||||
return (unsigned long)((uintptr_t)m_ptr + (uintptr_t)Utils::hash32((uint32_t)m_ptr));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const SharedPtr& sp) const noexcept
|
||||
{ return (m_ptr == sp.m_ptr); }
|
||||
{
|
||||
return (m_ptr == sp.m_ptr);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const SharedPtr& sp) const noexcept
|
||||
{ return (m_ptr != sp.m_ptr); }
|
||||
{
|
||||
return (m_ptr != sp.m_ptr);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>(const SharedPtr& sp) const noexcept
|
||||
{ return (reinterpret_cast<const uint8_t *>(m_ptr) > reinterpret_cast<const uint8_t *>(sp.m_ptr)); }
|
||||
{
|
||||
return (reinterpret_cast<const uint8_t*>(m_ptr) > reinterpret_cast<const uint8_t*>(sp.m_ptr));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<(const SharedPtr& sp) const noexcept
|
||||
{ return (reinterpret_cast<const uint8_t *>(m_ptr) < reinterpret_cast<const uint8_t *>(sp.m_ptr)); }
|
||||
{
|
||||
return (reinterpret_cast<const uint8_t*>(m_ptr) < reinterpret_cast<const uint8_t*>(sp.m_ptr));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator>=(const SharedPtr& sp) const noexcept
|
||||
{ return (reinterpret_cast<const uint8_t *>(m_ptr) >= reinterpret_cast<const uint8_t *>(sp.m_ptr)); }
|
||||
{
|
||||
return (reinterpret_cast<const uint8_t*>(m_ptr) >= reinterpret_cast<const uint8_t*>(sp.m_ptr));
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator<=(const SharedPtr& sp) const noexcept
|
||||
{ return (reinterpret_cast<const uint8_t *>(m_ptr) <= reinterpret_cast<const uint8_t *>(sp.m_ptr)); }
|
||||
{
|
||||
return (reinterpret_cast<const uint8_t*>(m_ptr) <= reinterpret_cast<const uint8_t*>(sp.m_ptr));
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_INLINE T* m_acquire() const noexcept
|
||||
|
@ -171,7 +200,8 @@ private:
|
|||
ZT_INLINE void m_release() const noexcept
|
||||
{
|
||||
if (likely(m_ptr != nullptr)) {
|
||||
if (unlikely(const_cast<std::atomic< int > *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_release) <= 1))
|
||||
if (unlikely(
|
||||
const_cast<std::atomic<int>*>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_release) <= 1))
|
||||
delete m_ptr;
|
||||
}
|
||||
}
|
||||
|
@ -184,13 +214,15 @@ private:
|
|||
// Augment std::swap to speed up some operations with SharedPtr.
|
||||
namespace std {
|
||||
|
||||
template< typename T >
|
||||
ZT_MAYBE_UNUSED ZT_INLINE void swap(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept
|
||||
{ a.swap(b); }
|
||||
template <typename T> ZT_MAYBE_UNUSED ZT_INLINE void swap(ZeroTier::SharedPtr<T>& a, ZeroTier::SharedPtr<T>& b) noexcept
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
ZT_MAYBE_UNUSED ZT_INLINE void move(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept
|
||||
{ a.move(b); }
|
||||
template <typename T> ZT_MAYBE_UNUSED ZT_INLINE void move(ZeroTier::SharedPtr<T>& a, ZeroTier::SharedPtr<T>& b) noexcept
|
||||
{
|
||||
a.move(b);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
|
|
@ -29,8 +29,7 @@
|
|||
* This can be used in place of Mutex to lock things that are extremely fast
|
||||
* to access. It should be used very sparingly.
|
||||
*/
|
||||
class Spinlock
|
||||
{
|
||||
class Spinlock {
|
||||
public:
|
||||
/**
|
||||
* Pause current thread using whatever methods might be available
|
||||
|
@ -51,7 +50,8 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE Spinlock() noexcept : m_locked(false)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE void lock() noexcept
|
||||
{
|
||||
|
@ -63,11 +63,18 @@ public:
|
|||
}
|
||||
|
||||
ZT_INLINE void unlock() noexcept
|
||||
{ m_locked.clear(std::memory_order_release); }
|
||||
{
|
||||
m_locked.clear(std::memory_order_release);
|
||||
}
|
||||
|
||||
private:
|
||||
ZT_INLINE Spinlock(const Spinlock &) noexcept {}
|
||||
ZT_INLINE const Spinlock &operator=(const Spinlock &) noexcept { return *this; }
|
||||
ZT_INLINE Spinlock(const Spinlock&) noexcept
|
||||
{
|
||||
}
|
||||
ZT_INLINE const Spinlock& operator=(const Spinlock&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::atomic_flag m_locked;
|
||||
};
|
||||
|
|
|
@ -14,21 +14,21 @@
|
|||
#ifndef ZT_STORE_HPP
|
||||
#define ZT_STORE_HPP
|
||||
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "CallContext.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Wrapper around API callbacks for data store
|
||||
*/
|
||||
class Store
|
||||
{
|
||||
class Store {
|
||||
public:
|
||||
ZT_INLINE Store(const Context& ctx) : m_ctx(ctx)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a state object
|
||||
|
@ -38,12 +38,21 @@ public:
|
|||
* @param idSize Size of object ID in qwords
|
||||
* @return Data or empty vector if not found
|
||||
*/
|
||||
ZT_INLINE Vector< uint8_t > get(const CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, unsigned int idSize) const
|
||||
ZT_INLINE Vector<uint8_t>
|
||||
get(const CallContext& cc, ZT_StateObjectType type, const uint64_t* const id, unsigned int idSize) const
|
||||
{
|
||||
Vector<uint8_t> dv;
|
||||
void* data = nullptr;
|
||||
void (*freeFunc)(void*) = nullptr;
|
||||
const int r = m_ctx.cb.stateGetFunction(reinterpret_cast<ZT_Node *>(m_ctx.node), m_ctx.uPtr, cc.tPtr, type, id, idSize, &data, &freeFunc);
|
||||
const int r = m_ctx.cb.stateGetFunction(
|
||||
reinterpret_cast<ZT_Node*>(m_ctx.node),
|
||||
m_ctx.uPtr,
|
||||
cc.tPtr,
|
||||
type,
|
||||
id,
|
||||
idSize,
|
||||
&data,
|
||||
&freeFunc);
|
||||
if (r > 0)
|
||||
dv.assign(reinterpret_cast<const uint8_t*>(data), reinterpret_cast<const uint8_t*>(data) + r);
|
||||
if ((data) && (freeFunc))
|
||||
|
@ -60,8 +69,17 @@ public:
|
|||
* @param data Data to store
|
||||
* @param len Length of data
|
||||
*/
|
||||
ZT_INLINE void put(const CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize, const void *const data, const unsigned int len) noexcept
|
||||
{ m_ctx.cb.statePutFunction(reinterpret_cast<ZT_Node *>(this), m_ctx.uPtr, cc.tPtr, type, id, idSize, data, (int)len); }
|
||||
ZT_INLINE void
|
||||
put(const CallContext& cc,
|
||||
ZT_StateObjectType type,
|
||||
const uint64_t* const id,
|
||||
const unsigned int idSize,
|
||||
const void* const data,
|
||||
const unsigned int len) noexcept
|
||||
{
|
||||
m_ctx.cb
|
||||
.statePutFunction(reinterpret_cast<ZT_Node*>(this), m_ctx.uPtr, cc.tPtr, type, id, idSize, data, (int)len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase a state object from the object store
|
||||
|
@ -70,8 +88,11 @@ public:
|
|||
* @param id Object ID
|
||||
* @param idSize Size of object ID in qwords
|
||||
*/
|
||||
ZT_INLINE void erase(const CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize) noexcept
|
||||
{ m_ctx.cb.statePutFunction(reinterpret_cast<ZT_Node *>(this), m_ctx.uPtr, cc.tPtr, type, id, idSize, nullptr, -1); }
|
||||
ZT_INLINE void
|
||||
erase(const CallContext& cc, ZT_StateObjectType type, const uint64_t* const id, const unsigned int idSize) noexcept
|
||||
{
|
||||
m_ctx.cb.statePutFunction(reinterpret_cast<ZT_Node*>(this), m_ctx.uPtr, cc.tPtr, type, id, idSize, nullptr, -1);
|
||||
}
|
||||
|
||||
private:
|
||||
const Context& m_ctx;
|
||||
|
|
|
@ -14,29 +14,24 @@
|
|||
#ifndef ZT_SYMMETRICKEY_HPP
|
||||
#define ZT_SYMMETRICKEY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "AES.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Container for symmetric keys and ciphers initialized with them.
|
||||
*/
|
||||
class SymmetricKey
|
||||
{
|
||||
class SymmetricKey {
|
||||
public:
|
||||
/**
|
||||
* Construct an uninitialized key (init() must be called)
|
||||
*/
|
||||
ZT_INLINE SymmetricKey():
|
||||
m_secret(),
|
||||
m_ts(-1),
|
||||
m_initialNonce(0),
|
||||
m_cipher(),
|
||||
m_nonce(0)
|
||||
{}
|
||||
ZT_INLINE SymmetricKey() : m_secret(), m_ts(-1), m_initialNonce(0), m_cipher(), m_nonce(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new symmetric key
|
||||
|
@ -47,24 +42,28 @@ public:
|
|||
* @param ts Key timestamp
|
||||
* @param key Key (must be 48 bytes / 384 bits)
|
||||
*/
|
||||
ZT_INLINE SymmetricKey(const int64_t ts, const void *const key) noexcept:
|
||||
m_secret(key),
|
||||
m_ts(ts),
|
||||
m_initialNonce(Utils::getSecureRandomU64() >> 1U),
|
||||
m_cipher(key),
|
||||
m_nonce(m_initialNonce)
|
||||
{}
|
||||
ZT_INLINE SymmetricKey(const int64_t ts, const void* const key) noexcept
|
||||
: m_secret(key)
|
||||
, m_ts(ts)
|
||||
, m_initialNonce(Utils::getSecureRandomU64() >> 1U)
|
||||
, m_cipher(key)
|
||||
, m_nonce(m_initialNonce)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE SymmetricKey(const SymmetricKey &k) noexcept:
|
||||
m_secret(k.m_secret),
|
||||
m_ts(k.m_ts),
|
||||
m_initialNonce(k.m_initialNonce),
|
||||
m_cipher(k.m_secret.data),
|
||||
m_nonce(k.m_nonce.load(std::memory_order_relaxed))
|
||||
{}
|
||||
ZT_INLINE SymmetricKey(const SymmetricKey& k) noexcept
|
||||
: m_secret(k.m_secret)
|
||||
, m_ts(k.m_ts)
|
||||
, m_initialNonce(k.m_initialNonce)
|
||||
, m_cipher(k.m_secret.data)
|
||||
, m_nonce(k.m_nonce.load(std::memory_order_relaxed))
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~SymmetricKey() noexcept
|
||||
{ Utils::burn(m_secret.data, ZT_SYMMETRIC_KEY_SIZE); }
|
||||
{
|
||||
Utils::burn(m_secret.data, ZT_SYMMETRIC_KEY_SIZE);
|
||||
}
|
||||
|
||||
ZT_INLINE SymmetricKey& operator=(const SymmetricKey& k) noexcept
|
||||
{
|
||||
|
@ -99,7 +98,9 @@ public:
|
|||
* @return Next unique IV for next message
|
||||
*/
|
||||
ZT_INLINE uint64_t nextMessage(const Address sender, const Address receiver) noexcept
|
||||
{ return m_nonce.fetch_add(1, std::memory_order_relaxed) ^ (((uint64_t)(sender > receiver)) << 63U); }
|
||||
{
|
||||
return m_nonce.fetch_add(1, std::memory_order_relaxed) ^ (((uint64_t)(sender > receiver)) << 63U);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of times this key has been used.
|
||||
|
@ -110,25 +111,33 @@ public:
|
|||
* @return Number of times nextMessage() has been called since object creation
|
||||
*/
|
||||
ZT_INLINE uint64_t odometer() const noexcept
|
||||
{ return m_nonce.load(std::memory_order_relaxed) - m_initialNonce; }
|
||||
{
|
||||
return m_nonce.load(std::memory_order_relaxed) - m_initialNonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Key creation timestamp or -1 if this is a long-lived key
|
||||
*/
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_ts; }
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 48-byte / 384-bit secret key
|
||||
*/
|
||||
ZT_INLINE const uint8_t* key() const noexcept
|
||||
{ return m_secret.data; }
|
||||
{
|
||||
return m_secret.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AES cipher (already initialized with secret key)
|
||||
*/
|
||||
ZT_INLINE const AES& aes() const noexcept
|
||||
{ return m_cipher; }
|
||||
{
|
||||
return m_cipher;
|
||||
}
|
||||
|
||||
private:
|
||||
Blob<ZT_SYMMETRIC_KEY_SIZE> m_secret;
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
#ifndef ZT_TAG_HPP
|
||||
#define ZT_TAG_HPP
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "C25519.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
|
||||
#define ZT_TAG_MARSHAL_SIZE_MAX (8 + 8 + 4 + 4 + 5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
|
||||
|
@ -43,16 +43,19 @@ class Context;
|
|||
* Unlike capabilities tags are signed only by the issuer and are never
|
||||
* transferable.
|
||||
*/
|
||||
class TagCredential : public Credential
|
||||
{
|
||||
class TagCredential : public Credential {
|
||||
friend class Credential;
|
||||
|
||||
public:
|
||||
static constexpr ZT_CredentialType credentialType() noexcept
|
||||
{ return ZT_CREDENTIAL_TYPE_TAG; }
|
||||
{
|
||||
return ZT_CREDENTIAL_TYPE_TAG;
|
||||
}
|
||||
|
||||
ZT_INLINE TagCredential() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nwid Network ID
|
||||
|
@ -61,42 +64,66 @@ public:
|
|||
* @param id Tag ID
|
||||
* @param value Tag value
|
||||
*/
|
||||
ZT_INLINE TagCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id, const uint32_t value) noexcept:
|
||||
m_id(id),
|
||||
m_value(value),
|
||||
m_networkId(nwid),
|
||||
m_ts(ts),
|
||||
m_issuedTo(issuedTo),
|
||||
m_signedBy(),
|
||||
m_signatureLength(0)
|
||||
{}
|
||||
ZT_INLINE TagCredential(
|
||||
const uint64_t nwid,
|
||||
const int64_t ts,
|
||||
const Address& issuedTo,
|
||||
const uint32_t id,
|
||||
const uint32_t value) noexcept
|
||||
: m_id(id)
|
||||
, m_value(value)
|
||||
, m_networkId(nwid)
|
||||
, m_ts(ts)
|
||||
, m_issuedTo(issuedTo)
|
||||
, m_signedBy()
|
||||
, m_signatureLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE uint32_t id() const noexcept
|
||||
{ return m_id; }
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint32_t& value() const noexcept
|
||||
{ return m_value; }
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
ZT_INLINE uint64_t networkId() const noexcept
|
||||
{ return m_networkId; }
|
||||
{
|
||||
return m_networkId;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t timestamp() const noexcept
|
||||
{ return m_ts; }
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
ZT_INLINE int64_t revision() const noexcept
|
||||
{ return m_ts; }
|
||||
{
|
||||
return m_ts;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& issuedTo() const noexcept
|
||||
{ return m_issuedTo; }
|
||||
{
|
||||
return m_issuedTo;
|
||||
}
|
||||
|
||||
ZT_INLINE const Address& signer() const noexcept
|
||||
{ return m_signedBy; }
|
||||
{
|
||||
return m_signedBy;
|
||||
}
|
||||
|
||||
ZT_INLINE const uint8_t* signature() const noexcept
|
||||
{ return m_signature; }
|
||||
{
|
||||
return m_signature;
|
||||
}
|
||||
|
||||
ZT_INLINE unsigned int signatureLength() const noexcept
|
||||
{ return m_signatureLength; }
|
||||
{
|
||||
return m_signatureLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign this tag
|
||||
|
@ -113,10 +140,14 @@ public:
|
|||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
||||
*/
|
||||
ZT_INLINE Credential::VerifyResult verify(const Context& ctx, const CallContext& cc) const noexcept
|
||||
{ return s_verify(ctx, cc, *this); }
|
||||
{
|
||||
return s_verify(ctx, cc, *this);
|
||||
}
|
||||
|
||||
static constexpr int marshalSizeMax() noexcept
|
||||
{ return ZT_TAG_MARSHAL_SIZE_MAX; }
|
||||
{
|
||||
return ZT_TAG_MARSHAL_SIZE_MAX;
|
||||
}
|
||||
|
||||
int marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept;
|
||||
|
||||
|
@ -124,43 +155,66 @@ public:
|
|||
|
||||
// Provides natural sort order by ID
|
||||
ZT_INLINE bool operator<(const TagCredential& t) const noexcept
|
||||
{ return (m_id < t.m_id); }
|
||||
{
|
||||
return (m_id < t.m_id);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator==(const TagCredential& t) const noexcept
|
||||
{ return (memcmp(this, &t, sizeof(TagCredential)) == 0); }
|
||||
{
|
||||
return (memcmp(this, &t, sizeof(TagCredential)) == 0);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator!=(const TagCredential& t) const noexcept
|
||||
{ return (memcmp(this, &t, sizeof(TagCredential)) != 0); }
|
||||
{
|
||||
return (memcmp(this, &t, sizeof(TagCredential)) != 0);
|
||||
}
|
||||
|
||||
// For searching sorted arrays or lists of Tags by ID
|
||||
struct IdComparePredicate
|
||||
{
|
||||
struct IdComparePredicate {
|
||||
ZT_INLINE bool operator()(const TagCredential& a, const TagCredential& b) const noexcept
|
||||
{ return (a.id() < b.id()); }
|
||||
{
|
||||
return (a.id() < b.id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const uint32_t a, const TagCredential& b) const noexcept
|
||||
{ return (a < b.id()); }
|
||||
{
|
||||
return (a < b.id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential& a, const uint32_t b) const noexcept
|
||||
{ return (a.id() < b); }
|
||||
{
|
||||
return (a.id() < b);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential* a, const TagCredential* b) const noexcept
|
||||
{ return (a->id() < b->id()); }
|
||||
{
|
||||
return (a->id() < b->id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential* a, const TagCredential& b) const noexcept
|
||||
{ return (a->id() < b.id()); }
|
||||
{
|
||||
return (a->id() < b.id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential& a, const TagCredential* b) const noexcept
|
||||
{ return (a.id() < b->id()); }
|
||||
{
|
||||
return (a.id() < b->id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const uint32_t a, const TagCredential* b) const noexcept
|
||||
{ return (a < b->id()); }
|
||||
{
|
||||
return (a < b->id());
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const TagCredential* a, const uint32_t b) const noexcept
|
||||
{ return (a->id() < b); }
|
||||
{
|
||||
return (a->id() < b);
|
||||
}
|
||||
|
||||
ZT_INLINE bool operator()(const uint32_t a, const uint32_t b) const noexcept
|
||||
{ return (a < b); }
|
||||
{
|
||||
return (a < b);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
1663
core/Tests.cpp
1663
core/Tests.cpp
File diff suppressed because it is too large
Load diff
|
@ -16,8 +16,8 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Spinlock.hpp"
|
||||
|
||||
// The number of buckets must be a power of two.
|
||||
|
@ -36,18 +36,19 @@ namespace ZeroTier {
|
|||
* fast lookup, with lookups sometimes requiring only a few instructions. It
|
||||
* uses a "lock free" (actually pointer-as-spinlock) design.
|
||||
*/
|
||||
template< typename V >
|
||||
class TinyMap
|
||||
{
|
||||
template <typename V> class TinyMap {
|
||||
private:
|
||||
typedef Vector<std::pair<uint64_t, V> > EV;
|
||||
|
||||
public:
|
||||
ZT_INLINE TinyMap()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE ~TinyMap()
|
||||
{ this->clear(); }
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
ZT_INLINE void clear()
|
||||
{
|
||||
|
@ -59,7 +60,8 @@ public:
|
|||
delete reinterpret_cast<EV*>(vptr);
|
||||
m_buckets[i].store(0, std::memory_order_release);
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +76,9 @@ public:
|
|||
const uintptr_t vptr = bucket.exchange(ZT_TINYMAP_LOCKED_POINTER, std::memory_order_acquire);
|
||||
if (likely(vptr != ZT_TINYMAP_LOCKED_POINTER)) {
|
||||
if (likely(vptr != 0)) {
|
||||
for(typename EV::const_iterator n(reinterpret_cast<const EV *>(vptr)->begin()); n != reinterpret_cast<const EV *>(vptr)->end(); ++n) {
|
||||
for (typename EV::const_iterator n(reinterpret_cast<const EV*>(vptr)->begin());
|
||||
n != reinterpret_cast<const EV*>(vptr)->end();
|
||||
++n) {
|
||||
if (likely(n->first == key)) {
|
||||
tmp = n->second;
|
||||
break;
|
||||
|
@ -83,7 +87,8 @@ public:
|
|||
}
|
||||
bucket.store(vptr, std::memory_order_release);
|
||||
return tmp;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +102,11 @@ public:
|
|||
if (likely(vptr != ZT_TINYMAP_LOCKED_POINTER)) {
|
||||
if (vptr == 0) {
|
||||
vptr = reinterpret_cast<uintptr_t>(new EV());
|
||||
} else {
|
||||
for (typename EV::iterator n(reinterpret_cast<EV *>(vptr)->begin()); n != reinterpret_cast<EV *>(vptr)->end(); ++n) {
|
||||
}
|
||||
else {
|
||||
for (typename EV::iterator n(reinterpret_cast<EV*>(vptr)->begin());
|
||||
n != reinterpret_cast<EV*>(vptr)->end();
|
||||
++n) {
|
||||
if (n->first == key) {
|
||||
n->second = value;
|
||||
bucket.store(vptr, std::memory_order_release);
|
||||
|
@ -109,7 +117,8 @@ public:
|
|||
reinterpret_cast<EV*>(vptr)->push_back(std::pair<uint64_t, V>(key, value));
|
||||
bucket.store(vptr, std::memory_order_release);
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +131,9 @@ public:
|
|||
uintptr_t vptr = bucket.exchange(ZT_TINYMAP_LOCKED_POINTER, std::memory_order_acquire);
|
||||
if (likely(vptr != ZT_TINYMAP_LOCKED_POINTER)) {
|
||||
if (likely(vptr != 0)) {
|
||||
for (typename EV::iterator n(reinterpret_cast<EV *>(vptr)->begin()); n != reinterpret_cast<EV *>(vptr)->end(); ++n) {
|
||||
for (typename EV::iterator n(reinterpret_cast<EV*>(vptr)->begin());
|
||||
n != reinterpret_cast<EV*>(vptr)->end();
|
||||
++n) {
|
||||
if (n->first == key) {
|
||||
reinterpret_cast<EV*>(vptr)->erase(n);
|
||||
break;
|
||||
|
@ -135,7 +146,8 @@ public:
|
|||
}
|
||||
bucket.store(vptr, std::memory_order_release);
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Spinlock::pause();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,15 +12,16 @@
|
|||
/****/
|
||||
|
||||
#include "Topology.hpp"
|
||||
|
||||
#include "Defaults.hpp"
|
||||
#include "TrustStore.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "TrustStore.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
Topology::Topology(const Context &ctx, const CallContext &cc) :
|
||||
m_ctx(ctx)
|
||||
{}
|
||||
Topology::Topology(const Context& ctx, const CallContext& cc) : m_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
SharedPtr<Peer> Topology::add(const CallContext& cc, const SharedPtr<Peer>& peer)
|
||||
{
|
||||
|
@ -71,8 +72,13 @@ void Topology::doPeriodicTasks(const CallContext &cc)
|
|||
{
|
||||
RWMutex::RLock l1(m_peers_l);
|
||||
for (Map<Address, SharedPtr<Peer> >::iterator i(m_peers.begin()); i != m_peers.end(); ++i) {
|
||||
// TODO: also delete if the peer has not exchanged meaningful communication in a while, such as a network frame or non-trivial control packet.
|
||||
if (((cc.ticks - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (!std::binary_search(rootLookup.begin(), rootLookup.end(), reinterpret_cast<uintptr_t>(i->second.ptr()))))
|
||||
// TODO: also delete if the peer has not exchanged meaningful communication in a while, such as a
|
||||
// network frame or non-trivial control packet.
|
||||
if (((cc.ticks - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT)
|
||||
&& (! std::binary_search(
|
||||
rootLookup.begin(),
|
||||
rootLookup.end(),
|
||||
reinterpret_cast<uintptr_t>(i->second.ptr()))))
|
||||
toDelete.push_back(i->first);
|
||||
}
|
||||
}
|
||||
|
@ -102,11 +108,13 @@ void Topology::doPeriodicTasks(const CallContext &cc)
|
|||
Path* const d = i->second.weakGC();
|
||||
if (likely(d == nullptr)) {
|
||||
++i;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_paths.erase(i++);
|
||||
try {
|
||||
toDelete.push_back(d);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +141,8 @@ void Topology::trustStoreChanged(const CallContext &cc)
|
|||
root.set(new Peer());
|
||||
if (root->init(m_ctx, cc, r->first)) {
|
||||
root = this->add(cc, root);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
root.zero();
|
||||
}
|
||||
}
|
||||
|
@ -158,8 +167,7 @@ void Topology::saveAll(const CallContext &cc)
|
|||
i->second->save(m_ctx, cc);
|
||||
}
|
||||
|
||||
struct p_RootRankingComparisonOperator
|
||||
{
|
||||
struct p_RootRankingComparisonOperator {
|
||||
ZT_INLINE bool operator()(const SharedPtr<Peer>& a, const SharedPtr<Peer>& b) const noexcept
|
||||
{
|
||||
// Sort roots first in order of which root has spoken most recently, but
|
||||
|
@ -171,7 +179,8 @@ struct p_RootRankingComparisonOperator
|
|||
const int64_t blr = b->lastReceive() / (ZT_PATH_KEEPALIVE_PERIOD / 2);
|
||||
if (alr < blr) {
|
||||
return true;
|
||||
} else if (blr == alr) {
|
||||
}
|
||||
else if (blr == alr) {
|
||||
const int bb = b->latency();
|
||||
if (bb < 0)
|
||||
return true;
|
||||
|
@ -188,7 +197,8 @@ void Topology::m_rankRoots()
|
|||
l_bestRoot.lock();
|
||||
m_bestRoot.zero();
|
||||
l_bestRoot.unlock();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::sort(m_roots.begin(), m_roots.end(), p_RootRankingComparisonOperator());
|
||||
l_bestRoot.lock();
|
||||
m_bestRoot = m_roots.front();
|
||||
|
@ -222,7 +232,8 @@ void Topology::m_loadCached(const CallContext &cc, const Address &zta, SharedPtr
|
|||
return;
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...) {
|
||||
peer.zero();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,21 +14,21 @@
|
|||
#ifndef ZT_TOPOLOGY_HPP
|
||||
#define ZT_TOPOLOGY_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Certificate.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Spinlock.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Certificate.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Spinlock.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -37,8 +37,7 @@ class Context;
|
|||
/**
|
||||
* Database of network topology
|
||||
*/
|
||||
class Topology
|
||||
{
|
||||
class Topology {
|
||||
public:
|
||||
Topology(const Context& ctx, const CallContext& cc);
|
||||
|
||||
|
|
|
@ -12,26 +12,22 @@
|
|||
/****/
|
||||
|
||||
#include "Trace.hpp"
|
||||
|
||||
#include "Context.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "FCV.hpp"
|
||||
|
||||
// NOTE: packet IDs are always handled in network byte order, so no need to convert them.
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
Trace::Trace(const Context &ctx) :
|
||||
m_ctx(ctx),
|
||||
m_traceFlags(0)
|
||||
{}
|
||||
Trace::Trace(const Context& ctx) : m_ctx(ctx), m_traceFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Trace::unexpectedError(
|
||||
const CallContext &cc,
|
||||
uint32_t codeLocation,
|
||||
const char *message,
|
||||
...)
|
||||
void Trace::unexpectedError(const CallContext& cc, uint32_t codeLocation, const char* message, ...)
|
||||
{
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_UNEXPECTED_ERROR);
|
||||
|
@ -163,7 +159,11 @@ void Trace::m_outgoingNetworkFrameDropped(
|
|||
Dictionary::append(buf, ZT_TRACE_FIELD_ETHERTYPE, etherType);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_LENGTH, frameLength);
|
||||
if (frameData)
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_DATA, frameData, std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(
|
||||
buf,
|
||||
ZT_TRACE_FIELD_FRAME_DATA,
|
||||
frameData,
|
||||
std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_REASON, reason);
|
||||
buf.push_back(0);
|
||||
m_ctx.node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
|
||||
|
@ -199,17 +199,18 @@ void Trace::m_incomingNetworkFrameDropped(
|
|||
Dictionary::append(buf, ZT_TRACE_FIELD_PACKET_VERB, verb);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_LENGTH, frameLength);
|
||||
if (frameData)
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_DATA, frameData, std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(
|
||||
buf,
|
||||
ZT_TRACE_FIELD_FRAME_DATA,
|
||||
frameData,
|
||||
std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FLAG_CREDENTIAL_REQUEST_SENT, credentialRequestSent);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_REASON, reason);
|
||||
buf.push_back(0);
|
||||
m_ctx.node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data());
|
||||
}
|
||||
|
||||
void Trace::m_networkConfigRequestSent(
|
||||
void *tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId)
|
||||
void Trace::m_networkConfigRequestSent(void* tPtr, uint32_t codeLocation, uint64_t networkId)
|
||||
{
|
||||
FCV<uint8_t, 4096> buf;
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED);
|
||||
|
@ -255,7 +256,11 @@ void Trace::m_networkFilter(
|
|||
Dictionary::append(buf, ZT_TRACE_FIELD_DEST_MAC, destMac.toInt());
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_LENGTH, frameLength);
|
||||
if (frameData)
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_FRAME_DATA, frameData, std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(
|
||||
buf,
|
||||
ZT_TRACE_FIELD_FRAME_DATA,
|
||||
frameData,
|
||||
std::min((unsigned int)64, (unsigned int)frameLength));
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_ETHERTYPE, etherType);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_VLAN_ID, vlanId);
|
||||
Dictionary::append(buf, ZT_TRACE_FIELD_RULE_FLAG_NOTEE, noTee);
|
||||
|
|
106
core/Trace.hpp
106
core/Trace.hpp
|
@ -14,15 +14,15 @@
|
|||
#ifndef ZT_TRACE_HPP
|
||||
#define ZT_TRACE_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#define ZT_TRACE_F_VL1 0x01U
|
||||
#define ZT_TRACE_F_VL2 0x02U
|
||||
|
@ -56,30 +56,30 @@ struct NetworkConfig;
|
|||
* turned into constants that are semi-official and stored in a database to
|
||||
* provide extra debug context.
|
||||
*/
|
||||
class Trace
|
||||
{
|
||||
class Trace {
|
||||
public:
|
||||
struct RuleResultLog : public TriviallyCopyable
|
||||
{
|
||||
struct RuleResultLog : public TriviallyCopyable {
|
||||
uint8_t l[ZT_MAX_NETWORK_RULES / 2]; // ZT_MAX_NETWORK_RULES 4-bit fields
|
||||
|
||||
ZT_INLINE void log(const unsigned int rn, const uint8_t thisRuleMatches, const uint8_t thisSetMatches) noexcept
|
||||
{ l[rn >> 1U] |= (((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U)) << ((rn & 1U) << 2U); }
|
||||
{
|
||||
l[rn >> 1U] |= (((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U)) << ((rn & 1U) << 2U);
|
||||
}
|
||||
|
||||
ZT_INLINE void logSkipped(const unsigned int rn, const uint8_t thisSetMatches) noexcept
|
||||
{ l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U); }
|
||||
{
|
||||
l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U);
|
||||
}
|
||||
|
||||
ZT_INLINE void clear() noexcept
|
||||
{ memoryZero(this); }
|
||||
{
|
||||
memoryZero(this);
|
||||
}
|
||||
};
|
||||
|
||||
explicit Trace(const Context& ctx);
|
||||
|
||||
void unexpectedError(
|
||||
const CallContext &cc,
|
||||
uint32_t codeLocation,
|
||||
const char *message,
|
||||
...);
|
||||
void unexpectedError(const CallContext& cc, uint32_t codeLocation, const char* message, ...);
|
||||
|
||||
ZT_INLINE void resettingPathsInScope(
|
||||
const CallContext& cc,
|
||||
|
@ -105,7 +105,15 @@ public:
|
|||
const Identity& triggeringPeer)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
|
||||
m_tryingNewPath(cc.tPtr, codeLocation, trying, physicalAddress, triggerAddress, triggeringPacketId, triggeringPacketVerb, triggeringPeer);
|
||||
m_tryingNewPath(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
trying,
|
||||
physicalAddress,
|
||||
triggerAddress,
|
||||
triggeringPacketId,
|
||||
triggeringPacketVerb,
|
||||
triggeringPeer);
|
||||
}
|
||||
|
||||
ZT_INLINE void learnedNewPath(
|
||||
|
@ -132,7 +140,16 @@ public:
|
|||
const ZT_TracePacketDropReason reason)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0))
|
||||
m_incomingPacketDropped(cc.tPtr, codeLocation, packetId, networkId, peerIdentity, physicalAddress, hops, verb, reason);
|
||||
m_incomingPacketDropped(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
packetId,
|
||||
networkId,
|
||||
peerIdentity,
|
||||
physicalAddress,
|
||||
hops,
|
||||
verb,
|
||||
reason);
|
||||
}
|
||||
|
||||
ZT_INLINE void outgoingNetworkFrameDropped(
|
||||
|
@ -147,7 +164,16 @@ public:
|
|||
ZT_TraceFrameDropReason reason)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
|
||||
m_outgoingNetworkFrameDropped(cc.tPtr, codeLocation, networkId, sourceMac, destMac, etherType, frameLength, frameData, reason);
|
||||
m_outgoingNetworkFrameDropped(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
networkId,
|
||||
sourceMac,
|
||||
destMac,
|
||||
etherType,
|
||||
frameLength,
|
||||
frameData,
|
||||
reason);
|
||||
}
|
||||
|
||||
ZT_INLINE void incomingNetworkFrameDropped(
|
||||
|
@ -167,13 +193,24 @@ public:
|
|||
ZT_TraceFrameDropReason reason)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
|
||||
m_incomingNetworkFrameDropped(cc.tPtr, codeLocation, networkId, sourceMac, destMac, etherType, peerIdentity, physicalAddress, hops, frameLength, frameData, verb, credentialRequestSent, reason);
|
||||
m_incomingNetworkFrameDropped(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
networkId,
|
||||
sourceMac,
|
||||
destMac,
|
||||
etherType,
|
||||
peerIdentity,
|
||||
physicalAddress,
|
||||
hops,
|
||||
frameLength,
|
||||
frameData,
|
||||
verb,
|
||||
credentialRequestSent,
|
||||
reason);
|
||||
}
|
||||
|
||||
ZT_INLINE void networkConfigRequestSent(
|
||||
const CallContext &cc,
|
||||
const uint32_t codeLocation,
|
||||
uint64_t networkId)
|
||||
ZT_INLINE void networkConfigRequestSent(const CallContext& cc, const uint32_t codeLocation, uint64_t networkId)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
|
||||
m_networkConfigRequestSent(cc.tPtr, codeLocation, networkId);
|
||||
|
@ -233,7 +270,15 @@ public:
|
|||
ZT_TraceCredentialRejectionReason reason)
|
||||
{
|
||||
if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0))
|
||||
m_credentialRejected(cc.tPtr, codeLocation, networkId, identity, credentialId, credentialTimestamp, credentialType, reason);
|
||||
m_credentialRejected(
|
||||
cc.tPtr,
|
||||
codeLocation,
|
||||
networkId,
|
||||
identity,
|
||||
credentialId,
|
||||
credentialTimestamp,
|
||||
credentialType,
|
||||
reason);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -302,10 +347,7 @@ private:
|
|||
bool credentialRequestSent,
|
||||
ZT_TraceFrameDropReason reason);
|
||||
|
||||
void m_networkConfigRequestSent(
|
||||
void *tPtr,
|
||||
uint32_t codeLocation,
|
||||
uint64_t networkId);
|
||||
void m_networkConfigRequestSent(void* tPtr, uint32_t codeLocation, uint64_t networkId);
|
||||
|
||||
void m_networkFilter(
|
||||
void* tPtr,
|
||||
|
|
|
@ -24,8 +24,7 @@ namespace ZeroTier {
|
|||
*
|
||||
* It also includes some static methods to do this conveniently.
|
||||
*/
|
||||
struct TriviallyCopyable
|
||||
{
|
||||
struct TriviallyCopyable {
|
||||
public:
|
||||
/**
|
||||
* Zero a TriviallyCopyable object
|
||||
|
@ -33,8 +32,7 @@ public:
|
|||
* @tparam T Automatically inferred type of object
|
||||
* @param obj Any TriviallyCopyable object
|
||||
*/
|
||||
template<typename T>
|
||||
static ZT_INLINE void memoryZero(T *obj) noexcept
|
||||
template <typename T> static ZT_INLINE void memoryZero(T* obj) noexcept
|
||||
{
|
||||
mustBeTriviallyCopyable(obj);
|
||||
Utils::zero<sizeof(T)>(obj);
|
||||
|
@ -46,16 +44,19 @@ public:
|
|||
* @tparam T Automatically inferred type of object
|
||||
* @param obj Any TriviallyCopyable object
|
||||
*/
|
||||
template<typename T>
|
||||
static ZT_INLINE void memoryZero(T &obj) noexcept
|
||||
template <typename T> static ZT_INLINE void memoryZero(T& obj) noexcept
|
||||
{
|
||||
mustBeTriviallyCopyable(obj);
|
||||
Utils::zero<sizeof(T)>(&obj);
|
||||
}
|
||||
|
||||
private:
|
||||
static ZT_INLINE void mustBeTriviallyCopyable(const TriviallyCopyable &) noexcept {}
|
||||
static ZT_INLINE void mustBeTriviallyCopyable(const TriviallyCopyable *) noexcept {}
|
||||
static ZT_INLINE void mustBeTriviallyCopyable(const TriviallyCopyable&) noexcept
|
||||
{
|
||||
}
|
||||
static ZT_INLINE void mustBeTriviallyCopyable(const TriviallyCopyable*) noexcept
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -12,15 +12,18 @@
|
|||
/****/
|
||||
|
||||
#include "TrustStore.hpp"
|
||||
|
||||
#include "LZ4.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
TrustStore::TrustStore()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
TrustStore::~TrustStore()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
SharedPtr<TrustStore::Entry> TrustStore::get(const H384& serial) const
|
||||
{
|
||||
|
@ -36,27 +39,29 @@ Map< Identity, SharedPtr< const Locator > > TrustStore::roots()
|
|||
|
||||
// Iterate using m_bySubjectIdentity to only scan certificates with subject identities.
|
||||
// This map also does not contian error or deprecated certificates.
|
||||
for (Map< Fingerprint, Vector< SharedPtr< Entry > > >::const_iterator cv(m_bySubjectIdentity.begin()); cv != m_bySubjectIdentity.end(); ++cv) {
|
||||
for (Map<Fingerprint, Vector<SharedPtr<Entry> > >::const_iterator cv(m_bySubjectIdentity.begin());
|
||||
cv != m_bySubjectIdentity.end();
|
||||
++cv) {
|
||||
for (Vector<SharedPtr<Entry> >::const_iterator c(cv->second.begin()); c != cv->second.end(); ++c) {
|
||||
|
||||
// A root set cert must be marked for this use and authorized to influence this node's config.
|
||||
if ((((*c)->m_certificate.usageFlags & ZT_CERTIFICATE_USAGE_ZEROTIER_ROOT_SET) != 0) && (((*c)->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_CONFIG) != 0)) {
|
||||
|
||||
// Add all identities to the root set, and for each entry in the set make sure we have the latest locator if there's more than one cert with one.
|
||||
if ((((*c)->m_certificate.usageFlags & ZT_CERTIFICATE_USAGE_ZEROTIER_ROOT_SET) != 0)
|
||||
&& (((*c)->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_CONFIG) != 0)) {
|
||||
// Add all identities to the root set, and for each entry in the set make sure we have the latest
|
||||
// locator if there's more than one cert with one.
|
||||
for (unsigned int j = 0; j < (*c)->certificate().subject.identityCount; ++j) {
|
||||
const Identity *const id = reinterpret_cast<const Identity *>((*c)->certificate().subject.identities[j].identity);
|
||||
const Identity* const id =
|
||||
reinterpret_cast<const Identity*>((*c)->certificate().subject.identities[j].identity);
|
||||
if ((id) && (*id)) { // sanity check
|
||||
SharedPtr<const Locator>& existingLoc = r[*id];
|
||||
const Locator *const loc = reinterpret_cast<const Locator *>((*c)->certificate().subject.identities[j].locator);
|
||||
const Locator* const loc =
|
||||
reinterpret_cast<const Locator*>((*c)->certificate().subject.identities[j].locator);
|
||||
if (loc) {
|
||||
if ((! existingLoc) || (existingLoc->revision() < loc->revision()))
|
||||
existingLoc.set(new Locator(*loc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return r;
|
||||
|
@ -149,31 +154,39 @@ bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
|
|||
Vector<Entry*> visited;
|
||||
visited.reserve(8);
|
||||
for (Map<H384, SharedPtr<Entry> >::iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
if ((c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) && (!c->second->m_onTrustPath) && ((c->second->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA) == 0)) {
|
||||
if ((c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) && (! c->second->m_onTrustPath)
|
||||
&& ((c->second->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA) == 0)) {
|
||||
// Trace the path of each certificate all the way back to a trusted CA.
|
||||
unsigned int pathLength = 0;
|
||||
Map<H384, SharedPtr<Entry> >::const_iterator current(c);
|
||||
visited.clear();
|
||||
for (;;) {
|
||||
if (pathLength <= current->second->m_certificate.maxPathLength) {
|
||||
|
||||
// Check if this cert isn't a CA or already part of a valid trust path. If so then step upward toward CA.
|
||||
if (((current->second->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA) == 0) && (!current->second->m_onTrustPath)) {
|
||||
// If the issuer (parent) certificiate is (1) valid, (2) not already visited (to prevent loops),
|
||||
// and (3) has a public key that matches this cert's issuer public key (sanity check), proceed
|
||||
// up the certificate graph toward a potential CA.
|
||||
// Check if this cert isn't a CA or already part of a valid trust path. If so then step upward
|
||||
// toward CA.
|
||||
if (((current->second->m_localTrust & ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ROOT_CA) == 0)
|
||||
&& (! current->second->m_onTrustPath)) {
|
||||
// If the issuer (parent) certificiate is (1) valid, (2) not already visited (to prevent
|
||||
// loops), and (3) has a public key that matches this cert's issuer public key (sanity
|
||||
// check), proceed up the certificate graph toward a potential CA.
|
||||
visited.push_back(current->second.ptr());
|
||||
const Map<H384, SharedPtr<Entry> >::const_iterator prevChild(current);
|
||||
current = m_bySerial.find(H384(current->second->m_certificate.issuer));
|
||||
if ((current != m_bySerial.end()) &&
|
||||
(std::find(visited.begin(), visited.end(), current->second.ptr()) == visited.end()) &&
|
||||
(current->second->m_error == ZT_CERTIFICATE_ERROR_NONE) &&
|
||||
(current->second->m_certificate.publicKeySize == prevChild->second->m_certificate.issuerPublicKeySize) &&
|
||||
(memcmp(current->second->m_certificate.publicKey, prevChild->second->m_certificate.issuerPublicKey, current->second->m_certificate.publicKeySize) == 0)) {
|
||||
if ((current != m_bySerial.end())
|
||||
&& (std::find(visited.begin(), visited.end(), current->second.ptr()) == visited.end())
|
||||
&& (current->second->m_error == ZT_CERTIFICATE_ERROR_NONE)
|
||||
&& (current->second->m_certificate.publicKeySize
|
||||
== prevChild->second->m_certificate.issuerPublicKeySize)
|
||||
&& (memcmp(
|
||||
current->second->m_certificate.publicKey,
|
||||
prevChild->second->m_certificate.issuerPublicKey,
|
||||
current->second->m_certificate.publicKeySize)
|
||||
== 0)) {
|
||||
++pathLength;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// If we've traced this to a root CA, flag its parents as also being on a trust path. Then
|
||||
// break the loop without setting an error. We don't flag the current cert as being on a
|
||||
// trust path since no other certificates depend on it.
|
||||
|
@ -183,7 +196,6 @@ bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we made it here without breaking or continuing, no path to a
|
||||
|
@ -201,33 +213,39 @@ bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
|
|||
m_bySubjectUniqueId.clear();
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) {
|
||||
if (c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) {
|
||||
|
||||
const unsigned int uniqueIdSize = c->second->m_certificate.subject.uniqueIdSize;
|
||||
if ((uniqueIdSize > 0) && (uniqueIdSize <= ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE)) {
|
||||
SharedPtr< Entry > &entry = m_bySubjectUniqueId[Blob< ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE >(c->second->m_certificate.subject.uniqueId, uniqueIdSize)];
|
||||
SharedPtr<Entry>& entry = m_bySubjectUniqueId[Blob<ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE>(
|
||||
c->second->m_certificate.subject.uniqueId,
|
||||
uniqueIdSize)];
|
||||
if (entry) {
|
||||
|
||||
// If there's already an entry, see if there's a newer certificate for this subject.
|
||||
if (c->second->m_certificate.subject.timestamp > entry->m_certificate.subject.timestamp) {
|
||||
entry->m_subjectDeprecated = true;
|
||||
entry = c->second;
|
||||
} else if (c->second->m_certificate.subject.timestamp < entry->m_certificate.subject.timestamp) {
|
||||
}
|
||||
else if (c->second->m_certificate.subject.timestamp < entry->m_certificate.subject.timestamp) {
|
||||
c->second->m_subjectDeprecated = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// Equal timestamps should never happen, but handle it anyway by comparing serials.
|
||||
if (memcmp(c->second->m_certificate.serialNo, entry->m_certificate.serialNo, ZT_CERTIFICATE_HASH_SIZE) > 0) {
|
||||
if (memcmp(
|
||||
c->second->m_certificate.serialNo,
|
||||
entry->m_certificate.serialNo,
|
||||
ZT_CERTIFICATE_HASH_SIZE)
|
||||
> 0) {
|
||||
entry->m_subjectDeprecated = true;
|
||||
entry = c->second;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
c->second->m_subjectDeprecated = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
entry = c->second;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,23 +254,24 @@ bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const
|
|||
m_bySubjectIdentity.clear();
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) {
|
||||
if ((c->second->m_error == ZT_CERTIFICATE_ERROR_NONE) && (! c->second->m_subjectDeprecated)) {
|
||||
|
||||
for (unsigned int i = 0; i < c->second->m_certificate.subject.identityCount; ++i) {
|
||||
const Identity *const id = reinterpret_cast<const Identity *>(c->second->m_certificate.subject.identities[i].identity);
|
||||
const Identity* const id =
|
||||
reinterpret_cast<const Identity*>(c->second->m_certificate.subject.identities[i].identity);
|
||||
if ((id) && (*id)) // sanity check
|
||||
m_bySubjectIdentity[id->fingerprint()].push_back(c->second);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// If purge is set, erase and return error and deprecated certs (that are not on a trust path).
|
||||
if (purge) {
|
||||
for (Map<H384, SharedPtr<Entry> >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) {
|
||||
if ( (c->second->error() != ZT_CERTIFICATE_ERROR_NONE) || ((c->second->m_subjectDeprecated) && (!c->second->m_onTrustPath)) ) {
|
||||
if ((c->second->error() != ZT_CERTIFICATE_ERROR_NONE)
|
||||
|| ((c->second->m_subjectDeprecated) && (! c->second->m_onTrustPath))) {
|
||||
purge->push_back(c->second);
|
||||
m_bySerial.erase(c++);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +311,11 @@ Vector< uint8_t > TrustStore::save() const
|
|||
b.push_back(0);
|
||||
|
||||
comp.resize((unsigned long)LZ4_COMPRESSBOUND(b.size()) + 8);
|
||||
compSize = LZ4_compress_fast(reinterpret_cast<const char *>(b.data()), reinterpret_cast<char *>(comp.data() + 8), (int)b.size(), (int)(comp.size() - 8));
|
||||
compSize = LZ4_compress_fast(
|
||||
reinterpret_cast<const char*>(b.data()),
|
||||
reinterpret_cast<char*>(comp.data() + 8),
|
||||
(int)b.size(),
|
||||
(int)(comp.size() - 8));
|
||||
if (unlikely(compSize <= 0)) // shouldn't be possible
|
||||
return Vector<uint8_t>();
|
||||
|
||||
|
@ -320,7 +343,12 @@ int TrustStore::load(const Vector< uint8_t > &data)
|
|||
Vector<uint8_t> uncomp;
|
||||
uncomp.resize(uncompSize);
|
||||
|
||||
if (LZ4_decompress_safe(reinterpret_cast<const char *>(data.data() + 8), reinterpret_cast<char *>(uncomp.data()), (int)(data.size() - 8), (int)uncompSize) != (int)uncompSize)
|
||||
if (LZ4_decompress_safe(
|
||||
reinterpret_cast<const char*>(data.data() + 8),
|
||||
reinterpret_cast<char*>(uncomp.data()),
|
||||
(int)(data.size() - 8),
|
||||
(int)uncompSize)
|
||||
!= (int)uncompSize)
|
||||
return -1;
|
||||
const uint8_t* b = uncomp.data();
|
||||
if (Utils::fnv1a32(b, (unsigned int)uncompSize) != Utils::loadBigEndian<uint32_t>(data.data() + 4))
|
||||
|
|
|
@ -14,16 +14,16 @@
|
|||
#ifndef ZT_TRUSTSTORE_HPP
|
||||
#define ZT_TRUSTSTORE_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Certificate.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -43,14 +43,12 @@ namespace ZeroTier {
|
|||
* hence there are no methods for doing that. There's only one instance in a
|
||||
* node anyway.
|
||||
*/
|
||||
class TrustStore
|
||||
{
|
||||
class TrustStore {
|
||||
public:
|
||||
/**
|
||||
* An entry in the node certificate trust store
|
||||
*/
|
||||
class Entry
|
||||
{
|
||||
class Entry {
|
||||
friend class SharedPtr<TrustStore::Entry>;
|
||||
friend class SharedPtr<const TrustStore::Entry>;
|
||||
friend class TrustStore;
|
||||
|
@ -60,7 +58,9 @@ public:
|
|||
* @return Reference to held certificate
|
||||
*/
|
||||
ZT_INLINE const Certificate& certificate() const noexcept
|
||||
{ return m_certificate; }
|
||||
{
|
||||
return m_certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local trust for this certificate
|
||||
|
@ -98,17 +98,21 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
Entry &operator=(const Entry &) { return *this; }
|
||||
Entry& operator=(const Entry&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_INLINE Entry(RWMutex &l, const Certificate &cert, const unsigned int lt) noexcept:
|
||||
__refCount(0),
|
||||
m_lock(l),
|
||||
m_certificate(cert),
|
||||
m_localTrust(lt),
|
||||
m_error(ZT_CERTIFICATE_ERROR_NONE),
|
||||
m_subjectDeprecated(false),
|
||||
m_onTrustPath(false)
|
||||
{}
|
||||
ZT_INLINE Entry(RWMutex& l, const Certificate& cert, const unsigned int lt) noexcept
|
||||
: __refCount(0)
|
||||
, m_lock(l)
|
||||
, m_certificate(cert)
|
||||
, m_localTrust(lt)
|
||||
, m_error(ZT_CERTIFICATE_ERROR_NONE)
|
||||
, m_subjectDeprecated(false)
|
||||
, m_onTrustPath(false)
|
||||
{
|
||||
}
|
||||
|
||||
std::atomic<int> __refCount;
|
||||
|
||||
|
@ -206,7 +210,8 @@ public:
|
|||
|
||||
private:
|
||||
Map<H384, SharedPtr<Entry> > m_bySerial; // all certificates
|
||||
Map< Blob< ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE >, SharedPtr< Entry > > m_bySubjectUniqueId; // non-rejected certificates only
|
||||
Map<Blob<ZT_CERTIFICATE_MAX_PUBLIC_KEY_SIZE>, SharedPtr<Entry> >
|
||||
m_bySubjectUniqueId; // non-rejected certificates only
|
||||
Map<Fingerprint, Vector<SharedPtr<Entry> > > m_bySubjectIdentity; // non-rejected certificates only
|
||||
ForwardList<SharedPtr<Entry> > m_addQueue;
|
||||
ForwardList<H384> m_deleteQueue;
|
||||
|
|
|
@ -12,16 +12,17 @@
|
|||
/****/
|
||||
|
||||
#include "Utils.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
#include "AES.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SHA512.hpp"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
@ -32,8 +33,8 @@
|
|||
#ifdef ZT_ARCH_ARM_HAS_NEON
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
|
@ -73,7 +74,6 @@ namespace Utils {
|
|||
#ifdef ZT_ARCH_ARM_HAS_NEON
|
||||
ARMCapabilities::ARMCapabilities() noexcept
|
||||
{
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
this->aes = true;
|
||||
|
@ -93,7 +93,8 @@ ARMCapabilities::ARMCapabilities() noexcept
|
|||
this->pmull = (hwcaps2 & HWCAP2_PMULL) != 0;
|
||||
this->sha1 = (hwcaps2 & HWCAP2_SHA1) != 0;
|
||||
this->sha2 = (hwcaps2 & HWCAP2_SHA2) != 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
const long hwcaps = getauxval(AT_HWCAP);
|
||||
this->aes = (hwcaps & HWCAP_AES) != 0;
|
||||
|
@ -107,7 +108,6 @@ ARMCapabilities::ARMCapabilities() noexcept
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
const ARMCapabilities ARMCAP;
|
||||
|
@ -126,11 +126,7 @@ CPUIDRegisters::CPUIDRegisters() noexcept
|
|||
ecx = (uint32_t)regs[2];
|
||||
edx = (uint32_t)regs[3];
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(1), "c"(0)
|
||||
);
|
||||
__asm__ __volatile__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1), "c"(0));
|
||||
#endif
|
||||
|
||||
rdrand = ((ecx & (1U << 30U)) != 0);
|
||||
|
@ -144,11 +140,7 @@ CPUIDRegisters::CPUIDRegisters() noexcept
|
|||
ecx = (uint32_t)regs[2];
|
||||
edx = (uint32_t)regs[3];
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(7), "c"(0)
|
||||
);
|
||||
__asm__ __volatile__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(7), "c"(0));
|
||||
#endif
|
||||
|
||||
vaes = aes && avx && ((ecx & (1U << 9U)) != 0);
|
||||
|
@ -215,14 +207,16 @@ char *hex(uint64_t i, char buf[17]) noexcept
|
|||
const unsigned int nyb = (unsigned int)(i >> (unsigned int)b) & 0xfU;
|
||||
if (p) {
|
||||
*(p++) = HEXCHARS[nyb];
|
||||
} else if (nyb != 0) {
|
||||
}
|
||||
else if (nyb != 0) {
|
||||
p = buf;
|
||||
*(p++) = HEXCHARS[nyb];
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
return buf;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
buf[0] = '0';
|
||||
buf[1] = 0;
|
||||
return buf;
|
||||
|
@ -236,7 +230,8 @@ uint64_t unhex(const char *s) noexcept
|
|||
int k = 0;
|
||||
while (k < 16) {
|
||||
char hc = *(s++);
|
||||
if (!hc) break;
|
||||
if (! hc)
|
||||
break;
|
||||
|
||||
uint8_t c = 0;
|
||||
if ((hc >= 48) && (hc <= 57))
|
||||
|
@ -271,9 +266,11 @@ unsigned int unhex(const char *h, unsigned int hlen, void *buf, unsigned int buf
|
|||
unsigned int l = 0;
|
||||
const char* hend = h + hlen;
|
||||
while (l < buflen) {
|
||||
if (h == hend) break;
|
||||
if (h == hend)
|
||||
break;
|
||||
uint8_t hc = *(reinterpret_cast<const uint8_t*>(h++));
|
||||
if (!hc) break;
|
||||
if (! hc)
|
||||
break;
|
||||
|
||||
uint8_t c = 0;
|
||||
if ((hc >= 48) && (hc <= 57))
|
||||
|
@ -283,9 +280,11 @@ unsigned int unhex(const char *h, unsigned int hlen, void *buf, unsigned int buf
|
|||
else if ((hc >= 65) && (hc <= 70))
|
||||
c = hc - 55;
|
||||
|
||||
if (h == hend) break;
|
||||
if (h == hend)
|
||||
break;
|
||||
hc = *(reinterpret_cast<const uint8_t*>(h++));
|
||||
if (!hc) break;
|
||||
if (! hc)
|
||||
break;
|
||||
|
||||
c <<= 4U;
|
||||
if ((hc >= 48) && (hc <= 57))
|
||||
|
@ -418,7 +417,8 @@ int b32e(const uint8_t *data, int length, char *result, int bufSize) noexcept
|
|||
buffer <<= 8U;
|
||||
buffer |= data[next++] & 0xffU;
|
||||
bitsLeft += 8;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int pad = 5 - bitsLeft;
|
||||
buffer <<= pad;
|
||||
bitsLeft += pad;
|
||||
|
@ -451,17 +451,21 @@ int b32d(const char *encoded, uint8_t *result, int bufSize) noexcept
|
|||
|
||||
if (ch == '0') {
|
||||
ch = 'O';
|
||||
} else if (ch == '1') {
|
||||
}
|
||||
else if (ch == '1') {
|
||||
ch = 'L';
|
||||
} else if (ch == '8') {
|
||||
}
|
||||
else if (ch == '8') {
|
||||
ch = 'B';
|
||||
}
|
||||
|
||||
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
|
||||
ch = (ch & 0x1f) - 1;
|
||||
} else if (ch >= '2' && ch <= '7') {
|
||||
}
|
||||
else if (ch >= '2' && ch <= '7') {
|
||||
ch -= '2' - 26;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
199
core/Utils.hpp
199
core/Utils.hpp
|
@ -16,13 +16,12 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -37,15 +36,11 @@ namespace Utils {
|
|||
// Macros to convert endian-ness at compile time for constants.
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)((uint16_t)((uint16_t)(x) << 8U) | (uint16_t)((uint16_t)(x) >> 8U)))
|
||||
#define ZT_CONST_TO_BE_UINT64(x) ( \
|
||||
(((uint64_t)(x) & 0x00000000000000ffULL) << 56U) | \
|
||||
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40U) | \
|
||||
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24U) | \
|
||||
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8U) | \
|
||||
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8U) | \
|
||||
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24U) | \
|
||||
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40U) | \
|
||||
(((uint64_t)(x) & 0xff00000000000000ULL) >> 56U))
|
||||
#define ZT_CONST_TO_BE_UINT64(x) \
|
||||
((((uint64_t)(x)&0x00000000000000ffULL) << 56U) | (((uint64_t)(x)&0x000000000000ff00ULL) << 40U) \
|
||||
| (((uint64_t)(x)&0x0000000000ff0000ULL) << 24U) | (((uint64_t)(x)&0x00000000ff000000ULL) << 8U) \
|
||||
| (((uint64_t)(x)&0x000000ff00000000ULL) >> 8U) | (((uint64_t)(x)&0x0000ff0000000000ULL) >> 24U) \
|
||||
| (((uint64_t)(x)&0x00ff000000000000ULL) >> 40U) | (((uint64_t)(x)&0xff00000000000000ULL) >> 56U))
|
||||
#else
|
||||
#define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)(x))
|
||||
#define ZT_CONST_TO_BE_UINT64(x) ((uint64_t)(x))
|
||||
|
@ -57,8 +52,7 @@ namespace Utils {
|
|||
#define ZT_ROL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||
|
||||
#ifdef ZT_ARCH_ARM_HAS_NEON
|
||||
struct ARMCapabilities
|
||||
{
|
||||
struct ARMCapabilities {
|
||||
ARMCapabilities() noexcept;
|
||||
bool aes, crc32, pmull, sha1, sha2;
|
||||
};
|
||||
|
@ -66,8 +60,7 @@ extern const ARMCapabilities ARMCAP;
|
|||
#endif
|
||||
|
||||
#ifdef ZT_ARCH_X64
|
||||
struct CPUIDRegisters
|
||||
{
|
||||
struct CPUIDRegisters {
|
||||
CPUIDRegisters() noexcept;
|
||||
bool rdrand, aes, avx, vaes, vpclmulqdq, avx2, avx512f, sha, fsrm;
|
||||
};
|
||||
|
@ -247,7 +240,9 @@ static ZT_INLINE char *stok(char *str, const char *delim, char **saveptr) noexce
|
|||
}
|
||||
|
||||
static ZT_INLINE unsigned int strToUInt(const char* s) noexcept
|
||||
{ return (unsigned int)strtoul(s, nullptr, 10); }
|
||||
{
|
||||
return (unsigned int)strtoul(s, nullptr, 10);
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned long long hexStrToU64(const char* s) noexcept
|
||||
{
|
||||
|
@ -261,21 +256,28 @@ static ZT_INLINE unsigned long long hexStrToU64(const char *s) noexcept
|
|||
#ifdef __GNUC__
|
||||
|
||||
static ZT_INLINE unsigned int countBits(const uint8_t v) noexcept
|
||||
{ return (unsigned int)__builtin_popcount((unsigned int)v); }
|
||||
{
|
||||
return (unsigned int)__builtin_popcount((unsigned int)v);
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned int countBits(const uint16_t v) noexcept
|
||||
{ return (unsigned int)__builtin_popcount((unsigned int)v); }
|
||||
{
|
||||
return (unsigned int)__builtin_popcount((unsigned int)v);
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned int countBits(const uint32_t v) noexcept
|
||||
{ return (unsigned int)__builtin_popcountl((unsigned long)v); }
|
||||
{
|
||||
return (unsigned int)__builtin_popcountl((unsigned long)v);
|
||||
}
|
||||
|
||||
static ZT_INLINE unsigned int countBits(const uint64_t v) noexcept
|
||||
{ return (unsigned int)__builtin_popcountll((unsigned long long)v); }
|
||||
{
|
||||
return (unsigned int)__builtin_popcountll((unsigned long long)v);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<typename T>
|
||||
static ZT_INLINE unsigned int countBits(T v) noexcept
|
||||
template <typename T> static ZT_INLINE unsigned int countBits(T v) noexcept
|
||||
{
|
||||
v = v - ((v >> 1) & (T) ~(T)0 / 3);
|
||||
v = (v & (T) ~(T)0 / 15 * 3) + ((v >> 2) & (T) ~(T)0 / 15 * 3);
|
||||
|
@ -300,15 +302,9 @@ static ZT_INLINE uint64_t swapBytes(const uint64_t n) noexcept
|
|||
return (uint64_t)_byteswap_uint64((unsigned __int64)n);
|
||||
#else
|
||||
return (
|
||||
((n & 0x00000000000000ffULL) << 56) |
|
||||
((n & 0x000000000000ff00ULL) << 40) |
|
||||
((n & 0x0000000000ff0000ULL) << 24) |
|
||||
((n & 0x00000000ff000000ULL) << 8) |
|
||||
((n & 0x000000ff00000000ULL) >> 8) |
|
||||
((n & 0x0000ff0000000000ULL) >> 24) |
|
||||
((n & 0x00ff000000000000ULL) >> 40) |
|
||||
((n & 0xff00000000000000ULL) >> 56)
|
||||
);
|
||||
((n & 0x00000000000000ffULL) << 56) | ((n & 0x000000000000ff00ULL) << 40) | ((n & 0x0000000000ff0000ULL) << 24)
|
||||
| ((n & 0x00000000ff000000ULL) << 8) | ((n & 0x000000ff00000000ULL) >> 8) | ((n & 0x0000ff0000000000ULL) >> 24)
|
||||
| ((n & 0x00ff000000000000ULL) >> 40) | ((n & 0xff00000000000000ULL) >> 56));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -353,109 +349,108 @@ static ZT_INLINE uint16_t swapBytes(const uint16_t n) noexcept
|
|||
|
||||
// These are helper adapters to load and swap integer types special cased by size
|
||||
// to work with all typedef'd variants, signed/unsigned, etc.
|
||||
template< typename I, unsigned int S >
|
||||
class _swap_bytes_bysize;
|
||||
template <typename I, unsigned int S> class _swap_bytes_bysize;
|
||||
|
||||
template< typename I >
|
||||
class _swap_bytes_bysize< I, 1 >
|
||||
{
|
||||
template <typename I> class _swap_bytes_bysize<I, 1> {
|
||||
public:
|
||||
static ZT_INLINE I s(const I n) noexcept
|
||||
{ return n; }
|
||||
{
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _swap_bytes_bysize< I, 2 >
|
||||
{
|
||||
template <typename I> class _swap_bytes_bysize<I, 2> {
|
||||
public:
|
||||
static ZT_INLINE I s(const I n) noexcept
|
||||
{ return (I)swapBytes((uint16_t)n); }
|
||||
{
|
||||
return (I)swapBytes((uint16_t)n);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _swap_bytes_bysize< I, 4 >
|
||||
{
|
||||
template <typename I> class _swap_bytes_bysize<I, 4> {
|
||||
public:
|
||||
static ZT_INLINE I s(const I n) noexcept
|
||||
{ return (I)swapBytes((uint32_t)n); }
|
||||
{
|
||||
return (I)swapBytes((uint32_t)n);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _swap_bytes_bysize< I, 8 >
|
||||
{
|
||||
template <typename I> class _swap_bytes_bysize<I, 8> {
|
||||
public:
|
||||
static ZT_INLINE I s(const I n) noexcept
|
||||
{ return (I)swapBytes((uint64_t)n); }
|
||||
{
|
||||
return (I)swapBytes((uint64_t)n);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I, unsigned int S >
|
||||
class _load_be_bysize;
|
||||
template <typename I, unsigned int S> class _load_be_bysize;
|
||||
|
||||
template< typename I >
|
||||
class _load_be_bysize< I, 1 >
|
||||
{
|
||||
template <typename I> class _load_be_bysize<I, 1> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{ return p[0]; }
|
||||
{
|
||||
return p[0];
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_be_bysize< I, 2 >
|
||||
{
|
||||
template <typename I> class _load_be_bysize<I, 2> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{ return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]); }
|
||||
{
|
||||
return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_be_bysize< I, 4 >
|
||||
{
|
||||
template <typename I> class _load_be_bysize<I, 4> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{ return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]); }
|
||||
{
|
||||
return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_be_bysize< I, 8 >
|
||||
{
|
||||
template <typename I> class _load_be_bysize<I, 8> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{ return (I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]); }
|
||||
{
|
||||
return (
|
||||
I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]);
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I, unsigned int S >
|
||||
class _load_le_bysize;
|
||||
template <typename I, unsigned int S> class _load_le_bysize;
|
||||
|
||||
template< typename I >
|
||||
class _load_le_bysize< I, 1 >
|
||||
{
|
||||
template <typename I> class _load_le_bysize<I, 1> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{ return p[0]; }
|
||||
{
|
||||
return p[0];
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_le_bysize< I, 2 >
|
||||
{
|
||||
template <typename I> class _load_le_bysize<I, 2> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{ return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U)); }
|
||||
{
|
||||
return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U));
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_le_bysize< I, 4 >
|
||||
{
|
||||
template <typename I> class _load_le_bysize<I, 4> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{ return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U)); }
|
||||
{
|
||||
return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U));
|
||||
}
|
||||
};
|
||||
|
||||
template< typename I >
|
||||
class _load_le_bysize< I, 8 >
|
||||
{
|
||||
template <typename I> class _load_le_bysize<I, 8> {
|
||||
public:
|
||||
static ZT_INLINE I l(const uint8_t* const p) noexcept
|
||||
{ return (I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U); }
|
||||
{
|
||||
return (
|
||||
I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -465,8 +460,7 @@ public:
|
|||
* @param n Value to convert
|
||||
* @return Value in big-endian order
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I hton(const I n) noexcept
|
||||
template <typename I> static ZT_INLINE I hton(const I n) noexcept
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return _swap_bytes_bysize<I, sizeof(I)>::s(n);
|
||||
|
@ -482,8 +476,7 @@ static ZT_INLINE I hton(const I n) noexcept
|
|||
* @param n Value to convert
|
||||
* @return Value in host byte order
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I ntoh(const I n) noexcept
|
||||
template <typename I> static ZT_INLINE I ntoh(const I n) noexcept
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return _swap_bytes_bysize<I, sizeof(I)>::s(n);
|
||||
|
@ -499,8 +492,7 @@ static ZT_INLINE I ntoh(const I n) noexcept
|
|||
* @param p Byte stream, must be at least sizeof(I) in size
|
||||
* @return Loaded raw integer
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I loadMachineEndian(const void *const restrict p) noexcept
|
||||
template <typename I> static ZT_INLINE I loadMachineEndian(const void* const restrict p) noexcept
|
||||
{
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
I tmp;
|
||||
|
@ -519,8 +511,7 @@ static ZT_INLINE I loadMachineEndian(const void *const restrict p) noexcept
|
|||
* @param p Byte array (must be at least sizeof(I))
|
||||
* @param i Integer to store
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE void storeMachineEndian(void *const restrict p, const I i) noexcept
|
||||
template <typename I> static ZT_INLINE void storeMachineEndian(void* const restrict p, const I i) noexcept
|
||||
{
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
for (unsigned int k = 0; k < sizeof(I); ++k)
|
||||
|
@ -537,8 +528,7 @@ static ZT_INLINE void storeMachineEndian(void *const restrict p, const I i) noex
|
|||
* @param p Byte stream, must be at least sizeof(I) in size
|
||||
* @return Decoded integer
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I loadBigEndian(const void *const restrict p) noexcept
|
||||
template <typename I> static ZT_INLINE I loadBigEndian(const void* const restrict p) noexcept
|
||||
{
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
return _load_be_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
|
||||
|
@ -554,8 +544,7 @@ static ZT_INLINE I loadBigEndian(const void *const restrict p) noexcept
|
|||
* @param p Byte stream to write (must be at least sizeof(I))
|
||||
* #param i Integer to write
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE void storeBigEndian(void *const restrict p, I i) noexcept
|
||||
template <typename I> static ZT_INLINE void storeBigEndian(void* const restrict p, I i) noexcept
|
||||
{
|
||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||
storeMachineEndian(p, hton(i));
|
||||
|
@ -571,8 +560,7 @@ static ZT_INLINE void storeBigEndian(void *const restrict p, I i) noexcept
|
|||
* @param p Byte stream, must be at least sizeof(I) in size
|
||||
* @return Decoded integer
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE I loadLittleEndian(const void *const restrict p) noexcept
|
||||
template <typename I> static ZT_INLINE I loadLittleEndian(const void* const restrict p) noexcept
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
|
||||
return _load_le_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
|
||||
|
@ -588,8 +576,7 @@ static ZT_INLINE I loadLittleEndian(const void *const restrict p) noexcept
|
|||
* @param p Byte stream to write (must be at least sizeof(I))
|
||||
* #param i Integer to write
|
||||
*/
|
||||
template< typename I >
|
||||
static ZT_INLINE void storeLittleEndian(void *const restrict p, const I i) noexcept
|
||||
template <typename I> static ZT_INLINE void storeLittleEndian(void* const restrict p, const I i) noexcept
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
storeMachineEndian(p, _swap_bytes_bysize<I, sizeof(I)>::s(i));
|
||||
|
@ -609,8 +596,7 @@ static ZT_INLINE void storeLittleEndian(void *const restrict p, const I i) noexc
|
|||
* @param dest Destination memory
|
||||
* @param src Source memory
|
||||
*/
|
||||
template< unsigned long L >
|
||||
static ZT_INLINE void copy(void *dest, const void *src) noexcept
|
||||
template <unsigned long L> static ZT_INLINE void copy(void* dest, const void* src) noexcept
|
||||
{
|
||||
#if defined(ZT_ARCH_X64) && defined(__GNUC__)
|
||||
uintptr_t l = L;
|
||||
|
@ -642,8 +628,7 @@ static ZT_INLINE void copy(void *dest, const void *src, unsigned long len) noexc
|
|||
* @tparam L Size in bytes
|
||||
* @param dest Memory to zero
|
||||
*/
|
||||
template< unsigned long L >
|
||||
static ZT_INLINE void zero(void *dest) noexcept
|
||||
template <unsigned long L> static ZT_INLINE void zero(void* dest) noexcept
|
||||
{
|
||||
#if defined(ZT_ARCH_X64) && defined(__GNUC__)
|
||||
uintptr_t l = L;
|
||||
|
|
509
core/VL1.cpp
509
core/VL1.cpp
|
@ -12,37 +12,39 @@
|
|||
/****/
|
||||
|
||||
#include "VL1.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "VL2.hpp"
|
||||
|
||||
#include "AES.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "Context.hpp"
|
||||
#include "Expect.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "LZ4.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Poly1305.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Expect.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "VL2.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
namespace {
|
||||
|
||||
ZT_INLINE const Identity& identityFromPeerPtr(const SharedPtr<Peer>& p)
|
||||
{ return (p) ? p->identity() : Identity::NIL; }
|
||||
|
||||
struct p_SalsaPolyCopyFunction
|
||||
{
|
||||
return (p) ? p->identity() : Identity::NIL;
|
||||
}
|
||||
|
||||
struct p_SalsaPolyCopyFunction {
|
||||
Salsa20 s20;
|
||||
Poly1305 poly1305;
|
||||
unsigned int hdrRemaining;
|
||||
|
||||
ZT_INLINE p_SalsaPolyCopyFunction(const void *salsaKey, const void *salsaIv) :
|
||||
s20(salsaKey, salsaIv),
|
||||
poly1305(),
|
||||
hdrRemaining(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START)
|
||||
ZT_INLINE p_SalsaPolyCopyFunction(const void* salsaKey, const void* salsaIv)
|
||||
: s20(salsaKey, salsaIv)
|
||||
, poly1305()
|
||||
, hdrRemaining(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START)
|
||||
{
|
||||
uint8_t macKey[ZT_POLY1305_KEY_SIZE];
|
||||
s20.crypt12(Utils::ZERO256, macKey, ZT_POLY1305_KEY_SIZE);
|
||||
|
@ -64,14 +66,13 @@ struct p_SalsaPolyCopyFunction
|
|||
}
|
||||
};
|
||||
|
||||
struct p_PolyCopyFunction
|
||||
{
|
||||
struct p_PolyCopyFunction {
|
||||
Poly1305 poly1305;
|
||||
unsigned int hdrRemaining;
|
||||
|
||||
ZT_INLINE p_PolyCopyFunction(const void *salsaKey, const void *salsaIv) :
|
||||
poly1305(),
|
||||
hdrRemaining(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START)
|
||||
ZT_INLINE p_PolyCopyFunction(const void* salsaKey, const void* salsaIv)
|
||||
: poly1305()
|
||||
, hdrRemaining(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START)
|
||||
{
|
||||
uint8_t macKey[ZT_POLY1305_KEY_SIZE];
|
||||
Salsa20(salsaKey, salsaIv).crypt12(Utils::ZERO256, macKey, ZT_POLY1305_KEY_SIZE);
|
||||
|
@ -95,11 +96,16 @@ struct p_PolyCopyFunction
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
VL1::VL1(const Context &ctx) :
|
||||
m_ctx(ctx)
|
||||
{}
|
||||
VL1::VL1(const Context& ctx) : m_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, const unsigned int len) noexcept
|
||||
void VL1::onRemotePacket(
|
||||
CallContext& cc,
|
||||
const int64_t localSocket,
|
||||
const InetAddress& fromAddr,
|
||||
SharedPtr<Buf>& data,
|
||||
const unsigned int len) noexcept
|
||||
{
|
||||
const SharedPtr<Path> path(m_ctx.topology->path(localSocket, fromAddr));
|
||||
|
||||
|
@ -117,7 +123,9 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
static_assert((ZT_PROTO_PACKET_ID_INDEX + sizeof(uint64_t)) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow");
|
||||
const uint64_t packetId = Utils::loadMachineEndian<uint64_t>(data->unsafeData + ZT_PROTO_PACKET_ID_INDEX);
|
||||
|
||||
static_assert((ZT_PROTO_PACKET_DESTINATION_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow");
|
||||
static_assert(
|
||||
(ZT_PROTO_PACKET_DESTINATION_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_FRAGMENT_LENGTH,
|
||||
"overflow");
|
||||
const Address destination(data->unsafeData + ZT_PROTO_PACKET_DESTINATION_INDEX);
|
||||
if (destination != m_ctx.identity.address()) {
|
||||
m_relay(cc, path, destination, data, len);
|
||||
|
@ -156,7 +164,8 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
// case Defragmenter<ZT_MAX_PACKET_FRAGMENTS>::ERR_OUT_OF_MEMORY:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (unlikely(len < ZT_PROTO_MIN_PACKET_LENGTH))
|
||||
return;
|
||||
static_assert(ZT_PROTO_PACKET_FLAGS_INDEX < ZT_PROTO_MIN_PACKET_LENGTH, "overflow");
|
||||
|
@ -182,7 +191,8 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
// case Defragmenter<ZT_MAX_PACKET_FRAGMENTS>::ERR_OUT_OF_MEMORY:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// This is a single whole packet with no fragments.
|
||||
Buf::Slice s = pktv.push();
|
||||
s.b.swap(data);
|
||||
|
@ -206,16 +216,31 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
int pktSize = 0;
|
||||
|
||||
static_assert(ZT_PROTO_PACKET_VERB_INDEX < ZT_PROTO_MIN_PACKET_LENGTH, "overflow");
|
||||
if (unlikely(((cipher == ZT_PROTO_CIPHER_POLY1305_NONE) || (cipher == ZT_PROTO_CIPHER_NONE)) && ((hdr[ZT_PROTO_PACKET_VERB_INDEX] & ZT_PROTO_VERB_MASK) == Protocol::VERB_HELLO))) {
|
||||
if (unlikely(
|
||||
((cipher == ZT_PROTO_CIPHER_POLY1305_NONE) || (cipher == ZT_PROTO_CIPHER_NONE))
|
||||
&& ((hdr[ZT_PROTO_PACKET_VERB_INDEX] & ZT_PROTO_VERB_MASK) == Protocol::VERB_HELLO))) {
|
||||
// Handle unencrypted HELLO packets.
|
||||
pktSize = pktv.mergeCopy(*pkt);
|
||||
if (unlikely(pktSize < ZT_PROTO_MIN_PACKET_LENGTH)) {
|
||||
ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize);
|
||||
ZT_SPEW(
|
||||
"discarding packet %.16llx from %s(%s): assembled packet size: %d",
|
||||
packetId,
|
||||
source.toString().c_str(),
|
||||
fromAddr.toString().c_str(),
|
||||
pktSize);
|
||||
return;
|
||||
}
|
||||
const SharedPtr<Peer> peer(m_HELLO(cc, path, *pkt, pktSize));
|
||||
if (likely(peer))
|
||||
peer->received(m_ctx, cc, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, Protocol::VERB_HELLO, Protocol::VERB_NOP);
|
||||
peer->received(
|
||||
m_ctx,
|
||||
cc,
|
||||
path,
|
||||
hops,
|
||||
packetId,
|
||||
pktSize - ZT_PROTO_PACKET_PAYLOAD_START,
|
||||
Protocol::VERB_HELLO,
|
||||
Protocol::VERB_NOP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -227,7 +252,6 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
SharedPtr<Peer> peer(m_ctx.topology->peer(cc, source));
|
||||
if (likely(peer)) {
|
||||
switch (cipher) {
|
||||
|
||||
case ZT_PROTO_CIPHER_POLY1305_NONE: {
|
||||
uint8_t perPacketKey[ZT_SALSA20_KEY_SIZE];
|
||||
Protocol::salsa2012DeriveKey(peer->rawIdentityKey(), perPacketKey, *pktv[0].b, pktv.totalSize());
|
||||
|
@ -235,7 +259,12 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
|
||||
pktSize = pktv.mergeMap<p_PolyCopyFunction&>(*pkt, ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, s20cf);
|
||||
if (unlikely(pktSize < ZT_PROTO_MIN_PACKET_LENGTH)) {
|
||||
ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize);
|
||||
ZT_SPEW(
|
||||
"discarding packet %.16llx from %s(%s): assembled packet size: %d",
|
||||
packetId,
|
||||
source.toString().c_str(),
|
||||
fromAddr.toString().c_str(),
|
||||
pktSize);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -243,23 +272,41 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
s20cf.poly1305.finish(mac);
|
||||
static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow");
|
||||
if (unlikely(Utils::loadMachineEndian<uint64_t>(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) {
|
||||
ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (none/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str());
|
||||
m_ctx.t->incomingPacketDropped(cc, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
ZT_SPEW(
|
||||
"discarding packet %.16llx from %s(%s): packet MAC failed (none/poly1305)",
|
||||
packetId,
|
||||
source.toString().c_str(),
|
||||
fromAddr.toString().c_str());
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0xcc89c812,
|
||||
packetId,
|
||||
0,
|
||||
peer->identity(),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_NOP,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
auth = ZT_VL1_AUTH_RESULT_FLAG_AUTHENTICATED;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ZT_PROTO_CIPHER_POLY1305_SALSA2012: {
|
||||
uint8_t perPacketKey[ZT_SALSA20_KEY_SIZE];
|
||||
Protocol::salsa2012DeriveKey(peer->rawIdentityKey(), perPacketKey, *pktv[0].b, pktv.totalSize());
|
||||
p_SalsaPolyCopyFunction s20cf(perPacketKey, &packetId);
|
||||
|
||||
pktSize = pktv.mergeMap< p_SalsaPolyCopyFunction & >(*pkt, ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, s20cf);
|
||||
pktSize =
|
||||
pktv.mergeMap<p_SalsaPolyCopyFunction&>(*pkt, ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, s20cf);
|
||||
if (unlikely(pktSize < ZT_PROTO_MIN_PACKET_LENGTH)) {
|
||||
ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize);
|
||||
ZT_SPEW(
|
||||
"discarding packet %.16llx from %s(%s): assembled packet size: %d",
|
||||
packetId,
|
||||
source.toString().c_str(),
|
||||
fromAddr.toString().c_str(),
|
||||
pktSize);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -267,27 +314,46 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
s20cf.poly1305.finish(mac);
|
||||
static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow");
|
||||
if (unlikely(Utils::loadMachineEndian<uint64_t>(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) {
|
||||
ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (salsa/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str());
|
||||
m_ctx.t->incomingPacketDropped(cc, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
ZT_SPEW(
|
||||
"discarding packet %.16llx from %s(%s): packet MAC failed (salsa/poly1305)",
|
||||
packetId,
|
||||
source.toString().c_str(),
|
||||
fromAddr.toString().c_str());
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0xcc89c812,
|
||||
packetId,
|
||||
0,
|
||||
peer->identity(),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_NOP,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
auth = ZT_VL1_AUTH_RESULT_FLAG_AUTHENTICATED | ZT_VL1_AUTH_RESULT_FLAG_ENCRYPTED;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ZT_PROTO_CIPHER_NONE: {
|
||||
// TODO
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ZT_PROTO_CIPHER_AES_GMAC_SIV: {
|
||||
// TODO
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
default:
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x5b001099, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x5b001099,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_NOP,
|
||||
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -296,13 +362,23 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
// If authentication was successful go on and process the packet.
|
||||
|
||||
if (unlikely(pktSize < ZT_PROTO_MIN_PACKET_LENGTH)) {
|
||||
ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size %d is smaller than minimum packet length", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize);
|
||||
ZT_SPEW(
|
||||
"discarding packet %.16llx from %s(%s): assembled packet size %d is smaller than minimum packet "
|
||||
"length",
|
||||
packetId,
|
||||
source.toString().c_str(),
|
||||
fromAddr.toString().c_str(),
|
||||
pktSize);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: should take instance ID into account here once that is fully implemented.
|
||||
if (unlikely(peer->deduplicateIncomingPacket(packetId))) {
|
||||
ZT_SPEW("discarding packet %.16llx from %s(%s): duplicate!", packetId, source.toString().c_str(), fromAddr.toString().c_str());
|
||||
ZT_SPEW(
|
||||
"discarding packet %.16llx from %s(%s): duplicate!",
|
||||
packetId,
|
||||
source.toString().c_str(),
|
||||
fromAddr.toString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -321,17 +397,34 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
reinterpret_cast<char*>(dec->unsafeData + ZT_PROTO_PACKET_PAYLOAD_START),
|
||||
pktSize - ZT_PROTO_PACKET_PAYLOAD_START,
|
||||
ZT_BUF_MEM_SIZE - ZT_PROTO_PACKET_PAYLOAD_START);
|
||||
if (likely((uncompressedLen >= 0) && (uncompressedLen <= (ZT_BUF_MEM_SIZE - ZT_PROTO_PACKET_PAYLOAD_START)))) {
|
||||
if (likely(
|
||||
(uncompressedLen >= 0)
|
||||
&& (uncompressedLen <= (ZT_BUF_MEM_SIZE - ZT_PROTO_PACKET_PAYLOAD_START)))) {
|
||||
pkt.swap(dec);
|
||||
ZT_SPEW("decompressed packet: %d -> %d", pktSize, ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen);
|
||||
pktSize = ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen;
|
||||
} else {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0xee9e4392, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA);
|
||||
}
|
||||
else {
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0xee9e4392,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
verb,
|
||||
ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_SPEW("%s from %s(%s) (%d bytes)", Protocol::verbName(verb), source.toString().c_str(), fromAddr.toString().c_str(), pktSize);
|
||||
ZT_SPEW(
|
||||
"%s from %s(%s) (%d bytes)",
|
||||
Protocol::verbName(verb),
|
||||
source.toString().c_str(),
|
||||
fromAddr.toString().c_str(),
|
||||
pktSize);
|
||||
|
||||
// NOTE: HELLO is normally sent in the clear (in terms of our usual AEAD modes) and is handled
|
||||
// above. We will try to process it here, but if so it'll still get re-authenticated via HELLO's
|
||||
|
@ -399,12 +492,30 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
break;
|
||||
|
||||
default:
|
||||
m_ctx.t->incomingPacketDropped(cc, 0xeeeeeff0, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0xeeeeeff0,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
verb,
|
||||
ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB);
|
||||
break;
|
||||
}
|
||||
if (likely(ok))
|
||||
peer->received(m_ctx, cc, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, verb, inReVerb);
|
||||
} else {
|
||||
peer->received(
|
||||
m_ctx,
|
||||
cc,
|
||||
path,
|
||||
hops,
|
||||
packetId,
|
||||
pktSize - ZT_PROTO_PACKET_PAYLOAD_START,
|
||||
verb,
|
||||
inReVerb);
|
||||
}
|
||||
else {
|
||||
// If decryption and authentication were not successful, try to look up identities.
|
||||
// This is rate limited by virtue of the retry rate limit timer.
|
||||
if (pktSize <= 0)
|
||||
|
@ -424,8 +535,13 @@ void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetA
|
|||
m_sendPendingWhois(cc);
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
m_ctx.t->unexpectedError(cc, 0xea1b6dea, "unexpected exception in onRemotePacket() parsing packet from %s", path->address().toString().c_str());
|
||||
}
|
||||
catch (...) {
|
||||
m_ctx.t->unexpectedError(
|
||||
cc,
|
||||
0xea1b6dea,
|
||||
"unexpected exception in onRemotePacket() parsing packet from %s",
|
||||
path->address().toString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,7 +576,8 @@ void VL1::m_sendPendingWhois(CallContext &cc)
|
|||
Vector<Address>::iterator a(toSend.begin());
|
||||
while (a != toSend.end()) {
|
||||
const uint64_t packetId = key.nextMessage(m_ctx.identity.address(), root->address());
|
||||
int p = Protocol::newPacket(outp, packetId, root->address(), m_ctx.identity.address(), Protocol::VERB_WHOIS);
|
||||
int p =
|
||||
Protocol::newPacket(outp, packetId, root->address(), m_ctx.identity.address(), Protocol::VERB_WHOIS);
|
||||
while ((a != toSend.end()) && (p < (sizeof(outp) - ZT_ADDRESS_LENGTH))) {
|
||||
a->copyTo(outp + p);
|
||||
++a;
|
||||
|
@ -480,7 +597,16 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
|
||||
const uint8_t protoVersion = pkt.lI8<ZT_PROTO_PACKET_PAYLOAD_START>();
|
||||
if (unlikely(protoVersion < ZT_PROTO_VERSION_MIN)) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x907a9891, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x907a9891,
|
||||
packetId,
|
||||
0,
|
||||
Identity::NIL,
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
const unsigned int versionMajor = pkt.lI8<ZT_PROTO_PACKET_PAYLOAD_START + 1>();
|
||||
|
@ -493,11 +619,29 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
// Get identity and verify that it matches the sending address in the packet.
|
||||
Identity id;
|
||||
if (unlikely(pkt.rO(ii, id) < 0)) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9810, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9810,
|
||||
packetId,
|
||||
0,
|
||||
Identity::NIL,
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
if (unlikely(id.address() != Address(pkt.unsafeData + ZT_PROTO_PACKET_SOURCE_INDEX))) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9010, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9010,
|
||||
packetId,
|
||||
0,
|
||||
Identity::NIL,
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
|
||||
|
@ -505,21 +649,53 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
SharedPtr<Peer> peer(m_ctx.topology->peer(cc, id.address(), true));
|
||||
if (peer) {
|
||||
if (unlikely(peer->identity() != id)) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9891,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
if (unlikely(peer->deduplicateIncomingPacket(packetId))) {
|
||||
ZT_SPEW("discarding packet %.16llx from %s(%s): duplicate!", packetId, id.address().toString().c_str(), path->address().toString().c_str());
|
||||
ZT_SPEW(
|
||||
"discarding packet %.16llx from %s(%s): duplicate!",
|
||||
packetId,
|
||||
id.address().toString().c_str(),
|
||||
path->address().toString().c_str());
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (unlikely(! id.locallyValidate())) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9892, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9892,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
peer.set(new Peer());
|
||||
if (unlikely(! peer->init(m_ctx, cc, id))) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9893, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9893,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
peer = m_ctx.topology->add(cc, peer);
|
||||
|
@ -535,7 +711,16 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
// field is ignored, and eventually it'll be undefined.
|
||||
uint8_t hmac[ZT_HMACSHA384_LEN];
|
||||
if (unlikely(packetSize < ZT_HMACSHA384_LEN)) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0xab9c9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0xab9c9891,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
packetSize -= ZT_HMACSHA384_LEN;
|
||||
|
@ -543,10 +728,20 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
Utils::storeMachineEndian<uint64_t>(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, 0); // set MAC field to 0
|
||||
HMACSHA384(peer->identityHelloHmacKey(), pkt.unsafeData, packetSize, hmac);
|
||||
if (unlikely(! Utils::secureEq(hmac, pkt.unsafeData + packetSize, ZT_HMACSHA384_LEN))) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9891,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// Older versions use Poly1305 MAC (but no whole packet encryption) for HELLO.
|
||||
if (likely(packetSize > ZT_PROTO_PACKET_ENCRYPTED_SECTION_START)) {
|
||||
uint8_t perPacketKey[ZT_SALSA20_KEY_SIZE];
|
||||
|
@ -554,15 +749,36 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
uint8_t macKey[ZT_POLY1305_KEY_SIZE];
|
||||
Salsa20(perPacketKey, &packetId).crypt12(Utils::ZERO256, macKey, ZT_POLY1305_KEY_SIZE);
|
||||
Poly1305 poly1305(macKey);
|
||||
poly1305.update(pkt.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START);
|
||||
poly1305.update(
|
||||
pkt.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,
|
||||
packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START);
|
||||
uint64_t polyMac[2];
|
||||
poly1305.finish(polyMac);
|
||||
if (unlikely(mac != polyMac[0])) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x11bfff82, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x11bfff82,
|
||||
packetId,
|
||||
0,
|
||||
id,
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_NOP,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
} else {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x11bfff81, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
}
|
||||
else {
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x11bfff81,
|
||||
packetId,
|
||||
0,
|
||||
id,
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_NOP,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
}
|
||||
|
@ -573,7 +789,16 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
|
||||
InetAddress sentTo;
|
||||
if (unlikely(pkt.rO(ii, sentTo) < 0)) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9811, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9811,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
|
||||
|
@ -593,12 +818,30 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
ii += 2; // skip reserved field
|
||||
const unsigned int dictSize = pkt.rI16(ii);
|
||||
if (unlikely((ii + dictSize) > packetSize)) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9815, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9815,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
return peer;
|
||||
}
|
||||
Dictionary md;
|
||||
if (! md.decode(pkt.unsafeData + ii, dictSize)) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x707a9816, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x707a9816,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
hops,
|
||||
Protocol::VERB_HELLO,
|
||||
ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
|
||||
return peer;
|
||||
}
|
||||
|
||||
|
@ -608,7 +851,12 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
}
|
||||
}
|
||||
|
||||
Protocol::newPacket(pkt, key.nextMessage(m_ctx.identity.address(), peer->address()), peer->address(), m_ctx.identity.address(), Protocol::VERB_OK);
|
||||
Protocol::newPacket(
|
||||
pkt,
|
||||
key.nextMessage(m_ctx.identity.address(), peer->address()),
|
||||
peer->address(),
|
||||
m_ctx.identity.address(),
|
||||
Protocol::VERB_OK);
|
||||
ii = ZT_PROTO_PACKET_PAYLOAD_START;
|
||||
pkt.wI8(ii, Protocol::VERB_HELLO);
|
||||
pkt.wI64(ii, packetId);
|
||||
|
@ -637,7 +885,15 @@ SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, B
|
|||
return peer;
|
||||
}
|
||||
|
||||
bool VL1::m_ERROR(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb)
|
||||
bool VL1::m_ERROR(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize,
|
||||
Protocol::Verb& inReVerb)
|
||||
{
|
||||
#if 0
|
||||
if (packetSize < (int)sizeof(Protocol::ERROR::Header)) {
|
||||
|
@ -684,26 +940,56 @@ bool VL1::m_ERROR(CallContext &cc, const uint64_t packetId, const unsigned int a
|
|||
#endif
|
||||
}
|
||||
|
||||
bool VL1::m_OK(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb)
|
||||
bool VL1::m_OK(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize,
|
||||
Protocol::Verb& inReVerb)
|
||||
{
|
||||
int ii = ZT_PROTO_PACKET_PAYLOAD_START + 13;
|
||||
|
||||
inReVerb = (Protocol::Verb)pkt.rI8(ii);
|
||||
const uint64_t inRePacketId = pkt.rI64(ii);
|
||||
if (unlikely(Buf::readOverflow(ii, packetSize))) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x4c1f1ff7, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x4c1f1ff7,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
0,
|
||||
Protocol::VERB_OK,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely(! m_ctx.expect->expecting(inRePacketId, cc.ticks))) {
|
||||
m_ctx.t->incomingPacketDropped(cc, 0x4c1f1ff8, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED);
|
||||
m_ctx.t->incomingPacketDropped(
|
||||
cc,
|
||||
0x4c1f1ff8,
|
||||
packetId,
|
||||
0,
|
||||
identityFromPeerPtr(peer),
|
||||
path->address(),
|
||||
0,
|
||||
Protocol::VERB_OK,
|
||||
ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED);
|
||||
return false;
|
||||
}
|
||||
|
||||
ZT_SPEW("got OK in-re %s (packet ID %.16llx) from %s(%s)", Protocol::verbName(inReVerb), inRePacketId, peer->address().toString().c_str(), path->address().toString().c_str());
|
||||
ZT_SPEW(
|
||||
"got OK in-re %s (packet ID %.16llx) from %s(%s)",
|
||||
Protocol::verbName(inReVerb),
|
||||
inRePacketId,
|
||||
peer->address().toString().c_str(),
|
||||
path->address().toString().c_str());
|
||||
|
||||
switch (inReVerb) {
|
||||
|
||||
case Protocol::VERB_HELLO:
|
||||
break;
|
||||
|
||||
|
@ -715,13 +1001,19 @@ bool VL1::m_OK(CallContext &cc, const uint64_t packetId, const unsigned int auth
|
|||
|
||||
case Protocol::VERB_MULTICAST_GATHER:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VL1::m_WHOIS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL1::m_WHOIS(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
#if 0
|
||||
if (packetSize < (int)sizeof(Protocol::OK::Header)) {
|
||||
|
@ -775,7 +1067,14 @@ bool VL1::m_WHOIS(CallContext &cc, const uint64_t packetId, const unsigned int a
|
|||
#endif
|
||||
}
|
||||
|
||||
bool VL1::m_RENDEZVOUS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL1::m_RENDEZVOUS(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
#if 0
|
||||
if (RR->topology->isRoot(peer->identity())) {
|
||||
|
@ -823,7 +1122,14 @@ bool VL1::m_RENDEZVOUS(CallContext &cc, const uint64_t packetId, const unsigned
|
|||
#endif
|
||||
}
|
||||
|
||||
bool VL1::m_ECHO(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL1::m_ECHO(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
#if 0
|
||||
const uint64_t packetId = Protocol::packetId(pkt,packetSize);
|
||||
|
@ -861,7 +1167,14 @@ bool VL1::m_ECHO(CallContext &cc, const uint64_t packetId, const unsigned int au
|
|||
#endif
|
||||
}
|
||||
|
||||
bool VL1::m_PUSH_DIRECT_PATHS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL1::m_PUSH_DIRECT_PATHS(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
#if 0
|
||||
if (packetSize < (int)sizeof(Protocol::PUSH_DIRECT_PATHS)) {
|
||||
|
@ -952,13 +1265,27 @@ bool VL1::m_PUSH_DIRECT_PATHS(CallContext &cc, const uint64_t packetId, const un
|
|||
#endif
|
||||
}
|
||||
|
||||
bool VL1::m_USER_MESSAGE(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL1::m_USER_MESSAGE(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VL1::m_ENCAP(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL1::m_ENCAP(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
// TODO: not implemented yet
|
||||
return true;
|
||||
|
|
104
core/VL1.hpp
104
core/VL1.hpp
|
@ -14,15 +14,15 @@
|
|||
#ifndef ZT_VL1_HPP
|
||||
#define ZT_VL1_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Defragmenter.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Defragmenter.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Protocol.hpp"
|
||||
|
||||
#define ZT_VL1_MAX_WHOIS_WAITING_PACKETS 32
|
||||
|
||||
|
@ -43,8 +43,7 @@ class VL2;
|
|||
*
|
||||
* This class is thread safe.
|
||||
*/
|
||||
class VL1
|
||||
{
|
||||
class VL1 {
|
||||
public:
|
||||
explicit VL1(const Context& ctx);
|
||||
|
||||
|
@ -62,20 +61,83 @@ public:
|
|||
* @param data Packet data
|
||||
* @param len Packet length
|
||||
*/
|
||||
void onRemotePacket(CallContext &cc, int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, unsigned int len) noexcept;
|
||||
void onRemotePacket(
|
||||
CallContext& cc,
|
||||
int64_t localSocket,
|
||||
const InetAddress& fromAddr,
|
||||
SharedPtr<Buf>& data,
|
||||
unsigned int len) noexcept;
|
||||
|
||||
private:
|
||||
void m_relay(CallContext& cc, const SharedPtr<Path>& path, Address destination, SharedPtr<Buf>& pkt, int pktSize);
|
||||
void m_sendPendingWhois(CallContext& cc);
|
||||
SharedPtr<Peer> m_HELLO(CallContext& cc, const SharedPtr<Path>& path, Buf& pkt, int packetSize);
|
||||
bool m_ERROR(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb);
|
||||
bool m_OK(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb);
|
||||
bool m_WHOIS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_RENDEZVOUS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_ECHO(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_PUSH_DIRECT_PATHS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_USER_MESSAGE(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_ENCAP(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_ERROR(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize,
|
||||
Protocol::Verb& inReVerb);
|
||||
bool m_OK(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize,
|
||||
Protocol::Verb& inReVerb);
|
||||
bool m_WHOIS(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_RENDEZVOUS(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_ECHO(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_PUSH_DIRECT_PATHS(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_USER_MESSAGE(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_ENCAP(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
const SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
|
||||
const Context& m_ctx;
|
||||
|
||||
|
@ -83,10 +145,10 @@ private:
|
|||
Defragmenter<ZT_MAX_PACKET_FRAGMENTS> m_inputPacketAssembler;
|
||||
|
||||
// Queue of outbound WHOIS reqeusts and packets waiting on them.
|
||||
struct p_WhoisQueueItem
|
||||
{
|
||||
struct p_WhoisQueueItem {
|
||||
ZT_INLINE p_WhoisQueueItem() : lastRetry(0), retries(0), waitingPacketCount(0)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
int64_t lastRetry;
|
||||
unsigned int retries;
|
||||
|
|
105
core/VL2.cpp
105
core/VL2.cpp
|
@ -12,58 +12,129 @@
|
|||
/****/
|
||||
|
||||
#include "VL2.hpp"
|
||||
|
||||
#include "Context.hpp"
|
||||
#include "VL1.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "MAC.hpp"
|
||||
#include "Network.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "Peer.hpp"
|
||||
#include "Topology.hpp"
|
||||
#include "VL1.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
VL2::VL2(const Context &ctx):
|
||||
m_ctx(ctx)
|
||||
VL2::VL2(const Context& ctx) : m_ctx(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
void VL2::onLocalEthernet(CallContext &cc, const SharedPtr< Network > &network, const MAC &from, const MAC &to, const unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len)
|
||||
void VL2::onLocalEthernet(
|
||||
CallContext& cc,
|
||||
const SharedPtr<Network>& network,
|
||||
const MAC& from,
|
||||
const MAC& to,
|
||||
const unsigned int etherType,
|
||||
unsigned int vlanId,
|
||||
SharedPtr<Buf>& data,
|
||||
unsigned int len)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_FRAME(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_FRAME(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_EXT_FRAME(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_EXT_FRAME(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_MULTICAST_LIKE(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_MULTICAST_LIKE(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_NETWORK_CREDENTIALS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_NETWORK_CREDENTIALS(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_NETWORK_CONFIG_REQUEST(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_NETWORK_CONFIG_REQUEST(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_NETWORK_CONFIG(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_NETWORK_CONFIG(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_MULTICAST_GATHER(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_MULTICAST_GATHER(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_MULTICAST_FRAME_deprecated(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_MULTICAST_FRAME_deprecated(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
bool VL2::m_MULTICAST(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize)
|
||||
bool VL2::m_MULTICAST(
|
||||
CallContext& cc,
|
||||
const uint64_t packetId,
|
||||
const unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
106
core/VL2.hpp
106
core/VL2.hpp
|
@ -14,14 +14,14 @@
|
|||
#ifndef ZT_VL2_HPP
|
||||
#define ZT_VL2_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "CallContext.hpp"
|
||||
#include "Constants.hpp"
|
||||
#include "Containers.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Protocol.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -32,8 +32,7 @@ class VL1;
|
|||
class Network;
|
||||
class MAC;
|
||||
|
||||
class VL2
|
||||
{
|
||||
class VL2 {
|
||||
friend class VL1;
|
||||
|
||||
public:
|
||||
|
@ -50,18 +49,89 @@ public:
|
|||
* @param data Ethernet payload
|
||||
* @param len Frame length
|
||||
*/
|
||||
void onLocalEthernet(CallContext &cc, const SharedPtr< Network > &network, const MAC &from, const MAC &to, unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len);
|
||||
void onLocalEthernet(
|
||||
CallContext& cc,
|
||||
const SharedPtr<Network>& network,
|
||||
const MAC& from,
|
||||
const MAC& to,
|
||||
unsigned int etherType,
|
||||
unsigned int vlanId,
|
||||
SharedPtr<Buf>& data,
|
||||
unsigned int len);
|
||||
|
||||
protected:
|
||||
bool m_FRAME(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_EXT_FRAME(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_MULTICAST_LIKE(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_NETWORK_CREDENTIALS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_NETWORK_CONFIG_REQUEST(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_NETWORK_CONFIG(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_MULTICAST_GATHER(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_MULTICAST_FRAME_deprecated(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_MULTICAST(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize);
|
||||
bool m_FRAME(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_EXT_FRAME(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_MULTICAST_LIKE(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_NETWORK_CREDENTIALS(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_NETWORK_CONFIG_REQUEST(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_NETWORK_CONFIG(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_MULTICAST_GATHER(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_MULTICAST_FRAME_deprecated(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
bool m_MULTICAST(
|
||||
CallContext& cc,
|
||||
uint64_t packetId,
|
||||
unsigned int auth,
|
||||
const SharedPtr<Path>& path,
|
||||
SharedPtr<Peer>& peer,
|
||||
Buf& pkt,
|
||||
int packetSize);
|
||||
|
||||
private:
|
||||
const Context& m_ctx;
|
||||
|
|
289
core/zerotier.h
289
core/zerotier.h
|
@ -257,8 +257,7 @@ extern "C" {
|
|||
*
|
||||
* Do not change these integer values. They're protocol constants.
|
||||
*/
|
||||
enum ZT_IdentityType
|
||||
{
|
||||
enum ZT_IdentityType {
|
||||
ZT_IDENTITY_TYPE_C25519 = 0, /* C25519/Ed25519 */
|
||||
ZT_IDENTITY_TYPE_P384 = 1 /* Combined C25519/NIST-P-384 key */
|
||||
};
|
||||
|
@ -284,13 +283,14 @@ typedef void ZT_Locator;
|
|||
* is correct for the platform. If it's not correct, a platform ifdef
|
||||
* will be needed.
|
||||
*/
|
||||
typedef struct { uint64_t bits[ZT_SOCKADDR_STORAGE_SIZE / 8]; } ZT_InetAddress;
|
||||
typedef struct {
|
||||
uint64_t bits[ZT_SOCKADDR_STORAGE_SIZE / 8];
|
||||
} ZT_InetAddress;
|
||||
|
||||
/**
|
||||
* IP scope types as identified by InetAddress.
|
||||
*/
|
||||
enum ZT_InetAddress_IpScope
|
||||
{
|
||||
enum ZT_InetAddress_IpScope {
|
||||
ZT_IP_SCOPE_NONE = 0, // NULL or not an IP address
|
||||
ZT_IP_SCOPE_MULTICAST = 1, // 224.0.0.0 and other V4/V6 multicast IPs
|
||||
ZT_IP_SCOPE_LOOPBACK = 2, // 127.0.0.1, ::1, etc.
|
||||
|
@ -304,8 +304,7 @@ enum ZT_InetAddress_IpScope
|
|||
/**
|
||||
* Full identity fingerprint with address and 384-bit hash of public key(s)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Short address (only least significant 40 bits are used)
|
||||
*/
|
||||
|
@ -407,8 +406,7 @@ typedef struct
|
|||
/**
|
||||
* Errors returned by functions that verify or handle certificates.
|
||||
*/
|
||||
enum ZT_CertificateError
|
||||
{
|
||||
enum ZT_CertificateError {
|
||||
/**
|
||||
* No error (certificate is valid or operation was successful)
|
||||
*/
|
||||
|
@ -463,8 +461,7 @@ enum ZT_CertificateError
|
|||
/**
|
||||
* Public key signing algorithm for certificates
|
||||
*/
|
||||
enum ZT_CertificatePublicKeyAlgorithm
|
||||
{
|
||||
enum ZT_CertificatePublicKeyAlgorithm {
|
||||
/**
|
||||
* Nil value indicating no signature.
|
||||
*/
|
||||
|
@ -509,8 +506,7 @@ enum ZT_CertificatePublicKeyAlgorithm
|
|||
* These fields are all optional and are all taken from the
|
||||
* most common fields present in X509 certificates.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
char serialNo[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||
char commonName[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||
char country[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
|
||||
|
@ -528,8 +524,7 @@ typedef struct
|
|||
/**
|
||||
* Identity and optional locator to help find a node on physical networks.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Identity (never NULL)
|
||||
*/
|
||||
|
@ -544,8 +539,7 @@ typedef struct
|
|||
/**
|
||||
* ID and primary controller for a network
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Network ID
|
||||
*/
|
||||
|
@ -560,8 +554,7 @@ typedef struct
|
|||
/**
|
||||
* Identification certificate subject
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Timestamp of subject, can also be a revision ID for this subject's name.
|
||||
*/
|
||||
|
@ -636,8 +629,7 @@ typedef struct
|
|||
* possible, small, and secure. X509 is both bloated and a security
|
||||
* disaster as it's very hard to implement correctly.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Serial number, a SHA384 hash of this certificate (minus signature).
|
||||
*/
|
||||
|
@ -721,8 +713,7 @@ typedef struct
|
|||
/**
|
||||
* A revocation for one or more certificates.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Certificate issuing this revocation.
|
||||
*/
|
||||
|
@ -762,8 +753,7 @@ typedef struct
|
|||
/**
|
||||
* A list of certificates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Function that is called to free this list (called by ZT_freeQueryResult)
|
||||
*/
|
||||
|
@ -788,8 +778,7 @@ typedef struct
|
|||
/**
|
||||
* Credential type IDs
|
||||
*/
|
||||
enum ZT_CredentialType
|
||||
{
|
||||
enum ZT_CredentialType {
|
||||
ZT_CREDENTIAL_TYPE_NULL = 0,
|
||||
ZT_CREDENTIAL_TYPE_COM = 1,
|
||||
ZT_CREDENTIAL_TYPE_CAPABILITY = 2,
|
||||
|
@ -807,8 +796,7 @@ enum ZT_CredentialType
|
|||
* Most of these are not currently implemented and are just reserved
|
||||
* for future use.
|
||||
*/
|
||||
enum ZT_EndpointType
|
||||
{
|
||||
enum ZT_EndpointType {
|
||||
ZT_ENDPOINT_TYPE_NIL = 0, /* Nil/empty endpoint */
|
||||
ZT_ENDPOINT_TYPE_ZEROTIER = 1, /* ZeroTier relaying (address+fingerprint) */
|
||||
ZT_ENDPOINT_TYPE_ETHERNET = 2, /* Ethernet with ethertype 0x9993 */
|
||||
|
@ -850,8 +838,7 @@ enum ZT_EndpointType
|
|||
*
|
||||
* All trace event structures start with a size and type.
|
||||
*/
|
||||
enum ZT_TraceEventType
|
||||
{
|
||||
enum ZT_TraceEventType {
|
||||
ZT_TRACE_UNEXPECTED_ERROR = 0,
|
||||
ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE = 1,
|
||||
ZT_TRACE_VL1_TRYING_NEW_PATH = 2,
|
||||
|
@ -867,8 +854,7 @@ enum ZT_TraceEventType
|
|||
/**
|
||||
* Trace VL1 packet drop reasons
|
||||
*/
|
||||
enum ZT_TracePacketDropReason
|
||||
{
|
||||
enum ZT_TracePacketDropReason {
|
||||
ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED = 0,
|
||||
ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD = 1,
|
||||
ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET = 2,
|
||||
|
@ -883,8 +869,7 @@ enum ZT_TracePacketDropReason
|
|||
/**
|
||||
* Trace VL2 frame drop reasons
|
||||
*/
|
||||
enum ZT_TraceFrameDropReason
|
||||
{
|
||||
enum ZT_TraceFrameDropReason {
|
||||
ZT_TRACE_FRAME_DROP_REASON_UNSPECIFIED = 0,
|
||||
ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_REMOTE = 1,
|
||||
ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_LOCAL = 2,
|
||||
|
@ -898,8 +883,7 @@ enum ZT_TraceFrameDropReason
|
|||
/**
|
||||
* Reasons for credential rejection
|
||||
*/
|
||||
enum ZT_TraceCredentialRejectionReason
|
||||
{
|
||||
enum ZT_TraceCredentialRejectionReason {
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED = 1,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED = 2,
|
||||
ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST = 3,
|
||||
|
@ -951,8 +935,7 @@ enum ZT_TraceCredentialRejectionReason
|
|||
* indicate serious problems like an inaccessible data store or a compile
|
||||
* problem.
|
||||
*/
|
||||
enum ZT_ResultCode
|
||||
{
|
||||
enum ZT_ResultCode {
|
||||
/**
|
||||
* Operation completed normally
|
||||
*/
|
||||
|
@ -1019,8 +1002,7 @@ enum ZT_ResultCode
|
|||
/**
|
||||
* Status codes sent to status update callback when things happen
|
||||
*/
|
||||
enum ZT_Event
|
||||
{
|
||||
enum ZT_Event {
|
||||
/**
|
||||
* Node has been initialized
|
||||
*
|
||||
|
@ -1106,8 +1088,7 @@ enum ZT_Event
|
|||
* Pointers to id and data might not remain valid after the event is
|
||||
* received.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Identity of sender
|
||||
*/
|
||||
|
@ -1132,8 +1113,7 @@ typedef struct
|
|||
/**
|
||||
* Current node status
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* 40-bit ZeroTier address of this node
|
||||
*/
|
||||
|
@ -1167,8 +1147,7 @@ typedef struct
|
|||
/**
|
||||
* Virtual network status codes
|
||||
*/
|
||||
enum ZT_VirtualNetworkStatus
|
||||
{
|
||||
enum ZT_VirtualNetworkStatus {
|
||||
/**
|
||||
* Waiting for network configuration (also means revision == 0)
|
||||
*/
|
||||
|
@ -1193,8 +1172,7 @@ enum ZT_VirtualNetworkStatus
|
|||
/**
|
||||
* Virtual network type codes
|
||||
*/
|
||||
enum ZT_VirtualNetworkType
|
||||
{
|
||||
enum ZT_VirtualNetworkType {
|
||||
/**
|
||||
* Private networks are authorized via membership credentials
|
||||
*/
|
||||
|
@ -1215,8 +1193,7 @@ enum ZT_VirtualNetworkType
|
|||
* Each rule is composed of zero or more MATCHes followed by an ACTION.
|
||||
* An ACTION with no MATCHes is always taken.
|
||||
*/
|
||||
enum ZT_VirtualNetworkRuleType
|
||||
{
|
||||
enum ZT_VirtualNetworkRuleType {
|
||||
/* 0 to 15 reserved for actions */
|
||||
|
||||
/**
|
||||
|
@ -1307,8 +1284,7 @@ enum ZT_VirtualNetworkRuleType
|
|||
* This is designed to be a more memory-efficient way of storing rules than
|
||||
* a wide table, yet still fast and simple to access in code.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Type and flags
|
||||
*
|
||||
|
@ -1325,13 +1301,11 @@ typedef struct
|
|||
/**
|
||||
* Union containing the value of this rule -- which field is used depends on 't'
|
||||
*/
|
||||
union
|
||||
{
|
||||
union {
|
||||
/**
|
||||
* IPv6 address in big-endian / network byte order and netmask bits
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint8_t ip[16];
|
||||
uint8_t mask;
|
||||
} ipv6;
|
||||
|
@ -1339,8 +1313,7 @@ typedef struct
|
|||
/**
|
||||
* IPv4 address in big-endian / network byte order
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint32_t ip;
|
||||
uint8_t mask;
|
||||
} ipv4;
|
||||
|
@ -1352,12 +1325,12 @@ typedef struct
|
|||
* the range is +/- INT32_MAX. It's packed this way so it fits in 16
|
||||
* bytes and doesn't enlarge the overall size of this union.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint64_t start; /* integer range start */
|
||||
uint32_t end; /* end of integer range (relative to start, inclusive, 0 for equality w/start) */
|
||||
uint16_t idx; /* index in packet of integer */
|
||||
uint8_t format; /* bits in integer (range 1-64, ((format&63)+1)) and endianness (MSB 1 for little, 0 for big) */
|
||||
uint8_t
|
||||
format; /* bits in integer (range 1-64, ((format&63)+1)) and endianness (MSB 1 for little, 0 for big) */
|
||||
} intRange;
|
||||
|
||||
/**
|
||||
|
@ -1413,8 +1386,7 @@ typedef struct
|
|||
/**
|
||||
* IP type of service a.k.a. DSCP field
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint8_t mask;
|
||||
uint8_t value[2];
|
||||
} ipTos;
|
||||
|
@ -1427,8 +1399,7 @@ typedef struct
|
|||
/**
|
||||
* ICMP type and code
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint8_t type; /* ICMP type, always matched */
|
||||
uint8_t code; /* ICMP code if matched */
|
||||
uint8_t flags; /* flag 0x01 means also match code, otherwise only match type */
|
||||
|
@ -1437,8 +1408,7 @@ typedef struct
|
|||
/**
|
||||
* For tag-related rules
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint32_t id;
|
||||
uint32_t value;
|
||||
} tag;
|
||||
|
@ -1446,8 +1416,7 @@ typedef struct
|
|||
/**
|
||||
* Destinations for TEE and REDIRECT
|
||||
*/
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint64_t address;
|
||||
uint32_t flags;
|
||||
uint16_t length;
|
||||
|
@ -1463,8 +1432,7 @@ typedef struct
|
|||
/**
|
||||
* A route to be pushed on a virtual network
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default
|
||||
*/
|
||||
|
@ -1489,8 +1457,7 @@ typedef struct
|
|||
/**
|
||||
* An Ethernet multicast group
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* MAC address (least significant 48 bits)
|
||||
*/
|
||||
|
@ -1505,8 +1472,7 @@ typedef struct
|
|||
/**
|
||||
* Virtual network configuration update type
|
||||
*/
|
||||
enum ZT_VirtualNetworkConfigOperation
|
||||
{
|
||||
enum ZT_VirtualNetworkConfigOperation {
|
||||
/**
|
||||
* Network is coming up (either for the first time or after service restart)
|
||||
*/
|
||||
|
@ -1531,8 +1497,7 @@ enum ZT_VirtualNetworkConfigOperation
|
|||
/**
|
||||
* Virtual network configuration
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* 64-bit ZeroTier network ID
|
||||
*/
|
||||
|
@ -1612,8 +1577,7 @@ typedef struct
|
|||
/**
|
||||
* A list of networks
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
void (*freeFunction)(const void*);
|
||||
|
||||
ZT_VirtualNetworkConfig* networks;
|
||||
|
@ -1623,8 +1587,7 @@ typedef struct
|
|||
/**
|
||||
* Address where this node could be reached via an external interface
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* IP and port as would be reachable by external nodes
|
||||
*/
|
||||
|
@ -1639,15 +1602,13 @@ typedef struct
|
|||
/**
|
||||
* Variant type for storing possible path endpoints or peer contact points.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Endpoint type, which determines what field in the union 'a' applies.
|
||||
*/
|
||||
enum ZT_EndpointType type;
|
||||
|
||||
union
|
||||
{
|
||||
union {
|
||||
/**
|
||||
* ZT_InetAddress, which is identically sized to sockaddr_storage.
|
||||
*
|
||||
|
@ -1689,8 +1650,7 @@ typedef void ZT_EndpointAttributes;
|
|||
/**
|
||||
* Network path to a peer
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* Path endpoint
|
||||
*/
|
||||
|
@ -1720,8 +1680,7 @@ typedef struct
|
|||
/**
|
||||
* Peer information
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
/**
|
||||
* ZeroTier address (40 bits)
|
||||
*/
|
||||
|
@ -1805,8 +1764,7 @@ typedef struct
|
|||
/**
|
||||
* List of peers
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
void (*freeFunction)(const void*);
|
||||
|
||||
ZT_Peer* peers;
|
||||
|
@ -1816,8 +1774,7 @@ typedef struct
|
|||
/**
|
||||
* ZeroTier core state objects
|
||||
*/
|
||||
enum ZT_StateObjectType
|
||||
{
|
||||
enum ZT_StateObjectType {
|
||||
/**
|
||||
* Null object -- ignored
|
||||
*/
|
||||
|
@ -2087,8 +2044,7 @@ typedef int (*ZT_PathLookupFunction)(
|
|||
/**
|
||||
* Structure for configuring ZeroTier core callback functions
|
||||
*/
|
||||
struct ZT_Node_Callbacks
|
||||
{
|
||||
struct ZT_Node_Callbacks {
|
||||
/**
|
||||
* REQUIRED: Function to store and/or replicate state objects
|
||||
*/
|
||||
|
@ -2190,11 +2146,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_new(
|
|||
* If you are using multiple threads, all other threads must be shut down
|
||||
* first. This can crash if processXXX() methods are in progress.
|
||||
*/
|
||||
ZT_SDK_API void ZT_Node_delete(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr);
|
||||
ZT_SDK_API void ZT_Node_delete(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr);
|
||||
|
||||
/**
|
||||
* Process a packet received from the physical wire
|
||||
|
@ -2296,13 +2248,8 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_join(
|
|||
*
|
||||
* @return OK (0) or error code if a fatal error condition has occurred
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_leave(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr,
|
||||
void **uptr,
|
||||
uint64_t nwid);
|
||||
ZT_SDK_API enum ZT_ResultCode
|
||||
ZT_Node_leave(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr, void** uptr, uint64_t nwid);
|
||||
|
||||
/**
|
||||
* Subscribe to an Ethernet multicast group
|
||||
|
@ -2364,8 +2311,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(
|
|||
*
|
||||
* @return ZeroTier address (least significant 40 bits of 64-bit int)
|
||||
*/
|
||||
ZT_SDK_API uint64_t ZT_Node_address(
|
||||
ZT_Node *node);
|
||||
ZT_SDK_API uint64_t ZT_Node_address(ZT_Node* node);
|
||||
|
||||
/**
|
||||
* Get this node's identity
|
||||
|
@ -2375,20 +2321,14 @@ ZT_SDK_API uint64_t ZT_Node_address(
|
|||
*
|
||||
* @return Identity
|
||||
*/
|
||||
ZT_SDK_API const ZT_Identity *ZT_Node_identity(
|
||||
ZT_Node *node);
|
||||
ZT_SDK_API const ZT_Identity* ZT_Node_identity(ZT_Node* node);
|
||||
|
||||
/**
|
||||
* Get the status of this node
|
||||
*
|
||||
* @param status Buffer to fill with current node status
|
||||
*/
|
||||
ZT_SDK_API void ZT_Node_status(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr,
|
||||
ZT_NodeStatus *status);
|
||||
ZT_SDK_API void ZT_Node_status(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr, ZT_NodeStatus* status);
|
||||
|
||||
/**
|
||||
* Get a list of known peer nodes
|
||||
|
@ -2398,11 +2338,7 @@ ZT_SDK_API void ZT_Node_status(
|
|||
*
|
||||
* @return List of known peers or NULL on failure
|
||||
*/
|
||||
ZT_SDK_API ZT_PeerList *ZT_Node_peers(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr);
|
||||
ZT_SDK_API ZT_PeerList* ZT_Node_peers(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr);
|
||||
|
||||
/**
|
||||
* Get the status of a virtual network
|
||||
|
@ -2413,12 +2349,8 @@ ZT_SDK_API ZT_PeerList *ZT_Node_peers(
|
|||
* @param nwid 64-bit network ID
|
||||
* @return Network configuration or NULL if we are not a member of this network
|
||||
*/
|
||||
ZT_SDK_API ZT_VirtualNetworkConfig *ZT_Node_networkConfig(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr,
|
||||
uint64_t nwid);
|
||||
ZT_SDK_API ZT_VirtualNetworkConfig*
|
||||
ZT_Node_networkConfig(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr, uint64_t nwid);
|
||||
|
||||
/**
|
||||
* Enumerate and get status of all networks
|
||||
|
@ -2426,8 +2358,7 @@ ZT_SDK_API ZT_VirtualNetworkConfig *ZT_Node_networkConfig(
|
|||
* @param node Node instance
|
||||
* @return List of networks or NULL on failure
|
||||
*/
|
||||
ZT_SDK_API ZT_VirtualNetworkList *ZT_Node_networks(
|
||||
ZT_Node *node);
|
||||
ZT_SDK_API ZT_VirtualNetworkList* ZT_Node_networks(ZT_Node* node);
|
||||
|
||||
/**
|
||||
* Set the network-associated user-defined pointer for a given network
|
||||
|
@ -2438,10 +2369,7 @@ ZT_SDK_API ZT_VirtualNetworkList *ZT_Node_networks(
|
|||
* @param nwid Network ID
|
||||
* @param ptr New network-associated pointer
|
||||
*/
|
||||
ZT_SDK_API void ZT_Node_setNetworkUserPtr(
|
||||
ZT_Node *node,
|
||||
uint64_t nwid,
|
||||
void *ptr);
|
||||
ZT_SDK_API void ZT_Node_setNetworkUserPtr(ZT_Node* node, uint64_t nwid, void* ptr);
|
||||
|
||||
/**
|
||||
* Set external interface addresses where this node could be reached
|
||||
|
@ -2491,12 +2419,8 @@ ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate(
|
|||
* @param serialNo 48-byte / 384-bit serial number of certificate to delete
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr,
|
||||
const void *serialNo);
|
||||
ZT_SDK_API enum ZT_ResultCode
|
||||
ZT_Node_deleteCertificate(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr, const void* serialNo);
|
||||
|
||||
/**
|
||||
* List certificates installed in this node's trust store
|
||||
|
@ -2504,11 +2428,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate(
|
|||
* @param node Node instance
|
||||
* @return List of certificates or NULL on error
|
||||
*/
|
||||
ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(
|
||||
ZT_Node *node,
|
||||
int64_t clock,
|
||||
int64_t ticks,
|
||||
void *tptr);
|
||||
ZT_SDK_API ZT_CertificateList* ZT_Node_listCertificates(ZT_Node* node, int64_t clock, int64_t ticks, void* tptr);
|
||||
|
||||
/**
|
||||
* Send a VERB_USER_MESSAGE to another ZeroTier node
|
||||
|
@ -2549,9 +2469,7 @@ ZT_SDK_API int ZT_Node_sendUserMessage(
|
|||
* @param networkConfigMasterInstance Instance of NetworkConfigMaster C++ class or NULL to disable
|
||||
* @return OK (0) or error code if a fatal error condition has occurred
|
||||
*/
|
||||
ZT_SDK_API void ZT_Node_setController(
|
||||
ZT_Node *node,
|
||||
void *networkConfigMasterInstance);
|
||||
ZT_SDK_API void ZT_Node_setController(ZT_Node* node, void* networkConfigMasterInstance);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -2645,11 +2563,7 @@ ZT_SDK_API enum ZT_IdentityType ZT_Identity_type(const ZT_Identity *id);
|
|||
* @param includePrivate If true include the private key if present
|
||||
* @return Pointer to buf or NULL on overflow or other error
|
||||
*/
|
||||
ZT_SDK_API char *ZT_Identity_toString(
|
||||
const ZT_Identity *id,
|
||||
char *buf,
|
||||
int capacity,
|
||||
int includePrivate);
|
||||
ZT_SDK_API char* ZT_Identity_toString(const ZT_Identity* id, char* buf, int capacity, int includePrivate);
|
||||
|
||||
/**
|
||||
* Check whether this identity object also holds a private key
|
||||
|
@ -2704,10 +2618,7 @@ ZT_SDK_API void ZT_Identity_delete(const ZT_Identity *id);
|
|||
* @param capacity Capacity of buffer
|
||||
* @return String or NULL on error
|
||||
*/
|
||||
ZT_SDK_API char *ZT_Endpoint_toString(
|
||||
const ZT_Endpoint *ep,
|
||||
char *buf,
|
||||
int capacity);
|
||||
ZT_SDK_API char* ZT_Endpoint_toString(const ZT_Endpoint* ep, char* buf, int capacity);
|
||||
|
||||
/**
|
||||
* Parse an endpoint as a string
|
||||
|
@ -2720,9 +2631,7 @@ ZT_SDK_API char *ZT_Endpoint_toString(
|
|||
* @param str String representation of endpoint
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API int ZT_Endpoint_fromString(
|
||||
ZT_Endpoint *ep,
|
||||
const char *str);
|
||||
ZT_SDK_API int ZT_Endpoint_fromString(ZT_Endpoint* ep, const char* str);
|
||||
|
||||
/**
|
||||
* Decode a binary serialized endpoint
|
||||
|
@ -2732,10 +2641,7 @@ ZT_SDK_API int ZT_Endpoint_fromString(
|
|||
* @param len Length of bytes
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API int ZT_Endpoint_fromBytes(
|
||||
ZT_Endpoint *ep,
|
||||
const void *bytes,
|
||||
unsigned int len);
|
||||
ZT_SDK_API int ZT_Endpoint_fromBytes(ZT_Endpoint* ep, const void* bytes, unsigned int len);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -2766,9 +2672,7 @@ ZT_SDK_API ZT_Locator *ZT_Locator_create(
|
|||
* @param len Length of data
|
||||
* @return Locator or NULL if data is not valid
|
||||
*/
|
||||
ZT_SDK_API ZT_Locator *ZT_Locator_unmarshal(
|
||||
const void *data,
|
||||
unsigned int len);
|
||||
ZT_SDK_API ZT_Locator* ZT_Locator_unmarshal(const void* data, unsigned int len);
|
||||
|
||||
/**
|
||||
* Decode a locator from string format
|
||||
|
@ -2786,10 +2690,7 @@ ZT_SDK_API ZT_Locator *ZT_Locator_fromString(const char *str);
|
|||
* @param bufSize Size of buffer in bytes (needs to be at least 2048 bytes in size)
|
||||
* @return Number of bytes stored to buf or -1 on error such as buffer too small
|
||||
*/
|
||||
ZT_SDK_API int ZT_Locator_marshal(
|
||||
const ZT_Locator *loc,
|
||||
void *buf,
|
||||
unsigned int bufSize);
|
||||
ZT_SDK_API int ZT_Locator_marshal(const ZT_Locator* loc, void* buf, unsigned int bufSize);
|
||||
|
||||
/**
|
||||
* Get this locator in string format
|
||||
|
@ -2799,10 +2700,7 @@ ZT_SDK_API int ZT_Locator_marshal(
|
|||
* @param capacity Capacity of buffer in bytes (recommended size: 4096)
|
||||
* @return Pointer to buffer or NULL if an error occurs
|
||||
*/
|
||||
ZT_SDK_API char *ZT_Locator_toString(
|
||||
const ZT_Locator *loc,
|
||||
char *buf,
|
||||
int capacity);
|
||||
ZT_SDK_API char* ZT_Locator_toString(const ZT_Locator* loc, char* buf, int capacity);
|
||||
|
||||
/**
|
||||
* Get a locator's revision
|
||||
|
@ -2845,9 +2743,7 @@ ZT_SDK_API unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc);
|
|||
* @param ep Endpoint number from 0 to 1 - endpointCount()
|
||||
* @return Endpoint or NULL if out of bounds
|
||||
*/
|
||||
ZT_SDK_API const ZT_Endpoint *ZT_Locator_endpoint(
|
||||
const ZT_Locator *loc,
|
||||
unsigned int ep);
|
||||
ZT_SDK_API const ZT_Endpoint* ZT_Locator_endpoint(const ZT_Locator* loc, unsigned int ep);
|
||||
|
||||
/**
|
||||
* Verify this locator's signature
|
||||
|
@ -2855,9 +2751,7 @@ ZT_SDK_API const ZT_Endpoint *ZT_Locator_endpoint(
|
|||
* @param signer Signing identity
|
||||
* @return Non-zero if locator is valid
|
||||
*/
|
||||
ZT_SDK_API int ZT_Locator_verify(
|
||||
const ZT_Locator *loc,
|
||||
const ZT_Identity *signer);
|
||||
ZT_SDK_API int ZT_Locator_verify(const ZT_Locator* loc, const ZT_Identity* signer);
|
||||
|
||||
/**
|
||||
* Delete a locator
|
||||
|
@ -2876,11 +2770,7 @@ ZT_SDK_API void ZT_Locator_delete(const ZT_Locator *loc);
|
|||
* @param revision Result: revision
|
||||
* @param build Result: build number
|
||||
*/
|
||||
ZT_SDK_API void ZT_version(
|
||||
int *major,
|
||||
int *minor,
|
||||
int *revision,
|
||||
int *build);
|
||||
ZT_SDK_API void ZT_version(int* major, int* minor, int* revision, int* build);
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -2967,11 +2857,8 @@ ZT_SDK_API ZT_Certificate *ZT_Certificate_sign(
|
|||
* @param verify If non-zero, verify signatures and structure
|
||||
* @return Certificate error, if any
|
||||
*/
|
||||
ZT_SDK_API enum ZT_CertificateError ZT_Certificate_decode(
|
||||
const ZT_Certificate **decodedCert,
|
||||
const void *cert,
|
||||
int certSize,
|
||||
int verify);
|
||||
ZT_SDK_API enum ZT_CertificateError
|
||||
ZT_Certificate_decode(const ZT_Certificate** decodedCert, const void* cert, int certSize, int verify);
|
||||
|
||||
/**
|
||||
* Encode a certificate
|
||||
|
@ -2981,10 +2868,7 @@ ZT_SDK_API enum ZT_CertificateError ZT_Certificate_decode(
|
|||
* @param encodedSize Value/result: size of certificate encoding buffer
|
||||
* @return OK (0) or error
|
||||
*/
|
||||
ZT_SDK_API int ZT_Certificate_encode(
|
||||
const ZT_Certificate *cert,
|
||||
void *encoded,
|
||||
int *encodedSize);
|
||||
ZT_SDK_API int ZT_Certificate_encode(const ZT_Certificate* cert, void* encoded, int* encodedSize);
|
||||
|
||||
/**
|
||||
* Verify certificate signatures and internal structure.
|
||||
|
@ -2993,9 +2877,7 @@ ZT_SDK_API int ZT_Certificate_encode(
|
|||
* @param clock Clock to check timestamp or -1 to skip this check
|
||||
* @return Certificate error or ZT_CERTIFICATE_ERROR_NONE if no errors found.
|
||||
*/
|
||||
ZT_SDK_API enum ZT_CertificateError ZT_Certificate_verify(
|
||||
const ZT_Certificate *cert,
|
||||
int64_t clock);
|
||||
ZT_SDK_API enum ZT_CertificateError ZT_Certificate_verify(const ZT_Certificate* cert, int64_t clock);
|
||||
|
||||
/**
|
||||
* Deep clone a certificate, returning one allocated C-side.
|
||||
|
@ -3109,7 +2991,8 @@ ZT_SDK_API void ZT_InetAddress_set(ZT_InetAddress *ia, const void *saddr);
|
|||
* @param ipLen Length of IP: 4 or 16 for IPv4 or IPv6
|
||||
* @param port IP port
|
||||
*/
|
||||
ZT_SDK_API void ZT_InetAddress_setIpBytes(ZT_InetAddress *ia, const void *ipBytes, unsigned int ipLen, unsigned int port);
|
||||
ZT_SDK_API void
|
||||
ZT_InetAddress_setIpBytes(ZT_InetAddress* ia, const void* ipBytes, unsigned int ipLen, unsigned int port);
|
||||
|
||||
/**
|
||||
* Set IP port
|
||||
|
@ -3178,7 +3061,11 @@ ZT_SDK_API const int ZT_AF_INET,ZT_AF_INET6;
|
|||
* @param f Function to invoke with each key and (binary) value
|
||||
* @return Non-zero if dictionary was valid
|
||||
*/
|
||||
ZT_SDK_API int ZT_Dictionary_parse(const void *dict, unsigned int len, void *arg, void (*f)(void *, const char *, unsigned int, const void *, unsigned int));
|
||||
ZT_SDK_API int ZT_Dictionary_parse(
|
||||
const void* dict,
|
||||
unsigned int len,
|
||||
void* arg,
|
||||
void (*f)(void*, const char*, unsigned int, const void*, unsigned int));
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -19,20 +19,20 @@
|
|||
#include <string.h>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <IPHlpApi.h>
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <netioapi.h>
|
||||
#include <IPHlpApi.h>
|
||||
#endif
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#ifndef ZT_SDK
|
||||
#include <net/route.h>
|
||||
#endif
|
||||
|
@ -44,11 +44,11 @@
|
|||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include "ManagedRoute.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "ManagedRoute.hpp"
|
||||
#include <vector>
|
||||
#ifdef __LINUX__
|
||||
#include "LinuxNetLink.hpp"
|
||||
#endif
|
||||
|
@ -71,24 +71,26 @@ static void _forkTarget(const InetAddress &t,InetAddress &left,InetAddress &righ
|
|||
right = t;
|
||||
reinterpret_cast<struct sockaddr_in*>(&right)->sin_addr.s_addr ^= Utils::hton((uint32_t)(1 << (32 - bits)));
|
||||
right.setPort(bits);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
right.zero();
|
||||
}
|
||||
} else if (t.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (t.ss_family == AF_INET6) {
|
||||
if (bits <= 128) {
|
||||
left.setPort(bits);
|
||||
right = t;
|
||||
uint8_t* b = reinterpret_cast<uint8_t*>(reinterpret_cast<struct sockaddr_in6*>(&right)->sin6_addr.s6_addr);
|
||||
b[bits / 8] ^= 1 << (8 - (bits % 8));
|
||||
right.setPort(bits);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
right.zero();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct _RTE
|
||||
{
|
||||
struct _RTE {
|
||||
InetAddress target;
|
||||
InetAddress via;
|
||||
char device[128];
|
||||
|
@ -128,7 +130,8 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
InetAddress sa_t, sa_v;
|
||||
int deviceIndex = -9999;
|
||||
|
||||
if (((rtm->rtm_flags & RTF_LLINFO) == 0)&&((rtm->rtm_flags & RTF_HOST) == 0)&&((rtm->rtm_flags & RTF_UP) != 0)&&((rtm->rtm_flags & RTF_MULTICAST) == 0)) {
|
||||
if (((rtm->rtm_flags & RTF_LLINFO) == 0) && ((rtm->rtm_flags & RTF_HOST) == 0)
|
||||
&& ((rtm->rtm_flags & RTF_UP) != 0) && ((rtm->rtm_flags & RTF_MULTICAST) == 0)) {
|
||||
int which = 0;
|
||||
while (saptr < saend) {
|
||||
struct sockaddr* sa = (struct sockaddr*)saptr;
|
||||
|
@ -152,9 +155,14 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
// printf("RTA_DST\n");
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
||||
if ((sin6->sin6_addr.s6_addr[0] == 0xfe)&&((sin6->sin6_addr.s6_addr[1] & 0xc0) == 0x80)) {
|
||||
// BSD uses this fucking strange in-band signaling method to encode device scope IDs for IPv6 addresses... probably a holdover from very early versions of the spec.
|
||||
unsigned int interfaceIndex = ((((unsigned int)sin6->sin6_addr.s6_addr[2]) << 8) & 0xff) | (((unsigned int)sin6->sin6_addr.s6_addr[3]) & 0xff);
|
||||
if ((sin6->sin6_addr.s6_addr[0] == 0xfe)
|
||||
&& ((sin6->sin6_addr.s6_addr[1] & 0xc0) == 0x80)) {
|
||||
// BSD uses this fucking strange in-band signaling method to encode device
|
||||
// scope IDs for IPv6 addresses... probably a holdover from very early
|
||||
// versions of the spec.
|
||||
unsigned int interfaceIndex =
|
||||
((((unsigned int)sin6->sin6_addr.s6_addr[2]) << 8) & 0xff)
|
||||
| (((unsigned int)sin6->sin6_addr.s6_addr[3]) & 0xff);
|
||||
sin6->sin6_addr.s6_addr[2] = 0;
|
||||
sin6->sin6_addr.s6_addr[3] = 0;
|
||||
if (! sin6->sin6_scope_id)
|
||||
|
@ -181,15 +189,19 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
salen = sizeof(struct sockaddr_in6);
|
||||
unsigned int bits = 0;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
unsigned char c = (unsigned char)((const struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[i];
|
||||
unsigned char c =
|
||||
(unsigned char)((const struct sockaddr_in6*)sa)->sin6_addr.s6_addr[i];
|
||||
if (c == 0xff)
|
||||
bits += 8;
|
||||
else break;
|
||||
else
|
||||
break;
|
||||
}
|
||||
sa_t.setPort(bits);
|
||||
} else if (sa_t.ss_family == AF_INET) {
|
||||
}
|
||||
else if (sa_t.ss_family == AF_INET) {
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
sa_t.setPort((unsigned int)Utils::countBits((uint32_t)((const struct sockaddr_in *)sa)->sin_addr.s_addr));
|
||||
sa_t.setPort((unsigned int)Utils::countBits(
|
||||
(uint32_t)((const struct sockaddr_in*)sa)->sin_addr.s_addr));
|
||||
}
|
||||
} break;
|
||||
/*
|
||||
|
@ -217,10 +229,12 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
rtes.back().via = sa_v;
|
||||
if (deviceIndex >= 0) {
|
||||
if_indextoname(deviceIndex, rtes.back().device);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
rtes.back().device[0] = (char)0;
|
||||
}
|
||||
rtes.back().metric = ((int)rtm->rtm_rmx.rmx_hopcount < 0) ? 0 : (int)rtm->rtm_rmx.rmx_hopcount;
|
||||
rtes.back().metric =
|
||||
((int)rtm->rtm_rmx.rmx_hopcount < 0) ? 0 : (int)rtm->rtm_rmx.rmx_hopcount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,29 +250,73 @@ static std::vector<_RTE> _getRTEs(const InetAddress &target,bool contains)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void _routeCmd(const char *op,const InetAddress &target,const InetAddress &via,const char *ifscope,const char *localInterface)
|
||||
static void _routeCmd(
|
||||
const char* op,
|
||||
const InetAddress& target,
|
||||
const InetAddress& via,
|
||||
const char* ifscope,
|
||||
const char* localInterface)
|
||||
{
|
||||
//char f1[1024],f2[1024]; printf("%s %s %s %s %s\n",op,target.toString(f1),via.toString(f2),ifscope,localInterface);
|
||||
// char f1[1024],f2[1024]; printf("%s %s %s %s
|
||||
// %s\n",op,target.toString(f1),via.toString(f2),ifscope,localInterface);
|
||||
long p = (long)fork();
|
||||
if (p > 0) {
|
||||
int exitcode = -1;
|
||||
::waitpid(p, &exitcode, 0);
|
||||
} else if (p == 0) {
|
||||
}
|
||||
else if (p == 0) {
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
char ttmp[64];
|
||||
char iptmp[64];
|
||||
if (via) {
|
||||
if ((ifscope) && (ifscope[0])) {
|
||||
::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp),(const char *)0);
|
||||
} else {
|
||||
::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),via.toIpString(iptmp),(const char *)0);
|
||||
::execl(
|
||||
ZT_BSD_ROUTE_CMD,
|
||||
ZT_BSD_ROUTE_CMD,
|
||||
op,
|
||||
"-ifscope",
|
||||
ifscope,
|
||||
((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),
|
||||
target.toString(ttmp),
|
||||
via.toIpString(iptmp),
|
||||
(const char*)0);
|
||||
}
|
||||
} else if ((localInterface)&&(localInterface[0])) {
|
||||
else {
|
||||
::execl(
|
||||
ZT_BSD_ROUTE_CMD,
|
||||
ZT_BSD_ROUTE_CMD,
|
||||
op,
|
||||
((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),
|
||||
target.toString(ttmp),
|
||||
via.toIpString(iptmp),
|
||||
(const char*)0);
|
||||
}
|
||||
}
|
||||
else if ((localInterface) && (localInterface[0])) {
|
||||
if ((ifscope) && (ifscope[0])) {
|
||||
::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,"-ifscope",ifscope,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),"-interface",localInterface,(const char *)0);
|
||||
} else {
|
||||
::execl(ZT_BSD_ROUTE_CMD,ZT_BSD_ROUTE_CMD,op,((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),target.toString(ttmp),"-interface",localInterface,(const char *)0);
|
||||
::execl(
|
||||
ZT_BSD_ROUTE_CMD,
|
||||
ZT_BSD_ROUTE_CMD,
|
||||
op,
|
||||
"-ifscope",
|
||||
ifscope,
|
||||
((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),
|
||||
target.toString(ttmp),
|
||||
"-interface",
|
||||
localInterface,
|
||||
(const char*)0);
|
||||
}
|
||||
else {
|
||||
::execl(
|
||||
ZT_BSD_ROUTE_CMD,
|
||||
ZT_BSD_ROUTE_CMD,
|
||||
op,
|
||||
((target.ss_family == AF_INET6) ? "-inet6" : "-inet"),
|
||||
target.toString(ttmp),
|
||||
"-interface",
|
||||
localInterface,
|
||||
(const char*)0);
|
||||
}
|
||||
}
|
||||
::_exit(-1);
|
||||
|
@ -277,7 +335,12 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress
|
|||
#ifdef __WINDOWS__ // --------------------------------------------------------
|
||||
#define ZT_ROUTING_SUPPORT_FOUND 1
|
||||
|
||||
static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &interfaceIndex,const InetAddress &target,const InetAddress &via)
|
||||
static bool _winRoute(
|
||||
bool del,
|
||||
const NET_LUID& interfaceLuid,
|
||||
const NET_IFINDEX& interfaceIndex,
|
||||
const InetAddress& target,
|
||||
const InetAddress& via)
|
||||
{
|
||||
MIB_IPFORWARD_ROW2 rtrow;
|
||||
InitializeIpForwardEntry(&rtrow);
|
||||
|
@ -286,22 +349,32 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &
|
|||
if (target.ss_family == AF_INET) {
|
||||
rtrow.DestinationPrefix.Prefix.si_family = AF_INET;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_family = AF_INET;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&target)->sin_addr.S_un.S_addr;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr =
|
||||
reinterpret_cast<const struct sockaddr_in*>(&target)->sin_addr.S_un.S_addr;
|
||||
if (via.ss_family == AF_INET) {
|
||||
rtrow.NextHop.si_family = AF_INET;
|
||||
rtrow.NextHop.Ipv4.sin_family = AF_INET;
|
||||
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&via)->sin_addr.S_un.S_addr;
|
||||
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr =
|
||||
reinterpret_cast<const struct sockaddr_in*>(&via)->sin_addr.S_un.S_addr;
|
||||
}
|
||||
} else if (target.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (target.ss_family == AF_INET6) {
|
||||
rtrow.DestinationPrefix.Prefix.si_family = AF_INET6;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6;
|
||||
memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte,reinterpret_cast<const struct sockaddr_in6 *>(&target)->sin6_addr.u.Byte,16);
|
||||
memcpy(
|
||||
rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte,
|
||||
reinterpret_cast<const struct sockaddr_in6*>(&target)->sin6_addr.u.Byte,
|
||||
16);
|
||||
if (via.ss_family == AF_INET6) {
|
||||
rtrow.NextHop.si_family = AF_INET6;
|
||||
rtrow.NextHop.Ipv6.sin6_family = AF_INET6;
|
||||
memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte,reinterpret_cast<const struct sockaddr_in6 *>(&via)->sin6_addr.u.Byte,16);
|
||||
memcpy(
|
||||
rtrow.NextHop.Ipv6.sin6_addr.u.Byte,
|
||||
reinterpret_cast<const struct sockaddr_in6*>(&via)->sin6_addr.u.Byte,
|
||||
16);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
rtrow.DestinationPrefix.PrefixLength = target.netmaskBits();
|
||||
|
@ -318,19 +391,26 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &
|
|||
rtrow.Origin = NlroManual;
|
||||
if (del) {
|
||||
return (DeleteIpForwardEntry2(&rtrow) == NO_ERROR);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
NTSTATUS r = CreateIpForwardEntry2(&rtrow);
|
||||
if (r == NO_ERROR) {
|
||||
return true;
|
||||
} else if (r == ERROR_OBJECT_ALREADY_EXISTS) {
|
||||
}
|
||||
else if (r == ERROR_OBJECT_ALREADY_EXISTS) {
|
||||
return (SetIpForwardEntry2(&rtrow) == NO_ERROR);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &interfaceIndex, const InetAddress &target, const InetAddress &via)
|
||||
static bool _winHasRoute(
|
||||
const NET_LUID& interfaceLuid,
|
||||
const NET_IFINDEX& interfaceIndex,
|
||||
const InetAddress& target,
|
||||
const InetAddress& via)
|
||||
{
|
||||
MIB_IPFORWARD_ROW2 rtrow;
|
||||
InitializeIpForwardEntry(&rtrow);
|
||||
|
@ -339,22 +419,32 @@ static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &inter
|
|||
if (target.ss_family == AF_INET) {
|
||||
rtrow.DestinationPrefix.Prefix.si_family = AF_INET;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_family = AF_INET;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&target)->sin_addr.S_un.S_addr;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr =
|
||||
reinterpret_cast<const struct sockaddr_in*>(&target)->sin_addr.S_un.S_addr;
|
||||
if (via.ss_family == AF_INET) {
|
||||
rtrow.NextHop.si_family = AF_INET;
|
||||
rtrow.NextHop.Ipv4.sin_family = AF_INET;
|
||||
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&via)->sin_addr.S_un.S_addr;
|
||||
rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr =
|
||||
reinterpret_cast<const struct sockaddr_in*>(&via)->sin_addr.S_un.S_addr;
|
||||
}
|
||||
} else if (target.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (target.ss_family == AF_INET6) {
|
||||
rtrow.DestinationPrefix.Prefix.si_family = AF_INET6;
|
||||
rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6;
|
||||
memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6 *>(&target)->sin6_addr.u.Byte, 16);
|
||||
memcpy(
|
||||
rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte,
|
||||
reinterpret_cast<const struct sockaddr_in6*>(&target)->sin6_addr.u.Byte,
|
||||
16);
|
||||
if (via.ss_family == AF_INET6) {
|
||||
rtrow.NextHop.si_family = AF_INET6;
|
||||
rtrow.NextHop.Ipv6.sin6_family = AF_INET6;
|
||||
memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast<const struct sockaddr_in6 *>(&via)->sin6_addr.u.Byte, 16);
|
||||
memcpy(
|
||||
rtrow.NextHop.Ipv6.sin6_addr.u.Byte,
|
||||
reinterpret_cast<const struct sockaddr_in6*>(&via)->sin6_addr.u.Byte,
|
||||
16);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
rtrow.DestinationPrefix.PrefixLength = target.netmaskBits();
|
||||
|
@ -365,12 +455,17 @@ static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &inter
|
|||
#endif // __WINDOWS__ --------------------------------------------------------
|
||||
|
||||
#ifndef ZT_ROUTING_SUPPORT_FOUND
|
||||
#error "ManagedRoute.cpp has no support for managing routes on this platform! You'll need to check and see if one of the existing ones will work and make sure proper defines are set, or write one. Please do a GitHub pull request if you do this for a new OS."
|
||||
#error \
|
||||
"ManagedRoute.cpp has no support for managing routes on this platform! You'll need to check and see if one of the existing ones will work and make sure proper defines are set, or write one. Please do a GitHub pull request if you do this for a new OS."
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
ManagedRoute::ManagedRoute(const InetAddress &target,const InetAddress &via,const InetAddress &src,const char *device)
|
||||
ManagedRoute::ManagedRoute(
|
||||
const InetAddress& target,
|
||||
const InetAddress& via,
|
||||
const InetAddress& src,
|
||||
const char* device)
|
||||
{
|
||||
_target = target;
|
||||
_via = via;
|
||||
|
@ -378,13 +473,15 @@ ManagedRoute::ManagedRoute(const InetAddress &target,const InetAddress &via,cons
|
|||
|
||||
if (_via.ss_family == AF_INET) {
|
||||
_via.setPort(32);
|
||||
} else if (_via.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (_via.ss_family == AF_INET6) {
|
||||
_via.setPort(128);
|
||||
}
|
||||
|
||||
if (_src.ss_family == AF_INET) {
|
||||
_src.setPort(32);
|
||||
} else if (_src.ss_family == AF_INET6) {
|
||||
}
|
||||
else if (_src.ss_family == AF_INET6) {
|
||||
_src.setPort(128);
|
||||
}
|
||||
|
||||
|
@ -414,7 +511,8 @@ bool ManagedRoute::sync()
|
|||
{
|
||||
#ifdef __WINDOWS__
|
||||
NET_LUID interfaceLuid;
|
||||
interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
|
||||
interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(
|
||||
_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
|
||||
NET_IFINDEX interfaceIndex = -1;
|
||||
if (ConvertInterfaceLuidToIndex(&interfaceLuid, &interfaceIndex) != NO_ERROR)
|
||||
return false;
|
||||
|
@ -423,7 +521,8 @@ bool ManagedRoute::sync()
|
|||
InetAddress leftt, rightt;
|
||||
if (_target.netmaskBits() == 0) // bifurcate only the default route
|
||||
_forkTarget(_target, leftt, rightt);
|
||||
else leftt = _target;
|
||||
else
|
||||
leftt = _target;
|
||||
|
||||
#ifdef __BSD__ // ------------------------------------------------------------
|
||||
|
||||
|
@ -527,7 +626,8 @@ void ManagedRoute::remove()
|
|||
{
|
||||
#ifdef __WINDOWS__
|
||||
NET_LUID interfaceLuid;
|
||||
interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
|
||||
interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(
|
||||
_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
|
||||
NET_IFINDEX interfaceIndex = -1;
|
||||
if (ConvertInterfaceLuidToIndex(&interfaceLuid, &interfaceIndex) != NO_ERROR)
|
||||
return;
|
||||
|
|
|
@ -14,25 +14,23 @@
|
|||
#ifndef ZT_MANAGEDROUTE_HPP
|
||||
#define ZT_MANAGEDROUTE_HPP
|
||||
|
||||
#include "../node/AtomicCounter.hpp"
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/SharedPtr.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../node/InetAddress.hpp"
|
||||
#include "../node/Utils.hpp"
|
||||
#include "../node/SharedPtr.hpp"
|
||||
#include "../node/AtomicCounter.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A ZT-managed route that used C++ RAII semantics to automatically clean itself up on deallocate
|
||||
*/
|
||||
class ManagedRoute
|
||||
{
|
||||
class ManagedRoute {
|
||||
friend class SharedPtr<ManagedRoute>;
|
||||
|
||||
public:
|
||||
|
@ -58,14 +56,31 @@ public:
|
|||
*/
|
||||
void remove();
|
||||
|
||||
inline const InetAddress &target() const { return _target; }
|
||||
inline const InetAddress &via() const { return _via; }
|
||||
inline const InetAddress &src() const { return _src; }
|
||||
inline const char *device() const { return _device; }
|
||||
inline const InetAddress& target() const
|
||||
{
|
||||
return _target;
|
||||
}
|
||||
inline const InetAddress& via() const
|
||||
{
|
||||
return _via;
|
||||
}
|
||||
inline const InetAddress& src() const
|
||||
{
|
||||
return _src;
|
||||
}
|
||||
inline const char* device() const
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
|
||||
private:
|
||||
ManagedRoute(const ManagedRoute &) {}
|
||||
inline ManagedRoute &operator=(const ManagedRoute &) { return *this; }
|
||||
ManagedRoute(const ManagedRoute&)
|
||||
{
|
||||
}
|
||||
inline ManagedRoute& operator=(const ManagedRoute&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
InetAddress _target;
|
||||
InetAddress _via;
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
*/
|
||||
/****/
|
||||
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include "../core/Constants.hpp"
|
||||
#include "../core/Containers.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
@ -84,7 +85,9 @@ bool OSUtils::redirectUnixOutputs(const char *stdoutPath, const char *stderrPath
|
|||
::close(fdout);
|
||||
return false;
|
||||
}
|
||||
} else fderr = fdout;
|
||||
}
|
||||
else
|
||||
fderr = fdout;
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
::dup2(fdout, STDOUT_FILENO);
|
||||
|
@ -105,7 +108,9 @@ Vector< String > OSUtils::listDirectory(const char *path, bool includeDirectorie
|
|||
WIN32_FIND_DATAA ffd;
|
||||
if ((hFind = FindFirstFileA((String(path) + "\\*").c_str(), &ffd)) != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
if ( (strcmp(ffd.cFileName,".")) && (strcmp(ffd.cFileName,"..")) && (((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)||(((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)&&(includeDirectories))) )
|
||||
if ((strcmp(ffd.cFileName, ".")) && (strcmp(ffd.cFileName, ".."))
|
||||
&& (((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
|| (((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) && (includeDirectories))))
|
||||
r.push_back(String(ffd.cFileName));
|
||||
} while (FindNextFileA(hFind, &ffd));
|
||||
FindClose(hFind);
|
||||
|
@ -121,9 +126,12 @@ Vector< String > OSUtils::listDirectory(const char *path, bool includeDirectorie
|
|||
if (readdir_r(d, &de, &dptr))
|
||||
break;
|
||||
if (dptr) {
|
||||
if ((strcmp(dptr->d_name, ".") != 0) && (strcmp(dptr->d_name, "..") != 0) && ((dptr->d_type != DT_DIR) || (includeDirectories)))
|
||||
if ((strcmp(dptr->d_name, ".") != 0) && (strcmp(dptr->d_name, "..") != 0)
|
||||
&& ((dptr->d_type != DT_DIR) || (includeDirectories)))
|
||||
r.push_back(String(dptr->d_name));
|
||||
} else break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
closedir(d);
|
||||
#endif
|
||||
|
@ -142,7 +150,8 @@ bool OSUtils::rmDashRf(const char *path)
|
|||
if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
|
||||
if (DeleteFileA((String(path) + ZT_PATH_SEPARATOR_S + ffd.cFileName).c_str()) == FALSE)
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (! rmDashRf((String(path) + ZT_PATH_SEPARATOR_S + ffd.cFileName).c_str()))
|
||||
return false;
|
||||
}
|
||||
|
@ -191,7 +200,17 @@ void OSUtils::lockDownFile(const char *path, bool isDir)
|
|||
startupInfo.cb = sizeof(startupInfo);
|
||||
memset(&startupInfo, 0, sizeof(STARTUPINFOA));
|
||||
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
||||
if (CreateProcessA(NULL,(LPSTR)(String("C:\\Windows\\System32\\icacls.exe \"") + path + "\" /inheritance:d /Q").c_str(),NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&startupInfo,&processInfo)) {
|
||||
if (CreateProcessA(
|
||||
NULL,
|
||||
(LPSTR)(String("C:\\Windows\\System32\\icacls.exe \"") + path + "\" /inheritance:d /Q").c_str(),
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
CREATE_NO_WINDOW,
|
||||
NULL,
|
||||
NULL,
|
||||
&startupInfo,
|
||||
&processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
|
@ -200,7 +219,17 @@ void OSUtils::lockDownFile(const char *path, bool isDir)
|
|||
startupInfo.cb = sizeof(startupInfo);
|
||||
memset(&startupInfo, 0, sizeof(STARTUPINFOA));
|
||||
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
||||
if (CreateProcessA(NULL,(LPSTR)(String("C:\\Windows\\System32\\icacls.exe \"") + path + "\" /remove *S-1-5-32-545 /Q").c_str(),NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&startupInfo,&processInfo)) {
|
||||
if (CreateProcessA(
|
||||
NULL,
|
||||
(LPSTR)(String("C:\\Windows\\System32\\icacls.exe \"") + path + "\" /remove *S-1-5-32-545 /Q").c_str(),
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
CREATE_NO_WINDOW,
|
||||
NULL,
|
||||
NULL,
|
||||
&startupInfo,
|
||||
&processInfo)) {
|
||||
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
|
@ -229,7 +258,8 @@ bool OSUtils::readFile(const char *path, String &buf)
|
|||
long n = (long)fread(tmp, 1, sizeof(tmp), f);
|
||||
if (n > 0)
|
||||
buf.append(tmp, n);
|
||||
else break;
|
||||
else
|
||||
break;
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
|
@ -244,7 +274,8 @@ bool OSUtils::writeFile(const char *path, const void *buf, unsigned int len)
|
|||
if ((long)fwrite(buf, 1, len, f) != (long)len) {
|
||||
fclose(f);
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
@ -268,13 +299,17 @@ Vector< String > OSUtils::split(const char *s, const char *const sep, const char
|
|||
if (escapeState) {
|
||||
escapeState = false;
|
||||
buf.push_back(*s);
|
||||
} else if (quoteState) {
|
||||
}
|
||||
else if (quoteState) {
|
||||
if (*s == quoteState) {
|
||||
quoteState = 0;
|
||||
fields.push_back(buf);
|
||||
buf.clear();
|
||||
} else buf.push_back(*s);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
buf.push_back(*s);
|
||||
}
|
||||
else {
|
||||
const char* quotTmp;
|
||||
if (strchr(esc, *s))
|
||||
escapeState = true;
|
||||
|
@ -285,7 +320,9 @@ Vector< String > OSUtils::split(const char *s, const char *const sep, const char
|
|||
fields.push_back(buf);
|
||||
buf.clear();
|
||||
} // else skip runs of separators
|
||||
} else buf.push_back(*s);
|
||||
}
|
||||
else
|
||||
buf.push_back(*s);
|
||||
}
|
||||
++s;
|
||||
}
|
||||
|
@ -355,7 +392,8 @@ ZeroTier::String OSUtils::platformDefaultHomePath()
|
|||
ZeroTier::String tmp(buf);
|
||||
tmp.append("\\ZeroTier");
|
||||
return tmp;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return ZeroTier::String("C:\\ZeroTier");
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -21,15 +21,15 @@
|
|||
#include <time.h>
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach.h>
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
|
@ -38,8 +38,7 @@ namespace ZeroTier {
|
|||
/**
|
||||
* Miscellaneous utility functions and global constants
|
||||
*/
|
||||
class OSUtils
|
||||
{
|
||||
class OSUtils {
|
||||
private:
|
||||
#ifdef __APPLE__
|
||||
static clock_serv_t s_machRealtimeClock;
|
||||
|
@ -252,7 +251,10 @@ public:
|
|||
* @param s Data to write
|
||||
* @return True if entire file was successfully written
|
||||
*/
|
||||
static ZT_INLINE bool writeFile(const char *path,const ZeroTier::String &s) { return writeFile(path,s.data(),(unsigned int)s.length()); }
|
||||
static ZT_INLINE bool writeFile(const char* path, const ZeroTier::String& s)
|
||||
{
|
||||
return writeFile(path, s.data(), (unsigned int)s.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Platform default ZeroTier One home path
|
||||
|
|
|
@ -14,31 +14,31 @@
|
|||
#ifndef ZT_THREAD_HPP
|
||||
#define ZT_THREAD_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../core/Constants.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
||||
#include "../core/Mutex.hpp"
|
||||
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../core/Mutex.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
template<typename C>
|
||||
static DWORD WINAPI ___zt_threadMain(LPVOID lpParam)
|
||||
template <typename C> static DWORD WINAPI ___zt_threadMain(LPVOID lpParam)
|
||||
{
|
||||
try {
|
||||
((C*)lpParam)->threadMain();
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Thread
|
||||
{
|
||||
class Thread {
|
||||
public:
|
||||
Thread()
|
||||
{
|
||||
|
@ -46,8 +46,7 @@ public:
|
|||
_tid = 0;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
static inline Thread start(C *instance)
|
||||
template <typename C> static inline Thread start(C* instance)
|
||||
{
|
||||
Thread t;
|
||||
t._th = CreateThread(NULL, 0, &___zt_threadMain<C>, (LPVOID)instance, 0, &t._tid);
|
||||
|
@ -64,7 +63,8 @@ public:
|
|||
GetExitCodeThread(t._th, &ec);
|
||||
if (ec == STILL_ACTIVE)
|
||||
WaitForSingleObject(t._th, 1000);
|
||||
else break;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,10 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
inline operator bool() const { return (_th != NULL); }
|
||||
inline operator bool() const
|
||||
{
|
||||
return (_th != NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE _th;
|
||||
|
@ -94,28 +97,28 @@ private:
|
|||
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
template<typename C>
|
||||
static void *___zt_threadMain(void *instance)
|
||||
template <typename C> static void* ___zt_threadMain(void* instance)
|
||||
{
|
||||
try {
|
||||
((C*)instance)->threadMain();
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
/**
|
||||
* A thread identifier, and static methods to start and join threads
|
||||
*/
|
||||
class Thread
|
||||
{
|
||||
class Thread {
|
||||
public:
|
||||
Thread()
|
||||
{
|
||||
|
@ -141,8 +144,7 @@ public:
|
|||
* @throws std::runtime_error Unable to create thread
|
||||
* @tparam C Class containing threadMain()
|
||||
*/
|
||||
template<typename C>
|
||||
static inline Thread start(C *instance)
|
||||
template <typename C> static inline Thread start(C* instance)
|
||||
{
|
||||
Thread t;
|
||||
pthread_attr_t tattr;
|
||||
|
@ -153,7 +155,8 @@ public:
|
|||
if (pthread_create(&t._tid, &tattr, &___zt_threadMain<C>, instance)) {
|
||||
pthread_attr_destroy(&tattr);
|
||||
throw std::runtime_error("pthread_create() failed, unable to create thread");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
t._started = true;
|
||||
pthread_attr_destroy(&tattr);
|
||||
}
|
||||
|
@ -176,9 +179,15 @@ public:
|
|||
*
|
||||
* @param ms Number of milliseconds to sleep
|
||||
*/
|
||||
static inline void sleep(unsigned long ms) { usleep(ms * 1000); }
|
||||
static inline void sleep(unsigned long ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
inline operator bool() const { return (_started); }
|
||||
inline operator bool() const
|
||||
{
|
||||
return (_started);
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_t _tid;
|
||||
|
|
|
@ -20,15 +20,15 @@ struct prf_ra {
|
|||
} prf_ra;
|
||||
#endif
|
||||
|
||||
#include "../core/Constants.hpp"
|
||||
#include "../core/Mutex.hpp"
|
||||
#include "../core/Containers.hpp"
|
||||
#include "../core/SHA512.hpp"
|
||||
#include "../core/AES.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include "rust-osdep.h"
|
||||
|
||||
#include "../core/AES.hpp"
|
||||
#include "../core/Constants.hpp"
|
||||
#include "../core/Containers.hpp"
|
||||
#include "../core/Mutex.hpp"
|
||||
#include "../core/SHA512.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifndef SIOCAUTOCONF_START
|
||||
#define SIOCAUTOCONF_START _IOWR('i', 132, struct in6_ifreq) /* accept rtadvd on this interface */
|
||||
|
@ -87,13 +87,15 @@ const char *platformDefaultHomePath()
|
|||
bufferSize = GetEnvironmentVariable("ZEROTIER_HOME", &userDefinedPath[0], bufferSize);
|
||||
if (bufferSize) {
|
||||
s_homePath = userDefinedPath;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
char buf[16384];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL, 0, buf))) {
|
||||
ZeroTier::String tmp(buf);
|
||||
tmp.append("\\ZeroTier");
|
||||
s_homePath = tmp;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
s_homePath = "C:\\ZeroTier";
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +104,8 @@ const char *platformDefaultHomePath()
|
|||
|
||||
if (const char* userDefinedPath = getenv("ZEROTIER_HOME")) {
|
||||
s_homePath = userDefinedPath;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
#ifdef __APPLE__
|
||||
s_homePath = "/Library/Application Support/ZeroTier";
|
||||
#else
|
||||
|
@ -126,16 +129,24 @@ const char *platformDefaultHomePath()
|
|||
}
|
||||
|
||||
int64_t msSinceEpoch()
|
||||
{ return ZeroTier::OSUtils::now(); }
|
||||
{
|
||||
return ZeroTier::OSUtils::now();
|
||||
}
|
||||
|
||||
int64_t msMonotonic()
|
||||
{ return ZeroTier::OSUtils::now_monotonic(); }
|
||||
{
|
||||
return ZeroTier::OSUtils::now_monotonic();
|
||||
}
|
||||
|
||||
void lockDownFile(const char* path, int isDir)
|
||||
{ ZeroTier::OSUtils::lockDownFile(path, isDir != 0); }
|
||||
{
|
||||
ZeroTier::OSUtils::lockDownFile(path, isDir != 0);
|
||||
}
|
||||
|
||||
void getSecureRandom(void* buf, unsigned int len)
|
||||
{ ZeroTier::Utils::getSecureRandom(buf, len); }
|
||||
{
|
||||
ZeroTier::Utils::getSecureRandom(buf, len);
|
||||
}
|
||||
|
||||
static ZT_INLINE ZeroTier::AES _makeHttpAuthCipher() noexcept
|
||||
{
|
||||
|
@ -146,9 +157,13 @@ static ZT_INLINE ZeroTier::AES _makeHttpAuthCipher() noexcept
|
|||
static const ZeroTier::AES HTTP_AUTH_CIPHER = _makeHttpAuthCipher();
|
||||
|
||||
void encryptHttpAuthNonce(void* block)
|
||||
{ HTTP_AUTH_CIPHER.encrypt(block, block); }
|
||||
{
|
||||
HTTP_AUTH_CIPHER.encrypt(block, block);
|
||||
}
|
||||
|
||||
void decryptHttpAuthNonce(void* block)
|
||||
{ HTTP_AUTH_CIPHER.decrypt(block, block); }
|
||||
{
|
||||
HTTP_AUTH_CIPHER.decrypt(block, block);
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue