diff --git a/node/EthernetTap.hpp b/node/EthernetTap.hpp index 1cd85730d..79dae1271 100644 --- a/node/EthernetTap.hpp +++ b/node/EthernetTap.hpp @@ -170,8 +170,8 @@ public: * This populates a set or, if already populated, modifies it to contain * only multicast groups in which this device is interested. * - * This should always include the blind wildcard MulticastGroup (MAC of - * ff:ff:ff:ff:ff:ff and 0 ADI field). + * This neither includes nor removes the broadcast (ff:ff:ff:ff:ff:ff / 0) + * group. * * @param groups Set to modify in place * @return True if set was changed since last call diff --git a/node/Network.cpp b/node/Network.cpp index 095838d57..d55101c29 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -48,6 +48,8 @@ namespace ZeroTier { +const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xff),0); + const char *Network::statusString(const Status s) throw() { diff --git a/node/Network.hpp b/node/Network.hpp index 44c5d5b5a..26766ffb7 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -108,6 +108,11 @@ private: inline void destroyOnDelete() throw() { _destroyOnDelete = true; } public: + /** + * Broadcast multicast group: ff:ff:ff:ff:ff:ff / 0 + */ + static const MulticastGroup BROADCAST; + /** * Possible network states */ @@ -157,9 +162,22 @@ public: { Mutex::Lock _l(_lock); EthernetTap *t = _tap; - if (t) - return _tap->updateMulticastGroups(_multicastGroups); - return false; + if (t) { + bool updated = _tap->updateMulticastGroups(_multicastGroups); + if ((_config)&&(_config->enableBroadcast())) { + if (_multicastGroups.count(BROADCAST)) + return updated; + else { + _multicastGroups.insert(BROADCAST); + return true; + } + } else { + if (_multicastGroups.count(BROADCAST)) { + _multicastGroups.erase(BROADCAST); + return true; + } else return updated; + } + } else return false; } /** diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 0d6cd0491..cc8dc3821 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -65,9 +65,11 @@ const NetworkConfig::MulticastRate &NetworkConfig::multicastRate(const Multicast return r->second; } -static const std::string _zero("0"); void NetworkConfig::_fromDictionary(const Dictionary &d) { + static const std::string zero("0"); + static const std::string one("1"); + // NOTE: d.get(name) throws if not found, d.get(name,default) returns default memset(_etWhitelist,0,sizeof(_etWhitelist)); @@ -82,9 +84,10 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) throw std::invalid_argument("configuration contains zero network ID"); _timestamp = Utils::hexStrToU64(d.get(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP).c_str()); _issuedTo = Address(d.get(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO)); - _multicastPrefixBits = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_PREFIX_BITS,_zero).c_str()); - _multicastDepth = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_DEPTH,_zero).c_str()); - _private = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE,_zero).c_str()) != 0); + _multicastPrefixBits = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_PREFIX_BITS,zero).c_str()); + _multicastDepth = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_DEPTH,zero).c_str()); + _private = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE,zero).c_str()) != 0); + _enableBroadcast = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST,one).c_str()) != 0); _name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME); _description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string()); diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 6e0404364..a53841de0 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -61,6 +61,7 @@ namespace ZeroTier { #define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" #define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" #define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com" +#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb" /** * Network configuration received from netconf master nodes @@ -117,13 +118,14 @@ public: inline const Address &issuedTo() const throw() { return _issuedTo; } inline unsigned int multicastPrefixBits() const throw() { return _multicastPrefixBits; } inline unsigned int multicastDepth() const throw() { return _multicastDepth; } + inline const std::map &multicastRates() const throw() { return _multicastRates; } inline bool isOpen() const throw() { return (!_private); } inline bool isPrivate() const throw() { return _private; } inline const std::string &name() const throw() { return _name; } inline const std::string &description() const throw() { return _description; } inline const std::set &staticIps() const throw() { return _staticIps; } - inline const std::map &multicastRates() const throw() { return _multicastRates; } inline const CertificateOfMembership &com() const throw() { return _com; } + inline bool enableBroadcast() const throw() { return _enableBroadcast; } /** * @param fromPeer Peer attempting to bridge other Ethernet peers onto network @@ -155,6 +157,7 @@ private: unsigned int _multicastPrefixBits; unsigned int _multicastDepth; bool _private; + bool _enableBroadcast; std::string _name; std::string _description; std::set _staticIps; diff --git a/node/UnixEthernetTap.cpp b/node/UnixEthernetTap.cpp index 4f9291ac7..36bb74424 100644 --- a/node/UnixEthernetTap.cpp +++ b/node/UnixEthernetTap.cpp @@ -710,8 +710,6 @@ bool UnixEthernetTap::updateMulticastGroups(std::set &groups) bool changed = false; - newGroups.insert(_blindWildcardMulticastGroup); // always join this - for(std::set::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) { if (!groups.count(*mg)) { groups.insert(*mg); @@ -719,7 +717,7 @@ bool UnixEthernetTap::updateMulticastGroups(std::set &groups) } } for(std::set::iterator mg(groups.begin());mg!=groups.end();) { - if (!newGroups.count(*mg)) { + if ((!newGroups.count(*mg))&&(*mg != _blindWildcardMulticastGroup)) { groups.erase(mg++); changed = true; } else ++mg; @@ -934,8 +932,6 @@ bool UnixEthernetTap::updateMulticastGroups(std::set &groups) bool changed = false; - newGroups.insert(_blindWildcardMulticastGroup); // always join this - for(std::set::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) { if (!groups.count(*mg)) { groups.insert(*mg); @@ -943,7 +939,7 @@ bool UnixEthernetTap::updateMulticastGroups(std::set &groups) } } for(std::set::iterator mg(groups.begin());mg!=groups.end();) { - if (!newGroups.count(*mg)) { + if ((!newGroups.count(*mg))&&(*mg != _blindWildcardMulticastGroup)) { groups.erase(mg++); changed = true; } else ++mg; diff --git a/node/WindowsEthernetTap.cpp b/node/WindowsEthernetTap.cpp index ea7f75104..2e8de8c17 100644 --- a/node/WindowsEthernetTap.cpp +++ b/node/WindowsEthernetTap.cpp @@ -616,8 +616,6 @@ bool WindowsEthernetTap::updateMulticastGroups(std::set &groups) } } - newGroups.insert(_blindWildcardMulticastGroup); // always join this - bool changed = false; for(std::set::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) { @@ -627,7 +625,7 @@ bool WindowsEthernetTap::updateMulticastGroups(std::set &groups) } } for(std::set::iterator mg(groups.begin());mg!=groups.end();) { - if (!newGroups.count(*mg)) { + if ((!newGroups.count(*mg))&&(*mg != _blindWildcardMulticastGroup)) { groups.erase(mg++); changed = true; } else ++mg;