WindowsEthernetTap.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371
  1. /*
  2. * Copyright (c)2019 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2026-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #include "WindowsEthernetTap.hpp"
  14. #include "../node/Constants.hpp"
  15. #include "../node/Mutex.hpp"
  16. #include "../node/Utils.hpp"
  17. #include "..\windows\TapDriver6\tap-windows.h"
  18. #include "OSUtils.hpp"
  19. #include "WinDNSHelper.hpp"
  20. #include <IPHlpApi.h>
  21. #include <SetupAPI.h>
  22. #include <atlbase.h>
  23. #include <cfgmgr32.h>
  24. #include <iostream>
  25. #include <malloc.h>
  26. #include <netcon.h>
  27. #include <netioapi.h>
  28. #include <netlistmgr.h>
  29. #include <newdev.h>
  30. #include <nldef.h>
  31. #include <set>
  32. #include <stdint.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <tchar.h>
  37. #include <wchar.h>
  38. #include <windows.h>
  39. #include <winreg.h>
  40. #include <winsock2.h>
  41. #include <ws2ipdef.h>
  42. #include <ws2tcpip.h>
  43. // Create a fake unused default route to force detection of network type on networks without gateways
  44. #define ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE
  45. // Function signatures of dynamically loaded functions, from newdev.h, setupapi.h, and cfgmgr32.h
  46. typedef BOOL(WINAPI* UpdateDriverForPlugAndPlayDevicesA_t)(_In_opt_ HWND hwndParent, _In_ LPCSTR HardwareId, _In_ LPCSTR FullInfPath, _In_ DWORD InstallFlags, _Out_opt_ PBOOL bRebootRequired);
  47. typedef BOOL(WINAPI* SetupDiGetINFClassA_t)(_In_ PCSTR InfName, _Out_ LPGUID ClassGuid, _Out_writes_(ClassNameSize) PSTR ClassName, _In_ DWORD ClassNameSize, _Out_opt_ PDWORD RequiredSize);
  48. typedef HDEVINFO(WINAPI* SetupDiCreateDeviceInfoList_t)(_In_opt_ CONST GUID* ClassGuid, _In_opt_ HWND hwndParent);
  49. typedef BOOL(WINAPI* SetupDiCreateDeviceInfoA_t)(
  50. _In_ HDEVINFO DeviceInfoSet,
  51. _In_ PCSTR DeviceName,
  52. _In_ CONST GUID* ClassGuid,
  53. _In_opt_ PCSTR DeviceDescription,
  54. _In_opt_ HWND hwndParent,
  55. _In_ DWORD CreationFlags,
  56. _Out_opt_ PSP_DEVINFO_DATA DeviceInfoData);
  57. typedef BOOL(
  58. WINAPI* SetupDiSetDeviceRegistryPropertyA_t)(_In_ HDEVINFO DeviceInfoSet, _Inout_ PSP_DEVINFO_DATA DeviceInfoData, _In_ DWORD Property, _In_reads_bytes_opt_(PropertyBufferSize) CONST BYTE* PropertyBuffer, _In_ DWORD PropertyBufferSize);
  59. typedef BOOL(WINAPI* SetupDiCallClassInstaller_t)(_In_ DI_FUNCTION InstallFunction, _In_ HDEVINFO DeviceInfoSet, _In_opt_ PSP_DEVINFO_DATA DeviceInfoData);
  60. typedef BOOL(WINAPI* SetupDiDestroyDeviceInfoList_t)(_In_ HDEVINFO DeviceInfoSet);
  61. typedef HDEVINFO(
  62. WINAPI* SetupDiGetClassDevsExA_t)(_In_opt_ CONST GUID* ClassGuid, _In_opt_ PCSTR Enumerator, _In_opt_ HWND hwndParent, _In_ DWORD Flags, _In_opt_ HDEVINFO DeviceInfoSet, _In_opt_ PCSTR MachineName, _Reserved_ PVOID Reserved);
  63. typedef BOOL(WINAPI* SetupDiOpenDeviceInfoA_t)(_In_ HDEVINFO DeviceInfoSet, _In_ PCSTR DeviceInstanceId, _In_opt_ HWND hwndParent, _In_ DWORD OpenFlags, _Out_opt_ PSP_DEVINFO_DATA DeviceInfoData);
  64. typedef BOOL(WINAPI* SetupDiEnumDeviceInfo_t)(_In_ HDEVINFO DeviceInfoSet, _In_ DWORD MemberIndex, _Out_ PSP_DEVINFO_DATA DeviceInfoData);
  65. typedef BOOL(
  66. WINAPI* SetupDiSetClassInstallParamsA_t)(_In_ HDEVINFO DeviceInfoSet, _In_opt_ PSP_DEVINFO_DATA DeviceInfoData, _In_reads_bytes_opt_(ClassInstallParamsSize) PSP_CLASSINSTALL_HEADER ClassInstallParams, _In_ DWORD ClassInstallParamsSize);
  67. typedef CONFIGRET(WINAPI* CM_Get_Device_ID_ExA_t)(_In_ DEVINST dnDevInst, _Out_writes_(BufferLen) PSTR Buffer, _In_ ULONG BufferLen, _In_ ULONG ulFlags, _In_opt_ HMACHINE hMachine);
  68. typedef BOOL(
  69. WINAPI* SetupDiGetDeviceInstanceIdA_t)(_In_ HDEVINFO DeviceInfoSet, _In_ PSP_DEVINFO_DATA DeviceInfoData, _Out_writes_opt_(DeviceInstanceIdSize) PSTR DeviceInstanceId, _In_ DWORD DeviceInstanceIdSize, _Out_opt_ PDWORD RequiredSize);
  70. namespace ZeroTier {
  71. namespace {
  72. // Static/singleton class that when initialized loads a bunch of environment information and a few dynamically loaded DLLs
  73. class WindowsEthernetTapEnv {
  74. public:
  75. WindowsEthernetTapEnv()
  76. {
  77. #ifdef _WIN64
  78. is64Bit = TRUE;
  79. // tapDriverPath = "\\tap-windows\\x64\\zttap300.inf";
  80. #else
  81. is64Bit = FALSE;
  82. IsWow64Process(GetCurrentProcess(), &is64Bit);
  83. if (is64Bit) {
  84. fprintf(stderr, "FATAL: you must use the 64-bit ZeroTier One service on 64-bit Windows systems\r\n");
  85. _exit(1);
  86. }
  87. // tapDriverPath = "\\tap-windows\\x86\\zttap300.inf";
  88. #endif
  89. tapDriverName = "zttap300";
  90. tapDriverPath = "\\zttap300.inf";
  91. setupApiMod = LoadLibraryA("setupapi.dll");
  92. if (! setupApiMod) {
  93. fprintf(stderr, "FATAL: unable to dynamically load setupapi.dll\r\n");
  94. _exit(1);
  95. }
  96. if (! (this->SetupDiGetINFClassA = (SetupDiGetINFClassA_t)GetProcAddress(setupApiMod, "SetupDiGetINFClassA"))) {
  97. fprintf(stderr, "FATAL: SetupDiGetINFClassA not found in setupapi.dll\r\n");
  98. _exit(1);
  99. }
  100. if (! (this->SetupDiCreateDeviceInfoList = (SetupDiCreateDeviceInfoList_t)GetProcAddress(setupApiMod, "SetupDiCreateDeviceInfoList"))) {
  101. fprintf(stderr, "FATAL: SetupDiCreateDeviceInfoList not found in setupapi.dll\r\n");
  102. _exit(1);
  103. }
  104. if (! (this->SetupDiCreateDeviceInfoA = (SetupDiCreateDeviceInfoA_t)GetProcAddress(setupApiMod, "SetupDiCreateDeviceInfoA"))) {
  105. fprintf(stderr, "FATAL: SetupDiCreateDeviceInfoA not found in setupapi.dll\r\n");
  106. _exit(1);
  107. }
  108. if (! (this->SetupDiSetDeviceRegistryPropertyA = (SetupDiSetDeviceRegistryPropertyA_t)GetProcAddress(setupApiMod, "SetupDiSetDeviceRegistryPropertyA"))) {
  109. fprintf(stderr, "FATAL: SetupDiSetDeviceRegistryPropertyA not found in setupapi.dll\r\n");
  110. _exit(1);
  111. }
  112. if (! (this->SetupDiCallClassInstaller = (SetupDiCallClassInstaller_t)GetProcAddress(setupApiMod, "SetupDiCallClassInstaller"))) {
  113. fprintf(stderr, "FATAL: SetupDiCallClassInstaller not found in setupapi.dll\r\n");
  114. _exit(1);
  115. }
  116. if (! (this->SetupDiDestroyDeviceInfoList = (SetupDiDestroyDeviceInfoList_t)GetProcAddress(setupApiMod, "SetupDiDestroyDeviceInfoList"))) {
  117. fprintf(stderr, "FATAL: SetupDiDestroyDeviceInfoList not found in setupapi.dll\r\n");
  118. _exit(1);
  119. }
  120. if (! (this->SetupDiGetClassDevsExA = (SetupDiGetClassDevsExA_t)GetProcAddress(setupApiMod, "SetupDiGetClassDevsExA"))) {
  121. fprintf(stderr, "FATAL: SetupDiGetClassDevsExA not found in setupapi.dll\r\n");
  122. _exit(1);
  123. }
  124. if (! (this->SetupDiOpenDeviceInfoA = (SetupDiOpenDeviceInfoA_t)GetProcAddress(setupApiMod, "SetupDiOpenDeviceInfoA"))) {
  125. fprintf(stderr, "FATAL: SetupDiOpenDeviceInfoA not found in setupapi.dll\r\n");
  126. _exit(1);
  127. }
  128. if (! (this->SetupDiEnumDeviceInfo = (SetupDiEnumDeviceInfo_t)GetProcAddress(setupApiMod, "SetupDiEnumDeviceInfo"))) {
  129. fprintf(stderr, "FATAL: SetupDiEnumDeviceInfo not found in setupapi.dll\r\n");
  130. _exit(1);
  131. }
  132. if (! (this->SetupDiSetClassInstallParamsA = (SetupDiSetClassInstallParamsA_t)GetProcAddress(setupApiMod, "SetupDiSetClassInstallParamsA"))) {
  133. fprintf(stderr, "FATAL: SetupDiSetClassInstallParamsA not found in setupapi.dll\r\n");
  134. _exit(1);
  135. }
  136. if (! (this->SetupDiGetDeviceInstanceIdA = (SetupDiGetDeviceInstanceIdA_t)GetProcAddress(setupApiMod, "SetupDiGetDeviceInstanceIdA"))) {
  137. fprintf(stderr, "FATAL: SetupDiGetDeviceInstanceIdA not found in setupapi.dll\r\n");
  138. _exit(1);
  139. }
  140. newDevMod = LoadLibraryA("newdev.dll");
  141. if (! newDevMod) {
  142. fprintf(stderr, "FATAL: unable to dynamically load newdev.dll\r\n");
  143. _exit(1);
  144. }
  145. if (! (this->UpdateDriverForPlugAndPlayDevicesA = (UpdateDriverForPlugAndPlayDevicesA_t)GetProcAddress(newDevMod, "UpdateDriverForPlugAndPlayDevicesA"))) {
  146. fprintf(stderr, "FATAL: UpdateDriverForPlugAndPlayDevicesA not found in newdev.dll\r\n");
  147. _exit(1);
  148. }
  149. cfgMgrMod = LoadLibraryA("cfgmgr32.dll");
  150. if (! cfgMgrMod) {
  151. fprintf(stderr, "FATAL: unable to dynamically load cfgmgr32.dll\r\n");
  152. _exit(1);
  153. }
  154. if (! (this->CM_Get_Device_ID_ExA = (CM_Get_Device_ID_ExA_t)GetProcAddress(cfgMgrMod, "CM_Get_Device_ID_ExA"))) {
  155. fprintf(stderr, "FATAL: CM_Get_Device_ID_ExA not found in cfgmgr32.dll\r\n");
  156. _exit(1);
  157. }
  158. }
  159. BOOL is64Bit; // is the system 64-bit, regardless of whether this binary is or not
  160. std::string tapDriverPath;
  161. std::string tapDriverName;
  162. UpdateDriverForPlugAndPlayDevicesA_t UpdateDriverForPlugAndPlayDevicesA;
  163. SetupDiGetINFClassA_t SetupDiGetINFClassA;
  164. SetupDiCreateDeviceInfoList_t SetupDiCreateDeviceInfoList;
  165. SetupDiCreateDeviceInfoA_t SetupDiCreateDeviceInfoA;
  166. SetupDiSetDeviceRegistryPropertyA_t SetupDiSetDeviceRegistryPropertyA;
  167. SetupDiCallClassInstaller_t SetupDiCallClassInstaller;
  168. SetupDiDestroyDeviceInfoList_t SetupDiDestroyDeviceInfoList;
  169. SetupDiGetClassDevsExA_t SetupDiGetClassDevsExA;
  170. SetupDiOpenDeviceInfoA_t SetupDiOpenDeviceInfoA;
  171. SetupDiEnumDeviceInfo_t SetupDiEnumDeviceInfo;
  172. SetupDiSetClassInstallParamsA_t SetupDiSetClassInstallParamsA;
  173. SetupDiGetDeviceInstanceIdA_t SetupDiGetDeviceInstanceIdA;
  174. CM_Get_Device_ID_ExA_t CM_Get_Device_ID_ExA;
  175. private:
  176. HMODULE setupApiMod;
  177. HMODULE newDevMod;
  178. HMODULE cfgMgrMod;
  179. };
  180. static const WindowsEthernetTapEnv WINENV;
  181. // Only create or delete devices one at a time
  182. static Mutex _systemTapInitLock;
  183. // Only perform installation or uninstallation options one at a time
  184. static Mutex _systemDeviceManagementLock;
  185. } // anonymous namespace
  186. std::string WindowsEthernetTap::addNewPersistentTapDevice(const char* pathToInf, std::string& deviceInstanceId)
  187. {
  188. Mutex::Lock _l(_systemDeviceManagementLock);
  189. GUID classGuid;
  190. char className[1024];
  191. if (! WINENV.SetupDiGetINFClassA(pathToInf, &classGuid, className, sizeof(className), (PDWORD)0)) {
  192. return std::string("SetupDiGetINFClassA() failed -- unable to read zttap driver INF file");
  193. }
  194. HDEVINFO deviceInfoSet = WINENV.SetupDiCreateDeviceInfoList(&classGuid, (HWND)0);
  195. if (deviceInfoSet == INVALID_HANDLE_VALUE) {
  196. return std::string("SetupDiCreateDeviceInfoList() failed");
  197. }
  198. SP_DEVINFO_DATA deviceInfoData;
  199. memset(&deviceInfoData, 0, sizeof(deviceInfoData));
  200. deviceInfoData.cbSize = sizeof(deviceInfoData);
  201. if (! WINENV.SetupDiCreateDeviceInfoA(deviceInfoSet, className, &classGuid, (PCSTR)0, (HWND)0, DICD_GENERATE_ID, &deviceInfoData)) {
  202. WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
  203. return std::string("SetupDiCreateDeviceInfoA() failed");
  204. }
  205. if (! WINENV.SetupDiSetDeviceRegistryPropertyA(deviceInfoSet, &deviceInfoData, SPDRP_HARDWAREID, (const BYTE*)WINENV.tapDriverName.c_str(), (DWORD)(WINENV.tapDriverName.length() + 1))) {
  206. WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
  207. return std::string("SetupDiSetDeviceRegistryPropertyA() failed");
  208. }
  209. if (! WINENV.SetupDiCallClassInstaller(DIF_REGISTERDEVICE, deviceInfoSet, &deviceInfoData)) {
  210. WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
  211. return std::string("SetupDiCallClassInstaller(DIF_REGISTERDEVICE) failed");
  212. }
  213. // HACK: During upgrades, this can fail while the installer is still running. So make 60 attempts
  214. // with a 1s delay between each attempt.
  215. bool driverInstalled = false;
  216. for (int retryCounter = 0; retryCounter < 60; ++retryCounter) {
  217. BOOL rebootRequired = FALSE;
  218. if (WINENV.UpdateDriverForPlugAndPlayDevicesA((HWND)0, WINENV.tapDriverName.c_str(), pathToInf, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, &rebootRequired)) {
  219. driverInstalled = true;
  220. break;
  221. }
  222. else
  223. Sleep(1000);
  224. }
  225. if (! driverInstalled) {
  226. WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
  227. return std::string("UpdateDriverForPlugAndPlayDevices() failed (made 60 attempts)");
  228. }
  229. char iidbuf[1024];
  230. DWORD iidReqSize = sizeof(iidbuf);
  231. if (WINENV.SetupDiGetDeviceInstanceIdA(deviceInfoSet, &deviceInfoData, iidbuf, sizeof(iidbuf), &iidReqSize)) {
  232. deviceInstanceId = iidbuf;
  233. } // failure here is not fatal since we only need this on Vista and 2008 -- other versions fill it into the registry automatically
  234. WINENV.SetupDiDestroyDeviceInfoList(deviceInfoSet);
  235. return std::string();
  236. }
  237. std::string WindowsEthernetTap::destroyAllLegacyPersistentTapDevices()
  238. {
  239. char subkeyName[1024];
  240. char subkeyClass[1024];
  241. char data[1024];
  242. std::set<std::string> instanceIdPathsToRemove;
  243. {
  244. HKEY nwAdapters;
  245. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) != ERROR_SUCCESS)
  246. return std::string("Could not open registry key");
  247. for (DWORD subkeyIndex = 0;; ++subkeyIndex) {
  248. DWORD type;
  249. DWORD dataLen;
  250. DWORD subkeyNameLen = sizeof(subkeyName);
  251. DWORD subkeyClassLen = sizeof(subkeyClass);
  252. FILETIME lastWriteTime;
  253. if (RegEnumKeyExA(nwAdapters, subkeyIndex, subkeyName, &subkeyNameLen, (DWORD*)0, subkeyClass, &subkeyClassLen, &lastWriteTime) == ERROR_SUCCESS) {
  254. type = 0;
  255. dataLen = sizeof(data);
  256. if (RegGetValueA(nwAdapters, subkeyName, "ComponentId", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS) {
  257. data[dataLen] = '\0';
  258. if ((! strnicmp(data, "zttap", 5)) && (WINENV.tapDriverName != data)) {
  259. std::string instanceIdPath;
  260. type = 0;
  261. dataLen = sizeof(data);
  262. if (RegGetValueA(nwAdapters, subkeyName, "DeviceInstanceID", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS)
  263. instanceIdPath.assign(data, dataLen);
  264. if (instanceIdPath.length() != 0)
  265. instanceIdPathsToRemove.insert(instanceIdPath);
  266. }
  267. }
  268. }
  269. else
  270. break; // end of list or failure
  271. }
  272. RegCloseKey(nwAdapters);
  273. }
  274. std::string errlist;
  275. for (std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin()); iidp != instanceIdPathsToRemove.end(); ++iidp) {
  276. std::string err = deletePersistentTapDevice(iidp->c_str());
  277. if (err.length() > 0) {
  278. if (errlist.length() > 0)
  279. errlist.push_back(',');
  280. errlist.append(err);
  281. }
  282. }
  283. return errlist;
  284. }
  285. std::string WindowsEthernetTap::destroyAllPersistentTapDevices()
  286. {
  287. char subkeyName[1024];
  288. char subkeyClass[1024];
  289. char data[1024];
  290. std::set<std::string> instanceIdPathsToRemove;
  291. {
  292. HKEY nwAdapters;
  293. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) != ERROR_SUCCESS)
  294. return std::string("Could not open registry key");
  295. for (DWORD subkeyIndex = 0;; ++subkeyIndex) {
  296. DWORD type;
  297. DWORD dataLen;
  298. DWORD subkeyNameLen = sizeof(subkeyName);
  299. DWORD subkeyClassLen = sizeof(subkeyClass);
  300. FILETIME lastWriteTime;
  301. if (RegEnumKeyExA(nwAdapters, subkeyIndex, subkeyName, &subkeyNameLen, (DWORD*)0, subkeyClass, &subkeyClassLen, &lastWriteTime) == ERROR_SUCCESS) {
  302. type = 0;
  303. dataLen = sizeof(data);
  304. if (RegGetValueA(nwAdapters, subkeyName, "ComponentId", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS) {
  305. data[dataLen] = '\0';
  306. if (! strnicmp(data, "zttap", 5)) {
  307. std::string instanceIdPath;
  308. type = 0;
  309. dataLen = sizeof(data);
  310. if (RegGetValueA(nwAdapters, subkeyName, "DeviceInstanceID", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS)
  311. instanceIdPath.assign(data, dataLen);
  312. if (instanceIdPath.length() != 0)
  313. instanceIdPathsToRemove.insert(instanceIdPath);
  314. }
  315. }
  316. }
  317. else
  318. break; // end of list or failure
  319. }
  320. RegCloseKey(nwAdapters);
  321. }
  322. std::string errlist;
  323. for (std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin()); iidp != instanceIdPathsToRemove.end(); ++iidp) {
  324. std::string err = deletePersistentTapDevice(iidp->c_str());
  325. if (err.length() > 0) {
  326. if (errlist.length() > 0)
  327. errlist.push_back(',');
  328. errlist.append(err);
  329. }
  330. }
  331. return errlist;
  332. }
  333. std::string WindowsEthernetTap::deletePersistentTapDevice(const char* instanceId)
  334. {
  335. char iid[256];
  336. SP_REMOVEDEVICE_PARAMS rmdParams;
  337. memset(&rmdParams, 0, sizeof(rmdParams));
  338. rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  339. rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
  340. rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
  341. rmdParams.HwProfile = 0;
  342. Mutex::Lock _l(_systemDeviceManagementLock);
  343. HDEVINFO devInfo = WINENV.SetupDiGetClassDevsExA((const GUID*)0, (PCSTR)0, (HWND)0, DIGCF_ALLCLASSES, (HDEVINFO)0, (PCSTR)0, (PVOID)0);
  344. if (devInfo == INVALID_HANDLE_VALUE)
  345. return std::string("SetupDiGetClassDevsExA() failed");
  346. WINENV.SetupDiOpenDeviceInfoA(devInfo, instanceId, (HWND)0, 0, (PSP_DEVINFO_DATA)0);
  347. SP_DEVINFO_DATA devInfoData;
  348. memset(&devInfoData, 0, sizeof(devInfoData));
  349. devInfoData.cbSize = sizeof(devInfoData);
  350. for (DWORD devIndex = 0; WINENV.SetupDiEnumDeviceInfo(devInfo, devIndex, &devInfoData); devIndex++) {
  351. if ((WINENV.CM_Get_Device_ID_ExA(devInfoData.DevInst, iid, sizeof(iid), 0, (HMACHINE)0) == CR_SUCCESS) && (! strcmp(iid, instanceId))) {
  352. if (! WINENV.SetupDiSetClassInstallParamsA(devInfo, &devInfoData, &rmdParams.ClassInstallHeader, sizeof(rmdParams))) {
  353. WINENV.SetupDiDestroyDeviceInfoList(devInfo);
  354. return std::string("SetupDiSetClassInstallParams() failed");
  355. }
  356. if (! WINENV.SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData)) {
  357. WINENV.SetupDiDestroyDeviceInfoList(devInfo);
  358. return std::string("SetupDiCallClassInstaller(DIF_REMOVE) failed");
  359. }
  360. WINENV.SetupDiDestroyDeviceInfoList(devInfo);
  361. return std::string();
  362. }
  363. }
  364. WINENV.SetupDiDestroyDeviceInfoList(devInfo);
  365. return std::string("instance ID not found");
  366. }
  367. bool WindowsEthernetTap::setPersistentTapDeviceState(const char* instanceId, bool enabled)
  368. {
  369. char iid[256];
  370. SP_PROPCHANGE_PARAMS params;
  371. Mutex::Lock _l(_systemDeviceManagementLock);
  372. HDEVINFO devInfo = WINENV.SetupDiGetClassDevsExA((const GUID*)0, (PCSTR)0, (HWND)0, DIGCF_ALLCLASSES, (HDEVINFO)0, (PCSTR)0, (PVOID)0);
  373. if (devInfo == INVALID_HANDLE_VALUE)
  374. return false;
  375. WINENV.SetupDiOpenDeviceInfoA(devInfo, instanceId, (HWND)0, 0, (PSP_DEVINFO_DATA)0);
  376. SP_DEVINFO_DATA devInfoData;
  377. memset(&devInfoData, 0, sizeof(devInfoData));
  378. devInfoData.cbSize = sizeof(devInfoData);
  379. for (DWORD devIndex = 0; WINENV.SetupDiEnumDeviceInfo(devInfo, devIndex, &devInfoData); devIndex++) {
  380. if ((WINENV.CM_Get_Device_ID_ExA(devInfoData.DevInst, iid, sizeof(iid), 0, (HMACHINE)0) == CR_SUCCESS) && (! strcmp(iid, instanceId))) {
  381. memset(&params, 0, sizeof(params));
  382. params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  383. params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  384. params.StateChange = enabled ? DICS_ENABLE : DICS_DISABLE;
  385. params.Scope = DICS_FLAG_GLOBAL;
  386. params.HwProfile = 0;
  387. WINENV.SetupDiSetClassInstallParamsA(devInfo, &devInfoData, &params.ClassInstallHeader, sizeof(params));
  388. WINENV.SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, devInfo, &devInfoData);
  389. memset(&params, 0, sizeof(params));
  390. params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  391. params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  392. params.StateChange = enabled ? DICS_ENABLE : DICS_DISABLE;
  393. params.Scope = DICS_FLAG_CONFIGSPECIFIC;
  394. params.HwProfile = 0;
  395. WINENV.SetupDiSetClassInstallParamsA(devInfo, &devInfoData, &params.ClassInstallHeader, sizeof(params));
  396. WINENV.SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, devInfo, &devInfoData);
  397. WINENV.SetupDiDestroyDeviceInfoList(devInfo);
  398. return true;
  399. }
  400. }
  401. WINENV.SetupDiDestroyDeviceInfoList(devInfo);
  402. return false;
  403. }
  404. WindowsEthernetTap::WindowsEthernetTap(
  405. const char* hp,
  406. const MAC& mac,
  407. unsigned int mtu,
  408. unsigned int metric,
  409. uint64_t nwid,
  410. const char* friendlyName,
  411. void (*handler)(void*, void*, uint64_t, const MAC&, const MAC&, unsigned int, unsigned int, const void*, unsigned int),
  412. void* arg)
  413. : _handler(handler)
  414. , _arg(arg)
  415. , _mac(mac)
  416. , _nwid(nwid)
  417. , _mtu(mtu)
  418. , _tap(INVALID_HANDLE_VALUE)
  419. , _friendlyName(friendlyName)
  420. , _injectSemaphore(INVALID_HANDLE_VALUE)
  421. , _pathToHelpers(hp)
  422. , _run(true)
  423. , _initialized(false)
  424. , _enabled(true)
  425. , _lastIfAddrsUpdate(0)
  426. {
  427. char subkeyName[1024];
  428. char subkeyClass[1024];
  429. char data[1024];
  430. char tag[24];
  431. // We "tag" registry entries with the network ID to identify persistent devices
  432. OSUtils::ztsnprintf(tag, sizeof(tag), "%.16llx", (unsigned long long)nwid);
  433. Mutex::Lock _l(_systemTapInitLock);
  434. HKEY nwAdapters;
  435. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) != ERROR_SUCCESS)
  436. throw std::runtime_error("unable to open registry key for network adapter enumeration");
  437. // Look for the tap instance that corresponds with this network
  438. for (DWORD subkeyIndex = 0;; ++subkeyIndex) {
  439. DWORD type;
  440. DWORD dataLen;
  441. DWORD subkeyNameLen = sizeof(subkeyName);
  442. DWORD subkeyClassLen = sizeof(subkeyClass);
  443. FILETIME lastWriteTime;
  444. if (RegEnumKeyExA(nwAdapters, subkeyIndex, subkeyName, &subkeyNameLen, (DWORD*)0, subkeyClass, &subkeyClassLen, &lastWriteTime) == ERROR_SUCCESS) {
  445. type = 0;
  446. dataLen = sizeof(data);
  447. if (RegGetValueA(nwAdapters, subkeyName, "ComponentId", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS) {
  448. data[dataLen] = (char)0;
  449. if (WINENV.tapDriverName == data) {
  450. std::string instanceId;
  451. type = 0;
  452. dataLen = sizeof(data);
  453. if (RegGetValueA(nwAdapters, subkeyName, "NetCfgInstanceId", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS)
  454. instanceId.assign(data, dataLen);
  455. std::string instanceIdPath;
  456. type = 0;
  457. dataLen = sizeof(data);
  458. if (RegGetValueA(nwAdapters, subkeyName, "DeviceInstanceID", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS)
  459. instanceIdPath.assign(data, dataLen);
  460. if ((_netCfgInstanceId.length() == 0) && (instanceId.length() != 0) && (instanceIdPath.length() != 0)) {
  461. type = 0;
  462. dataLen = sizeof(data);
  463. if (RegGetValueA(nwAdapters, subkeyName, "_ZeroTierTapIdentifier", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS) {
  464. data[dataLen] = '\0';
  465. if (! strcmp(data, tag)) {
  466. _netCfgInstanceId = instanceId;
  467. _deviceInstanceId = instanceIdPath;
  468. _mySubkeyName = subkeyName;
  469. break; // found it!
  470. }
  471. }
  472. }
  473. }
  474. }
  475. }
  476. else
  477. break; // no more subkeys or error occurred enumerating them
  478. }
  479. // If there is no device, try to create one
  480. bool creatingNewDevice = (_netCfgInstanceId.length() == 0);
  481. std::string newDeviceInstanceId;
  482. if (creatingNewDevice) {
  483. for (int getNewAttemptCounter = 0; getNewAttemptCounter < 2; ++getNewAttemptCounter) {
  484. for (DWORD subkeyIndex = 0;; ++subkeyIndex) {
  485. DWORD type;
  486. DWORD dataLen;
  487. DWORD subkeyNameLen = sizeof(subkeyName);
  488. DWORD subkeyClassLen = sizeof(subkeyClass);
  489. FILETIME lastWriteTime;
  490. if (RegEnumKeyExA(nwAdapters, subkeyIndex, subkeyName, &subkeyNameLen, (DWORD*)0, subkeyClass, &subkeyClassLen, &lastWriteTime) == ERROR_SUCCESS) {
  491. type = 0;
  492. dataLen = sizeof(data);
  493. if (RegGetValueA(nwAdapters, subkeyName, "ComponentId", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS) {
  494. data[dataLen] = '\0';
  495. if (WINENV.tapDriverName == data) {
  496. type = 0;
  497. dataLen = sizeof(data);
  498. if ((RegGetValueA(nwAdapters, subkeyName, "_ZeroTierTapIdentifier", RRF_RT_ANY, &type, (PVOID)data, &dataLen) != ERROR_SUCCESS) || (dataLen <= 0)) {
  499. type = 0;
  500. dataLen = sizeof(data);
  501. if (RegGetValueA(nwAdapters, subkeyName, "NetCfgInstanceId", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS) {
  502. RegSetKeyValueA(nwAdapters, subkeyName, "_ZeroTierTapIdentifier", REG_SZ, tag, (DWORD)(strlen(tag) + 1));
  503. _netCfgInstanceId.assign(data, dataLen);
  504. type = 0;
  505. dataLen = sizeof(data);
  506. if (RegGetValueA(nwAdapters, subkeyName, "DeviceInstanceID", RRF_RT_ANY, &type, (PVOID)data, &dataLen) == ERROR_SUCCESS)
  507. _deviceInstanceId.assign(data, dataLen);
  508. _mySubkeyName = subkeyName;
  509. // Disable DHCP by default on new devices
  510. HKEY tcpIpInterfaces;
  511. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ | KEY_WRITE, &tcpIpInterfaces) == ERROR_SUCCESS) {
  512. DWORD enable = 0;
  513. RegSetKeyValueA(tcpIpInterfaces, _netCfgInstanceId.c_str(), "EnableDHCP", REG_DWORD, &enable, sizeof(enable));
  514. RegCloseKey(tcpIpInterfaces);
  515. }
  516. break; // found an unused zttap device
  517. }
  518. }
  519. }
  520. }
  521. }
  522. else
  523. break; // no more keys or error occurred
  524. }
  525. if (_netCfgInstanceId.length() > 0) {
  526. break; // found an unused zttap device
  527. }
  528. else {
  529. // no unused zttap devices, so create one
  530. std::string errm = addNewPersistentTapDevice((std::string(_pathToHelpers) + WINENV.tapDriverPath).c_str(), newDeviceInstanceId);
  531. if (errm.length() > 0)
  532. throw std::runtime_error(std::string("unable to create new device instance: ") + errm);
  533. }
  534. }
  535. }
  536. if (_netCfgInstanceId.length() > 0) {
  537. char tmps[64];
  538. unsigned int tmpsl = OSUtils::ztsnprintf(tmps, sizeof(tmps), "%.2X-%.2X-%.2X-%.2X-%.2X-%.2X", (unsigned int)mac[0], (unsigned int)mac[1], (unsigned int)mac[2], (unsigned int)mac[3], (unsigned int)mac[4], (unsigned int)mac[5]) + 1;
  539. RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "NetworkAddress", REG_SZ, tmps, tmpsl);
  540. RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MAC", REG_SZ, tmps, tmpsl);
  541. tmpsl = OSUtils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu);
  542. RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MTU", REG_SZ, tmps, tmpsl);
  543. DWORD tmp = 0;
  544. RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "*NdisDeviceType", REG_DWORD, (LPCVOID)&tmp, sizeof(tmp));
  545. tmp = IF_TYPE_ETHERNET_CSMACD;
  546. RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "*IfType", REG_DWORD, (LPCVOID)&tmp, sizeof(tmp));
  547. if (creatingNewDevice) {
  548. // Vista/2008 does not set this
  549. if (newDeviceInstanceId.length() > 0)
  550. RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "DeviceInstanceID", REG_SZ, newDeviceInstanceId.c_str(), (DWORD)newDeviceInstanceId.length());
  551. // Set EnableDHCP to 0 by default on new devices
  552. tmp = 0;
  553. RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "EnableDHCP", REG_DWORD, (LPCVOID)&tmp, sizeof(tmp));
  554. }
  555. RegCloseKey(nwAdapters);
  556. }
  557. else {
  558. RegCloseKey(nwAdapters);
  559. throw std::runtime_error("unable to find or create tap adapter");
  560. }
  561. {
  562. char nobraces[128]; // strip braces from GUID before converting it, because Windows
  563. const char* nbtmp1 = _netCfgInstanceId.c_str();
  564. char* nbtmp2 = nobraces;
  565. while (*nbtmp1) {
  566. if ((*nbtmp1 != '{') && (*nbtmp1 != '}'))
  567. *nbtmp2++ = *nbtmp1;
  568. ++nbtmp1;
  569. }
  570. *nbtmp2 = (char)0;
  571. if (UuidFromStringA((RPC_CSTR)nobraces, &_deviceGuid) != RPC_S_OK)
  572. throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
  573. }
  574. // Get the LUID, which is one of like four fucking ways to refer to a network device in Windows
  575. if (ConvertInterfaceGuidToLuid(&_deviceGuid, &_deviceLuid) != NO_ERROR)
  576. throw std::runtime_error("unable to convert device interface GUID to LUID");
  577. //_initialized = true;
  578. if (friendlyName)
  579. setFriendlyName(friendlyName);
  580. _injectSemaphore = CreateSemaphore(NULL, 0, 1, NULL);
  581. _thread = Thread::start(this);
  582. }
  583. WindowsEthernetTap::~WindowsEthernetTap()
  584. {
  585. WinDNSHelper::removeDNS(_nwid);
  586. _run = false;
  587. ReleaseSemaphore(_injectSemaphore, 1, NULL);
  588. Thread::join(_thread);
  589. CloseHandle(_injectSemaphore);
  590. setPersistentTapDeviceState(_deviceInstanceId.c_str(), false);
  591. }
  592. void WindowsEthernetTap::setEnabled(bool en)
  593. {
  594. _enabled = en;
  595. }
  596. bool WindowsEthernetTap::enabled() const
  597. {
  598. return _enabled;
  599. }
  600. bool WindowsEthernetTap::addIp(const InetAddress& ip)
  601. {
  602. if (! ip.netmaskBits()) // sanity check... netmask of 0.0.0.0 is WUT?
  603. return false;
  604. Mutex::Lock _l(_assignedIps_m);
  605. if (std::find(_assignedIps.begin(), _assignedIps.end(), ip) != _assignedIps.end())
  606. return true;
  607. _assignedIps.push_back(ip);
  608. _syncIps();
  609. return true;
  610. }
  611. bool WindowsEthernetTap::removeIp(const InetAddress& ip)
  612. {
  613. if (ip.isV6())
  614. return true;
  615. {
  616. Mutex::Lock _l(_assignedIps_m);
  617. std::vector<InetAddress>::iterator aip(std::find(_assignedIps.begin(), _assignedIps.end(), ip));
  618. if (aip != _assignedIps.end())
  619. _assignedIps.erase(aip);
  620. }
  621. if (! _initialized)
  622. return false;
  623. try {
  624. MIB_UNICASTIPADDRESS_TABLE* ipt = (MIB_UNICASTIPADDRESS_TABLE*)0;
  625. if (GetUnicastIpAddressTable(AF_UNSPEC, &ipt) == NO_ERROR) {
  626. if ((ipt) && (ipt->NumEntries > 0)) {
  627. for (DWORD i = 0; i < (DWORD)ipt->NumEntries; ++i) {
  628. if (ipt->Table[i].InterfaceLuid.Value == _deviceLuid.Value) {
  629. InetAddress addr;
  630. switch (ipt->Table[i].Address.si_family) {
  631. case AF_INET:
  632. addr.set(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr), 4, ipt->Table[i].OnLinkPrefixLength);
  633. break;
  634. case AF_INET6:
  635. addr.set(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte, 16, ipt->Table[i].OnLinkPrefixLength);
  636. if (addr.ipScope() == InetAddress::IP_SCOPE_LINK_LOCAL)
  637. continue; // can't remove link-local IPv6 addresses
  638. break;
  639. }
  640. if (addr == ip) {
  641. DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
  642. FreeMibTable(ipt);
  643. if (ip.isV4()) {
  644. std::vector<std::string> regIps(_getRegistryIPv4Value("IPAddress"));
  645. std::vector<std::string> regSubnetMasks(_getRegistryIPv4Value("SubnetMask"));
  646. char ipbuf[64];
  647. std::string ipstr(ip.toIpString(ipbuf));
  648. for (std::vector<std::string>::iterator rip(regIps.begin()), rm(regSubnetMasks.begin()); ((rip != regIps.end()) && (rm != regSubnetMasks.end())); ++rip, ++rm) {
  649. if (*rip == ipstr) {
  650. regIps.erase(rip);
  651. regSubnetMasks.erase(rm);
  652. _setRegistryIPv4Value("IPAddress", regIps);
  653. _setRegistryIPv4Value("SubnetMask", regSubnetMasks);
  654. break;
  655. }
  656. }
  657. }
  658. return true;
  659. }
  660. }
  661. }
  662. }
  663. FreeMibTable((PVOID)ipt);
  664. }
  665. }
  666. catch (...) {
  667. }
  668. return false;
  669. }
  670. std::vector<InetAddress> WindowsEthernetTap::ips() const
  671. {
  672. static const InetAddress linkLocalLoopback("fe80::1/64"); // what is this and why does Windows assign it?
  673. std::vector<InetAddress> addrs;
  674. if (! _initialized)
  675. return addrs;
  676. uint64_t now = OSUtils::now();
  677. if ((now - _lastIfAddrsUpdate) <= GETIFADDRS_CACHE_TIME) {
  678. return _ifaddrs;
  679. }
  680. _lastIfAddrsUpdate = now;
  681. try {
  682. MIB_UNICASTIPADDRESS_TABLE* ipt = (MIB_UNICASTIPADDRESS_TABLE*)0;
  683. if (GetUnicastIpAddressTable(AF_UNSPEC, &ipt) == NO_ERROR) {
  684. if ((ipt) && (ipt->NumEntries > 0)) {
  685. for (DWORD i = 0; i < (DWORD)ipt->NumEntries; ++i) {
  686. if (ipt->Table[i].InterfaceLuid.Value == _deviceLuid.Value) {
  687. switch (ipt->Table[i].Address.si_family) {
  688. case AF_INET: {
  689. InetAddress ip(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr), 4, ipt->Table[i].OnLinkPrefixLength);
  690. if (ip != InetAddress::LO4)
  691. addrs.push_back(ip);
  692. } break;
  693. case AF_INET6: {
  694. InetAddress ip(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte, 16, ipt->Table[i].OnLinkPrefixLength);
  695. if ((ip != linkLocalLoopback) && (ip != InetAddress::LO6))
  696. addrs.push_back(ip);
  697. } break;
  698. }
  699. }
  700. }
  701. }
  702. FreeMibTable(ipt);
  703. }
  704. }
  705. catch (...) {
  706. } // sanity check, shouldn't happen unless out of memory
  707. std::sort(addrs.begin(), addrs.end());
  708. addrs.erase(std::unique(addrs.begin(), addrs.end()), addrs.end());
  709. _ifaddrs = addrs;
  710. return addrs;
  711. }
  712. void WindowsEthernetTap::put(const MAC& from, const MAC& to, unsigned int etherType, const void* data, unsigned int len)
  713. {
  714. if ((! _initialized) || (! _enabled) || (_tap == INVALID_HANDLE_VALUE) || (len > _mtu))
  715. return;
  716. Mutex::Lock _l(_injectPending_m);
  717. _injectPending.emplace();
  718. _injectPending.back().len = len + 14;
  719. char* const d = _injectPending.back().data;
  720. to.copyTo(d, 6);
  721. from.copyTo(d + 6, 6);
  722. d[12] = (char)((etherType >> 8) & 0xff);
  723. d[13] = (char)(etherType & 0xff);
  724. memcpy(d + 14, data, len);
  725. ReleaseSemaphore(_injectSemaphore, 1, NULL);
  726. }
  727. std::string WindowsEthernetTap::deviceName() const
  728. {
  729. char tmp[1024];
  730. if (ConvertInterfaceLuidToNameA(&_deviceLuid, tmp, sizeof(tmp)) != NO_ERROR)
  731. return std::string("[ConvertInterfaceLuidToName() failed]");
  732. return std::string(tmp);
  733. }
  734. void WindowsEthernetTap::setFriendlyName(const char* dn)
  735. {
  736. if (! _initialized)
  737. return;
  738. HKEY ifp;
  739. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, (std::string("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\") + _netCfgInstanceId).c_str(), 0, KEY_READ | KEY_WRITE, &ifp) == ERROR_SUCCESS) {
  740. RegSetKeyValueA(ifp, "Connection", "Name", REG_SZ, (LPCVOID)dn, (DWORD)(strlen(dn) + 1));
  741. RegCloseKey(ifp);
  742. }
  743. HRESULT hr = S_OK;
  744. INetSharingManager* nsm;
  745. hr = CoCreateInstance(__uuidof(NetSharingManager), NULL, CLSCTX_ALL, __uuidof(INetSharingManager), (void**)&nsm);
  746. if (hr != S_OK)
  747. return;
  748. bool found = false;
  749. INetSharingEveryConnectionCollection* nsecc = nullptr;
  750. hr = nsm->get_EnumEveryConnection(&nsecc);
  751. if (! nsecc) {
  752. fprintf(stderr, "Failed to get NSM connections");
  753. return;
  754. }
  755. IEnumVARIANT* ev = nullptr;
  756. IUnknown* unk = nullptr;
  757. hr = nsecc->get__NewEnum(&unk);
  758. if (unk) {
  759. hr = unk->QueryInterface(__uuidof(IEnumVARIANT), (void**)&ev);
  760. unk->Release();
  761. }
  762. if (ev) {
  763. VARIANT v;
  764. VariantInit(&v);
  765. while ((S_OK == ev->Next(1, &v, NULL)) && found == FALSE) {
  766. if (V_VT(&v) == VT_UNKNOWN) {
  767. INetConnection* nc = nullptr;
  768. V_UNKNOWN(&v)->QueryInterface(__uuidof(INetConnection), (void**)&nc);
  769. if (nc) {
  770. NETCON_PROPERTIES* ncp = nullptr;
  771. nc->GetProperties(&ncp);
  772. if (ncp != nullptr) {
  773. GUID curId = ncp->guidId;
  774. if (curId == _deviceGuid) {
  775. wchar_t wtext[255];
  776. mbstowcs(wtext, dn, strlen(dn) + 1);
  777. nc->Rename(wtext);
  778. found = true;
  779. }
  780. }
  781. nc->Release();
  782. }
  783. }
  784. VariantClear(&v);
  785. }
  786. ev->Release();
  787. }
  788. nsecc->Release();
  789. _friendlyName_m.lock();
  790. _friendlyName = dn;
  791. _friendlyName_m.unlock();
  792. }
  793. std::string WindowsEthernetTap::friendlyName() const
  794. {
  795. Mutex::Lock l(_friendlyName_m);
  796. return _friendlyName;
  797. }
  798. void WindowsEthernetTap::scanMulticastGroups(std::vector<MulticastGroup>& added, std::vector<MulticastGroup>& removed)
  799. {
  800. if (! _initialized)
  801. return;
  802. HANDLE t = _tap;
  803. if (t == INVALID_HANDLE_VALUE)
  804. return;
  805. std::vector<MulticastGroup> newGroups;
  806. // The ZT1 tap driver supports an IOCTL to get multicast memberships at the L2
  807. // level... something Windows does not seem to expose ordinarily. This lets
  808. // pretty much anything work... IPv4, IPv6, IPX, oldskool Netbios, who knows...
  809. unsigned char mcastbuf[TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE];
  810. DWORD bytesReturned = 0;
  811. if (DeviceIoControl(t, TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS, (LPVOID)mcastbuf, sizeof(mcastbuf), (LPVOID)mcastbuf, sizeof(mcastbuf), &bytesReturned, NULL)) {
  812. if ((bytesReturned > 0) && (bytesReturned <= TAP_WIN_IOCTL_GET_MULTICAST_MEMBERSHIPS_OUTPUT_BUF_SIZE)) { // sanity check
  813. MAC mac;
  814. DWORD i = 0;
  815. while ((i + 6) <= bytesReturned) {
  816. mac.setTo(mcastbuf + i, 6);
  817. i += 6;
  818. if ((mac.isMulticast()) && (! mac.isBroadcast())) {
  819. // exclude the nulls that may be returned or any other junk Windows puts in there
  820. newGroups.push_back(MulticastGroup(mac, 0));
  821. }
  822. }
  823. }
  824. }
  825. std::vector<InetAddress> allIps(ips());
  826. for (std::vector<InetAddress>::iterator ip(allIps.begin()); ip != allIps.end(); ++ip)
  827. newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));
  828. std::sort(newGroups.begin(), newGroups.end());
  829. newGroups.erase(std::unique(newGroups.begin(), newGroups.end()), newGroups.end());
  830. for (std::vector<MulticastGroup>::iterator m(newGroups.begin()); m != newGroups.end(); ++m) {
  831. if (! std::binary_search(_multicastGroups.begin(), _multicastGroups.end(), *m))
  832. added.push_back(*m);
  833. }
  834. for (std::vector<MulticastGroup>::iterator m(_multicastGroups.begin()); m != _multicastGroups.end(); ++m) {
  835. if (! std::binary_search(newGroups.begin(), newGroups.end(), *m))
  836. removed.push_back(*m);
  837. }
  838. _multicastGroups.swap(newGroups);
  839. }
  840. void WindowsEthernetTap::setMtu(unsigned int mtu)
  841. {
  842. if (mtu != _mtu) {
  843. _mtu = mtu;
  844. HKEY nwAdapters;
  845. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) == ERROR_SUCCESS) {
  846. char tmps[64];
  847. unsigned int tmpsl = OSUtils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu);
  848. RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MTU", REG_SZ, tmps, tmpsl);
  849. RegCloseKey(nwAdapters);
  850. }
  851. }
  852. }
  853. NET_IFINDEX WindowsEthernetTap::interfaceIndex() const
  854. {
  855. NET_IFINDEX idx = -1;
  856. if (ConvertInterfaceLuidToIndex(&_deviceLuid, &idx) == NO_ERROR)
  857. return idx;
  858. return -1;
  859. }
  860. void WindowsEthernetTap::threadMain() throw()
  861. {
  862. HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED);
  863. if (FAILED(hres)) {
  864. fprintf(stderr, "WinEthernetTap: COM initialization failed");
  865. return;
  866. }
  867. char tapReadBuf[ZT_MAX_MTU + 32];
  868. char tapPath[128];
  869. HANDLE wait4[3];
  870. OVERLAPPED tapOvlRead, tapOvlWrite;
  871. OSUtils::ztsnprintf(tapPath, sizeof(tapPath), "\\\\.\\Global\\%s.tap", _netCfgInstanceId.c_str());
  872. try {
  873. while (_run) {
  874. // Because Windows
  875. Sleep(250);
  876. setPersistentTapDeviceState(_deviceInstanceId.c_str(), false);
  877. Sleep(250);
  878. setPersistentTapDeviceState(_deviceInstanceId.c_str(), true);
  879. Sleep(250);
  880. setPersistentTapDeviceState(_deviceInstanceId.c_str(), false);
  881. Sleep(250);
  882. setPersistentTapDeviceState(_deviceInstanceId.c_str(), true);
  883. Sleep(250);
  884. _tap = CreateFileA(tapPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
  885. if (_tap == INVALID_HANDLE_VALUE) {
  886. Sleep(250);
  887. continue;
  888. }
  889. {
  890. uint32_t tmpi = 1;
  891. DWORD bytesReturned = 0;
  892. DeviceIoControl(_tap, TAP_WIN_IOCTL_SET_MEDIA_STATUS, &tmpi, sizeof(tmpi), &tmpi, sizeof(tmpi), &bytesReturned, NULL);
  893. }
  894. #ifdef ZT_WINDOWS_CREATE_FAKE_DEFAULT_ROUTE
  895. {
  896. /* This inserts a fake default route and a fake ARP entry, forcing
  897. * Windows to detect this as a "real" network and apply proper
  898. * firewall rules.
  899. *
  900. * This hack is completely stupid, but Windows made me do it
  901. * by being broken and insane.
  902. *
  903. * Background: Windows tries to detect its network location by
  904. * matching it to the ARP address of the default route. Networks
  905. * without default routes are "unidentified networks" and cannot
  906. * have their firewall classification changed by the user (easily).
  907. *
  908. * Yes, you read that right.
  909. *
  910. * The common workaround is to set *NdisDeviceType to 1, which
  911. * totally disables all Windows firewall functionality. This is
  912. * the answer you'll find on most forums for things like OpenVPN.
  913. *
  914. * Yes, you read that right.
  915. *
  916. * The default route workaround is also known, but for this to
  917. * work there must be a known default IP that resolves to a known
  918. * ARP address. This works for an OpenVPN tunnel, but not here
  919. * because this isn't a tunnel. It's a mesh. There is no "other
  920. * end," or any other known always on IP.
  921. *
  922. * So let's make a fake one and shove it in there along with its
  923. * fake static ARP entry. Also makes it instant-on and static.
  924. *
  925. * We'll have to see what DHCP does with this. In the future we
  926. * probably will not want to do this on DHCP-enabled networks, so
  927. * when we enable DHCP we will go in and yank this wacko hacko from
  928. * the routing table before doing so.
  929. *
  930. * Like Jesse Pinkman would say: "YEEEEAAH BITCH!" */
  931. const uint32_t fakeIp = htonl(0x19fffffe); // 25.255.255.254 -- unrouted IPv4 block
  932. for (int i = 0; i < 8; ++i) {
  933. MIB_IPNET_ROW2 ipnr;
  934. memset(&ipnr, 0, sizeof(ipnr));
  935. ipnr.Address.si_family = AF_INET;
  936. ipnr.Address.Ipv4.sin_addr.s_addr = fakeIp;
  937. ipnr.InterfaceLuid.Value = _deviceLuid.Value;
  938. ipnr.PhysicalAddress[0] = _mac[0] ^ 0x10; // just make something up that's consistent and not part of this net
  939. ipnr.PhysicalAddress[1] = 0x00;
  940. ipnr.PhysicalAddress[2] = (UCHAR)((_deviceGuid.Data1 >> 24) & 0xff);
  941. ipnr.PhysicalAddress[3] = (UCHAR)((_deviceGuid.Data1 >> 16) & 0xff);
  942. ipnr.PhysicalAddress[4] = (UCHAR)((_deviceGuid.Data1 >> 8) & 0xff);
  943. ipnr.PhysicalAddress[5] = (UCHAR)(_deviceGuid.Data1 & 0xff);
  944. ipnr.PhysicalAddressLength = 6;
  945. ipnr.State = NlnsPermanent;
  946. ipnr.IsRouter = 1;
  947. ipnr.IsUnreachable = 0;
  948. ipnr.ReachabilityTime.LastReachable = 0x0fffffff;
  949. ipnr.ReachabilityTime.LastUnreachable = 1;
  950. DWORD result = CreateIpNetEntry2(&ipnr);
  951. if (result != NO_ERROR)
  952. Sleep(250);
  953. else
  954. break;
  955. }
  956. for (int i = 0; i < 8; ++i) {
  957. MIB_IPFORWARD_ROW2 nr;
  958. memset(&nr, 0, sizeof(nr));
  959. InitializeIpForwardEntry(&nr);
  960. nr.InterfaceLuid.Value = _deviceLuid.Value;
  961. nr.DestinationPrefix.Prefix.si_family = AF_INET; // rest is left as 0.0.0.0/0
  962. nr.NextHop.si_family = AF_INET;
  963. nr.NextHop.Ipv4.sin_addr.s_addr = fakeIp;
  964. nr.Metric = 9999; // do not use as real default route
  965. nr.Protocol = MIB_IPPROTO_NETMGMT;
  966. DWORD result = CreateIpForwardEntry2(&nr);
  967. if (result != NO_ERROR)
  968. Sleep(250);
  969. else
  970. break;
  971. }
  972. }
  973. #endif
  974. // Assign or re-assign any should-be-assigned IPs in case we have restarted
  975. {
  976. Mutex::Lock _l(_assignedIps_m);
  977. _syncIps();
  978. }
  979. memset(&tapOvlRead, 0, sizeof(tapOvlRead));
  980. tapOvlRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  981. memset(&tapOvlWrite, 0, sizeof(tapOvlWrite));
  982. tapOvlWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  983. wait4[0] = _injectSemaphore;
  984. wait4[1] = tapOvlRead.hEvent;
  985. wait4[2] = tapOvlWrite.hEvent; // only included if writeInProgress is true
  986. ReadFile(_tap, tapReadBuf, sizeof(tapReadBuf), NULL, &tapOvlRead);
  987. bool writeInProgress = false;
  988. ULONGLONG timeOfLastBorkCheck = GetTickCount64();
  989. _initialized = true;
  990. unsigned int oldmtu = _mtu;
  991. setFriendlyName(_friendlyName.c_str());
  992. while (_run) {
  993. DWORD waitResult = WaitForMultipleObjectsEx(writeInProgress ? 3 : 2, wait4, FALSE, 2500, TRUE);
  994. if (! _run)
  995. break; // will also break outer while(_run) since _run is false
  996. // Check for changes in MTU and break to restart tap device to reconfigure in this case
  997. if (_mtu != oldmtu)
  998. break;
  999. // Check for issues with adapter and close/reopen if any are detected. This
  1000. // check fixes a while boatload of Windows adapter 'coma' issues after
  1001. // sleep/wake and when adapters are added/removed. Basically if the tap
  1002. // device is borked, whack it.
  1003. {
  1004. ULONGLONG tc = GetTickCount64();
  1005. if ((tc - timeOfLastBorkCheck) >= 2500) {
  1006. timeOfLastBorkCheck = tc;
  1007. char aabuf[16384];
  1008. ULONG aalen = sizeof(aabuf);
  1009. if (GetAdaptersAddresses(
  1010. AF_UNSPEC,
  1011. GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME,
  1012. (void*)0,
  1013. reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf),
  1014. &aalen)
  1015. == NO_ERROR) {
  1016. bool isBorked = false;
  1017. PIP_ADAPTER_ADDRESSES aa = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf);
  1018. while (aa) {
  1019. if (_deviceLuid.Value == aa->Luid.Value) {
  1020. isBorked = (aa->OperStatus != IfOperStatusUp);
  1021. break;
  1022. }
  1023. aa = aa->Next;
  1024. }
  1025. if (isBorked) {
  1026. // Close and reopen tap device if there's an issue (outer loop)
  1027. break;
  1028. }
  1029. }
  1030. }
  1031. }
  1032. if ((waitResult == WAIT_TIMEOUT) || (waitResult == WAIT_FAILED)) {
  1033. Sleep(250); // guard against spinning under some conditions
  1034. continue;
  1035. }
  1036. if (HasOverlappedIoCompleted(&tapOvlRead)) {
  1037. DWORD bytesRead = 0;
  1038. if (GetOverlappedResult(_tap, &tapOvlRead, &bytesRead, FALSE)) {
  1039. if ((bytesRead > 14) && (_enabled)) {
  1040. MAC to(tapReadBuf, 6);
  1041. MAC from(tapReadBuf + 6, 6);
  1042. unsigned int etherType = ((((unsigned int)tapReadBuf[12]) & 0xff) << 8) | (((unsigned int)tapReadBuf[13]) & 0xff);
  1043. try {
  1044. _handler(_arg, (void*)0, _nwid, from, to, etherType, 0, tapReadBuf + 14, bytesRead - 14);
  1045. }
  1046. catch (...) {
  1047. } // handlers should not throw
  1048. }
  1049. }
  1050. ReadFile(_tap, tapReadBuf, ZT_MAX_MTU + 32, NULL, &tapOvlRead);
  1051. }
  1052. if (writeInProgress) {
  1053. if (HasOverlappedIoCompleted(&tapOvlWrite)) {
  1054. writeInProgress = false;
  1055. _injectPending_m.lock();
  1056. _injectPending.pop();
  1057. }
  1058. else
  1059. continue; // still writing, so skip code below and wait
  1060. }
  1061. else
  1062. _injectPending_m.lock();
  1063. if (! _injectPending.empty()) {
  1064. WriteFile(_tap, _injectPending.front().data, _injectPending.front().len, NULL, &tapOvlWrite);
  1065. writeInProgress = true;
  1066. }
  1067. _injectPending_m.unlock();
  1068. }
  1069. CancelIo(_tap);
  1070. CloseHandle(tapOvlRead.hEvent);
  1071. CloseHandle(tapOvlWrite.hEvent);
  1072. CloseHandle(_tap);
  1073. _tap = INVALID_HANDLE_VALUE;
  1074. // We will restart and re-open the tap unless _run == false
  1075. }
  1076. }
  1077. catch (...) {
  1078. } // catch unexpected exceptions -- this should not happen but would prevent program crash or other weird issues since threads should not throw
  1079. CoUninitialize();
  1080. }
  1081. NET_IFINDEX WindowsEthernetTap::_getDeviceIndex()
  1082. {
  1083. MIB_IF_TABLE2* ift = (MIB_IF_TABLE2*)0;
  1084. if (GetIfTable2Ex(MibIfTableRaw, &ift) != NO_ERROR)
  1085. throw std::runtime_error("GetIfTable2Ex() failed");
  1086. if (ift->NumEntries > 0) {
  1087. for (ULONG i = 0; i < ift->NumEntries; ++i) {
  1088. if (ift->Table[i].InterfaceLuid.Value == _deviceLuid.Value) {
  1089. NET_IFINDEX idx = ift->Table[i].InterfaceIndex;
  1090. FreeMibTable(ift);
  1091. return idx;
  1092. }
  1093. }
  1094. }
  1095. FreeMibTable(&ift);
  1096. throw std::runtime_error("interface not found");
  1097. }
  1098. std::vector<std::string> WindowsEthernetTap::_getRegistryIPv4Value(const char* regKey)
  1099. {
  1100. std::vector<std::string> value;
  1101. HKEY tcpIpInterfaces;
  1102. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ | KEY_WRITE, &tcpIpInterfaces) == ERROR_SUCCESS) {
  1103. char buf[16384];
  1104. DWORD len = sizeof(buf);
  1105. DWORD kt = REG_MULTI_SZ;
  1106. if (RegGetValueA(tcpIpInterfaces, _netCfgInstanceId.c_str(), regKey, 0, &kt, &buf, &len) == ERROR_SUCCESS) {
  1107. switch (kt) {
  1108. case REG_SZ:
  1109. if (len > 0)
  1110. value.push_back(std::string(buf));
  1111. break;
  1112. case REG_MULTI_SZ: {
  1113. for (DWORD k = 0, s = 0; k < len; ++k) {
  1114. if (! buf[k]) {
  1115. if (s < k) {
  1116. value.push_back(std::string(buf + s));
  1117. s = k + 1;
  1118. }
  1119. else
  1120. break;
  1121. }
  1122. }
  1123. } break;
  1124. }
  1125. }
  1126. RegCloseKey(tcpIpInterfaces);
  1127. }
  1128. return value;
  1129. }
  1130. void WindowsEthernetTap::_setRegistryIPv4Value(const char* regKey, const std::vector<std::string>& value)
  1131. {
  1132. std::string regMulti;
  1133. for (std::vector<std::string>::const_iterator s(value.begin()); s != value.end(); ++s) {
  1134. regMulti.append(*s);
  1135. regMulti.push_back((char)0);
  1136. }
  1137. HKEY tcpIpInterfaces;
  1138. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ | KEY_WRITE, &tcpIpInterfaces) == ERROR_SUCCESS) {
  1139. if (regMulti.length() > 0) {
  1140. regMulti.push_back((char)0);
  1141. RegSetKeyValueA(tcpIpInterfaces, _netCfgInstanceId.c_str(), regKey, REG_MULTI_SZ, regMulti.data(), (DWORD)regMulti.length());
  1142. }
  1143. else {
  1144. RegDeleteKeyValueA(tcpIpInterfaces, _netCfgInstanceId.c_str(), regKey);
  1145. }
  1146. RegCloseKey(tcpIpInterfaces);
  1147. }
  1148. }
  1149. void WindowsEthernetTap::_syncIps()
  1150. {
  1151. // assumes _assignedIps_m is locked
  1152. if (! _initialized)
  1153. return;
  1154. std::vector<InetAddress> haveIps(ips());
  1155. for (std::vector<InetAddress>::const_iterator aip(_assignedIps.begin()); aip != _assignedIps.end(); ++aip) {
  1156. if (std::find(haveIps.begin(), haveIps.end(), *aip) == haveIps.end()) {
  1157. MIB_UNICASTIPADDRESS_ROW ipr;
  1158. InitializeUnicastIpAddressEntry(&ipr);
  1159. if (aip->isV4()) {
  1160. ipr.Address.Ipv4.sin_family = AF_INET;
  1161. ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t*)aip->rawIpData());
  1162. ipr.OnLinkPrefixLength = aip->netmaskBits();
  1163. if (ipr.OnLinkPrefixLength >= 32)
  1164. continue;
  1165. }
  1166. else if (aip->isV6()) {
  1167. ipr.Address.Ipv6.sin6_family = AF_INET6;
  1168. memcpy(ipr.Address.Ipv6.sin6_addr.u.Byte, aip->rawIpData(), 16);
  1169. ipr.OnLinkPrefixLength = aip->netmaskBits();
  1170. if (ipr.OnLinkPrefixLength >= 128)
  1171. continue;
  1172. }
  1173. else
  1174. continue;
  1175. ipr.PrefixOrigin = IpPrefixOriginManual;
  1176. ipr.SuffixOrigin = IpSuffixOriginManual;
  1177. ipr.ValidLifetime = 0xffffffff;
  1178. ipr.PreferredLifetime = 0xffffffff;
  1179. ipr.InterfaceLuid = _deviceLuid;
  1180. ipr.InterfaceIndex = _getDeviceIndex();
  1181. CreateUnicastIpAddressEntry(&ipr);
  1182. }
  1183. if (aip->isV4()) {
  1184. char ipbuf[64];
  1185. std::string ipStr(aip->toIpString(ipbuf));
  1186. std::vector<std::string> regIps(_getRegistryIPv4Value("IPAddress"));
  1187. if (std::find(regIps.begin(), regIps.end(), ipStr) == regIps.end()) {
  1188. std::vector<std::string> regSubnetMasks(_getRegistryIPv4Value("SubnetMask"));
  1189. regIps.push_back(ipStr);
  1190. regSubnetMasks.push_back(aip->netmask().toIpString(ipbuf));
  1191. _setRegistryIPv4Value("IPAddress", regIps);
  1192. _setRegistryIPv4Value("SubnetMask", regSubnetMasks);
  1193. }
  1194. }
  1195. }
  1196. }
  1197. void WindowsEthernetTap::setDns(const char* domain, const std::vector<InetAddress>& servers)
  1198. {
  1199. WinDNSHelper::setDNS(_nwid, domain, servers);
  1200. }
  1201. } // namespace ZeroTier