blob: e6366702b7e7d21355de4086225c9a477812a7b5 [file] [log] [blame]
[email protected]4e09d242013-05-02 03:19:351// Copyright (c) 2013 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/record_rdata.h"
6
Eric Orthbc28a522019-06-04 16:03:567#include <algorithm>
Rob Percivalc2b1a172017-09-25 13:30:428#include <numeric>
9
[email protected]d9806a972014-02-26 18:14:5710#include "base/big_endian.h"
[email protected]4e09d242013-05-02 03:19:3511#include "net/dns/dns_response.h"
Eric Orth8afaf152018-11-07 21:01:2612#include "net/dns/public/dns_protocol.h"
[email protected]4e09d242013-05-02 03:19:3513
14namespace net {
15
16static const size_t kSrvRecordMinimumSize = 6;
17
Qingsi Wangecd69252018-09-27 21:35:5518bool RecordRdata::HasValidSize(const base::StringPiece& data, uint16_t type) {
19 switch (type) {
20 case dns_protocol::kTypeSRV:
21 return data.size() >= kSrvRecordMinimumSize;
22 case dns_protocol::kTypeA:
23 return data.size() == IPAddress::kIPv4AddressSize;
24 case dns_protocol::kTypeAAAA:
25 return data.size() == IPAddress::kIPv6AddressSize;
26 case dns_protocol::kTypeCNAME:
27 case dns_protocol::kTypePTR:
28 case dns_protocol::kTypeTXT:
29 case dns_protocol::kTypeNSEC:
30 case dns_protocol::kTypeOPT:
Eric Orth828bd3ae2018-12-12 17:30:3631 case dns_protocol::kTypeSOA:
Qingsi Wangecd69252018-09-27 21:35:5532 return true;
33 default:
34 VLOG(1) << "Unsupported RDATA type.";
35 return false;
36 }
37}
38
[email protected]4e09d242013-05-02 03:19:3539SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) {
40}
41
Chris Watkins68b15032017-12-01 03:07:1342SrvRecordRdata::~SrvRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:3543
44// static
danakj22f90e72016-04-16 01:55:4045std::unique_ptr<SrvRecordRdata> SrvRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:3546 const base::StringPiece& data,
47 const DnsRecordParser& parser) {
Qingsi Wangecd69252018-09-27 21:35:5548 if (!HasValidSize(data, kType))
danakj22f90e72016-04-16 01:55:4049 return std::unique_ptr<SrvRecordRdata>();
[email protected]4e09d242013-05-02 03:19:3550
danakj22f90e72016-04-16 01:55:4051 std::unique_ptr<SrvRecordRdata> rdata(new SrvRecordRdata);
[email protected]4e09d242013-05-02 03:19:3552
[email protected]d9806a972014-02-26 18:14:5753 base::BigEndianReader reader(data.data(), data.size());
[email protected]4e09d242013-05-02 03:19:3554 // 2 bytes for priority, 2 bytes for weight, 2 bytes for port.
55 reader.ReadU16(&rdata->priority_);
56 reader.ReadU16(&rdata->weight_);
57 reader.ReadU16(&rdata->port_);
58
59 if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(),
60 &rdata->target_))
danakj22f90e72016-04-16 01:55:4061 return std::unique_ptr<SrvRecordRdata>();
[email protected]4e09d242013-05-02 03:19:3562
dchengc7eeda422015-12-26 03:56:4863 return rdata;
[email protected]4e09d242013-05-02 03:19:3564}
65
Avi Drissman13fc8932015-12-20 04:40:4666uint16_t SrvRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:3667 return SrvRecordRdata::kType;
68}
69
70bool SrvRecordRdata::IsEqual(const RecordRdata* other) const {
71 if (other->Type() != Type()) return false;
72 const SrvRecordRdata* srv_other = static_cast<const SrvRecordRdata*>(other);
73 return weight_ == srv_other->weight_ &&
74 port_ == srv_other->port_ &&
75 priority_ == srv_other->priority_ &&
76 target_ == srv_other->target_;
77}
78
Chris Watkins68b15032017-12-01 03:07:1379ARecordRdata::ARecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:3580
Chris Watkins68b15032017-12-01 03:07:1381ARecordRdata::~ARecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:3582
83// static
danakj22f90e72016-04-16 01:55:4084std::unique_ptr<ARecordRdata> ARecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:3585 const base::StringPiece& data,
86 const DnsRecordParser& parser) {
Qingsi Wangecd69252018-09-27 21:35:5587 if (!HasValidSize(data, kType))
danakj22f90e72016-04-16 01:55:4088 return std::unique_ptr<ARecordRdata>();
[email protected]4e09d242013-05-02 03:19:3589
danakj22f90e72016-04-16 01:55:4090 std::unique_ptr<ARecordRdata> rdata(new ARecordRdata);
martijna23c8962016-03-04 18:18:5191 rdata->address_ =
92 IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
dchengc7eeda422015-12-26 03:56:4893 return rdata;
[email protected]4e09d242013-05-02 03:19:3594}
95
Avi Drissman13fc8932015-12-20 04:40:4696uint16_t ARecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:3697 return ARecordRdata::kType;
98}
99
100bool ARecordRdata::IsEqual(const RecordRdata* other) const {
101 if (other->Type() != Type()) return false;
102 const ARecordRdata* a_other = static_cast<const ARecordRdata*>(other);
103 return address_ == a_other->address_;
104}
105
Chris Watkins68b15032017-12-01 03:07:13106AAAARecordRdata::AAAARecordRdata() = default;
[email protected]f6a9add2013-05-23 00:56:36107
Chris Watkins68b15032017-12-01 03:07:13108AAAARecordRdata::~AAAARecordRdata() = default;
[email protected]f6a9add2013-05-23 00:56:36109
110// static
danakj22f90e72016-04-16 01:55:40111std::unique_ptr<AAAARecordRdata> AAAARecordRdata::Create(
[email protected]f6a9add2013-05-23 00:56:36112 const base::StringPiece& data,
113 const DnsRecordParser& parser) {
Qingsi Wangecd69252018-09-27 21:35:55114 if (!HasValidSize(data, kType))
danakj22f90e72016-04-16 01:55:40115 return std::unique_ptr<AAAARecordRdata>();
[email protected]f6a9add2013-05-23 00:56:36116
danakj22f90e72016-04-16 01:55:40117 std::unique_ptr<AAAARecordRdata> rdata(new AAAARecordRdata);
martijna23c8962016-03-04 18:18:51118 rdata->address_ =
119 IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
dchengc7eeda422015-12-26 03:56:48120 return rdata;
[email protected]f6a9add2013-05-23 00:56:36121}
122
Avi Drissman13fc8932015-12-20 04:40:46123uint16_t AAAARecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36124 return AAAARecordRdata::kType;
125}
126
127bool AAAARecordRdata::IsEqual(const RecordRdata* other) const {
128 if (other->Type() != Type()) return false;
129 const AAAARecordRdata* a_other = static_cast<const AAAARecordRdata*>(other);
130 return address_ == a_other->address_;
131}
132
Chris Watkins68b15032017-12-01 03:07:13133CnameRecordRdata::CnameRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35134
Chris Watkins68b15032017-12-01 03:07:13135CnameRecordRdata::~CnameRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35136
137// static
danakj22f90e72016-04-16 01:55:40138std::unique_ptr<CnameRecordRdata> CnameRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35139 const base::StringPiece& data,
140 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40141 std::unique_ptr<CnameRecordRdata> rdata(new CnameRecordRdata);
[email protected]4e09d242013-05-02 03:19:35142
143 if (!parser.ReadName(data.begin(), &rdata->cname_))
danakj22f90e72016-04-16 01:55:40144 return std::unique_ptr<CnameRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35145
dchengc7eeda422015-12-26 03:56:48146 return rdata;
[email protected]4e09d242013-05-02 03:19:35147}
148
Avi Drissman13fc8932015-12-20 04:40:46149uint16_t CnameRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36150 return CnameRecordRdata::kType;
151}
152
153bool CnameRecordRdata::IsEqual(const RecordRdata* other) const {
154 if (other->Type() != Type()) return false;
155 const CnameRecordRdata* cname_other =
156 static_cast<const CnameRecordRdata*>(other);
157 return cname_ == cname_other->cname_;
158}
159
Chris Watkins68b15032017-12-01 03:07:13160PtrRecordRdata::PtrRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35161
Chris Watkins68b15032017-12-01 03:07:13162PtrRecordRdata::~PtrRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35163
164// static
danakj22f90e72016-04-16 01:55:40165std::unique_ptr<PtrRecordRdata> PtrRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35166 const base::StringPiece& data,
167 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40168 std::unique_ptr<PtrRecordRdata> rdata(new PtrRecordRdata);
[email protected]4e09d242013-05-02 03:19:35169
170 if (!parser.ReadName(data.begin(), &rdata->ptrdomain_))
danakj22f90e72016-04-16 01:55:40171 return std::unique_ptr<PtrRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35172
dchengc7eeda422015-12-26 03:56:48173 return rdata;
[email protected]4e09d242013-05-02 03:19:35174}
175
Avi Drissman13fc8932015-12-20 04:40:46176uint16_t PtrRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36177 return PtrRecordRdata::kType;
178}
179
180bool PtrRecordRdata::IsEqual(const RecordRdata* other) const {
181 if (other->Type() != Type()) return false;
182 const PtrRecordRdata* ptr_other = static_cast<const PtrRecordRdata*>(other);
183 return ptrdomain_ == ptr_other->ptrdomain_;
184}
185
Chris Watkins68b15032017-12-01 03:07:13186TxtRecordRdata::TxtRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35187
Chris Watkins68b15032017-12-01 03:07:13188TxtRecordRdata::~TxtRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35189
190// static
danakj22f90e72016-04-16 01:55:40191std::unique_ptr<TxtRecordRdata> TxtRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35192 const base::StringPiece& data,
193 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40194 std::unique_ptr<TxtRecordRdata> rdata(new TxtRecordRdata);
[email protected]4e09d242013-05-02 03:19:35195
196 for (size_t i = 0; i < data.size(); ) {
Avi Drissman13fc8932015-12-20 04:40:46197 uint8_t length = data[i];
[email protected]4e09d242013-05-02 03:19:35198
199 if (i + length >= data.size())
danakj22f90e72016-04-16 01:55:40200 return std::unique_ptr<TxtRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35201
202 rdata->texts_.push_back(data.substr(i + 1, length).as_string());
203
204 // Move to the next string.
205 i += length + 1;
206 }
207
dchengc7eeda422015-12-26 03:56:48208 return rdata;
[email protected]4e09d242013-05-02 03:19:35209}
210
Avi Drissman13fc8932015-12-20 04:40:46211uint16_t TxtRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36212 return TxtRecordRdata::kType;
213}
214
215bool TxtRecordRdata::IsEqual(const RecordRdata* other) const {
216 if (other->Type() != Type()) return false;
217 const TxtRecordRdata* txt_other = static_cast<const TxtRecordRdata*>(other);
218 return texts_ == txt_other->texts_;
219}
220
Chris Watkins68b15032017-12-01 03:07:13221NsecRecordRdata::NsecRecordRdata() = default;
[email protected]7e09a302013-06-26 04:12:30222
Chris Watkins68b15032017-12-01 03:07:13223NsecRecordRdata::~NsecRecordRdata() = default;
[email protected]7e09a302013-06-26 04:12:30224
225// static
danakj22f90e72016-04-16 01:55:40226std::unique_ptr<NsecRecordRdata> NsecRecordRdata::Create(
[email protected]7e09a302013-06-26 04:12:30227 const base::StringPiece& data,
228 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40229 std::unique_ptr<NsecRecordRdata> rdata(new NsecRecordRdata);
[email protected]7e09a302013-06-26 04:12:30230
231 // Read the "next domain". This part for the NSEC record format is
232 // ignored for mDNS, since it has no semantic meaning.
Raul Tambre94493c652019-03-11 17:18:35233 unsigned next_domain_length = parser.ReadName(data.data(), nullptr);
[email protected]7e09a302013-06-26 04:12:30234
235 // If we did not succeed in getting the next domain or the data length
236 // is too short for reading the bitmap header, return.
237 if (next_domain_length == 0 || data.length() < next_domain_length + 2)
danakj22f90e72016-04-16 01:55:40238 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30239
240 struct BitmapHeader {
Avi Drissman13fc8932015-12-20 04:40:46241 uint8_t block_number; // The block number should be zero.
242 uint8_t length; // Bitmap length in bytes. Between 1 and 32.
[email protected]7e09a302013-06-26 04:12:30243 };
244
245 const BitmapHeader* header = reinterpret_cast<const BitmapHeader*>(
246 data.data() + next_domain_length);
247
248 // The block number must be zero in mDns-specific NSEC records. The bitmap
249 // length must be between 1 and 32.
250 if (header->block_number != 0 || header->length == 0 || header->length > 32)
danakj22f90e72016-04-16 01:55:40251 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30252
253 base::StringPiece bitmap_data = data.substr(next_domain_length + 2);
254
255 // Since we may only have one block, the data length must be exactly equal to
256 // the domain length plus bitmap size.
257 if (bitmap_data.length() != header->length)
danakj22f90e72016-04-16 01:55:40258 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30259
260 rdata->bitmap_.insert(rdata->bitmap_.begin(),
261 bitmap_data.begin(),
262 bitmap_data.end());
263
dchengc7eeda422015-12-26 03:56:48264 return rdata;
[email protected]7e09a302013-06-26 04:12:30265}
266
Avi Drissman13fc8932015-12-20 04:40:46267uint16_t NsecRecordRdata::Type() const {
[email protected]7e09a302013-06-26 04:12:30268 return NsecRecordRdata::kType;
269}
270
271bool NsecRecordRdata::IsEqual(const RecordRdata* other) const {
272 if (other->Type() != Type())
273 return false;
274 const NsecRecordRdata* nsec_other =
275 static_cast<const NsecRecordRdata*>(other);
276 return bitmap_ == nsec_other->bitmap_;
277}
278
279bool NsecRecordRdata::GetBit(unsigned i) const {
280 unsigned byte_num = i/8;
281 if (bitmap_.size() < byte_num + 1)
282 return false;
283
284 unsigned bit_num = 7 - i % 8;
285 return (bitmap_[byte_num] & (1 << bit_num)) != 0;
286}
287
Chris Watkins68b15032017-12-01 03:07:13288OptRecordRdata::OptRecordRdata() = default;
Rob Percivalc2b1a172017-09-25 13:30:42289
Eric Orthbc28a522019-06-04 16:03:56290OptRecordRdata::OptRecordRdata(OptRecordRdata&& other) = default;
291
Chris Watkins68b15032017-12-01 03:07:13292OptRecordRdata::~OptRecordRdata() = default;
Rob Percivalc2b1a172017-09-25 13:30:42293
Eric Orthbc28a522019-06-04 16:03:56294OptRecordRdata& OptRecordRdata::operator=(OptRecordRdata&& other) = default;
295
Rob Percivalc2b1a172017-09-25 13:30:42296// static
297std::unique_ptr<OptRecordRdata> OptRecordRdata::Create(
298 const base::StringPiece& data,
299 const DnsRecordParser& parser) {
300 std::unique_ptr<OptRecordRdata> rdata(new OptRecordRdata);
301 rdata->buf_.assign(data.begin(), data.end());
302
303 base::BigEndianReader reader(data.data(), data.size());
304 while (reader.remaining() > 0) {
305 uint16_t opt_code, opt_data_size;
306 base::StringPiece opt_data;
307
308 if (!(reader.ReadU16(&opt_code) && reader.ReadU16(&opt_data_size) &&
309 reader.ReadPiece(&opt_data, opt_data_size))) {
310 return std::unique_ptr<OptRecordRdata>();
311 }
312 rdata->opts_.push_back(Opt(opt_code, opt_data));
313 }
314
315 return rdata;
316}
317
318uint16_t OptRecordRdata::Type() const {
319 return OptRecordRdata::kType;
320}
321
322bool OptRecordRdata::IsEqual(const RecordRdata* other) const {
323 if (other->Type() != Type())
324 return false;
325 const OptRecordRdata* opt_other = static_cast<const OptRecordRdata*>(other);
326 return opt_other->opts_ == opts_;
327}
328
329void OptRecordRdata::AddOpt(const Opt& opt) {
330 base::StringPiece opt_data = opt.data();
331
332 // Resize buffer to accommodate new OPT.
333 const size_t orig_rdata_size = buf_.size();
334 buf_.resize(orig_rdata_size + Opt::kHeaderSize + opt_data.size());
335
336 // Start writing from the end of the existing rdata.
337 base::BigEndianWriter writer(buf_.data() + orig_rdata_size, buf_.size());
338 bool success = writer.WriteU16(opt.code()) &&
339 writer.WriteU16(opt_data.size()) &&
340 writer.WriteBytes(opt_data.data(), opt_data.size());
341 DCHECK(success);
342
343 opts_.push_back(opt);
344}
345
Eric Orthbc28a522019-06-04 16:03:56346void OptRecordRdata::AddOpts(const OptRecordRdata& other) {
347 buf_.insert(buf_.end(), other.buf_.begin(), other.buf_.end());
348 opts_.insert(opts_.end(), other.opts_.begin(), other.opts_.end());
349}
350
351bool OptRecordRdata::ContainsOptCode(uint16_t opt_code) const {
352 return std::any_of(
353 opts_.begin(), opts_.end(),
354 [=](const OptRecordRdata::Opt& opt) { return opt.code() == opt_code; });
355}
356
Rob Percivalc2b1a172017-09-25 13:30:42357OptRecordRdata::Opt::Opt(uint16_t code, base::StringPiece data) : code_(code) {
358 data.CopyToString(&data_);
359}
360
361bool OptRecordRdata::Opt::operator==(const OptRecordRdata::Opt& other) const {
362 return code_ == other.code_ && data_ == other.data_;
363}
364
[email protected]4e09d242013-05-02 03:19:35365} // namespace net