mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
Bunch of work on pushing and replication of tags and capabilities, and protocol cleanup.
This commit is contained in:
parent
67cb03742e
commit
7e6e56e2bc
14 changed files with 409 additions and 464 deletions
|
@ -96,11 +96,6 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define ZT_MAX_NETWORK_SPECIALISTS 256
|
#define ZT_MAX_NETWORK_SPECIALISTS 256
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of static physical to ZeroTier address mappings (typically relays, etc.)
|
|
||||||
*/
|
|
||||||
#define ZT_MAX_NETWORK_PINNED 16
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of multicast group subscriptions per network
|
* Maximum number of multicast group subscriptions per network
|
||||||
*/
|
*/
|
||||||
|
@ -111,6 +106,16 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define ZT_MAX_NETWORK_RULES 256
|
#define ZT_MAX_NETWORK_RULES 256
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of per-node capabilities per network
|
||||||
|
*/
|
||||||
|
#define ZT_MAX_NETWORK_CAPABILITIES 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of per-node tags per network
|
||||||
|
*/
|
||||||
|
#define ZT_MAX_NETWORK_TAGS 16
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of direct network paths to a given peer
|
* Maximum number of direct network paths to a given peer
|
||||||
*/
|
*/
|
||||||
|
@ -126,11 +131,6 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define ZT_MAX_CAPABILITY_RULES 64
|
#define ZT_MAX_CAPABILITY_RULES 64
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum length of a capbility's short descriptive name
|
|
||||||
*/
|
|
||||||
#define ZT_MAX_CAPABILITY_NAME_LENGTH 63
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global maximum length for capability chain of custody (including initial issue)
|
* Global maximum length for capability chain of custody (including initial issue)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -109,6 +109,11 @@ public:
|
||||||
*/
|
*/
|
||||||
inline uint64_t networkId() const { return _nwid; }
|
inline uint64_t networkId() const { return _nwid; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Expiration time relative to network config timestamp
|
||||||
|
*/
|
||||||
|
inline uint64_t expiration() const { return _expiration; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign this capability and add signature to its chain of custody
|
* Sign this capability and add signature to its chain of custody
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,15 +19,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "RuntimeEnvironment.hpp"
|
|
||||||
#include "Address.hpp"
|
|
||||||
#include "MAC.hpp"
|
|
||||||
#include "InetAddress.hpp"
|
|
||||||
#include "Filter.hpp"
|
#include "Filter.hpp"
|
||||||
#include "Packet.hpp"
|
#include "InetAddress.hpp"
|
||||||
#include "Switch.hpp"
|
|
||||||
#include "Topology.hpp"
|
|
||||||
#include "Node.hpp"
|
|
||||||
|
|
||||||
// Returns true if packet appears valid; pos and proto will be set
|
// Returns true if packet appears valid; pos and proto will be set
|
||||||
static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto)
|
static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsigned int &pos,unsigned int &proto)
|
||||||
|
@ -61,8 +54,8 @@ static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsig
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
bool Filter::run(
|
bool Filter::run(
|
||||||
const RuntimeEnvironment *RR,
|
|
||||||
const uint64_t nwid,
|
const uint64_t nwid,
|
||||||
|
const bool receiving,
|
||||||
const Address &ztSource,
|
const Address &ztSource,
|
||||||
const Address &ztDest,
|
const Address &ztDest,
|
||||||
const MAC &macSource,
|
const MAC &macSource,
|
||||||
|
@ -72,8 +65,13 @@ bool Filter::run(
|
||||||
const unsigned int etherType,
|
const unsigned int etherType,
|
||||||
const unsigned int vlanId,
|
const unsigned int vlanId,
|
||||||
const ZT_VirtualNetworkRule *rules,
|
const ZT_VirtualNetworkRule *rules,
|
||||||
const unsigned int ruleCount)
|
const unsigned int ruleCount,
|
||||||
|
const Tag *tags,
|
||||||
|
const unsigned int tagCount,
|
||||||
|
Address &sendCopyOfPacketTo)
|
||||||
{
|
{
|
||||||
|
sendCopyOfPacketTo.zero();
|
||||||
|
|
||||||
// For each set of rules we start by assuming that they match (since no constraints
|
// For each set of rules we start by assuming that they match (since no constraints
|
||||||
// yields a 'match all' rule).
|
// yields a 'match all' rule).
|
||||||
uint8_t thisSetMatches = 1;
|
uint8_t thisSetMatches = 1;
|
||||||
|
@ -92,6 +90,8 @@ bool Filter::run(
|
||||||
// This set did match, so perform action!
|
// This set did match, so perform action!
|
||||||
if (rt != ZT_NETWORK_RULE_ACTION_DROP) {
|
if (rt != ZT_NETWORK_RULE_ACTION_DROP) {
|
||||||
if ((rt == ZT_NETWORK_RULE_ACTION_TEE)||(rt == ZT_NETWORK_RULE_ACTION_REDIRECT)) {
|
if ((rt == ZT_NETWORK_RULE_ACTION_TEE)||(rt == ZT_NETWORK_RULE_ACTION_REDIRECT)) {
|
||||||
|
sendCopyOfPacketTo = rules[rn].v.zt;
|
||||||
|
/*
|
||||||
// Tee and redirect both want this frame copied to somewhere else.
|
// Tee and redirect both want this frame copied to somewhere else.
|
||||||
Packet outp(Address(rules[rn].v.zt),RR->identity.address(),Packet::VERB_EXT_FRAME);
|
Packet outp(Address(rules[rn].v.zt),RR->identity.address(),Packet::VERB_EXT_FRAME);
|
||||||
outp.append(nwid);
|
outp.append(nwid);
|
||||||
|
@ -102,6 +102,7 @@ bool Filter::run(
|
||||||
outp.append(frameData,frameLen);
|
outp.append(frameData,frameLen);
|
||||||
outp.compress();
|
outp.compress();
|
||||||
RR->sw->send(outp,true,nwid);
|
RR->sw->send(outp,true,nwid);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
// For REDIRECT we will want to DROP at this node. For TEE we ACCEPT at this node but
|
// For REDIRECT we will want to DROP at this node. For TEE we ACCEPT at this node but
|
||||||
// also forward it along as we just did.
|
// also forward it along as we just did.
|
||||||
|
@ -244,9 +245,20 @@ bool Filter::run(
|
||||||
thisRuleMatches = (uint8_t)((frameLen >= (unsigned int)rules[rn].v.frameSize[0])&&(frameLen <= (unsigned int)rules[rn].v.frameSize[1]));
|
thisRuleMatches = (uint8_t)((frameLen >= (unsigned int)rules[rn].v.frameSize[0])&&(frameLen <= (unsigned int)rules[rn].v.frameSize[1]));
|
||||||
break;
|
break;
|
||||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE:
|
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE:
|
||||||
break;
|
|
||||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL:
|
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL:
|
||||||
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY:
|
case ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY:
|
||||||
|
for(unsigned int i=0;i<tagCount;++i) { // sequential scan is probably fastest since this is going to be <64 entries (usually only one or two)
|
||||||
|
if (tags[i].id() == rules[rn].v.tag.id) {
|
||||||
|
if (rt == ZT_NETWORK_RULE_MATCH_TAG_VALUE_RANGE) {
|
||||||
|
thisRuleMatches = (uint8_t)((tags[i].value() >= rules[rn].v.tag.value[0])&&(tags[i].value() <= rules[rn].v.tag.value[1]));
|
||||||
|
} else if (rt == ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ALL) {
|
||||||
|
thisRuleMatches = (uint8_t)((tags[i].value() & rules[rn].v.tag.value[0]) == rules[rn].v.tag.value[0]);
|
||||||
|
} else if (rt == ZT_NETWORK_RULE_MATCH_TAG_VALUE_BITS_ANY) {
|
||||||
|
thisRuleMatches = (uint8_t)((tags[i].value() & rules[rn].v.tag.value[0]) != 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,15 +21,16 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "../include/ZeroTierOne.h"
|
#include "../include/ZeroTierOne.h"
|
||||||
|
#include "Address.hpp"
|
||||||
|
#include "MAC.hpp"
|
||||||
|
#include "Tag.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class Address;
|
|
||||||
class RuntimeEnvironment;
|
|
||||||
class MAC;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network packet filter for rules engine
|
* Network packet filter for rules engine
|
||||||
*/
|
*/
|
||||||
|
@ -42,8 +43,8 @@ public:
|
||||||
* This returns whether or not the packet should be accepted and may also
|
* This returns whether or not the packet should be accepted and may also
|
||||||
* take other actions for e.g. the TEE and REDIRECT targets.
|
* take other actions for e.g. the TEE and REDIRECT targets.
|
||||||
*
|
*
|
||||||
* @param RR ZeroTier runtime environment (context)
|
|
||||||
* @param nwid ZeroTier network ID
|
* @param nwid ZeroTier network ID
|
||||||
|
* @param receiving True if on receiving side, false on sending side
|
||||||
* @param ztSource Source ZeroTier address
|
* @param ztSource Source ZeroTier address
|
||||||
* @param ztDest Destination ZeroTier address
|
* @param ztDest Destination ZeroTier address
|
||||||
* @param macSource Ethernet layer source address
|
* @param macSource Ethernet layer source address
|
||||||
|
@ -54,10 +55,14 @@ public:
|
||||||
* @param vlanId 16-bit VLAN ID
|
* @param vlanId 16-bit VLAN ID
|
||||||
* @param rules Pointer to array of rules
|
* @param rules Pointer to array of rules
|
||||||
* @param ruleCount Number of rules
|
* @param ruleCount Number of rules
|
||||||
|
* @param tags Tags associated with this node on this network
|
||||||
|
* @param tagCount Number of tags
|
||||||
|
* @param sendCopyOfPacketTo Result parameter: if non-NULL send a copy of this packet to another node
|
||||||
|
* @return True if packet should be accepted for send or receive
|
||||||
*/
|
*/
|
||||||
static bool run(
|
static bool run(
|
||||||
const RuntimeEnvironment *RR,
|
|
||||||
const uint64_t nwid,
|
const uint64_t nwid,
|
||||||
|
const bool receiving,
|
||||||
const Address &ztSource,
|
const Address &ztSource,
|
||||||
const Address &ztDest,
|
const Address &ztDest,
|
||||||
const MAC &macSource,
|
const MAC &macSource,
|
||||||
|
@ -67,7 +72,10 @@ public:
|
||||||
const unsigned int etherType,
|
const unsigned int etherType,
|
||||||
const unsigned int vlanId,
|
const unsigned int vlanId,
|
||||||
const ZT_VirtualNetworkRule *rules,
|
const ZT_VirtualNetworkRule *rules,
|
||||||
const unsigned int ruleCount);
|
const unsigned int ruleCount,
|
||||||
|
const Tag *tags,
|
||||||
|
const unsigned int tagCount,
|
||||||
|
Address &sendCopyOfPacketTo);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -38,6 +38,9 @@
|
||||||
#include "Node.hpp"
|
#include "Node.hpp"
|
||||||
#include "DeferredPackets.hpp"
|
#include "DeferredPackets.hpp"
|
||||||
#include "Filter.hpp"
|
#include "Filter.hpp"
|
||||||
|
#include "CertificateOfMembership.hpp"
|
||||||
|
#include "Capability.hpp"
|
||||||
|
#include "Tag.hpp"
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
@ -106,7 +109,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,bool deferred)
|
||||||
case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,peer);
|
case Packet::VERB_EXT_FRAME: return _doEXT_FRAME(RR,peer);
|
||||||
case Packet::VERB_ECHO: return _doECHO(RR,peer);
|
case Packet::VERB_ECHO: return _doECHO(RR,peer);
|
||||||
case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,peer);
|
case Packet::VERB_MULTICAST_LIKE: return _doMULTICAST_LIKE(RR,peer);
|
||||||
case Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE: return _doNETWORK_MEMBERSHIP_CERTIFICATE(RR,peer);
|
case Packet::VERB_NETWORK_CREDENTIALS: return _doNETWORK_CREDENTIALS(RR,peer);
|
||||||
case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,peer);
|
case Packet::VERB_NETWORK_CONFIG_REQUEST: return _doNETWORK_CONFIG_REQUEST(RR,peer);
|
||||||
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,peer);
|
case Packet::VERB_MULTICAST_GATHER: return _doMULTICAST_GATHER(RR,peer);
|
||||||
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,peer);
|
case Packet::VERB_MULTICAST_FRAME: return _doMULTICAST_FRAME(RR,peer);
|
||||||
|
@ -155,22 +158,10 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Packet::ERROR_IDENTITY_COLLISION:
|
case Packet::ERROR_IDENTITY_COLLISION:
|
||||||
if (RR->topology->isRoot(peer->identity()))
|
if (RR->topology->isUpstream(peer->identity()))
|
||||||
RR->node->postEvent(ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION);
|
RR->node->postEvent(ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: {
|
|
||||||
/* Note: certificates are public so it's safe to push them to anyone
|
|
||||||
* who asks. */
|
|
||||||
SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
|
|
||||||
if ((network)&&(network->hasConfig())&&(network->config().com)) {
|
|
||||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
|
|
||||||
network->config().com.serialize(outp);
|
|
||||||
outp.armor(peer->key(),true);
|
|
||||||
RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case Packet::ERROR_NETWORK_ACCESS_DENIED_: {
|
case Packet::ERROR_NETWORK_ACCESS_DENIED_: {
|
||||||
SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
|
SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)));
|
||||||
if ((network)&&(network->controller() == peer->address()))
|
if ((network)&&(network->controller() == peer->address()))
|
||||||
|
@ -218,9 +209,13 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,SharedPtr<Peer> &peer
|
||||||
uint64_t worldTimestamp = 0;
|
uint64_t worldTimestamp = 0;
|
||||||
{
|
{
|
||||||
unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
|
unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
|
||||||
if (ptr < size()) // ZeroTier One < 1.0.3 did not include physical destination address info
|
|
||||||
|
// Get external surface address if present (was not in old versions)
|
||||||
|
if (ptr < size())
|
||||||
ptr += externalSurfaceAddress.deserialize(*this,ptr);
|
ptr += externalSurfaceAddress.deserialize(*this,ptr);
|
||||||
if ((ptr + 16) <= size()) { // older versions also did not include World IDs or timestamps
|
|
||||||
|
// Get world ID and world timestamp if present (was not in old versions)
|
||||||
|
if ((ptr + 16) <= size()) {
|
||||||
worldId = at<uint64_t>(ptr); ptr += 8;
|
worldId = at<uint64_t>(ptr); ptr += 8;
|
||||||
worldTimestamp = at<uint64_t>(ptr);
|
worldTimestamp = at<uint64_t>(ptr);
|
||||||
}
|
}
|
||||||
|
@ -295,7 +290,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,SharedPtr<Peer> &peer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (externalSurfaceAddress)
|
if (externalSurfaceAddress)
|
||||||
RR->sa->iam(id.address(),_localAddress,_remoteAddress,externalSurfaceAddress,RR->topology->isRoot(id),RR->node->now());
|
RR->sa->iam(id.address(),_localAddress,_remoteAddress,externalSurfaceAddress,RR->topology->isUpstream(id),RR->node->now());
|
||||||
|
|
||||||
Packet outp(id.address(),RR->identity.address(),Packet::VERB_OK);
|
Packet outp(id.address(),RR->identity.address(),Packet::VERB_OK);
|
||||||
outp.append((unsigned char)Packet::VERB_HELLO);
|
outp.append((unsigned char)Packet::VERB_HELLO);
|
||||||
|
@ -379,13 +374,15 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool trusted = RR->topology->isRoot(peer->identity());
|
|
||||||
|
|
||||||
InetAddress externalSurfaceAddress;
|
InetAddress externalSurfaceAddress;
|
||||||
unsigned int ptr = ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2;
|
unsigned int ptr = ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2;
|
||||||
if (ptr < size()) // ZeroTier One < 1.0.3 did not include this field
|
|
||||||
|
// Get reported external surface address if present (was not on old versions)
|
||||||
|
if (ptr < size())
|
||||||
ptr += externalSurfaceAddress.deserialize(*this,ptr);
|
ptr += externalSurfaceAddress.deserialize(*this,ptr);
|
||||||
if ((trusted)&&((ptr + 2) <= size())) { // older versions also did not include this field, and right now we only use if from a root
|
|
||||||
|
// Handle world updates from root servers if present (was not on old versions)
|
||||||
|
if (((ptr + 2) <= size())&&(RR->topology->isRoot(peer->identity()))) {
|
||||||
World worldUpdate;
|
World worldUpdate;
|
||||||
const unsigned int worldLen = at<uint16_t>(ptr); ptr += 2;
|
const unsigned int worldLen = at<uint16_t>(ptr); ptr += 2;
|
||||||
if (worldLen > 0) {
|
if (worldLen > 0) {
|
||||||
|
@ -401,17 +398,13 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
|
||||||
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
|
peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision);
|
||||||
|
|
||||||
if (externalSurfaceAddress)
|
if (externalSurfaceAddress)
|
||||||
RR->sa->iam(peer->address(),_localAddress,_remoteAddress,externalSurfaceAddress,trusted,RR->node->now());
|
RR->sa->iam(peer->address(),_localAddress,_remoteAddress,externalSurfaceAddress,RR->topology->isUpstream(peer->identity()),RR->node->now());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Packet::VERB_WHOIS: {
|
case Packet::VERB_WHOIS: {
|
||||||
if (RR->topology->isRoot(peer->identity())) {
|
if (RR->topology->isUpstream(peer->identity())) {
|
||||||
const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY);
|
const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY);
|
||||||
// Right now we can skip this since OK(WHOIS) is only accepted from
|
RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr<Peer>(new Peer(RR,RR->identity,id))));
|
||||||
// roots. In the future it should be done if we query less trusted
|
|
||||||
// sources.
|
|
||||||
//if (id.locallyValidate())
|
|
||||||
RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr<Peer>(new Peer(RR,RR->identity,id))));
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -544,7 +537,6 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer>
|
||||||
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
|
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
|
||||||
if (!network->isAllowed(peer)) {
|
if (!network->isAllowed(peer)) {
|
||||||
TRACE("dropped FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)network->id());
|
TRACE("dropped FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)network->id());
|
||||||
_sendErrorNeedCertificate(RR,peer,network->id());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +591,6 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
|
||||||
|
|
||||||
if (!network->isAllowed(peer)) {
|
if (!network->isAllowed(peer)) {
|
||||||
TRACE("dropped EXT_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),network->id());
|
TRACE("dropped EXT_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),network->id());
|
||||||
_sendErrorNeedCertificate(RR,peer,network->id());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,20 +695,34 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IncomingPacket::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
|
bool IncomingPacket::_doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
CertificateOfMembership com;
|
CertificateOfMembership com;
|
||||||
|
Capability cap;
|
||||||
|
Tag tag;
|
||||||
|
|
||||||
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD;
|
unsigned int p = ZT_PACKET_IDX_PAYLOAD;
|
||||||
while (ptr < size()) {
|
while ((p < size())&&((*this)[p])) {
|
||||||
ptr += com.deserialize(*this,ptr);
|
p += com.deserialize(*this,p);
|
||||||
peer->validateAndSetNetworkMembershipCertificate(com.networkId(),com);
|
peer->validateAndSetNetworkMembershipCertificate(com.networkId(),com);
|
||||||
}
|
}
|
||||||
|
++p; // skip trailing 0 after COMs if present
|
||||||
|
|
||||||
peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP);
|
if (p < size()) { // check if new capabilities and tags fields are present
|
||||||
|
const unsigned int numCapabilities = at<uint16_t>(p); p += 2;
|
||||||
|
for(unsigned int i=0;i<numCapabilities;++i) {
|
||||||
|
p += cap.deserialize(*this,p);
|
||||||
|
}
|
||||||
|
const unsigned int numTags = at<uint16_t>(p); p += 2;
|
||||||
|
for(unsigned int i=0;i<numTags;++i) {
|
||||||
|
p += tag.deserialize(*this,p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CREDENTIALS,0,Packet::VERB_NOP);
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped NETWORK_MEMBERSHIP_CERTIFICATE from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str());
|
TRACE("dropped NETWORK_CREDENTIALS from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -859,7 +864,6 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
|
||||||
// that cert might be what we needed.
|
// that cert might be what we needed.
|
||||||
if (!network->isAllowed(peer)) {
|
if (!network->isAllowed(peer)) {
|
||||||
TRACE("dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)network->id());
|
TRACE("dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)network->id());
|
||||||
_sendErrorNeedCertificate(RR,peer,network->id());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1069,22 +1073,8 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
|
||||||
// into the one we send along to next hops.
|
// into the one we send along to next hops.
|
||||||
const unsigned int lengthOfSignedPortionAndSignature = 29 + vlf;
|
const unsigned int lengthOfSignedPortionAndSignature = 29 + vlf;
|
||||||
|
|
||||||
// Get previous hop's credential, if any
|
// Add length of second "additional fields" section.
|
||||||
const unsigned int previousHopCredentialLength = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 29 + vlf);
|
vlf += at<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 29 + vlf);
|
||||||
CertificateOfMembership previousHopCom;
|
|
||||||
if (previousHopCredentialLength >= 1) {
|
|
||||||
switch((*this)[ZT_PACKET_IDX_PAYLOAD + 31 + vlf]) {
|
|
||||||
case 0x01: { // network certificate of membership for previous hop
|
|
||||||
const unsigned int phcl = previousHopCom.deserialize(*this,ZT_PACKET_IDX_PAYLOAD + 32 + vlf);
|
|
||||||
if (phcl != (previousHopCredentialLength - 1)) {
|
|
||||||
TRACE("dropped CIRCUIT_TEST from %s(%s): previous hop COM invalid (%u != %u)",source().toString().c_str(),_remoteAddress.toString().c_str(),phcl,(previousHopCredentialLength - 1));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vlf += previousHopCredentialLength;
|
|
||||||
|
|
||||||
// Check credentials (signature already verified)
|
// Check credentials (signature already verified)
|
||||||
NetworkConfig originatorCredentialNetworkConfig;
|
NetworkConfig originatorCredentialNetworkConfig;
|
||||||
|
@ -1166,13 +1156,7 @@ bool IncomingPacket::_doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPt
|
||||||
if (breadth > 0) {
|
if (breadth > 0) {
|
||||||
Packet outp(Address(),RR->identity.address(),Packet::VERB_CIRCUIT_TEST);
|
Packet outp(Address(),RR->identity.address(),Packet::VERB_CIRCUIT_TEST);
|
||||||
outp.append(field(ZT_PACKET_IDX_PAYLOAD,lengthOfSignedPortionAndSignature),lengthOfSignedPortionAndSignature);
|
outp.append(field(ZT_PACKET_IDX_PAYLOAD,lengthOfSignedPortionAndSignature),lengthOfSignedPortionAndSignature);
|
||||||
const unsigned int previousHopCredentialPos = outp.size();
|
outp.append((uint16_t)0); // no additional fields
|
||||||
outp.append((uint16_t)0); // no previous hop credentials: default
|
|
||||||
if ((originatorCredentialNetworkConfig)&&(!originatorCredentialNetworkConfig.isPublic())&&(originatorCredentialNetworkConfig.com)) {
|
|
||||||
outp.append((uint8_t)0x01); // COM
|
|
||||||
originatorCredentialNetworkConfig.com.serialize(outp);
|
|
||||||
outp.setAt<uint16_t>(previousHopCredentialPos,(uint16_t)(outp.size() - (previousHopCredentialPos + 2)));
|
|
||||||
}
|
|
||||||
if (remainingHopsPtr < size())
|
if (remainingHopsPtr < size())
|
||||||
outp.append(field(remainingHopsPtr,size() - remainingHopsPtr),size() - remainingHopsPtr);
|
outp.append(field(remainingHopsPtr,size() - remainingHopsPtr),size() - remainingHopsPtr);
|
||||||
|
|
||||||
|
@ -1241,7 +1225,7 @@ bool IncomingPacket::_doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const
|
||||||
try {
|
try {
|
||||||
// If this were allowed from anyone, it would itself be a DOS vector. Right
|
// If this were allowed from anyone, it would itself be a DOS vector. Right
|
||||||
// now we only allow it from roots and controllers of networks you have joined.
|
// now we only allow it from roots and controllers of networks you have joined.
|
||||||
bool allowed = RR->topology->isRoot(peer->identity());
|
bool allowed = RR->topology->isUpstream(peer->identity());
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
std::vector< SharedPtr<Network> > allNetworks(RR->node->allNetworks());
|
std::vector< SharedPtr<Network> > allNetworks(RR->node->allNetworks());
|
||||||
for(std::vector< SharedPtr<Network> >::const_iterator n(allNetworks.begin());n!=allNetworks.end();++n) {
|
for(std::vector< SharedPtr<Network> >::const_iterator n(allNetworks.begin());n!=allNetworks.end();++n) {
|
||||||
|
@ -1300,16 +1284,6 @@ bool IncomingPacket::_doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IncomingPacket::_doREQUEST_OBJECT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IncomingPacket::_doOBJECT_UPDATED(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IncomingPacket::computeSalsa2012Sha512ProofOfWork(unsigned int difficulty,const void *challenge,unsigned int challengeLength,unsigned char result[16])
|
void IncomingPacket::computeSalsa2012Sha512ProofOfWork(unsigned int difficulty,const void *challenge,unsigned int challengeLength,unsigned char result[16])
|
||||||
{
|
{
|
||||||
unsigned char salsabuf[131072]; // 131072 == protocol constant, size of memory buffer for this proof of work function
|
unsigned char salsabuf[131072]; // 131072 == protocol constant, size of memory buffer for this proof of work function
|
||||||
|
@ -1388,15 +1362,4 @@ bool IncomingPacket::testSalsa2012Sha512ProofOfWorkResult(unsigned int difficult
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IncomingPacket::_sendErrorNeedCertificate(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,uint64_t nwid)
|
|
||||||
{
|
|
||||||
Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR);
|
|
||||||
outp.append((unsigned char)verb());
|
|
||||||
outp.append(packetId());
|
|
||||||
outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
|
|
||||||
outp.append(nwid);
|
|
||||||
outp.armor(peer->key(),true);
|
|
||||||
RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -172,7 +172,7 @@ private:
|
||||||
bool _doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doECHO(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doECHO(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doMULTICAST_LIKE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doNETWORK_CREDENTIALS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
|
@ -180,11 +180,6 @@ private:
|
||||||
bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
bool _doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
||||||
bool _doREQUEST_OBJECT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
|
||||||
bool _doOBJECT_UPDATED(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
|
|
||||||
|
|
||||||
// Send an ERROR_NEED_MEMBERSHIP_CERTIFICATE to a peer indicating that an updated cert is needed to communicate
|
|
||||||
void _sendErrorNeedCertificate(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,uint64_t nwid);
|
|
||||||
|
|
||||||
uint64_t _receiveTime;
|
uint64_t _receiveTime;
|
||||||
InetAddress _localAddress;
|
InetAddress _localAddress;
|
||||||
|
|
154
node/Membership.hpp
Normal file
154
node/Membership.hpp
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* ZeroTier One - Network Virtualization Everywhere
|
||||||
|
* Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZT_MEMBERSHIP_HPP
|
||||||
|
#define ZT_MEMBERSHIP_HPP
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "Constants.hpp"
|
||||||
|
#include "../include/ZeroTierOne.h"
|
||||||
|
#include "CertificateOfMembership.hpp"
|
||||||
|
#include "Capability.hpp"
|
||||||
|
#include "Tag.hpp"
|
||||||
|
#include "Hashtable.hpp"
|
||||||
|
#include "NetworkConfig.hpp"
|
||||||
|
|
||||||
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
class Peer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information related to a peer's participation on a network
|
||||||
|
*
|
||||||
|
* This structure is not thread-safe and must be locked during use.
|
||||||
|
*/
|
||||||
|
class Membership
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct TState
|
||||||
|
{
|
||||||
|
TState() : lastPushed(0),lastReceived(0) {}
|
||||||
|
// Last time we pushed this tag to this peer
|
||||||
|
uint64_t lastPushed;
|
||||||
|
// Last time we received this tag from this peer
|
||||||
|
uint64_t lastReceived;
|
||||||
|
// Tag from peer
|
||||||
|
Tag tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CState
|
||||||
|
{
|
||||||
|
CState() : lastPushed(0),lastReceived(0) {}
|
||||||
|
// Last time we pushed this capability to this peer
|
||||||
|
uint64_t lastPushed;
|
||||||
|
// Last time we received this capability from this peer
|
||||||
|
uint64_t lastReceived;
|
||||||
|
// Capability from peer
|
||||||
|
Capability cap;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Membership() :
|
||||||
|
_lastPushedCom(0),
|
||||||
|
_com(),
|
||||||
|
_caps(8),
|
||||||
|
_tags(8)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send COM and other credentials to this peer if needed
|
||||||
|
*
|
||||||
|
* This checks last pushed times for our COM and for other credentials and
|
||||||
|
* sends VERB_NETWORK_CREDENTIALS if the recipient might need them.
|
||||||
|
*
|
||||||
|
* @param peer Peer that "owns" this membership
|
||||||
|
* @param nconf Network configuration
|
||||||
|
* @param now Current time
|
||||||
|
* @param capIds Capability IDs that this peer might need
|
||||||
|
* @param capCount Number of capability IDs
|
||||||
|
* @param tagIds Tag IDs that this peer might need
|
||||||
|
* @param tagCount Number of tag IDs
|
||||||
|
*/
|
||||||
|
void sendCredentialsIfNeeded(const Peer &peer,const NetworkConfig &nconf,const uint64_t now,const uint32_t *capIds,const unsigned int capCount,const uint32_t *tagIds,const unsigned int tagCount) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nconf Network configuration
|
||||||
|
* @param id Tag ID
|
||||||
|
* @return Pointer to tag or NULL if not found
|
||||||
|
*/
|
||||||
|
inline const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const
|
||||||
|
{
|
||||||
|
const TState *t = _tags.get(id);
|
||||||
|
return ((t) ? (((t->lastReceived != 0)&&(t->tag.expiration() < nconf.timestamp)) ? &(t->tag) : (const Tag *)0) : (const Tag *)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nconf Network configuration
|
||||||
|
* @param id Capablity ID
|
||||||
|
* @return Pointer to capability or NULL if not found
|
||||||
|
*/
|
||||||
|
inline const Capability *getCapability(const NetworkConfig &nconf,const uint32_t id) const
|
||||||
|
{
|
||||||
|
const CState *c = _caps.get(id);
|
||||||
|
return ((c) ? (((c->lastReceived != 0)&&(c->cap.expiration() < nconf.timestamp)) ? &(c->cap) : (const Capability *)0) : (const Capability *)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up old or stale entries
|
||||||
|
*/
|
||||||
|
inline void clean(const uint64_t now)
|
||||||
|
{
|
||||||
|
uint32_t *i = (uint32_t *)0;
|
||||||
|
CState *cs = (CState *)0;
|
||||||
|
Hashtable<uint32_t,CState>::Iterator csi(_caps);
|
||||||
|
while (csi.next(i,cs)) {
|
||||||
|
if ((now - std::max(cs->lastPushed,cs->lastReceived)) > (ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA * 3))
|
||||||
|
_caps.erase(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = (uint32_t *)0;
|
||||||
|
TState *ts = (TState *)0;
|
||||||
|
Hashtable<uint32_t,TState>::Iterator tsi(_tags);
|
||||||
|
while (tsi.next(i,ts)) {
|
||||||
|
if ((now - std::max(ts->lastPushed,ts->lastReceived)) > (ZT_NETWORK_COM_DEFAULT_REVISION_MAX_DELTA * 3))
|
||||||
|
_tags.erase(*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Last time we pushed our COM to this peer
|
||||||
|
uint64_t _lastPushedCom;
|
||||||
|
|
||||||
|
// COM from this peer
|
||||||
|
CertificateOfMembership _com;
|
||||||
|
|
||||||
|
// Capability-related state
|
||||||
|
Hashtable<uint32_t,CState> _caps;
|
||||||
|
|
||||||
|
// Tag-related state
|
||||||
|
Hashtable<uint32_t,TState> _tags;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ZeroTier
|
||||||
|
|
||||||
|
#endif
|
|
@ -216,6 +216,8 @@ void Network::requestConfiguration()
|
||||||
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MAJOR);
|
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MAJOR);
|
||||||
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MINOR);
|
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,(uint64_t)ZEROTIER_ONE_VERSION_MINOR);
|
||||||
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,(uint64_t)ZEROTIER_ONE_VERSION_REVISION);
|
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,(uint64_t)ZEROTIER_ONE_VERSION_REVISION);
|
||||||
|
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_RULES,(uint64_t)ZT_MAX_NETWORK_RULES);
|
||||||
|
rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_CAPABILITY_RULES,(uint64_t)ZT_MAX_CAPABILITY_RULES);
|
||||||
|
|
||||||
if (controller() == RR->identity.address()) {
|
if (controller() == RR->identity.address()) {
|
||||||
if (RR->localNetworkController) {
|
if (RR->localNetworkController) {
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include "MulticastGroup.hpp"
|
#include "MulticastGroup.hpp"
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "CertificateOfMembership.hpp"
|
#include "CertificateOfMembership.hpp"
|
||||||
|
#include "Capability.hpp"
|
||||||
|
#include "Tag.hpp"
|
||||||
#include "Dictionary.hpp"
|
#include "Dictionary.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,6 +78,8 @@ namespace ZeroTier {
|
||||||
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION "majv"
|
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION "majv"
|
||||||
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION "minv"
|
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION "minv"
|
||||||
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION "revv"
|
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION "revv"
|
||||||
|
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_RULES "Mr"
|
||||||
|
#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_CAPABILITY_RULES "Mcr"
|
||||||
|
|
||||||
// These dictionary keys are short so they don't take up much room.
|
// These dictionary keys are short so they don't take up much room.
|
||||||
|
|
||||||
|
@ -288,6 +292,32 @@ public:
|
||||||
inline bool operator==(const NetworkConfig &nc) const { return (memcmp(this,&nc,sizeof(NetworkConfig)) == 0); }
|
inline bool operator==(const NetworkConfig &nc) const { return (memcmp(this,&nc,sizeof(NetworkConfig)) == 0); }
|
||||||
inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
|
inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a specialist or mask flags if already present
|
||||||
|
*
|
||||||
|
* This masks the existing flags if the specialist is already here or adds
|
||||||
|
* it otherwise.
|
||||||
|
*
|
||||||
|
* @param a Address of specialist
|
||||||
|
* @param f Flags (OR of specialist role/type flags)
|
||||||
|
* @return True if successfully masked or added
|
||||||
|
*/
|
||||||
|
inline bool addSpecialist(const Address &a,const uint64_t f)
|
||||||
|
{
|
||||||
|
const uint64_t aint = a.toInt();
|
||||||
|
for(unsigned int i=0;i<specialistCount;++i) {
|
||||||
|
if ((specialists[i] & 0xffffffffffULL) == aint) {
|
||||||
|
specialists[i] |= f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (specialistCount < ZT_MAX_NETWORK_SPECIALISTS) {
|
||||||
|
specialists[specialistCount++] = f | aint;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
inline void dump() const
|
inline void dump() const
|
||||||
{
|
{
|
||||||
|
@ -316,32 +346,6 @@ public:
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a specialist or mask flags if already present
|
|
||||||
*
|
|
||||||
* This masks the existing flags if the specialist is already here or adds
|
|
||||||
* it otherwise.
|
|
||||||
*
|
|
||||||
* @param a Address of specialist
|
|
||||||
* @param f Flags (OR of specialist role/type flags)
|
|
||||||
* @return True if successfully masked or added
|
|
||||||
*/
|
|
||||||
inline bool addSpecialist(const Address &a,const uint64_t f)
|
|
||||||
{
|
|
||||||
const uint64_t aint = a.toInt();
|
|
||||||
for(unsigned int i=0;i<specialistCount;++i) {
|
|
||||||
if ((specialists[i] & 0xffffffffffULL) == aint) {
|
|
||||||
specialists[i] |= f;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (specialistCount < ZT_MAX_NETWORK_SPECIALISTS) {
|
|
||||||
specialists[specialistCount++] = f | aint;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network ID that this configuration applies to
|
* Network ID that this configuration applies to
|
||||||
*/
|
*/
|
||||||
|
@ -397,6 +401,16 @@ public:
|
||||||
*/
|
*/
|
||||||
unsigned int ruleCount;
|
unsigned int ruleCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of capabilities
|
||||||
|
*/
|
||||||
|
unsigned int capabilityCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of tags
|
||||||
|
*/
|
||||||
|
unsigned int tagCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialist devices
|
* Specialist devices
|
||||||
*
|
*
|
||||||
|
@ -416,10 +430,20 @@ public:
|
||||||
InetAddress staticIps[ZT_MAX_ZT_ASSIGNED_ADDRESSES];
|
InetAddress staticIps[ZT_MAX_ZT_ASSIGNED_ADDRESSES];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rules table
|
* Base network rules
|
||||||
*/
|
*/
|
||||||
ZT_VirtualNetworkRule rules[ZT_MAX_NETWORK_RULES];
|
ZT_VirtualNetworkRule rules[ZT_MAX_NETWORK_RULES];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capabilities for this node on this network
|
||||||
|
*/
|
||||||
|
Capability capabilities[ZT_MAX_NETWORK_CAPABILITIES];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tags for this node on this network
|
||||||
|
*/
|
||||||
|
Tag tags[ZT_MAX_NETWORK_TAGS];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network type (currently just public or private)
|
* Network type (currently just public or private)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -38,7 +38,7 @@ const char *Packet::verbString(Verb v)
|
||||||
case VERB_EXT_FRAME: return "EXT_FRAME";
|
case VERB_EXT_FRAME: return "EXT_FRAME";
|
||||||
case VERB_ECHO: return "ECHO";
|
case VERB_ECHO: return "ECHO";
|
||||||
case VERB_MULTICAST_LIKE: return "MULTICAST_LIKE";
|
case VERB_MULTICAST_LIKE: return "MULTICAST_LIKE";
|
||||||
case VERB_NETWORK_MEMBERSHIP_CERTIFICATE: return "NETWORK_MEMBERSHIP_CERTIFICATE";
|
case VERB_NETWORK_CREDENTIALS: return "NETWORK_CREDENTIALS";
|
||||||
case VERB_NETWORK_CONFIG_REQUEST: return "NETWORK_CONFIG_REQUEST";
|
case VERB_NETWORK_CONFIG_REQUEST: return "NETWORK_CONFIG_REQUEST";
|
||||||
case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER";
|
case VERB_MULTICAST_GATHER: return "MULTICAST_GATHER";
|
||||||
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
|
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
|
||||||
|
@ -46,8 +46,6 @@ const char *Packet::verbString(Verb v)
|
||||||
case VERB_CIRCUIT_TEST: return "CIRCUIT_TEST";
|
case VERB_CIRCUIT_TEST: return "CIRCUIT_TEST";
|
||||||
case VERB_CIRCUIT_TEST_REPORT: return "CIRCUIT_TEST_REPORT";
|
case VERB_CIRCUIT_TEST_REPORT: return "CIRCUIT_TEST_REPORT";
|
||||||
case VERB_REQUEST_PROOF_OF_WORK: return "REQUEST_PROOF_OF_WORK";
|
case VERB_REQUEST_PROOF_OF_WORK: return "REQUEST_PROOF_OF_WORK";
|
||||||
case VERB_REQUEST_OBJECT: return "REQUEST_OBJECT";
|
|
||||||
case VERB_OBJECT_UPDATED: return "OBJECT_UPDATED";
|
|
||||||
}
|
}
|
||||||
return "(unknown)";
|
return "(unknown)";
|
||||||
}
|
}
|
||||||
|
|
215
node/Packet.hpp
215
node/Packet.hpp
|
@ -51,19 +51,23 @@
|
||||||
* + Yet another multicast redesign
|
* + Yet another multicast redesign
|
||||||
* + New crypto completely changes key agreement cipher
|
* + New crypto completely changes key agreement cipher
|
||||||
* 4 - 0.6.0 ... 1.0.6
|
* 4 - 0.6.0 ... 1.0.6
|
||||||
* + New identity format based on hashcash design
|
* + BREAKING CHANGE: New identity format based on hashcash design
|
||||||
* 5 - 1.1.0 ... 1.1.5
|
* 5 - 1.1.0 ... 1.1.5
|
||||||
* + Supports circuit test, proof of work, and echo
|
* + Supports circuit test, proof of work, and echo
|
||||||
* + Supports in-band world (root server definition) updates
|
* + Supports in-band world (root server definition) updates
|
||||||
* + Clustering! (Though this will work with protocol v4 clients.)
|
* + Clustering! (Though this will work with protocol v4 clients.)
|
||||||
* + Otherwise backward compatible with protocol v4
|
* + Otherwise backward compatible with protocol v4
|
||||||
* 6 - 1.1.5 ... 1.1.10
|
* 6 - 1.1.5 ... 1.1.10
|
||||||
* + Deprecate old dictionary-based network config format
|
* + Network configuration format revisions including binary values
|
||||||
* + Introduce new binary serialized network config and meta-data
|
* 7 - 1.1.10 -- 1.2.0
|
||||||
* 7 - 1.1.10 -- CURRENT
|
|
||||||
* + Introduce trusted paths for local SDN use
|
* + Introduce trusted paths for local SDN use
|
||||||
|
* 8 - 1.2.0 -- CURRENT
|
||||||
|
* + Multipart network configurations for large network configs
|
||||||
|
* + Tags and Capabilities
|
||||||
|
* + Inline push of CertificateOfMembership deprecated
|
||||||
|
* + Certificates of representation for federation and mesh
|
||||||
*/
|
*/
|
||||||
#define ZT_PROTO_VERSION 7
|
#define ZT_PROTO_VERSION 8
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimum supported protocol version
|
* Minimum supported protocol version
|
||||||
|
@ -523,7 +527,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* No operation (ignored, no reply)
|
* No operation (ignored, no reply)
|
||||||
*/
|
*/
|
||||||
VERB_NOP = 0,
|
VERB_NOP = 0x00,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Announcement of a node's existence:
|
* Announcement of a node's existence:
|
||||||
|
@ -566,7 +570,7 @@ public:
|
||||||
*
|
*
|
||||||
* ERROR has no payload.
|
* ERROR has no payload.
|
||||||
*/
|
*/
|
||||||
VERB_HELLO = 1,
|
VERB_HELLO = 0x01,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error response:
|
* Error response:
|
||||||
|
@ -575,7 +579,7 @@ public:
|
||||||
* <[1] error code>
|
* <[1] error code>
|
||||||
* <[...] error-dependent payload>
|
* <[...] error-dependent payload>
|
||||||
*/
|
*/
|
||||||
VERB_ERROR = 2,
|
VERB_ERROR = 0x02,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Success response:
|
* Success response:
|
||||||
|
@ -583,7 +587,7 @@ public:
|
||||||
* <[8] in-re packet ID>
|
* <[8] in-re packet ID>
|
||||||
* <[...] request-specific payload>
|
* <[...] request-specific payload>
|
||||||
*/
|
*/
|
||||||
VERB_OK = 3,
|
VERB_OK = 0x03,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query an identity by address:
|
* Query an identity by address:
|
||||||
|
@ -598,7 +602,7 @@ public:
|
||||||
* If the address is not found, no response is generated. WHOIS requests
|
* If the address is not found, no response is generated. WHOIS requests
|
||||||
* will time out much like ARP requests and similar do in L2.
|
* will time out much like ARP requests and similar do in L2.
|
||||||
*/
|
*/
|
||||||
VERB_WHOIS = 4,
|
VERB_WHOIS = 0x04,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Meet another node at a given protocol address:
|
* Meet another node at a given protocol address:
|
||||||
|
@ -626,7 +630,7 @@ public:
|
||||||
*
|
*
|
||||||
* No OK or ERROR is generated.
|
* No OK or ERROR is generated.
|
||||||
*/
|
*/
|
||||||
VERB_RENDEZVOUS = 5,
|
VERB_RENDEZVOUS = 0x05,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZT-to-ZT unicast ethernet frame (shortened EXT_FRAME):
|
* ZT-to-ZT unicast ethernet frame (shortened EXT_FRAME):
|
||||||
|
@ -642,31 +646,29 @@ public:
|
||||||
* ERROR may be generated if a membership certificate is needed for a
|
* ERROR may be generated if a membership certificate is needed for a
|
||||||
* closed network. Payload will be network ID.
|
* closed network. Payload will be network ID.
|
||||||
*/
|
*/
|
||||||
VERB_FRAME = 6,
|
VERB_FRAME = 0x06,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full Ethernet frame with MAC addressing and optional fields:
|
* Full Ethernet frame with MAC addressing and optional fields:
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
* <[1] flags>
|
* <[1] flags>
|
||||||
* [<[...] certificate of network membership>]
|
* [<[...] certificate of network membership (DEPRECATED)>]
|
||||||
* <[6] destination MAC or all zero for destination node>
|
* <[6] destination MAC or all zero for destination node>
|
||||||
* <[6] source MAC or all zero for node of origin>
|
* <[6] source MAC or all zero for node of origin>
|
||||||
* <[2] 16-bit ethertype>
|
* <[2] 16-bit ethertype>
|
||||||
* <[...] ethernet payload>
|
* <[...] ethernet payload>
|
||||||
*
|
*
|
||||||
* Flags:
|
* Flags:
|
||||||
* 0x01 - Certificate of network membership is attached
|
* 0x01 - Certificate of network membership attached (DEPRECATED)
|
||||||
*
|
*
|
||||||
* An extended frame carries full MAC addressing, making them a
|
* An extended frame carries full MAC addressing, making them a
|
||||||
* superset of VERB_FRAME. They're used for bridging or when we
|
* superset of VERB_FRAME. They're used for bridging or when we
|
||||||
* want to attach a certificate since FRAME does not support that.
|
* want to attach a certificate since FRAME does not support that.
|
||||||
*
|
*
|
||||||
* Multicast frames may not be sent as EXT_FRAME.
|
|
||||||
*
|
|
||||||
* ERROR may be generated if a membership certificate is needed for a
|
* ERROR may be generated if a membership certificate is needed for a
|
||||||
* closed network. Payload will be network ID.
|
* closed network. Payload will be network ID.
|
||||||
*/
|
*/
|
||||||
VERB_EXT_FRAME = 7,
|
VERB_EXT_FRAME = 0x07,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ECHO request (a.k.a. ping):
|
* ECHO request (a.k.a. ping):
|
||||||
|
@ -676,7 +678,7 @@ public:
|
||||||
* is generated. Response to ECHO requests is optional and ECHO may be
|
* is generated. Response to ECHO requests is optional and ECHO may be
|
||||||
* ignored if a node detects a possible flood.
|
* ignored if a node detects a possible flood.
|
||||||
*/
|
*/
|
||||||
VERB_ECHO = 8,
|
VERB_ECHO = 0x08,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Announce interest in multicast group(s):
|
* Announce interest in multicast group(s):
|
||||||
|
@ -690,45 +692,76 @@ public:
|
||||||
* controllers and root servers. In the current network, root servers
|
* controllers and root servers. In the current network, root servers
|
||||||
* will provide the service of final multicast cache.
|
* will provide the service of final multicast cache.
|
||||||
*
|
*
|
||||||
* If sending LIKEs to root servers for backward compatibility reasons,
|
* VERB_NETWORK_CREDENTIALS should be pushed along with this, especially
|
||||||
* VERB_NETWORK_MEMBERSHIP_CERTIFICATE must be sent as well ahead of
|
* if using upstream (e.g. root) nodes as multicast databases. This allows
|
||||||
* time so that roots can authenticate GATHER requests.
|
* GATHERs to be authenticated.
|
||||||
*
|
*
|
||||||
* OK/ERROR are not generated.
|
* OK/ERROR are not generated.
|
||||||
*/
|
*/
|
||||||
VERB_MULTICAST_LIKE = 9,
|
VERB_MULTICAST_LIKE = 0x09,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network member certificate replication/push:
|
* Network membership credential push:
|
||||||
* <[...] serialized certificate of membership>
|
* <[...] serialized certificate of membership>
|
||||||
* [ ... additional certificates may follow ...]
|
* [<[...] additional certificates of membership>]
|
||||||
|
* <[1] null byte for backward compatibility (see below)>
|
||||||
|
* <[2] 16-bit number of capabilities>
|
||||||
|
* <[...] one or more serialized Capability>
|
||||||
|
* <[2] 16-bit number of tags>
|
||||||
|
* <[...] one or more serialized Tags>
|
||||||
*
|
*
|
||||||
* This is sent in response to ERROR_NEED_MEMBERSHIP_CERTIFICATE and may
|
* This is sent in response to ERROR_NEED_MEMBERSHIP_CERTIFICATE and may
|
||||||
* be pushed at any other time to keep exchanged certificates up to date.
|
* be pushed at any other time to keep exchanged certificates up to date.
|
||||||
*
|
*
|
||||||
|
* Protocol versions prior to 8 do not support capabilities or tags and
|
||||||
|
* just expect an array of COMs. Adding a single NULL byte after the COM
|
||||||
|
* array causes these older versions to harmlessly abort parsing and
|
||||||
|
* ignore the newer fields. The new version checks for this null byte to
|
||||||
|
* indicate the end of the COM array, since all serialized COMs begin with
|
||||||
|
* non-zero bytes (see CertificateOfMembership).
|
||||||
|
*
|
||||||
* OK/ERROR are not generated.
|
* OK/ERROR are not generated.
|
||||||
*/
|
*/
|
||||||
VERB_NETWORK_MEMBERSHIP_CERTIFICATE = 10,
|
VERB_NETWORK_CREDENTIALS = 0x0a,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DEPRECATED but still supported, interpreted as an object request:
|
* Network configuration request:
|
||||||
|
* <[8] 64-bit network ID>
|
||||||
|
* <[2] 16-bit length of request meta-data dictionary>
|
||||||
|
* <[...] string-serialized request meta-data>
|
||||||
|
* [<[8] 64-bit timestamp of netconf we currently have>]
|
||||||
*
|
*
|
||||||
* /controller/network/<network ID>/member/<requester address>
|
* This message requests network configuration from a node capable of
|
||||||
*
|
* providing it. If the optional revision is included, a response is
|
||||||
* When received in this manner the response is sent via the old
|
* only generated if there is a newer network configuration available.
|
||||||
* OK(NETWORK_CONFIG_REQUEST) instead of OK(REQUEST_OBJECT). If the
|
|
||||||
* response is too large, a dictionary is sent with the single key
|
|
||||||
* OVF set to 1. In this case REQUEST_OBJECT must be used.
|
|
||||||
*
|
*
|
||||||
* OK response payload:
|
* OK response payload:
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
* <[2] 16-bit length of network configuration dictionary>
|
* <[2] 16-bit length of network configuration dictionary field>
|
||||||
* <[...] network configuration dictionary>
|
* <[...] network configuration dictionary (or fragment)>
|
||||||
|
* [<[4] 32-bit total length of assembled dictionary>]
|
||||||
|
* [<[4] 32-bit index of fragment in this reply>]
|
||||||
|
*
|
||||||
|
* Fields after the dictionary are extensions to support multipart
|
||||||
|
* sending of large network configs. If they are not present the
|
||||||
|
* sent config must be assumed to be whole.
|
||||||
*
|
*
|
||||||
* ERROR response payload:
|
* ERROR response payload:
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
*/
|
*/
|
||||||
VERB_NETWORK_CONFIG_REQUEST = 11,
|
VERB_NETWORK_CONFIG_REQUEST = 0x0b,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network configuration refresh request:
|
||||||
|
* <[...] array of 64-bit network IDs>
|
||||||
|
*
|
||||||
|
* This can be sent by the network controller to inform a node that it
|
||||||
|
* should now make a NETWORK_CONFIG_REQUEST.
|
||||||
|
*
|
||||||
|
* It does not generate an OK or ERROR message, and is treated only as
|
||||||
|
* a hint to refresh now.
|
||||||
|
*/
|
||||||
|
VERB_NETWORK_CONFIG_REFRESH = 0x0c,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request endpoints for multicast distribution:
|
* Request endpoints for multicast distribution:
|
||||||
|
@ -737,10 +770,10 @@ public:
|
||||||
* <[6] MAC address of multicast group being queried>
|
* <[6] MAC address of multicast group being queried>
|
||||||
* <[4] 32-bit ADI for multicast group being queried>
|
* <[4] 32-bit ADI for multicast group being queried>
|
||||||
* <[4] 32-bit requested max number of multicast peers>
|
* <[4] 32-bit requested max number of multicast peers>
|
||||||
* [<[...] network certificate of membership>]
|
* [<[...] network certificate of membership (DEPRECATED)>]
|
||||||
*
|
*
|
||||||
* Flags:
|
* Flags:
|
||||||
* 0x01 - Network certificate of membership is attached
|
* 0x01 - COM is attached (DEPRECATED)
|
||||||
*
|
*
|
||||||
* This message asks a peer for additional known endpoints that have
|
* This message asks a peer for additional known endpoints that have
|
||||||
* LIKEd a given multicast group. It's sent when the sender wishes
|
* LIKEd a given multicast group. It's sent when the sender wishes
|
||||||
|
@ -750,6 +783,9 @@ public:
|
||||||
* More than one OK response can occur if the response is broken up across
|
* More than one OK response can occur if the response is broken up across
|
||||||
* multiple packets or if querying a clustered node.
|
* multiple packets or if querying a clustered node.
|
||||||
*
|
*
|
||||||
|
* Send VERB_NETWORK_CREDENTIALS prior to GATHERing if doing so from
|
||||||
|
* upstream nodes like root servers that are not involved in our network.
|
||||||
|
*
|
||||||
* OK response payload:
|
* OK response payload:
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
* <[6] MAC address of multicast group being queried>
|
* <[6] MAC address of multicast group being queried>
|
||||||
|
@ -761,13 +797,13 @@ public:
|
||||||
*
|
*
|
||||||
* ERROR is not generated; queries that return no response are dropped.
|
* ERROR is not generated; queries that return no response are dropped.
|
||||||
*/
|
*/
|
||||||
VERB_MULTICAST_GATHER = 13,
|
VERB_MULTICAST_GATHER = 0x0d,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multicast frame:
|
* Multicast frame:
|
||||||
* <[8] 64-bit network ID>
|
* <[8] 64-bit network ID>
|
||||||
* <[1] flags>
|
* <[1] flags>
|
||||||
* [<[...] network certificate of membership>]
|
* [<[...] network certificate of membership (DEPRECATED)>]
|
||||||
* [<[4] 32-bit implicit gather limit>]
|
* [<[4] 32-bit implicit gather limit>]
|
||||||
* [<[6] source MAC>]
|
* [<[6] source MAC>]
|
||||||
* <[6] destination MAC (multicast address)>
|
* <[6] destination MAC (multicast address)>
|
||||||
|
@ -776,7 +812,7 @@ public:
|
||||||
* <[...] ethernet payload>
|
* <[...] ethernet payload>
|
||||||
*
|
*
|
||||||
* Flags:
|
* Flags:
|
||||||
* 0x01 - Network certificate of membership is attached
|
* 0x01 - Network certificate of membership attached (DEPRECATED)
|
||||||
* 0x02 - Implicit gather limit field is present
|
* 0x02 - Implicit gather limit field is present
|
||||||
* 0x04 - Source MAC is specified -- otherwise it's computed from sender
|
* 0x04 - Source MAC is specified -- otherwise it's computed from sender
|
||||||
*
|
*
|
||||||
|
@ -791,11 +827,11 @@ public:
|
||||||
* <[6] MAC address of multicast group>
|
* <[6] MAC address of multicast group>
|
||||||
* <[4] 32-bit ADI for multicast group>
|
* <[4] 32-bit ADI for multicast group>
|
||||||
* <[1] flags>
|
* <[1] flags>
|
||||||
* [<[...] network certficate of membership>]
|
* [<[...] network certficate of membership (DEPRECATED)>]
|
||||||
* [<[...] implicit gather results if flag 0x01 is set>]
|
* [<[...] implicit gather results if flag 0x01 is set>]
|
||||||
*
|
*
|
||||||
* OK flags (same bits as request flags):
|
* OK flags (same bits as request flags):
|
||||||
* 0x01 - OK includes certificate of network membership
|
* 0x01 - OK includes certificate of network membership (DEPRECATED)
|
||||||
* 0x02 - OK includes implicit gather results
|
* 0x02 - OK includes implicit gather results
|
||||||
*
|
*
|
||||||
* ERROR response payload:
|
* ERROR response payload:
|
||||||
|
@ -803,7 +839,9 @@ public:
|
||||||
* <[6] multicast group MAC>
|
* <[6] multicast group MAC>
|
||||||
* <[4] 32-bit multicast group ADI>
|
* <[4] 32-bit multicast group ADI>
|
||||||
*/
|
*/
|
||||||
VERB_MULTICAST_FRAME = 14,
|
VERB_MULTICAST_FRAME = 0x0e,
|
||||||
|
|
||||||
|
// 0x0f is reserved for an old deprecated message
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push of potential endpoints for direct communication:
|
* Push of potential endpoints for direct communication:
|
||||||
|
@ -839,7 +877,7 @@ public:
|
||||||
*
|
*
|
||||||
* OK and ERROR are not generated.
|
* OK and ERROR are not generated.
|
||||||
*/
|
*/
|
||||||
VERB_PUSH_DIRECT_PATHS = 16,
|
VERB_PUSH_DIRECT_PATHS = 0x10,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Source-routed circuit test message:
|
* Source-routed circuit test message:
|
||||||
|
@ -855,9 +893,8 @@ public:
|
||||||
* [ ... end of signed portion of request ... ]
|
* [ ... end of signed portion of request ... ]
|
||||||
* <[2] 16-bit length of signature of request>
|
* <[2] 16-bit length of signature of request>
|
||||||
* <[...] signature of request by originator>
|
* <[...] signature of request by originator>
|
||||||
* <[2] 16-bit previous hop credential length (including type)>
|
* <[2] 16-bit length of additional fields>
|
||||||
* [[1] previous hop credential type]
|
* [[...] additional fields]
|
||||||
* [[...] previous hop credential]
|
|
||||||
* <[...] next hop(s) in path>
|
* <[...] next hop(s) in path>
|
||||||
*
|
*
|
||||||
* Flags:
|
* Flags:
|
||||||
|
@ -867,9 +904,6 @@ public:
|
||||||
* Originator credential types:
|
* Originator credential types:
|
||||||
* 0x01 - 64-bit network ID for which originator is controller
|
* 0x01 - 64-bit network ID for which originator is controller
|
||||||
*
|
*
|
||||||
* Previous hop credential types:
|
|
||||||
* 0x01 - Certificate of network membership
|
|
||||||
*
|
|
||||||
* Path record format:
|
* Path record format:
|
||||||
* <[1] 8-bit flags (unused, must be zero)>
|
* <[1] 8-bit flags (unused, must be zero)>
|
||||||
* <[1] 8-bit breadth (number of next hops)>
|
* <[1] 8-bit breadth (number of next hops)>
|
||||||
|
@ -918,7 +952,7 @@ public:
|
||||||
* <[8] 64-bit timestamp (echoed from original>
|
* <[8] 64-bit timestamp (echoed from original>
|
||||||
* <[8] 64-bit test ID (echoed from original)>
|
* <[8] 64-bit test ID (echoed from original)>
|
||||||
*/
|
*/
|
||||||
VERB_CIRCUIT_TEST = 17,
|
VERB_CIRCUIT_TEST = 0x11,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Circuit test hop report:
|
* Circuit test hop report:
|
||||||
|
@ -955,7 +989,7 @@ public:
|
||||||
* If a test report is received and no circuit test was sent, it should be
|
* If a test report is received and no circuit test was sent, it should be
|
||||||
* ignored. This message generates no OK or ERROR response.
|
* ignored. This message generates no OK or ERROR response.
|
||||||
*/
|
*/
|
||||||
VERB_CIRCUIT_TEST_REPORT = 18,
|
VERB_CIRCUIT_TEST_REPORT = 0x12,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request proof of work:
|
* Request proof of work:
|
||||||
|
@ -998,63 +1032,7 @@ public:
|
||||||
*
|
*
|
||||||
* ERROR has no payload.
|
* ERROR has no payload.
|
||||||
*/
|
*/
|
||||||
VERB_REQUEST_PROOF_OF_WORK = 19,
|
VERB_REQUEST_PROOF_OF_WORK = 0x13
|
||||||
|
|
||||||
/**
|
|
||||||
* Request an object or a chunk of an object with optional meta-data:
|
|
||||||
* <[8] 64-bit chunk offset>
|
|
||||||
* <[2] 16-bit chunk length or 0 for any / sender-preferred>
|
|
||||||
* <[2] 16-bit object path length in bytes>
|
|
||||||
* <[...] object path>
|
|
||||||
* <[2] 16-bit length of request meta-data dictionary>
|
|
||||||
* <[...] request meta-data dictionary>
|
|
||||||
*
|
|
||||||
* This is used to request an object. Objects can be things like network
|
|
||||||
* configs, software updates, etc. This provides an in-band way to
|
|
||||||
* distribute such things and obsoletes the network config specific
|
|
||||||
* messages. (They are still supported for backward compatibility.)
|
|
||||||
*
|
|
||||||
* The use of path and request/response meta-data makes the semantics of
|
|
||||||
* this analogous to HTTP POST, and it could therefore be mapped to
|
|
||||||
* HTTP POST requests to permit plugins that leverage the ZT protocol
|
|
||||||
* to do out-of-band things like special authentication, etc.
|
|
||||||
*
|
|
||||||
* Large objects can be transferred via repeated calls with higher and
|
|
||||||
* higher chunk offsets and then SHA-512 verified on receipt, but this is
|
|
||||||
* not efficient. It should not be used heavily as an alternative to
|
|
||||||
* TCP. It's a bit more like X-Modem and other old-school SEND/ACK
|
|
||||||
* protocols. It is potentially a good idea for software updates since
|
|
||||||
* it means that ZT can update itself even on networks with no "vanilla"
|
|
||||||
* Internet access.
|
|
||||||
*
|
|
||||||
* OK and ERROR responses are optional but recommended. ERROR responses
|
|
||||||
* can include OBJECT_NOT_FOUND.
|
|
||||||
*
|
|
||||||
* OK response payload:
|
|
||||||
* <[16] first 16 bytes of SHA-512 of complete object>
|
|
||||||
* <[8] 64-bit total object size>
|
|
||||||
* <[8] 64-bit chunk offset>
|
|
||||||
* <[2] 16-bit length of chunk payload>
|
|
||||||
* <[...] chunk payload>
|
|
||||||
*/
|
|
||||||
VERB_REQUEST_OBJECT = 20,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notification of a remote object update:
|
|
||||||
* <[8] 64-bit total object size or 0 if unspecified here>
|
|
||||||
* <[16] first 16 bytes of SHA-512 of object (if size specified)>
|
|
||||||
* <[2] 16-bit length of object path>
|
|
||||||
* <[...] object path>
|
|
||||||
* <[2] 16-bit length of meta-data dictionary>
|
|
||||||
* <[...] meta-data dictionary>
|
|
||||||
*
|
|
||||||
* This can be sent to notify another peer that an object has updated and
|
|
||||||
* should be re-requested. The receiving peer is not required to do anything
|
|
||||||
* or send anything in response to this. If the first size field is zero, the
|
|
||||||
* SHA-512 hash is also unspecified and should be zero. This means that the
|
|
||||||
* object was updated but must be re-requested.
|
|
||||||
*/
|
|
||||||
VERB_OBJECT_UPDATED = 21
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1063,31 +1041,28 @@ public:
|
||||||
enum ErrorCode
|
enum ErrorCode
|
||||||
{
|
{
|
||||||
/* No error, not actually used in transit */
|
/* No error, not actually used in transit */
|
||||||
ERROR_NONE = 0,
|
ERROR_NONE = 0x00,
|
||||||
|
|
||||||
/* Invalid request */
|
/* Invalid request */
|
||||||
ERROR_INVALID_REQUEST = 1,
|
ERROR_INVALID_REQUEST = 0x01,
|
||||||
|
|
||||||
/* Bad/unsupported protocol version */
|
/* Bad/unsupported protocol version */
|
||||||
ERROR_BAD_PROTOCOL_VERSION = 2,
|
ERROR_BAD_PROTOCOL_VERSION = 0x02,
|
||||||
|
|
||||||
/* Unknown object queried */
|
/* Unknown object queried */
|
||||||
ERROR_OBJ_NOT_FOUND = 3,
|
ERROR_OBJ_NOT_FOUND = 0x03,
|
||||||
|
|
||||||
/* HELLO pushed an identity whose address is already claimed */
|
/* HELLO pushed an identity whose address is already claimed */
|
||||||
ERROR_IDENTITY_COLLISION = 4,
|
ERROR_IDENTITY_COLLISION = 0x04,
|
||||||
|
|
||||||
/* Verb or use case not supported/enabled by this node */
|
/* Verb or use case not supported/enabled by this node */
|
||||||
ERROR_UNSUPPORTED_OPERATION = 5,
|
ERROR_UNSUPPORTED_OPERATION = 0x05,
|
||||||
|
|
||||||
/* Message to private network rejected -- no unexpired certificate on file */
|
|
||||||
ERROR_NEED_MEMBERSHIP_CERTIFICATE = 6,
|
|
||||||
|
|
||||||
/* Tried to join network, but you're not a member */
|
/* Tried to join network, but you're not a member */
|
||||||
ERROR_NETWORK_ACCESS_DENIED_ = 7, /* extra _ 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 */
|
/* Multicasts to this group are not wanted */
|
||||||
ERROR_UNWANTED_MULTICAST = 8
|
ERROR_UNWANTED_MULTICAST = 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
//#ifdef ZT_TRACE
|
//#ifdef ZT_TRACE
|
||||||
|
|
169
node/Peer.hpp
169
node/Peer.hpp
|
@ -31,7 +31,6 @@
|
||||||
#include "../include/ZeroTierOne.h"
|
#include "../include/ZeroTierOne.h"
|
||||||
|
|
||||||
#include "RuntimeEnvironment.hpp"
|
#include "RuntimeEnvironment.hpp"
|
||||||
#include "CertificateOfMembership.hpp"
|
|
||||||
#include "Path.hpp"
|
#include "Path.hpp"
|
||||||
#include "Address.hpp"
|
#include "Address.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
@ -44,10 +43,6 @@
|
||||||
#include "Mutex.hpp"
|
#include "Mutex.hpp"
|
||||||
#include "NonCopyable.hpp"
|
#include "NonCopyable.hpp"
|
||||||
|
|
||||||
// Very rough computed estimate: (8 + 256 + 80 + (16 * 64) + (128 * 256) + (128 * 16))
|
|
||||||
// 1048576 provides tons of headroom -- overflow would just cause peer not to be persisted
|
|
||||||
#define ZT_PEER_SUGGESTED_SERIALIZATION_BUFFER_SIZE 1048576
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -362,31 +357,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void getBestActiveAddresses(uint64_t now,InetAddress &v4,InetAddress &v6) const;
|
void getBestActiveAddresses(uint64_t now,InetAddress &v4,InetAddress &v6) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Check network COM agreement with this peer
|
|
||||||
*
|
|
||||||
* @param nwid Network ID
|
|
||||||
* @param com Another certificate of membership
|
|
||||||
* @return True if supplied COM agrees with ours, false if not or if we don't have one
|
|
||||||
*/
|
|
||||||
bool networkMembershipCertificatesAgree(uint64_t nwid,const CertificateOfMembership &com) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check the validity of the COM and add/update if valid and new
|
|
||||||
*
|
|
||||||
* @param nwid Network ID
|
|
||||||
* @param com Externally supplied COM
|
|
||||||
*/
|
|
||||||
bool validateAndSetNetworkMembershipCertificate(uint64_t nwid,const CertificateOfMembership &com);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param nwid Network ID
|
|
||||||
* @param now Current time
|
|
||||||
* @param updateLastPushedTime If true, go ahead and update the last pushed time regardless of return value
|
|
||||||
* @return Whether or not this peer needs another COM push from us
|
|
||||||
*/
|
|
||||||
bool needsOurNetworkMembershipCertificate(uint64_t nwid,uint64_t now,bool updateLastPushedTime);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform periodic cleaning operations
|
* Perform periodic cleaning operations
|
||||||
*
|
*
|
||||||
|
@ -434,138 +404,12 @@ public:
|
||||||
else return std::pair<InetAddress,InetAddress>();
|
else return std::pair<InetAddress,InetAddress>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned int C>
|
|
||||||
inline void serialize(Buffer<C> &b) const
|
|
||||||
{
|
|
||||||
Mutex::Lock _l(_networkComs_m);
|
|
||||||
|
|
||||||
const unsigned int recSizePos = b.size();
|
|
||||||
b.addSize(4); // space for uint32_t field length
|
|
||||||
|
|
||||||
b.append((uint16_t)1); // version of serialized Peer data
|
|
||||||
|
|
||||||
_id.serialize(b,false);
|
|
||||||
|
|
||||||
b.append((uint64_t)_lastUsed);
|
|
||||||
b.append((uint64_t)_lastReceive);
|
|
||||||
b.append((uint64_t)_lastUnicastFrame);
|
|
||||||
b.append((uint64_t)_lastMulticastFrame);
|
|
||||||
b.append((uint64_t)_lastAnnouncedTo);
|
|
||||||
b.append((uint64_t)_lastDirectPathPushSent);
|
|
||||||
b.append((uint64_t)_lastDirectPathPushReceive);
|
|
||||||
b.append((uint64_t)_lastPathSort);
|
|
||||||
b.append((uint16_t)_vProto);
|
|
||||||
b.append((uint16_t)_vMajor);
|
|
||||||
b.append((uint16_t)_vMinor);
|
|
||||||
b.append((uint16_t)_vRevision);
|
|
||||||
b.append((uint32_t)_latency);
|
|
||||||
b.append((uint16_t)_directPathPushCutoffCount);
|
|
||||||
|
|
||||||
b.append((uint16_t)_numPaths);
|
|
||||||
for(unsigned int i=0;i<_numPaths;++i)
|
|
||||||
_paths[i].serialize(b);
|
|
||||||
|
|
||||||
b.append((uint32_t)_networkComs.size());
|
|
||||||
{
|
|
||||||
uint64_t *k = (uint64_t *)0;
|
|
||||||
_NetworkCom *v = (_NetworkCom *)0;
|
|
||||||
Hashtable<uint64_t,_NetworkCom>::Iterator i(const_cast<Peer *>(this)->_networkComs);
|
|
||||||
while (i.next(k,v)) {
|
|
||||||
b.append((uint64_t)*k);
|
|
||||||
b.append((uint64_t)v->ts);
|
|
||||||
v->com.serialize(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b.append((uint32_t)_lastPushedComs.size());
|
|
||||||
{
|
|
||||||
uint64_t *k = (uint64_t *)0;
|
|
||||||
uint64_t *v = (uint64_t *)0;
|
|
||||||
Hashtable<uint64_t,uint64_t>::Iterator i(const_cast<Peer *>(this)->_lastPushedComs);
|
|
||||||
while (i.next(k,v)) {
|
|
||||||
b.append((uint64_t)*k);
|
|
||||||
b.append((uint64_t)*v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b.template setAt<uint32_t>(recSizePos,(uint32_t)(b.size() - (recSizePos + 4))); // set size
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Peer from a serialized instance
|
|
||||||
*
|
|
||||||
* @param renv Runtime environment
|
|
||||||
* @param myIdentity This node's identity
|
|
||||||
* @param b Buffer containing serialized Peer data
|
|
||||||
* @param p Pointer to current position in buffer, will be updated in place as buffer is read (value/result)
|
|
||||||
* @return New instance of Peer or NULL if serialized data was corrupt or otherwise invalid (may also throw an exception via Buffer)
|
|
||||||
*/
|
|
||||||
template<unsigned int C>
|
|
||||||
static inline SharedPtr<Peer> deserializeNew(const RuntimeEnvironment *renv,const Identity &myIdentity,const Buffer<C> &b,unsigned int &p)
|
|
||||||
{
|
|
||||||
const unsigned int recSize = b.template at<uint32_t>(p); p += 4;
|
|
||||||
if ((p + recSize) > b.size())
|
|
||||||
return SharedPtr<Peer>(); // size invalid
|
|
||||||
if (b.template at<uint16_t>(p) != 1)
|
|
||||||
return SharedPtr<Peer>(); // version mismatch
|
|
||||||
p += 2;
|
|
||||||
|
|
||||||
Identity npid;
|
|
||||||
p += npid.deserialize(b,p);
|
|
||||||
if (!npid)
|
|
||||||
return SharedPtr<Peer>();
|
|
||||||
|
|
||||||
SharedPtr<Peer> np(new Peer(renv,myIdentity,npid));
|
|
||||||
|
|
||||||
np->_lastUsed = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_lastReceive = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_lastUnicastFrame = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_lastMulticastFrame = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_lastAnnouncedTo = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_lastDirectPathPushSent = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_lastDirectPathPushReceive = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_lastPathSort = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_vProto = b.template at<uint16_t>(p); p += 2;
|
|
||||||
np->_vMajor = b.template at<uint16_t>(p); p += 2;
|
|
||||||
np->_vMinor = b.template at<uint16_t>(p); p += 2;
|
|
||||||
np->_vRevision = b.template at<uint16_t>(p); p += 2;
|
|
||||||
np->_latency = b.template at<uint32_t>(p); p += 4;
|
|
||||||
np->_directPathPushCutoffCount = b.template at<uint16_t>(p); p += 2;
|
|
||||||
|
|
||||||
const unsigned int numPaths = b.template at<uint16_t>(p); p += 2;
|
|
||||||
for(unsigned int i=0;i<numPaths;++i) {
|
|
||||||
if (i < ZT_MAX_PEER_NETWORK_PATHS) {
|
|
||||||
p += np->_paths[np->_numPaths++].deserialize(b,p);
|
|
||||||
} else {
|
|
||||||
// Skip any paths beyond max, but still read stream
|
|
||||||
Path foo;
|
|
||||||
p += foo.deserialize(b,p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int numNetworkComs = b.template at<uint32_t>(p); p += 4;
|
|
||||||
for(unsigned int i=0;i<numNetworkComs;++i) {
|
|
||||||
_NetworkCom &c = np->_networkComs[b.template at<uint64_t>(p)]; p += 8;
|
|
||||||
c.ts = b.template at<uint64_t>(p); p += 8;
|
|
||||||
p += c.com.deserialize(b,p);
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int numLastPushed = b.template at<uint32_t>(p); p += 4;
|
|
||||||
for(unsigned int i=0;i<numLastPushed;++i) {
|
|
||||||
const uint64_t nwid = b.template at<uint64_t>(p); p += 8;
|
|
||||||
const uint64_t ts = b.template at<uint64_t>(p); p += 8;
|
|
||||||
np->_lastPushedComs.set(nwid,ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
return np;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _doDeadPathDetection(Path &p,const uint64_t now);
|
void _doDeadPathDetection(Path &p,const uint64_t now);
|
||||||
Path *_getBestPath(const uint64_t now);
|
Path *_getBestPath(const uint64_t now);
|
||||||
Path *_getBestPath(const uint64_t now,int inetAddressFamily);
|
Path *_getBestPath(const uint64_t now,int inetAddressFamily);
|
||||||
|
|
||||||
unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH]; // computed with key agreement, not serialized
|
unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH];
|
||||||
|
|
||||||
const RuntimeEnvironment *RR;
|
const RuntimeEnvironment *RR;
|
||||||
uint64_t _lastUsed;
|
uint64_t _lastUsed;
|
||||||
|
@ -586,17 +430,6 @@ private:
|
||||||
unsigned int _latency;
|
unsigned int _latency;
|
||||||
unsigned int _directPathPushCutoffCount;
|
unsigned int _directPathPushCutoffCount;
|
||||||
|
|
||||||
struct _NetworkCom
|
|
||||||
{
|
|
||||||
_NetworkCom() {}
|
|
||||||
_NetworkCom(uint64_t t,const CertificateOfMembership &c) : ts(t),com(c) {}
|
|
||||||
uint64_t ts;
|
|
||||||
CertificateOfMembership com;
|
|
||||||
};
|
|
||||||
Hashtable<uint64_t,_NetworkCom> _networkComs;
|
|
||||||
Hashtable<uint64_t,uint64_t> _lastPushedComs;
|
|
||||||
Mutex _networkComs_m;
|
|
||||||
|
|
||||||
AtomicCounter __refCount;
|
AtomicCounter __refCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,36 +47,7 @@ Topology::Topology(const RuntimeEnvironment *renv) :
|
||||||
_trustedPathCount(0),
|
_trustedPathCount(0),
|
||||||
_amRoot(false)
|
_amRoot(false)
|
||||||
{
|
{
|
||||||
std::string alls(RR->node->dataStoreGet("peers.save"));
|
// Get cached world if present
|
||||||
const uint8_t *all = reinterpret_cast<const uint8_t *>(alls.data());
|
|
||||||
RR->node->dataStoreDelete("peers.save");
|
|
||||||
|
|
||||||
Buffer<ZT_PEER_SUGGESTED_SERIALIZATION_BUFFER_SIZE> *deserializeBuf = new Buffer<ZT_PEER_SUGGESTED_SERIALIZATION_BUFFER_SIZE>();
|
|
||||||
unsigned int ptr = 0;
|
|
||||||
while ((ptr + 4) < alls.size()) {
|
|
||||||
try {
|
|
||||||
const unsigned int reclen = ( // each Peer serialized record is prefixed by a record length
|
|
||||||
((((unsigned int)all[ptr]) & 0xff) << 24) |
|
|
||||||
((((unsigned int)all[ptr + 1]) & 0xff) << 16) |
|
|
||||||
((((unsigned int)all[ptr + 2]) & 0xff) << 8) |
|
|
||||||
(((unsigned int)all[ptr + 3]) & 0xff)
|
|
||||||
);
|
|
||||||
unsigned int pos = 0;
|
|
||||||
deserializeBuf->copyFrom(all + ptr,reclen + 4);
|
|
||||||
SharedPtr<Peer> p(Peer::deserializeNew(RR,RR->identity,*deserializeBuf,pos));
|
|
||||||
ptr += pos;
|
|
||||||
if (!p)
|
|
||||||
break; // stop if invalid records
|
|
||||||
if (p->address() != RR->identity.address())
|
|
||||||
_peers.set(p->address(),p);
|
|
||||||
} catch ( ... ) {
|
|
||||||
break; // stop if invalid records
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete deserializeBuf;
|
|
||||||
|
|
||||||
clean(RR->node->now());
|
|
||||||
|
|
||||||
std::string dsWorld(RR->node->dataStoreGet("world"));
|
std::string dsWorld(RR->node->dataStoreGet("world"));
|
||||||
World cachedWorld;
|
World cachedWorld;
|
||||||
if (dsWorld.length() > 0) {
|
if (dsWorld.length() > 0) {
|
||||||
|
@ -87,6 +58,8 @@ Topology::Topology(const RuntimeEnvironment *renv) :
|
||||||
cachedWorld = World(); // clear if cached world is invalid
|
cachedWorld = World(); // clear if cached world is invalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use default or cached world depending on which is shinier
|
||||||
World defaultWorld;
|
World defaultWorld;
|
||||||
{
|
{
|
||||||
Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH);
|
Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH);
|
||||||
|
|
|
@ -705,6 +705,9 @@ public:
|
||||||
}
|
}
|
||||||
authToken = _trimString(authToken);
|
authToken = _trimString(authToken);
|
||||||
|
|
||||||
|
// Clean up any legacy files if present
|
||||||
|
OSUtils::rm((_homePath + ZT_PATH_SEPARATOR_S + "peers.save").c_str());
|
||||||
|
|
||||||
_node = new Node(
|
_node = new Node(
|
||||||
OSUtils::now(),
|
OSUtils::now(),
|
||||||
this,
|
this,
|
||||||
|
|
Loading…
Add table
Reference in a new issue