Bridge routing table - GitHub issue #68

This commit is contained in:
Adam Ierymenko 2014-06-10 17:18:59 -07:00
parent 6f831d5370
commit d44e1349d8
3 changed files with 69 additions and 3 deletions

View File

@ -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

View File

@ -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)

View File

@ -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;