diff options
| -rw-r--r-- | node/Cluster.cpp | 2 | ||||
| -rw-r--r-- | node/IncomingPacket.cpp | 13 | ||||
| -rw-r--r-- | node/Network.cpp | 27 | ||||
| -rw-r--r-- | node/Network.hpp | 6 | 
4 files changed, 27 insertions, 21 deletions
diff --git a/node/Cluster.cpp b/node/Cluster.cpp index 55503f63..b9359dc6 100644 --- a/node/Cluster.cpp +++ b/node/Cluster.cpp @@ -476,7 +476,7 @@ void Cluster::handleIncomingStateMessage(const void *msg,unsigned int len)  						if (network) {  							// Copy into a Packet just to conform to Network API. Eventually  							// will want to refactor. -							network->handleConfigChunk(Packet(dmsg),ptr); +							network->handleConfigChunk(0,Address(),Packet(dmsg),ptr);  						}  					}	break;  				} diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index e703af59..c11b0377 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -461,12 +461,8 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p  			case Packet::VERB_NETWORK_CONFIG_REQUEST: {  				const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_OK_IDX_PAYLOAD))); -				if (network) { -#ifdef ZT_ENABLE_CLUSTER -					RR->cluster->broadcastNetworkConfigChunk(field(ZT_PACKET_IDX_PAYLOAD,size() - ZT_PROTO_VERB_OK_IDX_PAYLOAD),size() - ZT_PROTO_VERB_OK_IDX_PAYLOAD); -#endif -					network->handleConfigChunk(*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD); -				} +				if (network) +					network->handleConfigChunk(packetId(),source(),*this,ZT_PROTO_VERB_OK_IDX_PAYLOAD);  			}	break;  			case Packet::VERB_MULTICAST_GATHER: { @@ -926,10 +922,7 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,const Shared  	try {  		const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PACKET_IDX_PAYLOAD)));  		if (network) { -#ifdef ZT_ENABLE_CLUSTER -			RR->cluster->broadcastNetworkConfigChunk(field(ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD),size() - ZT_PACKET_IDX_PAYLOAD); -#endif -			const uint64_t configUpdateId = network->handleConfigChunk(*this,ZT_PACKET_IDX_PAYLOAD); +			const uint64_t configUpdateId = network->handleConfigChunk(packetId(),source(),*this,ZT_PACKET_IDX_PAYLOAD);  			if (configUpdateId) {  				Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);  				outp.append((uint8_t)Packet::VERB_ECHO); diff --git a/node/Network.cpp b/node/Network.cpp index ec1bcb33..320dcf39 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -34,6 +34,7 @@  #include "NetworkController.hpp"  #include "Node.hpp"  #include "Peer.hpp" +#include "Cluster.hpp"  // Uncomment to make the rules engine dump trace info to stdout  //#define ZT_RULES_ENGINE_DEBUGGING 1 @@ -908,7 +909,7 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg)  		_myMulticastGroups.erase(i);  } -uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr) +uint64_t Network::handleConfigChunk(const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr)  {  	const unsigned int start = ptr; @@ -931,12 +932,12 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)  			chunkIndex = chunk.at<uint32_t>(ptr); ptr += 4;  			if (((chunkIndex + chunkLen) > totalLength)||(totalLength >= ZT_NETWORKCONFIG_DICT_CAPACITY)) { // >= since we need room for a null at the end -				TRACE("discarded chunk from %s: invalid length or length overflow",chunk.source().toString().c_str()); +				TRACE("discarded chunk from %s: invalid length or length overflow",source.toString().c_str());  				return 0;  			}  			if ((chunk[ptr] != 1)||(chunk.at<uint16_t>(ptr + 1) != ZT_C25519_SIGNATURE_LEN)) { -				TRACE("discarded chunk from %s: unrecognized signature type",chunk.source().toString().c_str()); +				TRACE("discarded chunk from %s: unrecognized signature type",source.toString().c_str());  				return 0;  			}  			const uint8_t *sig = reinterpret_cast<const uint8_t *>(chunk.field(ptr + 3,ZT_C25519_SIGNATURE_LEN)); @@ -964,30 +965,35 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)  			// If it's not a duplicate, check chunk signature  			const Identity controllerId(RR->topology->getIdentity(controller()));  			if (!controllerId) { // we should always have the controller identity by now, otherwise how would we have queried it the first time? -				TRACE("unable to verify chunk from %s: don't have controller identity",chunk.source().toString().c_str()); +				TRACE("unable to verify chunk from %s: don't have controller identity",source.toString().c_str());  				return 0;  			}  			if (!controllerId.verify(chunk.field(start,ptr - start),ptr - start,sig,ZT_C25519_SIGNATURE_LEN)) { -				TRACE("discarded chunk from %s: signature check failed",chunk.source().toString().c_str()); +				TRACE("discarded chunk from %s: signature check failed",source.toString().c_str());  				return 0;  			} +#ifdef ZT_ENABLE_CLUSTER +			if (source) +				RR->cluster->broadcastNetworkConfigChunk(chunk.field(start,chunk.size() - start),chunk.size() - start); +#endif +  			// New properly verified chunks can be flooded "virally" through the network  			if (fastPropagate) {  				Address *a = (Address *)0;  				Membership *m = (Membership *)0;  				Hashtable<Address,Membership>::Iterator i(_memberships);  				while (i.next(a,m)) { -					if ((*a != chunk.source())&&(*a != controller())) { +					if ((*a != source)&&(*a != controller())) {  						Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CONFIG);  						outp.append(reinterpret_cast<const uint8_t *>(chunk.data()) + start,chunk.size() - start);  						RR->sw->send(outp,true);  					}  				}  			} -		} else if (chunk.source() == controller()) { +		} else if ((source == controller())||(!source)) { // since old chunks aren't signed, only accept from controller itself (or via cluster backplane)  			// Legacy support for OK(NETWORK_CONFIG_REQUEST) from older controllers -			chunkId = chunk.packetId(); +			chunkId = packetId;  			configUpdateId = chunkId;  			totalLength = chunkLen;  			chunkIndex = 0; @@ -999,6 +1005,11 @@ uint64_t Network::handleConfigChunk(const Packet &chunk,unsigned int ptr)  				if ((!c)||(_incomingConfigChunks[i].ts < c->ts))  					c = &(_incomingConfigChunks[i]);  			} + +#ifdef ZT_ENABLE_CLUSTER +			if (source) +				RR->cluster->broadcastNetworkConfigChunk(chunk.field(start,chunk.size() - start),chunk.size() - start); +#endif  		} else {  			TRACE("discarded single-chunk unsigned legacy config: this is only allowed if the sender is the controller itself");  			return 0; diff --git a/node/Network.hpp b/node/Network.hpp index 1627be58..85ee6e9a 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -181,11 +181,13 @@ public:  	 * chunks via OK(NETWORK_CONFIG_REQUEST) or NETWORK_CONFIG. It verifies  	 * each chunk and once assembled applies the configuration.  	 * -	 * @param chunk Packet containing chunk +	 * @param packetId Packet ID or 0 if none (e.g. via cluster path) +	 * @param source Address of sender of chunk or NULL if none (e.g. via cluster path) +	 * @param chunk Buffer containing chunk  	 * @param ptr Index of chunk and related fields in packet  	 * @return Update ID if update was fully assembled and accepted or 0 otherwise  	 */ -	uint64_t handleConfigChunk(const Packet &chunk,unsigned int ptr); +	uint64_t handleConfigChunk(const uint64_t packetId,const Address &source,const Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &chunk,unsigned int ptr);  	/**  	 * Set network configuration  | 
