diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index eb8e399b2..9e4c19086 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -389,7 +389,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co allowedEtherTypes.push_back(et); } std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end()); - std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()); + allowedEtherTypes.erase(std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()),allowedEtherTypes.end()); std::string allowedEtherTypesCsv; for(std::vector::const_iterator i(allowedEtherTypes.begin());i!=allowedEtherTypes.end();++i) { if (allowedEtherTypesCsv.length()) diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index 15f03cbd6..19ce770a1 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -140,7 +140,7 @@ void CertificateOfMembership::fromString(const char *s) } std::sort(_qualifiers.begin(),_qualifiers.end()); - std::unique(_qualifiers.begin(),_qualifiers.end()); + _qualifiers.erase(std::unique(_qualifiers.begin(),_qualifiers.end()),_qualifiers.end()); } bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) const diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 940a58b26..83de36d43 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -273,6 +273,39 @@ InetAddress InetAddress::broadcast() const return r; } +bool InetAddress::isNetwork() const + throw() +{ + switch(ss_family) { + case AF_INET: { + unsigned int bits = netmaskBits(); + if (bits <= 0) + return false; + if (bits >= 32) + return false; + uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr); + return ((ip & (0xffffffff >> bits)) == 0); + } + case AF_INET6: { + unsigned int bits = netmaskBits(); + if (bits <= 0) + return false; + if (bits >= 128) + return false; + const unsigned char *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); + unsigned int p = bits / 8; + if ((ip[p++] & (0xff >> (bits % 8))) != 0) + return false; + while (p < 16) { + if (ip[p++]) + return false; + } + return true; + } + } + return false; +} + bool InetAddress::operator==(const InetAddress &a) const throw() { diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 16e3f4d52..35fd43142 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -343,6 +343,17 @@ struct InetAddress : public sockaddr_storage */ inline void zero() throw() { memset(this,0,sizeof(InetAddress)); } + /** + * Check whether this is a network/route rather than an IP assignment + * + * A network is an IP/netmask where everything after the netmask is + * zero e.g. 10.0.0.0/8. + * + * @return True if everything after netmask bits is zero + */ + bool isNetwork() const + throw(); + /** * @return True if address family is non-zero */ diff --git a/node/Network.cpp b/node/Network.cpp index c072e9785..4414e4d1c 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -502,7 +502,7 @@ std::vector Network::_allMulticastGroups() const if ((_config)&&(_config->enableBroadcast())) mgs.push_back(Network::BROADCAST); std::sort(mgs.begin(),mgs.end()); - std::unique(mgs.begin(),mgs.end()); + mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end()); return mgs; } diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 8d682947f..ba4d338bb 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -132,10 +132,18 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) case AF_INET: if ((!addr.netmaskBits())||(addr.netmaskBits() > 32)) continue; + else if (addr.isNetwork()) { + // TODO: add route to network -- this is a route without an IP assignment + continue; + } break; case AF_INET6: if ((!addr.netmaskBits())||(addr.netmaskBits() > 128)) continue; + else if (addr.isNetwork()) { + // TODO: add route to network -- this is a route without an IP assignment + continue; + } break; default: // ignore unrecognized address types or junk/empty fields continue; @@ -143,9 +151,9 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) _staticIps.push_back(addr); } if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) - throw std::invalid_argument("too many ZT-assigned IP addresses"); + throw std::invalid_argument("too many ZT-assigned IP addresses or routes"); std::sort(_staticIps.begin(),_staticIps.end()); - std::unique(_staticIps.begin(),_staticIps.end()); + _staticIps.erase(std::unique(_staticIps.begin(),_staticIps.end()),_staticIps.end()); std::vector gatewaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS,"").c_str(),",","","")); for(std::vector::const_iterator gwstr(gatewaysSplit.begin());gwstr!=gatewaysSplit.end();++gwstr) { @@ -163,7 +171,7 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) } } std::sort(_activeBridges.begin(),_activeBridges.end()); - std::unique(_activeBridges.begin(),_activeBridges.end()); + _activeBridges.erase(std::unique(_activeBridges.begin(),_activeBridges.end()),_activeBridges.end()); std::vector relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","","")); for(std::vector::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) { @@ -177,7 +185,7 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) } } std::sort(_relays.begin(),_relays.end()); - std::unique(_relays.begin(),_relays.end()); + _relays.erase(std::unique(_relays.begin(),_relays.end()),_relays.end()); _com.fromString(d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP,std::string())); } diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 75395fd53..5c7cdd7c0 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -78,9 +78,11 @@ namespace ZeroTier { #define ZT_NETWORKCONFIG_DICT_KEY_DESC "d" // IP/bits[,IP/bits,...] +// Note that IPs that end in all zeroes are routes with no assignment in them. #define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" // IP/bits[,IP/bits,...] +// Note that IPs that end in all zeroes are routes with no assignment in them. #define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" // serialized CertificateOfMembership diff --git a/node/Node.cpp b/node/Node.cpp index 850114341..8cdc6d62b 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -251,7 +251,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next // Attempt to contact network preferred relays that we don't have direct links to std::sort(networkRelays.begin(),networkRelays.end()); - std::unique(networkRelays.begin(),networkRelays.end()); + networkRelays.erase(std::unique(networkRelays.begin(),networkRelays.end()),networkRelays.end()); for(std::vector< std::pair >::const_iterator nr(networkRelays.begin());nr!=networkRelays.end();++nr) { if (nr->second) { SharedPtr rp(RR->topology->getPeer(nr->first)); diff --git a/service/OneService.cpp b/service/OneService.cpp index 212525460..7532bf750 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -864,7 +864,7 @@ public: for(unsigned int i=0;iassignedAddressCount;++i) newAssignedIps.push_back(InetAddress(nwc->assignedAddresses[i])); std::sort(newAssignedIps.begin(),newAssignedIps.end()); - std::unique(newAssignedIps.begin(),newAssignedIps.end()); + newAssignedIps.erase(std::unique(newAssignedIps.begin(),newAssignedIps.end()),newAssignedIps.end()); for(std::vector::iterator ip(newAssignedIps.begin());ip!=newAssignedIps.end();++ip) { if (!std::binary_search(assignedIps.begin(),assignedIps.end(),*ip)) t->second->addIp(*ip);