diff options
author | ADAM David Alan Martin <adam.martin@10gen.com> | 2018-02-09 16:35:52 -0500 |
---|---|---|
committer | ADAM David Alan Martin <adam.martin@10gen.com> | 2018-02-09 16:39:03 -0500 |
commit | 9820063b4a88f685704385c13f4ee34aed31c1cd (patch) | |
tree | 6cd8204b7973bae9d68549393b8caa9edf75c7d7 | |
parent | 3968e970161872b78fa88ad65a8785b54694c126 (diff) | |
download | mongo-9820063b4a88f685704385c13f4ee34aed31c1cd.tar.gz |
SERVER-33140 DNS must disregard irrelevant records
DNS Queries can return superfluous records of non-requested type in
Windows DNSApi calls. Windows implementations will now ignore
records of those types.
(cherry picked from commit bf33c24ff0cf4018dfa94e3a349421ace28d1fac)
-rw-r--r-- | src/mongo/base/error_codes.err | 1 | ||||
-rw-r--r-- | src/mongo/util/dns_query.cpp | 66 | ||||
-rw-r--r-- | src/mongo/util/dns_query_windows-impl.h | 21 |
3 files changed, 60 insertions, 28 deletions
diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err index 38bc2ef862e..8bbd50ceaa4 100644 --- a/src/mongo/base/error_codes.err +++ b/src/mongo/base/error_codes.err @@ -232,6 +232,7 @@ error_code("DNSProtocolError", 231) error_code("MaxSubPipelineDepthExceeded", 232) error_code("TooManyDocumentSequences", 233) error_code("RetryChangeStream", 234) +error_code("DNSRecordTypeMismatch", 240) # Error codes 4000-8999 are reserved. diff --git a/src/mongo/util/dns_query.cpp b/src/mongo/util/dns_query.cpp index 3eef7240851..d200b57e7bf 100644 --- a/src/mongo/util/dns_query.cpp +++ b/src/mongo/util/dns_query.cpp @@ -43,6 +43,8 @@ #include <boost/noncopyable.hpp> +#include "mongo/bson/util/builder.h" + // It is safe to include the implementation "headers" in an anonymous namespace, as the code is // meant to live in a single TU -- this one. Include one of these headers last. #define MONGO_UTIL_DNS_QUERY_PLATFORM_INCLUDE_WHITELIST @@ -66,15 +68,25 @@ std::vector<std::string> dns::lookupARecords(const std::string& service) { DNSQueryState dnsQuery; auto response = dnsQuery.lookup(service, DNSQueryClass::kInternet, DNSQueryType::kAddress); - if (response.size() == 0) { - uasserted(ErrorCodes::DNSProtocolError, - "Looking up " + service + " A record yielded no results."); + std::vector<std::string> rv; + + for (const auto& entry : response) { + try { + rv.push_back(entry.addressEntry()); + } catch (const ExceptionFor<ErrorCodes::DNSRecordTypeMismatch>&) { + } } - std::vector<std::string> rv; - std::transform(begin(response), end(response), back_inserter(rv), [](const auto& entry) { - return entry.addressEntry(); - }); + if (rv.empty()) { + StringBuilder oss; + oss << "Looking up " << service << " A record yielded "; + if (response.size() == 0) { + oss << "no results."; + } else { + oss << "no A records but " << response.size() << " other records"; + } + uasserted(ErrorCodes::DNSProtocolError, oss.str()); + } return rv; } @@ -86,9 +98,24 @@ std::vector<dns::SRVHostEntry> dns::lookupSRVRecords(const std::string& service) std::vector<SRVHostEntry> rv; - std::transform(begin(response), end(response), back_inserter(rv), [](const auto& entry) { - return entry.srvHostEntry(); - }); + for (const auto& entry : response) { + try { + rv.push_back(entry.srvHostEntry()); + } catch (const ExceptionFor<ErrorCodes::DNSRecordTypeMismatch>&) { + } + } + + if (rv.empty()) { + StringBuilder oss; + oss << "Looking up " << service << " SRV record yielded "; + if (response.size() == 0) { + oss << "no results."; + } else { + oss << "no SRV records but " << response.size() << " other records"; + } + uasserted(ErrorCodes::DNSProtocolError, oss.str()); + } + return rv; } @@ -100,20 +127,21 @@ std::vector<std::string> dns::lookupTXTRecords(const std::string& service) { std::vector<std::string> rv; for (auto& entry : response) { - auto txtEntry = entry.txtEntry(); - rv.insert(end(rv), - std::make_move_iterator(begin(txtEntry)), - std::make_move_iterator(end(txtEntry))); + try { + auto txtEntry = entry.txtEntry(); + rv.insert(end(rv), + std::make_move_iterator(begin(txtEntry)), + std::make_move_iterator(end(txtEntry))); + } catch (const ExceptionFor<ErrorCodes::DNSRecordTypeMismatch>&) { + } } + return rv; } std::vector<std::string> dns::getTXTRecords(const std::string& service) try { return lookupTXTRecords(service); -} catch (const DBException& ex) { - if (ex.code() == ErrorCodes::DNSHostNotFound) { - return {}; - } - throw; +} catch (const ExceptionFor<ErrorCodes::DNSHostNotFound>&) { + return {}; } } // namespace mongo diff --git a/src/mongo/util/dns_query_windows-impl.h b/src/mongo/util/dns_query_windows-impl.h index f131bd76275..c7eb5e8d29a 100644 --- a/src/mongo/util/dns_query_windows-impl.h +++ b/src/mongo/util/dns_query_windows-impl.h @@ -78,10 +78,11 @@ public: */ std::vector<std::string> txtEntry() const { if (this->_record->wType != DNS_TYPE_TEXT) { - std::ostringstream oss; + StringBuilder oss; oss << "Incorrect record format for \"" << this->_service - << "\": expected TXT record, found something else"; - uasserted(ErrorCodes::DNSProtocolError, oss.str()); + << "\": expected TXT record, found a record of type " << this->_record->wType + << " instead"; + uasserted(ErrorCodes::DNSRecordTypeMismatch, oss.str()); } std::vector<std::string> rv; @@ -97,10 +98,11 @@ public: */ std::string addressEntry() const { if (this->_record->wType != DNS_TYPE_A) { - std::ostringstream oss; + StringBuilder oss; oss << "Incorrect record format for \"" << this->_service - << "\": expected A record, found something else"; - uasserted(ErrorCodes::DNSProtocolError, oss.str()); + << "\": expected A record, found a record of type " << this->_record->wType + << " instead"; + uasserted(ErrorCodes::DNSRecordTypeMismatch, oss.str()); } std::string rv; @@ -121,10 +123,11 @@ public: */ SRVHostEntry srvHostEntry() const { if (this->_record->wType != DNS_TYPE_SRV) { - std::ostringstream oss; + StringBuilder oss; oss << "Incorrect record format for \"" << this->_service - << "\": expected SRV record, found something else"; - uasserted(ErrorCodes::DNSProtocolError, oss.str()); + << "\": expected SRV record, found a record of type " << this->_record->wType + << " instead"; + uasserted(ErrorCodes::DNSRecordTypeMismatch, oss.str()); } const auto& data = this->_record->Data.SRV; |