@ -115,8 +115,6 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr)
case Packet : : VERB_MULTICAST_GATHER : return _doMULTICAST_GATHER ( RR , tPtr , peer ) ;
case Packet : : VERB_MULTICAST_FRAME : return _doMULTICAST_FRAME ( RR , tPtr , peer ) ;
case Packet : : VERB_PUSH_DIRECT_PATHS : return _doPUSH_DIRECT_PATHS ( RR , tPtr , peer ) ;
case Packet : : VERB_CIRCUIT_TEST : return _doCIRCUIT_TEST ( RR , tPtr , peer ) ;
case Packet : : VERB_CIRCUIT_TEST_REPORT : return _doCIRCUIT_TEST_REPORT ( RR , tPtr , peer ) ;
case Packet : : VERB_USER_MESSAGE : return _doUSER_MESSAGE ( RR , tPtr , peer ) ;
}
} else {
@ -1252,196 +1250,6 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt
return true ;
}
bool IncomingPacket : : _doCIRCUIT_TEST ( const RuntimeEnvironment * RR , void * tPtr , 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 ( tPtr , originatorAddress ) ) ;
if ( ! originator ) {
RR - > sw - > requestWhois ( tPtr , 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 ) ;
// Tracks total length of variable length fields, initialized to originator credential length below
unsigned int vlf ;
// Originator credentials -- right now only a network ID for which the originator is controller or is authorized by controller is allowed
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 ;
}
}
// Add length of "additional fields," which are currently unused
vlf + = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 25 + vlf ) ;
// 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 ) ) {
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 ( ) ) ;
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST , 0 , Packet : : VERB_NOP , false ) ;
return true ;
}
vlf + = signatureLength ;
// 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 ;
// Add length of second "additional fields" section.
vlf + = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD + 29 + vlf ) ;
uint64_t reportFlags = 0 ;
// Check credentials (signature already verified)
if ( originatorCredentialNetworkId ) {
SharedPtr < Network > network ( RR - > node - > network ( originatorCredentialNetworkId ) ) ;
if ( ( ! network ) | | ( ! network - > config ( ) . circuitTestingAllowed ( originatorAddress ) ) ) {
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 ) ;
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST , 0 , Packet : : VERB_NOP , false ) ;
return true ;
}
if ( network - > gate ( tPtr , peer ) )
reportFlags | = ZT_CIRCUIT_TEST_REPORT_FLAGS_UPSTREAM_AUTHORIZED_IN_PATH ;
} else {
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 ( ) ) ;
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST , 0 , Packet : : VERB_NOP , false ) ;
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 ( tPtr , nextHop [ h ] ) ) ;
if ( nhp ) {
SharedPtr < Path > nhbp ( nhp - > getBestPath ( now , false ) ) ;
if ( ( nhbp ) & & ( nhbp - > alive ( now ) ) )
nextHopBestPathAddress [ h ] = nhbp - > address ( ) ;
}
}
}
// 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 ) ;
outp . append ( ( uint64_t ) 0 ) ; // field reserved for future use
outp . append ( ( uint8_t ) ZT_VENDOR_ZEROTIER ) ;
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 ) ;
outp . append ( ( uint16_t ) ZT_PLATFORM_UNSPECIFIED ) ;
outp . append ( ( uint16_t ) ZT_ARCHITECTURE_UNSPECIFIED ) ;
outp . append ( ( uint16_t ) 0 ) ; // error code, currently unused
outp . append ( ( uint64_t ) reportFlags ) ;
outp . append ( ( uint64_t ) packetId ( ) ) ;
peer - > address ( ) . appendTo ( outp ) ;
outp . append ( ( uint8_t ) hops ( ) ) ;
_path - > localAddress ( ) . serialize ( outp ) ;
_path - > address ( ) . serialize ( outp ) ;
outp . append ( ( uint16_t ) _path - > linkQuality ( ) ) ;
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
}
RR - > sw - > send ( tPtr , outp , true ) ;
}
// 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 ) ;
outp . append ( ( uint16_t ) 0 ) ; // no additional fields
if ( remainingHopsPtr < size ( ) )
outp . append ( field ( remainingHopsPtr , size ( ) - remainingHopsPtr ) , size ( ) - remainingHopsPtr ) ;
for ( unsigned int h = 0 ; h < breadth ; + + h ) {
if ( RR - > identity . address ( ) ! = nextHop [ h ] ) { // next hops that loop back to the current hop are not valid
outp . newInitializationVector ( ) ;
outp . setDestination ( nextHop [ h ] ) ;
RR - > sw - > send ( tPtr , outp , true ) ;
}
}
}
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST , 0 , Packet : : VERB_NOP , false ) ;
} catch ( . . . ) {
TRACE ( " dropped CIRCUIT_TEST from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
}
return true ;
}
bool IncomingPacket : : _doCIRCUIT_TEST_REPORT ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
{
try {
ZT_CircuitTestReport report ;
memset ( & report , 0 , sizeof ( report ) ) ;
report . current = peer - > address ( ) . toInt ( ) ;
report . upstream = Address ( field ( ZT_PACKET_IDX_PAYLOAD + 52 , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) . toInt ( ) ;
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 ) ;
report . sourcePacketHopCount = ( * this ) [ ZT_PACKET_IDX_PAYLOAD + 57 ] ; // end of fixed length headers: 58
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 ) ;
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 ) ;
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 58 + receivedOnLocalAddressLen + receivedFromRemoteAddressLen ;
if ( report . protocolVersion > = 9 ) {
report . receivedFromLinkQuality = at < uint16_t > ( ptr ) ; ptr + = 2 ;
} else {
report . receivedFromLinkQuality = ZT_PATH_LINK_QUALITY_MAX ;
ptr + = at < uint16_t > ( ptr ) + 2 ; // this field was once an 'extended field length' reserved field, which was always set to 0
}
report . nextHopCount = ( * this ) [ ptr + + ] ;
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 ) {
report . nextHops [ h ] . address = Address ( field ( ptr , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) . toInt ( ) ; ptr + = ZT_ADDRESS_LENGTH ;
ptr + = reinterpret_cast < InetAddress * > ( & ( report . nextHops [ h ] . physicalAddress ) ) - > deserialize ( * this , ptr ) ;
}
RR - > node - > postCircuitTestReport ( & report ) ;
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST_REPORT , 0 , Packet : : VERB_NOP , false ) ;
} catch ( . . . ) {
TRACE ( " dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
}
return true ;
}
bool IncomingPacket : : _doUSER_MESSAGE ( const RuntimeEnvironment * RR , void * tPtr , const SharedPtr < Peer > & peer )
{
try {
@ -1453,9 +1261,9 @@ bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,void *tPtr,con
um . length = size ( ) - ( ZT_PACKET_IDX_PAYLOAD + 8 ) ;
RR - > node - > postEvent ( tPtr , ZT_EVENT_USER_MESSAGE , reinterpret_cast < const void * > ( & um ) ) ;
}
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , Packet : : VERB_CIRCUIT_TEST_REPORT , 0 , Packet : : VERB_NOP , false ) ;
peer - > received ( tPtr , _path , hops ( ) , packetId ( ) , Packet : : VERB_USER_MESSAGE , 0 , Packet : : VERB_NOP , false ) ;
} catch ( . . . ) {
TRACE ( " dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
TRACE ( " dropped USER_MESSAGE from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _path - > address ( ) . toString ( ) . c_str ( ) ) ;
}
return true ;
}