summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.gitignore2
-rw-r--r--node/EthernetTap.cpp117
-rw-r--r--node/EthernetTap.hpp14
-rw-r--r--selftest.cpp2
-rw-r--r--vsprojects/SelfTest/SelfTest.vcxproj1
-rw-r--r--vsprojects/SelfTest/SelfTest.vcxproj.filters7
6 files changed, 110 insertions, 33 deletions
diff --git a/.gitignore b/.gitignore
index 71053b0e..fba7c321 100755
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,5 @@ mac-tap/tuntap/tap.kext
*.opensdf
*.user
*.cache
+
+/vsprojects/SelfTest/SelfTest.aps
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp
index 09af7179..48e93a34 100644
--- a/node/EthernetTap.cpp
+++ b/node/EthernetTap.cpp
@@ -692,6 +692,9 @@ void EthernetTap::threadMain()
#include <WS2tcpip.h>
#include <tchar.h>
#include <winreg.h>
+#include <wchar.h>
+
+#include "..\vsprojects\TapDriver\tap-windows.h"
namespace ZeroTier {
@@ -709,7 +712,10 @@ EthernetTap::EthernetTap(
_mtu(mtu),
_r(renv),
_handler(handler),
- _arg(arg)
+ _arg(arg),
+ _tap(INVALID_HANDLE_VALUE),
+ _injectSemaphore(INVALID_HANDLE_VALUE),
+ _run(true)
{
char subkeyName[4096];
char subkeyClass[4096];
@@ -724,8 +730,7 @@ EthernetTap::EthernetTap(
std::set<std::string> existingDeviceInstances;
std::string mySubkeyName;
- // Enumerate all Microsoft Loopback Adapter instances and look for one
- // that matches our tag.
+ // Enumerate tap instances and look for one tagged with this tag
for(DWORD subkeyIndex=0;subkeyIndex!=-1;) {
DWORD type;
DWORD dataLen;
@@ -739,7 +744,7 @@ EthernetTap::EthernetTap(
dataLen = sizeof(data);
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
data[dataLen] = '\0';
- if (!strcmpi(data,"*msloop")) {
+ if (!strnicmp(data,"zttap",5)) {
std::string instanceId;
type = 0;
dataLen = sizeof(data);
@@ -754,13 +759,9 @@ EthernetTap::EthernetTap(
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;
- mySubkeyName = subkeyName;
- subkeyIndex = -1; // break outer loop
- }
+ _myDeviceInstanceId = instanceId;
+ mySubkeyName = subkeyName;
+ subkeyIndex = -1; // break outer loop
}
}
}
@@ -779,24 +780,21 @@ EthernetTap::EthernetTap(
BOOL f64 = FALSE;
const char *devcon = ((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)(std::string("\"") + _r->homePath + devcon + "\" install " + windir + "\\inf\\netloop.inf *msloop").c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
+ if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" install \"" + _r->homePath + "\\ztTap100.inf\" ztTap100").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.
+
+ // Scan for the new instance by simply looking for taps that weren't
+ // there originally.
for(DWORD subkeyIndex=0;subkeyIndex!=-1;) {
DWORD type;
DWORD dataLen;
@@ -810,7 +808,7 @@ EthernetTap::EthernetTap(
dataLen = sizeof(data);
if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
data[dataLen] = '\0';
- if (!strcmpi(data,"*msloop")) {
+ if (!strnicmp(data,"zttap",5)) {
type = 0;
dataLen = sizeof(data);
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
@@ -830,26 +828,48 @@ EthernetTap::EthernetTap(
if (_myDeviceInstanceId.length() > 0) {
char tmps[4096];
- sprintf_s(tmps,"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac.data[0],(unsigned int)mac.data[1],(unsigned int)mac.data[2],(unsigned int)mac.data[3],(unsigned int)mac.data[4],(unsigned int)mac.data[5]);
- RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,strlen(tmps)+1);
- RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MAC",REG_SZ,tmps,strlen(tmps)+1);
+ unsigned int tmpsl = sprintf_s(tmps,"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac.data[0],(unsigned int)mac.data[1],(unsigned int)mac.data[2],(unsigned int)mac.data[3],(unsigned int)mac.data[4],(unsigned int)mac.data[5]) + 1;
+ RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl);
+ RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl);
DWORD tmp = mtu;
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MTU",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
tmp = 0;
RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"EnableDHCP",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
- RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"DriverDesc",REG_SZ,"ZeroTier One Virtual LAN",25);
}
RegCloseKey(nwAdapters);
if (_myDeviceInstanceId.length() == 0)
- throw std::runtime_error("unable to create new loopback adapter for tap");
+ throw std::runtime_error("unable to create new tap adapter");
+
+ wchar_t tapPath[4096];
+ swprintf_s(tapPath,L"\\\\.\\Global\\%S.tap",_myDeviceInstanceId.c_str());
+ _tap = CreateFile(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
+ if (_tap == INVALID_HANDLE_VALUE)
+ throw std::runtime_error("unable to open tap in \\\\.\\Global\\ namespace");
- //Thread::start(this);
+ uint32_t tmpi = 1;
+ DWORD bytesReturned = 0;
+ DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL);
+
+ memset(&_tapOvlRead,0,sizeof(_tapOvlRead));
+ _tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+ memset(&_tapOvlWrite,0,sizeof(_tapOvlWrite));
+ _tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+
+ _injectSemaphore = CreateSemaphore(NULL,0,1,NULL);
+ _thread = Thread::start(this);
}
EthernetTap::~EthernetTap()
{
+ _run = false;
+ ReleaseSemaphore(_injectSemaphore,1,NULL);
+ Thread::join(_thread);
+ CloseHandle(_tap);
+ CloseHandle(_tapOvlRead.hEvent);
+ CloseHandle(_tapOvlWrite.hEvent);
+ CloseHandle(_injectSemaphore);
}
void EthernetTap::whack()
@@ -881,7 +901,7 @@ void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const
memcpy(d + 14,data,len);
}
- //ReleaseSemaphore(_pcapIoThread.updateSem,1,NULL);
+ ReleaseSemaphore(_injectSemaphore,1,NULL);
}
std::string EthernetTap::deviceName() const
@@ -898,6 +918,51 @@ bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
void EthernetTap::threadMain()
throw()
{
+ HANDLE wait4[3];
+ wait4[0] = _injectSemaphore;
+ wait4[1] = _tapOvlRead.hEvent;
+ wait4[2] = _tapOvlWrite.hEvent;
+
+ ReadFile(_tap,_tapReadBuf,sizeof(_tapReadBuf),NULL,&_tapOvlRead);
+ bool writeInProgress = false;
+
+ for(;;) {
+ if (!_run) break;
+ WaitForMultipleObjectsEx(3,wait4,FALSE,INFINITE,TRUE);
+ if (!_run) break;
+
+ if (HasOverlappedIoCompleted(&_tapOvlRead)) {
+ DWORD bytesRead = 0;
+ if (GetOverlappedResult(_tap,&_tapOvlRead,&bytesRead,FALSE)) {
+ if (bytesRead > 14) {
+ MAC to(_tapReadBuf);
+ MAC from(_tapReadBuf + 6);
+ unsigned int etherType = Utils::ntoh(*((const uint16_t *)(_tapReadBuf + 12)));
+ Buffer<4096> tmp(_tapReadBuf + 14,bytesRead - 14);
+ printf("GOT FRAME: %u bytes: %s\r\n",(unsigned int)bytesRead,Utils::hex(_tapReadBuf,bytesRead).c_str());
+ //_handler(_arg,from,to,etherType,tmp);
+ }
+ }
+ ReadFile(_tap,_tapReadBuf,sizeof(_tapReadBuf),NULL,&_tapOvlRead);
+ }
+
+ if (writeInProgress) {
+ if (HasOverlappedIoCompleted(&_tapOvlWrite)) {
+ writeInProgress = false;
+ _injectPending_m.lock();
+ _injectPending.pop();
+ } else continue; // still writing, so skip code below and wait
+ } else _injectPending_m.lock();
+
+ if (!_injectPending.empty()) {
+ WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&_tapOvlWrite);
+ writeInProgress = true;
+ }
+
+ _injectPending_m.unlock();
+ }
+
+ CancelIo(_tap);
}
} // namespace ZeroTier
diff --git a/node/EthernetTap.hpp b/node/EthernetTap.hpp
index 69e5eafa..cff0953b 100644
--- a/node/EthernetTap.hpp
+++ b/node/EthernetTap.hpp
@@ -49,6 +49,11 @@
#include "Buffer.hpp"
#include "Array.hpp"
+#ifdef __WINDOWS__
+#include <WinSock2.h>
+#include <Windows.h>
+#endif
+
namespace ZeroTier {
class RuntimeEnvironment;
@@ -195,18 +200,23 @@ private:
void (*_handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &);
void *_arg;
-#ifdef __UNIX_LIKE__
Thread _thread;
+
+#ifdef __UNIX_LIKE__
char _dev[16];
int _fd;
int _shutdownSignalPipe[2];
#endif
#ifdef __WINDOWS__
+ HANDLE _tap;
+ OVERLAPPED _tapOvlRead,_tapOvlWrite;
+ char _tapReadBuf[ZT_IF_MTU + 32];
+ HANDLE _injectSemaphore;
std::string _myDeviceInstanceId;
std::queue< std::pair< Array<char,ZT_IF_MTU + 32>,unsigned int > > _injectPending;
Mutex _injectPending_m;
- Condition _injectPending_c;
+ volatile bool _run;
#endif
};
diff --git a/selftest.cpp b/selftest.cpp
index 836cee9a..4927deac 100644
--- a/selftest.cpp
+++ b/selftest.cpp
@@ -411,7 +411,7 @@ int main(int argc,char **argv)
///* For testing windows tap
try {
RuntimeEnvironment renv;
- renv.homePath = "C:";
+ renv.homePath = "C:\\ProgramData\\ZeroTier\\One";
EthernetTap tap(&renv,"test12345",MAC(0x32),2800,NULL,NULL);
Thread::sleep(100000000);
} catch (std::exception &exc) {
diff --git a/vsprojects/SelfTest/SelfTest.vcxproj b/vsprojects/SelfTest/SelfTest.vcxproj
index 5189da46..0847e783 100644
--- a/vsprojects/SelfTest/SelfTest.vcxproj
+++ b/vsprojects/SelfTest/SelfTest.vcxproj
@@ -125,6 +125,7 @@
<ClInclude Include="..\..\node\Topology.hpp" />
<ClInclude Include="..\..\node\UdpSocket.hpp" />
<ClInclude Include="..\..\node\Utils.hpp" />
+ <ClInclude Include="resource.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
diff --git a/vsprojects/SelfTest/SelfTest.vcxproj.filters b/vsprojects/SelfTest/SelfTest.vcxproj.filters
index 3704863e..fa8c8331 100644
--- a/vsprojects/SelfTest/SelfTest.vcxproj.filters
+++ b/vsprojects/SelfTest/SelfTest.vcxproj.filters
@@ -9,10 +9,6 @@
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
- </Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="targetver.h">
@@ -144,6 +140,9 @@
<ClInclude Include="..\..\node\Utils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\node\Defaults.cpp">