Parcourir la source

Push NETWORK_CONFIG_REFRESH on POSTs to /member/... in controller.

Adam Ierymenko il y a 9 ans
Parent
commit
ccea3d04d6
6 fichiers modifiés avec 68 ajouts et 0 suppressions
  1. 2 0
      controller/EmbeddedNetworkController.cpp
  2. 21 0
      include/ZeroTierOne.h
  3. 7 0
      node/Network.cpp
  4. 5 0
      node/Network.hpp
  5. 32 0
      node/Node.cpp
  6. 1 0
      node/Node.hpp

+ 2 - 0
controller/EmbeddedNetworkController.cpp

@@ -1081,6 +1081,8 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
 
 					_writeJson(_memberJP(nwid,Address(address),true).c_str(),member);
 
+					_node->pushNetworkRefresh(address,nwid,(const uint64_t *)0,(const uint64_t *)0,0);
+
 					// Add non-persisted fields
 					member["clock"] = now;
 

+ 21 - 0
include/ZeroTierOne.h

@@ -1853,6 +1853,27 @@ enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,v
  */
 void ZT_Node_circuitTestEnd(ZT_Node *node,ZT_CircuitTest *test);
 
+/**
+ * Push a network refresh
+ *
+ * This is used by network controller implementations to send a
+ * NETWORK_CONFIG_REFRESH message to tell a node to refresh its
+ * config and to optionally push one or more credential timestamp
+ * blacklist thresholds for members of the network.
+ *
+ * Code outside a controller implementation will have no use for
+ * this as these messages are ignored if they do not come from a
+ * controller.
+ *
+ * @param node Node instance
+ * @param dest ZeroTier address of destination to which to send NETWORK_CONFIG_REFRESH
+ * @param nwid Network ID
+ * @param blacklistAddresses Array of ZeroTier addresses of network members to set timestamp blacklists for
+ * @param blacklistBeforeTimestamps Timestamps before which to blacklist credentials for each corresponding address in blacklistAddresses[]
+ * @param blacklistCount Size of blacklistAddresses[] and blacklistBeforeTimestamps[]
+ */
+void ZT_Node_pushNetworkRefresh(ZT_Node *node,uint64_t dest,uint64_t nwid,const uint64_t *blacklistAddresses,const uint64_t *blacklistBeforeTimestamps,unsigned int blacklistCount);
+
 /**
  * Initialize cluster operation
  *

+ 7 - 0
node/Network.cpp

@@ -402,6 +402,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
 	_portInitialized(false),
 	_inboundConfigPacketId(0),
 	_lastConfigUpdate(0),
+	_lastRequestedConfiguration(0),
 	_destroyed(false),
 	_netconfFailure(NETCONF_FAILURE_NONE),
 	_portError(0)
@@ -691,6 +692,12 @@ void Network::handleInboundConfigChunk(const uint64_t inRePacketId,const void *d
 
 void Network::requestConfiguration()
 {
+	// Sanity limit: do not request more often than once per second
+	const uint64_t now = RR->node->now();
+	if ((now - _lastRequestedConfiguration) < 1000ULL)
+		return;
+	_lastRequestedConfiguration = RR->node->now();
+
 	Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> rmd;
 	rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION);
 	rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,(uint64_t)ZT_PROTO_VERSION);

+ 5 - 0
node/Network.hpp

@@ -249,6 +249,10 @@ public:
 
 	/**
 	 * Causes this network to request an updated configuration from its master node now
+	 *
+	 * There is a circuit breaker here to prevent this from being done more often
+	 * than once per second. This is to prevent things like NETWORK_CONFIG_REFRESH
+	 * from causing multiple requests.
 	 */
 	void requestConfiguration();
 
@@ -442,6 +446,7 @@ private:
 
 	NetworkConfig _config;
 	volatile uint64_t _lastConfigUpdate;
+	volatile uint64_t _lastRequestedConfiguration;
 
 	volatile bool _destroyed;
 

+ 32 - 0
node/Node.cpp

@@ -548,6 +548,31 @@ void Node::circuitTestEnd(ZT_CircuitTest *test)
 	}
 }
 
+void Node::pushNetworkRefresh(uint64_t dest,uint64_t nwid,const uint64_t *blacklistAddresses,const uint64_t *blacklistBeforeTimestamps,unsigned int blacklistCount)
+{
+	Packet outp(Address(dest),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REFRESH);
+	outp.append(nwid);
+	outp.addSize(2);
+	unsigned int c = 0;
+	for(unsigned int i=0;i<blacklistCount;++i) {
+		if ((outp.size() + 13) >= ZT_PROTO_MAX_PACKET_LENGTH) {
+			outp.setAt<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 8,(uint16_t)c);
+			RR->sw->send(outp,true);
+			outp = Packet(Address(dest),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REFRESH);
+			outp.append(nwid);
+			outp.addSize(2);
+			c = 0;
+		}
+		Address(blacklistAddresses[i]).appendTo(outp);
+		outp.append(blacklistBeforeTimestamps[i]);
+		++c;
+	}
+	if (c > 0) {
+		outp.setAt<uint16_t>(ZT_PACKET_IDX_PAYLOAD + 8,(uint16_t)c);
+		RR->sw->send(outp,true);
+	}
+}
+
 ZT_ResultCode Node::clusterInit(
 	unsigned int myId,
 	const struct sockaddr_storage *zeroTierPhysicalEndpoints,
@@ -935,6 +960,13 @@ void ZT_Node_circuitTestEnd(ZT_Node *node,ZT_CircuitTest *test)
 	} catch ( ... ) {}
 }
 
+void ZT_Node_pushNetworkRefresh(ZT_Node *node,uint64_t dest,uint64_t nwid,const uint64_t *blacklistAddresses,const uint64_t *blacklistBeforeTimestamps,unsigned int blacklistCount)
+{
+	try {
+		reinterpret_cast<ZeroTier::Node *>(node)->pushNetworkRefresh(dest,nwid,blacklistAddresses,blacklistBeforeTimestamps,blacklistCount);
+	} catch ( ... ) {}
+}
+
 enum ZT_ResultCode ZT_Node_clusterInit(
 	ZT_Node *node,
 	unsigned int myId,

+ 1 - 0
node/Node.hpp

@@ -102,6 +102,7 @@ public:
 	void setNetconfMaster(void *networkControllerInstance);
 	ZT_ResultCode circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *));
 	void circuitTestEnd(ZT_CircuitTest *test);
+	void pushNetworkRefresh(uint64_t dest,uint64_t nwid,const uint64_t *blacklistAddresses,const uint64_t *blacklistBeforeTimestamps,unsigned int blacklistCount);
 	ZT_ResultCode clusterInit(
 		unsigned int myId,
 		const struct sockaddr_storage *zeroTierPhysicalEndpoints,