diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 33e71c79d..742e039fc 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -100,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++) @@ -118,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++) @@ -138,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 @@ -215,7 +224,7 @@ DNSResolver::~DNSResolver() } } -std::vector DNSResolver::get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid) +std::vector 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 addresses; dnssec_available = false; @@ -231,7 +240,7 @@ std::vector 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, urlC, record_type, DNS_CLASS_IN, &result)) { dnssec_available = (result->secure || (!result->secure && result->bogus)); dnssec_valid = result->secure && !result->bogus; @@ -239,7 +248,7 @@ std::vector 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])); } } } @@ -247,66 +256,19 @@ std::vector DNSResolver::get_ipv4(const std::string& url, bool& dns return addresses; } -std::vector DNSResolver::get_ipv6(const std::string& url, bool& dnssec_available, bool& dnssec_valid) +std::vector DNSResolver::get_ipv4(const std::string& url, bool& dnssec_available, bool& dnssec_valid) { - std::vector 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 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 DNSResolver::get_txt_record(const std::string& url, bool& dnssec_available, bool& dnssec_valid) { - std::vector 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++) - { - records.push_back(std::string(result->data[i]+1, result->len[i]-1)); - } - } - } - - 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) diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index 332bceafe..63bf25445 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -130,6 +130,19 @@ public: 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 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 *