From 87f1b1b1e35de52d993779bc9de9f988e91147c4 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Oct 2014 13:16:16 -0700 Subject: [PATCH] Bug fix in new multicast frame handler, handling of old "P5" multicast frames in new way. --- node/IncomingPacket.cpp | 86 ++++++++++++++++++++++++++++++++++++++++- node/Packet.hpp | 37 +++++++++--------- node/Peer.cpp | 2 +- 3 files changed, 104 insertions(+), 21 deletions(-) diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 521ca7310..4f449d3e9 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -330,7 +330,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p case Packet::VERB_MULTICAST_FRAME: { unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS]; - if ((flags & 0x01) != 0) { + if ((flags & 0x01) != 0) { // frame includes implicit gather results uint64_t nwid = at(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID); MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC,6),6),at(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI)); _parseGatherResults(RR,peer,nwid,mg,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_GATHER_RESULTS); @@ -548,6 +548,88 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh // though since there aren't likely to be many older nodes left after // we do a software update. + // Quick and dirty -- this is all condemned code in any case + 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(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_NETWORK_ID); + const uint64_t guid = at(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(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_ADI)); + const unsigned int etherType = at(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ETHERTYPE); + const unsigned int frameLen = at(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(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
legacyPeers(RR->mc->getLegacySubscribers(nwid,dest)); + + setAt(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH,(uint16_t)0xffff); + + for(std::vector
::iterator lp(legacyPeers.begin());lp!=legacyPeers.end();++lp) { + if ((*lp != origin)&&(*lp != source())) { + newInitializationVector(); + setDestination(*lp); + setSource(RR->identity.address()); + compress(); + RR->sw->send(*this,true); + } + } + } else { + SharedPtr 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()); + } + #if 0 // old code preserved below try { Address origin(Address(field(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN,ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN),ZT_ADDRESS_LENGTH)); @@ -953,7 +1035,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share unsigned int comLen = 0; if ((flags & 0x01) != 0) { CertificateOfMembership com; - comLen = com.deserialize(*this,ZT_PROTO_VERB_EXT_FRAME_IDX_COM); + comLen = com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM); if (com.hasRequiredFields()) network->addMembershipCertificate(com,false); } diff --git a/node/Packet.hpp b/node/Packet.hpp index 68a4439e2..9dff4405c 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -224,38 +224,38 @@ // P5_MULTICAST_FRAME is deprecated #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH (ZT_PACKET_IDX_PAYLOAD) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH 2 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_FIFO (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_FIFO (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_FIFO 320 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_FIFO) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_FIFO + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_FIFO) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM 1024 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FLAGS (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_FLAGS 1 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS) -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_FLAGS) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX__START_OF_SIGNED_PORTION (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FLAGS) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FLAGS + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_FLAGS) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_NETWORK_ID 8 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_NETWORK_ID) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_NETWORK_ID + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_NETWORK_ID) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM_NONCE 2 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM_NONCE) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_BLOOM_NONCE + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_BLOOM_NONCE) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX_BITS 1 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX_BITS) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX_BITS + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX_BITS) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX 1 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_PREFIX + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_PROPAGATION_PREFIX) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ORIGIN 5 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN_MCID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN_MCID (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ORIGIN) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ORIGIN_MCID 3 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_GUID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_GUID (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_GUID 8 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_SOURCE_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN_MCID + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ORIGIN_MCID) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_SOURCE_MAC (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ORIGIN_MCID + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ORIGIN_MCID) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_SOURCE_MAC 6 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_SOURCE_MAC) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_MAC (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_SOURCE_MAC + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_SOURCE_MAC) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_DEST_MAC 6 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_ADI (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_MAC) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_ADI (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_MAC + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_DEST_MAC) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_DEST_ADI 4 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_DEST_ADI) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_DEST_ADI + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_DEST_ADI) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ETHERTYPE 2 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME_LEN (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_ETHERTYPE) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME_LEN (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_ETHERTYPE + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_ETHERTYPE) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_FRAME_LEN 2 -#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME_LEN + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_FRAME_LEN) +#define ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME (ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_FRAME_LEN + ZT_PROTO_VERB_P5_MULTICAST_FRAME_LEN_FRAME_LEN) #define ZT_PROTO_VERB_P5_MULTICAST_FRAME_FLAGS_HAS_MEMBERSHIP_CERTIFICATE 0x01 #define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD) @@ -272,7 +272,8 @@ #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ORIGIN + 5) #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + 8) #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1) -#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT + 4) +#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_GATHER_LIMIT + 4) +#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI ZT_PROTO_VERB_MULTICAST_FRAME_IDX_COM #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI + 4) #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC + 6) #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SOURCE_MAC + 6) diff --git a/node/Peer.cpp b/node/Peer.cpp index 8012c5fff..540a83a19 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -149,7 +149,7 @@ void Peer::receive( if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME)) _lastUnicastFrame = now; - else if (verb == Packet::VERB_MULTICAST_FRAME) + else if ((verb == Packet::VERB_P5_MULTICAST_FRAME)||(verb == Packet::VERB_MULTICAST_FRAME)) _lastMulticastFrame = now; }