aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2015-08-30 16:30:19 +0200
committerRiccardo Spagni <ric@spagni.net>2015-08-30 16:30:35 +0200
commitcf88e4dd24edab449765e78b34ec530f08373b68 (patch)
treeb09aa5a4a978f5c4e8061111aa5a238f795d93e1
parentMerge pull request #391 (diff)
parentunbound: use the mini event fallback implementation (diff)
downloadmonero-cf88e4dd24edab449765e78b34ec530f08373b68.tar.xz
Merge pull request #394
3c10239 unbound: use the mini event fallback implementation (moneromooo-monero) 4e138a0 dns_utils: remove unnecessary string conversion (moneromooo-monero) f928468 dns_utils: factor the fetching code for different DNS record types (moneromooo-monero) 4ef0da1 dns_utils: simplify string handling and fix leak (moneromooo-monero) ae5f28c dns_utils: add a const where possible (moneromooo-monero) f43d465 dns_utils: lock access to the singleton (moneromooo-monero) 5990344 dns: make ctor private (moneromooo-monero)
-rw-r--r--external/unbound/config.h.cmake.in3
-rw-r--r--src/common/dns_utils.cpp100
-rw-r--r--src/common/dns_utils.h26
-rw-r--r--tests/unit_tests/dns_resolver.cpp12
4 files changed, 64 insertions, 77 deletions
diff --git a/external/unbound/config.h.cmake.in b/external/unbound/config.h.cmake.in
index d9bfebf33..377bcd97f 100644
--- a/external/unbound/config.h.cmake.in
+++ b/external/unbound/config.h.cmake.in
@@ -575,7 +575,8 @@
#cmakedefine USE_GOST
/* Define if you want to use internal select based events */
-#cmakedefine USE_MINI_EVENT
+/* #cmakedefine USE_MINI_EVENT */
+#define USE_MINI_EVENT 1
/* Define this to enable SHA256 and SHA512 support. */
#cmakedefine USE_SHA2
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp
index e442d3d81..5cb5ed2de 100644
--- a/src/common/dns_utils.cpp
+++ b/src/common/dns_utils.cpp
@@ -38,6 +38,8 @@
using namespace epee;
namespace bf = boost::filesystem;
+static std::mutex instance_lock;
+
namespace
{
@@ -98,8 +100,10 @@ namespace tools
{
// fuck it, I'm tired of dealing with getnameinfo()/inet_ntop/etc
-std::string ipv4_to_string(const char* src)
+std::string ipv4_to_string(const char* src, size_t len)
{
+ assert(memchr(src, 0, len));
+
std::stringstream ss;
unsigned int bytes[4];
for (int i = 0; i < 4; i++)
@@ -116,8 +120,10 @@ std::string ipv4_to_string(const char* src)
// this obviously will need to change, but is here to reflect the above
// stop-gap measure and to make the tests pass at least...
-std::string ipv6_to_string(const char* src)
+std::string ipv6_to_string(const char* src, size_t len)
{
+ assert(memchr(src, 0, len));
+
std::stringstream ss;
unsigned int bytes[8];
for (int i = 0; i < 8; i++)
@@ -136,6 +142,11 @@ std::string ipv6_to_string(const char* src)
return ss.str();
}
+std::string txt_to_string(const char* src, size_t len)
+{
+ return std::string(src+1, len-1);
+}
+
// custom smart pointer.
// TODO: see if std::auto_ptr and the like support custom destructors
template<typename type, void (*freefunc)(type*)>
@@ -164,8 +175,6 @@ private:
};
typedef class scoped_ptr<ub_result,ub_resolve_free> ub_result_ptr;
-static void freestring(char *ptr) { free(ptr); }
-typedef class scoped_ptr<char,freestring> string_ptr;
struct DNSResolverData
{
@@ -213,14 +222,13 @@ DNSResolver::~DNSResolver()
}
}
-std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
+std::vector<std::string> DNSResolver::get_record(const std::string& url, int record_type, std::string (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid)
{
std::vector<std::string> addresses;
dnssec_available = false;
dnssec_valid = false;
- string_ptr urlC(strdup(url.c_str()));
- if (!check_address_syntax(urlC))
+ if (!check_address_syntax(url.c_str()))
{
return addresses;
}
@@ -229,7 +237,7 @@ std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dns
ub_result_ptr result;
// call DNS resolver, blocking. if return value not zero, something went wrong
- if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_A, DNS_CLASS_IN, &result))
+ if (!ub_resolve(m_data->m_ub_context, url.c_str(), record_type, DNS_CLASS_IN, &result))
{
dnssec_available = (result->secure || (!result->secure && result->bogus));
dnssec_valid = result->secure && !result->bogus;
@@ -237,7 +245,7 @@ std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dns
{
for (size_t i=0; result->data[i] != NULL; i++)
{
- addresses.push_back(ipv4_to_string(result->data[i]));
+ addresses.push_back((*reader)(result->data[i], result->len[i]));
}
}
}
@@ -245,70 +253,19 @@ std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dns
return addresses;
}
-std::vector<std::string> DNSResolver::get_ipv6(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
+std::vector<std::string> DNSResolver::get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
{
- std::vector<std::string> addresses;
- dnssec_available = false;
- dnssec_valid = false;
-
- string_ptr urlC(strdup(url.c_str()));
- if (!check_address_syntax(urlC))
- {
- return addresses;
- }
-
- ub_result_ptr result;
-
- // call DNS resolver, blocking. if return value not zero, something went wrong
- if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_AAAA, DNS_CLASS_IN, &result))
- {
- dnssec_available = (result->secure || (!result->secure && result->bogus));
- dnssec_valid = result->secure && !result->bogus;
- if (result->havedata)
- {
- for (size_t i=0; result->data[i] != NULL; i++)
- {
- addresses.push_back(ipv6_to_string(result->data[i]));
- }
- }
- }
+ return get_record(url, DNS_TYPE_A, ipv4_to_string, dnssec_available, dnssec_valid);
+}
- return addresses;
+std::vector<std::string> DNSResolver::get_ipv6(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
+{
+ return get_record(url, DNS_TYPE_AAAA, ipv6_to_string, dnssec_available, dnssec_valid);
}
std::vector<std::string> DNSResolver::get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid)
{
- std::vector<std::string> records;
- dnssec_available = false;
- dnssec_valid = false;
-
- string_ptr urlC(strdup(url.c_str()));
- if (!check_address_syntax(urlC))
- {
- return records;
- }
-
- ub_result_ptr result;
-
- // call DNS resolver, blocking. if return value not zero, something went wrong
- if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_TXT, DNS_CLASS_IN, &result))
- {
- dnssec_available = (result->secure || (!result->secure && result->bogus));
- dnssec_valid = result->secure && !result->bogus;
- if (result->havedata)
- {
- for (size_t i=0; result->data[i] != NULL; i++)
- {
- // plz fix this, but this does NOT work and spills over into parts of memory it shouldn't: records.push_back(result.ptr->data[i]);
- char *restxt;
- restxt = (char*) calloc(result->len[i]+1, 1);
- memcpy(restxt, result->data[i]+1, result->len[i]-1);
- records.push_back(restxt);
- }
- }
- }
-
- return records;
+ return get_record(url, DNS_TYPE_TXT, txt_to_string, dnssec_available, dnssec_valid);
}
std::string DNSResolver::get_dns_format_from_oa_address(const std::string& oa_addr)
@@ -326,6 +283,8 @@ std::string DNSResolver::get_dns_format_from_oa_address(const std::string& oa_ad
DNSResolver& DNSResolver::instance()
{
+ std::lock_guard<std::mutex> lock(instance_lock);
+
static DNSResolver* staticInstance = NULL;
if (staticInstance == NULL)
{
@@ -334,7 +293,12 @@ DNSResolver& DNSResolver::instance()
return *staticInstance;
}
-bool DNSResolver::check_address_syntax(const char *addr)
+DNSResolver DNSResolver::create()
+{
+ return DNSResolver();
+}
+
+bool DNSResolver::check_address_syntax(const char *addr) const
{
// if string doesn't contain a dot, we won't consider it a url for now.
if (strchr(addr,'.') == NULL)
diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h
index 1e726c80c..63bf25445 100644
--- a/src/common/dns_utils.h
+++ b/src/common/dns_utils.h
@@ -49,7 +49,7 @@ struct DNSResolverData;
*/
class DNSResolver
{
-public:
+private:
/**
* @brief Constructs an instance of DNSResolver
@@ -58,6 +58,8 @@ public:
*/
DNSResolver();
+public:
+
/**
* @brief takes care of freeing C pointers and such
*/
@@ -119,16 +121,36 @@ public:
*/
static DNSResolver& instance();
+ /**
+ * @brief Gets a new instance of DNSResolver
+ *
+ * @return returns a pointer to the new object
+ */
+ static DNSResolver create();
+
private:
/**
+ * @brief gets all records of a given type from a DNS query for the supplied URL;
+ * if no such record is present returns an empty vector.
+ *
+ * @param url A string containing a URL to query for
+ * @param record_type the record type to retrieve (DNS_TYPE_A, etc)
+ * @param reader a function that converts a record data to a string
+ *
+ * @return A vector of strings containing the requested record; or an empty vector
+ */
+ // TODO: modify this to accomodate DNSSEC
+ std::vector<std::string> get_record(const std::string& url, int record_type, std::string (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid);
+
+ /**
* @brief Checks a string to see if it looks like a URL
*
* @param addr the string to be checked
*
* @return true if it looks enough like a URL, false if not
*/
- bool check_address_syntax(const char *addr);
+ bool check_address_syntax(const char *addr) const;
DNSResolverData *m_data;
}; // class DNSResolver
diff --git a/tests/unit_tests/dns_resolver.cpp b/tests/unit_tests/dns_resolver.cpp
index 0709a773f..3285f7732 100644
--- a/tests/unit_tests/dns_resolver.cpp
+++ b/tests/unit_tests/dns_resolver.cpp
@@ -35,7 +35,7 @@
TEST(DNSResolver, IPv4Success)
{
- tools::DNSResolver resolver;
+ tools::DNSResolver resolver = tools::DNSResolver::create();
bool avail, valid;
@@ -55,7 +55,7 @@ TEST(DNSResolver, IPv4Success)
TEST(DNSResolver, IPv4Failure)
{
// guaranteed by IANA/ICANN/RFC to be invalid
- tools::DNSResolver resolver;
+ tools::DNSResolver resolver = tools::DNSResolver::create();
bool avail, valid;
@@ -70,7 +70,7 @@ TEST(DNSResolver, IPv4Failure)
TEST(DNSResolver, DNSSECSuccess)
{
- tools::DNSResolver resolver;
+ tools::DNSResolver resolver = tools::DNSResolver::create();
bool avail, valid;
@@ -86,7 +86,7 @@ TEST(DNSResolver, DNSSECSuccess)
TEST(DNSResolver, DNSSECFailure)
{
- tools::DNSResolver resolver;
+ tools::DNSResolver resolver = tools::DNSResolver::create();
bool avail, valid;
@@ -103,7 +103,7 @@ TEST(DNSResolver, DNSSECFailure)
// It would be great to include an IPv6 test and assume it'll pass, but not every ISP / resolver plays nicely with IPv6;)
/*TEST(DNSResolver, IPv6Success)
{
- tools::DNSResolver resolver;
+ tools::DNSResolver resolver = tools::DNSResolver::create();
bool avail, valid;
@@ -123,7 +123,7 @@ TEST(DNSResolver, DNSSECFailure)
TEST(DNSResolver, IPv6Failure)
{
// guaranteed by IANA/ICANN/RFC to be invalid
- tools::DNSResolver resolver;
+ tools::DNSResolver resolver = tools::DNSResolver::create();
bool avail, valid;