Index: net/base/dnsrr_resolver.cc |
diff --git a/net/base/dnsrr_resolver.cc b/net/base/dnsrr_resolver.cc |
index 14b7b93ce9075314af82d6eddfd3456caebbddab..203ae523c556fc3a898b4fed866db9acc6cb4917 100644 |
--- a/net/base/dnsrr_resolver.cc |
+++ b/net/base/dnsrr_resolver.cc |
@@ -8,6 +8,10 @@ |
#include <resolv.h> |
#endif |
+#if defined(OS_WIN) |
+#include <windns.h> |
+#endif |
+ |
#include "base/lock.h" |
#include "base/message_loop.h" |
#include "base/scoped_ptr.h" |
@@ -70,10 +74,30 @@ |
// |
// Post |
- |
- |
namespace net { |
+#if defined(OS_WIN) |
+// DnsRRIsParsedByWindows returns true if Windows knows how to parse the given |
+// RR type. RR data is returned in a DNS_RECORD structure which may be raw (if |
+// Windows doesn't parse it) or may be a parse result. It's unclear how this |
+// API is intended to evolve in the future. If Windows adds support for new RR |
+// types in a future version a client which expected raw data will break. |
+// See http://msdn.microsoft.com/en-us/library/ms682082(v=vs.85).aspx |
+static bool DnsRRIsParsedByWindows(uint16 rrtype) { |
+ // We only cover the types which are defined in dns_util.h |
+ switch (rrtype) { |
+ case kDNS_CNAME: |
+ case kDNS_TXT: |
+ case kDNS_DS: |
+ case kDNS_RRSIG: |
+ case kDNS_DNSKEY: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+#endif |
+ |
static const uint16 kClassIN = 1; |
// kMaxCacheEntries is the number of RRResponse objects that we'll cache. |
static const unsigned kMaxCacheEntries = 32; |
@@ -233,9 +257,67 @@ class RRResolverWorker { |
return; |
} |
+ // See http://msdn.microsoft.com/en-us/library/ms682016(v=vs.85).aspx |
+ PDNS_RECORD record = NULL; |
+ DNS_STATUS status = |
+ DnsQuery_A(name_.c_str(), rrtype_, DNS_QUERY_STANDARD, |
+ NULL /* pExtra (reserved) */, &record, NULL /* pReserved */); |
response_.fetch_time = base::Time::Now(); |
- response_.negative = true; |
- result_ = ERR_NAME_NOT_RESOLVED; |
+ response_.name = name_; |
+ response_.dnssec = false; |
+ response_.ttl = 0; |
+ |
+ if (status != 0) { |
+ response_.negative = true; |
+ result_ = ERR_NAME_NOT_RESOLVED; |
+ } else { |
+ response_.negative = false; |
+ result_ = OK; |
+ for (DNS_RECORD* cur = record; cur; cur = cur->pNext) { |
+ if (cur->wType == rrtype_) { |
+ response_.ttl = record->dwTtl; |
+ // Windows will parse some types of resource records. If we want one |
+ // of these types then we have to reserialise the record. |
+ switch (rrtype_) { |
+ case kDNS_TXT: { |
+ // http://msdn.microsoft.com/en-us/library/ms682109(v=vs.85).aspx |
+ const DNS_TXT_DATA* txt = &cur->Data.TXT; |
+ std::string rrdata; |
+ |
+ for (DWORD i = 0; i < txt->dwStringCount; i++) { |
+ // Although the string is typed as a PWSTR, it's actually just |
+ // an ASCII byte-string. Also, the string must be < 256 |
+ // elements because the length in the DNS packet is a single |
+ // byte. |
+ const char* s = reinterpret_cast<char*>(txt->pStringArray[i]); |
+ size_t len = strlen(s); |
+ DCHECK_LT(len, 256u); |
+ char len8 = static_cast<char>(len); |
+ rrdata.push_back(len8); |
+ rrdata += s; |
+ } |
+ response_.rrdatas.push_back(rrdata); |
+ break; |
+ } |
+ default: |
+ if (DnsRRIsParsedByWindows(rrtype_)) { |
+ // Windows parses this type, but we don't have code to unparse |
+ // it. |
+ NOTREACHED() << "you need to add code for the RR type here"; |
+ response_.negative = true; |
+ result_ = ERR_INVALID_ARGUMENT; |
+ } else { |
+ // This type is given to us raw. |
+ response_.rrdatas.push_back( |
+ std::string(reinterpret_cast<char*>(&cur->Data), |
+ cur->wDataLength)); |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
+ DnsRecordListFree(record, DnsFreeRecordList); |
Finish(); |
} |