mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Just about everything refactored for new Protocol/Buf code except Switch.
This commit is contained in:
parent
df346a6df6
commit
7d11522768
25 changed files with 214 additions and 239 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++()
|
||||
{
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue