瀏覽代碼

Fix semantics of std::unique() to actually remove duplicates (hidden memory leak?)

Adam Ierymenko 10 年之前
父節點
當前提交
dbee1b38b3

+ 1 - 1
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<int>::const_iterator i(allowedEtherTypes.begin());i!=allowedEtherTypes.end();++i) {
 				if (allowedEtherTypesCsv.length())

+ 1 - 1
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

+ 33 - 0
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<const struct sockaddr_in *>(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<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(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()
 {

+ 11 - 0
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
 	 */

+ 1 - 1
node/Network.cpp

@@ -502,7 +502,7 @@ std::vector<MulticastGroup> 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;
 }
 

+ 12 - 4
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<std::string> gatewaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS,"").c_str(),",","",""));
 	for(std::vector<std::string>::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<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","",""));
 	for(std::vector<std::string>::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()));
 }

+ 2 - 0
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

+ 1 - 1
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<Address,InetAddress> >::const_iterator nr(networkRelays.begin());nr!=networkRelays.end();++nr) {
 				if (nr->second) {
 					SharedPtr<Peer> rp(RR->topology->getPeer(nr->first));

+ 1 - 1
service/OneService.cpp

@@ -864,7 +864,7 @@ public:
 					for(unsigned int i=0;i<nwc->assignedAddressCount;++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<InetAddress>::iterator ip(newAssignedIps.begin());ip!=newAssignedIps.end();++ip) {
 						if (!std::binary_search(assignedIps.begin(),assignedIps.end(),*ip))
 							t->second->addIp(*ip);