| 
					
				 | 
			
			
				@@ -29,6 +29,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "Buffer.hpp" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "NetworkController.hpp" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "Node.hpp" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "Peer.hpp" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "../version.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -384,17 +385,20 @@ bool Network::_isAllowed(const SharedPtr<Peer> &peer) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// Assumes _lock is locked 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (!_config) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (_config.isPublic()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return ((_config.com)&&(peer->networkMembershipCertificatesAgree(_id,_config.com))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} catch (std::exception &exc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer->address().toString().c_str(),exc.what()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (_config) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (_config.isPublic()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				LockingPtr<Membership> m(peer->membership(_id,false)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (m) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return _config.com.agreesWith(m->com()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} catch ( ... ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		TRACE("isAllowed() check failed for peer %s: unexpected exception: unknown exception",peer->address().toString().c_str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		TRACE("isAllowed() check failed for peer %s: unexpected exception: unexpected exception",peer->address().toString().c_str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return false; // default position on any failure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class _MulticastAnnounceAll 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -405,13 +409,13 @@ public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		_controller(nw->controller()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		_network(nw), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		_anchors(nw->config().anchors()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		_rootAddresses(renv->topology->rootAddresses()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		_upstreamAddresses(renv->topology->upstreamAddresses()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	inline void operator()(Topology &t,const SharedPtr<Peer> &p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if ( (_network->_isAllowed(p)) || // FIXME: this causes multicast LIKEs for public networks to get spammed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( (_network->_isAllowed(p)) || // FIXME: this causes multicast LIKEs for public networks to get spammed, which isn't terrible but is a bit stupid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		     (p->address() == _controller) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		     (std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end()) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		     (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),p->address()) != _upstreamAddresses.end()) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				 (std::find(_anchors.begin(),_anchors.end(),p->address()) != _anchors.end()) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			peers.push_back(p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -422,7 +426,7 @@ private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	const Address _controller; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Network *const _network; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	const std::vector<Address> _anchors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const std::vector<Address> _rootAddresses; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	const std::vector<Address> _upstreamAddresses; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void Network::_announceMulticastGroups() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -438,31 +442,30 @@ void Network::_announceMulticastGroupsTo(const SharedPtr<Peer> &peer,const std:: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// 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())&&(peer->needsOurNetworkMembershipCertificate(_id,RR->node->now(),true))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		_config.com.serialize(outp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		RR->sw->send(outp,true,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// Anyone we announce multicast groups to will need our COM to authenticate GATHER requests. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		Packet outp(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		LockingPtr<Membership> m(peer->membership(_id,false)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (m) m->sendCredentialsIfNeeded(RR,RR->node->now(),*peer,_config); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for(std::vector<MulticastGroup>::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(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Packet outp(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()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for(std::vector<MulticastGroup>::const_iterator mg(allMulticastGroups.begin());mg!=allMulticastGroups.end();++mg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ((outp.size() + 24) >= ZT_PROTO_MAX_PACKET_LENGTH) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			outp.compress(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			RR->sw->send(outp,true,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			outp.reset(peer->address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			RR->sw->send(outp,true,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// 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.compress(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		RR->sw->send(outp,true,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |