mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
Tap now creates Microsoft Loopback Adapter instances and tags them with a special ID... work in progress.
This commit is contained in:
parent
a0a9d52213
commit
ca5334509c
2 changed files with 123 additions and 10 deletions
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Constants.hpp"
|
#include "Constants.hpp"
|
||||||
#include "EthernetTap.hpp"
|
#include "EthernetTap.hpp"
|
||||||
|
@ -687,6 +689,8 @@ void EthernetTap::threadMain()
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
static Mutex _systemTapInitLock;
|
||||||
|
|
||||||
EthernetTap::EthernetTap(
|
EthernetTap::EthernetTap(
|
||||||
const RuntimeEnvironment *renv,
|
const RuntimeEnvironment *renv,
|
||||||
const char *tag,
|
const char *tag,
|
||||||
|
@ -701,31 +705,125 @@ EthernetTap::EthernetTap(
|
||||||
_handler(handler),
|
_handler(handler),
|
||||||
_arg(arg)
|
_arg(arg)
|
||||||
{
|
{
|
||||||
|
char subkeyName[1024];
|
||||||
|
char subkeyClass[1024];
|
||||||
|
char data[1024];
|
||||||
|
|
||||||
|
Mutex::Lock _l(_systemTapInitLock); // only do one at a time, process-wide
|
||||||
|
|
||||||
HKEY nwAdapters;
|
HKEY nwAdapters;
|
||||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_ALL_ACCESS,&nwAdapters) != ERROR_SUCCESS)
|
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
|
||||||
throw std::runtime_error("unable to open registry key for network adapter enumeration");
|
throw std::runtime_error("unable to open registry key for network adapter enumeration");
|
||||||
|
|
||||||
|
std::string myDeviceInstanceId;
|
||||||
|
std::set<std::string> existingDeviceInstances;
|
||||||
|
|
||||||
|
// Enumerate all Microsoft Loopback Adapter instances and look for one
|
||||||
|
// that matches our tag.
|
||||||
for(DWORD subkeyIndex=0;subkeyIndex!=-1;) {
|
for(DWORD subkeyIndex=0;subkeyIndex!=-1;) {
|
||||||
char subkeyName[1024];
|
DWORD type;
|
||||||
char subkeyClass[1024];
|
DWORD dataLen;
|
||||||
DWORD subkeyNameLen = sizeof(subkeyName);
|
DWORD subkeyNameLen = sizeof(subkeyName);
|
||||||
DWORD subkeyClassLen = sizeof(subkeyClass);
|
DWORD subkeyClassLen = sizeof(subkeyClass);
|
||||||
FILETIME lastWriteTime;
|
FILETIME lastWriteTime;
|
||||||
switch (RegEnumKeyExA(nwAdapters,subkeyIndex++,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime)) {
|
switch (RegEnumKeyExA(nwAdapters,subkeyIndex++,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime)) {
|
||||||
case ERROR_NO_MORE_ITEMS: subkeyIndex = -1; break;
|
case ERROR_NO_MORE_ITEMS: subkeyIndex = -1; break;
|
||||||
case ERROR_SUCCESS: {
|
case ERROR_SUCCESS:
|
||||||
DWORD type = 0;
|
type = 0;
|
||||||
char data[1024];
|
dataLen = sizeof(data);
|
||||||
DWORD dataLen = sizeof(data);
|
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||||
if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
|
||||||
data[dataLen] = '\0';
|
data[dataLen] = '\0';
|
||||||
printf("%s: %s\r\n",subkeyName,data);
|
if (!strcmpi(data,"*msloop")) {
|
||||||
|
std::string instanceId;
|
||||||
|
type = 0;
|
||||||
|
dataLen = sizeof(data);
|
||||||
|
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||||
|
instanceId.assign(data,dataLen);
|
||||||
|
existingDeviceInstances.insert(instanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((myDeviceInstanceId.length() == 0)&&(instanceId.length() != 0)) {
|
||||||
|
type = 0;
|
||||||
|
dataLen = sizeof(data);
|
||||||
|
if (RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||||
|
data[dataLen] = '\0';
|
||||||
|
if (!strcmp(data,tag)) {
|
||||||
|
type = 0;
|
||||||
|
dataLen = sizeof(data);
|
||||||
|
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||||
|
myDeviceInstanceId = instanceId;
|
||||||
|
subkeyIndex = -1; // break outer loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no device, try to create one
|
||||||
|
if (myDeviceInstanceId.length() == 0) {
|
||||||
|
// Execute devcon to install an instance of the Microsoft Loopback Adapter
|
||||||
|
#ifdef _WIN64
|
||||||
|
std::string devcon(_r->homePath + "\\devcon64.exe");
|
||||||
|
#else
|
||||||
|
BOOL f64 = FALSE;
|
||||||
|
std::string devcon(_r->homePath + ((IsWow64Process(GetCurrentProcess(),&f64) == TRUE) ? "\\devcon64.exe" : "\\devcon32.exe"));
|
||||||
|
#endif
|
||||||
|
char windir[4096];
|
||||||
|
windir[0] = '\0';
|
||||||
|
GetWindowsDirectoryA(windir,sizeof(windir));
|
||||||
|
STARTUPINFOA startupInfo;
|
||||||
|
startupInfo.cb = sizeof(startupInfo);
|
||||||
|
PROCESS_INFORMATION processInfo;
|
||||||
|
memset(&startupInfo,0,sizeof(STARTUPINFOA));
|
||||||
|
memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
|
||||||
|
if (!CreateProcessA(NULL,(LPSTR)(devcon + " install " + windir + "\\inf\\netloop.inf *msloop").c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
|
||||||
|
RegCloseKey(nwAdapters);
|
||||||
|
throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon);
|
||||||
|
}
|
||||||
|
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||||
|
CloseHandle(processInfo.hProcess);
|
||||||
|
CloseHandle(processInfo.hThread);
|
||||||
|
|
||||||
|
// Scan for that new instance by looking for adapters of type
|
||||||
|
// *msloop that we did not already see on the first scan.
|
||||||
|
for(DWORD subkeyIndex=0;subkeyIndex!=-1;) {
|
||||||
|
DWORD type;
|
||||||
|
DWORD dataLen;
|
||||||
|
DWORD subkeyNameLen = sizeof(subkeyName);
|
||||||
|
DWORD subkeyClassLen = sizeof(subkeyClass);
|
||||||
|
FILETIME lastWriteTime;
|
||||||
|
switch (RegEnumKeyExA(nwAdapters,subkeyIndex++,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime)) {
|
||||||
|
case ERROR_NO_MORE_ITEMS: subkeyIndex = -1; break;
|
||||||
|
case ERROR_SUCCESS:
|
||||||
|
type = 0;
|
||||||
|
dataLen = sizeof(data);
|
||||||
|
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||||
|
data[dataLen] = '\0';
|
||||||
|
if (!strcmpi(data,"*msloop")) {
|
||||||
|
type = 0;
|
||||||
|
dataLen = sizeof(data);
|
||||||
|
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||||
|
if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) {
|
||||||
|
RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,strlen(tag)+1);
|
||||||
|
myDeviceInstanceId.assign(data,dataLen);
|
||||||
|
subkeyIndex = -1; // break outer loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RegCloseKey(nwAdapters);
|
RegCloseKey(nwAdapters);
|
||||||
|
|
||||||
|
if (myDeviceInstanceId.length() == 0)
|
||||||
|
throw std::runtime_error("unable to create new loopback adapter for tap");
|
||||||
}
|
}
|
||||||
|
|
||||||
EthernetTap::~EthernetTap()
|
EthernetTap::~EthernetTap()
|
||||||
|
|
15
selftest.cpp
15
selftest.cpp
|
@ -29,11 +29,14 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "node/Constants.hpp"
|
#include "node/Constants.hpp"
|
||||||
|
#include "node/RuntimeEnvironment.hpp"
|
||||||
#include "node/InetAddress.hpp"
|
#include "node/InetAddress.hpp"
|
||||||
#include "node/EllipticCurveKey.hpp"
|
#include "node/EllipticCurveKey.hpp"
|
||||||
#include "node/EllipticCurveKeyPair.hpp"
|
#include "node/EllipticCurveKeyPair.hpp"
|
||||||
|
@ -48,6 +51,7 @@
|
||||||
#include "node/NodeConfig.hpp"
|
#include "node/NodeConfig.hpp"
|
||||||
#include "node/Dictionary.hpp"
|
#include "node/Dictionary.hpp"
|
||||||
#include "node/RateLimiter.hpp"
|
#include "node/RateLimiter.hpp"
|
||||||
|
#include "node/EthernetTap.hpp"
|
||||||
|
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
|
@ -404,6 +408,16 @@ int _tmain(int argc, _TCHAR* argv[])
|
||||||
int main(int argc,char **argv)
|
int main(int argc,char **argv)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
RuntimeEnvironment renv;
|
||||||
|
renv.homePath = "C:";
|
||||||
|
EthernetTap tap(&renv,"test12345",MAC(),2800,NULL,NULL);
|
||||||
|
return 0;
|
||||||
|
} catch (std::exception &exc) {
|
||||||
|
std::cout << exc.what() << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
_initLibCrypto();
|
_initLibCrypto();
|
||||||
|
@ -419,4 +433,5 @@ int main(int argc,char **argv)
|
||||||
std::cout << std::endl << "SOMETHING FAILED!" << std::endl;
|
std::cout << std::endl << "SOMETHING FAILED!" << std::endl;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue