From dcc686a3a77e1ca79a3699fb7e489808a8068b5d Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Sun, 31 May 2020 06:47:56 -0700 Subject: [PATCH] Docs, YAGNI removal, use locator endpoints in peer contact attempts. --- node/AES.cpp | 18 +++++----- node/Peer.cpp | 90 +++++++++++++++++++++++++---------------------- node/Peer.hpp | 9 +++-- node/Protocol.hpp | 13 ++----- 4 files changed, 63 insertions(+), 67 deletions(-) diff --git a/node/AES.cpp b/node/AES.cpp index b13f47fca..f7b617d7a 100644 --- a/node/AES.cpp +++ b/node/AES.cpp @@ -940,7 +940,7 @@ void AES::CTR::finish() noexcept // Software AES and AES key expansion --------------------------------------------------------------------------------- #define readuint32_t(i) Utils::loadBigEndian(i) -#define writeuint32_t(o, v) Utils::storeBigEndian((o),(uint32_t)(v)) +#define writeuint32_t(o, v) Utils::storeBigEndian((o),(uint32_t)(v)) 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, @@ -1048,14 +1048,14 @@ void AES::_encryptSW(const uint8_t in[16], uint8_t out[16]) const noexcept { const uint32_t *const rk = _k.sw.ek; const uint32_t m8 = 0xff; - uint32_t s0 = readuint32_t(in) ^rk[0]; - uint32_t s1 = readuint32_t(in + 4) ^rk[1]; - uint32_t s2 = readuint32_t(in + 8) ^rk[2]; - uint32_t s3 = readuint32_t(in + 12) ^rk[3]; - uint32_t t0 = Te0[s0 >> 24U] ^Te1[(s1 >> 16U) & m8] ^Te2[(s2 >> 8U) & m8] ^Te3[s3 & m8] ^rk[4]; - uint32_t t1 = Te0[s1 >> 24U] ^Te1[(s2 >> 16U) & m8] ^Te2[(s3 >> 8U) & m8] ^Te3[s0 & m8] ^rk[5]; - uint32_t t2 = Te0[s2 >> 24U] ^Te1[(s3 >> 16U) & m8] ^Te2[(s0 >> 8U) & m8] ^Te3[s1 & m8] ^rk[6]; - uint32_t t3 = Te0[s3 >> 24U] ^Te1[(s0 >> 16U) & m8] ^Te2[(s1 >> 8U) & m8] ^Te3[s2 & m8] ^rk[7]; + uint32_t s0 = readuint32_t(in) ^ rk[0]; + uint32_t s1 = readuint32_t(in + 4) ^ rk[1]; + uint32_t s2 = readuint32_t(in + 8) ^ rk[2]; + uint32_t s3 = readuint32_t(in + 12) ^ rk[3]; + uint32_t t0 = Te0[s0 >> 24U] ^Te1[(s1 >> 16U) & m8] ^Te2[(s2 >> 8U) & m8] ^Te3[s3 & m8] ^ rk[4]; + uint32_t t1 = Te0[s1 >> 24U] ^Te1[(s2 >> 16U) & m8] ^Te2[(s3 >> 8U) & m8] ^Te3[s0 & m8] ^ rk[5]; + uint32_t t2 = Te0[s2 >> 24U] ^Te1[(s3 >> 16U) & m8] ^Te2[(s0 >> 8U) & m8] ^Te3[s1 & m8] ^ rk[6]; + uint32_t t3 = Te0[s3 >> 24U] ^Te1[(s0 >> 16U) & m8] ^Te2[(s1 >> 8U) & m8] ^Te3[s2 & m8] ^ rk[7]; s0 = Te0[t0 >> 24U] ^ Te1[(t1 >> 16U) & m8] ^ Te2[(t2 >> 8U) & m8] ^ Te3[t3 & m8] ^ rk[8]; s1 = Te0[t1 >> 24U] ^ Te1[(t2 >> 16U) & m8] ^ Te2[(t3 >> 8U) & m8] ^ Te3[t0 & m8] ^ rk[9]; s2 = Te0[t2 >> 24U] ^ Te1[(t3 >> 16U) & m8] ^ Te2[(t0 >> 8U) & m8] ^ Te3[t1 & m8] ^ rk[10]; diff --git a/node/Peer.cpp b/node/Peer.cpp index d8f1dddab..0f9f402d4 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -36,7 +36,6 @@ Peer::Peer(const RuntimeEnvironment *renv) : m_lastProbeReceived(0), m_alivePathCount(0), m_tryQueue(), - m_tryQueuePtr(m_tryQueue.end()), m_vProto(0), m_vMajor(0), m_vMinor(0), @@ -223,6 +222,9 @@ void Peer::pulse(void *const tPtr,const int64_t now,const bool isRoot) { RWMutex::Lock l(m_lock); + // 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 = false; if ( (m_vProto >= 11) && ( ((now - m_ephemeralPairTimestamp) >= (ZT_SYMMETRIC_KEY_TTL / 2)) || ((m_ephemeralKeys[0])&&(m_ephemeralKeys[0]->odometer() >= (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2))) ) ) { m_ephemeralPair.generate(); @@ -231,36 +233,46 @@ void Peer::pulse(void *const tPtr,const int64_t now,const bool isRoot) needHello = true; } - if (m_tryQueue.empty()&&(m_alivePathCount == 0)) { - InetAddress addr; - if (RR->node->externalPathLookup(tPtr, m_id, -1, addr)) { - if ((addr)&&(RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, addr))) { - RR->t->tryingNewPath(tPtr, 0x84a10000, m_id, addr, InetAddress::NIL, 0, 0, Identity::NIL); - sent(now,m_sendProbe(tPtr,-1,addr,nullptr,0,now)); - } - } - } - + // Prioritize paths and more importantly for here forget dead ones. m_prioritizePaths(now); - if (!m_tryQueue.empty()) { - for(int k=0;k::const_iterator ep(m_locator->endpoints().begin());ep!=m_locator->endpoints().end();++ep) { + if (ep->type == ZT_ENDPOINT_TYPE_IP_UDP) { + RR->t->tryingNewPath(tPtr, 0x84b22322, m_id, ep->ip(), InetAddress::NIL, 0, 0, Identity::NIL); + sent(now,m_sendProbe(tPtr,-1,ep->ip(),nullptr,0,now)); + } + } } - if (likely((now - m_tryQueuePtr->ts) < ZT_PATH_ALIVE_TIMEOUT)) { - if (m_tryQueuePtr->target.isInetAddr()) { + InetAddress addr; + if (RR->node->externalPathLookup(tPtr, m_id, -1, addr)) { + if ((addr)&&(RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, addr))) { + RR->t->tryingNewPath(tPtr, 0x84a10000, m_id, addr, InetAddress::NIL, 0, 0, Identity::NIL); + sent(now,m_sendProbe(tPtr,-1,addr,nullptr,0,now)); + } + } + } + } else { + // Attempt up to ZT_NAT_T_MAX_QUEUED_ATTEMPTS_PER_PULSE queued addresses. + + for (int k=0;kaddress().ipsEqual(m_tryQueuePtr->target.ip())) + if (m_paths[i]->address().ipsEqual(qi.target.ip())) goto skip_tryQueue_item; } - if ((m_alivePathCount == 0) && (m_tryQueuePtr->breakSymmetricBFG1024) && (RR->node->natMustDie())) { + if ((m_alivePathCount == 0) && (qi.natMustDie) && (RR->node->natMustDie())) { // Attempt aggressive NAT traversal if both requested and enabled. This sends a probe // to all ports under 1024, which assumes that the peer has bound to such a port and // has attempted to initiate a connection through it. This can traverse a decent number @@ -279,15 +291,17 @@ void Peer::pulse(void *const tPtr,const int64_t now,const bool isRoot) ports[b] = tmp; } } - sent(now,m_sendProbe(tPtr, -1, m_tryQueuePtr->target.ip(), ports, 1023, now)); + sent(now,m_sendProbe(tPtr, -1, qi.target.ip(), ports, 1023, now)); } else { - sent(now,m_sendProbe(tPtr, -1, m_tryQueuePtr->target.ip(), nullptr, 0, now)); + sent(now,m_sendProbe(tPtr, -1, qi.target.ip(), nullptr, 0, now)); } } } skip_tryQueue_item: - m_tryQueue.erase(m_tryQueuePtr++); + m_tryQueue.pop_front(); + if (m_tryQueue.empty()) + break; } } @@ -323,7 +337,7 @@ skip_tryQueue_item: } } -void Peer::contact(void *tPtr,const int64_t now,const Endpoint &ep,const bool breakSymmetricBFG1024) +void Peer::contact(void *tPtr,const int64_t now,const Endpoint &ep,const bool natMustDie) { static uint8_t foo = 0; RWMutex::Lock l(m_lock); @@ -336,25 +350,15 @@ void Peer::contact(void *tPtr,const int64_t now,const Endpoint &ep,const bool br ++foo; } - const bool wasEmpty = m_tryQueue.empty(); - if (!wasEmpty) { - for(List::iterator i(m_tryQueue.begin());i!=m_tryQueue.end();++i) { - if (i->target == ep) { - i->ts = now; - i->breakSymmetricBFG1024 = breakSymmetricBFG1024; - return; - } + for(List::iterator i(m_tryQueue.begin());i!=m_tryQueue.end();++i) { + if (i->target == ep) { + i->ts = now; + i->natMustDie = natMustDie; + return; } } -#ifdef __CPP11__ - m_tryQueue.emplace_back(now, ep, breakSymmetricBFG1024); -#else - _tryQueue.push_back(_TryQueueItem(now,ep,breakSymmetricBFG1024)); -#endif - - if (wasEmpty) - m_tryQueuePtr = m_tryQueue.begin(); + m_tryQueue.push_back(p_TryQueueItem(now, ep, natMustDie)); } void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,int64_t now) diff --git a/node/Peer.hpp b/node/Peer.hpp index 5adb21f45..bed66e2c9 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -524,19 +524,18 @@ private: // Addresses recieved via PUSH_DIRECT_PATHS etc. that we are scheduled to try. struct p_TryQueueItem { - ZT_INLINE p_TryQueueItem() : target(), ts(0), breakSymmetricBFG1024(false) + ZT_INLINE p_TryQueueItem() : ts(0), target(), natMustDie(false) {} - ZT_INLINE p_TryQueueItem(const int64_t now, const Endpoint &t, const bool bfg) : target(t), ts(now), breakSymmetricBFG1024(bfg) + ZT_INLINE p_TryQueueItem(const int64_t now, const Endpoint &t, const bool nmd) : ts(now), target(t), natMustDie(nmd) {} - Endpoint target; int64_t ts; - bool breakSymmetricBFG1024; + Endpoint target; + bool natMustDie; }; List m_tryQueue; - List::iterator m_tryQueuePtr; // loops over _tryQueue like a circular buffer uint16_t m_vProto; uint16_t m_vMajor; diff --git a/node/Protocol.hpp b/node/Protocol.hpp index c69be4a25..038378add 100644 --- a/node/Protocol.hpp +++ b/node/Protocol.hpp @@ -122,7 +122,7 @@ /** * Minimum supported protocol version */ -#define ZT_PROTO_VERSION_MIN 8 +#define ZT_PROTO_VERSION_MIN 9 /** * Maximum allowed packet size (can technically be increased up to 16384) @@ -154,7 +154,7 @@ #define ZT_PROTO_MAX_HOPS 7 /** - * NONE/Poly1305 (legacy) + * NONE/Poly1305 (used for HELLO for backward compatibility) */ #define ZT_PROTO_CIPHER_SUITE__POLY1305_NONE 0 @@ -164,13 +164,7 @@ #define ZT_PROTO_CIPHER_SUITE__POLY1305_SALSA2012 1 /** - * No encryption or authentication at all! - * - * This is used for trusted paths. The MAC field will contain the - * 64-bit trusted path ID. Both sides of a link must be configured - * to trust a given network with the same trusted path ID for this - * to be used. It's a high performance mode designed for use on - * secure LANs. + * Deprecated, not currently used. */ #define ZT_PROTO_CIPHER_SUITE__NONE 2 @@ -250,7 +244,6 @@ #define ZT_PROTO_PACKET_VERB_INDEX 27 #define ZT_PROTO_HELLO_NODE_META_INSTANCE_ID "i" -#define ZT_PROTO_HELLO_NODE_META_PREFERRED_CIPHER_MODE "a" #define ZT_PROTO_HELLO_NODE_META_LOCATOR "l" #define ZT_PROTO_HELLO_NODE_META_SOFTWARE_VENDOR "s" #define ZT_PROTO_HELLO_NODE_META_COMPLIANCE "c"