From a3db7d0728c1bc5181b8a70e8c379632125ee376 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 1 Oct 2015 11:11:52 -0700 Subject: Refactor: move network COMs out of Network and into Peer in prep for tightening up multicast lookup and other things. --- node/Network.hpp | 45 ++++++++++----------------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) (limited to 'node/Network.hpp') diff --git a/node/Network.hpp b/node/Network.hpp index ad9f18de..37077650 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -56,6 +56,7 @@ namespace ZeroTier { class RuntimeEnvironment; class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths; +class Peer; /** * A virtual LAN @@ -94,6 +95,12 @@ public: */ inline Address controller() throw() { return Address(_id >> 24); } + /** + * @param nwid Network ID + * @return Address of network's controller + */ + static inline Address controllerFor(uint64_t nwid) throw() { return Address(nwid >> 24); } + /** * @return Multicast group memberships for this network's port (local, not learned via bridging) */ @@ -177,33 +184,10 @@ public: void requestConfiguration(); /** - * Add or update a membership certificate - * - * @param cert Certificate of membership - * @return True if certificate was accepted as valid - */ - bool validateAndAddMembershipCertificate(const CertificateOfMembership &cert); - - /** - * Check if we should push membership certificate to a peer, AND update last pushed - * - * If we haven't pushed a cert to this peer in a long enough time, this returns - * true and updates the last pushed time. Otherwise it returns false. - * - * This doesn't actually send anything, since COMs can hitch a ride with several - * different kinds of packets. - * - * @param to Destination peer - * @param now Current time - * @return True if we should include a COM with whatever we're currently sending - */ - bool peerNeedsOurMembershipCertificate(const Address &to,uint64_t now); - - /** - * @param peer Peer address to check + * @param peer Peer to check * @return True if peer is allowed to communicate on this network */ - inline bool isAllowed(const Address &peer) const + inline bool isAllowed(const SharedPtr &peer) const { Mutex::Lock _l(_lock); return _isAllowed(peer); @@ -347,16 +331,9 @@ public: inline bool operator>=(const Network &n) const throw() { return (_id >= n._id); } private: - struct _RemoteMemberCertificateInfo - { - _RemoteMemberCertificateInfo() : com(),lastPushed(0) {} - CertificateOfMembership com; // remote member's COM - uint64_t lastPushed; // when did we last push ours to them? - }; - ZT_VirtualNetworkStatus _status() const; void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked - bool _isAllowed(const Address &peer) const; + bool _isAllowed(const SharedPtr &peer) const; void _announceMulticastGroups(); std::vector _allMulticastGroups() const; @@ -370,8 +347,6 @@ private: Hashtable< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge) Hashtable< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges) - Hashtable< Address,_RemoteMemberCertificateInfo > _certInfo; - SharedPtr _config; // Most recent network configuration, which is an immutable value-object volatile uint64_t _lastConfigUpdate; -- cgit v1.2.3 From 9405150b1147189586c427bc9e1fd9abb00b7ca0 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 1 Oct 2015 11:37:02 -0700 Subject: Restore group announcement on Peer::receive() but centralize packet composition in one place. --- node/Network.cpp | 91 +++++++++++++++++++---------------- node/Network.hpp | 11 ++++- node/Peer.cpp | 144 ++++++++++++++++++++++++------------------------------- 3 files changed, 123 insertions(+), 123 deletions(-) (limited to 'node/Network.hpp') diff --git a/node/Network.cpp b/node/Network.cpp index 9c8aabfa..d86145da 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -141,6 +141,12 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg) _myMulticastGroups.swap(nmg); } +bool Network::tryAnnounceMulticastGroupsTo(const SharedPtr &peer) +{ + Mutex::Lock _l(_lock); + return _tryAnnounceMulticastGroupsTo(RR->topology->rootAddresses(),_allMulticastGroups(),peer,RR->node->now()); +} + bool Network::applyConfiguration(const SharedPtr &conf) { if (_destroyed) // sanity check @@ -394,65 +400,56 @@ bool Network::_isAllowed(const SharedPtr &peer) const return false; // default position on any failure } -std::vector Network::_allMulticastGroups() const -{ - // Assumes _lock is locked - std::vector mgs; - mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1); - mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end()); - _multicastGroupsBehindMe.appendKeys(mgs); - if ((_config)&&(_config->enableBroadcast())) - mgs.push_back(Network::BROADCAST); - std::sort(mgs.begin(),mgs.end()); - mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end()); - return mgs; -} - // Used in Network::_announceMulticastGroups() class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths { public: _AnnounceMulticastGroupsToPeersWithActiveDirectPaths(const RuntimeEnvironment *renv,Network *nw) : - RR(renv), _now(renv->node->now()), + RR(renv), _network(nw), _rootAddresses(renv->topology->rootAddresses()), _allMulticastGroups(nw->_allMulticastGroups()) {} - inline void operator()(Topology &t,const SharedPtr &p) - { - if ( ( (p->hasActiveDirectPath(_now)) && ( (_network->_isAllowed(p)) || (p->address() == _network->controller()) ) ) || (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) ) { - Packet outp(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - - for(std::vector::iterator mg(_allMulticastGroups.begin());mg!=_allMulticastGroups.end();++mg) { - if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) { - outp.armor(p->key(),true); - p->send(RR,outp.data(),outp.size(),_now); - outp.reset(p->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - } - - // network ID, MAC, ADI - outp.append((uint64_t)_network->id()); - mg->mac().appendTo(outp); - outp.append((uint32_t)mg->adi()); - } - - if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { - outp.armor(p->key(),true); - p->send(RR,outp.data(),outp.size(),_now); - } - } - } + inline void operator()(Topology &t,const SharedPtr &p) { _network->_tryAnnounceMulticastGroupsTo(_rootAddresses,_allMulticastGroups,p,_now); } private: - const RuntimeEnvironment *RR; uint64_t _now; + const RuntimeEnvironment *RR; Network *_network; std::vector
_rootAddresses; std::vector _allMulticastGroups; }; +bool Network::_tryAnnounceMulticastGroupsTo(const std::vector
&alwaysAddresses,const std::vector &allMulticastGroups,const SharedPtr &peer,uint64_t now) const +{ + if ( ( (peer->hasActiveDirectPath(now)) && ( _isAllowed(peer) || (peer->address() == this->controller()) ) ) || (std::find(alwaysAddresses.begin(),alwaysAddresses.end(),peer->address()) != alwaysAddresses.end()) ) { + Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + + for(std::vector::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { + if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) { + outp.armor(peer->key(),true); + peer->send(RR,outp.data(),outp.size(),now); + outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + } + + // network ID, MAC, ADI + outp.append((uint64_t)_id); + mg->mac().appendTo(outp); + outp.append((uint32_t)mg->adi()); + } + + if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { + outp.armor(peer->key(),true); + peer->send(RR,outp.data(),outp.size(),now); + } + + return true; + } + return false; +} + void Network::_announceMulticastGroups() { // Assumes _lock is locked @@ -460,4 +457,18 @@ void Network::_announceMulticastGroups() RR->topology->eachPeer<_AnnounceMulticastGroupsToPeersWithActiveDirectPaths &>(afunc); } +std::vector Network::_allMulticastGroups() const +{ + // Assumes _lock is locked + std::vector mgs; + mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1); + mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end()); + _multicastGroupsBehindMe.appendKeys(mgs); + if ((_config)&&(_config->enableBroadcast())) + mgs.push_back(Network::BROADCAST); + std::sort(mgs.begin(),mgs.end()); + mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end()); + return mgs; +} + } // namespace ZeroTier diff --git a/node/Network.hpp b/node/Network.hpp index 37077650..b942e5f9 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -93,7 +93,7 @@ public: /** * @return Address of network's controller (most significant 40 bits of ID) */ - inline Address controller() throw() { return Address(_id >> 24); } + inline Address controller() const throw() { return Address(_id >> 24); } /** * @param nwid Network ID @@ -140,6 +140,14 @@ public: */ void multicastUnsubscribe(const MulticastGroup &mg); + /** + * Announce multicast groups to a peer if that peer is authorized on this network + * + * @param peer Peer to try to announce multicast groups to + * @return True if peer was authorized and groups were announced + */ + bool tryAnnounceMulticastGroupsTo(const SharedPtr &peer); + /** * Apply a NetworkConfig to this network * @@ -334,6 +342,7 @@ private: ZT_VirtualNetworkStatus _status() const; void _externalConfig(ZT_VirtualNetworkConfig *ec) const; // assumes _lock is locked bool _isAllowed(const SharedPtr &peer) const; + bool _tryAnnounceMulticastGroupsTo(const std::vector
&rootAddresses,const std::vector &allMulticastGroups,const SharedPtr &peer,uint64_t now) const; void _announceMulticastGroups(); std::vector _allMulticastGroups() const; diff --git a/node/Peer.cpp b/node/Peer.cpp index 6203d0b4..d98e0807 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -96,106 +96,86 @@ void Peer::received( Packet::Verb inReVerb) { const uint64_t now = RR->node->now(); - Mutex::Lock _l(_lock); + bool needMulticastGroupAnnounce = false; - _lastReceive = now; + { + Mutex::Lock _l(_lock); - if (!hops) { - bool pathIsConfirmed = false; + _lastReceive = now; - /* Learn new paths from direct (hops == 0) packets */ - { - unsigned int np = _numPaths; - for(unsigned int p=0;preceived(now); - _numPaths = np; - pathIsConfirmed = true; - _sortPaths(now); - } + if (slot) { + *slot = RemotePath(localAddr,remoteAddr,false); + slot->received(now); + _numPaths = np; + pathIsConfirmed = true; + _sortPaths(now); + } - } else { + } else { - /* If this path is not known, send a HELLO. We don't learn - * paths without confirming that a bidirectional link is in - * fact present, but any packet that decodes and authenticates - * correctly is considered valid. */ - if ((now - _lastPathConfirmationSent) >= ZT_MIN_PATH_CONFIRMATION_INTERVAL) { - _lastPathConfirmationSent = now; - TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),remoteAddr.toString().c_str()); - attemptToContactAt(RR,localAddr,remoteAddr,now); - } + /* If this path is not known, send a HELLO. We don't learn + * paths without confirming that a bidirectional link is in + * fact present, but any packet that decodes and authenticates + * correctly is considered valid. */ + if ((now - _lastPathConfirmationSent) >= ZT_MIN_PATH_CONFIRMATION_INTERVAL) { + _lastPathConfirmationSent = now; + TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),remoteAddr.toString().c_str()); + attemptToContactAt(RR,localAddr,remoteAddr,now); + } + } } } } - /* Announce multicast groups of interest to direct peers if they are - * considered authorized members of a given network. Also announce to - * root servers and network controllers. */ - /* - if ((pathIsConfirmed)&&((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000))) { + if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) { _lastAnnouncedTo = now; - - const bool isRoot = RR->topology->isRoot(_id); - - Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - const std::vector< SharedPtr > networks(RR->node->allNetworks()); - for(std::vector< SharedPtr >::const_iterator n(networks.begin());n!=networks.end();++n) { - if ( (isRoot) || ((*n)->isAllowed(_id.address())) || (_id.address() == (*n)->controller()) ) { - const std::vector mgs((*n)->allMulticastGroups()); - for(std::vector::const_iterator mg(mgs.begin());mg!=mgs.end();++mg) { - if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) { - outp.armor(_key,true); - RR->node->putPacket(localAddr,remoteAddr,outp.data(),outp.size()); - outp.reset(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - } - - // network ID, MAC, ADI - outp.append((uint64_t)(*n)->id()); - mg->mac().appendTo(outp); - outp.append((uint32_t)mg->adi()); - } - } - } - if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { - outp.armor(_key,true); - RR->node->putPacket(localAddr,remoteAddr,outp.data(),outp.size()); - } + needMulticastGroupAnnounce = true; } - */ + + if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME)) + _lastUnicastFrame = now; + else if (verb == Packet::VERB_MULTICAST_FRAME) + _lastMulticastFrame = now; } - if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME)) - _lastUnicastFrame = now; - else if (verb == Packet::VERB_MULTICAST_FRAME) - _lastMulticastFrame = now; + if (needMulticastGroupAnnounce) { + const std::vector< SharedPtr > networks(RR->node->allNetworks()); + for(std::vector< SharedPtr >::const_iterator n(networks.begin());n!=networks.end();++n) + (*n)->tryAnnounceMulticastGroupsTo(SharedPtr(this)); + } } void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now) -- cgit v1.2.3 From d6676a9d6cffed96850d7da7daffbf329109a7d5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 1 Oct 2015 12:50:19 -0700 Subject: Always announce multicast groups, not just to peers with direct links, and push network COMs to any MULTICAST_LIKE recipient for future use. --- node/Network.cpp | 81 ++++++++++++++++++++++++++++++++------------------------ node/Network.hpp | 4 +-- 2 files changed, 49 insertions(+), 36 deletions(-) (limited to 'node/Network.hpp') diff --git a/node/Network.cpp b/node/Network.cpp index d86145da..a9e4e55b 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -400,11 +400,53 @@ bool Network::_isAllowed(const SharedPtr &peer) const return false; // default position on any failure } -// Used in Network::_announceMulticastGroups() -class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths +bool Network::_tryAnnounceMulticastGroupsTo(const std::vector
&alwaysAddresses,const std::vector &allMulticastGroups,const SharedPtr &peer,uint64_t now) const +{ + // assumes _lock is locked + if ( + (_isAllowed(peer)) || + (peer->address() == this->controller()) || + (std::find(alwaysAddresses.begin(),alwaysAddresses.end(),peer->address()) != alwaysAddresses.end()) + ) { + + if ((_config)&&(_config->com())&&(!_config->isPublic())&&(peer->needsOurNetworkMembershipCertificate(_id,now,true))) { + Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE); + _config->com().serialize(outp); + outp.armor(peer->key(),true); + peer->send(RR,outp.data(),outp.size(),now); + } + + { + Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + + for(std::vector::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { + if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) { + outp.armor(peer->key(),true); + peer->send(RR,outp.data(),outp.size(),now); + outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + } + + // network ID, MAC, ADI + outp.append((uint64_t)_id); + mg->mac().appendTo(outp); + outp.append((uint32_t)mg->adi()); + } + + if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { + outp.armor(peer->key(),true); + peer->send(RR,outp.data(),outp.size(),now); + } + } + + return true; + } + return false; +} + +class _AnnounceMulticastGroupsToAll { public: - _AnnounceMulticastGroupsToPeersWithActiveDirectPaths(const RuntimeEnvironment *renv,Network *nw) : + _AnnounceMulticastGroupsToAll(const RuntimeEnvironment *renv,Network *nw) : _now(renv->node->now()), RR(renv), _network(nw), @@ -421,40 +463,11 @@ private: std::vector
_rootAddresses; std::vector _allMulticastGroups; }; - -bool Network::_tryAnnounceMulticastGroupsTo(const std::vector
&alwaysAddresses,const std::vector &allMulticastGroups,const SharedPtr &peer,uint64_t now) const -{ - if ( ( (peer->hasActiveDirectPath(now)) && ( _isAllowed(peer) || (peer->address() == this->controller()) ) ) || (std::find(alwaysAddresses.begin(),alwaysAddresses.end(),peer->address()) != alwaysAddresses.end()) ) { - Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - - for(std::vector::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { - if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) { - outp.armor(peer->key(),true); - peer->send(RR,outp.data(),outp.size(),now); - outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - } - - // network ID, MAC, ADI - outp.append((uint64_t)_id); - mg->mac().appendTo(outp); - outp.append((uint32_t)mg->adi()); - } - - if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { - outp.armor(peer->key(),true); - peer->send(RR,outp.data(),outp.size(),now); - } - - return true; - } - return false; -} - void Network::_announceMulticastGroups() { // Assumes _lock is locked - _AnnounceMulticastGroupsToPeersWithActiveDirectPaths afunc(RR,this); - RR->topology->eachPeer<_AnnounceMulticastGroupsToPeersWithActiveDirectPaths &>(afunc); + _AnnounceMulticastGroupsToAll afunc(RR,this); + RR->topology->eachPeer<_AnnounceMulticastGroupsToAll &>(afunc); } std::vector Network::_allMulticastGroups() const diff --git a/node/Network.hpp b/node/Network.hpp index b942e5f9..f7939323 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -55,8 +55,8 @@ namespace ZeroTier { class RuntimeEnvironment; -class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths; class Peer; +class _AnnounceMulticastGroupsToAll; // internal function object in Network.cpp /** * A virtual LAN @@ -64,7 +64,7 @@ class Peer; class Network : NonCopyable { friend class SharedPtr; - friend class _AnnounceMulticastGroupsToPeersWithActiveDirectPaths; + friend class _AnnounceMulticastGroupsToAll; public: /** -- cgit v1.2.3 From 35676217e8fea27d271bbc3b976165e1f8436da1 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 23 Oct 2015 14:50:07 -0700 Subject: Refactor multicast group announcement to work directly or indirectly. --- node/Cluster.cpp | 6 ++- node/Network.cpp | 120 ++++++++++++++++++++++++++++++------------------------- node/Network.hpp | 5 ++- 3 files changed, 73 insertions(+), 58 deletions(-) (limited to 'node/Network.hpp') diff --git a/node/Cluster.cpp b/node/Cluster.cpp index 4088c967..900804b7 100644 --- a/node/Cluster.cpp +++ b/node/Cluster.cpp @@ -449,11 +449,12 @@ void Cluster::replicateHavePeer(const Identity &peerId) void Cluster::replicateMulticastLike(uint64_t nwid,const Address &peerAddress,const MulticastGroup &group) { - Buffer<4096> buf; + Buffer<2048> buf; buf.append((uint64_t)nwid); peerAddress.appendTo(buf); group.mac().appendTo(buf); buf.append((uint32_t)group.adi()); + TRACE("replicating %s MULTICAST_LIKE %.16llx/%s/%u to all members",peerAddress.toString().c_str(),nwid,group.mac().toString().c_str(),(unsigned int)group.adi()); { Mutex::Lock _l(_memberIds_m); for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { @@ -465,8 +466,9 @@ void Cluster::replicateMulticastLike(uint64_t nwid,const Address &peerAddress,co void Cluster::replicateCertificateOfNetworkMembership(const CertificateOfMembership &com) { - Buffer<4096> buf; + Buffer<2048> buf; com.serialize(buf); + TRACE("replicating %s COM for %.16llx to all members",com.issuedTo().toString().c_str(),com.networkId()); { Mutex::Lock _l(_memberIds_m); for(std::vector::const_iterator mid(_memberIds.begin());mid!=_memberIds.end();++mid) { diff --git a/node/Network.cpp b/node/Network.cpp index 46f93241..cd30e386 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -144,7 +144,15 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg) bool Network::tryAnnounceMulticastGroupsTo(const SharedPtr &peer) { Mutex::Lock _l(_lock); - return _tryAnnounceMulticastGroupsTo(RR->topology->rootAddresses(),_allMulticastGroups(),peer,RR->node->now()); + if ( + (_isAllowed(peer)) || + (peer->address() == this->controller()) || + (RR->topology->isRoot(peer->identity())) + ) { + _announceMulticastGroupsTo(peer->address(),_allMulticastGroups()); + return true; + } + return false; } bool Network::applyConfiguration(const SharedPtr &conf) @@ -400,77 +408,80 @@ bool Network::_isAllowed(const SharedPtr &peer) const return false; // default position on any failure } -bool Network::_tryAnnounceMulticastGroupsTo(const std::vector
&alwaysAddresses,const std::vector &allMulticastGroups,const SharedPtr &peer,uint64_t now) const -{ - // assumes _lock is locked - if ( - (_isAllowed(peer)) || - (peer->address() == this->controller()) || - (std::find(alwaysAddresses.begin(),alwaysAddresses.end(),peer->address()) != alwaysAddresses.end()) - ) { - - if ((_config)&&(_config->com())&&(!_config->isPublic())&&(peer->needsOurNetworkMembershipCertificate(_id,now,true))) { - Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE); - _config->com().serialize(outp); - outp.armor(peer->key(),true); - peer->send(RR,outp.data(),outp.size(),now); - } - - { - Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - - for(std::vector::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { - if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) { - outp.armor(peer->key(),true); - peer->send(RR,outp.data(),outp.size(),now); - outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); - } - - // network ID, MAC, ADI - outp.append((uint64_t)_id); - mg->mac().appendTo(outp); - outp.append((uint32_t)mg->adi()); - } - - if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { - outp.armor(peer->key(),true); - peer->send(RR,outp.data(),outp.size(),now); - } - } - - return true; - } - return false; -} - -class _AnnounceMulticastGroupsToAll +class _GetPeersThatNeedMulticastAnnouncement { public: - _AnnounceMulticastGroupsToAll(const RuntimeEnvironment *renv,Network *nw) : + _GetPeersThatNeedMulticastAnnouncement(const RuntimeEnvironment *renv,Network *nw) : _now(renv->node->now()), + _controller(nw->controller()), _network(nw), - _rootAddresses(renv->topology->rootAddresses()), - _allMulticastGroups(nw->_allMulticastGroups()) + _rootAddresses(renv->topology->rootAddresses()) {} - - inline void operator()(Topology &t,const SharedPtr &p) { _network->_tryAnnounceMulticastGroupsTo(_rootAddresses,_allMulticastGroups,p,_now); } - + inline void operator()(Topology &t,const SharedPtr &p) + { + if ( + (_network->_isAllowed(p)) || + (p->address() == _controller) || + (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) + ) { + peers.push_back(p->address()); + } + } + std::vector
peers; private: uint64_t _now; + Address _controller; Network *_network; std::vector
_rootAddresses; - std::vector _allMulticastGroups; }; void Network::_announceMulticastGroups() { // Assumes _lock is locked - _AnnounceMulticastGroupsToAll afunc(RR,this); - RR->topology->eachPeer<_AnnounceMulticastGroupsToAll &>(afunc); + + _GetPeersThatNeedMulticastAnnouncement gpfunc(RR,this); + RR->topology->eachPeer<_GetPeersThatNeedMulticastAnnouncement &>(gpfunc); + + std::vector allMulticastGroups(_allMulticastGroups()); + for(std::vector
::const_iterator pa(gpfunc.peers.begin());pa!=gpfunc.peers.end();++pa) + _announceMulticastGroupsTo(*pa,allMulticastGroups); +} + +void Network::_announceMulticastGroupsTo(const Address &peerAddress,const std::vector &allMulticastGroups) const +{ + // Assumes _lock is locked + + // We push COMs ahead of MULTICAST_LIKE since they're used for access control -- a COM is a public + // credential so "over-sharing" isn't really an issue (and we only do so with roots). + if ((_config)&&(_config->com())&&(!_config->isPublic())) { + Packet outp(peerAddress,RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE); + _config->com().serialize(outp); + RR->sw->send(outp,true,0); + } + + { + Packet outp(peerAddress,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + + for(std::vector::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { + if ((outp.size() + 18) >= ZT_UDP_DEFAULT_PAYLOAD_MTU) { + RR->sw->send(outp,true,0); + outp.reset(peerAddress,RR->identity.address(),Packet::VERB_MULTICAST_LIKE); + } + + // network ID, MAC, ADI + outp.append((uint64_t)_id); + mg->mac().appendTo(outp); + outp.append((uint32_t)mg->adi()); + } + + if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) + RR->sw->send(outp,true,0); + } } std::vector Network::_allMulticastGroups() const { // Assumes _lock is locked + std::vector mgs; mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1); mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end()); @@ -479,6 +490,7 @@ std::vector Network::_allMulticastGroups() const mgs.push_back(Network::BROADCAST); std::sort(mgs.begin(),mgs.end()); mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end()); + return mgs; } diff --git a/node/Network.hpp b/node/Network.hpp index f7939323..0effa8e2 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -56,7 +56,7 @@ namespace ZeroTier { class RuntimeEnvironment; class Peer; -class _AnnounceMulticastGroupsToAll; // internal function object in Network.cpp +class _GetPeersThatNeedMulticastAnnouncement; /** * A virtual LAN @@ -64,7 +64,7 @@ class _AnnounceMulticastGroupsToAll; // internal function object in Network.cpp class Network : NonCopyable { friend class SharedPtr; - friend class _AnnounceMulticastGroupsToAll; + friend class _GetPeersThatNeedMulticastAnnouncement; // internal function object public: /** @@ -344,6 +344,7 @@ private: bool _isAllowed(const SharedPtr &peer) const; bool _tryAnnounceMulticastGroupsTo(const std::vector
&rootAddresses,const std::vector &allMulticastGroups,const SharedPtr &peer,uint64_t now) const; void _announceMulticastGroups(); + void _announceMulticastGroupsTo(const Address &peerAddress,const std::vector &allMulticastGroups) const; std::vector _allMulticastGroups() const; const RuntimeEnvironment *RR; -- cgit v1.2.3