mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 13:03:45 +02:00
Build fixes.
This commit is contained in:
parent
996589894d
commit
d537428421
20 changed files with 575 additions and 436 deletions
|
@ -57,8 +57,8 @@ else(WIN32)
|
||||||
-Wall
|
-Wall
|
||||||
-Wno-deprecated
|
-Wno-deprecated
|
||||||
-Wno-unused-function
|
-Wno-unused-function
|
||||||
-mmacosx-version-min=10.9
|
-mmacosx-version-min=10.12
|
||||||
$<$<CONFIG:Debug>:-g>
|
$<$<CONFIG:DEBUG>:-g>
|
||||||
$<$<CONFIG:DEBUG>:-O0>
|
$<$<CONFIG:DEBUG>:-O0>
|
||||||
$<$<CONFIG:RELEASE>:-Ofast>
|
$<$<CONFIG:RELEASE>:-Ofast>
|
||||||
$<$<CONFIG:RELEASE>:-ffast-math>
|
$<$<CONFIG:RELEASE>:-ffast-math>
|
||||||
|
@ -79,7 +79,7 @@ else(WIN32)
|
||||||
-Wno-deprecated
|
-Wno-deprecated
|
||||||
-Wno-unused-function
|
-Wno-unused-function
|
||||||
-Wno-format
|
-Wno-format
|
||||||
$<$<CONFIG:Debug>:-g>
|
$<$<CONFIG:DEBUG>:-g>
|
||||||
$<$<CONFIG:DEBUG>:-O0>
|
$<$<CONFIG:DEBUG>:-O0>
|
||||||
$<$<CONFIG:RELEASE>:-O3>
|
$<$<CONFIG:RELEASE>:-O3>
|
||||||
$<$<CONFIG:RELEASE>:-ffast-math>
|
$<$<CONFIG:RELEASE>:-ffast-math>
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
#include "MIMC52.hpp"
|
#include "MIMC52.hpp"
|
||||||
#include "SHA512.hpp"
|
#include "SHA512.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "Speck128.hpp"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
// This gets defined on any architecture whose FPU is not capable of doing the mulmod52() FPU trick.
|
// This gets defined on any architecture whose FPU is not capable of doing the mulmod52() FPU trick.
|
||||||
//#define ZT_MIMC52_NO_FPU
|
//#define ZT_MIMC52_NO_FPU
|
||||||
|
@ -114,7 +111,7 @@ uint64_t mimc52Delay(const void *const salt,const unsigned int saltSize,const un
|
||||||
uint64_t x = Utils::swapBytes(hash[1]) % p;
|
uint64_t x = Utils::swapBytes(hash[1]) % p;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Speck128<8> roundConstantGenerator(hash + 2);
|
//Speck128<8> roundConstantGenerator(hash + 2);
|
||||||
const uint64_t e = ((p * 2) - 1) / 3;
|
const uint64_t e = ((p * 2) - 1) / 3;
|
||||||
const uint64_t m52 = 0xfffffffffffffULL;
|
const uint64_t m52 = 0xfffffffffffffULL;
|
||||||
const uint64_t rmin1 = rounds - 1;
|
const uint64_t rmin1 = rounds - 1;
|
||||||
|
@ -122,7 +119,7 @@ uint64_t mimc52Delay(const void *const salt,const unsigned int saltSize,const un
|
||||||
#pragma unroll 16
|
#pragma unroll 16
|
||||||
for(unsigned long r=0;r<rounds;++r) {
|
for(unsigned long r=0;r<rounds;++r) {
|
||||||
uint64_t sx = sxx,sy = rmin1 - r;
|
uint64_t sx = sxx,sy = rmin1 - r;
|
||||||
roundConstantGenerator.encryptXY(sx,sy);
|
//roundConstantGenerator.encryptXY(sx,sy);
|
||||||
x = (x - sy) & m52;
|
x = (x - sy) & m52;
|
||||||
x = modpow52(x,e,p);
|
x = modpow52(x,e,p);
|
||||||
}
|
}
|
||||||
|
@ -143,7 +140,7 @@ bool mimc52Verify(const void *const salt,const unsigned int saltSize,unsigned lo
|
||||||
uint64_t x = Utils::swapBytes(hash[1]) % p;
|
uint64_t x = Utils::swapBytes(hash[1]) % p;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Speck128<8> roundConstantGenerator(hash + 2);
|
//Speck128<8> roundConstantGenerator(hash + 2);
|
||||||
const uint64_t m52 = 0xfffffffffffffULL;
|
const uint64_t m52 = 0xfffffffffffffULL;
|
||||||
uint64_t y = proof & m52;
|
uint64_t y = proof & m52;
|
||||||
const uint64_t sxx = hash[4];
|
const uint64_t sxx = hash[4];
|
||||||
|
@ -154,7 +151,7 @@ bool mimc52Verify(const void *const salt,const unsigned int saltSize,unsigned lo
|
||||||
#pragma unroll 16
|
#pragma unroll 16
|
||||||
for(unsigned long r=0;r<rounds;++r) {
|
for(unsigned long r=0;r<rounds;++r) {
|
||||||
uint64_t sx = sxx,sy = r;
|
uint64_t sx = sxx,sy = r;
|
||||||
roundConstantGenerator.encryptXY(sx,sy);
|
//roundConstantGenerator.encryptXY(sx,sy);
|
||||||
#ifdef ZT_MIMC52_NO_FPU
|
#ifdef ZT_MIMC52_NO_FPU
|
||||||
#ifdef x64_cubemod
|
#ifdef x64_cubemod
|
||||||
x64_cubemod(y,p);
|
x64_cubemod(y,p);
|
||||||
|
|
|
@ -137,6 +137,8 @@ public:
|
||||||
template<typename V>
|
template<typename V>
|
||||||
class Vector : public std::vector< V,Utils::Mallocator<V> >
|
class Vector : public std::vector< V,Utils::Mallocator<V> >
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
ZT_INLINE Vector() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
|
|
|
@ -46,11 +46,11 @@ namespace ZeroTier {
|
||||||
* @tparam P Type for pointer to a path object (default: SharedPtr<Path>)
|
* @tparam P Type for pointer to a path object (default: SharedPtr<Path>)
|
||||||
*/
|
*/
|
||||||
template<
|
template<
|
||||||
unsigned int MF = ZT_MAX_PACKET_FRAGMENTS,
|
unsigned int MF = ZT_MAX_PACKET_FRAGMENTS,
|
||||||
unsigned int MFP = ZT_MAX_INCOMING_FRAGMENTS_PER_PATH,
|
unsigned int MFP = ZT_MAX_INCOMING_FRAGMENTS_PER_PATH,
|
||||||
unsigned int GCS = (ZT_MAX_PACKET_FRAGMENTS * 2),
|
unsigned int GCS = (ZT_MAX_PACKET_FRAGMENTS * 2),
|
||||||
unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4),
|
unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4),
|
||||||
typename P = SharedPtr<Path> >
|
typename P = SharedPtr <Path> >
|
||||||
class Defragmenter
|
class Defragmenter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -96,7 +96,8 @@ public:
|
||||||
ERR_OUT_OF_MEMORY
|
ERR_OUT_OF_MEMORY
|
||||||
};
|
};
|
||||||
|
|
||||||
ZT_INLINE Defragmenter() {} // NOLINT(hicpp-use-equals-default,modernize-use-equals-default)
|
ZT_INLINE Defragmenter()
|
||||||
|
{} // NOLINT(hicpp-use-equals-default,modernize-use-equals-default)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a fragment of a multi-part message
|
* Process a fragment of a multi-part message
|
||||||
|
@ -141,8 +142,8 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_INLINE ResultCode assemble(
|
ZT_INLINE ResultCode assemble(
|
||||||
const uint64_t messageId,
|
const uint64_t messageId,
|
||||||
FCV< Buf::Slice,MF > &message,
|
FCV <Buf::Slice, MF> &message,
|
||||||
SharedPtr<Buf> &fragment,
|
SharedPtr <Buf> &fragment,
|
||||||
const unsigned int fragmentDataIndex,
|
const unsigned int fragmentDataIndex,
|
||||||
const unsigned int fragmentDataSize,
|
const unsigned int fragmentDataSize,
|
||||||
const unsigned int fragmentNo,
|
const unsigned int fragmentNo,
|
||||||
|
@ -151,7 +152,7 @@ public:
|
||||||
const P &via)
|
const P &via)
|
||||||
{
|
{
|
||||||
// Sanity checks for malformed fragments or invalid input parameters.
|
// Sanity checks for malformed fragments or invalid input parameters.
|
||||||
if ((fragmentNo >= totalFragmentsExpected)||(totalFragmentsExpected > MF)||(totalFragmentsExpected == 0))
|
if ((fragmentNo >= totalFragmentsExpected) || (totalFragmentsExpected > MF) || (totalFragmentsExpected == 0))
|
||||||
return ERR_INVALID_FRAGMENT;
|
return ERR_INVALID_FRAGMENT;
|
||||||
|
|
||||||
// We hold the read lock on _messages unless we need to add a new entry or do GC.
|
// We hold the read lock on _messages unless we need to add a new entry or do GC.
|
||||||
|
@ -166,15 +167,15 @@ public:
|
||||||
// under the target size. This tries to minimize the amount of time the write
|
// under the target size. This tries to minimize the amount of time the write
|
||||||
// lock is held since many threads can hold the read lock but all threads must
|
// lock is held since many threads can hold the read lock but all threads must
|
||||||
// wait if someone holds the write lock.
|
// wait if someone holds the write lock.
|
||||||
std::vector<std::pair<int64_t,uint64_t> > messagesByLastUsedTime;
|
std::vector<std::pair<int64_t, uint64_t> > messagesByLastUsedTime;
|
||||||
messagesByLastUsedTime.reserve(m_messages.size());
|
messagesByLastUsedTime.reserve(m_messages.size());
|
||||||
|
|
||||||
for(typename Map< uint64_t,p_E >::const_iterator i(m_messages.begin());i != m_messages.end();++i)
|
for (typename Map<uint64_t, p_E>::const_iterator i(m_messages.begin());i != m_messages.end();++i)
|
||||||
messagesByLastUsedTime.push_back(std::pair<int64_t,uint64_t>(i->second.lastUsed,i->first));
|
messagesByLastUsedTime.push_back(std::pair<int64_t, uint64_t>(i->second.lastUsed, i->first));
|
||||||
std::sort(messagesByLastUsedTime.begin(),messagesByLastUsedTime.end());
|
std::sort(messagesByLastUsedTime.begin(), messagesByLastUsedTime.end());
|
||||||
|
|
||||||
ml.writing(); // acquire write lock on _messages
|
ml.writing(); // acquire write lock on _messages
|
||||||
for (unsigned long x = 0,y = (messagesByLastUsedTime.size() - GCS); x <= y; ++x)
|
for (unsigned long x = 0, y = (messagesByLastUsedTime.size() - GCS);x <= y;++x)
|
||||||
m_messages.erase(messagesByLastUsedTime[x].second);
|
m_messages.erase(messagesByLastUsedTime[x].second);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ERR_OUT_OF_MEMORY;
|
||||||
|
@ -187,7 +188,7 @@ public:
|
||||||
ml.writing(); // acquire write lock on _messages if not already
|
ml.writing(); // acquire write lock on _messages if not already
|
||||||
try {
|
try {
|
||||||
e = &(m_messages[messageId]);
|
e = &(m_messages[messageId]);
|
||||||
} catch ( ... ) {
|
} catch (...) {
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ERR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
e->id = messageId;
|
e->id = messageId;
|
||||||
|
@ -214,7 +215,7 @@ public:
|
||||||
|
|
||||||
// If there is a path associated with this fragment make sure we've registered
|
// If there is a path associated with this fragment make sure we've registered
|
||||||
// ourselves as in flight, check the limit, and abort if exceeded.
|
// ourselves as in flight, check the limit, and abort if exceeded.
|
||||||
if ((via)&&(!e->via)) {
|
if ((via) && (!e->via)) {
|
||||||
e->via = via;
|
e->via = via;
|
||||||
bool tooManyPerPath = false;
|
bool tooManyPerPath = false;
|
||||||
via->m_inboundFragmentedMessages_l.lock();
|
via->m_inboundFragmentedMessages_l.lock();
|
||||||
|
@ -224,7 +225,7 @@ public:
|
||||||
} else {
|
} else {
|
||||||
tooManyPerPath = true;
|
tooManyPerPath = true;
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch (...) {
|
||||||
// This would indicate something like bad_alloc thrown by the set. Treat
|
// This would indicate something like bad_alloc thrown by the set. Treat
|
||||||
// it as limit exceeded.
|
// it as limit exceeded.
|
||||||
tooManyPerPath = true;
|
tooManyPerPath = true;
|
||||||
|
@ -252,7 +253,7 @@ public:
|
||||||
++e->fragmentsReceived;
|
++e->fragmentsReceived;
|
||||||
|
|
||||||
// If we now have all fragments then assemble them.
|
// If we now have all fragments then assemble them.
|
||||||
if ((e->fragmentsReceived >= e->totalFragmentsExpected)&&(e->totalFragmentsExpected > 0)) {
|
if ((e->fragmentsReceived >= e->totalFragmentsExpected) && (e->totalFragmentsExpected > 0)) {
|
||||||
// This message is done so de-register it with its path if one is associated.
|
// This message is done so de-register it with its path if one is associated.
|
||||||
if (e->via) {
|
if (e->via) {
|
||||||
e->via->m_inboundFragmentedMessages_l.lock();
|
e->via->m_inboundFragmentedMessages_l.lock();
|
||||||
|
@ -294,20 +295,22 @@ private:
|
||||||
// p_E is an entry in the message queue.
|
// p_E is an entry in the message queue.
|
||||||
struct p_E
|
struct p_E
|
||||||
{
|
{
|
||||||
ZT_INLINE p_E() noexcept :
|
ZT_INLINE p_E() noexcept:
|
||||||
id(0),
|
id(0),
|
||||||
lastUsed(0),
|
lastUsed(0),
|
||||||
totalFragmentsExpected(0),
|
totalFragmentsExpected(0),
|
||||||
fragmentsReceived(0) {}
|
fragmentsReceived(0)
|
||||||
|
{}
|
||||||
|
|
||||||
ZT_INLINE p_E(const p_E &e) noexcept :
|
ZT_INLINE p_E(const p_E &e) noexcept:
|
||||||
id(e.id),
|
id(e.id),
|
||||||
lastUsed(e.lastUsed),
|
lastUsed(e.lastUsed),
|
||||||
totalFragmentsExpected(e.totalFragmentsExpected),
|
totalFragmentsExpected(e.totalFragmentsExpected),
|
||||||
fragmentsReceived(e.fragmentsReceived),
|
fragmentsReceived(e.fragmentsReceived),
|
||||||
via(e.via),
|
via(e.via),
|
||||||
message(e.message),
|
message(e.message),
|
||||||
lock() {}
|
lock()
|
||||||
|
{}
|
||||||
|
|
||||||
ZT_INLINE ~p_E()
|
ZT_INLINE ~p_E()
|
||||||
{
|
{
|
||||||
|
@ -336,11 +339,11 @@ private:
|
||||||
unsigned int totalFragmentsExpected;
|
unsigned int totalFragmentsExpected;
|
||||||
unsigned int fragmentsReceived;
|
unsigned int fragmentsReceived;
|
||||||
P via;
|
P via;
|
||||||
FCV< Buf::Slice,MF > message;
|
FCV <Buf::Slice, MF> message;
|
||||||
Mutex lock;
|
Mutex lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
Map< uint64_t,Defragmenter<MF,MFP,GCS,GCT,P>::p_E > m_messages;
|
Map <uint64_t, Defragmenter<MF, MFP, GCS, GCT, P>::p_E> m_messages;
|
||||||
RWMutex m_messages_l;
|
RWMutex m_messages_l;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "SHA512.hpp"
|
#include "SHA512.hpp"
|
||||||
#include "Salsa20.hpp"
|
#include "Salsa20.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
#include "AES.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -26,102 +25,102 @@ namespace {
|
||||||
|
|
||||||
// This is the memory-intensive hash function used to compute v0 identities from v0 public keys.
|
// This is the memory-intensive hash function used to compute v0 identities from v0 public keys.
|
||||||
#define ZT_V0_IDENTITY_GEN_MEMORY 2097152
|
#define ZT_V0_IDENTITY_GEN_MEMORY 2097152
|
||||||
void identityV0ProofOfWorkFrankenhash(const void *const publicKey,unsigned int publicKeyBytes,void *const digest,void *const genmem) noexcept
|
|
||||||
|
void identityV0ProofOfWorkFrankenhash(const void *const publicKey, unsigned int publicKeyBytes, void *const digest, void *const genmem) noexcept
|
||||||
{
|
{
|
||||||
// Digest publicKey[] to obtain initial digest
|
// Digest publicKey[] to obtain initial digest
|
||||||
SHA512(digest,publicKey,publicKeyBytes);
|
SHA512(digest, publicKey, publicKeyBytes);
|
||||||
|
|
||||||
// Initialize genmem[] using Salsa20 in a CBC-like configuration since
|
// Initialize genmem[] using Salsa20 in a CBC-like configuration since
|
||||||
// ordinary Salsa20 is randomly seek-able. This is good for a cipher
|
// ordinary Salsa20 is randomly seek-able. This is good for a cipher
|
||||||
// but is not what we want for sequential memory-hardness.
|
// but is not what we want for sequential memory-hardness.
|
||||||
Utils::zero<ZT_V0_IDENTITY_GEN_MEMORY>(genmem);
|
Utils::zero<ZT_V0_IDENTITY_GEN_MEMORY>(genmem);
|
||||||
Salsa20 s20(digest,(char *)digest + 32);
|
Salsa20 s20(digest, (char *) digest + 32);
|
||||||
s20.crypt20((char *)genmem,(char *)genmem,64);
|
s20.crypt20((char *) genmem, (char *) genmem, 64);
|
||||||
for(unsigned long i=64;i<ZT_V0_IDENTITY_GEN_MEMORY;i+=64) {
|
for (unsigned long i = 64;i < ZT_V0_IDENTITY_GEN_MEMORY;i += 64) {
|
||||||
unsigned long k = i - 64;
|
unsigned long k = i - 64;
|
||||||
*((uint64_t *)((char *)genmem + i)) = *((uint64_t *)((char *)genmem + k));
|
*((uint64_t *) ((char *) genmem + i)) = *((uint64_t *) ((char *) genmem + k));
|
||||||
*((uint64_t *)((char *)genmem + i + 8)) = *((uint64_t *)((char *)genmem + k + 8));
|
*((uint64_t *) ((char *) genmem + i + 8)) = *((uint64_t *) ((char *) genmem + k + 8));
|
||||||
*((uint64_t *)((char *)genmem + i + 16)) = *((uint64_t *)((char *)genmem + k + 16));
|
*((uint64_t *) ((char *) genmem + i + 16)) = *((uint64_t *) ((char *) genmem + k + 16));
|
||||||
*((uint64_t *)((char *)genmem + i + 24)) = *((uint64_t *)((char *)genmem + k + 24));
|
*((uint64_t *) ((char *) genmem + i + 24)) = *((uint64_t *) ((char *) genmem + k + 24));
|
||||||
*((uint64_t *)((char *)genmem + i + 32)) = *((uint64_t *)((char *)genmem + k + 32));
|
*((uint64_t *) ((char *) genmem + i + 32)) = *((uint64_t *) ((char *) genmem + k + 32));
|
||||||
*((uint64_t *)((char *)genmem + i + 40)) = *((uint64_t *)((char *)genmem + k + 40));
|
*((uint64_t *) ((char *) genmem + i + 40)) = *((uint64_t *) ((char *) genmem + k + 40));
|
||||||
*((uint64_t *)((char *)genmem + i + 48)) = *((uint64_t *)((char *)genmem + k + 48));
|
*((uint64_t *) ((char *) genmem + i + 48)) = *((uint64_t *) ((char *) genmem + k + 48));
|
||||||
*((uint64_t *)((char *)genmem + i + 56)) = *((uint64_t *)((char *)genmem + k + 56));
|
*((uint64_t *) ((char *) genmem + i + 56)) = *((uint64_t *) ((char *) genmem + k + 56));
|
||||||
s20.crypt20((char *)genmem + i,(char *)genmem + i,64);
|
s20.crypt20((char *) genmem + i, (char *) genmem + i, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render final digest using genmem as a lookup table
|
// Render final digest using genmem as a lookup table
|
||||||
for(unsigned long i=0;i<(ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t));) {
|
for (unsigned long i = 0;i < (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t));) {
|
||||||
unsigned long idx1 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (64 / sizeof(uint64_t))); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
unsigned long idx1 = (unsigned long) (Utils::ntoh(((uint64_t *) genmem)[i++]) % (64 / sizeof(uint64_t))); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||||
unsigned long idx2 = (unsigned long)(Utils::ntoh(((uint64_t *)genmem)[i++]) % (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t))); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
unsigned long idx2 = (unsigned long) (Utils::ntoh(((uint64_t *) genmem)[i++]) % (ZT_V0_IDENTITY_GEN_MEMORY / sizeof(uint64_t))); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||||
uint64_t tmp = ((uint64_t *)genmem)[idx2];
|
uint64_t tmp = ((uint64_t *) genmem)[idx2];
|
||||||
((uint64_t *)genmem)[idx2] = ((uint64_t *)digest)[idx1];
|
((uint64_t *) genmem)[idx2] = ((uint64_t *) digest)[idx1];
|
||||||
((uint64_t *)digest)[idx1] = tmp;
|
((uint64_t *) digest)[idx1] = tmp;
|
||||||
s20.crypt20(digest,digest,64);
|
s20.crypt20(digest, digest, 64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct identityV0ProofOfWorkCriteria
|
struct identityV0ProofOfWorkCriteria
|
||||||
{
|
{
|
||||||
ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *sb,char *gm) noexcept : digest(sb),genmem(gm) {}
|
ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *sb, char *gm) noexcept: digest(sb), genmem(gm)
|
||||||
|
{}
|
||||||
|
|
||||||
ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE]) const noexcept
|
ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE]) const noexcept
|
||||||
{
|
{
|
||||||
identityV0ProofOfWorkFrankenhash(pub,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,digest,genmem);
|
identityV0ProofOfWorkFrankenhash(pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, digest, genmem);
|
||||||
return (digest[0] < 17);
|
return (digest[0] < 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *digest;
|
unsigned char *digest;
|
||||||
char *genmem;
|
char *genmem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ZT_IDENTITY_V1_POW_MEMORY_SIZE 131072
|
||||||
|
|
||||||
// This is a simpler memory-intensive hash function for V1 identity generation.
|
// This is a simpler memory-intensive hash function for V1 identity generation.
|
||||||
// It's not quite as heavy as the V0 frankenhash, is a little more orderly in
|
// It's not quite as heavy as the V0 frankenhash, is a little more orderly in
|
||||||
// its design, but remains relatively resistant to GPU acceleration due to memory
|
// its design, but remains relatively resistant to GPU acceleration due to memory
|
||||||
// requirements for efficient computation.
|
// requirements for efficient computation.
|
||||||
#define ZT_IDENTITY_V1_POW_MEMORY_SIZE 262144
|
bool identityV1ProofOfWorkCriteria(const void *in, const unsigned int len)
|
||||||
#define ZT_IDENTITY_V1_POW_MEMORY_SIZE_U64 32768
|
|
||||||
bool identityV1ProofOfWorkCriteria(const void *in,const unsigned int len)
|
|
||||||
{
|
{
|
||||||
uint64_t b[ZT_IDENTITY_V1_POW_MEMORY_SIZE_U64];
|
uint64_t b[ZT_IDENTITY_V1_POW_MEMORY_SIZE / 8];
|
||||||
|
|
||||||
SHA512(b,in,len);
|
SHA384(b, in, len);
|
||||||
AES c(b);
|
Utils::zero<ZT_IDENTITY_V1_POW_MEMORY_SIZE - 48>(b + 6);
|
||||||
for(unsigned int i=8;i<ZT_IDENTITY_V1_POW_MEMORY_SIZE_U64;i+=8) {
|
Salsa20(b,b + 4).crypt12(b,b,ZT_IDENTITY_V1_POW_MEMORY_SIZE);
|
||||||
SHA512(b + i,b + (i - 8),64);
|
|
||||||
if (unlikely((b[i] % 31ULL) == (b[i - 1] >> 59U)))
|
|
||||||
c.encrypt(b + i,b + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
for(unsigned int i=0;i<ZT_IDENTITY_V1_POW_MEMORY_SIZE_U64;i+=4) {
|
for (unsigned int i=0;i<(ZT_IDENTITY_V1_POW_MEMORY_SIZE / 8);) {
|
||||||
|
const unsigned int i1 = i + 1;
|
||||||
|
const unsigned int i2 = i + 2;
|
||||||
|
const unsigned int i3 = i + 3;
|
||||||
b[i] = Utils::swapBytes(b[i]);
|
b[i] = Utils::swapBytes(b[i]);
|
||||||
b[i + 1] = Utils::swapBytes(b[i + 1]);
|
i += 4;
|
||||||
b[i + 2] = Utils::swapBytes(b[i + 2]);
|
b[i1] = Utils::swapBytes(b[i1]);
|
||||||
b[i + 3] = Utils::swapBytes(b[i + 3]);
|
b[i2] = Utils::swapBytes(b[i2]);
|
||||||
|
b[i3] = Utils::swapBytes(b[i3]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::sort(b,b + ZT_IDENTITY_V1_POW_MEMORY_SIZE_U64);
|
|
||||||
|
std::sort(b,b + (ZT_IDENTITY_V1_POW_MEMORY_SIZE / 8));
|
||||||
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
for(unsigned int i=0;i<ZT_IDENTITY_V1_POW_MEMORY_SIZE_U64;i+=4) {
|
for (unsigned int i=0;i<(ZT_IDENTITY_V1_POW_MEMORY_SIZE / 8);) {
|
||||||
|
const unsigned int i1 = i + 1;
|
||||||
|
const unsigned int i2 = i + 2;
|
||||||
|
const unsigned int i3 = i + 3;
|
||||||
b[i] = Utils::swapBytes(b[i]);
|
b[i] = Utils::swapBytes(b[i]);
|
||||||
b[i + 1] = Utils::swapBytes(b[i + 1]);
|
i += 4;
|
||||||
b[i + 2] = Utils::swapBytes(b[i + 2]);
|
b[i1] = Utils::swapBytes(b[i1]);
|
||||||
b[i + 3] = Utils::swapBytes(b[i + 3]);
|
b[i2] = Utils::swapBytes(b[i2]);
|
||||||
|
b[i3] = Utils::swapBytes(b[i3]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Hash resulting sorted array to get final result for PoW criteria test.
|
SHA384(b, b, ZT_IDENTITY_V1_POW_MEMORY_SIZE, in, len);
|
||||||
// We also include the original input after so that cryptographically this
|
|
||||||
// is exactly like SHA384(in). This should make any FIPS types happy as
|
|
||||||
// this means the identity hash is SHA384 and not some weird construction.
|
|
||||||
SHA384(b,b,ZT_IDENTITY_V1_POW_MEMORY_SIZE,in,len);
|
|
||||||
|
|
||||||
// PoW passes if sum of first two 64-bit integers (treated as little-endian) mod 180 is 0.
|
return (b[0] % 1093U) == 0;
|
||||||
// This value was picked to yield about 1-2s total on typical desktop and server cores in 2020.
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
const uint64_t finalHash = Utils::swapBytes(b[0]) + Utils::swapBytes(b[1]);
|
|
||||||
#else
|
|
||||||
const uint64_t finalHash = b[0] + b[1];
|
|
||||||
#endif
|
|
||||||
return (finalHash % 180U) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
@ -133,7 +132,7 @@ bool Identity::generate(const Type t)
|
||||||
m_type = t;
|
m_type = t;
|
||||||
m_hasPrivate = true;
|
m_hasPrivate = true;
|
||||||
|
|
||||||
switch(t) {
|
switch (t) {
|
||||||
|
|
||||||
case C25519: {
|
case C25519: {
|
||||||
// Generate C25519/Ed25519 key pair whose hash satisfies a "hashcash" criterion and generate the
|
// Generate C25519/Ed25519 key pair whose hash satisfies a "hashcash" criterion and generate the
|
||||||
|
@ -142,7 +141,7 @@ bool Identity::generate(const Type t)
|
||||||
char *const genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
char *const genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
||||||
Address address;
|
Address address;
|
||||||
do {
|
do {
|
||||||
C25519::generateSatisfying(identityV0ProofOfWorkCriteria(digest,genmem),m_pub,m_priv);
|
C25519::generateSatisfying(identityV0ProofOfWorkCriteria(digest, genmem), m_pub, m_priv);
|
||||||
address.setTo(digest + 59);
|
address.setTo(digest + 59);
|
||||||
} while (address.isReserved());
|
} while (address.isReserved());
|
||||||
delete[] genmem;
|
delete[] genmem;
|
||||||
|
@ -151,18 +150,18 @@ bool Identity::generate(const Type t)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case P384: {
|
case P384: {
|
||||||
for(;;) {
|
for (;;) {
|
||||||
// Loop until we pass the PoW criteria. The nonce is only 8 bits, so generate
|
// Loop until we pass the PoW criteria. The nonce is only 8 bits, so generate
|
||||||
// some new key material every time it wraps. The ECC384 generator is slightly
|
// some new key material every time it wraps. The ECC384 generator is slightly
|
||||||
// faster so use that one.
|
// faster so use that one.
|
||||||
m_pub[0] = 0; // zero nonce
|
m_pub[0] = 0; // zero nonce
|
||||||
C25519::generateCombined(m_pub + 1,m_priv + 1);
|
C25519::generateCombined(m_pub + 1, m_priv + 1);
|
||||||
ECC384GenerateKey(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
ECC384GenerateKey(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||||
for(;;) {
|
for (;;) {
|
||||||
if (identityV1ProofOfWorkCriteria(m_pub,sizeof(m_pub)))
|
if (identityV1ProofOfWorkCriteria(m_pub, sizeof(m_pub)))
|
||||||
break;
|
break;
|
||||||
if (++m_pub[0] == 0)
|
if (++m_pub[0] == 0)
|
||||||
ECC384GenerateKey(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
ECC384GenerateKey(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we passed PoW then check that the address is valid, otherwise loop
|
// If we passed PoW then check that the address is valid, otherwise loop
|
||||||
|
@ -183,25 +182,25 @@ bool Identity::generate(const Type t)
|
||||||
bool Identity::locallyValidate() const noexcept
|
bool Identity::locallyValidate() const noexcept
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if ((m_fp)&&((!m_fp.address().isReserved()))) {
|
if ((m_fp) && ((!m_fp.address().isReserved()))) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case C25519: {
|
case C25519: {
|
||||||
uint8_t digest[64];
|
uint8_t digest[64];
|
||||||
char *const genmem = (char *)malloc(ZT_V0_IDENTITY_GEN_MEMORY);
|
char *const genmem = (char *) malloc(ZT_V0_IDENTITY_GEN_MEMORY);
|
||||||
if (!genmem)
|
if (!genmem)
|
||||||
return false;
|
return false;
|
||||||
identityV0ProofOfWorkFrankenhash(m_pub,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,digest,genmem);
|
identityV0ProofOfWorkFrankenhash(m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, digest, genmem);
|
||||||
free(genmem);
|
free(genmem);
|
||||||
return ((m_fp.address() == Address(digest + 59)) && (digest[0] < 17));
|
return ((m_fp.address() == Address(digest + 59)) && (digest[0] < 17));
|
||||||
}
|
}
|
||||||
case P384: {
|
case P384: {
|
||||||
if (m_fp.address() != Address(m_fp.hash()))
|
if (m_fp.address() != Address(m_fp.hash()))
|
||||||
return false;
|
return false;
|
||||||
return identityV1ProofOfWorkCriteria(m_pub,sizeof(m_pub));
|
return identityV1ProofOfWorkCriteria(m_pub, sizeof(m_pub));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch ( ... ) {}
|
} catch (...) {}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,10 +209,10 @@ void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
||||||
if (m_hasPrivate) {
|
if (m_hasPrivate) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case C25519:
|
case C25519:
|
||||||
SHA384(h,m_pub,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,m_priv,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
SHA384(h, m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE);
|
||||||
break;
|
break;
|
||||||
case P384:
|
case P384:
|
||||||
SHA384(h,m_pub,sizeof(m_pub),m_priv,sizeof(m_priv));
|
SHA384(h, m_pub, sizeof(m_pub), m_priv, sizeof(m_priv));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -221,21 +220,21 @@ void Identity::hashWithPrivate(uint8_t h[ZT_FINGERPRINT_HASH_SIZE]) const
|
||||||
Utils::zero<48>(h);
|
Utils::zero<48>(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Identity::sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
|
unsigned int Identity::sign(const void *data, unsigned int len, void *sig, unsigned int siglen) const
|
||||||
{
|
{
|
||||||
if (m_hasPrivate) {
|
if (m_hasPrivate) {
|
||||||
switch(m_type) {
|
switch (m_type) {
|
||||||
case C25519:
|
case C25519:
|
||||||
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
|
if (siglen >= ZT_C25519_SIGNATURE_LEN) {
|
||||||
C25519::sign(m_priv,m_pub,data,len,sig);
|
C25519::sign(m_priv, m_pub, data, len, sig);
|
||||||
return ZT_C25519_SIGNATURE_LEN;
|
return ZT_C25519_SIGNATURE_LEN;
|
||||||
}
|
}
|
||||||
case P384:
|
case P384:
|
||||||
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
|
if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
|
||||||
// SECURITY: signatures also include the public keys to further enforce their coupling.
|
// SECURITY: signatures also include the public keys to further enforce their coupling.
|
||||||
uint8_t h[48];
|
uint8_t h[48];
|
||||||
SHA384(h,data,len,m_pub,sizeof(m_pub));
|
SHA384(h, data, len, m_pub, sizeof(m_pub));
|
||||||
ECC384ECDSASign(m_priv + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,h,(uint8_t *)sig);
|
ECC384ECDSASign(m_priv + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, h, (uint8_t *) sig);
|
||||||
return ZT_ECC384_SIGNATURE_SIZE;
|
return ZT_ECC384_SIGNATURE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,23 +242,23 @@ unsigned int Identity::sign(const void *data,unsigned int len,void *sig,unsigned
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Identity::verify(const void *data,unsigned int len,const void *sig,unsigned int siglen) const
|
bool Identity::verify(const void *data, unsigned int len, const void *sig, unsigned int siglen) const
|
||||||
{
|
{
|
||||||
switch(m_type) {
|
switch (m_type) {
|
||||||
case C25519:
|
case C25519:
|
||||||
return C25519::verify(m_pub,data,len,sig,siglen);
|
return C25519::verify(m_pub, data, len, sig, siglen);
|
||||||
case P384:
|
case P384:
|
||||||
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
|
if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
|
||||||
uint8_t h[48];
|
uint8_t h[48];
|
||||||
SHA384(h,data,len,m_pub,sizeof(m_pub));
|
SHA384(h, data, len, m_pub, sizeof(m_pub));
|
||||||
return ECC384ECDSAVerify(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,h,(const uint8_t *)sig);
|
return ECC384ECDSAVerify(m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, h, (const uint8_t *) sig);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Identity::agree(const Identity &id,uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) const
|
bool Identity::agree(const Identity &id, uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) const
|
||||||
{
|
{
|
||||||
uint8_t rawkey[128];
|
uint8_t rawkey[128];
|
||||||
uint8_t h[64];
|
uint8_t h[64];
|
||||||
|
@ -268,9 +267,9 @@ bool Identity::agree(const Identity &id,uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) cons
|
||||||
if ((id.m_type == C25519) || (id.m_type == P384)) {
|
if ((id.m_type == C25519) || (id.m_type == P384)) {
|
||||||
// If we are a C25519 key we can agree with another C25519 key or with only the
|
// If we are a C25519 key we can agree with another C25519 key or with only the
|
||||||
// C25519 portion of a type 1 P-384 key.
|
// C25519 portion of a type 1 P-384 key.
|
||||||
C25519::agree(m_priv,id.m_pub,rawkey);
|
C25519::agree(m_priv, id.m_pub, rawkey);
|
||||||
SHA512(h,rawkey,ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
SHA512(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key,h);
|
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key, h);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (m_type == P384) {
|
} else if (m_type == P384) {
|
||||||
|
@ -280,16 +279,16 @@ bool Identity::agree(const Identity &id,uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) cons
|
||||||
// P384 to be kosher, the C25519 secret can be considered a "salt"
|
// P384 to be kosher, the C25519 secret can be considered a "salt"
|
||||||
// or something. For those who don't trust P384 this means the privacy of
|
// or something. For those who don't trust P384 this means the privacy of
|
||||||
// your traffic is also protected by C25519.
|
// your traffic is also protected by C25519.
|
||||||
C25519::agree(m_priv,id.m_pub,rawkey);
|
C25519::agree(m_priv, id.m_pub, rawkey);
|
||||||
ECC384ECDH(id.m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE,rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
ECC384ECDH(id.m_pub + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, m_priv + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, rawkey + ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||||
SHA384(h,rawkey,ZT_C25519_ECDH_SHARED_SECRET_SIZE + ZT_ECC384_SHARED_SECRET_SIZE);
|
SHA384(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE + ZT_ECC384_SHARED_SECRET_SIZE);
|
||||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key,h);
|
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key, h);
|
||||||
return true;
|
return true;
|
||||||
} else if (id.m_type == C25519) {
|
} else if (id.m_type == C25519) {
|
||||||
// If the other identity is a C25519 identity we can agree using only that type.
|
// If the other identity is a C25519 identity we can agree using only that type.
|
||||||
C25519::agree(m_priv,id.m_pub,rawkey);
|
C25519::agree(m_priv, id.m_pub, rawkey);
|
||||||
SHA512(h,rawkey,ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
SHA512(h, rawkey, ZT_C25519_ECDH_SHARED_SECRET_SIZE);
|
||||||
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key,h);
|
Utils::copy<ZT_SYMMETRIC_KEY_SIZE>(key, h);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,40 +296,40 @@ bool Identity::agree(const Identity &id,uint8_t key[ZT_SYMMETRIC_KEY_SIZE]) cons
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
|
char *Identity::toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
|
||||||
{
|
{
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
m_fp.address().toString(p);
|
m_fp.address().toString(p);
|
||||||
p += 10;
|
p += 10;
|
||||||
*(p++) = ':';
|
*(p++) = ':';
|
||||||
|
|
||||||
switch(m_type) {
|
switch (m_type) {
|
||||||
case C25519: {
|
case C25519: {
|
||||||
*(p++) = '0';
|
*(p++) = '0';
|
||||||
*(p++) = ':';
|
*(p++) = ':';
|
||||||
Utils::hex(m_pub,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE,p);
|
Utils::hex(m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE, p);
|
||||||
p += ZT_C25519_COMBINED_PUBLIC_KEY_SIZE * 2;
|
p += ZT_C25519_COMBINED_PUBLIC_KEY_SIZE * 2;
|
||||||
if ((m_hasPrivate)&&(includePrivate)) {
|
if ((m_hasPrivate) && (includePrivate)) {
|
||||||
*(p++) = ':';
|
*(p++) = ':';
|
||||||
Utils::hex(m_priv,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE,p);
|
Utils::hex(m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE, p);
|
||||||
p += ZT_C25519_COMBINED_PRIVATE_KEY_SIZE * 2;
|
p += ZT_C25519_COMBINED_PRIVATE_KEY_SIZE * 2;
|
||||||
}
|
}
|
||||||
*p = (char)0;
|
*p = (char) 0;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
case P384: {
|
case P384: {
|
||||||
*(p++) = '1';
|
*(p++) = '1';
|
||||||
*(p++) = ':';
|
*(p++) = ':';
|
||||||
int el = Utils::b32e(m_pub,sizeof(m_pub),p,(int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
int el = Utils::b32e(m_pub, sizeof(m_pub), p, (int) (ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t) (p - buf)));
|
||||||
if (el <= 0) return nullptr;
|
if (el <= 0) return nullptr;
|
||||||
p += el;
|
p += el;
|
||||||
if ((m_hasPrivate)&&(includePrivate)) {
|
if ((m_hasPrivate) && (includePrivate)) {
|
||||||
*(p++) = ':';
|
*(p++) = ':';
|
||||||
el = Utils::b32e(m_priv,sizeof(m_priv),p,(int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
|
el = Utils::b32e(m_priv, sizeof(m_priv), p, (int) (ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t) (p - buf)));
|
||||||
if (el <= 0) return nullptr;
|
if (el <= 0) return nullptr;
|
||||||
p += el;
|
p += el;
|
||||||
}
|
}
|
||||||
*p = (char)0;
|
*p = (char) 0;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,13 +341,13 @@ bool Identity::fromString(const char *str)
|
||||||
{
|
{
|
||||||
char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH];
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
if ((!str)||(!Utils::scopy(tmp,sizeof(tmp),str)))
|
if ((!str) || (!Utils::scopy(tmp, sizeof(tmp), str)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int fno = 0;
|
int fno = 0;
|
||||||
char *saveptr = nullptr;
|
char *saveptr = nullptr;
|
||||||
for(char *f=Utils::stok(tmp,":",&saveptr);((f)&&(fno < 4));f=Utils::stok(nullptr,":",&saveptr)) {
|
for (char *f = Utils::stok(tmp, ":", &saveptr);((f) && (fno < 4));f = Utils::stok(nullptr, ":", &saveptr)) {
|
||||||
switch(fno++) {
|
switch (fno++) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
m_fp.m_cfp.address = Utils::hexStrToU64(f) & ZT_ADDRESS_MASK;
|
m_fp.m_cfp.address = Utils::hexStrToU64(f) & ZT_ADDRESS_MASK;
|
||||||
|
@ -359,9 +358,9 @@ bool Identity::fromString(const char *str)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
if ((f[0] == '0')&&(!f[1])) {
|
if ((f[0] == '0') && (!f[1])) {
|
||||||
m_type = C25519;
|
m_type = C25519;
|
||||||
} else if ((f[0] == '1')&&(!f[1])) {
|
} else if ((f[0] == '1') && (!f[1])) {
|
||||||
m_type = P384;
|
m_type = P384;
|
||||||
} else {
|
} else {
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
|
@ -370,17 +369,17 @@ bool Identity::fromString(const char *str)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
switch(m_type) {
|
switch (m_type) {
|
||||||
|
|
||||||
case C25519:
|
case C25519:
|
||||||
if (Utils::unhex(f,strlen(f),m_pub,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) != ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) {
|
if (Utils::unhex(f, strlen(f), m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) != ZT_C25519_COMBINED_PUBLIC_KEY_SIZE) {
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case P384:
|
case P384:
|
||||||
if (Utils::b32d(f,m_pub,sizeof(m_pub)) != sizeof(m_pub)) {
|
if (Utils::b32d(f, m_pub, sizeof(m_pub)) != sizeof(m_pub)) {
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -391,10 +390,10 @@ bool Identity::fromString(const char *str)
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
if (strlen(f) > 1) {
|
if (strlen(f) > 1) {
|
||||||
switch(m_type) {
|
switch (m_type) {
|
||||||
|
|
||||||
case C25519:
|
case C25519:
|
||||||
if (Utils::unhex(f,strlen(f),m_priv,ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) != ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
if (Utils::unhex(f, strlen(f), m_priv, ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) != ZT_C25519_COMBINED_PRIVATE_KEY_SIZE) {
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -403,7 +402,7 @@ bool Identity::fromString(const char *str)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case P384:
|
case P384:
|
||||||
if (Utils::b32d(f,m_priv,sizeof(m_priv)) != sizeof(m_priv)) {
|
if (Utils::b32d(f, m_priv, sizeof(m_priv)) != sizeof(m_priv)) {
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -424,7 +423,7 @@ bool Identity::fromString(const char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_computeHash();
|
m_computeHash();
|
||||||
if ((m_type == P384)&&(m_fp.address() != Address(m_fp.hash()))) {
|
if ((m_type == P384) && (m_fp.address() != Address(m_fp.hash()))) {
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -432,17 +431,17 @@ bool Identity::fromString(const char *str)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate) const noexcept
|
int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], const bool includePrivate) const noexcept
|
||||||
{
|
{
|
||||||
m_fp.address().copyTo(data);
|
m_fp.address().copyTo(data);
|
||||||
switch(m_type) {
|
switch (m_type) {
|
||||||
|
|
||||||
case C25519:
|
case C25519:
|
||||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
|
data[ZT_ADDRESS_LENGTH] = (uint8_t) C25519;
|
||||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1,m_pub);
|
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1, m_pub);
|
||||||
if ((includePrivate)&&(m_hasPrivate)) {
|
if ((includePrivate) && (m_hasPrivate)) {
|
||||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1,m_priv);
|
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1, m_priv);
|
||||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||||
} else {
|
} else {
|
||||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = 0;
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE] = 0;
|
||||||
|
@ -450,11 +449,11 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool incl
|
||||||
}
|
}
|
||||||
|
|
||||||
case P384:
|
case P384:
|
||||||
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
|
data[ZT_ADDRESS_LENGTH] = (uint8_t) P384;
|
||||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1,m_pub);
|
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1, m_pub);
|
||||||
if ((includePrivate)&&(m_hasPrivate)) {
|
if ((includePrivate) && (m_hasPrivate)) {
|
||||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,m_priv);
|
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE>(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1, m_priv);
|
||||||
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
|
||||||
} else {
|
} else {
|
||||||
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
|
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = 0;
|
||||||
|
@ -465,7 +464,7 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool incl
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Identity::unmarshal(const uint8_t *data,const int len) noexcept
|
int Identity::unmarshal(const uint8_t *data, const int len) noexcept
|
||||||
{
|
{
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
|
|
||||||
|
@ -474,13 +473,13 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
|
||||||
m_fp.m_cfp.address = Address(data).toInt();
|
m_fp.m_cfp.address = Address(data).toInt();
|
||||||
|
|
||||||
unsigned int privlen;
|
unsigned int privlen;
|
||||||
switch((m_type = (Type)data[ZT_ADDRESS_LENGTH])) {
|
switch ((m_type = (Type) data[ZT_ADDRESS_LENGTH])) {
|
||||||
|
|
||||||
case C25519:
|
case C25519:
|
||||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1))
|
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(m_pub,data + ZT_ADDRESS_LENGTH + 1);
|
Utils::copy<ZT_C25519_COMBINED_PUBLIC_KEY_SIZE>(m_pub, data + ZT_ADDRESS_LENGTH + 1);
|
||||||
m_computeHash();
|
m_computeHash();
|
||||||
|
|
||||||
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE];
|
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE];
|
||||||
|
@ -488,7 +487,7 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
|
||||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE))
|
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE))
|
||||||
return -1;
|
return -1;
|
||||||
m_hasPrivate = true;
|
m_hasPrivate = true;
|
||||||
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(m_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1);
|
Utils::copy<ZT_C25519_COMBINED_PRIVATE_KEY_SIZE>(m_priv, data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1);
|
||||||
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_COMBINED_PUBLIC_KEY_SIZE + 1 + ZT_C25519_COMBINED_PRIVATE_KEY_SIZE;
|
||||||
} else if (privlen == 0) {
|
} else if (privlen == 0) {
|
||||||
m_hasPrivate = false;
|
m_hasPrivate = false;
|
||||||
|
@ -500,7 +499,7 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
|
||||||
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1))
|
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(m_pub,data + ZT_ADDRESS_LENGTH + 1);
|
Utils::copy<ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE>(m_pub, data + ZT_ADDRESS_LENGTH + 1);
|
||||||
m_computeHash(); // this sets the address for P384
|
m_computeHash(); // this sets the address for P384
|
||||||
if (m_fp.address() != Address(m_fp.hash())) // this sanity check is possible with V1 identities
|
if (m_fp.address() != Address(m_fp.hash())) // this sanity check is possible with V1 identities
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -525,15 +524,15 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
|
||||||
|
|
||||||
void Identity::m_computeHash()
|
void Identity::m_computeHash()
|
||||||
{
|
{
|
||||||
switch(m_type) {
|
switch (m_type) {
|
||||||
default:
|
default:
|
||||||
m_fp.zero();
|
m_fp.zero();
|
||||||
break;
|
break;
|
||||||
case C25519:
|
case C25519:
|
||||||
SHA384(m_fp.m_cfp.hash,m_pub,ZT_C25519_COMBINED_PUBLIC_KEY_SIZE);
|
SHA384(m_fp.m_cfp.hash, m_pub, ZT_C25519_COMBINED_PUBLIC_KEY_SIZE);
|
||||||
break;
|
break;
|
||||||
case P384:
|
case P384:
|
||||||
SHA384(m_fp.m_cfp.hash,m_pub,sizeof(m_pub));
|
SHA384(m_fp.m_cfp.hash, m_pub, sizeof(m_pub));
|
||||||
m_fp.m_cfp.address = Address(m_fp.m_cfp.hash).toInt();
|
m_fp.m_cfp.address = Address(m_fp.m_cfp.hash).toInt();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -545,13 +544,13 @@ extern "C" {
|
||||||
|
|
||||||
ZT_Identity *ZT_Identity_new(enum ZT_Identity_Type type)
|
ZT_Identity *ZT_Identity_new(enum ZT_Identity_Type type)
|
||||||
{
|
{
|
||||||
if ((type != ZT_IDENTITY_TYPE_C25519)&&(type != ZT_IDENTITY_TYPE_P384))
|
if ((type != ZT_IDENTITY_TYPE_C25519) && (type != ZT_IDENTITY_TYPE_P384))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
try {
|
try {
|
||||||
ZeroTier::Identity *const id = new ZeroTier::Identity(); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
ZeroTier::Identity *const id = new ZeroTier::Identity(); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||||
id->generate((ZeroTier::Identity::Type)type);
|
id->generate((ZeroTier::Identity::Type) type);
|
||||||
return reinterpret_cast<ZT_Identity *>(id);
|
return reinterpret_cast<ZT_Identity *>(id);
|
||||||
} catch ( ... ) {
|
} catch (...) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -567,7 +566,7 @@ ZT_Identity *ZT_Identity_fromString(const char *idStr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return reinterpret_cast<ZT_Identity *>(id);
|
return reinterpret_cast<ZT_Identity *>(id);
|
||||||
} catch ( ... ) {
|
} catch (...) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -579,34 +578,34 @@ int ZT_Identity_validate(const ZT_Identity *id)
|
||||||
return reinterpret_cast<const ZeroTier::Identity *>(id)->locallyValidate() ? 1 : 0;
|
return reinterpret_cast<const ZeroTier::Identity *>(id)->locallyValidate() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ZT_Identity_sign(const ZT_Identity *id,const void *data,unsigned int len,void *signature,unsigned int signatureBufferLength)
|
unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned int len, void *signature, unsigned int signatureBufferLength)
|
||||||
{
|
{
|
||||||
if (!id)
|
if (!id)
|
||||||
return 0;
|
return 0;
|
||||||
if (signatureBufferLength < ZT_SIGNATURE_BUFFER_SIZE)
|
if (signatureBufferLength < ZT_SIGNATURE_BUFFER_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
return reinterpret_cast<const ZeroTier::Identity *>(id)->sign(data,len,signature,signatureBufferLength);
|
return reinterpret_cast<const ZeroTier::Identity *>(id)->sign(data, len, signature, signatureBufferLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ZT_Identity_verify(const ZT_Identity *id,const void *data,unsigned int len,const void *signature,unsigned int sigLen)
|
int ZT_Identity_verify(const ZT_Identity *id, const void *data, unsigned int len, const void *signature, unsigned int sigLen)
|
||||||
{
|
{
|
||||||
if ((!id)||(!signature)||(!sigLen))
|
if ((!id) || (!signature) || (!sigLen))
|
||||||
return 0;
|
return 0;
|
||||||
return reinterpret_cast<const ZeroTier::Identity *>(id)->verify(data,len,signature,sigLen) ? 1 : 0;
|
return reinterpret_cast<const ZeroTier::Identity *>(id)->verify(data, len, signature, sigLen) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ZT_Identity_Type ZT_Identity_type(const ZT_Identity *id)
|
enum ZT_Identity_Type ZT_Identity_type(const ZT_Identity *id)
|
||||||
{
|
{
|
||||||
if (!id)
|
if (!id)
|
||||||
return (ZT_Identity_Type)0;
|
return (ZT_Identity_Type) 0;
|
||||||
return (enum ZT_Identity_Type)reinterpret_cast<const ZeroTier::Identity *>(id)->type();
|
return (enum ZT_Identity_Type) reinterpret_cast<const ZeroTier::Identity *>(id)->type();
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ZT_Identity_toString(const ZT_Identity *id,char *buf,int capacity,int includePrivate)
|
char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int includePrivate)
|
||||||
{
|
{
|
||||||
if ((!id)||(!buf)||(capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH))
|
if ((!id) || (!buf) || (capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
reinterpret_cast<const ZeroTier::Identity *>(id)->toString(includePrivate != 0,buf);
|
reinterpret_cast<const ZeroTier::Identity *>(id)->toString(includePrivate != 0, buf);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,20 +20,23 @@
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
const InetAddress InetAddress::LO4((const void *)("\x7f\x00\x00\x01"),4,0);
|
const InetAddress InetAddress::LO4((const void *) ("\x7f\x00\x00\x01"), 4, 0);
|
||||||
const InetAddress InetAddress::LO6((const void *)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"),16,0);
|
const InetAddress InetAddress::LO6((const void *) ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0);
|
||||||
const InetAddress InetAddress::NIL;
|
const InetAddress InetAddress::NIL;
|
||||||
|
|
||||||
InetAddress::IpScope InetAddress::ipScope() const noexcept
|
InetAddress::IpScope InetAddress::ipScope() const noexcept
|
||||||
{
|
{
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
|
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
const uint32_t ip = Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr);
|
const uint32_t ip = Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr);
|
||||||
switch(ip >> 24U) {
|
switch (ip >> 24U) {
|
||||||
case 0x00: return IP_SCOPE_NONE; // 0.0.0.0/8 (reserved, never used)
|
case 0x00:
|
||||||
case 0x06: return IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army)
|
return IP_SCOPE_NONE; // 0.0.0.0/8 (reserved, never used)
|
||||||
case 0x0a: return IP_SCOPE_PRIVATE; // 10.0.0.0/8
|
case 0x06:
|
||||||
|
return IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army)
|
||||||
|
case 0x0a:
|
||||||
|
return IP_SCOPE_PRIVATE; // 10.0.0.0/8
|
||||||
case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD)
|
case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD)
|
||||||
case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN)
|
||||||
case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA)
|
||||||
|
@ -44,11 +47,13 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
|
||||||
case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA)
|
||||||
case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
|
case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security)
|
||||||
case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD)
|
||||||
case 0x38: return IP_SCOPE_PSEUDOPRIVATE; // 56.0.0.0/8 (US Postal Service)
|
case 0x38:
|
||||||
|
return IP_SCOPE_PSEUDOPRIVATE; // 56.0.0.0/8 (US Postal Service)
|
||||||
case 0x64:
|
case 0x64:
|
||||||
if ((ip & 0xffc00000) == 0x64400000) return IP_SCOPE_PRIVATE; // 100.64.0.0/10
|
if ((ip & 0xffc00000) == 0x64400000) return IP_SCOPE_PRIVATE; // 100.64.0.0/10
|
||||||
break;
|
break;
|
||||||
case 0x7f: return IP_SCOPE_LOOPBACK; // 127.0.0.0/8
|
case 0x7f:
|
||||||
|
return IP_SCOPE_LOOPBACK; // 127.0.0.0/8
|
||||||
case 0xa9:
|
case 0xa9:
|
||||||
if ((ip & 0xffff0000) == 0xa9fe0000) return IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
|
if ((ip & 0xffff0000) == 0xa9fe0000) return IP_SCOPE_LINK_LOCAL; // 169.254.0.0/16
|
||||||
break;
|
break;
|
||||||
|
@ -58,11 +63,14 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
|
||||||
case 0xc0:
|
case 0xc0:
|
||||||
if ((ip & 0xffff0000) == 0xc0a80000) return IP_SCOPE_PRIVATE; // 192.168.0.0/16
|
if ((ip & 0xffff0000) == 0xc0a80000) return IP_SCOPE_PRIVATE; // 192.168.0.0/16
|
||||||
break;
|
break;
|
||||||
case 0xff: return IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable)
|
case 0xff:
|
||||||
|
return IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable)
|
||||||
}
|
}
|
||||||
switch(ip >> 28U) {
|
switch (ip >> 28U) {
|
||||||
case 0xe: return IP_SCOPE_MULTICAST; // 224.0.0.0/4
|
case 0xe:
|
||||||
case 0xf: return IP_SCOPE_PSEUDOPRIVATE; // 240.0.0.0/4 ("reserved," usually unusable)
|
return IP_SCOPE_MULTICAST; // 224.0.0.0/4
|
||||||
|
case 0xf:
|
||||||
|
return IP_SCOPE_PSEUDOPRIVATE; // 240.0.0.0/4 ("reserved," usually unusable)
|
||||||
}
|
}
|
||||||
return IP_SCOPE_GLOBAL;
|
return IP_SCOPE_GLOBAL;
|
||||||
}
|
}
|
||||||
|
@ -71,17 +79,17 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
|
||||||
const uint8_t *const ip = as.sa_in6.sin6_addr.s6_addr;
|
const uint8_t *const ip = as.sa_in6.sin6_addr.s6_addr;
|
||||||
if ((ip[0] & 0xf0U) == 0xf0) {
|
if ((ip[0] & 0xf0U) == 0xf0) {
|
||||||
if (ip[0] == 0xff) return IP_SCOPE_MULTICAST; // ff00::/8
|
if (ip[0] == 0xff) return IP_SCOPE_MULTICAST; // ff00::/8
|
||||||
if ((ip[0] == 0xfe)&&((ip[1] & 0xc0U) == 0x80)) {
|
if ((ip[0] == 0xfe) && ((ip[1] & 0xc0U) == 0x80)) {
|
||||||
unsigned int k = 2;
|
unsigned int k = 2;
|
||||||
while ((!ip[k])&&(k < 15)) ++k;
|
while ((!ip[k]) && (k < 15)) ++k;
|
||||||
if ((k == 15)&&(ip[15] == 0x01))
|
if ((k == 15) && (ip[15] == 0x01))
|
||||||
return IP_SCOPE_LOOPBACK; // fe80::1/128
|
return IP_SCOPE_LOOPBACK; // fe80::1/128
|
||||||
else return IP_SCOPE_LINK_LOCAL; // fe80::/10
|
else return IP_SCOPE_LINK_LOCAL; // fe80::/10
|
||||||
}
|
}
|
||||||
if ((ip[0] & 0xfeU) == 0xfc) return IP_SCOPE_PRIVATE; // fc00::/7
|
if ((ip[0] & 0xfeU) == 0xfc) return IP_SCOPE_PRIVATE; // fc00::/7
|
||||||
}
|
}
|
||||||
unsigned int k = 0;
|
unsigned int k = 0;
|
||||||
while ((!ip[k])&&(k < 15)) ++k;
|
while ((!ip[k]) && (k < 15)) ++k;
|
||||||
if (k == 15) { // all 0's except last byte
|
if (k == 15) { // all 0's except last byte
|
||||||
if (ip[15] == 0x01) return IP_SCOPE_LOOPBACK; // ::1/128
|
if (ip[15] == 0x01) return IP_SCOPE_LOOPBACK; // ::1/128
|
||||||
if (ip[15] == 0x00) return IP_SCOPE_NONE; // ::/128
|
if (ip[15] == 0x00) return IP_SCOPE_NONE; // ::/128
|
||||||
|
@ -93,28 +101,28 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept
|
||||||
return IP_SCOPE_NONE;
|
return IP_SCOPE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port) noexcept
|
void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept
|
||||||
{
|
{
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
if (ipLen == 4) {
|
if (ipLen == 4) {
|
||||||
as.sa_in.sin_family = AF_INET;
|
as.sa_in.sin_family = AF_INET;
|
||||||
as.sa_in.sin_port = Utils::hton((uint16_t)port);
|
as.sa_in.sin_port = Utils::hton((uint16_t) port);
|
||||||
as.sa_in.sin_addr.s_addr = Utils::loadAsIsEndian<uint32_t>(ipBytes);
|
as.sa_in.sin_addr.s_addr = Utils::loadAsIsEndian<uint32_t>(ipBytes);
|
||||||
} else if (ipLen == 16) {
|
} else if (ipLen == 16) {
|
||||||
as.sa_in6.sin6_family = AF_INET6;
|
as.sa_in6.sin6_family = AF_INET6;
|
||||||
as.sa_in6.sin6_port = Utils::hton((uint16_t)port);
|
as.sa_in6.sin6_port = Utils::hton((uint16_t) port);
|
||||||
Utils::copy<16>(as.sa_in6.sin6_addr.s6_addr,ipBytes);
|
Utils::copy<16>(as.sa_in6.sin6_addr.s6_addr, ipBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InetAddress::isDefaultRoute() const noexcept
|
bool InetAddress::isDefaultRoute() const noexcept
|
||||||
{
|
{
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
return ((as.sa_in.sin_port == 0)&&(as.sa_in.sin_addr.s_addr == 0));
|
return ((as.sa_in.sin_port == 0) && (as.sa_in.sin_addr.s_addr == 0));
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
if (as.sa_in6.sin6_port == 0) {
|
if (as.sa_in6.sin6_port == 0) {
|
||||||
for (unsigned int i=0;i<16;++i) {
|
for (unsigned int i = 0;i < 16;++i) {
|
||||||
if (as.sa_in6.sin6_addr.s6_addr[i])
|
if (as.sa_in6.sin6_addr.s6_addr[i])
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -132,17 +140,21 @@ char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noex
|
||||||
if (*p) {
|
if (*p) {
|
||||||
while (*p) ++p;
|
while (*p) ++p;
|
||||||
*(p++) = '/';
|
*(p++) = '/';
|
||||||
Utils::decimal(port(),p);
|
Utils::decimal(port(), p);
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
|
char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept
|
||||||
{
|
{
|
||||||
buf[0] = (char)0;
|
buf[0] = (char) 0;
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET: inet_ntop(AF_INET,&as.sa_in.sin_addr.s_addr,buf,INET_ADDRSTRLEN); break;
|
case AF_INET:
|
||||||
case AF_INET6: inet_ntop(AF_INET6,as.sa_in6.sin6_addr.s6_addr,buf,INET6_ADDRSTRLEN); break;
|
inet_ntop(AF_INET, &as.sa_in.sin_addr.s_addr, buf, INET_ADDRSTRLEN);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
inet_ntop(AF_INET6, as.sa_in6.sin6_addr.s6_addr, buf, INET6_ADDRSTRLEN);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -155,27 +167,27 @@ bool InetAddress::fromString(const char *ipSlashPort) noexcept
|
||||||
|
|
||||||
if (!*ipSlashPort)
|
if (!*ipSlashPort)
|
||||||
return true;
|
return true;
|
||||||
if (!Utils::scopy(buf,sizeof(buf),ipSlashPort))
|
if (!Utils::scopy(buf, sizeof(buf), ipSlashPort))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
char *portAt = buf;
|
char *portAt = buf;
|
||||||
while ((*portAt)&&(*portAt != '/'))
|
while ((*portAt) && (*portAt != '/'))
|
||||||
++portAt;
|
++portAt;
|
||||||
unsigned int port = 0;
|
unsigned int port = 0;
|
||||||
if (*portAt) {
|
if (*portAt) {
|
||||||
*(portAt++) = (char)0;
|
*(portAt++) = (char) 0;
|
||||||
port = Utils::strToUInt(portAt) & 0xffffU;
|
port = Utils::strToUInt(portAt) & 0xffffU;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strchr(buf,':')) {
|
if (strchr(buf, ':')) {
|
||||||
as.sa_in6.sin6_family = AF_INET6;
|
as.sa_in6.sin6_family = AF_INET6;
|
||||||
as.sa_in6.sin6_port = Utils::hton((uint16_t)port);
|
as.sa_in6.sin6_port = Utils::hton((uint16_t) port);
|
||||||
inet_pton(AF_INET6,buf,as.sa_in6.sin6_addr.s6_addr);
|
inet_pton(AF_INET6, buf, as.sa_in6.sin6_addr.s6_addr);
|
||||||
return true;
|
return true;
|
||||||
} else if (strchr(buf,'.')) {
|
} else if (strchr(buf, '.')) {
|
||||||
as.sa_in.sin_family = AF_INET;
|
as.sa_in.sin_family = AF_INET;
|
||||||
as.sa_in.sin_port = Utils::hton((uint16_t)port);
|
as.sa_in.sin_port = Utils::hton((uint16_t) port);
|
||||||
inet_pton(AF_INET,buf,&as.sa_in.sin_addr.s_addr);
|
inet_pton(AF_INET, buf, &as.sa_in.sin_addr.s_addr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,22 +197,23 @@ bool InetAddress::fromString(const char *ipSlashPort) noexcept
|
||||||
InetAddress InetAddress::netmask() const noexcept
|
InetAddress InetAddress::netmask() const noexcept
|
||||||
{
|
{
|
||||||
InetAddress r(*this);
|
InetAddress r(*this);
|
||||||
switch(r.as.ss.ss_family) {
|
switch (r.as.ss.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
r.as.sa_in.sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits())));
|
r.as.sa_in.sin_addr.s_addr = Utils::hton((uint32_t) (0xffffffffU << (32 - netmaskBits())));
|
||||||
break;
|
break;
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
uint64_t nm[2];
|
uint64_t nm[2];
|
||||||
const unsigned int bits = netmaskBits();
|
const unsigned int bits = netmaskBits();
|
||||||
if(bits) {
|
if (bits) {
|
||||||
nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
nm[0] = Utils::hton((uint64_t) ((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||||
nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
nm[1] = Utils::hton((uint64_t) ((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||||
} else {
|
} else {
|
||||||
nm[0] = 0;
|
nm[0] = 0;
|
||||||
nm[1] = 0;
|
nm[1] = 0;
|
||||||
}
|
}
|
||||||
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr,nm);
|
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, nm);
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +222,7 @@ InetAddress InetAddress::broadcast() const noexcept
|
||||||
{
|
{
|
||||||
if (as.ss.ss_family == AF_INET) {
|
if (as.ss.ss_family == AF_INET) {
|
||||||
InetAddress r(*this);
|
InetAddress r(*this);
|
||||||
reinterpret_cast<sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffffU >> netmaskBits()));
|
reinterpret_cast<sockaddr_in *>(&r)->sin_addr.s_addr |= Utils::hton((uint32_t) (0xffffffffU >> netmaskBits()));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return InetAddress();
|
return InetAddress();
|
||||||
|
@ -218,18 +231,19 @@ InetAddress InetAddress::broadcast() const noexcept
|
||||||
InetAddress InetAddress::network() const noexcept
|
InetAddress InetAddress::network() const noexcept
|
||||||
{
|
{
|
||||||
InetAddress r(*this);
|
InetAddress r(*this);
|
||||||
switch(r.as.ss.ss_family) {
|
switch (r.as.ss.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
r.as.sa_in.sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits())));
|
r.as.sa_in.sin_addr.s_addr &= Utils::hton((uint32_t) (0xffffffffU << (32 - netmaskBits())));
|
||||||
break;
|
break;
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
uint64_t nm[2];
|
uint64_t nm[2];
|
||||||
const unsigned int bits = netmaskBits();
|
const unsigned int bits = netmaskBits();
|
||||||
Utils::copy<16>(nm,reinterpret_cast<sockaddr_in6 *>(&r)->sin6_addr.s6_addr);
|
Utils::copy<16>(nm, reinterpret_cast<sockaddr_in6 *>(&r)->sin6_addr.s6_addr);
|
||||||
nm[0] &= Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
nm[0] &= Utils::hton((uint64_t) ((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
|
||||||
nm[1] &= Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
nm[1] &= Utils::hton((uint64_t) ((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
|
||||||
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr,nm);
|
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, nm);
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -237,7 +251,7 @@ InetAddress InetAddress::network() const noexcept
|
||||||
bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
|
bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
|
||||||
{
|
{
|
||||||
if (addr.as.ss.ss_family == as.ss.ss_family) {
|
if (addr.as.ss.ss_family == as.ss.ss_family) {
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
const InetAddress mask(netmask());
|
const InetAddress mask(netmask());
|
||||||
InetAddress addr_mask(addr.netmask());
|
InetAddress addr_mask(addr.netmask());
|
||||||
|
@ -245,7 +259,7 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
|
||||||
const uint8_t *const m = mask.as.sa_in6.sin6_addr.s6_addr;
|
const uint8_t *const m = mask.as.sa_in6.sin6_addr.s6_addr;
|
||||||
const uint8_t *const a = addr.as.sa_in6.sin6_addr.s6_addr;
|
const uint8_t *const a = addr.as.sa_in6.sin6_addr.s6_addr;
|
||||||
const uint8_t *const b = as.sa_in6.sin6_addr.s6_addr;
|
const uint8_t *const b = as.sa_in6.sin6_addr.s6_addr;
|
||||||
for(unsigned int i=0;i<16;++i) {
|
for (unsigned int i = 0;i < 16;++i) {
|
||||||
if ((a[i] & m[i]) != (b[i] & n[i]))
|
if ((a[i] & m[i]) != (b[i] & n[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -259,14 +273,14 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept
|
||||||
bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
||||||
{
|
{
|
||||||
if (addr.as.ss.ss_family == as.ss.ss_family) {
|
if (addr.as.ss.ss_family == as.ss.ss_family) {
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
const unsigned int bits = netmaskBits();
|
const unsigned int bits = netmaskBits();
|
||||||
if (bits == 0)
|
if (bits == 0)
|
||||||
return true;
|
return true;
|
||||||
return (
|
return (
|
||||||
(Utils::ntoh((uint32_t)addr.as.sa_in.sin_addr.s_addr) >> (32 - bits)) ==
|
(Utils::ntoh((uint32_t) addr.as.sa_in.sin_addr.s_addr) >> (32 - bits)) ==
|
||||||
(Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr) >> (32 - bits))
|
(Utils::ntoh((uint32_t) as.sa_in.sin_addr.s_addr) >> (32 - bits))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
|
@ -274,7 +288,7 @@ bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
||||||
const uint8_t *const m = mask.as.sa_in6.sin6_addr.s6_addr;
|
const uint8_t *const m = mask.as.sa_in6.sin6_addr.s6_addr;
|
||||||
const uint8_t *const a = addr.as.sa_in6.sin6_addr.s6_addr;
|
const uint8_t *const a = addr.as.sa_in6.sin6_addr.s6_addr;
|
||||||
const uint8_t *const b = as.sa_in6.sin6_addr.s6_addr;
|
const uint8_t *const b = as.sa_in6.sin6_addr.s6_addr;
|
||||||
for(unsigned int i=0;i<16;++i) {
|
for (unsigned int i = 0;i < 16;++i) {
|
||||||
if ((a[i] & m[i]) != b[i])
|
if ((a[i] & m[i]) != b[i])
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -287,14 +301,14 @@ bool InetAddress::containsAddress(const InetAddress &addr) const noexcept
|
||||||
|
|
||||||
bool InetAddress::isNetwork() const noexcept
|
bool InetAddress::isNetwork() const noexcept
|
||||||
{
|
{
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
unsigned int bits = netmaskBits();
|
unsigned int bits = netmaskBits();
|
||||||
if (bits <= 0)
|
if (bits <= 0)
|
||||||
return false;
|
return false;
|
||||||
if (bits >= 32)
|
if (bits >= 32)
|
||||||
return false;
|
return false;
|
||||||
const uint32_t ip = Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr);
|
const uint32_t ip = Utils::ntoh((uint32_t) as.sa_in.sin_addr.s_addr);
|
||||||
return ((ip & (0xffffffffU >> bits)) == 0);
|
return ((ip & (0xffffffffU >> bits)) == 0);
|
||||||
}
|
}
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
|
@ -320,23 +334,23 @@ bool InetAddress::isNetwork() const noexcept
|
||||||
int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept
|
int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept
|
||||||
{
|
{
|
||||||
unsigned int port;
|
unsigned int port;
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
port = Utils::ntoh((uint16_t)reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
port = Utils::ntoh((uint16_t) reinterpret_cast<const sockaddr_in *>(this)->sin_port);
|
||||||
data[0] = 4;
|
data[0] = 4;
|
||||||
data[1] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[0];
|
data[1] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[0];
|
||||||
data[2] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[1];
|
data[2] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[1];
|
||||||
data[3] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[2];
|
data[3] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[2];
|
||||||
data[4] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[3];
|
data[4] = reinterpret_cast<const uint8_t *>(&as.sa_in.sin_addr.s_addr)[3];
|
||||||
data[5] = (uint8_t)(port >> 8U);
|
data[5] = (uint8_t) (port >> 8U);
|
||||||
data[6] = (uint8_t)port;
|
data[6] = (uint8_t) port;
|
||||||
return 7;
|
return 7;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
port = Utils::ntoh((uint16_t)as.sa_in6.sin6_port);
|
port = Utils::ntoh((uint16_t) as.sa_in6.sin6_port);
|
||||||
data[0] = 6;
|
data[0] = 6;
|
||||||
Utils::copy<16>(data + 1,as.sa_in6.sin6_addr.s6_addr);
|
Utils::copy<16>(data + 1, as.sa_in6.sin6_addr.s6_addr);
|
||||||
data[17] = (uint8_t)(port >> 8U);
|
data[17] = (uint8_t) (port >> 8U);
|
||||||
data[18] = (uint8_t)port;
|
data[18] = (uint8_t) port;
|
||||||
return 19;
|
return 19;
|
||||||
default:
|
default:
|
||||||
data[0] = 0;
|
data[0] = 0;
|
||||||
|
@ -344,12 +358,12 @@ int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const no
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int InetAddress::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept
|
||||||
{
|
{
|
||||||
memoryZero(this);
|
memoryZero(this);
|
||||||
if (unlikely(len <= 0))
|
if (unlikely(len <= 0))
|
||||||
return -1;
|
return -1;
|
||||||
switch(data[0]) {
|
switch (data[0]) {
|
||||||
case 0:
|
case 0:
|
||||||
return 1;
|
return 1;
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -364,7 +378,7 @@ int InetAddress::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
||||||
return -1;
|
return -1;
|
||||||
as.sa_in6.sin6_family = AF_INET6;
|
as.sa_in6.sin6_family = AF_INET6;
|
||||||
as.sa_in6.sin6_port = Utils::loadAsIsEndian<uint16_t>(data + 17);
|
as.sa_in6.sin6_port = Utils::loadAsIsEndian<uint16_t>(data + 17);
|
||||||
Utils::copy<16>(as.sa_in6.sin6_addr.s6_addr,data + 1);
|
Utils::copy<16>(as.sa_in6.sin6_addr.s6_addr, data + 1);
|
||||||
return 19;
|
return 19;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -395,46 +409,46 @@ InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) noexcept
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress) noexcept
|
InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress) noexcept
|
||||||
{
|
{
|
||||||
InetAddress r;
|
InetAddress r;
|
||||||
r.as.sa_in6.sin6_family = AF_INET6;
|
r.as.sa_in6.sin6_family = AF_INET6;
|
||||||
r.as.sa_in6.sin6_port = ZT_CONST_TO_BE_UINT16(88); // /88 includes 0xfd + network ID, discriminating by device ID below that
|
r.as.sa_in6.sin6_port = ZT_CONST_TO_BE_UINT16(88); // /88 includes 0xfd + network ID, discriminating by device ID below that
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[0] = 0xfd;
|
r.as.sa_in6.sin6_addr.s6_addr[0] = 0xfd;
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56U);
|
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t) (nwid >> 56U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48U);
|
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t) (nwid >> 48U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 40U);
|
r.as.sa_in6.sin6_addr.s6_addr[3] = (uint8_t) (nwid >> 40U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[4] = (uint8_t)(nwid >> 32U);
|
r.as.sa_in6.sin6_addr.s6_addr[4] = (uint8_t) (nwid >> 32U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[5] = (uint8_t)(nwid >> 24U);
|
r.as.sa_in6.sin6_addr.s6_addr[5] = (uint8_t) (nwid >> 24U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[6] = (uint8_t)(nwid >> 16U);
|
r.as.sa_in6.sin6_addr.s6_addr[6] = (uint8_t) (nwid >> 16U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[7] = (uint8_t)(nwid >> 8U);
|
r.as.sa_in6.sin6_addr.s6_addr[7] = (uint8_t) (nwid >> 8U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[8] = (uint8_t)nwid;
|
r.as.sa_in6.sin6_addr.s6_addr[8] = (uint8_t) nwid;
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[9] = 0x99;
|
r.as.sa_in6.sin6_addr.s6_addr[9] = 0x99;
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[10] = 0x93;
|
r.as.sa_in6.sin6_addr.s6_addr[10] = 0x93;
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[11] = (uint8_t)(zeroTierAddress >> 32U);
|
r.as.sa_in6.sin6_addr.s6_addr[11] = (uint8_t) (zeroTierAddress >> 32U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[12] = (uint8_t)(zeroTierAddress >> 24U);
|
r.as.sa_in6.sin6_addr.s6_addr[12] = (uint8_t) (zeroTierAddress >> 24U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16U);
|
r.as.sa_in6.sin6_addr.s6_addr[13] = (uint8_t) (zeroTierAddress >> 16U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8U);
|
r.as.sa_in6.sin6_addr.s6_addr[14] = (uint8_t) (zeroTierAddress >> 8U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[15] = (uint8_t)zeroTierAddress;
|
r.as.sa_in6.sin6_addr.s6_addr[15] = (uint8_t) zeroTierAddress;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
InetAddress InetAddress::makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress) noexcept
|
InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress) noexcept
|
||||||
{
|
{
|
||||||
nwid ^= (nwid >> 32U);
|
nwid ^= (nwid >> 32U);
|
||||||
InetAddress r;
|
InetAddress r;
|
||||||
r.as.sa_in6.sin6_family = AF_INET6;
|
r.as.sa_in6.sin6_family = AF_INET6;
|
||||||
r.as.sa_in6.sin6_port = ZT_CONST_TO_BE_UINT16(40);
|
r.as.sa_in6.sin6_port = ZT_CONST_TO_BE_UINT16(40);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[0] = 0xfc;
|
r.as.sa_in6.sin6_addr.s6_addr[0] = 0xfc;
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24U);
|
r.as.sa_in6.sin6_addr.s6_addr[1] = (uint8_t) (nwid >> 24U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 16U);
|
r.as.sa_in6.sin6_addr.s6_addr[2] = (uint8_t) (nwid >> 16U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 8U);
|
r.as.sa_in6.sin6_addr.s6_addr[3] = (uint8_t) (nwid >> 8U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[4] = (uint8_t)nwid;
|
r.as.sa_in6.sin6_addr.s6_addr[4] = (uint8_t) nwid;
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[5] = (uint8_t)(zeroTierAddress >> 32U);
|
r.as.sa_in6.sin6_addr.s6_addr[5] = (uint8_t) (zeroTierAddress >> 32U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[6] = (uint8_t)(zeroTierAddress >> 24U);
|
r.as.sa_in6.sin6_addr.s6_addr[6] = (uint8_t) (zeroTierAddress >> 24U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[7] = (uint8_t)(zeroTierAddress >> 16U);
|
r.as.sa_in6.sin6_addr.s6_addr[7] = (uint8_t) (zeroTierAddress >> 16U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[8] = (uint8_t)(zeroTierAddress >> 8U);
|
r.as.sa_in6.sin6_addr.s6_addr[8] = (uint8_t) (zeroTierAddress >> 8U);
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[9] = (uint8_t)zeroTierAddress;
|
r.as.sa_in6.sin6_addr.s6_addr[9] = (uint8_t) zeroTierAddress;
|
||||||
r.as.sa_in6.sin6_addr.s6_addr[15] = 0x01;
|
r.as.sa_in6.sin6_addr.s6_addr[15] = 0x01;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,28 +71,54 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hasher for unordered sets and maps in C++11
|
// Hasher for unordered sets and maps in C++11
|
||||||
struct Hasher { ZT_INLINE std::size_t operator()(const InetAddress &a) const noexcept { return (std::size_t)a.hashCode(); } };
|
struct Hasher
|
||||||
|
{
|
||||||
|
ZT_INLINE std::size_t operator()(const InetAddress &a) const noexcept
|
||||||
|
{ return (std::size_t) a.hashCode(); }
|
||||||
|
};
|
||||||
|
|
||||||
ZT_INLINE InetAddress() noexcept { memoryZero(this); }
|
ZT_INLINE InetAddress() noexcept
|
||||||
|
{ memoryZero(this); }
|
||||||
|
|
||||||
explicit ZT_INLINE InetAddress(const sockaddr_storage &ss) noexcept { *this = ss; }
|
explicit ZT_INLINE InetAddress(const sockaddr_storage &ss) noexcept
|
||||||
explicit ZT_INLINE InetAddress(const sockaddr_storage *const ss) noexcept { *this = ss; }
|
{ *this = ss; }
|
||||||
explicit ZT_INLINE InetAddress(const sockaddr &sa) noexcept { *this = sa; }
|
|
||||||
explicit ZT_INLINE InetAddress(const sockaddr *const sa) noexcept { *this = sa; }
|
|
||||||
explicit ZT_INLINE InetAddress(const sockaddr_in &sa) noexcept { *this = sa; }
|
|
||||||
explicit ZT_INLINE InetAddress(const sockaddr_in *const sa) noexcept { *this = sa; }
|
|
||||||
explicit ZT_INLINE InetAddress(const sockaddr_in6 &sa) noexcept { *this = sa; }
|
|
||||||
explicit ZT_INLINE InetAddress(const sockaddr_in6 *const sa) noexcept { *this = sa; }
|
|
||||||
|
|
||||||
ZT_INLINE InetAddress(const void *const ipBytes,const unsigned int ipLen,const unsigned int port) noexcept { this->set(ipBytes,ipLen,port); }
|
explicit ZT_INLINE InetAddress(const sockaddr_storage *const ss) noexcept
|
||||||
ZT_INLINE InetAddress(const uint32_t ipv4,const unsigned int port) noexcept { this->set(&ipv4,4,port); }
|
{ *this = ss; }
|
||||||
explicit ZT_INLINE InetAddress(const char *const ipSlashPort) noexcept { this->fromString(ipSlashPort); }
|
|
||||||
|
explicit ZT_INLINE InetAddress(const sockaddr &sa) noexcept
|
||||||
|
{ *this = sa; }
|
||||||
|
|
||||||
|
explicit ZT_INLINE InetAddress(const sockaddr *const sa) noexcept
|
||||||
|
{ *this = sa; }
|
||||||
|
|
||||||
|
explicit ZT_INLINE InetAddress(const sockaddr_in &sa) noexcept
|
||||||
|
{ *this = sa; }
|
||||||
|
|
||||||
|
explicit ZT_INLINE InetAddress(const sockaddr_in *const sa) noexcept
|
||||||
|
{ *this = sa; }
|
||||||
|
|
||||||
|
explicit ZT_INLINE InetAddress(const sockaddr_in6 &sa) noexcept
|
||||||
|
{ *this = sa; }
|
||||||
|
|
||||||
|
explicit ZT_INLINE InetAddress(const sockaddr_in6 *const sa) noexcept
|
||||||
|
{ *this = sa; }
|
||||||
|
|
||||||
|
ZT_INLINE InetAddress(const void *const ipBytes, const unsigned int ipLen, const unsigned int port) noexcept
|
||||||
|
{ this->set(ipBytes, ipLen, port); }
|
||||||
|
|
||||||
|
ZT_INLINE InetAddress(const uint32_t ipv4, const unsigned int port) noexcept
|
||||||
|
{ this->set(&ipv4, 4, port); }
|
||||||
|
|
||||||
|
explicit ZT_INLINE InetAddress(const char *const ipSlashPort) noexcept
|
||||||
|
{ this->fromString(ipSlashPort); }
|
||||||
|
|
||||||
ZT_INLINE InetAddress &operator=(const sockaddr_storage &ss) noexcept
|
ZT_INLINE InetAddress &operator=(const sockaddr_storage &ss) noexcept
|
||||||
{
|
{
|
||||||
as.ss = ss;
|
as.ss = ss;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE InetAddress &operator=(const sockaddr_storage *ss) noexcept
|
ZT_INLINE InetAddress &operator=(const sockaddr_storage *ss) noexcept
|
||||||
{
|
{
|
||||||
if (ss)
|
if (ss)
|
||||||
|
@ -100,11 +126,13 @@ public:
|
||||||
else memoryZero(this);
|
else memoryZero(this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE InetAddress &operator=(const sockaddr_in &sa) noexcept
|
ZT_INLINE InetAddress &operator=(const sockaddr_in &sa) noexcept
|
||||||
{
|
{
|
||||||
as.sa_in = sa;
|
as.sa_in = sa;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE InetAddress &operator=(const sockaddr_in *sa) noexcept
|
ZT_INLINE InetAddress &operator=(const sockaddr_in *sa) noexcept
|
||||||
{
|
{
|
||||||
if (sa)
|
if (sa)
|
||||||
|
@ -112,11 +140,13 @@ public:
|
||||||
else memoryZero(this);
|
else memoryZero(this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE InetAddress &operator=(const sockaddr_in6 &sa) noexcept
|
ZT_INLINE InetAddress &operator=(const sockaddr_in6 &sa) noexcept
|
||||||
{
|
{
|
||||||
as.sa_in6 = sa;
|
as.sa_in6 = sa;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE InetAddress &operator=(const sockaddr_in6 *sa) noexcept
|
ZT_INLINE InetAddress &operator=(const sockaddr_in6 *sa) noexcept
|
||||||
{
|
{
|
||||||
if (sa)
|
if (sa)
|
||||||
|
@ -124,6 +154,7 @@ public:
|
||||||
else memoryZero(this);
|
else memoryZero(this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE InetAddress &operator=(const sockaddr &sa) noexcept
|
ZT_INLINE InetAddress &operator=(const sockaddr &sa) noexcept
|
||||||
{
|
{
|
||||||
if (sa.sa_family == AF_INET)
|
if (sa.sa_family == AF_INET)
|
||||||
|
@ -133,6 +164,7 @@ public:
|
||||||
else memoryZero(this);
|
else memoryZero(this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE InetAddress &operator=(const sockaddr *sa) noexcept
|
ZT_INLINE InetAddress &operator=(const sockaddr *sa) noexcept
|
||||||
{
|
{
|
||||||
if (sa) {
|
if (sa) {
|
||||||
|
@ -147,12 +179,14 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE void clear() noexcept { memoryZero(this); }
|
ZT_INLINE void clear() noexcept
|
||||||
|
{ memoryZero(this); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Address family (ss_family in sockaddr_storage)
|
* @return Address family (ss_family in sockaddr_storage)
|
||||||
*/
|
*/
|
||||||
ZT_INLINE uint8_t family() const noexcept { return as.ss.ss_family; }
|
ZT_INLINE uint8_t family() const noexcept
|
||||||
|
{ return as.ss.ss_family; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return IP scope classification (e.g. loopback, link-local, private, global)
|
* @return IP scope classification (e.g. loopback, link-local, private, global)
|
||||||
|
@ -166,7 +200,7 @@ public:
|
||||||
* @param ipLen Length of IP address: 4 or 16
|
* @param ipLen Length of IP address: 4 or 16
|
||||||
* @param port Port number or 0 for none
|
* @param port Port number or 0 for none
|
||||||
*/
|
*/
|
||||||
void set(const void *ipBytes,unsigned int ipLen,unsigned int port) noexcept;
|
void set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the port component
|
* Set the port component
|
||||||
|
@ -175,9 +209,13 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_INLINE void setPort(unsigned int port) noexcept
|
ZT_INLINE void setPort(unsigned int port) noexcept
|
||||||
{
|
{
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET: as.sa_in.sin_port = Utils::hton((uint16_t)port); break;
|
case AF_INET:
|
||||||
case AF_INET6: as.sa_in6.sin6_port = Utils::hton((uint16_t)port); break;
|
as.sa_in.sin_port = Utils::hton((uint16_t) port);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
as.sa_in6.sin6_port = Utils::hton((uint16_t) port);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,13 +228,25 @@ public:
|
||||||
* @return ASCII IP/port format representation
|
* @return ASCII IP/port format representation
|
||||||
*/
|
*/
|
||||||
char *toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
|
char *toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
|
||||||
ZT_INLINE String toString() const { char buf[ZT_INETADDRESS_STRING_SIZE_MAX]; toString(buf); return String(buf); }
|
|
||||||
|
ZT_INLINE String toString() const
|
||||||
|
{
|
||||||
|
char buf[ZT_INETADDRESS_STRING_SIZE_MAX];
|
||||||
|
toString(buf);
|
||||||
|
return String(buf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return IP portion only, in ASCII string format
|
* @return IP portion only, in ASCII string format
|
||||||
*/
|
*/
|
||||||
char *toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
|
char *toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept;
|
||||||
ZT_INLINE String toIpString() const { char buf[ZT_INETADDRESS_STRING_SIZE_MAX]; toIpString(buf); return String(buf); }
|
|
||||||
|
ZT_INLINE String toIpString() const
|
||||||
|
{
|
||||||
|
char buf[ZT_INETADDRESS_STRING_SIZE_MAX];
|
||||||
|
toIpString(buf);
|
||||||
|
return String(buf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ipSlashPort IP/port (port is optional, will be 0 if not included)
|
* @param ipSlashPort IP/port (port is optional, will be 0 if not included)
|
||||||
|
@ -209,10 +259,13 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_INLINE unsigned int port() const noexcept
|
ZT_INLINE unsigned int port() const noexcept
|
||||||
{
|
{
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET: return Utils::ntoh((uint16_t)as.sa_in.sin_port);
|
case AF_INET:
|
||||||
case AF_INET6: return Utils::ntoh((uint16_t)as.sa_in6.sin6_port);
|
return Utils::ntoh((uint16_t) as.sa_in.sin_port);
|
||||||
default: return 0;
|
case AF_INET6:
|
||||||
|
return Utils::ntoh((uint16_t) as.sa_in6.sin6_port);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +278,8 @@ public:
|
||||||
*
|
*
|
||||||
* @return Netmask bits
|
* @return Netmask bits
|
||||||
*/
|
*/
|
||||||
ZT_INLINE unsigned int netmaskBits() const noexcept { return port(); }
|
ZT_INLINE unsigned int netmaskBits() const noexcept
|
||||||
|
{ return port(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if netmask bits is valid for the address type
|
* @return True if netmask bits is valid for the address type
|
||||||
|
@ -233,9 +287,11 @@ public:
|
||||||
ZT_INLINE bool netmaskBitsValid() const noexcept
|
ZT_INLINE bool netmaskBitsValid() const noexcept
|
||||||
{
|
{
|
||||||
const unsigned int n = port();
|
const unsigned int n = port();
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET: return (n <= 32);
|
case AF_INET:
|
||||||
case AF_INET6: return (n <= 128);
|
return (n <= 32);
|
||||||
|
case AF_INET6:
|
||||||
|
return (n <= 128);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -248,7 +304,8 @@ public:
|
||||||
*
|
*
|
||||||
* @return Gateway metric
|
* @return Gateway metric
|
||||||
*/
|
*/
|
||||||
ZT_INLINE unsigned int metric() const noexcept { return port(); }
|
ZT_INLINE unsigned int metric() const noexcept
|
||||||
|
{ return port(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a full netmask as an InetAddress
|
* Construct a full netmask as an InetAddress
|
||||||
|
@ -293,22 +350,27 @@ public:
|
||||||
/**
|
/**
|
||||||
* @return True if this is an IPv4 address
|
* @return True if this is an IPv4 address
|
||||||
*/
|
*/
|
||||||
ZT_INLINE bool isV4() const noexcept { return (as.ss.ss_family == AF_INET); }
|
ZT_INLINE bool isV4() const noexcept
|
||||||
|
{ return (as.ss.ss_family == AF_INET); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if this is an IPv6 address
|
* @return True if this is an IPv6 address
|
||||||
*/
|
*/
|
||||||
ZT_INLINE bool isV6() const noexcept { return (as.ss.ss_family == AF_INET6); }
|
ZT_INLINE bool isV6() const noexcept
|
||||||
|
{ return (as.ss.ss_family == AF_INET6); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return pointer to raw address bytes or NULL if not available
|
* @return pointer to raw address bytes or NULL if not available
|
||||||
*/
|
*/
|
||||||
ZT_INLINE const void *rawIpData() const noexcept
|
ZT_INLINE const void *rawIpData() const noexcept
|
||||||
{
|
{
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET: return reinterpret_cast<const void *>(&(as.sa_in.sin_addr.s_addr));
|
case AF_INET:
|
||||||
case AF_INET6: return reinterpret_cast<const void *>(as.sa_in6.sin6_addr.s6_addr);
|
return reinterpret_cast<const void *>(&(as.sa_in.sin_addr.s_addr));
|
||||||
default: return nullptr;
|
case AF_INET6:
|
||||||
|
return reinterpret_cast<const void *>(as.sa_in6.sin6_addr.s6_addr);
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,14 +380,14 @@ public:
|
||||||
ZT_INLINE InetAddress ipOnly() const noexcept
|
ZT_INLINE InetAddress ipOnly() const noexcept
|
||||||
{
|
{
|
||||||
InetAddress r;
|
InetAddress r;
|
||||||
switch(as.ss.ss_family) {
|
switch (as.ss.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
r.as.sa_in.sin_family = AF_INET;
|
r.as.sa_in.sin_family = AF_INET;
|
||||||
r.as.sa_in.sin_addr.s_addr = as.sa_in.sin_addr.s_addr;
|
r.as.sa_in.sin_addr.s_addr = as.sa_in.sin_addr.s_addr;
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
r.as.sa_in6.sin6_family = AF_INET6;
|
r.as.sa_in6.sin6_family = AF_INET6;
|
||||||
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr,as.sa_in6.sin6_addr.s6_addr);
|
Utils::copy<16>(r.as.sa_in6.sin6_addr.s6_addr, as.sa_in6.sin6_addr.s6_addr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -344,8 +406,8 @@ public:
|
||||||
if (f == AF_INET)
|
if (f == AF_INET)
|
||||||
return as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr;
|
return as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr;
|
||||||
if (f == AF_INET6)
|
if (f == AF_INET6)
|
||||||
return memcmp(as.sa_in6.sin6_addr.s6_addr,a.as.sa_in6.sin6_addr.s6_addr,16) == 0;
|
return memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 16) == 0;
|
||||||
return memcmp(this,&a,sizeof(InetAddress)) == 0;
|
return memcmp(this, &a, sizeof(InetAddress)) == 0;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -365,8 +427,8 @@ public:
|
||||||
if (f == AF_INET)
|
if (f == AF_INET)
|
||||||
return as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr;
|
return as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr;
|
||||||
if (f == AF_INET6)
|
if (f == AF_INET6)
|
||||||
return memcmp(as.sa_in6.sin6_addr.s6_addr,a.as.sa_in6.sin6_addr.s6_addr,8) == 0;
|
return memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 8) == 0;
|
||||||
return (memcmp(this,&a,sizeof(InetAddress)) == 0);
|
return (memcmp(this, &a, sizeof(InetAddress)) == 0);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -374,15 +436,15 @@ public:
|
||||||
ZT_INLINE unsigned long hashCode() const noexcept
|
ZT_INLINE unsigned long hashCode() const noexcept
|
||||||
{
|
{
|
||||||
if (as.ss.ss_family == AF_INET) {
|
if (as.ss.ss_family == AF_INET) {
|
||||||
return (unsigned long)Utils::hash32(((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce);
|
return (unsigned long) Utils::hash32(((uint32_t) as.sa_in.sin_addr.s_addr + (uint32_t) as.sa_in.sin_port) ^ (uint32_t) Utils::s_mapNonce);
|
||||||
} else if (as.ss.ss_family == AF_INET6) {
|
} else if (as.ss.ss_family == AF_INET6) {
|
||||||
return (unsigned long)Utils::hash64(
|
return (unsigned long) Utils::hash64(
|
||||||
(Utils::loadAsIsEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr) +
|
(Utils::loadAsIsEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr) +
|
||||||
Utils::loadAsIsEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr + 8) +
|
Utils::loadAsIsEndian<uint64_t>(as.sa_in6.sin6_addr.s6_addr + 8) +
|
||||||
(uint64_t)as.sa_in6.sin6_port) ^
|
(uint64_t) as.sa_in6.sin6_port) ^
|
||||||
Utils::s_mapNonce);
|
Utils::s_mapNonce);
|
||||||
}
|
}
|
||||||
return Utils::fnv1a32(this,sizeof(InetAddress));
|
return Utils::fnv1a32(this, sizeof(InetAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -398,48 +460,61 @@ public:
|
||||||
/**
|
/**
|
||||||
* @return True if address family is non-zero
|
* @return True if address family is non-zero
|
||||||
*/
|
*/
|
||||||
explicit ZT_INLINE operator bool() const noexcept { return (as.ss.ss_family != 0); }
|
explicit ZT_INLINE operator bool() const noexcept
|
||||||
|
{ return (as.ss.ss_family != 0); }
|
||||||
|
|
||||||
|
static constexpr int marshalSizeMax() noexcept
|
||||||
|
{ return ZT_INETADDRESS_MARSHAL_SIZE_MAX; }
|
||||||
|
|
||||||
static constexpr int marshalSizeMax() noexcept { return ZT_INETADDRESS_MARSHAL_SIZE_MAX; }
|
|
||||||
int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept;
|
int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept;
|
||||||
int unmarshal(const uint8_t *restrict data,int len) noexcept;
|
|
||||||
|
int unmarshal(const uint8_t *restrict data, int len) noexcept;
|
||||||
|
|
||||||
ZT_INLINE bool operator==(const InetAddress &a) const noexcept
|
ZT_INLINE bool operator==(const InetAddress &a) const noexcept
|
||||||
{
|
{
|
||||||
if (as.ss.ss_family == a.as.ss.ss_family) {
|
if (as.ss.ss_family == a.as.ss.ss_family) {
|
||||||
if (as.ss.ss_family == AF_INET)
|
if (as.ss.ss_family == AF_INET)
|
||||||
return ((as.sa_in.sin_port == a.as.sa_in.sin_port)&&(as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr));
|
return ((as.sa_in.sin_port == a.as.sa_in.sin_port) && (as.sa_in.sin_addr.s_addr == a.as.sa_in.sin_addr.s_addr));
|
||||||
if (as.ss.ss_family == AF_INET6)
|
if (as.ss.ss_family == AF_INET6)
|
||||||
return ((as.sa_in6.sin6_port == a.as.sa_in6.sin6_port)&&(memcmp(as.sa_in6.sin6_addr.s6_addr,a.as.sa_in6.sin6_addr.s6_addr,16) == 0));
|
return ((as.sa_in6.sin6_port == a.as.sa_in6.sin6_port) && (memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 16) == 0));
|
||||||
return memcmp(this,&a,sizeof(InetAddress)) == 0;
|
return memcmp(this, &a, sizeof(InetAddress)) == 0;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_INLINE bool operator<(const InetAddress &a) const noexcept
|
ZT_INLINE bool operator<(const InetAddress &a) const noexcept
|
||||||
{
|
{
|
||||||
if (as.ss.ss_family == a.as.ss.ss_family) {
|
if (as.ss.ss_family == a.as.ss.ss_family) {
|
||||||
if (as.ss.ss_family == AF_INET) {
|
if (as.ss.ss_family == AF_INET) {
|
||||||
const uint16_t p0 = Utils::ntoh((uint16_t)as.sa_in.sin_port);
|
const uint16_t p0 = Utils::ntoh((uint16_t) as.sa_in.sin_port);
|
||||||
const uint16_t p1 = Utils::ntoh((uint16_t)a.as.sa_in.sin_port);
|
const uint16_t p1 = Utils::ntoh((uint16_t) a.as.sa_in.sin_port);
|
||||||
if (p0 == p1)
|
if (p0 == p1)
|
||||||
return Utils::ntoh((uint32_t)as.sa_in.sin_addr.s_addr) < Utils::ntoh((uint32_t)a.as.sa_in.sin_addr.s_addr);
|
return Utils::ntoh((uint32_t) as.sa_in.sin_addr.s_addr) < Utils::ntoh((uint32_t) a.as.sa_in.sin_addr.s_addr);
|
||||||
return p0 < p1;
|
return p0 < p1;
|
||||||
}
|
}
|
||||||
if (as.ss.ss_family == AF_INET6) {
|
if (as.ss.ss_family == AF_INET6) {
|
||||||
const uint16_t p0 = Utils::ntoh((uint16_t)as.sa_in6.sin6_port);
|
const uint16_t p0 = Utils::ntoh((uint16_t) as.sa_in6.sin6_port);
|
||||||
const uint16_t p1 = Utils::ntoh((uint16_t)a.as.sa_in6.sin6_port);
|
const uint16_t p1 = Utils::ntoh((uint16_t) a.as.sa_in6.sin6_port);
|
||||||
if (p0 == p1)
|
if (p0 == p1)
|
||||||
return memcmp(as.sa_in6.sin6_addr.s6_addr,a.as.sa_in6.sin6_addr.s6_addr,16) < 0;
|
return memcmp(as.sa_in6.sin6_addr.s6_addr, a.as.sa_in6.sin6_addr.s6_addr, 16) < 0;
|
||||||
return p0 < p1;
|
return p0 < p1;
|
||||||
}
|
}
|
||||||
return memcmp(this,&a,sizeof(InetAddress)) < 0;
|
return memcmp(this, &a, sizeof(InetAddress)) < 0;
|
||||||
}
|
}
|
||||||
return as.ss.ss_family < a.as.ss.ss_family;
|
return as.ss.ss_family < a.as.ss.ss_family;
|
||||||
}
|
}
|
||||||
ZT_INLINE bool operator!=(const InetAddress &a) const noexcept { return !(*this == a); }
|
|
||||||
ZT_INLINE bool operator>(const InetAddress &a) const noexcept { return (a < *this); }
|
ZT_INLINE bool operator!=(const InetAddress &a) const noexcept
|
||||||
ZT_INLINE bool operator<=(const InetAddress &a) const noexcept { return !(a < *this); }
|
{ return !(*this == a); }
|
||||||
ZT_INLINE bool operator>=(const InetAddress &a) const noexcept { return !(*this < a); }
|
|
||||||
|
ZT_INLINE bool operator>(const InetAddress &a) const noexcept
|
||||||
|
{ return (a < *this); }
|
||||||
|
|
||||||
|
ZT_INLINE bool operator<=(const InetAddress &a) const noexcept
|
||||||
|
{ return !(a < *this); }
|
||||||
|
|
||||||
|
ZT_INLINE bool operator>=(const InetAddress &a) const noexcept
|
||||||
|
{ return !(*this < a); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute an IPv6 link-local address
|
* Compute an IPv6 link-local address
|
||||||
|
@ -490,17 +565,18 @@ public:
|
||||||
* @param zeroTierAddress 40-bit device address (in least significant 40 bits, highest 24 bits ignored)
|
* @param zeroTierAddress 40-bit device address (in least significant 40 bits, highest 24 bits ignored)
|
||||||
* @return IPv6 private unicast address with /88 netmask
|
* @return IPv6 private unicast address with /88 netmask
|
||||||
*/
|
*/
|
||||||
static InetAddress makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress) noexcept;
|
static InetAddress makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute a private IPv6 "6plane" unicast address from network ID and ZeroTier address
|
* Compute a private IPv6 "6plane" unicast address from network ID and ZeroTier address
|
||||||
*/
|
*/
|
||||||
static InetAddress makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress) noexcept;
|
static InetAddress makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Union allowing this to be accessed as a sockaddr of any supported type.
|
* Union allowing this to be accessed as a sockaddr of any supported type.
|
||||||
*/
|
*/
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
sockaddr_storage ss;
|
sockaddr_storage ss;
|
||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
sockaddr_in sa_in;
|
sockaddr_in sa_in;
|
||||||
|
@ -508,22 +584,53 @@ public:
|
||||||
} as;
|
} as;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *const p) noexcept { return reinterpret_cast<InetAddress *>(p); }
|
static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *const p) noexcept
|
||||||
static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *const p) noexcept { return reinterpret_cast<InetAddress *>(p); }
|
{ return reinterpret_cast<InetAddress *>(p); }
|
||||||
static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept { return reinterpret_cast<InetAddress *>(p); }
|
|
||||||
static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept { return reinterpret_cast<InetAddress *>(p); }
|
static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *const p) noexcept
|
||||||
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept { return reinterpret_cast<const InetAddress *>(p); }
|
{ return reinterpret_cast<InetAddress *>(p); }
|
||||||
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *const p) noexcept { return reinterpret_cast<const InetAddress *>(p); }
|
|
||||||
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexcept { return reinterpret_cast<const InetAddress *>(p); }
|
static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept
|
||||||
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept { return reinterpret_cast<const InetAddress *>(p); }
|
{ return reinterpret_cast<InetAddress *>(p); }
|
||||||
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept { return *reinterpret_cast<InetAddress *>(&p); }
|
|
||||||
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in6 &p) noexcept { return *reinterpret_cast<InetAddress *>(&p); }
|
static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept
|
||||||
static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept { return *reinterpret_cast<InetAddress *>(&p); }
|
{ return reinterpret_cast<InetAddress *>(p); }
|
||||||
static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept { return *reinterpret_cast<InetAddress *>(&p); }
|
|
||||||
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept { return *reinterpret_cast<const InetAddress *>(&p); }
|
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept
|
||||||
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in6 &p) noexcept { return *reinterpret_cast<const InetAddress *>(&p); }
|
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||||
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr &p) noexcept { return *reinterpret_cast<const InetAddress *>(&p); }
|
|
||||||
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept { return *reinterpret_cast<const InetAddress *>(&p); }
|
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *const p) noexcept
|
||||||
|
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||||
|
|
||||||
|
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexcept
|
||||||
|
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||||
|
|
||||||
|
static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept
|
||||||
|
{ return reinterpret_cast<const InetAddress *>(p); }
|
||||||
|
|
||||||
|
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept
|
||||||
|
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||||
|
|
||||||
|
static ZT_INLINE InetAddress &asInetAddress(sockaddr_in6 &p) noexcept
|
||||||
|
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||||
|
|
||||||
|
static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept
|
||||||
|
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||||
|
|
||||||
|
static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept
|
||||||
|
{ return *reinterpret_cast<InetAddress *>(&p); }
|
||||||
|
|
||||||
|
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept
|
||||||
|
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||||
|
|
||||||
|
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in6 &p) noexcept
|
||||||
|
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||||
|
|
||||||
|
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr &p) noexcept
|
||||||
|
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||||
|
|
||||||
|
static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept
|
||||||
|
{ return *reinterpret_cast<const InetAddress *>(&p); }
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
bool Locator::sign(const int64_t ts,const Identity &id) noexcept
|
bool Locator::sign(const int64_t ts, const Identity &id) noexcept
|
||||||
{
|
{
|
||||||
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||||
if (!id.hasPrivate())
|
if (!id.hasPrivate())
|
||||||
|
@ -23,7 +23,7 @@ bool Locator::sign(const int64_t ts,const Identity &id) noexcept
|
||||||
m_ts = ts;
|
m_ts = ts;
|
||||||
if (m_endpointCount > 0)
|
if (m_endpointCount > 0)
|
||||||
std::sort(m_at, m_at + m_endpointCount);
|
std::sort(m_at, m_at + m_endpointCount);
|
||||||
const unsigned int signLen = marshal(signData,true);
|
const unsigned int signLen = marshal(signData, true);
|
||||||
m_signatureLength = id.sign(signData, signLen, m_signature, sizeof(m_signature));
|
m_signatureLength = id.sign(signData, signLen, m_signature, sizeof(m_signature));
|
||||||
return (m_signatureLength > 0);
|
return (m_signatureLength > 0);
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,11 @@ bool Locator::verify(const Identity &id) const noexcept
|
||||||
if ((m_ts == 0) || (m_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS) || (m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
if ((m_ts == 0) || (m_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS) || (m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||||
return false;
|
return false;
|
||||||
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX];
|
||||||
const unsigned int signLen = marshal(signData,true);
|
const unsigned int signLen = marshal(signData, true);
|
||||||
return id.verify(signData, signLen, m_signature, m_signatureLength);
|
return id.verify(signData, signLen, m_signature, m_signatureLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature) const noexcept
|
int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool excludeSignature) const noexcept
|
||||||
{
|
{
|
||||||
if ((m_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS) || (m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
if ((m_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS) || (m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -47,7 +47,7 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool exclud
|
||||||
int p = 9;
|
int p = 9;
|
||||||
|
|
||||||
if (m_ts > 0) {
|
if (m_ts > 0) {
|
||||||
Utils::storeBigEndian(data + p,(uint16_t)m_endpointCount);
|
Utils::storeBigEndian(data + p, (uint16_t) m_endpointCount);
|
||||||
p += 2;
|
p += 2;
|
||||||
for (unsigned int i = 0;i < m_endpointCount;++i) {
|
for (unsigned int i = 0;i < m_endpointCount;++i) {
|
||||||
int tmp = m_at[i].marshal(data + p);
|
int tmp = m_at[i].marshal(data + p);
|
||||||
|
@ -57,10 +57,10 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool exclud
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!excludeSignature) {
|
if (!excludeSignature) {
|
||||||
Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength);
|
Utils::storeBigEndian(data + p, (uint16_t) m_signatureLength);
|
||||||
p += 2;
|
p += 2;
|
||||||
Utils::copy(data + p, m_signature, m_signatureLength);
|
Utils::copy(data + p, m_signature, m_signatureLength);
|
||||||
p += (int)m_signatureLength;
|
p += (int) m_signatureLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::storeBigEndian(data + p, m_flags);
|
Utils::storeBigEndian(data + p, m_flags);
|
||||||
|
@ -70,7 +70,7 @@ int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool exclud
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Locator::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
int Locator::unmarshal(const uint8_t *restrict data, const int len) noexcept
|
||||||
{
|
{
|
||||||
if (len <= (1 + 8 + 2 + 48))
|
if (len <= (1 + 8 + 2 + 48))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -86,7 +86,7 @@ int Locator::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
||||||
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
|
if (ec > ZT_LOCATOR_MAX_ENDPOINTS)
|
||||||
return -1;
|
return -1;
|
||||||
m_endpointCount = ec;
|
m_endpointCount = ec;
|
||||||
for (unsigned int i = 0; i < ec; ++i) {
|
for (unsigned int i = 0;i < ec;++i) {
|
||||||
int tmp = m_at[i].unmarshal(data + p, len - p);
|
int tmp = m_at[i].unmarshal(data + p, len - p);
|
||||||
if (tmp < 0)
|
if (tmp < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -100,10 +100,10 @@ int Locator::unmarshal(const uint8_t *restrict data,const int len) noexcept
|
||||||
if (sl > ZT_SIGNATURE_BUFFER_SIZE)
|
if (sl > ZT_SIGNATURE_BUFFER_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
m_signatureLength = sl;
|
m_signatureLength = sl;
|
||||||
if ((p + (int)sl) > len)
|
if ((p + (int) sl) > len)
|
||||||
return -1;
|
return -1;
|
||||||
Utils::copy(m_signature, data + p, sl);
|
Utils::copy(m_signature, data + p, sl);
|
||||||
p += (int)sl;
|
p += (int) sl;
|
||||||
|
|
||||||
if ((p + 2) > len)
|
if ((p + 2) > len)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @return True if locator is signed
|
* @return True if locator is signed
|
||||||
*/
|
*/
|
||||||
ZT_INLINE bool isSigned() const noexcept { return (m_signatureLength > 0); }
|
ZT_INLINE bool isSigned() const noexcept { return m_signatureLength > 0; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Length of signature in bytes or 0 if none
|
* @return Length of signature in bytes or 0 if none
|
||||||
|
@ -110,7 +110,7 @@ public:
|
||||||
*/
|
*/
|
||||||
bool verify(const Identity &id) const noexcept;
|
bool verify(const Identity &id) const noexcept;
|
||||||
|
|
||||||
explicit ZT_INLINE operator bool() const noexcept { return (m_ts != 0); }
|
explicit ZT_INLINE operator bool() const noexcept { return m_ts != 0; }
|
||||||
|
|
||||||
static constexpr int marshalSizeMax() noexcept { return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
static constexpr int marshalSizeMax() noexcept { return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
|
||||||
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],bool excludeSignature = false) const noexcept;
|
int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],bool excludeSignature = false) const noexcept;
|
||||||
|
|
|
@ -33,6 +33,7 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
|
||||||
if (!nconf.com) // sanity check
|
if (!nconf.com) // sanity check
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if 0
|
||||||
SharedPtr<Buf> outp(new Buf());
|
SharedPtr<Buf> outp(new Buf());
|
||||||
Protocol::Header &ph = outp->as<Protocol::Header>(); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
Protocol::Header &ph = outp->as<Protocol::Header>(); // NOLINT(hicpp-use-auto,modernize-use-auto)
|
||||||
|
|
||||||
|
@ -109,6 +110,7 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_lastPushedCredentials = now;
|
m_lastPushedCredentials = now;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf,const T &r) const noexcept
|
ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf,const T &r) const noexcept
|
||||||
{
|
{
|
||||||
if (s_isUnspoofableAddress(nconf, r))
|
if (m_isUnspoofableAddress(nconf, r))
|
||||||
return true;
|
return true;
|
||||||
for(Map< uint32_t,CertificateOfOwnership >::const_iterator i(m_remoteCoos.begin());i != m_remoteCoos.end();++i) {
|
for(Map< uint32_t,CertificateOfOwnership >::const_iterator i(m_remoteCoos.begin());i != m_remoteCoos.end();++i) {
|
||||||
if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r)))
|
if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r)))
|
||||||
|
@ -158,7 +158,7 @@ private:
|
||||||
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
|
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
|
||||||
// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
|
// address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to
|
||||||
// always return true for them. A certificate is not required for these.
|
// always return true for them. A certificate is not required for these.
|
||||||
ZT_INLINE static bool s_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) noexcept { return false; }
|
constexpr bool m_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) const noexcept { return false; }
|
||||||
bool m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept;
|
bool m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept;
|
||||||
|
|
||||||
// This compares the remote credential's timestamp to the timestamp in our network config
|
// This compares the remote credential's timestamp to the timestamp in our network config
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace ZeroTier {
|
||||||
* @tparam TUNIT Unit of time in milliseconds (default: 1000 for one second)
|
* @tparam TUNIT Unit of time in milliseconds (default: 1000 for one second)
|
||||||
* @tparam LSIZE Log size in units of time (default: 10 for 10s worth of data)
|
* @tparam LSIZE Log size in units of time (default: 10 for 10s worth of data)
|
||||||
*/
|
*/
|
||||||
template<int64_t TUNIT = 1000,unsigned long LSIZE = 10>
|
template<int64_t TUNIT = 1000, unsigned long LSIZE = 10>
|
||||||
class Meter
|
class Meter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -43,7 +43,8 @@ public:
|
||||||
*
|
*
|
||||||
* @param now Start time
|
* @param now Start time
|
||||||
*/
|
*/
|
||||||
ZT_INLINE Meter() noexcept {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,hicpp-use-equals-default,modernize-use-equals-default)
|
ZT_INLINE Meter() noexcept
|
||||||
|
{} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,hicpp-use-equals-default,modernize-use-equals-default)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a measurement
|
* Add a measurement
|
||||||
|
@ -51,7 +52,7 @@ public:
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
* @param count Count of items (usually bytes)
|
* @param count Count of items (usually bytes)
|
||||||
*/
|
*/
|
||||||
ZT_INLINE void log(const int64_t now,uint64_t count) noexcept
|
ZT_INLINE void log(const int64_t now, uint64_t count) noexcept
|
||||||
{
|
{
|
||||||
// We log by choosing a log bucket based on the current time in units modulo
|
// We log by choosing a log bucket based on the current time in units modulo
|
||||||
// the log size and then if it's a new bucket setting it or otherwise adding
|
// the log size and then if it's a new bucket setting it or otherwise adding
|
||||||
|
@ -71,12 +72,12 @@ public:
|
||||||
* @param rate Result parameter: rate in count/TUNIT
|
* @param rate Result parameter: rate in count/TUNIT
|
||||||
* @param total Total count for life of object
|
* @param total Total count for life of object
|
||||||
*/
|
*/
|
||||||
ZT_INLINE void rate(double &rate,uint64_t &total) const noexcept
|
ZT_INLINE void rate(double &rate, uint64_t &total) const noexcept
|
||||||
{
|
{
|
||||||
total = 0;
|
total = 0;
|
||||||
for(unsigned long i=0;i<LSIZE;++i)
|
for (unsigned long i = 0;i < LSIZE;++i)
|
||||||
total += m_counts[i].load();
|
total += m_counts[i].load();
|
||||||
rate = (double)total / (double)LSIZE;
|
rate = (double) total / (double) LSIZE;
|
||||||
total += m_totalExclCounts.load();
|
total += m_totalExclCounts.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -539,8 +539,8 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const F
|
||||||
m_id(nwid),
|
m_id(nwid),
|
||||||
m_mac(renv->identity.address(), nwid),
|
m_mac(renv->identity.address(), nwid),
|
||||||
m_portInitialized(false),
|
m_portInitialized(false),
|
||||||
m_lastConfigUpdate(0),
|
|
||||||
m_destroyed(false),
|
m_destroyed(false),
|
||||||
|
m_lastConfigUpdate(0),
|
||||||
_netconfFailure(NETCONF_FAILURE_NONE)
|
_netconfFailure(NETCONF_FAILURE_NONE)
|
||||||
{
|
{
|
||||||
if (controllerFingerprint)
|
if (controllerFingerprint)
|
||||||
|
@ -556,7 +556,7 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,const F
|
||||||
bool got = false;
|
bool got = false;
|
||||||
try {
|
try {
|
||||||
Dictionary dict;
|
Dictionary dict;
|
||||||
std::vector<uint8_t> nconfData(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp));
|
Vector<uint8_t> nconfData(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp));
|
||||||
if (nconfData.size() > 2) {
|
if (nconfData.size() > 2) {
|
||||||
nconfData.push_back(0);
|
nconfData.push_back(0);
|
||||||
if (dict.decode(nconfData.data(),(unsigned int)nconfData.size())) {
|
if (dict.decode(nconfData.data(),(unsigned int)nconfData.size())) {
|
||||||
|
@ -864,7 +864,7 @@ void Network::multicastSubscribe(void *tPtr,const MulticastGroup &mg)
|
||||||
void Network::multicastUnsubscribe(const MulticastGroup &mg)
|
void Network::multicastUnsubscribe(const MulticastGroup &mg)
|
||||||
{
|
{
|
||||||
Mutex::Lock l(m_myMulticastGroups_l);
|
Mutex::Lock l(m_myMulticastGroups_l);
|
||||||
std::vector<MulticastGroup>::iterator i(std::lower_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg));
|
Vector<MulticastGroup>::iterator i(std::lower_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg));
|
||||||
if ((i != m_myMulticastGroups.end()) && (*i == mg) )
|
if ((i != m_myMulticastGroups.end()) && (*i == mg) )
|
||||||
m_myMulticastGroups.erase(i);
|
m_myMulticastGroups.erase(i);
|
||||||
}
|
}
|
||||||
|
@ -984,7 +984,7 @@ uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr
|
||||||
c->chunks[chunkIndex].assign(chunkData,chunkData + chunkLen);
|
c->chunks[chunkIndex].assign(chunkData,chunkData + chunkLen);
|
||||||
|
|
||||||
int haveLength = 0;
|
int haveLength = 0;
|
||||||
for(std::map< int,std::vector<uint8_t> >::const_iterator ch(c->chunks.begin());ch!=c->chunks.end();++ch)
|
for(std::map< int,Vector<uint8_t> >::const_iterator ch(c->chunks.begin());ch!=c->chunks.end();++ch)
|
||||||
haveLength += (int)ch->second.size();
|
haveLength += (int)ch->second.size();
|
||||||
if (haveLength > ZT_MAX_NETWORK_CONFIG_BYTES) {
|
if (haveLength > ZT_MAX_NETWORK_CONFIG_BYTES) {
|
||||||
c->touchCtr = 0;
|
c->touchCtr = 0;
|
||||||
|
@ -994,8 +994,8 @@ uint64_t Network::handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr
|
||||||
}
|
}
|
||||||
|
|
||||||
if (haveLength == totalLength) {
|
if (haveLength == totalLength) {
|
||||||
std::vector<uint8_t> assembledConfig;
|
Vector<uint8_t> assembledConfig;
|
||||||
for(std::map< int,std::vector<uint8_t> >::const_iterator ch(c->chunks.begin());ch!=c->chunks.end();++ch)
|
for(std::map< int,Vector<uint8_t> >::const_iterator ch(c->chunks.begin());ch!=c->chunks.end();++ch)
|
||||||
assembledConfig.insert(assembledConfig.end(),ch->second.begin(),ch->second.end());
|
assembledConfig.insert(assembledConfig.end(),ch->second.begin(),ch->second.end());
|
||||||
|
|
||||||
Dictionary dict;
|
Dictionary dict;
|
||||||
|
@ -1048,10 +1048,10 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
|
||||||
if (saveToDisk) {
|
if (saveToDisk) {
|
||||||
try {
|
try {
|
||||||
Dictionary d;
|
Dictionary d;
|
||||||
if (nconf.toDictionary(d,false)) {
|
if (nconf.toDictionary(d)) {
|
||||||
uint64_t tmp[2];
|
uint64_t tmp[2];
|
||||||
tmp[0] = m_id; tmp[1] = 0;
|
tmp[0] = m_id; tmp[1] = 0;
|
||||||
std::vector<uint8_t> d2;
|
Vector<uint8_t> d2;
|
||||||
d.encode(d2);
|
d.encode(d2);
|
||||||
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,d2.data(),(unsigned int)d2.size());
|
RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,d2.data(),(unsigned int)d2.size());
|
||||||
}
|
}
|
||||||
|
@ -1445,7 +1445,7 @@ void Network::m_externalConfig(ZT_VirtualNetworkConfig *ec) const
|
||||||
ec->status = m_status();
|
ec->status = m_status();
|
||||||
ec->type = (m_config) ? (m_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE;
|
ec->type = (m_config) ? (m_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE;
|
||||||
ec->mtu = (m_config) ? m_config.mtu : ZT_DEFAULT_MTU;
|
ec->mtu = (m_config) ? m_config.mtu : ZT_DEFAULT_MTU;
|
||||||
std::vector<Address> ab;
|
Vector<Address> ab;
|
||||||
for(unsigned int i=0;i < m_config.specialistCount;++i) {
|
for(unsigned int i=0;i < m_config.specialistCount;++i) {
|
||||||
if ((m_config.specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)
|
if ((m_config.specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0)
|
||||||
ab.push_back(Address(m_config.specialists[i]));
|
ab.push_back(Address(m_config.specialists[i]));
|
||||||
|
@ -1503,7 +1503,7 @@ void Network::m_announceMulticastGroupsTo(void *tPtr, const Address &peer, const
|
||||||
// Assumes _myMulticastGroups_l and _memberships_l are locked
|
// Assumes _myMulticastGroups_l and _memberships_l are locked
|
||||||
ScopedPtr<Packet> outp(new Packet(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE));
|
ScopedPtr<Packet> outp(new Packet(peer,RR->identity.address(),Packet::VERB_MULTICAST_LIKE));
|
||||||
|
|
||||||
for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
|
for(Vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) {
|
||||||
if ((outp->size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) {
|
if ((outp->size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) {
|
||||||
outp->compress();
|
outp->compress();
|
||||||
RR->sw->send(tPtr,*outp,true);
|
RR->sw->send(tPtr,*outp,true);
|
||||||
|
@ -1529,7 +1529,7 @@ Vector<MulticastGroup> Network::m_allMulticastGroups() const
|
||||||
Vector<MulticastGroup> mgs;
|
Vector<MulticastGroup> mgs;
|
||||||
mgs.reserve(m_myMulticastGroups.size() + m_multicastGroupsBehindMe.size() + 1);
|
mgs.reserve(m_myMulticastGroups.size() + m_multicastGroupsBehindMe.size() + 1);
|
||||||
mgs.insert(mgs.end(), m_myMulticastGroups.begin(), m_myMulticastGroups.end());
|
mgs.insert(mgs.end(), m_myMulticastGroups.begin(), m_myMulticastGroups.end());
|
||||||
for(Map<MulticastGroup,uint64_t>::const_iterator i(m_multicastGroupsBehindMe.begin());i != m_multicastGroupsBehindMe.end();++i)
|
for(Map<MulticastGroup,int64_t>::const_iterator i(m_multicastGroupsBehindMe.begin());i != m_multicastGroupsBehindMe.end();++i)
|
||||||
mgs.push_back(i->first);
|
mgs.push_back(i->first);
|
||||||
if ((m_config) && (m_config.enableBroadcast()))
|
if ((m_config) && (m_config.enableBroadcast()))
|
||||||
mgs.push_back(Network::BROADCAST);
|
mgs.push_back(Network::BROADCAST);
|
||||||
|
|
|
@ -31,13 +31,7 @@ namespace ZeroTier {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
// Structure containing all the core objects for a ZeroTier node to reduce memory allocations.
|
||||||
* All core objects of a ZeroTier node.
|
|
||||||
*
|
|
||||||
* This is just a box that allows us to allocate all core objects
|
|
||||||
* and data structures at once for a bit of memory saves and improved
|
|
||||||
* cache adjacency.
|
|
||||||
*/
|
|
||||||
struct _NodeObjects
|
struct _NodeObjects
|
||||||
{
|
{
|
||||||
ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR,void *const tPtr) :
|
ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR,void *const tPtr) :
|
||||||
|
@ -195,7 +189,7 @@ struct _processBackgroundTasks_eachPeer
|
||||||
Node *const parent;
|
Node *const parent;
|
||||||
void *const tPtr;
|
void *const tPtr;
|
||||||
bool online;
|
bool online;
|
||||||
std::vector< SharedPtr<Peer> > rootsNotOnline;
|
Vector< SharedPtr<Peer> > rootsNotOnline;
|
||||||
ZT_INLINE void operator()(const SharedPtr<Peer> &peer,const bool isRoot) noexcept
|
ZT_INLINE void operator()(const SharedPtr<Peer> &peer,const bool isRoot) noexcept
|
||||||
{
|
{
|
||||||
peer->pulse(tPtr,now,isRoot);
|
peer->pulse(tPtr,now,isRoot);
|
||||||
|
@ -226,7 +220,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr,int64_t now,volatile int64
|
||||||
postEvent(tPtr, m_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
postEvent(tPtr, m_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
RR->topology->rankRoots(now);
|
RR->topology->rankRoots();
|
||||||
|
|
||||||
if (pf.online) {
|
if (pf.online) {
|
||||||
// If we have at least one online root, request whois for roots not online.
|
// If we have at least one online root, request whois for roots not online.
|
||||||
|
@ -234,7 +228,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr,int64_t now,volatile int64
|
||||||
// IP addresses. It will also auto-discover IPs for roots that were not added
|
// IP addresses. It will also auto-discover IPs for roots that were not added
|
||||||
// with an initial bootstrap address.
|
// with an initial bootstrap address.
|
||||||
// TODO
|
// TODO
|
||||||
//for (std::vector<Address>::const_iterator r(pf.rootsNotOnline.begin()); r != pf.rootsNotOnline.end(); ++r)
|
//for (Vector<Address>::const_iterator r(pf.rootsNotOnline.begin()); r != pf.rootsNotOnline.end(); ++r)
|
||||||
// RR->sw->requestWhois(tPtr,now,*r);
|
// RR->sw->requestWhois(tPtr,now,*r);
|
||||||
}
|
}
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
|
@ -360,7 +354,7 @@ ZT_ResultCode Node::removeRoot(void *tPtr,const ZT_Identity *identity)
|
||||||
{
|
{
|
||||||
if (!identity)
|
if (!identity)
|
||||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||||
RR->topology->removeRoot(*reinterpret_cast<const Identity *>(identity));
|
RR->topology->removeRoot(tPtr, *reinterpret_cast<const Identity *>(identity));
|
||||||
return ZT_RESULT_OK;
|
return ZT_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +374,7 @@ void Node::status(ZT_NodeStatus *status) const
|
||||||
|
|
||||||
ZT_PeerList *Node::peers() const
|
ZT_PeerList *Node::peers() const
|
||||||
{
|
{
|
||||||
std::vector< SharedPtr<Peer> > peers;
|
Vector< SharedPtr<Peer> > peers;
|
||||||
RR->topology->getAllPeers(peers);
|
RR->topology->getAllPeers(peers);
|
||||||
std::sort(peers.begin(),peers.end(),_sortPeerPtrsByAddress());
|
std::sort(peers.begin(),peers.end(),_sortPeerPtrsByAddress());
|
||||||
|
|
||||||
|
@ -393,7 +387,7 @@ ZT_PeerList *Node::peers() const
|
||||||
|
|
||||||
const int64_t now = m_now;
|
const int64_t now = m_now;
|
||||||
pl->peerCount = 0;
|
pl->peerCount = 0;
|
||||||
for(std::vector< SharedPtr<Peer> >::iterator pi(peers.begin());pi!=peers.end();++pi) { // NOLINT(modernize-use-auto,modernize-loop-convert,hicpp-use-auto)
|
for(Vector< SharedPtr<Peer> >::iterator pi(peers.begin());pi!=peers.end();++pi) { // NOLINT(modernize-use-auto,modernize-loop-convert,hicpp-use-auto)
|
||||||
ZT_Peer *const p = &(pl->peers[pl->peerCount]);
|
ZT_Peer *const p = &(pl->peers[pl->peerCount]);
|
||||||
|
|
||||||
p->address = (*pi)->address().toInt();
|
p->address = (*pi)->address().toInt();
|
||||||
|
@ -420,14 +414,15 @@ ZT_PeerList *Node::peers() const
|
||||||
Utils::copy<sizeof(sockaddr_storage)>(&(p->bootstrap[p->bootstrapAddressCount++]),&(*i));
|
Utils::copy<sizeof(sockaddr_storage)>(&(p->bootstrap[p->bootstrapAddressCount++]),&(*i));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector< SharedPtr<Path> > paths;
|
Vector< SharedPtr<Path> > paths;
|
||||||
(*pi)->getAllPaths(paths);
|
(*pi)->getAllPaths(paths);
|
||||||
p->pathCount = 0;
|
p->pathCount = 0;
|
||||||
for(std::vector< SharedPtr<Path> >::iterator path(paths.begin());path!=paths.end();++path) { // NOLINT(modernize-use-auto,modernize-loop-convert,hicpp-use-auto)
|
for(Vector< SharedPtr<Path> >::iterator path(paths.begin());path!=paths.end();++path) { // NOLINT(modernize-use-auto,modernize-loop-convert,hicpp-use-auto)
|
||||||
Utils::copy<sizeof(sockaddr_storage)>(&(p->paths[p->pathCount].address),&((*path)->address()));
|
Utils::copy<sizeof(sockaddr_storage)>(&(p->paths[p->pathCount].address),&((*path)->address()));
|
||||||
p->paths[p->pathCount].lastSend = (*path)->lastOut();
|
p->paths[p->pathCount].lastSend = (*path)->lastOut();
|
||||||
p->paths[p->pathCount].lastReceive = (*path)->lastIn();
|
p->paths[p->pathCount].lastReceive = (*path)->lastIn();
|
||||||
p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address());
|
// TODO
|
||||||
|
//p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address());
|
||||||
p->paths[p->pathCount].alive = (*path)->alive(now) ? 1 : 0;
|
p->paths[p->pathCount].alive = (*path)->alive(now) ? 1 : 0;
|
||||||
p->paths[p->pathCount].preferred = (p->pathCount == 0) ? 1 : 0;
|
p->paths[p->pathCount].preferred = (p->pathCount == 0) ? 1 : 0;
|
||||||
++p->pathCount;
|
++p->pathCount;
|
||||||
|
@ -613,15 +608,17 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
|
||||||
|
|
||||||
if (destination == RR->identity.address()) {
|
if (destination == RR->identity.address()) {
|
||||||
SharedPtr<Network> n(network(nwid));
|
SharedPtr<Network> n(network(nwid));
|
||||||
if (!n) return;
|
if (!n)
|
||||||
|
return;
|
||||||
n->setConfiguration((void *)0,nc,true);
|
n->setConfiguration((void *)0,nc,true);
|
||||||
} else {
|
} else {
|
||||||
Dictionary dconf;
|
Dictionary dconf;
|
||||||
if (nc.toDictionary(dconf,sendLegacyFormatConfig)) {
|
if (nc.toDictionary(dconf)) {
|
||||||
uint64_t configUpdateId = Utils::random();
|
uint64_t configUpdateId = Utils::random();
|
||||||
if (!configUpdateId) ++configUpdateId;
|
if (!configUpdateId)
|
||||||
|
++configUpdateId;
|
||||||
|
|
||||||
std::vector<uint8_t> ddata;
|
Vector<uint8_t> ddata;
|
||||||
dconf.encode(ddata);
|
dconf.encode(ddata);
|
||||||
// TODO
|
// TODO
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -164,11 +164,10 @@ void Peer::send(void *tPtr,int64_t now,const void *data,unsigned int len) noexce
|
||||||
sent(now,len);
|
sent(now,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Peer::hello(void *tPtr,int64_t localSocket,const InetAddress &atAddress,int64_t now)
|
unsigned int Peer::hello(void *tPtr,int64_t localSocket,const InetAddress &atAddress,const int64_t now)
|
||||||
{
|
{
|
||||||
Buf outp;
|
Buf outp;
|
||||||
|
|
||||||
const int64_t now = RR->node->now();
|
|
||||||
const uint64_t packetId = m_identityKey->nextMessage(RR->identity.address(),m_id.address());
|
const uint64_t packetId = m_identityKey->nextMessage(RR->identity.address(),m_id.address());
|
||||||
int ii = Protocol::newPacket(outp,packetId,m_id.address(),RR->identity.address(),Protocol::VERB_HELLO);
|
int ii = Protocol::newPacket(outp,packetId,m_id.address(),RR->identity.address(),Protocol::VERB_HELLO);
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,13 @@ public:
|
||||||
void update(const void *data,unsigned int len) noexcept;
|
void update(const void *data,unsigned int len) noexcept;
|
||||||
void finish(void *auth) noexcept;
|
void finish(void *auth) noexcept;
|
||||||
|
|
||||||
|
static ZT_INLINE void compute(void *const auth, const void *const data, const unsigned int len, const void *const key) noexcept
|
||||||
|
{
|
||||||
|
Poly1305 p(key);
|
||||||
|
p.update(data,len);
|
||||||
|
p.finish(auth);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct {
|
struct {
|
||||||
size_t aligner;
|
size_t aligner;
|
||||||
|
|
|
@ -27,13 +27,15 @@ namespace ZeroTier {
|
||||||
class _ResetWithinScope
|
class _ResetWithinScope
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ZT_INLINE _ResetWithinScope(void *tPtr,int64_t now,int inetAddressFamily,InetAddress::IpScope scope) :
|
ZT_INLINE _ResetWithinScope(void *tPtr, int64_t now, int inetAddressFamily, InetAddress::IpScope scope) :
|
||||||
_now(now),
|
_now(now),
|
||||||
_tPtr(tPtr),
|
_tPtr(tPtr),
|
||||||
_family(inetAddressFamily),
|
_family(inetAddressFamily),
|
||||||
_scope(scope) {}
|
_scope(scope)
|
||||||
|
{}
|
||||||
|
|
||||||
ZT_INLINE void operator()(const SharedPtr<Peer> &p) { p->resetWithinScope(_tPtr,_scope,_family,_now); }
|
ZT_INLINE void operator()(const SharedPtr<Peer> &p)
|
||||||
|
{ p->resetWithinScope(_tPtr, _scope, _family, _now); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t _now;
|
int64_t _now;
|
||||||
|
@ -47,17 +49,17 @@ SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now)
|
void SelfAwareness::iam(void *tPtr, const Identity &reporter, const int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted, int64_t now)
|
||||||
{
|
{
|
||||||
const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
|
const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
|
||||||
|
|
||||||
if ((scope != reporterPhysicalAddress.ipScope())||(scope == InetAddress::IP_SCOPE_NONE)||(scope == InetAddress::IP_SCOPE_LOOPBACK)||(scope == InetAddress::IP_SCOPE_MULTICAST))
|
if ((scope != reporterPhysicalAddress.ipScope()) || (scope == InetAddress::IP_SCOPE_NONE) || (scope == InetAddress::IP_SCOPE_LOOPBACK) || (scope == InetAddress::IP_SCOPE_MULTICAST))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Mutex::Lock l(m_phy_l);
|
Mutex::Lock l(m_phy_l);
|
||||||
p_PhySurfaceEntry &entry = m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)];
|
p_PhySurfaceEntry &entry = m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)];
|
||||||
|
|
||||||
if ( (trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress)) ) {
|
if ((trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress))) {
|
||||||
// Changes to external surface reported by trusted peers causes path reset in this scope
|
// Changes to external surface reported by trusted peers causes path reset in this scope
|
||||||
entry.mySurface = myPhysicalAddress;
|
entry.mySurface = myPhysicalAddress;
|
||||||
entry.ts = now;
|
entry.ts = now;
|
||||||
|
@ -66,17 +68,17 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv
|
||||||
// Erase all entries in this scope that were not reported from this remote address to prevent 'thrashing'
|
// Erase all entries in this scope that were not reported from this remote address to prevent 'thrashing'
|
||||||
// due to multiple reports of endpoint change.
|
// due to multiple reports of endpoint change.
|
||||||
// Don't use 'entry' after this since hash table gets modified.
|
// Don't use 'entry' after this since hash table gets modified.
|
||||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::iterator i(m_phy.begin());i != m_phy.end();) {
|
for (Map<p_PhySurfaceKey, p_PhySurfaceEntry>::iterator i(m_phy.begin());i != m_phy.end();) {
|
||||||
if ((i->first.scope == scope)&&(i->first.reporterPhysicalAddress != reporterPhysicalAddress))
|
if ((i->first.scope == scope) && (i->first.reporterPhysicalAddress != reporterPhysicalAddress))
|
||||||
m_phy.erase(i++);
|
m_phy.erase(i++);
|
||||||
else ++i;
|
else ++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset all paths within this scope and address family
|
// Reset all paths within this scope and address family
|
||||||
_ResetWithinScope rset(tPtr,now,myPhysicalAddress.family(),(InetAddress::IpScope)scope);
|
_ResetWithinScope rset(tPtr, now, myPhysicalAddress.family(), (InetAddress::IpScope) scope);
|
||||||
RR->topology->eachPeer<_ResetWithinScope &>(rset);
|
RR->topology->eachPeer<_ResetWithinScope &>(rset);
|
||||||
|
|
||||||
RR->t->resettingPathsInScope(tPtr,0x9afff100,reporter,reporterPhysicalAddress,entry.mySurface,myPhysicalAddress,scope);
|
RR->t->resettingPathsInScope(tPtr, 0x9afff100, reporter, reporterPhysicalAddress, entry.mySurface, myPhysicalAddress, scope);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise just update DB to use to determine external surface info
|
// Otherwise just update DB to use to determine external surface info
|
||||||
entry.mySurface = myPhysicalAddress;
|
entry.mySurface = myPhysicalAddress;
|
||||||
|
@ -88,30 +90,30 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv
|
||||||
void SelfAwareness::clean(int64_t now)
|
void SelfAwareness::clean(int64_t now)
|
||||||
{
|
{
|
||||||
Mutex::Lock l(m_phy_l);
|
Mutex::Lock l(m_phy_l);
|
||||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::iterator i(m_phy.begin());i != m_phy.end();) {
|
for (Map<p_PhySurfaceKey, p_PhySurfaceEntry>::iterator i(m_phy.begin());i != m_phy.end();) {
|
||||||
if ((now - i->second.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
if ((now - i->second.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||||
m_phy.erase(i++);
|
m_phy.erase(i++);
|
||||||
else ++i;
|
else ++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiMap<unsigned int,InetAddress> SelfAwareness::externalAddresses(const int64_t now) const
|
MultiMap<unsigned int, InetAddress> SelfAwareness::externalAddresses(const int64_t now) const
|
||||||
{
|
{
|
||||||
MultiMap<unsigned int,InetAddress> r;
|
MultiMap<unsigned int, InetAddress> r;
|
||||||
|
|
||||||
// Count endpoints reporting each IP/port combo
|
// Count endpoints reporting each IP/port combo
|
||||||
Map<InetAddress,unsigned long> counts;
|
Map<InetAddress, unsigned long> counts;
|
||||||
{
|
{
|
||||||
Mutex::Lock l(m_phy_l);
|
Mutex::Lock l(m_phy_l);
|
||||||
for(Map<p_PhySurfaceKey,p_PhySurfaceEntry>::const_iterator i(m_phy.begin());i != m_phy.end();++i) {
|
for (Map<p_PhySurfaceKey, p_PhySurfaceEntry>::const_iterator i(m_phy.begin());i != m_phy.end();++i) {
|
||||||
if ((now - i->second.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
if ((now - i->second.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||||
++counts[i->second.mySurface];
|
++counts[i->second.mySurface];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invert to create a map from count to address
|
// Invert to create a map from count to address
|
||||||
for(Map<InetAddress,unsigned long>::iterator i(counts.begin());i!=counts.end();++i)
|
for (Map<InetAddress, unsigned long>::iterator i(counts.begin());i != counts.end();++i)
|
||||||
r.insert(std::pair<unsigned long,InetAddress>(i->second,i->first));
|
r.insert(std::pair<unsigned long, InetAddress>(i->second, i->first));
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,8 @@ public:
|
||||||
ZT_INLINE bool weakGC()
|
ZT_INLINE bool weakGC()
|
||||||
{
|
{
|
||||||
if (m_ptr) {
|
if (m_ptr) {
|
||||||
if (m_ptr->__refCount.compare_exchange_strong(1,0)) {
|
int one = 1;
|
||||||
|
if (m_ptr->__refCount.compare_exchange_strong(one,(int)0)) {
|
||||||
delete m_ptr;
|
delete m_ptr;
|
||||||
m_ptr = nullptr;
|
m_ptr = nullptr;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -413,7 +413,7 @@ extern "C" const char *ZTT_general()
|
||||||
return "FCV object life cycle test failed (2)";
|
return "FCV object life cycle test failed (2)";
|
||||||
}
|
}
|
||||||
test.clear();
|
test.clear();
|
||||||
if (cnt != (long)test.size()) {
|
if (cnt != (long)test2.size()) {
|
||||||
ZT_T_PRINTF("FAILED (expected 512 objects, got %lu (3))" ZT_EOL_S,cnt);
|
ZT_T_PRINTF("FAILED (expected 512 objects, got %lu (3))" ZT_EOL_S,cnt);
|
||||||
return "FCV object life cycle test failed (3)";
|
return "FCV object life cycle test failed (3)";
|
||||||
}
|
}
|
||||||
|
@ -515,7 +515,7 @@ extern "C" const char *ZTT_general()
|
||||||
FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS> message;
|
FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS> message;
|
||||||
FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS> ref;
|
FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS> ref;
|
||||||
|
|
||||||
int frags = 1 + (int)(Utils::random() % 16);
|
int frags = 1 + (int)(Utils::random() % ZT_MAX_PACKET_FRAGMENTS);
|
||||||
int skip = ((k & 3) == 1) ? -1 : (int)(Utils::random() % frags);
|
int skip = ((k & 3) == 1) ? -1 : (int)(Utils::random() % frags);
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
message.resize(frags);
|
message.resize(frags);
|
||||||
|
@ -803,12 +803,12 @@ extern "C" const char *ZTT_crypto()
|
||||||
{
|
{
|
||||||
uint8_t tag[16];
|
uint8_t tag[16];
|
||||||
ZT_T_PRINTF("[crypto] Testing Poly1305... ");
|
ZT_T_PRINTF("[crypto] Testing Poly1305... ");
|
||||||
poly1305(tag,POLY1305_TV0_INPUT,sizeof(POLY1305_TV0_INPUT),POLY1305_TV0_KEY);
|
Poly1305::compute(tag,POLY1305_TV0_INPUT,sizeof(POLY1305_TV0_INPUT),POLY1305_TV0_KEY);
|
||||||
if (memcmp(tag,POLY1305_TV0_TAG,16) != 0) {
|
if (memcmp(tag,POLY1305_TV0_TAG,16) != 0) {
|
||||||
ZT_T_PRINTF("FAILED (test vector 0)" ZT_EOL_S);
|
ZT_T_PRINTF("FAILED (test vector 0)" ZT_EOL_S);
|
||||||
return "poly1305 test vector 0 failed";
|
return "poly1305 test vector 0 failed";
|
||||||
}
|
}
|
||||||
poly1305(tag,POLY1305_TV1_INPUT,sizeof(POLY1305_TV1_INPUT),POLY1305_TV1_KEY);
|
Poly1305::compute(tag,POLY1305_TV1_INPUT,sizeof(POLY1305_TV1_INPUT),POLY1305_TV1_KEY);
|
||||||
if (memcmp(tag,POLY1305_TV1_TAG,16) != 0) {
|
if (memcmp(tag,POLY1305_TV1_TAG,16) != 0) {
|
||||||
ZT_T_PRINTF("FAILED (test vector 1)" ZT_EOL_S);
|
ZT_T_PRINTF("FAILED (test vector 1)" ZT_EOL_S);
|
||||||
return "poly1305 test vector 1 failed";
|
return "poly1305 test vector 1 failed";
|
||||||
|
@ -1014,7 +1014,7 @@ extern "C" const char *ZTT_benchmarkCrypto()
|
||||||
ZT_T_PRINTF("[crypto] Benchmarking Poly1305... ");
|
ZT_T_PRINTF("[crypto] Benchmarking Poly1305... ");
|
||||||
int64_t start = now();
|
int64_t start = now();
|
||||||
for(long i=0;i<150000;++i)
|
for(long i=0;i<150000;++i)
|
||||||
poly1305(tag,tmp,sizeof(tmp),tag);
|
Poly1305::compute(tag,tmp,sizeof(tmp),tag);
|
||||||
int64_t end = now();
|
int64_t end = now();
|
||||||
foo = tag[0]; // prevent optimization
|
foo = tag[0]; // prevent optimization
|
||||||
ZT_T_PRINTF("%.4f MiB/sec" ZT_EOL_S,((16384.0 * 150000.0) / 1048576.0) / ((double)(end - start) / 1000.0));
|
ZT_T_PRINTF("%.4f MiB/sec" ZT_EOL_S,((16384.0 * 150000.0) / 1048576.0) / ((double)(end - start) / 1000.0));
|
||||||
|
|
|
@ -51,6 +51,11 @@ namespace Utils {
|
||||||
#define ZT_CONST_TO_BE_UINT64(x) ((uint64_t)(x))
|
#define ZT_CONST_TO_BE_UINT64(x) ((uint64_t)(x))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ZT_ROR64(x, r) (((x) >> (r)) | ((x) << (64 - (r))))
|
||||||
|
#define ZT_ROL64(x, r) (((x) << (r)) | ((x) >> (64 - (r))))
|
||||||
|
#define ZT_ROR32(x, r) (((x) >> (r)) | ((x) << (32 - (r))))
|
||||||
|
#define ZT_ROL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||||
|
|
||||||
#ifdef ZT_ARCH_X64
|
#ifdef ZT_ARCH_X64
|
||||||
struct CPUIDRegisters
|
struct CPUIDRegisters
|
||||||
{
|
{
|
||||||
|
@ -759,6 +764,9 @@ struct Mallocator
|
||||||
ZT_INLINE size_type max_size() const noexcept { return std::numeric_limits<size_t>::max() / sizeof(T); }
|
ZT_INLINE size_type max_size() const noexcept { return std::numeric_limits<size_t>::max() / sizeof(T); }
|
||||||
ZT_INLINE void construct(pointer p,const T& val) { new((void *)p) T(val); }
|
ZT_INLINE void construct(pointer p,const T& val) { new((void *)p) T(val); }
|
||||||
ZT_INLINE void destroy(pointer p) { p->~T(); }
|
ZT_INLINE void destroy(pointer p) { p->~T(); }
|
||||||
|
|
||||||
|
constexpr bool operator==(const Mallocator &) const noexcept { return true; }
|
||||||
|
constexpr bool operator!=(const Mallocator &) const noexcept { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
|
Loading…
Add table
Reference in a new issue