2025-08-06 12:10:18 -04:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
2013-07-11 16:19:06 -04:00
*
2025-08-06 12:10:18 -04:00
* (c) ZeroTier, Inc.
* https://www.zerotier.com/
2013-07-11 16:19:06 -04:00
*/
2014-09-24 09:04:09 -07:00
#include "IncomingPacket.hpp"
2024-09-26 08:52:29 -04:00
#include "../include/ZeroTierOne.h"
#include "../version.h"
2020-05-12 01:35:48 -07:00
#include "Bond.hpp"
2024-09-26 08:52:29 -04:00
#include "Capability.hpp"
#include "CertificateOfMembership.hpp"
#include "Constants.hpp"
2023-04-26 08:49:54 -07:00
#include "Metrics.hpp"
2024-09-26 08:52:29 -04:00
#include "NetworkController.hpp"
#include "Node.hpp"
2024-08-18 15:07:18 -07:00
#include "PacketMultiplexer.hpp"
2024-09-26 08:52:29 -04:00
#include "Path.hpp"
#include "Peer.hpp"
#include "Revocation.hpp"
#include "RuntimeEnvironment.hpp"
#include "SelfAwareness.hpp"
#include "Switch.hpp"
#include "Tag.hpp"
#include "Topology.hpp"
#include "Trace.hpp"
#include "World.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2013-07-11 16:19:06 -04:00
namespace ZeroTier {
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: tryDecode ( const RuntimeEnvironment * RR , void * tPtr , int32_t flowId )
2013-07-11 16:19:06 -04:00
{
2016-07-21 23:02:54 +02:00
const Address sourceAddress ( source ());
2016-07-12 11:30:22 -07:00
2016-07-21 23:02:54 +02:00
try {
2016-07-12 08:29:50 -07: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 16:58:05 -07:00
const uint64_t tpid = trustedPathId ();
2025-07-03 12:02:18 -04:00
if ( RR -> topology -> shouldInboundPathBeTrusted ( _path -> address (), tpid )) {
2022-04-14 20:10:20 -04:00
_authenticated = true ;
2025-07-03 12:02:18 -04:00
}
else {
RR -> t -> incomingPacketMessageAuthenticationFailure ( tPtr , _path , packetId (), sourceAddress , hops (), "path not trusted" );
2016-07-12 08:29:50 -07:00
return true ;
}
2025-07-03 12:02:18 -04:00
}
else if (( c == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE ) && ( verb () == Packet :: VERB_HELLO )) {
2016-09-09 11:36:10 -07:00
// Only HELLO is allowed in the clear, but will still have a MAC
2025-07-03 12:02:18 -04:00
return _doHELLO ( RR , tPtr , false );
2013-07-11 17:52:04 -04:00
}
2025-07-03 12:02:18 -04:00
const SharedPtr < Peer > peer ( RR -> topology -> getPeer ( tPtr , sourceAddress ));
2014-10-02 10:06:29 -07:00
if ( peer ) {
2025-07-03 12:02:18 -04:00
if ( ! _authenticated ) {
if ( ! dearmor ( peer -> key (), peer -> aesKeys (), RR -> identity )) {
RR -> t -> incomingPacketMessageAuthenticationFailure ( tPtr , _path , packetId (), sourceAddress , hops (), "invalid MAC" );
2020-05-12 01:35:48 -07:00
peer -> recordIncomingInvalidPacket ( _path );
2016-07-12 08:29:50 -07:00
return true ;
}
2016-06-29 11:43:22 -07:00
}
2016-07-12 08:29:50 -07:00
2025-07-03 12:02:18 -04:00
if ( ! uncompress ()) {
RR -> t -> incomingPacketInvalid ( tPtr , _path , packetId (), sourceAddress , hops (), Packet :: VERB_NOP , "LZ4 decompression failed" );
2016-06-29 11:43:22 -07:00
return true ;
2014-10-02 10:06:29 -07:00
}
2022-04-14 20:13:57 -04:00
_authenticated = true ;
2015-10-07 10:30:47 -07:00
const Packet :: Verb v = verb ();
2020-05-12 01:35:48 -07:00
2019-03-19 16:43:43 -07:00
bool r = true ;
2025-07-03 12:02:18 -04:00
switch ( v ) {
// case Packet::VERB_NOP:
default : // ignore unknown verbs, but if they pass auth check they are "received"
2023-04-28 14:24:19 -07:00
Metrics :: pkt_nop_in ++ ;
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), v , 0 , Packet :: VERB_NOP , false , 0 , ZT_QOS_NO_FLOW );
2019-03-19 16:43:43 -07:00
break ;
2023-05-01 14:48:16 -04:00
case Packet :: VERB_HELLO :
r = _doHELLO ( RR , tPtr , true );
break ;
case Packet :: VERB_ACK :
r = _doACK ( RR , tPtr , peer );
break ;
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 ;
case Packet :: VERB_FRAME :
r = _doFRAME ( RR , tPtr , peer , flowId );
break ;
case Packet :: VERB_EXT_FRAME :
r = _doEXT_FRAME ( RR , tPtr , peer , flowId );
break ;
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 ;
case Packet :: VERB_PATH_NEGOTIATION_REQUEST :
r = _doPATH_NEGOTIATION_REQUEST ( RR , tPtr , peer );
break ;
2014-10-02 10:06:29 -07:00
}
2019-03-19 16:43:43 -07:00
if ( r ) {
2025-07-03 12:02:18 -04:00
RR -> node -> statsLogVerb (( unsigned int ) v , ( unsigned int ) size ());
2019-03-19 16:43:43 -07:00
return true ;
}
return false ;
2025-07-03 12:02:18 -04:00
}
else {
RR -> sw -> requestWhois ( tPtr , RR -> node -> now (), sourceAddress );
2014-10-02 10:06:29 -07:00
return false ;
2013-07-11 17:52:04 -04:00
}
2025-07-03 12:02:18 -04:00
}
catch (...) {
RR -> t -> incomingPacketInvalid ( tPtr , _path , packetId (), sourceAddress , hops (), verb (), "unexpected exception in tryDecode()" );
2014-10-02 10:06:29 -07:00
return true ;
2013-07-11 17:52:04 -04:00
}
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doERROR ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2013-07-11 18:15:51 -04:00
{
2017-07-17 10:43:28 -07: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 ;
2013-12-24 10:39:29 -08:00
2023-04-28 14:24:19 -07:00
Metrics :: pkt_error_in ++ ;
2023-04-26 08:49:54 -07:00
2017-07-17 10:43:28 -07:00
/* 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. */
2016-09-26 16:17:02 -07:00
2025-07-03 12:02:18 -04:00
switch ( errorCode ) {
2017-07-17 10:43:28 -07:00
case Packet :: ERROR_OBJ_NOT_FOUND :
// Object not found, currently only meaningful from network controllers.
if ( inReVerb == Packet :: VERB_NETWORK_CONFIG_REQUEST ) {
2016-09-26 16:17:02 -07:00
const SharedPtr < Network > network ( RR -> node -> network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD )));
2025-07-03 12:02:18 -04:00
if (( network ) && ( network -> controller () == peer -> address ())) {
2021-12-01 12:07:05 -08:00
network -> setNotFound ( tPtr );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
}
2023-04-28 14:24:19 -07:00
Metrics :: pkt_error_obj_not_found_in ++ ;
2017-07-17 10:43:28 -07:00
break ;
2014-09-30 16:28:25 -07:00
2017-07-17 10:43:28 -07: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 ) {
const SharedPtr < Network > network ( RR -> node -> network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD )));
2025-07-03 12:02:18 -04:00
if (( network ) && ( network -> controller () == peer -> address ())) {
2021-12-01 12:07:05 -08:00
network -> setNotFound ( tPtr );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
}
2023-04-28 14:24:19 -07:00
Metrics :: pkt_error_unsupported_op_in ++ ;
2017-07-17 10:43:28 -07:00
break ;
2014-09-30 16:28:25 -07:00
2017-07-17 10:43:28 -07:00
case Packet :: ERROR_IDENTITY_COLLISION :
// FIXME: for federation this will need a payload with a signature or something.
2023-04-26 08:49:54 -07:00
if ( RR -> topology -> isUpstream ( peer -> identity ())) {
2025-07-03 12:02:18 -04:00
RR -> node -> postEvent ( tPtr , ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION );
2023-04-26 08:49:54 -07:00
}
2023-04-28 14:24:19 -07:00
Metrics :: pkt_error_identity_collision_in ++ ;
2017-07-17 10:43:28 -07:00
break ;
2013-12-24 10:39:29 -08:00
2017-07-17 10:43:28 -07:00
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 15:52:57 -07:00
const int64_t now = RR -> node -> now ();
2025-07-03 12:02:18 -04:00
if (( network ) && ( network -> config (). com )) {
network -> peerRequestedCredentials ( tPtr , peer -> address (), now );
2023-04-26 08:49:54 -07:00
}
2023-04-28 14:24:19 -07:00
Metrics :: pkt_error_need_membership_cert_in ++ ;
2025-07-03 12:02:18 -04:00
} break ;
2017-07-17 10:43:28 -07:00
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 )));
2025-07-03 12:02:18 -04:00
if (( network ) && ( network -> controller () == peer -> address ())) {
2021-12-01 12:07:05 -08:00
network -> setAccessDenied ( tPtr );
2023-04-26 08:49:54 -07:00
}
2023-04-28 14:24:19 -07:00
Metrics :: pkt_error_network_access_denied_in ++ ;
2025-07-03 12:02:18 -04:00
} break ;
2017-07-17 10:43:28 -07:00
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 ));
2025-07-03 12:02:18 -04:00
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 ());
2017-07-17 10:43:28 -07:00
}
2023-04-28 14:24:19 -07:00
Metrics :: pkt_error_unwanted_multicast_in ++ ;
2025-07-03 12:02:18 -04:00
} break ;
2017-07-17 10:43:28 -07:00
2021-05-25 14:40:40 -04:00
case Packet :: ERROR_NETWORK_AUTHENTICATION_REQUIRED : {
2025-07-03 12:02:18 -04:00
// fprintf(stderr, "\nPacket::ERROR_NETWORK_AUTHENTICATION_REQUIRED\n\n");
2021-05-25 14:40:40 -04:00
const SharedPtr < Network > network ( RR -> node -> network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD )));
2025-07-03 12:02:18 -04:00
if (( network ) && ( network -> controller () == peer -> address ())) {
2021-05-25 14:40:40 -04:00
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 ) {
2025-07-03 12:02:18 -04:00
Dictionary < 8192 > authInfo ((( const char * ) this -> data ()) + ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 10 ), errorDataSize );
2021-11-04 15:40:08 -07:00
uint64_t authVer = authInfo . getUI ( ZT_AUTHINFO_DICT_KEY_VERSION , 0ULL );
if ( authVer == 0 ) {
char authenticationURL [ 2048 ];
2021-12-01 10:44:29 -08:00
2021-11-04 15:40:08 -07:00
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_AUTHENTICATION_URL , authenticationURL , sizeof ( authenticationURL )) > 0 ) {
2025-07-03 12:02:18 -04:00
authenticationURL [ sizeof ( authenticationURL ) - 1 ] = 0 ; // ensure always zero terminated
2021-12-01 12:07:05 -08:00
network -> setAuthenticationRequired ( tPtr , authenticationURL );
2021-11-04 15:40:08 -07:00
}
2025-07-03 12:02:18 -04:00
}
else if ( authVer == 1 ) {
2021-11-11 16:19:26 -08:00
char issuerURL [ 2048 ] = { 0 };
2021-11-04 15:40:08 -07:00
char centralAuthURL [ 2048 ] = { 0 };
char ssoNonce [ 64 ] = { 0 };
2025-07-03 12:02:18 -04:00
char ssoState [ 128 ] = { 0 };
2021-11-04 15:40:08 -07:00
char ssoClientID [ 256 ] = { 0 };
2023-01-19 15:39:15 -08:00
char ssoProvider [ 64 ] = { 0 };
2021-11-04 15:40:08 -07:00
2021-11-11 16:19:26 -08:00
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_ISSUER_URL , issuerURL , sizeof ( issuerURL )) > 0 ) {
issuerURL [ sizeof ( issuerURL ) - 1 ] = 0 ;
2021-11-04 15:40:08 -07:00
}
2025-07-03 12:02:18 -04:00
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_CENTRAL_ENDPOINT_URL , centralAuthURL , sizeof ( centralAuthURL )) > 0 ) {
2021-11-04 15:40:08 -07:00
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 ;
}
2025-07-03 12:02:18 -04:00
if ( authInfo . get ( ZT_AUTHINFO_DICT_KEY_SSO_PROVIDER , ssoProvider , sizeof ( ssoProvider )) > 0 ) {
2023-01-19 15:39:15 -08:00
ssoProvider [ sizeof ( ssoProvider ) - 1 ] = 0 ;
2025-07-03 12:02:18 -04:00
}
else {
2023-01-19 15:39:15 -08:00
strncpy ( ssoProvider , "default" , sizeof ( ssoProvider ));
}
2021-11-04 15:40:08 -07:00
2023-01-19 15:39:15 -08:00
network -> setAuthenticationRequired ( tPtr , issuerURL , centralAuthURL , ssoClientID , ssoProvider , ssoNonce , ssoState );
2021-05-25 14:40:40 -04:00
}
}
2025-07-03 12:02:18 -04:00
}
else {
2021-12-01 12:07:05 -08:00
network -> setAuthenticationRequired ( tPtr , "" );
2021-11-04 15:40:08 -07:00
}
2021-05-25 14:40:40 -04:00
}
2023-04-28 14:24:19 -07:00
Metrics :: pkt_error_authentication_required_in ++ ;
2025-07-03 12:02:18 -04:00
} break ;
2021-05-25 14:40:40 -04:00
2023-05-01 14:48:16 -04:00
default :
break ;
2013-07-11 18:15:51 -04:00
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_ERROR , inRePacketId , inReVerb , false , networkId , ZT_QOS_NO_FLOW );
2017-07-17 10:43:28 -07:00
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2022-06-08 10:01:54 -07:00
bool IncomingPacket :: _doACK ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
{
/*
2023-08-15 12:59:58 -07:00
if (! peer->rateGateACK(RR->node->now())) {
2022-06-08 10:01:54 -07:00
return true;
}
int32_t ackedBytes;
if (payloadLength() != sizeof(ackedBytes)) {
return true; // ignore
}
memcpy(&ackedBytes, payload(), sizeof(ackedBytes));
2023-08-15 12:59:58 -07:00
peer->receivedAck(_path, RR->node->now(), Utils::ntoh(ackedBytes));
2022-06-08 10:01:54 -07:00
*/
2023-04-28 14:24:19 -07:00
Metrics :: pkt_ack_in ++ ;
2022-06-08 10:01:54 -07:00
return true ;
}
bool IncomingPacket :: _doQOS_MEASUREMENT ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2018-05-30 17:45:29 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_qos_in ++ ;
2023-08-15 12:59:58 -07:00
if ( ! peer -> rateGateQoS ( RR -> node -> now (), _path )) {
2018-06-07 15:26:18 -07:00
return true ;
2020-05-12 01:35:48 -07:00
}
if ( payloadLength () > ZT_QOS_MAX_PACKET_SIZE || payloadLength () < ZT_QOS_MIN_PACKET_SIZE ) {
2022-06-08 10:01:54 -07:00
return true ; // ignore
2020-05-12 01:35:48 -07: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 10:01:54 -07:00
char * begin = ( char * ) payload ();
char * ptr = begin ;
2020-05-12 01:35:48 -07: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 10:01:54 -07:00
ptr += sizeof ( uint64_t );
2020-05-12 01:35:48 -07:00
memcpy (( void * ) & rx_ts [ count ], ptr , sizeof ( uint16_t ));
2022-06-08 10:01:54 -07:00
ptr += sizeof ( uint16_t );
2020-05-12 01:35:48 -07:00
count ++ ;
}
2023-08-15 12:59:58 -07:00
peer -> receivedQoS ( _path , now , count , rx_id , rx_ts );
2018-05-30 17:45:29 -07:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doHELLO ( const RuntimeEnvironment * RR , void * tPtr , const bool alreadyAuthenticated )
2013-07-11 17:52:04 -04:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_hello_in ++ ;
2017-10-02 15:52:57 -07:00
const int64_t now = RR -> node -> now ();
2016-09-09 11:36:10 -07:00
2017-07-17 10:43:28 -07: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 15:52:57 -07:00
const int64_t timestamp = at < int64_t > ( ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP );
2017-07-17 10:43:28 -07:00
Identity id ;
2025-07-03 12:02:18 -04:00
unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id . deserialize ( * this , ZT_PROTO_VERB_HELLO_IDX_IDENTITY );
2015-10-07 10:30:47 -07:00
2017-07-17 10:43:28 -07:00
if ( protoVersion < ZT_PROTO_VERSION_MIN ) {
2025-07-03 12:02:18 -04:00
RR -> t -> incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , "protocol version too old" );
2017-07-17 10:43:28 -07:00
return true ;
}
if ( fromAddress != id . address ()) {
2025-07-03 12:02:18 -04:00
RR -> t -> incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , "identity/address mismatch" );
2017-07-17 10:43:28 -07:00
return true ;
}
2017-02-05 16:19:03 -08:00
2025-07-03 12:02:18 -04:00
SharedPtr < Peer > peer ( RR -> topology -> getPeer ( tPtr , id . address ()));
2017-07-17 10:43:28 -07:00
if ( peer ) {
// We already have an identity with this address -- check for collisions
2025-07-03 12:02:18 -04:00
if ( ! alreadyAuthenticated ) {
2017-07-17 10:43:28 -07:00
if ( peer -> identity () != id ) {
// Identity is different from the one we already have -- address collision
2014-12-16 09:29:40 -08:00
2017-07-17 10:43:28 -07:00
// Check rate limits
2025-07-03 12:02:18 -04:00
if ( ! RR -> node -> rateGateIdentityVerification ( now , _path -> address ())) {
2017-07-17 10:43:28 -07:00
return true ;
2023-05-01 14:48:16 -04:00
}
2016-11-18 12:59:04 -08:00
2020-09-14 20:44:21 -04:00
uint8_t key [ ZT_SYMMETRIC_KEY_SIZE ];
2025-07-03 12:02:18 -04:00
if ( RR -> identity . agree ( id , key )) {
if ( dearmor ( key , peer -> aesKeysIfSupported (), RR -> identity )) { // ensure packet is authentic, otherwise drop
RR -> t -> incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , "address collision" );
Packet outp ( id . address (), RR -> identity . address (), Packet :: VERB_ERROR );
2017-07-17 10:43:28 -07:00
outp . append (( uint8_t ) Packet :: VERB_HELLO );
outp . append (( uint64_t ) pid );
outp . append (( uint8_t ) Packet :: ERROR_IDENTITY_COLLISION );
2025-07-03 12:02:18 -04:00
outp . armor ( key , true , false , peer -> aesKeysIfSupported (), peer -> identity ());
2023-05-02 11:16:55 -07:00
Metrics :: pkt_error_out ++ ;
Metrics :: pkt_error_identity_collision_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), RR -> node -> now ());
2013-12-31 11:03:45 -08:00
}
2025-07-03 12:02:18 -04:00
else {
RR -> t -> incomingPacketMessageAuthenticationFailure ( tPtr , _path , pid , fromAddress , hops (), "invalid MAC" );
}
}
else {
RR -> t -> incomingPacketMessageAuthenticationFailure ( tPtr , _path , pid , fromAddress , hops (), "invalid identity" );
2013-10-05 10:19:12 -04:00
}
2014-12-16 09:29:40 -08:00
2016-09-09 11:36:10 -07:00
return true ;
2025-07-03 12:02:18 -04:00
}
else {
2017-07-17 10:43:28 -07:00
// Identity is the same as the one we already have -- check packet integrity
2025-07-03 12:02:18 -04:00
if ( ! dearmor ( peer -> key (), peer -> aesKeysIfSupported (), RR -> identity )) {
RR -> t -> incomingPacketMessageAuthenticationFailure ( tPtr , _path , pid , fromAddress , hops (), "invalid MAC" );
2017-07-17 10:43:28 -07:00
return true ;
}
// Continue at // VALID
2014-10-13 14:12:51 -07:00
}
2025-07-03 12:02:18 -04:00
} // else if alreadyAuthenticated then continue at // VALID
}
else {
2017-07-17 10:43:28 -07:00
// We don't already have an identity with this address -- validate and learn it
2014-12-16 09:29:40 -08:00
2017-07-17 10:43:28 -07:00
// Sanity check: this basically can't happen
if ( alreadyAuthenticated ) {
2025-07-03 12:02:18 -04:00
RR -> t -> incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , "illegal alreadyAuthenticated state" );
2017-07-17 10:43:28 -07:00
return true ;
2013-10-16 17:47:26 -04:00
}
2013-07-11 17:52:04 -04:00
2017-07-17 10:43:28 -07:00
// Check rate limits
2025-07-03 12:02:18 -04:00
if ( ! RR -> node -> rateGateIdentityVerification ( now , _path -> address ())) {
RR -> t -> incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , "rate limit exceeded" );
2017-07-17 10:43:28 -07:00
return true ;
2017-02-06 07:17:45 -08:00
}
2017-02-05 16:19:03 -08:00
2017-07-17 10:43:28 -07:00
// Check packet integrity and MAC (this is faster than locallyValidate() so do it first to filter out total crap)
2025-07-03 12:02:18 -04:00
SharedPtr < Peer > newPeer ( new Peer ( RR , RR -> identity , id ));
if ( ! dearmor ( newPeer -> key (), newPeer -> aesKeysIfSupported (), RR -> identity )) {
RR -> t -> incomingPacketMessageAuthenticationFailure ( tPtr , _path , pid , fromAddress , hops (), "invalid MAC" );
2017-07-17 10:43:28 -07:00
return true ;
2017-02-05 16:19:03 -08:00
}
2017-07-17 10:43:28 -07:00
// Check that identity's address is valid as per the derivation function
2025-07-03 12:02:18 -04:00
if ( ! id . locallyValidate ()) {
RR -> t -> incomingPacketDroppedHELLO ( tPtr , _path , pid , fromAddress , "invalid identity" );
2017-07-17 10:43:28 -07:00
return true ;
}
2017-02-05 16:19:03 -08:00
2025-07-03 12:02:18 -04:00
peer = RR -> topology -> addPeer ( tPtr , newPeer );
2017-07-17 10:43:28 -07:00
// Continue at // VALID
}
// VALID -- if we made it here, packet passed identity and authenticity checks!
// Get external surface address if present (was not in old versions)
InetAddress externalSurfaceAddress ;
if ( ptr < size ()) {
2025-07-03 12:02:18 -04:00
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 );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
}
// Get primary planet world ID and world timestamp if present
uint64_t planetWorldId = 0 ;
uint64_t planetWorldTimestamp = 0 ;
if (( ptr + 16 ) <= size ()) {
2023-05-01 14:48:16 -04:00
planetWorldId = at < uint64_t > ( ptr );
ptr += 8 ;
planetWorldTimestamp = at < uint64_t > ( ptr );
ptr += 8 ;
2017-07-17 10:43:28 -07:00
}
2025-07-03 12:02:18 -04:00
std :: vector < std :: pair < uint64_t , uint64_t > > moonIdsAndTimestamps ;
2017-07-17 10:43:28 -07:00
if ( ptr < size ()) {
// Remainder of packet, if present, is encrypted
2025-07-03 12:02:18 -04:00
cryptField ( peer -> key (), ptr , size () - ptr );
2017-07-17 10:43:28 -07:00
// Get moon IDs and timestamps if present
if (( ptr + 2 ) <= size ()) {
2023-05-01 14:48:16 -04:00
const unsigned int numMoons = at < uint16_t > ( ptr );
ptr += 2 ;
2025-07-03 12:02:18 -04:00
for ( unsigned int i = 0 ; i < numMoons ; ++ i ) {
2023-05-01 14:48:16 -04:00
if (( World :: Type )( * this )[ ptr ++ ] == World :: TYPE_MOON ) {
2025-07-03 12:02:18 -04:00
moonIdsAndTimestamps . push_back ( std :: pair < uint64_t , uint64_t > ( at < uint64_t > ( ptr ), at < uint64_t > ( ptr + 8 )));
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
ptr += 16 ;
}
}
}
// Send OK(HELLO) with an echo of the packet's timestamp and some of the same
// information about us: version, sent-to address, etc.
2025-07-03 12:02:18 -04:00
Packet outp ( id . address (), RR -> identity . address (), Packet :: VERB_OK );
2017-07-17 10:43:28 -07:00
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 );
2025-07-03 12:02:18 -04:00
_path -> address (). serialize ( outp );
2017-07-17 10:43:28 -07:00
const unsigned int worldUpdateSizeAt = outp . size ();
2025-07-03 12:02:18 -04:00
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 );
2017-07-17 10:43:28 -07:00
}
2025-07-03 12:02:18 -04:00
if ( ! moonIdsAndTimestamps . empty ()) {
2017-07-17 10:43:28 -07:00
std :: vector < World > moons ( RR -> topology -> moons ());
2025-07-03 12:02:18 -04:00
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 ) {
2017-07-17 10:43:28 -07:00
if ( i -> first == m -> id ()) {
2023-05-01 14:48:16 -04:00
if ( m -> timestamp () > i -> second ) {
2025-07-03 12:02:18 -04:00
m -> serialize ( outp , false );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
break ;
}
}
}
}
2025-07-03 12:02:18 -04:00
outp . setAt < uint16_t > ( worldUpdateSizeAt , ( uint16_t )( outp . size () - ( worldUpdateSizeAt + 2 )));
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), peer -> identity ());
peer -> recordOutgoingPacket ( _path , outp . packetId (), outp . payloadLength (), outp . verb (), ZT_QOS_NO_FLOW , now );
2023-05-02 11:16:55 -07:00
Metrics :: pkt_ok_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), now );
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
peer -> setRemoteVersion ( protoVersion , vMajor , vMinor , vRevision ); // important for this to go first so received() knows the version
peer -> received ( tPtr , _path , hops (), pid , payloadLength (), Packet :: VERB_HELLO , 0 , Packet :: VERB_NOP , false , 0 , ZT_QOS_NO_FLOW );
2017-07-17 10:43:28 -07:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doOK ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2017-07-17 10:43:28 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_ok_in ++ ;
2017-07-17 10:43:28 -07: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 ;
2025-07-03 12:02:18 -04:00
if ( ! RR -> node -> expectingReplyTo ( inRePacketId )) {
2017-07-17 10:43:28 -07:00
return true ;
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
switch ( inReVerb ) {
2017-07-17 10:43:28 -07: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 );
2023-05-01 14:48:16 -04:00
if ( vProto < ZT_PROTO_VERSION_MIN ) {
2017-07-17 10:43:28 -07:00
return true ;
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
InetAddress externalSurfaceAddress ;
unsigned int ptr = ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2 ;
// Get reported external surface address if present
2023-05-01 14:48:16 -04:00
if ( ptr < size ()) {
2025-07-03 12:02:18 -04:00
ptr += externalSurfaceAddress . deserialize ( * this , ptr );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
// Handle planet or moon updates if present
2017-02-05 16:19:03 -08:00
if (( ptr + 2 ) <= size ()) {
2023-05-01 14:48:16 -04:00
const unsigned int worldsLen = at < uint16_t > ( ptr );
ptr += 2 ;
2017-07-17 10:43:28 -07:00
if ( RR -> topology -> shouldAcceptWorldUpdateFrom ( peer -> address ())) {
const unsigned int endOfWorlds = ptr + worldsLen ;
while ( ptr < endOfWorlds ) {
World w ;
2025-07-03 12:02:18 -04:00
ptr += w . deserialize ( * this , ptr );
RR -> topology -> addWorld ( tPtr , w , false );
2017-07-17 10:43:28 -07:00
}
2025-07-03 12:02:18 -04:00
}
else {
2017-07-17 10:43:28 -07:00
ptr += worldsLen ;
2017-02-05 16:19:03 -08:00
}
}
2025-07-03 12:02:18 -04:00
if ( ! hops ()) {
_path -> updateLatency (( unsigned int ) latency , RR -> node -> now ());
2018-05-30 17:45:29 -07:00
}
2017-10-25 12:42:14 -07:00
2025-07-03 12:02:18 -04:00
peer -> setRemoteVersion ( vProto , vMajor , vMinor , vRevision );
2014-01-07 16:37:36 -08:00
2025-07-03 12:02:18 -04:00
if (( externalSurfaceAddress ) && ( hops () == 0 )) {
RR -> sa -> iam ( tPtr , peer -> address (), _path -> localSocket (), _path -> address (), externalSurfaceAddress , RR -> topology -> isUpstream ( peer -> identity ()), RR -> node -> now ());
2023-05-01 14:48:16 -04:00
}
2025-07-03 12:02:18 -04:00
} break ;
2017-02-05 16:19:03 -08:00
2017-07-17 10:43:28 -07:00
case Packet :: VERB_WHOIS :
if ( RR -> topology -> isUpstream ( peer -> identity ())) {
2025-07-03 12:02:18 -04:00
const Identity id ( * this , ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY );
RR -> sw -> doAnythingWaitingForPeer ( tPtr , RR -> topology -> addPeer ( tPtr , SharedPtr < Peer > ( new Peer ( RR , RR -> identity , id ))));
2017-07-17 10:43:28 -07:00
}
break ;
2015-10-13 12:10:44 -07:00
2017-07-17 10:43:28 -07:00
case Packet :: VERB_NETWORK_CONFIG_REQUEST : {
networkId = at < uint64_t > ( ZT_PROTO_VERB_OK_IDX_PAYLOAD );
const SharedPtr < Network > network ( RR -> node -> network ( networkId ));
2023-05-01 14:48:16 -04:00
if ( network ) {
2025-07-03 12:02:18 -04:00
network -> handleConfigChunk ( tPtr , packetId (), source (), * this , ZT_PROTO_VERB_OK_IDX_PAYLOAD );
2023-05-01 14:48:16 -04:00
}
2025-07-03 12:02:18 -04:00
} break ;
2017-07-17 10:43:28 -07:00
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 ) {
2025-07-03 12:02:18 -04:00
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 ));
2017-07-17 10:43:28 -07:00
const unsigned int count = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4 );
2025-07-03 12:02:18 -04: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 10:43:28 -07:00
}
2025-07-03 12:02:18 -04:00
} break ;
2017-07-17 10:43:28 -07: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 );
2025-07-03 12:02:18 -04:00
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 ));
2017-07-17 10:43:28 -07:00
const SharedPtr < Network > network ( RR -> node -> network ( networkId ));
if ( network ) {
unsigned int offset = 0 ;
2025-07-03 12:02:18 -04:00
if (( flags & 0x01 ) != 0 ) { // deprecated but still used by older peers
2017-07-17 10:43:28 -07:00
CertificateOfMembership com ;
2025-07-03 12:02:18 -04:00
offset += com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS );
2023-05-01 14:48:16 -04:00
if ( com ) {
2025-07-03 12:02:18 -04:00
network -> addCredential ( tPtr , com );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
}
if (( flags & 0x02 ) != 0 ) {
// OK(MULTICAST_FRAME) includes implicit gather results
offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS ;
2023-05-01 14:48:16 -04:00
unsigned int totalKnown = at < uint32_t > ( offset );
offset += 4 ;
unsigned int count = at < uint16_t > ( offset );
offset += 2 ;
2025-07-03 12:02:18 -04:00
RR -> mc -> addMultiple ( tPtr , RR -> node -> now (), networkId , mg , field ( offset , count * 5 ), count , totalKnown );
2017-01-27 13:50:56 -08:00
}
}
2025-07-03 12:02:18 -04:00
} break ;
2015-10-15 07:22:17 -07:00
2023-05-01 14:48:16 -04:00
default :
break ;
2013-07-11 18:15:51 -04:00
}
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_OK , inRePacketId , inReVerb , false , networkId , ZT_QOS_NO_FLOW );
2013-12-24 10:39:29 -08:00
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doWHOIS ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2013-07-11 18:15:51 -04:00
{
2025-07-03 12:02:18 -04:00
if (( ! RR -> topology -> amUpstream ()) && ( ! peer -> rateGateInboundWhoisRequest ( RR -> node -> now ()))) {
2017-07-17 10:43:28 -07:00
return true ;
2023-04-26 08:49:54 -07:00
}
2023-04-28 14:24:19 -07:00
Metrics :: pkt_whois_in ++ ;
2016-09-09 11:36:10 -07:00
2025-07-03 12:02:18 -04:00
Packet outp ( peer -> address (), RR -> identity . address (), Packet :: VERB_OK );
2017-07-17 10:43:28 -07:00
outp . append (( unsigned char ) Packet :: VERB_WHOIS );
outp . append ( packetId ());
2016-08-23 11:29:02 -07:00
2017-07-17 10:43:28 -07:00
unsigned int count = 0 ;
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ;
while (( ptr + ZT_ADDRESS_LENGTH ) <= size ()) {
2025-07-03 12:02:18 -04:00
const Address addr ( field ( ptr , ZT_ADDRESS_LENGTH ), ZT_ADDRESS_LENGTH );
2017-07-17 10:43:28 -07:00
ptr += ZT_ADDRESS_LENGTH ;
2016-08-23 11:29:02 -07:00
2025-07-03 12:02:18 -04:00
const Identity id ( RR -> topology -> getIdentity ( tPtr , addr ));
2017-07-17 10:43:28 -07:00
if ( id ) {
2025-07-03 12:02:18 -04:00
id . serialize ( outp , false );
2017-07-17 10:43:28 -07:00
++ count ;
2025-07-03 12:02:18 -04:00
}
else {
2017-07-17 10:43:28 -07:00
// Request unknown WHOIS from upstream from us (if we have one)
2025-07-03 12:02:18 -04:00
RR -> sw -> requestWhois ( tPtr , RR -> node -> now (), addr );
2013-07-11 18:15:51 -04:00
}
}
2017-07-17 10:43:28 -07:00
if ( count > 0 ) {
2023-05-02 11:16:55 -07:00
Metrics :: pkt_ok_out ++ ;
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), RR -> identity );
_path -> send ( RR , tPtr , outp . data (), outp . size (), RR -> node -> now ());
2017-07-17 10:43:28 -07:00
}
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_WHOIS , 0 , Packet :: VERB_NOP , false , 0 , ZT_QOS_NO_FLOW );
2017-07-17 10:43:28 -07:00
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doRENDEZVOUS ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2013-07-11 18:15:51 -04:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_rendezvous_in ++ ;
2017-07-17 10:43:28 -07:00
if ( RR -> topology -> isUpstream ( peer -> identity ())) {
2025-07-03 12:02:18 -04:00
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 ));
2017-07-17 10:43:28 -07:00
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 ];
2025-07-03 12:02:18 -04:00
if (( port > 0 ) && (( addrlen == 4 ) || ( addrlen == 16 ))) {
InetAddress atAddr ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS , addrlen ), addrlen , port );
if ( RR -> node -> shouldUsePathForZeroTierTraffic ( tPtr , with , _path -> localSocket (), atAddr )) {
2017-07-17 10:43:28 -07:00
const uint64_t junk = RR -> node -> prng ();
2025-07-03 12:02:18 -04:00
RR -> node -> putPacket ( tPtr , _path -> localSocket (), atAddr , & junk , 4 , 2 ); // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls
rendezvousWith -> attemptToContactAt ( tPtr , _path -> localSocket (), atAddr , RR -> node -> now (), false );
2015-10-19 12:56:29 -07:00
}
2013-07-11 18:15:51 -04:00
}
}
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_RENDEZVOUS , 0 , Packet :: VERB_NOP , false , 0 , ZT_QOS_NO_FLOW );
2017-07-17 10:43:28 -07:00
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2020-05-12 01:35:48 -07:00
// Returns true if packet appears valid; pos and proto will be set
2024-09-26 08:52:29 -04:00
static bool _ipv6GetPayload ( const uint8_t * frameData , unsigned int frameLen , unsigned int & pos , unsigned int & proto )
2013-07-11 18:15:51 -04:00
{
2023-05-01 14:48:16 -04:00
if ( frameLen < 40 ) {
2020-05-12 01:35:48 -07:00
return false ;
2023-05-01 14:48:16 -04:00
}
2020-05-12 01:35:48 -07:00
pos = 40 ;
proto = frameData [ 6 ];
while ( pos <= frameLen ) {
2025-07-03 12:02:18 -04:00
switch ( proto ) {
case 0 : // hop-by-hop options
case 43 : // routing
case 60 : // destination options
case 135 : // mobility options
2023-05-01 14:48:16 -04:00
if (( pos + 8 ) > frameLen ) {
2025-07-03 12:02:18 -04:00
return false ; // invalid!
2023-05-01 14:48:16 -04:00
}
2020-05-12 01:35:48 -07:00
proto = frameData [ pos ];
pos += (( unsigned int ) frameData [ pos + 1 ] * 8 ) + 8 ;
break ;
2025-07-03 12:02:18 -04:00
// 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
2020-05-12 01:35:48 -07:00
default :
return true ;
}
}
2025-07-03 12:02:18 -04:00
return false ; // overflow == invalid
2020-05-12 01:35:48 -07:00
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doFRAME ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer , int32_t flowId )
2020-05-12 01:35:48 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_frame_in ++ ;
2020-05-12 01:35:48 -07:00
int32_t _flowId = ZT_QOS_NO_FLOW ;
2023-08-15 12:59:58 -07:00
if ( peer -> flowHashingSupported ()) {
2024-06-07 13:02:10 -07:00
if ( size () > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ) {
2020-05-12 01:35:48 -07:00
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE );
const unsigned int frameLen = size () - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
2025-07-09 18:01:11 -07:00
const uint8_t * const frameData = reinterpret_cast < const uint8_t *> ( data ()) + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
2020-05-12 01:35:48 -07:00
if ( etherType == ZT_ETHERTYPE_IPV4 && ( frameLen >= 20 )) {
uint16_t srcPort = 0 ;
uint16_t dstPort = 0 ;
2025-07-09 18:01:11 -07:00
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;
2020-05-12 01:35:48 -07:00
break ;
// All these start with 16-bit source and destination port in that order
2025-07-09 18:01:11 -07:00
case 0x06 : // TCP
case 0x11 : // UDP
case 0x84 : // SCTP
case 0x88 : // UDPLite
2020-05-12 01:35:48 -07:00
if ( frameLen > ( headerLen + 4 )) {
unsigned int pos = headerLen + 0 ;
2025-07-09 18:01:11 -07:00
srcPort = ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ++ ]) << 8 ;
srcPort |= ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ]);
2020-05-12 01:35:48 -07:00
pos ++ ;
2025-07-09 18:01:11 -07:00
dstPort = ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ++ ]) << 8 ;
dstPort |= ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ]);
2020-05-12 01:35:48 -07:00
_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 ;
2025-07-09 18:01:11 -07:00
_ipv6GetPayload (( const uint8_t * ) frameData , frameLen , pos , proto );
switch ( proto ) {
case 0x3A : // ICMPv6
// flowId = 0x3A;
2020-05-12 01:35:48 -07:00
break ;
// All these start with 16-bit source and destination port in that order
2025-07-09 18:01:11 -07:00
case 0x06 : // TCP
case 0x11 : // UDP
case 0x84 : // SCTP
case 0x88 : // UDPLite
2020-05-12 01:35:48 -07:00
if ( frameLen > ( pos + 4 )) {
2025-07-09 18:01:11 -07:00
srcPort = ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ++ ]) << 8 ;
srcPort |= ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ]);
2020-05-12 01:35:48 -07:00
pos ++ ;
2025-07-09 18:01:11 -07:00
dstPort = ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ++ ]) << 8 ;
dstPort |= ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ]);
2020-05-12 01:35:48 -07:00
_flowId = dstPort ^ srcPort ^ proto ;
}
break ;
default :
break ;
}
}
}
}
2017-07-17 10:43:28 -07: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 ) {
2025-07-03 12:02:18 -04:00
if ( network -> gate ( tPtr , peer )) {
2017-07-17 10:43:28 -07:00
trustEstablished = true ;
if ( size () > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ) {
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE );
2025-07-03 12:02:18 -04:00
const MAC sourceMac ( peer -> address (), nwid );
2017-07-17 10:43:28 -07:00
const unsigned int frameLen = size () - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
2025-07-03 12:02:18 -04:00
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 -> pm -> putFrame ( tPtr , nwid , network -> userPtr (), sourceMac , network -> mac (), etherType , 0 , ( const void * ) frameData , frameLen , _flowId );
2023-05-01 14:48:16 -04:00
}
2014-06-18 09:00:53 -07:00
}
2025-07-03 12:02:18 -04:00
}
else {
_sendErrorNeedCredentials ( RR , tPtr , peer , nwid );
2019-03-19 16:43:43 -07:00
return false ;
2013-07-11 18:15:51 -04:00
}
}
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_FRAME , 0 , Packet :: VERB_NOP , trustEstablished , nwid , _flowId );
2017-07-17 10:43:28 -07:00
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doEXT_FRAME ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer , int32_t flowId )
2013-09-27 16:03:13 -04:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_ext_frame_in ++ ;
2024-06-07 13:02:10 -07:00
int32_t _flowId = ZT_QOS_NO_FLOW ;
if ( peer -> flowHashingSupported ()) {
if ( size () > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) {
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE );
const unsigned int frameLen = size () - ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ;
2025-07-09 18:01:11 -07:00
const uint8_t * const frameData = reinterpret_cast < const uint8_t *> ( data ()) + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ;
2024-06-07 13:02:10 -07:00
if ( etherType == ZT_ETHERTYPE_IPV4 && ( frameLen >= 20 )) {
uint16_t srcPort = 0 ;
uint16_t dstPort = 0 ;
2025-07-09 18:01:11 -07:00
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;
2024-06-07 13:02:10 -07:00
break ;
// All these start with 16-bit source and destination port in that order
2025-07-09 18:01:11 -07:00
case 0x06 : // TCP
case 0x11 : // UDP
case 0x84 : // SCTP
case 0x88 : // UDPLite
2024-06-07 13:02:10 -07:00
if ( frameLen > ( headerLen + 4 )) {
unsigned int pos = headerLen + 0 ;
2025-07-09 18:01:11 -07:00
srcPort = ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ++ ]) << 8 ;
srcPort |= ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ]);
2024-06-07 13:02:10 -07:00
pos ++ ;
2025-07-09 18:01:11 -07:00
dstPort = ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ++ ]) << 8 ;
dstPort |= ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ]);
2024-06-07 13:02:10 -07:00
_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 ;
2025-07-09 18:01:11 -07:00
_ipv6GetPayload (( const uint8_t * ) frameData , frameLen , pos , proto );
switch ( proto ) {
case 0x3A : // ICMPv6
// flowId = 0x3A;
2024-06-07 13:02:10 -07:00
break ;
// All these start with 16-bit source and destination port in that order
2025-07-09 18:01:11 -07:00
case 0x06 : // TCP
case 0x11 : // UDP
case 0x84 : // SCTP
case 0x88 : // UDPLite
2024-06-07 13:02:10 -07:00
if ( frameLen > ( pos + 4 )) {
2025-07-09 18:01:11 -07:00
srcPort = ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ++ ]) << 8 ;
srcPort |= ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ]);
2024-06-07 13:02:10 -07:00
pos ++ ;
2025-07-09 18:01:11 -07:00
dstPort = ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ++ ]) << 8 ;
dstPort |= ( reinterpret_cast < const uint8_t *> ( frameData )[ pos ]);
2024-06-07 13:02:10 -07:00
_flowId = dstPort ^ srcPort ^ proto ;
}
break ;
default :
break ;
}
}
}
}
2017-07-17 10:43:28 -07: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 ];
2016-09-09 08:43:58 -07:00
2017-07-17 10:43:28 -07:00
unsigned int comLen = 0 ;
2025-07-03 12:02:18 -04:00
if (( flags & 0x01 ) != 0 ) { // inline COM with EXT_FRAME is deprecated but still used with old peers
2017-07-17 10:43:28 -07:00
CertificateOfMembership com ;
2025-07-03 12:02:18 -04:00
comLen = com . deserialize ( * this , ZT_PROTO_VERB_EXT_FRAME_IDX_COM );
2023-05-01 14:48:16 -04:00
if ( com ) {
2025-07-03 12:02:18 -04:00
network -> addCredential ( tPtr , com );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
}
2016-09-09 08:43:58 -07:00
2025-07-03 12:02:18 -04: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 16:43:43 -07:00
return false ;
2017-07-17 10:43:28 -07: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 );
2025-07-03 12:02:18 -04:00
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 );
2017-07-17 10:43:28 -07:00
const unsigned int frameLen = size () - ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD );
2025-07-03 12:02:18 -04:00
const uint8_t * const frameData = ( const uint8_t * ) field ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD , frameLen );
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
if (( ! from ) || ( from == network -> mac ())) {
2025-07-09 18:01:11 -07: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-09-09 08:43:58 -07:00
return true ;
}
2025-07-03 12:02:18 -04:00
switch ( network -> filterIncomingPacket ( tPtr , peer , RR -> identity . address (), from , to , frameData , frameLen , etherType , 0 )) {
2017-07-17 10:43:28 -07:00
case 1 :
2025-07-03 12:02:18 -04:00
if ( from != MAC ( peer -> address (), nwid )) {
2017-07-17 10:43:28 -07:00
if ( network -> config (). permitsBridging ( peer -> address ())) {
2025-07-03 12:02:18 -04:00
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)" );
2025-07-09 18:01:11 -07: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 10:43:28 -07:00
return true ;
2016-08-29 15:54:06 -07:00
}
2025-07-03 12:02:18 -04:00
}
else if ( to != network -> mac ()) {
2017-07-17 10:43:28 -07:00
if ( to . isMulticast ()) {
if ( network -> config (). multicastLimit == 0 ) {
2025-07-03 12:02:18 -04:00
RR -> t -> incomingNetworkFrameDropped ( tPtr , network , _path , packetId (), size (), peer -> address (), Packet :: VERB_EXT_FRAME , from , to , "multicast disabled" );
2025-07-09 18:01:11 -07: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 10:43:28 -07:00
return true ;
}
2025-07-03 12:02:18 -04: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)" );
2025-07-09 18:01:11 -07: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 10:43:28 -07:00
return true ;
}
}
// fall through -- 2 means accept regardless of bridging checks or other restrictions
case 2 :
2025-07-09 18:01:11 -07:00
RR -> pm -> putFrame ( tPtr , nwid , network -> userPtr (), from , to , etherType , 0 , ( const void * ) frameData , frameLen , _flowId );
2017-07-17 10:43:28 -07:00
break ;
2016-08-24 16:16:39 -07:00
}
2014-06-10 21:41:34 -07:00
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
if (( flags & 0x10 ) != 0 ) { // ACK requested
Packet outp ( peer -> address (), RR -> identity . address (), Packet :: VERB_OK );
2017-07-17 10:43:28 -07:00
outp . append (( uint8_t ) Packet :: VERB_EXT_FRAME );
outp . append (( uint64_t ) packetId ());
outp . append (( uint64_t ) nwid );
2020-05-12 01:35:48 -07:00
const int64_t now = RR -> node -> now ();
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), peer -> identity ());
peer -> recordOutgoingPacket ( _path , outp . packetId (), outp . payloadLength (), outp . verb (), ZT_QOS_NO_FLOW , now );
2023-05-02 11:16:55 -07:00
Metrics :: pkt_ok_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), RR -> node -> now ());
2017-07-17 10:43:28 -07:00
}
2025-07-09 18:01:11 -07:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_EXT_FRAME , 0 , Packet :: VERB_NOP , true , nwid , _flowId );
2025-07-03 12:02:18 -04:00
}
else {
2025-07-09 18:01:11 -07:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_EXT_FRAME , 0 , Packet :: VERB_NOP , false , nwid , _flowId );
2014-06-10 21:41:34 -07:00
}
2017-07-17 10:43:28 -07:00
2013-09-27 16:03:13 -04:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doECHO ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2015-10-07 16:11:50 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_echo_in ++ ;
2020-05-12 01:35:48 -07:00
uint64_t now = RR -> node -> now ();
2025-07-03 12:02:18 -04:00
if ( ! _path -> rateGateEchoRequest ( now )) {
2017-07-17 10:43:28 -07:00
return true ;
2020-05-12 01:35:48 -07:00
}
2016-09-09 11:36:10 -07:00
2017-07-17 10:43:28 -07:00
const uint64_t pid = packetId ();
2025-07-03 12:02:18 -04:00
Packet outp ( peer -> address (), RR -> identity . address (), Packet :: VERB_OK );
2017-07-17 10:43:28 -07:00
outp . append (( unsigned char ) Packet :: VERB_ECHO );
outp . append (( uint64_t ) pid );
2023-05-01 14:48:16 -04:00
if ( size () > ZT_PACKET_IDX_PAYLOAD ) {
2025-07-03 12:02:18 -04:00
outp . append ( reinterpret_cast < const unsigned char *> ( data ()) + ZT_PACKET_IDX_PAYLOAD , size () - ZT_PACKET_IDX_PAYLOAD );
2023-05-01 14:48:16 -04:00
}
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), peer -> identity ());
peer -> recordOutgoingPacket ( _path , outp . packetId (), outp . payloadLength (), outp . verb (), ZT_QOS_NO_FLOW , now );
2023-05-02 11:16:55 -07:00
Metrics :: pkt_ok_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), RR -> node -> now ());
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), pid , payloadLength (), Packet :: VERB_ECHO , 0 , Packet :: VERB_NOP , false , 0 , ZT_QOS_NO_FLOW );
2016-09-09 11:36:10 -07:00
2015-10-07 16:11:50 -07:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doMULTICAST_LIKE ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2013-07-11 18:15:51 -04:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_multicast_like_in ++ ;
2017-10-02 15:52:57 -07:00
const int64_t now = RR -> node -> now ();
2019-03-21 16:18:49 -07:00
bool authorized = false ;
uint64_t lastNwid = 0 ;
2019-03-14 14:29:15 -07:00
// Packet contains a series of 18-byte network,MAC,ADI tuples
2025-07-03 12:02:18 -04:00
for ( unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ; ptr < size (); ptr += 18 ) {
2019-03-21 16:18:49 -07:00
const uint64_t nwid = at < uint64_t > ( ptr );
if ( nwid != lastNwid ) {
lastNwid = nwid ;
SharedPtr < Network > network ( RR -> node -> network ( nwid ));
2023-05-01 14:48:16 -04:00
if ( network ) {
2025-07-03 12:02:18 -04:00
authorized = network -> gate ( tPtr , peer );
2023-05-01 14:48:16 -04:00
}
2025-07-03 12:02:18 -04:00
if ( ! authorized ) {
authorized = (( RR -> topology -> amUpstream ()) || ( RR -> node -> localControllerHasAuthorized ( now , nwid , peer -> address ())));
2023-05-01 14:48:16 -04:00
}
2019-03-21 16:18:49 -07:00
}
2023-05-01 14:48:16 -04:00
if ( authorized ) {
2025-07-03 12:02:18 -04:00
RR -> mc -> add ( tPtr , now , nwid , MulticastGroup ( MAC ( field ( ptr + 8 , 6 ), 6 ), at < uint32_t > ( ptr + 14 )), peer -> address ());
2023-05-01 14:48:16 -04:00
}
2019-03-21 16:18:49 -07:00
}
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_MULTICAST_LIKE , 0 , Packet :: VERB_NOP , false , 0 , ZT_QOS_NO_FLOW );
2013-09-25 10:55:27 -04:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doNETWORK_CREDENTIALS ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2013-07-29 13:56:20 -04:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_network_credentials_in ++ ;
2025-07-03 12:02:18 -04:00
if ( ! peer -> rateGateCredentialsReceived ( RR -> node -> now ())) {
2017-07-17 10:43:28 -07:00
return true ;
2023-04-26 08:49:54 -07:00
}
2016-09-13 10:13:23 -07:00
2017-07-17 10:43:28 -07:00
CertificateOfMembership com ;
Capability cap ;
Tag tag ;
Revocation revocation ;
CertificateOfOwnership coo ;
bool trustEstablished = false ;
SharedPtr < Network > network ;
2013-12-24 10:39:29 -08:00
2017-07-17 10:43:28 -07:00
unsigned int p = ZT_PACKET_IDX_PAYLOAD ;
2025-07-03 12:02:18 -04:00
while (( p < size ()) && (( * this )[ p ] != 0 )) {
p += com . deserialize ( * this , p );
2017-07-17 10:43:28 -07:00
if ( com ) {
network = RR -> node -> network ( com . networkId ());
if ( network ) {
2025-07-03 12:02:18 -04:00
switch ( network -> addCredential ( tPtr , com )) {
2017-07-17 10:43:28 -07:00
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 14:29:15 -07:00
}
2013-10-16 17:47:26 -04:00
}
}
2025-07-03 12:02:18 -04:00
++ p ; // skip trailing 0 after COMs if present
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
if ( p < size ()) { // older ZeroTier versions do not send capabilities, tags, or revocations
2023-05-01 14:48:16 -04:00
const unsigned int numCapabilities = at < uint16_t > ( p );
p += 2 ;
2025-07-03 12:02:18 -04:00
for ( unsigned int i = 0 ; i < numCapabilities ; ++ i ) {
p += cap . deserialize ( * this , p );
if (( ! network ) || ( network -> id () != cap . networkId ())) {
2017-07-17 10:43:28 -07:00
network = RR -> node -> network ( cap . networkId ());
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
if ( network ) {
2025-07-03 12:02:18 -04:00
switch ( network -> addCredential ( tPtr , cap )) {
2017-07-17 10:43:28 -07:00
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 ;
}
}
}
2023-05-01 14:48:16 -04:00
if ( p >= size ()) {
return true ;
}
2017-07-17 10:43:28 -07:00
2023-05-01 14:48:16 -04:00
const unsigned int numTags = at < uint16_t > ( p );
p += 2 ;
2025-07-03 12:02:18 -04:00
for ( unsigned int i = 0 ; i < numTags ; ++ i ) {
p += tag . deserialize ( * this , p );
if (( ! network ) || ( network -> id () != tag . networkId ())) {
2017-07-17 10:43:28 -07:00
network = RR -> node -> network ( tag . networkId ());
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
if ( network ) {
2025-07-03 12:02:18 -04:00
switch ( network -> addCredential ( tPtr , tag )) {
2017-07-17 10:43:28 -07:00
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 ;
}
}
}
2023-05-01 14:48:16 -04:00
if ( p >= size ()) {
return true ;
}
2017-07-17 10:43:28 -07:00
2023-05-01 14:48:16 -04:00
const unsigned int numRevocations = at < uint16_t > ( p );
p += 2 ;
2025-07-03 12:02:18 -04:00
for ( unsigned int i = 0 ; i < numRevocations ; ++ i ) {
p += revocation . deserialize ( * this , p );
if (( ! network ) || ( network -> id () != revocation . networkId ())) {
2017-07-17 10:43:28 -07:00
network = RR -> node -> network ( revocation . networkId ());
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
if ( network ) {
2025-07-03 12:02:18 -04:00
switch ( network -> addCredential ( tPtr , peer -> address (), revocation )) {
2017-07-17 10:43:28 -07:00
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 ;
}
}
}
2023-05-01 14:48:16 -04:00
if ( p >= size ()) {
return true ;
}
2017-07-17 10:43:28 -07:00
2023-05-01 14:48:16 -04:00
const unsigned int numCoos = at < uint16_t > ( p );
p += 2 ;
2025-07-03 12:02:18 -04:00
for ( unsigned int i = 0 ; i < numCoos ; ++ i ) {
p += coo . deserialize ( * this , p );
if (( ! network ) || ( network -> id () != coo . networkId ())) {
2017-07-17 10:43:28 -07:00
network = RR -> node -> network ( coo . networkId ());
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
if ( network ) {
2025-07-03 12:02:18 -04:00
switch ( network -> addCredential ( tPtr , coo )) {
2017-07-17 10:43:28 -07:00
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 ;
}
}
}
}
2025-07-03 12:02:18 -04: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 10:43:28 -07:00
2013-08-02 17:17:34 -04:00
return true ;
2013-07-29 13:56:20 -04:00
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doNETWORK_CONFIG_REQUEST ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2013-07-29 13:56:20 -04:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_network_config_request_in ++ ;
2017-07-17 10:43:28 -07: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 ();
2015-01-08 14:27:55 -08:00
2017-07-17 10:43:28 -07:00
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 ;
2025-07-03 12:02:18 -04:00
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 );
2017-07-17 10:43:28 -07:00
outp . append (( unsigned char ) Packet :: VERB_NETWORK_CONFIG_REQUEST );
outp . append ( requestPacketId );
outp . append (( unsigned char ) Packet :: ERROR_UNSUPPORTED_OPERATION );
outp . append ( nwid );
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), peer -> identity ());
2023-05-02 11:16:55 -07:00
Metrics :: pkt_error_out ++ ;
Metrics :: pkt_error_unsupported_op_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), RR -> node -> now ());
2013-08-02 17:17:34 -04:00
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04: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 10:43:28 -07:00
2013-08-02 17:17:34 -04:00
return true ;
2013-07-29 13:56:20 -04:00
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doNETWORK_CONFIG ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2016-08-09 13:52:08 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_network_config_in ++ ;
2017-07-17 10:43:28 -07:00
const SharedPtr < Network > network ( RR -> node -> network ( at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD )));
if ( network ) {
2025-07-03 12:02:18 -04:00
const uint64_t configUpdateId = network -> handleConfigChunk ( tPtr , packetId (), source (), * this , ZT_PACKET_IDX_PAYLOAD );
2017-07-17 10:43:28 -07:00
if ( configUpdateId ) {
2022-01-20 09:44:56 -08:00
Packet outp ( peer -> address (), RR -> identity . address (), Packet :: VERB_OK );
2017-07-17 10:43:28 -07: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 01:35:48 -07:00
const int64_t now = RR -> node -> now ();
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), peer -> identity ());
peer -> recordOutgoingPacket ( _path , outp . packetId (), outp . payloadLength (), outp . verb (), ZT_QOS_NO_FLOW , now );
2023-05-02 11:16:55 -07:00
Metrics :: pkt_ok_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), RR -> node -> now ());
2016-09-27 11:33:48 -07:00
}
2016-08-09 13:52:08 -07:00
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04: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 10:43:28 -07:00
2016-08-09 13:52:08 -07:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doMULTICAST_GATHER ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2014-09-26 14:18:25 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_multicast_gather_in ++ ;
2017-07-17 10:43:28 -07: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 ];
2025-07-03 12:02:18 -04:00
const MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC , 6 ), 6 ), at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI ));
2017-07-17 10:43:28 -07:00
const unsigned int gatherLimit = at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT );
2014-09-30 16:28:25 -07:00
2017-07-17 10:43:28 -07:00
const SharedPtr < Network > network ( RR -> node -> network ( nwid ));
2016-09-09 11:36:10 -07:00
2017-07-17 10:43:28 -07:00
if (( flags & 0x01 ) != 0 ) {
try {
CertificateOfMembership com ;
2025-07-03 12:02:18 -04:00
com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM );
if (( com ) && ( network )) {
network -> addCredential ( tPtr , com );
2023-05-01 14:48:16 -04:00
}
2025-07-03 12:02:18 -04:00
}
catch (...) {
} // discard invalid COMs
2014-09-30 16:28:25 -07:00
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
const bool trustEstablished = ( network ) ? network -> gate ( tPtr , peer ) : false ;
2019-03-14 14:29:15 -07:00
const int64_t now = RR -> node -> now ();
2025-07-03 12:02:18 -04:00
if (( gatherLimit > 0 ) && (( trustEstablished ) || ( RR -> topology -> amUpstream ()) || ( RR -> node -> localControllerHasAuthorized ( now , nwid , peer -> address ())))) {
Packet outp ( peer -> address (), RR -> identity . address (), Packet :: VERB_OK );
2017-07-17 10:43:28 -07:00
outp . append (( unsigned char ) Packet :: VERB_MULTICAST_GATHER );
outp . append ( packetId ());
outp . append ( nwid );
mg . mac (). appendTo ( outp );
outp . append (( uint32_t ) mg . adi ());
2025-07-03 12:02:18 -04:00
const unsigned int gatheredLocally = RR -> mc -> gather ( peer -> address (), nwid , mg , outp , gatherLimit );
2017-07-17 10:43:28 -07:00
if ( gatheredLocally > 0 ) {
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), peer -> identity ());
peer -> recordOutgoingPacket ( _path , outp . packetId (), outp . payloadLength (), outp . verb (), ZT_QOS_NO_FLOW , now );
2023-05-02 11:16:55 -07:00
Metrics :: pkt_ok_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), now );
2017-07-17 10:43:28 -07:00
}
}
2025-07-03 12:02:18 -04: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 10:43:28 -07:00
2014-09-30 16:28:25 -07:00
return true ;
2014-09-26 14:18:25 -07:00
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doMULTICAST_FRAME ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2014-09-26 14:18:25 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_multicast_frame_in ++ ;
2017-07-17 10:43:28 -07: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-26 14:18:25 -07:00
2017-07-17 10:43:28 -07: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-10-09 12:42:25 -07:00
2017-07-17 10:43:28 -07:00
if (( flags & 0x01 ) != 0 ) {
// This is deprecated but may still be sent by old peers
CertificateOfMembership com ;
2025-07-03 12:02:18 -04:00
offset += com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM );
2023-05-01 14:48:16 -04:00
if ( com ) {
2025-07-03 12:02:18 -04:00
network -> addCredential ( tPtr , com );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
}
2014-10-09 12:42:25 -07:00
2025-07-03 12:02:18 -04:00
if ( ! network -> gate ( tPtr , peer )) {
_sendErrorNeedCredentials ( RR , tPtr , peer , nwid );
2019-03-19 16:43:43 -07:00
return false ;
2016-08-24 16:16:39 -07:00
}
2017-07-17 10:43:28 -07: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 ) {
2025-07-03 12:02:18 -04:00
from . setTo ( field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC , 6 ), 6 );
2017-07-17 10:43:28 -07:00
offset += 6 ;
2025-07-03 12:02:18 -04:00
}
else {
from . fromAddress ( peer -> address (), nwid );
2017-07-17 10:43:28 -07:00
}
2025-07-03 12:02:18 -04: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 ));
2017-07-17 10:43:28 -07:00
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 );
if ( network -> config (). multicastLimit == 0 ) {
2025-07-03 12:02:18 -04:00
RR -> t -> incomingNetworkFrameDropped ( tPtr , network , _path , packetId (), size (), peer -> address (), Packet :: VERB_MULTICAST_FRAME , from , to . mac (), "multicast disabled" );
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_MULTICAST_FRAME , 0 , Packet :: VERB_NOP , false , nwid , ZT_QOS_NO_FLOW );
2017-07-17 10:43:28 -07:00
return true ;
}
2025-07-03 12:02:18 -04:00
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" );
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 10:43:28 -07:00
return true ;
}
2025-07-03 12:02:18 -04:00
if (( ! from ) || ( from . isMulticast ()) || ( from == network -> mac ())) {
RR -> t -> incomingPacketInvalid ( tPtr , _path , packetId (), source (), hops (), Packet :: VERB_MULTICAST_FRAME , "invalid source MAC" );
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 10:43:28 -07:00
return true ;
}
2025-07-03 12:02:18 -04:00
const uint8_t * const frameData = ( const uint8_t * ) field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME , frameLen );
2018-01-26 22:14:10 -05:00
2025-07-03 12:02:18 -04:00
if (( flags & 0x08 ) && ( network -> config (). isMulticastReplicator ( RR -> identity . address ()))) {
RR -> mc -> send ( tPtr , RR -> node -> now (), network , peer -> address (), to , from , etherType , frameData , frameLen );
2023-05-01 14:48:16 -04:00
}
2018-01-26 22:14:10 -05:00
2025-07-03 12:02:18 -04:00
if ( from != MAC ( peer -> address (), nwid )) {
2017-07-17 10:43:28 -07:00
if ( network -> config (). permitsBridging ( peer -> address ())) {
2025-07-03 12:02:18 -04:00
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)" );
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 10:43:28 -07:00
return true ;
}
}
2025-07-03 12:02:18 -04: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 );
2023-05-01 14:48:16 -04:00
}
2017-07-17 10:43:28 -07:00
}
if ( gatherLimit ) {
2025-07-03 12:02:18 -04:00
Packet outp ( source (), RR -> identity . address (), Packet :: VERB_OK );
2017-07-17 10:43:28 -07:00
outp . append (( unsigned char ) Packet :: VERB_MULTICAST_FRAME );
outp . append ( packetId ());
outp . append ( nwid );
to . mac (). appendTo ( outp );
outp . append (( uint32_t ) to . adi ());
2025-07-03 12:02:18 -04:00
outp . append (( unsigned char ) 0x02 ); // flag 0x02 = contains gather results
if ( RR -> mc -> gather ( peer -> address (), nwid , to , outp , gatherLimit )) {
2020-05-12 01:35:48 -07:00
const int64_t now = RR -> node -> now ();
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), peer -> identity ());
peer -> recordOutgoingPacket ( _path , outp . packetId (), outp . payloadLength (), outp . verb (), ZT_QOS_NO_FLOW , now );
2023-05-02 11:16:55 -07:00
Metrics :: pkt_ok_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), RR -> node -> now ());
2017-07-17 10:43:28 -07:00
}
}
2025-07-03 12:02:18 -04: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 16:28:25 -07:00
}
2017-07-17 10:43:28 -07:00
2014-09-30 16:28:25 -07:00
return true ;
2014-09-26 14:18:25 -07:00
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doPUSH_DIRECT_PATHS ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2015-07-06 15:05:04 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_push_direct_paths_in ++ ;
2017-10-02 15:52:57 -07:00
const int64_t now = RR -> node -> now ();
2015-10-07 16:20:54 -07:00
2025-07-03 12:02:18 -04:00
if ( ! peer -> rateGatePushDirectPaths ( now )) {
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 10:43:28 -07:00
return true ;
2015-07-06 15:28:48 -07:00
}
2017-07-17 10:43:28 -07:00
// Second, limit addresses by scope and type
2025-07-03 12:02:18 -04:00
uint8_t countPerScope [ ZT_INETADDRESS_MAX_SCOPE + 1 ][ 2 ]; // [][0] is v4, [][1] is v6
memset ( countPerScope , 0 , sizeof ( countPerScope ));
2017-07-17 10:43:28 -07:00
unsigned int count = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD );
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2 ;
2025-07-03 12:02:18 -04:00
while ( count -- ) { // if ptr overflows Buffer will throw
2017-07-17 10:43:28 -07:00
unsigned int flags = ( * this )[ ptr ++ ];
2023-05-01 14:48:16 -04:00
unsigned int extLen = at < uint16_t > ( ptr );
ptr += 2 ;
2025-07-03 12:02:18 -04:00
ptr += extLen ; // unused right now
2017-07-17 10:43:28 -07:00
unsigned int addrType = ( * this )[ ptr ++ ];
unsigned int addrLen = ( * this )[ ptr ++ ];
2025-07-03 12:02:18 -04:00
switch ( addrType ) {
2017-07-17 10:43:28 -07:00
case 4 : {
2025-07-03 12:02:18 -04:00
const InetAddress a ( field ( ptr , 4 ), 4 , at < uint16_t > ( ptr + 4 ));
if ((( flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH ) == 0 ) && // not being told to forget
( ! ((( 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
2017-07-17 10:43:28 -07:00
{
if (( flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT ) != 0 ) {
2025-07-03 12:02:18 -04:00
peer -> clusterRedirect ( tPtr , _path , a , now );
}
else if ( ++ countPerScope [( int ) a . ipScope ()][ 0 ] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY ) {
peer -> attemptToContactAt ( tPtr , InetAddress (), a , now , false );
2017-07-17 10:43:28 -07:00
}
}
2025-07-03 12:02:18 -04:00
} break ;
2017-07-17 10:43:28 -07:00
case 6 : {
2025-07-03 12:02:18 -04:00
const InetAddress a ( field ( ptr , 16 ), 16 , at < uint16_t > ( ptr + 16 ));
if ((( flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH ) == 0 ) && // not being told to forget
( ! ((( 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
2017-07-17 10:43:28 -07:00
{
if (( flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT ) != 0 ) {
2025-07-03 12:02:18 -04:00
peer -> clusterRedirect ( tPtr , _path , a , now );
}
else if ( ++ countPerScope [( int ) a . ipScope ()][ 1 ] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY ) {
peer -> attemptToContactAt ( tPtr , InetAddress (), a , now , false );
2017-07-17 10:43:28 -07:00
}
}
2025-07-03 12:02:18 -04:00
} break ;
2017-07-17 10:43:28 -07:00
}
ptr += addrLen ;
}
2025-07-03 12:02:18 -04: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 10:43:28 -07:00
2015-07-06 15:05:04 -07:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doUSER_MESSAGE ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2017-01-09 15:55:07 -08:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_user_message_in ++ ;
2017-07-17 10:43:28 -07: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 );
2025-07-03 12:02:18 -04:00
um . data = reinterpret_cast < const void *> ( reinterpret_cast < const uint8_t *> ( data ()) + ZT_PACKET_IDX_PAYLOAD + 8 );
2017-07-17 10:43:28 -07:00
um . length = size () - ( ZT_PACKET_IDX_PAYLOAD + 8 );
2025-07-03 12:02:18 -04:00
RR -> node -> postEvent ( tPtr , ZT_EVENT_USER_MESSAGE , reinterpret_cast < const void *> ( & um ));
2017-01-09 15:55:07 -08:00
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04: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 10:43:28 -07:00
2017-01-09 15:55:07 -08:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doREMOTE_TRACE ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2017-07-14 13:03:16 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_remote_trace_in ++ ;
2017-07-14 13:03:16 -07:00
ZT_RemoteTrace rt ;
2025-07-03 12:02:18 -04:00
const char * ptr = reinterpret_cast < const char *> ( data ()) + ZT_PACKET_IDX_PAYLOAD ;
const char * const eof = reinterpret_cast < const char *> ( data ()) + size ();
2017-07-17 10:43:28 -07:00
rt . origin = peer -> address (). toInt ();
2025-07-03 12:02:18 -04:00
rt . data = const_cast < char *> ( ptr ); // start of first string
2017-07-17 10:43:28 -07:00
while ( ptr < eof ) {
2025-07-03 12:02:18 -04:00
if ( ! * ptr ) { // end of string
2017-07-17 10:43:28 -07:00
rt . len = ( unsigned int )( ptr - rt . data );
2025-07-03 12:02:18 -04:00
if (( rt . len > 0 ) && ( rt . len <= ZT_MAX_REMOTE_TRACE_SIZE )) {
RR -> node -> postEvent ( tPtr , ZT_EVENT_REMOTE_TRACE , & rt );
2017-07-17 17:02:50 -07:00
}
2025-07-03 12:02:18 -04:00
rt . data = const_cast < char *> ( ++ ptr ); // start of next string, if any
}
else {
2017-07-17 10:43:28 -07:00
++ ptr ;
2017-07-14 13:03:16 -07:00
}
}
2017-07-17 10:43:28 -07:00
2025-07-03 12:02:18 -04:00
peer -> received ( tPtr , _path , hops (), packetId (), payloadLength (), Packet :: VERB_REMOTE_TRACE , 0 , Packet :: VERB_NOP , false , 0 , ZT_QOS_NO_FLOW );
2017-07-17 10:43:28 -07:00
2017-07-14 13:03:16 -07:00
return true ;
}
2024-09-26 08:52:29 -04:00
bool IncomingPacket :: _doPATH_NEGOTIATION_REQUEST ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer )
2020-05-12 01:35:48 -07:00
{
2023-04-28 14:24:19 -07:00
Metrics :: pkt_path_negotiation_request_in ++ ;
2020-05-12 01:35:48 -07:00
uint64_t now = RR -> node -> now ();
2025-07-03 12:02:18 -04:00
if ( ! peer -> rateGatePathNegotiation ( now , _path )) {
2020-05-12 01:35:48 -07:00
return true ;
}
if ( payloadLength () != sizeof ( int16_t )) {
return true ;
}
int16_t remoteUtility = 0 ;
memcpy ( & remoteUtility , payload (), sizeof ( int16_t ));
2023-08-15 12:59:58 -07:00
peer -> processIncomingPathNegotiationRequest ( now , _path , Utils :: ntoh ( remoteUtility ));
2020-05-12 01:35:48 -07:00
return true ;
}
2024-09-26 08:52:29 -04:00
void IncomingPacket :: _sendErrorNeedCredentials ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer >& peer , const uint64_t nwid )
2016-09-27 13:49:43 -07:00
{
2025-07-03 12:02:18 -04:00
Packet outp ( source (), RR -> identity . address (), Packet :: VERB_ERROR );
2019-03-19 16:43:43 -07:00
outp . append (( uint8_t ) verb ());
outp . append ( packetId ());
outp . append (( uint8_t ) Packet :: ERROR_NEED_MEMBERSHIP_CERTIFICATE );
outp . append ( nwid );
2025-07-03 12:02:18 -04:00
outp . armor ( peer -> key (), true , false , peer -> aesKeysIfSupported (), peer -> identity ());
2023-05-02 11:16:55 -07:00
Metrics :: pkt_error_out ++ ;
Metrics :: pkt_error_need_membership_cert_out ++ ;
2025-07-03 12:02:18 -04:00
_path -> send ( RR , tPtr , outp . data (), outp . size (), RR -> node -> now ());
2016-09-27 13:49:43 -07:00
}
2025-07-03 12:02:18 -04:00
} // namespace ZeroTier