2
0

WindowsEthernetTap.cpp 48 KB

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