64template <
typename REG,
typename NETAPI>
74 LR
"(SOFTWARE\Policies\Microsoft\WindowsNT\DNSClient)",
75 LR"(System\CurrentControlSet\Services\TCPIP\Parameters)"};
90 typename REG::Key key(subkey);
93 auto [list, error] = REG::get_string(key, L
"SearchList");
94 if (!error && !list.empty())
96 return {std::move(key),
true};
101 return {std::move(key),
false};
105 return {
typename REG::Key{},
false};
116 auto [value, error] = REG::get_string(key, L
"InitialSearchList");
117 return error ? false :
true;
133 err = REG::set_string(key, L
"InitialSearchList", searchlist);
138 err = REG::set_string(key, L
"SearchList", searchlist);
154 auto [searchlist, error] = REG::get_string(key, L
"SearchList");
161 LSTATUS err = REG::set_string(key, L
"OriginalSearchList", searchlist);
182 typename REG::Key tcpip_params(LR
"(SYSTEM\CurrentControlSet\Services\Tcpip\Parameters)");
183 auto [domain, error] = REG::get_string(tcpip_params, L
"Domain");
184 if (!error && !domain.empty())
190 typename REG::Key itfs(REG::subkey_ipv4_itfs);
191 typename REG::KeyEnumerator itf_guids(itfs);
192 for (
const auto &itf_guid : itf_guids)
195 if (!NETAPI::interface_connected(itf_guid))
201 std::wstring domain = interface_dns_domain<REG>(itf_guid);
228 const std::wstring iid = NETAPI::get_itf_id(itf_name);
234 typename REG::Key itf_key(std::wstring(REG::subkey_ipv4_itfs) + L
"\\" + iid);
235 PCWSTR name = dhcp_enabled_on_itf<REG>(itf_key) ? L
"DhcpDomain" : L
"Domain";
236 LSTATUS err = REG::set_string(itf_key, name, domain);
255 auto [list, error] = REG::get_string(key, L
"SearchList");
264 list.append(domains);
266 LSTATUS err = REG::set_string(key, L
"SearchList", list);
267 return err ? false :
true;
294 bool single_domain = domains.find(
',') == domains.npos;
295 if (!initial_list_exists)
304 else if (!single_domain)
313 std::wstring wide_domains = wstring::from_utf8(domains);
314 bool success_adding = single_domain && !list_exists
333 auto [originallist, error] = REG::get_string(list_key, L
"OriginalSearchList");
334 if (!error || error == ERROR_FILE_NOT_FOUND)
337 REG::set_string(list_key, L
"SearchList", originallist);
340 REG::delete_value(list_key, L
"InitialSearchList");
341 REG::delete_value(list_key, L
"OriginalSearchList");
366 auto [searchlist, error] = REG::get_string(list_key, L
"SearchList");
373 const std::wstring wdomains = wstring::from_utf8(domains);
374 auto pos = searchlist.find(wdomains);
375 if (pos != searchlist.npos)
378 if (searchlist.size() == wdomains.size())
386 searchlist.erase(pos, wdomains.size() + 1);
391 searchlist.erase(pos - 1, wdomains.size() + 1);
395 auto [initiallist, err] = REG::get_string(list_key, L
"InitialSearchList");
402 if (searchlist == initiallist)
410 REG::set_string(list_key, L
"SearchList", searchlist);
442 std::ostringstream
os;
443 os <<
"DNS::ActionCreate"
444 <<
" interface name=[" <<
itf_name_ <<
"]"
480 std::ostringstream ss;
481 ss <<
"DNS::ActionDelete"
482 <<
" interface name=[" <<
itf_name_ <<
"]"
502 const char *gpol_status =
"";
503 Reg::Key gpol_nrpt_key(Reg::gpol_nrpt_subkey);
504 if (gpol_nrpt_key.defined())
510 log <<
to_string() <<
": " << status << gpol_status << std::endl;
520 return "DNS::ActionApply";
532 SC_HANDLE scm =
static_cast<SC_HANDLE
>(INVALID_HANDLE_VALUE);
533 SC_HANDLE dnssvc =
static_cast<SC_HANDLE
>(INVALID_HANDLE_VALUE);
535 scm = ::OpenSCManager(
nullptr,
nullptr, SC_MANAGER_ALL_ACCESS);
541 dnssvc = ::OpenServiceA(scm,
"Dnscache", SERVICE_PAUSE_CONTINUE);
542 if (dnssvc ==
nullptr)
547 SERVICE_STATUS status;
548 if (::ControlService(dnssvc, SERVICE_CONTROL_PARAMCHANGE, &status) == 0)
556 if (dnssvc != INVALID_HANDLE_VALUE)
558 ::CloseServiceHandle(dnssvc);
560 if (scm != INVALID_HANDLE_VALUE)
562 ::CloseServiceHandle(scm);
575 ::GetSystemInfo(&si);
576 const bool win_32bit = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL;
589 using publish_fn_t = NTSTATUS(__stdcall *)(
595 DWORD ExplicitScope);
596 publish_fn_t RtlPublishWnfStateData;
597 constexpr DWORD WNF_GPOL_SYSTEM_CHANGES_HI = 0x0D891E2A;
598 constexpr DWORD WNF_GPOL_SYSTEM_CHANGES_LO = 0xA3BC0875;
600 HMODULE ntdll = ::LoadLibraryA(
"ntdll.dll");
601 if (ntdll ==
nullptr)
604 RtlPublishWnfStateData =
reinterpret_cast<publish_fn_t
>(::GetProcAddress(ntdll,
"RtlPublishWnfStateData"));
605 if (RtlPublishWnfStateData ==
nullptr)
608 if (RtlPublishWnfStateData(WNF_GPOL_SYSTEM_CHANGES_LO, WNF_GPOL_SYSTEM_CHANGES_HI, 0, 0, 0, 0) != ERROR_SUCCESS)
622 using publish_fn_t = NTSTATUS (*)(
627 __int64 ExplicitScope);
628 publish_fn_t RtlPublishWnfStateData;
629 constexpr INT64 WNF_GPOL_SYSTEM_CHANGES = 0x0D891E2AA3BC0875;
631 HMODULE ntdll = ::LoadLibraryA(
"ntdll.dll");
632 if (ntdll ==
nullptr)
635 RtlPublishWnfStateData =
reinterpret_cast<publish_fn_t
>(::GetProcAddress(ntdll,
"RtlPublishWnfStateData"));
636 if (RtlPublishWnfStateData ==
nullptr)
639 if (RtlPublishWnfStateData(WNF_GPOL_SYSTEM_CHANGES, 0, 0, 0, 0) != ERROR_SUCCESS)
bool apply_gpol_nrtp_rules_64()
Signal the DNS resolver (and others potentially) to reload the NRTP rules group policy settings on 64...
bool apply_gpol_nrtp_rules_32()
Signal the DNS resolver (and others potentially) to reload the NRTP rules group policy settings on 32...
std::string to_string() const override
Return the log message.
void execute(std::ostream &log) override
Apply any modification to the DNS settings by signaling the resolver.
bool apply_gpol_nrtp_rules()
Signal the DNS resolver (and others potentially) to reload the NRTP rules group policy settings.
bool apply_dns_settings()
Signal the DNS resolver to reload its settings.
std::string to_string() const override
Produce a textual representating of the DNS data.
ActionCreate(const std::string &itf_name, const std::string &search_domains)
void execute(std::ostream &log) override
Apply DNS data to the system.
const std::string search_domains_
const std::string itf_name_
void execute(std::ostream &log) override
Undo any modification to the DNS settings.
const std::string search_domains_
const std::string itf_name_
ActionDelete(const std::string &itf_name, const std::string &search_domains)
std::string to_string() const override
Return the log message.
Manage DNS search suffixes for Windows.
static bool add_to_searchlist(typename REG::Key &key, const std::wstring &domains)
Append domain suffixes to an existing search list.
static bool initial_searchlist_exists(typename REG::Key &key)
Check if a initial list had already been created.
static std::pair< typename REG::Key, bool > open_searchlist_key()
Return the Key for the DNS domain "SearchList" value.
static bool set_initial_searchlist(typename REG::Key &key, const std::wstring &searchlist)
static bool set_itf_domain_suffix(const std::string &itf_name, const std::wstring &domain)
Set interface specific domain suffix.
static constexpr std::array< PCWSTR, 2 > searchlist_subkeys
static bool set_initial_searchlist_from_existing(typename REG::Key &key)
Set the initial searchlist from the existing search list.
OPENVPN_EXCEPTION(dns_error)
static bool set_initial_searchlist_from_domains(typename REG::Key &key)
static void reset_search_domains(typename REG::Key &list_key)
Reset the DNS "SearchList" to its original value.
static void set_search_domains(const std::string &itf_name, const std::string &domains)
Add DNS search domain(s)
static void remove_search_domains(const std::string &itf_name, const std::string &domains)
Remove domain suffix(es) from the system.
DNS utilities for Windows.
BufferType< unsigned char > Buffer
dns_options search_domains
static std::stringstream out