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