summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/common.gypi1
-rw-r--r--net/base/dns_util.h2
-rw-r--r--net/base/dnsrr_resolver.cc90
-rw-r--r--net/base/dnsrr_resolver_unittest.cc43
4 files changed, 125 insertions, 11 deletions
diff --git a/build/common.gypi b/build/common.gypi
index 1adb172..768160a 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -1385,6 +1385,7 @@
'VCLinkerTool': {
'AdditionalDependencies': [
'wininet.lib',
+ 'dnsapi.lib',
'version.lib',
'msimg32.lib',
'ws2_32.lib',
diff --git a/net/base/dns_util.h b/net/base/dns_util.h
index 1120140..d86fcb9 100644
--- a/net/base/dns_util.h
+++ b/net/base/dns_util.h
@@ -28,6 +28,8 @@ std::string TrimEndingDot(const std::string& host);
// DNS resource record types. See
// http://www.iana.org/assignments/dns-parameters
+// WARNING: if you're adding any new values here you may need to add them to
+// dnsrr_resolver.cc:DnsRRIsParsedByWindows.
static const uint16 kDNS_CNAME = 5;
static const uint16 kDNS_TXT = 16;
diff --git a/net/base/dnsrr_resolver.cc b/net/base/dnsrr_resolver.cc
index 14b7b93..203ae52 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();
}
diff --git a/net/base/dnsrr_resolver_unittest.cc b/net/base/dnsrr_resolver_unittest.cc
index dfa904a..560052a 100644
--- a/net/base/dnsrr_resolver_unittest.cc
+++ b/net/base/dnsrr_resolver_unittest.cc
@@ -17,8 +17,6 @@ namespace net {
class DnsRRResolverTest : public testing::Test {
};
-#if defined(OS_LINUX)
-
class ExplodingCallback : public CallbackRunner<Tuple1<int> > {
public:
virtual void RunWithParams(const Tuple1<int>& params) {
@@ -26,8 +24,39 @@ class ExplodingCallback : public CallbackRunner<Tuple1<int> > {
}
};
-// This test is disabled because it depends on the external network to pass.
-// However, it may be useful when chaging the code.
+// These tests are disabled because they depend on the external network to
+// pass. However, they may be useful when chaging the code.
+TEST_F(DnsRRResolverTest, DISABLED_ResolveReal) {
+ RRResponse response;
+ TestCompletionCallback callback;
+ DnsRRResolver resolver;
+ DnsRRResolver::Handle handle;
+
+ handle = resolver.Resolve("test.imperialviolet.org", 13172, 0,
+ &callback, &response, 0, BoundNetLog());
+ ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
+ ASSERT_EQ(OK, callback.WaitForResult());
+ ASSERT_EQ(1u, response.rrdatas.size());
+ LOG(ERROR) << "result length " << response.rrdatas[0].size();
+ LOG(ERROR) << "result is " << response.rrdatas[0];
+}
+
+TEST_F(DnsRRResolverTest, DISABLED_ResolveReal2) {
+ RRResponse response;
+ TestCompletionCallback callback;
+ DnsRRResolver resolver;
+ DnsRRResolver::Handle handle;
+
+ handle = resolver.Resolve("google.com", kDNS_TXT, 0,
+ &callback, &response, 0, BoundNetLog());
+ ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle);
+ ASSERT_EQ(OK, callback.WaitForResult());
+ ASSERT_EQ(1u, response.rrdatas.size());
+ LOG(ERROR) << "result length " << response.rrdatas[0].size();
+ LOG(ERROR) << "result is " << response.rrdatas[0];
+}
+
+
TEST_F(DnsRRResolverTest, Resolve) {
RRResponse response;
TestCompletionCallback callback;
@@ -55,7 +84,7 @@ TEST_F(DnsRRResolverTest, Resolve) {
ASSERT_EQ(1u, resolver.cache_hits());
ASSERT_EQ(0u, resolver.inflight_joins());
- // Test that a callback is never made. This depends on there before another
+ // Test that a callback is never made. This depends on there being another
// test after this one which will pump the MessageLoop.
ExplodingCallback callback3;
handle = resolver.Resolve("www.testing.notatld", kDNS_TESTING, 0,
@@ -94,6 +123,7 @@ TEST_F(DnsRRResolverTest, Resolve) {
ASSERT_EQ(1u, resolver.inflight_joins());
}
+#if defined(OS_POSIX)
// This is a DNS packet resulting from querying a recursive resolver for a TXT
// record for agl._pka.imperialviolet.org. You should be able to get a
// replacement from a packet capture should it ever be needed.
@@ -178,7 +208,6 @@ TEST_F(DnsRRResolverTest, FuzzCorruption) {
response.ParseFromResponse(copy, sizeof(copy), kDNS_TXT);
}
}
-
-#endif // OS_LINUX
+#endif
} // namespace net