summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@zerotier.com>2013-08-22 14:30:55 -0400
committerAdam Ierymenko <adam.ierymenko@zerotier.com>2013-08-22 14:30:55 -0400
commitca5334509c406230c49f0d87acc58fe569ec7b65 (patch)
treec051b38c99c445bd9a17df5ed9d281747c46e0ce
parenta0a9d5221381f52f06071cfdbf5d2331a96318d2 (diff)
downloadinfinitytier-ca5334509c406230c49f0d87acc58fe569ec7b65.tar.gz
infinitytier-ca5334509c406230c49f0d87acc58fe569ec7b65.zip
Tap now creates Microsoft Loopback Adapter instances and tags them with a special ID... work in progress.
-rw-r--r--node/EthernetTap.cpp118
-rw-r--r--selftest.cpp15
2 files changed, 123 insertions, 10 deletions
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp
index dd555576..b9524a02 100644
--- a/node/EthernetTap.cpp
+++ b/node/EthernetTap.cpp
@@ -27,6 +27,8 @@
#include <string>
#include <map>
+#include <set>
+#include <algorithm>
#include "Constants.hpp"
#include "EthernetTap.hpp"
@@ -687,6 +689,8 @@ void EthernetTap::threadMain()
namespace ZeroTier {
+static Mutex _systemTapInitLock;
+
EthernetTap::EthernetTap(
const RuntimeEnvironment *renv,
const char *tag,
@@ -701,31 +705,125 @@ EthernetTap::EthernetTap(
_handler(handler),
_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;
- 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");
+ 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;) {
- char subkeyName[1024];
- char subkeyClass[1024];
+ 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: {
- DWORD type = 0;
- char data[1024];
- DWORD dataLen = sizeof(data);
- if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
+ 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';
- 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);
+
+ if (myDeviceInstanceId.length() == 0)
+ throw std::runtime_error("unable to create new loopback adapter for tap");
}
EthernetTap::~EthernetTap()
diff --git a/selftest.cpp b/selftest.cpp
index 305b9fad..ab78c8f8 100644
--- a/selftest.cpp
+++ b/selftest.cpp
@@ -29,11 +29,14 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+
+#include <stdexcept>
#include <iostream>
#include <string>
#include <vector>
#include "node/Constants.hpp"
+#include "node/RuntimeEnvironment.hpp"
#include "node/InetAddress.hpp"
#include "node/EllipticCurveKey.hpp"
#include "node/EllipticCurveKeyPair.hpp"
@@ -48,6 +51,7 @@
#include "node/NodeConfig.hpp"
#include "node/Dictionary.hpp"
#include "node/RateLimiter.hpp"
+#include "node/EthernetTap.hpp"
#include <openssl/rand.h>
@@ -404,6 +408,16 @@ int _tmain(int argc, _TCHAR* argv[])
int main(int argc,char **argv)
#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;
_initLibCrypto();
@@ -419,4 +433,5 @@ int main(int argc,char **argv)
std::cout << std::endl << "SOMETHING FAILED!" << std::endl;
return r;
+*/
}