mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 20:43:44 +02:00
work in progress
This commit is contained in:
parent
22e95b3bcb
commit
891bf99894
18 changed files with 114 additions and 781 deletions
|
@ -1310,20 +1310,6 @@ void EmbeddedNetworkController::_request(
|
||||||
nc->mtu = std::max(std::min((unsigned int)OSUtils::jsonInt(network["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU);
|
nc->mtu = std::max(std::min((unsigned int)OSUtils::jsonInt(network["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU);
|
||||||
nc->multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"],32ULL);
|
nc->multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"],32ULL);
|
||||||
|
|
||||||
std::string rtt(OSUtils::jsonString(member["remoteTraceTarget"],""));
|
|
||||||
if (rtt.length() == 10) {
|
|
||||||
nc->remoteTraceTarget = Address(Utils::hexStrToU64(rtt.c_str()));
|
|
||||||
nc->remoteTraceLevel = (Trace::Level)OSUtils::jsonInt(member["remoteTraceLevel"],0ULL);
|
|
||||||
} else {
|
|
||||||
rtt = OSUtils::jsonString(network["remoteTraceTarget"],"");
|
|
||||||
if (rtt.length() == 10) {
|
|
||||||
nc->remoteTraceTarget = Address(Utils::hexStrToU64(rtt.c_str()));
|
|
||||||
} else {
|
|
||||||
nc->remoteTraceTarget.zero();
|
|
||||||
}
|
|
||||||
nc->remoteTraceLevel = (Trace::Level)OSUtils::jsonInt(network["remoteTraceLevel"],0ULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::vector<Address>::const_iterator ab(ns.activeBridges.begin());ab!=ns.activeBridges.end();++ab)
|
for(std::vector<Address>::const_iterator ab(ns.activeBridges.begin());ab!=ns.activeBridges.end();++ab)
|
||||||
nc->addSpecialist(*ab,ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE);
|
nc->addSpecialist(*ab,ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE);
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @return Hash code for use with Hashtable
|
* @return Hash code for use with Hashtable
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)_a; }
|
ZT_ALWAYS_INLINE unsigned long hashCode() const { return reinterpret_cast<unsigned long>(_a); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Hexadecimal string
|
* @return Hexadecimal string
|
||||||
|
@ -134,6 +134,10 @@ public:
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE uint8_t operator[](unsigned int i) const { return (uint8_t)(_a >> (32 - (i * 8))); }
|
ZT_ALWAYS_INLINE uint8_t operator[](unsigned int i) const { return (uint8_t)(_a >> (32 - (i * 8))); }
|
||||||
|
|
||||||
|
ZT_ALWAYS_INLINE operator unsigned int() const { return reinterpret_cast<unsigned int>(_a); }
|
||||||
|
ZT_ALWAYS_INLINE operator unsigned long() const { return reinterpret_cast<unsigned long>(_a); }
|
||||||
|
ZT_ALWAYS_INLINE operator unsigned long long() const { return reinterpret_cast<unsigned long long>(_a); }
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE void zero() { _a = 0; }
|
ZT_ALWAYS_INLINE void zero() { _a = 0; }
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE bool operator==(const uint64_t &a) const { return (_a == (a & 0xffffffffffULL)); }
|
ZT_ALWAYS_INLINE bool operator==(const uint64_t &a) const { return (_a == (a & 0xffffffffffULL)); }
|
||||||
|
|
|
@ -237,7 +237,7 @@ public:
|
||||||
* @param n Number of times to append
|
* @param n Number of times to append
|
||||||
* @throws std::out_of_range Attempt to append beyond capacity
|
* @throws std::out_of_range Attempt to append beyond capacity
|
||||||
*/
|
*/
|
||||||
inline void append(unsigned char c,unsigned int n)
|
inline void append(uint8_t c,unsigned int n)
|
||||||
{
|
{
|
||||||
if (unlikely((_l + n) > C))
|
if (unlikely((_l + n) > C))
|
||||||
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
||||||
|
|
|
@ -24,7 +24,6 @@ set(core_headers
|
||||||
Locator.hpp
|
Locator.hpp
|
||||||
MAC.hpp
|
MAC.hpp
|
||||||
Membership.hpp
|
Membership.hpp
|
||||||
Multicaster.hpp
|
|
||||||
MulticastGroup.hpp
|
MulticastGroup.hpp
|
||||||
Mutex.hpp
|
Mutex.hpp
|
||||||
Network.hpp
|
Network.hpp
|
||||||
|
@ -59,7 +58,6 @@ set(core_src
|
||||||
IncomingPacket.cpp
|
IncomingPacket.cpp
|
||||||
InetAddress.cpp
|
InetAddress.cpp
|
||||||
Membership.cpp
|
Membership.cpp
|
||||||
Multicaster.cpp
|
|
||||||
Network.cpp
|
Network.cpp
|
||||||
NetworkConfig.cpp
|
NetworkConfig.cpp
|
||||||
Node.cpp
|
Node.cpp
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
#ifndef ZT_CONSTANTS_HPP
|
#ifndef ZT_CONSTANTS_HPP
|
||||||
#define ZT_CONSTANTS_HPP
|
#define ZT_CONSTANTS_HPP
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Core includes and OS/platform setup stuff */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
#include "../include/ZeroTierCore.h"
|
#include "../include/ZeroTierCore.h"
|
||||||
|
|
||||||
#if __has_include("version.h")
|
#if __has_include("version.h")
|
||||||
|
@ -174,6 +178,10 @@
|
||||||
#define ZT_INVALID_SOCKET -1
|
#define ZT_INVALID_SOCKET -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Internal ZeroTier constants */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Length of a ZeroTier address in bytes
|
* Length of a ZeroTier address in bytes
|
||||||
*/
|
*/
|
||||||
|
@ -288,6 +296,11 @@
|
||||||
*/
|
*/
|
||||||
#define ZT_MULTICAST_GATHER_PERIOD ZT_MULTICAST_ANNOUNCE_PERIOD
|
#define ZT_MULTICAST_GATHER_PERIOD ZT_MULTICAST_ANNOUNCE_PERIOD
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Period for multicast GATHER if there are no known recipients
|
||||||
|
*/
|
||||||
|
#define ZT_MULTICAST_GATHER_PERIOD_WHEN_NO_RECIPIENTS 2500
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timeout for outgoing multicasts
|
* Timeout for outgoing multicasts
|
||||||
*
|
*
|
||||||
|
|
|
@ -115,26 +115,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute a 128-bit short hash of this identity's public key
|
* @param h Buffer to receive SHA384 of public key(s)
|
||||||
*
|
|
||||||
* This is the first 128 bits of a SHA384 hash and is the hash used
|
|
||||||
* in VERB_WILL_RELAY to report reachability.
|
|
||||||
*
|
|
||||||
* @param h 128-bit buffer to receive hash (must be 16 bytes in size)
|
|
||||||
*/
|
*/
|
||||||
ZT_ALWAYS_INLINE void publicKeyHash128(void *const h) const
|
ZT_ALWAYS_INLINE bool hash(uint8_t h[48]) const
|
||||||
{
|
{
|
||||||
uint8_t tmp[48];
|
|
||||||
switch(_type) {
|
switch(_type) {
|
||||||
case C25519:
|
case C25519:
|
||||||
SHA384(tmp,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
SHA384(h,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
|
||||||
break;
|
return true;
|
||||||
case P384:
|
case P384:
|
||||||
SHA384(tmp,&_pub,sizeof(_pub));
|
SHA384(h,&_pub,sizeof(_pub));
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
for(int i=0;i<16;++i)
|
return false;
|
||||||
((uint8_t *)h)[i] = tmp[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -41,13 +41,8 @@ namespace ZeroTier {
|
||||||
class MulticastGroup
|
class MulticastGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ZT_ALWAYS_INLINE MulticastGroup() :
|
ZT_ALWAYS_INLINE MulticastGroup() : _mac(),_adi(0) {}
|
||||||
_mac(),
|
ZT_ALWAYS_INLINE MulticastGroup(const MAC &m,uint32_t a) : _mac(m),_adi(a) {}
|
||||||
_adi(0) {}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE MulticastGroup(const MAC &m,uint32_t a) :
|
|
||||||
_mac(m),
|
|
||||||
_adi(a) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive the multicast group used for address resolution (ARP/NDP) for an IP
|
* Derive the multicast group used for address resolution (ARP/NDP) for an IP
|
||||||
|
@ -74,10 +69,36 @@ public:
|
||||||
return MulticastGroup();
|
return MulticastGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Ethernet MAC portion of multicast group
|
||||||
|
*/
|
||||||
ZT_ALWAYS_INLINE const MAC &mac() const { return _mac; }
|
ZT_ALWAYS_INLINE const MAC &mac() const { return _mac; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Additional distinguishing information, which is normally zero except for IPv4 ARP where it's the IPv4 address
|
||||||
|
*/
|
||||||
ZT_ALWAYS_INLINE uint32_t adi() const { return _adi; }
|
ZT_ALWAYS_INLINE uint32_t adi() const { return _adi; }
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (_mac.hashCode() ^ (unsigned long)_adi); }
|
/**
|
||||||
|
* @return 32-bit hash ID of this multicast group
|
||||||
|
*/
|
||||||
|
ZT_ALWAYS_INLINE uint32_t id() const
|
||||||
|
{
|
||||||
|
uint64_t m = _mac.toInt();
|
||||||
|
uint32_t x1 = _adi;
|
||||||
|
uint32_t x2 = (uint32_t)(m >> 32);
|
||||||
|
uint32_t x3 = (uint32_t)m;
|
||||||
|
x1 = ((x1 >> 16) ^ x1) * 0x45d9f3b;
|
||||||
|
x2 = ((x2 >> 16) ^ x2) * 0x45d9f3b;
|
||||||
|
x3 = ((x3 >> 16) ^ x3) * 0x45d9f3b;
|
||||||
|
x1 = ((x1 >> 16) ^ x1) * 0x45d9f3b;
|
||||||
|
x2 = ((x2 >> 16) ^ x2) * 0x45d9f3b;
|
||||||
|
x3 = ((x3 >> 16) ^ x3) * 0x45d9f3b;
|
||||||
|
x1 = (x1 >> 16) ^ x1;
|
||||||
|
x2 = (x2 >> 16) ^ x2;
|
||||||
|
x3 = (x3 >> 16) ^ x3;
|
||||||
|
return (x1 ^ x2 ^ x3);
|
||||||
|
}
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE bool operator==(const MulticastGroup &g) const { return ((_mac == g._mac)&&(_adi == g._adi)); }
|
ZT_ALWAYS_INLINE bool operator==(const MulticastGroup &g) const { return ((_mac == g._mac)&&(_adi == g._adi)); }
|
||||||
ZT_ALWAYS_INLINE bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); }
|
ZT_ALWAYS_INLINE bool operator!=(const MulticastGroup &g) const { return ((_mac != g._mac)||(_adi != g._adi)); }
|
||||||
|
@ -93,6 +114,8 @@ public:
|
||||||
ZT_ALWAYS_INLINE bool operator<=(const MulticastGroup &g) const { return !(g < *this); }
|
ZT_ALWAYS_INLINE bool operator<=(const MulticastGroup &g) const { return !(g < *this); }
|
||||||
ZT_ALWAYS_INLINE bool operator>=(const MulticastGroup &g) const { return !(*this < g); }
|
ZT_ALWAYS_INLINE bool operator>=(const MulticastGroup &g) const { return !(*this < g); }
|
||||||
|
|
||||||
|
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (_mac.hashCode() ^ (unsigned long)_adi); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MAC _mac;
|
MAC _mac;
|
||||||
uint32_t _adi;
|
uint32_t _adi;
|
||||||
|
|
|
@ -1,326 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c)2019 ZeroTier, Inc.
|
|
||||||
*
|
|
||||||
* Use of this software is governed by the Business Source License included
|
|
||||||
* in the LICENSE.TXT file in the project's root directory.
|
|
||||||
*
|
|
||||||
* Change Date: 2023-01-01
|
|
||||||
*
|
|
||||||
* On the date above, in accordance with the Business Source License, use
|
|
||||||
* of this software will be governed by version 2.0 of the Apache License.
|
|
||||||
*/
|
|
||||||
/****/
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "Constants.hpp"
|
|
||||||
#include "RuntimeEnvironment.hpp"
|
|
||||||
#include "Multicaster.hpp"
|
|
||||||
#include "Network.hpp"
|
|
||||||
#include "Membership.hpp"
|
|
||||||
#include "Topology.hpp"
|
|
||||||
#include "Switch.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
|
||||||
|
|
||||||
Multicaster::Multicaster(const RuntimeEnvironment *renv) :
|
|
||||||
RR(renv),
|
|
||||||
_groups(32) {}
|
|
||||||
|
|
||||||
Multicaster::~Multicaster() {}
|
|
||||||
|
|
||||||
unsigned int Multicaster::send(
|
|
||||||
void *tPtr,
|
|
||||||
int64_t now,
|
|
||||||
const SharedPtr<Network> &network,
|
|
||||||
const MulticastGroup &mg,
|
|
||||||
const MAC &src,
|
|
||||||
unsigned int etherType,
|
|
||||||
const unsigned int existingBloomMultiplier,
|
|
||||||
const uint8_t existingBloom[ZT_MULTICAST_BLOOM_FILTER_SIZE_BITS / 8],
|
|
||||||
const void *const data,
|
|
||||||
unsigned int len)
|
|
||||||
{
|
|
||||||
static const unsigned int PRIMES[16] = { 3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59 }; // 2 is skipped as it's even
|
|
||||||
|
|
||||||
std::vector< std::pair<int64_t,Address> > recipients;
|
|
||||||
|
|
||||||
const NetworkConfig &config = network->config();
|
|
||||||
if (config.multicastLimit == 0) return 0; // multicast disabled
|
|
||||||
|
|
||||||
Address specialists[ZT_MAX_NETWORK_SPECIALISTS],multicastReplicators[ZT_MAX_NETWORK_SPECIALISTS];
|
|
||||||
unsigned int specialistCount = 0,multicastReplicatorCount = 0,bridgeCount = 0;
|
|
||||||
bool amMulticastReplicator = false;
|
|
||||||
for(unsigned int i=0;i<config.specialistCount;++i) {
|
|
||||||
if (RR->identity.address() == config.specialists[i]) {
|
|
||||||
amMulticastReplicator |= ((config.specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0);
|
|
||||||
} else {
|
|
||||||
specialists[specialistCount++] = config.specialists[i];
|
|
||||||
if ((config.specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) {
|
|
||||||
recipients.push_back(std::pair<int64_t,Address>(0,config.specialists[i]));
|
|
||||||
++bridgeCount;
|
|
||||||
} if ((config.specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR) != 0) {
|
|
||||||
multicastReplicators[multicastReplicatorCount++] = config.specialists[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(&(specialists[0]),&(specialists[specialistCount])); // for binary search
|
|
||||||
|
|
||||||
int64_t lastGather = 0;
|
|
||||||
_K groupKey(network->id(),mg);
|
|
||||||
{
|
|
||||||
Mutex::Lock l(_groups_l);
|
|
||||||
const _G *const g = _groups.get(groupKey);
|
|
||||||
if (g) {
|
|
||||||
lastGather = g->lastGather;
|
|
||||||
recipients.reserve(recipients.size() + g->members.size());
|
|
||||||
Hashtable< Address,int64_t >::Iterator mi(const_cast<_G *>(g)->members);
|
|
||||||
Address *mik = nullptr;
|
|
||||||
int64_t *miv = nullptr;
|
|
||||||
while (mi.next(mik,miv)) {
|
|
||||||
if (!std::binary_search(&(specialists[0]),&(specialists[specialistCount]),*mik))
|
|
||||||
recipients.push_back(std::pair<int64_t,Address>(*miv,*mik));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort recipients, maintaining bridges first in list
|
|
||||||
std::sort(recipients.begin() + bridgeCount,recipients.end(),std::greater< std::pair<int64_t,Address> >());
|
|
||||||
|
|
||||||
// Gather new recipients periodically, being more aggressive if we have none.
|
|
||||||
if ((now - lastGather) > (recipients.empty() ? 5000 : ZT_MULTICAST_GATHER_PERIOD)) {
|
|
||||||
{
|
|
||||||
Mutex::Lock l(_groups_l);
|
|
||||||
_groups[groupKey].lastGather = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet outp(network->controller(),RR->identity.address(),Packet::VERB_MULTICAST_GATHER);
|
|
||||||
outp.append(network->id());
|
|
||||||
outp.append((uint8_t)0);
|
|
||||||
mg.mac().appendTo(outp);
|
|
||||||
outp.append(mg.adi());
|
|
||||||
outp.append((uint32_t)0xffffffff);
|
|
||||||
RR->sw->send(tPtr,outp,true);
|
|
||||||
|
|
||||||
for(unsigned int i=0;i<specialistCount;++i) {
|
|
||||||
outp.newInitializationVector();
|
|
||||||
outp.setDestination(specialists[i]);
|
|
||||||
RR->sw->send(tPtr,outp,true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// LEGACY: roots may know about older versions' multicast subscriptions but
|
|
||||||
// the root's role here is being phased out.
|
|
||||||
SharedPtr<Peer> root(RR->topology->root(now));
|
|
||||||
if (root) {
|
|
||||||
outp.newInitializationVector();
|
|
||||||
outp.setDestination(root->address());
|
|
||||||
outp.armor(root->key(),true);
|
|
||||||
root->sendDirect(tPtr,outp.data(),outp.size(),now,true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recipients.empty())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
unsigned int sentCount = 0;
|
|
||||||
|
|
||||||
uint64_t bloomFilter[ZT_MULTICAST_BLOOM_FILTER_SIZE_BITS / 64];
|
|
||||||
unsigned int bloomMultiplier;
|
|
||||||
if (existingBloom) {
|
|
||||||
memcpy(bloomFilter,existingBloom,sizeof(bloomFilter));
|
|
||||||
bloomMultiplier = existingBloomMultiplier;
|
|
||||||
} else {
|
|
||||||
memset(bloomFilter,0,sizeof(bloomFilter));
|
|
||||||
bloomMultiplier = 1;
|
|
||||||
|
|
||||||
// Iteratively search for a bloom multiplier that results in no collisions
|
|
||||||
// among known recipients. Usually the first iteration is good unless
|
|
||||||
// the recipient set is quite large.
|
|
||||||
if (recipients.size() > 1) {
|
|
||||||
unsigned long bestMultColl = 0xffffffff;
|
|
||||||
for(int k=0;k<16;++k) { // 16 == arbitrary limit on iterations for this search, also must be <= size of PRIMES
|
|
||||||
const unsigned int mult = PRIMES[k];
|
|
||||||
unsigned long coll = 0;
|
|
||||||
for(std::vector< std::pair<int64_t,Address> >::const_iterator r(recipients.begin());r!=recipients.end();++r) {
|
|
||||||
const unsigned int bfi = mult * (unsigned int)r->second.toInt();
|
|
||||||
const unsigned int byte = (bfi >> 3) % sizeof(bloomFilter);
|
|
||||||
const uint8_t bit = 1 << (bfi & 7);
|
|
||||||
coll += ((((uint8_t *)bloomFilter)[byte] & bit) != 0);
|
|
||||||
((uint8_t *)bloomFilter)[byte] |= bit;
|
|
||||||
}
|
|
||||||
memset(bloomFilter,0,sizeof(bloomFilter));
|
|
||||||
|
|
||||||
if (coll <= bestMultColl) {
|
|
||||||
bloomMultiplier = mult;
|
|
||||||
if (coll == 0) // perfect score, no need to continue searching
|
|
||||||
break;
|
|
||||||
bestMultColl = coll;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if there is a multicast replicator, trying to pick the fastest/best one.
|
|
||||||
Address bestReplicator;
|
|
||||||
if (multicastReplicatorCount > 0) {
|
|
||||||
unsigned int bestReplicatorLatency = 0xffff;
|
|
||||||
for(unsigned int i=0;i<multicastReplicatorCount;++i) {
|
|
||||||
const unsigned int bfi = bloomMultiplier * (unsigned int)multicastReplicators[i].toInt();
|
|
||||||
if ((((uint8_t *)bloomFilter)[(bfi >> 3) % sizeof(bloomFilter)] & (1 << (bfi & 7))) == 0) {
|
|
||||||
SharedPtr<Peer> peer(RR->topology->get(multicastReplicators[i]));
|
|
||||||
if (peer) {
|
|
||||||
const unsigned int lat = peer->latency(now);
|
|
||||||
if (lat <= bestReplicatorLatency) {
|
|
||||||
bestReplicator = peer->address();
|
|
||||||
bestReplicatorLatency = lat;
|
|
||||||
}
|
|
||||||
} else if (!bestReplicator) {
|
|
||||||
bestReplicator = multicastReplicators[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is a multicast replicator, aggressively replicate. Multicast
|
|
||||||
// replicators are not subject to send count limits.
|
|
||||||
if (amMulticastReplicator) {
|
|
||||||
std::vector< std::pair< int,Address > > byLatency;
|
|
||||||
for(std::vector< std::pair<int64_t,Address> >::const_iterator r(recipients.begin());r!=recipients.end();++r) {
|
|
||||||
const unsigned int bfi = bloomMultiplier * (unsigned int)r->second.toInt();
|
|
||||||
if ((((uint8_t *)bloomFilter)[(bfi >> 3) % sizeof(bloomFilter)] & (1 << (bfi & 7))) == 0) {
|
|
||||||
SharedPtr<Peer> peer(RR->topology->get(r->second));
|
|
||||||
byLatency.push_back(std::pair< int,Address >((peer) ? (int)peer->latency(now) : 0xffff,r->second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(byLatency.begin(),byLatency.end());
|
|
||||||
|
|
||||||
unsigned long cnt = byLatency.size();
|
|
||||||
if (bestReplicator)
|
|
||||||
cnt /= 2; // send to only the best half of the latency-sorted population if there are more replicators
|
|
||||||
for(unsigned long i=0;i<cnt;++i) {
|
|
||||||
const unsigned int bfi = bloomMultiplier * (unsigned int)byLatency[i].second.toInt();
|
|
||||||
((uint8_t *)bloomFilter)[(bfi >> 3) % sizeof(bloomFilter)] |= 1 << (bfi & 7);
|
|
||||||
|
|
||||||
Packet outp(byLatency[i].second,RR->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
|
||||||
outp.append(network->id());
|
|
||||||
outp.append((uint8_t)0x04);
|
|
||||||
src.appendTo(outp);
|
|
||||||
mg.mac().appendTo(outp);
|
|
||||||
outp.append(mg.adi());
|
|
||||||
outp.append((uint16_t)etherType);
|
|
||||||
outp.append(data,len);
|
|
||||||
outp.compress();
|
|
||||||
RR->sw->send(tPtr,outp,true);
|
|
||||||
|
|
||||||
++sentCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward to the next multicast replicator, if any.
|
|
||||||
if (bestReplicator) {
|
|
||||||
const unsigned int bfi = bloomMultiplier * (unsigned int)bestReplicator.toInt();
|
|
||||||
((uint8_t *)bloomFilter)[(bfi >> 3) % sizeof(bloomFilter)] |= 1 << (bfi & 7);
|
|
||||||
|
|
||||||
Packet outp(bestReplicator,RR->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
|
||||||
outp.append((uint8_t)(0x04 | 0x08));
|
|
||||||
RR->identity.address().appendTo(outp);
|
|
||||||
outp.append((uint16_t)bloomMultiplier);
|
|
||||||
outp.append((uint16_t)sizeof(bloomFilter));
|
|
||||||
outp.append(((uint8_t *)bloomFilter),sizeof(bloomFilter));
|
|
||||||
src.appendTo(outp);
|
|
||||||
mg.mac().appendTo(outp);
|
|
||||||
outp.append(mg.adi());
|
|
||||||
outp.append((uint16_t)etherType);
|
|
||||||
outp.append(data,len);
|
|
||||||
outp.compress();
|
|
||||||
RR->sw->send(tPtr,outp,true);
|
|
||||||
|
|
||||||
++sentCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is a multicast replicator, we've already replicated.
|
|
||||||
if (amMulticastReplicator)
|
|
||||||
return (unsigned int)recipients.size();
|
|
||||||
|
|
||||||
// Find the two best next hops (that have never seen this multicast)
|
|
||||||
// that are newer version nodes.
|
|
||||||
SharedPtr<Peer> nextHops[2];
|
|
||||||
unsigned int nextHopsBestLatency[2] = { 0xffff,0xffff };
|
|
||||||
for(std::vector< std::pair<int64_t,Address> >::iterator r(recipients.begin());r!=recipients.end();++r) {
|
|
||||||
if (r->first >= 0) {
|
|
||||||
const unsigned int bfi = bloomMultiplier * (unsigned int)r->second.toInt();
|
|
||||||
if ((((uint8_t *)bloomFilter)[(bfi >> 3) % sizeof(bloomFilter)] & (1 << (bfi & 7))) == 0) {
|
|
||||||
const SharedPtr<Peer> peer(RR->topology->get(r->second));
|
|
||||||
if ((peer)&&(peer->remoteVersionProtocol() >= 11)) {
|
|
||||||
r->first = -1; // use this field now to flag as non-legacy
|
|
||||||
const unsigned int lat = peer->latency(now);
|
|
||||||
for(unsigned int nh=0;nh<2;++nh) {
|
|
||||||
if (lat <= nextHopsBestLatency[nh]) {
|
|
||||||
nextHopsBestLatency[nh] = lat;
|
|
||||||
nextHops[nh] = peer;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set bits for next hops in bloom filter
|
|
||||||
for(unsigned int nh=0;nh<2;++nh) {
|
|
||||||
if (nextHops[nh]) {
|
|
||||||
const unsigned int bfi = bloomMultiplier * (unsigned int)nextHops[nh]->address().toInt();
|
|
||||||
((uint8_t *)bloomFilter)[(bfi >> 3) % sizeof(bloomFilter)] |= 1 << (bfi & 7);
|
|
||||||
++sentCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send to legacy peers and flag these in bloom filter
|
|
||||||
const unsigned int limit = config.multicastLimit + bridgeCount;
|
|
||||||
for(std::vector< std::pair<int64_t,Address> >::const_iterator r(recipients.begin());(r!=recipients.end())&&(sentCount<limit);++r) {
|
|
||||||
if (r->first >= 0) {
|
|
||||||
const unsigned int bfi = bloomMultiplier * (unsigned int)r->second.toInt();
|
|
||||||
((uint8_t *)bloomFilter)[(bfi >> 3) % sizeof(bloomFilter)] |= 1 << (bfi & 7);
|
|
||||||
|
|
||||||
Packet outp(r->second,RR->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
|
||||||
outp.append(network->id());
|
|
||||||
outp.append((uint8_t)0x04);
|
|
||||||
src.appendTo(outp);
|
|
||||||
mg.mac().appendTo(outp);
|
|
||||||
outp.append(mg.adi());
|
|
||||||
outp.append((uint16_t)etherType);
|
|
||||||
outp.append(data,len);
|
|
||||||
outp.compress();
|
|
||||||
RR->sw->send(tPtr,outp,true);
|
|
||||||
|
|
||||||
++sentCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send to next hops for P2P propagation
|
|
||||||
for(unsigned int nh=0;nh<2;++nh) {
|
|
||||||
if (nextHops[nh]) {
|
|
||||||
Packet outp(nextHops[nh]->address(),RR->identity.address(),Packet::VERB_MULTICAST_FRAME);
|
|
||||||
outp.append((uint8_t)(0x04 | 0x08));
|
|
||||||
RR->identity.address().appendTo(outp);
|
|
||||||
outp.append((uint16_t)bloomMultiplier);
|
|
||||||
outp.append((uint16_t)sizeof(bloomFilter));
|
|
||||||
outp.append(((uint8_t *)bloomFilter),sizeof(bloomFilter));
|
|
||||||
src.appendTo(outp);
|
|
||||||
mg.mac().appendTo(outp);
|
|
||||||
outp.append(mg.adi());
|
|
||||||
outp.append((uint16_t)etherType);
|
|
||||||
outp.append(data,len);
|
|
||||||
outp.compress();
|
|
||||||
RR->sw->send(tPtr,outp,true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (unsigned int)recipients.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Multicaster::clean(int64_t now)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ZeroTier
|
|
|
@ -1,236 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c)2019 ZeroTier, Inc.
|
|
||||||
*
|
|
||||||
* Use of this software is governed by the Business Source License included
|
|
||||||
* in the LICENSE.TXT file in the project's root directory.
|
|
||||||
*
|
|
||||||
* Change Date: 2023-01-01
|
|
||||||
*
|
|
||||||
* On the date above, in accordance with the Business Source License, use
|
|
||||||
* of this software will be governed by version 2.0 of the Apache License.
|
|
||||||
*/
|
|
||||||
/****/
|
|
||||||
|
|
||||||
#ifndef ZT_MULTICASTER_HPP
|
|
||||||
#define ZT_MULTICASTER_HPP
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Constants.hpp"
|
|
||||||
#include "Hashtable.hpp"
|
|
||||||
#include "Address.hpp"
|
|
||||||
#include "MAC.hpp"
|
|
||||||
#include "MulticastGroup.hpp"
|
|
||||||
#include "Utils.hpp"
|
|
||||||
#include "Mutex.hpp"
|
|
||||||
#include "SharedPtr.hpp"
|
|
||||||
#include "Packet.hpp"
|
|
||||||
|
|
||||||
// Size in bits -- do not change as this is about as large as we can support
|
|
||||||
// This leaves room for up to 10000 MTU data (max supported MTU) and header
|
|
||||||
// information in a maximum supported size packet. Note that data compression
|
|
||||||
// will practically reduce this size in transit for sparse or saturated fields.
|
|
||||||
#define ZT_MULTICAST_BLOOM_FILTER_SIZE_BITS 50048
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
|
||||||
|
|
||||||
class RuntimeEnvironment;
|
|
||||||
class CertificateOfMembership;
|
|
||||||
class Packet;
|
|
||||||
class Network;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multicast database and outbound multicast logic
|
|
||||||
*/
|
|
||||||
class Multicaster
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
// Composite key of network ID and multicast group
|
|
||||||
struct _K
|
|
||||||
{
|
|
||||||
uint64_t nwid;
|
|
||||||
MulticastGroup mg;
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE _K() : nwid(0),mg() {}
|
|
||||||
ZT_ALWAYS_INLINE _K(const uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {}
|
|
||||||
ZT_ALWAYS_INLINE bool operator==(const _K &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); }
|
|
||||||
ZT_ALWAYS_INLINE bool operator!=(const _K &k) const { return ((nwid != k.nwid)||(mg != k.mg)); }
|
|
||||||
ZT_ALWAYS_INLINE unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Multicast group info
|
|
||||||
struct _G
|
|
||||||
{
|
|
||||||
ZT_ALWAYS_INLINE _G() : lastGather(0),members(16) {}
|
|
||||||
int64_t lastGather;
|
|
||||||
Hashtable< Address,int64_t > members;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Outbound multicast
|
|
||||||
struct _OM
|
|
||||||
{
|
|
||||||
uint64_t nwid;
|
|
||||||
MAC src;
|
|
||||||
MulticastGroup mg;
|
|
||||||
unsigned int etherType;
|
|
||||||
unsigned int dataSize;
|
|
||||||
unsigned int count;
|
|
||||||
unsigned int limit;
|
|
||||||
unsigned int bloomFilterMultiplier;
|
|
||||||
uint64_t bloomFilter[ZT_MULTICAST_BLOOM_FILTER_SIZE_BITS / 64];
|
|
||||||
uint8_t data[ZT_MAX_MTU];
|
|
||||||
Mutex lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Multicaster(const RuntimeEnvironment *renv);
|
|
||||||
~Multicaster();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add or update a member in a multicast group
|
|
||||||
*
|
|
||||||
* @param now Current time
|
|
||||||
* @param nwid Network ID
|
|
||||||
* @param mg Multicast group
|
|
||||||
* @param member New member address
|
|
||||||
*/
|
|
||||||
ZT_ALWAYS_INLINE void add(const int64_t now,const uint64_t nwid,const MulticastGroup &mg,const Address &member)
|
|
||||||
{
|
|
||||||
Mutex::Lock l(_groups_l);
|
|
||||||
_groups[_K(nwid,mg)].members.set(member,now);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add multiple addresses from a binary array of 5-byte address fields
|
|
||||||
*
|
|
||||||
* It's up to the caller to check bounds on the array before calling this.
|
|
||||||
*
|
|
||||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
|
||||||
* @param now Current time
|
|
||||||
* @param nwid Network ID
|
|
||||||
* @param mg Multicast group
|
|
||||||
* @param addresses Raw binary addresses in big-endian format, as a series of 5-byte fields
|
|
||||||
* @param count Number of addresses
|
|
||||||
* @param totalKnown Total number of known addresses as reported by peer
|
|
||||||
*/
|
|
||||||
ZT_ALWAYS_INLINE void addMultiple(const int64_t now,const uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,const unsigned int totalKnown)
|
|
||||||
{
|
|
||||||
Mutex::Lock l(_groups_l);
|
|
||||||
const uint8_t *a = (const uint8_t *)addresses;
|
|
||||||
_G &g = _groups[_K(nwid,mg)];
|
|
||||||
while (count--) {
|
|
||||||
g.members.set(Address(a,ZT_ADDRESS_LENGTH),now);
|
|
||||||
a += ZT_ADDRESS_LENGTH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a multicast group member (if present)
|
|
||||||
*
|
|
||||||
* @param nwid Network ID
|
|
||||||
* @param mg Multicast group
|
|
||||||
* @param member Member to unsubscribe
|
|
||||||
*/
|
|
||||||
ZT_ALWAYS_INLINE void remove(const uint64_t nwid,const MulticastGroup &mg,const Address &member)
|
|
||||||
{
|
|
||||||
Mutex::Lock l(_groups_l);
|
|
||||||
const _K gk(nwid,mg);
|
|
||||||
_G *const g = _groups.get(gk);
|
|
||||||
if (g) {
|
|
||||||
g->members.erase(member);
|
|
||||||
if (g->members.empty())
|
|
||||||
_groups.erase(gk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterate over members of a multicast group until function returns false
|
|
||||||
*
|
|
||||||
* Iteration order is in inverse order of most recent receipt of a LIKE
|
|
||||||
* for a given membership.
|
|
||||||
*
|
|
||||||
* @param nwid Network ID
|
|
||||||
* @param mg Multicast group
|
|
||||||
* @param func f(Address)
|
|
||||||
* @return Total number of known members (regardless of when function aborted)
|
|
||||||
*/
|
|
||||||
template<typename F>
|
|
||||||
ZT_ALWAYS_INLINE unsigned long eachMember(const uint64_t nwid,const MulticastGroup &mg,F func) const
|
|
||||||
{
|
|
||||||
std::vector< std::pair<int64_t,Address> > sortedByTime;
|
|
||||||
{
|
|
||||||
Mutex::Lock l(_groups_l);
|
|
||||||
const _K gk(nwid,mg);
|
|
||||||
const _G *const g = _groups.get(gk);
|
|
||||||
if (g) {
|
|
||||||
sortedByTime.reserve(g->members.size());
|
|
||||||
{
|
|
||||||
Hashtable< Address,int64_t >::Iterator mi(const_cast<_G *>(g)->members);
|
|
||||||
Address *mik = nullptr;
|
|
||||||
int64_t *miv = nullptr;
|
|
||||||
while (mi.next(mik,miv))
|
|
||||||
sortedByTime.push_back(std::pair<int64_t,Address>(*miv,*mik));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(sortedByTime.begin(),sortedByTime.end());
|
|
||||||
for(std::vector< std::pair<int64_t,Address> >::const_reverse_iterator i(sortedByTime.rbegin());i!=sortedByTime.rend();++i) {
|
|
||||||
if (!func(i->second))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return sortedByTime.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a multicast
|
|
||||||
*
|
|
||||||
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
|
|
||||||
* @param now Current time
|
|
||||||
* @param network Network
|
|
||||||
* @param mg Multicast group
|
|
||||||
* @param src Source Ethernet MAC address or NULL to skip in packet and compute from ZT address (non-bridged mode)
|
|
||||||
* @param etherType Ethernet frame type
|
|
||||||
* @param existingBloomMultiplier Existing bloom filter multiplier or 0 if none
|
|
||||||
* @param existingBloom Existing bloom filter or NULL if none
|
|
||||||
* @param data Packet data
|
|
||||||
* @param len Length of packet data
|
|
||||||
* @return Number of known recipients for multicast (including bridges and replicators)
|
|
||||||
*/
|
|
||||||
unsigned int send(
|
|
||||||
void *tPtr,
|
|
||||||
int64_t now,
|
|
||||||
const SharedPtr<Network> &network,
|
|
||||||
const MulticastGroup &mg,
|
|
||||||
const MAC &src,
|
|
||||||
unsigned int etherType,
|
|
||||||
const unsigned int existingBloomMultiplier,
|
|
||||||
const uint8_t existingBloom[ZT_MULTICAST_BLOOM_FILTER_SIZE_BITS / 8],
|
|
||||||
const void *const data,
|
|
||||||
unsigned int len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean up database
|
|
||||||
*
|
|
||||||
* @param RR Runtime environment
|
|
||||||
* @param now Current time
|
|
||||||
*/
|
|
||||||
void clean(int64_t now);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const RuntimeEnvironment *const RR;
|
|
||||||
|
|
||||||
_OM _txQueue[ZT_TX_QUEUE_SIZE];
|
|
||||||
unsigned int _txQueuePtr;
|
|
||||||
Mutex _txQueue_l;
|
|
||||||
|
|
||||||
Hashtable< _K,_G > _groups;
|
|
||||||
Mutex _groups_l;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ZeroTier
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "MulticastGroup.hpp"
|
#include "MulticastGroup.hpp"
|
||||||
#include "MAC.hpp"
|
#include "MAC.hpp"
|
||||||
#include "Dictionary.hpp"
|
#include "Dictionary.hpp"
|
||||||
#include "Multicaster.hpp"
|
|
||||||
#include "Membership.hpp"
|
#include "Membership.hpp"
|
||||||
#include "NetworkConfig.hpp"
|
#include "NetworkConfig.hpp"
|
||||||
#include "CertificateOfMembership.hpp"
|
#include "CertificateOfMembership.hpp"
|
||||||
|
|
|
@ -34,9 +34,8 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta)) return false;
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,this->credentialTimeMaxDelta)) return false;
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision)) return false;
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REVISION,this->revision)) return false;
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString(tmp2))) return false;
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,this->issuedTo.toString(tmp2))) return false;
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET,this->remoteTraceTarget.toString(tmp2))) return false;
|
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL,(uint64_t)this->remoteTraceLevel)) return false;
|
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags)) return false;
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,this->flags)) return false;
|
||||||
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TOKEN,this->token)) return false;
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) return false;
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,(uint64_t)this->multicastLimit)) return false;
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) return false;
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)this->type)) return false;
|
||||||
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) return false;
|
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name)) return false;
|
||||||
|
@ -125,8 +124,6 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
|
||||||
this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0);
|
this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0);
|
||||||
if (!this->issuedTo)
|
if (!this->issuedTo)
|
||||||
return false;
|
return false;
|
||||||
this->remoteTraceTarget = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET);
|
|
||||||
this->remoteTraceLevel = (Trace::Level)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL);
|
|
||||||
this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,0);
|
this->multicastLimit = (unsigned int)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,0);
|
||||||
d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name,sizeof(this->name));
|
d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME,this->name,sizeof(this->name));
|
||||||
|
|
||||||
|
@ -141,6 +138,7 @@ bool NetworkConfig::fromDictionary(const Dictionary<ZT_NETWORKCONFIG_DICT_CAPACI
|
||||||
} else {
|
} else {
|
||||||
// Otherwise we can use the new fields
|
// Otherwise we can use the new fields
|
||||||
this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,0);
|
this->flags = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_FLAGS,0);
|
||||||
|
this->token = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TOKEN,0);
|
||||||
this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)ZT_NETWORK_TYPE_PRIVATE);
|
this->type = (ZT_VirtualNetworkType)d.getUI(ZT_NETWORKCONFIG_DICT_KEY_TYPE,(uint64_t)ZT_NETWORK_TYPE_PRIVATE);
|
||||||
|
|
||||||
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp))
|
if (d.get(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp))
|
||||||
|
|
|
@ -87,6 +87,11 @@ namespace ZeroTier {
|
||||||
*/
|
*/
|
||||||
#define ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR 0x0000040000000000ULL
|
#define ZT_NETWORKCONFIG_SPECIALIST_TYPE_MULTICAST_REPLICATOR 0x0000040000000000ULL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Device that can probe and receive remote trace info about this network
|
||||||
|
*/
|
||||||
|
#define ZT_NETWORKCONFIG_SPECIALIST_TYPE_DIAGNOSTICIAN 0x0000080000000000ULL
|
||||||
|
|
||||||
// Dictionary capacity needed for max size network config
|
// Dictionary capacity needed for max size network config
|
||||||
#define ZT_NETWORKCONFIG_DICT_CAPACITY (1024 + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS) + (sizeof(CertificateOfOwnership) * ZT_MAX_CERTIFICATES_OF_OWNERSHIP))
|
#define ZT_NETWORKCONFIG_DICT_CAPACITY (1024 + (sizeof(ZT_VirtualNetworkRule) * ZT_MAX_NETWORK_RULES) + (sizeof(Capability) * ZT_MAX_NETWORK_CAPABILITIES) + (sizeof(Tag) * ZT_MAX_NETWORK_TAGS) + (sizeof(CertificateOfOwnership) * ZT_MAX_CERTIFICATES_OF_OWNERSHIP))
|
||||||
|
|
||||||
|
@ -133,14 +138,12 @@ namespace ZeroTier {
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
|
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
|
||||||
// address of member
|
// address of member
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
|
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
|
||||||
// remote trace target
|
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET "tt"
|
|
||||||
// remote trace level
|
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_LEVEL "tl"
|
|
||||||
// flags(hex)
|
// flags(hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_FLAGS "f"
|
#define ZT_NETWORKCONFIG_DICT_KEY_FLAGS "f"
|
||||||
// integer(hex)
|
// integer(hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
|
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
|
||||||
|
// integer(hex)
|
||||||
|
#define ZT_NETWORKCONFIG_DICT_KEY_TOKEN "k"
|
||||||
// network type (hex)
|
// network type (hex)
|
||||||
#define ZT_NETWORKCONFIG_DICT_KEY_TYPE "t"
|
#define ZT_NETWORKCONFIG_DICT_KEY_TYPE "t"
|
||||||
// text
|
// text
|
||||||
|
@ -180,9 +183,7 @@ struct NetworkConfig
|
||||||
credentialTimeMaxDelta(0),
|
credentialTimeMaxDelta(0),
|
||||||
revision(0),
|
revision(0),
|
||||||
issuedTo(),
|
issuedTo(),
|
||||||
remoteTraceTarget(),
|
|
||||||
flags(0),
|
flags(0),
|
||||||
remoteTraceLevel(Trace::LEVEL_NORMAL),
|
|
||||||
mtu(0),
|
mtu(0),
|
||||||
multicastLimit(0),
|
multicastLimit(0),
|
||||||
specialistCount(0),
|
specialistCount(0),
|
||||||
|
@ -336,20 +337,15 @@ struct NetworkConfig
|
||||||
*/
|
*/
|
||||||
Address issuedTo;
|
Address issuedTo;
|
||||||
|
|
||||||
/**
|
|
||||||
* If non-NULL, remote traces related to this network are sent here
|
|
||||||
*/
|
|
||||||
Address remoteTraceTarget;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flags (64-bit)
|
* Flags (64-bit)
|
||||||
*/
|
*/
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote trace level
|
* Token (64-bit token known only to network members)
|
||||||
*/
|
*/
|
||||||
Trace::Level remoteTraceLevel;
|
uint64_t token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network MTU
|
* Network MTU
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "RuntimeEnvironment.hpp"
|
#include "RuntimeEnvironment.hpp"
|
||||||
#include "NetworkController.hpp"
|
#include "NetworkController.hpp"
|
||||||
#include "Switch.hpp"
|
#include "Switch.hpp"
|
||||||
#include "Multicaster.hpp"
|
|
||||||
#include "Topology.hpp"
|
#include "Topology.hpp"
|
||||||
#include "Buffer.hpp"
|
#include "Buffer.hpp"
|
||||||
#include "Packet.hpp"
|
#include "Packet.hpp"
|
||||||
|
@ -93,11 +92,10 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
|
||||||
try {
|
try {
|
||||||
const unsigned long ts = sizeof(Trace) + (((sizeof(Trace) & 0xf) != 0) ? (16 - (sizeof(Trace) & 0xf)) : 0);
|
const unsigned long ts = sizeof(Trace) + (((sizeof(Trace) & 0xf) != 0) ? (16 - (sizeof(Trace) & 0xf)) : 0);
|
||||||
const unsigned long sws = sizeof(Switch) + (((sizeof(Switch) & 0xf) != 0) ? (16 - (sizeof(Switch) & 0xf)) : 0);
|
const unsigned long sws = sizeof(Switch) + (((sizeof(Switch) & 0xf) != 0) ? (16 - (sizeof(Switch) & 0xf)) : 0);
|
||||||
const unsigned long mcs = sizeof(Multicaster) + (((sizeof(Multicaster) & 0xf) != 0) ? (16 - (sizeof(Multicaster) & 0xf)) : 0);
|
|
||||||
const unsigned long topologys = sizeof(Topology) + (((sizeof(Topology) & 0xf) != 0) ? (16 - (sizeof(Topology) & 0xf)) : 0);
|
const unsigned long topologys = sizeof(Topology) + (((sizeof(Topology) & 0xf) != 0) ? (16 - (sizeof(Topology) & 0xf)) : 0);
|
||||||
const unsigned long sas = sizeof(SelfAwareness) + (((sizeof(SelfAwareness) & 0xf) != 0) ? (16 - (sizeof(SelfAwareness) & 0xf)) : 0);
|
const unsigned long sas = sizeof(SelfAwareness) + (((sizeof(SelfAwareness) & 0xf) != 0) ? (16 - (sizeof(SelfAwareness) & 0xf)) : 0);
|
||||||
|
|
||||||
m = reinterpret_cast<char *>(::malloc(16 + ts + sws + mcs + topologys + sas));
|
m = reinterpret_cast<char *>(::malloc(16 + ts + sws + topologys + sas));
|
||||||
if (!m)
|
if (!m)
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
RR->rtmem = m;
|
RR->rtmem = m;
|
||||||
|
@ -107,15 +105,12 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64
|
||||||
m += ts;
|
m += ts;
|
||||||
RR->sw = new (m) Switch(RR);
|
RR->sw = new (m) Switch(RR);
|
||||||
m += sws;
|
m += sws;
|
||||||
RR->mc = new (m) Multicaster(RR);
|
|
||||||
m += mcs;
|
|
||||||
RR->topology = new (m) Topology(RR,RR->identity);
|
RR->topology = new (m) Topology(RR,RR->identity);
|
||||||
m += topologys;
|
m += topologys;
|
||||||
RR->sa = new (m) SelfAwareness(RR);
|
RR->sa = new (m) SelfAwareness(RR);
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
if (RR->sa) RR->sa->~SelfAwareness();
|
if (RR->sa) RR->sa->~SelfAwareness();
|
||||||
if (RR->topology) RR->topology->~Topology();
|
if (RR->topology) RR->topology->~Topology();
|
||||||
if (RR->mc) RR->mc->~Multicaster();
|
|
||||||
if (RR->sw) RR->sw->~Switch();
|
if (RR->sw) RR->sw->~Switch();
|
||||||
if (RR->t) RR->t->~Trace();
|
if (RR->t) RR->t->~Trace();
|
||||||
::free(m);
|
::free(m);
|
||||||
|
@ -133,7 +128,6 @@ Node::~Node()
|
||||||
}
|
}
|
||||||
if (RR->sa) RR->sa->~SelfAwareness();
|
if (RR->sa) RR->sa->~SelfAwareness();
|
||||||
if (RR->topology) RR->topology->~Topology();
|
if (RR->topology) RR->topology->~Topology();
|
||||||
if (RR->mc) RR->mc->~Multicaster();
|
|
||||||
if (RR->sw) RR->sw->~Switch();
|
if (RR->sw) RR->sw->~Switch();
|
||||||
if (RR->t) RR->t->~Trace();
|
if (RR->t) RR->t->~Trace();
|
||||||
::free(RR->rtmem);
|
::free(RR->rtmem);
|
||||||
|
@ -309,7 +303,6 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
||||||
(*network)->doPeriodicTasks(tptr,now);
|
(*network)->doPeriodicTasks(tptr,now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RR->t->updateMemoizedSettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) {
|
if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) {
|
||||||
|
@ -333,7 +326,6 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
||||||
|
|
||||||
RR->topology->doPeriodicTasks(now);
|
RR->topology->doPeriodicTasks(now);
|
||||||
RR->sa->clean(now);
|
RR->sa->clean(now);
|
||||||
RR->mc->clean(now);
|
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
169
node/Packet.hpp
169
node/Packet.hpp
|
@ -545,13 +545,15 @@ public:
|
||||||
* 0x7 - (reserved for future use)
|
* 0x7 - (reserved for future use)
|
||||||
*
|
*
|
||||||
* An extended frame carries full MAC addressing, making it a
|
* An extended frame carries full MAC addressing, making it a
|
||||||
* superset of VERB_FRAME. It is used for bridged traffic,
|
* superset of VERB_FRAME. If 0x20 is set then p2p or hub and
|
||||||
* redirected or observed traffic via rules, and can in theory
|
* spoke multicast propagation is requested.
|
||||||
* be used for multicast though MULTICAST_FRAME exists for that
|
|
||||||
* purpose and has additional options and capabilities.
|
|
||||||
*
|
*
|
||||||
* OK payload (if ACK flag is set):
|
* OK payload (if ACK flag is set):
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
|
* <[1] flags>
|
||||||
|
* <[6] destination MAC or all zero for destination node>
|
||||||
|
* <[6] source MAC or all zero for node of origin>
|
||||||
|
* <[2] 16-bit ethertype>
|
||||||
*/
|
*/
|
||||||
VERB_EXT_FRAME = 0x07,
|
VERB_EXT_FRAME = 0x07,
|
||||||
|
|
||||||
|
@ -566,7 +568,7 @@ public:
|
||||||
VERB_ECHO = 0x08,
|
VERB_ECHO = 0x08,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Announce interest in multicast group(s):
|
* Announce interest in multicast group(s) (DEPRECATED):
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
* <[6] multicast Ethernet address>
|
* <[6] multicast Ethernet address>
|
||||||
* <[4] multicast additional distinguishing information (ADI)>
|
* <[4] multicast additional distinguishing information (ADI)>
|
||||||
|
@ -680,108 +682,19 @@ public:
|
||||||
*/
|
*/
|
||||||
VERB_NETWORK_CONFIG = 0x0c,
|
VERB_NETWORK_CONFIG = 0x0c,
|
||||||
|
|
||||||
/**
|
|
||||||
* Request endpoints for multicast distribution:
|
|
||||||
* <[8] 64-bit network ID>
|
|
||||||
* <[1] flags (unused, must be 0)>
|
|
||||||
* <[6] MAC address of multicast group being queried>
|
|
||||||
* <[4] 32-bit ADI for multicast group being queried>
|
|
||||||
* <[4] 32-bit requested max number of multicast peers>
|
|
||||||
*
|
|
||||||
* More than one OK response can occur if the response is broken up across
|
|
||||||
* multiple packets or if querying a clustered node.
|
|
||||||
*
|
|
||||||
* OK response payload:
|
|
||||||
* <[8] 64-bit network ID>
|
|
||||||
* <[6] MAC address of multicast group being queried>
|
|
||||||
* <[4] 32-bit ADI for multicast group being queried>
|
|
||||||
* [begin gather results -- these same fields can be in OK(MULTICAST_FRAME)]
|
|
||||||
* <[4] 32-bit total number of known members in this multicast group>
|
|
||||||
* <[2] 16-bit number of members enumerated in this packet>
|
|
||||||
* <[...] series of 5-byte ZeroTier addresses of enumerated members>
|
|
||||||
*
|
|
||||||
* ERROR is not generated; queries that return no response are dropped.
|
|
||||||
*/
|
|
||||||
VERB_MULTICAST_GATHER = 0x0d,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multicast frame:
|
|
||||||
* <[8] 64-bit network ID>
|
|
||||||
* <[1] flags>
|
|
||||||
* [<[...] network certificate of membership (DEPRECATED)>]
|
|
||||||
* [<[4] 32-bit implicit gather limit (DEPRECATED)>]
|
|
||||||
* [<[5] ZeroTier address of originating sender (including w/0x08)>]
|
|
||||||
* [<[2] 16-bit bloom filter multiplier>]
|
|
||||||
* [<[2] 16-bit length of propagation bloom filter in bytes]
|
|
||||||
* [<[...] propagation bloom filter>]
|
|
||||||
* [<[6] source MAC>]
|
|
||||||
* <[6] destination MAC (multicast address)>
|
|
||||||
* <[4] 32-bit multicast ADI (multicast address extension)>
|
|
||||||
* <[2] 16-bit ethertype>
|
|
||||||
* <[...] ethernet payload>
|
|
||||||
* [<[2] 16-bit length of signature>]
|
|
||||||
* [<[...] signature (algorithm depends on sender identity)>]
|
|
||||||
*
|
|
||||||
* Flags:
|
|
||||||
* 0x01 - Network certificate of membership attached (DEPRECATED)
|
|
||||||
* 0x02 - Implicit gather limit field is present (DEPRECATED)
|
|
||||||
* 0x04 - Source MAC is specified -- otherwise it's computed from sender
|
|
||||||
* 0x08 - Propagation bloom filter is included
|
|
||||||
* 0x10 - Signature by sending identity is included
|
|
||||||
*
|
|
||||||
* Version 1.x only supports sender-side replication. Version 2.x also
|
|
||||||
* supports peer to peer and hub and spoke models. For that there is
|
|
||||||
* a new field: a bloom filter that tracks recipients by ZeroTier address.
|
|
||||||
*
|
|
||||||
* Bits in the bloom filter are set by multiplying the address by the
|
|
||||||
* indicated multiplier and then taking that modulo the number of bits
|
|
||||||
* in the filter. Both the length of the filter and this multiplier are
|
|
||||||
* variable and can be selected based on the sender's knowledge of
|
|
||||||
* the total recipient set to minimize the chance of collision, as a
|
|
||||||
* collision would result in a multicast not reaching one particular
|
|
||||||
* recipient. The algorithm for selecting these is not defined by the
|
|
||||||
* protocol.
|
|
||||||
*
|
|
||||||
* The ZeroTier address of the originating sender is also included
|
|
||||||
* before the bloom filter if flag bit 0x08 is set.
|
|
||||||
*
|
|
||||||
* Version 2.x also supports an optional signature of the packet's
|
|
||||||
* payload by the sending ZeroTier node. This can be used to validate
|
|
||||||
* multicasts propagated cooperatively, since unlike sender side
|
|
||||||
* replication the message MAC alone cannot be used for this. This
|
|
||||||
* imposes a non-trivial CPU cost on the sender and so it's optional.
|
|
||||||
* Note that the bloom filter itself is not included in the signature
|
|
||||||
* because it can be changed in transit.
|
|
||||||
*
|
|
||||||
* OK is not sent.
|
|
||||||
*
|
|
||||||
* ERROR_MULTICAST_STFU is generated if a recipient no longer wishes to
|
|
||||||
* receive these multicasts. It's essentially a source quench. Its
|
|
||||||
* payload is:
|
|
||||||
*
|
|
||||||
* ERROR response payload:
|
|
||||||
* <[8] 64-bit network ID>
|
|
||||||
* <[6] multicast group MAC>
|
|
||||||
* <[4] 32-bit multicast group ADI>
|
|
||||||
*/
|
|
||||||
VERB_MULTICAST_FRAME = 0x0e,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push of potential endpoints for direct communication:
|
* Push of potential endpoints for direct communication:
|
||||||
* <[2] 16-bit number of paths>
|
* <[2] 16-bit number of paths>
|
||||||
* <[...] paths>
|
* <[...] paths>
|
||||||
*
|
*
|
||||||
* Path record format:
|
* Path record format:
|
||||||
* <[1] 8-bit path flags>
|
* <[1] 8-bit path flags (always 0, currently unused)>
|
||||||
* <[2] length of extended path characteristics or 0 for none>
|
* <[2] length of extended path characteristics or 0 for none>
|
||||||
* <[...] extended path characteristics>
|
* <[...] extended path characteristics>
|
||||||
* <[1] address type>
|
* <[1] address type>
|
||||||
* <[1] address length in bytes>
|
* <[1] address length in bytes>
|
||||||
* <[...] address>
|
* <[...] address>
|
||||||
*
|
*
|
||||||
* Path record flags:
|
|
||||||
* 0x01 - Forget this path if currently known (not implemented yet)
|
|
||||||
*
|
|
||||||
* The receiver may, upon receiving a push, attempt to establish a
|
* The receiver may, upon receiving a push, attempt to establish a
|
||||||
* direct link to one or more of the indicated addresses. It is the
|
* direct link to one or more of the indicated addresses. It is the
|
||||||
* responsibility of the sender to limit which peers it pushes direct
|
* responsibility of the sender to limit which peers it pushes direct
|
||||||
|
@ -911,37 +824,40 @@ public:
|
||||||
VERB_WILL_RELAY = 0x17,
|
VERB_WILL_RELAY = 0x17,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A push of one or more ephemeral key pairs:
|
* Multicast frame (since 2.x, 0x0e is deprecated multicast frame):
|
||||||
* <[1] 8-bit length of random padding>
|
* <[1] 8-bit propagation depth or 0xff to not propagate>
|
||||||
* <[...] random padding>
|
* <[1] 8-bit flags>
|
||||||
* <[1] 8-bit number of keys in message>
|
* <[8] 64-bit timestamp>
|
||||||
* [... begin keys ...]
|
* <[5] 40-bit address of sending member>
|
||||||
* <[1] 8-bit key type>
|
* <[8] 64-bit network ID>
|
||||||
* <[...] public key (length determined by type)>
|
* <[6] MAC address of multicast group>
|
||||||
* [<[...] additional keys ...>]
|
* <[4] 32-bit ADI of multicast group>
|
||||||
* [... end keys ...]
|
* <[6] 48-bit source MAC of packet or all 0 if from sender>
|
||||||
*
|
* <[2] 16-bit ethertype>
|
||||||
* This verb is used to push ephemeral keys. A node replies to each
|
* <[2] 16-bit length of payload>
|
||||||
* ephemeral key push with an OK message containing its own current
|
* <[...] ethernet payload>
|
||||||
* ephemeral keys that it wants to use for p2p communication.
|
* <[2] 16-bit length of signature or 0 if not present>
|
||||||
*
|
* <[...] signature of fields after propagation depth>
|
||||||
* These are ephemeral public keys. Currently keys of type C25519
|
|
||||||
* and P-384 are supported and both will be pushed.
|
|
||||||
*
|
|
||||||
* If more than one key is pushed, key agreement is performed using
|
|
||||||
* all keys for which both peers pushed the same key type. The raw
|
|
||||||
* results of these keys are then hashed together in order of key
|
|
||||||
* type ID with SHA384 to yield a session key. If the desired session
|
|
||||||
* key is shorter than 384 bits the first N bits are used.
|
|
||||||
*
|
|
||||||
* The random padding component can be used to ranomize the length
|
|
||||||
* of these packets so adversaries can't easily selectively block
|
|
||||||
* ephemeral key exchange by exploiting a fixed packet length.
|
|
||||||
*
|
|
||||||
* OK response payload:
|
|
||||||
* <[...] responder's keys, same format as verb payload>
|
|
||||||
*/
|
*/
|
||||||
VERB_EPHEMERAL_KEY = 0x18
|
VERB_MULTICAST = 0x18,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multicast subscription/unsubscription request:
|
||||||
|
* <[1] 8-bit propagation depth of 0xff to not propagate>
|
||||||
|
* <[1] 8-bit flags>
|
||||||
|
* <[8] 64-bit timestamp>
|
||||||
|
* <[5] 40-bit address of subscribing/unsubscribing member>
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[2] 16-bit number of multicast group IDs to subscribe>
|
||||||
|
* <[...] series of 32-bit multicast group IDs>
|
||||||
|
* <[2] 16-bit number of multicast group IDs to unsubscribe>
|
||||||
|
* <[...] series of 32-bit multicast group IDs>
|
||||||
|
* <[2] 16-bit length of signature or 0 if not present>
|
||||||
|
* <[...] signature of fields after propagation depth>
|
||||||
|
*/
|
||||||
|
VERB_MULTICAST_SUBSCRIBE = 0x19,
|
||||||
|
|
||||||
|
// protocol max: 0x1f
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -973,9 +889,6 @@ public:
|
||||||
/* Tried to join network, but you're not a member */
|
/* Tried to join network, but you're not a member */
|
||||||
ERROR_NETWORK_ACCESS_DENIED_ = 0x07, /* extra _ at end to avoid Windows name conflict */
|
ERROR_NETWORK_ACCESS_DENIED_ = 0x07, /* extra _ at end to avoid Windows name conflict */
|
||||||
|
|
||||||
/* Multicasts to this group are not wanted */
|
|
||||||
ERROR_MULTICAST_STFU = 0x08,
|
|
||||||
|
|
||||||
/* Cannot deliver a forwarded ZeroTier packet (e.g. hops exceeded, no routes) */
|
/* Cannot deliver a forwarded ZeroTier packet (e.g. hops exceeded, no routes) */
|
||||||
/* Payload: <packet ID>, <destination>, <... additional packet ID / destinations> */
|
/* Payload: <packet ID>, <destination>, <... additional packet ID / destinations> */
|
||||||
ERROR_CANNOT_DELIVER = 0x09
|
ERROR_CANNOT_DELIVER = 0x09
|
||||||
|
|
|
@ -26,7 +26,6 @@ class NodeConfig;
|
||||||
class Switch;
|
class Switch;
|
||||||
class Topology;
|
class Topology;
|
||||||
class Node;
|
class Node;
|
||||||
class Multicaster;
|
|
||||||
class NetworkController;
|
class NetworkController;
|
||||||
class SelfAwareness;
|
class SelfAwareness;
|
||||||
class Trace;
|
class Trace;
|
||||||
|
@ -42,7 +41,6 @@ public:
|
||||||
,localNetworkController((NetworkController *)0)
|
,localNetworkController((NetworkController *)0)
|
||||||
,rtmem((void *)0)
|
,rtmem((void *)0)
|
||||||
,sw((Switch *)0)
|
,sw((Switch *)0)
|
||||||
,mc((Multicaster *)0)
|
|
||||||
,topology((Topology *)0)
|
,topology((Topology *)0)
|
||||||
,sa((SelfAwareness *)0)
|
,sa((SelfAwareness *)0)
|
||||||
{
|
{
|
||||||
|
@ -69,7 +67,6 @@ public:
|
||||||
|
|
||||||
Trace *t;
|
Trace *t;
|
||||||
Switch *sw;
|
Switch *sw;
|
||||||
Multicaster *mc;
|
|
||||||
Topology *topology;
|
Topology *topology;
|
||||||
SelfAwareness *sa;
|
SelfAwareness *sa;
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <CommonCrypto/CommonDigest.h>
|
#include <CommonCrypto/CommonDigest.h>
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
#ifdef ZT_USE_LIBCRYPTO
|
#ifdef ZT_USE_LIBCRYPTO
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ZT_SHA512_DIGEST_LEN 64
|
#define ZT_SHA512_DIGEST_LEN 64
|
||||||
#define ZT_SHA384_DIGEST_LEN 48
|
#define ZT_SHA384_DIGEST_LEN 48
|
||||||
|
@ -66,6 +66,7 @@ static ZT_ALWAYS_INLINE void SHA384(void *digest,const void *data0,unsigned int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZT_HAVE_NATIVE_SHA512
|
||||||
#ifdef ZT_USE_LIBCRYPTO
|
#ifdef ZT_USE_LIBCRYPTO
|
||||||
#define ZT_HAVE_NATIVE_SHA512 1
|
#define ZT_HAVE_NATIVE_SHA512 1
|
||||||
static ZT_ALWAYS_INLINE void SHA512(void *digest,const void *data,unsigned int len)
|
static ZT_ALWAYS_INLINE void SHA512(void *digest,const void *data,unsigned int len)
|
||||||
|
@ -91,6 +92,7 @@ static ZT_ALWAYS_INLINE void SHA384(void *digest,const void *data0,unsigned int
|
||||||
SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
|
SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef ZT_HAVE_NATIVE_SHA512
|
#ifndef ZT_HAVE_NATIVE_SHA512
|
||||||
void SHA512(void *digest,const void *data,unsigned int len);
|
void SHA512(void *digest,const void *data,unsigned int len);
|
||||||
|
|
|
@ -410,23 +410,6 @@ void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Trace::updateMemoizedSettings()
|
|
||||||
{
|
|
||||||
const std::vector< SharedPtr<Network> > nws(RR->node->allNetworks());
|
|
||||||
{
|
|
||||||
Mutex::Lock l(_byNet_m);
|
|
||||||
_byNet.clear();
|
|
||||||
for(std::vector< SharedPtr<Network> >::const_iterator n(nws.begin());n!=nws.end();++n) {
|
|
||||||
const Address dest((*n)->config().remoteTraceTarget);
|
|
||||||
if (dest) {
|
|
||||||
std::pair<Address,Trace::Level> &m = _byNet[(*n)->id()];
|
|
||||||
m.first = dest;
|
|
||||||
m.second = (*n)->config().remoteTraceLevel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Trace::_send(void *const tPtr,const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> &d,const Address &dest)
|
void Trace::_send(void *const tPtr,const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> &d,const Address &dest)
|
||||||
{
|
{
|
||||||
Packet outp(dest,RR->identity.address(),Packet::VERB_REMOTE_TRACE);
|
Packet outp(dest,RR->identity.address(),Packet::VERB_REMOTE_TRACE);
|
||||||
|
|
|
@ -138,8 +138,6 @@ public:
|
||||||
void credentialRejected(void *const tPtr,const Tag &c,const char *reason);
|
void credentialRejected(void *const tPtr,const Tag &c,const char *reason);
|
||||||
void credentialRejected(void *const tPtr,const Revocation &c,const char *reason);
|
void credentialRejected(void *const tPtr,const Revocation &c,const char *reason);
|
||||||
|
|
||||||
void updateMemoizedSettings();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const RuntimeEnvironment *const RR;
|
const RuntimeEnvironment *const RR;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue