summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/AtomicCounter.hpp2
-rw-r--r--node/Capability.cpp3
-rw-r--r--node/CertificateOfMembership.cpp3
-rw-r--r--node/CertificateOfOwnership.cpp3
-rw-r--r--node/Constants.hpp20
-rw-r--r--node/IncomingPacket.cpp17
-rw-r--r--node/Membership.cpp3
-rw-r--r--node/Multicaster.cpp2
-rw-r--r--node/Mutex.hpp88
-rw-r--r--node/Network.cpp1
-rw-r--r--node/NetworkConfig.cpp5
-rw-r--r--node/Node.cpp44
-rw-r--r--node/Node.hpp2
-rw-r--r--node/Packet.hpp6
-rw-r--r--node/Peer.cpp33
-rw-r--r--node/Peer.hpp84
-rw-r--r--node/Revocation.cpp3
-rw-r--r--node/SelfAwareness.cpp52
-rw-r--r--node/Switch.cpp160
-rw-r--r--node/Switch.hpp37
-rw-r--r--node/Tag.cpp3
-rw-r--r--node/Topology.cpp68
-rw-r--r--node/Topology.hpp111
-rw-r--r--node/Trace.cpp79
-rw-r--r--node/Trace.hpp9
25 files changed, 468 insertions, 370 deletions
diff --git a/node/AtomicCounter.hpp b/node/AtomicCounter.hpp
index abb342fe..34b58e91 100644
--- a/node/AtomicCounter.hpp
+++ b/node/AtomicCounter.hpp
@@ -50,7 +50,7 @@ public:
inline int load() const
{
#ifdef __GNUC__
- return __sync_or_and_fetch(&_v,0);
+ return __sync_or_and_fetch(const_cast<int *>(&_v),0);
#else
return _v.load();
#endif
diff --git a/node/Capability.cpp b/node/Capability.cpp
index 0e02025a..47dca1fc 100644
--- a/node/Capability.cpp
+++ b/node/Capability.cpp
@@ -30,6 +30,7 @@
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp"
+#include "Node.hpp"
namespace ZeroTier {
@@ -59,7 +60,7 @@ int Capability::verify(const RuntimeEnvironment *RR,void *tPtr) const
if (!id.verify(tmp.data(),tmp.size(),_custody[c].signature))
return -1;
} else {
- RR->sw->requestWhois(tPtr,_custody[c].from);
+ RR->sw->requestWhois(tPtr,RR->node->now(),_custody[c].from);
return 1;
}
}
diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp
index 100253e1..dedcccff 100644
--- a/node/CertificateOfMembership.cpp
+++ b/node/CertificateOfMembership.cpp
@@ -29,6 +29,7 @@
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp"
+#include "Node.hpp"
namespace ZeroTier {
@@ -223,7 +224,7 @@ int CertificateOfMembership::verify(const RuntimeEnvironment *RR,void *tPtr) con
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) {
- RR->sw->requestWhois(tPtr,_signedBy);
+ RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
return 1;
}
diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp
index 31d0ae18..eeb0d99c 100644
--- a/node/CertificateOfOwnership.cpp
+++ b/node/CertificateOfOwnership.cpp
@@ -30,6 +30,7 @@
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp"
+#include "Node.hpp"
namespace ZeroTier {
@@ -39,7 +40,7 @@ int CertificateOfOwnership::verify(const RuntimeEnvironment *RR,void *tPtr) cons
return -1;
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) {
- RR->sw->requestWhois(tPtr,_signedBy);
+ RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
return 1;
}
try {
diff --git a/node/Constants.hpp b/node/Constants.hpp
index 3f050ead..651fe50d 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -172,15 +172,6 @@
#define ZT_ADDRESS_RESERVED_PREFIX 0xff
/**
- * Default payload MTU for UDP packets
- *
- * In the future we might support UDP path MTU discovery, but for now we
- * set a maximum that is equal to 1500 minus 8 (for PPPoE overhead, common
- * in some markets) minus 48 (IPv6 UDP overhead).
- */
-#define ZT_UDP_DEFAULT_PAYLOAD_MTU 1444
-
-/**
* Default MTU used for Ethernet tap device
*/
#define ZT_DEFAULT_MTU 2800
@@ -226,22 +217,17 @@
/**
* Delay between WHOIS retries in ms
*/
-#define ZT_WHOIS_RETRY_DELAY 1000
-
-/**
- * Maximum identity WHOIS retries (each attempt tries consulting a different peer)
- */
-#define ZT_MAX_WHOIS_RETRIES 4
+#define ZT_WHOIS_RETRY_DELAY 500
/**
* Transmit queue entry timeout
*/
-#define ZT_TRANSMIT_QUEUE_TIMEOUT (ZT_WHOIS_RETRY_DELAY * (ZT_MAX_WHOIS_RETRIES + 1))
+#define ZT_TRANSMIT_QUEUE_TIMEOUT 5000
/**
* Receive queue entry timeout
*/
-#define ZT_RECEIVE_QUEUE_TIMEOUT (ZT_WHOIS_RETRY_DELAY * (ZT_MAX_WHOIS_RETRIES + 1))
+#define ZT_RECEIVE_QUEUE_TIMEOUT 5000
/**
* Maximum latency to allow for OK(HELLO) before packet is discarded
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index e5e10476..685f2f09 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -66,10 +66,9 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
// packets are dropped on the floor.
const uint64_t tpid = trustedPathId();
if (RR->topology->shouldInboundPathBeTrusted(_path->address(),tpid)) {
- RR->t->incomingPacketTrustedPath(tPtr,_path,packetId(),sourceAddress,tpid,true);
trusted = true;
} else {
- RR->t->incomingPacketTrustedPath(tPtr,_path,packetId(),sourceAddress,tpid,false);
+ RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"path not trusted");
return true;
}
} else if ((c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)&&(verb() == Packet::VERB_HELLO)) {
@@ -81,7 +80,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
if (peer) {
if (!trusted) {
if (!dearmor(peer->key())) {
- RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops());
+ RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"invalid MAC");
return true;
}
}
@@ -116,7 +115,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
case Packet::VERB_REMOTE_TRACE: return _doREMOTE_TRACE(RR,tPtr,peer);
}
} else {
- RR->sw->requestWhois(tPtr,sourceAddress);
+ RR->sw->requestWhois(tPtr,RR->node->now(),sourceAddress);
return false;
}
} catch ( ... ) {
@@ -246,10 +245,10 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
outp.armor(key,true,_path->nextOutgoingCounter());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
} else {
- RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops());
+ RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
}
} else {
- RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops());
+ RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid identity");
}
return true;
@@ -257,7 +256,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
// Identity is the same as the one we already have -- check packet integrity
if (!dearmor(peer->key())) {
- RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops());
+ RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
return true;
}
@@ -282,7 +281,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
// Check packet integrity and MAC (this is faster than locallyValidate() so do it first to filter out total crap)
SharedPtr<Peer> newPeer(new Peer(RR,RR->identity,id));
if (!dearmor(newPeer->key())) {
- RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops());
+ RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
return true;
}
@@ -557,7 +556,7 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const Shar
++count;
} else {
// Request unknown WHOIS from upstream from us (if we have one)
- RR->sw->requestWhois(tPtr,addr);
+ RR->sw->requestWhois(tPtr,RR->node->now(),addr);
}
}
diff --git a/node/Membership.cpp b/node/Membership.cpp
index a1453307..17de6554 100644
--- a/node/Membership.cpp
+++ b/node/Membership.cpp
@@ -147,7 +147,6 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
return ADD_REJECTED;
case 0:
_com = com;
- RR->t->credentialAccepted(tPtr,com);
return ADD_ACCEPTED_NEW;
case 1:
return ADD_DEFERRED_FOR_WHOIS;
@@ -179,7 +178,6 @@ static Membership::AddCredentialResult _addCredImpl(Hashtable<uint32_t,C> &remot
RR->t->credentialRejected(tPtr,cred,"invalid");
return Membership::ADD_REJECTED;
case 0:
- RR->t->credentialAccepted(tPtr,cred);
if (!rc)
rc = &(remoteCreds[cred.id()]);
*rc = cred;
@@ -205,7 +203,6 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
switch(ct) {
case Credential::CREDENTIAL_TYPE_COM:
if (rev.threshold() > _comRevocationThreshold) {
- RR->t->credentialAccepted(tPtr,rev);
_comRevocationThreshold = rev.threshold();
return ADD_ACCEPTED_NEW;
}
diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp
index fb7b068f..e8c8613a 100644
--- a/node/Multicaster.cpp
+++ b/node/Multicaster.cpp
@@ -111,7 +111,7 @@ unsigned int Multicaster::gather(const Address &queryingPeer,uint64_t nwid,const
// Members are returned in random order so that repeated gather queries
// will return different subsets of a large multicast group.
k = 0;
- while ((added < limit)&&(k < s->members.size())&&((appendTo.size() + ZT_ADDRESS_LENGTH) <= ZT_UDP_DEFAULT_PAYLOAD_MTU)) {
+ while ((added < limit)&&(k < s->members.size())&&((appendTo.size() + ZT_ADDRESS_LENGTH) <= ZT_PROTO_MAX_PACKET_LENGTH)) {
rptr = (unsigned int)RR->node->prng();
restart_member_scan:
diff --git a/node/Mutex.hpp b/node/Mutex.hpp
index 854f321a..b68e5d93 100644
--- a/node/Mutex.hpp
+++ b/node/Mutex.hpp
@@ -32,47 +32,96 @@
#ifdef __UNIX_LIKE__
+#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
namespace ZeroTier {
+#if defined(__GNUC__) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
+
+// Inline ticket lock on x64 systems with GCC and CLANG (Mac, Linux) -- this is really fast as long as locking durations are very short
class Mutex : NonCopyable
{
public:
- Mutex()
+ Mutex() :
+ nextTicket(0),
+ nowServing(0)
{
- pthread_mutex_init(&_mh,(const pthread_mutexattr_t *)0);
}
- ~Mutex()
+ inline void lock() const
{
- pthread_mutex_destroy(&_mh);
+ const uint16_t myTicket = __sync_fetch_and_add(&(const_cast<Mutex *>(this)->nextTicket),1);
+ while (nowServing != myTicket) {
+ __asm__ __volatile__("rep;nop"::);
+ __asm__ __volatile__("":::"memory");
+ }
}
- inline void lock()
+ inline void unlock() const
{
- pthread_mutex_lock(&_mh);
+ ++(const_cast<Mutex *>(this)->nowServing);
}
- inline void unlock()
+ /**
+ * Uses C++ contexts and constructor/destructor to lock/unlock automatically
+ */
+ class Lock : NonCopyable
{
- pthread_mutex_unlock(&_mh);
+ public:
+ Lock(Mutex &m) :
+ _m(&m)
+ {
+ m.lock();
+ }
+
+ Lock(const Mutex &m) :
+ _m(const_cast<Mutex *>(&m))
+ {
+ _m->lock();
+ }
+
+ ~Lock()
+ {
+ _m->unlock();
+ }
+
+ private:
+ Mutex *const _m;
+ };
+
+private:
+ uint16_t nextTicket;
+ uint16_t nowServing;
+};
+
+#else
+
+// libpthread based mutex lock
+class Mutex : NonCopyable
+{
+public:
+ Mutex()
+ {
+ pthread_mutex_init(&_mh,(const pthread_mutexattr_t *)0);
+ }
+
+ ~Mutex()
+ {
+ pthread_mutex_destroy(&_mh);
}
inline void lock() const
{
- (const_cast <Mutex *> (this))->lock();
+ pthread_mutex_lock(&((const_cast <Mutex *> (this))->_mh));
}
inline void unlock() const
{
- (const_cast <Mutex *> (this))->unlock();
+ pthread_mutex_unlock(&((const_cast <Mutex *> (this))->_mh));
}
- /**
- * Uses C++ contexts and constructor/destructor to lock/unlock automatically
- */
class Lock : NonCopyable
{
public:
@@ -101,6 +150,8 @@ private:
pthread_mutex_t _mh;
};
+#endif
+
} // namespace ZeroTier
#endif // Apple / Linux
@@ -112,6 +163,7 @@ private:
namespace ZeroTier {
+// Windows critical section based lock
class Mutex : NonCopyable
{
public:
@@ -125,16 +177,6 @@ public:
DeleteCriticalSection(&_cs);
}
- inline void lock()
- {
- EnterCriticalSection(&_cs);
- }
-
- inline void unlock()
- {
- LeaveCriticalSection(&_cs);
- }
-
inline void lock() const
{
(const_cast <Mutex *> (this))->lock();
diff --git a/node/Network.cpp b/node/Network.cpp
index f7b144e3..16155c33 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -1346,7 +1346,6 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
ec->status = _status();
ec->type = (_config) ? (_config.isPrivate() ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC) : ZT_NETWORK_TYPE_PRIVATE;
ec->mtu = (_config) ? _config.mtu : ZT_DEFAULT_MTU;
- ec->physicalMtu = ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 16);
ec->dhcp = 0;
std::vector<Address> ab(_config.activeBridges());
ec->bridge = ((_config.allowPassiveBridging())||(std::find(ab.begin(),ab.end(),RR->identity.address()) != ab.end())) ? 1 : 0;
diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp
index 0bf4bc19..110a20b0 100644
--- a/node/NetworkConfig.cpp
+++ b/node/NetworkConfig.cpp
@@ -35,6 +35,7 @@ namespace ZeroTier {
bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,bool includeLegacy) const
{
Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> *tmp = new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>();
+ char tmp2[128];
try {
d.clear();
@@ -46,8 +47,8 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP,this->timestamp)) 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_ISSUED_TO,this->issuedTo)) return false;
- if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_REMOTE_TRACE_TARGET,this->remoteTraceTarget)) 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_FLAGS,this->flags)) 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;
diff --git a/node/Node.cpp b/node/Node.cpp
index 0df3a97a..871fb21b 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -100,7 +100,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6
} else {
idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0;
n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1);
- if ((n > 0)&&(n < sizeof(RR->publicIdentityStr))&&(n < sizeof(tmp))) {
+ if ((n > 0)&&(n < (int)sizeof(RR->publicIdentityStr))&&(n < (int)sizeof(tmp))) {
if (memcmp(tmp,RR->publicIdentityStr,n))
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
}
@@ -249,6 +249,19 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint
try {
_lastPingCheck = now;
+ // Do pings and keepalives
+ Hashtable< Address,std::vector<InetAddress> > upstreamsToContact;
+ RR->topology->getUpstreamsToContact(upstreamsToContact);
+ _PingPeersThatNeedPing pfunc(RR,tptr,upstreamsToContact,now);
+ RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
+
+ // Run WHOIS to create Peer for any upstreams we could not contact (including pending moon seeds)
+ Hashtable< Address,std::vector<InetAddress> >::Iterator i(upstreamsToContact);
+ Address *upstreamAddress = (Address *)0;
+ std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
+ while (i.next(upstreamAddress,upstreamStableEndpoints))
+ RR->sw->requestWhois(tptr,now,*upstreamAddress);
+
// Get networks that need config without leaving mutex locked
{
std::vector< std::pair< SharedPtr<Network>,bool > > nwl;
@@ -268,19 +281,6 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint
}
}
- // Do pings and keepalives
- Hashtable< Address,std::vector<InetAddress> > upstreamsToContact;
- RR->topology->getUpstreamsToContact(upstreamsToContact);
- _PingPeersThatNeedPing pfunc(RR,tptr,upstreamsToContact,now);
- RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
-
- // Run WHOIS to create Peer for any upstreams we could not contact (including pending moon seeds)
- Hashtable< Address,std::vector<InetAddress> >::Iterator i(upstreamsToContact);
- Address *upstreamAddress = (Address *)0;
- std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
- while (i.next(upstreamAddress,upstreamStableEndpoints))
- RR->sw->requestWhois(tptr,*upstreamAddress);
-
// Update online status, post status change as event
const bool oldOnline = _online;
_online = (((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amRoot()));
@@ -561,9 +561,9 @@ uint64_t Node::prng()
return z + y;
}
-void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count)
+ZT_ResultCode Node::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork, const ZT_PhysicalPathConfiguration *pathConfig)
{
- RR->topology->setTrustedPaths(reinterpret_cast<const InetAddress *>(networks),ids,count);
+ return ZT_RESULT_OK;
}
World Node::planet() const
@@ -592,7 +592,7 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
const unsigned int totalSize = dconf->sizeBytes();
unsigned int chunkIndex = 0;
while (chunkIndex < totalSize) {
- const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 256)));
+ const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH - (ZT_PACKET_IDX_PAYLOAD + 256)));
Packet outp(destination,RR->identity.address(),(requestPacketId) ? Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG);
if (requestPacketId) {
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
@@ -815,7 +815,7 @@ enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,u
}
}
-ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId)
+enum ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId)
{
try {
return reinterpret_cast<ZeroTier::Node *>(node)->deorbit(tptr,moonWorldId);
@@ -902,11 +902,13 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance)
} catch ( ... ) {}
}
-void ZT_Node_setTrustedPaths(ZT_Node *node,const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count)
+enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
{
try {
- reinterpret_cast<ZeroTier::Node *>(node)->setTrustedPaths(networks,ids,count);
- } catch ( ... ) {}
+ return reinterpret_cast<ZeroTier::Node *>(node)->setPhysicalPathConfiguration(pathNetwork,pathConfig);
+ } catch ( ... ) {
+ return ZT_RESULT_FATAL_ERROR_INTERNAL;
+ }
}
void ZT_version(int *major,int *minor,int *revision)
diff --git a/node/Node.hpp b/node/Node.hpp
index 9658174f..1aa01c9a 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -192,7 +192,7 @@ public:
inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }
uint64_t prng();
- void setTrustedPaths(const struct sockaddr_storage *networks,const uint64_t *ids,unsigned int count);
+ ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig);
World planet() const;
std::vector<World> moons() const;
diff --git a/node/Packet.hpp b/node/Packet.hpp
index 5fc631b1..db70e06f 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -225,12 +225,8 @@
/**
* Packet buffer size (can be changed)
- *
- * The current value is big enough for ZT_MAX_PACKET_FRAGMENTS, the pragmatic
- * packet fragment limit, times the default UDP MTU. Most packets won't be
- * this big.
*/
-#define ZT_PROTO_MAX_PACKET_LENGTH (ZT_MAX_PACKET_FRAGMENTS * ZT_UDP_DEFAULT_PAYLOAD_MTU)
+#define ZT_PROTO_MAX_PACKET_LENGTH (ZT_MAX_PACKET_FRAGMENTS * ZT_DEFAULT_PHYSMTU)
/**
* Minimum viable packet length (a.k.a. header length)
diff --git a/node/Peer.cpp b/node/Peer.cpp
index 986e52ef..a954b716 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -194,8 +194,12 @@ void Peer::received(
}
}
}
- } else if (this->trustEstablished(now)) {
- // Send PUSH_DIRECT_PATHS if hops>0 (relayed) and we have a trust relationship (common network membership)
+ }
+
+ // If we are being relayed or if we're using a global address, send PUSH_DIRECT_PATHS.
+ // In the global address case we push only configured direct paths to accomplish
+ // fall-forward to local backplane networks over e.g. LAN or Amazon VPC.
+ if ( ((hops > 0)||(path->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) && (this->trustEstablished(now)) ) {
if ((now - _lastDirectPathPushSent) >= ZT_DIRECT_PATH_PUSH_INTERVAL) {
_lastDirectPathPushSent = now;
@@ -205,13 +209,15 @@ void Peer::received(
for(std::vector<InetAddress>::const_iterator i(dps.begin());i!=dps.end();++i)
pathsToPush.push_back(*i);
- std::vector<InetAddress> sym(RR->sa->getSymmetricNatPredictions());
- for(unsigned long i=0,added=0;i<sym.size();++i) {
- InetAddress tmp(sym[(unsigned long)RR->node->prng() % sym.size()]);
- if (std::find(pathsToPush.begin(),pathsToPush.end(),tmp) == pathsToPush.end()) {
- pathsToPush.push_back(tmp);
- if (++added >= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY)
- break;
+ if (hops > 0) {
+ std::vector<InetAddress> sym(RR->sa->getSymmetricNatPredictions());
+ for(unsigned long i=0,added=0;i<sym.size();++i) {
+ InetAddress tmp(sym[(unsigned long)RR->node->prng() % sym.size()]);
+ if (std::find(pathsToPush.begin(),pathsToPush.end(),tmp) == pathsToPush.end()) {
+ pathsToPush.push_back(tmp);
+ if (++added >= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY)
+ break;
+ }
}
}
@@ -369,7 +375,7 @@ void Peer::tryMemorizedPath(void *tPtr,uint64_t now)
_lastTriedMemorizedPath = now;
InetAddress mp;
if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp))
- attemptToContactAt(tPtr,InetAddress(),mp,now,true,0);
+ attemptToContactAt(tPtr,-1,mp,now,true,0);
}
}
@@ -424,18 +430,21 @@ void Peer::redirect(void *tPtr,const int64_t localSocket,const InetAddress &remo
SharedPtr<Path> op;
SharedPtr<Path> np(RR->topology->getPath(localSocket,remoteAddress));
+ np->received(now);
attemptToContactAt(tPtr,localSocket,remoteAddress,now,true,np->nextOutgoingCounter());
{
Mutex::Lock _l(_paths_m);
if (remoteAddress.ss_family == AF_INET) {
op = _v4Path.p;
- _v4Path.p = np;
+ _v4Path.lr = now;
_v4Path.sticky = now;
+ _v4Path.p = np;
} else if (remoteAddress.ss_family == AF_INET6) {
op = _v6Path.p;
- _v6Path.p = np;
+ _v6Path.lr = now;
_v6Path.sticky = now;
+ _v6Path.p = np;
}
}
diff --git a/node/Peer.hpp b/node/Peer.hpp
index c6423a59..af9163a5 100644
--- a/node/Peer.hpp
+++ b/node/Peer.hpp
@@ -439,6 +439,90 @@ public:
return false;
}
+ /**
+ * Serialize a peer for storage in local cache
+ *
+ * This does not serialize everything, just identity and addresses where the peer
+ * may be reached.
+ */
+ template<unsigned int C>
+ inline void serialize(Buffer<C> &b) const
+ {
+ b.append((uint8_t)0);
+
+ _id.serialize(b);
+
+ b.append(_lastReceive);
+ b.append(_lastNontrivialReceive);
+ b.append(_lastTriedMemorizedPath);
+ b.append(_lastDirectPathPushSent);
+ b.append(_lastDirectPathPushReceive);
+ b.append(_lastCredentialRequestSent);
+ b.append(_lastWhoisRequestReceived);
+ b.append(_lastEchoRequestReceived);
+ b.append(_lastComRequestReceived);
+ b.append(_lastComRequestSent);
+ b.append(_lastCredentialsReceived);
+ b.append(_lastTrustEstablishedPacketReceived);
+
+ b.append((uint16_t)_vProto);
+ b.append((uint16_t)_vMajor);
+ b.append((uint16_t)_vMinor);
+ b.append((uint16_t)_vRevision);
+
+ {
+ Mutex::Lock _l(_paths_m);
+ unsigned int pcount = 0;
+ if (_v4Path.p) ++pcount;
+ if (_v6Path.p) ++pcount;
+ b.append((uint8_t)pcount);
+ if (_v4Path.p) _v4Path.p->address().serialize(b);
+ if (_v6Path.p) _v6Path.p->address().serialize(b);
+ }
+
+ b.append((uint16_t)0);
+ }
+
+ template<unsigned int C>
+ inline static SharedPtr<Peer> deserializeFromCache(uint64_t now,void *tPtr,Buffer<C> &b,const RuntimeEnvironment *renv)
+ {
+ try {
+ unsigned int ptr = 0;
+ if (b[ptr++] != 0)
+ return SharedPtr<Peer>();
+
+ Identity id;
+ ptr += id.deserialize(b,ptr);
+ if (!id)
+ return SharedPtr<Peer>();
+
+ SharedPtr<Peer> p(new Peer(renv,renv->identity,id));
+
+ ptr += 12 * 8; // skip deserializing ephemeral state in this case
+
+ p->_vProto = b.template at<uint16_t>(ptr); ptr += 2;
+ p->_vMajor = b.template at<uint16_t>(ptr); ptr += 2;
+ p->_vMinor = b.template at<uint16_t>(ptr); ptr += 2;
+ p->_vRevision = b.template at<uint16_t>(ptr); ptr += 2;
+
+ const unsigned int pcount = (unsigned int)b[ptr++];
+ for(unsigned int i=0;i<pcount;++i) {
+ InetAddress inaddr;
+ try {
+ ptr += inaddr.deserialize(b,ptr);
+ if (inaddr)
+ p->attemptToContactAt(tPtr,-1,inaddr,now,true,0);
+ } catch ( ... ) {
+ break;
+ }
+ }
+
+ return p;
+ } catch ( ... ) {
+ return SharedPtr<Peer>();
+ }
+ }
+
private:
struct _PeerPath
{
diff --git a/node/Revocation.cpp b/node/Revocation.cpp
index 026058da..89a2db95 100644
--- a/node/Revocation.cpp
+++ b/node/Revocation.cpp
@@ -30,6 +30,7 @@
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp"
+#include "Node.hpp"
namespace ZeroTier {
@@ -39,7 +40,7 @@ int Revocation::verify(const RuntimeEnvironment *RR,void *tPtr) const
return -1;
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) {
- RR->sw->requestWhois(tPtr,_signedBy);
+ RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
return 1;
}
try {
diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp
index cdbb6303..0af0d691 100644
--- a/node/SelfAwareness.cpp
+++ b/node/SelfAwareness.cpp
@@ -147,13 +147,14 @@ std::vector<InetAddress> SelfAwareness::getSymmetricNatPredictions()
* read or modify traffic, but they could gather meta-data for forensics
* purpsoes or use this as a DOS attack vector. */
- std::map< uint32_t,std::pair<uint64_t,unsigned int> > maxPortByIp;
+ std::map< uint32_t,unsigned int > maxPortByIp;
InetAddress theOneTrueSurface;
- bool symmetric = false;
{
Mutex::Lock _l(_phy_m);
- { // First get IPs from only trusted peers, and perform basic NAT type characterization
+ // First check to see if this is a symmetric NAT and enumerate external IPs learned from trusted peers
+ bool symmetric = false;
+ {
Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
PhySurfaceKey *k = (PhySurfaceKey *)0;
PhySurfaceEntry *e = (PhySurfaceEntry *)0;
@@ -163,42 +164,47 @@ std::vector<InetAddress> SelfAwareness::getSymmetricNatPredictions()
theOneTrueSurface = e->mySurface;
else if (theOneTrueSurface != e->mySurface)
symmetric = true;
- maxPortByIp[reinterpret_cast<const struct sockaddr_in *>(&(e->mySurface))->sin_addr.s_addr] = std::pair<uint64_t,unsigned int>(e->ts,e->mySurface.port());
+ maxPortByIp[reinterpret_cast<const struct sockaddr_in *>(&(e->mySurface))->sin_addr.s_addr] = e->mySurface.port();
}
}
}
+ if (!symmetric)
+ return std::vector<InetAddress>();
- { // Then find max port per IP from a trusted peer
+ { // Then find the highest issued port per IP
Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
PhySurfaceKey *k = (PhySurfaceKey *)0;
PhySurfaceEntry *e = (PhySurfaceEntry *)0;
while (i.next(k,e)) {
if ((e->mySurface.ss_family == AF_INET)&&(e->mySurface.ipScope() == InetAddress::IP_SCOPE_GLOBAL)) {
- std::map< uint32_t,std::pair<uint64_t,unsigned int> >::iterator mp(maxPortByIp.find(reinterpret_cast<const struct sockaddr_in *>(&(e->mySurface))->sin_addr.s_addr));
- if ((mp != maxPortByIp.end())&&(mp->second.first < e->ts)) {
- mp->second.first = e->ts;
- mp->second.second = e->mySurface.port();
- }
+ const unsigned int port = e->mySurface.port();
+ std::map< uint32_t,unsigned int >::iterator mp(maxPortByIp.find(reinterpret_cast<const struct sockaddr_in *>(&(e->mySurface))->sin_addr.s_addr));
+ if ((mp != maxPortByIp.end())&&(mp->second < port))
+ mp->second = port;
}
}
}
}
- if (symmetric) {
- std::vector<InetAddress> r;
- for(unsigned int k=1;k<=3;++k) {
- for(std::map< uint32_t,std::pair<uint64_t,unsigned int> >::iterator i(maxPortByIp.begin());i!=maxPortByIp.end();++i) {
- unsigned int p = i->second.second + k;
- if (p > 65535) p -= 64511;
- InetAddress pred(&(i->first),4,p);
- if (std::find(r.begin(),r.end(),pred) == r.end())
- r.push_back(pred);
- }
- }
- return r;
+ std::vector<InetAddress> r;
+
+ // Try next port up from max for each
+ for(std::map< uint32_t,unsigned int >::iterator i(maxPortByIp.begin());i!=maxPortByIp.end();++i) {
+ unsigned int p = i->second + 1;
+ if (p > 65535) p -= 64511;
+ const InetAddress pred(&(i->first),4,p);
+ if (std::find(r.begin(),r.end(),pred) == r.end())
+ r.push_back(pred);
+ }
+
+ // Try a random port for each -- there are only 65535 so eventually it should work
+ for(std::map< uint32_t,unsigned int >::iterator i(maxPortByIp.begin());i!=maxPortByIp.end();++i) {
+ const InetAddress pred(&(i->first),4,1024 + ((unsigned int)RR->node->prng() % 64511));
+ if (std::find(r.begin(),r.end(),pred) == r.end())
+ r.push_back(pred);
}
- return std::vector<InetAddress>();
+ return r;
}
} // namespace ZeroTier
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 053f793e..f46b3e73 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -50,7 +50,6 @@ namespace ZeroTier {
Switch::Switch(const RuntimeEnvironment *renv) :
RR(renv),
_lastBeaconResponse(0),
- _outstandingWhoisRequests(32),
_lastUniteAttempt(8) // only really used on root servers and upstreams, and it'll grow there just fine
{
}
@@ -229,8 +228,8 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre
}
}
} else {
- relayTo = RR->topology->getUpstreamPeer(&source,1,true);
- if (relayTo)
+ relayTo = RR->topology->getUpstreamPeer();
+ if ((relayTo)&&(relayTo->address() != source))
relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true);
}
}
@@ -545,41 +544,48 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const
void Switch::send(void *tPtr,Packet &packet,bool encrypt)
{
- if (packet.destination() == RR->identity.address())
+ const Address dest(packet.destination());
+ if (dest == RR->identity.address())
return;
if (!_trySend(tPtr,packet,encrypt)) {
- Mutex::Lock _l(_txQueue_m);
- _txQueue.push_back(TXQueueEntry(packet.destination(),RR->node->now(),packet,encrypt));
+ {
+ Mutex::Lock _l(_txQueue_m);
+ _txQueue.push_back(TXQueueEntry(dest,RR->node->now(),packet,encrypt));
+ }
+ if (!RR->topology->getPeer(tPtr,dest))
+ requestWhois(tPtr,RR->node->now(),dest);
}
}
-void Switch::requestWhois(void *tPtr,const Address &addr)
+void Switch::requestWhois(void *tPtr,const uint64_t now,const Address &addr)
{
if (addr == RR->identity.address())
return;
- bool inserted = false;
+
{
- Mutex::Lock _l(_outstandingWhoisRequests_m);
- WhoisRequest &r = _outstandingWhoisRequests[addr];
- if (r.lastSent) {
- r.retries = 0; // reset retry count if entry already existed, but keep waiting and retry again after normal timeout
- } else {
- r.lastSent = RR->node->now();
- inserted = true;
- }
+ Mutex::Lock _l(_lastSentWhoisRequest_m);
+ uint64_t &last = _lastSentWhoisRequest[addr];
+ if ((now - last) < ZT_WHOIS_RETRY_DELAY)
+ return;
+ else last = now;
+ }
+
+ const SharedPtr<Peer> upstream(RR->topology->getUpstreamPeer());
+ if (upstream) {
+ Packet outp(upstream->address(),RR->identity.address(),Packet::VERB_WHOIS);
+ addr.appendTo(outp);
+ RR->node->expectReplyTo(outp.packetId());
+ send(tPtr,outp,true);
}
- if (inserted)
- _sendWhoisRequest(tPtr,addr,(const Address *)0,0);
}
void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
{
- { // cancel pending WHOIS since we now know this peer
- Mutex::Lock _l(_outstandingWhoisRequests_m);
- _outstandingWhoisRequests.erase(peer->address());
+ {
+ Mutex::Lock _l(_lastSentWhoisRequest_m);
+ _lastSentWhoisRequest.erase(peer->address());
}
- // finish processing any packets waiting on peer's public key / identity
const uint64_t now = RR->node->now();
for(unsigned int ptr=0;ptr<ZT_RX_QUEUE_SIZE;++ptr) {
RXQueueEntry *const rq = &(_rxQueue[ptr]);
@@ -589,57 +595,62 @@ void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
}
}
- { // finish sending any packets waiting on peer's public key / identity
+ {
Mutex::Lock _l(_txQueue_m);
for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) {
if (txi->dest == peer->address()) {
- if (_trySend(tPtr,txi->packet,txi->encrypt))
+ if (_trySend(tPtr,txi->packet,txi->encrypt)) {
_txQueue.erase(txi++);
- else ++txi;
- } else ++txi;
- }
- }
-}
-
-unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now)
-{
- unsigned long nextDelay = 0xffffffff; // ceiling delay, caller will cap to minimum
-
- { // Retry outstanding WHOIS requests
- Mutex::Lock _l(_outstandingWhoisRequests_m);
- Hashtable< Address,WhoisRequest >::Iterator i(_outstandingWhoisRequests);
- Address *a = (Address *)0;
- WhoisRequest *r = (WhoisRequest *)0;
- while (i.next(a,r)) {
- const unsigned long since = (unsigned long)(now - r->lastSent);
- if (since >= ZT_WHOIS_RETRY_DELAY) {
- if (r->retries >= ZT_MAX_WHOIS_RETRIES) {
- _outstandingWhoisRequests.erase(*a);
} else {
- r->lastSent = now;
- r->peersConsulted[r->retries] = _sendWhoisRequest(tPtr,*a,r->peersConsulted,(r->retries > 1) ? r->retries : 0);
- ++r->retries;
- nextDelay = std::min(nextDelay,(unsigned long)ZT_WHOIS_RETRY_DELAY);
+ ++txi;
}
} else {
- nextDelay = std::min(nextDelay,ZT_WHOIS_RETRY_DELAY - since);
+ ++txi;
}
}
}
+}
+
+unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now)
+{
+ const uint64_t timeSinceLastCheck = now - _lastCheckedQueues;
+ if (timeSinceLastCheck < ZT_WHOIS_RETRY_DELAY)
+ return (unsigned long)(ZT_WHOIS_RETRY_DELAY - timeSinceLastCheck);
+ _lastCheckedQueues = now;
- { // Time out TX queue packets that never got WHOIS lookups or other info.
+ std::vector<Address> needWhois;
+ {
Mutex::Lock _l(_txQueue_m);
for(std::list< TXQueueEntry >::iterator txi(_txQueue.begin());txi!=_txQueue.end();) {
- if (_trySend(tPtr,txi->packet,txi->encrypt))
+ if (_trySend(tPtr,txi->packet,txi->encrypt)) {
_txQueue.erase(txi++);
- else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) {
+ } else if ((now - txi->creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) {
RR->t->txTimedOut(tPtr,txi->dest);
_txQueue.erase(txi++);
- } else ++txi;
+ } else {
+ if (!RR->topology->getPeer(tPtr,txi->dest))
+ needWhois.push_back(txi->dest);
+ ++txi;
+ }
+ }
+ }
+ for(std::vector<Address>::const_iterator i(needWhois.begin());i!=needWhois.end();++i)
+ requestWhois(tPtr,now,*i);
+
+ for(unsigned int ptr=0;ptr<ZT_RX_QUEUE_SIZE;++ptr) {
+ RXQueueEntry *const rq = &(_rxQueue[ptr]);
+ if ((rq->timestamp)&&(rq->complete)) {
+ if ((rq->frag0.tryDecode(RR,tPtr))||((now - rq->timestamp) > ZT_RECEIVE_QUEUE_TIMEOUT)) {
+ rq->timestamp = 0;
+ } else {
+ const Address src(rq->frag0.source());
+ if (!RR->topology->getPeer(tPtr,src))
+ requestWhois(tPtr,now,src);
+ }
}
}
- { // Remove really old last unite attempt entries to keep table size controlled
+ {
Mutex::Lock _l(_lastUniteAttempt_m);
Hashtable< _LastUniteKey,uint64_t >::Iterator i(_lastUniteAttempt);
_LastUniteKey *k = (_LastUniteKey *)0;
@@ -650,7 +661,18 @@ unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now)
}
}
- return nextDelay;
+ {
+ Mutex::Lock _l(_lastSentWhoisRequest_m);
+ Hashtable< Address,uint64_t >::Iterator i(_lastSentWhoisRequest);
+ Address *a = (Address *)0;
+ uint64_t *ts = (uint64_t *)0;
+ while (i.next(a,ts)) {
+ if ((now - *ts) > (ZT_WHOIS_RETRY_DELAY * 2))
+ _lastSentWhoisRequest.erase(*a);
+ }
+ }
+
+ return ZT_WHOIS_RETRY_DELAY;
}
bool Switch::_shouldUnite(const uint64_t now,const Address &source,const Address &destination)
@@ -664,18 +686,6 @@ bool Switch::_shouldUnite(const uint64_t now,const Address &source,const Address
return false;
}
-Address Switch::_sendWhoisRequest(void *tPtr,const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted)
-{
- SharedPtr<Peer> upstream(RR->topology->getUpstreamPeer(peersAlreadyConsulted,numPeersAlreadyConsulted,false));
- if (upstream) {
- Packet outp(upstream->address(),RR->identity.address(),Packet::VERB_WHOIS);
- addr.appendTo(outp);
- RR->node->expectReplyTo(outp.packetId());
- send(tPtr,outp,true);
- }
- return Address();
-}
-
bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
{
SharedPtr<Path> viaPath;
@@ -709,14 +719,16 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
}
}
} else {
- requestWhois(tPtr,destination);
- return false; // if we are not in cluster mode, there is no way we can send without knowing the peer directly
+ return false;
}
- unsigned int chunkSize = std::min(packet.size(),(unsigned int)ZT_UDP_DEFAULT_PAYLOAD_MTU);
+ unsigned int mtu = ZT_DEFAULT_PHYSMTU;
+ uint64_t trustedPathId = 0;
+ RR->topology->getOutboundPathInfo(viaPath->address(),mtu,trustedPathId);
+
+ unsigned int chunkSize = std::min(packet.size(),mtu);
packet.setFragmented(chunkSize < packet.size());
- const uint64_t trustedPathId = RR->topology->getOutboundPathTrust(viaPath->address());
if (trustedPathId) {
packet.setTrusted(trustedPathId);
} else {
@@ -728,13 +740,13 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
// Too big for one packet, fragment the rest
unsigned int fragStart = chunkSize;
unsigned int remaining = packet.size() - chunkSize;
- unsigned int fragsRemaining = (remaining / (ZT_UDP_DEFAULT_PAYLOAD_MTU - ZT_PROTO_MIN_FRAGMENT_LENGTH));
- if ((fragsRemaining * (ZT_UDP_DEFAULT_PAYLOAD_MTU - ZT_PROTO_MIN_FRAGMENT_LENGTH)) < remaining)
+ unsigned int fragsRemaining = (remaining / (mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH));
+ if ((fragsRemaining * (mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH)) < remaining)
++fragsRemaining;
const unsigned int totalFragments = fragsRemaining + 1;
for(unsigned int fno=1;fno<totalFragments;++fno) {
- chunkSize = std::min(remaining,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - ZT_PROTO_MIN_FRAGMENT_LENGTH));
+ chunkSize = std::min(remaining,(unsigned int)(mtu - ZT_PROTO_MIN_FRAGMENT_LENGTH));
Packet::Fragment frag(packet,fragStart,chunkSize,fno,totalFragments);
viaPath->send(RR,tPtr,frag.data(),frag.size(),now);
fragStart += chunkSize;
diff --git a/node/Switch.hpp b/node/Switch.hpp
index 114bc5e1..c258a255 100644
--- a/node/Switch.hpp
+++ b/node/Switch.hpp
@@ -111,9 +111,10 @@ public:
* Request WHOIS on a given address
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
+ * @param now Current time
* @param addr Address to look up
*/
- void requestWhois(void *tPtr,const Address &addr);
+ void requestWhois(void *tPtr,const uint64_t now,const Address &addr);
/**
* Run any processes that are waiting for this peer's identity
@@ -139,34 +140,27 @@ public:
private:
bool _shouldUnite(const uint64_t now,const Address &source,const Address &destination);
- Address _sendWhoisRequest(void *tPtr,const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted);
bool _trySend(void *tPtr,Packet &packet,bool encrypt); // packet is modified if return is true
const RuntimeEnvironment *const RR;
uint64_t _lastBeaconResponse;
+ volatile uint64_t _lastCheckedQueues;
- // Outstanding WHOIS requests and how many retries they've undergone
- struct WhoisRequest
- {
- WhoisRequest() : lastSent(0),retries(0) {}
- uint64_t lastSent;
- Address peersConsulted[ZT_MAX_WHOIS_RETRIES]; // by retry
- unsigned int retries; // 0..ZT_MAX_WHOIS_RETRIES
- };
- Hashtable< Address,WhoisRequest > _outstandingWhoisRequests;
- Mutex _outstandingWhoisRequests_m;
+ // Time we last sent a WHOIS request for each address
+ Hashtable< Address,uint64_t > _lastSentWhoisRequest;
+ Mutex _lastSentWhoisRequest_m;
// Packets waiting for WHOIS replies or other decode info or missing fragments
struct RXQueueEntry
{
RXQueueEntry() : timestamp(0) {}
- uint64_t timestamp; // 0 if entry is not in use
- uint64_t packetId;
+ volatile uint64_t timestamp; // 0 if entry is not in use
+ volatile uint64_t packetId;
IncomingPacket frag0; // head of packet
Packet::Fragment frags[ZT_MAX_PACKET_FRAGMENTS - 1]; // later fragments (if any)
unsigned int totalFragments; // 0 if only frag0 received, waiting for frags
uint32_t haveFragments; // bit mask, LSB to MSB
- bool complete; // if true, packet is complete
+ volatile bool complete; // if true, packet is complete
};
RXQueueEntry _rxQueue[ZT_RX_QUEUE_SIZE];
AtomicCounter _rxQueuePtr;
@@ -174,19 +168,20 @@ private:
// Returns matching or next available RX queue entry
inline RXQueueEntry *_findRXQueueEntry(uint64_t packetId)
{
- unsigned int ptr = static_cast<unsigned int>(_rxQueuePtr.load());
- for(unsigned int k=0;k<ZT_RX_QUEUE_SIZE;++k) {
- RXQueueEntry *rq = &(_rxQueue[--ptr % ZT_RX_QUEUE_SIZE]);
+ const unsigned int current = static_cast<unsigned int>(_rxQueuePtr.load());
+ for(unsigned int k=1;k<=ZT_RX_QUEUE_SIZE;++k) {
+ RXQueueEntry *rq = &(_rxQueue[(current - k) % ZT_RX_QUEUE_SIZE]);
if ((rq->packetId == packetId)&&(rq->timestamp))
return rq;
}
- return &(_rxQueue[static_cast<unsigned int>(++_rxQueuePtr) % ZT_RX_QUEUE_SIZE]);
+ ++_rxQueuePtr;
+ return &(_rxQueue[static_cast<unsigned int>(current) % ZT_RX_QUEUE_SIZE]);
}
- // Returns next RX queue entry in ring buffer and increments ring counter
+ // Returns current entry in rx queue ring buffer and increments ring pointer
inline RXQueueEntry *_nextRXQueueEntry()
{
- return &(_rxQueue[static_cast<unsigned int>(++_rxQueuePtr) % ZT_RX_QUEUE_SIZE]);
+ return &(_rxQueue[static_cast<unsigned int>((++_rxQueuePtr) - 1) % ZT_RX_QUEUE_SIZE]);
}
// ZeroTier-layer TX queue entry
diff --git a/node/Tag.cpp b/node/Tag.cpp
index 39b17f2a..bde41a70 100644
--- a/node/Tag.cpp
+++ b/node/Tag.cpp
@@ -30,6 +30,7 @@
#include "Topology.hpp"
#include "Switch.hpp"
#include "Network.hpp"
+#include "Node.hpp"
namespace ZeroTier {
@@ -39,7 +40,7 @@ int Tag::verify(const RuntimeEnvironment *RR,void *tPtr) const
return -1;
const Identity id(RR->topology->getIdentity(tPtr,_signedBy));
if (!id) {
- RR->sw->requestWhois(tPtr,_signedBy);
+ RR->sw->requestWhois(tPtr,RR->node->now(),_signedBy);
return 1;
}
try {
diff --git a/node/Topology.cpp b/node/Topology.cpp
index edca0180..905b6a91 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -65,7 +65,7 @@ static const unsigned char ZT_DEFAULT_WORLD[ZT_DEFAULT_WORLD_LENGTH] = {0x01,0x0
Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
RR(renv),
- _trustedPathCount(0),
+ _numConfiguredPhysicalPaths(0),
_amRoot(false)
{
uint8_t tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH];
@@ -88,6 +88,15 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
addWorld(tPtr,defaultPlanet,false);
}
+Topology::~Topology()
+{
+ Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
+ Address *a = (Address *)0;
+ SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
+ while (i.next(a,p))
+ _savePeer((void *)0,*p);
+}
+
SharedPtr<Peer> Topology::addPeer(void *tPtr,const SharedPtr<Peer> &peer)
{
SharedPtr<Peer> np;
@@ -113,23 +122,21 @@ SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta)
return *ap;
}
- /*
try {
- char buf[ZT_PEER_MAX_SERIALIZED_STATE_SIZE];
+ Buffer<ZT_PEER_MAX_SERIALIZED_STATE_SIZE> buf;
uint64_t idbuf[2]; idbuf[0] = zta.toInt(); idbuf[1] = 0;
- int len = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,idbuf,buf,(unsigned int)sizeof(buf));
+ int len = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,idbuf,buf.unsafeData(),ZT_PEER_MAX_SERIALIZED_STATE_SIZE);
if (len > 0) {
Mutex::Lock _l(_peers_m);
SharedPtr<Peer> &ap = _peers[zta];
if (ap)
return ap;
- ap = Peer::createFromStateUpdate(RR,tPtr,buf,len);
+ ap = Peer::deserializeFromCache(RR->node->now(),tPtr,buf,RR);
if (!ap)
_peers.erase(zta);
return ap;
}
} catch ( ... ) {} // ignore invalid identities or other strage failures
- */
return SharedPtr<Peer>();
}
@@ -147,13 +154,11 @@ Identity Topology::getIdentity(void *tPtr,const Address &zta)
return Identity();
}
-SharedPtr<Peer> Topology::getUpstreamPeer(const Address *avoid,unsigned int avoidCount,bool strictAvoid)
+SharedPtr<Peer> Topology::getUpstreamPeer()
{
const uint64_t now = RR->node->now();
- unsigned int bestQualityOverall = ~((unsigned int)0);
- unsigned int bestQualityNotAvoid = ~((unsigned int)0);
- const SharedPtr<Peer> *bestOverall = (const SharedPtr<Peer> *)0;
- const SharedPtr<Peer> *bestNotAvoid = (const SharedPtr<Peer> *)0;
+ unsigned int bestq = ~((unsigned int)0);
+ const SharedPtr<Peer> *best = (const SharedPtr<Peer> *)0;
Mutex::Lock _l1(_peers_m);
Mutex::Lock _l2(_upstreams_m);
@@ -161,32 +166,17 @@ SharedPtr<Peer> Topology::getUpstreamPeer(const Address *avoid,unsigned int avoi
for(std::vector<Address>::const_iterator a(_upstreamAddresses.begin());a!=_upstreamAddresses.end();++a) {
const SharedPtr<Peer> *p = _peers.get(*a);
if (p) {
- bool avoiding = false;
- for(unsigned int i=0;i<avoidCount;++i) {
- if (avoid[i] == (*p)->address()) {
- avoiding = true;
- break;
- }
- }
const unsigned int q = (*p)->relayQuality(now);
- if (q <= bestQualityOverall) {
- bestQualityOverall = q;
- bestOverall = &(*p);
- }
- if ((!avoiding)&&(q <= bestQualityNotAvoid)) {
- bestQualityNotAvoid = q;
- bestNotAvoid = &(*p);
+ if (q <= bestq) {
+ bestq = q;
+ best = p;
}
}
}
- if (bestNotAvoid) {
- return *bestNotAvoid;
- } else if ((!strictAvoid)&&(bestOverall)) {
- return *bestOverall;
- }
-
- return SharedPtr<Peer>();
+ if (!best)
+ return SharedPtr<Peer>();
+ return *best;
}
bool Topology::isUpstream(const Identity &id) const
@@ -383,8 +373,10 @@ void Topology::doPeriodicTasks(void *tPtr,uint64_t now)
Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
while (i.next(a,p)) {
- if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) )
+ if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) ) {
+ _savePeer(tPtr,*p);
_peers.erase(*a);
+ }
}
}
@@ -440,4 +432,14 @@ void Topology::_memoizeUpstreams(void *tPtr)
_cor.sign(RR->identity,RR->node->now());
}
+void Topology::_savePeer(void *tPtr,const SharedPtr<Peer> &peer)
+{
+ try {
+ Buffer<ZT_PEER_MAX_SERIALIZED_STATE_SIZE> buf;
+ peer->serialize(buf);
+ uint64_t tmpid[2]; tmpid[0] = peer->address().toInt(); tmpid[1] = 0;
+ RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER,tmpid,buf.data(),buf.size());
+ } catch ( ... ) {} // sanity check, discard invalid entries
+}
+
} // namespace ZeroTier
diff --git a/node/Topology.hpp b/node/Topology.hpp
index 30e58abc..34df28a1 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -59,6 +59,7 @@ class Topology
{
public:
Topology(const RuntimeEnvironment *renv,void *tPtr);
+ ~Topology();
/**
* Add a peer to database
@@ -126,19 +127,9 @@ public:
/**
* Get the current best upstream peer
*
- * @return Root server with lowest latency or NULL if none
+ * @return Upstream or NULL if none available
*/
- inline SharedPtr<Peer> getUpstreamPeer() { return getUpstreamPeer((const Address *)0,0,false); }
-
- /**
- * Get the current best upstream peer, avoiding those in the supplied avoid list
- *
- * @param avoid Nodes to avoid
- * @param avoidCount Number of nodes to avoid
- * @param strictAvoid If false, consider avoided root servers anyway if no non-avoid root servers are available
- * @return Root server or NULL if none available
- */
- SharedPtr<Peer> getUpstreamPeer(const Address *avoid,unsigned int avoidCount,bool strictAvoid);
+ SharedPtr<Peer> getUpstreamPeer();
/**
* @param id Identity to check
@@ -349,6 +340,41 @@ public:
inline bool amRoot() const { return _amRoot; }
/**
+ * Get info about a path
+ *
+ * The supplied result variables are not modified if no special config info is found.
+ *
+ * @param physicalAddress Physical endpoint address
+ * @param mtu Variable set to MTU
+ * @param trustedPathId Variable set to trusted path ID
+ */
+ inline void getOutboundPathInfo(const InetAddress &physicalAddress,unsigned int &mtu,uint64_t &trustedPathId)
+ {
+ for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
+ if (_physicalPathConfig[i].first.containsAddress(physicalAddress)) {
+ trustedPathId = _physicalPathConfig[i].second.trustedPathId;
+ mtu = _physicalPathConfig[i].second.mtu;
+ return;
+ }
+ }
+ }
+
+ /**
+ * Get the payload MTU for an outbound physical path (returns default if not configured)
+ *
+ * @param physicalAddress Physical endpoint address
+ * @return MTU
+ */
+ inline unsigned int getOutboundPathMtu(const InetAddress &physicalAddress)
+ {
+ for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
+ if (_physicalPathConfig[i].first.containsAddress(physicalAddress))
+ return _physicalPathConfig[i].second.mtu;
+ }
+ return ZT_DEFAULT_PHYSMTU;
+ }
+
+ /**
* Get the outbound trusted path ID for a physical address, or 0 if none
*
* @param physicalAddress Physical address to which we are sending the packet
@@ -356,9 +382,9 @@ public:
*/
inline uint64_t getOutboundPathTrust(const InetAddress &physicalAddress)
{
- for(unsigned int i=0;i<_trustedPathCount;++i) {
- if (_trustedPathNetworks[i].containsAddress(physicalAddress))
- return _trustedPathIds[i];
+ for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
+ if (_physicalPathConfig[i].first.containsAddress(physicalAddress))
+ return _physicalPathConfig[i].second.trustedPathId;
}
return 0;
}
@@ -371,30 +397,48 @@ public:
*/
inline bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId)
{
- for(unsigned int i=0;i<_trustedPathCount;++i) {
- if ((_trustedPathIds[i] == trustedPathId)&&(_trustedPathNetworks[i].containsAddress(physicalAddress)))
+ for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i) {
+ if ((_physicalPathConfig[i].second.trustedPathId == trustedPathId)&&(_physicalPathConfig[i].first.containsAddress(physicalAddress)))
return true;
}
return false;
}
/**
- * Set trusted paths in this topology
- *
- * @param networks Array of networks (prefix/netmask bits)
- * @param ids Array of trusted path IDs
- * @param count Number of trusted paths (if larger than ZT_MAX_TRUSTED_PATHS overflow is ignored)
+ * Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration)
*/
- inline void setTrustedPaths(const InetAddress *networks,const uint64_t *ids,unsigned int count)
+ inline void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
{
- if (count > ZT_MAX_TRUSTED_PATHS)
- count = ZT_MAX_TRUSTED_PATHS;
- Mutex::Lock _l(_trustedPaths_m);
- for(unsigned int i=0;i<count;++i) {
- _trustedPathIds[i] = ids[i];
- _trustedPathNetworks[i] = networks[i];
+ if (!pathNetwork) {
+ _numConfiguredPhysicalPaths = 0;
+ } else {
+ std::map<InetAddress,ZT_PhysicalPathConfiguration> cpaths;
+ for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i<j;++i)
+ cpaths[_physicalPathConfig[i].first] = _physicalPathConfig[i].second;
+
+ if (pathConfig) {
+ ZT_PhysicalPathConfiguration pc(*pathConfig);
+
+ if (pc.mtu <= 0)
+ pc.mtu = ZT_DEFAULT_PHYSMTU;
+ else if (pc.mtu < ZT_MIN_PHYSMTU)
+ pc.mtu = ZT_MIN_PHYSMTU;
+ else if (pc.mtu > ZT_MAX_PHYSMTU)
+ pc.mtu = ZT_MAX_PHYSMTU;
+
+ cpaths[*(reinterpret_cast<const InetAddress *>(pathNetwork))] = pc;
+ } else {
+ cpaths.erase(*(reinterpret_cast<const InetAddress *>(pathNetwork)));
+ }
+
+ unsigned int cnt = 0;
+ for(std::map<InetAddress,ZT_PhysicalPathConfiguration>::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cnt<ZT_MAX_CONFIGURABLE_PATHS));++i) {
+ _physicalPathConfig[cnt].first = i->first;
+ _physicalPathConfig[cnt].second = i->second;
+ ++cnt;
+ }
+ _numConfiguredPhysicalPaths = cnt;
}
- _trustedPathCount = count;
}
/**
@@ -419,13 +463,12 @@ public:
private:
Identity _getIdentity(void *tPtr,const Address &zta);
void _memoizeUpstreams(void *tPtr);
+ void _savePeer(void *tPtr,const SharedPtr<Peer> &peer);
const RuntimeEnvironment *const RR;
- uint64_t _trustedPathIds[ZT_MAX_TRUSTED_PATHS];
- InetAddress _trustedPathNetworks[ZT_MAX_TRUSTED_PATHS];
- unsigned int _trustedPathCount;
- Mutex _trustedPaths_m;
+ std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
+ volatile unsigned int _numConfiguredPhysicalPaths;
Hashtable< Address,SharedPtr<Peer> > _peers;
Mutex _peers_m;
diff --git a/node/Trace.cpp b/node/Trace.cpp
index 98a4adcb..8e78b676 100644
--- a/node/Trace.cpp
+++ b/node/Trace.cpp
@@ -164,12 +164,7 @@ void Trace::incomingNetworkFrameDropped(void *const tPtr,const SharedPtr<Network
_send(tPtr,d,*network);
}
-void Trace::incomingPacketTrustedPath(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const uint64_t trustedPathId,bool approved)
-{
- // TODO
-}
-
-void Trace::incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops)
+void Trace::incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const char *reason)
{
char tmp[128];
Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
@@ -179,6 +174,8 @@ void Trace::incomingPacketMessageAuthenticationFailure(void *const tPtr,const Sh
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_ZTADDR,source);
d.add(ZT_REMOTE_TRACE_FIELD__REMOTE_PHYADDR,path->address().toString(tmp));
d.add(ZT_REMOTE_TRACE_FIELD__LOCAL_SOCKET,path->localSocket());
+ if (reason)
+ d.add(ZT_REMOTE_TRACE_FIELD__REASON,reason);
_send(tPtr,d,0);
}
@@ -344,76 +341,6 @@ void Trace::credentialRejected(void *const tPtr,const Revocation &c,const char *
_send(tPtr,d,c.networkId());
}
-void Trace::credentialAccepted(void *const tPtr,const CertificateOfMembership &c)
-{
- Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
- d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S);
- d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
- _send(tPtr,d,c.networkId());
-}
-
-void Trace::credentialAccepted(void *const tPtr,const CertificateOfOwnership &c)
-{
- Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
- d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S);
- d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
- _send(tPtr,d,c.networkId());
-}
-
-void Trace::credentialAccepted(void *const tPtr,const CertificateOfRepresentation &c)
-{
- Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
- d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S);
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
- _send(tPtr,d,0);
-}
-
-void Trace::credentialAccepted(void *const tPtr,const Capability &c)
-{
- Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
- d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S);
- d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
- _send(tPtr,d,c.networkId());
-}
-
-void Trace::credentialAccepted(void *const tPtr,const Tag &c)
-{
- Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
- d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S);
- d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TIMESTAMP,c.timestamp());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ISSUED_TO,c.issuedTo());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_INFO,(uint64_t)c.value());
- _send(tPtr,d,c.networkId());
-}
-
-void Trace::credentialAccepted(void *const tPtr,const Revocation &c)
-{
- Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> d;
- d.add(ZT_REMOTE_TRACE_FIELD__EVENT,ZT_REMOTE_TRACE_EVENT__CREDENTIAL_ACCEPTED_S);
- d.add(ZT_REMOTE_TRACE_FIELD__NETWORK_ID,c.networkId());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_TYPE,(uint64_t)c.credentialType());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_ID,(uint64_t)c.id());
- d.add(ZT_REMOTE_TRACE_FIELD__CREDENTIAL_REVOCATION_TARGET,c.target());
- _send(tPtr,d,c.networkId());
-}
-
void Trace::_send(void *const tPtr,const Dictionary<ZT_MAX_REMOTE_TRACE_SIZE> &d)
{
#ifdef ZT_TRACE
diff --git a/node/Trace.hpp b/node/Trace.hpp
index d66d0871..a7b2b194 100644
--- a/node/Trace.hpp
+++ b/node/Trace.hpp
@@ -108,8 +108,7 @@ public:
void peerLearnedNewPath(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &oldPath,const SharedPtr<Path> &newPath,const uint64_t packetId);
void peerRedirected(void *const tPtr,const uint64_t networkId,Peer &peer,const SharedPtr<Path> &oldPath,const SharedPtr<Path> &newPath);
- void incomingPacketTrustedPath(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const uint64_t trustedPathId,bool approved);
- void incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops);
+ void incomingPacketMessageAuthenticationFailure(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const char *reason);
void incomingPacketInvalid(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const unsigned int hops,const Packet::Verb verb,const char *reason);
void incomingPacketDroppedHELLO(void *const tPtr,const SharedPtr<Path> &path,const uint64_t packetId,const Address &source,const char *reason);
@@ -142,12 +141,6 @@ public:
void credentialRejected(void *const tPtr,const Capability &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 credentialAccepted(void *const tPtr,const CertificateOfMembership &c);
- void credentialAccepted(void *const tPtr,const CertificateOfOwnership &c);
- void credentialAccepted(void *const tPtr,const CertificateOfRepresentation &c);
- void credentialAccepted(void *const tPtr,const Capability &c);
- void credentialAccepted(void *const tPtr,const Tag &c);
- void credentialAccepted(void *const tPtr,const Revocation &c);
private:
const RuntimeEnvironment *const RR;