2013-07-11 16:19:06 -04:00
/*
2015-02-17 13:11:34 -08:00
* ZeroTier One - Network Virtualization Everywhere
* Copyright ( C ) 2011 - 2015 ZeroTier , Inc .
2013-07-11 16:19:06 -04: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/>.
*
* - -
*
* ZeroTier may be used and distributed under the terms of the GPLv3 , which
* are available at : http : //www.gnu.org/licenses/gpl-3.0.html
*
* If you would like to embed ZeroTier into a commercial application or
* redistribute it in a modified binary form , please contact ZeroTier Networks
* LLC . Start here : http : //www.zerotier.com/
*/
2013-10-02 13:50:42 -04:00
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
2013-09-13 15:47:00 -04:00
# include "../version.h"
2013-08-02 17:17:34 -04:00
# include "Constants.hpp"
2013-10-01 16:01:36 -04:00
# include "Defaults.hpp"
2013-07-11 16:19:06 -04:00
# include "RuntimeEnvironment.hpp"
2014-09-24 09:04:09 -07:00
# include "IncomingPacket.hpp"
2014-10-01 16:29:52 -07:00
# include "Topology.hpp"
2013-07-11 16:19:06 -04:00
# include "Switch.hpp"
2013-07-11 17:52:04 -04:00
# include "Peer.hpp"
2015-04-15 15:12:09 -07:00
# include "NetworkController.hpp"
2015-04-06 20:17:21 -07:00
# include "SelfAwareness.hpp"
2013-07-11 16:19:06 -04:00
namespace ZeroTier {
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : tryDecode ( const RuntimeEnvironment * RR )
2013-07-11 16:19:06 -04:00
{
2014-10-02 10:06:29 -07:00
try {
2014-10-02 10:54:34 -07:00
if ( ( cipher ( ) = = ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE ) & & ( verb ( ) = = Packet : : VERB_HELLO ) ) {
2014-10-02 10:06:29 -07:00
// Unencrypted HELLOs are handled here since they are used to
// populate our identity cache in the first place. _doHELLO() is special
// in that it contains its own authentication logic.
return _doHELLO ( RR ) ;
2013-07-11 17:52:04 -04:00
}
2014-10-02 10:06:29 -07:00
SharedPtr < Peer > peer = RR - > topology - > getPeer ( source ( ) ) ;
if ( peer ) {
if ( ! dearmor ( peer - > key ( ) ) ) {
TRACE ( " dropped packet from %s(%s), MAC authentication failed (size: %u) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , size ( ) ) ;
2013-07-11 18:15:51 -04:00
return true ;
2014-10-02 10:06:29 -07:00
}
if ( ! uncompress ( ) ) {
TRACE ( " dropped packet from %s(%s), compressed data invalid " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
//TRACE("<< %s from %s(%s)",Packet::verbString(verb()),source().toString().c_str(),_remoteAddress.toString().c_str());
switch ( verb ( ) ) {
//case Packet::VERB_NOP:
default : // ignore unknown verbs, but if they pass auth check they are "received"
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , verb ( ) , 0 , Packet : : VERB_NOP ) ;
2014-10-02 10:06:29 -07:00
return true ;
case Packet : : VERB_HELLO : return _doHELLO ( RR ) ;
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_MULTICAST_LIKE : return _doMULTICAST_LIKE ( RR , peer ) ;
case Packet : : VERB_NETWORK_MEMBERSHIP_CERTIFICATE : return _doNETWORK_MEMBERSHIP_CERTIFICATE ( RR , peer ) ;
case Packet : : VERB_NETWORK_CONFIG_REQUEST : return _doNETWORK_CONFIG_REQUEST ( RR , peer ) ;
2015-01-05 17:47:59 -08:00
case Packet : : VERB_NETWORK_CONFIG_REFRESH : return _doNETWORK_CONFIG_REFRESH ( RR , peer ) ;
2014-10-02 10:06:29 -07:00
case Packet : : VERB_MULTICAST_GATHER : return _doMULTICAST_GATHER ( RR , peer ) ;
case Packet : : VERB_MULTICAST_FRAME : return _doMULTICAST_FRAME ( RR , peer ) ;
2015-07-06 15:05:04 -07:00
case Packet : : VERB_PUSH_DIRECT_PATHS : return _doPUSH_DIRECT_PATHS ( RR , peer ) ;
2014-10-02 10:06:29 -07:00
}
} else {
RR - > sw - > requestWhois ( source ( ) ) ;
return false ;
2013-07-11 17:52:04 -04:00
}
2014-10-02 10:06:29 -07:00
} catch ( . . . ) {
// Exceptions are more informatively caught in _do...() handlers but
// this outer try/catch will catch anything else odd.
TRACE ( " dropped ??? from %s(%s): unexpected exception in tryDecode() " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
2013-07-11 17:52:04 -04:00
}
2013-07-11 18:15:51 -04:00
}
2013-07-11 17:52:04 -04:00
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doERROR ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
2015-04-06 14:50:53 -07:00
const Packet : : Verb inReVerb = ( Packet : : Verb ) ( * this ) [ ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB ] ;
const uint64_t inRePacketId = at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID ) ;
const Packet : : ErrorCode errorCode = ( Packet : : ErrorCode ) ( * this ) [ ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE ] ;
2013-12-24 10:39:29 -08:00
2014-09-30 16:28:25 -07:00
//TRACE("ERROR %s from %s(%s) in-re %s",Packet::errorString(errorCode),source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb));
2013-09-27 16:03:13 -04:00
switch ( errorCode ) {
2014-09-30 16:28:25 -07:00
2013-09-27 16:03:13 -04:00
case Packet : : ERROR_OBJ_NOT_FOUND :
if ( inReVerb = = Packet : : VERB_WHOIS ) {
2015-06-19 10:23:25 -07:00
if ( RR - > topology - > isRoot ( peer - > identity ( ) ) )
2014-09-24 13:53:03 -07:00
RR - > sw - > cancelWhoisRequest ( Address ( field ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ) ;
2013-10-17 05:37:01 -04:00
} else if ( inReVerb = = Packet : : VERB_NETWORK_CONFIG_REQUEST ) {
2015-04-06 14:50:53 -07:00
SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2013-10-17 05:37:01 -04:00
if ( ( network ) & & ( network - > controller ( ) = = source ( ) ) )
2014-01-27 23:13:36 -08:00
network - > setNotFound ( ) ;
2013-09-27 16:03:13 -04:00
}
break ;
2014-09-30 16:28:25 -07:00
2015-01-09 16:35:20 -05:00
case Packet : : ERROR_UNSUPPORTED_OPERATION :
if ( inReVerb = = Packet : : VERB_NETWORK_CONFIG_REQUEST ) {
2015-04-06 14:50:53 -07:00
SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2015-01-09 16:35:20 -05:00
if ( ( network ) & & ( network - > controller ( ) = = source ( ) ) )
network - > setNotFound ( ) ;
}
break ;
2013-09-27 16:03:13 -04:00
case Packet : : ERROR_IDENTITY_COLLISION :
2015-06-19 10:23:25 -07:00
if ( RR - > topology - > isRoot ( peer - > identity ( ) ) )
2015-04-06 14:50:53 -07:00
RR - > node - > postEvent ( ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION ) ;
2013-09-27 16:03:13 -04:00
break ;
2014-09-30 16:28:25 -07:00
2013-10-16 17:47:26 -04:00
case Packet : : ERROR_NEED_MEMBERSHIP_CERTIFICATE : {
2015-07-07 08:54:48 -07:00
/* Note: certificates are public so it's safe to push them to anyone
* who asks . We won ' t communicate unless we also get a certificate
* from the remote that agrees . */
2015-04-06 14:50:53 -07:00
SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2014-10-09 12:42:25 -07:00
if ( network ) {
SharedPtr < NetworkConfig > nconf ( network - > config2 ( ) ) ;
if ( nconf ) {
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_NETWORK_MEMBERSHIP_CERTIFICATE ) ;
nconf - > com ( ) . serialize ( outp ) ;
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2014-10-09 12:42:25 -07:00
}
}
2013-10-16 17:47:26 -04:00
} break ;
2014-09-30 16:28:25 -07:00
2014-01-17 17:09:59 -08:00
case Packet : : ERROR_NETWORK_ACCESS_DENIED_ : {
2015-04-06 14:50:53 -07:00
SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2013-10-17 05:37:01 -04:00
if ( ( network ) & & ( network - > controller ( ) = = source ( ) ) )
2014-01-27 23:13:36 -08:00
network - > setAccessDenied ( ) ;
2013-10-17 05:37:01 -04:00
} break ;
2014-09-30 16:28:25 -07:00
2014-10-09 12:42:25 -07:00
case Packet : : ERROR_UNWANTED_MULTICAST : {
2015-07-07 11:49:38 -07:00
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ;
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 " , nwid , peer - > address ( ) . toString ( ) . c_str ( ) , mg . toString ( ) . c_str ( ) ) ;
RR - > mc - > remove ( nwid , mg , peer - > address ( ) ) ;
2014-10-09 12:42:25 -07:00
} break ;
2014-09-30 16:28:25 -07:00
default : break ;
2013-09-27 16:03:13 -04:00
}
2013-12-24 10:39:29 -08:00
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_ERROR , inRePacketId , inReVerb ) ;
2013-07-11 18:15:51 -04:00
} catch ( std : : exception & ex ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped ERROR from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 18:15:51 -04:00
} catch ( . . . ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped ERROR from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 17:52:04 -04:00
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doHELLO ( const RuntimeEnvironment * RR )
2013-07-11 17:52:04 -04:00
{
2015-07-07 08:54:48 -07:00
/* Note: this is the only packet ever sent in the clear, and it's also
* the only packet that we authenticate via a different path . Authentication
* occurs here and is based on the validity of the identity and the
* integrity of the packet ' s MAC , but it must be done after we check
* the identity since HELLO is a mechanism for learning new identities
* in the first place . */
2013-07-11 17:52:04 -04:00
try {
2015-04-06 14:50:53 -07: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-04-06 20:17:21 -07:00
Identity id ;
unsigned int destAddrPtr = id . deserialize ( * this , ZT_PROTO_VERB_HELLO_IDX_IDENTITY ) + ZT_PROTO_VERB_HELLO_IDX_IDENTITY ;
2015-07-13 08:36:22 -07:00
if ( protoVersion < ZT_PROTO_VERSION_MIN ) {
TRACE ( " dropped HELLO from %s(%s): protocol version too old " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
2015-07-07 08:54:48 -07:00
if ( source ( ) ! = id . address ( ) ) {
TRACE ( " dropped HELLO from %s(%s): identity not for sending address " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
2015-04-06 20:17:21 -07:00
InetAddress destAddr ;
2015-04-30 16:40:04 -07:00
if ( destAddrPtr < size ( ) ) { // ZeroTier One < 1.0.3 did not include this field
const unsigned int destAddrType = ( * this ) [ destAddrPtr + + ] ;
switch ( destAddrType ) {
case ZT_PROTO_DEST_ADDRESS_TYPE_IPV4 :
destAddr . set ( field ( destAddrPtr , 4 ) , 4 , at < uint16_t > ( destAddrPtr + 4 ) ) ;
break ;
case ZT_PROTO_DEST_ADDRESS_TYPE_IPV6 :
destAddr . set ( field ( destAddrPtr , 16 ) , 16 , at < uint16_t > ( destAddrPtr + 16 ) ) ;
break ;
}
2015-04-06 20:17:21 -07:00
}
2015-04-06 14:50:53 -07:00
2014-09-24 13:53:03 -07:00
SharedPtr < Peer > peer ( RR - > topology - > getPeer ( id . address ( ) ) ) ;
2013-10-05 10:19:12 -04:00
if ( peer ) {
2014-12-16 09:29:40 -08:00
// We already have an identity with this address -- check for collisions
2013-10-05 10:19:12 -04:00
if ( peer - > identity ( ) ! = id ) {
2014-12-16 09:29:40 -08:00
// Identity is different from the one we already have -- address collision
2013-10-05 10:19:12 -04:00
unsigned char key [ ZT_PEER_SECRET_KEY_LENGTH ] ;
2014-09-24 13:53:03 -07:00
if ( RR - > identity . agree ( id , key , ZT_PEER_SECRET_KEY_LENGTH ) ) {
2013-12-31 11:03:45 -08:00
if ( dearmor ( key ) ) { // ensure packet is authentic, otherwise drop
2015-04-08 16:49:21 -07:00
RR - > node - > postEvent ( ZT1_EVENT_AUTHENTICATION_FAILURE , ( const void * ) & _remoteAddress ) ;
TRACE ( " rejected HELLO from %s(%s): address already claimed " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2015-04-06 14:50:53 -07:00
Packet outp ( id . address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2013-12-31 11:03:45 -08:00
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_IDENTITY_COLLISION ) ;
outp . armor ( key , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2013-12-31 11:03:45 -08:00
} else {
2015-04-08 16:49:21 -07:00
RR - > node - > postEvent ( ZT1_EVENT_AUTHENTICATION_FAILURE , ( const void * ) & _remoteAddress ) ;
TRACE ( " rejected HELLO from %s(%s): packet failed authentication " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-12-31 11:03:45 -08:00
}
} else {
2015-04-08 16:49:21 -07:00
RR - > node - > postEvent ( ZT1_EVENT_AUTHENTICATION_FAILURE , ( const void * ) & _remoteAddress ) ;
TRACE ( " rejected HELLO from %s(%s): key agreement failed " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-10-05 10:19:12 -04:00
}
2014-12-16 09:29:40 -08:00
2013-10-05 10:19:12 -04:00
return true ;
2014-12-16 09:29:40 -08:00
} else {
// Identity is the same as the one we already have -- check packet integrity
if ( ! dearmor ( peer - > key ( ) ) ) {
2015-04-08 16:49:21 -07:00
RR - > node - > postEvent ( ZT1_EVENT_AUTHENTICATION_FAILURE , ( const void * ) & _remoteAddress ) ;
TRACE ( " rejected HELLO from %s(%s): packet failed authentication " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2014-12-16 09:29:40 -08:00
return true ;
}
2015-04-06 14:50:53 -07:00
// Continue at // VALID
2014-10-13 14:12:51 -07:00
}
2013-10-16 17:47:26 -04:00
} else {
2014-12-16 09:29:40 -08:00
// We don't already have an identity with this address -- validate and learn it
2015-07-07 08:54:48 -07:00
// Check identity proof of work
2014-12-16 09:29:40 -08:00
if ( ! id . locallyValidate ( ) ) {
2015-04-08 16:49:21 -07:00
RR - > node - > postEvent ( ZT1_EVENT_AUTHENTICATION_FAILURE , ( const void * ) & _remoteAddress ) ;
2015-04-06 14:50:53 -07:00
TRACE ( " dropped HELLO from %s(%s): identity invalid " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2014-12-16 09:29:40 -08:00
return true ;
}
2015-07-07 08:54:48 -07:00
// Check packet integrity and authentication
2014-09-24 13:53:03 -07:00
SharedPtr < Peer > newPeer ( new Peer ( RR - > identity , id ) ) ;
2013-12-31 11:03:45 -08:00
if ( ! dearmor ( newPeer - > key ( ) ) ) {
2015-04-08 16:49:21 -07:00
RR - > node - > postEvent ( ZT1_EVENT_AUTHENTICATION_FAILURE , ( const void * ) & _remoteAddress ) ;
TRACE ( " rejected HELLO from %s(%s): packet failed authentication " , id . address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-12-31 11:03:45 -08:00
return true ;
}
2014-12-16 09:29:40 -08:00
2014-09-24 13:53:03 -07:00
peer = RR - > topology - > addPeer ( newPeer ) ;
2014-12-16 09:29:40 -08:00
2015-04-06 14:50:53 -07:00
// Continue at // VALID
2013-10-16 17:47:26 -04:00
}
2013-10-05 10:19:12 -04:00
2015-04-06 14:50:53 -07:00
// VALID -- continues here
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_HELLO , 0 , Packet : : VERB_NOP ) ;
2014-09-30 16:28:25 -07:00
peer - > setRemoteVersion ( protoVersion , vMajor , vMinor , vRevision ) ;
2013-10-05 10:19:12 -04:00
2015-04-30 16:40:04 -07:00
bool trusted = false ;
2015-06-19 10:23:25 -07:00
if ( RR - > topology - > isRoot ( id ) ) {
2015-04-06 20:17:21 -07:00
RR - > node - > postNewerVersionIfNewer ( vMajor , vMinor , vRevision ) ;
2015-04-30 16:40:04 -07:00
trusted = true ;
2015-04-06 20:17:21 -07:00
}
2015-04-30 16:40:04 -07:00
if ( destAddr )
2015-05-04 18:34:30 -07:00
RR - > sa - > iam ( id . address ( ) , _remoteAddress , destAddr , trusted , RR - > node - > now ( ) ) ;
2014-01-07 16:37:36 -08:00
2015-04-06 14:50:53 -07:00
Packet outp ( id . address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2015-04-06 20:17:21 -07:00
2013-10-05 10:19:12 -04:00
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
outp . append ( packetId ( ) ) ;
outp . append ( timestamp ) ;
outp . append ( ( unsigned char ) ZT_PROTO_VERSION ) ;
outp . append ( ( unsigned char ) ZEROTIER_ONE_VERSION_MAJOR ) ;
outp . append ( ( unsigned char ) ZEROTIER_ONE_VERSION_MINOR ) ;
outp . append ( ( uint16_t ) ZEROTIER_ONE_VERSION_REVISION ) ;
2015-04-06 20:17:21 -07:00
switch ( _remoteAddress . ss_family ) {
case AF_INET :
outp . append ( ( unsigned char ) ZT_PROTO_DEST_ADDRESS_TYPE_IPV4 ) ;
outp . append ( _remoteAddress . rawIpData ( ) , 4 ) ;
outp . append ( ( uint16_t ) _remoteAddress . port ( ) ) ;
break ;
case AF_INET6 :
outp . append ( ( unsigned char ) ZT_PROTO_DEST_ADDRESS_TYPE_IPV6 ) ;
outp . append ( _remoteAddress . rawIpData ( ) , 16 ) ;
outp . append ( ( uint16_t ) _remoteAddress . port ( ) ) ;
break ;
default :
outp . append ( ( unsigned char ) ZT_PROTO_DEST_ADDRESS_TYPE_NONE ) ;
break ;
}
2013-10-05 10:19:12 -04:00
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2013-07-11 17:52:04 -04:00
} catch ( std : : exception & ex ) {
2015-04-09 20:54:00 -07:00
TRACE ( " dropped HELLO from %s(%s): %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 18:15:51 -04:00
} catch ( . . . ) {
2015-04-09 20:54:00 -07:00
TRACE ( " dropped HELLO from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doOK ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
2015-04-06 14:50:53 -07:00
const Packet : : Verb inReVerb = ( Packet : : Verb ) ( * this ) [ ZT_PROTO_VERB_OK_IDX_IN_RE_VERB ] ;
const uint64_t inRePacketId = at < uint64_t > ( ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID ) ;
2013-12-24 10:39:29 -08:00
2014-01-29 20:09:55 -05:00
//TRACE("%s(%s): OK(%s)",source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb));
2013-12-24 10:39:29 -08:00
2013-07-11 18:15:51 -04:00
switch ( inReVerb ) {
2014-09-30 16:28:25 -07:00
2013-07-11 22:06:25 -04:00
case Packet : : VERB_HELLO : {
2015-04-06 14:50:53 -07: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 16:28:25 -07:00
2015-04-30 16:40:04 -07:00
InetAddress destAddr ;
unsigned int destAddrPtr = ZT_PROTO_VERB_HELLO__OK__IDX_REVISION + 2 ; // dest address, if present, will start after 16-bit revision
if ( destAddrPtr < size ( ) ) { // ZeroTier One < 1.0.3 did not include this field
const unsigned int destAddrType = ( * this ) [ destAddrPtr + + ] ;
switch ( destAddrType ) {
case ZT_PROTO_DEST_ADDRESS_TYPE_IPV4 :
destAddr . set ( field ( destAddrPtr , 4 ) , 4 , at < uint16_t > ( destAddrPtr + 4 ) ) ;
break ;
case ZT_PROTO_DEST_ADDRESS_TYPE_IPV6 :
destAddr . set ( field ( destAddrPtr , 16 ) , 16 , at < uint16_t > ( destAddrPtr + 16 ) ) ;
break ;
}
}
2014-09-30 16:28:25 -07:00
if ( vProto < ZT_PROTO_VERSION_MIN ) {
TRACE ( " %s(%s): OK(HELLO) dropped, protocol version too old " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
2015-04-30 18:25:31 -07:00
TRACE ( " %s(%s): OK(HELLO), version %u.%u.%u, latency %u, reported external address %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , vMajor , vMinor , vRevision , latency , ( ( destAddr ) ? destAddr . toString ( ) . c_str ( ) : " (none) " ) ) ;
2014-09-30 16:28:25 -07:00
2014-02-03 10:46:37 -08:00
peer - > addDirectLatencyMeasurment ( latency ) ;
2014-09-30 16:28:25 -07:00
peer - > setRemoteVersion ( vProto , vMajor , vMinor , vRevision ) ;
2013-12-26 20:57:17 -08:00
2015-04-30 16:40:04 -07:00
bool trusted = false ;
2015-06-19 10:23:25 -07:00
if ( RR - > topology - > isRoot ( peer - > identity ( ) ) ) {
2015-04-06 14:50:53 -07:00
RR - > node - > postNewerVersionIfNewer ( vMajor , vMinor , vRevision ) ;
2015-04-30 16:40:04 -07:00
trusted = true ;
}
if ( destAddr )
2015-05-04 18:34:30 -07:00
RR - > sa - > iam ( peer - > address ( ) , _remoteAddress , destAddr , trusted , RR - > node - > now ( ) ) ;
2013-07-11 22:06:25 -04:00
} break ;
2014-09-30 16:28:25 -07:00
2013-08-05 12:16:25 -04:00
case Packet : : VERB_WHOIS : {
2015-06-19 10:23:25 -07:00
/* Right now only root servers are allowed to send OK(WHOIS) to prevent
* poisoning attacks . Further decentralization will require some other
* kind of trust mechanism . */
if ( RR - > topology - > isRoot ( peer - > identity ( ) ) ) {
2015-04-06 14:50:53 -07:00
const Identity id ( * this , ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY ) ;
2013-10-05 10:19:12 -04:00
if ( id . locallyValidate ( ) )
2014-09-24 13:53:03 -07:00
RR - > sw - > doAnythingWaitingForPeer ( RR - > topology - > addPeer ( SharedPtr < Peer > ( new Peer ( RR - > identity , id ) ) ) ) ;
2013-08-05 12:16:25 -04:00
}
} break ;
2014-09-30 16:28:25 -07:00
2013-08-03 12:53:46 -04:00
case Packet : : VERB_NETWORK_CONFIG_REQUEST : {
2015-04-06 14:50:53 -07:00
const SharedPtr < Network > nw ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID ) ) ) ;
if ( ( nw ) & & ( nw - > controller ( ) = = peer - > address ( ) ) ) {
const unsigned int dictlen = at < uint16_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN ) ;
const std : : string dict ( ( const char * ) field ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT , dictlen ) , dictlen ) ;
2013-08-03 12:53:46 -04:00
if ( dict . length ( ) ) {
2015-07-23 09:50:10 -07:00
nw - > setConfiguration ( Dictionary ( dict ) ) ;
2013-09-11 16:49:01 -04:00
TRACE ( " got network configuration for network %.16llx from %s " , ( unsigned long long ) nw - > id ( ) , source ( ) . toString ( ) . c_str ( ) ) ;
2013-08-03 12:53:46 -04:00
}
}
} break ;
2014-09-30 16:28:25 -07:00
case Packet : : VERB_MULTICAST_GATHER : {
2015-04-06 14:50:53 -07:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID ) ;
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 ) ) ;
2014-10-09 17:58:31 -07:00
TRACE ( " %s(%s): OK(MULTICAST_GATHER) %.16llx/%s length %u " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , nwid , mg . toString ( ) . c_str ( ) , size ( ) ) ;
2015-04-06 14:50:53 -07:00
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 16:28:25 -07:00
} break ;
case Packet : : VERB_MULTICAST_FRAME : {
2015-04-06 14:50:53 -07: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 12:42:25 -07:00
2015-04-15 13:15:09 -07:00
//TRACE("%s(%s): OK(MULTICAST_FRAME) %.16llx/%s flags %.2x",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),nwid,mg.toString().c_str(),flags);
2014-10-09 17:58:31 -07:00
2014-10-09 12:42:25 -07:00
unsigned int offset = 0 ;
if ( ( flags & 0x01 ) ! = 0 ) {
// OK(MULTICAST_FRAME) includes certificate of membership update
CertificateOfMembership com ;
2014-10-29 16:24:19 -07:00
offset + = com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS ) ;
2015-04-06 14:50:53 -07:00
SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
2014-10-09 12:42:25 -07:00
if ( ( network ) & & ( com . hasRequiredFields ( ) ) )
2015-07-07 08:14:41 -07:00
network - > validateAndAddMembershipCertificate ( com ) ;
2014-10-09 12:42:25 -07:00
}
if ( ( flags & 0x02 ) ! = 0 ) {
// OK(MULTICAST_FRAME) includes implicit gather results
2014-10-29 16:24:19 -07:00
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 ;
2015-04-06 14:50:53 -07:00
RR - > mc - > addMultiple ( RR - > node - > now ( ) , nwid , mg , field ( offset , count * 5 ) , count , totalKnown ) ;
2014-10-02 13:50:37 -07:00
}
2014-09-30 16:28:25 -07:00
} break ;
default : break ;
2013-07-11 18:15:51 -04:00
}
2013-12-24 10:39:29 -08:00
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_OK , inRePacketId , inReVerb ) ;
2013-07-11 18:15:51 -04:00
} catch ( std : : exception & ex ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped OK from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 18:15:51 -04:00
} catch ( . . . ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped OK from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doWHOIS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
2014-06-23 08:19:41 -07:00
try {
if ( payloadLength ( ) = = ZT_ADDRESS_LENGTH ) {
2015-04-06 14:50:53 -07:00
const SharedPtr < Peer > queried ( RR - > topology - > getPeer ( Address ( payload ( ) , ZT_ADDRESS_LENGTH ) ) ) ;
2014-10-13 14:12:51 -07:00
if ( queried ) {
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2014-06-23 08:19:41 -07:00
outp . append ( ( unsigned char ) Packet : : VERB_WHOIS ) ;
outp . append ( packetId ( ) ) ;
2014-10-13 14:12:51 -07:00
queried - > identity ( ) . serialize ( outp , false ) ;
2014-06-23 08:19:41 -07:00
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2014-06-23 08:19:41 -07:00
} else {
2014-10-13 14:12:51 -07:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2014-06-23 08:19:41 -07:00
outp . append ( ( unsigned char ) Packet : : VERB_WHOIS ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_OBJ_NOT_FOUND ) ;
outp . append ( payload ( ) , ZT_ADDRESS_LENGTH ) ;
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2014-06-23 08:19:41 -07:00
}
2013-07-11 18:15:51 -04:00
} else {
2014-06-23 08:19:41 -07:00
TRACE ( " dropped WHOIS from %s(%s): missing or invalid address " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_WHOIS , 0 , Packet : : VERB_NOP ) ;
2014-06-23 08:19:41 -07:00
} catch ( . . . ) {
TRACE ( " dropped WHOIS from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doRENDEZVOUS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
2015-06-01 19:05:27 -07:00
const Address with ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
const SharedPtr < Peer > withPeer ( RR - > topology - > getPeer ( with ) ) ;
if ( withPeer ) {
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 ) ) ) {
InetAddress atAddr ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS , addrlen ) , addrlen , port ) ;
TRACE ( " RENDEZVOUS from %s says %s might be at %s, starting NAT-t " , peer - > address ( ) . toString ( ) . c_str ( ) , with . toString ( ) . c_str ( ) , atAddr . toString ( ) . c_str ( ) ) ;
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_RENDEZVOUS , 0 , Packet : : VERB_NOP ) ;
RR - > sw - > rendezvous ( withPeer , _localInterfaceId , atAddr ) ;
2013-07-11 18:15:51 -04:00
} else {
2015-06-01 19:05:27 -07:00
TRACE ( " dropped corrupt RENDEZVOUS from %s(%s) (bad address or port) " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
} else {
2015-06-01 19:05:27 -07:00
TRACE ( " ignored RENDEZVOUS from %s(%s) to meet unknown peer %s " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , with . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
} catch ( std : : exception & ex ) {
2015-04-06 14:50:53 -07:00
TRACE ( " dropped RENDEZVOUS from %s(%s): %s " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 18:15:51 -04:00
} catch ( . . . ) {
2015-04-06 14:50:53 -07:00
TRACE ( " dropped RENDEZVOUS from %s(%s): unexpected exception " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doFRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
2015-04-06 14:50:53 -07:00
const SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ) ) ;
2013-07-11 18:15:51 -04:00
if ( network ) {
2014-06-18 09:00:53 -07:00
if ( size ( ) > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ) {
if ( ! network - > isAllowed ( peer - > address ( ) ) ) {
TRACE ( " dropped FRAME from %s(%s): not a member of private network %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ( unsigned long long ) network - > id ( ) ) ;
2014-09-24 13:53:03 -07:00
_sendErrorNeedCertificate ( RR , peer , network - > id ( ) ) ;
2014-06-18 09:00:53 -07:00
return true ;
}
2015-04-06 14:50:53 -07:00
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE ) ;
2014-06-18 09:00:53 -07:00
if ( ! network - > config ( ) - > permitsEtherType ( etherType ) ) {
TRACE ( " dropped FRAME from %s(%s): ethertype %.4x not allowed on %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ( unsigned int ) etherType , ( unsigned long long ) network - > id ( ) ) ;
return true ;
}
2015-04-06 14:50:53 -07:00
const unsigned int payloadLen = size ( ) - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
RR - > node - > putFrame ( network - > id ( ) , MAC ( peer - > address ( ) , network - > id ( ) ) , network - > mac ( ) , etherType , 0 , field ( ZT_PROTO_VERB_FRAME_IDX_PAYLOAD , payloadLen ) , payloadLen ) ;
2014-06-18 09:00:53 -07:00
}
2014-09-30 17:26:34 -07:00
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_FRAME , 0 , Packet : : VERB_NOP ) ;
2013-07-11 18:15:51 -04:00
} else {
2013-12-24 10:39:29 -08:00
TRACE ( " dropped FRAME from %s(%s): we are not connected to network %.16llx " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ) ;
2013-07-11 18:15:51 -04:00
}
} catch ( std : : exception & ex ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped FRAME from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 18:15:51 -04:00
} catch ( . . . ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped FRAME from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doEXT_FRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
2014-06-10 21:41:34 -07:00
try {
2015-04-06 14:50:53 -07:00
SharedPtr < Network > network ( RR - > node - > network ( at < uint64_t > ( ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID ) ) ) ;
2014-06-10 21:41:34 -07:00
if ( network ) {
2014-06-18 09:00:53 -07:00
if ( size ( ) > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) {
2015-04-06 14:50:53 -07:00
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS ] ;
2014-06-13 21:06:34 -07:00
2014-09-30 16:28:25 -07:00
unsigned int comLen = 0 ;
2015-07-07 08:54:48 -07:00
bool comFailed = false ;
2014-09-30 16:28:25 -07:00
if ( ( flags & 0x01 ) ! = 0 ) {
CertificateOfMembership com ;
comLen = com . deserialize ( * this , ZT_PROTO_VERB_EXT_FRAME_IDX_COM ) ;
2015-07-07 08:54:48 -07:00
if ( com . hasRequiredFields ( ) ) {
if ( ! network - > validateAndAddMembershipCertificate ( com ) )
comFailed = true ; // technically this check is redundant to isAllowed(), but do it anyway for thoroughness
}
2014-09-30 17:26:34 -07:00
}
2015-07-07 08:54:48 -07:00
if ( ( comFailed ) | | ( ! network - > isAllowed ( peer - > address ( ) ) ) ) {
2014-09-30 17:26:34 -07:00
TRACE ( " dropped EXT_FRAME from %s(%s): not a member of private network %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , network - > id ( ) ) ;
_sendErrorNeedCertificate ( RR , peer , network - > id ( ) ) ;
return true ;
2014-09-30 16:28:25 -07:00
}
// Everything after flags must be adjusted based on the length
// of the certificate, if there was one...
2015-04-06 14:50:53 -07:00
const unsigned int etherType = at < uint16_t > ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE ) ;
2014-06-18 09:00:53 -07:00
if ( ! network - > config ( ) - > permitsEtherType ( etherType ) ) {
TRACE ( " dropped EXT_FRAME from %s(%s): ethertype %.4x not allowed on network %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ( unsigned int ) etherType , ( unsigned long long ) network - > id ( ) ) ;
return true ;
}
2014-09-30 16:28:25 -07: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 ) ;
if ( to . isMulticast ( ) ) {
TRACE ( " dropped EXT_FRAME from %s@%s(%s) to %s: destination is multicast, must use MULTICAST_FRAME " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) ) ;
return true ;
}
2014-06-18 09:00:53 -07:00
2014-09-30 17:26:34 -07:00
if ( ( ! from ) | | ( from . isMulticast ( ) ) | | ( from = = network - > mac ( ) ) ) {
TRACE ( " dropped EXT_FRAME from %s@%s(%s) to %s: invalid source MAC " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) ) ;
2014-06-10 21:41:34 -07:00
return true ;
}
if ( from ! = MAC ( peer - > address ( ) , network - > id ( ) ) ) {
if ( network - > permitsBridging ( peer - > address ( ) ) ) {
network - > learnBridgeRoute ( from , peer - > address ( ) ) ;
} else {
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 ( ) , _remoteAddress . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , network - > id ( ) ) ;
return true ;
}
2015-07-06 12:34:35 -07:00
} else if ( to ! = network - > mac ( ) ) {
2014-09-24 13:53:03 -07:00
if ( ! network - > permitsBridging ( RR - > identity . address ( ) ) ) {
2014-06-10 21:41:34 -07: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 ( ) , _remoteAddress . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , network - > id ( ) ) ;
return true ;
}
}
2015-04-06 14:50:53 -07:00
const unsigned int payloadLen = size ( ) - ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) ;
RR - > node - > putFrame ( network - > id ( ) , from , to , etherType , 0 , field ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD , payloadLen ) , payloadLen ) ;
2014-06-12 11:40:30 -07:00
}
2014-09-30 17:26:34 -07:00
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP ) ;
2014-06-10 21:41:34 -07:00
} else {
TRACE ( " dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ) ;
}
} catch ( std : : exception & ex ) {
TRACE ( " dropped EXT_FRAME from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped EXT_FRAME from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doMULTICAST_LIKE ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-09-27 16:03:13 -04:00
{
try {
2015-04-06 14:50:53 -07:00
const uint64_t now = RR - > node - > now ( ) ;
2013-09-27 16:03:13 -04:00
// Iterate through 18-byte network,MAC,ADI tuples
2014-09-30 16:28:25 -07:00
for ( unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ; ptr < size ( ) ; ptr + = 18 )
2014-11-21 10:50:27 -08:00
RR - > mc - > add ( now , at < uint64_t > ( ptr ) , MulticastGroup ( MAC ( field ( ptr + 8 , 6 ) , 6 ) , at < uint32_t > ( ptr + 14 ) ) , peer - > address ( ) ) ;
2013-12-24 10:39:29 -08:00
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_LIKE , 0 , Packet : : VERB_NOP ) ;
2013-09-27 16:03:13 -04:00
} catch ( std : : exception & ex ) {
TRACE ( " dropped MULTICAST_LIKE from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped MULTICAST_LIKE from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
return true ;
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doNETWORK_MEMBERSHIP_CERTIFICATE ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-29 13:56:20 -04:00
{
2013-10-16 17:47:26 -04:00
try {
2013-10-17 06:41:52 -04:00
CertificateOfMembership com ;
2013-12-24 10:39:29 -08:00
2013-10-17 06:41:52 -04:00
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ;
while ( ptr < size ( ) ) {
ptr + = com . deserialize ( * this , ptr ) ;
2014-09-30 17:26:34 -07:00
if ( com . hasRequiredFields ( ) ) {
2015-04-06 14:50:53 -07:00
SharedPtr < Network > network ( RR - > node - > network ( com . networkId ( ) ) ) ;
2015-07-07 10:00:34 -07:00
if ( network )
network - > validateAndAddMembershipCertificate ( com ) ;
2013-10-16 17:47:26 -04:00
}
}
2013-12-24 10:39:29 -08:00
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_NETWORK_MEMBERSHIP_CERTIFICATE , 0 , Packet : : VERB_NOP ) ;
2013-10-16 17:47:26 -04:00
} catch ( std : : exception & ex ) {
TRACE ( " dropped NETWORK_MEMBERSHIP_CERTIFICATE from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped NETWORK_MEMBERSHIP_CERTIFICATE from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
2013-08-02 17:17:34 -04:00
return true ;
2013-07-29 13:56:20 -04:00
}
2014-09-24 13:53:03 -07:00
bool IncomingPacket : : _doNETWORK_CONFIG_REQUEST ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-29 13:56:20 -04:00
{
2013-08-02 17:17:34 -04:00
try {
2015-04-06 14:50:53 -07:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID ) ;
const unsigned int metaDataLength = at < uint16_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN ) ;
const Dictionary metaData ( ( const char * ) field ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT , metaDataLength ) , metaDataLength ) ;
2015-09-08 11:35:55 -07:00
//const uint64_t haveRevision = ((ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT + metaDataLength + 8) <= size()) ? at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT + metaDataLength) : 0ULL;
2015-02-24 12:28:58 -08:00
2015-04-01 19:09:18 -07:00
const unsigned int h = hops ( ) ;
2015-04-06 14:50:53 -07:00
const uint64_t pid = packetId ( ) ;
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , h , pid , Packet : : VERB_NETWORK_CONFIG_REQUEST , 0 , Packet : : VERB_NOP ) ;
2015-01-08 14:27:55 -08:00
2015-04-15 15:12:09 -07:00
if ( RR - > localNetworkController ) {
2015-02-24 12:28:58 -08:00
Dictionary netconf ;
2015-09-08 11:35:55 -07:00
switch ( RR - > localNetworkController - > doNetworkConfigRequest ( ( h > 0 ) ? InetAddress ( ) : _remoteAddress , RR - > identity , peer - > identity ( ) , nwid , metaData , netconf ) ) {
2015-07-23 09:50:10 -07:00
2015-04-15 15:12:09 -07:00
case NetworkController : : NETCONF_QUERY_OK : {
2015-04-06 14:50:53 -07:00
const std : : string netconfStr ( netconf . toString ( ) ) ;
2015-02-24 12:28:58 -08:00
if ( netconfStr . length ( ) > 0xffff ) { // sanity check since field ix 16-bit
2015-04-08 16:49:21 -07:00
TRACE ( " NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large " , ( unsigned int ) netconfStr . length ( ) ) ;
2015-02-24 12:28:58 -08:00
} else {
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
2015-04-01 19:09:18 -07:00
outp . append ( pid ) ;
2015-02-24 12:28:58 -08:00
outp . append ( nwid ) ;
outp . append ( ( uint16_t ) netconfStr . length ( ) ) ;
2015-04-24 15:05:28 -07:00
outp . append ( netconfStr . data ( ) , ( unsigned int ) netconfStr . length ( ) ) ;
2015-02-24 12:28:58 -08:00
outp . compress ( ) ;
2015-06-17 12:46:12 -07:00
outp . armor ( peer - > key ( ) , true ) ;
2015-02-24 12:28:58 -08:00
if ( outp . size ( ) > ZT_PROTO_MAX_PACKET_LENGTH ) {
2015-04-08 16:49:21 -07:00
TRACE ( " NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large " , ( unsigned int ) netconfStr . length ( ) ) ;
2015-02-24 12:28:58 -08:00
} else {
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2015-02-24 12:28:58 -08:00
}
}
} break ;
2015-07-23 09:50:10 -07:00
2015-04-15 15:12:09 -07:00
case NetworkController : : NETCONF_QUERY_OBJECT_NOT_FOUND : {
2015-02-24 12:28:58 -08:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
2015-04-01 19:09:18 -07:00
outp . append ( pid ) ;
2015-02-24 12:28:58 -08:00
outp . append ( ( unsigned char ) Packet : : ERROR_OBJ_NOT_FOUND ) ;
outp . append ( nwid ) ;
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2015-02-24 12:28:58 -08:00
} break ;
2015-07-23 09:50:10 -07:00
2015-04-15 15:12:09 -07:00
case NetworkController : : NETCONF_QUERY_ACCESS_DENIED : {
2015-02-24 12:28:58 -08:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
2015-04-01 19:09:18 -07:00
outp . append ( pid ) ;
2015-02-24 12:28:58 -08:00
outp . append ( ( unsigned char ) Packet : : ERROR_NETWORK_ACCESS_DENIED_ ) ;
outp . append ( nwid ) ;
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2015-02-24 12:28:58 -08:00
} break ;
2015-07-23 09:50:10 -07:00
2015-04-15 15:12:09 -07:00
case NetworkController : : NETCONF_QUERY_INTERNAL_SERVER_ERROR :
2015-04-08 16:49:21 -07:00
TRACE ( " NETWORK_CONFIG_REQUEST failed: internal error: %s " , netconf . get ( " error " , " (unknown) " ) . c_str ( ) ) ;
2015-02-24 12:28:58 -08:00
break ;
2015-07-23 09:50:10 -07:00
2015-07-23 10:10:17 -07:00
case NetworkController : : NETCONF_QUERY_IGNORE :
break ;
2015-02-24 12:28:58 -08:00
default :
2015-04-15 15:12:09 -07:00
TRACE ( " NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest() " ) ;
2015-02-24 12:28:58 -08:00
break ;
2015-07-23 09:50:10 -07:00
2015-02-24 12:28:58 -08:00
}
2015-01-08 14:27:55 -08:00
} else {
2015-02-24 12:28:58 -08:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2015-01-08 14:27:55 -08:00
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
2015-04-01 19:09:18 -07:00
outp . append ( pid ) ;
2015-01-08 14:27:55 -08:00
outp . append ( ( unsigned char ) Packet : : ERROR_UNSUPPORTED_OPERATION ) ;
outp . append ( nwid ) ;
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2015-01-08 14:27:55 -08:00
}
2013-08-02 17:17:34 -04:00
} catch ( std : : exception & exc ) {
TRACE ( " dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , exc . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
return true ;
2013-07-29 13:56:20 -04:00
}
2015-01-05 17:47:59 -08:00
bool IncomingPacket : : _doNETWORK_CONFIG_REFRESH ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
try {
2015-01-08 14:27:55 -08:00
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ;
while ( ( ptr + 8 ) < = size ( ) ) {
uint64_t nwid = at < uint64_t > ( ptr ) ;
2015-04-06 14:50:53 -07:00
SharedPtr < Network > nw ( RR - > node - > network ( nwid ) ) ;
if ( ( nw ) & & ( peer - > address ( ) = = nw - > controller ( ) ) )
2015-01-08 14:27:55 -08:00
nw - > requestConfiguration ( ) ;
ptr + = 8 ;
}
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_NETWORK_CONFIG_REFRESH , 0 , Packet : : VERB_NOP ) ;
2015-01-05 17:47:59 -08:00
} catch ( std : : exception & exc ) {
TRACE ( " dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , exc . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
return true ;
}
2014-09-26 14:18:25 -07:00
bool IncomingPacket : : _doMULTICAST_GATHER ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2014-09-30 16:28:25 -07:00
try {
2015-04-06 14:50:53 -07:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID ) ;
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 16:28:25 -07:00
2014-10-09 17:58:31 -07:00
//TRACE("<<MC %s(%s) GATHER up to %u in %.16llx/%s",source().toString().c_str(),_remoteAddress.toString().c_str(),gatherLimit,nwid,mg.toString().c_str());
2014-09-30 16:28:25 -07:00
if ( gatherLimit ) {
2014-10-09 17:58:31 -07:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2014-09-30 16:28:25 -07:00
outp . append ( ( unsigned char ) Packet : : VERB_MULTICAST_GATHER ) ;
outp . append ( packetId ( ) ) ;
outp . append ( nwid ) ;
mg . mac ( ) . appendTo ( outp ) ;
outp . append ( ( uint32_t ) mg . adi ( ) ) ;
2014-10-05 10:34:25 -07:00
if ( RR - > mc - > gather ( peer - > address ( ) , nwid , mg , outp , gatherLimit ) ) {
2014-09-30 16:28:25 -07:00
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2014-09-30 16:28:25 -07:00
}
}
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_GATHER , 0 , Packet : : VERB_NOP ) ;
2014-09-30 16:28:25 -07:00
} catch ( std : : exception & exc ) {
TRACE ( " dropped MULTICAST_GATHER from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , exc . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped MULTICAST_GATHER from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
return true ;
2014-09-26 14:18:25 -07:00
}
bool IncomingPacket : : _doMULTICAST_FRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2014-09-30 16:28:25 -07:00
try {
2015-04-06 14:50:53 -07:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID ) ;
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS ] ;
2014-09-30 16:28:25 -07:00
2015-04-06 14:50:53 -07:00
const SharedPtr < Network > network ( RR - > node - > network ( nwid ) ) ;
2014-10-09 12:42:25 -07:00
if ( network ) {
// Offset -- size of optional fields added to position of later fields
unsigned int offset = 0 ;
2014-09-30 16:28:25 -07:00
2014-10-09 12:42:25 -07:00
if ( ( flags & 0x01 ) ! = 0 ) {
CertificateOfMembership com ;
offset + = com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM ) ;
if ( com . hasRequiredFields ( ) )
2015-07-07 08:14:41 -07:00
network - > validateAndAddMembershipCertificate ( com ) ;
2014-10-09 12:42:25 -07:00
}
2014-09-30 16:28:25 -07:00
2014-10-09 12:42:25 -07:00
// Check membership after we've read any included COM, since
// that cert might be what we needed.
if ( ! network - > isAllowed ( peer - > address ( ) ) ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): not a member of private network %.16llx " , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ( unsigned long long ) network - > id ( ) ) ;
_sendErrorNeedCertificate ( RR , peer , network - > id ( ) ) ;
return true ;
}
2014-09-30 16:28:25 -07:00
2014-10-09 12:42:25 -07:00
unsigned int gatherLimit = 0 ;
if ( ( flags & 0x02 ) ! = 0 ) {
gatherLimit = at < uint32_t > ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT ) ;
offset + = 4 ;
}
2014-09-30 16:28:25 -07:00
2014-10-09 12:42:25 -07: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-09 17:58:31 -07:00
from . fromAddress ( peer - > address ( ) , nwid ) ;
2014-10-09 12:42:25 -07:00
}
2014-09-30 16:28:25 -07:00
2015-04-06 14:50:53 -07:00
const MulticastGroup to ( MAC ( field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC , 6 ) , 6 ) , at < uint32_t > ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI ) ) ;
const unsigned int etherType = at < uint16_t > ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE ) ;
const unsigned int payloadLen = size ( ) - ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME ) ;
2014-10-01 16:29:52 -07:00
2014-10-09 17:58:31 -07: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,payloadLen);
2014-10-10 09:09:56 -07:00
if ( ( payloadLen > 0 ) & & ( payloadLen < = ZT_IF_MTU ) ) {
2014-10-09 12:42:25 -07:00
if ( ! to . mac ( ) . isMulticast ( ) ) {
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 ( ) , _remoteAddress . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) ) ;
return true ;
}
if ( ( ! from ) | | ( from . isMulticast ( ) ) | | ( from = = network - > mac ( ) ) ) {
TRACE ( " dropped MULTICAST_FRAME from %s@%s(%s) to %s: invalid source MAC " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) ) ;
return true ;
2014-10-01 16:29:52 -07:00
}
2014-09-30 17:26:34 -07:00
2014-10-09 12:42:25 -07:00
if ( from ! = MAC ( peer - > address ( ) , network - > id ( ) ) ) {
if ( network - > permitsBridging ( peer - > address ( ) ) ) {
network - > learnBridgeRoute ( from , peer - > address ( ) ) ;
} else {
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 ( ) , _remoteAddress . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , network - > id ( ) ) ;
return true ;
2014-09-30 17:33:20 -07:00
}
2014-09-30 17:26:34 -07:00
}
2014-10-09 12:42:25 -07:00
2015-04-06 14:50:53 -07:00
RR - > node - > putFrame ( network - > id ( ) , from , to . mac ( ) , etherType , 0 , field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME , payloadLen ) , payloadLen ) ;
2014-09-30 16:28:25 -07:00
}
2014-10-09 12:42:25 -07: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 ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2014-10-09 12:42:25 -07:00
}
}
} // else ignore -- not a member of this network
2014-09-30 16:28:25 -07:00
2015-09-23 13:49:56 -07:00
peer - > received ( RR , _localInterfaceId , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP ) ;
2014-09-30 16:28:25 -07:00
} catch ( std : : exception & exc ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , exc . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
return true ;
2014-09-26 14:18:25 -07:00
}
2015-07-06 15:05:04 -07:00
bool IncomingPacket : : _doPUSH_DIRECT_PATHS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2015-07-06 15:28:48 -07:00
try {
unsigned int count = at < uint16_t > ( ZT_PACKET_IDX_PAYLOAD ) ;
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2 ;
2015-07-13 09:29:51 -07:00
while ( count - - ) { // if ptr overflows Buffer will throw
2015-07-07 08:54:48 -07:00
// TODO: properly handle blacklisting, support other features... see Packet.hpp.
2015-07-06 15:28:48 -07: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 09:29:51 -07:00
2015-07-06 15:28:48 -07:00
switch ( addrType ) {
case 4 : {
InetAddress a ( field ( ptr , 4 ) , 4 , at < uint16_t > ( ptr + 4 ) ) ;
2015-07-13 09:29:51 -07:00
if ( ( ( flags & ( 0x01 | 0x02 ) ) = = 0 ) & & ( Path : : isAddressValidForPath ( a ) ) ) {
TRACE ( " attempting to contact %s at pushed direct path %s " , peer - > address ( ) . toString ( ) . c_str ( ) , a . toString ( ) . c_str ( ) ) ;
2015-09-23 13:49:56 -07:00
peer - > attemptToContactAt ( RR , _localInterfaceId , a , RR - > node - > now ( ) ) ;
2015-07-13 09:29:51 -07:00
}
2015-07-06 15:28:48 -07:00
} break ;
case 6 : {
InetAddress a ( field ( ptr , 16 ) , 16 , at < uint16_t > ( ptr + 16 ) ) ;
2015-07-13 09:29:51 -07:00
if ( ( ( flags & ( 0x01 | 0x02 ) ) = = 0 ) & & ( Path : : isAddressValidForPath ( a ) ) ) {
TRACE ( " attempting to contact %s at pushed direct path %s " , peer - > address ( ) . toString ( ) . c_str ( ) , a . toString ( ) . c_str ( ) ) ;
2015-09-23 13:49:56 -07:00
peer - > attemptToContactAt ( RR , _localInterfaceId , a , RR - > node - > now ( ) ) ;
2015-07-13 09:29:51 -07:00
}
2015-07-06 15:28:48 -07:00
} break ;
}
ptr + = addrLen ;
}
} catch ( std : : exception & exc ) {
TRACE ( " dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , exc . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
2015-07-06 15:05:04 -07:00
return true ;
}
2014-09-24 13:53:03 -07:00
void IncomingPacket : : _sendErrorNeedCertificate ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer , uint64_t nwid )
2014-06-18 09:00:53 -07:00
{
2014-09-24 13:53:03 -07:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2014-06-18 09:00:53 -07:00
outp . append ( ( unsigned char ) verb ( ) ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_NEED_MEMBERSHIP_CERTIFICATE ) ;
outp . append ( nwid ) ;
outp . armor ( peer - > key ( ) , true ) ;
2015-09-23 13:49:56 -07:00
RR - > node - > putPacket ( _localInterfaceId , _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2014-06-18 09:00:53 -07:00
}
2013-07-11 16:19:06 -04:00
} // namespace ZeroTier