Home | History | Annotate | Download | only in dns
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/dns/dns_response.h"
      6 
      7 #include "base/time/time.h"
      8 #include "net/base/address_list.h"
      9 #include "net/base/io_buffer.h"
     10 #include "net/base/net_util.h"
     11 #include "net/dns/dns_protocol.h"
     12 #include "net/dns/dns_query.h"
     13 #include "net/dns/dns_test_util.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace net {
     17 
     18 namespace {
     19 
     20 TEST(DnsRecordParserTest, Constructor) {
     21   const char data[] = { 0 };
     22 
     23   EXPECT_FALSE(DnsRecordParser().IsValid());
     24   EXPECT_TRUE(DnsRecordParser(data, 1, 0).IsValid());
     25   EXPECT_TRUE(DnsRecordParser(data, 1, 1).IsValid());
     26 
     27   EXPECT_FALSE(DnsRecordParser(data, 1, 0).AtEnd());
     28   EXPECT_TRUE(DnsRecordParser(data, 1, 1).AtEnd());
     29 }
     30 
     31 TEST(DnsRecordParserTest, ReadName) {
     32   const uint8 data[] = {
     33       // all labels "foo.example.com"
     34       0x03, 'f', 'o', 'o',
     35       0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
     36       0x03, 'c', 'o', 'm',
     37       // byte 0x10
     38       0x00,
     39       // byte 0x11
     40       // part label, part pointer, "bar.example.com"
     41       0x03, 'b', 'a', 'r',
     42       0xc0, 0x04,
     43       // byte 0x17
     44       // all pointer to "bar.example.com", 2 jumps
     45       0xc0, 0x11,
     46       // byte 0x1a
     47   };
     48 
     49   std::string out;
     50   DnsRecordParser parser(data, sizeof(data), 0);
     51   ASSERT_TRUE(parser.IsValid());
     52 
     53   EXPECT_EQ(0x11u, parser.ReadName(data + 0x00, &out));
     54   EXPECT_EQ("foo.example.com", out);
     55   // Check that the last "." is never stored.
     56   out.clear();
     57   EXPECT_EQ(0x1u, parser.ReadName(data + 0x10, &out));
     58   EXPECT_EQ("", out);
     59   out.clear();
     60   EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, &out));
     61   EXPECT_EQ("bar.example.com", out);
     62   out.clear();
     63   EXPECT_EQ(0x2u, parser.ReadName(data + 0x17, &out));
     64   EXPECT_EQ("bar.example.com", out);
     65 
     66   // Parse name without storing it.
     67   EXPECT_EQ(0x11u, parser.ReadName(data + 0x00, NULL));
     68   EXPECT_EQ(0x1u, parser.ReadName(data + 0x10, NULL));
     69   EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, NULL));
     70   EXPECT_EQ(0x2u, parser.ReadName(data + 0x17, NULL));
     71 
     72   // Check that it works even if initial position is different.
     73   parser = DnsRecordParser(data, sizeof(data), 0x12);
     74   EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, NULL));
     75 }
     76 
     77 TEST(DnsRecordParserTest, ReadNameFail) {
     78   const uint8 data[] = {
     79       // label length beyond packet
     80       0x30, 'x', 'x',
     81       0x00,
     82       // pointer offset beyond packet
     83       0xc0, 0x20,
     84       // pointer loop
     85       0xc0, 0x08,
     86       0xc0, 0x06,
     87       // incorrect label type (currently supports only direct and pointer)
     88       0x80, 0x00,
     89       // truncated name (missing root label)
     90       0x02, 'x', 'x',
     91   };
     92 
     93   DnsRecordParser parser(data, sizeof(data), 0);
     94   ASSERT_TRUE(parser.IsValid());
     95 
     96   std::string out;
     97   EXPECT_EQ(0u, parser.ReadName(data + 0x00, &out));
     98   EXPECT_EQ(0u, parser.ReadName(data + 0x04, &out));
     99   EXPECT_EQ(0u, parser.ReadName(data + 0x08, &out));
    100   EXPECT_EQ(0u, parser.ReadName(data + 0x0a, &out));
    101   EXPECT_EQ(0u, parser.ReadName(data + 0x0c, &out));
    102   EXPECT_EQ(0u, parser.ReadName(data + 0x0e, &out));
    103 }
    104 
    105 TEST(DnsRecordParserTest, ReadRecord) {
    106   const uint8 data[] = {
    107       // Type CNAME record.
    108       0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
    109       0x03, 'c', 'o', 'm',
    110       0x00,
    111       0x00, 0x05,              // TYPE is CNAME.
    112       0x00, 0x01,              // CLASS is IN.
    113       0x00, 0x01, 0x24, 0x74,  // TTL is 0x00012474.
    114       0x00, 0x06,              // RDLENGTH is 6 bytes.
    115       0x03, 'f', 'o', 'o',     // compressed name in record
    116       0xc0, 0x00,
    117       // Type A record.
    118       0x03, 'b', 'a', 'r',     // compressed owner name
    119       0xc0, 0x00,
    120       0x00, 0x01,              // TYPE is A.
    121       0x00, 0x01,              // CLASS is IN.
    122       0x00, 0x20, 0x13, 0x55,  // TTL is 0x00201355.
    123       0x00, 0x04,              // RDLENGTH is 4 bytes.
    124       0x7f, 0x02, 0x04, 0x01,  // IP is 127.2.4.1
    125   };
    126 
    127   std::string out;
    128   DnsRecordParser parser(data, sizeof(data), 0);
    129 
    130   DnsResourceRecord record;
    131   EXPECT_TRUE(parser.ReadRecord(&record));
    132   EXPECT_EQ("example.com", record.name);
    133   EXPECT_EQ(dns_protocol::kTypeCNAME, record.type);
    134   EXPECT_EQ(dns_protocol::kClassIN, record.klass);
    135   EXPECT_EQ(0x00012474u, record.ttl);
    136   EXPECT_EQ(6u, record.rdata.length());
    137   EXPECT_EQ(6u, parser.ReadName(record.rdata.data(), &out));
    138   EXPECT_EQ("foo.example.com", out);
    139   EXPECT_FALSE(parser.AtEnd());
    140 
    141   EXPECT_TRUE(parser.ReadRecord(&record));
    142   EXPECT_EQ("bar.example.com", record.name);
    143   EXPECT_EQ(dns_protocol::kTypeA, record.type);
    144   EXPECT_EQ(dns_protocol::kClassIN, record.klass);
    145   EXPECT_EQ(0x00201355u, record.ttl);
    146   EXPECT_EQ(4u, record.rdata.length());
    147   EXPECT_EQ(base::StringPiece("\x7f\x02\x04\x01"), record.rdata);
    148   EXPECT_TRUE(parser.AtEnd());
    149 
    150   // Test truncated record.
    151   parser = DnsRecordParser(data, sizeof(data) - 2, 0);
    152   EXPECT_TRUE(parser.ReadRecord(&record));
    153   EXPECT_FALSE(parser.AtEnd());
    154   EXPECT_FALSE(parser.ReadRecord(&record));
    155 }
    156 
    157 TEST(DnsResponseTest, InitParse) {
    158   // This includes \0 at the end.
    159   const char qname_data[] = "\x0A""codereview""\x08""chromium""\x03""org";
    160   const base::StringPiece qname(qname_data, sizeof(qname_data));
    161   // Compilers want to copy when binding temporary to const &, so must use heap.
    162   scoped_ptr<DnsQuery> query(new DnsQuery(0xcafe, qname, dns_protocol::kTypeA));
    163 
    164   const uint8 response_data[] = {
    165     // Header
    166     0xca, 0xfe,               // ID
    167     0x81, 0x80,               // Standard query response, RA, no error
    168     0x00, 0x01,               // 1 question
    169     0x00, 0x02,               // 2 RRs (answers)
    170     0x00, 0x00,               // 0 authority RRs
    171     0x00, 0x00,               // 0 additional RRs
    172 
    173     // Question
    174     // This part is echoed back from the respective query.
    175     0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
    176     0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
    177     0x03, 'o', 'r', 'g',
    178     0x00,
    179     0x00, 0x01,        // TYPE is A.
    180     0x00, 0x01,        // CLASS is IN.
    181 
    182     // Answer 1
    183     0xc0, 0x0c,        // NAME is a pointer to name in Question section.
    184     0x00, 0x05,        // TYPE is CNAME.
    185     0x00, 0x01,        // CLASS is IN.
    186     0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    187     0x24, 0x74,
    188     0x00, 0x12,        // RDLENGTH is 18 bytes.
    189     // ghs.l.google.com in DNS format.
    190     0x03, 'g', 'h', 's',
    191     0x01, 'l',
    192     0x06, 'g', 'o', 'o', 'g', 'l', 'e',
    193     0x03, 'c', 'o', 'm',
    194     0x00,
    195 
    196     // Answer 2
    197     0xc0, 0x35,         // NAME is a pointer to name in Answer 1.
    198     0x00, 0x01,         // TYPE is A.
    199     0x00, 0x01,         // CLASS is IN.
    200     0x00, 0x00,         // TTL (4 bytes) is 53 seconds.
    201     0x00, 0x35,
    202     0x00, 0x04,         // RDLENGTH is 4 bytes.
    203     0x4a, 0x7d,         // RDATA is the IP: 74.125.95.121
    204     0x5f, 0x79,
    205   };
    206 
    207   DnsResponse resp;
    208   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
    209 
    210   // Reject too short.
    211   EXPECT_FALSE(resp.InitParse(query->io_buffer()->size() - 1, *query));
    212   EXPECT_FALSE(resp.IsValid());
    213 
    214   // Reject wrong id.
    215   scoped_ptr<DnsQuery> other_query(query->CloneWithNewId(0xbeef));
    216   EXPECT_FALSE(resp.InitParse(sizeof(response_data), *other_query));
    217   EXPECT_FALSE(resp.IsValid());
    218 
    219   // Reject wrong question.
    220   scoped_ptr<DnsQuery> wrong_query(
    221       new DnsQuery(0xcafe, qname, dns_protocol::kTypeCNAME));
    222   EXPECT_FALSE(resp.InitParse(sizeof(response_data), *wrong_query));
    223   EXPECT_FALSE(resp.IsValid());
    224 
    225   // Accept matching question.
    226   EXPECT_TRUE(resp.InitParse(sizeof(response_data), *query));
    227   EXPECT_TRUE(resp.IsValid());
    228 
    229   // Check header access.
    230   EXPECT_EQ(0x8180, resp.flags());
    231   EXPECT_EQ(0x0, resp.rcode());
    232   EXPECT_EQ(2u, resp.answer_count());
    233 
    234   // Check question access.
    235   EXPECT_EQ(query->qname(), resp.qname());
    236   EXPECT_EQ(query->qtype(), resp.qtype());
    237   EXPECT_EQ("codereview.chromium.org", resp.GetDottedName());
    238 
    239   DnsResourceRecord record;
    240   DnsRecordParser parser = resp.Parser();
    241   EXPECT_TRUE(parser.ReadRecord(&record));
    242   EXPECT_FALSE(parser.AtEnd());
    243   EXPECT_TRUE(parser.ReadRecord(&record));
    244   EXPECT_TRUE(parser.AtEnd());
    245   EXPECT_FALSE(parser.ReadRecord(&record));
    246 }
    247 
    248 TEST(DnsResponseTest, InitParseWithoutQuery) {
    249   DnsResponse resp;
    250   memcpy(resp.io_buffer()->data(), kT0ResponseDatagram,
    251          sizeof(kT0ResponseDatagram));
    252 
    253   // Accept matching question.
    254   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(kT0ResponseDatagram)));
    255   EXPECT_TRUE(resp.IsValid());
    256 
    257   // Check header access.
    258   EXPECT_EQ(0x8180, resp.flags());
    259   EXPECT_EQ(0x0, resp.rcode());
    260   EXPECT_EQ(kT0RecordCount, resp.answer_count());
    261 
    262   // Check question access.
    263   EXPECT_EQ(kT0Qtype, resp.qtype());
    264   EXPECT_EQ(kT0HostName, resp.GetDottedName());
    265 
    266   DnsResourceRecord record;
    267   DnsRecordParser parser = resp.Parser();
    268   for (unsigned i = 0; i < kT0RecordCount; i ++) {
    269     EXPECT_FALSE(parser.AtEnd());
    270     EXPECT_TRUE(parser.ReadRecord(&record));
    271   }
    272   EXPECT_TRUE(parser.AtEnd());
    273   EXPECT_FALSE(parser.ReadRecord(&record));
    274 }
    275 
    276 TEST(DnsResponseTest, InitParseWithoutQueryNoQuestions) {
    277   const uint8 response_data[] = {
    278     // Header
    279     0xca, 0xfe,               // ID
    280     0x81, 0x80,               // Standard query response, RA, no error
    281     0x00, 0x00,               // No question
    282     0x00, 0x01,               // 2 RRs (answers)
    283     0x00, 0x00,               // 0 authority RRs
    284     0x00, 0x00,               // 0 additional RRs
    285 
    286     // Answer 1
    287     0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
    288     0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
    289     0x03, 'o', 'r', 'g',
    290     0x00,
    291     0x00, 0x01,         // TYPE is A.
    292     0x00, 0x01,         // CLASS is IN.
    293     0x00, 0x00,         // TTL (4 bytes) is 53 seconds.
    294     0x00, 0x35,
    295     0x00, 0x04,         // RDLENGTH is 4 bytes.
    296     0x4a, 0x7d,         // RDATA is the IP: 74.125.95.121
    297     0x5f, 0x79,
    298   };
    299 
    300   DnsResponse resp;
    301   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
    302 
    303   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
    304 
    305   // Check header access.
    306   EXPECT_EQ(0x8180, resp.flags());
    307   EXPECT_EQ(0x0, resp.rcode());
    308   EXPECT_EQ(0x1u, resp.answer_count());
    309 
    310   DnsResourceRecord record;
    311   DnsRecordParser parser = resp.Parser();
    312 
    313   EXPECT_FALSE(parser.AtEnd());
    314   EXPECT_TRUE(parser.ReadRecord(&record));
    315   EXPECT_EQ("codereview.chromium.org", record.name);
    316   EXPECT_EQ(0x00000035u, record.ttl);
    317   EXPECT_EQ(dns_protocol::kTypeA, record.type);
    318 
    319   EXPECT_TRUE(parser.AtEnd());
    320   EXPECT_FALSE(parser.ReadRecord(&record));
    321 }
    322 
    323 TEST(DnsResponseTest, InitParseWithoutQueryTwoQuestions) {
    324   const uint8 response_data[] = {
    325     // Header
    326     0xca, 0xfe,               // ID
    327     0x81, 0x80,               // Standard query response, RA, no error
    328     0x00, 0x02,               // 2 questions
    329     0x00, 0x01,               // 2 RRs (answers)
    330     0x00, 0x00,               // 0 authority RRs
    331     0x00, 0x00,               // 0 additional RRs
    332 
    333     // Question 1
    334     0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
    335     0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
    336     0x03, 'o', 'r', 'g',
    337     0x00,
    338     0x00, 0x01,        // TYPE is A.
    339     0x00, 0x01,        // CLASS is IN.
    340 
    341     // Question 2
    342     0x0b, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', '2',
    343     0xc0, 0x18,        // pointer to "chromium.org"
    344     0x00, 0x01,        // TYPE is A.
    345     0x00, 0x01,        // CLASS is IN.
    346 
    347     // Answer 1
    348     0xc0, 0x0c,         // NAME is a pointer to name in Question section.
    349     0x00, 0x01,         // TYPE is A.
    350     0x00, 0x01,         // CLASS is IN.
    351     0x00, 0x00,         // TTL (4 bytes) is 53 seconds.
    352     0x00, 0x35,
    353     0x00, 0x04,         // RDLENGTH is 4 bytes.
    354     0x4a, 0x7d,         // RDATA is the IP: 74.125.95.121
    355     0x5f, 0x79,
    356   };
    357 
    358   DnsResponse resp;
    359   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
    360 
    361   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
    362 
    363   // Check header access.
    364   EXPECT_EQ(0x8180, resp.flags());
    365   EXPECT_EQ(0x0, resp.rcode());
    366   EXPECT_EQ(0x01u, resp.answer_count());
    367 
    368   DnsResourceRecord record;
    369   DnsRecordParser parser = resp.Parser();
    370 
    371   EXPECT_FALSE(parser.AtEnd());
    372   EXPECT_TRUE(parser.ReadRecord(&record));
    373   EXPECT_EQ("codereview.chromium.org", record.name);
    374   EXPECT_EQ(0x35u, record.ttl);
    375   EXPECT_EQ(dns_protocol::kTypeA, record.type);
    376 
    377   EXPECT_TRUE(parser.AtEnd());
    378   EXPECT_FALSE(parser.ReadRecord(&record));
    379 }
    380 
    381 TEST(DnsResponseTest, InitParseWithoutQueryPacketTooShort) {
    382   const uint8 response_data[] = {
    383     // Header
    384     0xca, 0xfe,               // ID
    385     0x81, 0x80,               // Standard query response, RA, no error
    386     0x00, 0x00,               // No question
    387   };
    388 
    389   DnsResponse resp;
    390   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
    391 
    392   EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(response_data)));
    393 }
    394 
    395 void VerifyAddressList(const std::vector<const char*>& ip_addresses,
    396                        const AddressList& addrlist) {
    397   ASSERT_EQ(ip_addresses.size(), addrlist.size());
    398 
    399   for (size_t i = 0; i < addrlist.size(); ++i) {
    400     EXPECT_EQ(ip_addresses[i], addrlist[i].ToStringWithoutPort());
    401   }
    402 }
    403 
    404 TEST(DnsResponseTest, ParseToAddressList) {
    405   const struct TestCase {
    406     size_t query_size;
    407     const uint8* response_data;
    408     size_t response_size;
    409     const char* const* expected_addresses;
    410     size_t num_expected_addresses;
    411     const char* expected_cname;
    412     int expected_ttl_sec;
    413   } cases[] = {
    414       {
    415         kT0QuerySize,
    416         kT0ResponseDatagram, arraysize(kT0ResponseDatagram),
    417         kT0IpAddresses, arraysize(kT0IpAddresses),
    418         kT0CanonName,
    419         kT0TTL,
    420       },
    421       {
    422         kT1QuerySize,
    423         kT1ResponseDatagram, arraysize(kT1ResponseDatagram),
    424         kT1IpAddresses, arraysize(kT1IpAddresses),
    425         kT1CanonName,
    426         kT1TTL,
    427       },
    428       {
    429         kT2QuerySize,
    430         kT2ResponseDatagram, arraysize(kT2ResponseDatagram),
    431         kT2IpAddresses, arraysize(kT2IpAddresses),
    432         kT2CanonName,
    433         kT2TTL,
    434       },
    435       {
    436         kT3QuerySize,
    437         kT3ResponseDatagram, arraysize(kT3ResponseDatagram),
    438         kT3IpAddresses, arraysize(kT3IpAddresses),
    439         kT3CanonName,
    440         kT3TTL,
    441       },
    442   };
    443 
    444   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    445     const TestCase& t = cases[i];
    446     DnsResponse response(t.response_data, t.response_size, t.query_size);
    447     AddressList addr_list;
    448     base::TimeDelta ttl;
    449     EXPECT_EQ(DnsResponse::DNS_PARSE_OK,
    450               response.ParseToAddressList(&addr_list, &ttl));
    451     std::vector<const char*> expected_addresses(
    452         t.expected_addresses,
    453         t.expected_addresses + t.num_expected_addresses);
    454     VerifyAddressList(expected_addresses, addr_list);
    455     EXPECT_EQ(t.expected_cname, addr_list.canonical_name());
    456     EXPECT_EQ(base::TimeDelta::FromSeconds(t.expected_ttl_sec), ttl);
    457   }
    458 }
    459 
    460 const uint8 kResponseTruncatedRecord[] = {
    461   // Header: 1 question, 1 answer RR
    462   0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
    463   // Question: name = 'a', type = A (0x1)
    464   0x01,  'a', 0x00, 0x00, 0x01, 0x00, 0x01,
    465   // Answer: name = 'a', type = A, TTL = 0xFF, RDATA = 10.10.10.10
    466   0x01,  'a', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    467   0x00, 0x04, 0x0A, 0x0A, 0x0A,  // Truncated RDATA.
    468 };
    469 
    470 const uint8 kResponseTruncatedCNAME[] = {
    471   // Header: 1 question, 1 answer RR
    472   0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
    473   // Question: name = 'a', type = A (0x1)
    474   0x01,  'a', 0x00, 0x00, 0x01, 0x00, 0x01,
    475   // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'foo' (truncated)
    476   0x01,  'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    477   0x00, 0x03, 0x03,  'f',  'o',  // Truncated name.
    478 };
    479 
    480 const uint8 kResponseNameMismatch[] = {
    481   // Header: 1 question, 1 answer RR
    482   0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
    483   // Question: name = 'a', type = A (0x1)
    484   0x01,  'a', 0x00, 0x00, 0x01, 0x00, 0x01,
    485   // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
    486   0x01,  'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    487   0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
    488 };
    489 
    490 const uint8 kResponseNameMismatchInChain[] = {
    491   // Header: 1 question, 3 answer RR
    492   0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
    493   // Question: name = 'a', type = A (0x1)
    494   0x01,  'a', 0x00, 0x00, 0x01, 0x00, 0x01,
    495   // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
    496   0x01,  'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    497   0x00, 0x03, 0x01,  'b', 0x00,
    498   // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
    499   0x01,  'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    500   0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
    501   // Answer: name = 'c', type = A, TTL = 0xFF, RDATA = 10.10.10.11
    502   0x01,  'c', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    503   0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0B,
    504 };
    505 
    506 const uint8 kResponseSizeMismatch[] = {
    507   // Header: 1 answer RR
    508   0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
    509   // Question: name = 'a', type = AAAA (0x1c)
    510   0x01,  'a', 0x00, 0x00, 0x1c, 0x00, 0x01,
    511   // Answer: name = 'a', type = AAAA, TTL = 0xFF, RDATA = 10.10.10.10
    512   0x01,  'a', 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    513   0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
    514 };
    515 
    516 const uint8 kResponseCNAMEAfterAddress[] = {
    517   // Header: 2 answer RR
    518   0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
    519   // Question: name = 'a', type = A (0x1)
    520   0x01,  'a', 0x00, 0x00, 0x01, 0x00, 0x01,
    521   // Answer: name = 'a', type = A, TTL = 0xFF, RDATA = 10.10.10.10.
    522   0x01,  'a', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    523   0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
    524   // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
    525   0x01,  'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    526   0x00, 0x03, 0x01,  'b', 0x00,
    527 };
    528 
    529 const uint8 kResponseNoAddresses[] = {
    530   // Header: 1 question, 1 answer RR, 1 authority RR
    531   0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    532   // Question: name = 'a', type = A (0x1)
    533   0x01,  'a', 0x00, 0x00, 0x01, 0x00, 0x01,
    534   // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
    535   0x01,  'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    536   0x00, 0x03, 0x01, 'b', 0x00,
    537   // Authority section
    538   // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
    539   0x01,  'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
    540   0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
    541 };
    542 
    543 TEST(DnsResponseTest, ParseToAddressListFail) {
    544   const struct TestCase {
    545     const uint8* data;
    546     size_t size;
    547     DnsResponse::Result expected_result;
    548   } cases[] = {
    549     { kResponseTruncatedRecord, arraysize(kResponseTruncatedRecord),
    550       DnsResponse::DNS_MALFORMED_RESPONSE },
    551     { kResponseTruncatedCNAME, arraysize(kResponseTruncatedCNAME),
    552       DnsResponse::DNS_MALFORMED_CNAME },
    553     { kResponseNameMismatch, arraysize(kResponseNameMismatch),
    554       DnsResponse::DNS_NAME_MISMATCH },
    555     { kResponseNameMismatchInChain, arraysize(kResponseNameMismatchInChain),
    556       DnsResponse::DNS_NAME_MISMATCH },
    557     { kResponseSizeMismatch, arraysize(kResponseSizeMismatch),
    558       DnsResponse::DNS_SIZE_MISMATCH },
    559     { kResponseCNAMEAfterAddress, arraysize(kResponseCNAMEAfterAddress),
    560       DnsResponse::DNS_CNAME_AFTER_ADDRESS },
    561     // Not actually a failure, just an empty result.
    562     { kResponseNoAddresses, arraysize(kResponseNoAddresses),
    563       DnsResponse::DNS_PARSE_OK },
    564   };
    565 
    566   const size_t kQuerySize = 12 + 7;
    567 
    568   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    569     const TestCase& t = cases[i];
    570 
    571     DnsResponse response(t.data, t.size, kQuerySize);
    572     AddressList addr_list;
    573     base::TimeDelta ttl;
    574     EXPECT_EQ(t.expected_result,
    575               response.ParseToAddressList(&addr_list, &ttl));
    576   }
    577 }
    578 
    579 }  // namespace
    580 
    581 }  // namespace net
    582