瀏覽代碼

Bridge routing table - GitHub issue #68

Adam Ierymenko 11 年之前
父節點
當前提交
d44e1349d8
共有 3 個文件被更改,包括 69 次插入3 次删除
  1. 11 0
      node/Constants.hpp
  2. 25 0
      node/Network.cpp
  3. 33 3
      node/Network.hpp

+ 11 - 0
node/Constants.hpp

@@ -396,4 +396,15 @@ error_no_byte_order_defined;
  */
 #define ZT_UPDATE_HTTP_TIMEOUT 30
 
+/**
+ * Sanity limit on maximum bridge routes
+ *
+ * If the number of bridge routes exceeds this, we cull routes from the
+ * bridges with the most MACs behind them until it doesn't. This is a
+ * sanity limit to prevent memory-filling DOS attacks, nothing more. No
+ * physical LAN has anywhere even close to this many nodes. Note that this
+ * does not limit the size of ZT virtual LANs, only bridge routing.
+ */
+#define ZT_MAX_BRIDGE_ROUTES 67108864
+
 #endif

+ 25 - 0
node/Network.cpp

@@ -333,6 +333,31 @@ void Network::threadMain()
 	}
 }
 
+void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
+{
+	Mutex::Lock _l(_lock);
+	_bridgeRoutes[mac] = addr;
+
+	// If _bridgeRoutes exceeds sanity limit, trim worst offenders until below -- denial of service circuit breaker
+	while (_bridgeRoutes.size() > ZT_MAX_BRIDGE_ROUTES) {
+		std::map<Address,unsigned long> counts;
+		Address maxAddr;
+		unsigned long maxCount = 0;
+		for(std::map<MAC,Address>::iterator br(_bridgeRoutes.begin());br!=_bridgeRoutes.end();++br) {
+			unsigned long c = ++counts[br->second];
+			if (c > maxCount) {
+				maxCount = c;
+				maxAddr = br->second;
+			}
+		}
+		for(std::map<MAC,Address>::iterator br(_bridgeRoutes.begin());br!=_bridgeRoutes.end();) {
+			if (br->second == maxAddr)
+				_bridgeRoutes.erase(br++);
+			else ++br;
+		}
+	}
+}
+
 void Network::_restoreState()
 {
 	if (!_id)

+ 33 - 3
node/Network.hpp

@@ -416,6 +416,27 @@ public:
 		return std::set<InetAddress>();
 	}
 
+	/**
+	 * @param mac MAC address
+	 * @return ZeroTier address of bridge to this MAC or null address if not found
+	 */
+	inline Address findBridgeTo(const MAC &mac) const
+	{
+		Mutex::Lock _l(_lock);
+		std::map<MAC,Address>::const_iterator br(_bridgeRoutes.find(mac));
+		if (br == _bridgeRoutes.end())
+			return Address();
+		return br->second;
+	}
+
+	/**
+	 * Set a bridge route
+	 *
+	 * @param mac MAC address of destination
+	 * @param addr Bridge this MAC is reachable behind
+	 */
+	void learnBridgeRoute(const MAC &mac,const Address &addr);
+
 private:
 	static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data);
 
@@ -424,24 +445,33 @@ private:
 	void _dumpMulticastCerts();
 
 	uint64_t _id;
-	NodeConfig *_nc;
-	MAC _mac;
+	NodeConfig *_nc; // parent NodeConfig object
+	MAC _mac; // local MAC address
 	const RuntimeEnvironment *_r;
-	EthernetTap *volatile _tap;
+	EthernetTap *volatile _tap; // tap device or NULL if not initialized yet
+
 	std::set<MulticastGroup> _multicastGroups;
 	std::map< std::pair<Address,MulticastGroup>,BandwidthAccount > _multicastRateAccounts;
+
 	std::map<Address,CertificateOfMembership> _membershipCertificates;
 	std::map<Address,uint64_t> _lastPushedMembershipCertificate;
+
+	std::map<MAC,Address> _bridgeRoutes;
+
 	SharedPtr<NetworkConfig> _config;
 	volatile uint64_t _lastConfigUpdate;
+
 	volatile bool _destroyOnDelete;
+
 	volatile enum {
 		NETCONF_FAILURE_NONE,
 		NETCONF_FAILURE_ACCESS_DENIED,
 		NETCONF_FAILURE_NOT_FOUND,
 		NETCONF_FAILURE_INIT_FAILED
 	} _netconfFailure;
+
 	Thread _setupThread;
+
 	Mutex _lock;
 
 	AtomicCounter __refCount;