Browse Source

Save enumeration of statically assigned IPs so they will always be reassigned on device "power cycle."

Adam Ierymenko 10 years ago
parent
commit
922d9657b9

+ 1 - 1
ext/installfiles/windows/ZeroTier One.aip

@@ -23,7 +23,7 @@
     <ROW Property="CTRLS" Value="2"/>
     <ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>
     <ROW Property="Manufacturer" Value="ZeroTier, Inc."/>
-    <ROW Property="ProductCode" Value="1033:{631AEF67-1E3B-4A70-BAAE-81C576D2A1E4} " Type="16"/>
+    <ROW Property="ProductCode" Value="1033:{B29840D5-AC05-4F09-970F-34071C06912C} " Type="16"/>
     <ROW Property="ProductLanguage" Value="1033"/>
     <ROW Property="ProductName" Value="ZeroTier One"/>
     <ROW Property="ProductVersion" Value="1.0.4" Type="32"/>

+ 70 - 48
osdep/WindowsEthernetTap.cpp

@@ -639,63 +639,28 @@ bool WindowsEthernetTap::enabled() const
 
 bool WindowsEthernetTap::addIp(const InetAddress &ip)
 {
-	if (!_initialized)
-		return false;
 	if (!ip.netmaskBits()) // sanity check... netmask of 0.0.0.0 is WUT?
 		return false;
-
-	std::vector<InetAddress> haveIps(ips());
-
-	try {
-		// Add IP to interface at the netlink level if not already assigned.
-		if (!std::binary_search(haveIps.begin(),haveIps.end(),ip)) {
-			MIB_UNICASTIPADDRESS_ROW ipr;
-
-			InitializeUnicastIpAddressEntry(&ipr);
-			if (ip.isV4()) {
-				ipr.Address.Ipv4.sin_family = AF_INET;
-				ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)ip.rawIpData());
-				ipr.OnLinkPrefixLength = ip.port();
-				if (ipr.OnLinkPrefixLength >= 32)
-					return false;
-			} else if (ip.isV6()) {
-				ipr.Address.Ipv6.sin6_family = AF_INET6;
-				memcpy(ipr.Address.Ipv6.sin6_addr.u.Byte,ip.rawIpData(),16);
-				ipr.OnLinkPrefixLength = ip.port();
-				if (ipr.OnLinkPrefixLength >= 128)
-					return false;
-			} else return false;
-
-			ipr.PrefixOrigin = IpPrefixOriginManual;
-			ipr.SuffixOrigin = IpSuffixOriginManual;
-			ipr.ValidLifetime = 0xffffffff;
-			ipr.PreferredLifetime = 0xffffffff;
-
-			ipr.InterfaceLuid = _deviceLuid;
-			ipr.InterfaceIndex = _getDeviceIndex();
-
-			if (CreateUnicastIpAddressEntry(&ipr) != NO_ERROR)
-				return false;
-		}
-
-		std::vector<std::string> regIps(_getRegistryIPv4Value("IPAddress"));
-		if (std::find(regIps.begin(),regIps.end(),ip.toIpString()) == regIps.end()) {
-			std::vector<std::string> regSubnetMasks(_getRegistryIPv4Value("SubnetMask"));
-			regIps.push_back(ip.toIpString());
-			regSubnetMasks.push_back(ip.netmask().toIpString());
-			_setRegistryIPv4Value("IPAddress",regIps);
-			_setRegistryIPv4Value("SubnetMask",regSubnetMasks);
-		}
-	} catch ( ... ) {
-		return false;
-	}
+	Mutex::Lock _l(_assignedIps_m);
+	if (std::find(_assignedIps.begin(),_assignedIps.end(),ip) != _assignedIps.end())
+		return true;
+	_assignedIps.push_back(ip);
+	_syncIps();
 	return true;
 }
 
 bool WindowsEthernetTap::removeIp(const InetAddress &ip)
 {
+	{
+		Mutex::Lock _l(_assignedIps_m);
+		std::vector<InetAddress>::iterator aip(std::find(_assignedIps.begin(),_assignedIps.end(),ip));
+		if (aip != _assignedIps.end())
+			_assignedIps.erase(aip);
+	}
+
 	if (!_initialized)
 		return false;
+
 	try {
 		MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
 		if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
@@ -972,6 +937,12 @@ void WindowsEthernetTap::threadMain()
 			}
 #endif
 
+			// Assign or re-assign any should-be-assigned IPs in case we have restarted
+			{
+				Mutex::Lock _l(_assignedIps_m);
+				_syncIps();
+			}
+
 			memset(&tapOvlRead,0,sizeof(tapOvlRead));
 			tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
 			memset(&tapOvlWrite,0,sizeof(tapOvlWrite));
@@ -1135,4 +1106,55 @@ void WindowsEthernetTap::_setRegistryIPv4Value(const char *regKey,const std::vec
 	}
 }
 
+void WindowsEthernetTap::_syncIps()
+{
+	// assumes _assignedIps_m is locked
+
+	if (!_initialized)
+		return;
+
+	std::vector<InetAddress> haveIps(ips());
+
+	for(std::vector<InetAddress>::const_iterator aip(_assignedIps.begin());aip!=_assignedIps.end();++aip) {
+		if (std::find(haveIps.begin(),haveIps.end(),*aip) == haveIps.end()) {
+			MIB_UNICASTIPADDRESS_ROW ipr;
+
+			InitializeUnicastIpAddressEntry(&ipr);
+			if (aip->isV4()) {
+				ipr.Address.Ipv4.sin_family = AF_INET;
+				ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)aip->rawIpData());
+				ipr.OnLinkPrefixLength = aip->netmaskBits();
+				if (ipr.OnLinkPrefixLength >= 32)
+					continue;
+			} else if (aip->isV6()) {
+				ipr.Address.Ipv6.sin6_family = AF_INET6;
+				memcpy(ipr.Address.Ipv6.sin6_addr.u.Byte,aip->rawIpData(),16);
+				ipr.OnLinkPrefixLength = aip->netmaskBits();
+				if (ipr.OnLinkPrefixLength >= 128)
+					continue;
+			} else continue;
+
+			ipr.PrefixOrigin = IpPrefixOriginManual;
+			ipr.SuffixOrigin = IpSuffixOriginManual;
+			ipr.ValidLifetime = 0xffffffff;
+			ipr.PreferredLifetime = 0xffffffff;
+
+			ipr.InterfaceLuid = _deviceLuid;
+			ipr.InterfaceIndex = _getDeviceIndex();
+
+			CreateUnicastIpAddressEntry(&ipr);
+		}
+
+		std::string ipStr(aip->toString());
+		std::vector<std::string> regIps(_getRegistryIPv4Value("IPAddress"));
+		if (std::find(regIps.begin(),regIps.end(),ipStr) == regIps.end()) {
+			std::vector<std::string> regSubnetMasks(_getRegistryIPv4Value("SubnetMask"));
+			regIps.push_back(ipStr);
+			regSubnetMasks.push_back(aip->netmask().toIpString());
+			_setRegistryIPv4Value("IPAddress",regIps);
+			_setRegistryIPv4Value("SubnetMask",regSubnetMasks);
+		}
+	}
+}
+
 } // namespace ZeroTier

+ 5 - 2
osdep/WindowsEthernetTap.hpp

@@ -41,6 +41,7 @@
 #include "../node/Mutex.hpp"
 #include "../node/Array.hpp"
 #include "../node/MulticastGroup.hpp"
+#include "../node/InetAddress.hpp"
 #include "../osdep/Thread.hpp"
 
 namespace ZeroTier {
@@ -117,11 +118,10 @@ public:
 		throw();
 
 private:
-	bool _disableTapDevice();
-	bool _enableTapDevice();
 	NET_IFINDEX _getDeviceIndex(); // throws on failure
 	std::vector<std::string> _getRegistryIPv4Value(const char *regKey);
 	void _setRegistryIPv4Value(const char *regKey,const std::vector<std::string> &value);
+	void _syncIps();
 
 	void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
 	void *_arg;
@@ -137,6 +137,9 @@ private:
 	std::string _netCfgInstanceId;
 	std::string _deviceInstanceId;
 
+	std::vector<InetAddress> _assignedIps; // IPs assigned with addIp
+	Mutex _assignedIps_m;
+
 	std::vector<MulticastGroup> _multicastGroups;
 
 	std::queue< std::pair< Array<char,ZT_IF_MTU + 32>,unsigned int > > _injectPending;