57template <
typename REG,
typename NETAPI>
76 const std::wstring &domains,
86 throw nrpt_error(
"cannot open NRPT base key");
88 typename REG::Key rule_key(nrpt(), wstring::from_utf8(
rule_id),
true);
89 if (!rule_key.defined())
91 throw nrpt_error(
"cannot create NRPT rule subkey");
95 status = REG::set_multi_string(rule_key, L
"Name", domains);
96 check_reg_error<nrpt_error>(status,
"Name");
99 status = REG::set_string(rule_key, L
"GenericDNSServers",
servers);
100 check_reg_error<nrpt_error>(status,
"GenericDNSServers");
105 status = REG::set_dword(rule_key, L
"DNSSECValidationRequired", 1);
106 check_reg_error<nrpt_error>(status,
"DNSSECValidationRequired");
108 status = REG::set_dword(rule_key, L
"DNSSECQueryIPSECRequired", 0);
109 check_reg_error<nrpt_error>(status,
"DNSSECQueryIPSECRequired");
111 status = REG::set_dword(rule_key, L
"DNSSECQueryIPSECEncryption", 0);
112 check_reg_error<nrpt_error>(status,
"DNSSECQueryIPSECEncryption");
118 status = REG::set_dword(rule_key, L
"ConfigOptions", dnssec ? 0xA : 0x8);
119 check_reg_error<nrpt_error>(status,
"ConfigOptions");
122 status = REG::set_dword(rule_key, L
"Version", 2);
123 check_reg_error<nrpt_error>(status,
"Version");
140 for (
const auto &exclude : data)
159 std::vector<std::wstring> del_subkeys;
160 static constexpr std::array<PCWSTR, 2> nrpt_subkeys{
161 REG::gpol_nrpt_subkey, REG::local_nrpt_subkey};
163 for (
const auto &nrpt_subkey : nrpt_subkeys)
165 const auto pid = L
"-" + std::to_wstring(process_id);
166 typename REG::Key nrpt_key(nrpt_subkey);
167 typename REG::KeyEnumerator nrpt_rules(nrpt_key);
169 for (
const auto &nrpt_rule_id : nrpt_rules)
172 if (nrpt_rule_id.find(wstring::from_utf8(
id_prefix())) != 0)
174 if (process_id && nrpt_rule_id.rfind(pid) != (nrpt_rule_id.size() - pid.size()))
177 std::wostringstream rule_subkey;
178 rule_subkey << nrpt_subkey << L
"\\" << nrpt_rule_id;
179 del_subkeys.push_back(rule_subkey.str());
183 for (
const auto &subkey : del_subkeys)
185 REG::delete_subkey(subkey);
208 typename REG::Key itf_key(std::wstring(REG::subkey_ipv4_itfs) + L
"\\" + itf_guid);
210 auto [
servers, error] = REG::get_string(itf_key, L
"NameServer");
211 if (!error && !
servers.empty())
216 if (dhcp_enabled_on_itf<REG>(itf_key))
218 auto [
servers, error] = REG::get_string(itf_key, L
"DhcpNameServer");
219 if (!error && !
servers.empty())
236 typename REG::Key itf_key(std::wstring(REG::subkey_ipv6_itfs) + L
"\\" + itf_guid);
238 auto [
servers, error] = REG::get_string(itf_key, L
"NameServer");
239 if (!error && !
servers.empty())
244 if (dhcp_enabled_on_itf<REG>(itf_key))
246 auto [in6_addrs, error] = REG::get_binary(itf_key, L
"Dhcpv6DNSServers");
249 std::vector<std::wstring> addresses;
250 size_t in6_addr_count = in6_addrs.size() /
sizeof(IN6_ADDR);
251 for (
size_t i = 0; i < in6_addr_count; ++i)
254 IN6_ADDR *in6_addr =
reinterpret_cast<IN6_ADDR *
>(in6_addrs.data()) + i;
255 if (::InetNtopW(AF_INET6, in6_addr,
ipv6, _countof(
ipv6)))
257 addresses.emplace_back(
ipv6);
281 std::vector<ExcludeRuleData> data;
282 typename REG::Key itfs(REG::subkey_ipv4_itfs);
283 typename REG::KeyEnumerator itf_guids(itfs);
284 for (
const auto &itf_guid : itf_guids)
287 if (!NETAPI::interface_connected(itf_guid))
292 std::wstring domain = interface_dns_domain<REG>(itf_guid);
293 if (domain.empty() || std::find(sd.begin(), sd.end(), domain) != sd.end())
301 addresses.insert(addresses.end(), addr6.begin(), addr6.end());
302 if (addresses.empty())
308 domain.resize(domain.size() + 3);
309 domain.insert(domain.begin(), L
'.');
310 domain.push_back(L
'\0');
311 domain.push_back(L
'\0');
313 data.push_back({domain, addresses});
330 typename REG::Key key(REG::gpol_nrpt_subkey);
335 return typename REG::Key(REG::local_nrpt_subkey);
345 static const char prefix[] =
"OpenVPNDNSRouting";
357 static std::string
gen_rule_id(DWORD process_id,
bool exclude_rule, std::uint32_t n)
359 std::ostringstream ss;
365 ss <<
"-" << process_id;
376 static inline std::string
rule_id(DWORD process_id)
396 const std::vector<std::string> &split_domains,
397 const std::vector<std::string> &dns_servers,
420 std::wstring domains;
425 domains.push_back(L
'\0');
426 domains.push_back(L
'\0');
436 log <<
to_string() <<
" id=[" <<
id <<
"]" << std::endl;
447 std::ostringstream
os;
448 os <<
"NRPT::ActionCreate"
452 <<
" dnssec=[" <<
dnssec_ <<
"]";
493 std::ostringstream ss;
494 ss <<
"NRPT::ActionDelete pid=[" <<
process_id_ <<
"]";
const std::vector< std::string > split_domains_
void execute(std::ostream &log) override
Apply NRPT data to the registry.
const std::vector< std::string > dns_servers_
std::string to_string() const override
Produce a textual representating of the NRPT data.
ActionCreate(DWORD process_id, const std::vector< std::string > &split_domains, const std::vector< std::string > &dns_servers, const std::vector< std::wstring > &search_domains, bool dnssec)
const std::vector< std::wstring > search_domains_
ActionDelete(DWORD process_id)
std::string to_string() const override
Return the log message.
void execute(std::ostream &log) override
Delete all rules this process has set.
Manage NRPT rules for Windows.
static std::vector< ExcludeRuleData > collect_exclude_rule_data(const std::vector< std::wstring > &sd)
Get all the data necessary for excluding local domains from the tunnel.
static const char * id_prefix()
Return the rule id prefix any rule starts with.
static void delete_rules(DWORD process_id)
Remove our NRPT rules from the registry.
static std::string exclude_rule_id(DWORD process_id, std::uint32_t n)
Return a NRPT exclude rule id.
static std::vector< std::wstring > interface_ipv6_dns_servers(const std::wstring &itf_guid)
Get IPv6 DNS server addresses of an interface.
static void create_exclude_rules(DWORD process_id, const std::vector< std::wstring > &search_domains)
static REG::Key open_nrpt_base_key()
Open the NRPT key to store our rules at.
static void create_rule(const std::string &rule_id, const std::wstring &domains, const std::wstring &servers, bool dnssec)
Create a NRPT rule in the registry.
static std::string rule_id(DWORD process_id)
Return a NRPT rule id.
static std::string gen_rule_id(DWORD process_id, bool exclude_rule, std::uint32_t n)
Generate a rule id string.
static std::vector< std::wstring > interface_ipv4_dns_servers(const std::wstring &itf_guid)
Get IPv4 DNS server addresses of an interface.
OPENVPN_EXCEPTION(nrpt_error)
DNS utilities for Windows.
auto join(const T &strings, const typename T::value_type &delim, const bool tail=false)
std::vector< T > split(const T &str, const typename T::value_type sep, const int maxsplit=-1)
std::vector< std::wstring > addresses
dns_options search_domains