• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(DnsRecordParserTest,Constructor)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 
TEST(DnsRecordParserTest,ReadName)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 
TEST(DnsRecordParserTest,ReadNameFail)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 
TEST(DnsRecordParserTest,ReadRecord)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 
TEST(DnsResponseTest,InitParse)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 
TEST(DnsResponseTest,InitParseWithoutQuery)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 
TEST(DnsResponseTest,InitParseWithoutQueryNoQuestions)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 
TEST(DnsResponseTest,InitParseWithoutQueryTwoQuestions)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 
TEST(DnsResponseTest,InitParseWithoutQueryPacketTooShort)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 
VerifyAddressList(const std::vector<const char * > & ip_addresses,const AddressList & addrlist)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 
TEST(DnsResponseTest,ParseToAddressList)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 
TEST(DnsResponseTest,ParseToAddressListFail)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