mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-29 15:43:52 +00:00
Tap works! At least in isolation. Time to create the Windows executable and the Windows service to run it and handle auto-update.
This commit is contained in:
parent
e0bdc02139
commit
bbbc032959
2
.gitignore
vendored
2
.gitignore
vendored
@ -18,3 +18,5 @@ mac-tap/tuntap/tap.kext
|
||||
*.opensdf
|
||||
*.user
|
||||
*.cache
|
||||
|
||||
/vsprojects/SelfTest/SelfTest.aps
|
||||
|
@ -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");
|
||||
|
||||
//Thread::start(this);
|
||||
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");
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
Loading…
x
Reference in New Issue
Block a user