2013-07-11 16:19:06 -04:00
/*
* ZeroTier One - Global Peer to Peer Ethernet
* Copyright ( C ) 2012 - 2013 ZeroTier Networks LLC
*
* 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-09-13 15:47:00 -04:00
# include "../version.h"
2013-08-02 17:17:34 -04:00
# include "Constants.hpp"
2013-07-11 16:19:06 -04:00
# include "RuntimeEnvironment.hpp"
# include "Topology.hpp"
# include "PacketDecoder.hpp"
# include "Switch.hpp"
2013-07-11 17:52:04 -04:00
# include "Peer.hpp"
2013-07-11 22:06:25 -04:00
# include "NodeConfig.hpp"
# include "Filter.hpp"
2013-08-02 17:17:34 -04:00
# include "Service.hpp"
2013-07-11 16:19:06 -04:00
namespace ZeroTier {
bool PacketDecoder : : tryDecode ( const RuntimeEnvironment * _r )
throw ( std : : out_of_range , std : : runtime_error )
{
2013-07-11 17:52:04 -04:00
if ( ( ! encrypted ( ) ) & & ( verb ( ) = = Packet : : VERB_HELLO ) ) {
// Unencrypted HELLOs are handled here since they are used to
2013-09-25 10:55:27 -04:00
// populate our identity cache in the first place. _doHELLO() is special
// in that it contains its own authentication logic.
2013-07-11 22:06:25 -04:00
TRACE ( " HELLO from %s(%s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
return _doHELLO ( _r ) ;
}
2013-07-11 22:06:25 -04:00
SharedPtr < Peer > peer = _r - > topology - > getPeer ( source ( ) ) ;
2013-07-11 17:52:04 -04:00
if ( peer ) {
2013-09-25 10:55:27 -04:00
// Resume saved intermediate decode state?
2013-08-05 12:16:25 -04:00
if ( _step = = DECODE_WAITING_FOR_MULTICAST_FRAME_ORIGINAL_SENDER_LOOKUP ) {
// In this state we have already authenticated and decrypted the
// packet and are waiting for the lookup of the original sender
// for a multicast frame. So check to see if we've got it.
2013-07-11 22:06:25 -04:00
return _doMULTICAST_FRAME ( _r , peer ) ;
}
2013-09-25 10:55:27 -04:00
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 17:52:04 -04:00
return true ;
}
2013-07-11 18:15:51 -04:00
if ( ! uncompress ( ) ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped packet from %s(%s), compressed data invalid " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 17:52:04 -04:00
return true ;
}
2013-07-11 22:06:25 -04:00
Packet : : Verb v = verb ( ) ;
2013-08-05 12:16:25 -04:00
// Once a packet is determined to be basically valid, it can be used
// to passively learn a new network path to the sending peer. It
// also results in statistics updates.
2013-07-11 22:06:25 -04:00
peer - > onReceive ( _r , _localPort , _remoteAddress , hops ( ) , v , Utils : : now ( ) ) ;
2013-07-11 18:15:51 -04:00
2013-07-11 22:06:25 -04:00
switch ( v ) {
2013-07-11 17:52:04 -04:00
case Packet : : VERB_NOP :
2013-07-11 22:06:25 -04:00
TRACE ( " NOP from %s(%s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
return true ;
2013-07-11 17:52:04 -04:00
case Packet : : VERB_HELLO :
2013-09-25 10:55:27 -04:00
return _doHELLO ( _r ) ; // legal, but why? :)
2013-07-11 17:52:04 -04:00
case Packet : : VERB_ERROR :
2013-07-11 22:06:25 -04:00
return _doERROR ( _r , peer ) ;
2013-07-11 17:52:04 -04:00
case Packet : : VERB_OK :
2013-07-11 22:06:25 -04:00
return _doOK ( _r , peer ) ;
2013-07-11 17:52:04 -04:00
case Packet : : VERB_WHOIS :
2013-07-11 22:06:25 -04:00
return _doWHOIS ( _r , peer ) ;
2013-07-11 17:52:04 -04:00
case Packet : : VERB_RENDEZVOUS :
2013-07-11 22:06:25 -04:00
return _doRENDEZVOUS ( _r , peer ) ;
2013-07-11 17:52:04 -04:00
case Packet : : VERB_FRAME :
2013-07-11 22:06:25 -04:00
return _doFRAME ( _r , peer ) ;
2013-07-11 17:52:04 -04:00
case Packet : : VERB_MULTICAST_LIKE :
2013-07-11 22:06:25 -04:00
return _doMULTICAST_LIKE ( _r , peer ) ;
2013-09-25 10:55:27 -04:00
case Packet : : VERB_MULTICAST_GOT :
return _doMULTICAST_GOT ( _r , peer ) ;
2013-07-11 17:52:04 -04:00
case Packet : : VERB_MULTICAST_FRAME :
2013-07-11 22:06:25 -04:00
return _doMULTICAST_FRAME ( _r , peer ) ;
2013-07-29 16:18:29 -04:00
case Packet : : VERB_NETWORK_MEMBERSHIP_CERTIFICATE :
return _doNETWORK_MEMBERSHIP_CERTIFICATE ( _r , peer ) ;
2013-07-29 13:56:20 -04:00
case Packet : : VERB_NETWORK_CONFIG_REQUEST :
return _doNETWORK_CONFIG_REQUEST ( _r , peer ) ;
case Packet : : VERB_NETWORK_CONFIG_REFRESH :
return _doNETWORK_CONFIG_REFRESH ( _r , peer ) ;
2013-07-11 17:52:04 -04:00
default :
// This might be something from a new or old version of the protocol.
2013-09-16 13:02:10 -04:00
// Technically it passed MAC so the packet is still valid, but we
2013-07-11 17:52:04 -04:00
// ignore it.
2013-07-11 22:06:25 -04:00
TRACE ( " ignored unrecognized verb %.2x from %s(%s) " , ( unsigned int ) v , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
return true ;
2013-07-11 17:52:04 -04:00
}
} else {
2013-08-05 12:16:25 -04:00
_step = DECODE_WAITING_FOR_SENDER_LOOKUP ; // should already be this...
2013-07-11 22:06:25 -04:00
_r - > sw - > requestWhois ( source ( ) ) ;
2013-07-11 17:52:04 -04:00
return false ;
}
2013-07-11 18:15:51 -04:00
}
2013-07-11 17:52:04 -04:00
2013-07-11 22:06:25 -04:00
void PacketDecoder : : _CBaddPeerFromHello ( void * arg , const SharedPtr < Peer > & p , Topology : : PeerVerifyResult result )
{
_CBaddPeerFromHello_Data * req = ( _CBaddPeerFromHello_Data * ) arg ;
const RuntimeEnvironment * _r = req - > renv ;
2013-08-06 10:39:20 -04:00
try {
switch ( result ) {
case Topology : : PEER_VERIFY_ACCEPTED_NEW :
case Topology : : PEER_VERIFY_ACCEPTED_ALREADY_HAVE :
case Topology : : PEER_VERIFY_ACCEPTED_DISPLACED_INVALID_ADDRESS : {
_r - > sw - > doAnythingWaitingForPeer ( p ) ;
Packet outp ( req - > source , _r - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
outp . append ( req - > helloPacketId ) ;
outp . append ( req - > helloTimestamp ) ;
2013-09-13 13:35:31 -04: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 ) ;
2013-08-06 10:39:20 -04:00
outp . encrypt ( p - > cryptKey ( ) ) ;
2013-09-16 13:02:10 -04:00
outp . macSet ( p - > macKey ( ) ) ;
2013-08-06 10:39:20 -04:00
_r - > demarc - > send ( req - > localPort , req - > remoteAddress , outp . data ( ) , outp . size ( ) , - 1 ) ;
} break ;
2013-07-11 22:06:25 -04:00
2013-08-06 10:39:20 -04:00
case Topology : : PEER_VERIFY_REJECTED_INVALID_IDENTITY : {
Packet outp ( req - > source , _r - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
outp . append ( req - > helloPacketId ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_IDENTITY_INVALID ) ;
outp . encrypt ( p - > cryptKey ( ) ) ;
2013-09-16 13:02:10 -04:00
outp . macSet ( p - > macKey ( ) ) ;
2013-08-06 10:39:20 -04:00
_r - > demarc - > send ( req - > localPort , req - > remoteAddress , outp . data ( ) , outp . size ( ) , - 1 ) ;
} break ;
2013-07-11 22:06:25 -04:00
2013-08-06 10:39:20 -04:00
case Topology : : PEER_VERIFY_REJECTED_DUPLICATE :
case Topology : : PEER_VERIFY_REJECTED_DUPLICATE_TRIAGED : {
Packet outp ( req - > source , _r - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
outp . append ( req - > helloPacketId ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_IDENTITY_COLLISION ) ;
outp . encrypt ( p - > cryptKey ( ) ) ;
2013-09-16 13:02:10 -04:00
outp . macSet ( p - > macKey ( ) ) ;
2013-08-06 10:39:20 -04:00
_r - > demarc - > send ( req - > localPort , req - > remoteAddress , outp . data ( ) , outp . size ( ) , - 1 ) ;
} break ;
}
} catch ( . . . ) {
TRACE ( " unexpected exception in addPeer() result callback for peer received via HELLO " ) ;
2013-07-11 22:06:25 -04:00
}
delete req ;
}
void PacketDecoder : : _CBaddPeerFromWhois ( void * arg , const SharedPtr < Peer > & p , Topology : : PeerVerifyResult result )
{
2013-08-06 10:39:20 -04:00
const RuntimeEnvironment * _r = ( const RuntimeEnvironment * ) arg ;
try {
switch ( result ) {
case Topology : : PEER_VERIFY_ACCEPTED_NEW :
case Topology : : PEER_VERIFY_ACCEPTED_ALREADY_HAVE :
case Topology : : PEER_VERIFY_ACCEPTED_DISPLACED_INVALID_ADDRESS :
_r - > sw - > doAnythingWaitingForPeer ( p ) ;
break ;
default :
break ;
}
} catch ( . . . ) {
TRACE ( " unexpected exception in addPeer() result callback for peer received via OK(WHOIS) " ) ;
2013-07-11 22:06:25 -04:00
}
}
bool PacketDecoder : : _doERROR ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
# ifdef ZT_TRACE
2013-07-11 22:06:25 -04:00
Packet : : Verb inReVerb = ( Packet : : Verb ) ( * this ) [ ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB ] ;
Packet : : ErrorCode errorCode = ( Packet : : ErrorCode ) ( * this ) [ ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE ] ;
TRACE ( " ERROR %s from %s(%s) in-re %s " , Packet : : errorString ( errorCode ) , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , Packet : : verbString ( inReVerb ) ) ;
2013-07-11 18:15:51 -04:00
# endif
// TODO (sorta):
// The fact is that the protocol works fine without error handling.
// The only error that really needs to be handled here is duplicate
// identity collision, which if it comes from a supernode should cause
// us to restart and regenerate a new identity.
} 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
}
2013-07-11 18:15:51 -04:00
bool PacketDecoder : : _doHELLO ( const RuntimeEnvironment * _r )
2013-07-11 17:52:04 -04:00
{
try {
2013-07-11 22:06:25 -04:00
//unsigned int protoVersion = (*this)[ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION];
unsigned int vMajor = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION ] ;
unsigned int vMinor = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION ] ;
unsigned int vRevision = at < uint16_t > ( ZT_PROTO_VERB_HELLO_IDX_REVISION ) ;
uint64_t timestamp = at < uint64_t > ( ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP ) ;
Identity id ( * this , ZT_PROTO_VERB_HELLO_IDX_IDENTITY ) ;
2013-07-11 17:52:04 -04:00
2013-08-23 10:54:45 -04:00
// Initial sniff test for valid addressing and that this is indeed the
// submitter's identity.
2013-08-05 12:16:25 -04:00
if ( ( id . address ( ) . isReserved ( ) ) | | ( id . address ( ) ! = source ( ) ) ) {
# ifdef ZT_TRACE
if ( id . address ( ) . isReserved ( ) ) {
2013-08-23 10:54:45 -04:00
TRACE ( " dropped HELLO from %s(%s): identity has reserved address " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-08-05 12:16:25 -04:00
} else {
2013-08-23 10:54:45 -04:00
TRACE ( " dropped HELLO from %s(%s): identity is not for sender of packet (HELLO is a self-announcement) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-08-05 12:16:25 -04:00
}
# endif
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 17:52:04 -04:00
}
// Is this a HELLO for a peer we already know? If so just update its
// packet receive stats and send an OK.
SharedPtr < Peer > existingPeer ( _r - > topology - > getPeer ( id . address ( ) ) ) ;
if ( ( existingPeer ) & & ( existingPeer - > identity ( ) = = id ) ) {
2013-07-11 22:06:25 -04:00
existingPeer - > onReceive ( _r , _localPort , _remoteAddress , hops ( ) , Packet : : VERB_HELLO , Utils : : now ( ) ) ;
existingPeer - > setRemoteVersion ( vMajor , vMinor , vRevision ) ;
2013-07-11 17:52:04 -04:00
2013-07-11 22:06:25 -04:00
Packet outp ( source ( ) , _r - > identity . address ( ) , Packet : : VERB_OK ) ;
2013-07-11 17:52:04 -04:00
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
2013-07-11 22:06:25 -04:00
outp . append ( packetId ( ) ) ;
2013-07-11 17:52:04 -04:00
outp . append ( timestamp ) ;
outp . encrypt ( existingPeer - > cryptKey ( ) ) ;
2013-09-16 13:02:10 -04:00
outp . macSet ( existingPeer - > macKey ( ) ) ;
2013-07-11 22:06:25 -04:00
_r - > demarc - > send ( _localPort , _remoteAddress , outp . data ( ) , outp . size ( ) , - 1 ) ;
return true ;
2013-07-11 17:52:04 -04:00
}
2013-08-23 10:54:45 -04:00
SharedPtr < Peer > candidate ( new Peer ( _r - > identity , id ) ) ;
candidate - > setPathAddress ( _remoteAddress , false ) ;
2013-09-13 14:41:20 -04:00
candidate - > setRemoteVersion ( vMajor , vMinor , vRevision ) ;
2013-08-23 10:54:45 -04:00
2013-07-11 17:52:04 -04:00
_CBaddPeerFromHello_Data * arg = new _CBaddPeerFromHello_Data ;
2013-07-11 22:06:25 -04:00
arg - > renv = _r ;
arg - > source = source ( ) ;
arg - > remoteAddress = _remoteAddress ;
arg - > localPort = _localPort ;
2013-07-11 17:52:04 -04:00
arg - > vMajor = vMajor ;
arg - > vMinor = vMinor ;
arg - > vRevision = vRevision ;
2013-07-11 22:06:25 -04:00
arg - > helloPacketId = packetId ( ) ;
2013-07-11 17:52:04 -04:00
arg - > helloTimestamp = timestamp ;
2013-07-11 22:06:25 -04:00
_r - > topology - > addPeer ( candidate , & PacketDecoder : : _CBaddPeerFromHello , arg ) ;
2013-07-11 17:52:04 -04:00
} catch ( std : : exception & ex ) {
2013-07-11 22:06:25 -04: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 ( . . . ) {
2013-07-11 22:06:25 -04: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-09-13 14:41:20 -04:00
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2013-07-11 22:06:25 -04:00
bool PacketDecoder : : _doOK ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
2013-07-11 22:06:25 -04:00
Packet : : Verb inReVerb = ( Packet : : Verb ) ( * this ) [ ZT_PROTO_VERB_OK_IDX_IN_RE_VERB ] ;
2013-07-11 18:15:51 -04:00
switch ( inReVerb ) {
2013-07-11 22:06:25 -04:00
case Packet : : VERB_HELLO : {
2013-07-11 18:15:51 -04:00
// OK from HELLO permits computation of latency.
2013-07-11 22:06:25 -04:00
unsigned int latency = std : : min ( ( unsigned int ) ( Utils : : now ( ) - at < uint64_t > ( ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP ) ) , ( unsigned int ) 0xffff ) ;
TRACE ( " %s(%s): OK(HELLO), latency: %u " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , latency ) ;
peer - > setLatency ( _remoteAddress , latency ) ;
} break ;
2013-08-05 12:16:25 -04:00
case Packet : : VERB_WHOIS : {
2013-07-11 22:06:25 -04:00
TRACE ( " %s(%s): OK(%s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , Packet : : verbString ( inReVerb ) ) ;
2013-08-05 12:16:25 -04:00
if ( _r - > topology - > isSupernode ( source ( ) ) ) {
// Right now, only supernodes are queried for WHOIS so we only
// accept OK(WHOIS) from supernodes. Otherwise peers could
2013-08-23 10:54:45 -04:00
// potentially cache-poison.
2013-07-11 22:06:25 -04:00
_r - > topology - > addPeer ( SharedPtr < Peer > ( new Peer ( _r - > identity , Identity ( * this , ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY ) ) ) , & PacketDecoder : : _CBaddPeerFromWhois , const_cast < void * > ( ( const void * ) _r ) ) ;
2013-08-05 12:16:25 -04:00
}
} break ;
2013-08-03 12:53:46 -04:00
case Packet : : VERB_NETWORK_CONFIG_REQUEST : {
SharedPtr < Network > nw ( _r - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID ) ) ) ;
if ( ( nw ) & & ( nw - > controller ( ) = = source ( ) ) ) {
2013-08-23 10:54:45 -04:00
// OK(NETWORK_CONFIG_REQUEST) is only accepted from a network's
// controller.
2013-08-03 12:53:46 -04:00
unsigned int dictlen = at < uint16_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN ) ;
std : : string dict ( ( const char * ) field ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT , dictlen ) , dictlen ) ;
if ( dict . length ( ) ) {
Network : : Config netconf ( 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-09-04 09:27:56 -04:00
nw - > setConfiguration ( netconf ) ;
2013-08-03 12:53:46 -04:00
}
}
} break ;
2013-07-11 18:15:51 -04:00
default :
2013-07-12 22:07:48 -04:00
//TRACE("%s(%s): OK(%s)",source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb));
2013-07-11 18:15:51 -04:00
break ;
}
} 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
}
2013-07-11 22:06:25 -04:00
bool PacketDecoder : : _doWHOIS ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
2013-07-11 22:06:25 -04:00
if ( payloadLength ( ) = = ZT_ADDRESS_LENGTH ) {
2013-07-29 16:18:29 -04:00
SharedPtr < Peer > p ( _r - > topology - > getPeer ( Address ( payload ( ) , ZT_ADDRESS_LENGTH ) ) ) ;
2013-07-11 18:15:51 -04:00
if ( p ) {
2013-07-11 22:06:25 -04:00
Packet outp ( source ( ) , _r - > identity . address ( ) , Packet : : VERB_OK ) ;
2013-07-11 18:15:51 -04:00
outp . append ( ( unsigned char ) Packet : : VERB_WHOIS ) ;
2013-07-11 22:06:25 -04:00
outp . append ( packetId ( ) ) ;
2013-07-11 18:15:51 -04:00
p - > identity ( ) . serialize ( outp , false ) ;
outp . encrypt ( peer - > cryptKey ( ) ) ;
2013-09-16 13:02:10 -04:00
outp . macSet ( peer - > macKey ( ) ) ;
2013-07-11 22:06:25 -04:00
_r - > demarc - > send ( _localPort , _remoteAddress , outp . data ( ) , outp . size ( ) , - 1 ) ;
2013-07-29 16:18:29 -04:00
TRACE ( " sent WHOIS response to %s for %s " , source ( ) . toString ( ) . c_str ( ) , Address ( payload ( ) , ZT_ADDRESS_LENGTH ) . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
} else {
2013-07-11 22:06:25 -04:00
Packet outp ( source ( ) , _r - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2013-07-11 18:15:51 -04:00
outp . append ( ( unsigned char ) Packet : : VERB_WHOIS ) ;
2013-07-11 22:06:25 -04:00
outp . append ( packetId ( ) ) ;
2013-08-12 21:25:36 -04:00
outp . append ( ( unsigned char ) Packet : : ERROR_OBJ_NOT_FOUND ) ;
2013-07-11 22:06:25 -04:00
outp . append ( payload ( ) , ZT_ADDRESS_LENGTH ) ;
2013-07-11 18:15:51 -04:00
outp . encrypt ( peer - > cryptKey ( ) ) ;
2013-09-16 13:02:10 -04:00
outp . macSet ( peer - > macKey ( ) ) ;
2013-07-11 22:06:25 -04:00
_r - > demarc - > send ( _localPort , _remoteAddress , outp . data ( ) , outp . size ( ) , - 1 ) ;
2013-07-29 16:18:29 -04:00
TRACE ( " sent WHOIS ERROR to %s for %s (not found) " , source ( ) . toString ( ) . c_str ( ) , Address ( payload ( ) , ZT_ADDRESS_LENGTH ) . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
} else {
2013-07-11 22:06:25 -04: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
}
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 18:15:51 -04:00
}
2013-07-11 22:06:25 -04:00
bool PacketDecoder : : _doRENDEZVOUS ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
2013-08-06 10:39:20 -04:00
/*
* At the moment , we only obey RENDEZVOUS if it comes from a designated
* supernode . If relay offloading is implemented to scale the net , this
* will need reconsideration .
*
* The reason is that RENDEZVOUS could technically be used to cause a
* peer to send a weird encrypted UDP packet to an arbitrary IP : port .
* The sender of RENDEZVOUS has no control over the content of this
* packet , but it ' s still maybe something we want to not allow just
* anyone to order due to possible DDOS or network forensic implications .
* So if we diversify relays , we ' ll need some way of deciding whether the
2013-08-23 10:54:45 -04:00
* sender is someone we should trust with a RENDEZVOUS hint .
2013-08-06 10:39:20 -04:00
*/
2013-08-05 12:16:25 -04:00
if ( _r - > topology - > isSupernode ( source ( ) ) ) {
Address with ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
SharedPtr < Peer > withPeer ( _r - > topology - > getPeer ( with ) ) ;
if ( withPeer ) {
unsigned int port = at < uint16_t > ( ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT ) ;
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 " , source ( ) . toString ( ) . c_str ( ) , with . toString ( ) . c_str ( ) , atAddr . toString ( ) . c_str ( ) ) ;
_r - > sw - > contact ( withPeer , atAddr ) ;
} else {
TRACE ( " dropped corrupt RENDEZVOUS from %s(%s) (bad address or port) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
2013-07-11 18:15:51 -04:00
} else {
2013-08-05 12:16:25 -04:00
TRACE ( " ignored RENDEZVOUS from %s(%s) to meet unknown peer %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , with . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
} else {
2013-08-05 12:16:25 -04:00
TRACE ( " ignored RENDEZVOUS from %s(%s): source not supernode " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
} catch ( std : : exception & ex ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped RENDEZVOUS from %s(%s): %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 RENDEZVOUS 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
}
2013-07-11 22:06:25 -04:00
bool PacketDecoder : : _doFRAME ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
2013-07-11 22:06:25 -04:00
SharedPtr < Network > network ( _r - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ) ) ;
2013-07-11 18:15:51 -04:00
if ( network ) {
2013-07-11 22:06:25 -04:00
if ( network - > isAllowed ( source ( ) ) ) {
unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE ) ;
2013-08-28 16:01:27 -04:00
if ( network - > permitsEtherType ( etherType ) ) {
2013-07-11 22:06:25 -04:00
network - > tap ( ) . put ( source ( ) . toMAC ( ) , network - > tap ( ) . mac ( ) , etherType , data ( ) + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD , size ( ) - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ) ;
2013-08-28 16:01:27 -04:00
} else if ( size ( ) > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ) {
TRACE ( " dropped FRAME from %s: ethernet type %u not allowed on network %.16llx " , source ( ) . toString ( ) . c_str ( ) , etherType , ( unsigned long long ) network - > id ( ) ) ;
2013-07-11 18:15:51 -04:00
}
} else {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped FRAME from %s(%s): not a member of closed network %llu " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , network - > id ( ) ) ;
2013-07-11 18:15:51 -04:00
}
} else {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped FRAME from %s(%s): network %llu unknown " , 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
}
2013-07-11 22:06:25 -04:00
bool PacketDecoder : : _doMULTICAST_LIKE ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
2013-07-11 18:15:51 -04:00
{
try {
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ;
2013-09-25 17:41:49 -04:00
if ( ptr > = size ( ) )
return true ;
2013-07-11 22:06:25 -04:00
uint64_t now = Utils : : now ( ) ;
2013-09-25 17:41:49 -04:00
Address src ( source ( ) ) ;
2013-07-11 18:15:51 -04:00
2013-09-25 17:41:49 -04:00
// Iterate through 18-byte network,MAC,ADI tuples
for ( ; ; ) {
_r - > mc - > likesGroup ( at < uint64_t > ( ptr ) , src , MulticastGroup ( MAC ( field ( ptr + 8 , 6 ) ) , at < uint32_t > ( ptr + 14 ) ) , now ) ;
if ( ( ptr + = 18 ) > = size ( ) )
break ;
2013-07-11 18:15:51 -04:00
}
} catch ( std : : exception & ex ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped MULTICAST_LIKE 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 MULTICAST_LIKE from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 18:15:51 -04:00
}
2013-09-25 10:55:27 -04:00
return true ;
}
bool PacketDecoder : : _doMULTICAST_GOT ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
{
// Right now only supernodes act as propagation hubs
if ( ! _r - > topology - > amSupernode ( ) ) {
TRACE ( " dropped MULTICAST_GOT from %s: I am not a supernode " , source ( ) . toString ( ) . c_str ( ) ) ;
return true ;
}
try {
2013-09-25 17:41:49 -04:00
_r - > mc - > got ( at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GOT_IDX_NETWORK_ID ) , source ( ) , at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GOT_IDX_MULTICAST_GUID ) ) ;
2013-09-25 10:55:27 -04:00
} catch ( std : : exception & ex ) {
TRACE ( " dropped MULTICAST_GOT from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped MULTICAST_GOT 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
}
2013-09-25 17:41:49 -04:00
// Function object used in _doMULTICAST_FRAME
struct _doMULTICAST_FRAME_fillQueueWithNextHops
2013-07-11 18:15:51 -04:00
{
2013-09-25 17:41:49 -04:00
_doMULTICAST_FRAME_fillQueueWithNextHops ( char * nq , unsigned int want )
ptr ( nq ) ,
need ( want ) { }
inline bool operator ( ) ( const Address & a ) const
throw ( )
{
a . copyTo ( ptr , ZT_ADDRESS_LENGTH ) ;
ptr + = ZT_ADDRESS_LENGTH ;
return ( - - need ! = 0 ) ;
}
2013-08-21 11:45:06 -04:00
2013-09-25 17:41:49 -04:00
char * ptr ;
unsigned int need ;
} ;
2013-08-21 11:45:06 -04:00
2013-09-25 17:41:49 -04:00
bool PacketDecoder : : _doMULTICAST_FRAME ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
{
try {
unsigned int forwardCount = at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FORWARD_COUNT ) ;
char * queue = ( char * ) field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_QUEUE , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_QUEUE ) ;
Address magnet ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_MAGNET , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
Address submitterAddr ( Address ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ) ;
SharedPtr < Peer > submitter ( _r - > topology - > getPeer ( submitterAddr ) ) ;
if ( ! submitter ) {
_r - > sw - > requestWhois ( submitterAddr ) ;
_step = DECODE_WAITING_FOR_MULTICAST_FRAME_ORIGINAL_SENDER_LOOKUP ; // causes processing to come back here
return false ;
}
uint64_t guid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER ) ; // 40-bit sender address + 24-bit sender unique ID
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID ) ;
MAC sourceMac ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC , 6 ) ) ;
MulticastGroup dest ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DESTINATION_MAC , 6 ) ) , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DESTINATION_ADI ) ) ;
unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE ) ;
unsigned int frameLen = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD_LENGTH ) ;
unsigned char * frame = field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD , frameLen ) ;
unsigned int signatureLen = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD + frameLen ) ;
unsigned char * signature = field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD + frameLen + 2 , signatureLen ) ;
unsigned int signedPartLen = ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD - ZT_PROTO_VERB_MULTICAST_FRAME_IDX_MAGNET ) + frameLen ;
if ( ! submitter - > identity ( ) . verify ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_MAGNET , signedPartLen ) , signedPartLen , signature , signatureLen ) ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): failed signature verification, claims to be from %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , submitterAddr . toString ( ) . c_str ( ) ) ;
return true ;
}
2013-08-21 11:45:06 -04:00
2013-09-25 17:41:49 -04:00
SharedPtr < Network > network ( _r - > nc - > network ( nwid ) ) ;
if ( network ) {
if ( ! network - > isAllowed ( submitterAddr ) ) {
} else if ( ! dest . mac ( ) . isMulticast ( ) ) {
} else if ( ( ! network - > permitsBridging ( ) ) & & ( ! submitterAddr . wouldHaveMac ( sourceMac ) ) ) {
} else if ( ! network - > permitsEtherType ( etherType ) ) {
} else if ( network - > multicastDeduplicate ( guid ) ) {
} else if ( network - > updateAndCheckMulticastBalance ( submitterAddr , dest , frameLen ) ) {
network - > tap ( ) . put ( sourceMac , dest . mac ( ) , etherType , frame , frameLen ) ;
2013-08-28 16:01:27 -04:00
}
2013-09-25 17:41:49 -04:00
}
2013-08-28 16:01:27 -04:00
2013-09-25 17:41:49 -04:00
if ( magnet ! = _r - > identity . address ( ) ) {
Packet outp ( magnet , _r - > identity . address ( ) , Packet : : VERB_MULTICAST_GOT ) ;
outp . append ( nwid ) ;
outp . append ( guid ) ;
_r - > sw - > send ( outp , true ) ;
}
2013-08-21 11:45:06 -04:00
2013-09-25 17:41:49 -04:00
setAt ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FORWARD_COUNT , ( uint32_t ) + + forwardCount ) ;
char newQueue [ ZT_PROTO_VERB_MULTICAST_FRAME_LEN_QUEUE + ZT_ADDRESS_LENGTH ] ; // room for an extra if we need a nextHop
unsigned int newQueueLen = 0 ;
// Top of FIFO is next hop (if there is one)
Address nextHop ( queue , ZT_ADDRESS_LENGTH ) ;
// Deduplicate the rest of the queue[], adding them to newQueue
if ( nextHop ) { // there was a next hop, so there was something there
char firstByteSeen [ 256 ] ;
for ( unsigned int j = 0 ; j < ( 256 / 8 ) ; + + j )
( ( uint64_t * ) firstByteSeen ) [ j ] = 0 ;
for ( unsigned int i = ZT_ADDRESS_LENGTH ; i < ZT_PROTO_VERB_MULTICAST_FRAME_LEN_QUEUE ; i + = ZT_ADDRESS_LENGTH ) {
char * qs = queue + i ;
if ( Utils : : isZero ( qs , ZT_ADDRESS_LENGTH ) ) // zero terminates queue
break ;
bool isdup = false ;
if ( firstByteSeen [ ( unsigned int ) queue [ i ] ] ) {
for ( unsigned int i2 = ZT_ADDRESS_LENGTH ; i2 < ZT_PROTO_VERB_MULTICAST_FRAME_LEN_QUEUE ; i2 + = ZT_ADDRESS_LENGTH ) {
if ( ( i2 ! = i ) & & ( ! memcmp ( qs , queue + i2 , ZT_ADDRESS_LENGTH ) ) ) {
isdup = true ;
break ;
}
}
} else firstByteSeen [ ( unsigned int ) queue [ i ] ] = 1 ;
if ( ! isdup ) {
char * nq = newQueue + ( newQueueLen + + * ZT_ADDRESS_LENGTH ) ;
for ( unsigned int j = 0 ; j < ZT_ADDRESS_LENGTH ; + + j )
nq [ j ] = qs [ j ] ;
2013-08-21 11:45:06 -04:00
}
2013-07-11 18:15:51 -04:00
}
2013-09-25 17:41:49 -04:00
}
2013-08-21 11:45:06 -04:00
2013-09-25 17:41:49 -04:00
// Get next hops, including an extra if we don't have a next hop yet
unsigned int needQueueItems = ( ( ZT_PROTO_VERB_MULTICAST_FRAME_LEN_QUEUE / ZT_ADDRESS_LENGTH ) - newQueueLen ) ;
if ( ! nextHop )
+ + needQueueItems ;
if ( needQueueItems )
newQueueLen + = _r - > mc - > getNextHops ( nwid , dest , guid , _doMULTICAST_FRAME_fillQueueWithNextHops ( newQueue , needQueueItems ) ) ;
// Copy new queue over old queue, and pick off next hop if we need one
if ( newQueueLen ) {
char * nq = newQueue ;
if ( ! nextHop ) {
nextHop . setTo ( nq , ZT_ADDRESS_LENGTH ) ;
nq + = ZT_ADDRESS_LENGTH ;
- - newQueueLen ;
}
unsigned int i = 0 ;
unsigned int k = ZT_ADDRESS_LENGTH * newQueueLen ;
while ( i < k )
nq [ i ] = newQueue [ i ] ;
while ( i < ZT_PROTO_VERB_MULTICAST_FRAME_LEN_QUEUE )
nq [ i ] = 0 ;
} else memset ( queue , 0 , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_QUEUE ) ;
// If there's still no next hop, it's the magnet
if ( ! nextHop )
nextHop = magnet ;
// Send to next hop, unless it's us of course
if ( nextHop ! = _r - > identity . address ( ) ) {
newInitializationVector ( ) ;
setDestination ( nextHop ) ;
setSource ( _r - > identity . address ( ) ) ;
compress ( ) ;
_r - > sw - > send ( * this , true ) ;
2013-07-11 18:15:51 -04:00
}
2013-09-25 17:41:49 -04:00
return true ;
2013-07-11 18:15:51 -04:00
} catch ( std : : exception & ex ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped MULTICAST_FRAME from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 17:52:04 -04:00
} catch ( . . . ) {
2013-07-11 22:06:25 -04:00
TRACE ( " dropped MULTICAST_FRAME from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 17:52:04 -04:00
}
2013-09-25 17:41:49 -04:00
2013-07-11 22:06:25 -04:00
return true ;
2013-07-11 16:19:06 -04:00
}
2013-07-29 16:18:29 -04:00
bool PacketDecoder : : _doNETWORK_MEMBERSHIP_CERTIFICATE ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
2013-07-29 13:56:20 -04:00
{
2013-08-02 17:17:34 -04:00
// TODO: not implemented yet, will be needed for private networks.
return true ;
2013-07-29 13:56:20 -04:00
}
bool PacketDecoder : : _doNETWORK_CONFIG_REQUEST ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
{
2013-08-02 17:17:34 -04:00
try {
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID ) ;
# ifndef __WINDOWS__
if ( _r - > netconfService ) {
2013-08-12 21:25:36 -04:00
char tmp [ 128 ] ;
2013-08-02 17:17:34 -04:00
unsigned int dictLen = at < uint16_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN ) ;
Dictionary request ;
2013-08-05 12:16:25 -04:00
if ( dictLen )
request [ " meta " ] = std : : string ( ( const char * ) field ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT , dictLen ) , dictLen ) ;
2013-08-02 17:17:34 -04:00
request [ " type " ] = " netconf-request " ;
request [ " peerId " ] = peer - > identity ( ) . toString ( false ) ;
2013-08-30 17:05:43 -04:00
Utils : : snprintf ( tmp , sizeof ( tmp ) , " %llx " , ( unsigned long long ) nwid ) ;
2013-08-02 17:17:34 -04:00
request [ " nwid " ] = tmp ;
2013-08-30 17:05:43 -04:00
Utils : : snprintf ( tmp , sizeof ( tmp ) , " %llx " , ( unsigned long long ) packetId ( ) ) ;
2013-08-02 17:17:34 -04:00
request [ " requestId " ] = tmp ;
2013-08-06 01:28:56 -04:00
//TRACE("to netconf:\n%s",request.toString().c_str());
2013-08-02 17:17:34 -04:00
_r - > netconfService - > send ( request ) ;
} else {
# endif // !__WINDOWS__
Packet outp ( source ( ) , _r - > identity . address ( ) , Packet : : VERB_ERROR ) ;
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_UNSUPPORTED_OPERATION ) ;
outp . append ( nwid ) ;
outp . encrypt ( peer - > cryptKey ( ) ) ;
2013-09-16 13:02:10 -04:00
outp . macSet ( peer - > macKey ( ) ) ;
2013-08-02 17:17:34 -04:00
_r - > demarc - > send ( _localPort , _remoteAddress , outp . data ( ) , outp . size ( ) , - 1 ) ;
# ifndef __WINDOWS__
}
# endif // !__WINDOWS__
} 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
}
bool PacketDecoder : : _doNETWORK_CONFIG_REFRESH ( const RuntimeEnvironment * _r , const SharedPtr < Peer > & peer )
{
2013-08-02 17:17:34 -04:00
try {
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REFRESH_IDX_NETWORK_ID ) ;
SharedPtr < Network > nw ( _r - > nc - > network ( nwid ) ) ;
if ( ( nw ) & & ( source ( ) = = nw - > controller ( ) ) ) // only respond to requests from controller
nw - > requestConfiguration ( ) ;
} 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 ;
2013-07-29 13:56:20 -04:00
}
2013-07-11 16:19:06 -04:00
} // namespace ZeroTier