2013-07-11 20:19:06 +00:00
/*
* ZeroTier One - Global Peer to Peer Ethernet
2014-02-16 20:40:22 +00:00
* Copyright ( C ) 2011 - 2014 ZeroTier Networks LLC
2013-07-11 20:19:06 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
* - -
*
* 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 17:50:42 +00:00
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
2013-09-13 19:47:00 +00:00
# include "../version.h"
2013-08-02 21:17:34 +00:00
# include "Constants.hpp"
2013-10-01 20:01:36 +00:00
# include "Defaults.hpp"
2013-07-11 20:19:06 +00:00
# include "RuntimeEnvironment.hpp"
2014-09-24 16:04:09 +00:00
# include "IncomingPacket.hpp"
2014-10-01 23:29:52 +00:00
# include "Topology.hpp"
2013-07-11 20:19:06 +00:00
# include "Switch.hpp"
2013-07-11 21:52:04 +00:00
# include "Peer.hpp"
2013-07-12 02:06:25 +00:00
# include "NodeConfig.hpp"
2013-08-02 21:17:34 +00:00
# include "Service.hpp"
2013-12-27 04:57:17 +00:00
# include "SoftwareUpdater.hpp"
2013-07-11 20:19:06 +00:00
namespace ZeroTier {
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : tryDecode ( const RuntimeEnvironment * RR )
2013-07-11 20:19:06 +00:00
{
2014-10-02 17:06:29 +00:00
try {
2014-10-02 17:54:34 +00:00
if ( ( cipher ( ) = = ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE ) & & ( verb ( ) = = Packet : : VERB_HELLO ) ) {
2014-10-02 17:06:29 +00: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 21:52:04 +00:00
}
2014-10-02 17:06:29 +00: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 22:15:51 +00:00
return true ;
2014-10-02 17:06:29 +00: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"
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , verb ( ) , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
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 ) ;
2014-10-10 01:32:05 +00:00
case Packet : : VERB_P5_MULTICAST_FRAME : return _doP5_MULTICAST_FRAME ( RR , peer ) ;
2014-10-02 17:06:29 +00:00
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 ) ;
case Packet : : VERB_NETWORK_CONFIG_REFRESH : return _doNETWORK_CONFIG_REFRESH ( RR , peer ) ;
case Packet : : VERB_MULTICAST_GATHER : return _doMULTICAST_GATHER ( RR , peer ) ;
case Packet : : VERB_MULTICAST_FRAME : return _doMULTICAST_FRAME ( RR , peer ) ;
}
} else {
RR - > sw - > requestWhois ( source ( ) ) ;
return false ;
2013-07-11 21:52:04 +00:00
}
2014-10-02 17:06:29 +00:00
} catch ( . . . ) {
// Exceptions are more informatively caught in _do...() handlers but
// this outer try/catch will catch anything else odd.
TRACE ( " dropped ??? from %s(%s): unexpected exception in tryDecode() " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
2013-07-11 21:52:04 +00:00
}
2013-07-11 22:15:51 +00:00
}
2013-07-11 21:52:04 +00:00
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doERROR ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
try {
2013-07-12 02:06:25 +00:00
Packet : : Verb inReVerb = ( Packet : : Verb ) ( * this ) [ ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB ] ;
2013-12-24 18:39:29 +00:00
uint64_t inRePacketId = at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID ) ;
2013-07-12 02:06:25 +00:00
Packet : : ErrorCode errorCode = ( Packet : : ErrorCode ) ( * this ) [ ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE ] ;
2013-12-24 18:39:29 +00:00
2014-09-30 23:28:25 +00: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 20:03:13 +00:00
switch ( errorCode ) {
2014-09-30 23:28:25 +00:00
2013-09-27 20:03:13 +00:00
case Packet : : ERROR_OBJ_NOT_FOUND :
if ( inReVerb = = Packet : : VERB_WHOIS ) {
2014-09-24 20:53:03 +00:00
if ( RR - > topology - > isSupernode ( source ( ) ) )
RR - > sw - > cancelWhoisRequest ( Address ( field ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ) ;
2013-10-17 09:37:01 +00:00
} else if ( inReVerb = = Packet : : VERB_NETWORK_CONFIG_REQUEST ) {
2014-09-24 20:53:03 +00:00
SharedPtr < Network > network ( RR - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2013-10-17 09:37:01 +00:00
if ( ( network ) & & ( network - > controller ( ) = = source ( ) ) )
2014-01-28 07:13:36 +00:00
network - > setNotFound ( ) ;
2013-09-27 20:03:13 +00:00
}
break ;
2014-09-30 23:28:25 +00:00
2013-09-27 20:03:13 +00:00
case Packet : : ERROR_IDENTITY_COLLISION :
// TODO: if it comes from a supernode, regenerate a new identity
2014-09-24 20:53:03 +00:00
// if (RR->topology->isSupernode(source())) {}
2013-09-27 20:03:13 +00:00
break ;
2014-09-30 23:28:25 +00:00
2013-10-16 21:47:26 +00:00
case Packet : : ERROR_NEED_MEMBERSHIP_CERTIFICATE : {
2014-09-24 20:53:03 +00:00
SharedPtr < Network > network ( RR - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2014-10-09 19:42:25 +00: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 ) ;
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
}
}
2013-10-16 21:47:26 +00:00
} break ;
2014-09-30 23:28:25 +00:00
2014-01-18 01:09:59 +00:00
case Packet : : ERROR_NETWORK_ACCESS_DENIED_ : {
2014-09-24 20:53:03 +00:00
SharedPtr < Network > network ( RR - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_ERROR_IDX_PAYLOAD ) ) ) ;
2013-10-17 09:37:01 +00:00
if ( ( network ) & & ( network - > controller ( ) = = source ( ) ) )
2014-01-28 07:13:36 +00:00
network - > setAccessDenied ( ) ;
2013-10-17 09:37:01 +00:00
} break ;
2014-09-30 23:28:25 +00:00
2014-10-09 19:42:25 +00:00
case Packet : : ERROR_UNWANTED_MULTICAST : {
// TODO: unsubscribe
} break ;
2014-09-30 23:28:25 +00:00
default : break ;
2013-09-27 20:03:13 +00:00
}
2013-12-24 18:39:29 +00:00
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_ERROR , inRePacketId , inReVerb , Utils : : now ( ) ) ;
2013-07-11 22:15:51 +00:00
} catch ( std : : exception & ex ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped ERROR from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped ERROR from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 21:52:04 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doHELLO ( const RuntimeEnvironment * RR )
2013-07-11 21:52:04 +00:00
{
try {
2013-10-05 14:19:12 +00:00
unsigned int protoVersion = ( * this ) [ ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION ] ;
2013-07-12 02:06:25 +00:00
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 21:52:04 +00:00
2014-09-30 23:28:25 +00:00
if ( protoVersion < ZT_PROTO_VERSION_MIN ) {
TRACE ( " dropped HELLO from %s(%s): protocol version too old " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 21:52:04 +00:00
}
2014-09-30 23:28:25 +00:00
2013-10-05 14:19:12 +00:00
if ( ! id . locallyValidate ( ) ) {
TRACE ( " dropped HELLO from %s(%s): identity invalid " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 21:52:04 +00:00
}
2013-10-21 18:12:00 +00:00
// Do we already have this peer?
2014-09-24 20:53:03 +00:00
SharedPtr < Peer > peer ( RR - > topology - > getPeer ( id . address ( ) ) ) ;
2013-10-05 14:19:12 +00:00
if ( peer ) {
2013-10-21 18:12:00 +00:00
// Check to make sure this isn't a colliding identity (different key,
// but same address). The odds are spectacularly low but it could happen.
// Could also be a sign of someone doing something nasty.
2013-10-05 14:19:12 +00:00
if ( peer - > identity ( ) ! = id ) {
unsigned char key [ ZT_PEER_SECRET_KEY_LENGTH ] ;
2014-09-24 20:53:03 +00:00
if ( RR - > identity . agree ( id , key , ZT_PEER_SECRET_KEY_LENGTH ) ) {
2013-12-31 19:03:45 +00:00
if ( dearmor ( key ) ) { // ensure packet is authentic, otherwise drop
2014-06-23 15:19:41 +00:00
LOG ( " rejected HELLO from %s(%s): address already claimed " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2014-09-24 20:53:03 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2013-12-31 19:03:45 +00:00
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_IDENTITY_COLLISION ) ;
outp . armor ( key , true ) ;
2014-03-19 20:56:48 +00:00
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2013-12-31 19:03:45 +00:00
} else {
LOG ( " rejected HELLO from %s(%s): packet failed authentication " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
} else {
2014-06-23 15:19:41 +00:00
LOG ( " rejected HELLO from %s(%s): key agreement failed " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-10-05 14:19:12 +00:00
}
return true ;
2013-12-31 19:03:45 +00:00
} else if ( ! dearmor ( peer - > key ( ) ) ) {
2014-06-23 15:19:41 +00:00
LOG ( " rejected HELLO from %s(%s): packet failed authentication " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-12-31 19:03:45 +00:00
return true ;
} // else continue and respond
2013-10-16 21:47:26 +00:00
} else {
2013-10-21 18:12:00 +00:00
// If we don't have a peer record on file, check the identity cache (if
// we have one) to see if we have a cached identity. Then check that for
// collision before adding a new peer.
2014-09-24 20:53:03 +00:00
Identity alreadyHaveCachedId ( RR - > topology - > getIdentity ( id . address ( ) ) ) ;
2013-10-21 18:12:00 +00:00
if ( ( alreadyHaveCachedId ) & & ( id ! = alreadyHaveCachedId ) ) {
unsigned char key [ ZT_PEER_SECRET_KEY_LENGTH ] ;
2014-09-24 20:53:03 +00:00
if ( RR - > identity . agree ( id , key , ZT_PEER_SECRET_KEY_LENGTH ) ) {
2013-12-31 19:03:45 +00:00
if ( dearmor ( key ) ) { // ensure packet is authentic, otherwise drop
2014-06-23 15:19:41 +00:00
LOG ( " rejected HELLO from %s(%s): address already claimed " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2014-09-24 20:53:03 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2013-12-31 19:03:45 +00:00
outp . append ( ( unsigned char ) Packet : : VERB_HELLO ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_IDENTITY_COLLISION ) ;
outp . armor ( key , true ) ;
2014-03-19 20:56:48 +00:00
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2013-12-31 19:03:45 +00:00
} else {
LOG ( " rejected HELLO from %s(%s): packet failed authentication " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
} else {
2014-06-23 15:19:41 +00:00
LOG ( " rejected HELLO from %s(%s): key agreement failed " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-10-21 18:12:00 +00:00
}
return true ;
2013-12-24 18:39:29 +00:00
} // else continue since identity is already known and matches
2013-10-21 18:12:00 +00:00
2013-12-31 19:03:45 +00:00
// If this is a new peer, learn it
2014-09-24 20:53:03 +00:00
SharedPtr < Peer > newPeer ( new Peer ( RR - > identity , id ) ) ;
2013-12-31 19:03:45 +00:00
if ( ! dearmor ( newPeer - > key ( ) ) ) {
LOG ( " rejected HELLO from %s(%s): packet failed authentication " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
2014-09-24 20:53:03 +00:00
peer = RR - > topology - > addPeer ( newPeer ) ;
2013-10-16 21:47:26 +00:00
}
2013-10-05 14:19:12 +00:00
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_HELLO , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
2014-09-30 23:28:25 +00:00
peer - > setRemoteVersion ( protoVersion , vMajor , vMinor , vRevision ) ;
2013-10-05 14:19:12 +00:00
2014-01-08 00:37:36 +00:00
// If a supernode has a version higher than ours, this causes a software
// update check to run now.
2014-09-24 20:53:03 +00:00
if ( ( RR - > updater ) & & ( RR - > topology - > isSupernode ( peer - > address ( ) ) ) )
RR - > updater - > sawRemoteVersion ( vMajor , vMinor , vRevision ) ;
2014-01-08 00:37:36 +00:00
2014-09-24 20:53:03 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2013-10-05 14:19:12 +00: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 ) ;
outp . armor ( peer - > key ( ) , true ) ;
2014-03-19 20:56:48 +00:00
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2013-07-11 21:52:04 +00:00
} catch ( std : : exception & ex ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped HELLO from %s(%s): %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped HELLO from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doOK ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
try {
2013-07-12 02:06:25 +00:00
Packet : : Verb inReVerb = ( Packet : : Verb ) ( * this ) [ ZT_PROTO_VERB_OK_IDX_IN_RE_VERB ] ;
2013-12-24 18:39:29 +00:00
uint64_t inRePacketId = at < uint64_t > ( ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID ) ;
2014-01-30 01:09:55 +00:00
//TRACE("%s(%s): OK(%s)",source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb));
2013-12-24 18:39:29 +00:00
2013-07-11 22:15:51 +00:00
switch ( inReVerb ) {
2014-09-30 23:28:25 +00:00
2013-07-12 02:06:25 +00:00
case Packet : : VERB_HELLO : {
2014-02-03 18:46:37 +00:00
unsigned int latency = std : : min ( ( unsigned int ) ( Utils : : now ( ) - at < uint64_t > ( ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP ) ) , ( unsigned int ) 0xffff ) ;
2014-09-30 23:28:25 +00:00
unsigned int vProto = ( * this ) [ ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION ] ;
2013-09-27 20:03:13 +00:00
unsigned int vMajor = ( * this ) [ ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION ] ;
unsigned int vMinor = ( * this ) [ ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION ] ;
unsigned int vRevision = at < uint16_t > ( ZT_PROTO_VERB_HELLO__OK__IDX_REVISION ) ;
2014-09-30 23:28:25 +00: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 ;
}
2014-02-03 18:46:37 +00:00
TRACE ( " %s(%s): OK(HELLO), version %u.%u.%u, latency %u " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , vMajor , vMinor , vRevision , latency ) ;
2014-09-30 23:28:25 +00:00
2014-02-03 18:46:37 +00:00
peer - > addDirectLatencyMeasurment ( latency ) ;
2014-09-30 23:28:25 +00:00
peer - > setRemoteVersion ( vProto , vMajor , vMinor , vRevision ) ;
2013-12-27 04:57:17 +00:00
// If a supernode has a version higher than ours, this causes a software
2014-02-03 18:46:37 +00:00
// update check to run now. This might bum-rush download.zerotier.com, but
// it's hosted on S3 so hopefully it can take it. This should cause updates
// to propagate out very quickly.
2014-09-24 20:53:03 +00:00
if ( ( RR - > updater ) & & ( RR - > topology - > isSupernode ( peer - > address ( ) ) ) )
RR - > updater - > sawRemoteVersion ( vMajor , vMinor , vRevision ) ;
2013-07-12 02:06:25 +00:00
} break ;
2014-09-30 23:28:25 +00:00
2013-08-05 16:16:25 +00:00
case Packet : : VERB_WHOIS : {
2013-10-05 14:19:12 +00:00
// Right now only supernodes are allowed to send OK(WHOIS) to prevent
// poisoning attacks. Further decentralization will require some other
// kind of trust mechanism.
2014-09-24 20:53:03 +00:00
if ( RR - > topology - > isSupernode ( source ( ) ) ) {
2013-10-05 14:19:12 +00:00
Identity id ( * this , ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY ) ;
if ( id . locallyValidate ( ) )
2014-09-24 20:53:03 +00:00
RR - > sw - > doAnythingWaitingForPeer ( RR - > topology - > addPeer ( SharedPtr < Peer > ( new Peer ( RR - > identity , id ) ) ) ) ;
2013-08-05 16:16:25 +00:00
}
} break ;
2014-09-30 23:28:25 +00:00
2013-08-03 16:53:46 +00:00
case Packet : : VERB_NETWORK_CONFIG_REQUEST : {
2014-09-24 20:53:03 +00:00
SharedPtr < Network > nw ( RR - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID ) ) ) ;
2013-08-03 16:53:46 +00:00
if ( ( nw ) & & ( nw - > controller ( ) = = source ( ) ) ) {
2013-08-23 14:54:45 +00:00
// OK(NETWORK_CONFIG_REQUEST) is only accepted from a network's
// controller.
2013-08-03 16:53:46 +00: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 ( ) ) {
2013-10-18 17:20:34 +00:00
nw - > setConfiguration ( Dictionary ( dict ) ) ;
2013-09-11 20:49:01 +00:00
TRACE ( " got network configuration for network %.16llx from %s " , ( unsigned long long ) nw - > id ( ) , source ( ) . toString ( ) . c_str ( ) ) ;
2013-08-03 16:53:46 +00:00
}
}
} break ;
2014-09-30 23:28:25 +00:00
case Packet : : VERB_MULTICAST_GATHER : {
2014-10-02 20:50:37 +00:00
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID ) ;
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-10 00:58:31 +00: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 ( ) ) ;
2014-10-02 20:50:37 +00:00
_parseGatherResults ( RR , peer , nwid , mg , ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS ) ;
2014-09-30 23:28:25 +00:00
} break ;
case Packet : : VERB_MULTICAST_FRAME : {
2014-10-02 20:50:37 +00:00
unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS ] ;
2014-10-09 19:42:25 +00:00
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID ) ;
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-10 00:58:31 +00:00
TRACE ( " %s(%s): OK(MULTICAST_FRAME) %.16llx/%s flags %.2x " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , nwid , mg . toString ( ) . c_str ( ) , flags ) ;
2014-10-09 19:42:25 +00:00
unsigned int offset = 0 ;
if ( ( flags & 0x01 ) ! = 0 ) {
// OK(MULTICAST_FRAME) includes certificate of membership update
CertificateOfMembership com ;
offset + = com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_PAYLOAD ) ;
SharedPtr < Network > network ( RR - > nc - > network ( nwid ) ) ;
if ( ( network ) & & ( com . hasRequiredFields ( ) ) )
network - > addMembershipCertificate ( com , false ) ;
}
if ( ( flags & 0x02 ) ! = 0 ) {
// OK(MULTICAST_FRAME) includes implicit gather results
_parseGatherResults ( RR , peer , nwid , mg , offset + ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_PAYLOAD ) ;
2014-10-02 20:50:37 +00:00
}
2014-09-30 23:28:25 +00:00
} break ;
default : break ;
2013-07-11 22:15:51 +00:00
}
2013-12-24 18:39:29 +00:00
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_OK , inRePacketId , inReVerb , Utils : : now ( ) ) ;
2013-07-11 22:15:51 +00:00
} catch ( std : : exception & ex ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped OK from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped OK from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doWHOIS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
2014-06-23 15:19:41 +00:00
try {
if ( payloadLength ( ) = = ZT_ADDRESS_LENGTH ) {
2014-09-24 20:53:03 +00:00
Identity id ( RR - > topology - > getIdentity ( Address ( payload ( ) , ZT_ADDRESS_LENGTH ) ) ) ;
2014-06-23 15:19:41 +00:00
if ( id ) {
2014-09-24 20:53:03 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2014-06-23 15:19:41 +00:00
outp . append ( ( unsigned char ) Packet : : VERB_WHOIS ) ;
outp . append ( packetId ( ) ) ;
id . serialize ( outp , false ) ;
outp . armor ( peer - > key ( ) , true ) ;
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
//TRACE("sent WHOIS response to %s for %s",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str());
} else {
2014-09-24 20:53:03 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2014-06-23 15:19:41 +00: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 ) ;
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
//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 22:15:51 +00:00
} else {
2014-06-23 15:19:41 +00:00
TRACE ( " dropped WHOIS from %s(%s): missing or invalid address " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2014-06-23 15:19:41 +00:00
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_WHOIS , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
2014-06-23 15:19:41 +00:00
} catch ( . . . ) {
TRACE ( " dropped WHOIS from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doRENDEZVOUS ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
try {
2013-08-06 14:39:20 +00: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 14:54:45 +00:00
* sender is someone we should trust with a RENDEZVOUS hint .
2013-08-06 14:39:20 +00:00
*/
2014-09-24 20:53:03 +00:00
if ( RR - > topology - > isSupernode ( source ( ) ) ) {
2013-08-05 16:16:25 +00:00
Address with ( field ( ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
2014-09-24 20:53:03 +00:00
SharedPtr < Peer > withPeer ( RR - > topology - > getPeer ( with ) ) ;
2013-08-05 16:16:25 +00:00
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 ( ) ) ;
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_RENDEZVOUS , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
RR - > sw - > contact ( withPeer , atAddr ) ;
2013-08-05 16:16:25 +00:00
} else {
TRACE ( " dropped corrupt RENDEZVOUS from %s(%s) (bad address or port) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
2013-07-11 22:15:51 +00:00
} else {
2013-08-05 16:16:25 +00: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 22:15:51 +00:00
}
} else {
2013-08-05 16:16:25 +00:00
TRACE ( " ignored RENDEZVOUS from %s(%s): source not supernode " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
} catch ( std : : exception & ex ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped RENDEZVOUS from %s(%s): %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped RENDEZVOUS from %s(%s): unexpected exception " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doFRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
try {
2014-09-24 20:53:03 +00:00
SharedPtr < Network > network ( RR - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID ) ) ) ;
2013-07-11 22:15:51 +00:00
if ( network ) {
2014-06-18 16:00:53 +00: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 20:53:03 +00:00
_sendErrorNeedCertificate ( RR , peer , network - > id ( ) ) ;
2014-06-18 16:00:53 +00:00
return true ;
}
unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE ) ;
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 ;
}
2014-10-02 17:06:29 +00:00
unsigned int payloadLen = size ( ) - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD ;
network - > tapPut ( MAC ( peer - > address ( ) , network - > id ( ) ) , network - > mac ( ) , etherType , field ( ZT_PROTO_VERB_FRAME_IDX_PAYLOAD , payloadLen ) , payloadLen ) ;
2014-06-18 16:00:53 +00:00
}
2014-10-01 00:26:34 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_FRAME , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
2013-07-11 22:15:51 +00:00
} else {
2013-12-24 18:39:29 +00: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 22:15:51 +00:00
}
} catch ( std : : exception & ex ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped FRAME from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 22:15:51 +00:00
} catch ( . . . ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped FRAME from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 22:15:51 +00:00
}
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doEXT_FRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-11 22:15:51 +00:00
{
2014-06-11 04:41:34 +00:00
try {
2014-09-24 20:53:03 +00:00
SharedPtr < Network > network ( RR - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID ) ) ) ;
2014-06-11 04:41:34 +00:00
if ( network ) {
2014-06-18 16:00:53 +00:00
if ( size ( ) > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) {
2014-09-30 23:28:25 +00:00
unsigned int flags = ( * this ) [ ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS ] ;
2014-06-14 04:06:34 +00:00
2014-09-30 23:28:25 +00:00
unsigned int comLen = 0 ;
if ( ( flags & 0x01 ) ! = 0 ) {
CertificateOfMembership com ;
comLen = com . deserialize ( * this , ZT_PROTO_VERB_EXT_FRAME_IDX_COM ) ;
if ( com . hasRequiredFields ( ) )
2014-10-01 00:26:34 +00:00
network - > addMembershipCertificate ( com , false ) ;
}
if ( ! network - > isAllowed ( peer - > address ( ) ) ) {
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 23:28:25 +00:00
}
// Everything after flags must be adjusted based on the length
// of the certificate, if there was one...
unsigned int etherType = at < uint16_t > ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE ) ;
2014-06-18 16:00:53 +00: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 23:28:25 +00:00
const MAC to ( field ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_TO , ZT_PROTO_VERB_EXT_FRAME_LEN_TO ) , ZT_PROTO_VERB_EXT_FRAME_LEN_TO ) ;
const MAC from ( field ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_FROM , ZT_PROTO_VERB_EXT_FRAME_LEN_FROM ) , ZT_PROTO_VERB_EXT_FRAME_LEN_FROM ) ;
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 16:00:53 +00:00
2014-10-01 00:26:34 +00: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-11 04:41:34 +00: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 ;
}
2014-09-30 23:28:25 +00:00
}
2014-06-11 04:41:34 +00:00
if ( to ! = network - > mac ( ) ) {
2014-09-24 20:53:03 +00:00
if ( ! network - > permitsBridging ( RR - > identity . address ( ) ) ) {
2014-06-11 04:41:34 +00:00
TRACE ( " dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network " , from . toString ( ) . c_str ( ) , peer - > address ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , to . toString ( ) . c_str ( ) , network - > id ( ) ) ;
return true ;
}
}
2014-09-30 23:28:25 +00:00
unsigned int payloadLen = size ( ) - ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD ) ;
if ( payloadLen )
network - > tapPut ( from , to , etherType , field ( comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD , payloadLen ) , payloadLen ) ;
2014-06-12 18:40:30 +00:00
}
2014-10-01 00:26:34 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_EXT_FRAME , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
2014-06-11 04:41:34 +00: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-12 02:06:25 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2014-09-30 23:28:25 +00:00
bool IncomingPacket : : _doP5_MULTICAST_FRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-09-25 21:41:49 +00:00
{
2014-10-09 19:42:25 +00:00
/* This handles the old deprecated "P5" multicast frame, and will
* go away once there are no longer nodes using this on the network .
* We handle these old nodes by accepting these as simple multicasts
* and if we are a supernode performing individual relaying of them
* to all older nodes that expect them . This won ' t be too expensive
* though since there aren ' t likely to be many older nodes left after
* we do a software update . */
2014-09-30 23:28:25 +00:00
2014-10-10 00:58:31 +00:00
// Quick and dirty dedup -- this is all condemned code in any case
2014-10-06 20:16:16 +00:00
static uint64_t p5MulticastDedupBuffer [ 1024 ] ;
static unsigned long p5MulticastDedupBufferPtr = 0 ;
static Mutex p5MulticastDedupBuffer_m ;
try {
Address origin ( Address ( field ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN , ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ORIGIN ) , ZT_ADDRESS_LENGTH ) ) ;
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FLAGS ] ;
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_NETWORK_ID ) ;
const uint64_t guid = at < uint64_t > ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_GUID ) ;
const MAC sourceMac ( field ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_SOURCE_MAC , ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_SOURCE_MAC ) , ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_SOURCE_MAC ) ;
const MulticastGroup dest ( MAC ( field ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_MAC , ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_DEST_MAC ) , ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_DEST_MAC ) , at < uint32_t > ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_ADI ) ) ;
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ETHERTYPE ) ;
const unsigned int frameLen = at < uint16_t > ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME_LEN ) ;
const unsigned char * const frame = field ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME , frameLen ) ;
const unsigned int signatureLen = at < uint16_t > ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME + frameLen ) ;
{
Mutex : : Lock _l ( p5MulticastDedupBuffer_m ) ;
if ( ! p5MulticastDedupBufferPtr ) {
memset ( p5MulticastDedupBuffer , 0 , sizeof ( p5MulticastDedupBuffer ) ) ;
} else {
for ( unsigned int i = 0 ; i < 1024 ; + + i ) {
if ( p5MulticastDedupBuffer [ i ] = = guid )
return true ;
}
}
p5MulticastDedupBuffer [ p5MulticastDedupBufferPtr + + % 1024 ] = guid ;
}
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_P5_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
if ( RR - > topology - > amSupernode ( ) ) {
std : : vector < Address > legacyPeers ( RR - > mc - > getLegacySubscribers ( nwid , dest ) ) ;
setAt ( ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH , ( uint16_t ) 0xffff ) ;
2014-10-09 16:02:46 +00:00
setSource ( RR - > identity . address ( ) ) ;
compress ( ) ;
2014-10-06 20:16:16 +00:00
for ( std : : vector < Address > : : iterator lp ( legacyPeers . begin ( ) ) ; lp ! = legacyPeers . end ( ) ; + + lp ) {
if ( ( * lp ! = origin ) & & ( * lp ! = source ( ) ) ) {
newInitializationVector ( ) ;
setDestination ( * lp ) ;
RR - > sw - > send ( * this , true ) ;
}
}
2014-10-09 16:02:46 +00:00
return true ;
2014-10-06 20:16:16 +00:00
} else {
SharedPtr < Network > network ( RR - > nc - > network ( nwid ) ) ; // will be NULL if not a member
if ( network ) {
if ( ( flags & ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE ) ) {
CertificateOfMembership com ;
com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2 + signatureLen ) ;
if ( com . hasRequiredFields ( ) )
network - > addMembershipCertificate ( com , false ) ;
}
if ( ! network - > isAllowed ( origin ) ) {
_sendErrorNeedCertificate ( RR , peer , network - > id ( ) ) ;
return true ;
}
if ( frameLen ) {
if ( ! dest . mac ( ) . isMulticast ( ) )
return true ;
if ( ( ! sourceMac ) | | ( sourceMac . isMulticast ( ) ) | | ( sourceMac = = network - > mac ( ) ) )
return true ;
if ( sourceMac ! = MAC ( origin , network - > id ( ) ) ) {
if ( network - > permitsBridging ( origin ) ) {
network - > learnBridgeRoute ( sourceMac , origin ) ;
} else return true ;
}
network - > tapPut ( sourceMac , dest . mac ( ) , etherType , frame , frameLen ) ;
}
}
}
} catch ( std : : exception & ex ) {
TRACE ( " dropped P5_MULTICAST_FRAME from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
} catch ( . . . ) {
TRACE ( " dropped P5_MULTICAST_FRAME from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
2014-09-30 23:28:25 +00:00
#if 0 // old code preserved below
2013-09-25 21:41:49 +00:00
try {
2013-09-26 21:45:19 +00:00
Address origin ( Address ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN ) , ZT_ADDRESS_LENGTH ) ) ;
2014-09-24 20:53:03 +00:00
SharedPtr < Peer > originPeer ( RR - > topology - > getPeer ( origin ) ) ;
2013-09-26 21:45:19 +00:00
if ( ! originPeer ) {
2013-09-30 15:05:35 +00:00
// We must have the origin's identity in order to authenticate a multicast
2014-09-24 20:53:03 +00:00
RR - > sw - > requestWhois ( origin ) ;
2013-09-25 21:41:49 +00:00
_step = DECODE_WAITING_FOR_MULTICAST_FRAME_ORIGINAL_SENDER_LOOKUP ; // causes processing to come back here
return false ;
}
2013-09-26 21:45:19 +00:00
2014-06-30 18:31:04 +00:00
// These fields in the packet are changed by each forwarder
2013-10-01 20:01:36 +00:00
unsigned int depth = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH ) ;
2013-10-02 17:50:42 +00:00
unsigned char * const fifo = field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO ) ;
unsigned char * const bloom = field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM ) ;
// These fields don't -- they're signed by the original sender
2013-10-25 18:51:55 +00:00
const unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS ] ;
2013-10-02 17:50:42 +00:00
const uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID ) ;
const uint16_t bloomNonce = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE ) ;
const unsigned int prefixBits = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS ] ;
const unsigned int prefix = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX ] ;
const uint64_t guid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GUID ) ;
2014-05-23 21:32:31 +00:00
const MAC sourceMac ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC ) , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC ) ;
const MulticastGroup dest ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC ) , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC ) , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI ) ) ;
2013-10-02 17:50:42 +00:00
const unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE ) ;
const unsigned int frameLen = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN ) ;
const unsigned char * const frame = field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME , frameLen ) ;
const unsigned int signatureLen = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen ) ;
const unsigned char * const signature = field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2 , signatureLen ) ;
2014-06-23 15:19:41 +00:00
if ( ( ! sourceMac ) | | ( sourceMac . isMulticast ( ) ) ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): invalid source MAC %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , sourceMac . toString ( ) . c_str ( ) ) ;
return true ;
}
2014-09-24 20:53:03 +00:00
SharedPtr < Network > network ( RR - > nc - > network ( nwid ) ) ;
2014-06-30 18:31:04 +00:00
SharedPtr < NetworkConfig > nconf ;
if ( network )
nconf = network - > config2 ( ) ;
2013-10-25 18:51:55 +00:00
2013-12-22 18:56:03 +00:00
/* Grab, verify, and learn certificate of network membership if any -- provided we are
* a member of this network . Note : we can do this before verification of the actual
* packet , since the certificate has its own separate signature . In other words a valid
* COM does not imply a valid multicast ; they are two separate things . The ability to
* include the COM with the multicast is a performance optimization to allow peers to
* distribute their COM along with their packets instead of as a separate transaction .
* This causes network memberships to start working faster . */
2013-10-25 18:51:55 +00:00
if ( ( ( flags & ZT_PROTO_VERB_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE ) ) & & ( network ) ) {
CertificateOfMembership originCom ( * this , ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME + frameLen + 2 + signatureLen ) ;
2013-12-22 18:56:03 +00:00
Address comSignedBy ( originCom . signedBy ( ) ) ;
if ( ( originCom . networkId ( ) = = nwid ) & & ( comSignedBy = = network - > controller ( ) ) ) {
2014-09-24 20:53:03 +00:00
SharedPtr < Peer > comSigningPeer ( RR - > topology - > getPeer ( comSignedBy ) ) ;
2013-12-22 18:56:03 +00:00
if ( ! comSigningPeer ) {
// Technically this should never happen because the COM should be signed by
// the master for this network (in current usage) and we ought to already have
// that cached. But handle it anyway.
2014-09-24 20:53:03 +00:00
RR - > sw - > requestWhois ( comSignedBy ) ;
2013-10-25 18:51:55 +00:00
_step = DECODE_WAITING_FOR_MULTICAST_FRAME_ORIGINAL_SENDER_LOOKUP ; // causes processing to come back here
return false ;
2013-12-22 18:56:03 +00:00
} else if ( originCom . verify ( comSigningPeer - > identity ( ) ) ) {
// The certificate is valid so learn it. As explained above this does not
// imply validation of the multicast. That happens later. Look for a call
// to network->isAllowed().
2013-10-25 18:51:55 +00:00
network - > addMembershipCertificate ( originCom ) ;
2013-12-22 18:56:03 +00:00
} else {
// Go ahead and drop the multicast though if the COM was invalid, since this
// obviously signifies a problem.
LOG ( " dropped MULTICAST_FRAME from %s(%s): included COM failed authentication check " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
2013-10-25 18:51:55 +00:00
}
2013-12-22 18:56:03 +00:00
} else {
// Go ahead and drop the multicast here too, since this also ought never to
// happen and certainly indicates a problem.
LOG ( " dropped MULTICAST_FRAME from %s(%s): included COM is not for this network " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
2013-10-25 18:51:55 +00:00
}
}
2013-12-22 18:56:03 +00:00
// Check the multicast frame's signature to verify that its original sender is
// who it claims to be.
2013-10-02 17:50:42 +00:00
const unsigned int signedPartLen = ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME - ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION ) + frameLen ;
2013-09-27 20:03:13 +00:00
if ( ! originPeer - > identity ( ) . verify ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION , signedPartLen ) , signedPartLen , signature , signatureLen ) ) {
2013-12-22 18:56:03 +00:00
LOG ( " dropped MULTICAST_FRAME from %s(%s): failed signature verification, claims to be from %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , origin . toString ( ) . c_str ( ) ) ;
2013-09-26 21:45:19 +00:00
return true ;
}
2013-12-22 18:56:03 +00:00
// Security check to prohibit multicasts that are really Ethernet unicasts...
// otherwise people could do weird things like multicast out a TCP SYN.
2013-10-16 21:47:26 +00:00
if ( ! dest . mac ( ) . isMulticast ( ) ) {
2013-12-22 18:56:03 +00:00
LOG ( " dropped MULTICAST_FRAME from %s(%s): %s is not a multicast/broadcast address " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , dest . mac ( ) . toString ( ) . c_str ( ) ) ;
2013-10-16 21:47:26 +00:00
return true ;
}
2013-12-24 18:39:29 +00:00
// At this point the frame is basically valid, so we can call it a receive
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
2013-12-24 18:39:29 +00:00
2013-12-22 18:56:03 +00:00
// This gets updated later in most cases but start with the global limit.
2013-09-30 17:51:56 +00:00
unsigned int maxDepth = ZT_MULTICAST_GLOBAL_MAX_DEPTH ;
2013-09-26 21:45:19 +00:00
2014-09-24 20:53:03 +00:00
if ( ( origin = = RR - > identity . address ( ) ) | | ( RR - > mc - > deduplicate ( nwid , guid ) ) ) {
2013-12-22 18:56:03 +00:00
// This is a boomerang or a duplicate of a multicast we've already seen. Ordinary
// nodes drop these, while supernodes will keep propagating them since they can
// act as bridges between sparse multicast networks more than once.
2014-09-24 20:53:03 +00:00
if ( ! RR - > topology - > amSupernode ( ) ) {
2013-09-30 15:05:35 +00:00
TRACE ( " dropped MULTICAST_FRAME from %s(%s): duplicate " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
} else {
2013-10-16 21:47:26 +00:00
// If we are actually a member of this network (will just about always
// be the case unless we're a supernode), check to see if we should
// inject the packet. This also gives us an opportunity to check things
// like multicast bandwidth constraints.
2014-06-30 18:31:04 +00:00
if ( ( network ) & & ( nconf ) ) {
// Learn real maxDepth from netconf
maxDepth = std : : min ( ( unsigned int ) ZT_MULTICAST_GLOBAL_MAX_DEPTH , nconf - > multicastDepth ( ) ) ;
if ( ! maxDepth )
maxDepth = ZT_MULTICAST_GLOBAL_MAX_DEPTH ;
if ( ! network - > isAllowed ( origin ) ) {
// Papers, please...
2014-09-24 20:53:03 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2014-06-30 18:31:04 +00:00
outp . append ( ( unsigned char ) Packet : : VERB_MULTICAST_FRAME ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_NEED_MEMBERSHIP_CERTIFICATE ) ;
outp . append ( nwid ) ;
outp . armor ( peer - > key ( ) , true ) ;
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
TRACE ( " dropped MULTICAST_FRAME from %s(%s) into %.16llx: sender %s not allowed or we don't have a certificate " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , nwid , origin . toString ( ) . c_str ( ) ) ;
return true ;
}
2014-06-14 04:06:34 +00:00
2014-06-30 18:31:04 +00:00
if ( MAC ( origin , network - > id ( ) ) ! = sourceMac ) {
if ( ! nconf - > permitsBridging ( origin ) ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s) into %.16llx: source mac %s doesn't belong to %s, and bridging is not supported on network " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , nwid , sourceMac . toString ( ) . c_str ( ) , origin . toString ( ) . c_str ( ) ) ;
2013-10-18 17:20:34 +00:00
return true ;
2014-06-14 04:06:34 +00:00
}
2014-06-30 18:31:04 +00:00
network - > learnBridgeRoute ( sourceMac , origin ) ;
}
2014-06-14 04:06:34 +00:00
2014-06-30 18:31:04 +00:00
if ( ! nconf - > permitsEtherType ( etherType ) ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s) into %.16llx: ethertype %u is not allowed " , source ( ) . toString ( ) . c_str ( ) , nwid , _remoteAddress . toString ( ) . c_str ( ) , etherType ) ;
return true ;
}
2014-06-14 04:06:34 +00:00
2014-06-30 18:31:04 +00:00
if ( ! network - > updateAndCheckMulticastBalance ( origin , dest , frameLen ) ) {
// Rate limits can only be checked by members of this network, but
// there should be enough of them that over-limit multicasts get
// their propagation aborted.
TRACE ( " dropped MULTICAST_FRAME from %s(%s): rate limits exceeded for sender %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , origin . toString ( ) . c_str ( ) ) ;
return true ;
2013-09-30 15:05:35 +00:00
}
2014-06-30 18:31:04 +00:00
network - > tapPut ( sourceMac , dest . mac ( ) , etherType , frame , frameLen ) ;
2013-09-27 20:03:13 +00:00
}
2013-09-25 21:41:49 +00:00
}
2013-08-28 20:01:27 +00:00
2014-06-23 15:19:41 +00:00
// Depth of 0xffff means "do not forward." Check first since
// incrementing this would integer overflow a 16-bit int.
2013-09-30 15:05:35 +00:00
if ( depth = = 0xffff ) {
TRACE ( " not forwarding MULTICAST_FRAME from %s(%s): depth == 0xffff (do not forward) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
return true ;
}
2014-06-23 15:19:41 +00:00
// Check if graph traversal depth has exceeded configured maximum.
2013-09-30 17:51:56 +00:00
if ( + + depth > maxDepth ) {
2013-09-30 15:05:35 +00:00
TRACE ( " not forwarding MULTICAST_FRAME from %s(%s): max propagation depth reached " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-09-27 20:03:13 +00:00
return true ;
}
2013-12-22 18:56:03 +00:00
// Update depth in packet with new incremented value
2013-09-26 21:45:19 +00:00
setAt ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH , ( uint16_t ) depth ) ;
// New FIFO with room for one extra, since head will be next hop
unsigned char newFifo [ ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO + ZT_ADDRESS_LENGTH ] ;
unsigned char * newFifoPtr = newFifo ;
2013-10-02 17:50:42 +00:00
unsigned char * const newFifoEnd = newFifo + sizeof ( newFifo ) ;
// Copy old FIFO into new buffer, terminating at first NULL address
for ( unsigned char * f = fifo , * const fifoEnd = ( fifo + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO ) ; f ! = fifoEnd ; ) {
unsigned char * nf = newFifoPtr ;
unsigned char * e = nf + ZT_ADDRESS_LENGTH ;
unsigned char * ftmp = f ;
unsigned char zeroCheckMask = 0 ;
while ( nf ! = e )
zeroCheckMask | = ( * ( nf + + ) = * ( ftmp + + ) ) ;
if ( zeroCheckMask ) {
f = ftmp ;
newFifoPtr = nf ;
} else break ;
2013-09-25 21:41:49 +00:00
}
2013-08-21 15:45:06 +00:00
2014-06-30 18:31:04 +00:00
// Add any other next hops we know about to FIFO
Multicaster : : AddToPropagationQueue appender (
& newFifoPtr ,
newFifoEnd ,
bloom ,
bloomNonce ,
origin ,
prefixBits ,
prefix ,
2014-09-24 20:53:03 +00:00
RR - > topology ,
2014-06-30 18:31:04 +00:00
Utils : : now ( ) ) ;
if ( nconf ) {
for ( std : : set < Address > : : const_iterator ab ( nconf - > activeBridges ( ) . begin ( ) ) ; ab ! = nconf - > activeBridges ( ) . end ( ) ; + + ab ) {
if ( ! appender ( * ab ) )
break ;
}
}
2014-09-24 20:53:03 +00:00
RR - > mc - > getNextHops ( nwid , dest , appender ) ;
2013-09-26 21:45:19 +00:00
2013-12-22 18:56:03 +00:00
// Zero-terminate new FIFO if not completely full. We pad the remainder with
// zeroes because this improves data compression ratios.
2013-09-26 21:45:19 +00:00
while ( newFifoPtr ! = newFifoEnd )
* ( newFifoPtr + + ) = ( unsigned char ) 0 ;
// First element in newFifo[] is next hop
Address nextHop ( newFifo , ZT_ADDRESS_LENGTH ) ;
2014-09-24 20:53:03 +00:00
if ( ( ! nextHop ) & & ( ! RR - > topology - > amSupernode ( ) ) ) {
SharedPtr < Peer > supernode ( RR - > topology - > getBestSupernode ( & origin , 1 , true ) ) ;
2013-09-30 20:31:22 +00:00
if ( supernode )
nextHop = supernode - > address ( ) ;
}
2014-09-24 20:53:03 +00:00
if ( ( ! nextHop ) | | ( nextHop = = RR - > identity . address ( ) ) ) { // check against our addr is a sanity check
2013-10-03 18:38:07 +00:00
//TRACE("not forwarding MULTICAST_FRAME from %s(%s): no next hop",source().toString().c_str(),_remoteAddress.toString().c_str());
2013-09-27 20:03:13 +00:00
return true ;
2013-07-11 22:15:51 +00:00
}
2013-09-25 21:41:49 +00:00
2013-09-27 20:03:13 +00:00
// The rest of newFifo[] goes back into the packet
memcpy ( fifo , newFifo + ZT_ADDRESS_LENGTH , ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO ) ;
// Send to next hop, reusing this packet as scratch space
newInitializationVector ( ) ;
setDestination ( nextHop ) ;
2014-09-24 20:53:03 +00:00
setSource ( RR - > identity . address ( ) ) ;
2013-09-27 20:03:13 +00:00
compress ( ) ; // note: bloom filters and empty FIFOs are highly compressable!
2014-09-24 20:53:03 +00:00
RR - > sw - > send ( * this , true ) ;
2013-09-27 20:03:13 +00:00
2013-09-25 21:41:49 +00:00
return true ;
2013-07-11 22:15:51 +00:00
} catch ( std : : exception & ex ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped MULTICAST_FRAME from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;
2013-07-11 21:52:04 +00:00
} catch ( . . . ) {
2013-07-12 02:06:25 +00:00
TRACE ( " dropped MULTICAST_FRAME from %s(%s): unexpected exception: (unknown) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
2013-07-11 21:52:04 +00:00
}
2014-09-30 23:28:25 +00:00
# endif
2013-09-25 21:41:49 +00:00
2013-07-12 02:06:25 +00:00
return true ;
2013-07-11 20:19:06 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doMULTICAST_LIKE ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-09-27 20:03:13 +00:00
{
try {
2013-10-07 21:00:53 +00:00
uint64_t now = Utils : : now ( ) ;
2013-09-27 20:03:13 +00:00
// Iterate through 18-byte network,MAC,ADI tuples
2014-09-30 23:28:25 +00:00
for ( unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ; ptr < size ( ) ; ptr + = 18 )
2014-10-10 00:58:31 +00:00
RR - > mc - > add ( now , at < uint64_t > ( ptr ) , MulticastGroup ( MAC ( field ( ptr + 8 , 6 ) , 6 ) , at < uint32_t > ( ptr + 14 ) ) , Address ( ) , peer - > address ( ) ) ;
2013-12-24 18:39:29 +00:00
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_LIKE , 0 , Packet : : VERB_NOP , now ) ;
2013-09-27 20:03:13 +00: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 20:53:03 +00:00
bool IncomingPacket : : _doNETWORK_MEMBERSHIP_CERTIFICATE ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-29 17:56:20 +00:00
{
2013-10-16 21:47:26 +00:00
try {
2013-10-17 10:41:52 +00:00
CertificateOfMembership com ;
2013-12-24 18:39:29 +00:00
2013-10-17 10:41:52 +00:00
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ;
while ( ptr < size ( ) ) {
ptr + = com . deserialize ( * this , ptr ) ;
2014-10-01 00:26:34 +00:00
if ( com . hasRequiredFields ( ) ) {
SharedPtr < Network > network ( RR - > nc - > network ( com . networkId ( ) ) ) ;
if ( network )
network - > addMembershipCertificate ( com , false ) ;
2013-10-16 21:47:26 +00:00
}
}
2013-12-24 18:39:29 +00:00
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_NETWORK_MEMBERSHIP_CERTIFICATE , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
2013-10-16 21:47:26 +00: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 21:17:34 +00:00
return true ;
2013-07-29 17:56:20 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doNETWORK_CONFIG_REQUEST ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-29 17:56:20 +00:00
{
2013-08-02 21:17:34 +00:00
try {
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID ) ;
2014-09-30 23:28:25 +00:00
2013-08-02 21:17:34 +00:00
# ifndef __WINDOWS__
2014-09-24 20:53:03 +00:00
if ( RR - > netconfService ) {
2013-08-13 01:25:36 +00:00
char tmp [ 128 ] ;
2013-08-02 21:17:34 +00:00
unsigned int dictLen = at < uint16_t > ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN ) ;
Dictionary request ;
2013-08-05 16:16:25 +00:00
if ( dictLen )
request [ " meta " ] = std : : string ( ( const char * ) field ( ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT , dictLen ) , dictLen ) ;
2013-08-02 21:17:34 +00:00
request [ " type " ] = " netconf-request " ;
request [ " peerId " ] = peer - > identity ( ) . toString ( false ) ;
2014-05-24 00:10:23 +00:00
Utils : : snprintf ( tmp , sizeof ( tmp ) , " %.16llx " , ( unsigned long long ) nwid ) ;
2013-08-02 21:17:34 +00:00
request [ " nwid " ] = tmp ;
2014-05-24 00:10:23 +00:00
Utils : : snprintf ( tmp , sizeof ( tmp ) , " %.16llx " , ( unsigned long long ) packetId ( ) ) ;
2013-08-02 21:17:34 +00:00
request [ " requestId " ] = tmp ;
2013-10-18 13:48:02 +00:00
if ( ! hops ( ) )
request [ " from " ] = _remoteAddress . toString ( ) ;
2013-08-06 05:28:56 +00:00
//TRACE("to netconf:\n%s",request.toString().c_str());
2014-09-24 20:53:03 +00:00
RR - > netconfService - > send ( request ) ;
2013-08-02 21:17:34 +00:00
} else {
# endif // !__WINDOWS__
2014-09-30 23:28:25 +00:00
// Send unsupported operation if there is no netconf service
// configured on this node (or if this is a Windows machine,
// which doesn't support that at all).
2014-09-24 20:53:03 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2013-08-02 21:17:34 +00:00
outp . append ( ( unsigned char ) Packet : : VERB_NETWORK_CONFIG_REQUEST ) ;
outp . append ( packetId ( ) ) ;
outp . append ( ( unsigned char ) Packet : : ERROR_UNSUPPORTED_OPERATION ) ;
outp . append ( nwid ) ;
2013-09-27 20:03:13 +00:00
outp . armor ( peer - > key ( ) , true ) ;
2014-03-19 20:56:48 +00:00
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
2014-09-30 23:28:25 +00:00
2013-08-02 21:17:34 +00:00
# ifndef __WINDOWS__
}
# endif // !__WINDOWS__
2014-09-30 23:28:25 +00:00
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_NETWORK_CONFIG_REQUEST , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
2013-08-02 21:17:34 +00: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 17:56:20 +00:00
}
2014-09-24 20:53:03 +00:00
bool IncomingPacket : : _doNETWORK_CONFIG_REFRESH ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
2013-07-29 17:56:20 +00:00
{
2013-08-02 21:17:34 +00:00
try {
2013-10-17 09:37:01 +00:00
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD ;
while ( ( ptr + sizeof ( uint64_t ) ) < = size ( ) ) {
uint64_t nwid = at < uint64_t > ( ptr ) ; ptr + = sizeof ( uint64_t ) ;
2014-09-24 20:53:03 +00:00
SharedPtr < Network > nw ( RR - > nc - > network ( nwid ) ) ;
2013-10-25 17:43:04 +00:00
if ( ( nw ) & & ( source ( ) = = nw - > controller ( ) ) ) { // only respond to requests from controller
TRACE ( " NETWORK_CONFIG_REFRESH from %s, refreshing network %.16llx " , source ( ) . toString ( ) . c_str ( ) , nwid ) ;
2013-10-17 09:37:01 +00:00
nw - > requestConfiguration ( ) ;
2013-10-25 17:43:04 +00:00
}
2013-10-17 09:37:01 +00:00
}
2014-09-24 20:53:03 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_NETWORK_CONFIG_REFRESH , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
2013-08-02 21:17:34 +00: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 ;
2013-07-29 17:56:20 +00:00
}
2014-09-26 21:18:25 +00:00
bool IncomingPacket : : _doMULTICAST_GATHER ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2014-09-30 23:28:25 +00:00
try {
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID ) ;
MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC , 6 ) , 6 ) , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI ) ) ;
unsigned int gatherLimit = at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT ) ;
2014-10-10 00:58:31 +00: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 23:28:25 +00:00
if ( gatherLimit ) {
2014-10-10 00:58:31 +00:00
Packet outp ( peer - > address ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
2014-09-30 23:28:25 +00:00
outp . append ( ( unsigned char ) Packet : : VERB_MULTICAST_GATHER ) ;
outp . append ( packetId ( ) ) ;
outp . append ( nwid ) ;
mg . mac ( ) . appendTo ( outp ) ;
outp . append ( ( uint32_t ) mg . adi ( ) ) ;
2014-10-05 17:34:25 +00:00
if ( RR - > mc - > gather ( peer - > address ( ) , nwid , mg , outp , gatherLimit ) ) {
2014-09-30 23:28:25 +00:00
outp . armor ( peer - > key ( ) , true ) ;
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
}
}
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_GATHER , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
} 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 21:18:25 +00:00
}
bool IncomingPacket : : _doMULTICAST_FRAME ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer )
{
2014-09-30 23:28:25 +00:00
try {
2014-10-09 19:42:25 +00:00
uint64_t nwid = at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID ) ;
unsigned int flags = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS ] ;
2014-09-30 23:28:25 +00:00
2014-10-09 19:42:25 +00:00
SharedPtr < Network > network ( RR - > nc - > network ( nwid ) ) ; // will be NULL if not a member
if ( network ) {
// Offset -- size of optional fields added to position of later fields
unsigned int offset = 0 ;
2014-09-30 23:28:25 +00:00
2014-10-09 19:42:25 +00:00
if ( ( flags & 0x01 ) ! = 0 ) {
CertificateOfMembership com ;
offset + = com . deserialize ( * this , ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM ) ;
if ( com . hasRequiredFields ( ) )
network - > addMembershipCertificate ( com , false ) ;
}
2014-09-30 23:28:25 +00:00
2014-10-09 19:42:25 +00: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 23:28:25 +00:00
2014-10-09 19:42:25 +00:00
unsigned int gatherLimit = 0 ;
if ( ( flags & 0x02 ) ! = 0 ) {
gatherLimit = at < uint32_t > ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT ) ;
offset + = 4 ;
}
2014-09-30 23:28:25 +00:00
2014-10-09 19:42:25 +00:00
MAC from ;
if ( ( flags & 0x04 ) ! = 0 ) {
from . setTo ( field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC , 6 ) , 6 ) ;
offset + = 6 ;
} else {
2014-10-10 00:58:31 +00:00
from . fromAddress ( peer - > address ( ) , nwid ) ;
2014-10-09 19:42:25 +00:00
}
2014-09-30 23:28:25 +00:00
2014-10-09 19:42:25 +00:00
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 ) ) ;
unsigned int etherType = at < uint16_t > ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE ) ;
unsigned int payloadLen = size ( ) - ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME ) ;
2014-10-01 23:29:52 +00:00
2014-10-10 00:58:31 +00:00
//TRACE("<<MC FRAME %.16llx/%s from %s@%s flags %.2x length %u",nwid,to.toString().c_str(),from.toString().c_str(),peer->address().toString().c_str(),flags,payloadLen);
2014-10-10 16:09:56 +00:00
if ( ( payloadLen > 0 ) & & ( payloadLen < = ZT_IF_MTU ) ) {
2014-10-09 19:42:25 +00: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 23:29:52 +00:00
}
2014-10-01 00:26:34 +00:00
2014-10-09 19:42:25 +00: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-10-01 00:33:20 +00:00
}
2014-10-01 00:26:34 +00:00
}
2014-10-09 19:42:25 +00:00
2014-10-10 00:58:31 +00:00
network - > tapPut ( from , to . mac ( ) , etherType , field ( offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME , payloadLen ) , payloadLen ) ;
2014-09-30 23:28:25 +00:00
}
2014-10-09 19:42:25 +00:00
if ( gatherLimit ) {
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_OK ) ;
outp . append ( ( unsigned char ) Packet : : VERB_MULTICAST_FRAME ) ;
outp . append ( packetId ( ) ) ;
outp . append ( nwid ) ;
to . mac ( ) . appendTo ( outp ) ;
outp . append ( ( uint32_t ) to . adi ( ) ) ;
outp . append ( ( unsigned char ) 0x02 ) ; // flag 0x02 = contains gather results
if ( RR - > mc - > gather ( peer - > address ( ) , nwid , to , outp , gatherLimit ) ) {
outp . armor ( peer - > key ( ) , true ) ;
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
}
}
} // else ignore -- not a member of this network
2014-09-30 23:28:25 +00:00
peer - > receive ( RR , _fromSock , _remoteAddress , hops ( ) , packetId ( ) , Packet : : VERB_MULTICAST_FRAME , 0 , Packet : : VERB_NOP , Utils : : now ( ) ) ;
} 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 21:18:25 +00:00
}
2014-09-24 20:53:03 +00:00
void IncomingPacket : : _sendErrorNeedCertificate ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer , uint64_t nwid )
2014-06-18 16:00:53 +00:00
{
2014-09-24 20:53:03 +00:00
Packet outp ( source ( ) , RR - > identity . address ( ) , Packet : : VERB_ERROR ) ;
2014-06-18 16:00:53 +00: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 ) ;
_fromSock - > send ( _remoteAddress , outp . data ( ) , outp . size ( ) ) ;
}
2014-10-02 20:50:37 +00:00
void IncomingPacket : : _parseGatherResults ( const RuntimeEnvironment * RR , const SharedPtr < Peer > & peer , uint64_t nwid , const MulticastGroup & mg , unsigned int offset )
{
//unsigned int totalKnown = at<uint32_t>(offset);
unsigned int count = at < uint16_t > ( offset + 4 ) ;
const unsigned char * p = ( const unsigned char * ) data ( ) + offset + 6 ;
const unsigned char * e = ( const unsigned char * ) data ( ) + size ( ) ;
Address atmp ;
uint64_t now = Utils : : now ( ) ;
for ( unsigned int i = 0 ; i < count ; + + i ) {
const unsigned char * n = p + ZT_ADDRESS_LENGTH ;
if ( n > e )
break ;
atmp . setTo ( p , ZT_ADDRESS_LENGTH ) ;
RR - > mc - > add ( now , nwid , mg , peer - > address ( ) , atmp ) ;
p = n ;
}
}
2013-07-11 20:19:06 +00:00
} // namespace ZeroTier