1 // Copyright 2013 The Chromium Authors
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/record_parsed.h"
6
7 #include <memory>
8
9 #include "base/time/time.h"
10 #include "net/dns/dns_response.h"
11 #include "net/dns/dns_test_util.h"
12 #include "net/dns/public/dns_protocol.h"
13 #include "net/dns/record_rdata.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace net {
17
18 static const uint8_t kT1ResponseWithCacheFlushBit[] = {
19 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', 0x08, 'c', 'h', 'r',
20 'o', 'm', 'i', 'u', 'm', 0x03, 'o', 'r', 'g', 0x00, 0x00,
21 0x05, // TYPE is CNAME.
22 0x80, 0x01, // CLASS is IN with cache flush bit set.
23 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
24 0x24, 0x74, 0x00, 0x12, // RDLENGTH is 18 bytes.
25 // ghs.l.google.com in DNS format.
26 0x03, 'g', 'h', 's', 0x01, 'l', 0x06, 'g', 'o', 'o', 'g', 'l', 'e', 0x03,
27 'c', 'o', 'm', 0x00};
28
TEST(RecordParsedTest,ParseSingleRecord)29 TEST(RecordParsedTest, ParseSingleRecord) {
30 DnsRecordParser parser(kT1ResponseDatagram, sizeof(kT1ResponseDatagram),
31 sizeof(dns_protocol::Header), kT1RecordCount);
32 std::unique_ptr<const RecordParsed> record;
33 const CnameRecordRdata* rdata;
34
35 std::string dotted_qname;
36 uint16_t qtype;
37 parser.ReadQuestion(dotted_qname, qtype);
38
39 record = RecordParsed::CreateFrom(&parser, base::Time());
40 EXPECT_TRUE(record != nullptr);
41
42 ASSERT_EQ("codereview.chromium.org", record->name());
43 ASSERT_EQ(dns_protocol::kTypeCNAME, record->type());
44 ASSERT_EQ(dns_protocol::kClassIN, record->klass());
45
46 rdata = record->rdata<CnameRecordRdata>();
47 ASSERT_TRUE(rdata != nullptr);
48 ASSERT_EQ(kT1CanonName, rdata->cname());
49
50 ASSERT_FALSE(record->rdata<SrvRecordRdata>());
51 ASSERT_TRUE(record->IsEqual(record.get(), true));
52 }
53
TEST(RecordParsedTest,CacheFlushBitCompare)54 TEST(RecordParsedTest, CacheFlushBitCompare) {
55 DnsRecordParser parser1(kT1ResponseDatagram, sizeof(kT1ResponseDatagram),
56 sizeof(dns_protocol::Header), kT1RecordCount);
57 std::string dotted_qname;
58 uint16_t qtype;
59 parser1.ReadQuestion(dotted_qname, qtype);
60
61 std::unique_ptr<const RecordParsed> record1 =
62 RecordParsed::CreateFrom(&parser1, base::Time());
63
64 DnsRecordParser parser2(kT1ResponseWithCacheFlushBit,
65 sizeof(kT1ResponseWithCacheFlushBit), 0,
66 kT1RecordCount);
67
68 std::unique_ptr<const RecordParsed> record2 =
69 RecordParsed::CreateFrom(&parser2, base::Time());
70
71 EXPECT_FALSE(record1->IsEqual(record2.get(), false));
72 EXPECT_TRUE(record1->IsEqual(record2.get(), true));
73 EXPECT_FALSE(record2->IsEqual(record1.get(), false));
74 EXPECT_TRUE(record2->IsEqual(record1.get(), true));
75 }
76
TEST(RecordParsedTest,ParseUnknownRdata)77 TEST(RecordParsedTest, ParseUnknownRdata) {
78 static const char kRecordData[] =
79 // NAME="foo.test"
80 "\003foo\004test\000"
81 // TYPE=MD (an obsolete type that will likely never be recognized by
82 // Chrome)
83 "\000\003"
84 // CLASS=IN
85 "\000\001"
86 // TTL=30 seconds
87 "\000\000\000\036"
88 // RDLENGTH=12 bytes
89 "\000\014"
90 // RDATA="garbage data"
91 "garbage data";
92 DnsRecordParser parser(kRecordData, sizeof(kRecordData) - 1, 0 /* offset */,
93 /*num_records=*/1);
94
95 std::unique_ptr<const RecordParsed> record =
96 RecordParsed::CreateFrom(&parser, base::Time());
97
98 ASSERT_TRUE(record);
99 EXPECT_EQ(record->name(), "foo.test");
100 EXPECT_EQ(record->type(), 3u);
101 EXPECT_EQ(record->klass(), dns_protocol::kClassIN);
102 EXPECT_EQ(record->ttl(), 30u);
103 EXPECT_FALSE(record->rdata<ARecordRdata>());
104 EXPECT_FALSE(record->rdata_for_testing());
105 }
106
TEST(RecordParsedTest,EqualityHandlesUnknownRdata)107 TEST(RecordParsedTest, EqualityHandlesUnknownRdata) {
108 static constexpr char kData[] =
109 // NAME="foo.test"
110 "\003foo\004test\000"
111 // TYPE=MD (an obsolete type that will likely never be recognized by
112 // Chrome)
113 "\000\003"
114 // CLASS=IN
115 "\000\001"
116 // TTL=30 seconds
117 "\000\000\000\036"
118 // RDLENGTH=12 bytes
119 "\000\014"
120 // RDATA="garbage data"
121 "garbage data"
122 // NAME="foo.test"
123 "\003foo\004test\000"
124 // TYPE=A
125 "\000\001"
126 // CLASS=IN
127 "\000\001"
128 // TTL=30 seconds
129 "\000\000\000\036"
130 // RDLENGTH=4 bytes
131 "\000\004"
132 // RDATA=8.8.8.8
133 "\010\010\010\010";
134 DnsRecordParser parser(kData, sizeof(kData) - 1, 0 /* offset */,
135 /*num_records=*/2);
136
137 std::unique_ptr<const RecordParsed> unknown_record =
138 RecordParsed::CreateFrom(&parser, base::Time());
139 ASSERT_TRUE(unknown_record);
140 ASSERT_FALSE(unknown_record->rdata_for_testing());
141
142 std::unique_ptr<const RecordParsed> known_record =
143 RecordParsed::CreateFrom(&parser, base::Time());
144 ASSERT_TRUE(known_record);
145 ASSERT_TRUE(known_record->rdata_for_testing());
146
147 EXPECT_TRUE(
148 unknown_record->IsEqual(unknown_record.get(), false /* is_mdns */));
149 EXPECT_TRUE(
150 unknown_record->IsEqual(unknown_record.get(), true /* is_mdns */));
151 EXPECT_TRUE(known_record->IsEqual(known_record.get(), false /* is_mdns */));
152 EXPECT_TRUE(known_record->IsEqual(known_record.get(), true /* is_mdns */));
153 EXPECT_FALSE(
154 unknown_record->IsEqual(known_record.get(), false /* is_mdns */));
155 EXPECT_FALSE(unknown_record->IsEqual(known_record.get(), true /* is_mdns */));
156 EXPECT_FALSE(
157 known_record->IsEqual(unknown_record.get(), false /* is_mdns */));
158 EXPECT_FALSE(known_record->IsEqual(unknown_record.get(), true /* is_mdns */));
159 }
160
TEST(RecordParsedTest,RejectMalformedRdata)161 TEST(RecordParsedTest, RejectMalformedRdata) {
162 static const char kRecordData[] =
163 // NAME="foo.test"
164 "\003foo\004test\000"
165 // TYPE=PTR
166 "\000\014"
167 // CLASS=IN
168 "\000\001"
169 // TTL=31 seconds
170 "\000\000\000\037"
171 // RDLENGTH=1 byte
172 "\000\001"
173 // RDATA=truncated name
174 "\001";
175 DnsRecordParser parser(kRecordData, sizeof(kRecordData) - 1, 0 /* offset */,
176 /*num_records=*/1);
177
178 std::unique_ptr<const RecordParsed> record =
179 RecordParsed::CreateFrom(&parser, base::Time());
180
181 EXPECT_FALSE(record);
182 }
183
184 } // namespace net
185