Răsfoiți Sursa

Fix to cluster network configs.

Adam Ierymenko 8 ani în urmă
părinte
comite
ed31cb76d6
4 a modificat fișierele cu 27 adăugiri și 21 ștergeri
  1. 1 1
      node/Cluster.cpp
  2. 3 10
      node/IncomingPacket.cpp
  3. 19 8
      node/Network.cpp
  4. 4 2
      node/Network.hpp

+ 1 - 1
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;
 				}

+ 3 - 10
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);

+ 19 - 8
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;

+ 4 - 2
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