Electroneum
dns_utils.cpp
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyright (c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "common/dns_utils.h"
31 // check local first (in the event of static or in-source compilation of libunbound)
32 #include "unbound.h"
33 
34 #include <stdlib.h>
35 #include "include_base_utils.h"
36 #include "common/threadpool.h"
37 #include "crypto/crypto.h"
38 #include <boost/optional.hpp>
39 #include <random>
40 #include <boost/filesystem/fstream.hpp>
41 #include <boost/thread/mutex.hpp>
42 #include <boost/thread/thread.hpp>
43 #include <boost/algorithm/string/join.hpp>
44 using namespace epee;
45 
46 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
47 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "net.dns"
48 
49 static const char *DEFAULT_DNS_PUBLIC_ADDR[] =
50 {
51  "194.150.168.168", // CCC (Germany)
52  "80.67.169.40", // FDN (France)
53  "89.233.43.71", // http://censurfridns.dk (Denmark)
54  "109.69.8.51", // punCAT (Spain)
55  "193.58.251.251" // SkyDNS (Russia)
56 };
57 
58 static boost::mutex instance_lock;
59 
60 namespace
61 {
62 
63 /*
64  * The following two functions were taken from unbound-anchor.c, from
65  * the unbound library packaged with this source. The license and source
66  * can be found in $PROJECT_ROOT/external/unbound
67  */
68 
69 /* Cert builtin commented out until it's used, as the compiler complains
70 
71 // return the built in root update certificate
72 static const char*
73 get_builtin_cert(void)
74 {
75  return
76 // The ICANN CA fetched at 24 Sep 2010. Valid to 2028
77 "-----BEGIN CERTIFICATE-----\n"
78 "MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
79 "TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
80 "BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n"
81 "DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n"
82 "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n"
83 "MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n"
84 "cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n"
85 "G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n"
86 "ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n"
87 "paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n"
88 "MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n"
89 "iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n"
90 "Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n"
91 "DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n"
92 "6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n"
93 "2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n"
94 "15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n"
95 "0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n"
96 "j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n"
97 "-----END CERTIFICATE-----\n"
98  ;
99 }
100 */
101 
103 static const char* const*
104 get_builtin_ds(void)
105 {
106  static const char * const ds[] =
107  {
108  ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n",
109  ". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n",
110  NULL
111  };
112  return ds;
113 }
114 
115 /************************************************************
116  ************************************************************
117  ***********************************************************/
118 
119 } // anonymous namespace
120 
121 namespace tools
122 {
123 
124 static const char *get_record_name(int record_type)
125 {
126  switch (record_type)
127  {
128  case DNS_TYPE_A: return "A";
129  case DNS_TYPE_TXT: return "TXT";
130  case DNS_TYPE_AAAA: return "AAAA";
131  default: return "unknown";
132  }
133 }
134 
135 // fuck it, I'm tired of dealing with getnameinfo()/inet_ntop/etc
136 boost::optional<std::string> ipv4_to_string(const char* src, size_t len)
137 {
138  if (len < 4)
139  {
140  MERROR("Invalid IPv4 address: " << std::string(src, len));
141  return boost::none;
142  }
143 
144  std::stringstream ss;
145  unsigned int bytes[4];
146  for (int i = 0; i < 4; i++)
147  {
148  unsigned char a = src[i];
149  bytes[i] = a;
150  }
151  ss << bytes[0] << "."
152  << bytes[1] << "."
153  << bytes[2] << "."
154  << bytes[3];
155  return ss.str();
156 }
157 
158 // this obviously will need to change, but is here to reflect the above
159 // stop-gap measure and to make the tests pass at least...
160 boost::optional<std::string> ipv6_to_string(const char* src, size_t len)
161 {
162  if (len < 8)
163  {
164  MERROR("Invalid IPv4 address: " << std::string(src, len));
165  return boost::none;
166  }
167 
168  std::stringstream ss;
169  unsigned int bytes[8];
170  for (int i = 0; i < 8; i++)
171  {
172  unsigned char a = src[i];
173  bytes[i] = a;
174  }
175  ss << bytes[0] << ":"
176  << bytes[1] << ":"
177  << bytes[2] << ":"
178  << bytes[3] << ":"
179  << bytes[4] << ":"
180  << bytes[5] << ":"
181  << bytes[6] << ":"
182  << bytes[7];
183  return ss.str();
184 }
185 
186 boost::optional<std::string> txt_to_string(const char* src, size_t len)
187 {
188  if (len == 0)
189  return boost::none;
190  return std::string(src+1, len-1);
191 }
192 
193 // custom smart pointer.
194 // TODO: see if std::auto_ptr and the like support custom destructors
195 template<typename type, void (*freefunc)(type*)>
197 {
198 public:
200  ptr(nullptr)
201  {
202  }
203  scoped_ptr(type *p):
204  ptr(p)
205  {
206  }
208  {
209  freefunc(ptr);
210  }
211  operator type *() { return ptr; }
212  type **operator &() { return &ptr; }
213  type *operator->() { return ptr; }
214  operator const type*() const { return &ptr; }
215 
216 private:
217  type* ptr;
218 };
219 
221 
223 {
225 };
226 
227 // work around for bug https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=515 needed for it to compile on e.g. Debian 7
228 class string_copy {
229 public:
230  string_copy(const char *s): str(strdup(s)) {}
231  ~string_copy() { free(str); }
232  operator char*() { return str; }
233 
234 public:
235  char *str;
236 };
237 
238 static void add_anchors(ub_ctx *ctx)
239 {
240  const char * const *ds = ::get_builtin_ds();
241  while (*ds)
242  {
243  MINFO("adding trust anchor: " << *ds);
244  ub_ctx_add_ta(ctx, string_copy(*ds++));
245  }
246 }
247 
248 DNSResolver::DNSResolver() : m_data(new DNSResolverData())
249 {
250  int use_dns_public = 0;
251  std::vector<std::string> dns_public_addr;
252  const char *DNS_PUBLIC = getenv("DNS_PUBLIC");
253  if (DNS_PUBLIC)
254  {
255  dns_public_addr = tools::dns_utils::parse_dns_public(DNS_PUBLIC);
256  if (!dns_public_addr.empty())
257  {
258  MGINFO("Using public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)");
259  use_dns_public = 1;
260  }
261  else
262  {
263  MERROR("Failed to parse DNS_PUBLIC");
264  }
265  }
266 
267  // init libunbound context
268  m_data->m_ub_context = ub_ctx_create();
269 
270  if (use_dns_public)
271  {
272  for (const auto &ip: dns_public_addr)
273  ub_ctx_set_fwd(m_data->m_ub_context, string_copy(ip.c_str()));
274  ub_ctx_set_option(m_data->m_ub_context, string_copy("do-udp:"), string_copy("no"));
275  ub_ctx_set_option(m_data->m_ub_context, string_copy("do-tcp:"), string_copy("yes"));
276  }
277  else {
278  // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent
279  ub_ctx_resolvconf(m_data->m_ub_context, NULL);
280  ub_ctx_hosts(m_data->m_ub_context, NULL);
281  }
282 
283  add_anchors(m_data->m_ub_context);
284 
285  if (!DNS_PUBLIC)
286  {
287  // if no DNS_PUBLIC specified, we try a lookup to what we know
288  // should be a valid DNSSEC record, and switch to known good
289  // DNSSEC resolvers if verification fails
290  bool available, valid;
291  static const char *probe_hostname = "updates.electroneumpulse.org";
292  auto records = get_txt_record(probe_hostname, available, valid);
293  if (!valid)
294  {
295  MINFO("Failed to verify DNSSEC record from " << probe_hostname << ", falling back to TCP with well known DNSSEC resolvers");
296  ub_ctx_delete(m_data->m_ub_context);
297  m_data->m_ub_context = ub_ctx_create();
298  add_anchors(m_data->m_ub_context);
299  for (const auto &ip: DEFAULT_DNS_PUBLIC_ADDR)
300  ub_ctx_set_fwd(m_data->m_ub_context, string_copy(ip));
301  ub_ctx_set_option(m_data->m_ub_context, string_copy("do-udp:"), string_copy("no"));
302  ub_ctx_set_option(m_data->m_ub_context, string_copy("do-tcp:"), string_copy("yes"));
303  }
304  }
305 }
306 
308 {
309  if (m_data)
310  {
311  if (m_data->m_ub_context != NULL)
312  {
313  ub_ctx_delete(m_data->m_ub_context);
314  }
315  delete m_data;
316  }
317 }
318 
319 std::vector<std::string> DNSResolver::get_record(const std::string& url, int record_type, boost::optional<std::string> (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid)
320 {
321  std::vector<std::string> addresses;
322  dnssec_available = false;
323  dnssec_valid = false;
324 
325  if (!check_address_syntax(url.c_str()))
326  {
327  return addresses;
328  }
329 
330  // destructor takes care of cleanup
331  ub_result_ptr result;
332 
333  // call DNS resolver, blocking. if return value not zero, something went wrong
334  if (!ub_resolve(m_data->m_ub_context, string_copy(url.c_str()), record_type, DNS_CLASS_IN, &result))
335  {
336  dnssec_available = (result->secure || result->bogus);
337  dnssec_valid = result->secure && !result->bogus;
338  if (result->havedata)
339  {
340  for (size_t i=0; result->data[i] != NULL; i++)
341  {
342  boost::optional<std::string> res = (*reader)(result->data[i], result->len[i]);
343  if (res)
344  {
345  MINFO("Found \"" << *res << "\" in " << get_record_name(record_type) << " record for " << url);
346  addresses.push_back(*res);
347  }
348  }
349  }
350  }
351 
352  return addresses;
353 }
354 
355 std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
356 {
357  return get_record(url, DNS_TYPE_A, ipv4_to_string, dnssec_available, dnssec_valid);
358 }
359 
360 std::vector<std::string> DNSResolver::get_ipv6(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
361 {
362  return get_record(url, DNS_TYPE_AAAA, ipv6_to_string, dnssec_available, dnssec_valid);
363 }
364 
365 std::vector<std::string> DNSResolver::get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
366 {
367  return get_record(url, DNS_TYPE_TXT, txt_to_string, dnssec_available, dnssec_valid);
368 }
369 
371 {
372  std::string addr(oa_addr);
373  auto first_at = addr.find("@");
374  if (first_at == std::string::npos)
375  return addr;
376 
377  // convert name@domain.tld to name.domain.tld
378  addr.replace(first_at, 1, ".");
379 
380  return addr;
381 }
382 
384 {
385  boost::lock_guard<boost::mutex> lock(instance_lock);
386 
387  static DNSResolver staticInstance;
388  return staticInstance;
389 }
390 
392 {
393  return DNSResolver();
394 }
395 
396 bool DNSResolver::check_address_syntax(const char *addr) const
397 {
398  // if string doesn't contain a dot, we won't consider it a url for now.
399  if (strchr(addr,'.') == NULL)
400  {
401  return false;
402  }
403  return true;
404 }
405 
406 namespace dns_utils
407 {
408 
409 //-----------------------------------------------------------------------
410 // TODO: parse the string in a less stupid way, probably with regex
412 {
413  // make sure the txt record has "oa1:etn" and find it
414  auto pos = s.find("oa1:etn");
415  if (pos == std::string::npos)
416  return {};
417  // search from there to find "recipient_address="
418  pos = s.find("recipient_address=", pos);
419  if (pos == std::string::npos)
420  return {};
421  pos += 18; // move past "recipient_address="
422  // find the next semicolon
423  auto pos2 = s.find(";", pos);
424  if (pos2 != std::string::npos)
425  {
426  // length of address == 98, we can at least validate that much here
427  if (pos2 - pos == 98)
428  {
429  return s.substr(pos, 98);
430  }
431  else if (pos2 - pos == 109) // length of address == 109 --> integrated address
432  {
433  return s.substr(pos, 109);
434  }
435  }
436  return {};
437 }
452 std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec_valid)
453 {
454  std::vector<std::string> addresses;
455  // get txt records
456  bool dnssec_available, dnssec_isvalid;
458  auto records = DNSResolver::instance().get_txt_record(oa_addr, dnssec_available, dnssec_isvalid);
459 
460  // TODO: update this to allow for conveying that dnssec was not available
461  if (dnssec_available && dnssec_isvalid)
462  {
463  dnssec_valid = true;
464  }
465  else dnssec_valid = false;
466 
467  // for each txt record, try to find a electroneum address in it.
468  for (auto& rec : records)
469  {
471  if (addr.size())
472  {
473  addresses.push_back(addr);
474  }
475  }
476  return addresses;
477 }
478 
479 std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, std::function<std::string(const std::string&, const std::vector<std::string>&, bool)> dns_confirm)
480 {
481  // attempt to get address from dns query
482  auto addresses = addresses_from_url(url, dnssec_valid);
483  if (addresses.empty())
484  {
485  LOG_ERROR("wrong address: " << url);
486  return {};
487  }
488  return dns_confirm(url, addresses, dnssec_valid);
489 }
490 
491 namespace
492 {
493  bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b)
494  {
495  if (a.size() != b.size()) return false;
496 
497  for (const auto& record_in_a : a)
498  {
499  bool ok = false;
500  for (const auto& record_in_b : b)
501  {
502  if (record_in_a == record_in_b)
503  {
504  ok = true;
505  break;
506  }
507  }
508  if (!ok) return false;
509  }
510 
511  return true;
512  }
513 }
514 
515 bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std::vector<std::string> &dns_urls, std::string type)
516 {
517  // Prevent infinite recursion when distributing
518  if (dns_urls.empty()) return false;
519 
520  std::vector<std::vector<std::string> > records;
521  records.resize(dns_urls.size());
522 
523  size_t first_index = crypto::rand_idx(dns_urls.size());
524 
525  // send all requests in parallel
526  std::deque<bool> avail(dns_urls.size(), false), valid(dns_urls.size(), false);
529  for (size_t n = 0; n < dns_urls.size(); ++n)
530  {
531  tpool.submit(&waiter,[n, dns_urls, &records, &avail, &valid](){
532  records[n] = tools::DNSResolver::instance().get_txt_record(dns_urls[n], avail[n], valid[n]);
533  });
534  }
535  waiter.wait(&tpool);
536 
537  size_t cur_index = first_index;
538  do
539  {
540  const std::string &url = dns_urls[cur_index];
541  if (!avail[cur_index])
542  {
543  records[cur_index].clear();
544  LOG_PRINT_L2("DNSSEC not available for " << type << " at URL: " << url << ", skipping.");
545  }
546  if (!valid[cur_index])
547  {
548  records[cur_index].clear();
549  LOG_PRINT_L2("DNSSEC validation failed for " << type << " at URL: " << url << ", skipping.");
550  }
551 
552  cur_index++;
553  if (cur_index == dns_urls.size())
554  {
555  cur_index = 0;
556  }
557  } while (cur_index != first_index);
558 
559  size_t num_valid_records = 0;
560 
561  for( const auto& record_set : records)
562  {
563  if (record_set.size() != 0)
564  {
565  num_valid_records++;
566  }
567  }
568 
569  if (num_valid_records < 2)
570  {
571  LOG_PRINT_L1("WARNING: no two valid ElectroneumPulse DNS " << type << " records were received, only " << num_valid_records);
572  return false;
573  }
574 
575  int good_records_index = -1;
576  for (size_t i = 0; i < records.size() - 1; ++i)
577  {
578  if (records[i].size() == 0) continue;
579 
580  for (size_t j = i + 1; j < records.size(); ++j)
581  {
582  if (dns_records_match(records[i], records[j]))
583  {
584  good_records_index = i;
585  break;
586  }
587  }
588  if (good_records_index >= 0) break;
589  }
590 
591  if (good_records_index < 0)
592  {
593  LOG_PRINT_L1("WARNING: no two ElectroneumPulse DNS " << type << " records matched");
594  return false;
595  }
596 
597  good_records = records[good_records_index];
598  return true;
599 }
600 
601 std::vector<std::string> parse_dns_public(const char *s)
602 {
603  unsigned ip0, ip1, ip2, ip3;
604  char c;
605  std::vector<std::string> dns_public_addr;
606  if (!strcmp(s, "tcp"))
607  {
608  for (size_t i = 0; i < sizeof(DEFAULT_DNS_PUBLIC_ADDR) / sizeof(DEFAULT_DNS_PUBLIC_ADDR[0]); ++i)
609  dns_public_addr.push_back(DEFAULT_DNS_PUBLIC_ADDR[i]);
610  LOG_PRINT_L0("Using default public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)");
611  }
612  else if (sscanf(s, "tcp://%u.%u.%u.%u%c", &ip0, &ip1, &ip2, &ip3, &c) == 4)
613  {
614  if (ip0 > 255 || ip1 > 255 || ip2 > 255 || ip3 > 255)
615  {
616  MERROR("Invalid IP: " << s << ", using default");
617  }
618  else
619  {
620  dns_public_addr.push_back(std::string(s + strlen("tcp://")));
621  }
622  }
623  else
624  {
625  MERROR("Invalid DNS_PUBLIC contents, ignored");
626  }
627  return dns_public_addr;
628 }
629 
630 } // namespace tools::dns_utils
631 
632 } // namespace tools
const char * res
Definition: hmac_keccak.cpp:41
#define MERROR(x)
Definition: misc_log_ex.h:73
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
#define MINFO(x)
Definition: misc_log_ex.h:75
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
::std::string string
Definition: gtest-port.h:1097
A global thread pool.
Definition: threadpool.h:43
int ub_ctx_resolvconf(struct ub_ctx *ctx, const char *fname)
std::vector< std::string > get_ipv4(const std::string &url, bool &dnssec_available, bool &dnssec_valid)
gets ipv4 addresses from DNS query of a URL
Definition: dns_utils.cpp:355
type * operator->()
Definition: dns_utils.cpp:213
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
static DNSResolver create()
Gets a new instance of DNSResolver.
Definition: dns_utils.cpp:391
boost::optional< std::string > ipv6_to_string(const char *src, size_t len)
Definition: dns_utils.cpp:160
int ub_ctx_set_option(struct ub_ctx *ctx, const char *opt, const char *val)
static threadpool & getInstance()
Definition: threadpool.h:46
std::string get_account_address_as_str_from_url(const std::string &url, bool &dnssec_valid, std::function< std::string(const std::string &, const std::vector< std::string > &, bool)> dns_confirm)
Definition: dns_utils.cpp:479
#define MGINFO(x)
Definition: misc_log_ex.h:80
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition: crypto.h:244
Archiver & operator &(Archiver &ar, Student &s)
void wait(threadpool *tpool)
Definition: threadpool.cpp:115
std::vector< std::string > get_ipv6(const std::string &url, bool &dnssec_available, bool &dnssec_valid)
gets ipv6 addresses from DNS query
Definition: dns_utils.cpp:360
Various Tools.
Definition: tools.cpp:31
std::vector< std::string > addresses_from_url(const std::string &url, bool &dnssec_valid)
gets a electroneum address from the TXT record of a DNS entry
Definition: dns_utils.cpp:452
struct ub_ctx * ub_ctx_create(void)
std::string get_dns_format_from_oa_address(const std::string &oa_addr)
Gets a DNS address from OpenAlias format.
Definition: dns_utils.cpp:370
Provides high-level access to DNS resolution.
Definition: dns_utils.h:55
boost::endian::big_uint32_t ip
Definition: socks.cpp:61
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
static DNSResolver & instance()
Gets the singleton instance of DNSResolver.
Definition: dns_utils.cpp:383
boost::optional< std::string > ipv4_to_string(const char *src, size_t len)
Definition: dns_utils.cpp:136
int ub_ctx_set_fwd(struct ub_ctx *ctx, const char *addr)
std::vector< std::string > parse_dns_public(const char *s)
Definition: dns_utils.cpp:601
int ub_ctx_hosts(struct ub_ctx *ctx, const char *fname)
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
boost::optional< std::string > txt_to_string(const char *src, size_t len)
Definition: dns_utils.cpp:186
std::string address_from_txt_record(const std::string &s)
Definition: dns_utils.cpp:411
scoped_ptr(type *p)
Definition: dns_utils.cpp:203
void ub_ctx_delete(struct ub_ctx *ctx)
int ub_resolve(struct ub_ctx *ctx, const char *name, int rrtype, int rrclass, struct ub_result **result)
class scoped_ptr< ub_result, ub_resolve_free > ub_result_ptr
Definition: dns_utils.cpp:220
void ub_resolve_free(struct ub_result *result)
std::vector< std::string > get_txt_record(const std::string &url, bool &dnssec_available, bool &dnssec_valid)
gets all TXT records from a DNS query for the supplied URL; if no TXT record present returns an empty...
Definition: dns_utils.cpp:365
bool load_txt_records_from_dns(std::vector< std::string > &good_records, const std::vector< std::string > &dns_urls, std::string type)
Definition: dns_utils.cpp:515
~DNSResolver()
takes care of freeing C pointers and such
Definition: dns_utils.cpp:307
string_copy(const char *s)
Definition: dns_utils.cpp:230
int ub_ctx_add_ta(struct ub_ctx *ctx, const char *ta)
Definition: context.h:62