diff options
author | agayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-03 21:26:49 +0000 |
---|---|---|
committer | agayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-03 21:26:49 +0000 |
commit | b5810641da6e56bc416deded72ba939b37c23922 (patch) | |
tree | a3f40b472e41552a0408b78ebef6cd4e5e779a59 /net | |
parent | 74b962aa204b487dabcdb2fb9e7c7c7c62db1c5f (diff) | |
download | chromium_src-b5810641da6e56bc416deded72ba939b37c23922.zip chromium_src-b5810641da6e56bc416deded72ba939b37c23922.tar.gz chromium_src-b5810641da6e56bc416deded72ba939b37c23922.tar.bz2 |
Implements DnsRequest and DnsResponse classes.
BUG=60149
TEST=net_unittests --gtest_filter="DnsQuery*:DnsResponse*"
Review URL: http://codereview.chromium.org/7065062
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87868 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/dns_query.cc | 111 | ||||
-rw-r--r-- | net/base/dns_query.h | 72 | ||||
-rw-r--r-- | net/base/dns_query_unittest.cc | 109 | ||||
-rw-r--r-- | net/base/dns_response.cc | 106 | ||||
-rw-r--r-- | net/base/dns_response.h | 48 | ||||
-rw-r--r-- | net/base/dns_response_unittest.cc | 152 | ||||
-rw-r--r-- | net/base/dns_util.h | 6 | ||||
-rw-r--r-- | net/base/dnsrr_resolver.cc | 1 | ||||
-rw-r--r-- | net/base/net_error_list.h | 17 | ||||
-rw-r--r-- | net/net.gyp | 6 |
10 files changed, 626 insertions, 2 deletions
diff --git a/net/base/dns_query.cc b/net/base/dns_query.cc new file mode 100644 index 0000000..ba79150 --- /dev/null +++ b/net/base/dns_query.cc @@ -0,0 +1,111 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/dns_query.h" + +#include <string> + +#include "base/rand_util.h" +#include "net/base/address_family.h" +#include "net/base/dns_util.h" + +namespace net { + +namespace { + +void PackUint16BE(char buf[2], uint16 v) { + buf[0] = v >> 8; + buf[1] = v & 0xff; +} + +uint16 QTypeFromAddressFamily(AddressFamily address_family) { + switch (address_family) { + case ADDRESS_FAMILY_IPV4: + return kDNS_A; + case ADDRESS_FAMILY_IPV6: + return kDNS_AAAA; + default: + NOTREACHED() << "Bad address family"; + return kDNS_A; + } +} + +} // namespace + +// DNS query consists of a 12-byte header followed by a question section. +// For details, see RFC 1035 section 4.1.1. This header template sets RD +// bit, which directs the name server to pursue query recursively, and sets +// the QDCOUNT to 1, meaning the question section has a single entry. The +// first two bytes of the header form a 16-bit random query ID to be copied +// in the corresponding reply by the name server -- randomized during +// DnsQuery construction. +static const char kHeader[] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const size_t kHeaderLen = arraysize(kHeader); + +DnsQuery::DnsQuery(const std::string& hostname, + AddressFamily address_family, + int port) + : port_(port), + id_(0), + qtype_(QTypeFromAddressFamily(address_family)), + hostname_(hostname) { + std::string qname; + if (!net::DNSDomainFromDot(hostname, &qname)) + return; + + size_t query_size = kHeaderLen + qname.size() + + sizeof(qtype_) + sizeof(kClassIN); + + io_buffer_ = new IOBufferWithSize(query_size); + + int byte_offset = 0; + char* buffer_head = io_buffer_->data(); + memcpy(&buffer_head[byte_offset], kHeader, kHeaderLen); + byte_offset += kHeaderLen; + memcpy(&buffer_head[byte_offset], &qname[0], qname.size()); + byte_offset += qname.size(); + PackUint16BE(&buffer_head[byte_offset], qtype_); + byte_offset += sizeof(qtype_); + PackUint16BE(&buffer_head[byte_offset], kClassIN); + + // Randomize ID, first two bytes. + id_ = base::RandUint64() & 0xffff; + PackUint16BE(&buffer_head[0], id_); +} + +DnsQuery::~DnsQuery() { +} + +int DnsQuery::port() const { + DCHECK(IsValid()); + return port_; +} + +uint16 DnsQuery::id() const { + DCHECK(IsValid()); + return id_; +} + +uint16 DnsQuery::qtype() const { + DCHECK(IsValid()); + return qtype_; +} + +AddressFamily DnsQuery::address_family() const { + DCHECK(IsValid()); + return address_family_; +} + +const std::string& DnsQuery::hostname() const { + DCHECK(IsValid()); + return hostname_; +} + +IOBufferWithSize* DnsQuery::io_buffer() const { + DCHECK(IsValid()); + return io_buffer_.get(); +} + +} // namespace net diff --git a/net/base/dns_query.h b/net/base/dns_query.h new file mode 100644 index 0000000..bc25997 --- /dev/null +++ b/net/base/dns_query.h @@ -0,0 +1,72 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_DNS_QUERY_H_ +#define NET_BASE_DNS_QUERY_H_ +#pragma once + +#include <string> + +#include "net/base/address_family.h" +#include "net/base/io_buffer.h" +#include "net/base/net_util.h" + +namespace net{ + +// A class that encapsulates bits and pieces related to DNS request processing. +class DnsQuery { + public: + // Constructs an object containing an IOBuffer with raw DNS query string + // for |hostname| with the given |address_family|; |port| is here due to + // legacy -- getaddrinfo() takes service name, which is mapped to some + // port and returns sockaddr_in structures with ports filled in, so do we + // -- look at DnsResponse::Parse() to see where it is used. + + // Every generated object has a random ID, hence two objects generated + // with the same set of constructor arguments are generally not equal; + // there is a 1/2^16 chance of them being equal due to size of |id_|. + DnsQuery(const std::string& hostname, AddressFamily address_family, int port); + ~DnsQuery(); + + // Returns true if the constructed object was valid. + bool IsValid() const { return io_buffer_.get() != NULL; } + + // DnsQuery field accessors. These should only be called on an object + // for whom |IsValid| is true. + int port() const; + uint16 id() const; + uint16 qtype() const; + AddressFamily address_family() const; + const std::string& hostname() const; + + // IOBuffer accessor to be used for writing out the query. + IOBufferWithSize* io_buffer() const; + + private: + // Port to be used by corresponding DnsResponse when filling sockaddr_ins + // to be returned. + int port_; + + // ID of the query. + uint16 id_; + + // Type of query, currently, either A or AAAA. + uint16 qtype_; + + // Address family of the query; used when constructing new object from + // this one. + AddressFamily address_family_; + + // Hostname that we are trying to resolve. + std::string hostname_; + + // Contains query bytes to be consumed by higher level Write() call. + scoped_refptr<IOBufferWithSize> io_buffer_; + + DISALLOW_COPY_AND_ASSIGN(DnsQuery); +}; + +} // namespace net + +#endif // NET_BASE_DNS_QUERY_H_ diff --git a/net/base/dns_query_unittest.cc b/net/base/dns_query_unittest.cc new file mode 100644 index 0000000..ba21c4e --- /dev/null +++ b/net/base/dns_query_unittest.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/dns_query.h" +#include "net/base/dns_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +// DNS query consists of a header followed by a question. Header format +// and question format are described below. For the meaning of specific +// fields, please see RFC 1035. + +// Header format. +// 1 1 1 1 1 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | ID | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | QDCOUNT | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | ANCOUNT | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | NSCOUNT | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | ARCOUNT | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +// Question format. +// 1 1 1 1 1 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | | +// / QNAME / +// / / +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | QTYPE | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | QCLASS | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +TEST(DnsQueryTest, RandomIdTest) { + const std::string kHostname = "www.google.com"; + const uint16 kPort = 80; + + DnsQuery q1(kHostname, ADDRESS_FAMILY_IPV4, kPort); + EXPECT_TRUE(q1.IsValid()); + EXPECT_EQ(kPort, q1.port()); + EXPECT_EQ(kDNS_A, q1.qtype()); + EXPECT_EQ(kHostname, q1.hostname()); + + DnsQuery q2(kHostname, ADDRESS_FAMILY_IPV4, kPort); + EXPECT_TRUE(q2.IsValid()); + EXPECT_EQ(kPort, q2.port()); + EXPECT_EQ(kDNS_A, q2.qtype()); + EXPECT_EQ(kHostname, q2.hostname()); + + // This has a 1/2^16 probability of failure. + EXPECT_FALSE(q1.id() == q2.id()); +} + +TEST(DnsQueryTest, ConstructorTest) { + const std::string kHostname = "www.google.com"; + const uint16 kPort = 80; + + DnsQuery q1(kHostname, ADDRESS_FAMILY_IPV4, kPort); + EXPECT_TRUE(q1.IsValid()); + EXPECT_EQ(kPort, q1.port()); + EXPECT_EQ(kDNS_A, q1.qtype()); + EXPECT_EQ(kHostname, q1.hostname()); + + uint8 id_hi = q1.id() >> 8, id_lo = q1.id() & 0xff; + + // See the top of the file for the description of a DNS query. + const uint8 query_data[] = { + // Header + id_hi, id_lo, + 0x01, 0x00, // Flags -- set RD (recursion desired) bit. + 0x00, 0x01, // Set QDCOUNT (question count) to 1, all the + // rest are 0 for a query. + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + + // Question + 0x03, 0x77, 0x77, 0x77, // QNAME: www.google.com in DNS format. + 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x03, 0x63, 0x6f, 0x6d, 0x00, + + 0x00, 0x01, // QTYPE: A query. + 0x00, 0x01, // QCLASS: IN class. + }; + + int expected_size = arraysize(query_data); + EXPECT_EQ(expected_size, q1.io_buffer()->size()); + EXPECT_EQ(0, memcmp(q1.io_buffer()->data(), query_data, + q1.io_buffer()->size())); + + // Query with a long hostname. + const char hostname_too_long[] = "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.1234"; + + DnsQuery q2(hostname_too_long, ADDRESS_FAMILY_IPV4, kPort); + EXPECT_FALSE(q2.IsValid()); +} + +} // namespace net diff --git a/net/base/dns_response.cc b/net/base/dns_response.cc new file mode 100644 index 0000000..9cfbae2 --- /dev/null +++ b/net/base/dns_response.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/dns_response.h" + +#include "net/base/address_list.h" +#include "net/base/dns_util.h" +#include "net/base/net_errors.h" + +namespace net { + +// RFC 1035, section 4.2.1: Messages carried by UDP are restricted to 512 +// bytes (not counting the IP nor UDP headers). +static const int kMaxResponseSize = 512; + +DnsResponse::DnsResponse(DnsQuery* query) + : query_(query), + io_buffer_(new IOBufferWithSize(kMaxResponseSize + 1)) { + DCHECK(query_); + DCHECK(query_->IsValid()); +} + +DnsResponse::~DnsResponse() { +} + +int DnsResponse::Parse(int nbytes, AddressList* results) { + DCHECK(query_->IsValid()); + + // Response includes query, it should be at least that size. + if (nbytes < query_->io_buffer()->size() || nbytes > kMaxResponseSize) + return ERR_DNS_MALFORMED_RESPONSE; + + DnsResponseBuffer response(reinterpret_cast<uint8*>(io_buffer_->data()), + io_buffer_->size()); + uint16 id; + if (!response.U16(&id) || id != query_->id()) // Make sure IDs match. + return ERR_DNS_MALFORMED_RESPONSE; + + uint8 flags, rcode; + if (!response.U8(&flags) || !response.U8(&rcode)) + return ERR_DNS_MALFORMED_RESPONSE; + + if (flags & 2) // TC is set -- server wants TCP, we don't support it (yet?). + return ERR_DNS_SERVER_REQUIRES_TCP; + + rcode &= 0x0f; // 3 means NXDOMAIN, the rest means server failed. + if (rcode && (rcode != 3)) + return ERR_DNS_SERVER_FAILED; + + uint16 query_count, answer_count, authority_count, additional_count; + if (!response.U16(&query_count) || + !response.U16(&answer_count) || + !response.U16(&authority_count) || + !response.U16(&additional_count)) { + return ERR_DNS_MALFORMED_RESPONSE; + } + + if (query_count != 1) // Sent a single question, shouldn't have changed. + return ERR_DNS_MALFORMED_RESPONSE; + + std::string hostname; + uint16 qtype, qclass; + if (!response.DNSName(&hostname) || + !response.U16(&qtype) || + !response.U16(&qclass) || + hostname != query_->hostname() || // Make sure Question section + qtype != query_->qtype() || // echoed back. + qclass != kClassIN) { + return ERR_DNS_MALFORMED_RESPONSE; + } + + if (answer_count < 1) + return ERR_NAME_NOT_RESOLVED; + + std::vector<IPAddressNumber> rdatas; + while (answer_count--) { + uint32 ttl; + uint16 rdlength; + if (!response.DNSName(NULL) || + !response.U16(&qtype) || + !response.U16(&qclass) || + !response.U32(&ttl) || + !response.U16(&rdlength)) { + return ERR_DNS_MALFORMED_RESPONSE; + } + + if (qtype == query_->qtype() && + qclass == kClassIN && + (rdlength == kIPv4AddressSize || rdlength == kIPv6AddressSize)) { + base::StringPiece rdata; + if (!response.Block(&rdata, rdlength)) + return ERR_DNS_MALFORMED_RESPONSE; + rdatas.push_back(IPAddressNumber(rdata.begin(), rdata.end())); + } else if (!response.Skip(rdlength)) + return ERR_DNS_MALFORMED_RESPONSE; + } + + if (rdatas.empty()) + return ERR_NAME_NOT_RESOLVED; + + *results = AddressList::CreateFromIPAddressList(rdatas, query_->port()); + return OK; +} + +} // namespace net diff --git a/net/base/dns_response.h b/net/base/dns_response.h new file mode 100644 index 0000000..39ee47d --- /dev/null +++ b/net/base/dns_response.h @@ -0,0 +1,48 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_DNS_RESPONSE_H_ +#define NET_BASE_DNS_RESPONSE_H_ +#pragma once + +#include "net/base/dns_query.h" + +namespace net{ + +class AddressList; + +// A class that encapsulates bits and pieces related to DNS response +// processing. +class DnsResponse { + public: + // Constructs an object with an IOBuffer large enough to read + // one byte more than largest possible response, to detect malformed + // responses; |query| is a pointer to the DnsQuery for which |this| + // is supposed to be a response. + explicit DnsResponse(DnsQuery* query); + ~DnsResponse(); + + // Internal buffer accessor into which actual bytes of response will be + // read. + IOBufferWithSize* io_buffer() { return io_buffer_.get(); } + + // Parses response of size nbytes and puts address into |results|, + // returns net_error code in case of failure. + int Parse(int nbytes, AddressList* results); + + private: + // The matching query; |this| is the response for |query_|. We do not + // own it, lifetime of |this| should be within the limits of lifetime of + // |query_|. + const DnsQuery* const query_; + + // Buffer into which response bytes are read. + scoped_refptr<IOBufferWithSize> io_buffer_; + + DISALLOW_COPY_AND_ASSIGN(DnsResponse); +}; + +} // namespace net + +#endif // NET_BASE_DNS_RESPONSE_H_ diff --git a/net/base/dns_response_unittest.cc b/net/base/dns_response_unittest.cc new file mode 100644 index 0000000..df56d2f --- /dev/null +++ b/net/base/dns_response_unittest.cc @@ -0,0 +1,152 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/address_list.h" +#include "net/base/dns_response.h" +#include "net/base/net_errors.h" +#include "net/base/sys_addrinfo.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +// DNS response consists of a header followed by a question followed by +// answer. Header format, question format and response format are +// described below. For the meaning of specific fields, please see RFC +// 1035. + +// Header format. +// 1 1 1 1 1 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | ID | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | QDCOUNT | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | ANCOUNT | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | NSCOUNT | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | ARCOUNT | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +// Question format. +// 1 1 1 1 1 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | | +// / QNAME / +// / / +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | QTYPE | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | QCLASS | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +// Answser format. +// 1 1 1 1 1 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | | +// / / +// / NAME / +// | | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | TYPE | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | CLASS | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | TTL | +// | | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +// | RDLENGTH | +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| +// / RDATA / +// / / +// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +TEST(DnsResponseTest, ResponseWithCnameA) { + const std::string kHostname = "codereview.chromium.org"; + const uint16 kPort = 80; + + DnsQuery q1(kHostname, ADDRESS_FAMILY_IPV4, kPort); + uint8 id_hi = q1.id() >> 8, id_lo = q1.id() & 0xff; + + uint8 ip[] = { // codereview.chromium.org resolves to + 0x4a, 0x7d, 0x5f, 0x79 // 74.125.95.121 + }; + + uint8 response_data[] = { + // Header + id_hi, id_lo, // ID + 0x81, 0x80, // Standard query response, no error + 0x00, 0x01, // 1 question + 0x00, 0x02, // 2 RRs (answers) + 0x00, 0x00, // 0 authority RRs + 0x00, 0x00, // 0 additional RRs + + // Question + 0x0a, 0x63, 0x6f, 0x64, // This part is echoed back from the + 0x65, 0x72, 0x65, 0x76, // respective query. + 0x69, 0x65, 0x77, 0x08, + 0x63, 0x68, 0x72, 0x6f, + 0x6d, 0x69, 0x75, 0x6d, + 0x03, 0x6f, 0x72, 0x67, + 0x00, + 0x00, 0x01, + 0x00, 0x01, + + // Answer 1 + 0xc0, 0x0c, // NAME is a pointer to name in Question section. + 0x00, 0x05, // TYPE is CNAME. + 0x00, 0x01, // CLASS is IN. + 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. + 0x24, 0x74, + 0x00, 0x12, // RDLENGTH is 18 bytse. + 0x03, 0x67, 0x68, 0x73, // ghs.l.google.com in DNS format. + 0x01, 0x6c, 0x06, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x03, 0x63, 0x6f, + 0x6d, 0x00, + + // Answer 2 + 0xc0, 0x35, // NAME is a pointer to name in Question section. + 0x00, 0x01, // TYPE is A. + 0x00, 0x01, // CLASS is IN. + 0x00, 0x00, // TTL (4 bytes) is 53 seconds. + 0x00, 0x35, + 0x00, 0x04, // RDLENGTH is 4 bytes. + ip[0], ip[1], ip[2], ip[3], // RDATA is the IP. + }; + + // Create a response object and simulate reading into it. + DnsResponse r1(&q1); + memcpy(r1.io_buffer()->data(), &response_data[0], + r1.io_buffer()->size()); + + int response_size = arraysize(response_data); + AddressList address_list; + EXPECT_EQ(OK, r1.Parse(response_size, &address_list)); + + // Verify AddressList content. + size_t sockaddr_size = sizeof(struct sockaddr_in); + const struct addrinfo* ai = address_list.head(); + EXPECT_EQ(kPort, address_list.GetPort()); + + // addrinfo part. + EXPECT_TRUE(ai != NULL); + EXPECT_EQ(AF_INET, ai->ai_family); + EXPECT_EQ(SOCK_STREAM, ai->ai_socktype); + EXPECT_EQ(sockaddr_size, ai->ai_addrlen); + + // sockaddr_in part. + struct sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(ai->ai_addr); + ASSERT_TRUE(sa != NULL); + EXPECT_EQ(AF_INET, sa->sin_family); + EXPECT_EQ(kPort, ntohs(sa->sin_port)); + EXPECT_EQ(0, memcmp(&sa->sin_addr, &ip[0], kIPv4AddressSize)); +} + +} // namespace net diff --git a/net/base/dns_util.h b/net/base/dns_util.h index 6c940c1..939a4a7 100644 --- a/net/base/dns_util.h +++ b/net/base/dns_util.h @@ -31,13 +31,17 @@ NET_TEST bool IsSTD3ASCIIValidCharacter(char c); // Returns the hostname by trimming the ending dot, if one exists. NET_API std::string TrimEndingDot(const std::string& host); +// DNS class types. +static const uint16 kClassIN = 1; + // 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_A = 1; static const uint16 kDNS_CNAME = 5; static const uint16 kDNS_TXT = 16; +static const uint16 kDNS_AAAA = 28; static const uint16 kDNS_CERT = 37; static const uint16 kDNS_DS = 43; static const uint16 kDNS_RRSIG = 46; diff --git a/net/base/dnsrr_resolver.cc b/net/base/dnsrr_resolver.cc index 454a9fe..81f9111 100644 --- a/net/base/dnsrr_resolver.cc +++ b/net/base/dnsrr_resolver.cc @@ -98,7 +98,6 @@ static bool DnsRRIsParsedByWindows(uint16 rrtype) { } #endif -static const uint16 kClassIN = 1; // kMaxCacheEntries is the number of RRResponse objects that we'll cache. static const unsigned kMaxCacheEntries = 32; // kNegativeTTLSecs is the number of seconds for which we'll cache a negative diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index 19e5da0..9edc9ce 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -231,6 +231,23 @@ NET_ERROR(SSL_CLIENT_AUTH_SIGNATURE_FAILED, -141) // which exceeds size threshold). NET_ERROR(MSG_TOO_BIG, -142) +// DNS resolver received a malformed response. +NET_ERROR(DNS_MALFORMED_RESPONSE, -143) + +// DNS server requires TCP +NET_ERROR(DNS_SERVER_REQUIRES_TCP, -144) + +// DNS server failed. This error is returned for all of the following +// error conditions: +// 1 - Format error - The name server was unable to interpret the query. +// 2 - Server failure - The name server was unable to process this query +// due to a problem with the name server. +// 4 - Not Implemented - The name server does not support the requested +// kind of query. +// 5 - Refused - The name server refuses to perform the specified +// operation for policy reasons. +NET_ERROR(DNS_SERVER_FAILED, -145) + // Certificate error codes // // The values of certificate error codes must be consecutive. diff --git a/net/net.gyp b/net/net.gyp index 28173e4..b73eead 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -69,6 +69,10 @@ 'base/data_url.h', 'base/directory_lister.cc', 'base/directory_lister.h', + 'base/dns_query.cc', + 'base/dns_query.h', + 'base/dns_response.cc', + 'base/dns_response.h', 'base/dns_reload_timer.cc', 'base/dns_reload_timer.h', 'base/dnssec_chain_verifier.cc', @@ -839,6 +843,8 @@ 'base/crl_filter_unittest.cc', 'base/data_url_unittest.cc', 'base/directory_lister_unittest.cc', + 'base/dns_query_unittest.cc', + 'base/dns_response_unittest.cc', 'base/dnssec_unittest.cc', 'base/dns_util_unittest.cc', 'base/dnsrr_resolver_unittest.cc', |