mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-08-20 21:33:57 -07:00
Merge branch 'dns' into dev
This commit is contained in:
commit
8d0a3563e4
27 changed files with 822 additions and 21 deletions
|
@ -54,6 +54,7 @@ public:
|
|||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {}
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
virtual void setFriendlyName(const char *friendlyName) = 0;
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed) = 0;
|
||||
virtual void setMtu(unsigned int mtu) = 0;
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) = 0;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {}
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
|
18
osdep/MacDNSHelper.hpp
Normal file
18
osdep/MacDNSHelper.hpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef MAC_DNS_HELPER
|
||||
#define MAC_DNS_HELPER
|
||||
|
||||
#include <vector>
|
||||
#include "../node/InetAddress.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
class MacDNSHelper
|
||||
{
|
||||
public:
|
||||
static void setDNS(uint64_t nwid, const char *domain, const std::vector<InetAddress> &servers);
|
||||
static void removeDNS(uint64_t nwid);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
79
osdep/MacDNSHelper.mm
Normal file
79
osdep/MacDNSHelper.mm
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "MacDNSHelper.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
void MacDNSHelper::setDNS(uint64_t nwid, const char *domain, const std::vector<InetAddress> &servers)
|
||||
{
|
||||
SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL);
|
||||
|
||||
CFStringRef *s = new CFStringRef[4];
|
||||
for (unsigned int i = 0; i < servers.size(); ++i) {
|
||||
char buf[64];
|
||||
ZeroTier::InetAddress a = servers[i];
|
||||
const char *ipStr = a.toIpString(buf);
|
||||
s[i] = CFStringCreateWithCString(NULL, ipStr, kCFStringEncodingUTF8);
|
||||
}
|
||||
|
||||
CFArrayRef serverArray = CFArrayCreate(NULL, (const void**)s, servers.size(), &kCFTypeArrayCallBacks);
|
||||
|
||||
CFStringRef keys[2];
|
||||
keys[0] = CFSTR("SupplementalMatchDomains");
|
||||
keys[1] = CFSTR("ServerAddresses");
|
||||
|
||||
CFStringRef cfdomain = CFStringCreateWithCString(NULL, domain, kCFStringEncodingUTF8);
|
||||
CFArrayRef domainArray = CFArrayCreate(NULL, (const void**)&cfdomain, 1, &kCFTypeArrayCallBacks);
|
||||
|
||||
CFTypeRef values[2];
|
||||
values[0] = domainArray;
|
||||
values[1] = serverArray;
|
||||
|
||||
CFDictionaryRef dict = CFDictionaryCreate(NULL,
|
||||
(const void**)keys, (const void**)values, 2, &kCFCopyStringDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
char buf[256] = {0};
|
||||
sprintf(buf, "State:/Network/Service/%.16llx/DNS", nwid);
|
||||
CFStringRef key = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
|
||||
CFArrayRef list = SCDynamicStoreCopyKeyList(ds, key);
|
||||
|
||||
CFIndex i = 0, j = CFArrayGetCount(list);
|
||||
bool ret = TRUE;
|
||||
if (j <= 0) {
|
||||
ret &= SCDynamicStoreAddValue(ds, key, dict);
|
||||
} else {
|
||||
ret &= SCDynamicStoreSetValue(ds, (CFStringRef)CFArrayGetValueAtIndex(list, i), dict);
|
||||
}
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Error writing DNS configuration\n");
|
||||
}
|
||||
|
||||
CFRelease(list);
|
||||
CFRelease(key);
|
||||
CFRelease(dict);
|
||||
CFRelease(domainArray);
|
||||
CFRelease(cfdomain);
|
||||
CFRelease(serverArray);
|
||||
for (int i = 0; i < servers.size(); ++i) {
|
||||
CFRelease(s[i]);
|
||||
}
|
||||
delete[] s;
|
||||
CFRelease(ds);
|
||||
}
|
||||
|
||||
void MacDNSHelper::removeDNS(uint64_t nwid)
|
||||
{
|
||||
SCDynamicStoreRef ds = SCDynamicStoreCreate(NULL, CFSTR("zerotier"), NULL, NULL);
|
||||
|
||||
char buf[256] = {0};
|
||||
sprintf(buf, "State:/Network/Service/%.16llx/DNS", nwid);
|
||||
CFStringRef key = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
|
||||
SCDynamicStoreRemoveValue(ds, key);
|
||||
CFRelease(key);
|
||||
CFRelease(ds);
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include "OSUtils.hpp"
|
||||
#include "MacEthernetTap.hpp"
|
||||
#include "MacEthernetTapAgent.h"
|
||||
#include "MacDNSHelper.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
@ -54,6 +55,7 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
|
||||
static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
|
||||
|
||||
|
@ -200,6 +202,8 @@ MacEthernetTap::MacEthernetTap(
|
|||
|
||||
MacEthernetTap::~MacEthernetTap()
|
||||
{
|
||||
MacDNSHelper::removeDNS(_nwid);
|
||||
|
||||
Mutex::Lock _gl(globalTapCreateLock);
|
||||
::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
|
||||
Thread::join(_thread);
|
||||
|
@ -452,6 +456,11 @@ void MacEthernetTap::threadMain()
|
|||
}
|
||||
}
|
||||
|
||||
void MacEthernetTap::setDns(const char *domain, const std::vector<InetAddress> &servers)
|
||||
{
|
||||
MacDNSHelper::setDNS(this->_nwid, domain, servers);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif // __APPLE__
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers);
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include <netinet/in_var.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#include "MacDNSHelper.hpp"
|
||||
|
||||
// OSX compile fix... in6_var defines this in a struct which namespaces it for C++ ... why?!?
|
||||
struct prf_ra {
|
||||
u_char onlink : 1;
|
||||
|
@ -441,6 +443,8 @@ MacKextEthernetTap::MacKextEthernetTap(
|
|||
|
||||
MacKextEthernetTap::~MacKextEthernetTap()
|
||||
{
|
||||
MacDNSHelper::removeDNS(_nwid);
|
||||
|
||||
::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
|
||||
Thread::join(_thread);
|
||||
|
||||
|
@ -687,4 +691,9 @@ void MacKextEthernetTap::threadMain()
|
|||
}
|
||||
}
|
||||
|
||||
void MacKextEthernetTap::setDns(const char *domain, const std::vector<InetAddress> &servers)
|
||||
{
|
||||
MacDNSHelper::setDNS(_nwid, domain, servers);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -56,6 +56,8 @@ public:
|
|||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers);
|
||||
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
virtual std::string deviceName() const;
|
||||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setDns(const char *domain, const std::vector<InetAddress> &servers) {}
|
||||
|
||||
void threadMain()
|
||||
throw();
|
||||
|
|
353
osdep/WinDNSHelper.cpp
Normal file
353
osdep/WinDNSHelper.cpp
Normal file
|
@ -0,0 +1,353 @@
|
|||
#include "WinDNSHelper.hpp"
|
||||
|
||||
#include <comdef.h>
|
||||
#include <WbemIdl.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <strsafe.h>
|
||||
|
||||
#define MAX_KEY_LENGTH 255
|
||||
#define MAX_VALUE_NAME 16383
|
||||
|
||||
namespace ZeroTier
|
||||
{
|
||||
|
||||
BOOL RegDelnodeRecurse(HKEY hKeyRoot, LPTSTR lpSubKey)
|
||||
{
|
||||
LPTSTR lpEnd;
|
||||
LONG lResult;
|
||||
DWORD dwSize;
|
||||
TCHAR szName[MAX_PATH];
|
||||
HKEY hKey;
|
||||
FILETIME ftWrite;
|
||||
|
||||
// First, see if we can delete the key without having
|
||||
// to recurse.
|
||||
|
||||
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
|
||||
|
||||
if (lResult == ERROR_SUCCESS)
|
||||
return TRUE;
|
||||
|
||||
lResult = RegOpenKeyEx(hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
|
||||
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
{
|
||||
if (lResult == ERROR_FILE_NOT_FOUND) {
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for an ending slash and add one if it is missing.
|
||||
|
||||
lpEnd = lpSubKey + lstrlen(lpSubKey);
|
||||
|
||||
if (*(lpEnd - 1) != TEXT('\\'))
|
||||
{
|
||||
*lpEnd = TEXT('\\');
|
||||
lpEnd++;
|
||||
*lpEnd = TEXT('\0');
|
||||
}
|
||||
|
||||
// Enumerate the keys
|
||||
|
||||
dwSize = MAX_PATH;
|
||||
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
||||
NULL, NULL, &ftWrite);
|
||||
|
||||
if (lResult == ERROR_SUCCESS)
|
||||
{
|
||||
do {
|
||||
|
||||
*lpEnd = TEXT('\0');
|
||||
StringCchCat(lpSubKey, MAX_PATH * 2, szName);
|
||||
|
||||
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
|
||||
break;
|
||||
}
|
||||
|
||||
dwSize = MAX_PATH;
|
||||
|
||||
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
||||
NULL, NULL, &ftWrite);
|
||||
|
||||
} while (lResult == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
lpEnd--;
|
||||
*lpEnd = TEXT('\0');
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
// Try again to delete the key.
|
||||
|
||||
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
|
||||
|
||||
if (lResult == ERROR_SUCCESS)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//*************************************************************
|
||||
//
|
||||
// RegDelnode()
|
||||
//
|
||||
// Purpose: Deletes a registry key and all its subkeys / values.
|
||||
//
|
||||
// Parameters: hKeyRoot - Root key
|
||||
// lpSubKey - SubKey to delete
|
||||
//
|
||||
// Return: TRUE if successful.
|
||||
// FALSE if an error occurs.
|
||||
//
|
||||
//*************************************************************
|
||||
|
||||
BOOL RegDelnode(HKEY hKeyRoot, LPCTSTR lpSubKey)
|
||||
{
|
||||
TCHAR szDelKey[MAX_PATH * 2];
|
||||
|
||||
StringCchCopy(szDelKey, MAX_PATH * 2, lpSubKey);
|
||||
return RegDelnodeRecurse(hKeyRoot, szDelKey);
|
||||
|
||||
}
|
||||
std::vector<std::string> getSubKeys(const char* key)
|
||||
{
|
||||
std::vector<std::string> subkeys;
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||
key,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
|
||||
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
|
||||
DWORD cbName; // size of name string
|
||||
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
|
||||
DWORD cchClassName = MAX_PATH; // size of class string
|
||||
DWORD cSubKeys = 0; // number of subkeys
|
||||
DWORD cbMaxSubKey; // longest subkey size
|
||||
DWORD cchMaxClass; // longest class string
|
||||
DWORD cValues; // number of values for key
|
||||
DWORD cchMaxValue; // longest value name
|
||||
DWORD cbMaxValueData; // longest value data
|
||||
DWORD cbSecurityDescriptor; // size of security descriptor
|
||||
FILETIME ftLastWriteTime; // last write time
|
||||
|
||||
DWORD i, retCode;
|
||||
|
||||
TCHAR achValue[MAX_VALUE_NAME];
|
||||
DWORD cchValue = MAX_VALUE_NAME;
|
||||
|
||||
retCode = RegQueryInfoKey(
|
||||
hKey, // key handle
|
||||
achClass, // buffer for class name
|
||||
&cchClassName, // size of class string
|
||||
NULL, // reserved
|
||||
&cSubKeys, // number of subkeys
|
||||
&cbMaxSubKey, // longest subkey size
|
||||
&cchMaxClass, // longest class string
|
||||
&cValues, // number of values for this key
|
||||
&cchMaxValue, // longest value name
|
||||
&cbMaxValueData, // longest value data
|
||||
&cbSecurityDescriptor, // security descriptor
|
||||
&ftLastWriteTime); // last write time
|
||||
|
||||
for (i = 0; i < cSubKeys; ++i) {
|
||||
cbName = MAX_KEY_LENGTH;
|
||||
retCode = RegEnumKeyEx(
|
||||
hKey,
|
||||
i,
|
||||
achKey,
|
||||
&cbName,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&ftLastWriteTime);
|
||||
if (retCode == ERROR_SUCCESS) {
|
||||
subkeys.push_back(achKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
return subkeys;
|
||||
}
|
||||
|
||||
std::vector<std::string> getValueList(const char* key) {
|
||||
std::vector<std::string> values;
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||
key,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
|
||||
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
|
||||
DWORD cbName; // size of name string
|
||||
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
|
||||
DWORD cchClassName = MAX_PATH; // size of class string
|
||||
DWORD cSubKeys = 0; // number of subkeys
|
||||
DWORD cbMaxSubKey; // longest subkey size
|
||||
DWORD cchMaxClass; // longest class string
|
||||
DWORD cValues; // number of values for key
|
||||
DWORD cchMaxValue; // longest value name
|
||||
DWORD cbMaxValueData; // longest value data
|
||||
DWORD cbSecurityDescriptor; // size of security descriptor
|
||||
FILETIME ftLastWriteTime; // last write time
|
||||
|
||||
DWORD i, retCode;
|
||||
|
||||
TCHAR achValue[MAX_VALUE_NAME];
|
||||
DWORD cchValue = MAX_VALUE_NAME;
|
||||
|
||||
retCode = RegQueryInfoKey(
|
||||
hKey, // key handle
|
||||
achClass, // buffer for class name
|
||||
&cchClassName, // size of class string
|
||||
NULL, // reserved
|
||||
&cSubKeys, // number of subkeys
|
||||
&cbMaxSubKey, // longest subkey size
|
||||
&cchMaxClass, // longest class string
|
||||
&cValues, // number of values for this key
|
||||
&cchMaxValue, // longest value name
|
||||
&cbMaxValueData, // longest value data
|
||||
&cbSecurityDescriptor, // security descriptor
|
||||
&ftLastWriteTime); // last write time
|
||||
|
||||
for (i = 0, retCode = ERROR_SUCCESS; i < cValues; ++i) {
|
||||
cchValue = MAX_VALUE_NAME;
|
||||
achValue[0] = '\0';
|
||||
retCode = RegEnumValue(
|
||||
hKey,
|
||||
i,
|
||||
achValue,
|
||||
&cchValue,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
if (retCode == ERROR_SUCCESS) {
|
||||
values.push_back(achValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
return values;
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> WinDNSHelper::hasDNSConfig(uint64_t nwid)
|
||||
{
|
||||
char networkStr[20] = { 0 };
|
||||
sprintf(networkStr, "%.16llx", nwid);
|
||||
|
||||
const char* baseKey = "SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters\\DnsPolicyConfig";
|
||||
auto subkeys = getSubKeys(baseKey);
|
||||
for (auto it = subkeys.begin(); it != subkeys.end(); ++it) {
|
||||
char sub[MAX_KEY_LENGTH] = { 0 };
|
||||
sprintf(sub, "%s\\%s", baseKey, it->c_str());
|
||||
auto dnsRecords = getValueList(sub);
|
||||
for (auto it2 = dnsRecords.begin(); it2 != dnsRecords.end(); ++it2) {
|
||||
if ((*it2) == "Comment") {
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||
sub,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == ERROR_SUCCESS) {
|
||||
|
||||
char buf[16384] = { 0 };
|
||||
DWORD size = sizeof(buf);
|
||||
DWORD retCode = RegGetValueA(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
sub,
|
||||
it2->c_str(),
|
||||
RRF_RT_REG_SZ,
|
||||
NULL,
|
||||
&buf,
|
||||
&size);
|
||||
if (retCode == ERROR_SUCCESS) {
|
||||
if (std::string(networkStr) == std::string(buf)) {
|
||||
RegCloseKey(hKey);
|
||||
return std::make_pair(true, std::string(sub));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(false, std::string());
|
||||
}
|
||||
|
||||
void WinDNSHelper::setDNS(uint64_t nwid, const char* domain, const std::vector<InetAddress>& servers)
|
||||
{
|
||||
auto hasConfig = hasDNSConfig(nwid);
|
||||
|
||||
std::stringstream ss;
|
||||
for (auto it = servers.begin(); it != servers.end(); ++it) {
|
||||
char ipaddr[256] = { 0 };
|
||||
ss << it->toIpString(ipaddr);
|
||||
if ((it + 1) != servers.end()) {
|
||||
ss << ";";
|
||||
}
|
||||
}
|
||||
std::string serverValue = ss.str();
|
||||
|
||||
if (hasConfig.first) {
|
||||
// update existing config
|
||||
HKEY dnsKey;
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, hasConfig.second.c_str(), 0, KEY_READ | KEY_WRITE, &dnsKey) == ERROR_SUCCESS) {
|
||||
auto retCode = RegSetKeyValueA(dnsKey, NULL, "GenericDNSServers", REG_SZ, serverValue.data(), (DWORD)serverValue.length());
|
||||
if (retCode != ERROR_SUCCESS) {
|
||||
fprintf(stderr, "Error writing dns servers: %d\n", retCode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// add new config
|
||||
const char* baseKey = "SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters\\DnsPolicyConfig";
|
||||
GUID guid;
|
||||
CoCreateGuid(&guid);
|
||||
wchar_t guidTmp[128] = { 0 };
|
||||
char guidStr[128] = { 0 };
|
||||
StringFromGUID2(guid, guidTmp, 128);
|
||||
wcstombs(guidStr, guidTmp, 128);
|
||||
char fullKey[MAX_KEY_LENGTH] = { 0 };
|
||||
sprintf(fullKey, "%s\\%s", baseKey, guidStr);
|
||||
HKEY dnsKey;
|
||||
RegCreateKeyA(HKEY_LOCAL_MACHINE, fullKey, &dnsKey);
|
||||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, fullKey, 0, KEY_READ | KEY_WRITE, &dnsKey) == ERROR_SUCCESS) {
|
||||
char nwString[32] = { 0 };
|
||||
sprintf(nwString, "%.16llx", nwid);
|
||||
RegSetKeyValueA(dnsKey, NULL, "Comment", REG_SZ, nwString, strlen(nwString));
|
||||
|
||||
DWORD configOpts = 8;
|
||||
RegSetKeyValueA(dnsKey, NULL, "ConfigOptions", REG_DWORD, &configOpts, sizeof(DWORD));
|
||||
RegSetKeyValueA(dnsKey, NULL, "DisplayName", REG_SZ, "", 0);
|
||||
RegSetKeyValueA(dnsKey, NULL, "GenericDNSServers", REG_SZ, serverValue.data(), serverValue.length());
|
||||
RegSetKeyValueA(dnsKey, NULL, "IPSECCARestriction", REG_SZ, "", 0);
|
||||
std::string d = "." + std::string(domain);
|
||||
RegSetKeyValueA(dnsKey, NULL, "Name", REG_MULTI_SZ, d.data(), d.length());
|
||||
DWORD version = 2;
|
||||
RegSetKeyValueA(dnsKey, NULL, "Version", REG_DWORD, &version, sizeof(DWORD));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WinDNSHelper::removeDNS(uint64_t nwid)
|
||||
{
|
||||
auto hasConfig = hasDNSConfig(nwid);
|
||||
if (hasConfig.first) {
|
||||
RegDelnode(HKEY_LOCAL_MACHINE, hasConfig.second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
24
osdep/WinDNSHelper.hpp
Normal file
24
osdep/WinDNSHelper.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef WIN_DNS_HELPER_H_
|
||||
#define WIN_DNS_HELPER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include "../node/InetAddress.hpp"
|
||||
|
||||
|
||||
namespace ZeroTier
|
||||
{
|
||||
|
||||
class WinDNSHelper
|
||||
{
|
||||
public:
|
||||
static void setDNS(uint64_t nwid, const char* domain, const std::vector<InetAddress>& servers);
|
||||
static void removeDNS(uint64_t nwid);
|
||||
|
||||
private:
|
||||
static std::pair<bool, std::string> hasDNSConfig(uint64_t nwid);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -44,6 +44,7 @@
|
|||
#include "OSUtils.hpp"
|
||||
|
||||
#include "..\windows\TapDriver6\tap-windows.h"
|
||||
#include "WinDNSHelper.hpp"
|
||||
|
||||
#include <netcon.h>
|
||||
|
||||
|
@ -473,6 +474,29 @@ WindowsEthernetTap::WindowsEthernetTap(
|
|||
char data[1024];
|
||||
char tag[24];
|
||||
|
||||
// Initialize COM
|
||||
HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
if (FAILED(hres)) {
|
||||
throw std::runtime_error("WinEthernetTap: COM initialization failed");
|
||||
}
|
||||
|
||||
hres = CoInitializeSecurity(
|
||||
NULL,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
RPC_C_AUTHN_LEVEL_DEFAULT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE,
|
||||
NULL,
|
||||
EOAC_NONE,
|
||||
NULL
|
||||
);
|
||||
if (FAILED(hres)) {
|
||||
CoUninitialize();
|
||||
throw std::runtime_error("WinEthernetTap: Failed to initialize security");
|
||||
}
|
||||
|
||||
|
||||
// We "tag" registry entries with the network ID to identify persistent devices
|
||||
OSUtils::ztsnprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid);
|
||||
|
||||
|
@ -646,6 +670,8 @@ WindowsEthernetTap::WindowsEthernetTap(
|
|||
|
||||
WindowsEthernetTap::~WindowsEthernetTap()
|
||||
{
|
||||
WinDNSHelper::removeDNS(_nwid);
|
||||
CoUninitialize();
|
||||
_run = false;
|
||||
ReleaseSemaphore(_injectSemaphore,1,NULL);
|
||||
Thread::join(_thread);
|
||||
|
@ -1290,4 +1316,9 @@ void WindowsEthernetTap::_syncIps()
|
|||
}
|
||||
}
|
||||
|
||||
void WindowsEthernetTap::setDns(const char* domain, const std::vector<InetAddress>& servers)
|
||||
{
|
||||
WinDNSHelper::setDNS(_nwid, domain, servers);
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -97,6 +97,7 @@ public:
|
|||
virtual void setFriendlyName(const char *friendlyName);
|
||||
virtual void scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed);
|
||||
virtual void setMtu(unsigned int mtu);
|
||||
virtual void setDns(const char* domain, const std::vector<InetAddress> &servers);
|
||||
|
||||
inline const NET_LUID &luid() const { return _deviceLuid; }
|
||||
inline const GUID &guid() const { return _deviceGuid; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue