This source file includes following definitions.
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- VerifyAddressList
- TEST
- TEST
#include "net/dns/dns_response.h"
#include "base/time/time.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/net_util.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/dns_query.h"
#include "net/dns/dns_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
TEST(DnsRecordParserTest, Constructor) {
const char data[] = { 0 };
EXPECT_FALSE(DnsRecordParser().IsValid());
EXPECT_TRUE(DnsRecordParser(data, 1, 0).IsValid());
EXPECT_TRUE(DnsRecordParser(data, 1, 1).IsValid());
EXPECT_FALSE(DnsRecordParser(data, 1, 0).AtEnd());
EXPECT_TRUE(DnsRecordParser(data, 1, 1).AtEnd());
}
TEST(DnsRecordParserTest, ReadName) {
const uint8 data[] = {
0x03, 'f', 'o', 'o',
0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
0x03, 'c', 'o', 'm',
0x00,
0x03, 'b', 'a', 'r',
0xc0, 0x04,
0xc0, 0x11,
};
std::string out;
DnsRecordParser parser(data, sizeof(data), 0);
ASSERT_TRUE(parser.IsValid());
EXPECT_EQ(0x11u, parser.ReadName(data + 0x00, &out));
EXPECT_EQ("foo.example.com", out);
out.clear();
EXPECT_EQ(0x1u, parser.ReadName(data + 0x10, &out));
EXPECT_EQ("", out);
out.clear();
EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, &out));
EXPECT_EQ("bar.example.com", out);
out.clear();
EXPECT_EQ(0x2u, parser.ReadName(data + 0x17, &out));
EXPECT_EQ("bar.example.com", out);
EXPECT_EQ(0x11u, parser.ReadName(data + 0x00, NULL));
EXPECT_EQ(0x1u, parser.ReadName(data + 0x10, NULL));
EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, NULL));
EXPECT_EQ(0x2u, parser.ReadName(data + 0x17, NULL));
parser = DnsRecordParser(data, sizeof(data), 0x12);
EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, NULL));
}
TEST(DnsRecordParserTest, ReadNameFail) {
const uint8 data[] = {
0x30, 'x', 'x',
0x00,
0xc0, 0x20,
0xc0, 0x08,
0xc0, 0x06,
0x80, 0x00,
0x02, 'x', 'x',
};
DnsRecordParser parser(data, sizeof(data), 0);
ASSERT_TRUE(parser.IsValid());
std::string out;
EXPECT_EQ(0u, parser.ReadName(data + 0x00, &out));
EXPECT_EQ(0u, parser.ReadName(data + 0x04, &out));
EXPECT_EQ(0u, parser.ReadName(data + 0x08, &out));
EXPECT_EQ(0u, parser.ReadName(data + 0x0a, &out));
EXPECT_EQ(0u, parser.ReadName(data + 0x0c, &out));
EXPECT_EQ(0u, parser.ReadName(data + 0x0e, &out));
}
TEST(DnsRecordParserTest, ReadRecord) {
const uint8 data[] = {
0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
0x03, 'c', 'o', 'm',
0x00,
0x00, 0x05,
0x00, 0x01,
0x00, 0x01, 0x24, 0x74,
0x00, 0x06,
0x03, 'f', 'o', 'o',
0xc0, 0x00,
0x03, 'b', 'a', 'r',
0xc0, 0x00,
0x00, 0x01,
0x00, 0x01,
0x00, 0x20, 0x13, 0x55,
0x00, 0x04,
0x7f, 0x02, 0x04, 0x01,
};
std::string out;
DnsRecordParser parser(data, sizeof(data), 0);
DnsResourceRecord record;
EXPECT_TRUE(parser.ReadRecord(&record));
EXPECT_EQ("example.com", record.name);
EXPECT_EQ(dns_protocol::kTypeCNAME, record.type);
EXPECT_EQ(dns_protocol::kClassIN, record.klass);
EXPECT_EQ(0x00012474u, record.ttl);
EXPECT_EQ(6u, record.rdata.length());
EXPECT_EQ(6u, parser.ReadName(record.rdata.data(), &out));
EXPECT_EQ("foo.example.com", out);
EXPECT_FALSE(parser.AtEnd());
EXPECT_TRUE(parser.ReadRecord(&record));
EXPECT_EQ("bar.example.com", record.name);
EXPECT_EQ(dns_protocol::kTypeA, record.type);
EXPECT_EQ(dns_protocol::kClassIN, record.klass);
EXPECT_EQ(0x00201355u, record.ttl);
EXPECT_EQ(4u, record.rdata.length());
EXPECT_EQ(base::StringPiece("\x7f\x02\x04\x01"), record.rdata);
EXPECT_TRUE(parser.AtEnd());
parser = DnsRecordParser(data, sizeof(data) - 2, 0);
EXPECT_TRUE(parser.ReadRecord(&record));
EXPECT_FALSE(parser.AtEnd());
EXPECT_FALSE(parser.ReadRecord(&record));
}
TEST(DnsResponseTest, InitParse) {
const char qname_data[] = "\x0A""codereview""\x08""chromium""\x03""org";
const base::StringPiece qname(qname_data, sizeof(qname_data));
scoped_ptr<DnsQuery> query(new DnsQuery(0xcafe, qname, dns_protocol::kTypeA));
const uint8 response_data[] = {
0xca, 0xfe,
0x81, 0x80,
0x00, 0x01,
0x00, 0x02,
0x00, 0x00,
0x00, 0x00,
0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
0x03, 'o', 'r', 'g',
0x00,
0x00, 0x01,
0x00, 0x01,
0xc0, 0x0c,
0x00, 0x05,
0x00, 0x01,
0x00, 0x01,
0x24, 0x74,
0x00, 0x12,
0x03, 'g', 'h', 's',
0x01, 'l',
0x06, 'g', 'o', 'o', 'g', 'l', 'e',
0x03, 'c', 'o', 'm',
0x00,
0xc0, 0x35,
0x00, 0x01,
0x00, 0x01,
0x00, 0x00,
0x00, 0x35,
0x00, 0x04,
0x4a, 0x7d,
0x5f, 0x79,
};
DnsResponse resp;
memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
EXPECT_FALSE(resp.InitParse(query->io_buffer()->size() - 1, *query));
EXPECT_FALSE(resp.IsValid());
scoped_ptr<DnsQuery> other_query(query->CloneWithNewId(0xbeef));
EXPECT_FALSE(resp.InitParse(sizeof(response_data), *other_query));
EXPECT_FALSE(resp.IsValid());
scoped_ptr<DnsQuery> wrong_query(
new DnsQuery(0xcafe, qname, dns_protocol::kTypeCNAME));
EXPECT_FALSE(resp.InitParse(sizeof(response_data), *wrong_query));
EXPECT_FALSE(resp.IsValid());
EXPECT_TRUE(resp.InitParse(sizeof(response_data), *query));
EXPECT_TRUE(resp.IsValid());
EXPECT_EQ(0x8180, resp.flags());
EXPECT_EQ(0x0, resp.rcode());
EXPECT_EQ(2u, resp.answer_count());
EXPECT_EQ(query->qname(), resp.qname());
EXPECT_EQ(query->qtype(), resp.qtype());
EXPECT_EQ("codereview.chromium.org", resp.GetDottedName());
DnsResourceRecord record;
DnsRecordParser parser = resp.Parser();
EXPECT_TRUE(parser.ReadRecord(&record));
EXPECT_FALSE(parser.AtEnd());
EXPECT_TRUE(parser.ReadRecord(&record));
EXPECT_TRUE(parser.AtEnd());
EXPECT_FALSE(parser.ReadRecord(&record));
}
TEST(DnsResponseTest, InitParseWithoutQuery) {
DnsResponse resp;
memcpy(resp.io_buffer()->data(), kT0ResponseDatagram,
sizeof(kT0ResponseDatagram));
EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(kT0ResponseDatagram)));
EXPECT_TRUE(resp.IsValid());
EXPECT_EQ(0x8180, resp.flags());
EXPECT_EQ(0x0, resp.rcode());
EXPECT_EQ(kT0RecordCount, resp.answer_count());
EXPECT_EQ(kT0Qtype, resp.qtype());
EXPECT_EQ(kT0HostName, resp.GetDottedName());
DnsResourceRecord record;
DnsRecordParser parser = resp.Parser();
for (unsigned i = 0; i < kT0RecordCount; i ++) {
EXPECT_FALSE(parser.AtEnd());
EXPECT_TRUE(parser.ReadRecord(&record));
}
EXPECT_TRUE(parser.AtEnd());
EXPECT_FALSE(parser.ReadRecord(&record));
}
TEST(DnsResponseTest, InitParseWithoutQueryNoQuestions) {
const uint8 response_data[] = {
0xca, 0xfe,
0x81, 0x80,
0x00, 0x00,
0x00, 0x01,
0x00, 0x00,
0x00, 0x00,
0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
0x03, 'o', 'r', 'g',
0x00,
0x00, 0x01,
0x00, 0x01,
0x00, 0x00,
0x00, 0x35,
0x00, 0x04,
0x4a, 0x7d,
0x5f, 0x79,
};
DnsResponse resp;
memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
EXPECT_EQ(0x8180, resp.flags());
EXPECT_EQ(0x0, resp.rcode());
EXPECT_EQ(0x1u, resp.answer_count());
DnsResourceRecord record;
DnsRecordParser parser = resp.Parser();
EXPECT_FALSE(parser.AtEnd());
EXPECT_TRUE(parser.ReadRecord(&record));
EXPECT_EQ("codereview.chromium.org", record.name);
EXPECT_EQ(0x00000035u, record.ttl);
EXPECT_EQ(dns_protocol::kTypeA, record.type);
EXPECT_TRUE(parser.AtEnd());
EXPECT_FALSE(parser.ReadRecord(&record));
}
TEST(DnsResponseTest, InitParseWithoutQueryTwoQuestions) {
const uint8 response_data[] = {
0xca, 0xfe,
0x81, 0x80,
0x00, 0x02,
0x00, 0x01,
0x00, 0x00,
0x00, 0x00,
0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
0x03, 'o', 'r', 'g',
0x00,
0x00, 0x01,
0x00, 0x01,
0x0b, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', '2',
0xc0, 0x18,
0x00, 0x01,
0x00, 0x01,
0xc0, 0x0c,
0x00, 0x01,
0x00, 0x01,
0x00, 0x00,
0x00, 0x35,
0x00, 0x04,
0x4a, 0x7d,
0x5f, 0x79,
};
DnsResponse resp;
memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
EXPECT_EQ(0x8180, resp.flags());
EXPECT_EQ(0x0, resp.rcode());
EXPECT_EQ(0x01u, resp.answer_count());
DnsResourceRecord record;
DnsRecordParser parser = resp.Parser();
EXPECT_FALSE(parser.AtEnd());
EXPECT_TRUE(parser.ReadRecord(&record));
EXPECT_EQ("codereview.chromium.org", record.name);
EXPECT_EQ(0x35u, record.ttl);
EXPECT_EQ(dns_protocol::kTypeA, record.type);
EXPECT_TRUE(parser.AtEnd());
EXPECT_FALSE(parser.ReadRecord(&record));
}
TEST(DnsResponseTest, InitParseWithoutQueryPacketTooShort) {
const uint8 response_data[] = {
0xca, 0xfe,
0x81, 0x80,
0x00, 0x00,
};
DnsResponse resp;
memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(response_data)));
}
void VerifyAddressList(const std::vector<const char*>& ip_addresses,
const AddressList& addrlist) {
ASSERT_EQ(ip_addresses.size(), addrlist.size());
for (size_t i = 0; i < addrlist.size(); ++i) {
EXPECT_EQ(ip_addresses[i], addrlist[i].ToStringWithoutPort());
}
}
TEST(DnsResponseTest, ParseToAddressList) {
const struct TestCase {
size_t query_size;
const uint8* response_data;
size_t response_size;
const char* const* expected_addresses;
size_t num_expected_addresses;
const char* expected_cname;
int expected_ttl_sec;
} cases[] = {
{
kT0QuerySize,
kT0ResponseDatagram, arraysize(kT0ResponseDatagram),
kT0IpAddresses, arraysize(kT0IpAddresses),
kT0CanonName,
kT0TTL,
},
{
kT1QuerySize,
kT1ResponseDatagram, arraysize(kT1ResponseDatagram),
kT1IpAddresses, arraysize(kT1IpAddresses),
kT1CanonName,
kT1TTL,
},
{
kT2QuerySize,
kT2ResponseDatagram, arraysize(kT2ResponseDatagram),
kT2IpAddresses, arraysize(kT2IpAddresses),
kT2CanonName,
kT2TTL,
},
{
kT3QuerySize,
kT3ResponseDatagram, arraysize(kT3ResponseDatagram),
kT3IpAddresses, arraysize(kT3IpAddresses),
kT3CanonName,
kT3TTL,
},
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
const TestCase& t = cases[i];
DnsResponse response(t.response_data, t.response_size, t.query_size);
AddressList addr_list;
base::TimeDelta ttl;
EXPECT_EQ(DnsResponse::DNS_PARSE_OK,
response.ParseToAddressList(&addr_list, &ttl));
std::vector<const char*> expected_addresses(
t.expected_addresses,
t.expected_addresses + t.num_expected_addresses);
VerifyAddressList(expected_addresses, addr_list);
EXPECT_EQ(t.expected_cname, addr_list.canonical_name());
EXPECT_EQ(base::TimeDelta::FromSeconds(t.expected_ttl_sec), ttl);
}
}
const uint8 kResponseTruncatedRecord[] = {
0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x04, 0x0A, 0x0A, 0x0A,
};
const uint8 kResponseTruncatedCNAME[] = {
0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x03, 0x03, 'f', 'o',
};
const uint8 kResponseNameMismatch[] = {
0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
};
const uint8 kResponseNameMismatchInChain[] = {
0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x03, 0x01, 'b', 0x00,
0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
0x01, 'c', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0B,
};
const uint8 kResponseSizeMismatch[] = {
0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x01, 'a', 0x00, 0x00, 0x1c, 0x00, 0x01,
0x01, 'a', 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
};
const uint8 kResponseCNAMEAfterAddress[] = {
0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x03, 0x01, 'b', 0x00,
};
const uint8 kResponseNoAddresses[] = {
0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x03, 0x01, 'b', 0x00,
0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
};
TEST(DnsResponseTest, ParseToAddressListFail) {
const struct TestCase {
const uint8* data;
size_t size;
DnsResponse::Result expected_result;
} cases[] = {
{ kResponseTruncatedRecord, arraysize(kResponseTruncatedRecord),
DnsResponse::DNS_MALFORMED_RESPONSE },
{ kResponseTruncatedCNAME, arraysize(kResponseTruncatedCNAME),
DnsResponse::DNS_MALFORMED_CNAME },
{ kResponseNameMismatch, arraysize(kResponseNameMismatch),
DnsResponse::DNS_NAME_MISMATCH },
{ kResponseNameMismatchInChain, arraysize(kResponseNameMismatchInChain),
DnsResponse::DNS_NAME_MISMATCH },
{ kResponseSizeMismatch, arraysize(kResponseSizeMismatch),
DnsResponse::DNS_SIZE_MISMATCH },
{ kResponseCNAMEAfterAddress, arraysize(kResponseCNAMEAfterAddress),
DnsResponse::DNS_CNAME_AFTER_ADDRESS },
{ kResponseNoAddresses, arraysize(kResponseNoAddresses),
DnsResponse::DNS_PARSE_OK },
};
const size_t kQuerySize = 12 + 7;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
const TestCase& t = cases[i];
DnsResponse response(t.data, t.size, kQuerySize);
AddressList addr_list;
base::TimeDelta ttl;
EXPECT_EQ(t.expected_result,
response.ParseToAddressList(&addr_list, &ttl));
}
}
}
}