@ -494,106 +494,106 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
{
try {
SharedPtr < Network > network ( _r - > nc - > network ( at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID ) ) ) ;
if ( network ) {
if ( network - > isAllowed ( source ( ) ) ) {
if ( size ( ) > ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD ) {
Address originalSubmitterAddress ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER_ADDRESS , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
MAC fromMac ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC , 6 ) ) ;
MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DESTINATION_MAC , 6 ) ) , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI ) ) ;
unsigned int hops = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOP_COUNT ] ;
unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE ) ;
unsigned int datalen = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD_LENGTH ) ;
unsigned int signaturelen = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SIGNATURE_LENGTH ) ;
unsigned char * dataAndSignature = field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD , datalen + signaturelen ) ;
uint64_t mccrc = Multicaster : : computeMulticastDedupCrc ( network - > id ( ) , fromMac , mg , etherType , dataAndSignature , datalen ) ;
uint64_t now = Utils : : now ( ) ;
bool isDuplicate = _r - > multicaster - > checkDuplicate ( mccrc , now ) ;
if ( originalSubmitterAddress = = _r - > identity . address ( ) ) {
// Technically should not happen, since the original submitter is
// excluded from consideration as a propagation recipient.
TRACE ( " dropped boomerang MULTICAST_FRAME received from %s(%s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
} else if ( ( ! isDuplicate ) | | ( _r - > topology - > amSupernode ( ) ) ) {
//
// If I am a supernode, I will repeatedly propagate duplicates. That's
// because supernodes are used to bridge sparse multicast groups. Non-
// supernodes will ignore duplicates completely.
//
// TODO: supernodes should keep a local bloom filter too and OR it with
// the bloom from the packet in order to pick different recipients each
// time a multicast returns to them for repropagation.
//
SharedPtr < Peer > originalSubmitter ( _r - > topology - > getPeer ( originalSubmitterAddress ) ) ;
if ( ! originalSubmitter ) {
TRACE ( " requesting WHOIS on original multicast frame submitter %s " , originalSubmitterAddress . toString ( ) . c_str ( ) ) ;
_r - > sw - > requestWhois ( originalSubmitterAddress ) ;
_step = DECODE_WAITING_FOR_MULTICAST_FRAME_ORIGINAL_SENDER_LOOKUP ;
return false ; // try again if/when we get OK(WHOIS)
} else if ( Multicaster : : verifyMulticastPacket ( originalSubmitter - > identity ( ) , network - > id ( ) , fromMac , mg , etherType , dataAndSignature , datalen , dataAndSignature + datalen , signaturelen ) ) {
_r - > multicaster - > addToDedupHistory ( mccrc , now ) ;
// Even if we are a supernode, we still don't repeatedly inject
// duplicates into our own tap.
if ( ! isDuplicate )
network - > tap ( ) . put ( fromMac , mg . mac ( ) , etherType , dataAndSignature , datalen ) ;
if ( + + hops < ZT_MULTICAST_PROPAGATION_DEPTH ) {
Address upstream ( source ( ) ) ; // save this since we mangle it
Multicaster : : MulticastBloomFilter bloom ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM_FILTER , ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES ) ) ;
SharedPtr < Peer > propPeers [ ZT_MULTICAST_PROPAGATION_BREADTH ] ;
unsigned int np = _r - > multicaster - > pickNextPropagationPeers (
* ( _r - > prng ) ,
* ( _r - > topology ) ,
network - > id ( ) ,
mg ,
originalSubmitterAddress ,
upstream ,
bloom ,
ZT_MULTICAST_PROPAGATION_BREADTH ,
propPeers ,
now ) ;
// In a bit of a hack, we re-use this packet to repeat it
// to our multicast propagation recipients. Afterwords we
// return true just to be sure this is the end of this
// packet's life cycle, since it is now mangled.
setSource ( _r - > identity . address ( ) ) ;
( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOP_COUNT ] = hops ;
memcpy ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM_FILTER , ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES ) , bloom . data ( ) , ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES ) ;
compress ( ) ;
for ( unsigned int i = 0 ; i < np ; + + i ) {
//TRACE("propagating multicast from original node %s: %s -> %s",originalSubmitterAddress.toString().c_str(),upstream.toString().c_str(),propPeers[i]->address().toString().c_str());
// Re-use this packet to re-send multicast frame to everyone
// downstream from us.
newInitializationVector ( ) ;
setDestination ( propPeers [ i ] - > address ( ) ) ;
_r - > sw - > send ( * this , true ) ;
}
return true ;
} else {
//TRACE("terminating MULTICAST_FRAME propagation from %s(%s): max depth reached",source().toString().c_str(),_remoteAddress.toString().c_str());
if ( ( network ) & & ( network - > isAllowed ( source ( ) ) ) ) {
Address originalSubmitterAddress ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER_ADDRESS , ZT_ADDRESS_LENGTH ) , ZT_ADDRESS_LENGTH ) ;
MAC fromMac ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC , 6 ) ) ;
MulticastGroup mg ( MAC ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DESTINATION_MAC , 6 ) ) , at < uint32_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ADI ) ) ;
unsigned int hops = ( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOP_COUNT ] ;
unsigned int etherType = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE ) ;
unsigned int datalen = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD_LENGTH ) ;
unsigned int signaturelen = at < uint16_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SIGNATURE_LENGTH ) ;
unsigned char * dataAndSignature = field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD , datalen + signaturelen ) ;
uint64_t mccrc = Multicaster : : computeMulticastDedupCrc ( network - > id ( ) , fromMac , mg , etherType , dataAndSignature , datalen ) ;
uint64_t now = Utils : : now ( ) ;
bool isDuplicate = _r - > multicaster - > checkDuplicate ( mccrc , now ) ;
if ( originalSubmitterAddress = = _r - > identity . address ( ) ) {
// Technically should not happen, since the original submitter is
// excluded from consideration as a propagation recipient.
TRACE ( " dropped boomerang MULTICAST_FRAME received from %s(%s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
} else if ( ( ! isDuplicate ) | | ( _r - > topology - > amSupernode ( ) ) ) {
//
// If I am a supernode, I will repeatedly propagate duplicates. That's
// because supernodes are used to bridge sparse multicast groups. Non-
// supernodes will ignore duplicates completely.
//
// TODO: supernodes should keep a local bloom filter too and OR it with
// the bloom from the packet in order to pick different recipients each
// time a multicast returns to them for repropagation.
//
SharedPtr < Peer > originalSubmitter ( _r - > topology - > getPeer ( originalSubmitterAddress ) ) ;
if ( ! originalSubmitter ) {
TRACE ( " requesting WHOIS on original multicast frame submitter %s " , originalSubmitterAddress . toString ( ) . c_str ( ) ) ;
_r - > sw - > requestWhois ( originalSubmitterAddress ) ;
_step = DECODE_WAITING_FOR_MULTICAST_FRAME_ORIGINAL_SENDER_LOOKUP ;
return false ; // try again if/when we get OK(WHOIS)
} else if ( Multicaster : : verifyMulticastPacket ( originalSubmitter - > identity ( ) , network - > id ( ) , fromMac , mg , etherType , dataAndSignature , datalen , dataAndSignature + datalen , signaturelen ) ) {
// In checking the multicast rate, we don't re-check if this is
// a duplicate. That's because if isDuplicate is true it means
// we're a supernode and it's a second pass relay.
if ( ( isDuplicate ) | | ( network - > multicastRateGate ( originalSubmitter - > address ( ) , datalen ) ) ) {
_r - > multicaster - > addToDedupHistory ( mccrc , now ) ;
// Even if we are a supernode, we still don't repeatedly inject
// duplicates into our own tap.
if ( ! isDuplicate )
network - > tap ( ) . put ( fromMac , mg . mac ( ) , etherType , dataAndSignature , datalen ) ;
if ( + + hops < ZT_MULTICAST_PROPAGATION_DEPTH ) {
Address upstream ( source ( ) ) ; // save this since we mangle it
Multicaster : : MulticastBloomFilter bloom ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM_FILTER , ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES ) ) ;
SharedPtr < Peer > propPeers [ ZT_MULTICAST_PROPAGATION_BREADTH ] ;
unsigned int np = _r - > multicaster - > pickNextPropagationPeers (
* ( _r - > prng ) ,
* ( _r - > topology ) ,
network - > id ( ) ,
mg ,
originalSubmitterAddress ,
upstream ,
bloom ,
ZT_MULTICAST_PROPAGATION_BREADTH ,
propPeers ,
now ) ;
// In a bit of a hack, we re-use this packet to repeat it
// to our multicast propagation recipients. Afterwords we
// return true just to be sure this is the end of this
// packet's life cycle, since it is now mangled.
setSource ( _r - > identity . address ( ) ) ;
( * this ) [ ZT_PROTO_VERB_MULTICAST_FRAME_IDX_HOP_COUNT ] = hops ;
memcpy ( field ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_BLOOM_FILTER , ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES ) , bloom . data ( ) , ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES ) ;
compress ( ) ;
for ( unsigned int i = 0 ; i < np ; + + i ) {
//TRACE("propagating multicast from original node %s: %s -> %s",originalSubmitterAddress.toString().c_str(),upstream.toString().c_str(),propPeers[i]->address().toString().c_str());
// Re-use this packet to re-send multicast frame to everyone
// downstream from us.
newInitializationVector ( ) ;
setDestination ( propPeers [ i ] - > address ( ) ) ;
_r - > sw - > send ( * this , true ) ;
}
// Return here just to be safe, since this packet's state is no
// longer valid.
return true ;
} else {
LOG ( " rejected MULTICAST_FRAME from %s(%s) due to failed signature check (falsely claims origin %s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , originalSubmitterAddress . toString ( ) . c_str ( ) ) ;
//TRACE("terminating MULTICAST_FRAME propagation from %s(%s): max depth reached",source().toString().c_str(),_remoteAddress.toString().c_str());
}
} else {
TRACE ( " dropped redundant MULTICAST_FRAME from %s(%s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
LOG ( " dropped MULTICAST_FRAME from original sender %s: rate limit overrun " , originalSubmitter - > address ( ) . toString ( ) . c_str ( ) ) ;
}
} else {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): invalid short packet " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
TRACE ( " rejected MULTICAST_FRAME forwarded by %s(%s): failed signature check (falsely claims origin %s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , originalSubmitter Address . toString ( ) . c_str ( ) ) ;
}
} else {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): not a member of closed network %llu " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , network - > id ( ) ) ;
TRACE ( " dropped duplicate MULTICAST_FRAME from %s(%s) " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) ) ;
}
} else {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): network %llu unknown or we are not a member " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , at < uint64_t > ( ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID ) ) ;
TRACE ( " dropped MULTICAST_FRAME from %s(%s): network %.16llx unknown or sender not allowed " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ( unsigned long long ) network - > id ( ) ) ;
}
} catch ( std : : exception & ex ) {
TRACE ( " dropped MULTICAST_FRAME from %s(%s): unexpected exception: %s " , source ( ) . toString ( ) . c_str ( ) , _remoteAddress . toString ( ) . c_str ( ) , ex . what ( ) ) ;