Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Unified Diff: net/dns/dns_response.cc

Issue 9369045: [net] HostResolverImpl + DnsTransaction + DnsConfigService = Asynchronous DNS ready for experiments. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Denitted. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/dns/dns_response.h ('k') | net/dns/dns_response_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/dns/dns_response.cc
diff --git a/net/dns/dns_response.cc b/net/dns/dns_response.cc
index 760bd5b68064dbc60c6a0f5b14b63e3e9d9b6f71..95180953eb17b3bedab442d170947f2fe16df9e9 100644
--- a/net/dns/dns_response.cc
+++ b/net/dns/dns_response.cc
@@ -4,7 +4,9 @@
#include "net/dns/dns_response.h"
+#include "base/string_util.h"
#include "base/sys_byteorder.h"
+#include "net/base/address_list.h"
#include "net/base/big_endian.h"
#include "net/base/dns_util.h"
#include "net/base/io_buffer.h"
@@ -32,7 +34,8 @@ DnsRecordParser::DnsRecordParser(const void* packet,
DCHECK_LE(offset, length);
}
-int DnsRecordParser::ParseName(const void* const vpos, std::string* out) const {
+unsigned DnsRecordParser::ReadName(const void* const vpos,
+ std::string* out) const {
const char* const pos = reinterpret_cast<const char*>(vpos);
DCHECK(packet_);
DCHECK_LE(packet_, pos);
@@ -41,9 +44,9 @@ int DnsRecordParser::ParseName(const void* const vpos, std::string* out) const {
const char* p = pos;
const char* end = packet_ + length_;
// Count number of seen bytes to detect loops.
- size_t seen = 0;
+ unsigned seen = 0;
// Remember how many bytes were consumed before first jump.
- size_t consumed = 0;
+ unsigned consumed = 0;
if (pos >= end)
return 0;
@@ -54,7 +57,7 @@ int DnsRecordParser::ParseName(const void* const vpos, std::string* out) const {
}
for (;;) {
- // The two couple of bits of the length give the type of the length. It's
+ // The first two bits of the length give the type of the length. It's
// either a direct length or a pointer to the remainder of the name.
switch (*p & dns_protocol::kLabelMask) {
case dns_protocol::kLabelPointer: {
@@ -105,9 +108,9 @@ int DnsRecordParser::ParseName(const void* const vpos, std::string* out) const {
}
}
-bool DnsRecordParser::ParseRecord(DnsResourceRecord* out) {
+bool DnsRecordParser::ReadRecord(DnsResourceRecord* out) {
DCHECK(packet_);
- size_t consumed = ParseName(cur_, &out->name);
+ size_t consumed = ReadName(cur_, &out->name);
if (!consumed)
return false;
BigEndianReader reader(cur_ + consumed,
@@ -182,7 +185,7 @@ uint8 DnsResponse::rcode() const {
return ntohs(header()->flags) & dns_protocol::kRcodeMask;
}
-int DnsResponse::answer_count() const {
+unsigned DnsResponse::answer_count() const {
DCHECK(parser_.IsValid());
return ntohs(header()->ancount);
}
@@ -220,4 +223,71 @@ const dns_protocol::Header* DnsResponse::header() const {
return reinterpret_cast<const dns_protocol::Header*>(io_buffer_->data());
}
+DnsResponse::Result DnsResponse::ParseToAddressList(
+ AddressList* addr_list,
+ base::TimeDelta* ttl) const {
+ DCHECK(IsValid());
+ // DnsTransaction already verified that |response| matches the issued query.
+ // We still need to determine if there is a valid chain of CNAMEs from the
+ // query name to the RR owner name.
+ // We err on the side of caution with the assumption that if we are too picky,
+ // we can always fall back to the system getaddrinfo.
+
+ // Expected owner of record. No trailing dot.
+ std::string expected_name = GetDottedName();
+
+ uint16 expected_type = qtype();
+ DCHECK(expected_type == dns_protocol::kTypeA ||
+ expected_type == dns_protocol::kTypeAAAA);
+
+ size_t expected_size = (expected_type == dns_protocol::kTypeAAAA)
+ ? kIPv6AddressSize : kIPv4AddressSize;
+
+ uint32 cname_ttl_sec = kuint32max;
+ uint32 addr_ttl_sec = kuint32max;
+ IPAddressList ip_addresses;
+ DnsRecordParser parser = Parser();
+ DnsResourceRecord record;
+ unsigned ancount = answer_count();
+ for (unsigned i = 0; i < ancount; ++i) {
+ if (!parser.ReadRecord(&record))
+ return DNS_MALFORMED_RESPONSE;
+
+ if (base::strcasecmp(record.name.c_str(), expected_name.c_str()) != 0)
+ return DNS_NAME_MISMATCH;
+ if (record.type == dns_protocol::kTypeCNAME) {
+ // Following the CNAME chain, only if no addresses seen.
+ if (!ip_addresses.empty())
+ return DNS_CNAME_AFTER_ADDRESS;
+
+ if (record.rdata.size() !=
+ parser.ReadName(record.rdata.begin(), &expected_name))
+ return DNS_MALFORMED_CNAME;
+
+ cname_ttl_sec = std::min(cname_ttl_sec, record.ttl);
+ } else if (record.type == expected_type) {
+ if (record.rdata.size() != expected_size)
+ return DNS_SIZE_MISMATCH;
+ if (ip_addresses.empty()) {
+ addr_ttl_sec = record.ttl;
+ } else {
+ if (addr_ttl_sec != record.ttl)
+ return DNS_ADDRESS_TTL_MISMATCH;
+ }
+ ip_addresses.push_back(IPAddressNumber(record.rdata.begin(),
+ record.rdata.end()));
+ }
+ }
+
+ if (ip_addresses.empty())
+ return DNS_NO_ADDRESSES;
+
+ // getcanonname in eglibc returns the first owner name of an A or AAAA RR.
+ // If the response passed all the checks so far, then |expected_name| is it.
+ *addr_list = AddressList::CreateFromIPAddressList(ip_addresses,
+ expected_name);
+ *ttl = base::TimeDelta::FromSeconds(std::min(cname_ttl_sec, addr_ttl_sec));
+ return DNS_SUCCESS;
+}
+
} // namespace net
« no previous file with comments | « net/dns/dns_response.h ('k') | net/dns/dns_response_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698