It almost compiles again

This commit is contained in:
Adam Ierymenko 2020-02-07 13:54:17 -08:00
parent df4b1e9b12
commit 60de5ed3dd
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
24 changed files with 456 additions and 284 deletions

View file

@ -328,6 +328,9 @@ enum ZT_CredentialType
*/ */
enum ZT_TraceEventType enum ZT_TraceEventType
{ {
/* An unexpected error is an internal assertion / sanity check failure, out of memory, etc. */
ZT_TRACE_UNEXPECTED_ERROR = 0,
/* VL1 events related to the peer-to-peer layer */ /* VL1 events related to the peer-to-peer layer */
ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE = 1, ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE = 1,
ZT_TRACE_VL1_TRYING_NEW_PATH = 2, ZT_TRACE_VL1_TRYING_NEW_PATH = 2,
@ -433,16 +436,25 @@ ZT_PACKED_STRUCT(struct ZT_TraceEventPathAddress
*/ */
ZT_PACKED_STRUCT(struct ZT_TraceEvent ZT_PACKED_STRUCT(struct ZT_TraceEvent
{ {
uint16_t evSize; /* sizeof(ZT_TraceEvent_XX structure) (inclusive size in bytes) */ uint16_t evSize; /* sizeof(ZT_TraceEvent_XX structure) (inclusive) */
uint16_t evType; /* ZT_TraceEventType */ uint16_t evType; /* ZT_TraceEventType */
uint32_t codeLocation; /* arbitrary identifier of location in source code */
}); });
/* Temporary macros to make it easier to declare all ZT_TraceEvent's sub-types */ /* Temporary macros to make it easier to declare all ZT_TraceEvent's sub-types */
#define _ZT_TRACE_EVENT_STRUCT_START(e) ZT_PACKED_STRUCT_START struct ZT_TraceEvent_##e { \ #define _ZT_TRACE_EVENT_STRUCT_START(e) ZT_PACKED_STRUCT_START struct ZT_TraceEvent_##e { \
uint16_t evSize; \ uint16_t evSize; \
uint16_t evType; uint16_t evType; \
uint32_t codeLocation;
#define _ZT_TRACE_EVENT_STRUCT_END() } ZT_PACKED_STRUCT_END; #define _ZT_TRACE_EVENT_STRUCT_END() } ZT_PACKED_STRUCT_END;
/**
* An unexpected or internal error occurred
*/
_ZT_TRACE_EVENT_STRUCT_START(UNEXPECTED_ERROR)
char message[256]; /* arbitrary human-readable message */
_ZT_TRACE_EVENT_STRUCT_END()
/** /**
* Node is resetting all paths in a given address scope * Node is resetting all paths in a given address scope
* *

View file

@ -66,7 +66,7 @@ void *_Buf_get()
#else #else
s_pool.store(bb); s_pool.store(bb);
#endif #endif
b = (Buf *)malloc(sizeof(Buf<>)); b = (Buf *)malloc(sizeof(Buf));
if (!b) if (!b)
throw std::bad_alloc(); throw std::bad_alloc();
} else { } else {

View file

@ -19,8 +19,8 @@
#include "CertificateOfMembership.hpp" #include "CertificateOfMembership.hpp"
#include "CertificateOfOwnership.hpp" #include "CertificateOfOwnership.hpp"
#include "Revocation.hpp" #include "Revocation.hpp"
#include "Switch.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Topology.hpp"
// These are compile-time asserts to make sure temporary marshal buffers here and // These are compile-time asserts to make sure temporary marshal buffers here and
// also in NtworkConfig.cpp are always large enough to marshal all credential types. // also in NtworkConfig.cpp are always large enough to marshal all credential types.

View file

@ -14,17 +14,17 @@
#ifndef ZT_ENDPOINT_HPP #ifndef ZT_ENDPOINT_HPP
#define ZT_ENDPOINT_HPP #define ZT_ENDPOINT_HPP
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include "Constants.hpp" #include "Constants.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "TriviallyCopyable.hpp" #include "TriviallyCopyable.hpp"
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
// max name size + type byte + port (for DNS name/port) + 3x 16-bit coordinate for location // max name size + type byte + port (for DNS name/port) + 3x 16-bit coordinate for location
#define ZT_ENDPOINT_MARSHAL_SIZE_MAX (ZT_ENDPOINT_MAX_NAME_SIZE+1+2+2+2+2) #define ZT_ENDPOINT_MARSHAL_SIZE_MAX (ZT_ENDPOINT_MAX_NAME_SIZE+1+2+2+2+2)

View file

@ -83,6 +83,8 @@ struct _Identity_generate_cond
} // anonymous namespace } // anonymous namespace
const Identity Identity::NIL;
void Identity::generate(const Type t) void Identity::generate(const Type t)
{ {
uint8_t digest[64]; uint8_t digest[64];

View file

@ -56,6 +56,11 @@ public:
P384 = ZT_CRYPTO_ALG_P384 // Type 1 -- NIST P-384 with linked Curve25519/Ed25519 secondaries (2.x+) P384 = ZT_CRYPTO_ALG_P384 // Type 1 -- NIST P-384 with linked Curve25519/Ed25519 secondaries (2.x+)
}; };
/**
* A nil/empty identity instance
*/
static const Identity NIL;
ZT_ALWAYS_INLINE Identity() { memoryZero(this); } ZT_ALWAYS_INLINE Identity() { memoryZero(this); }
ZT_ALWAYS_INLINE ~Identity() { Utils::burn(reinterpret_cast<void *>(&this->_priv),sizeof(this->_priv)); } ZT_ALWAYS_INLINE ~Identity() { Utils::burn(reinterpret_cast<void *>(&this->_priv),sizeof(this->_priv)); }

View file

@ -87,57 +87,57 @@ public:
ZT_ALWAYS_INLINE InetAddress() { memoryZero(this); } ZT_ALWAYS_INLINE InetAddress() { memoryZero(this); }
ZT_ALWAYS_INLINE InetAddress(const InetAddress &a) { memoryCopy(this,&a); } ZT_ALWAYS_INLINE InetAddress(const InetAddress &a) { memoryCopy(this,&a); }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage &ss) { *this = ss; } explicit ZT_ALWAYS_INLINE InetAddress(const sockaddr_storage &ss) { *this = ss; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_storage *ss) { *this = ss; } explicit ZT_ALWAYS_INLINE InetAddress(const sockaddr_storage *ss) { *this = ss; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr &sa) { *this = sa; } explicit ZT_ALWAYS_INLINE InetAddress(const sockaddr &sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr *sa) { *this = sa; } explicit ZT_ALWAYS_INLINE InetAddress(const sockaddr *sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in &sa) { *this = sa; } explicit ZT_ALWAYS_INLINE InetAddress(const sockaddr_in &sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in *sa) { *this = sa; } explicit ZT_ALWAYS_INLINE InetAddress(const sockaddr_in *sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 &sa) { *this = sa; } explicit ZT_ALWAYS_INLINE InetAddress(const sockaddr_in6 &sa) { *this = sa; }
explicit ZT_ALWAYS_INLINE InetAddress(const struct sockaddr_in6 *sa) { *this = sa; } explicit ZT_ALWAYS_INLINE InetAddress(const sockaddr_in6 *sa) { *this = sa; }
ZT_ALWAYS_INLINE InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); } ZT_ALWAYS_INLINE InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); }
ZT_ALWAYS_INLINE InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); } ZT_ALWAYS_INLINE InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); }
explicit ZT_ALWAYS_INLINE InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); } explicit ZT_ALWAYS_INLINE InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); }
ZT_ALWAYS_INLINE void clear() { memoryZero(this); } ZT_ALWAYS_INLINE void clear() { memoryZero(this); }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_storage &ss) ZT_ALWAYS_INLINE InetAddress &operator=(const sockaddr_storage &ss)
{ {
memoryCopyUnsafe(this,&ss); memoryCopyUnsafe(this,&ss);
return *this; return *this;
} }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_storage *ss) ZT_ALWAYS_INLINE InetAddress &operator=(const sockaddr_storage *ss)
{ {
if (ss) if (ss)
memoryCopyUnsafe(this,ss); memoryCopyUnsafe(this,ss);
else memoryZero(this); else memoryZero(this);
return *this; return *this;
} }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in &sa) ZT_ALWAYS_INLINE InetAddress &operator=(const sockaddr_in &sa)
{ {
copySockaddrToThis(&sa); copySockaddrToThis(&sa);
return *this; return *this;
} }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in *sa) ZT_ALWAYS_INLINE InetAddress &operator=(const sockaddr_in *sa)
{ {
if (sa) if (sa)
copySockaddrToThis(sa); copySockaddrToThis(sa);
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress)); else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
return *this; return *this;
} }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in6 &sa) ZT_ALWAYS_INLINE InetAddress &operator=(const sockaddr_in6 &sa)
{ {
copySockaddrToThis(&sa); copySockaddrToThis(&sa);
return *this; return *this;
} }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr_in6 *sa) ZT_ALWAYS_INLINE InetAddress &operator=(const sockaddr_in6 *sa)
{ {
if (sa) if (sa)
copySockaddrToThis(sa); copySockaddrToThis(sa);
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress)); else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
return *this; return *this;
} }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr &sa) ZT_ALWAYS_INLINE InetAddress &operator=(const sockaddr &sa)
{ {
if (sa.sa_family == AF_INET) if (sa.sa_family == AF_INET)
copySockaddrToThis(reinterpret_cast<const sockaddr_in *>(&sa)); copySockaddrToThis(reinterpret_cast<const sockaddr_in *>(&sa));
@ -146,7 +146,7 @@ public:
else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress)); else memset(reinterpret_cast<void *>(this),0,sizeof(InetAddress));
return *this; return *this;
} }
ZT_ALWAYS_INLINE InetAddress &operator=(const struct sockaddr *sa) ZT_ALWAYS_INLINE InetAddress &operator=(const sockaddr *sa)
{ {
if (sa) { if (sa) {
if (sa->sa_family == AF_INET) if (sa->sa_family == AF_INET)

View file

@ -14,14 +14,14 @@
#ifndef ZT_MULTICASTGROUP_HPP #ifndef ZT_MULTICASTGROUP_HPP
#define ZT_MULTICASTGROUP_HPP #define ZT_MULTICASTGROUP_HPP
#include <cstdint>
#include "Constants.hpp" #include "Constants.hpp"
#include "MAC.hpp" #include "MAC.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "TriviallyCopyable.hpp" #include "TriviallyCopyable.hpp"
#include <cstdint>
namespace ZeroTier { namespace ZeroTier {
/** /**
@ -64,7 +64,7 @@ public:
// multicast address directly from the IP address, and it gives us // multicast address directly from the IP address, and it gives us
// 24 bits of uniqueness. Collisions aren't likely to be common enough // 24 bits of uniqueness. Collisions aren't likely to be common enough
// to care about. // to care about.
const uint8_t *a = (const uint8_t *)ip.rawIpData(); const uint8_t *const a = reinterpret_cast<const uint8_t *>(ip.rawIpData());
return MulticastGroup(MAC(0x33,0x33,0xff,a[13],a[14],a[15]),0); return MulticastGroup(MAC(0x33,0x33,0xff,a[13],a[14],a[15]),0);
} }
return MulticastGroup(); return MulticastGroup();

View file

@ -196,7 +196,7 @@ public:
* @param size Size of data in chunk buffer (total, not relative to ptr) * @param size Size of data in chunk buffer (total, not relative to ptr)
* @return Update ID if update was fully assembled and accepted or 0 otherwise * @return Update ID if update was fully assembled and accepted or 0 otherwise
*/ */
uint64_t handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr<Peer> &source,const Buf<> &chunk,int ptr,int size); uint64_t handleConfigChunk(void *tPtr,uint64_t packetId,const SharedPtr<Peer> &source,const Buf &chunk,int ptr,int size);
/** /**
* Set network configuration * Set network configuration

View file

@ -65,7 +65,7 @@ public:
void operator delete(void* p) { _mm_free(p); } void operator delete(void* p) { _mm_free(p); }
#endif #endif
// Public API Functions ---------------------------------------------------- // Public API Functions ---------------------------------------------------------------------------------------------
ZT_ResultCode processWirePacket( ZT_ResultCode processWirePacket(
void *tptr, void *tptr,
@ -104,7 +104,7 @@ public:
int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len); int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
void setController(void *networkControllerInstance); void setController(void *networkControllerInstance);
// Internal functions ------------------------------------------------------ // Internal functions -----------------------------------------------------------------------------------------------
/** /**
* @return Most recent time value supplied to core via API * @return Most recent time value supplied to core via API

View file

@ -12,14 +12,15 @@
/****/ /****/
#include "Constants.hpp" #include "Constants.hpp"
#include "RuntimeEnvironment.hpp"
#include "Trace.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "Topology.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "Switch.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "SelfAwareness.hpp" #include "SelfAwareness.hpp"
#include "Packet.hpp"
#include "Trace.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "Protocol.hpp"
#include <set> #include <set>
@ -43,7 +44,11 @@ Peer::Peer(const RuntimeEnvironment *renv) :
_lastTriedStaticPath(0), _lastTriedStaticPath(0),
_lastPrioritizedPaths(0), _lastPrioritizedPaths(0),
_latency(0xffff), _latency(0xffff),
_alivePathCount(0) _alivePathCount(0),
_vProto(0),
_vMajor(0),
_vMinor(0),
_vRevision(0)
{ {
} }
@ -52,10 +57,6 @@ bool Peer::init(const Identity &myIdentity,const Identity &peerIdentity)
if (_id == peerIdentity) if (_id == peerIdentity)
return true; return true;
_id = peerIdentity; _id = peerIdentity;
_vProto = 0;
_vMajor = 0;
_vMinor = 0;
_vRevision = 0;
return myIdentity.agree(peerIdentity,_key); return myIdentity.agree(peerIdentity,_key);
} }
@ -65,9 +66,9 @@ void Peer::received(
const unsigned int hops, const unsigned int hops,
const uint64_t packetId, const uint64_t packetId,
const unsigned int payloadLength, const unsigned int payloadLength,
const Packet::Verb verb, const Protocol::Verb verb,
const uint64_t inRePacketId, const uint64_t inRePacketId,
const Packet::Verb inReVerb, const Protocol::Verb inReVerb,
const uint64_t networkId) const uint64_t networkId)
{ {
const int64_t now = RR->node->now(); const int64_t now = RR->node->now();
@ -83,7 +84,7 @@ void Peer::received(
} }
_lock.runlock(); _lock.runlock();
if (verb == Packet::VERB_OK) { if (verb == Protocol::VERB_OK) {
RWMutex::Lock l(_lock); RWMutex::Lock l(_lock);
int64_t lastReceiveTimeMax = 0; int64_t lastReceiveTimeMax = 0;
@ -115,10 +116,10 @@ void Peer::received(
_paths[lastReceiveTimeMaxAt] = path; _paths[lastReceiveTimeMaxAt] = path;
_bootstrap = path->address(); _bootstrap = path->address();
_prioritizePaths(now); _prioritizePaths(now);
RR->t->learnedNewPath(tPtr,packetId,_id,path->address(),old); RR->t->learnedNewPath(tPtr,0x582fabdd,packetId,_id,path->address(),old);
} else { } else {
if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,path->localSocket(),path->address())) { if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,path->localSocket(),path->address())) {
RR->t->tryingNewPath(tPtr,_id,path->address(),path->address(),packetId,(uint8_t)verb,_id.address(),_id.hash(),ZT_TRACE_TRYING_NEW_PATH_REASON_PACKET_RECEIVED_FROM_UNKNOWN_PATH); RR->t->tryingNewPath(tPtr,0xb7747ddd,_id,path->address(),path->address(),packetId,(uint8_t)verb,_id.address(),_id.hash(),ZT_TRACE_TRYING_NEW_PATH_REASON_PACKET_RECEIVED_FROM_UNKNOWN_PATH);
sendHELLO(tPtr,path->localSocket(),path->address(),now); sendHELLO(tPtr,path->localSocket(),path->address(),now);
path->sent(now); path->sent(now);
} }
@ -131,11 +132,11 @@ path_check_done:
InetAddress addr; InetAddress addr;
if ((_bootstrap.type() == Endpoint::INETADDR_V4)||(_bootstrap.type() == Endpoint::INETADDR_V6)) { if ((_bootstrap.type() == Endpoint::INETADDR_V4)||(_bootstrap.type() == Endpoint::INETADDR_V6)) {
RR->t->tryingNewPath(tPtr,_id,_bootstrap.inetAddr(),InetAddress::NIL,0,0,0,nullptr,ZT_TRACE_TRYING_NEW_PATH_REASON_BOOTSTRAP_ADDRESS); RR->t->tryingNewPath(tPtr,0x0a009444,_id,_bootstrap.inetAddr(),InetAddress::NIL,0,0,0,nullptr,ZT_TRACE_TRYING_NEW_PATH_REASON_BOOTSTRAP_ADDRESS);
sendHELLO(tPtr,-1,_bootstrap.inetAddr(),now); sendHELLO(tPtr,-1,_bootstrap.inetAddr(),now);
} if (RR->node->externalPathLookup(tPtr,_id,-1,addr)) { } if (RR->node->externalPathLookup(tPtr,_id,-1,addr)) {
if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,-1,addr)) { if (RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id,-1,addr)) {
RR->t->tryingNewPath(tPtr,_id,_bootstrap.inetAddr(),InetAddress::NIL,0,0,0,nullptr,ZT_TRACE_TRYING_NEW_PATH_REASON_EXPLICITLY_SUGGESTED_ADDRESS); RR->t->tryingNewPath(tPtr,0x84a10000,_id,_bootstrap.inetAddr(),InetAddress::NIL,0,0,0,nullptr,ZT_TRACE_TRYING_NEW_PATH_REASON_EXPLICITLY_SUGGESTED_ADDRESS);
sendHELLO(tPtr,-1,addr,now); sendHELLO(tPtr,-1,addr,now);
} }
} }
@ -155,6 +156,7 @@ path_check_done:
} }
if (!addrs.empty()) { if (!addrs.empty()) {
#if 0
ScopedPtr<Packet> outp(new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS)); ScopedPtr<Packet> outp(new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS));
outp->addSize(2); // leave room for count outp->addSize(2); // leave room for count
unsigned int count = 0; unsigned int count = 0;
@ -197,6 +199,7 @@ path_check_done:
outp->armor(_key,true); outp->armor(_key,true);
path->send(RR,tPtr,outp->data(),outp->size(),now); path->send(RR,tPtr,outp->data(),outp->size(),now);
} }
#endif
} }
} }
} }
@ -222,6 +225,7 @@ bool Peer::shouldTryPath(void *tPtr,int64_t now,const SharedPtr<Peer> &suggested
void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now) void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now)
{ {
#if 0
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO); Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO);
outp.append((unsigned char)ZT_PROTO_VERSION); outp.append((unsigned char)ZT_PROTO_VERSION);
@ -240,6 +244,7 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
} else { } else {
RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC
} }
#endif
} }
void Peer::ping(void *tPtr,int64_t now,const bool pingAllAddressTypes) void Peer::ping(void *tPtr,int64_t now,const bool pingAllAddressTypes)

View file

@ -44,8 +44,12 @@ unsigned long long _packetIdCtr = _initPacketID();
static std::atomic<unsigned long long> _packetIdCtr(_initPacketID()); static std::atomic<unsigned long long> _packetIdCtr(_initPacketID());
#endif #endif
uintptr_t _checkStructureSizing() uintptr_t _checkSizes()
{ {
// These are compiled time checked assertions that make sure our platform/compiler is sane
// and that packed structures are working properly.
if (ZT_PROTO_MAX_PACKET_LENGTH > ZT_BUF_MEM_SIZE)
throw std::runtime_error("ZT_PROTO_MAX_PACKET_LENGTH > ZT_BUF_MEM_SIZE");
if (sizeof(Header) != ZT_PROTO_MIN_PACKET_LENGTH) if (sizeof(Header) != ZT_PROTO_MIN_PACKET_LENGTH)
throw std::runtime_error("sizeof(Header) != ZT_PROTO_MIN_PACKET_LENGTH"); throw std::runtime_error("sizeof(Header) != ZT_PROTO_MIN_PACKET_LENGTH");
if (sizeof(FragmentHeader) != ZT_PROTO_MIN_FRAGMENT_LENGTH) if (sizeof(FragmentHeader) != ZT_PROTO_MIN_FRAGMENT_LENGTH)
@ -55,7 +59,8 @@ uintptr_t _checkStructureSizing()
} // anonymous namespace } // anonymous namespace
volatile uintptr_t _compileTimeStructCheckHappened = _checkStructureSizing(); // Make compiler compile and "run" _checkSizes()
volatile uintptr_t _checkSizesIMeanIt = _checkSizes();
uint64_t getPacketId() uint64_t getPacketId()
{ {

View file

@ -50,6 +50,7 @@
* 10 - 1.4.0 ... 1.4.6 * 10 - 1.4.0 ... 1.4.6
* 11 - 2.0.0 ... CURRENT * 11 - 2.0.0 ... CURRENT
* + Peer-to-peer multicast replication * + Peer-to-peer multicast replication
* + HELLO and OK(HELLO) include an extra HMAC to further harden auth
* + Old planet/moon stuff is DEAD! * + Old planet/moon stuff is DEAD!
* + AES encryption support * + AES encryption support
* + NIST P-384 (type 1) identities * + NIST P-384 (type 1) identities
@ -152,7 +153,10 @@
#define ZT_PROTO_VERB_MASK 0x1fU #define ZT_PROTO_VERB_MASK 0x1fU
/** /**
* Key derivation function label for the key used with HMAC-384 in HELLO * Key derivation function label for the keys used with HMAC-384 in HELLO
*
* With the KDF the 'iter' parameter is 0 for the key used for
* HMAC in HELLO and 1 for the one used in OK(HELLO).
*/ */
#define ZT_PROTO_KDF_KEY_LABEL_HELLO_HMAC 'H' #define ZT_PROTO_KDF_KEY_LABEL_HELLO_HMAC 'H'
@ -284,6 +288,7 @@ enum Verb
* ordinary packet authentication. * ordinary packet authentication.
* *
* OK payload: * OK payload:
* [... HMAC-384 starts here ...]
* <[8] HELLO timestamp field echo> * <[8] HELLO timestamp field echo>
* <[1] protocol version> * <[1] protocol version>
* <[1] software major version> * <[1] software major version>
@ -293,6 +298,7 @@ enum Verb
* <[2] 16-bit reserved (legacy) field, always 0> * <[2] 16-bit reserved (legacy) field, always 0>
* <[2] 16-bit length of meta-data dictionary> * <[2] 16-bit length of meta-data dictionary>
* <[...] meta-data dictionary> * <[...] meta-data dictionary>
* <[2] 16-bit length of any additional fields>
* <[48] HMAC-SHA384 of all fields to this point (as plaintext)> * <[48] HMAC-SHA384 of all fields to this point (as plaintext)>
* *
* With the exception of the timestamp, the other fields pertain to the * With the exception of the timestamp, the other fields pertain to the
@ -824,26 +830,24 @@ namespace OK {
*/ */
ZT_PACKED_STRUCT(struct Header ZT_PACKED_STRUCT(struct Header
{ {
Protocol::Header h;
uint8_t inReVerb; uint8_t inReVerb;
uint64_t inRePacketId; uint64_t inRePacketId;
}); });
ZT_PACKED_STRUCT(struct WHOIS ZT_PACKED_STRUCT(struct WHOIS
{ {
Protocol::Header h; OK::Header h;
OK::Header oh;
}); });
ZT_PACKED_STRUCT(struct ECHO ZT_PACKED_STRUCT(struct ECHO
{ {
Protocol::Header h; OK::Header h;
OK::Header oh;
}); });
ZT_PACKED_STRUCT(struct HELLO ZT_PACKED_STRUCT(struct HELLO
{ {
Protocol::Header h; OK::Header h;
OK::Header oh;
uint64_t timestampEcho; uint64_t timestampEcho;
uint8_t versionProtocol; uint8_t versionProtocol;
uint8_t versionMajor; uint8_t versionMajor;
@ -853,8 +857,7 @@ ZT_PACKED_STRUCT(struct HELLO
ZT_PACKED_STRUCT(struct EXT_FRAME ZT_PACKED_STRUCT(struct EXT_FRAME
{ {
Protocol::Header h; OK::Header h;
OK::Header oh;
uint64_t networkId; uint64_t networkId;
uint8_t flags; uint8_t flags;
uint8_t destMac[6]; uint8_t destMac[6];
@ -864,8 +867,7 @@ ZT_PACKED_STRUCT(struct EXT_FRAME
ZT_PACKED_STRUCT(struct NETWORK_CONFIG ZT_PACKED_STRUCT(struct NETWORK_CONFIG
{ {
Protocol::Header h; OK::Header h;
OK::Header oh;
uint64_t networkId; uint64_t networkId;
uint64_t configUpdateId; uint64_t configUpdateId;
}); });
@ -883,6 +885,7 @@ namespace ERROR {
*/ */
ZT_PACKED_STRUCT(struct Header ZT_PACKED_STRUCT(struct Header
{ {
Protocol::Header h;
int8_t inReVerb; int8_t inReVerb;
uint64_t inRePacketId; uint64_t inRePacketId;
uint8_t error; uint8_t error;
@ -890,15 +893,13 @@ ZT_PACKED_STRUCT(struct Header
ZT_PACKED_STRUCT(struct NEED_MEMBERSHIP_CERTIFICATE ZT_PACKED_STRUCT(struct NEED_MEMBERSHIP_CERTIFICATE
{ {
Protocol::Header h; ERROR::Header h;
ERROR::Header eh;
uint64_t networkId; uint64_t networkId;
}); });
ZT_PACKED_STRUCT(struct UNSUPPORTED_OPERATION__NETWORK_CONFIG_REQUEST ZT_PACKED_STRUCT(struct UNSUPPORTED_OPERATION__NETWORK_CONFIG_REQUEST
{ {
Protocol::Header h; ERROR::Header h;
ERROR::Header eh;
uint64_t networkId; uint64_t networkId;
}); });
@ -906,19 +907,6 @@ ZT_PACKED_STRUCT(struct UNSUPPORTED_OPERATION__NETWORK_CONFIG_REQUEST
/****************************************************************************/ /****************************************************************************/
/**
* Increment the 3-bit hops field embedded in the packet flags field
*/
ZT_ALWAYS_INLINE unsigned int incrementPacketHops(Header &h)
{
uint8_t flags = h.flags;
uint8_t hops = flags;
flags &= 0xf8U;
++hops;
h.flags = flags | (hops & 0x07U);
return (unsigned int)hops;
}
/** /**
* @return 3-bit hops field embedded in packet flags field * @return 3-bit hops field embedded in packet flags field
*/ */

View file

@ -22,8 +22,8 @@
namespace ZeroTier { namespace ZeroTier {
class NodeConfig; class VL1;
class Switch; class VL2;
class Topology; class Topology;
class Node; class Node;
class NetworkController; class NetworkController;
@ -36,19 +36,24 @@ class Trace;
class RuntimeEnvironment class RuntimeEnvironment
{ {
public: public:
inline RuntimeEnvironment(Node *n) : ZT_ALWAYS_INLINE RuntimeEnvironment(Node *n) :
node(n) node(n),
,localNetworkController((NetworkController *)0) localNetworkController(nullptr),
,rtmem((void *)0) rtmem(nullptr),
,sw((Switch *)0) t(nullptr),
,topology((Topology *)0) vl2(nullptr),
,sa((SelfAwareness *)0) vl1(nullptr),
topology(nullptr),
sa(nullptr)
{ {
publicIdentityStr[0] = (char)0; publicIdentityStr[0] = (char)0;
secretIdentityStr[0] = (char)0; secretIdentityStr[0] = (char)0;
} }
inline ~RuntimeEnvironment() { Utils::burn(secretIdentityStr,sizeof(secretIdentityStr)); } ZT_ALWAYS_INLINE ~RuntimeEnvironment()
{
Utils::burn(secretIdentityStr,sizeof(secretIdentityStr));
}
// Node instance that owns this RuntimeEnvironment // Node instance that owns this RuntimeEnvironment
Node *const node; Node *const node;
@ -66,7 +71,8 @@ public:
* These are constant and never null after startup unless indicated. */ * These are constant and never null after startup unless indicated. */
Trace *t; Trace *t;
Switch *sw; VL2 *vl2;
VL1 *vl1;
Topology *topology; Topology *topology;
SelfAwareness *sa; SelfAwareness *sa;

View file

@ -1,14 +1,13 @@
// This code is public domain, taken from a PD crypto source file on GitHub. // This code is public domain, taken from a PD crypto source file on GitHub.
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include "SHA512.hpp" #include "SHA512.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include <utility> #include <utility>
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <cstring>
namespace ZeroTier { namespace ZeroTier {

View file

@ -21,7 +21,6 @@
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "Topology.hpp" #include "Topology.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "Switch.hpp"
#include "Trace.hpp" #include "Trace.hpp"
// Entry timeout -- make it fairly long since this is just to prevent stale buildup // Entry timeout -- make it fairly long since this is just to prevent stale buildup
@ -86,7 +85,7 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv
_ResetWithinScope rset(tPtr,now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope); _ResetWithinScope rset(tPtr,now,myPhysicalAddress.ss_family,(InetAddress::IpScope)scope);
RR->topology->eachPeer<_ResetWithinScope &>(rset); RR->topology->eachPeer<_ResetWithinScope &>(rset);
RR->t->resettingPathsInScope(tPtr,reporter,reporterPhysicalAddress,entry.mySurface,myPhysicalAddress,scope); RR->t->resettingPathsInScope(tPtr,0x9afff100,reporter,reporterPhysicalAddress,entry.mySurface,myPhysicalAddress,scope);
} else { } else {
// Otherwise just update DB to use to determine external surface info // Otherwise just update DB to use to determine external surface info
entry.mySurface = myPhysicalAddress; entry.mySurface = myPhysicalAddress;

View file

@ -14,6 +14,7 @@
#ifndef ZT_SHAREDPTR_HPP #ifndef ZT_SHAREDPTR_HPP
#define ZT_SHAREDPTR_HPP #define ZT_SHAREDPTR_HPP
#include "Constants.hpp"
#include "AtomicCounter.hpp" #include "AtomicCounter.hpp"
#include "TriviallyCopyable.hpp" #include "TriviallyCopyable.hpp"

View file

@ -16,6 +16,10 @@
#include "Node.hpp" #include "Node.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
// NOTE: packet IDs are always handled in network byte order, so no need to convert them. // NOTE: packet IDs are always handled in network byte order, so no need to convert them.
namespace ZeroTier { namespace ZeroTier {
@ -25,13 +29,31 @@ Trace::Trace(const RuntimeEnvironment *renv) :
_vl1(false), _vl1(false),
_vl2(false), _vl2(false),
_vl2Filter(false), _vl2Filter(false),
_vl2Multicast(false), _vl2Multicast(false)
_eventBufSize(0)
{ {
} }
void Trace::unexpectedError(
void *tPtr,
uint32_t codeLocation,
const char *message,
...)
{
va_list ap;
ZT_TraceEvent_UNEXPECTED_ERROR ev;
ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_UNEXPECTED_ERROR);
ev.codeLocation = codeLocation;
memset(ev.message,0,sizeof(ev.message));
va_start(ap,message);
vsnprintf(ev.message,sizeof(ev.message),message,ap);
va_end(ap);
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
}
void Trace::_resettingPathsInScope( void Trace::_resettingPathsInScope(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
const Identity &reporter, const Identity &reporter,
const InetAddress &from, const InetAddress &from,
const InetAddress &oldExternal, const InetAddress &oldExternal,
@ -39,30 +61,32 @@ void Trace::_resettingPathsInScope(
const InetAddress::IpScope scope) const InetAddress::IpScope scope)
{ {
ZT_TraceEvent_VL1_RESETTING_PATHS_IN_SCOPE ev; ZT_TraceEvent_VL1_RESETTING_PATHS_IN_SCOPE ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE);
ev.codeLocation = Utils::hton(codeLocation);
from.forTrace(ev.from); from.forTrace(ev.from);
oldExternal.forTrace(ev.oldExternal); oldExternal.forTrace(ev.oldExternal);
newExternal.forTrace(ev.newExternal); newExternal.forTrace(ev.newExternal);
ev.scope = (uint8_t)scope; ev.scope = (uint8_t)scope;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev); RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
} }
void Trace::_tryingNewPath( void Trace::_tryingNewPath(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
const Identity &trying, const Identity &trying,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &triggerAddress, const InetAddress &triggerAddress,
uint64_t triggeringPacketId, const uint64_t triggeringPacketId,
uint8_t triggeringPacketVerb, const uint8_t triggeringPacketVerb,
uint64_t triggeredByAddress, const uint64_t triggeredByAddress,
const uint8_t *triggeredByIdentityHash, const uint8_t *triggeredByIdentityHash,
ZT_TraceTryingNewPathReason reason) const ZT_TraceTryingNewPathReason reason)
{ {
ZT_TraceEvent_VL1_TRYING_NEW_PATH ev; ZT_TraceEvent_VL1_TRYING_NEW_PATH ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL1_TRYING_NEW_PATH); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL1_TRYING_NEW_PATH);
ev.codeLocation = Utils::hton(codeLocation);
ev.address = Utils::hton(trying.address().toInt()); ev.address = Utils::hton(trying.address().toInt());
memcpy(ev.identityHash,trying.hash(),48); memcpy(ev.identityHash,trying.hash(),48);
physicalAddress.forTrace(ev.physicalAddress); physicalAddress.forTrace(ev.physicalAddress);
@ -74,21 +98,22 @@ void Trace::_tryingNewPath(
memcpy(ev.triggeredByIdentityHash,triggeredByIdentityHash,48); memcpy(ev.triggeredByIdentityHash,triggeredByIdentityHash,48);
else memset(ev.triggeredByIdentityHash,0,48); else memset(ev.triggeredByIdentityHash,0,48);
ev.reason = (uint8_t)reason; ev.reason = (uint8_t)reason;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev); RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
} }
void Trace::_learnedNewPath( void Trace::_learnedNewPath(
void *const tPtr, void *const tPtr,
uint64_t packetId, const uint32_t codeLocation,
const uint64_t packetId,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &replaced) const InetAddress &replaced)
{ {
ZT_TraceEvent_VL1_LEARNED_NEW_PATH ev; ZT_TraceEvent_VL1_LEARNED_NEW_PATH ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL1_LEARNED_NEW_PATH); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL1_LEARNED_NEW_PATH);
ev.packetId = packetId; ev.codeLocation = Utils::hton(codeLocation);
ev.packetId = packetId; // packet IDs are kept in big-endian
ev.address = Utils::hton(peerIdentity.address().toInt()); ev.address = Utils::hton(peerIdentity.address().toInt());
memcpy(ev.identityHash,peerIdentity.hash(),48); memcpy(ev.identityHash,peerIdentity.hash(),48);
physicalAddress.forTrace(ev.physicalAddress); physicalAddress.forTrace(ev.physicalAddress);
@ -99,18 +124,20 @@ void Trace::_learnedNewPath(
void Trace::_incomingPacketDropped( void Trace::_incomingPacketDropped(
void *const tPtr, void *const tPtr,
uint64_t packetId, const uint32_t codeLocation,
uint64_t networkId, const uint64_t packetId,
const uint64_t networkId,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
uint8_t hops, const uint8_t hops,
uint8_t verb, const uint8_t verb,
ZT_TracePacketDropReason reason) const ZT_TracePacketDropReason reason)
{ {
ZT_TraceEvent_VL1_INCOMING_PACKET_DROPPED ev; ZT_TraceEvent_VL1_INCOMING_PACKET_DROPPED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL1_INCOMING_PACKET_DROPPED); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL1_INCOMING_PACKET_DROPPED);
ev.packetId = packetId; ev.codeLocation = Utils::hton(codeLocation);
ev.packetId = packetId; // packet IDs are kept in big-endian
ev.networkId = Utils::hton(networkId); ev.networkId = Utils::hton(networkId);
if (peerIdentity) { if (peerIdentity) {
ev.address = Utils::hton(peerIdentity.address().toInt()); ev.address = Utils::hton(peerIdentity.address().toInt());
@ -129,17 +156,19 @@ void Trace::_incomingPacketDropped(
void Trace::_outgoingNetworkFrameDropped( void Trace::_outgoingNetworkFrameDropped(
void *const tPtr, void *const tPtr,
uint64_t networkId, const uint32_t codeLocation,
const uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
uint16_t etherType, const uint16_t etherType,
uint16_t frameLength, const uint16_t frameLength,
const uint8_t *frameData, const uint8_t *frameData,
ZT_TraceFrameDropReason reason) const ZT_TraceFrameDropReason reason)
{ {
ZT_TraceEvent_VL2_OUTGOING_FRAME_DROPPED ev; ZT_TraceEvent_VL2_OUTGOING_FRAME_DROPPED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_OUTGOING_FRAME_DROPPED); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL2_OUTGOING_FRAME_DROPPED);
ev.codeLocation = Utils::hton(codeLocation);
ev.networkId = Utils::hton(networkId); ev.networkId = Utils::hton(networkId);
ev.sourceMac = Utils::hton(sourceMac.toInt()); ev.sourceMac = Utils::hton(sourceMac.toInt());
ev.destMac = Utils::hton(destMac.toInt()); ev.destMac = Utils::hton(destMac.toInt());
@ -159,21 +188,23 @@ void Trace::_outgoingNetworkFrameDropped(
void Trace::_incomingNetworkFrameDropped( void Trace::_incomingNetworkFrameDropped(
void *const tPtr, void *const tPtr,
uint64_t networkId, const uint32_t codeLocation,
const uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
uint8_t hops, const uint8_t hops,
uint16_t frameLength, const uint16_t frameLength,
const uint8_t *frameData, const uint8_t *frameData,
uint8_t verb, const uint8_t verb,
bool credentialRequestSent, const bool credentialRequestSent,
ZT_TraceFrameDropReason reason) const ZT_TraceFrameDropReason reason)
{ {
ZT_TraceEvent_VL2_INCOMING_FRAME_DROPPED ev; ZT_TraceEvent_VL2_INCOMING_FRAME_DROPPED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_INCOMING_FRAME_DROPPED); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL2_INCOMING_FRAME_DROPPED);
ev.codeLocation = Utils::hton(codeLocation);
ev.networkId = Utils::hton(networkId); ev.networkId = Utils::hton(networkId);
ev.sourceMac = Utils::hton(sourceMac.toInt()); ev.sourceMac = Utils::hton(sourceMac.toInt());
ev.destMac = Utils::hton(destMac.toInt()); ev.destMac = Utils::hton(destMac.toInt());
@ -197,38 +228,41 @@ void Trace::_incomingNetworkFrameDropped(
void Trace::_networkConfigRequestSent( void Trace::_networkConfigRequestSent(
void *const tPtr, void *const tPtr,
uint64_t networkId) const uint32_t codeLocation,
const uint64_t networkId)
{ {
ZT_TraceEvent_VL2_NETWORK_CONFIG_REQUESTED ev; ZT_TraceEvent_VL2_NETWORK_CONFIG_REQUESTED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED);
ev.codeLocation = Utils::hton(codeLocation);
ev.networkId = Utils::hton(networkId); ev.networkId = Utils::hton(networkId);
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev); RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
} }
void Trace::_networkFilter( void Trace::_networkFilter(
void *const tPtr, void *const tPtr,
uint64_t networkId, const uint32_t codeLocation,
const uint64_t networkId,
const uint8_t primaryRuleSetLog[512], const uint8_t primaryRuleSetLog[512],
const uint8_t matchingCapabilityRuleSetLog[512], const uint8_t matchingCapabilityRuleSetLog[512],
uint32_t matchingCapabilityId, const uint32_t matchingCapabilityId,
int64_t matchingCapabilityTimestamp, const int64_t matchingCapabilityTimestamp,
const Address &source, const Address &source,
const Address &dest, const Address &dest,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
uint16_t frameLength, const uint16_t frameLength,
const uint8_t *frameData, const uint8_t *frameData,
uint16_t etherType, const uint16_t etherType,
uint16_t vlanId, const uint16_t vlanId,
bool noTee, const bool noTee,
bool inbound, const bool inbound,
int accept) const int accept)
{ {
ZT_TraceEvent_VL2_NETWORK_FILTER ev; ZT_TraceEvent_VL2_NETWORK_FILTER ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_FILTER); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_FILTER);
ev.codeLocation = Utils::hton(codeLocation);
ev.networkId = Utils::hton(networkId); ev.networkId = Utils::hton(networkId);
memcpy(ev.primaryRuleSetLog,primaryRuleSetLog,sizeof(ev.primaryRuleSetLog)); memcpy(ev.primaryRuleSetLog,primaryRuleSetLog,sizeof(ev.primaryRuleSetLog));
if (matchingCapabilityRuleSetLog) if (matchingCapabilityRuleSetLog)
@ -253,29 +287,29 @@ void Trace::_networkFilter(
ev.noTee = (uint8_t)noTee; ev.noTee = (uint8_t)noTee;
ev.inbound = (uint8_t)inbound; ev.inbound = (uint8_t)inbound;
ev.accept = (int8_t)accept; ev.accept = (int8_t)accept;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev); RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
} }
void Trace::_credentialRejected( void Trace::_credentialRejected(
void *const tPtr, void *const tPtr,
uint64_t networkId, const uint32_t codeLocation,
const uint64_t networkId,
const Address &address, const Address &address,
uint32_t credentialId, const uint32_t credentialId,
int64_t credentialTimestamp, const int64_t credentialTimestamp,
uint8_t credentialType, const uint8_t credentialType,
ZT_TraceCredentialRejectionReason reason) const ZT_TraceCredentialRejectionReason reason)
{ {
ZT_TraceEvent_VL2_CREDENTIAL_REJECTED ev; ZT_TraceEvent_VL2_CREDENTIAL_REJECTED ev;
ev.evSize = CONST_TO_BE_UINT16(sizeof(ev)); ev.evSize = ZT_CONST_TO_BE_UINT16(sizeof(ev));
ev.evType = CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_FILTER); ev.evType = ZT_CONST_TO_BE_UINT16(ZT_TRACE_VL2_NETWORK_FILTER);
ev.codeLocation = Utils::hton(codeLocation);
ev.networkId = Utils::hton(networkId); ev.networkId = Utils::hton(networkId);
ev.address = Utils::hton(address.toInt()); ev.address = Utils::hton(address.toInt());
ev.credentialId = Utils::hton(credentialId); ev.credentialId = Utils::hton(credentialId);
ev.credentialTimestamp = Utils::hton(credentialTimestamp); ev.credentialTimestamp = Utils::hton(credentialTimestamp);
ev.credentialType = credentialType; ev.credentialType = credentialType;
ev.reason = (uint8_t)reason; ev.reason = (uint8_t)reason;
RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev); RR->node->postEvent(tPtr,ZT_EVENT_TRACE,&ev);
} }

View file

@ -66,19 +66,27 @@ public:
explicit Trace(const RuntimeEnvironment *renv); explicit Trace(const RuntimeEnvironment *renv);
void unexpectedError(
void *tPtr,
uint32_t codeLocation,
const char *message,
...);
ZT_ALWAYS_INLINE void resettingPathsInScope( ZT_ALWAYS_INLINE void resettingPathsInScope(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
const Identity &reporter, const Identity &reporter,
const InetAddress &from, const InetAddress &from,
const InetAddress &oldExternal, const InetAddress &oldExternal,
const InetAddress &newExternal, const InetAddress &newExternal,
const InetAddress::IpScope scope) const InetAddress::IpScope scope)
{ {
if (_vl1) _resettingPathsInScope(tPtr,reporter,from,oldExternal,newExternal,scope); if (_vl1) _resettingPathsInScope(tPtr,codeLocation,reporter,from,oldExternal,newExternal,scope);
} }
ZT_ALWAYS_INLINE void tryingNewPath( ZT_ALWAYS_INLINE void tryingNewPath(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
const Identity &trying, const Identity &trying,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &triggerAddress, const InetAddress &triggerAddress,
@ -88,21 +96,23 @@ public:
const uint8_t *triggeredByIdentityHash, const uint8_t *triggeredByIdentityHash,
ZT_TraceTryingNewPathReason reason) ZT_TraceTryingNewPathReason reason)
{ {
if (_vl1) _tryingNewPath(tPtr,trying,physicalAddress,triggerAddress,triggeringPacketId,triggeringPacketVerb,triggeredByAddress,triggeredByIdentityHash,reason); if (_vl1) _tryingNewPath(tPtr,codeLocation,trying,physicalAddress,triggerAddress,triggeringPacketId,triggeringPacketVerb,triggeredByAddress,triggeredByIdentityHash,reason);
} }
ZT_ALWAYS_INLINE void learnedNewPath( ZT_ALWAYS_INLINE void learnedNewPath(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
uint64_t packetId, uint64_t packetId,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &replaced) const InetAddress &replaced)
{ {
if (_vl1) _learnedNewPath(tPtr,packetId,peerIdentity,physicalAddress,replaced); if (_vl1) _learnedNewPath(tPtr,codeLocation,packetId,peerIdentity,physicalAddress,replaced);
} }
ZT_ALWAYS_INLINE void incomingPacketDropped( ZT_ALWAYS_INLINE void incomingPacketDropped(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
uint64_t packetId, uint64_t packetId,
uint64_t networkId, uint64_t networkId,
const Identity &peerIdentity, const Identity &peerIdentity,
@ -111,11 +121,12 @@ public:
uint8_t verb, uint8_t verb,
const ZT_TracePacketDropReason reason) const ZT_TracePacketDropReason reason)
{ {
if (_vl1) _incomingPacketDropped(tPtr,packetId,networkId,peerIdentity,physicalAddress,hops,verb,reason); if (_vl1) _incomingPacketDropped(tPtr,codeLocation,packetId,networkId,peerIdentity,physicalAddress,hops,verb,reason);
} }
ZT_ALWAYS_INLINE void outgoingNetworkFrameDropped( ZT_ALWAYS_INLINE void outgoingNetworkFrameDropped(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
@ -124,11 +135,12 @@ public:
const uint8_t *frameData, const uint8_t *frameData,
ZT_TraceFrameDropReason reason) ZT_TraceFrameDropReason reason)
{ {
if (_vl2) _outgoingNetworkFrameDropped(tPtr,networkId,sourceMac,destMac,etherType,frameLength,frameData,reason); if (_vl2) _outgoingNetworkFrameDropped(tPtr,codeLocation,networkId,sourceMac,destMac,etherType,frameLength,frameData,reason);
} }
ZT_ALWAYS_INLINE void incomingNetworkFrameDropped( ZT_ALWAYS_INLINE void incomingNetworkFrameDropped(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
@ -141,18 +153,20 @@ public:
bool credentialRequestSent, bool credentialRequestSent,
ZT_TraceFrameDropReason reason) ZT_TraceFrameDropReason reason)
{ {
if (_vl2) _incomingNetworkFrameDropped(tPtr,networkId,sourceMac,destMac,peerIdentity,physicalAddress,hops,frameLength,frameData,verb,credentialRequestSent,reason); if (_vl2) _incomingNetworkFrameDropped(tPtr,codeLocation,networkId,sourceMac,destMac,peerIdentity,physicalAddress,hops,frameLength,frameData,verb,credentialRequestSent,reason);
} }
ZT_ALWAYS_INLINE void networkConfigRequestSent( ZT_ALWAYS_INLINE void networkConfigRequestSent(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
uint64_t networkId) uint64_t networkId)
{ {
if (_vl2) _networkConfigRequestSent(tPtr,networkId); if (_vl2) _networkConfigRequestSent(tPtr,codeLocation,networkId);
} }
ZT_ALWAYS_INLINE void networkFilter( ZT_ALWAYS_INLINE void networkFilter(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const uint8_t primaryRuleSetLog[512], const uint8_t primaryRuleSetLog[512],
const uint8_t matchingCapabilityRuleSetLog[512], const uint8_t matchingCapabilityRuleSetLog[512],
@ -173,6 +187,7 @@ public:
if (_vl2Filter) { if (_vl2Filter) {
_networkFilter( _networkFilter(
tPtr, tPtr,
codeLocation,
networkId, networkId,
primaryRuleSetLog, primaryRuleSetLog,
matchingCapabilityRuleSetLog, matchingCapabilityRuleSetLog,
@ -194,6 +209,7 @@ public:
ZT_ALWAYS_INLINE void credentialRejected( ZT_ALWAYS_INLINE void credentialRejected(
void *const tPtr, void *const tPtr,
const uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const Address &address, const Address &address,
uint32_t credentialId, uint32_t credentialId,
@ -201,12 +217,13 @@ public:
uint8_t credentialType, uint8_t credentialType,
ZT_TraceCredentialRejectionReason reason) ZT_TraceCredentialRejectionReason reason)
{ {
if (_vl2) _credentialRejected(tPtr,networkId,address,credentialId,credentialTimestamp,credentialType,reason); if (_vl2) _credentialRejected(tPtr,codeLocation,networkId,address,credentialId,credentialTimestamp,credentialType,reason);
} }
private: private:
void _resettingPathsInScope( void _resettingPathsInScope(
void *tPtr, void *tPtr,
uint32_t codeLocation,
const Identity &reporter, const Identity &reporter,
const InetAddress &from, const InetAddress &from,
const InetAddress &oldExternal, const InetAddress &oldExternal,
@ -214,6 +231,7 @@ private:
InetAddress::IpScope scope); InetAddress::IpScope scope);
void _tryingNewPath( void _tryingNewPath(
void *tPtr, void *tPtr,
uint32_t codeLocation,
const Identity &trying, const Identity &trying,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &triggerAddress, const InetAddress &triggerAddress,
@ -224,12 +242,14 @@ private:
ZT_TraceTryingNewPathReason reason); ZT_TraceTryingNewPathReason reason);
void _learnedNewPath( void _learnedNewPath(
void *tPtr, void *tPtr,
uint32_t codeLocation,
uint64_t packetId, uint64_t packetId,
const Identity &peerIdentity, const Identity &peerIdentity,
const InetAddress &physicalAddress, const InetAddress &physicalAddress,
const InetAddress &replaced); const InetAddress &replaced);
void _incomingPacketDropped( void _incomingPacketDropped(
void *tPtr, void *tPtr,
uint32_t codeLocation,
uint64_t packetId, uint64_t packetId,
uint64_t networkId, uint64_t networkId,
const Identity &peerIdentity, const Identity &peerIdentity,
@ -239,6 +259,7 @@ private:
ZT_TracePacketDropReason reason); ZT_TracePacketDropReason reason);
void _outgoingNetworkFrameDropped( void _outgoingNetworkFrameDropped(
void *tPtr, void *tPtr,
uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
@ -247,7 +268,8 @@ private:
const uint8_t *frameData, const uint8_t *frameData,
ZT_TraceFrameDropReason reason); ZT_TraceFrameDropReason reason);
void _incomingNetworkFrameDropped( void _incomingNetworkFrameDropped(
void *const tPtr, void *tPtr,
uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const MAC &sourceMac, const MAC &sourceMac,
const MAC &destMac, const MAC &destMac,
@ -261,9 +283,11 @@ private:
ZT_TraceFrameDropReason reason); ZT_TraceFrameDropReason reason);
void _networkConfigRequestSent( void _networkConfigRequestSent(
void *tPtr, void *tPtr,
uint32_t codeLocation,
uint64_t networkId); uint64_t networkId);
void _networkFilter( void _networkFilter(
void *tPtr, void *tPtr,
uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const uint8_t primaryRuleSetLog[512], const uint8_t primaryRuleSetLog[512],
const uint8_t matchingCapabilityRuleSetLog[512], const uint8_t matchingCapabilityRuleSetLog[512],
@ -282,6 +306,7 @@ private:
int accept); int accept);
void _credentialRejected( void _credentialRejected(
void *tPtr, void *tPtr,
uint32_t codeLocation,
uint64_t networkId, uint64_t networkId,
const Address &address, const Address &address,
uint32_t credentialId, uint32_t credentialId,
@ -300,9 +325,6 @@ private:
Mutex lock; Mutex lock;
}; };
uint8_t _eventBuf[8192]; // must be less than ZT_PROTO_MAX_PACKET_LENGTH
unsigned int _eventBufSize;
std::vector<_MonitoringPeer> _monitoringPeers; std::vector<_MonitoringPeer> _monitoringPeers;
RWMutex _monitoringPeers_l; RWMutex _monitoringPeers_l;
}; };

View file

@ -409,22 +409,27 @@ int b32d(const char *encoded,uint8_t *result,int bufSize)
uint64_t random() uint64_t random()
{ {
// https://en.wikipedia.org/wiki/Xorshift#xoshiro256** // https://en.wikipedia.org/wiki/Xorshift#xoshiro256**
static Mutex l; static volatile uint64_t s_s0 = getSecureRandomU64();
static uint64_t s0 = getSecureRandomU64(); static volatile uint64_t s_s1 = getSecureRandomU64();
static uint64_t s1 = getSecureRandomU64(); static volatile uint64_t s_s2 = getSecureRandomU64();
static uint64_t s2 = getSecureRandomU64(); static volatile uint64_t s_s3 = getSecureRandomU64();
static uint64_t s3 = getSecureRandomU64();
l.lock(); uint64_t s0 = s_s0;
const uint64_t result = ROL64(s1 * 5,7) * 9; uint64_t s1 = s_s1;
uint64_t s2 = s_s2;
uint64_t s3 = s_s3;
const uint64_t result = ROL64(s1 * 5,7U) * 9;
const uint64_t t = s1 << 17U; const uint64_t t = s1 << 17U;
s2 ^= s0; s2 ^= s0;
s3 ^= s1; s3 ^= s1;
s1 ^= s2; s1 ^= s2;
s0 ^= s3; s0 ^= s3;
s2 ^= t; s2 ^= t;
s3 = ROL64(s3,45); s3 = ROL64(s3,45U);
l.unlock(); s_s0 = s0;
s_s1 = s1;
s_s2 = s2;
s_s3 = s3;
return result; return result;
} }

View file

@ -13,6 +13,7 @@
#include "VL1.hpp" #include "VL1.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "Node.hpp"
#include "Topology.hpp" #include "Topology.hpp"
#include "VL2.hpp" #include "VL2.hpp"
#include "Salsa20.hpp" #include "Salsa20.hpp"
@ -21,12 +22,24 @@
#include "Identity.hpp" #include "Identity.hpp"
#include "SelfAwareness.hpp" #include "SelfAwareness.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"
#include "Peer.hpp"
#include "Path.hpp"
namespace ZeroTier { namespace ZeroTier {
namespace {
ZT_ALWAYS_INLINE const Identity &ifPeerNonNull(const SharedPtr<Peer> &p)
{
if (p)
return p->identity();
return Identity::NIL;
}
} // anonymous namespace
VL1::VL1(const RuntimeEnvironment *renv) : VL1::VL1(const RuntimeEnvironment *renv) :
RR(renv), RR(renv)
_vl2(nullptr)
{ {
} }
@ -40,6 +53,7 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
const SharedPtr<Path> path(RR->topology->getPath(localSocket,fromAddr)); const SharedPtr<Path> path(RR->topology->getPath(localSocket,fromAddr));
path->received(now); path->received(now);
// Really short packets are keepalives and other junk.
if (len < ZT_PROTO_MIN_FRAGMENT_LENGTH) if (len < ZT_PROTO_MIN_FRAGMENT_LENGTH)
return; return;
@ -131,8 +145,10 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
// Subject pktv to a few sanity checks just to make sure Defragmenter worked correctly and // Subject pktv to a few sanity checks just to make sure Defragmenter worked correctly and
// there is enough room in each slice to shift their contents to sizes that are multiples // there is enough room in each slice to shift their contents to sizes that are multiples
// of 64 if needed for crypto. // of 64 if needed for crypto.
if ((pktv.empty()) || (((int)pktv[0].e - (int)pktv[0].s) < sizeof(Protocol::Header))) if ((pktv.empty()) || (((int)pktv[0].e - (int)pktv[0].s) < sizeof(Protocol::Header))) {
RR->t->unexpectedError(tPtr,0x3df19990,"empty or undersized packet vector");
return; return;
}
for(FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS>::const_iterator s(pktv.begin());s!=pktv.end();++s) { for(FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS>::const_iterator s(pktv.begin());s!=pktv.end();++s) {
if ((s->e > (ZT_BUF_MEM_SIZE - 64))||(s->s > s->e)) if ((s->e > (ZT_BUF_MEM_SIZE - 64))||(s->s > s->e))
return; return;
@ -155,7 +171,7 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
for(FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS>::const_iterator s(pktv.begin()+1);s!=pktv.end();++s) for(FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS>::const_iterator s(pktv.begin()+1);s!=pktv.end();++s)
packetSize += s->e - s->s; packetSize += s->e - s->s;
if (packetSize > ZT_PROTO_MAX_PACKET_LENGTH) { if (packetSize > ZT_PROTO_MAX_PACKET_LENGTH) {
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,Identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); RR->t->incomingPacketDropped(tPtr,0x010348da,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return; return;
} }
@ -163,18 +179,15 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
if ((!peer)&&(!(((cipher == ZT_PROTO_CIPHER_SUITE__POLY1305_NONE)||(cipher == ZT_PROTO_CIPHER_SUITE__NONE))&&((ph->verb & 0x1fU) == Protocol::VERB_HELLO)))) { if ((!peer)&&(!(((cipher == ZT_PROTO_CIPHER_SUITE__POLY1305_NONE)||(cipher == ZT_PROTO_CIPHER_SUITE__NONE))&&((ph->verb & 0x1fU) == Protocol::VERB_HELLO)))) {
pkt = Buf::assembleSliceVector(pktv); pkt = Buf::assembleSliceVector(pktv);
if (pkt.e < ZT_PROTO_MIN_PACKET_LENGTH) { if (pkt.e < ZT_PROTO_MIN_PACKET_LENGTH) {
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,Identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); RR->t->incomingPacketDropped(tPtr,0xbada9366,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return; return;
} }
{ {
Mutex::Lock wl(_whoisQueue_l); Mutex::Lock wl(_whoisQueue_l);
_WhoisQueueItem &wq = _whoisQueue[source]; _WhoisQueueItem &wq = _whoisQueue[source];
wq.inboundPackets.push_back(pkt); wq.inboundPackets.push_back(pkt);
if (wq.retries == 0) {
wq.retries = 1;
_sendPendingWhois();
}
} }
_sendPendingWhois(tPtr,now);
return; return;
} }
@ -182,8 +195,10 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
case ZT_PROTO_CIPHER_SUITE__POLY1305_NONE: case ZT_PROTO_CIPHER_SUITE__POLY1305_NONE:
if (peer) { if (peer) {
pkt = Buf::assembleSliceVector(pktv); pkt = Buf::assembleSliceVector(pktv);
if (pkt.e < ZT_PROTO_MIN_PACKET_LENGTH) if (pkt.e < ZT_PROTO_MIN_PACKET_LENGTH) {
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,Identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); RR->t->incomingPacketDropped(tPtr,0x432aa9da,ph->packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return;
}
ph = &(pkt.b->as<Protocol::Header>()); ph = &(pkt.b->as<Protocol::Header>());
// Generate one-time-use MAC key using Salsa20. // Generate one-time-use MAC key using Salsa20.
@ -196,7 +211,7 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
uint64_t mac[2]; uint64_t mac[2];
poly1305(mac,pkt.b->b + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,macKey); poly1305(mac,pkt.b->b + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,macKey);
if (ph->mac != mac[0]) { if (ph->mac != mac[0]) {
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(tPtr,0xcc89c812,ph->packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
authenticated = true; authenticated = true;
@ -216,8 +231,10 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
// Get a buffer to store the decrypted and fully contiguous packet. // Get a buffer to store the decrypted and fully contiguous packet.
pkt.b = Buf::get(); pkt.b = Buf::get();
if (!pkt.b) // only possible on out of memory condition if (!pkt.b) {
RR->t->unexpectedError(tPtr,0x1de16991,"Buf::get() failed (out of memory?)");
return; return;
}
// Salsa20 is a stream cipher but it's only seekable to multiples of 64 bytes. // Salsa20 is a stream cipher but it's only seekable to multiples of 64 bytes.
// This moves data in slices around so that all slices have sizes that are // This moves data in slices around so that all slices have sizes that are
@ -237,6 +254,8 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
} }
// Simultaneously decrypt and assemble packet into a contiguous buffer. // Simultaneously decrypt and assemble packet into a contiguous buffer.
// Since we moved data around above all slices will have sizes that are
// multiples of 64.
memcpy(pkt.b->b,ph,sizeof(Protocol::Header)); memcpy(pkt.b->b,ph,sizeof(Protocol::Header));
pkt.e = sizeof(Protocol::Header); pkt.e = sizeof(Protocol::Header);
for(FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS>::iterator s(pktv.begin());s!=pktv.end();++s) { for(FCV<Buf::Slice,ZT_MAX_PACKET_FRAGMENTS>::iterator s(pktv.begin());s!=pktv.end();++s) {
@ -250,12 +269,12 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
uint64_t mac[2]; uint64_t mac[2];
poly1305(mac,pkt.b->b + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,macKey); poly1305(mac,pkt.b->b + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,macKey);
if (ph->mac != mac[0]) { if (ph->mac != mac[0]) {
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(tPtr,0xbc881231,ph->packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
authenticated = true; authenticated = true;
} else { } else {
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,Identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(tPtr,0xb0b01999,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
break; break;
@ -267,14 +286,13 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
pkt = Buf::assembleSliceVector(pktv); pkt = Buf::assembleSliceVector(pktv);
if (pkt.e < ZT_PROTO_MIN_PACKET_LENGTH) if (pkt.e < ZT_PROTO_MIN_PACKET_LENGTH)
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,Identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); RR->t->incomingPacketDropped(tPtr,0x3d3337df,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
ph = &(pkt.b->as<Protocol::Header>()); ph = &(pkt.b->as<Protocol::Header>());
if (RR->topology->shouldInboundPathBeTrusted(path->address(),Utils::ntoh(ph->mac))) { if (RR->topology->shouldInboundPathBeTrusted(path->address(),Utils::ntoh(ph->mac))) {
authenticated = true; authenticated = true;
} else { } else {
if (peer) RR->t->incomingPacketDropped(tPtr,0x2dfa910b,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_NOT_TRUSTED_PATH);
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_NOT_TRUSTED_PATH);
return; return;
} }
} break; } break;
@ -285,8 +303,7 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
// break; // break;
default: default:
if (peer) RR->t->incomingPacketDropped(tPtr,0x5b001099,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return; return;
} }
@ -295,16 +312,20 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
// Return any still held buffers in pktv to the buffer pool. // Return any still held buffers in pktv to the buffer pool.
pktv.clear(); pktv.clear();
const Protocol::Verb verb = (Protocol::Verb)(ph->verb & ZT_PROTO_VERB_MASK);
// Decompress packet payload if compressed. // Decompress packet payload if compressed.
if ((ph->verb & ZT_PROTO_VERB_FLAG_COMPRESSED) != 0) { if ((ph->verb & ZT_PROTO_VERB_FLAG_COMPRESSED) != 0) {
if (!authenticated) { if (!authenticated) {
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,Identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); RR->t->incomingPacketDropped(tPtr,0x390bcd0a,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,verb,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return; return;
} }
SharedPtr<Buf> nb(Buf::get()); SharedPtr<Buf> nb(Buf::get());
if (!nb) // can only happen if we're out of memory if (!nb) {
RR->t->unexpectedError(tPtr,0xffe169fa,"Buf::get() failed (out of memory?)");
return; return;
}
const int uncompressedLen = LZ4_decompress_safe( const int uncompressedLen = LZ4_decompress_safe(
reinterpret_cast<const char *>(pkt.b->b + ZT_PROTO_PACKET_PAYLOAD_START), reinterpret_cast<const char *>(pkt.b->b + ZT_PROTO_PACKET_PAYLOAD_START),
@ -316,13 +337,14 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
pkt.b.swap(nb); pkt.b.swap(nb);
pkt.e = packetSize = (unsigned int)uncompressedLen; pkt.e = packetSize = (unsigned int)uncompressedLen;
} else { } else {
if (peer) RR->t->incomingPacketDropped(tPtr,0xee9e4392,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,verb,ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA);
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,peer->identity(),path->address(),hops,(Protocol::Verb)(ph->verb & ZT_PROTO_VERB_MASK),ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA);
return; return;
} }
} }
const Protocol::Verb verb = (Protocol::Verb)(ph->verb & ZT_PROTO_VERB_MASK); // VL1 and VL2 are conceptually and (mostly) logically separate layers.
// Verbs that relate to VL1 (P2P transport) are handled in this class.
// VL2 (virtual Ethernet / SDN) verbs are handled in the VL2 class.
switch(verb) { switch(verb) {
case Protocol::VERB_NOP: case Protocol::VERB_NOP:
peer->received(tPtr,path,hops,ph->packetId,packetSize - ZT_PROTO_PACKET_PAYLOAD_START,Protocol::VERB_NOP,0,Protocol::VERB_NOP,0); peer->received(tPtr,path,hops,ph->packetId,packetSize - ZT_PROTO_PACKET_PAYLOAD_START,Protocol::VERB_NOP,0,Protocol::VERB_NOP,0);
@ -333,32 +355,26 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd
case Protocol::VERB_OK: _OK(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_OK: _OK(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_WHOIS: _WHOIS(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_WHOIS: _WHOIS(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_RENDEZVOUS: _RENDEZVOUS(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_RENDEZVOUS: _RENDEZVOUS(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_FRAME: _vl2->_FRAME(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_FRAME: RR->vl2->_FRAME(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_EXT_FRAME: _vl2->_EXT_FRAME(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_EXT_FRAME: RR->vl2->_EXT_FRAME(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_ECHO: _ECHO(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); case Protocol::VERB_ECHO: _ECHO(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated);
case Protocol::VERB_MULTICAST_LIKE: _vl2->_MULTICAST_LIKE(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_MULTICAST_LIKE: RR->vl2->_MULTICAST_LIKE(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_NETWORK_CREDENTIALS: _vl2->_NETWORK_CREDENTIALS(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_NETWORK_CREDENTIALS: RR->vl2->_NETWORK_CREDENTIALS(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_NETWORK_CONFIG_REQUEST: _vl2->_NETWORK_CONFIG_REQUEST(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_NETWORK_CONFIG_REQUEST: RR->vl2->_NETWORK_CONFIG_REQUEST(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_NETWORK_CONFIG: _vl2->_NETWORK_CONFIG(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_NETWORK_CONFIG: RR->vl2->_NETWORK_CONFIG(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_MULTICAST_GATHER: _vl2->_MULTICAST_GATHER(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_MULTICAST_GATHER: RR->vl2->_MULTICAST_GATHER(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_MULTICAST_FRAME_deprecated: _vl2->_MULTICAST_FRAME_deprecated(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_MULTICAST_FRAME_deprecated: RR->vl2->_MULTICAST_FRAME_deprecated(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_PUSH_DIRECT_PATHS: _PUSH_DIRECT_PATHS(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_PUSH_DIRECT_PATHS: _PUSH_DIRECT_PATHS(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_USER_MESSAGE: _USER_MESSAGE(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_USER_MESSAGE: _USER_MESSAGE(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_MULTICAST: _vl2->_MULTICAST(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_MULTICAST: RR->vl2->_MULTICAST(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
case Protocol::VERB_ENCAP: _ENCAP(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break; case Protocol::VERB_ENCAP: _ENCAP(tPtr,path,peer,*pkt.b,(int)packetSize,authenticated); break;
default: default:
if (peer) RR->t->incomingPacketDropped(tPtr,0xdeadeff0,ph->packetId,0,ifPeerNonNull(peer),path->address(),hops,verb,ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB);
RR->t->incomingPacketDropped(tPtr,ph->packetId,0,peer->identity(),path->address(),hops,verb,ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB);
break; break;
} }
} catch ( ... ) { } catch ( ... ) {
uint64_t packetId = 0; RR->t->unexpectedError(tPtr,0xea1b6dea,"unexpected exception in onRemotePacket()");
if (len >= 8) {
for(int i=0;i<8;++i)
reinterpret_cast<uint8_t *>(&packetId)[i] = data->b[i];
}
RR->t->incomingPacketDropped(tPtr,packetId,0,Identity(),path->address(),0,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
} }
} }
@ -366,15 +382,59 @@ void VL1::_relay(void *tPtr,const SharedPtr<Path> &path,const Address &destinati
{ {
} }
void VL1::_sendPendingWhois() void VL1::_sendPendingWhois(void *const tPtr,const int64_t now)
{ {
// assume _whoisQueue_l locked SharedPtr<Peer> root(RR->topology->root());
if (!root)
return;
SharedPtr<Path> rootPath(root->path(now));
if (!rootPath)
return;
std::vector<Address> toSend;
{
Mutex::Lock wl(_whoisQueue_l);
Hashtable<Address,_WhoisQueueItem>::Iterator wi(_whoisQueue);
Address *a = nullptr;
_WhoisQueueItem *wq = nullptr;
while (wi.next(a,wq)) {
if ((now - wq->lastRetry) >= ZT_WHOIS_RETRY_DELAY) {
wq->lastRetry = now;
++wq->retries;
toSend.push_back(*a);
}
}
}
Buf outp;
Protocol::Header &ph = outp.as<Protocol::Header>();
std::vector<Address>::iterator a(toSend.begin());
while (a != toSend.end()) {
ph.packetId = Protocol::getPacketId();
root->address().copyTo(ph.destination);
RR->identity.address().copyTo(ph.source);
ph.flags = 0;
ph.verb = Protocol::VERB_OK;
int ptr = sizeof(Protocol::Header);
while ((a != toSend.end())&&(ptr < (ZT_PROTO_MAX_PACKET_LENGTH - 1))) {
a->copyTo(outp.b + ptr);
++a;
ptr += ZT_ADDRESS_LENGTH;
}
if (ptr > sizeof(Protocol::Header)) {
Protocol::armor(outp,ptr,root->key(),ZT_PROTO_CIPHER_SUITE__POLY1305_SALSA2012);
rootPath->send(RR,tPtr,outp.b,ptr,now);
}
}
} }
void VL1::_HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated) void VL1::_HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated)
{ {
if (packetSize < sizeof(Protocol::HELLO)) { if (packetSize < sizeof(Protocol::HELLO)) {
RR->t->incomingPacketDropped(tPtr,0,0,Identity(),path->address(),0,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); RR->t->incomingPacketDropped(tPtr,0x2bdb0001,0,0,ifPeerNonNull(peer),path->address(),0,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return; return;
} }
@ -383,20 +443,22 @@ void VL1::_HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Bu
int ptr = sizeof(Protocol::HELLO); int ptr = sizeof(Protocol::HELLO);
if (p.versionProtocol < ZT_PROTO_VERSION_MIN) { if (p.versionProtocol < ZT_PROTO_VERSION_MIN) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,Identity(),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD); RR->t->incomingPacketDropped(tPtr,0xe8d12bad,p.h.packetId,0,ifPeerNonNull(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD);
return; return;
} }
Identity id; Identity id;
if (pkt.rO(ptr,id) < 0) { if (pkt.rO(ptr,id) < 0) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,Identity(),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(tPtr,0x707a9810,p.h.packetId,0,ifPeerNonNull(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return; return;
} }
if (Address(p.h.source) != id.address()) { if (Address(p.h.source) != id.address()) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(tPtr,0x06aa9ff1,p.h.packetId,0,Identity::NIL,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
// Packet is basically valid and identity unmarshaled ---------------------------------------------------------------
// Get long-term static key for this node. // Get long-term static key for this node.
uint8_t key[ZT_PEER_SECRET_KEY_LENGTH]; uint8_t key[ZT_PEER_SECRET_KEY_LENGTH];
if ((peer)&&(id == peer->identity())) { if ((peer)&&(id == peer->identity())) {
@ -404,12 +466,12 @@ void VL1::_HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Bu
} else { } else {
peer.zero(); peer.zero();
if (!RR->identity.agree(id,key)) { if (!RR->identity.agree(id,key)) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(tPtr,0x46db8010,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
} }
// Verify packet using Poly1305. For v2.x+ HELLOs this will be the first of two MACs for HELLO. // Verify packet using Poly1305, which for v2.x
{ {
uint8_t perPacketKey[ZT_PEER_SECRET_KEY_LENGTH]; uint8_t perPacketKey[ZT_PEER_SECRET_KEY_LENGTH];
uint8_t macKey[ZT_POLY1305_KEY_LEN]; uint8_t macKey[ZT_POLY1305_KEY_LEN];
@ -418,31 +480,31 @@ void VL1::_HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Bu
uint64_t mac[2]; uint64_t mac[2];
poly1305(mac,pkt.b + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,macKey); poly1305(mac,pkt.b + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,macKey);
if (p.h.mac != mac[0]) { if (p.h.mac != mac[0]) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); RR->t->incomingPacketDropped(tPtr,0x11bfff81,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
} }
// Packet has passed Poly1305 verification --------------------------------------------------------------------------
InetAddress externalSurfaceAddress; InetAddress externalSurfaceAddress;
Dictionary nodeMetaData; Dictionary nodeMetaData;
uint8_t hmacKey[ZT_PEER_SECRET_KEY_LENGTH],hmac[ZT_HMACSHA384_LEN];
bool hmacAuthenticated = false;
// Get external surface address if present. // Get external surface address if present.
if (ptr < packetSize) { if (ptr < packetSize) {
if (pkt.rO(ptr,externalSurfaceAddress) < 0) { if (pkt.rO(ptr,externalSurfaceAddress) < 0) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(tPtr,0xf1000023,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return; return;
} }
} }
if (ptr < packetSize) { if (ptr < packetSize) {
// NOTE to auditors: // Everything after this point is encrypted with Salsa20/12. This is only a privacy measure
// Anything after the external surface address is encrypted using Salsa20/12. // since there's nothing truly secret in a HELLO packet. It also means that an observer
// The key for this is un-mangled static peer key. This is a bit of a legacy // can't even get ephemeral public keys without first knowing the long term secret key,
// thing and isn't absolutely necessary, but does help conceal information // adding a little defense in depth.
// that does not need to be in plaintext. This should not be considered
// a required part of the security/authentication model since leakage of
// this information would have no impact on either authentication or actual
// payload encryption.
uint8_t iv[8]; uint8_t iv[8];
for(int i=0;i<8;++i) iv[i] = pkt.b[i]; for(int i=0;i<8;++i) iv[i] = pkt.b[i];
iv[7] &= 0xf8U; iv[7] &= 0xf8U;
@ -454,44 +516,52 @@ void VL1::_HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Bu
const unsigned int dictionarySize = pkt.rI16(ptr); const unsigned int dictionarySize = pkt.rI16(ptr);
const void *const dictionaryBytes = pkt.b + ptr; const void *const dictionaryBytes = pkt.b + ptr;
if ((ptr += (int)dictionarySize) > packetSize) { if ((ptr += (int)dictionarySize) > packetSize) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(tPtr,0x0d0f0112,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return; return;
} }
ptr += pkt.rI16(ptr); // skip any additional fields, currently always 0 ptr += pkt.rI16(ptr); // skip any additional fields, currently always 0
if (ptr > packetSize) { if (ptr > packetSize) {
RR->t->incomingPacketDropped(tPtr,0,0,Identity(),path->address(),0,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); RR->t->incomingPacketDropped(tPtr,0x451f2341,0,p.h.packetId,id,path->address(),0,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET);
return; return;
} }
if ((ptr + ZT_SHA384_DIGEST_LEN) <= packetSize) { if ((ptr + ZT_SHA384_DIGEST_LEN) <= packetSize) {
uint8_t hmacKey[ZT_PEER_SECRET_KEY_LENGTH],mac[ZT_HMACSHA384_LEN]; KBKDFHMACSHA384(key,ZT_PROTO_KDF_KEY_LABEL_HELLO_HMAC,0,0,hmacKey); // iter == 0 for HELLO
KBKDFHMACSHA384(key,ZT_PROTO_KDF_KEY_LABEL_HELLO_HMAC,0,0,hmacKey); HMACSHA384(hmacKey,pkt.b + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,hmac);
HMACSHA384(hmacKey,pkt.b + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,mac); if (!Utils::secureEq(pkt.b + ptr,hmac,ZT_HMACSHA384_LEN)) {
if (!Utils::secureEq(pkt.b + ptr,mac,ZT_HMACSHA384_LEN)) { RR->t->incomingPacketDropped(tPtr,0x1000662a,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return; return;
} }
hmacAuthenticated = true;
} }
if (dictionarySize) { if (dictionarySize) {
if (!nodeMetaData.decode(dictionaryBytes,dictionarySize)) { if (!nodeMetaData.decode(dictionaryBytes,dictionarySize)) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(tPtr,0x67192344,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return; return;
} }
} }
} }
} }
// v2.x+ peers must include HMAC, older peers don't
if ((!hmacAuthenticated)&&(p.versionProtocol >= 11)) {
RR->t->incomingPacketDropped(tPtr,0x571feeea,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED);
return;
}
// Packet is fully decoded and has passed full HMAC (if present) ----------------------------------------------------
const int64_t now = RR->node->now(); const int64_t now = RR->node->now();
if (!peer) { if (!peer) {
if (!RR->node->rateGateIdentityVerification(now,path->address())) { if (!RR->node->rateGateIdentityVerification(now,path->address())) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_RATE_LIMIT_EXCEEDED); RR->t->incomingPacketDropped(tPtr,0xaffa9ff7,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_RATE_LIMIT_EXCEEDED);
return; return;
} }
if (!id.locallyValidate()) { if (!id.locallyValidate()) {
RR->t->incomingPacketDropped(tPtr,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); RR->t->incomingPacketDropped(tPtr,0x2ff7a909,p.h.packetId,0,id,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT);
return; return;
} }
peer.set(new Peer(RR)); peer.set(new Peer(RR));
@ -501,24 +571,30 @@ void VL1::_HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Bu
peer = RR->topology->add(tPtr,peer); peer = RR->topology->add(tPtr,peer);
} }
// All validation steps complete, peer learned if not yet known -----------------------------------------------------
if ((hops == 0)&&(externalSurfaceAddress)) if ((hops == 0)&&(externalSurfaceAddress))
RR->sa->iam(tPtr,id,path->localSocket(),path->address(),externalSurfaceAddress,RR->topology->isRoot(id),now); RR->sa->iam(tPtr,id,path->localSocket(),path->address(),externalSurfaceAddress,RR->topology->isRoot(id),now);
// Send OK(HELLO) with an echo of the packet's timestamp and some of the same std::vector<uint8_t> myNodeMetaDataBin;
// information about us: version, sent-to address, etc. {
Dictionary myNodeMetaData;
myNodeMetaData.encode(myNodeMetaDataBin);
}
if (myNodeMetaDataBin.size() > ZT_PROTO_MAX_PACKET_LENGTH) // sanity check
return;
SharedPtr<Buf> outp(Buf::get()); Buf outp;
if (!outp) return; Protocol::OK::HELLO &ok = outp.as<Protocol::OK::HELLO>();
Protocol::OK::HELLO &ok = outp->as<Protocol::OK::HELLO>();
ok.h.packetId = Protocol::getPacketId(); ok.h.h.packetId = Protocol::getPacketId();
id.address().copyTo(ok.h.destination); id.address().copyTo(ok.h.h.destination);
RR->identity.address().copyTo(ok.h.source); RR->identity.address().copyTo(ok.h.h.source);
ok.h.flags = 0; ok.h.h.flags = 0;
ok.h.verb = Protocol::VERB_OK; ok.h.h.verb = Protocol::VERB_OK;
ok.oh.inReVerb = Protocol::VERB_HELLO; ok.h.inReVerb = Protocol::VERB_HELLO;
ok.oh.inRePacketId = p.h.packetId; ok.h.inRePacketId = p.h.packetId;
ok.timestampEcho = p.timestamp; ok.timestampEcho = p.timestamp;
ok.versionProtocol = ZT_PROTO_VERSION; ok.versionProtocol = ZT_PROTO_VERSION;
@ -527,33 +603,24 @@ void VL1::_HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Bu
ok.versionRev = ZT_CONST_TO_BE_UINT16(ZEROTIER_ONE_VERSION_REVISION); ok.versionRev = ZT_CONST_TO_BE_UINT16(ZEROTIER_ONE_VERSION_REVISION);
int outl = sizeof(Protocol::OK::HELLO); int outl = sizeof(Protocol::OK::HELLO);
outp->wO(outl,path->address()); outp.wO(outl,path->address());
#if 0 if (p.versionProtocol >= 11) {
ZT_GET_NEW_BUF(outp,Protocol::OK::HELLO); outp.wI(outl,(uint16_t)0); // legacy field, always 0
outp.wI(outl,(uint16_t)myNodeMetaDataBin.size());
outp.wB(outl,myNodeMetaDataBin.data(),(unsigned int)myNodeMetaDataBin.size());
outp.wI(outl,(uint16_t)0); // length of additional fields, currently 0
outp->data.fields.h.packetId = Protocol::getPacketId(); if ((outl + ZT_HMACSHA384_LEN) > ZT_PROTO_MAX_PACKET_LENGTH) // sanity check, shouldn't be possible
peer->address().copyTo(outp->data.fields.h.destination); return;
RR->identity.address().copyTo(outp->data.fields.h.source);
outp->data.fields.h.flags = 0;
outp->data.fields.h.verb = Protocol::VERB_OK;
outp->data.fields.oh.inReVerb = Protocol::VERB_HELLO; KBKDFHMACSHA384(key,ZT_PROTO_KDF_KEY_LABEL_HELLO_HMAC,0,1,hmacKey); // iter == 1 for OK
outp->data.fields.oh.inRePacketId = p.idBE; HMACSHA384(hmacKey,outp.b + sizeof(ok.h),outl - sizeof(ok.h),outp.b + outl);
outl += ZT_HMACSHA384_LEN;
outp->data.fields.timestampEcho = pkt.data.fields.timestamp;
outp->data.fields.versionProtocol = ZT_PROTO_VERSION;
outp->data.fields.versionMajor = ZEROTIER_ONE_VERSION_MAJOR;
outp->data.fields.versionMinor = ZEROTIER_ONE_VERSION_MINOR;
outp->data.fields.versionRev = CONST_TO_BE_UINT16(ZEROTIER_ONE_VERSION_REVISION);
int outl = sizeof(Protocol::OK::HELLO);
outp->wO(outl,p.path->address());
if (!Buf<>::writeOverflow(outl)) {
Protocol::armor(*outp,outl,peer->key(),ZT_PROTO_CIPHER_SUITE__POLY1305_SALSA2012);
p.path->send(RR,tPtr,outp->data.bytes,outl,RR->node->now());
} }
#endif
Protocol::armor(outp,outl,peer->key(),ZT_PROTO_CIPHER_SUITE__POLY1305_SALSA2012);
path->send(RR,tPtr,outp.b,outl,now);
peer->setRemoteVersion(p.versionProtocol,p.versionMajor,p.versionMinor,Utils::ntoh(p.versionRev)); peer->setRemoteVersion(p.versionProtocol,p.versionMajor,p.versionMinor,Utils::ntoh(p.versionRev));
peer->received(tPtr,path,hops,p.h.packetId,packetSize - ZT_PROTO_PACKET_PAYLOAD_START,Protocol::VERB_HELLO,0,Protocol::VERB_NOP,0); peer->received(tPtr,path,hops,p.h.packetId,packetSize - ZT_PROTO_PACKET_PAYLOAD_START,Protocol::VERB_HELLO,0,Protocol::VERB_NOP,0);

View file

@ -53,7 +53,7 @@ public:
private: private:
void _relay(void *tPtr,const SharedPtr<Path> &path,const Address &destination,SharedPtr<Buf> &data,unsigned int len); void _relay(void *tPtr,const SharedPtr<Path> &path,const Address &destination,SharedPtr<Buf> &data,unsigned int len);
void _sendPendingWhois(); void _sendPendingWhois(void *tPtr,int64_t now);
// Handlers for VL1 verbs // Handlers for VL1 verbs
void _HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated); void _HELLO(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated);
@ -67,7 +67,6 @@ private:
void _ENCAP(void *tPtr,const SharedPtr<Path> &path,const SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated); void _ENCAP(void *tPtr,const SharedPtr<Path> &path,const SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated);
const RuntimeEnvironment *RR; const RuntimeEnvironment *RR;
VL2 *const _vl2;
struct _WhoisQueueItem struct _WhoisQueueItem
{ {

View file

@ -13,10 +13,13 @@
#include "VL2.hpp" #include "VL2.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "Node.hpp"
#include "VL1.hpp" #include "VL1.hpp"
#include "Topology.hpp" #include "Topology.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "Path.hpp" #include "Path.hpp"
#include "Network.hpp"
#include "MAC.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -28,6 +31,10 @@ VL2::~VL2()
{ {
} }
void VL2::onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{
}
void VL2::_FRAME(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated) void VL2::_FRAME(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated)
{ {
} }

View file

@ -28,6 +28,8 @@ class Path;
class Peer; class Peer;
class RuntimeEnvironment; class RuntimeEnvironment;
class VL1; class VL1;
class Network;
class MAC;
class VL2 class VL2
{ {
@ -37,6 +39,20 @@ public:
VL2(const RuntimeEnvironment *renv); VL2(const RuntimeEnvironment *renv);
~VL2(); ~VL2();
/**
* Called when a packet comes from a local Ethernet tap
*
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param network Which network's TAP did this packet come from?
* @param from Originating MAC address
* @param to Destination MAC address
* @param etherType Ethernet packet type
* @param vlanId VLAN ID or 0 if none
* @param data Ethernet payload
* @param len Frame length
*/
void onLocalEthernet(void *tPtr,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
protected: protected:
void _FRAME(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated); void _FRAME(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated);
void _EXT_FRAME(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated); void _EXT_FRAME(void *tPtr,const SharedPtr<Path> &path,SharedPtr<Peer> &peer,Buf &pkt,int packetSize,bool authenticated);