2013-07-11 20:19:06 +00:00
/*
2020-05-12 08:35:48 +00:00
* Copyright ( c ) 2013 - 2020 ZeroTier , Inc .
2013-07-11 20:19:06 +00:00
*
2019-08-23 16:23:39 +00:00
* Use of this software is governed by the Business Source License included
* in the LICENSE . TXT file in the project ' s root directory .
2013-07-11 20:19:06 +00:00
*
2020-08-20 19:51:39 +00:00
* Change Date : 2025 - 01 - 01
2013-07-11 20:19:06 +00:00
*
2019-08-23 16:23:39 +00:00
* On the date above , in accordance with the Business Source License , use
* of this software will be governed by version 2.0 of the Apache License .
2013-07-11 20:19:06 +00:00
*/
2019-08-23 16:23:39 +00:00
/****/
2013-07-11 20:19:06 +00:00
2013-10-02 17:50:42 +00:00
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
2013-09-13 19:47:00 +00:00
# include "../version.h"
2015-10-06 21:42:51 +00:00
# include "../include/ZeroTierOne.h"
2013-09-13 19:47:00 +00:00
2013-08-02 21:17:34 +00:00
# include "Constants.hpp"
2013-07-11 20:19:06 +00:00
# include "RuntimeEnvironment.hpp"
2014-09-24 16:04:09 +00:00
# include "IncomingPacket.hpp"
2014-10-01 23:29:52 +00:00
# include "Topology.hpp"
2013-07-11 20:19:06 +00:00
# include "Switch.hpp"
2013-07-11 21:52:04 +00:00
# include "Peer.hpp"
2015-04-15 22:12:09 +00:00
# include "NetworkController.hpp"
2015-04-07 03:17:21 +00:00
# include "SelfAwareness.hpp"
2015-10-07 20:35:46 +00:00
# include "Salsa20.hpp"
# include "SHA512.hpp"
2015-10-13 19:10:44 +00:00
# include "World.hpp"
2015-10-27 22:00:16 +00:00
# include "Node.hpp"
2016-08-04 01:04:08 +00:00
# include "CertificateOfMembership.hpp"
# include "Capability.hpp"
# include "Tag.hpp"
2016-09-23 23:08:38 +00:00
# include "Revocation.hpp"
2017-07-07 23:58:05 +00:00
# include "Trace.hpp"
2020-05-12 08:35:48 +00:00
# include "Path.hpp"
# include "Bond.hpp"
2013-07-11 20:19:06 +00:00
namespace ZeroTier {
2020-05-12 08:35:48 +00:00
bool IncomingPacket : : tryDecode ( const RuntimeEnvironment * RR , void * tPtr , int32_t flowId )
2013-07-11 20:19:06 +00:00
{
2016-07-21 21:02:54 +00:00
const Address sourceAddress ( source ( ) ) ;
2016-07-12 18:30:22 +00:00
2016-07-21 21:02:54 +00:00
try {
2016-07-12 15:29:50 +00:00
// Check for trusted paths or unencrypted HELLOs (HELLO is the only packet sent in the clear)
const unsigned int c = cipher ( ) ;
if ( c = = ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH ) {
// If this is marked as a packet via a trusted path, check source address and path ID.
// Obviously if no trusted paths are configured this always returns false and such
// packets are dropped on the floor.
2017-07-07 23:58:05 +00:00
const uint64_t tpid = trustedPathId ( ) ;
if ( RR - > topology - > shouldInboundPathBeTrusted ( _path - > address ( ) , tpid ) ) {
2022-04-15 00:10:20 +00:00
_authenticated = true ;
2016-07-12 15:29:50 +00:00
} else {
2017-08-18 20:59:22 +00:00
RR - > t - > incomingPacketMessageAuthenticationFailure ( tPtr , _path , packetId ( ) , sourceAddress , hops ( ) , " path not trusted " ) ;
2016-07-12 15:29:50 +00:00
return true ;
}
} else if ( ( c = = ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE ) & & ( verb ( ) = = Packet : : VERB_HELLO ) ) {
2016-09-09 18:36:10 +00:00
// Only HELLO is allowed in the clear, but will still have a MAC
2017-03-28 00:03:17 +00:00
return _doHELLO ( RR , tPtr , false ) ;
2013-07-11 21:52:04 +00:00
}
2017-03-28 00:03:17 +00:00
const SharedPtr < Peer > peer ( RR - > topology - > getPeer ( tPtr , sourceAddress ) ) ;
2014-10-02 17:06:29 +00:00
if ( peer ) {
2022-04-15 00:10:20 +00:00
if ( ! _authenticated ) {
2021-02-13 05:01:49 +00:00
if ( ! dearmor ( peer - > key ( ) , peer - > aesKeys ( ) ) ) {
2017-08-18 20:59:22 +00:00
RR - > t - > incomingPacketMessageAuthenticationFailure ( tPtr , _path , packetId ( ) , sourceAddress , hops ( ) , " invalid MAC " ) ;
2020-05-12 08:35:48 +00:00
peer - > recordIncomingInvalidPacket ( _path ) ;
2016-07-12 15:29:50 +00:00
return true ;
}
2016-06-29 18:43:22 +00:00
}
2016-07-12 15:29:50 +00:00
2016-06-29 18:43:22 +00:00
if ( ! uncompress ( ) ) {
2017-07-13 17:51:05 +00:00
RR - > t - > incomingPacketInvalid ( tPtr , _path , packetId ( ) , sourceAddress , hops ( ) , Packet : : VERB_NOP , " LZ4 decompression failed " ) ;
2016-06-29 18:43:22 +00:00
return true ;
2014-10-02 17:06:29 +00:00
}
2022-04-15 00:13:57 +00:00
_authenticated = true ;
2015-10-07 17:30:47 +00:00
const Packet : : Verb v = verb ( ) ;
2020-05-12 08:35:48 +00:00
2019-03-19 23:43:43 +00:00
bool r = true ;
2015-10-07 17:30:47 +00:00
switch ( v ) {
2014-10-02 17:06:29 +00:00
//case Packet::VERB_NOP:
default : // ignore unknown verbs, but if they pass auth check they are "received"
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , v , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2019-03-19 23:43:43 +00:00
break ;
case Packet : : VERB_HELLO : r = _doHELLO ( RR , tPtr , true ) ; break ;
2022-06-08 17:01:54 +00:00
case Packet : : VERB_ACK : r = _doACK ( RR , tPtr , peer ) ; break ;
2019-03-19 23:43:43 +00:00
case Packet : : VERB_QOS_MEASUREMENT : r = _doQOS_MEASUREMENT ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_ERROR : r = _doERROR ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_OK : r = _doOK ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_WHOIS : r = _doWHOIS ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_RENDEZVOUS : r = _doRENDEZVOUS ( RR , tPtr , peer ) ; break ;
2020-05-12 08:35:48 +00:00
case Packet : : VERB_FRAME : r = _doFRAME ( RR , tPtr , peer , flowId ) ; break ;
case Packet : : VERB_EXT_FRAME : r = _doEXT_FRAME ( RR , tPtr , peer , flowId ) ; break ;
2019-03-19 23:43:43 +00:00
case Packet : : VERB_ECHO : r = _doECHO ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_MULTICAST_LIKE : r = _doMULTICAST_LIKE ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_NETWORK_CREDENTIALS : r = _doNETWORK_CREDENTIALS ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_NETWORK_CONFIG_REQUEST : r = _doNETWORK_CONFIG_REQUEST ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_NETWORK_CONFIG : r = _doNETWORK_CONFIG ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_MULTICAST_GATHER : r = _doMULTICAST_GATHER ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_MULTICAST_FRAME : r = _doMULTICAST_FRAME ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_PUSH_DIRECT_PATHS : r = _doPUSH_DIRECT_PATHS ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_USER_MESSAGE : r = _doUSER_MESSAGE ( RR , tPtr , peer ) ; break ;
case Packet : : VERB_REMOTE_TRACE : r = _doREMOTE_TRACE ( RR , tPtr , peer ) ; break ;
2020-05-12 08:35:48 +00:00
case Packet : : VERB_PATH_NEGOTIATION_REQUEST : r = _doPATH_NEGOTIATION_REQUEST ( RR , tPtr , peer ) ; break ;
2019-03-19 23:43:43 +00:00
}
if ( r ) {
RR - > node - > statsLogVerb ( ( unsigned int ) v , ( unsigned int ) size ( ) ) ;
return true ;
2014-10-02 17:06:29 +00:00
}
2019-03-19 23:43:43 +00:00
return false ;
2014-10-02 17:06:29 +00:00
} else {
2017-08-23 23:42:17 +00:00
RR - > sw - > requestWhois ( tPtr , RR - > node - > now ( ) , sourceAddress ) ;
2014-10-02 17:06:29 +00:00
return false ;
2013-07-11 21:52:04 +00:00
}
2014-10-02 17:06:29 +00:00
} catch ( . . . ) {
2017-07-17 20:48:39 +00:00
RR - > t - > incomingPacketInvalid ( tPtr , _path , packetId ( ) , sourceAddress , hops ( ) , verb ( ) , " unexpected exception in tryDecode() " ) ;
2014-10-02 17:06:29 +00:00
return true ;
2013-07-11 21:52:04 +00:00
}
2013-07-11 22:15:51 +00:00
}
2013-07-11 21:52:04 +00:00
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doERROR ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
2017-07-17 17:43:28 +00:00
const Packet : : Verb inReVerb = ( Packet : : Verb ) ( * this ) [ ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB ] ;
const uint64_t inRePacketId = at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID ) ;
const Packet : : ErrorCode errorCode = ( Packet : : ErrorCode ) ( * this ) [ ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE ] ;
uint64_t networkId = 0 ;
/* Security note: we do not gate doERROR() with expectingReplyTo() to
* avoid having to log every outgoing packet ID . Instead we put the
* logic to determine whether we should consider an ERROR in each
* error handler . In most cases these are only trusted in specific
* circumstances . */
switch ( errorCode ) {
case Packet : : ERROR_OBJ_NOT_FOUND :
// Object not found, currently only meaningful from network controllers.
if ( inReVerb = = Packet : : VERB_NETWORK_CONFIG_REQUEST ) {
const SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
if ( ( network ) & & ( network - > controller ( ) = = peer - > address ( ) ) )
2021-12-01 20:07:05 +00:00
network - > setNotFound ( tPtr ) ;
2017-07-17 17:43:28 +00:00
}
break ;
2016-09-09 15:43:58 +00:00
2017-07-17 17:43:28 +00:00
case Packet : : ERROR_UNSUPPORTED_OPERATION :
// This can be sent in response to any operation, though right now we only
// consider it meaningful from network controllers. This would indicate
// that the queried node does not support acting as a controller.
if ( inReVerb = = Packet : : VERB_NETWORK_CONFIG_REQUEST ) {
2016-09-26 23:17:02 +00:00
const SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2015-10-07 17:30:47 +00:00
if ( ( network ) & & ( network - > controller ( ) = = peer - > address ( ) ) )
2021-12-01 20:07:05 +00:00
network - > setNotFound ( tPtr ) ;
2017-07-17 17:43:28 +00:00
}
break ;
case Packet : : ERROR_IDENTITY_COLLISION :
// FIXME: for federation this will need a payload with a signature or something.
if ( RR - > topology - > isUpstream ( peer - > identity ( ) ) )
RR - > node - > postEvent ( tPtr , ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION ) ;
break ;
case Packet : : ERROR_NEED_MEMBERSHIP_CERTIFICATE : {
// Peers can send this in response to frames if they do not have a recent enough COM from us
networkId = at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ;
const SharedPtr < Network > network ( RR - > node - > network ( networkId ) ) ;
2017-10-02 22:52:57 +00:00
const int64_t now = RR - > node - > now ( ) ;
2019-03-19 23:43:43 +00:00
if ( ( network ) & & ( network - > config ( ) . com ) )
2022-04-19 20:06:53 +00:00
network - > peerRequestedCredentials ( tPtr , peer - > address ( ) , now ) ;
2017-07-17 17:43:28 +00:00
} break ;
case Packet : : ERROR_NETWORK_ACCESS_DENIED_ : {
// Network controller: network access denied.
const SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
if ( ( network ) & & ( network - > controller ( ) = = peer - > address ( ) ) )
2021-12-01 20:07:05 +00:00
network - > setAccessDenied ( tPtr ) ;
2017-07-17 17:43:28 +00:00
} break ;
case Packet : : ERROR_UNWANTED_MULTICAST : {
// Members of networks can use this error to indicate that they no longer
// want to receive multicasts on a given channel.
networkId = at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ;
const SharedPtr < Network > network ( RR - > node - > network ( networkId ) ) ;
if ( ( network ) & & ( network - > gate ( tPtr , peer ) ) ) {
const MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8 , 6 ) , 6 ) , at < uint32_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14 ) ) ;
RR - > mc - > remove ( network - > id ( ) , mg , peer - > address ( ) ) ;
}
} break ;
2014-09-30 23:28:25 +00:00
2021-05-25 18:40:40 +00:00
case Packet : : ERROR_NETWORK_AUTHENTICATION_REQUIRED : {
2022-02-17 04:39:18 +00:00
//fprintf(stderr, "\nPacket::ERROR_NETWORK_AUTHENTICATION_REQUIRED\n\n");
2021-05-25 18:40:40 +00:00
const SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
if ( ( network ) & & ( network - > controller ( ) = = peer - > address ( ) ) ) {
int s = ( int ) size ( ) - ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8 ) ;
if ( s > 2 ) {
const uint16_t errorDataSize = at < uint16_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8 ) ;
s - = 2 ;
if ( s > = ( int ) errorDataSize ) {
2021-11-04 22:40:08 +00:00
Dictionary < 8192 > authInfo ( ( ( const char * ) this - > data ( ) ) + ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 10 ) , errorDataSize ) ;
uint64_t authVer = authInfo . getUI ( ZT_AUTHINFO_DICT_KEY_VERSION , 0ULL ) ;
if ( authVer = = 0 ) {
char authenticationURL [ 2048 ] ;
2021-12-01 18:44:29 +00:00
2021-11-04 22:40:08 +00:00
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_AUTHENTICATION_URL , authenticationURL , sizeof ( authenticationURL ) ) > 0 ) {
authenticationURL [ sizeof ( authenticationURL ) - 1 ] = 0 ; // ensure always zero terminated
2021-12-01 20:07:05 +00:00
network - > setAuthenticationRequired ( tPtr , authenticationURL ) ;
2021-11-04 22:40:08 +00:00
}
} else if ( authVer = = 1 ) {
2021-11-12 00:19:26 +00:00
char issuerURL [ 2048 ] = { 0 } ;
2021-11-04 22:40:08 +00:00
char centralAuthURL [ 2048 ] = { 0 } ;
char ssoNonce [ 64 ] = { 0 } ;
char ssoState [ 128 ] = { 0 } ;
char ssoClientID [ 256 ] = { 0 } ;
2023-01-19 23:39:15 +00:00
char ssoProvider [ 64 ] = { 0 } ;
2021-11-04 22:40:08 +00:00
2021-11-12 00:19:26 +00:00
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_ISSUER_URL , issuerURL , sizeof ( issuerURL ) ) > 0 ) {
issuerURL [ sizeof ( issuerURL ) - 1 ] = 0 ;
2021-11-04 22:40:08 +00:00
}
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_CENTRAL_ENDPOINT_URL , centralAuthURL , sizeof ( centralAuthURL ) ) > 0 ) {
centralAuthURL [ sizeof ( centralAuthURL ) - 1 ] = 0 ;
}
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_NONCE , ssoNonce , sizeof ( ssoNonce ) ) > 0 ) {
ssoNonce [ sizeof ( ssoNonce ) - 1 ] = 0 ;
}
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_STATE , ssoState , sizeof ( ssoState ) ) > 0 ) {
ssoState [ sizeof ( ssoState ) - 1 ] = 0 ;
}
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_CLIENT_ID , ssoClientID , sizeof ( ssoClientID ) ) > 0 ) {
ssoClientID [ sizeof ( ssoClientID ) - 1 ] = 0 ;
}
2023-01-19 23:39:15 +00:00
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_SSO_PROVIDER , ssoProvider , sizeof ( ssoProvider ) ) > 0 ) {
ssoProvider [ sizeof ( ssoProvider ) - 1 ] = 0 ;
} else {
strncpy ( ssoProvider , " default " , sizeof ( ssoProvider ) ) ;
}
2021-11-04 22:40:08 +00:00
2023-01-19 23:39:15 +00:00
network - > setAuthenticationRequired ( tPtr , issuerURL , centralAuthURL , ssoClientID , ssoProvider , ssoNonce , ssoState ) ;
2021-05-25 18:40:40 +00:00
}
}
2021-12-01 18:44:29 +00:00
} else {
2021-12-01 20:07:05 +00:00
network - > setAuthenticationRequired ( tPtr , " " ) ;
2021-11-04 22:40:08 +00:00
}
2021-05-25 18:40:40 +00:00
}
} break ;
2017-07-17 17:43:28 +00:00
default : break ;
}
2014-09-30 23:28:25 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_ERROR , inRePacketId , inReVerb , false , networkId , ZT_QOS_NO_FLOW ) ;
2018-05-31 00:45:29 +00:00
return true ;
}
2022-06-08 17:01:54 +00:00
bool IncomingPacket : : _doACK ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2018-05-31 00:45:29 +00:00
{
2022-06-08 17:01:54 +00:00
/*
2020-05-12 08:35:48 +00:00
SharedPtr < Bond > bond = peer - > bond ( ) ;
2022-06-08 17:01:54 +00:00
if ( ! bond | | ! bond - > rateGateACK ( RR - > node - > now ( ) ) ) {
return true ;
}
int32_t ackedBytes ;
if ( payloadLength ( ) ! = sizeof ( ackedBytes ) ) {
return true ; // ignore
}
memcpy ( & ackedBytes , payload ( ) , sizeof ( ackedBytes ) ) ;
if ( bond ) {
bond - > receivedAck ( _path , RR - > node - > now ( ) , Utils : : ntoh ( ackedBytes ) ) ;
}
*/
return true ;
}
bool IncomingPacket : : _doQOS_MEASUREMENT ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
{
SharedPtr < Bond > bond = peer - > bond ( ) ;
if ( ! bond | | ! bond - > rateGateQoS ( RR - > node - > now ( ) , _path ) ) {
2018-06-07 22:26:18 +00:00
return true ;
2020-05-12 08:35:48 +00:00
}
if ( payloadLength ( ) > ZT_QOS_MAX_PACKET_SIZE | | payloadLength ( ) < ZT_QOS_MIN_PACKET_SIZE ) {
2022-06-08 17:01:54 +00:00
return true ; // ignore
2020-05-12 08:35:48 +00:00
}
const int64_t now = RR - > node - > now ( ) ;
uint64_t rx_id [ ZT_QOS_TABLE_SIZE ] ;
uint16_t rx_ts [ ZT_QOS_TABLE_SIZE ] ;
2022-06-08 17:01:54 +00:00
char * begin = ( char * ) payload ( ) ;
char * ptr = begin ;
2020-05-12 08:35:48 +00:00
int count = 0 ;
unsigned int len = payloadLength ( ) ;
// Read packet IDs and latency compensation intervals for each packet tracked by this QoS packet
while ( ptr < ( begin + len ) & & ( count < ZT_QOS_TABLE_SIZE ) ) {
memcpy ( ( void * ) & rx_id [ count ] , ptr , sizeof ( uint64_t ) ) ;
2022-06-08 17:01:54 +00:00
ptr + = sizeof ( uint64_t ) ;
2020-05-12 08:35:48 +00:00
memcpy ( ( void * ) & rx_ts [ count ] , ptr , sizeof ( uint16_t ) ) ;
2022-06-08 17:01:54 +00:00
ptr + = sizeof ( uint16_t ) ;
2020-05-12 08:35:48 +00:00
count + + ;
}
if ( bond ) {
bond - > receivedQoS ( _path , now , count , rx_id , rx_ts ) ;
2018-05-31 00:45:29 +00:00
}
return true ;
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doHELLO ( const RuntimeEnvironment * RR , void * tPtr , const bool alreadyAuthenticated )
2013-07-11 21:52:04 +00:00
{
2017-10-02 22:52:57 +00:00
const int64_t now = RR - > node - > now ( ) ;
2015-04-07 03:17:21 +00:00
2017-07-17 17:43:28 +00:00
const uint64_t pid = packetId ( ) ;
const Address fromAddress ( source ( ) ) ;
const unsigned int protoVersion = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION ] ;
const unsigned int vMajor = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION ] ;
const unsigned int vMinor = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION ] ;
const unsigned int vRevision = at < uint16_t > ( ZT_PROTO_VERB_HELLO_IDX_REVISION ) ;
2017-10-02 22:52:57 +00:00
const int64_t timestamp = at < int64_t > ( ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP ) ;
2017-07-17 17:43:28 +00:00
Identity id ;
unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id . deserialize ( * this , ZT_PROTO_VERB_HELLO_IDX_IDENTITY ) ;
if ( protoVersion < ZT_PROTO_VERSION_MIN ) {
RR - > t - > incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , " protocol version too old " ) ;
return true ;
}
if ( fromAddress ! = id . address ( ) ) {
RR - > t - > incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , " identity/address mismatch " ) ;
return true ;
}
SharedPtr < Peer > peer ( RR - > topology - > getPeer ( tPtr , id . address ( ) ) ) ;
if ( peer ) {
// We already have an identity with this address -- check for collisions
if ( ! alreadyAuthenticated ) {
if ( peer - > identity ( ) ! = id ) {
// Identity is different from the one we already have -- address collision
2015-11-05 20:22:58 +00:00
2017-07-17 17:43:28 +00:00
// Check rate limits
if ( ! RR - > node - > rateGateIdentityVerification ( now , _path - > address ( ) ) )
2015-11-05 20:22:58 +00:00
return true ;
2014-12-16 17:29:40 +00:00
2020-09-15 00:44:21 +00:00
uint8_t key [ ZT_SYMMETRIC_KEY_SIZE ] ;
if ( RR - > identity . agree ( id , key ) ) {
2020-08-25 21:13:20 +00:00
if ( dearmor ( key , peer - > aesKeysIfSupported ( ) ) ) { // ensure packet is authentic, otherwise drop
2017-07-17 17:43:28 +00:00
RR - > t - > incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , " address collision " ) ;
Packet outp ( id . address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( uint8_t ) Packet : : VERB_HELLO ) ;
outp . append ( ( uint64_t ) pid ) ;
outp . append ( ( uint8_t ) Packet : : ERROR_IDENTITY_COLLISION ) ;
2020-08-21 21:23:31 +00:00
outp . armor ( key , true , peer - > aesKeysIfSupported ( ) ) ;
2017-07-17 17:43:28 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
} else {
2017-08-18 20:59:22 +00:00
RR - > t - > incomingPacketMessageAuthenticationFailure ( tPtr , _path , pid , fromAddress , hops ( ) , " invalid MAC " ) ;
2015-11-05 20:22:58 +00:00
}
2017-07-17 17:43:28 +00:00
} else {
2017-08-18 20:59:22 +00:00
RR - > t - > incomingPacketMessageAuthenticationFailure ( tPtr , _path , pid , fromAddress , hops ( ) , " invalid identity " ) ;
2015-11-05 20:22:58 +00:00
}
2014-12-16 17:29:40 +00:00
2016-11-18 20:59:04 +00:00
return true ;
2017-07-17 17:43:28 +00:00
} else {
// Identity is the same as the one we already have -- check packet integrity
2016-11-18 20:59:04 +00:00
2020-08-25 21:13:20 +00:00
if ( ! dearmor ( peer - > key ( ) , peer - > aesKeysIfSupported ( ) ) ) {
2017-08-18 20:59:22 +00:00
RR - > t - > incomingPacketMessageAuthenticationFailure ( tPtr , _path , pid , fromAddress , hops ( ) , " invalid MAC " ) ;
2017-07-17 17:43:28 +00:00
return true ;
}
2016-11-18 19:09:19 +00:00
2017-07-17 17:43:28 +00:00
// Continue at // VALID
2016-09-09 18:36:10 +00:00
}
2017-07-17 17:43:28 +00:00
} // else if alreadyAuthenticated then continue at // VALID
} else {
// We don't already have an identity with this address -- validate and learn it
2014-12-16 17:29:40 +00:00
2017-07-17 17:43:28 +00:00
// Sanity check: this basically can't happen
if ( alreadyAuthenticated ) {
RR - > t - > incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , " illegal alreadyAuthenticated state " ) ;
return true ;
2013-10-16 21:47:26 +00:00
}
2013-10-05 14:19:12 +00:00
2017-07-17 17:43:28 +00:00
// Check rate limits
if ( ! RR - > node - > rateGateIdentityVerification ( now , _path - > address ( ) ) ) {
RR - > t - > incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , " rate limit exceeded " ) ;
return true ;
}
2016-09-09 18:36:10 +00:00
2017-07-17 17:43:28 +00:00
// 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 ) ) ;
2020-08-25 21:13:20 +00:00
if ( ! dearmor ( newPeer - > key ( ) , newPeer - > aesKeysIfSupported ( ) ) ) {
2017-08-18 20:59:22 +00:00
RR - > t - > incomingPacketMessageAuthenticationFailure ( tPtr , _path , pid , fromAddress , hops ( ) , " invalid MAC " ) ;
2017-07-17 17:43:28 +00:00
return true ;
2017-02-06 15:17:45 +00:00
}
2017-02-06 00:19:03 +00:00
2017-07-17 17:43:28 +00:00
// Check that identity's address is valid as per the derivation function
if ( ! id . locallyValidate ( ) ) {
RR - > t - > incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , " invalid identity " ) ;
return true ;
2017-02-06 00:19:03 +00:00
}
2017-07-17 17:43:28 +00:00
peer = RR - > topology - > addPeer ( tPtr , newPeer ) ;
2017-02-06 00:19:03 +00:00
2017-07-17 17:43:28 +00:00
// Continue at // VALID
}
2017-02-06 00:19:03 +00:00
2017-07-17 17:43:28 +00:00
// VALID -- if we made it here, packet passed identity and authenticity checks!
2017-02-06 00:19:03 +00:00
2017-07-17 17:43:28 +00:00
// Get external surface address if present (was not in old versions)
InetAddress externalSurfaceAddress ;
if ( ptr < size ( ) ) {
ptr + = externalSurfaceAddress . deserialize ( * this , ptr ) ;
if ( ( externalSurfaceAddress ) & & ( hops ( ) = = 0 ) )
RR - > sa - > iam ( tPtr , id . address ( ) , _path - > localSocket ( ) , _path - > address ( ) , externalSurfaceAddress , RR - > topology - > isUpstream ( id ) , now ) ;
}
2014-01-08 00:37:36 +00:00
2017-07-17 17:43:28 +00:00
// Get primary planet world ID and world timestamp if present
uint64_t planetWorldId = 0 ;
uint64_t planetWorldTimestamp = 0 ;
if ( ( ptr + 16 ) < = size ( ) ) {
planetWorldId = at < uint64_t > ( ptr ) ; ptr + = 8 ;
planetWorldTimestamp = at < uint64_t > ( ptr ) ; ptr + = 8 ;
}
2017-02-06 00:19:03 +00:00
2017-07-17 17:43:28 +00:00
std : : vector < std : : pair < uint64_t , uint64_t > > moonIdsAndTimestamps ;
if ( ptr < size ( ) ) {
// Remainder of packet, if present, is encrypted
cryptField ( peer - > key ( ) , ptr , size ( ) - ptr ) ;
// Get moon IDs and timestamps if present
if ( ( ptr + 2 ) < = size ( ) ) {
const unsigned int numMoons = at < uint16_t > ( ptr ) ; ptr + = 2 ;
for ( unsigned int i = 0 ; i < numMoons ; + + i ) {
if ( ( World : : Type ) ( * this ) [ ptr + + ] = = World : : TYPE_MOON )
moonIdsAndTimestamps . push_back ( std : : pair < uint64_t , uint64_t > ( at < uint64_t > ( ptr ) , at < uint64_t > ( ptr + 8 ) ) ) ;
ptr + = 16 ;
}
2015-11-02 17:32:56 +00:00
}
2017-07-17 17:43:28 +00:00
}
// Send OK(HELLO) with an echo of the packet's timestamp and some of the same
// information about us: version, sent-to address, etc.
Packet outp ( id . address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
outp . append ( ( uint64_t ) pid ) ;
outp . append ( ( uint64_t ) timestamp ) ;
outp . append ( ( unsigned char ) ZT_PROTO_VERSION ) ;
outp . append ( ( unsigned char ) ZEROTIER_ONE_VERSION_MAJOR ) ;
outp . append ( ( unsigned char ) ZEROTIER_ONE_VERSION_MINOR ) ;
outp . append ( ( uint16_t ) ZEROTIER_ONE_VERSION_REVISION ) ;
if ( protoVersion > = 5 ) {
_path - > address ( ) . serialize ( outp ) ;
} else {
/* LEGACY COMPATIBILITY HACK:
*
* For a while now ( since 1.0 .3 ) , ZeroTier has recognized changes in
* its network environment empirically by examining its external network
* address as reported by trusted peers . In versions prior to 1.1 .0
* ( protocol version < 5 ) , they did this by saving a snapshot of this
* information ( in SelfAwareness . hpp ) keyed by reporting device ID and
* address type .
*
* This causes problems when clustering is combined with symmetric NAT .
* Symmetric NAT remaps ports , so different endpoints in a cluster will
* report back different exterior addresses . Since the old code keys
* this by device ID and not sending physical address and compares the
* entire address including port , it constantly thinks its external
* surface is changing and resets connections when talking to a cluster .
*
* In new code we key by sending physical address and device and we also
* take the more conservative position of only interpreting changes in
* IP address ( neglecting port ) as a change in network topology that
* necessitates a reset . But we can make older clients work here by
* nulling out the port field . Since this info is only used for empirical
* detection of link changes , it doesn ' t break anything else .
*/
InetAddress tmpa ( _path - > address ( ) ) ;
tmpa . setPort ( 0 ) ;
tmpa . serialize ( outp ) ;
}
const unsigned int worldUpdateSizeAt = outp . size ( ) ;
outp . addSize ( 2 ) ; // make room for 16-bit size field
if ( ( planetWorldId ) & & ( RR - > topology - > planetWorldTimestamp ( ) > planetWorldTimestamp ) & & ( planetWorldId = = RR - > topology - > planetWorldId ( ) ) ) {
RR - > topology - > planet ( ) . serialize ( outp , false ) ;
}
2020-07-16 16:31:56 +00:00
if ( ! moonIdsAndTimestamps . empty ( ) ) {
2017-07-17 17:43:28 +00:00
std : : vector < World > moons ( RR - > topology - > moons ( ) ) ;
for ( std : : vector < World > : : const_iterator m ( moons . begin ( ) ) ; m ! = moons . end ( ) ; + + m ) {
for ( std : : vector < std : : pair < uint64_t , uint64_t > > : : const_iterator i ( moonIdsAndTimestamps . begin ( ) ) ; i ! = moonIdsAndTimestamps . end ( ) ; + + i ) {
if ( i - > first = = m - > id ( ) ) {
if ( m - > timestamp ( ) > i - > second )
m - > serialize ( outp , false ) ;
break ;
2017-01-27 21:50:56 +00:00
}
}
2015-10-13 19:10:44 +00:00
}
2017-07-17 17:43:28 +00:00
}
outp . setAt < uint16_t > ( worldUpdateSizeAt , ( uint16_t ) ( outp . size ( ) - ( worldUpdateSizeAt + 2 ) ) ) ;
2015-10-15 14:22:17 +00:00
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2020-05-12 08:35:48 +00:00
peer - > recordOutgoingPacket ( _path , outp . packetId ( ) , outp . payloadLength ( ) , outp . verb ( ) , ZT_QOS_NO_FLOW , now ) ;
2017-07-17 17:43:28 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , now ) ;
peer - > setRemoteVersion ( protoVersion , vMajor , vMinor , vRevision ) ; // important for this to go first so received() knows the version
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , pid , payloadLength ( ) , Packet : : VERB_HELLO , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2015-10-28 00:59:17 +00:00
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doOK ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
2017-07-17 17:43:28 +00:00
const Packet : : Verb inReVerb = ( Packet : : Verb ) ( * this ) [ ZT_PROTO_VERB_OK_IDX_IN_RE_VERB ] ;
const uint64_t inRePacketId = at < uint64_t > ( ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID ) ;
uint64_t networkId = 0 ;
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
if ( ! RR - > node - > expectingReplyTo ( inRePacketId ) )
return true ;
2017-02-04 18:21:31 +00:00
2017-07-17 17:43:28 +00:00
switch ( inReVerb ) {
2015-10-28 00:59:17 +00:00
2017-07-17 17:43:28 +00:00
case Packet : : VERB_HELLO : {
const uint64_t latency = RR - > node - > now ( ) - at < uint64_t > ( ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP ) ;
const unsigned int vProto = ( * this ) [ ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION ] ;
const unsigned int vMajor = ( * this ) [ ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION ] ;
const unsigned int vMinor = ( * this ) [ ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION ] ;
const unsigned int vRevision = at < uint16_t > ( ZT_PROTO_VERB_HELLO__OK__IDX_REVISION ) ;
if ( vProto < ZT_PROTO_VERSION_MIN )
return true ;
2017-02-04 21:17:00 +00:00
2017-07-17 17:43:28 +00:00
InetAddress externalSurfaceAddress ;
unsigned int ptr = ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2 ;
2013-12-27 04:57:17 +00:00
2017-07-17 17:43:28 +00:00
// Get reported external surface address if present
if ( ptr < size ( ) )
ptr + = externalSurfaceAddress . deserialize ( * this , ptr ) ;
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
// Handle planet or moon updates if present
if ( ( ptr + 2 ) < = size ( ) ) {
const unsigned int worldsLen = at < uint16_t > ( ptr ) ; ptr + = 2 ;
if ( RR - > topology - > shouldAcceptWorldUpdateFrom ( peer - > address ( ) ) ) {
const unsigned int endOfWorlds = ptr + worldsLen ;
while ( ptr < endOfWorlds ) {
World w ;
ptr + = w . deserialize ( * this , ptr ) ;
RR - > topology - > addWorld ( tPtr , w , false ) ;
}
} else {
ptr + = worldsLen ;
2013-08-05 16:16:25 +00:00
}
2017-07-17 17:43:28 +00:00
}
2014-09-30 23:28:25 +00:00
2019-07-15 21:30:34 +00:00
if ( ! hops ( ) ) {
2020-05-12 08:35:48 +00:00
SharedPtr < Bond > bond = peer - > bond ( ) ;
if ( ! bond ) {
_path - > updateLatency ( ( unsigned int ) latency , RR - > node - > now ( ) ) ;
}
2018-05-31 00:45:29 +00:00
}
2017-10-25 19:42:14 +00:00
2017-07-17 17:43:28 +00:00
peer - > setRemoteVersion ( vProto , vMajor , vMinor , vRevision ) ;
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
if ( ( externalSurfaceAddress ) & & ( hops ( ) = = 0 ) )
RR - > sa - > iam ( tPtr , peer - > address ( ) , _path - > localSocket ( ) , _path - > address ( ) , externalSurfaceAddress , RR - > topology - > isUpstream ( peer - > identity ( ) ) , RR - > node - > now ( ) ) ;
} break ;
2014-10-09 19:42:25 +00:00
2017-07-17 17:43:28 +00:00
case Packet : : VERB_WHOIS :
if ( RR - > topology - > isUpstream ( peer - > identity ( ) ) ) {
const Identity id ( * this , ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY ) ;
2021-09-21 02:05:49 +00:00
RR - > sw - > doAnythingWaitingForPeer ( tPtr , RR - > topology - > addPeer ( tPtr , SharedPtr < Peer > ( new Peer ( RR , RR - > identity , id ) ) ) ) ;
2017-07-17 17:43:28 +00:00
}
break ;
case Packet : : VERB_NETWORK_CONFIG_REQUEST : {
networkId = at < uint64_t > ( ZT_PROTO_VERB_OK_IDX_PAYLOAD ) ;
const SharedPtr < Network > network ( RR - > node - > network ( networkId ) ) ;
if ( network )
network - > handleConfigChunk ( tPtr , packetId ( ) , source ( ) , * this , ZT_PROTO_VERB_OK_IDX_PAYLOAD ) ;
} break ;
case Packet : : VERB_MULTICAST_GATHER : {
networkId = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID ) ;
const SharedPtr < Network > network ( RR - > node - > network ( networkId ) ) ;
if ( network ) {
const MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC , 6 ) , 6 ) , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI ) ) ;
const unsigned int count = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4 ) ;
2020-05-12 08:35:48 +00:00
RR - > mc - > addMultiple ( tPtr , RR - > node - > now ( ) , networkId , mg , field ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6 , count * 5 ) , count , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS ) ) ;
2017-07-17 17:43:28 +00:00
}
} break ;
2014-10-09 19:42:25 +00:00
2017-07-17 17:43:28 +00:00
case Packet : : VERB_MULTICAST_FRAME : {
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS ] ;
networkId = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID ) ;
const MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC , 6 ) , 6 ) , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI ) ) ;
2014-10-09 19:42:25 +00:00
2017-07-17 17:43:28 +00:00
const SharedPtr < Network > network ( RR - > node - > network ( networkId ) ) ;
if ( network ) {
unsigned int offset = 0 ;
if ( ( flags & 0x01 ) ! = 0 ) { // deprecated but still used by older peers
CertificateOfMembership com ;
offset + = com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS ) ;
if ( com )
network - > addCredential ( tPtr , com ) ;
2014-10-02 20:50:37 +00:00
}
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
if ( ( flags & 0x02 ) ! = 0 ) {
// OK(MULTICAST_FRAME) includes implicit gather results
offset + = ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS ;
unsigned int totalKnown = at < uint32_t > ( offset ) ; offset + = 4 ;
unsigned int count = at < uint16_t > ( offset ) ; offset + = 2 ;
RR - > mc - > addMultiple ( tPtr , RR - > node - > now ( ) , networkId , mg , field ( offset , count * 5 ) , count , totalKnown ) ;
}
}
} break ;
2013-12-24 18:39:29 +00:00
2017-07-17 17:43:28 +00:00
default : break ;
2013-07-11 22:15:51 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_OK , inRePacketId , inReVerb , false , networkId , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doWHOIS ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
2018-01-25 12:11:59 +00:00
if ( ( ! RR - > topology - > amUpstream ( ) ) & & ( ! peer - > rateGateInboundWhoisRequest ( RR - > node - > now ( ) ) ) )
2017-07-17 17:43:28 +00:00
return true ;
2016-08-23 18:29:02 +00:00
2017-07-17 17:43:28 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_WHOIS ) ;
outp . append ( packetId ( ) ) ;
2016-08-23 18:29:02 +00:00
2017-07-17 17:43:28 +00:00
unsigned int count = 0 ;
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ;
while ( ( ptr + ZT_ADDRESS_LENGTH ) < = size ( ) ) {
const Address addr ( field ( ptr , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
ptr + = ZT_ADDRESS_LENGTH ;
2016-08-23 18:29:02 +00:00
2017-07-17 17:43:28 +00:00
const Identity id ( RR - > topology - > getIdentity ( tPtr , addr ) ) ;
if ( id ) {
id . serialize ( outp , false ) ;
+ + count ;
} else {
// Request unknown WHOIS from upstream from us (if we have one)
2017-08-23 23:42:17 +00:00
RR - > sw - > requestWhois ( tPtr , RR - > node - > now ( ) , addr ) ;
2016-08-23 18:29:02 +00:00
}
2017-07-17 17:43:28 +00:00
}
2016-08-23 18:29:02 +00:00
2017-07-17 17:43:28 +00:00
if ( count > 0 ) {
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2017-07-17 17:43:28 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_WHOIS , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doRENDEZVOUS ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
2017-07-17 17:43:28 +00:00
if ( RR - > topology - > isUpstream ( peer - > identity ( ) ) ) {
const Address with ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
const SharedPtr < Peer > rendezvousWith ( RR - > topology - > getPeer ( tPtr , with ) ) ;
if ( rendezvousWith ) {
const unsigned int port = at < uint16_t > ( ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT ) ;
const unsigned int addrlen = ( * this ) [ ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN ] ;
if ( ( port > 0 ) & & ( ( addrlen = = 4 ) | | ( addrlen = = 16 ) ) ) {
2019-07-15 21:30:34 +00:00
InetAddress atAddr ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS , addrlen ) , addrlen , port ) ;
2017-07-17 17:43:28 +00:00
if ( RR - > node - > shouldUsePathForZeroTierTraffic ( tPtr , with , _path - > localSocket ( ) , atAddr ) ) {
const uint64_t junk = RR - > node - > prng ( ) ;
RR - > node - > putPacket ( tPtr , _path - > localSocket ( ) , atAddr , & junk , 4 , 2 ) ; // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls
2018-01-08 21:06:24 +00:00
rendezvousWith - > attemptToContactAt ( tPtr , _path - > localSocket ( ) , atAddr , RR - > node - > now ( ) , false ) ;
2015-10-19 19:56:29 +00:00
}
2013-07-11 22:15:51 +00:00
}
}
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_RENDEZVOUS , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2020-05-12 08:35:48 +00:00
// Returns true if packet appears valid; pos and proto will be set
static bool _ipv6GetPayload ( const uint8_t * frameData , unsigned int frameLen , unsigned int & pos , unsigned int & proto )
2013-07-11 22:15:51 +00:00
{
2020-05-12 08:35:48 +00:00
if ( frameLen < 40 )
return false ;
pos = 40 ;
proto = frameData [ 6 ] ;
while ( pos < = frameLen ) {
switch ( proto ) {
case 0 : // hop-by-hop options
case 43 : // routing
case 60 : // destination options
case 135 : // mobility options
if ( ( pos + 8 ) > frameLen )
return false ; // invalid!
proto = frameData [ pos ] ;
pos + = ( ( unsigned int ) frameData [ pos + 1 ] * 8 ) + 8 ;
break ;
//case 44: // fragment -- we currently can't parse these and they are deprecated in IPv6 anyway
//case 50:
//case 51: // IPSec ESP and AH -- we have to stop here since this is encrypted stuff
default :
return true ;
}
}
return false ; // overflow == invalid
}
bool IncomingPacket : : _doFRAME ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer , int32_t flowId )
{
int32_t _flowId = ZT_QOS_NO_FLOW ;
SharedPtr < Bond > bond = peer - > bond ( ) ;
2022-10-10 06:07:16 +00:00
if ( bond & & bond - > flowHashingSupported ( ) ) {
2020-05-12 08:35:48 +00:00
if ( size ( ) > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) {
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE ) ;
const unsigned int frameLen = size ( ) - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
const uint8_t * const frameData = reinterpret_cast < const uint8_t * > ( data ( ) ) + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
if ( etherType = = ZT_ETHERTYPE_IPV4 & & ( frameLen > = 20 ) ) {
uint16_t srcPort = 0 ;
uint16_t dstPort = 0 ;
uint8_t proto = ( reinterpret_cast < const uint8_t * > ( frameData ) [ 9 ] ) ;
const unsigned int headerLen = 4 * ( reinterpret_cast < const uint8_t * > ( frameData ) [ 0 ] & 0xf ) ;
switch ( proto ) {
case 0x01 : // ICMP
//flowId = 0x01;
break ;
// All these start with 16-bit source and destination port in that order
case 0x06 : // TCP
case 0x11 : // UDP
case 0x84 : // SCTP
case 0x88 : // UDPLite
if ( frameLen > ( headerLen + 4 ) ) {
unsigned int pos = headerLen + 0 ;
srcPort = ( reinterpret_cast < const uint8_t * > ( frameData ) [ pos + + ] ) < < 8 ;
srcPort | = ( reinterpret_cast < const uint8_t * > ( frameData ) [ pos ] ) ;
pos + + ;
dstPort = ( reinterpret_cast < const uint8_t * > ( frameData ) [ pos + + ] ) < < 8 ;
dstPort | = ( reinterpret_cast < const uint8_t * > ( frameData ) [ pos ] ) ;
_flowId = dstPort ^ srcPort ^ proto ;
}
break ;
}
}
if ( etherType = = ZT_ETHERTYPE_IPV6 & & ( frameLen > = 40 ) ) {
uint16_t srcPort = 0 ;
uint16_t dstPort = 0 ;
unsigned int pos ;
unsigned int proto ;
_ipv6GetPayload ( ( const uint8_t * ) frameData , frameLen , pos , proto ) ;
switch ( proto ) {
case 0x3A : // ICMPv6
//flowId = 0x3A;
break ;
// All these start with 16-bit source and destination port in that order
case 0x06 : // TCP
case 0x11 : // UDP
case 0x84 : // SCTP
case 0x88 : // UDPLite
if ( frameLen > ( pos + 4 ) ) {
srcPort = ( reinterpret_cast < const uint8_t * > ( frameData ) [ pos + + ] ) < < 8 ;
srcPort | = ( reinterpret_cast < const uint8_t * > ( frameData ) [ pos ] ) ;
pos + + ;
dstPort = ( reinterpret_cast < const uint8_t * > ( frameData ) [ pos + + ] ) < < 8 ;
dstPort | = ( reinterpret_cast < const uint8_t * > ( frameData ) [ pos ] ) ;
_flowId = dstPort ^ srcPort ^ proto ;
}
break ;
default :
break ;
}
}
}
}
2017-07-17 17:43:28 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ;
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
bool trustEstablished = false ;
if ( network ) {
if ( network - > gate ( tPtr , peer ) ) {
trustEstablished = true ;
if ( size ( ) > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ) {
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE ) ;
const MAC sourceMac ( peer - > address ( ) , nwid ) ;
const unsigned int frameLen = size ( ) - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
const uint8_t * const frameData = reinterpret_cast < const uint8_t * > ( data ( ) ) + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
if ( network - > filterIncomingPacket ( tPtr , peer , RR - > identity . address ( ) , sourceMac , network - > mac ( ) , frameData , frameLen , etherType , 0 ) > 0 )
RR - > node - > putFrame ( tPtr , nwid , network - > userPtr ( ) , sourceMac , network - > mac ( ) , etherType , 0 , ( const void * ) frameData , frameLen ) ;
2014-06-18 16:00:53 +00:00
}
2013-07-11 22:15:51 +00:00
} else {
2017-03-28 00:03:17 +00:00
_sendErrorNeedCredentials ( RR , tPtr , peer , nwid ) ;
2019-03-19 23:43:43 +00:00
return false ;
2013-07-11 22:15:51 +00:00
}
}
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_FRAME , 0 , Packet : : VERB_NOP , trustEstablished , nwid , _flowId ) ;
2017-07-17 17:43:28 +00:00
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2020-05-12 08:35:48 +00:00
bool IncomingPacket : : _doEXT_FRAME ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer , int32_t flowId )
2013-07-11 22:15:51 +00:00
{
2017-07-17 17:43:28 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID ) ;
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
if ( network ) {
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS ] ;
unsigned int comLen = 0 ;
if ( ( flags & 0x01 ) ! = 0 ) { // inline COM with EXT_FRAME is deprecated but still used with old peers
CertificateOfMembership com ;
comLen = com . deserialize ( * this , ZT_PROTO_VERB_EXT_FRAME_IDX_COM ) ;
if ( com )
network - > addCredential ( tPtr , com ) ;
}
2014-10-01 00:26:34 +00:00
2017-07-17 17:43:28 +00:00
if ( ! network - > gate ( tPtr , peer ) ) {
RR - > t - > incomingNetworkAccessDenied ( tPtr , network , _path , packetId ( ) , size ( ) , peer - > address ( ) , Packet : : VERB_EXT_FRAME , true ) ;
_sendErrorNeedCredentials ( RR , tPtr , peer , nwid ) ;
2019-03-19 23:43:43 +00:00
return false ;
2017-07-17 17:43:28 +00:00
}
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
if ( size ( ) > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) {
const unsigned int etherType = at < uint16_t > ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE ) ;
const MAC to ( field ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_TO , ZT_PROTO_VERB_EXT_FRAME_LEN_TO ) , ZT_PROTO_VERB_EXT_FRAME_LEN_TO ) ;
const MAC from ( field ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_FROM , ZT_PROTO_VERB_EXT_FRAME_LEN_FROM ) , ZT_PROTO_VERB_EXT_FRAME_LEN_FROM ) ;
const unsigned int frameLen = size ( ) - ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) ;
const uint8_t * const frameData = ( const uint8_t * ) field ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD , frameLen ) ;
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
if ( ( ! from ) | | ( from = = network - > mac ( ) ) ) {
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true , nwid , flowId ) ; // trustEstablished because COM is okay
2017-07-17 17:43:28 +00:00
return true ;
}
2014-06-11 04:41:34 +00:00
2017-07-17 17:43:28 +00:00
switch ( network - > filterIncomingPacket ( tPtr , peer , RR - > identity . address ( ) , from , to , frameData , frameLen , etherType , 0 ) ) {
case 1 :
if ( from ! = MAC ( peer - > address ( ) , nwid ) ) {
if ( network - > config ( ) . permitsBridging ( peer - > address ( ) ) ) {
network - > learnBridgeRoute ( from , peer - > address ( ) ) ;
} else {
RR - > t - > incomingNetworkFrameDropped ( tPtr , network , _path , packetId ( ) , size ( ) , peer - > address ( ) , Packet : : VERB_EXT_FRAME , from , to , " bridging not allowed (remote) " ) ;
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true , nwid , flowId ) ; // trustEstablished because COM is okay
2017-07-17 17:43:28 +00:00
return true ;
}
} else if ( to ! = network - > mac ( ) ) {
if ( to . isMulticast ( ) ) {
if ( network - > config ( ) . multicastLimit = = 0 ) {
RR - > t - > incomingNetworkFrameDropped ( tPtr , network , _path , packetId ( ) , size ( ) , peer - > address ( ) , Packet : : VERB_EXT_FRAME , from , to , " multicast disabled " ) ;
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true , nwid , flowId ) ; // trustEstablished because COM is okay
2016-08-29 22:54:06 +00:00
return true ;
}
2017-07-17 17:43:28 +00:00
} else if ( ! network - > config ( ) . permitsBridging ( RR - > identity . address ( ) ) ) {
RR - > t - > incomingNetworkFrameDropped ( tPtr , network , _path , packetId ( ) , size ( ) , peer - > address ( ) , Packet : : VERB_EXT_FRAME , from , to , " bridging not allowed (local) " ) ;
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true , nwid , flowId ) ; // trustEstablished because COM is okay
2017-07-17 17:43:28 +00:00
return true ;
2016-08-29 22:54:06 +00:00
}
2017-07-17 17:43:28 +00:00
}
// fall through -- 2 means accept regardless of bridging checks or other restrictions
case 2 :
RR - > node - > putFrame ( tPtr , nwid , network - > userPtr ( ) , from , to , etherType , 0 , ( const void * ) frameData , frameLen ) ;
break ;
2016-08-24 23:16:39 +00:00
}
2017-07-17 17:43:28 +00:00
}
2016-09-23 23:08:38 +00:00
2017-07-17 17:43:28 +00:00
if ( ( flags & 0x10 ) ! = 0 ) { // ACK requested
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( uint8_t ) Packet : : VERB_EXT_FRAME ) ;
outp . append ( ( uint64_t ) packetId ( ) ) ;
outp . append ( ( uint64_t ) nwid ) ;
2020-05-12 08:35:48 +00:00
const int64_t now = RR - > node - > now ( ) ;
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2020-05-12 08:35:48 +00:00
peer - > recordOutgoingPacket ( _path , outp . packetId ( ) , outp . payloadLength ( ) , outp . verb ( ) , ZT_QOS_NO_FLOW , now ) ;
2017-07-17 17:43:28 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2014-06-11 04:41:34 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true , nwid , flowId ) ;
2017-07-17 17:43:28 +00:00
} else {
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , false , nwid , flowId ) ;
2014-06-11 04:41:34 +00:00
}
2017-07-17 17:43:28 +00:00
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doECHO ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2015-10-07 23:11:50 +00:00
{
2020-05-12 08:35:48 +00:00
uint64_t now = RR - > node - > now ( ) ;
2022-02-21 22:37:39 +00:00
if ( ! _path - > rateGateEchoRequest ( now ) ) {
2017-07-17 17:43:28 +00:00
return true ;
2020-05-12 08:35:48 +00:00
}
2016-09-09 18:36:10 +00:00
2017-07-17 17:43:28 +00:00
const uint64_t pid = packetId ( ) ;
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_ECHO ) ;
outp . append ( ( uint64_t ) pid ) ;
if ( size ( ) > ZT_PACKET_IDX_PAYLOAD )
outp . append ( reinterpret_cast < const unsigned char * > ( data ( ) ) + ZT_PACKET_IDX_PAYLOAD , size ( ) - ZT_PACKET_IDX_PAYLOAD ) ;
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2020-05-12 08:35:48 +00:00
peer - > recordOutgoingPacket ( _path , outp . packetId ( ) , outp . payloadLength ( ) , outp . verb ( ) , ZT_QOS_NO_FLOW , now ) ;
2017-07-17 17:43:28 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , pid , payloadLength ( ) , Packet : : VERB_ECHO , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2016-09-09 18:36:10 +00:00
2015-10-07 23:11:50 +00:00
return true ;
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doMULTICAST_LIKE ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2013-09-27 20:03:13 +00:00
{
2017-10-02 22:52:57 +00:00
const int64_t now = RR - > node - > now ( ) ;
2019-03-21 23:18:49 +00:00
bool authorized = false ;
uint64_t lastNwid = 0 ;
2019-03-14 21:29:15 +00:00
// Packet contains a series of 18-byte network,MAC,ADI tuples
2019-03-21 23:18:49 +00:00
for ( unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ; ptr < size ( ) ; ptr + = 18 ) {
const uint64_t nwid = at < uint64_t > ( ptr ) ;
if ( nwid ! = lastNwid ) {
lastNwid = nwid ;
SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
if ( network )
authorized = network - > gate ( tPtr , peer ) ;
if ( ! authorized )
authorized = ( ( RR - > topology - > amUpstream ( ) ) | | ( RR - > node - > localControllerHasAuthorized ( now , nwid , peer - > address ( ) ) ) ) ;
}
if ( authorized )
RR - > mc - > add ( tPtr , now , nwid , MulticastGroup ( MAC ( field ( ptr + 8 , 6 ) , 6 ) , at < uint32_t > ( ptr + 14 ) ) , peer - > address ( ) ) ;
}
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_MULTICAST_LIKE , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2013-09-27 20:03:13 +00:00
return true ;
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doNETWORK_CREDENTIALS ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2013-07-29 17:56:20 +00:00
{
2017-07-17 17:43:28 +00:00
if ( ! peer - > rateGateCredentialsReceived ( RR - > node - > now ( ) ) )
return true ;
2016-09-13 17:13:23 +00:00
2017-07-17 17:43:28 +00:00
CertificateOfMembership com ;
Capability cap ;
Tag tag ;
Revocation revocation ;
CertificateOfOwnership coo ;
bool trustEstablished = false ;
SharedPtr < Network > network ;
unsigned int p = ZT_PACKET_IDX_PAYLOAD ;
while ( ( p < size ( ) ) & & ( ( * this ) [ p ] ! = 0 ) ) {
p + = com . deserialize ( * this , p ) ;
if ( com ) {
network = RR - > node - > network ( com . networkId ( ) ) ;
if ( network ) {
switch ( network - > addCredential ( tPtr , com ) ) {
case Membership : : ADD_REJECTED :
break ;
case Membership : : ADD_ACCEPTED_NEW :
case Membership : : ADD_ACCEPTED_REDUNDANT :
trustEstablished = true ;
break ;
case Membership : : ADD_DEFERRED_FOR_WHOIS :
return false ;
}
2019-03-14 21:29:15 +00:00
}
2013-10-16 21:47:26 +00:00
}
2017-07-17 17:43:28 +00:00
}
+ + p ; // skip trailing 0 after COMs if present
if ( p < size ( ) ) { // older ZeroTier versions do not send capabilities, tags, or revocations
const unsigned int numCapabilities = at < uint16_t > ( p ) ; p + = 2 ;
for ( unsigned int i = 0 ; i < numCapabilities ; + + i ) {
p + = cap . deserialize ( * this , p ) ;
if ( ( ! network ) | | ( network - > id ( ) ! = cap . networkId ( ) ) )
network = RR - > node - > network ( cap . networkId ( ) ) ;
if ( network ) {
switch ( network - > addCredential ( tPtr , cap ) ) {
case Membership : : ADD_REJECTED :
break ;
case Membership : : ADD_ACCEPTED_NEW :
case Membership : : ADD_ACCEPTED_REDUNDANT :
trustEstablished = true ;
break ;
case Membership : : ADD_DEFERRED_FOR_WHOIS :
return false ;
2016-08-09 00:33:26 +00:00
}
2016-08-04 01:04:08 +00:00
}
2017-07-17 17:43:28 +00:00
}
2016-08-04 16:51:15 +00:00
2017-07-17 17:43:28 +00:00
if ( p > = size ( ) ) return true ;
const unsigned int numTags = at < uint16_t > ( p ) ; p + = 2 ;
for ( unsigned int i = 0 ; i < numTags ; + + i ) {
p + = tag . deserialize ( * this , p ) ;
if ( ( ! network ) | | ( network - > id ( ) ! = tag . networkId ( ) ) )
network = RR - > node - > network ( tag . networkId ( ) ) ;
if ( network ) {
switch ( network - > addCredential ( tPtr , tag ) ) {
case Membership : : ADD_REJECTED :
break ;
case Membership : : ADD_ACCEPTED_NEW :
case Membership : : ADD_ACCEPTED_REDUNDANT :
trustEstablished = true ;
break ;
case Membership : : ADD_DEFERRED_FOR_WHOIS :
return false ;
2016-08-09 00:33:26 +00:00
}
2016-08-04 01:04:08 +00:00
}
2017-07-17 17:43:28 +00:00
}
2016-09-23 23:08:38 +00:00
2017-07-17 17:43:28 +00:00
if ( p > = size ( ) ) return true ;
const unsigned int numRevocations = at < uint16_t > ( p ) ; p + = 2 ;
for ( unsigned int i = 0 ; i < numRevocations ; + + i ) {
p + = revocation . deserialize ( * this , p ) ;
if ( ( ! network ) | | ( network - > id ( ) ! = revocation . networkId ( ) ) )
network = RR - > node - > network ( revocation . networkId ( ) ) ;
if ( network ) {
switch ( network - > addCredential ( tPtr , peer - > address ( ) , revocation ) ) {
case Membership : : ADD_REJECTED :
break ;
case Membership : : ADD_ACCEPTED_NEW :
case Membership : : ADD_ACCEPTED_REDUNDANT :
trustEstablished = true ;
break ;
case Membership : : ADD_DEFERRED_FOR_WHOIS :
return false ;
2016-09-23 23:08:38 +00:00
}
}
2017-07-17 17:43:28 +00:00
}
2017-02-23 19:47:36 +00:00
2017-07-17 17:43:28 +00:00
if ( p > = size ( ) ) return true ;
const unsigned int numCoos = at < uint16_t > ( p ) ; p + = 2 ;
for ( unsigned int i = 0 ; i < numCoos ; + + i ) {
p + = coo . deserialize ( * this , p ) ;
if ( ( ! network ) | | ( network - > id ( ) ! = coo . networkId ( ) ) )
network = RR - > node - > network ( coo . networkId ( ) ) ;
if ( network ) {
switch ( network - > addCredential ( tPtr , coo ) ) {
case Membership : : ADD_REJECTED :
break ;
case Membership : : ADD_ACCEPTED_NEW :
case Membership : : ADD_ACCEPTED_REDUNDANT :
trustEstablished = true ;
break ;
case Membership : : ADD_DEFERRED_FOR_WHOIS :
return false ;
2017-02-23 19:47:36 +00:00
}
}
2016-08-04 01:04:08 +00:00
}
2013-10-16 21:47:26 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_NETWORK_CREDENTIALS , 0 , Packet : : VERB_NOP , trustEstablished , ( network ) ? network - > id ( ) : 0 , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2013-08-02 21:17:34 +00:00
return true ;
2013-07-29 17:56:20 +00:00
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doNETWORK_CONFIG_REQUEST ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2013-07-29 17:56:20 +00:00
{
2017-07-17 17:43:28 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID ) ;
const unsigned int hopCount = hops ( ) ;
const uint64_t requestPacketId = packetId ( ) ;
if ( RR - > localNetworkController ) {
const unsigned int metaDataLength = ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN < = size ( ) ) ? at < uint16_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN ) : 0 ;
const char * metaDataBytes = ( metaDataLength ! = 0 ) ? ( const char * ) field ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT , metaDataLength ) : ( const char * ) 0 ;
const Dictionary < ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY > metaData ( metaDataBytes , metaDataLength ) ;
RR - > localNetworkController - > request ( nwid , ( hopCount > 0 ) ? InetAddress ( ) : _path - > address ( ) , requestPacketId , peer - > identity ( ) , metaData ) ;
} else {
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
outp . append ( requestPacketId ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_UNSUPPORTED_OPERATION ) ;
outp . append ( nwid ) ;
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2017-07-17 17:43:28 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2013-08-02 21:17:34 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hopCount , requestPacketId , payloadLength ( ) , Packet : : VERB_NETWORK_CONFIG_REQUEST , 0 , Packet : : VERB_NOP , false , nwid , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2013-08-02 21:17:34 +00:00
return true ;
2013-07-29 17:56:20 +00:00
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doNETWORK_CONFIG ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2016-08-09 20:52:08 +00:00
{
2017-07-17 17:43:28 +00:00
const SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD ) ) ) ;
if ( network ) {
const uint64_t configUpdateId = network - > handleConfigChunk ( tPtr , packetId ( ) , source ( ) , * this , ZT_PACKET_IDX_PAYLOAD ) ;
if ( configUpdateId ) {
2022-01-20 17:44:56 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2017-07-17 17:43:28 +00:00
outp . append ( ( uint8_t ) Packet : : VERB_ECHO ) ;
outp . append ( ( uint64_t ) packetId ( ) ) ;
outp . append ( ( uint64_t ) network - > id ( ) ) ;
outp . append ( ( uint64_t ) configUpdateId ) ;
2020-05-12 08:35:48 +00:00
const int64_t now = RR - > node - > now ( ) ;
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2020-05-12 08:35:48 +00:00
peer - > recordOutgoingPacket ( _path , outp . packetId ( ) , outp . payloadLength ( ) , outp . verb ( ) , ZT_QOS_NO_FLOW , now ) ;
2022-04-20 01:29:11 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2016-09-27 18:33:48 +00:00
}
2016-08-09 20:52:08 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_NETWORK_CONFIG , 0 , Packet : : VERB_NOP , false , ( network ) ? network - > id ( ) : 0 , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2016-08-09 20:52:08 +00:00
return true ;
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doMULTICAST_GATHER ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2014-09-26 21:18:25 +00:00
{
2017-07-17 17:43:28 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID ) ;
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS ] ;
const MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC , 6 ) , 6 ) , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI ) ) ;
const unsigned int gatherLimit = at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT ) ;
2016-09-09 18:36:10 +00:00
2017-07-17 17:43:28 +00:00
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
2016-08-23 18:29:02 +00:00
2017-07-17 17:43:28 +00:00
if ( ( flags & 0x01 ) ! = 0 ) {
try {
CertificateOfMembership com ;
com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM ) ;
2019-03-14 21:29:15 +00:00
if ( ( com ) & & ( network ) )
network - > addCredential ( tPtr , com ) ;
2017-07-17 17:43:28 +00:00
} catch ( . . . ) { } // discard invalid COMs
}
2014-09-30 23:28:25 +00:00
2022-04-19 23:59:54 +00:00
const bool trustEstablished = ( network ) ? network - > gate ( tPtr , peer ) : false ;
2019-03-14 21:29:15 +00:00
const int64_t now = RR - > node - > now ( ) ;
if ( ( gatherLimit > 0 ) & & ( ( trustEstablished ) | | ( RR - > topology - > amUpstream ( ) ) | | ( RR - > node - > localControllerHasAuthorized ( now , nwid , peer - > address ( ) ) ) ) ) {
2017-07-17 17:43:28 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_MULTICAST_GATHER ) ;
outp . append ( packetId ( ) ) ;
outp . append ( nwid ) ;
mg . mac ( ) . appendTo ( outp ) ;
outp . append ( ( uint32_t ) mg . adi ( ) ) ;
const unsigned int gatheredLocally = RR - > mc - > gather ( peer - > address ( ) , nwid , mg , outp , gatherLimit ) ;
if ( gatheredLocally > 0 ) {
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2020-05-12 08:35:48 +00:00
peer - > recordOutgoingPacket ( _path , outp . packetId ( ) , outp . payloadLength ( ) , outp . verb ( ) , ZT_QOS_NO_FLOW , now ) ;
2019-03-14 21:29:15 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , now ) ;
2017-07-17 17:43:28 +00:00
}
2014-09-30 23:28:25 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_MULTICAST_GATHER , 0 , Packet : : VERB_NOP , trustEstablished , nwid , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2014-09-30 23:28:25 +00:00
return true ;
2014-09-26 21:18:25 +00:00
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doMULTICAST_FRAME ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2014-09-26 21:18:25 +00:00
{
2017-07-17 17:43:28 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID ) ;
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS ] ;
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
if ( network ) {
// Offset -- size of optional fields added to position of later fields
unsigned int offset = 0 ;
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
if ( ( flags & 0x01 ) ! = 0 ) {
// This is deprecated but may still be sent by old peers
CertificateOfMembership com ;
offset + = com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM ) ;
if ( com )
network - > addCredential ( tPtr , com ) ;
}
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
if ( ! network - > gate ( tPtr , peer ) ) {
_sendErrorNeedCredentials ( RR , tPtr , peer , nwid ) ;
2019-03-19 23:43:43 +00:00
return false ;
2017-07-17 17:43:28 +00:00
}
unsigned int gatherLimit = 0 ;
if ( ( flags & 0x02 ) ! = 0 ) {
gatherLimit = at < uint32_t > ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT ) ;
offset + = 4 ;
}
MAC from ;
if ( ( flags & 0x04 ) ! = 0 ) {
from . setTo ( field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC , 6 ) , 6 ) ;
offset + = 6 ;
} else {
from . fromAddress ( peer - > address ( ) , nwid ) ;
}
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
const MulticastGroup to ( MAC ( field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC , 6 ) , 6 ) , at < uint32_t > ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI ) ) ;
const unsigned int etherType = at < uint16_t > ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE ) ;
const unsigned int frameLen = size ( ) - ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME ) ;
2014-10-01 23:29:52 +00:00
2017-07-17 17:43:28 +00:00
if ( network - > config ( ) . multicastLimit = = 0 ) {
RR - > t - > incomingNetworkFrameDropped ( tPtr , network , _path , packetId ( ) , size ( ) , peer - > address ( ) , Packet : : VERB_MULTICAST_FRAME , from , to . mac ( ) , " multicast disabled " ) ;
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , false , nwid , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
return true ;
}
if ( ( frameLen > 0 ) & & ( frameLen < = ZT_MAX_MTU ) ) {
if ( ! to . mac ( ) . isMulticast ( ) ) {
RR - > t - > incomingPacketInvalid ( tPtr , _path , packetId ( ) , source ( ) , hops ( ) , Packet : : VERB_MULTICAST_FRAME , " destination not multicast " ) ;
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , true , nwid , ZT_QOS_NO_FLOW ) ; // trustEstablished because COM is okay
2017-07-17 17:43:28 +00:00
return true ;
}
if ( ( ! from ) | | ( from . isMulticast ( ) ) | | ( from = = network - > mac ( ) ) ) {
RR - > t - > incomingPacketInvalid ( tPtr , _path , packetId ( ) , source ( ) , hops ( ) , Packet : : VERB_MULTICAST_FRAME , " invalid source MAC " ) ;
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , true , nwid , ZT_QOS_NO_FLOW ) ; // trustEstablished because COM is okay
2017-07-07 23:58:05 +00:00
return true ;
}
2014-10-10 00:58:31 +00:00
2018-01-27 03:14:10 +00:00
const uint8_t * const frameData = ( const uint8_t * ) field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME , frameLen ) ;
if ( ( flags & 0x08 ) & & ( network - > config ( ) . isMulticastReplicator ( RR - > identity . address ( ) ) ) )
RR - > mc - > send ( tPtr , RR - > node - > now ( ) , network , peer - > address ( ) , to , from , etherType , frameData , frameLen ) ;
2017-07-17 17:43:28 +00:00
if ( from ! = MAC ( peer - > address ( ) , nwid ) ) {
if ( network - > config ( ) . permitsBridging ( peer - > address ( ) ) ) {
network - > learnBridgeRoute ( from , peer - > address ( ) ) ;
} else {
RR - > t - > incomingNetworkFrameDropped ( tPtr , network , _path , packetId ( ) , size ( ) , peer - > address ( ) , Packet : : VERB_MULTICAST_FRAME , from , to . mac ( ) , " bridging not allowed (remote) " ) ;
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , true , nwid , ZT_QOS_NO_FLOW ) ; // trustEstablished because COM is okay
2014-10-09 19:42:25 +00:00
return true ;
2014-10-01 23:29:52 +00:00
}
2014-09-30 23:28:25 +00:00
}
2014-10-09 19:42:25 +00:00
2017-07-17 17:43:28 +00:00
if ( network - > filterIncomingPacket ( tPtr , peer , RR - > identity . address ( ) , from , to . mac ( ) , frameData , frameLen , etherType , 0 ) > 0 )
RR - > node - > putFrame ( tPtr , nwid , network - > userPtr ( ) , from , to . mac ( ) , etherType , 0 , ( const void * ) frameData , frameLen ) ;
}
2014-09-30 23:28:25 +00:00
2017-07-17 17:43:28 +00:00
if ( gatherLimit ) {
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_MULTICAST_FRAME ) ;
outp . append ( packetId ( ) ) ;
outp . append ( nwid ) ;
to . mac ( ) . appendTo ( outp ) ;
outp . append ( ( uint32_t ) to . adi ( ) ) ;
outp . append ( ( unsigned char ) 0x02 ) ; // flag 0x02 = contains gather results
if ( RR - > mc - > gather ( peer - > address ( ) , nwid , to , outp , gatherLimit ) ) {
2020-05-12 08:35:48 +00:00
const int64_t now = RR - > node - > now ( ) ;
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2020-05-12 08:35:48 +00:00
peer - > recordOutgoingPacket ( _path , outp . packetId ( ) , outp . payloadLength ( ) , outp . verb ( ) , ZT_QOS_NO_FLOW , now ) ;
2017-07-17 17:43:28 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
}
2016-08-24 23:16:39 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , true , nwid , ZT_QOS_NO_FLOW ) ;
2014-09-30 23:28:25 +00:00
}
2017-07-17 17:43:28 +00:00
2014-09-30 23:28:25 +00:00
return true ;
2014-09-26 21:18:25 +00:00
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doPUSH_DIRECT_PATHS ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2015-07-06 22:05:04 +00:00
{
2017-10-02 22:52:57 +00:00
const int64_t now = RR - > node - > now ( ) ;
2015-10-28 16:11:30 +00:00
2017-07-17 17:43:28 +00:00
if ( ! peer - > rateGatePushDirectPaths ( now ) ) {
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_PUSH_DIRECT_PATHS , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
return true ;
}
2015-10-28 01:18:26 +00:00
2017-07-17 17:43:28 +00:00
// Second, limit addresses by scope and type
uint8_t countPerScope [ ZT_INETADDRESS_MAX_SCOPE + 1 ] [ 2 ] ; // [][0] is v4, [][1] is v6
memset ( countPerScope , 0 , sizeof ( countPerScope ) ) ;
unsigned int count = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD ) ;
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2 ;
while ( count - - ) { // if ptr overflows Buffer will throw
unsigned int flags = ( * this ) [ ptr + + ] ;
unsigned int extLen = at < uint16_t > ( ptr ) ; ptr + = 2 ;
ptr + = extLen ; // unused right now
unsigned int addrType = ( * this ) [ ptr + + ] ;
unsigned int addrLen = ( * this ) [ ptr + + ] ;
switch ( addrType ) {
case 4 : {
const InetAddress a ( field ( ptr , 4 ) , 4 , at < uint16_t > ( ptr + 4 ) ) ;
if (
2018-05-31 00:45:29 +00:00
( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH ) = = 0 ) & & // not being told to forget
2017-07-17 17:43:28 +00:00
( ! ( ( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT ) = = 0 ) & & ( peer - > hasActivePathTo ( now , a ) ) ) ) & & // not already known
( RR - > node - > shouldUsePathForZeroTierTraffic ( tPtr , peer - > address ( ) , _path - > localSocket ( ) , a ) ) ) // should use path
{
if ( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT ) ! = 0 ) {
2017-10-25 22:44:10 +00:00
peer - > clusterRedirect ( tPtr , _path , a , now ) ;
2017-07-17 17:43:28 +00:00
} else if ( + + countPerScope [ ( int ) a . ipScope ( ) ] [ 0 ] < = ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY ) {
2018-01-08 21:06:24 +00:00
peer - > attemptToContactAt ( tPtr , InetAddress ( ) , a , now , false ) ;
2015-07-13 16:29:51 +00:00
}
2017-07-17 17:43:28 +00:00
}
} break ;
case 6 : {
2020-05-12 08:35:48 +00:00
2017-07-17 17:43:28 +00:00
const InetAddress a ( field ( ptr , 16 ) , 16 , at < uint16_t > ( ptr + 16 ) ) ;
if (
2018-05-31 00:45:29 +00:00
( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH ) = = 0 ) & & // not being told to forget
2017-07-17 17:43:28 +00:00
( ! ( ( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT ) = = 0 ) & & ( peer - > hasActivePathTo ( now , a ) ) ) ) & & // not already known
( RR - > node - > shouldUsePathForZeroTierTraffic ( tPtr , peer - > address ( ) , _path - > localSocket ( ) , a ) ) ) // should use path
{
if ( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT ) ! = 0 ) {
2017-10-25 22:44:10 +00:00
peer - > clusterRedirect ( tPtr , _path , a , now ) ;
2017-07-17 17:43:28 +00:00
} else if ( + + countPerScope [ ( int ) a . ipScope ( ) ] [ 1 ] < = ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY ) {
2018-01-08 21:06:24 +00:00
peer - > attemptToContactAt ( tPtr , InetAddress ( ) , a , now , false ) ;
2015-07-13 16:29:51 +00:00
}
2017-07-17 17:43:28 +00:00
}
} break ;
2015-07-06 22:28:48 +00:00
}
2017-07-17 17:43:28 +00:00
ptr + = addrLen ;
2015-07-06 22:28:48 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_PUSH_DIRECT_PATHS , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2015-07-06 22:05:04 +00:00
return true ;
}
2017-03-28 00:03:17 +00:00
bool IncomingPacket : : _doUSER_MESSAGE ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
2017-01-09 23:55:07 +00:00
{
2017-07-17 17:43:28 +00:00
if ( likely ( size ( ) > = ( ZT_PACKET_IDX_PAYLOAD + 8 ) ) ) {
ZT_UserMessage um ;
um . origin = peer - > address ( ) . toInt ( ) ;
um . typeId = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD ) ;
um . data = reinterpret_cast < const void * > ( reinterpret_cast < const uint8_t * > ( data ( ) ) + ZT_PACKET_IDX_PAYLOAD + 8 ) ;
um . length = size ( ) - ( ZT_PACKET_IDX_PAYLOAD + 8 ) ;
RR - > node - > postEvent ( tPtr , ZT_EVENT_USER_MESSAGE , reinterpret_cast < const void * > ( & um ) ) ;
2017-01-09 23:55:07 +00:00
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_USER_MESSAGE , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
2017-07-17 17:43:28 +00:00
2017-01-09 23:55:07 +00:00
return true ;
}
2017-07-14 20:03:16 +00:00
bool IncomingPacket : : _doREMOTE_TRACE ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
{
ZT_RemoteTrace rt ;
2017-07-17 17:43:28 +00:00
const char * ptr = reinterpret_cast < const char * > ( data ( ) ) + ZT_PACKET_IDX_PAYLOAD ;
const char * const eof = reinterpret_cast < const char * > ( data ( ) ) + size ( ) ;
rt . origin = peer - > address ( ) . toInt ( ) ;
rt . data = const_cast < char * > ( ptr ) ; // start of first string
while ( ptr < eof ) {
if ( ! * ptr ) { // end of string
rt . len = ( unsigned int ) ( ptr - rt . data ) ;
2017-07-18 00:02:50 +00:00
if ( ( rt . len > 0 ) & & ( rt . len < = ZT_MAX_REMOTE_TRACE_SIZE ) ) {
2017-07-17 17:43:28 +00:00
RR - > node - > postEvent ( tPtr , ZT_EVENT_REMOTE_TRACE , & rt ) ;
2017-07-18 00:02:50 +00:00
}
2017-07-17 17:43:28 +00:00
rt . data = const_cast < char * > ( + + ptr ) ; // start of next string, if any
} else {
+ + ptr ;
2017-07-14 20:03:16 +00:00
}
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , payloadLength ( ) , Packet : : VERB_REMOTE_TRACE , 0 , Packet : : VERB_NOP , false , 0 , ZT_QOS_NO_FLOW ) ;
return true ;
}
2017-07-17 17:43:28 +00:00
2020-05-12 08:35:48 +00:00
bool IncomingPacket : : _doPATH_NEGOTIATION_REQUEST ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
{
uint64_t now = RR - > node - > now ( ) ;
SharedPtr < Bond > bond = peer - > bond ( ) ;
2021-09-02 04:37:49 +00:00
if ( ! bond | | ! bond - > rateGatePathNegotiation ( now , _path ) ) {
2020-05-12 08:35:48 +00:00
return true ;
}
if ( payloadLength ( ) ! = sizeof ( int16_t ) ) {
return true ;
}
int16_t remoteUtility = 0 ;
memcpy ( & remoteUtility , payload ( ) , sizeof ( int16_t ) ) ;
if ( peer - > bond ( ) ) {
peer - > bond ( ) - > processIncomingPathNegotiationRequest ( now , _path , Utils : : ntoh ( remoteUtility ) ) ;
}
2017-07-14 20:03:16 +00:00
return true ;
}
2017-03-28 00:03:17 +00:00
void IncomingPacket : : _sendErrorNeedCredentials ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer , const uint64_t nwid )
2016-09-27 20:49:43 +00:00
{
2019-03-19 23:43:43 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( uint8_t ) verb ( ) ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( uint8_t ) Packet : : ERROR_NEED_MEMBERSHIP_CERTIFICATE ) ;
outp . append ( nwid ) ;
2020-08-21 21:23:31 +00:00
outp . armor ( peer - > key ( ) , true , peer - > aesKeysIfSupported ( ) ) ;
2019-03-19 23:43:43 +00:00
_path - > send ( RR , tPtr , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2016-09-27 20:49:43 +00:00
}
2013-07-11 20:19:06 +00:00
} // namespace ZeroTier