OpenVPN 3 Core Library
Loading...
Searching...
No Matches
dns_options.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2022- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12
13#pragma once
14
15#include <map>
16#include <vector>
17#include <algorithm>
18#include <sstream>
19
23#include <openvpn/addr/ip.hpp>
24
25#ifdef HAVE_JSON
27#endif
28
29namespace openvpn {
30
36{
42 std::string to_string() const
43 {
44 std::ostringstream os;
45 os << address;
46 if (port)
47 {
48 os << " " << port;
49 }
50 return os.str();
51 }
52
53 void validate(const std::string &title) const
54 {
56 }
57
58#ifdef HAVE_JSON
59 Json::Value to_json() const
60 {
61 Json::Value root(Json::objectValue);
62 root["address"] = Json::Value(address);
63 if (port)
64 {
65 root["port"] = Json::Value(port);
66 }
67 return root;
68 }
69
70 void from_json(const Json::Value &root, const std::string &title)
71 {
72 json::assert_dict(root, title);
73 json::to_uint_optional(root, port, "port", 0u, title);
74
75 std::string addr_str;
76 json::to_string(root, addr_str, "address", title);
78 }
79#endif
80
81 bool operator==(const DnsAddress &) const = default;
82
83 std::string address;
84 unsigned int port = 0;
85};
86
92{
98 std::string to_string() const
99 {
100 return domain;
101 }
102
103 void validate(const std::string &title) const
104 {
106 }
107
108#ifdef HAVE_JSON
109 Json::Value to_json() const
110 {
111 return Json::Value(domain);
112 }
113
114 void from_json(const Json::Value &value, const std::string &title)
115 {
116 if (!value.isString())
117 {
118 throw json::json_parse("string " + title + " is of incorrect type");
119 }
120 domain = value.asString();
121 }
122#endif
123
124 std::string domain;
125
126 bool operator==(const DnsDomain &) const = default;
127};
128
134{
135 enum class Security
136 {
137 Unset,
138 No,
139 Yes,
141 };
142
143 std::string dnssec_string(const Security dnssec) const
144 {
145 switch (dnssec)
146 {
147 case Security::No:
148 return "No";
149 case Security::Yes:
150 return "Yes";
152 return "Optional";
153 default:
154 return "Unset";
155 }
156 }
157
158 enum class Transport
159 {
160 Unset,
161 Plain,
162 HTTPS,
163 TLS
164 };
165
166 std::string transport_string(const Transport transport) const
167 {
168 switch (transport)
169 {
170 case Transport::Plain:
171 return "Plain";
172 case Transport::HTTPS:
173 return "HTTPS";
174 case Transport::TLS:
175 return "TLS";
176 default:
177 return "Unset";
178 }
179 }
180
181 std::string to_string(const char *prefix = "") const
182 {
183 std::ostringstream os;
184 os << prefix << "Addresses:\n";
185 for (const auto &address : addresses)
186 {
187 os << prefix << " " << address.to_string() << '\n';
188 }
189 if (!domains.empty())
190 {
191 os << prefix << "Domains:\n";
192 for (const auto &domain : domains)
193 {
194 os << prefix << " " << domain.to_string() << '\n';
195 }
196 }
197 if (dnssec != Security::Unset)
198 {
199 os << prefix << "DNSSEC: " << dnssec_string(dnssec) << '\n';
200 }
202 {
203 os << prefix << "Transport: " << transport_string(transport) << '\n';
204 }
205 if (!sni.empty())
206 {
207 os << prefix << "SNI: " << sni << '\n';
208 }
209 return os.str();
210 }
211
212#ifdef HAVE_JSON
213 Json::Value to_json() const
214 {
215 Json::Value server(Json::objectValue);
216 json::from_vector(server, addresses, "addresses");
217 if (!domains.empty())
218 {
219 json::from_vector(server, domains, "domains");
220 }
221 if (dnssec != Security::Unset)
222 {
223 server["dnssec"] = Json::Value(dnssec_string(dnssec));
224 }
226 {
227 server["transport"] = Json::Value(transport_string(transport));
228 }
229 if (!sni.empty())
230 {
231 server["sni"] = Json::Value(sni);
232 }
233 return server;
234 }
235
236 void from_json(const Json::Value &root, const std::string &title)
237 {
238 json::assert_dict(root, title);
239 json::to_vector(root, addresses, "addresses", title);
240 if (json::exists(root, "domains"))
241 {
242 json::to_vector(root, domains, "domains", title);
243 }
244 if (json::exists(root, "dnssec"))
245 {
246 std::string dnssec_str;
247 json::to_string(root, dnssec_str, "dnssec", title);
248 if (dnssec_str == "Optional")
249 {
251 }
252 else if (dnssec_str == "Yes")
253 {
255 }
256 else if (dnssec_str == "No")
257 {
259 }
260 else
261 {
262 throw json::json_parse("dnssec value " + dnssec_str + "is unknown");
263 }
264 }
265 if (json::exists(root, "transport"))
266 {
267 std::string transport_str;
268 json::to_string(root, transport_str, "transport", title);
269 if (transport_str == "Plain")
270 {
272 }
273 else if (transport_str == "HTTPS")
274 {
276 }
277 else if (transport_str == "TLS")
278 {
280 }
281 else
282 {
283 throw json::json_parse("transport value " + transport_str + "is unknown");
284 }
285 }
286 json::to_string_optional(root, sni, "sni", "", title);
287 }
288#endif
289
290 bool operator==(const DnsServer &at) const = default;
291
292 std::vector<DnsAddress> addresses;
293 std::vector<DnsDomain> domains;
296 std::string sni;
297};
298
304{
305 std::string to_string() const
306 {
307 std::ostringstream os;
308 if (!servers.empty())
309 {
310 os << "DNS Servers:\n";
311 for (const auto &elem : servers)
312 {
313 os << " Priority: " << elem.first << '\n';
314 os << elem.second.to_string(" ");
315 }
316 }
317 if (!search_domains.empty())
318 {
319 os << "DNS Search Domains:\n";
320 for (const auto &domain : search_domains)
321 {
322 os << " " << domain.to_string() << '\n';
323 }
324 }
325 return os.str();
326 }
327
328#ifdef HAVE_JSON
329 Json::Value to_json() const
330 {
331 Json::Value root(Json::objectValue);
332 Json::Value servers_json(Json::objectValue);
333 for (const auto &[prio, server] : servers)
334 {
335 servers_json[std::to_string(prio)] = server.to_json();
336 }
337 root["servers"] = std::move(servers_json);
338 json::from_vector(root, search_domains, "search_domains");
339 return root;
340 }
341
342 void from_json(const Json::Value &root, const std::string &title)
343 {
344 json::assert_dict(root, title);
345 json::assert_dict(root["servers"], title);
346 for (const auto &prio : root["servers"].getMemberNames())
347 {
348 DnsServer server;
349 server.from_json(root["servers"][prio], title);
350 servers[std::stoi(prio)] = std::move(server);
351 }
352 json::to_vector(root, search_domains, "search_domains", title);
353 }
354#endif
355
356 bool operator==(const DnsOptions &at) const = default;
357
358 bool from_dhcp_options = false;
359 std::vector<DnsDomain> search_domains;
360 std::map<int, DnsServer> servers;
361
362 protected:
363 DnsServer &get_server(const int priority)
364 {
365 auto it = servers.insert(std::make_pair(priority, DnsServer())).first;
366 return (*it).second;
367 }
368};
369
370} // namespace openvpn
static Addr from_string(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:105
std::string to_string() const
Definition ip.hpp:528
static std::string validate(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:131
void validate_host(const std::string &host, const std::string &title)
Definition hostport.hpp:93
void assert_dict(const Json::Value &obj, const TITLE &title)
void to_string_optional(const Json::Value &root, std::string &dest, const NAME &name, const std::string &default_value, const TITLE &title)
void to_string(const Json::Value &root, std::string &dest, const NAME &name, const TITLE &title)
void to_vector(const Json::Value &root, T &vec, const NAME &name, const TITLE &title)
bool exists(const Json::Value &root, const NAME &name)
void from_vector(Json::Value &root, const T &vec, const NAME &name)
void to_uint_optional(const Json::Value &root, unsigned int &dest, const NAME &name, const unsigned int default_value, const TITLE &title)
A name server address and optional port.
bool operator==(const DnsAddress &) const =default
Json::Value to_json() const
void from_json(const Json::Value &root, const std::string &title)
void validate(const std::string &title) const
std::string to_string() const
Return string representation of the DnsAddress object.
A DNS domain name.
bool operator==(const DnsDomain &) const =default
void validate(const std::string &title) const
std::string to_string() const
Return string representation of the DnsDomain object.
Json::Value to_json() const
void from_json(const Json::Value &value, const std::string &title)
All DNS options set with the –dns or –dhcp-option directive.
std::map< int, DnsServer > servers
DnsServer & get_server(const int priority)
void from_json(const Json::Value &root, const std::string &title)
std::vector< DnsDomain > search_domains
bool operator==(const DnsOptions &at) const =default
std::string to_string() const
Json::Value to_json() const
DNS settings for a name server.
std::vector< DnsAddress > addresses
std::vector< DnsDomain > domains
std::string transport_string(const Transport transport) const
std::string dnssec_string(const Security dnssec) const
std::string to_string(const char *prefix="") const
bool operator==(const DnsServer &at) const =default
Json::Value to_json() const
void from_json(const Json::Value &root, const std::string &title)
remote_address address
std::ostringstream os