Index: net/dns/dns_response.cc |
diff --git a/net/dns/dns_response.cc b/net/dns/dns_response.cc |
index 760bd5b68064dbc60c6a0f5b14b63e3e9d9b6f71..0df83c4b88eafad6bfef2e119e5fac050da0f045 100644 |
--- a/net/dns/dns_response.cc |
+++ b/net/dns/dns_response.cc |
@@ -5,6 +5,7 @@ |
#include "net/dns/dns_response.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" |
@@ -220,4 +221,51 @@ const dns_protocol::Header* DnsResponse::header() const { |
return reinterpret_cast<const dns_protocol::Header*>(io_buffer_->data()); |
} |
+bool DnsResponseToAddressList(const DnsResponse* response, |
+ AddressList* addr_list, |
+ base::TimeDelta* ttl) { |
+ DCHECK(response->IsValid()); |
+ // DnsTransaction already verified that |response| matches the issued query |
+ // in terms of query header. We still need to determine if there is a valid |
+ // chain of CNAMEs from the query name to the RR owner name. |
+ |
+ // Expected owner of record. |
+ std::string expected_name = response->GetDottedName(); |
+ |
+ // getcanonname in eglibc returns the first owner name of an A or AAAA RR. |
+ std::string canon_name; |
+ |
+ uint32 ttl_sec = kuint32max; |
+ IPAddressList ip_addresses; |
+ DnsRecordParser parser = response->Parser(); |
+ DnsResourceRecord record; |
+ while (parser.ParseRecord(&record)) { |
+ if (record.name != expected_name) { |
+ // We ignore records owned by unexpected name. |
+ continue; |
+ } |
+ if (record.type == dns_protocol::kTypeCNAME) { |
+ // New |hostname|, following the CNAME chain. |
+ if (!parser.ParseName(record.rdata.begin(), &expected_name)) { |
+ return false; |
+ } |
+ } else if (record.type == response->qtype() && |
+ (record.rdata.size() == kIPv4AddressSize || |
+ record.rdata.size() == kIPv6AddressSize)) { |
+ ip_addresses.push_back(IPAddressNumber(record.rdata.begin(), |
+ record.rdata.end())); |
+ ttl_sec = std::min(ttl_sec, record.ttl); |
+ if (canon_name.empty()) |
+ canon_name = record.name; |
+ } |
+ } |
+ if (ip_addresses.empty()) |
+ return false; |
+ |
+ *addr_list = AddressList::CreateFromIPAddressList(ip_addresses, |
+ canon_name); |
+ *ttl = base::TimeDelta::FromSeconds(ttl_sec); |
+ return true; |
+} |
+ |
} // namespace net |