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_rdata.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <utility>
10
11 #include "base/big_endian.h"
12 #include "net/dns/dns_response.h"
13 #include "net/dns/dns_test_util.h"
14 #include "net/test/gtest_util.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/abseil-cpp/absl/types/optional.h"
18
19 namespace net {
20 namespace {
21
22 using ::testing::ElementsAreArray;
23 using ::testing::IsNull;
24 using ::testing::NotNull;
25 using ::testing::SizeIs;
26
MakeStringPiece(const uint8_t * data,unsigned size)27 base::StringPiece MakeStringPiece(const uint8_t* data, unsigned size) {
28 const char* data_cc = reinterpret_cast<const char*>(data);
29 return base::StringPiece(data_cc, size);
30 }
31
TEST(RecordRdataTest,ParseSrvRecord)32 TEST(RecordRdataTest, ParseSrvRecord) {
33 // These are just the rdata portions of the DNS records, rather than complete
34 // records, but it works well enough for this test.
35
36 const uint8_t
37 record[] =
38 {
39 0x00, 0x01, 0x00, 0x02, 0x00, 0x50, 0x03, 'w', 'w',
40 'w', 0x06, 'g', 'o', 'o', 'g', 'l', 'e', 0x03,
41 'c', 'o', 'm', 0x00, 0x01, 0x01, 0x01, 0x02, 0x01,
42 0x03, 0x04, 'w', 'w', 'w', '2', 0xc0, 0x0a, // Pointer to
43 // "google.com"
44 };
45
46 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
47 const unsigned first_record_len = 22;
48 base::StringPiece record1_strpiece = MakeStringPiece(
49 record, first_record_len);
50 base::StringPiece record2_strpiece = MakeStringPiece(
51 record + first_record_len, sizeof(record) - first_record_len);
52
53 std::unique_ptr<SrvRecordRdata> record1_obj =
54 SrvRecordRdata::Create(record1_strpiece, parser);
55 ASSERT_TRUE(record1_obj != nullptr);
56 ASSERT_EQ(1, record1_obj->priority());
57 ASSERT_EQ(2, record1_obj->weight());
58 ASSERT_EQ(80, record1_obj->port());
59
60 ASSERT_EQ("www.google.com", record1_obj->target());
61
62 std::unique_ptr<SrvRecordRdata> record2_obj =
63 SrvRecordRdata::Create(record2_strpiece, parser);
64 ASSERT_TRUE(record2_obj != nullptr);
65 ASSERT_EQ(257, record2_obj->priority());
66 ASSERT_EQ(258, record2_obj->weight());
67 ASSERT_EQ(259, record2_obj->port());
68
69 ASSERT_EQ("www2.google.com", record2_obj->target());
70
71 ASSERT_TRUE(record1_obj->IsEqual(record1_obj.get()));
72 ASSERT_FALSE(record1_obj->IsEqual(record2_obj.get()));
73 }
74
TEST(RecordRdataTest,ParseARecord)75 TEST(RecordRdataTest, ParseARecord) {
76 // These are just the rdata portions of the DNS records, rather than complete
77 // records, but it works well enough for this test.
78
79 const uint8_t record[] = {
80 0x7F, 0x00, 0x00, 0x01 // 127.0.0.1
81 };
82
83 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
84 base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
85
86 std::unique_ptr<ARecordRdata> record_obj =
87 ARecordRdata::Create(record_strpiece, parser);
88 ASSERT_TRUE(record_obj != nullptr);
89
90 ASSERT_EQ("127.0.0.1", record_obj->address().ToString());
91
92 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
93 }
94
TEST(RecordRdataTest,ParseAAAARecord)95 TEST(RecordRdataTest, ParseAAAARecord) {
96 // These are just the rdata portions of the DNS records, rather than complete
97 // records, but it works well enough for this test.
98
99 const uint8_t record[] = {
100 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 // 1234:5678::9A
102 };
103
104 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
105 base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
106
107 std::unique_ptr<AAAARecordRdata> record_obj =
108 AAAARecordRdata::Create(record_strpiece, parser);
109 ASSERT_TRUE(record_obj != nullptr);
110
111 ASSERT_EQ("1234:5678::9", record_obj->address().ToString());
112
113 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
114 }
115
TEST(RecordRdataTest,ParseCnameRecord)116 TEST(RecordRdataTest, ParseCnameRecord) {
117 // These are just the rdata portions of the DNS records, rather than complete
118 // records, but it works well enough for this test.
119
120 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o',
121 'g', 'l', 'e', 0x03, 'c', 'o', 'm', 0x00};
122
123 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
124 base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
125
126 std::unique_ptr<CnameRecordRdata> record_obj =
127 CnameRecordRdata::Create(record_strpiece, parser);
128 ASSERT_TRUE(record_obj != nullptr);
129
130 ASSERT_EQ("www.google.com", record_obj->cname());
131
132 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
133 }
134
TEST(RecordRdataTest,ParsePtrRecord)135 TEST(RecordRdataTest, ParsePtrRecord) {
136 // These are just the rdata portions of the DNS records, rather than complete
137 // records, but it works well enough for this test.
138
139 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o',
140 'g', 'l', 'e', 0x03, 'c', 'o', 'm', 0x00};
141
142 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
143 base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
144
145 std::unique_ptr<PtrRecordRdata> record_obj =
146 PtrRecordRdata::Create(record_strpiece, parser);
147 ASSERT_TRUE(record_obj != nullptr);
148
149 ASSERT_EQ("www.google.com", record_obj->ptrdomain());
150
151 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
152 }
153
TEST(RecordRdataTest,ParseTxtRecord)154 TEST(RecordRdataTest, ParseTxtRecord) {
155 // These are just the rdata portions of the DNS records, rather than complete
156 // records, but it works well enough for this test.
157
158 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o',
159 'g', 'l', 'e', 0x03, 'c', 'o', 'm'};
160
161 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
162 base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
163
164 std::unique_ptr<TxtRecordRdata> record_obj =
165 TxtRecordRdata::Create(record_strpiece, parser);
166 ASSERT_TRUE(record_obj != nullptr);
167
168 std::vector<std::string> expected;
169 expected.push_back("www");
170 expected.push_back("google");
171 expected.push_back("com");
172
173 ASSERT_EQ(expected, record_obj->texts());
174
175 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
176 }
177
TEST(RecordRdataTest,ParseNsecRecord)178 TEST(RecordRdataTest, ParseNsecRecord) {
179 // These are just the rdata portions of the DNS records, rather than complete
180 // records, but it works well enough for this test.
181
182 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o',
183 'o', 'g', 'l', 'e', 0x03, 'c', 'o',
184 'm', 0x00, 0x00, 0x02, 0x40, 0x01};
185
186 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
187 base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
188
189 std::unique_ptr<NsecRecordRdata> record_obj =
190 NsecRecordRdata::Create(record_strpiece, parser);
191 ASSERT_TRUE(record_obj != nullptr);
192
193 ASSERT_EQ(16u, record_obj->bitmap_length());
194
195 EXPECT_FALSE(record_obj->GetBit(0));
196 EXPECT_TRUE(record_obj->GetBit(1));
197 for (int i = 2; i < 15; i++) {
198 EXPECT_FALSE(record_obj->GetBit(i));
199 }
200 EXPECT_TRUE(record_obj->GetBit(15));
201
202 ASSERT_TRUE(record_obj->IsEqual(record_obj.get()));
203 }
204
TEST(RecordRdataTest,CreateNsecRecordWithEmptyBitmapReturnsNull)205 TEST(RecordRdataTest, CreateNsecRecordWithEmptyBitmapReturnsNull) {
206 // These are just the rdata portions of the DNS records, rather than complete
207 // records, but it works well enough for this test.
208 // This record has a bitmap that is 0 bytes long.
209 const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o', 'g',
210 'l', 'e', 0x03, 'c', 'o', 'm', 0x00, 0x00, 0x00};
211
212 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
213 base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
214
215 std::unique_ptr<NsecRecordRdata> record_obj =
216 NsecRecordRdata::Create(record_strpiece, parser);
217 ASSERT_FALSE(record_obj);
218 }
219
TEST(RecordRdataTest,CreateNsecRecordWithOversizedBitmapReturnsNull)220 TEST(RecordRdataTest, CreateNsecRecordWithOversizedBitmapReturnsNull) {
221 // These are just the rdata portions of the DNS records, rather than complete
222 // records, but it works well enough for this test.
223 // This record has a bitmap that is 33 bytes long. The maximum size allowed by
224 // RFC 3845, Section 2.1.2, is 32 bytes.
225 const uint8_t record[] = {
226 0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o', 'g', 'l', 'e',
227 0x03, 'c', 'o', 'm', 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
231
232 DnsRecordParser parser(record, sizeof(record), 0, /*num_records=*/0);
233 base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record));
234
235 std::unique_ptr<NsecRecordRdata> record_obj =
236 NsecRecordRdata::Create(record_strpiece, parser);
237 ASSERT_FALSE(record_obj);
238 }
239
240 } // namespace
241 } // namespace net
242