mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
Delete persistent tap device on Windows when we leave a network.
This commit is contained in:
parent
28665079a0
commit
afbbf61588
3 changed files with 101 additions and 28 deletions
|
@ -570,6 +570,11 @@ std::string EthernetTap::deviceName() const
|
||||||
return std::string(_dev);
|
return std::string(_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string EthernetTap::persistentId() const
|
||||||
|
{
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __LINUX__
|
#ifdef __LINUX__
|
||||||
bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
|
bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
|
||||||
{
|
{
|
||||||
|
@ -901,6 +906,11 @@ void EthernetTap::threadMain()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EthernetTap::deletePersistentTapDevice(const RuntimeEnvironment *_r,const char *pid)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
||||||
#endif // __UNIX_LIKE__ //////////////////////////////////////////////////////
|
#endif // __UNIX_LIKE__ //////////////////////////////////////////////////////
|
||||||
|
@ -1278,31 +1288,9 @@ bool EthernetTap::addIP(const InetAddress &ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update registry to contain all non-link-local IPs for this interface
|
_syncIpsWithRegistry(haveIps);
|
||||||
std::string regMultiIps,regMultiNetmasks;
|
|
||||||
for(std::set<InetAddress>::const_iterator i(haveIps.begin());i!=haveIps.end();++i) {
|
|
||||||
if (!i->isLinkLocal()) {
|
|
||||||
regMultiIps.append(i->toIpString());
|
|
||||||
regMultiIps.push_back((char)0);
|
|
||||||
regMultiNetmasks.append(i->netmask().toIpString());
|
|
||||||
regMultiNetmasks.push_back((char)0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HKEY tcpIpInterfaces;
|
|
||||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
|
|
||||||
if (regMultiIps.length()) {
|
|
||||||
regMultiIps.push_back((char)0);
|
|
||||||
regMultiNetmasks.push_back((char)0);
|
|
||||||
RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"IPAddress",REG_MULTI_SZ,regMultiIps.data(),(DWORD)regMultiIps.length());
|
|
||||||
RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"SubnetMask",REG_MULTI_SZ,regMultiNetmasks.data(),(DWORD)regMultiNetmasks.length());
|
|
||||||
} else {
|
|
||||||
RegDeleteKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"IPAddress");
|
|
||||||
RegDeleteKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"SubnetMask");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RegCloseKey(tcpIpInterfaces);
|
|
||||||
} catch (std::exception &exc) {
|
} catch (std::exception &exc) {
|
||||||
LOG("unexpected exception adding IP address to %s: %s",ip.toString().c_str(),deviceName().c_str(),exc.what());
|
LOG("unexpected exception adding IP address %s to %s: %s",ip.toString().c_str(),deviceName().c_str(),exc.what());
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
LOG("unexpected exception adding IP address %s to %s: unknown exception",ip.toString().c_str(),deviceName().c_str());
|
LOG("unexpected exception adding IP address %s to %s: unknown exception",ip.toString().c_str(),deviceName().c_str());
|
||||||
}
|
}
|
||||||
|
@ -1331,13 +1319,18 @@ bool EthernetTap::removeIP(const InetAddress &ip)
|
||||||
if (addr == ip) {
|
if (addr == ip) {
|
||||||
DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
|
DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
|
||||||
FreeMibTable(ipt);
|
FreeMibTable(ipt);
|
||||||
|
_syncIpsWithRegistry(ips());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FreeMibTable((PVOID)ipt);
|
FreeMibTable((PVOID)ipt);
|
||||||
}
|
}
|
||||||
} catch ( ... ) {}
|
} catch (std::exception &exc) {
|
||||||
|
LOG("unexpected exception removing IP address %s from %s: %s",ip.toString().c_str(),deviceName().c_str(),exc.what());
|
||||||
|
} catch ( ... ) {
|
||||||
|
LOG("unexpected exception removing IP address %s from %s: unknown exception",ip.toString().c_str(),deviceName().c_str());
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,6 +1391,11 @@ std::string EthernetTap::deviceName() const
|
||||||
return _myDeviceInstanceId;
|
return _myDeviceInstanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string EthernetTap::persistentId() const
|
||||||
|
{
|
||||||
|
return _myDeviceInstanceIdPath;
|
||||||
|
}
|
||||||
|
|
||||||
bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
|
bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
|
||||||
{
|
{
|
||||||
std::set<MulticastGroup> newGroups;
|
std::set<MulticastGroup> newGroups;
|
||||||
|
@ -1501,6 +1499,59 @@ void EthernetTap::threadMain()
|
||||||
CancelIo(_tap);
|
CancelIo(_tap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EthernetTap::deletePersistentTapDevice(const RuntimeEnvironment *_r,const char *pid)
|
||||||
|
{
|
||||||
|
#ifdef _WIN64
|
||||||
|
BOOL is64Bit = TRUE;
|
||||||
|
const char *devcon = "\\devcon_x64.exe";
|
||||||
|
#else
|
||||||
|
BOOL is64Bit = FALSE;
|
||||||
|
IsWow64Process(GetCurrentProcess(),&is64Bit);
|
||||||
|
const char *devcon = ((is64Bit == TRUE) ? "\\devcon_x64.exe" : "\\devcon_x86.exe");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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 + "\" remove @" + pid).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
|
||||||
|
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||||
|
CloseHandle(processInfo.hProcess);
|
||||||
|
CloseHandle(processInfo.hThread);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EthernetTap::_syncIpsWithRegistry(const std::set<InetAddress> &haveIps)
|
||||||
|
{
|
||||||
|
// Update registry to contain all non-link-local IPs for this interface
|
||||||
|
std::string regMultiIps,regMultiNetmasks;
|
||||||
|
for(std::set<InetAddress>::const_iterator i(haveIps.begin());i!=haveIps.end();++i) {
|
||||||
|
if (!i->isLinkLocal()) {
|
||||||
|
regMultiIps.append(i->toIpString());
|
||||||
|
regMultiIps.push_back((char)0);
|
||||||
|
regMultiNetmasks.append(i->netmask().toIpString());
|
||||||
|
regMultiNetmasks.push_back((char)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HKEY tcpIpInterfaces;
|
||||||
|
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
|
||||||
|
if (regMultiIps.length()) {
|
||||||
|
regMultiIps.push_back((char)0);
|
||||||
|
regMultiNetmasks.push_back((char)0);
|
||||||
|
RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"IPAddress",REG_MULTI_SZ,regMultiIps.data(),(DWORD)regMultiIps.length());
|
||||||
|
RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"SubnetMask",REG_MULTI_SZ,regMultiNetmasks.data(),(DWORD)regMultiNetmasks.length());
|
||||||
|
} else {
|
||||||
|
RegDeleteKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"IPAddress");
|
||||||
|
RegDeleteKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"SubnetMask");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RegCloseKey(tcpIpInterfaces);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
||||||
#endif // __WINDOWS__ ////////////////////////////////////////////////////////
|
#endif // __WINDOWS__ ////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -175,6 +175,11 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string deviceName() const;
|
std::string deviceName() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return OS-internal persistent device ID or empty string if not applicable to this platform or not persistent
|
||||||
|
*/
|
||||||
|
std::string persistentId() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill or modify a set to contain multicast groups for this device
|
* Fill or modify a set to contain multicast groups for this device
|
||||||
*
|
*
|
||||||
|
@ -195,6 +200,19 @@ public:
|
||||||
void threadMain()
|
void threadMain()
|
||||||
throw();
|
throw();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove persistent tap device by device name
|
||||||
|
*
|
||||||
|
* This has no effect on platforms that do not have persistent taps.
|
||||||
|
* On platforms like Windows with persistent devices the device is
|
||||||
|
* uninstalled.
|
||||||
|
*
|
||||||
|
* @param _r Runtime environment
|
||||||
|
* @param pdev Device name as returned by persistentId() while tap is running
|
||||||
|
* @return True if a device was deleted
|
||||||
|
*/
|
||||||
|
static bool deletePersistentTapDevice(const RuntimeEnvironment *_r,const char *pid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const MAC _mac;
|
const MAC _mac;
|
||||||
const unsigned int _mtu;
|
const unsigned int _mtu;
|
||||||
|
@ -215,6 +233,8 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
void _syncIpsWithRegistry(const std::set<InetAddress> &haveIps);
|
||||||
|
|
||||||
HANDLE _tap;
|
HANDLE _tap;
|
||||||
OVERLAPPED _tapOvlRead,_tapOvlWrite;
|
OVERLAPPED _tapOvlRead,_tapOvlWrite;
|
||||||
char _tapReadBuf[ZT_IF_MTU + 32];
|
char _tapReadBuf[ZT_IF_MTU + 32];
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "Switch.hpp"
|
#include "Switch.hpp"
|
||||||
#include "Packet.hpp"
|
#include "Packet.hpp"
|
||||||
#include "Buffer.hpp"
|
#include "Buffer.hpp"
|
||||||
|
#include "EthernetTap.hpp"
|
||||||
|
|
||||||
#define ZT_NETWORK_CERT_WRITE_BUF_SIZE 131072
|
#define ZT_NETWORK_CERT_WRITE_BUF_SIZE 131072
|
||||||
|
|
||||||
|
@ -55,13 +56,14 @@ const char *Network::statusString(const Status s)
|
||||||
|
|
||||||
Network::~Network()
|
Network::~Network()
|
||||||
{
|
{
|
||||||
|
std::string devPersistentId(_tap->persistentId());
|
||||||
delete _tap;
|
delete _tap;
|
||||||
|
|
||||||
if (_destroyOnDelete) {
|
if (_destroyOnDelete) {
|
||||||
Utils::rm(std::string(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".conf"));
|
Utils::rm(std::string(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".conf"));
|
||||||
Utils::rm(std::string(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".mcerts"));
|
Utils::rm(std::string(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".mcerts"));
|
||||||
|
if (devPersistentId.length())
|
||||||
// TODO: on Windows we need to also remove the tap interface since they're
|
EthernetTap::deletePersistentTapDevice(_r,devPersistentId.c_str());
|
||||||
// sticky on that platform.
|
|
||||||
} else {
|
} else {
|
||||||
// Causes flush of membership certs to disk
|
// Causes flush of membership certs to disk
|
||||||
clean();
|
clean();
|
||||||
|
|
Loading…
Add table
Reference in a new issue