Just about everything refactored for new Protocol/Buf code except Switch.

This commit is contained in:
Adam Ierymenko 2020-02-03 16:18:33 -08:00
parent df346a6df6
commit 7d11522768
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
25 changed files with 214 additions and 239 deletions

View file

@ -522,7 +522,7 @@ void EmbeddedNetworkController::request(
const InetAddress &fromAddr,
uint64_t requestPacketId,
const Identity &identity,
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData)
const Dictionary &metaData)
{
if (((!_signingId)||(!_signingId.hasPrivate()))||(_signingId.address().toInt() != (nwid >> 24))||(!_sender))
return;
@ -1104,7 +1104,7 @@ void EmbeddedNetworkController::onNetworkUpdate(const void *db,uint64_t networkI
const int64_t now = OSUtils::now();
std::lock_guard<std::mutex> l(_memberStatus_l);
for(auto i=_memberStatus.begin();i!=_memberStatus.end();++i) {
if ((i->first.networkId == networkId)&&(i->second.online(now))&&(i->second.lastRequestMetaData))
if ((i->first.networkId == networkId)&&(i->second.online(now))&&(i->second.lastRequestMetaData.size() > 0))
request(networkId,InetAddress(),0,i->second.identity,i->second.lastRequestMetaData);
}
}
@ -1115,7 +1115,7 @@ void EmbeddedNetworkController::onNetworkMemberUpdate(const void *db,uint64_t ne
try {
std::lock_guard<std::mutex> l(_memberStatus_l);
_MemberStatus &ms = _memberStatus[_MemberStatusKey(networkId,memberId)];
if ((ms.online(OSUtils::now()))&&(ms.lastRequestMetaData))
if ((ms.online(OSUtils::now()))&&(ms.lastRequestMetaData.size() > 0))
request(networkId,InetAddress(),0,ms.identity,ms.lastRequestMetaData);
} catch ( ... ) {}
}
@ -1139,7 +1139,7 @@ void EmbeddedNetworkController::_request(
const InetAddress &fromAddr,
uint64_t requestPacketId,
const Identity &identity,
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData)
const Dictionary &metaData)
{
char nwids[24];
DB::NetworkSummaryInfo ns;
@ -1212,19 +1212,18 @@ void EmbeddedNetworkController::_request(
autoAuthCredentialType = "public";
} else {
char presentedAuth[512];
if (metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH,presentedAuth,sizeof(presentedAuth)) > 0) {
presentedAuth[511] = (char)0; // sanity check
if ((strlen(presentedAuth) > 6)&&(!strncmp(presentedAuth,"token:",6))) {
const char *const presentedToken = presentedAuth + 6;
json authTokens(network["authTokens"]);
json &tokenExpires = authTokens[presentedToken];
if (tokenExpires.is_number()) {
if ((tokenExpires == 0)||(tokenExpires > now)) {
authorized = true;
autoAuthorized = true;
autoAuthCredentialType = "token";
autoAuthCredential = presentedToken;
}
metaData.getS(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH,presentedAuth,sizeof(presentedAuth));
presentedAuth[511] = 0; // sanity check, make sure always terminated
if ((strlen(presentedAuth) > 6)&&(!strncmp(presentedAuth,"token:",6))) {
const char *const presentedToken = presentedAuth + 6;
json authTokens(network["authTokens"]);
json &tokenExpires = authTokens[presentedToken];
if (tokenExpires.is_number()) {
if ((tokenExpires == 0)||(tokenExpires > now)) {
authorized = true;
autoAuthorized = true;
autoAuthCredentialType = "token";
autoAuthCredential = presentedToken;
}
}
}
@ -1296,6 +1295,7 @@ void EmbeddedNetworkController::_request(
nc->credentialTimeMaxDelta = credentialtmd;
nc->revision = OSUtils::jsonInt(network["revision"],0ULL);
nc->issuedTo = identity.address();
memcpy(nc->issuedToIdentityHash,identity.hash(),sizeof(nc->issuedToIdentityHash));
if (OSUtils::jsonBool(network["enableBroadcast"],true)) nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST;
Utils::scopy(nc->name,sizeof(nc->name),OSUtils::jsonString(network["name"],"").c_str());
nc->mtu = std::max(std::min((unsigned int)OSUtils::jsonInt(network["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU);

View file

@ -64,7 +64,7 @@ public:
const InetAddress &fromAddr,
uint64_t requestPacketId,
const Identity &identity,
const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
const Dictionary &metaData);
unsigned int handleControlPlaneHttpGET(
const std::vector<std::string> &path,
@ -87,7 +87,7 @@ public:
virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId);
private:
void _request(uint64_t nwid,const InetAddress &fromAddr,uint64_t requestPacketId,const Identity &identity,const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData);
void _request(uint64_t nwid,const InetAddress &fromAddr,uint64_t requestPacketId,const Identity &identity,const Dictionary &metaData);
void _startThreads();
struct _RQEntry
@ -96,31 +96,34 @@ private:
uint64_t requestPacketId;
InetAddress fromAddr;
Identity identity;
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> metaData;
Dictionary metaData;
enum {
RQENTRY_TYPE_REQUEST = 0
} type;
};
struct _MemberStatusKey
{
_MemberStatusKey() : networkId(0),nodeId(0) {}
_MemberStatusKey(const uint64_t nwid,const uint64_t nid) : networkId(nwid),nodeId(nid) {}
ZT_ALWAYS_INLINE _MemberStatusKey() : networkId(0),nodeId(0) {}
ZT_ALWAYS_INLINE _MemberStatusKey(const uint64_t nwid,const uint64_t nid) : networkId(nwid),nodeId(nid) {}
uint64_t networkId;
uint64_t nodeId;
inline bool operator==(const _MemberStatusKey &k) const { return ((k.networkId == networkId)&&(k.nodeId == nodeId)); }
};
struct _MemberStatus
{
_MemberStatus() : lastRequestTime(0),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
ZT_ALWAYS_INLINE _MemberStatus() : lastRequestTime(0),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
uint64_t lastRequestTime;
int vMajor,vMinor,vRev,vProto;
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> lastRequestMetaData;
Dictionary lastRequestMetaData;
Identity identity;
inline bool online(const int64_t now) const { return ((now - lastRequestTime) < (ZT_NETWORK_AUTOCONF_DELAY * 2)); }
};
struct _MemberStatusHash
{
inline std::size_t operator()(const _MemberStatusKey &networkIdNodeId) const
ZT_ALWAYS_INLINE std::size_t operator()(const _MemberStatusKey &networkIdNodeId) const
{
return (std::size_t)(networkIdNodeId.networkId + networkIdNodeId.nodeId);
}

View file

@ -26,11 +26,7 @@
#include "../../node/InetAddress.hpp"
#include "../../node/Utils.hpp"
#include "../../node/Identity.hpp"
#include "../../node/Buffer.hpp"
#include "../../node/Salsa20.hpp"
#include "../../node/AES.hpp"
#include "../../node/Locator.hpp"
#include "../../node/NetworkConfig.hpp"
#include "../../node/Dictionary.hpp"
#include "../../node/SHA512.hpp"
#include "../../node/C25519.hpp"
@ -126,6 +122,7 @@ static const C25519TestVector C25519_TEST_VECTORS[ZT_NUM_C25519_TEST_VECTORS] =
{{0x25,0x87,0x1e,0x6f,0xe8,0xd0,0xde,0x1d,0xd5,0xf2,0xd3,0x5b,0xff,0x9e,0x67,0x99,0x60,0xb4,0x0e,0xb7,0x98,0x1b,0x2a,0x3a,0x9c,0xec,0xc1,0xe1,0x2e,0x2b,0xc0,0x3e,0x3c,0xfb,0x64,0x91,0x72,0xc6,0x7e,0x57,0x47,0x00,0x97,0xbf,0x8e,0x0e,0xbf,0xad,0xd9,0x28,0x86,0x7c,0xfd,0x41,0x91,0xae,0x2d,0xee,0xc0,0xb2,0x32,0x7d,0x99,0x7d},{0x63,0xc1,0xf9,0x61,0x9c,0x9e,0x1a,0xd7,0xca,0xa3,0x71,0xd6,0x34,0x3d,0xa7,0x08,0x36,0x0c,0xec,0x37,0x35,0x94,0x1a,0x45,0xa9,0xfa,0xf2,0xb5,0x25,0x92,0xbf,0xd1,0x1e,0xca,0xdd,0x5a,0x23,0xad,0x9e,0x45,0xc3,0x66,0xcb,0x8f,0xda,0xa3,0xd1,0xe6,0x27,0x38,0x11,0x54,0x67,0x31,0x03,0x64,0x35,0xe0,0x68,0x0b,0x93,0xee,0x81,0x17},{0x8b,0x01,0xe9,0x99,0x54,0x54,0x73,0x15,0x0b,0xac,0x38,0x7b,0xe9,0xe3,0x17,0x4f,0x02,0x3e,0xe3,0x8e,0xda,0x41,0xa0,0x9d,0x10,0xe0,0xda,0x11,0xfe,0xec,0x2f,0x42,0xe7,0xc8,0xb3,0xde,0x2f,0x7b,0xfd,0xdf,0x7c,0x34,0x3b,0x5e,0xac,0x22,0x8c,0x99,0x3d,0xa1,0xa9,0xd9,0x81,0xb6,0x51,0xc8,0xaf,0x3e,0x75,0xed,0x45,0xcf,0xf7,0xb9},{0xaf,0xe9,0x9c,0x16,0x4a,0x8f,0x3b,0x0f,0xef,0x71,0x2f,0xaa,0x8d,0x7d,0xce,0xed,0xea,0x31,0x93,0xaf,0x2c,0x75,0xc6,0xfa,0xda,0x3e,0xa6,0xea,0x2a,0x3e,0x7b,0x72,0xb6,0xf8,0xd7,0x9a,0x88,0xcb,0x0b,0x81,0x97,0x24,0x29,0x3b,0x11,0x23,0x69,0xc2,0xff,0x98,0x39,0x25,0x99,0xae,0xe1,0x07,0x3e,0x97,0xde,0x10,0x21,0x23,0x7a,0x2d},{0xbe,0x2f,0xb9,0x4c,0x41,0x5a,0x9a,0xf6,0xfb,0xf8,0x26,0x9d,0x81,0x7f,0x39,0x91,0xaf,0x5b,0xf1,0xd7,0x93,0x0a,0xdf,0x18,0x19,0x4a,0x80,0x74,0x14,0x98,0x2b,0xf2,0x3b,0x25,0xc5,0xe8,0xfc,0x07,0x3f,0x5d,0xa1,0x39,0x27,0x4e,0x1c,0xd2,0x7a,0xfe,0x3e,0x7b,0x03,0x35,0x15,0x9e,0x35,0x2b,0xd0,0xbe,0x67,0x48,0x42,0xdd,0xa4,0xdd},{0xbd,0xcd,0xd7,0xbf,0xb1,0x0a,0xdb,0x9f,0x85,0x42,0xba,0xf4,0xc8,0xff,0xb0,0xe1,0x9a,0x18,0x6d,0x1a,0xe0,0x37,0xc1,0xa2,0xe1,0x1c,0x38,0x55,0x14,0xbf,0x64,0x67,0x84,0x47,0xb6,0x0a,0xf6,0x93,0xf1,0x10,0xab,0x09,0xf0,0x60,0x84,0xe2,0x4e,0x4b,0x5e,0xa2,0xd2,0xd1,0x19,0x22,0xd7,0xc4,0x85,0x13,0x23,0xa3,0x6a,0xb6,0x75,0x0f,0x43,0xe6,0xde,0x7b,0x67,0x2a,0x73,0x77,0x9e,0xb4,0x94,0x6c,0xc3,0x9a,0x67,0x51,0xcf,0xe9,0x47,0x46,0x0e,0x3a,0x12,0x7d,0x7c,0x66,0x73,0x6c,0xd5,0x4a,0x21,0x4d},{0x89,0x7e,0xd0,0xbf,0x2e,0x9f,0x0c,0xff,0x6e,0x56,0x25,0x9b,0x79,0x99,0x52,0x27,0xc2,0x3a,0xaa,0xf0,0x47,0x6d,0xed,0x05,0xa1,0xeb,0x9c,0x92,0x28,0x7f,0x1b,0xc8,0x1c,0x57,0x76,0xab,0x05,0xe3,0xd3,0xb7,0xa3,0xf5,0xac,0xa8,0x21,0x33,0x7c,0xb7,0xe7,0xc2,0xd0,0x25,0x6f,0xdf,0x34,0xd1,0xb0,0x34,0x41,0x46,0x30,0x9c,0x76,0x07,0x43,0xe6,0xde,0x7b,0x67,0x2a,0x73,0x77,0x9e,0xb4,0x94,0x6c,0xc3,0x9a,0x67,0x51,0xcf,0xe9,0x47,0x46,0x0e,0x3a,0x12,0x7d,0x7c,0x66,0x73,0x6c,0xd5,0x4a,0x21,0x4d}}
};
/*
static const uint8_t AES_TEST_VECTOR_0_KEY[32] = { 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 };
static const uint8_t AES_TEST_VECTOR_0_IN[16] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a };
static const uint8_t AES_TEST_VECTOR_0_OUT[16] = { 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c,0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 };
@ -144,6 +141,7 @@ static const uint8_t AES_GMAC_VECTOR_2_KEY[32] = { 0x63,0x2f,0xd9,0x48,0xcf,0x70
static const uint8_t AES_GMAC_VECTOR_2_IV[12] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b };
static const uint8_t AES_GMAC_VECTOR_2_IN[541] = { 0xc8,0x36,0x38,0xe8,0x53,0xc8,0x86,0xa3,0xe3,0xad,0x9e,0x2a,0x91,0x47,0xb9,0x51,0xad,0xf7,0x78,0x89,0x9a,0xeb,0x80,0x41,0x67,0xa9,0x16,0xc4,0x93,0xcc,0x77,0x3d,0x8c,0xcf,0x4d,0xb5,0x0b,0xda,0xfd,0xc2,0x8c,0x83,0x5d,0x66,0x43,0x74,0x21,0xbd,0xc4,0xab,0x41,0xd8,0x40,0x53,0x34,0xe8,0x05,0xcb,0x89,0x45,0x09,0xb0,0xa4,0xa6,0x04,0x95,0x19,0x2c,0xab,0x94,0xe1,0x8d,0x7b,0x59,0x8b,0xb9,0x31,0xae,0x3c,0x25,0xd3,0x23,0xab,0x8f,0x95,0xa3,0x8b,0xa5,0xc1,0x66,0x8b,0x57,0xe4,0x88,0x70,0xc9,0xe0,0xa1,0x16,0x39,0xf8,0x12,0xb3,0xe5,0x95,0x38,0x3a,0x01,0x1d,0xcc,0xc0,0xc3,0xa9,0x1c,0x72,0xa7,0x46,0x79,0x51,0x05,0xb2,0x85,0x5a,0x97,0x16,0x97,0xa6,0x85,0xa4,0xf2,0x0b,0x3c,0x90,0x52,0xa3,0xe0,0xbe,0xad,0x06,0x1b,0x8e,0x04,0x22,0xeb,0x3a,0x48,0xb9,0x84,0x24,0x0b,0x24,0x42,0xd9,0xed,0x6b,0x5c,0xc1,0xb6,0x2e,0xa5,0xc0,0x07,0xfe,0x3e,0xbc,0x9a,0x92,0x26,0xb5,0xa6,0x5f,0x09,0x13,0x85,0x5a,0xcf,0x61,0x56,0x65,0x0f,0x4c,0x64,0x79,0xfa,0x0a,0xcf,0xc0,0x95,0x8d,0x4d,0xc6,0xbe,0xee,0xb3,0x67,0xd8,0xa7,0x40,0x90,0x61,0xe3,0xba,0xcb,0x18,0xe0,0x61,0x7b,0x33,0x86,0xf7,0xef,0x64,0xe5,0x36,0xf0,0x9c,0xb6,0x34,0xb1,0xe1,0x2a,0xd8,0xd8,0x5e,0x6b,0x61,0x92,0xa0,0x8e,0x04,0x7b,0xbf,0xa5,0x84,0x39,0x3a,0xe0,0x27,0xc7,0xb0,0x83,0x88,0x4f,0x3e,0x49,0x14,0xaa,0x34,0xde,0xb4,0xbb,0x4c,0xe4,0xbf,0xae,0x9a,0xf9,0x88,0x7a,0x1f,0x18,0xa0,0x8c,0x60,0xc0,0x5c,0x46,0xa1,0xd1,0x36,0x99,0x60,0x9b,0x73,0xa2,0x9a,0x0b,0x8d,0x6e,0x2f,0xe1,0x58,0x7a,0x39,0x71,0xed,0xfc,0x34,0xe4,0x98,0x57,0x7e,0x86,0xf1,0xe5,0x00,0x7d,0x1b,0x6a,0xfa,0xf8,0x6e,0x7b,0x12,0x44,0x04,0x60,0x02,0x81,0x12,0x09,0x00,0xb4,0x35,0x9e,0x03,0x73,0x79,0x9b,0x13,0xc5,0xd7,0x0e,0xce,0x49,0x87,0x48,0x1a,0x67,0x89,0x93,0xef,0xd1,0xdf,0x2d,0x48,0x6d,0x30,0xd5,0xec,0x49,0xfe,0x15,0x1b,0xa6,0x2b,0x6c,0x08,0x8e,0x39,0x73,0x68,0x87,0xa7,0x43,0x28,0x16,0x77,0x86,0xd1,0xcb,0x13,0xe4,0xd3,0xda,0x63,0xcd,0x3a,0x2a,0x35,0xd5,0xfa,0x36,0x67,0xc8,0x4c,0x6b,0xa1,0x8a,0xaf,0x7b,0x4c,0x43,0xb0,0x2f,0x4a,0xcc,0xc0,0x11,0xc6,0x30,0x8e,0xa3,0xd2,0x4a,0x1b,0x2a,0x4f,0xec,0x97,0x83,0xa6,0x4c,0xee,0x51,0xaf,0x06,0x0a,0x1d,0x80,0xd9,0xcf,0xb7,0x69,0x23,0x15,0x3a,0x26,0x04,0x34,0x33,0x76,0x30,0x9f,0xfb,0x56,0xb4,0x26,0xee,0xfa,0x54,0x6c,0x18,0xf9,0xd5,0x32,0x5d,0x03,0xcb,0x2c,0x20,0x30,0x0c,0xa0,0xbb,0xde,0x01,0x77,0x65,0xb0,0x18,0x30,0xd2,0x55,0x9f,0x9b,0xcf,0xb8,0x9b,0xb4,0xbc,0x0b,0x49,0x52,0x53,0x30,0x48,0xa5,0x12,0xe5,0x3b,0x47,0x84,0xff,0xf1,0x53,0x5d,0x5c,0x04,0x70,0x63,0x91,0xc3,0xc0,0xf0,0xea,0xcb,0x44,0x4f,0x8c,0x85,0x42,0x6a,0xc7,0xfa,0xc7,0xb5,0x30,0x03,0x12,0x65,0xca,0xba,0x4f,0x67,0xbb,0xef,0xb6,0xc6,0x3f,0x19,0xe2,0xb5,0x4b,0x8c,0xfc,0x9e,0x18,0xb0,0x33,0x89,0x6e,0xde,0x61,0x0a,0xe3,0x5e,0xa3,0x5d,0x2e,0x80,0x3e,0x53,0x67,0xfb,0x7b,0x7a,0xbf,0xd5,0xf4,0x47 };
static const uint8_t AES_GMAC_VECTOR_2_OUT[16] = { 0x67,0x39,0x4f,0x00,0x04,0x28,0xaf,0xe9,0xb4,0x2e,0xb5,0x3c,0x42,0x24,0x86,0xa3 };
*/
extern "C" int ZT_TestCrypto()
{
@ -443,7 +441,6 @@ extern "C" int ZT_TestCrypto()
extern "C" int ZT_TestIdentity()
{
Identity id;
Buffer<512> buf;
char buf2[1024];
std::cout << "[identity] Validate known-good identity... "; std::cout.flush();
@ -490,6 +487,7 @@ extern "C" int ZT_TestIdentity()
}
}
/*
{
Identity id2;
buf.clear();
@ -517,6 +515,7 @@ extern "C" int ZT_TestIdentity()
return -1;
}
}
*/
{
Identity id2;
@ -634,60 +633,6 @@ extern "C" int ZT_TestOther()
std::cout << " " << InetAddress("").toString(buf);
std::cout << ZT_EOL_S;
{
std::cout << "[other] Testing/fuzzing Dictionary... "; std::cout.flush();
for(int k=0;k<250;++k) {
Dictionary<8194> *test = new Dictionary<8194>();
char key[32][16];
char value[32][64];
memset(key, 0, sizeof(key));
memset(value, 0, sizeof(value));
for(unsigned int q=0;q<32;++q) {
Utils::hex((uint32_t)((Utils::random() % 1000) + (q * 1000)),key[q]);
int r = (int)(Utils::random() % 64);
for(int x=0;x<r;++x)
value[q][x] = ("0123456789\0\t\r\n= ")[Utils::random() % 16];
value[q][r] = (char)0;
test->add(key[q],value[q],r);
}
for(unsigned int q=0;q<1024;++q) {
int r = (int)(Utils::random() % 32);
char tmp[128];
if (test->get(key[r],tmp,sizeof(tmp)) >= 0) {
if (strcmp(value[r],tmp)) {
std::cout << "FAILED (invalid value '" << value[r] << "' != '" << tmp << "')!" ZT_EOL_S;
return -1;
}
} else {
std::cout << "FAILED (can't find key '" << key[r] << "')!" ZT_EOL_S;
return -1;
}
}
delete test;
}
int foo = 0;
volatile int *volatile bar = &foo; // force compiler not to optimize out test.get() below
for(int k=0;k<200;++k) {
int r = rand() % 8194;
unsigned char *tmp = new unsigned char[8194];
for(int q=0;q<r;++q)
tmp[q] = (unsigned char)((rand() % 254) + 1); // don't put nulls since those will always just terminate scan
tmp[r] = (r % 32) ? (char)(rand() & 0xff) : (char)0; // every 32nd iteration don't terminate the string maybe...
Dictionary<8194> *test = new Dictionary<8194>((const char *)tmp);
for(unsigned int q=0;q<100;++q) {
char tmp[128];
for(unsigned int x=0;x<128;++x)
tmp[x] = (char)(rand() & 0xff);
tmp[127] = (char)0;
char value[8194];
*bar += test->get(tmp,value,sizeof(value));
}
delete test;
delete[] tmp;
}
std::cout << "PASS (junk value to prevent optimization-out of test: " << foo << ")" ZT_EOL_S;
}
std::cout.flush();
return 0;
}

View file

@ -15,23 +15,25 @@
#define ZT_ATOMICCOUNTER_HPP
#include "Constants.hpp"
#include "TriviallyCopyable.hpp"
#ifndef __GNUC__
#include <atomic>
#include <intrin.h>
#endif
namespace ZeroTier {
/**
* Simple atomic counter
* Simple atomic integer used for reference and other counters
*
* @tparam T Type of underlying integer (default: int)
*/
template<typename T = int>
class AtomicCounter
class AtomicCounter : public TriviallyCopyable
{
public:
explicit ZT_ALWAYS_INLINE AtomicCounter(T iv = T(0)) : _v(iv) {}
ZT_ALWAYS_INLINE AtomicCounter() : _v(0) {}
explicit ZT_ALWAYS_INLINE AtomicCounter(T iv) : _v(iv) {}
ZT_ALWAYS_INLINE T load() const
{
@ -42,10 +44,7 @@ public:
#endif
}
ZT_ALWAYS_INLINE void zero()
{
_v = T(0);
}
ZT_ALWAYS_INLINE void zero() { _v = 0; }
ZT_ALWAYS_INLINE T operator++()
{

View file

@ -19,6 +19,7 @@
#include "Utils.hpp"
#include "SharedPtr.hpp"
#include "Mutex.hpp"
#include "TriviallyCopyable.hpp"
#include <cstdint>
#include <cstring>
@ -113,7 +114,7 @@ public:
/**
* Slice is almost exactly like the built-in slice data structure in Go
*/
struct Slice
struct Slice : TriviallyCopyable
{
ZT_ALWAYS_INLINE Slice(const SharedPtr<Buf> &b_,const unsigned int s_,const unsigned int e_) : b(b_),s(s_),e(e_) {}
ZT_ALWAYS_INLINE Slice() : b(),s(0),e(0) {}

View file

@ -33,7 +33,7 @@ void CertificateOfOwnership::addThing(const MAC &mac)
{
if (_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return;
_thingTypes[_thingCount] = THING_MAC_ADDRESS;
mac.copyTo(_thingValues[_thingCount],6);
mac.copyTo(_thingValues[_thingCount]);
++_thingCount;
}

View file

@ -88,6 +88,7 @@ public:
struct Result
{
ZT_ALWAYS_INLINE Result() : message(),messageFragmentCount(0),error(Defragmenter::ERR_NONE) {}
explicit ZT_ALWAYS_INLINE Result(const Defragmenter::ErrorCode e) : message(),messageFragmentCount(0),error(e) {}
/**
* Fully assembled message as a series of slices of fragments
@ -186,25 +187,21 @@ public:
const unsigned long messageQueueSizeTarget,
const unsigned long messageQueueSizeGCTrigger)
{
Result r;
// Sanity checks for malformed fragments or invalid input parameters.
if ((fragmentNo >= totalFragmentsExpected)||(totalFragmentsExpected > MF)||(totalFragmentsExpected == 0)) {
r.error = ERR_INVALID_FRAGMENT;
return r;
}
if ((fragmentNo >= totalFragmentsExpected)||(totalFragmentsExpected > MF)||(totalFragmentsExpected == 0))
return Result(ERR_INVALID_FRAGMENT);
// If there is only one fragment just return that fragment and we are done.
if (totalFragmentsExpected < 2) {
if (fragmentNo == 0) {
Result r;
r.message[0].b.move(fragment);
r.message[0].s = fragmentDataIndex;
r.message[0].e = fragmentDataSize;
r.messageFragmentCount = 1;
return r;
} else {
r.error = ERR_INVALID_FRAGMENT;
return r;
return Result(ERR_INVALID_FRAGMENT);
}
}
@ -246,8 +243,7 @@ public:
_messages_l.lock();
_messages.clear();
_messages_l.unlock();
r.error = ERR_OUT_OF_MEMORY;
return r;
return Result(ERR_OUT_OF_MEMORY);
}
}
}
@ -260,8 +256,7 @@ public:
RWMutex::Lock ml(_messages_l);
e = &(_messages[messageId]);
} catch ( ... ) {
r.error = ERR_OUT_OF_MEMORY;
return r;
return Result(ERR_OUT_OF_MEMORY);
}
e->id = messageId;
}
@ -292,8 +287,7 @@ public:
}
via->_inboundFragmentedMessages_l.unlock();
if (tooManyPerPath) {
r.error = ERR_TOO_MANY_FRAGMENTS_FOR_PATH;
return r;
return Result(ERR_TOO_MANY_FRAGMENTS_FOR_PATH);
}
}
@ -305,11 +299,9 @@ public:
// data would just mean the transfer is corrupt and would be detected
// later e.g. by packet MAC check. Other use cases of this code like
// network configs check each fragment so this basically can't happen.
Buf<>::Slice &s = e->fragment[fragmentNo];
if (s.b) {
r.error = ERR_DUPLICATE_FRAGMENT;
return r;
}
Buf<>::Slice &s = e->result.message[fragmentNo];
if (s.b)
return Result(ERR_DUPLICATE_FRAGMENT);
// Take ownership of fragment, setting 'fragment' pointer to NULL. The simple
// transfer of the pointer avoids a synchronized increment/decrement of the object's
@ -319,7 +311,7 @@ public:
s.e = fragmentDataIndex + fragmentDataSize;
// If we now have all fragments then assemble them.
if (++e->fragmentCount >= totalFragmentsExpected) {
if (++e->result.messageFragmentCount >= totalFragmentsExpected) {
// This message is done so de-register it with its path if one is associated.
if (e->via) {
e->via->_inboundFragmentedMessages_l.lock();
@ -328,18 +320,10 @@ public:
e->via.zero();
}
// PERFORMANCE HACK: SharedPtr<> is introspective and only holds a pointer, so we
// can 'move' the pointers it holds very quickly by bulk copying the source
// slices and then zeroing the originals. This is only okay if the destination
// currently holds no pointers, which should always be the case. Don't try this
// at home kids.
unsigned int msize = e->fragmentCount * sizeof(Buf<>::Slice);
memcpy(reinterpret_cast<void *>(r.message),reinterpret_cast<const void *>(e->fragment),msize);
memset(reinterpret_cast<void *>(e->fragment),0,msize);
r.messageFragmentCount = e->fragmentCount;
return e->result;
}
return r;
return Result(ERR_NONE);
}
/**
@ -354,7 +338,7 @@ public:
private:
struct _E
{
ZT_ALWAYS_INLINE _E() : id(0),lastUsed(0),via(),fragmentCount(0) {}
ZT_ALWAYS_INLINE _E() : id(0),lastUsed(0),via() {}
ZT_ALWAYS_INLINE ~_E()
{
// Ensure that this entry is not in use while it is being deleted!
@ -369,8 +353,7 @@ private:
uint64_t id;
volatile int64_t lastUsed;
SharedPtr<Path> via;
Buf<>::Slice fragment[MF];
unsigned int fragmentCount;
Result result;
Mutex lock;
};

View file

@ -53,10 +53,7 @@ public:
ZT_ALWAYS_INLINE Endpoint() { memoryZero(this); }
explicit ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa)
{
*this = sa;
}
explicit ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) { *this = sa; }
ZT_ALWAYS_INLINE Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) :
_t(ZEROTIER)
@ -74,9 +71,7 @@ public:
explicit ZT_ALWAYS_INLINE Endpoint(const char *url) :
_t(URL)
{
Utils::scopy(_v.url,sizeof(_v.url),url);
}
{ Utils::scopy(_v.url,sizeof(_v.url),url); }
ZT_ALWAYS_INLINE Endpoint &operator=(const InetAddress &sa)
{

View file

@ -358,7 +358,7 @@ private:
static ZT_ALWAYS_INLINE unsigned long _hc(const uint32_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
static ZT_ALWAYS_INLINE unsigned long _hc(const uint16_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
static ZT_ALWAYS_INLINE unsigned long _hc(const uint8_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
static ZT_ALWAYS_INLINE unsigned long _hc(const int64_t i) { return (unsigned long)(i ^ (i >> 32U)); }
static ZT_ALWAYS_INLINE unsigned long _hc(const int64_t i) { return (unsigned long)((unsigned long long)i ^ ((unsigned long long)i >> 32U)); }
static ZT_ALWAYS_INLINE unsigned long _hc(const int32_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
static ZT_ALWAYS_INLINE unsigned long _hc(const int16_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
static ZT_ALWAYS_INLINE unsigned long _hc(const int8_t i) { return ((unsigned long)i * (unsigned long)0x9e3779b1); }

View file

@ -336,7 +336,7 @@ ZT_ALWAYS_INLINE bool _doOK(IncomingPacket &p,const RuntimeEnvironment *const RR
networkId = pkt.rI64(ptr);
const SharedPtr<Network> network(RR->node->network(networkId));
if (network)
network->handleConfigChunk(tPtr,p.idBE,peer->address(),pkt,sizeof(Protocol::OK::Header),(int)p.size);
network->handleConfigChunk(tPtr,p.idBE,peer,pkt,sizeof(Protocol::OK::Header),(int)p.size);
} break;
case Protocol::VERB_MULTICAST_GATHER: {
@ -782,33 +782,34 @@ ZT_ALWAYS_INLINE bool _doNETWORK_CONFIG_REQUEST(IncomingPacket &p,const RuntimeE
ZT_ALWAYS_INLINE bool _doNETWORK_CONFIG(IncomingPacket &p,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer)
{
int ptr = sizeof(Protocol::Header);
const uint64_t nwid = p.pkt->rI64(ptr);
if (Buf<>::readOverflow(ptr,p.size)) {
RR->t->incomingPacketDropped(tPtr,p.idBE,0,peer->identity(),p.path->address(),p.hops,Protocol::VERB_NETWORK_CONFIG_REQUEST,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
if (ptr >= (int)p.size) {
RR->t->incomingPacketDropped(tPtr,p.idBE,0,peer->identity(),p.path->address(),p.hops,Protocol::VERB_NETWORK_CONFIG,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return true;
}
const SharedPtr<Network> network(RR->node->network(nwid));
if (network) {
}
const uint64_t configUpdateId = network->handleConfigChunk(tPtr,p.idBE,peer,*p.pkt,ptr,(int)p.size - ptr);
if (configUpdateId != 0) {
ZT_GET_NEW_BUF(outp,Protocol::OK::NETWORK_CONFIG);
/*
const SharedPtr<Network> network(RR->node->network(pkt.at<uint64_t>(ZT_PACKET_IDX_PAYLOAD)));
if (network) {
const uint64_t configUpdateId = network->handleConfigChunk(tPtr,pkt.packetId(),pkt.source(),pkt,ZT_PACKET_IDX_PAYLOAD);
if (configUpdateId) {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
outp.append((uint8_t)Packet::VERB_ECHO);
outp.append((uint64_t)pkt.packetId());
outp.append((uint64_t)network->id());
outp.append((uint64_t)configUpdateId);
outp.armor(peer->key(),true);
path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
outp->data.fields.h.packetId = Protocol::getPacketId();
peer->address().copyTo(outp->data.fields.h.destination);
RR->identity.address().copyTo(outp->data.fields.h.source);
outp->data.fields.h.flags = 0;
outp->data.fields.h.verb = Protocol::VERB_OK;
outp->data.fields.oh.inReVerb = Protocol::VERB_NETWORK_CONFIG;
outp->data.fields.oh.inRePacketId = p.idBE;
outp->data.fields.networkId = Utils::hton(nwid);
outp->data.fields.configUpdateId = Utils::hton(configUpdateId);
Protocol::armor(*outp,sizeof(Protocol::OK::NETWORK_CONFIG),peer->key(),ZT_PROTO_CIPHER_SUITE__POLY1305_SALSA2012);
p.path->send(RR,tPtr,outp->data.bytes,sizeof(Protocol::OK::NETWORK_CONFIG),RR->node->now());
}
}
peer->received(tPtr,path,pkt.hops(),pkt.packetId(),pkt.payloadLength(),Packet::VERB_NETWORK_CONFIG,0,Packet::VERB_NOP,(network) ? network->id() : 0);
*/
peer->received(tPtr,p.path,p.hops,p.idBE,p.size,Protocol::VERB_NETWORK_CONFIG,0,Protocol::VERB_NOP,nwid);
return true;
@ -873,17 +874,17 @@ ZT_ALWAYS_INLINE bool _doPUSH_DIRECT_PATHS(IncomingPacket &p,const RuntimeEnviro
ZT_ALWAYS_INLINE bool _doUSER_MESSAGE(IncomingPacket &p,const RuntimeEnvironment *const RR,void *const tPtr,const SharedPtr<Peer> &peer)
{
/*
if (likely(pkt.size() >= (ZT_PACKET_IDX_PAYLOAD + 8))) {
ZT_UserMessage um;
um.id = (const ZT_Identity *)(&(peer->identity()));
um.typeId = pkt.at<uint64_t>(ZT_PACKET_IDX_PAYLOAD);
um.data = reinterpret_cast<const void *>(reinterpret_cast<const uint8_t *>(pkt.data()) + ZT_PACKET_IDX_PAYLOAD + 8);
um.length = pkt.size() - (ZT_PACKET_IDX_PAYLOAD + 8);
ZT_UserMessage um;
int ptr = sizeof(Protocol::Header);
um.id = reinterpret_cast<const ZT_Identity *>(&(peer->identity()));
um.typeId = p.pkt->rI64(ptr);
int ds = (int)p.size - ptr;
if (ds > 0) {
um.data = p.pkt->data.bytes + ptr;
um.length = (unsigned int)ds;
RR->node->postEvent(tPtr,ZT_EVENT_USER_MESSAGE,reinterpret_cast<const void *>(&um));
}
peer->received(tPtr,path,pkt.hops(),pkt.packetId(),pkt.payloadLength(),Packet::VERB_USER_MESSAGE,0,Packet::VERB_NOP,0);
*/
peer->received(tPtr,p.path,p.hops,p.idBE,p.size,Protocol::VERB_USER_MESSAGE,0,Protocol::VERB_NOP,0);
return true;
}

View file

@ -849,7 +849,7 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg)
_myMulticastGroups.erase(i);
}
uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const Address &source,const Buf<> &chunk,int ptr,int size)
uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr<Peer> &source,const Buf<> &chunk,int ptr,int size)
{
if (_destroyed)
return 0;
@ -907,7 +907,7 @@ uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const Address &
Membership *m = nullptr;
Hashtable<Address,Membership>::Iterator i(_memberships);
while (i.next(a,m)) {
if ((*a != source)&&(*a != controller())) {
if ((*a != source->address())&&(*a != controller())) {
ZT_GET_NEW_BUF(outp,Protocol::Header);
outp->data.fields.packetId = Protocol::getPacketId();
@ -926,7 +926,7 @@ uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const Address &
}
}
}
} else if ((source == controller())||(!source)) {
} else if ((!source)||(source->address() != this->controller())) {
// Legacy support for OK(NETWORK_CONFIG_REQUEST) from older controllers that don't sign chunks and don't
// support multiple chunks. Since old controllers don't sign chunks we only accept the message if it comes
// directly from the controller.
@ -990,6 +990,9 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
try {
if ((nconf.issuedTo != RR->identity.address())||(nconf.networkId != _id))
return 0; // invalid config that is not for us or not for this network
if ((!Utils::allZero(nconf.issuedToIdentityHash,ZT_IDENTITY_HASH_SIZE))&&(memcmp(nconf.issuedToIdentityHash,RR->identity.hash(),ZT_IDENTITY_HASH_SIZE) != 0))
return 0; // full identity hash is present and does not match
if (_config == nconf)
return 1; // OK config, but duplicate of what we already have

View file

@ -77,7 +77,7 @@ public:
~Network();
ZT_ALWAYS_INLINE uint64_t id() const { return _id; }
ZT_ALWAYS_INLINE Address controller() const { return Address(_id >> 24); }
ZT_ALWAYS_INLINE Address controller() const { return Address(_id >> 24U); }
ZT_ALWAYS_INLINE bool multicastEnabled() const { return (_config.multicastLimit > 0); }
ZT_ALWAYS_INLINE bool hasConfig() const { return (_config); }
ZT_ALWAYS_INLINE uint64_t lastConfigUpdate() const { return _lastConfigUpdate; }
@ -190,13 +190,13 @@ public:
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param packetId Packet ID or 0 if none (e.g. via cluster path)
* @param source Address of sender of chunk or NULL if none (e.g. via cluster path)
* @param source Peer that actually sent this chunk (probably controller)
* @param chunk Buffer containing chunk
* @param ptr Index of chunk and related fields in packet (starting with network ID)
* @param size Size of data in chunk buffer (total, not relative to ptr)
* @return Update ID if update was fully assembled and accepted or 0 otherwise
*/
uint64_t handleConfigChunk(void *tPtr,uint64_t packetId,const Address &source,const Buf<> &chunk,int ptr,int size);
uint64_t handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr<Peer> &source,const Buf<> &chunk,int ptr,int size);
/**
* Set network configuration
@ -403,7 +403,7 @@ private:
Mutex _config_l;
Mutex _memberships_l;
AtomicCounter __refCount;
AtomicCounter<int> __refCount;
};
} // namespace ZeroTier

View file

@ -275,7 +275,8 @@ struct NetworkConfig : TriviallyCopyable
/**
* Hash of identity public key(s) of node to whom this is issued
*
* TODO
* If this field is all zero it is treated as undefined since old controllers
* do not set it.
*/
uint8_t issuedToIdentityHash[ZT_IDENTITY_HASH_SIZE];

View file

@ -18,7 +18,6 @@
#include <cstdlib>
#include <cstring>
#include <map>
#include <vector>
#include "Constants.hpp"

View file

@ -47,37 +47,6 @@ class Path
friend class Defragmenter;
public:
/**
* Efficient unique key for paths in a Hashtable
*/
class HashKey
{
public:
ZT_ALWAYS_INLINE HashKey() {}
ZT_ALWAYS_INLINE HashKey(const int64_t l,const InetAddress &r)
{
if (r.ss_family == AF_INET) {
_k[0] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_addr.s_addr;
_k[1] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_port;
_k[2] = (uint64_t)l;
} else if (r.ss_family == AF_INET6) {
memcpy(_k,reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,16);
_k[2] = ((uint64_t)reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port << 32) ^ (uint64_t)l;
} else {
memcpy(_k,&r,std::min(sizeof(_k),sizeof(InetAddress)));
_k[2] += (uint64_t)l;
}
}
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); }
ZT_ALWAYS_INLINE bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); }
ZT_ALWAYS_INLINE bool operator!=(const HashKey &k) const { return (!(*this == k)); }
private:
uint64_t _k[3];
};
ZT_ALWAYS_INLINE Path(const int64_t l,const InetAddress &r) :
_localSocket(l),
_lastIn(0),

View file

@ -855,6 +855,14 @@ ZT_PACKED_STRUCT(struct EXT_FRAME
uint16_t etherType;
});
ZT_PACKED_STRUCT(struct NETWORK_CONFIG
{
Protocol::Header h;
OK::Header oh;
uint64_t networkId;
uint64_t configUpdateId;
});
} // namespace OK
namespace ERROR {

View file

@ -250,9 +250,9 @@ void KBKDFHMACSHA384(const uint8_t key[32],const char label,const char context,c
{
uint8_t kbkdfMsg[13];
uint8_t kbuf[48];
kbkdfMsg[0] = (uint8_t)(iter >> 24);
kbkdfMsg[1] = (uint8_t)(iter >> 16);
kbkdfMsg[2] = (uint8_t)(iter >> 8);
kbkdfMsg[0] = (uint8_t)(iter >> 24U);
kbkdfMsg[1] = (uint8_t)(iter >> 16U);
kbkdfMsg[2] = (uint8_t)(iter >> 8U);
kbkdfMsg[3] = (uint8_t)iter;
kbkdfMsg[4] = (uint8_t)'Z';
kbkdfMsg[5] = (uint8_t)'T'; // preface our labels with something ZT-specific

View file

@ -80,6 +80,7 @@ private:
ZT_ALWAYS_INLINE bool operator==(const PhySurfaceKey &k) const { return ((reporter == k.reporter)&&(receivedOnLocalSocket == k.receivedOnLocalSocket)&&(reporterPhysicalAddress == k.reporterPhysicalAddress)&&(scope == k.scope)); }
ZT_ALWAYS_INLINE bool operator!=(const PhySurfaceKey &k) const { return (!(*this == k)); }
};
struct PhySurfaceEntry
{
InetAddress mySurface;

View file

@ -15,6 +15,7 @@
#define ZT_SHAREDPTR_HPP
#include "AtomicCounter.hpp"
#include "TriviallyCopyable.hpp"
namespace ZeroTier {
@ -26,7 +27,7 @@ namespace ZeroTier {
* AtomicCounter called __refCount.
*/
template<typename T>
class SharedPtr
class SharedPtr : public TriviallyCopyable
{
public:
ZT_ALWAYS_INLINE SharedPtr() : _ptr((T *)0) {}

View file

@ -15,6 +15,8 @@
namespace ZeroTier {
const uint64_t Topology::s_pathHashSalt = Utils::getSecureRandomU64();
// Sorts roots so as to put the lowest latency alive root first.
struct _RootSortComparisonOperator
{
@ -89,8 +91,8 @@ void Topology::getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
allPeers.clear();
allPeers.reserve(_peers.size());
Hashtable< Address,SharedPtr<Peer> >::Iterator i(*(const_cast<Hashtable< Address,SharedPtr<Peer> > *>(&_peers)));
Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
Address *a = nullptr;
SharedPtr<Peer> *p = nullptr;
while (i.next(a,p))
allPeers.push_back(*p);
}
@ -189,8 +191,8 @@ void Topology::doPeriodicTasks(void *tPtr,const int64_t now)
{
RWMutex::Lock l1(_peers_l);
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
Address *a = nullptr;
SharedPtr<Peer> *p = nullptr;
while (i.next(a,p)) {
if ( (!(*p)->alive(now)) && (_roots.count((*p)->identity()) == 0) ) {
(*p)->save(tPtr);
@ -200,9 +202,9 @@ void Topology::doPeriodicTasks(void *tPtr,const int64_t now)
}
{
RWMutex::Lock l1(_paths_l);
Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(_paths);
Path::HashKey *k = (Path::HashKey *)0;
SharedPtr<Path> *p = (SharedPtr<Path> *)0;
Hashtable< uint64_t,SharedPtr<Path> >::Iterator i(_paths);
uint64_t *k = nullptr;
SharedPtr<Path> *p = nullptr;
while (i.next(k,p)) {
if (p->references() <= 1)
_paths.erase(*k);
@ -214,8 +216,8 @@ void Topology::saveAll(void *tPtr)
{
RWMutex::RLock l(_peers_l);
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
Address *a = nullptr;
SharedPtr<Peer> *p = nullptr;
while (i.next(a,p)) {
if ( (!(*p)->alive(RR->node->now())) && (_roots.count((*p)->identity()) == 0) ) {
(*p)->save((void *)0);

View file

@ -92,7 +92,7 @@ public:
*/
ZT_ALWAYS_INLINE SharedPtr<Path> getPath(const int64_t l,const InetAddress &r)
{
const Path::HashKey k(l,r);
const uint64_t k = _pathHash(l,r);
_paths_l.rlock();
SharedPtr<Path> p(_paths[k]);
@ -205,8 +205,8 @@ public:
ZT_ALWAYS_INLINE void eachPath(F f) const
{
RWMutex::RLock l(_paths_l);
Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(const_cast<Topology *>(this)->_paths);
Path::HashKey *k = nullptr;
Hashtable< uint64_t,SharedPtr<Path> >::Iterator i(const_cast<Topology *>(this)->_paths);
uint64_t *k = nullptr;
SharedPtr<Path> *p = nullptr;
while (i.next(k,p)) {
f(*((const SharedPtr<Path> *)p));
@ -310,6 +310,31 @@ public:
private:
void _loadCached(void *tPtr,const Address &zta,SharedPtr<Peer> &peer);
// This is a secure random integer created at startup to salt the calculation of path hash map keys
static const uint64_t s_pathHashSalt;
// Get a hash key for looking up paths by their local port and destination address
ZT_ALWAYS_INLINE uint64_t _pathHash(int64_t l,const InetAddress &r) const
{
if (r.ss_family == AF_INET) {
return Utils::hash64(s_pathHashSalt ^ (uint64_t)(reinterpret_cast<const struct sockaddr_in *>(&r)->sin_addr.s_addr)) + (uint64_t)Utils::ntoh(reinterpret_cast<const struct sockaddr_in *>(&r)->sin_port) + (uint64_t)l;
} else if (r.ss_family == AF_INET6) {
#ifdef ZT_NO_UNALIGNED_ACCESS
uint64_t h = s_pathHashSalt;
for(int i=0;i<16;++i) {
h += (uint64_t)((reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr)[i]);
h += (h << 10U);
h ^= (h >> 6U);
}
#else
uint64_t h = Utils::hash64(s_pathHashSalt ^ (reinterpret_cast<const uint64_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr)[0] + reinterpret_cast<const uint64_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr)[1]));
#endif
return h + (uint64_t)Utils::ntoh(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port) + (uint64_t)l;
} else {
return Utils::hashString(reinterpret_cast<const void *>(&r),sizeof(InetAddress)) + (uint64_t)l;
}
}
const RuntimeEnvironment *const RR;
const Identity _myIdentity;
@ -320,7 +345,7 @@ private:
unsigned int _numConfiguredPhysicalPaths;
Hashtable< Address,SharedPtr<Peer> > _peers;
Hashtable< Path::HashKey,SharedPtr<Path> > _paths;
Hashtable< uint64_t,SharedPtr<Path> > _paths;
std::set< Identity > _roots; // locked by _peers_l
std::vector< SharedPtr<Peer> > _rootPeers; // locked by _peers_l
};

View file

@ -321,6 +321,13 @@ void getSecureRandom(void *buf,unsigned int bytes)
}
}
uint64_t getSecureRandomU64()
{
uint64_t tmp = 0;
getSecureRandom(&tmp,sizeof(tmp));
return tmp;
}
int b32e(const uint8_t *data,int length,char *result,int bufSize)
{
if (length < 0 || length > (1 << 28)) {
@ -397,22 +404,15 @@ int b32d(const char *encoded,uint8_t *result,int bufSize)
return count;
}
static uint64_t _secureRandom64()
{
uint64_t tmp = 0;
getSecureRandom(&tmp,sizeof(tmp));
return tmp;
}
#define ROL64(x,k) (((x) << (k)) | ((x) >> (64 - (k))))
uint64_t random()
{
// https://en.wikipedia.org/wiki/Xorshift#xoshiro256**
static Mutex l;
static uint64_t s0 = _secureRandom64();
static uint64_t s1 = _secureRandom64();
static uint64_t s2 = _secureRandom64();
static uint64_t s3 = _secureRandom64();
static uint64_t s0 = getSecureRandomU64();
static uint64_t s1 = getSecureRandomU64();
static uint64_t s2 = getSecureRandomU64();
static uint64_t s3 = getSecureRandomU64();
l.lock();
const uint64_t result = ROL64(s1 * 5,7) * 9;

View file

@ -139,6 +139,11 @@ unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen
*/
void getSecureRandom(void *buf,unsigned int bytes);
/**
* @return Secure random 64-bit integer
*/
uint64_t getSecureRandomU64();
/**
* Encode string to base32
*
@ -178,6 +183,41 @@ uint64_t random();
*/
bool scopy(char *dest,unsigned int len,const char *src);
/**
* Mix bits in a 64-bit integer
*
* https://nullprogram.com/blog/2018/07/31/
*
* @param x Integer to mix
* @return Hashed value
*/
static ZT_ALWAYS_INLINE uint64_t hash64(uint64_t x)
{
x ^= x >> 30U;
x *= 0xbf58476d1ce4e5b9ULL;
x ^= x >> 27U;
x *= 0x94d049bb133111ebULL;
x ^= x >> 31U;
return x;
}
/**
* @param b Buffer to check
* @param l Length of buffer
* @return True if buffer is all zero
*/
static ZT_ALWAYS_INLINE bool allZero(const void *const b,const unsigned int l)
{
const uint8_t *x = reinterpret_cast<const uint8_t *>(b);
const uint8_t *const y = x + l;
while (x != y) {
if (*x != 0)
return false;
++x;
}
return true;
}
/**
* Wrapper around reentrant strtok functions, which differ in name by platform
*

View file

@ -57,11 +57,11 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response
_ArpEntry *targetEntry = _cache.get(reinterpret_cast<const uint32_t *>(arp)[6]);
if ((targetEntry)&&(targetEntry->local)) {
memcpy(response,ARP_RESPONSE_HEADER,8);
targetEntry->mac.copyTo(reinterpret_cast<uint8_t *>(response) + 8,6);
targetEntry->mac.copyTo(reinterpret_cast<uint8_t *>(response) + 8);
memcpy(reinterpret_cast<uint8_t *>(response) + 14,reinterpret_cast<const uint8_t *>(arp) + 24,4);
memcpy(reinterpret_cast<uint8_t *>(response) + 18,reinterpret_cast<const uint8_t *>(arp) + 8,10);
responseLen = 28;
responseDest.setTo(reinterpret_cast<const uint8_t *>(arp) + 8,6);
responseDest.setTo(reinterpret_cast<const uint8_t *>(arp) + 8);
}
} else if (!memcmp(arp,ARP_RESPONSE_HEADER,8)) {
// Learn cache entries for remote IPs from relevant ARP replies
@ -70,7 +70,7 @@ uint32_t Arp::processIncomingArp(const void *arp,unsigned int len,void *response
_ArpEntry *queryEntry = _cache.get(responseIp);
if ((queryEntry)&&(!queryEntry->local)&&((now - queryEntry->lastQuerySent) <= ZT_ARP_QUERY_MAX_TTL)) {
queryEntry->lastResponseReceived = now;
queryEntry->mac.setTo(reinterpret_cast<const uint8_t *>(arp) + 8,6);
queryEntry->mac.setTo(reinterpret_cast<const uint8_t *>(arp) + 8);
ip = responseIp;
}
}
@ -102,7 +102,7 @@ MAC Arp::query(const MAC &localMac,uint32_t localIp,uint32_t targetIp,void *quer
uint8_t *q = reinterpret_cast<uint8_t *>(query);
memcpy(q,ARP_REQUEST_HEADER,8); q += 8; // ARP request header information, always the same
localMac.copyTo(q,6); q += 6; // sending host MAC address
localMac.copyTo(q); q += 6; // sending host MAC address
memcpy(q,&localIp,4); q += 4; // sending host IP (IP already in big-endian byte order)
memset(q,0,6); q += 6; // sending zeros for target MAC address as thats what we want to find
memcpy(q,&targetIp,4); // target IP address for resolution (IP already in big-endian byte order)

View file

@ -14,9 +14,6 @@
#ifndef ZT_MANAGEDROUTE_HPP
#define ZT_MANAGEDROUTE_HPP
#include <stdlib.h>
#include <string.h>
#include "../node/InetAddress.hpp"
#include "../node/Utils.hpp"
#include "../node/SharedPtr.hpp"
@ -25,6 +22,8 @@
#include <stdexcept>
#include <vector>
#include <map>
#include <cstdlib>
#include <cstring>
namespace ZeroTier {
@ -84,7 +83,7 @@ private:
char _device[128];
char _systemDevice[128]; // for route overrides
AtomicCounter __refCount;
AtomicCounter<int> __refCount;
};
} // namespace ZeroTier