summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--node/Constants.hpp11
-rw-r--r--node/Network.cpp25
-rw-r--r--node/Network.hpp36
3 files changed, 69 insertions, 3 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp
index 37a3b3a9..6634836f 100644
--- a/node/Constants.hpp
+++ b/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
diff --git a/node/Network.cpp b/node/Network.cpp
index d55101c2..3091638a 100644
--- a/node/Network.cpp
+++ b/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)
diff --git a/node/Network.hpp b/node/Network.hpp
index 26766ffb..b40afd45 100644
--- a/node/Network.hpp
+++ b/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;