mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-29 15:43:52 +00:00
Because Windows, because Windows. Now it upgrades correctly from 1.0.1, including automatic driver update from NDIS5 to NDIS6. Also a bit more robust on creating new ports, just in case.
This commit is contained in:
parent
922d9657b9
commit
620562f7cf
@ -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:{B29840D5-AC05-4F09-970F-34071C06912C} " Type="16"/>
|
||||
<ROW Property="ProductCode" Value="1033:{539E07E1-8687-4B88-BA01-91ED2DD5E162} " Type="16"/>
|
||||
<ROW Property="ProductLanguage" Value="1033"/>
|
||||
<ROW Property="ProductName" Value="ZeroTier One"/>
|
||||
<ROW Property="ProductVersion" Value="1.0.4" Type="32"/>
|
||||
@ -101,8 +101,8 @@
|
||||
<ATTRIBUTE name="Enable" value="false"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.ChainedPackageComponent">
|
||||
<ROW ChainedPackage="ZeroTierOne_NDIS6_x64.msi" Order="1" Options="108" InstallCondition="((NOT Installed) AND (VersionNT64))" RemoveCondition="((REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) AND (VersionNT64))"/>
|
||||
<ROW ChainedPackage="ZeroTierOne_NDIS6_x86.msi" Order="2" Options="108" InstallCondition="((NOT Installed) AND (NOT VersionNT64))" RemoveCondition="((REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) AND (NOT VersionNT64))"/>
|
||||
<ROW ChainedPackage="ZeroTierOne_NDIS6_x64.msi" Order="1" Options="108" InstallCondition="(VersionNT64)" RemoveCondition="((REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) AND (VersionNT64))"/>
|
||||
<ROW ChainedPackage="ZeroTierOne_NDIS6_x86.msi" Order="2" Options="108" InstallCondition="(NOT VersionNT64)" RemoveCondition="((REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) AND (NOT VersionNT64))"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.ChainedPackageFileComponent">
|
||||
<ROW FileId="ZeroTierOne_NDIS6_x64.msi" ChainedPackage="ZeroTierOne_NDIS6_x64.msi" Options="1" TargetPath="ZeroTierOne_NDIS6_x64.msi" Content="..\..\bin\tap-windows-ndis6\x64\ZeroTierOne_NDIS6_x64.msi"/>
|
||||
|
@ -234,10 +234,19 @@ std::string WindowsEthernetTap::addNewPersistentTapDevice(const char *pathToInf)
|
||||
return std::string("SetupDiCallClassInstaller(DIF_REGISTERDEVICE) failed");
|
||||
}
|
||||
|
||||
BOOL rebootRequired = FALSE;
|
||||
if (!WINENV.UpdateDriverForPlugAndPlayDevicesA((HWND)0,WINENV.tapDriverName.c_str(),pathToInf,INSTALLFLAG_FORCE|INSTALLFLAG_NONINTERACTIVE,&rebootRequired)) {
|
||||
// HACK: During upgrades, this can fail while the installer is still running. So make 60 attempts
|
||||
// with a 1s delay between each attempt.
|
||||
bool driverInstalled = false;
|
||||
for(int retryCounter=0;retryCounter<60;++retryCounter) {
|
||||
BOOL rebootRequired = FALSE;
|
||||
if (WINENV.UpdateDriverForPlugAndPlayDevicesA((HWND)0,WINENV.tapDriverName.c_str(),pathToInf,INSTALLFLAG_FORCE|INSTALLFLAG_NONINTERACTIVE,&rebootRequired)) {
|
||||
driverInstalled = true;
|
||||
break;
|
||||
} else Sleep(1000);
|
||||
}
|
||||
if (!driverInstalled) {
|
||||
WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
return std::string("UpdateDriverForPlugAndPlayDevices() failed -- unable to install driver on device");
|
||||
return std::string("UpdateDriverForPlugAndPlayDevices() failed (made 60 attempts)");
|
||||
}
|
||||
|
||||
WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
@ -285,13 +294,16 @@ std::string WindowsEthernetTap::destroyAllLegacyPersistentTapDevices()
|
||||
RegCloseKey(nwAdapters);
|
||||
}
|
||||
|
||||
std::string errlist;
|
||||
for(std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin());iidp!=instanceIdPathsToRemove.end();++iidp) {
|
||||
std::string err = deletePersistentTapDevice(iidp->c_str());
|
||||
if (err.length() > 0)
|
||||
return err;
|
||||
if (err.length() > 0) {
|
||||
if (errlist.length() > 0)
|
||||
errlist.push_back(',');
|
||||
errlist.append(err);
|
||||
}
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return errlist;
|
||||
}
|
||||
|
||||
std::string WindowsEthernetTap::destroyAllPersistentTapDevices()
|
||||
@ -334,13 +346,16 @@ std::string WindowsEthernetTap::destroyAllPersistentTapDevices()
|
||||
RegCloseKey(nwAdapters);
|
||||
}
|
||||
|
||||
std::string errlist;
|
||||
for(std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin());iidp!=instanceIdPathsToRemove.end();++iidp) {
|
||||
std::string err = deletePersistentTapDevice(iidp->c_str());
|
||||
if (err.length() > 0)
|
||||
return err;
|
||||
if (err.length() > 0) {
|
||||
if (errlist.length() > 0)
|
||||
errlist.push_back(',');
|
||||
errlist.append(err);
|
||||
}
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return errlist;
|
||||
}
|
||||
|
||||
std::string WindowsEthernetTap::deletePersistentTapDevice(const char *instanceId)
|
||||
@ -455,7 +470,6 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
char subkeyClass[4096];
|
||||
char data[4096];
|
||||
char tag[24];
|
||||
std::set<std::string> existingDeviceInstances;
|
||||
std::string mySubkeyName;
|
||||
|
||||
if (mtu > 2800)
|
||||
@ -487,10 +501,8 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
std::string instanceId;
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
||||
instanceId.assign(data,dataLen);
|
||||
existingDeviceInstances.insert(instanceId);
|
||||
}
|
||||
|
||||
std::string instanceIdPath;
|
||||
type = 0;
|
||||
@ -520,50 +532,61 @@ WindowsEthernetTap::WindowsEthernetTap(
|
||||
// If there is no device, try to create one
|
||||
bool creatingNewDevice = (_netCfgInstanceId.length() == 0);
|
||||
if (creatingNewDevice) {
|
||||
std::string errm = addNewPersistentTapDevice((std::string(_pathToHelpers) + WINENV.tapDriverPath).c_str());
|
||||
if (errm.length() != 0)
|
||||
throw std::runtime_error(errm);
|
||||
for(int getNewAttemptCounter=0;getNewAttemptCounter<2;++getNewAttemptCounter) {
|
||||
for(DWORD subkeyIndex=0;;++subkeyIndex) {
|
||||
DWORD type;
|
||||
DWORD dataLen;
|
||||
DWORD subkeyNameLen = sizeof(subkeyName);
|
||||
DWORD subkeyClassLen = sizeof(subkeyClass);
|
||||
FILETIME lastWriteTime;
|
||||
if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
data[dataLen] = '\0';
|
||||
|
||||
// Scan for the new instance by simply looking for taps that weren't originally there...
|
||||
for(DWORD subkeyIndex=0;;++subkeyIndex) {
|
||||
DWORD type;
|
||||
DWORD dataLen;
|
||||
DWORD subkeyNameLen = sizeof(subkeyName);
|
||||
DWORD subkeyClassLen = sizeof(subkeyClass);
|
||||
FILETIME lastWriteTime;
|
||||
if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
data[dataLen] = '\0';
|
||||
|
||||
if (WINENV.tapDriverName == data) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) {
|
||||
RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,(DWORD)(strlen(tag)+1));
|
||||
_netCfgInstanceId.assign(data,dataLen);
|
||||
if (WINENV.tapDriverName == data) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if ((RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) != ERROR_SUCCESS)||(dataLen <= 0)) {
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
||||
_deviceInstanceId.assign(data,dataLen);
|
||||
mySubkeyName = subkeyName;
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,(DWORD)(strlen(tag)+1));
|
||||
|
||||
// Disable DHCP by default on newly created devices
|
||||
HKEY tcpIpInterfaces;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
|
||||
DWORD enable = 0;
|
||||
RegSetKeyValueA(tcpIpInterfaces,_netCfgInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable));
|
||||
RegCloseKey(tcpIpInterfaces);
|
||||
_netCfgInstanceId.assign(data,dataLen);
|
||||
|
||||
type = 0;
|
||||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
|
||||
_deviceInstanceId.assign(data,dataLen);
|
||||
|
||||
mySubkeyName = subkeyName;
|
||||
|
||||
// Disable DHCP by default on new devices
|
||||
HKEY tcpIpInterfaces;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
|
||||
DWORD enable = 0;
|
||||
RegSetKeyValueA(tcpIpInterfaces,_netCfgInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable));
|
||||
RegCloseKey(tcpIpInterfaces);
|
||||
}
|
||||
|
||||
break; // found an unused zttap device
|
||||
}
|
||||
|
||||
break; // found it!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else break; // no more keys or error occurred
|
||||
} else break; // no more keys or error occurred
|
||||
}
|
||||
|
||||
if (_netCfgInstanceId.length() > 0) {
|
||||
break; // found an unused zttap device
|
||||
} else {
|
||||
// no unused zttap devices, so create one
|
||||
std::string errm = addNewPersistentTapDevice((std::string(_pathToHelpers) + WINENV.tapDriverPath).c_str());
|
||||
if (errm.length() > 0)
|
||||
throw std::runtime_error(std::string("unable to create new device instance: ")+errm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -943,6 +943,17 @@ public:
|
||||
friendlyName,
|
||||
StapFrameHandler,
|
||||
(void *)this))).first;
|
||||
} catch (std::exception &exc) {
|
||||
#ifdef __WINDOWS__
|
||||
FILE *tapFailLog = fopen((_homePath + ZT_PATH_SEPARATOR_S"port_error_log.txt").c_str(),"a");
|
||||
if (tapFailLog) {
|
||||
fprintf(tapFailLog,"%.16llx: %s"ZT_EOL_S,(unsigned long long)nwid,exc.what());
|
||||
fclose(tapFailLog);
|
||||
}
|
||||
#else
|
||||
fprintf(stderr,"ERROR: unable to configure virtual network port: %s"ZT_EOL_S,exc.what());
|
||||
#endif
|
||||
return -999;
|
||||
} catch ( ... ) {
|
||||
return -999; // tap init failed
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user