2013-07-11 20:19:06 +00:00
/*
2015-02-17 21:11:34 +00:00
* ZeroTier One - Network Virtualization Everywhere
2016-01-12 22:04:55 +00:00
* Copyright ( C ) 2011 - 2016 ZeroTier , Inc . https : //www.zerotier.com/
2013-07-11 20:19:06 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
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-20 23:31:41 +00:00
# include "Cluster.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"
2013-07-11 20:19:06 +00:00
namespace ZeroTier {
2016-08-04 18:40:38 +00:00
bool IncomingPacket : : tryDecode ( const RuntimeEnvironment * RR )
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 ( ) ;
bool trusted = false ;
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.
2016-09-02 18:51:33 +00:00
if ( RR - > topology - > shouldInboundPathBeTrusted ( _path - > address ( ) , trustedPathId ( ) ) ) {
2016-07-12 15:29:50 +00:00
trusted = true ;
2016-09-02 18:51:33 +00:00
TRACE ( " TRUSTED PATH packet approved from %s(%s), trusted path ID %llx " , sourceAddress . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , trustedPathId ( ) ) ;
2016-07-12 15:29:50 +00:00
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped packet from %s(%s), cipher set to trusted path mode but path %llx@%s is not trusted! " , sourceAddress . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , trustedPathId ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
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
return _doHELLO ( RR , false ) ;
2013-07-11 21:52:04 +00:00
}
2015-11-05 20:22:58 +00:00
SharedPtr < Peer > peer ( RR - > topology - > getPeer ( sourceAddress ) ) ;
2014-10-02 17:06:29 +00:00
if ( peer ) {
2016-07-12 15:29:50 +00:00
if ( ! trusted ) {
if ( ! dearmor ( peer - > key ( ) ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped packet from %s(%s), MAC authentication failed (size: %u) " , sourceAddress . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , size ( ) ) ;
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 ( ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped packet from %s(%s), compressed data invalid " , sourceAddress . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2016-06-29 18:43:22 +00:00
return true ;
2014-10-02 17:06:29 +00:00
}
2015-10-07 17:30:47 +00:00
const Packet : : Verb v = verb ( ) ;
2016-09-02 18:51:33 +00:00
//TRACE("<< %s from %s(%s)",Packet::verbString(v),sourceAddress.toString().c_str(),_path->address().toString().c_str());
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"
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , v , 0 , Packet : : VERB_NOP , false ) ;
2014-10-02 17:06:29 +00:00
return true ;
2015-11-05 20:22:58 +00:00
2016-09-09 18:36:10 +00:00
case Packet : : VERB_HELLO : return _doHELLO ( RR , true ) ;
2016-09-02 18:51:33 +00:00
case Packet : : VERB_ERROR : return _doERROR ( RR , peer ) ;
case Packet : : VERB_OK : return _doOK ( RR , peer ) ;
case Packet : : VERB_WHOIS : return _doWHOIS ( RR , peer ) ;
case Packet : : VERB_RENDEZVOUS : return _doRENDEZVOUS ( RR , peer ) ;
case Packet : : VERB_FRAME : return _doFRAME ( RR , peer ) ;
case Packet : : VERB_EXT_FRAME : return _doEXT_FRAME ( RR , peer ) ;
case Packet : : VERB_ECHO : return _doECHO ( RR , peer ) ;
case Packet : : VERB_MULTICAST_LIKE : return _doMULTICAST_LIKE ( RR , peer ) ;
case Packet : : VERB_NETWORK_CREDENTIALS : return _doNETWORK_CREDENTIALS ( RR , peer ) ;
case Packet : : VERB_NETWORK_CONFIG_REQUEST : return _doNETWORK_CONFIG_REQUEST ( RR , peer ) ;
case Packet : : VERB_NETWORK_CONFIG_REFRESH : return _doNETWORK_CONFIG_REFRESH ( RR , peer ) ;
case Packet : : VERB_MULTICAST_GATHER : return _doMULTICAST_GATHER ( RR , peer ) ;
case Packet : : VERB_MULTICAST_FRAME : return _doMULTICAST_FRAME ( RR , peer ) ;
case Packet : : VERB_PUSH_DIRECT_PATHS : return _doPUSH_DIRECT_PATHS ( RR , peer ) ;
case Packet : : VERB_CIRCUIT_TEST : return _doCIRCUIT_TEST ( RR , peer ) ;
case Packet : : VERB_CIRCUIT_TEST_REPORT : return _doCIRCUIT_TEST_REPORT ( RR , peer ) ;
case Packet : : VERB_REQUEST_PROOF_OF_WORK : return _doREQUEST_PROOF_OF_WORK ( RR , peer ) ;
2016-08-23 21:38:20 +00:00
case Packet : : VERB_USER_MESSAGE :
return true ;
2014-10-02 17:06:29 +00:00
}
} else {
2015-10-07 17:30:47 +00:00
RR - > sw - > requestWhois ( 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 ( . . . ) {
// Exceptions are more informatively caught in _do...() handlers but
// this outer try/catch will catch anything else odd.
2016-09-02 18:51:33 +00:00
TRACE ( " dropped ??? from %s(%s): unexpected exception in tryDecode() " , sourceAddress . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
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
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doERROR ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
try {
2015-04-06 21:50:53 +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 ] ;
2013-12-24 18:39:29 +00:00
2016-09-02 18:51:33 +00:00
//TRACE("ERROR %s from %s(%s) in-re %s",Packet::errorString(errorCode),peer->address().toString().c_str(),_path->address().toString().c_str(),Packet::verbString(inReVerb));
2013-09-27 20:03:13 +00:00
switch ( errorCode ) {
2014-09-30 23:28:25 +00:00
2013-09-27 20:03:13 +00:00
case Packet : : ERROR_OBJ_NOT_FOUND :
2016-09-13 17:13:23 +00:00
// Object not found, currently only meaningful from network controllers.
2015-11-08 21:57:02 +00:00
if ( inReVerb = = Packet : : VERB_NETWORK_CONFIG_REQUEST ) {
2015-04-06 21:50:53 +00:00
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 ( ) ) )
2014-01-28 07:13:36 +00:00
network - > setNotFound ( ) ;
2013-09-27 20:03:13 +00:00
}
break ;
2014-09-30 23:28:25 +00:00
2015-01-09 21:35:20 +00:00
case Packet : : ERROR_UNSUPPORTED_OPERATION :
2016-09-13 17:13:23 +00:00
// 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.
2015-01-09 21:35:20 +00:00
if ( inReVerb = = Packet : : VERB_NETWORK_CONFIG_REQUEST ) {
2015-04-06 21:50:53 +00:00
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 ( ) ) )
2015-01-09 21:35:20 +00:00
network - > setNotFound ( ) ;
}
break ;
2013-09-27 20:03:13 +00:00
case Packet : : ERROR_IDENTITY_COLLISION :
2016-09-21 04:21:34 +00:00
// FIXME: for federation this will need a payload with a signature or something.
2016-08-09 21:46:11 +00:00
if ( RR - > topology - > isRoot ( peer - > identity ( ) ) )
2015-09-24 23:21:36 +00:00
RR - > node - > postEvent ( ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION ) ;
2013-09-27 20:03:13 +00:00
break ;
2014-09-30 23:28:25 +00:00
2016-09-09 15:43:58 +00:00
case Packet : : ERROR_NEED_MEMBERSHIP_CERTIFICATE : {
2016-09-21 04:21:34 +00:00
// Peers can send this in response to frames if they do not have a recent enough COM from us
2016-09-09 15:43:58 +00:00
SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2016-09-21 04:21:34 +00:00
const uint64_t now = RR - > node - > now ( ) ;
if ( ( network ) & & ( network - > config ( ) . com ) & & ( peer - > rateGateComRequest ( now ) ) ) {
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_NETWORK_CREDENTIALS ) ;
network - > config ( ) . com . serialize ( outp ) ;
outp . append ( ( uint8_t ) 0 ) ;
outp . armor ( peer - > key ( ) , true ) ;
_path - > send ( RR , outp . data ( ) , outp . size ( ) , now ) ;
2016-09-09 15:43:58 +00:00
}
} break ;
2014-01-18 01:09:59 +00:00
case Packet : : ERROR_NETWORK_ACCESS_DENIED_ : {
2016-09-13 17:13:23 +00:00
// Network controller: network access denied.
2015-04-06 21:50:53 +00:00
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 ( ) ) )
2014-01-28 07:13:36 +00:00
network - > setAccessDenied ( ) ;
2013-10-17 09:37:01 +00:00
} break ;
2014-09-30 23:28:25 +00:00
2014-10-09 19:42:25 +00:00
case Packet : : ERROR_UNWANTED_MULTICAST : {
2016-09-13 17:13:23 +00:00
// Members of networks can use this error to indicate that they no longer
// want to receive multicasts on a given channel.
2016-09-09 15:43:58 +00:00
SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
if ( ( network ) & & ( network - > gate ( peer , verb ( ) , packetId ( ) ) ) ) {
MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8 , 6 ) , 6 ) , at < uint32_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14 ) ) ;
TRACE ( " %.16llx: peer %s unsubscrubed from multicast group %s " , network - > id ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , mg . toString ( ) . c_str ( ) ) ;
RR - > mc - > remove ( network - > id ( ) , mg , peer - > address ( ) ) ;
}
2014-10-09 19:42:25 +00:00
} break ;
2014-09-30 23:28:25 +00:00
default : break ;
2013-09-27 20:03:13 +00:00
}
2013-12-24 18:39:29 +00:00
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_ERROR , inRePacketId , inReVerb , false ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped ERROR from %s(%s): unexpected exception " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 21:52:04 +00:00
}
2016-09-09 18:36:10 +00:00
bool IncomingPacket : : _doHELLO ( const RuntimeEnvironment * RR , const bool alreadyAuthenticated )
2013-07-11 21:52:04 +00:00
{
try {
2016-09-09 18:36:10 +00:00
const uint64_t now = RR - > node - > now ( ) ;
2015-10-07 17:30:47 +00:00
const uint64_t pid = packetId ( ) ;
const Address fromAddress ( source ( ) ) ;
2015-04-06 21:50:53 +00:00
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 ) ;
const uint64_t timestamp = at < uint64_t > ( ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP ) ;
2015-10-07 17:30:47 +00:00
2015-04-07 03:17:21 +00:00
Identity id ;
2015-10-28 00:59:17 +00:00
InetAddress externalSurfaceAddress ;
2015-10-13 19:10:44 +00:00
uint64_t worldId = ZT_WORLD_ID_NULL ;
uint64_t worldTimestamp = 0 ;
{
unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id . deserialize ( * this , ZT_PROTO_VERB_HELLO_IDX_IDENTITY ) ;
2016-08-04 01:04:08 +00:00
// Get external surface address if present (was not in old versions)
if ( ptr < size ( ) )
2015-10-28 00:59:17 +00:00
ptr + = externalSurfaceAddress . deserialize ( * this , ptr ) ;
2016-08-04 01:04:08 +00:00
// Get world ID and world timestamp if present (was not in old versions)
if ( ( ptr + 16 ) < = size ( ) ) {
2015-10-13 19:10:44 +00:00
worldId = at < uint64_t > ( ptr ) ; ptr + = 8 ;
worldTimestamp = at < uint64_t > ( ptr ) ;
}
}
2015-07-13 15:36:22 +00:00
2015-10-07 17:30:47 +00:00
if ( fromAddress ! = id . address ( ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped HELLO from %s(%s): identity not for sending address " , fromAddress . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-07-07 15:54:48 +00:00
return true ;
}
2016-09-09 18:36:10 +00:00
if ( protoVersion < ZT_PROTO_VERSION_MIN ) {
TRACE ( " dropped HELLO from %s(%s): protocol version too old " , id . address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
return true ;
}
2015-04-07 03:17:21 +00:00
2016-09-09 18:36:10 +00:00
SharedPtr < Peer > peer ( RR - > topology - > getPeer ( id . address ( ) ) ) ;
if ( peer ) {
// We already have an identity with this address -- check for collisions
if ( ! alreadyAuthenticated ) {
2015-11-05 20:22:58 +00:00
if ( peer - > identity ( ) ! = id ) {
// Identity is different from the one we already have -- address collision
2016-09-13 17:46:36 +00:00
uint8_t key [ ZT_PEER_SECRET_KEY_LENGTH ] ;
2015-11-05 20:22:58 +00:00
if ( RR - > identity . agree ( id , key , ZT_PEER_SECRET_KEY_LENGTH ) ) {
if ( dearmor ( key ) ) { // ensure packet is authentic, otherwise drop
2016-09-02 18:51:33 +00:00
TRACE ( " rejected HELLO from %s(%s): address already claimed " , id . address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-11-05 20:22:58 +00:00
Packet outp ( id . address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2016-09-13 17:46:36 +00:00
outp . append ( ( uint8_t ) Packet : : VERB_HELLO ) ;
2015-11-05 20:22:58 +00:00
outp . append ( ( uint64_t ) pid ) ;
2016-09-13 17:46:36 +00:00
outp . append ( ( uint8_t ) Packet : : ERROR_IDENTITY_COLLISION ) ;
2015-11-05 20:22:58 +00:00
outp . armor ( key , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2015-11-05 20:22:58 +00:00
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " rejected HELLO from %s(%s): packet failed authentication " , id . address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-11-05 20:22:58 +00:00
}
2013-12-31 19:03:45 +00:00
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " rejected HELLO from %s(%s): key agreement failed " , id . address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-12-31 19:03:45 +00:00
}
2015-11-05 20:22:58 +00:00
return true ;
2013-12-31 19:03:45 +00:00
} else {
2015-11-05 20:22:58 +00:00
// Identity is the same as the one we already have -- check packet integrity
2014-12-16 17:29:40 +00:00
2015-11-05 20:22:58 +00:00
if ( ! dearmor ( peer - > key ( ) ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " rejected HELLO from %s(%s): packet failed authentication " , id . address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-11-05 20:22:58 +00:00
return true ;
}
// Continue at // VALID
}
2016-09-09 18:36:10 +00:00
} // else continue at // VALID
} else {
// We don't already have an identity with this address -- validate and learn it
2015-11-05 20:22:58 +00:00
2016-09-09 18:36:10 +00:00
// Sanity check: this basically can't happen
if ( alreadyAuthenticated ) {
TRACE ( " dropped HELLO from %s(%s): somehow already authenticated with unknown peer? " , id . address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
return true ;
}
2014-12-16 17:29:40 +00:00
2016-09-13 17:46:36 +00:00
// Check that identity's address is valid as per the derivation function
2016-09-09 18:36:10 +00:00
if ( ! id . locallyValidate ( ) ) {
TRACE ( " dropped HELLO from %s(%s): identity invalid " , id . address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
return true ;
}
2014-12-16 17:29:40 +00:00
2016-09-09 18:36:10 +00:00
// Check packet integrity and authentication
SharedPtr < Peer > newPeer ( new Peer ( RR , RR - > identity , id ) ) ;
if ( ! dearmor ( newPeer - > key ( ) ) ) {
TRACE ( " rejected HELLO from %s(%s): packet failed authentication " , id . address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
return true ;
2014-10-13 21:12:51 +00:00
}
2016-09-09 18:36:10 +00:00
peer = RR - > topology - > addPeer ( newPeer ) ;
2014-12-16 17:29:40 +00:00
2016-09-09 18:36:10 +00:00
// Continue at // VALID
2013-10-16 21:47:26 +00:00
}
2013-10-05 14:19:12 +00:00
2016-09-09 18:36:10 +00:00
// VALID -- if we made it here, packet passed identity and authenticity checks!
2016-09-13 17:13:23 +00:00
// Learn our external surface address from other peers to help us negotiate symmetric NATs
// and detect changes to our global IP that can trigger path renegotiation.
2016-09-06 21:05:58 +00:00
if ( ( externalSurfaceAddress ) & & ( hops ( ) = = 0 ) )
2016-09-09 18:36:10 +00:00
RR - > sa - > iam ( id . address ( ) , _path - > localAddress ( ) , _path - > address ( ) , externalSurfaceAddress , RR - > topology - > isUpstream ( id ) , now ) ;
2014-01-08 00:37:36 +00:00
2015-04-06 21:50:53 +00:00
Packet outp ( id . address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2013-10-05 14:19:12 +00:00
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
2015-10-07 17:30:47 +00:00
outp . append ( ( uint64_t ) pid ) ;
outp . append ( ( uint64_t ) timestamp ) ;
2013-10-05 14:19:12 +00:00
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 ) ;
2015-11-02 17:32:56 +00:00
if ( protoVersion > = 5 ) {
2016-09-02 18:51:33 +00:00
_path - > address ( ) . serialize ( outp ) ;
2015-11-02 17:32:56 +00:00
} 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 .
*/
2016-09-02 18:51:33 +00:00
InetAddress tmpa ( _path - > address ( ) ) ;
2015-11-02 17:32:56 +00:00
tmpa . setPort ( 0 ) ;
tmpa . serialize ( outp ) ;
}
2015-10-13 19:10:44 +00:00
2015-10-15 14:22:17 +00:00
if ( ( worldId ! = ZT_WORLD_ID_NULL ) & & ( RR - > topology - > worldTimestamp ( ) > worldTimestamp ) & & ( worldId = = RR - > topology - > worldId ( ) ) ) {
World w ( RR - > topology - > world ( ) ) ;
const unsigned int sizeAt = outp . size ( ) ;
outp . addSize ( 2 ) ; // make room for 16-bit size field
w . serialize ( outp , false ) ;
outp . setAt < uint16_t > ( sizeAt , ( uint16_t ) ( outp . size ( ) - ( sizeAt + 2 ) ) ) ;
2015-10-13 19:10:44 +00:00
} else {
2015-10-15 14:22:17 +00:00
outp . append ( ( uint16_t ) 0 ) ; // no world update needed
2015-10-13 19:10:44 +00:00
}
2015-10-15 14:22:17 +00:00
outp . armor ( peer - > key ( ) , true ) ;
2016-09-09 18:36:10 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , now ) ;
2015-10-28 00:59:17 +00:00
2015-12-22 00:15:39 +00:00
peer - > setRemoteVersion ( protoVersion , vMajor , vMinor , vRevision ) ; // important for this to go first so received() knows the version
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , pid , Packet : : VERB_HELLO , 0 , Packet : : VERB_NOP , false ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped HELLO from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doOK ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
try {
2015-04-06 21:50:53 +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 ) ;
2016-09-13 17:33:03 +00:00
bool trustEstablished = false ;
2013-12-24 18:39:29 +00:00
2016-09-13 17:13:23 +00:00
// Don't parse OK packets that are not in response to a packet ID we sent
2016-09-09 15:43:58 +00:00
if ( ! RR - > node - > expectingReplyTo ( inRePacketId ) ) {
TRACE ( " %s(%s): OK(%s) DROPPED: not expecting reply to %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , Packet : : verbString ( inReVerb ) , packetId ( ) ) ;
return true ;
}
//TRACE("%s(%s): OK(%s)",peer->address().toString().c_str(),_path->address().toString().c_str(),Packet::verbString(inReVerb));
2013-12-24 18:39:29 +00:00
2013-07-11 22:15:51 +00:00
switch ( inReVerb ) {
2014-09-30 23:28:25 +00:00
2013-07-12 02:06:25 +00:00
case Packet : : VERB_HELLO : {
2015-04-06 21:50:53 +00:00
const unsigned int latency = std : : min ( ( unsigned int ) ( RR - > node - > now ( ) - at < uint64_t > ( ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP ) ) , ( unsigned int ) 0xffff ) ;
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 ) ;
2014-09-30 23:28:25 +00:00
2015-10-28 00:59:17 +00:00
if ( vProto < ZT_PROTO_VERSION_MIN ) {
2016-09-02 18:51:33 +00:00
TRACE ( " %s(%s): OK(HELLO) dropped, protocol version too old " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-10-28 00:59:17 +00:00
return true ;
}
InetAddress externalSurfaceAddress ;
2015-10-13 19:17:47 +00:00
unsigned int ptr = ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2 ;
2016-08-04 01:04:08 +00:00
// Get reported external surface address if present (was not on old versions)
if ( ptr < size ( ) )
2015-10-28 00:59:17 +00:00
ptr + = externalSurfaceAddress . deserialize ( * this , ptr ) ;
2016-08-04 01:04:08 +00:00
// Handle world updates from root servers if present (was not on old versions)
if ( ( ( ptr + 2 ) < = size ( ) ) & & ( RR - > topology - > isRoot ( peer - > identity ( ) ) ) ) {
2015-10-13 19:17:47 +00:00
World worldUpdate ;
const unsigned int worldLen = at < uint16_t > ( ptr ) ; ptr + = 2 ;
if ( worldLen > 0 ) {
World w ;
w . deserialize ( * this , ptr ) ;
RR - > topology - > worldUpdateIfValid ( w ) ;
}
}
2015-04-30 23:40:04 +00:00
2016-09-02 18:51:33 +00:00
TRACE ( " %s(%s): OK(HELLO), version %u.%u.%u, latency %u, reported external address %s " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , vMajor , vMinor , vRevision , latency , ( ( externalSurfaceAddress ) ? externalSurfaceAddress . toString ( ) . c_str ( ) : " (none) " ) ) ;
2014-09-30 23:28:25 +00:00
2014-02-03 18:46:37 +00:00
peer - > addDirectLatencyMeasurment ( latency ) ;
2014-09-30 23:28:25 +00:00
peer - > setRemoteVersion ( vProto , vMajor , vMinor , vRevision ) ;
2013-12-27 04:57:17 +00:00
2016-09-06 21:05:58 +00:00
if ( ( externalSurfaceAddress ) & & ( hops ( ) = = 0 ) )
2016-09-02 18:51:33 +00:00
RR - > sa - > iam ( peer - > address ( ) , _path - > localAddress ( ) , _path - > address ( ) , externalSurfaceAddress , RR - > topology - > isUpstream ( peer - > identity ( ) ) , RR - > node - > now ( ) ) ;
2013-07-12 02:06:25 +00:00
} break ;
2014-09-30 23:28:25 +00:00
2013-08-05 16:16:25 +00:00
case Packet : : VERB_WHOIS : {
2016-08-04 01:04:08 +00:00
if ( RR - > topology - > isUpstream ( peer - > identity ( ) ) ) {
2015-04-06 21:50:53 +00:00
const Identity id ( * this , ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY ) ;
2016-08-04 01:04:08 +00:00
RR - > sw - > doAnythingWaitingForPeer ( RR - > topology - > addPeer ( SharedPtr < Peer > ( new Peer ( RR , RR - > identity , id ) ) ) ) ;
2013-08-05 16:16:25 +00:00
}
} break ;
2014-09-30 23:28:25 +00:00
2013-08-03 16:53:46 +00:00
case Packet : : VERB_NETWORK_CONFIG_REQUEST : {
2016-08-10 20:41:22 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID ) ;
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
if ( ( network ) & & ( network - > controller ( ) = = peer - > address ( ) ) ) {
2016-09-13 17:33:03 +00:00
trustEstablished = true ;
2016-08-09 20:14:38 +00:00
const unsigned int chunkLen = at < uint16_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN ) ;
const void * chunkData = field ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT , chunkLen ) ;
unsigned int chunkIndex = 0 ;
unsigned int totalSize = chunkLen ;
if ( ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT + chunkLen ) < size ( ) ) {
totalSize = at < uint32_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT + chunkLen ) ;
chunkIndex = at < uint32_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT + chunkLen + 4 ) ;
2013-08-03 16:53:46 +00:00
}
2016-09-02 18:51:33 +00:00
TRACE ( " %s(%s): OK(NETWORK_CONFIG_REQUEST) chunkLen==%u chunkIndex==%u totalSize==%u " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , chunkLen , chunkIndex , totalSize ) ;
2016-08-10 20:41:22 +00:00
network - > handleInboundConfigChunk ( inRePacketId , chunkData , chunkLen , chunkIndex , totalSize ) ;
2013-08-03 16:53:46 +00:00
}
} break ;
2014-09-30 23:28:25 +00:00
2015-12-22 00:15:39 +00:00
//case Packet::VERB_ECHO: {
//} break;
2014-09-30 23:28:25 +00:00
case Packet : : VERB_MULTICAST_GATHER : {
2015-04-06 21:50:53 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID ) ;
2016-09-09 15:43:58 +00:00
SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
2016-09-09 18:36:10 +00:00
if ( ( network ) & & ( network - > gateMulticastGatherReply ( peer , verb ( ) , packetId ( ) ) ) ) {
2016-09-13 17:33:03 +00:00
trustEstablished = true ;
2016-09-09 15:43:58 +00: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 ) ) ;
//TRACE("%s(%s): OK(MULTICAST_GATHER) %.16llx/%s length %u",source().toString().c_str(),_path->address().toString().c_str(),nwid,mg.toString().c_str(),size());
const unsigned int count = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4 ) ;
RR - > mc - > addMultiple ( RR - > node - > now ( ) , nwid , 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 ) ) ;
}
2014-09-30 23:28:25 +00:00
} break ;
case Packet : : VERB_MULTICAST_FRAME : {
2015-04-06 21:50:53 +00:00
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS ] ;
const uint64_t nwid = 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
2016-09-02 18:51:33 +00:00
//TRACE("%s(%s): OK(MULTICAST_FRAME) %.16llx/%s flags %.2x",peer->address().toString().c_str(),_path->address().toString().c_str(),nwid,mg.toString().c_str(),flags);
2014-10-10 00:58:31 +00:00
2016-09-09 15:43:58 +00:00
SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
if ( network ) {
unsigned int offset = 0 ;
2014-10-09 19:42:25 +00:00
2016-09-09 15:43:58 +00:00
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 )
2016-08-09 00:33:26 +00:00
network - > addCredential ( com ) ;
}
2014-10-09 19:42:25 +00:00
2016-09-09 18:36:10 +00:00
if ( network - > gateMulticastGatherReply ( peer , verb ( ) , packetId ( ) ) ) {
2016-09-13 17:33:03 +00:00
trustEstablished = true ;
2016-09-09 15:43:58 +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 ( RR - > node - > now ( ) , nwid , mg , field ( offset , count * 5 ) , count , totalKnown ) ;
}
}
2014-10-02 20:50:37 +00:00
}
2014-09-30 23:28:25 +00:00
} break ;
default : break ;
2013-07-11 22:15:51 +00:00
}
2013-12-24 18:39:29 +00:00
2016-09-13 17:33:03 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_OK , inRePacketId , inReVerb , trustEstablished ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped OK from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doWHOIS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
2014-06-23 15:19:41 +00:00
try {
2016-09-09 18:36:10 +00:00
if ( ! peer - > rateGateInboundWhoisRequest ( RR - > node - > now ( ) ) ) {
TRACE ( " dropped WHOIS from %s(%s): rate limit circuit breaker tripped " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
return true ;
}
2016-08-23 18:29:02 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_WHOIS ) ;
outp . append ( packetId ( ) ) ;
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-04 19:14:13 +00:00
const Identity id ( RR - > topology - > getIdentity ( addr ) ) ;
if ( id ) {
id . serialize ( outp , false ) ;
2016-08-23 18:29:02 +00:00
+ + count ;
2014-06-23 15:19:41 +00:00
} else {
2016-08-23 18:29:02 +00:00
// If I am not the root and don't know this identity, ask upstream. Downstream
// peer may re-request in the future and if so we will be able to provide it.
if ( ! RR - > topology - > amRoot ( ) )
RR - > sw - > requestWhois ( addr ) ;
2015-11-08 21:57:02 +00:00
# ifdef ZT_ENABLE_CLUSTER
2016-08-23 18:29:02 +00:00
// Distribute WHOIS queries across a cluster if we do not know the ID.
// This may result in duplicate OKs to the querying peer, which is fine.
2015-11-08 21:57:02 +00:00
if ( RR - > cluster )
RR - > cluster - > sendDistributedQuery ( * this ) ;
# endif
2014-06-23 15:19:41 +00:00
}
2013-07-11 22:15:51 +00:00
}
2016-08-23 18:29:02 +00:00
if ( count > 0 ) {
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2016-08-23 18:29:02 +00:00
}
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_WHOIS , 0 , Packet : : VERB_NOP , false ) ;
2014-06-23 15:19:41 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped WHOIS from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doRENDEZVOUS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
try {
2016-09-09 15:43:58 +00:00
if ( ! RR - > topology - > isUpstream ( peer - > identity ( ) ) ) {
TRACE ( " RENDEZVOUS from %s ignored since source is not upstream " , peer - > address ( ) . toString ( ) . c_str ( ) ) ;
} else {
const Address with ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
const SharedPtr < Peer > rendezvousWith ( RR - > topology - > getPeer ( 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 ) ) ) {
const InetAddress atAddr ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS , addrlen ) , addrlen , port ) ;
if ( RR - > node - > shouldUsePathForZeroTierTraffic ( _path - > localAddress ( ) , atAddr ) ) {
RR - > node - > putPacket ( _path - > localAddress ( ) , atAddr , " ABRE " , 4 , 2 ) ; // send low-TTL junk packet to 'open' local NAT(s) and stateful firewalls
rendezvousWith - > attemptToContactAt ( _path - > localAddress ( ) , atAddr , RR - > node - > now ( ) ) ;
TRACE ( " RENDEZVOUS from %s says %s might be at %s, sent verification attempt " , peer - > address ( ) . toString ( ) . c_str ( ) , with . toString ( ) . c_str ( ) , atAddr . toString ( ) . c_str ( ) ) ;
} else {
TRACE ( " RENDEZVOUS from %s says %s might be at %s, ignoring since path is not suitable " , peer - > address ( ) . toString ( ) . c_str ( ) , with . toString ( ) . c_str ( ) , atAddr . toString ( ) . c_str ( ) ) ;
}
2015-10-19 19:56:29 +00:00
} else {
2016-09-09 15:43:58 +00:00
TRACE ( " dropped corrupt RENDEZVOUS from %s(%s) (bad address or port) " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-10-19 19:56:29 +00:00
}
2013-07-11 22:15:51 +00:00
} else {
2016-09-09 15:43:58 +00:00
TRACE ( " ignored RENDEZVOUS from %s(%s) to meet unknown peer %s " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , with . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
}
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_RENDEZVOUS , 0 , Packet : : VERB_NOP , false ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped RENDEZVOUS from %s(%s): unexpected exception " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doFRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
try {
2016-09-07 22:15:52 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ;
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
2016-09-09 15:43:58 +00:00
bool trustEstablished = false ;
2013-07-11 22:15:51 +00:00
if ( network ) {
2016-09-09 15:43:58 +00:00
if ( ! network - > gate ( peer , verb ( ) , packetId ( ) ) ) {
TRACE ( " dropped FRAME from %s(%s): not a member of private network %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , ( unsigned long long ) network - > id ( ) ) ;
} else {
trustEstablished = true ;
if ( size ( ) > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ) {
2016-08-24 23:16:39 +00:00
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE ) ;
2016-09-07 22:15:52 +00:00
const MAC sourceMac ( peer - > address ( ) , nwid ) ;
2016-08-24 23:16:39 +00:00
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 ;
2016-08-31 23:50:22 +00:00
if ( network - > filterIncomingPacket ( peer , RR - > identity . address ( ) , sourceMac , network - > mac ( ) , frameData , frameLen , etherType , 0 ) > 0 )
2016-09-07 22:15:52 +00:00
RR - > node - > putFrame ( 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 {
2016-09-07 22:15:52 +00:00
TRACE ( " dropped FRAME from %s(%s): we are not a member of network %.16llx " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ) ;
2013-07-11 22:15:51 +00:00
}
2016-09-09 15:43:58 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_FRAME , 0 , Packet : : VERB_NOP , trustEstablished ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped FRAME from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doEXT_FRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
2014-06-11 04:41:34 +00:00
try {
2016-09-07 22:15:52 +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 ) ) ;
2014-06-11 04:41:34 +00:00
if ( network ) {
2016-09-09 15:43:58 +00:00
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS ] ;
2014-06-14 04:06:34 +00:00
2016-09-09 15:43:58 +00:00
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 ( com ) ;
}
2014-10-01 00:26:34 +00:00
2016-09-09 15:43:58 +00:00
if ( ! network - > gate ( peer , verb ( ) , packetId ( ) ) ) {
TRACE ( " dropped EXT_FRAME from %s(%s): not a member of private network %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , network - > id ( ) ) ;
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , false ) ;
return true ;
}
2014-09-30 23:28:25 +00:00
2016-09-09 15:43:58 +00:00
if ( size ( ) > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) {
2015-04-06 21:50:53 +00:00
const unsigned int etherType = at < uint16_t > ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE ) ;
2014-09-30 23:28:25 +00: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 ) ;
2016-08-29 22:54:06 +00:00
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
2014-10-01 00:26:34 +00:00
if ( ( ! from ) | | ( from . isMulticast ( ) ) | | ( from = = network - > mac ( ) ) ) {
2016-09-09 15:43:58 +00:00
TRACE ( " dropped EXT_FRAME from %s@%s(%s) to %s: invalid source MAC %s " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , from . toString ( ) . c_str ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true ) ; // trustEstablished because COM is okay
2014-06-11 04:41:34 +00:00
return true ;
}
2016-08-29 22:54:06 +00:00
switch ( network - > filterIncomingPacket ( peer , RR - > identity . address ( ) , from , to , frameData , frameLen , etherType , 0 ) ) {
case 1 :
2016-09-07 22:15:52 +00:00
if ( from ! = MAC ( peer - > address ( ) , nwid ) ) {
2016-08-29 22:54:06 +00:00
if ( network - > config ( ) . permitsBridging ( peer - > address ( ) ) ) {
network - > learnBridgeRoute ( from , peer - > address ( ) ) ;
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped EXT_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , network - > id ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true ) ; // trustEstablished because COM is okay
2016-08-29 22:54:06 +00:00
return true ;
}
2016-09-13 21:27:18 +00:00
} else if ( to ! = network - > mac ( ) ) {
if ( to . isMulticast ( ) ) {
if ( network - > config ( ) . multicastLimit = = 0 ) {
TRACE ( " dropped EXT_FRAME from %s@%s(%s) to %s: network %.16llx does not allow multicast " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , network - > id ( ) ) ;
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true ) ; // trustEstablished because COM is okay
return true ;
}
} else if ( ! network - > config ( ) . permitsBridging ( RR - > identity . address ( ) ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , network - > id ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true ) ; // trustEstablished because COM is okay
2016-08-29 22:54:06 +00:00
return true ;
}
}
2016-08-31 23:50:22 +00:00
// fall through -- 2 means accept regardless of bridging checks or other restrictions
2016-08-29 22:54:06 +00:00
case 2 :
2016-09-07 22:15:52 +00:00
RR - > node - > putFrame ( nwid , network - > userPtr ( ) , from , to , etherType , 0 , ( const void * ) frameData , frameLen ) ;
2016-08-29 22:54:06 +00:00
break ;
2014-06-11 04:41:34 +00:00
}
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , true ) ;
2016-08-24 23:16:39 +00:00
}
2014-06-11 04:41:34 +00:00
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , false ) ;
2014-06-11 04:41:34 +00:00
}
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped EXT_FRAME from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2014-06-11 04:41:34 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2015-10-07 23:11:50 +00:00
bool IncomingPacket : : _doECHO ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
try {
2016-09-09 18:36:10 +00:00
if ( ! peer - > rateGateEchoRequest ( RR - > node - > now ( ) ) ) {
TRACE ( " dropped ECHO from %s(%s): rate limit circuit breaker tripped " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
return true ;
}
2015-10-07 23:20:54 +00:00
const uint64_t pid = packetId ( ) ;
2015-10-07 23:11:50 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_ECHO ) ;
2015-10-07 23:20:54 +00:00
outp . append ( ( uint64_t ) pid ) ;
2015-12-22 00:15:39 +00:00
if ( size ( ) > ZT_PACKET_IDX_PAYLOAD )
outp . append ( reinterpret_cast < const unsigned char * > ( data ( ) ) + ZT_PACKET_IDX_PAYLOAD , size ( ) - ZT_PACKET_IDX_PAYLOAD ) ;
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2016-09-09 18:36:10 +00:00
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , pid , Packet : : VERB_ECHO , 0 , Packet : : VERB_NOP , false ) ;
2015-10-08 20:25:38 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped ECHO from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-10-08 20:25:38 +00:00
}
2015-10-07 23:11:50 +00:00
return true ;
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doMULTICAST_LIKE ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-09-27 20:03:13 +00:00
{
try {
2015-04-06 21:50:53 +00:00
const uint64_t now = RR - > node - > now ( ) ;
2013-09-27 20:03:13 +00:00
2016-09-09 18:36:10 +00:00
uint64_t authOnNetwork [ 256 ] ;
unsigned int authOnNetworkCount = 0 ;
SharedPtr < Network > network ;
2016-09-13 17:13:23 +00:00
bool trustEstablished = false ;
2016-09-09 18:36:10 +00:00
2013-09-27 20:03:13 +00:00
// Iterate through 18-byte network,MAC,ADI tuples
2015-10-20 23:31:41 +00:00
for ( unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ; ptr < size ( ) ; ptr + = 18 ) {
2015-10-27 19:01:00 +00:00
const uint64_t nwid = at < uint64_t > ( ptr ) ;
2016-09-09 18:36:10 +00:00
bool auth = false ;
for ( unsigned int i = 0 ; i < authOnNetworkCount ; + + i ) {
if ( nwid = = authOnNetwork [ i ] ) {
auth = true ;
break ;
}
}
if ( ! auth ) {
if ( ( ! network ) | | ( network - > id ( ) ! = nwid ) )
network = RR - > node - > network ( nwid ) ;
2016-09-13 17:13:23 +00:00
const bool authOnNet = ( ( network ) & & ( network - > gate ( peer , verb ( ) , packetId ( ) ) ) ) ;
trustEstablished | = authOnNet ;
if ( authOnNet | | RR - > mc - > cacheAuthorized ( peer - > address ( ) , nwid , now ) ) {
2016-09-09 18:36:10 +00:00
auth = true ;
if ( authOnNetworkCount < 256 ) // sanity check, packets can't really be this big
authOnNetwork [ authOnNetworkCount + + ] = nwid ;
}
}
if ( auth ) {
const MulticastGroup group ( MAC ( field ( ptr + 8 , 6 ) , 6 ) , at < uint32_t > ( ptr + 14 ) ) ;
RR - > mc - > add ( now , nwid , group , peer - > address ( ) ) ;
}
2015-10-20 23:31:41 +00:00
}
2013-12-24 18:39:29 +00:00
2016-09-13 17:13:23 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_LIKE , 0 , Packet : : VERB_NOP , trustEstablished ) ;
2013-09-27 20:03:13 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped MULTICAST_LIKE from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-09-27 20:03:13 +00:00
}
return true ;
}
2016-08-04 01:04:08 +00:00
bool IncomingPacket : : _doNETWORK_CREDENTIALS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-29 17:56:20 +00:00
{
2013-10-16 21:47:26 +00:00
try {
2016-09-13 17:13:23 +00:00
if ( ! peer - > rateGateCredentialsReceived ( RR - > node - > now ( ) ) ) {
TRACE ( " dropped NETWORK_CREDENTIALS from %s(%s): rate limit circuit breaker tripped " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
return true ;
}
2013-10-17 10:41:52 +00:00
CertificateOfMembership com ;
2016-08-04 01:04:08 +00:00
Capability cap ;
Tag tag ;
2016-09-13 17:13:23 +00:00
bool trustEstablished = false ;
2013-12-24 18:39:29 +00:00
2016-08-04 01:04:08 +00:00
unsigned int p = ZT_PACKET_IDX_PAYLOAD ;
while ( ( p < size ( ) ) & & ( ( * this ) [ p ] ) ) {
p + = com . deserialize ( * this , p ) ;
2016-08-09 00:33:26 +00:00
if ( com ) {
SharedPtr < Network > network ( RR - > node - > network ( com . networkId ( ) ) ) ;
if ( network ) {
2016-09-13 17:13:23 +00:00
switch ( network - > addCredential ( com ) ) {
case 0 : trustEstablished = true ; break ;
case 1 : return false ; // wait for WHOIS
}
2016-09-09 18:36:10 +00:00
} else RR - > mc - > addCredential ( com , false ) ;
2016-08-09 00:33:26 +00:00
}
2013-10-16 21:47:26 +00:00
}
2016-08-04 01:04:08 +00:00
+ + p ; // skip trailing 0 after COMs if present
if ( p < size ( ) ) { // check if new capabilities and tags fields are present
const unsigned int numCapabilities = at < uint16_t > ( p ) ; p + = 2 ;
for ( unsigned int i = 0 ; i < numCapabilities ; + + i ) {
p + = cap . deserialize ( * this , p ) ;
2016-08-09 00:33:26 +00:00
SharedPtr < Network > network ( RR - > node - > network ( cap . networkId ( ) ) ) ;
if ( network ) {
2016-09-13 17:13:23 +00:00
switch ( network - > addCredential ( cap ) ) {
case 0 : trustEstablished = true ; break ;
case 1 : return false ; // wait for WHOIS
}
2016-08-09 00:33:26 +00:00
}
2016-08-04 01:04:08 +00:00
}
2016-08-04 16:51:15 +00:00
2016-08-04 01:04:08 +00:00
const unsigned int numTags = at < uint16_t > ( p ) ; p + = 2 ;
for ( unsigned int i = 0 ; i < numTags ; + + i ) {
p + = tag . deserialize ( * this , p ) ;
2016-08-09 00:33:26 +00:00
SharedPtr < Network > network ( RR - > node - > network ( tag . networkId ( ) ) ) ;
if ( network ) {
2016-09-13 17:13:23 +00:00
switch ( network - > addCredential ( tag ) ) {
case 0 : trustEstablished = true ; break ;
case 1 : return false ; // wait for WHOIS
}
2016-08-09 00:33:26 +00:00
}
2016-08-04 01:04:08 +00:00
}
}
2013-12-24 18:39:29 +00:00
2016-09-13 17:13:23 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_NETWORK_CREDENTIALS , 0 , Packet : : VERB_NOP , trustEstablished ) ;
2013-10-16 21:47:26 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped NETWORK_CREDENTIALS from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-10-16 21:47:26 +00:00
}
2013-08-02 21:17:34 +00:00
return true ;
2013-07-29 17:56:20 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doNETWORK_CONFIG_REQUEST ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-29 17:56:20 +00:00
{
2013-08-02 21:17:34 +00:00
try {
2015-04-06 21:50:53 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID ) ;
2016-08-09 21:46:11 +00:00
const unsigned int hopCount = hops ( ) ;
2016-08-09 16:34:13 +00:00
const uint64_t requestPacketId = packetId ( ) ;
2016-09-09 18:36:10 +00:00
bool trustEstablished = false ;
2015-01-08 22:27:55 +00:00
2015-04-15 22:12:09 +00:00
if ( RR - > localNetworkController ) {
2016-09-09 18:36:10 +00:00
const unsigned int metaDataLength = at < uint16_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN ) ;
const char * metaDataBytes = ( const char * ) field ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT , metaDataLength ) ;
const Dictionary < ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY > metaData ( metaDataBytes , metaDataLength ) ;
2016-08-09 20:52:08 +00:00
NetworkConfig * netconf = new NetworkConfig ( ) ;
try {
2016-09-02 18:51:33 +00:00
switch ( RR - > localNetworkController - > doNetworkConfigRequest ( ( hopCount > 0 ) ? InetAddress ( ) : _path - > address ( ) , RR - > identity , peer - > identity ( ) , nwid , metaData , * netconf ) ) {
2016-08-09 20:52:08 +00:00
case NetworkController : : NETCONF_QUERY_OK : {
2016-09-09 18:36:10 +00:00
trustEstablished = true ;
2016-08-09 20:52:08 +00:00
Dictionary < ZT_NETWORKCONFIG_DICT_CAPACITY > * dconf = new Dictionary < ZT_NETWORKCONFIG_DICT_CAPACITY > ( ) ;
try {
if ( netconf - > toDictionary ( * dconf , metaData . getUI ( ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION , 0 ) < 6 ) ) {
2016-08-23 18:57:56 +00:00
dconf - > wrapWithSignature ( ZT_NETWORKCONFIG_DICT_KEY_SIGNATURE , RR - > identity . privateKeyPair ( ) ) ;
2016-08-09 20:52:08 +00:00
const unsigned int totalSize = dconf - > sizeBytes ( ) ;
unsigned int chunkIndex = 0 ;
while ( chunkIndex < totalSize ) {
2016-08-09 21:46:11 +00:00
const unsigned int chunkLen = std : : min ( totalSize - chunkIndex , ( unsigned int ) ( ZT_PROTO_MAX_PACKET_LENGTH - ( ZT_PACKET_IDX_PAYLOAD + 32 ) ) ) ;
2016-08-09 20:52:08 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
outp . append ( requestPacketId ) ;
outp . append ( nwid ) ;
outp . append ( ( uint16_t ) chunkLen ) ;
outp . append ( ( const void * ) ( dconf - > data ( ) + chunkIndex ) , chunkLen ) ;
outp . append ( ( uint32_t ) totalSize ) ;
outp . append ( ( uint32_t ) chunkIndex ) ;
outp . compress ( ) ;
2016-08-09 22:45:26 +00:00
RR - > sw - > send ( outp , true ) ;
2016-08-09 20:52:08 +00:00
chunkIndex + = chunkLen ;
}
2016-08-09 16:34:13 +00:00
}
2016-08-09 20:52:08 +00:00
delete dconf ;
} catch ( . . . ) {
delete dconf ;
throw ;
2016-08-09 16:34:13 +00:00
}
2016-08-09 20:52:08 +00:00
} break ;
case NetworkController : : NETCONF_QUERY_OBJECT_NOT_FOUND : {
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_OBJ_NOT_FOUND ) ;
outp . append ( nwid ) ;
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2016-08-09 20:52:08 +00:00
} break ;
case NetworkController : : NETCONF_QUERY_ACCESS_DENIED : {
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_NETWORK_ACCESS_DENIED_ ) ;
outp . append ( nwid ) ;
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2016-08-09 20:52:08 +00:00
} break ;
case NetworkController : : NETCONF_QUERY_INTERNAL_SERVER_ERROR :
break ;
case NetworkController : : NETCONF_QUERY_IGNORE :
break ;
default :
TRACE ( " NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest() " ) ;
break ;
}
delete netconf ;
} catch ( . . . ) {
delete netconf ;
throw ;
2015-02-24 20:28:58 +00:00
}
2015-01-08 22:27:55 +00:00
} else {
2015-02-24 20:28:58 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2015-01-08 22:27:55 +00:00
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
2016-08-09 16:34:13 +00:00
outp . append ( requestPacketId ) ;
2015-01-08 22:27:55 +00:00
outp . append ( ( unsigned char ) Packet : : ERROR_UNSUPPORTED_OPERATION ) ;
outp . append ( nwid ) ;
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2015-01-08 22:27:55 +00:00
}
2016-08-25 00:48:13 +00:00
2016-09-09 18:36:10 +00:00
peer - > received ( _path , hopCount , requestPacketId , Packet : : VERB_NETWORK_CONFIG_REQUEST , 0 , Packet : : VERB_NOP , trustEstablished ) ;
2016-08-18 00:37:37 +00:00
} catch ( std : : exception & exc ) {
fprintf ( stderr , " WARNING: network config request failed with exception: %s " ZT_EOL_S , exc . what ( ) ) ;
2016-09-02 18:51:33 +00:00
TRACE ( " dropped NETWORK_CONFIG_REQUEST from %s(%s): %s " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , exc . what ( ) ) ;
2013-08-02 21:17:34 +00:00
} catch ( . . . ) {
2016-08-18 00:37:37 +00:00
fprintf ( stderr , " WARNING: network config request failed with exception: unknown exception " ZT_EOL_S ) ;
2016-09-02 18:51:33 +00:00
TRACE ( " dropped NETWORK_CONFIG_REQUEST from %s(%s): unknown exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2013-08-02 21:17:34 +00:00
}
return true ;
2013-07-29 17:56:20 +00:00
}
2016-08-09 20:52:08 +00:00
bool IncomingPacket : : _doNETWORK_CONFIG_REFRESH ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
try {
2016-08-23 20:46:36 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD ) ;
2016-09-13 17:13:23 +00:00
bool trustEstablished = false ;
2016-08-23 20:46:36 +00:00
if ( Network : : controllerFor ( nwid ) = = peer - > address ( ) ) {
SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
if ( network ) {
network - > requestConfiguration ( ) ;
2016-09-13 17:13:23 +00:00
trustEstablished = true ;
2016-08-23 20:46:36 +00:00
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped NETWORK_CONFIG_REFRESH from %s(%s): not a member of %.16llx " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , nwid ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_NETWORK_CONFIG_REFRESH , 0 , Packet : : VERB_NOP , false ) ;
2016-08-23 20:46:36 +00:00
return true ;
}
const unsigned int blacklistCount = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 8 ) ;
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 10 ;
for ( unsigned int i = 0 ; i < blacklistCount ; + + i ) {
network - > blacklistBefore ( Address ( field ( ptr , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) , at < uint64_t > ( ptr + 5 ) ) ;
ptr + = 13 ;
2016-08-09 20:52:08 +00:00
}
}
2016-08-25 00:50:51 +00:00
2016-09-13 17:13:23 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_NETWORK_CONFIG_REFRESH , 0 , Packet : : VERB_NOP , trustEstablished ) ;
2016-08-09 20:52:08 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2016-08-09 20:52:08 +00:00
}
return true ;
}
2014-09-26 21:18:25 +00:00
bool IncomingPacket : : _doMULTICAST_GATHER ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2014-09-30 23:28:25 +00:00
try {
2015-04-06 21:50:53 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID ) ;
2016-08-23 18:29:02 +00:00
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_GATHER_IDX_FLAGS ] ;
2015-04-06 21:50:53 +00: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 ) ) ;
const unsigned int gatherLimit = at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT ) ;
2014-09-30 23:28:25 +00:00
2016-09-02 18:51:33 +00:00
//TRACE("<<MC %s(%s) GATHER up to %u in %.16llx/%s",source().toString().c_str(),_path->address().toString().c_str(),gatherLimit,nwid,mg.toString().c_str());
2014-10-10 00:58:31 +00:00
2016-09-09 18:36:10 +00:00
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
2016-08-23 18:29:02 +00:00
if ( ( flags & 0x01 ) ! = 0 ) {
try {
CertificateOfMembership com ;
com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_GATHER_IDX_COM ) ;
if ( com ) {
if ( network )
network - > addCredential ( com ) ;
2016-09-09 18:36:10 +00:00
else RR - > mc - > addCredential ( com , false ) ;
2016-08-23 18:29:02 +00:00
}
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " MULTICAST_GATHER from %s(%s): discarded invalid COM " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2016-08-23 18:29:02 +00:00
}
}
2016-09-09 18:45:34 +00:00
const bool trustEstablished = ( ( network ) & & ( network - > gate ( peer , verb ( ) , packetId ( ) ) ) ) ;
if ( ( trustEstablished | | RR - > mc - > cacheAuthorized ( peer - > address ( ) , nwid , RR - > node - > now ( ) ) ) & & ( gatherLimit > 0 ) ) {
2014-10-10 00:58:31 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2014-09-30 23:28:25 +00: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 ( ) ) ;
2015-11-08 21:57:02 +00:00
const unsigned int gatheredLocally = RR - > mc - > gather ( peer - > address ( ) , nwid , mg , outp , gatherLimit ) ;
2016-09-02 18:51:33 +00:00
if ( gatheredLocally > 0 ) {
2014-09-30 23:28:25 +00:00
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2014-09-30 23:28:25 +00:00
}
2015-11-08 21:57:02 +00:00
2016-08-23 18:29:02 +00:00
// If we are a member of a cluster, distribute this GATHER across it
2015-11-08 21:57:02 +00:00
# ifdef ZT_ENABLE_CLUSTER
if ( ( RR - > cluster ) & & ( gatheredLocally < gatherLimit ) )
RR - > cluster - > sendDistributedQuery ( * this ) ;
# endif
2014-09-30 23:28:25 +00:00
}
2016-09-09 18:45:34 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_GATHER , 0 , Packet : : VERB_NOP , trustEstablished ) ;
2014-09-30 23:28:25 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped MULTICAST_GATHER from %s(%s): unexpected exception " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2014-09-30 23:28:25 +00:00
}
return true ;
2014-09-26 21:18:25 +00:00
}
bool IncomingPacket : : _doMULTICAST_FRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2014-09-30 23:28:25 +00:00
try {
2015-04-06 21:50:53 +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
2015-04-06 21:50:53 +00:00
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
2014-10-09 19:42:25 +00:00
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
2016-08-23 18:29:02 +00:00
if ( ( flags & 0x01 ) ! = 0 ) {
// This is deprecated but may still be sent by old peers
2014-10-09 19:42:25 +00:00
CertificateOfMembership com ;
offset + = com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM ) ;
2016-08-09 00:33:26 +00:00
if ( com )
network - > addCredential ( com ) ;
2014-10-09 19:42:25 +00:00
}
2014-09-30 23:28:25 +00:00
2016-09-09 02:48:05 +00:00
if ( ! network - > gate ( peer , verb ( ) , packetId ( ) ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , ( unsigned long long ) network - > id ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , false ) ;
2014-10-09 19:42:25 +00:00
return true ;
}
2014-09-30 23:28:25 +00:00
2016-09-13 21:27:18 +00:00
if ( network - > config ( ) . multicastLimit = = 0 ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): network %.16llx does not allow multicast " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , ( unsigned long long ) network - > id ( ) ) ;
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , false ) ;
return true ;
}
2014-10-09 19:42:25 +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 ;
}
2014-09-30 23:28:25 +00:00
2014-10-09 19:42:25 +00:00
MAC from ;
if ( ( flags & 0x04 ) ! = 0 ) {
from . setTo ( field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC , 6 ) , 6 ) ;
offset + = 6 ;
} else {
2014-10-10 00:58:31 +00:00
from . fromAddress ( peer - > address ( ) , nwid ) ;
2014-10-09 19:42:25 +00:00
}
2014-09-30 23:28:25 +00:00
2015-04-06 21:50:53 +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 ) ;
2016-07-25 23:51:10 +00:00
const unsigned int frameLen = size ( ) - ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME ) ;
2014-10-01 23:29:52 +00:00
2016-07-25 23:51:10 +00:00
//TRACE("<<MC FRAME %.16llx/%s from %s@%s flags %.2x length %u",nwid,to.toString().c_str(),from.toString().c_str(),peer->address().toString().c_str(),flags,frameLen);
2014-10-10 00:58:31 +00:00
2016-07-25 23:51:10 +00:00
if ( ( frameLen > 0 ) & & ( frameLen < = ZT_IF_MTU ) ) {
2014-10-09 19:42:25 +00:00
if ( ! to . mac ( ) . isMulticast ( ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped MULTICAST_FRAME from %s@%s(%s) to %s: destination is unicast, must use FRAME or EXT_FRAME " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , true ) ; // trustEstablished because COM is okay
2014-10-09 19:42:25 +00:00
return true ;
}
if ( ( ! from ) | | ( from . isMulticast ( ) ) | | ( from = = network - > mac ( ) ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped MULTICAST_FRAME from %s@%s(%s) to %s: invalid source MAC " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , true ) ; // trustEstablished because COM is okay
2014-10-09 19:42:25 +00:00
return true ;
2014-10-01 23:29:52 +00:00
}
2014-10-01 00:26:34 +00:00
2016-09-07 22:15:52 +00:00
if ( from ! = MAC ( peer - > address ( ) , nwid ) ) {
2016-04-12 19:32:33 +00:00
if ( network - > config ( ) . permitsBridging ( peer - > address ( ) ) ) {
2014-10-09 19:42:25 +00:00
network - > learnBridgeRoute ( from , peer - > address ( ) ) ;
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped MULTICAST_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , network - > id ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , true ) ; // trustEstablished because COM is okay
2014-10-09 19:42:25 +00:00
return true ;
2014-10-01 00:33:20 +00:00
}
2014-10-01 00:26:34 +00:00
}
2014-10-09 19:42:25 +00:00
2016-07-25 23:51:10 +00:00
const uint8_t * const frameData = ( const uint8_t * ) field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME , frameLen ) ;
2016-08-31 23:50:22 +00:00
if ( network - > filterIncomingPacket ( peer , RR - > identity . address ( ) , from , to . mac ( ) , frameData , frameLen , etherType , 0 ) > 0 ) {
2016-09-07 22:15:52 +00:00
RR - > node - > putFrame ( nwid , network - > userPtr ( ) , from , to . mac ( ) , etherType , 0 , ( const void * ) frameData , frameLen ) ;
2016-07-25 23:51:10 +00:00
}
2014-09-30 23:28:25 +00:00
}
2014-10-09 19:42:25 +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 ) ) {
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2014-10-09 19:42:25 +00:00
}
}
2014-09-30 23:28:25 +00:00
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , true ) ;
2016-08-24 23:16:39 +00:00
} else {
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , false ) ;
2016-08-24 23:16:39 +00:00
}
2014-09-30 23:28:25 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped MULTICAST_FRAME from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2014-09-30 23:28:25 +00:00
}
return true ;
2014-09-26 21:18:25 +00:00
}
2015-07-06 22:05:04 +00:00
bool IncomingPacket : : _doPUSH_DIRECT_PATHS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2015-07-06 22:28:48 +00:00
try {
2015-10-16 17:28:09 +00:00
const uint64_t now = RR - > node - > now ( ) ;
2015-10-28 16:11:30 +00:00
// First, subject this to a rate limit
2016-09-09 18:36:10 +00:00
if ( ! peer - > rateGatePushDirectPaths ( now ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped PUSH_DIRECT_PATHS from %s(%s): circuit breaker tripped " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_PUSH_DIRECT_PATHS , 0 , Packet : : VERB_NOP , false ) ;
2015-10-28 01:18:26 +00:00
return true ;
}
2015-10-28 16:11:30 +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 ) ) ;
2015-10-20 22:27:53 +00:00
2015-07-06 22:28:48 +00:00
unsigned int count = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD ) ;
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2 ;
2015-07-13 16:29:51 +00:00
while ( count - - ) { // if ptr overflows Buffer will throw
2015-10-13 01:25:29 +00:00
// TODO: some flags are not yet implemented
2015-07-07 15:54:48 +00:00
2015-07-06 22:28:48 +00:00
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 + + ] ;
2015-07-13 16:29:51 +00:00
2015-07-06 22:28:48 +00:00
switch ( addrType ) {
case 4 : {
InetAddress a ( field ( ptr , 4 ) , 4 , at < uint16_t > ( ptr + 4 ) ) ;
2016-04-19 16:22:51 +00:00
bool redundant = false ;
if ( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT ) ! = 0 ) {
2016-09-02 21:20:55 +00:00
peer - > setClusterOptimal ( a ) ;
2016-04-19 16:22:51 +00:00
} else {
redundant = peer - > hasActivePathTo ( now , a ) ;
}
2016-09-02 18:51:33 +00:00
if ( ( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH ) = = 0 ) & & ( ! redundant ) & & ( RR - > node - > shouldUsePathForZeroTierTraffic ( _path - > localAddress ( ) , a ) ) ) {
2015-10-28 16:11:30 +00:00
if ( + + countPerScope [ ( int ) a . ipScope ( ) ] [ 0 ] < = ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY ) {
TRACE ( " attempting to contact %s at pushed direct path %s " , peer - > address ( ) . toString ( ) . c_str ( ) , a . toString ( ) . c_str ( ) ) ;
2016-09-07 19:01:03 +00:00
peer - > attemptToContactAt ( InetAddress ( ) , a , now ) ;
2015-10-28 16:11:30 +00:00
} else {
TRACE ( " ignoring contact for %s at %s -- too many per scope " , peer - > address ( ) . toString ( ) . c_str ( ) , a . toString ( ) . c_str ( ) ) ;
2015-10-20 22:27:53 +00:00
}
2015-07-13 16:29:51 +00:00
}
2015-07-06 22:28:48 +00:00
} break ;
case 6 : {
InetAddress a ( field ( ptr , 16 ) , 16 , at < uint16_t > ( ptr + 16 ) ) ;
2016-04-19 16:22:51 +00:00
bool redundant = false ;
if ( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT ) ! = 0 ) {
2016-09-02 21:20:55 +00:00
peer - > setClusterOptimal ( a ) ;
2016-04-19 16:22:51 +00:00
} else {
redundant = peer - > hasActivePathTo ( now , a ) ;
}
2016-09-02 18:51:33 +00:00
if ( ( ( flags & ZT_PUSH_DIRECT_PATHS_FLAG_FORGET_PATH ) = = 0 ) & & ( ! redundant ) & & ( RR - > node - > shouldUsePathForZeroTierTraffic ( _path - > localAddress ( ) , a ) ) ) {
2015-10-28 16:11:30 +00:00
if ( + + countPerScope [ ( int ) a . ipScope ( ) ] [ 1 ] < = ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY ) {
TRACE ( " attempting to contact %s at pushed direct path %s " , peer - > address ( ) . toString ( ) . c_str ( ) , a . toString ( ) . c_str ( ) ) ;
2016-09-07 19:01:03 +00:00
peer - > attemptToContactAt ( InetAddress ( ) , a , now ) ;
2015-10-28 16:11:30 +00:00
} else {
TRACE ( " ignoring contact for %s at %s -- too many per scope " , peer - > address ( ) . toString ( ) . c_str ( ) , a . toString ( ) . c_str ( ) ) ;
2015-10-20 22:27:53 +00:00
}
2015-07-13 16:29:51 +00:00
}
2015-07-06 22:28:48 +00:00
} break ;
}
ptr + = addrLen ;
}
2015-10-07 23:20:54 +00:00
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_PUSH_DIRECT_PATHS , 0 , Packet : : VERB_NOP , false ) ;
2015-07-06 22:28:48 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-07-06 22:28:48 +00:00
}
2015-07-06 22:05:04 +00:00
return true ;
}
2015-09-30 20:59:05 +00:00
bool IncomingPacket : : _doCIRCUIT_TEST ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
try {
const Address originatorAddress ( field ( ZT_PACKET_IDX_PAYLOAD , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
SharedPtr < Peer > originator ( RR - > topology - > getPeer ( originatorAddress ) ) ;
if ( ! originator ) {
RR - > sw - > requestWhois ( originatorAddress ) ;
return false ;
}
const unsigned int flags = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 5 ) ;
const uint64_t timestamp = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD + 7 ) ;
const uint64_t testId = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD + 15 ) ;
2015-10-06 18:47:16 +00:00
// Tracks total length of variable length fields, initialized to originator credential length below
unsigned int vlf ;
2016-08-23 18:29:02 +00:00
// Originator credentials -- right now only a network ID for which the originator is controller or is authorized by controller is allowed
2015-10-06 18:47:16 +00:00
const unsigned int originatorCredentialLength = vlf = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 23 ) ;
uint64_t originatorCredentialNetworkId = 0 ;
if ( originatorCredentialLength > = 1 ) {
switch ( ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 25 ] ) {
case 0x01 : { // 64-bit network ID, originator must be controller
if ( originatorCredentialLength > = 9 )
originatorCredentialNetworkId = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD + 26 ) ;
} break ;
default : break ;
}
2015-09-30 20:59:05 +00:00
}
2015-10-06 18:47:16 +00:00
// Add length of "additional fields," which are currently unused
vlf + = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 25 + vlf ) ;
2015-09-30 20:59:05 +00:00
2015-10-06 18:47:16 +00:00
// Verify signature -- only tests signed by their originators are allowed
const unsigned int signatureLength = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 27 + vlf ) ;
if ( ! originator - > identity ( ) . verify ( field ( ZT_PACKET_IDX_PAYLOAD , 27 + vlf ) , 27 + vlf , field ( ZT_PACKET_IDX_PAYLOAD + 29 + vlf , signatureLength ) , signatureLength ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped CIRCUIT_TEST from %s(%s): signature by originator %s invalid " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , originatorAddress . toString ( ) . c_str ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST , 0 , Packet : : VERB_NOP , false ) ;
2015-09-30 20:59:05 +00:00
return true ;
}
vlf + = signatureLength ;
2015-10-06 18:47:16 +00:00
// Save this length so we can copy the immutable parts of this test
// into the one we send along to next hops.
const unsigned int lengthOfSignedPortionAndSignature = 29 + vlf ;
2016-08-04 01:04:08 +00:00
// Add length of second "additional fields" section.
vlf + = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 29 + vlf ) ;
2015-10-06 18:47:16 +00:00
2016-09-09 15:43:58 +00:00
uint64_t reportFlags = 0 ;
2015-10-06 18:47:16 +00:00
// Check credentials (signature already verified)
if ( originatorCredentialNetworkId ) {
2016-08-23 18:29:02 +00:00
SharedPtr < Network > network ( RR - > node - > network ( originatorCredentialNetworkId ) ) ;
if ( ( ! network ) | | ( ! network - > config ( ) . circuitTestingAllowed ( originatorAddress ) ) ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped CIRCUIT_TEST from %s(%s): originator %s specified network ID %.16llx as credential, and we don't belong to that network or originator is not allowed' " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , originatorAddress . toString ( ) . c_str ( ) , originatorCredentialNetworkId ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST , 0 , Packet : : VERB_NOP , false ) ;
2015-10-06 18:47:16 +00:00
return true ;
}
2016-09-09 15:43:58 +00:00
if ( network - > gate ( peer , verb ( ) , packetId ( ) ) )
reportFlags | = ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH ;
2015-10-06 18:47:16 +00:00
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped CIRCUIT_TEST from %s(%s): originator %s did not specify a credential or credential type " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) , originatorAddress . toString ( ) . c_str ( ) ) ;
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST , 0 , Packet : : VERB_NOP , false ) ;
2015-10-06 18:47:16 +00:00
return true ;
}
const uint64_t now = RR - > node - > now ( ) ;
unsigned int breadth = 0 ;
Address nextHop [ 256 ] ; // breadth is a uin8_t, so this is the max
InetAddress nextHopBestPathAddress [ 256 ] ;
unsigned int remainingHopsPtr = ZT_PACKET_IDX_PAYLOAD + 33 + vlf ;
if ( ( ZT_PACKET_IDX_PAYLOAD + 31 + vlf ) < size ( ) ) {
// unsigned int nextHopFlags = (*this)[ZT_PACKET_IDX_PAYLOAD + 31 + vlf]
breadth = ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 32 + vlf ] ;
for ( unsigned int h = 0 ; h < breadth ; + + h ) {
nextHop [ h ] . setTo ( field ( remainingHopsPtr , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
remainingHopsPtr + = ZT_ADDRESS_LENGTH ;
SharedPtr < Peer > nhp ( RR - > topology - > getPeer ( nextHop [ h ] ) ) ;
if ( nhp ) {
2016-09-07 18:13:17 +00:00
SharedPtr < Path > nhbp ( nhp - > getBestPath ( now , false ) ) ;
2016-09-02 20:33:56 +00:00
if ( ( nhbp ) & & ( nhbp - > alive ( now ) ) )
2016-09-02 18:51:33 +00:00
nextHopBestPathAddress [ h ] = nhbp - > address ( ) ;
2015-10-06 18:47:16 +00:00
}
}
}
// Report back to originator, depending on flags and whether we are last hop
if ( ( ( flags & 0x01 ) ! = 0 ) | | ( ( breadth = = 0 ) & & ( ( flags & 0x02 ) ! = 0 ) ) ) {
Packet outp ( originatorAddress , RR - > identity . address ( ) , Packet : : VERB_CIRCUIT_TEST_REPORT ) ;
outp . append ( ( uint64_t ) timestamp ) ;
outp . append ( ( uint64_t ) testId ) ;
2016-02-22 20:59:26 +00:00
outp . append ( ( uint64_t ) 0 ) ; // field reserved for future use
2015-10-06 21:42:51 +00:00
outp . append ( ( uint8_t ) ZT_VENDOR_ZEROTIER ) ;
2015-10-06 18:47:16 +00:00
outp . append ( ( uint8_t ) ZT_PROTO_VERSION ) ;
outp . append ( ( uint8_t ) ZEROTIER_ONE_VERSION_MAJOR ) ;
outp . append ( ( uint8_t ) ZEROTIER_ONE_VERSION_MINOR ) ;
outp . append ( ( uint16_t ) ZEROTIER_ONE_VERSION_REVISION ) ;
2015-10-06 21:42:51 +00:00
outp . append ( ( uint16_t ) ZT_PLATFORM_UNSPECIFIED ) ;
outp . append ( ( uint16_t ) ZT_ARCHITECTURE_UNSPECIFIED ) ;
2015-10-06 18:47:16 +00:00
outp . append ( ( uint16_t ) 0 ) ; // error code, currently unused
2016-09-09 15:43:58 +00:00
outp . append ( ( uint64_t ) reportFlags ) ;
2015-10-06 18:47:16 +00:00
outp . append ( ( uint64_t ) packetId ( ) ) ;
2015-10-09 22:05:26 +00:00
peer - > address ( ) . appendTo ( outp ) ;
2015-10-06 18:47:16 +00:00
outp . append ( ( uint8_t ) hops ( ) ) ;
2016-09-02 18:51:33 +00:00
_path - > localAddress ( ) . serialize ( outp ) ;
_path - > address ( ) . serialize ( outp ) ;
2015-10-06 18:47:16 +00:00
outp . append ( ( uint16_t ) 0 ) ; // no additional fields
outp . append ( ( uint8_t ) breadth ) ;
for ( unsigned int h = 0 ; h < breadth ; + + h ) {
nextHop [ h ] . appendTo ( outp ) ;
nextHopBestPathAddress [ h ] . serialize ( outp ) ; // appends 0 if null InetAddress
}
2016-08-09 22:45:26 +00:00
RR - > sw - > send ( outp , true ) ;
2015-10-06 18:47:16 +00:00
}
// If there are next hops, forward the test along through the graph
if ( breadth > 0 ) {
Packet outp ( Address ( ) , RR - > identity . address ( ) , Packet : : VERB_CIRCUIT_TEST ) ;
outp . append ( field ( ZT_PACKET_IDX_PAYLOAD , lengthOfSignedPortionAndSignature ) , lengthOfSignedPortionAndSignature ) ;
2016-08-04 01:04:08 +00:00
outp . append ( ( uint16_t ) 0 ) ; // no additional fields
2015-10-06 18:47:16 +00:00
if ( remainingHopsPtr < size ( ) )
outp . append ( field ( remainingHopsPtr , size ( ) - remainingHopsPtr ) , size ( ) - remainingHopsPtr ) ;
2015-09-30 20:59:05 +00:00
2015-10-06 18:47:16 +00:00
for ( unsigned int h = 0 ; h < breadth ; + + h ) {
2015-10-09 23:22:34 +00:00
if ( RR - > identity . address ( ) ! = nextHop [ h ] ) { // next hops that loop back to the current hop are not valid
outp . newInitializationVector ( ) ;
outp . setDestination ( nextHop [ h ] ) ;
2016-08-09 22:45:26 +00:00
RR - > sw - > send ( outp , true ) ;
2015-10-09 23:22:34 +00:00
}
2015-09-30 20:59:05 +00:00
}
}
2015-10-07 23:20:54 +00:00
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST , 0 , Packet : : VERB_NOP , false ) ;
2015-09-30 20:59:05 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped CIRCUIT_TEST from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-09-30 20:59:05 +00:00
}
return true ;
}
bool IncomingPacket : : _doCIRCUIT_TEST_REPORT ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2015-10-08 20:25:38 +00:00
try {
ZT_CircuitTestReport report ;
memset ( & report , 0 , sizeof ( report ) ) ;
2015-10-09 22:05:26 +00:00
report . current = peer - > address ( ) . toInt ( ) ;
report . upstream = Address ( field ( ZT_PACKET_IDX_PAYLOAD + 52 , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) . toInt ( ) ;
2015-10-08 20:25:38 +00:00
report . testId = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD + 8 ) ;
report . timestamp = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD ) ;
report . sourcePacketId = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD + 44 ) ;
report . flags = at < uint64_t > ( ZT_PACKET_IDX_PAYLOAD + 36 ) ;
2015-10-09 22:05:26 +00:00
report . sourcePacketHopCount = ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 57 ] ; // end of fixed length headers: 58
2015-10-08 20:25:38 +00:00
report . errorCode = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 34 ) ;
report . vendor = ( enum ZT_Vendor ) ( ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 24 ] ) ;
report . protocolVersion = ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 25 ] ;
report . majorVersion = ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 26 ] ;
report . minorVersion = ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 27 ] ;
report . revision = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 28 ) ;
report . platform = ( enum ZT_Platform ) at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 30 ) ;
report . architecture = ( enum ZT_Architecture ) at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 32 ) ;
2015-10-09 22:05:26 +00:00
const unsigned int receivedOnLocalAddressLen = reinterpret_cast < InetAddress * > ( & ( report . receivedOnLocalAddress ) ) - > deserialize ( * this , ZT_PACKET_IDX_PAYLOAD + 58 ) ;
const unsigned int receivedFromRemoteAddressLen = reinterpret_cast < InetAddress * > ( & ( report . receivedFromRemoteAddress ) ) - > deserialize ( * this , ZT_PACKET_IDX_PAYLOAD + 58 + receivedOnLocalAddressLen ) ;
2015-10-08 20:25:38 +00:00
2015-10-09 22:05:26 +00:00
unsigned int nhptr = ZT_PACKET_IDX_PAYLOAD + 58 + receivedOnLocalAddressLen + receivedFromRemoteAddressLen ;
2015-10-08 20:25:38 +00:00
nhptr + = at < uint16_t > ( nhptr ) + 2 ; // add "additional field" length, which right now will be zero
report . nextHopCount = ( * this ) [ nhptr + + ] ;
if ( report . nextHopCount > ZT_CIRCUIT_TEST_MAX_HOP_BREADTH ) // sanity check, shouldn't be possible
report . nextHopCount = ZT_CIRCUIT_TEST_MAX_HOP_BREADTH ;
for ( unsigned int h = 0 ; h < report . nextHopCount ; + + h ) {
2015-10-09 23:22:34 +00:00
report . nextHops [ h ] . address = Address ( field ( nhptr , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) . toInt ( ) ; nhptr + = ZT_ADDRESS_LENGTH ;
2015-10-08 20:25:38 +00:00
nhptr + = reinterpret_cast < InetAddress * > ( & ( report . nextHops [ h ] . physicalAddress ) ) - > deserialize ( * this , nhptr ) ;
}
RR - > node - > postCircuitTestReport ( & report ) ;
2016-09-07 22:15:52 +00:00
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST_REPORT , 0 , Packet : : VERB_NOP , false ) ;
2015-10-08 20:25:38 +00:00
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-10-08 20:25:38 +00:00
}
2015-09-30 20:59:05 +00:00
return true ;
}
2015-10-07 20:35:46 +00:00
bool IncomingPacket : : _doREQUEST_PROOF_OF_WORK ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
try {
2016-06-21 21:58:30 +00:00
// If this were allowed from anyone, it would itself be a DOS vector. Right
// now we only allow it from roots and controllers of networks you have joined.
2016-08-04 01:04:08 +00:00
bool allowed = RR - > topology - > isUpstream ( peer - > identity ( ) ) ;
2016-06-21 21:58:30 +00:00
if ( ! allowed ) {
std : : vector < SharedPtr < Network > > allNetworks ( RR - > node - > allNetworks ( ) ) ;
for ( std : : vector < SharedPtr < Network > > : : const_iterator n ( allNetworks . begin ( ) ) ; n ! = allNetworks . end ( ) ; + + n ) {
if ( peer - > address ( ) = = ( * n ) - > controller ( ) ) {
allowed = true ;
break ;
}
}
}
if ( allowed ) {
2015-10-07 23:20:54 +00:00
const uint64_t pid = packetId ( ) ;
2015-10-07 20:35:46 +00:00
const unsigned int difficulty = ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 1 ] ;
const unsigned int challengeLength = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 2 ) ;
if ( challengeLength > ZT_PROTO_MAX_PACKET_LENGTH )
return true ; // sanity check, drop invalid size
const unsigned char * challenge = field ( ZT_PACKET_IDX_PAYLOAD + 4 , challengeLength ) ;
switch ( ( * this ) [ ZT_PACKET_IDX_PAYLOAD ] ) {
// Salsa20/12+SHA512 hashcash
case 0x01 : {
2015-10-07 20:46:44 +00:00
if ( difficulty < = 14 ) {
unsigned char result [ 16 ] ;
computeSalsa2012Sha512ProofOfWork ( difficulty , challenge , challengeLength , result ) ;
TRACE ( " PROOF_OF_WORK computed for %s: difficulty==%u, challengeLength==%u, result: %.16llx%.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , difficulty , challengeLength , Utils : : ntoh ( * ( reinterpret_cast < const uint64_t * > ( result ) ) ) , Utils : : ntoh ( * ( reinterpret_cast < const uint64_t * > ( result + 8 ) ) ) ) ;
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_REQUEST_PROOF_OF_WORK ) ;
2015-10-07 23:20:54 +00:00
outp . append ( pid ) ;
2015-10-07 20:46:44 +00:00
outp . append ( ( uint16_t ) sizeof ( result ) ) ;
outp . append ( result , sizeof ( result ) ) ;
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2015-10-07 20:46:44 +00:00
} else {
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( unsigned char ) Packet : : VERB_REQUEST_PROOF_OF_WORK ) ;
2015-10-07 23:20:54 +00:00
outp . append ( pid ) ;
2015-10-07 20:46:44 +00:00
outp . append ( ( unsigned char ) Packet : : ERROR_INVALID_REQUEST ) ;
outp . armor ( peer - > key ( ) , true ) ;
2016-09-02 18:51:33 +00:00
_path - > send ( RR , outp . data ( ) , outp . size ( ) , RR - > node - > now ( ) ) ;
2015-10-07 20:46:44 +00:00
}
2015-10-07 20:35:46 +00:00
} break ;
default :
2016-09-02 18:51:33 +00:00
TRACE ( " dropped REQUEST_PROOF_OF_WORK from %s(%s): unrecognized proof of work type " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-10-07 20:35:46 +00:00
break ;
}
2015-10-07 23:20:54 +00:00
2016-09-07 22:24:53 +00:00
peer - > received ( _path , hops ( ) , pid , Packet : : VERB_REQUEST_PROOF_OF_WORK , 0 , Packet : : VERB_NOP , false ) ;
2015-10-07 20:35:46 +00:00
} else {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped REQUEST_PROOF_OF_WORK from %s(%s): not trusted enough " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-10-07 20:35:46 +00:00
}
} catch ( . . . ) {
2016-09-02 18:51:33 +00:00
TRACE ( " dropped REQUEST_PROOF_OF_WORK from %s(%s): unexpected exception " , peer - > address ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
2015-10-07 20:35:46 +00:00
}
return true ;
}
void IncomingPacket : : computeSalsa2012Sha512ProofOfWork ( unsigned int difficulty , const void * challenge , unsigned int challengeLength , unsigned char result [ 16 ] )
{
unsigned char salsabuf [ 131072 ] ; // 131072 == protocol constant, size of memory buffer for this proof of work function
char candidatebuf [ ZT_PROTO_MAX_PACKET_LENGTH + 256 ] ;
unsigned char shabuf [ ZT_SHA512_DIGEST_LEN ] ;
const uint64_t s20iv = 0 ; // zero IV for Salsa20
char * const candidate = ( char * ) ( ( ( ( uintptr_t ) & ( candidatebuf [ 0 ] ) ) | 0xf ) + 1 ) ; // align to 16-byte boundary to ensure that uint64_t type punning of initial nonce is okay
Salsa20 s20 ;
unsigned int d ;
unsigned char * p ;
Utils : : getSecureRandom ( candidate , 16 ) ;
memcpy ( candidate + 16 , challenge , challengeLength ) ;
if ( difficulty > 512 )
difficulty = 512 ; // sanity check
try_salsa2012sha512_again :
+ + * ( reinterpret_cast < volatile uint64_t * > ( candidate ) ) ;
SHA512 : : hash ( shabuf , candidate , 16 + challengeLength ) ;
2015-10-09 16:39:27 +00:00
s20 . init ( shabuf , 256 , & s20iv ) ;
2015-10-07 20:35:46 +00:00
memset ( salsabuf , 0 , sizeof ( salsabuf ) ) ;
2015-10-09 16:39:27 +00:00
s20 . encrypt12 ( salsabuf , salsabuf , sizeof ( salsabuf ) ) ;
2015-10-07 20:35:46 +00:00
SHA512 : : hash ( shabuf , salsabuf , sizeof ( salsabuf ) ) ;
d = difficulty ;
p = shabuf ;
while ( d > = 8 ) {
if ( * ( p + + ) )
goto try_salsa2012sha512_again ;
d - = 8 ;
}
if ( d > 0 ) {
if ( ( ( ( ( unsigned int ) * p ) < < d ) & 0xff00 ) ! = 0 )
goto try_salsa2012sha512_again ;
}
memcpy ( result , candidate , 16 ) ;
}
bool IncomingPacket : : testSalsa2012Sha512ProofOfWorkResult ( unsigned int difficulty , const void * challenge , unsigned int challengeLength , const unsigned char proposedResult [ 16 ] )
{
unsigned char salsabuf [ 131072 ] ; // 131072 == protocol constant, size of memory buffer for this proof of work function
char candidate [ ZT_PROTO_MAX_PACKET_LENGTH + 256 ] ;
unsigned char shabuf [ ZT_SHA512_DIGEST_LEN ] ;
const uint64_t s20iv = 0 ; // zero IV for Salsa20
Salsa20 s20 ;
unsigned int d ;
unsigned char * p ;
if ( difficulty > 512 )
difficulty = 512 ; // sanity check
memcpy ( candidate , proposedResult , 16 ) ;
memcpy ( candidate + 16 , challenge , challengeLength ) ;
SHA512 : : hash ( shabuf , candidate , 16 + challengeLength ) ;
2015-10-09 16:39:27 +00:00
s20 . init ( shabuf , 256 , & s20iv ) ;
2015-10-07 20:35:46 +00:00
memset ( salsabuf , 0 , sizeof ( salsabuf ) ) ;
2015-10-09 16:39:27 +00:00
s20 . encrypt12 ( salsabuf , salsabuf , sizeof ( salsabuf ) ) ;
2015-10-07 20:35:46 +00:00
SHA512 : : hash ( shabuf , salsabuf , sizeof ( salsabuf ) ) ;
d = difficulty ;
p = shabuf ;
while ( d > = 8 ) {
if ( * ( p + + ) )
return false ;
d - = 8 ;
}
if ( d > 0 ) {
if ( ( ( ( ( unsigned int ) * p ) < < d ) & 0xff00 ) ! = 0 )
return false ;
}
return true ;
}
2013-07-11 20:19:06 +00:00
} // namespace ZeroTier