summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/IncomingPacket.cpp66
-rw-r--r--node/Multicaster.cpp17
-rw-r--r--node/Multicaster.hpp8
3 files changed, 45 insertions, 46 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index 68771daa..2753aa7c 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -604,52 +604,54 @@ bool IncomingPacket::_doP5_MULTICAST_FRAME(const RuntimeEnvironment *RR,const Sh
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));
+ // To support legacy peers, old fashioned "P5" multicasts are propagated manually by supernodes.
+ // If the sending peer is >=1.0.0, they only go to legacy peers. Otherwise they go to all
+ // peers.
+
+ const unsigned int limit = 128; // use a fairly generous limit since we want legacy peers to always work until they go away
+ const bool senderIsLegacy = (peer->remoteVersionMajor() < 1);
+
+ std::vector<Address> members(RR->mc->getMembers(nwid,dest,limit));
setAt(ZT_PROTO_VERB_P5_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH,(uint16_t)0xffff);
setSource(RR->identity.address());
compress();
-
- unsigned int count = 0;
- for(std::vector<Address>::iterator lp(legacyPeers.begin());lp!=legacyPeers.end();++lp) {
- if ((*lp != origin)&&(*lp != source())) {
+ for(std::vector<Address>::iterator lp(members.begin());lp!=members.end();++lp) {
+ SharedPtr<Peer> lpp(RR->topology->getPeer(*lp));
+ if ( (*lp != origin) && (*lp != peer->address()) && ((senderIsLegacy) || (!lpp) || (lpp->remoteVersionMajor() < 1)) ) {
newInitializationVector();
setDestination(*lp);
RR->sw->send(*this,true);
- if (++count >= 128) // harded-coded sanity limit for these legacy nodes
- break;
}
}
+ }
- return true;
- } 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);
- }
+ SharedPtr<Network> network(RR->nc->network(nwid));
+ 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());
+ if (!network->isAllowed(origin)) {
+ _sendErrorNeedCertificate(RR,peer,network->id());
+ return true;
+ }
+
+ if ((frameLen > 0)&&(frameLen <= 2800)) {
+ 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;
}
- 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);
- }
+ network->tapPut(sourceMac,dest.mac(),etherType,frame,frameLen);
}
}
} catch (std::exception &ex) {
diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp
index 25884431..1269d35b 100644
--- a/node/Multicaster.cpp
+++ b/node/Multicaster.cpp
@@ -118,21 +118,18 @@ restart_member_scan:
return added;
}
-std::vector<Address> Multicaster::getLegacySubscribers(uint64_t nwid,const MulticastGroup &mg) const
+std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup &mg,unsigned int limit) const
{
std::vector<Address> ls;
Mutex::Lock _l(_groups_m);
-
std::map< std::pair<uint64_t,MulticastGroup>,MulticastGroupStatus >::const_iterator gs(_groups.find(std::pair<uint64_t,MulticastGroup>(nwid,mg)));
if (gs == _groups.end())
return ls;
-
- for(std::vector<MulticastGroupMember>::const_iterator m(gs->second.members.begin());m!=gs->second.members.end();++m) {
- SharedPtr<Peer> p(RR->topology->getPeer(m->address));
- if ((p)&&(p->remoteVersionKnown())&&(p->remoteVersionMajor() < 1))
- ls.push_back(m->address);
+ for(std::vector<MulticastGroupMember>::const_reverse_iterator m(gs->second.members.rbegin());m!=gs->second.members.rend();++m) {
+ ls.push_back(m->address);
+ if (ls.size() >= limit)
+ break;
}
-
return ls;
}
@@ -281,7 +278,9 @@ void Multicaster::send(
outp.append((unsigned char)0);
RR->identity.address().appendTo(outp);
outp.append((const void *)&rn,3); // random multicast ID
- src.appendTo(outp);
+ if (src)
+ src.appendTo(outp);
+ else MAC(RR->identity.address(),nwid).appendTo(outp);
mg.mac().appendTo(outp);
outp.append((uint32_t)mg.adi());
outp.append((uint16_t)etherType);
diff --git a/node/Multicaster.hpp b/node/Multicaster.hpp
index 74151251..ed9c0d30 100644
--- a/node/Multicaster.hpp
+++ b/node/Multicaster.hpp
@@ -120,14 +120,12 @@ public:
unsigned int gather(const Address &queryingPeer,uint64_t nwid,const MulticastGroup &mg,Packet &appendTo,unsigned int limit) const;
/**
- * Get known peers with versions <1.0.0 and that are not supernodes
- *
- * This is legacy peer compatibility code and will be removed later.
+ * Get subscribers to a multicast group
*
* @param nwid Network ID
* @param mg Multicast group
*/
- std::vector<Address> getLegacySubscribers(uint64_t nwid,const MulticastGroup &mg) const;
+ std::vector<Address> getMembers(uint64_t nwid,const MulticastGroup &mg,unsigned int limit) const;
/**
* Send a multicast
@@ -138,7 +136,7 @@ public:
* @param nwid Network ID
* @param alwaysSendTo Send to these peers first and even if not included in subscriber list
* @param mg Multicast group
- * @param src Source Ethernet MAC address
+ * @param src Source Ethernet MAC address or NULL to skip in packet and compute from ZT address (non-bridged mode)
* @param etherType Ethernet frame type
* @param data Packet data
* @param len Length of packet data