47 const auto min_prio = std::numeric_limits<std::int8_t>::min();
48 const auto max_prio = std::numeric_limits<std::int8_t>::max();
51 if (!parse_number_validate<int>(prio_str, 4, min_prio, max_prio, &priority))
52 OPENVPN_THROW_ARG1(option_error, ERR_INVALID_OPTION_DNS,
"dns server priority '" << prio_str <<
"' invalid");
62 if (indices ==
nullptr)
67 for (
const auto i : *indices)
71 const auto &o = opt[i];
72 if (o.size() >= 3 && o.ref(1) ==
"search-domains")
74 for (std::size_t j = 2; j < o.size(); j++)
79 else if (o.size() >= 5 && o.ref(1) ==
"server")
84 const auto &server_suboption = o.ref(3);
85 if (server_suboption ==
"address" && o.size() <= 12)
87 for (std::size_t j = 4; j < o.size(); j++)
91 server.addresses.emplace_back(
DnsAddress(o.ref(j)));
96 ERR_INVALID_OPTION_DNS,
97 "dns server " << priority <<
" error: " << error.what());
101 else if (server_suboption ==
"resolve-domains")
103 for (std::size_t j = 4; j < o.size(); j++)
105 server.domains.emplace_back(o.ref(j));
108 else if (server_suboption ==
"dnssec" && o.size() == 5)
112 server.parse_dnssec_value(o.ref(4));
117 ERR_INVALID_OPTION_DNS,
118 "dns server " << priority <<
" error: " << error.what());
121 else if (server_suboption ==
"transport" && o.size() == 5)
125 server.parse_transport_value(o.ref(4));
129 OPENVPN_THROW_ARG1(option_error, ERR_INVALID_OPTION_DNS,
"dns server " << priority <<
" error: " << error.what());
132 else if (server_suboption ==
"sni" && o.size() == 5)
134 server.sni = o.ref(4);
138 OPENVPN_THROW_ARG1(option_error, ERR_INVALID_OPTION_DNS,
"dns server " << priority <<
" option '" << server_suboption <<
"' unknown or too many parameters");
146 catch (
const std::exception &e)
154 std::vector<int> remove_servers;
155 for (
const auto &[priority, server] :
servers)
157 if (server.addresses.empty())
160 parse_errors +=
"dns server " + std::to_string(priority) +
" does not have an address assigned";
161 remove_servers.push_back(priority);
164 for (
const auto &prio : remove_servers)
178 auto dhcp_map = opt.
map().find(
"dhcp-option");
179 if (dhcp_map == opt.
map().end())
191 std::string adapter_domain_suffix;
192 for (
const auto &i : dhcp_map->second)
197 const std::string &type = o.
get(1, 64);
198 if (type ==
"DNS" || type ==
"DNS6")
210 catch (
const IP::ip_exception &)
217 ERR_INVALID_OPTION_DNS,
221 else if (type ==
"DOMAIN" || type ==
"DOMAIN-SEARCH")
224 for (
size_t i = 2; i < o.
size(); ++i)
226 using StrVec = std::vector<std::string>;
227 const StrVec domains = Split::by_space<StrVec, StandardLex, SpaceMatch, Split::NullLimit>(o.
get(i, 256));
232 for (
const auto &domain : domains)
235 if (use_search_as_split_domains)
238 server.domains.emplace_back(domain);
247 else if (type ==
"ADAPTER_DOMAIN_SUFFIX")
252 adapter_domain_suffix = o.
ref(2);
257 catch (
const std::exception &e)
264 if (!adapter_domain_suffix.empty())
269 if (!ignore_values && !
servers.empty() &&
servers[0].addresses.empty())
272 parse_errors +=
"dns server does not have an address assigned";
293 || opt.
ref(0) !=
"dns"
294 || opt.
ref(1) !=
"server")
316 for (
const auto i : *indices)
318 if (pushed[i].size() < 3 || pushed[i].ref(1) !=
"server")
321 pushed_prios.emplace_back(priority);
325 DnsFilter filter(std::move(pushed_prios));
const IndexMap & map() const
void extend(const OptionList &other, FilterBase *filt=nullptr)
const IndexList * get_index_ptr(const std::string &name) const
void exact_args(const size_t n) const
const std::string & get(const size_t index, const size_t max_len) const
void min_args(const size_t n) const
const std::string & ref(const size_t i) const
std::string render(const unsigned int flags) const
#define OPENVPN_THROW_ARG1(exc, arg, stuff)
A name server address and optional port.
DnsFilter(PriorityList &&pushed_prios)
const PriorityList pushed_prios_
bool filter(const Option &opt) override
std::vector< std::int8_t > PriorityList
void merge(OptionList &pushed, const OptionList &config) const override
void parse_dns_options(const OptionList &opt)
static int parse_priority(const std::string &prio_str)
void parse_dhcp_options(const OptionList &opt, bool use_search_as_split_domains, bool ignore_values)
DnsOptionsParser(const OptionList &opt, bool use_dhcp_search_domains_as_split_domains)
All DNS options set with the –dns or –dhcp-option directive.
std::map< int, DnsServer > servers
List of DNS servers to use, according to the list of priority.
DnsServer & get_server(const int priority)
std::vector< DnsDomain > search_domains
List of global DNS search domains to use.
bool from_dhcp_options
Set to true if the DNS options comes from –dhcp-option options.
static const char config[]