blob: 87c707ef3f85e9760e5928754ec0e36212b5a7fe [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
Rob Percivalc2b1a172017-09-25 13:30:427#include <numeric>
8
[email protected]d9806a972014-02-26 18:14:579#include "base/big_endian.h"
[email protected]4e09d242013-05-02 03:19:3510#include "net/dns/dns_response.h"
Eric Orth8afaf152018-11-07 21:01:2611#include "net/dns/public/dns_protocol.h"
[email protected]4e09d242013-05-02 03:19:3512
13namespace net {
14
15static const size_t kSrvRecordMinimumSize = 6;
16
Chris Watkins68b15032017-12-01 03:07:1317RecordRdata::RecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:3518
Qingsi Wangecd69252018-09-27 21:35:5519bool RecordRdata::HasValidSize(const base::StringPiece& data, uint16_t type) {
20 switch (type) {
21 case dns_protocol::kTypeSRV:
22 return data.size() >= kSrvRecordMinimumSize;
23 case dns_protocol::kTypeA:
24 return data.size() == IPAddress::kIPv4AddressSize;
25 case dns_protocol::kTypeAAAA:
26 return data.size() == IPAddress::kIPv6AddressSize;
27 case dns_protocol::kTypeCNAME:
28 case dns_protocol::kTypePTR:
29 case dns_protocol::kTypeTXT:
30 case dns_protocol::kTypeNSEC:
31 case dns_protocol::kTypeOPT:
Eric Orth828bd3ae2018-12-12 17:30:3632 case dns_protocol::kTypeSOA:
Qingsi Wangecd69252018-09-27 21:35:5533 return true;
34 default:
35 VLOG(1) << "Unsupported RDATA type.";
36 return false;
37 }
38}
39
[email protected]4e09d242013-05-02 03:19:3540SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) {
41}
42
Chris Watkins68b15032017-12-01 03:07:1343SrvRecordRdata::~SrvRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:3544
45// static
danakj22f90e72016-04-16 01:55:4046std::unique_ptr<SrvRecordRdata> SrvRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:3547 const base::StringPiece& data,
48 const DnsRecordParser& parser) {
Qingsi Wangecd69252018-09-27 21:35:5549 if (!HasValidSize(data, kType))
danakj22f90e72016-04-16 01:55:4050 return std::unique_ptr<SrvRecordRdata>();
[email protected]4e09d242013-05-02 03:19:3551
danakj22f90e72016-04-16 01:55:4052 std::unique_ptr<SrvRecordRdata> rdata(new SrvRecordRdata);
[email protected]4e09d242013-05-02 03:19:3553
[email protected]d9806a972014-02-26 18:14:5754 base::BigEndianReader reader(data.data(), data.size());
[email protected]4e09d242013-05-02 03:19:3555 // 2 bytes for priority, 2 bytes for weight, 2 bytes for port.
56 reader.ReadU16(&rdata->priority_);
57 reader.ReadU16(&rdata->weight_);
58 reader.ReadU16(&rdata->port_);
59
60 if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(),
61 &rdata->target_))
danakj22f90e72016-04-16 01:55:4062 return std::unique_ptr<SrvRecordRdata>();
[email protected]4e09d242013-05-02 03:19:3563
dchengc7eeda422015-12-26 03:56:4864 return rdata;
[email protected]4e09d242013-05-02 03:19:3565}
66
Avi Drissman13fc8932015-12-20 04:40:4667uint16_t SrvRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:3668 return SrvRecordRdata::kType;
69}
70
71bool SrvRecordRdata::IsEqual(const RecordRdata* other) const {
72 if (other->Type() != Type()) return false;
73 const SrvRecordRdata* srv_other = static_cast<const SrvRecordRdata*>(other);
74 return weight_ == srv_other->weight_ &&
75 port_ == srv_other->port_ &&
76 priority_ == srv_other->priority_ &&
77 target_ == srv_other->target_;
78}
79
Chris Watkins68b15032017-12-01 03:07:1380ARecordRdata::ARecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:3581
Chris Watkins68b15032017-12-01 03:07:1382ARecordRdata::~ARecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:3583
84// static
danakj22f90e72016-04-16 01:55:4085std::unique_ptr<ARecordRdata> ARecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:3586 const base::StringPiece& data,
87 const DnsRecordParser& parser) {
Qingsi Wangecd69252018-09-27 21:35:5588 if (!HasValidSize(data, kType))
danakj22f90e72016-04-16 01:55:4089 return std::unique_ptr<ARecordRdata>();
[email protected]4e09d242013-05-02 03:19:3590
danakj22f90e72016-04-16 01:55:4091 std::unique_ptr<ARecordRdata> rdata(new ARecordRdata);
martijna23c8962016-03-04 18:18:5192 rdata->address_ =
93 IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
dchengc7eeda422015-12-26 03:56:4894 return rdata;
[email protected]4e09d242013-05-02 03:19:3595}
96
Avi Drissman13fc8932015-12-20 04:40:4697uint16_t ARecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:3698 return ARecordRdata::kType;
99}
100
101bool ARecordRdata::IsEqual(const RecordRdata* other) const {
102 if (other->Type() != Type()) return false;
103 const ARecordRdata* a_other = static_cast<const ARecordRdata*>(other);
104 return address_ == a_other->address_;
105}
106
Chris Watkins68b15032017-12-01 03:07:13107AAAARecordRdata::AAAARecordRdata() = default;
[email protected]f6a9add2013-05-23 00:56:36108
Chris Watkins68b15032017-12-01 03:07:13109AAAARecordRdata::~AAAARecordRdata() = default;
[email protected]f6a9add2013-05-23 00:56:36110
111// static
danakj22f90e72016-04-16 01:55:40112std::unique_ptr<AAAARecordRdata> AAAARecordRdata::Create(
[email protected]f6a9add2013-05-23 00:56:36113 const base::StringPiece& data,
114 const DnsRecordParser& parser) {
Qingsi Wangecd69252018-09-27 21:35:55115 if (!HasValidSize(data, kType))
danakj22f90e72016-04-16 01:55:40116 return std::unique_ptr<AAAARecordRdata>();
[email protected]f6a9add2013-05-23 00:56:36117
danakj22f90e72016-04-16 01:55:40118 std::unique_ptr<AAAARecordRdata> rdata(new AAAARecordRdata);
martijna23c8962016-03-04 18:18:51119 rdata->address_ =
120 IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
dchengc7eeda422015-12-26 03:56:48121 return rdata;
[email protected]f6a9add2013-05-23 00:56:36122}
123
Avi Drissman13fc8932015-12-20 04:40:46124uint16_t AAAARecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36125 return AAAARecordRdata::kType;
126}
127
128bool AAAARecordRdata::IsEqual(const RecordRdata* other) const {
129 if (other->Type() != Type()) return false;
130 const AAAARecordRdata* a_other = static_cast<const AAAARecordRdata*>(other);
131 return address_ == a_other->address_;
132}
133
Chris Watkins68b15032017-12-01 03:07:13134CnameRecordRdata::CnameRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35135
Chris Watkins68b15032017-12-01 03:07:13136CnameRecordRdata::~CnameRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35137
138// static
danakj22f90e72016-04-16 01:55:40139std::unique_ptr<CnameRecordRdata> CnameRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35140 const base::StringPiece& data,
141 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40142 std::unique_ptr<CnameRecordRdata> rdata(new CnameRecordRdata);
[email protected]4e09d242013-05-02 03:19:35143
144 if (!parser.ReadName(data.begin(), &rdata->cname_))
danakj22f90e72016-04-16 01:55:40145 return std::unique_ptr<CnameRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35146
dchengc7eeda422015-12-26 03:56:48147 return rdata;
[email protected]4e09d242013-05-02 03:19:35148}
149
Avi Drissman13fc8932015-12-20 04:40:46150uint16_t CnameRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36151 return CnameRecordRdata::kType;
152}
153
154bool CnameRecordRdata::IsEqual(const RecordRdata* other) const {
155 if (other->Type() != Type()) return false;
156 const CnameRecordRdata* cname_other =
157 static_cast<const CnameRecordRdata*>(other);
158 return cname_ == cname_other->cname_;
159}
160
Chris Watkins68b15032017-12-01 03:07:13161PtrRecordRdata::PtrRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35162
Chris Watkins68b15032017-12-01 03:07:13163PtrRecordRdata::~PtrRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35164
165// static
danakj22f90e72016-04-16 01:55:40166std::unique_ptr<PtrRecordRdata> PtrRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35167 const base::StringPiece& data,
168 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40169 std::unique_ptr<PtrRecordRdata> rdata(new PtrRecordRdata);
[email protected]4e09d242013-05-02 03:19:35170
171 if (!parser.ReadName(data.begin(), &rdata->ptrdomain_))
danakj22f90e72016-04-16 01:55:40172 return std::unique_ptr<PtrRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35173
dchengc7eeda422015-12-26 03:56:48174 return rdata;
[email protected]4e09d242013-05-02 03:19:35175}
176
Avi Drissman13fc8932015-12-20 04:40:46177uint16_t PtrRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36178 return PtrRecordRdata::kType;
179}
180
181bool PtrRecordRdata::IsEqual(const RecordRdata* other) const {
182 if (other->Type() != Type()) return false;
183 const PtrRecordRdata* ptr_other = static_cast<const PtrRecordRdata*>(other);
184 return ptrdomain_ == ptr_other->ptrdomain_;
185}
186
Chris Watkins68b15032017-12-01 03:07:13187TxtRecordRdata::TxtRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35188
Chris Watkins68b15032017-12-01 03:07:13189TxtRecordRdata::~TxtRecordRdata() = default;
[email protected]4e09d242013-05-02 03:19:35190
191// static
danakj22f90e72016-04-16 01:55:40192std::unique_ptr<TxtRecordRdata> TxtRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35193 const base::StringPiece& data,
194 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40195 std::unique_ptr<TxtRecordRdata> rdata(new TxtRecordRdata);
[email protected]4e09d242013-05-02 03:19:35196
197 for (size_t i = 0; i < data.size(); ) {
Avi Drissman13fc8932015-12-20 04:40:46198 uint8_t length = data[i];
[email protected]4e09d242013-05-02 03:19:35199
200 if (i + length >= data.size())
danakj22f90e72016-04-16 01:55:40201 return std::unique_ptr<TxtRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35202
203 rdata->texts_.push_back(data.substr(i + 1, length).as_string());
204
205 // Move to the next string.
206 i += length + 1;
207 }
208
dchengc7eeda422015-12-26 03:56:48209 return rdata;
[email protected]4e09d242013-05-02 03:19:35210}
211
Avi Drissman13fc8932015-12-20 04:40:46212uint16_t TxtRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36213 return TxtRecordRdata::kType;
214}
215
216bool TxtRecordRdata::IsEqual(const RecordRdata* other) const {
217 if (other->Type() != Type()) return false;
218 const TxtRecordRdata* txt_other = static_cast<const TxtRecordRdata*>(other);
219 return texts_ == txt_other->texts_;
220}
221
Chris Watkins68b15032017-12-01 03:07:13222NsecRecordRdata::NsecRecordRdata() = default;
[email protected]7e09a302013-06-26 04:12:30223
Chris Watkins68b15032017-12-01 03:07:13224NsecRecordRdata::~NsecRecordRdata() = default;
[email protected]7e09a302013-06-26 04:12:30225
226// static
danakj22f90e72016-04-16 01:55:40227std::unique_ptr<NsecRecordRdata> NsecRecordRdata::Create(
[email protected]7e09a302013-06-26 04:12:30228 const base::StringPiece& data,
229 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40230 std::unique_ptr<NsecRecordRdata> rdata(new NsecRecordRdata);
[email protected]7e09a302013-06-26 04:12:30231
232 // Read the "next domain". This part for the NSEC record format is
233 // ignored for mDNS, since it has no semantic meaning.
Raul Tambre94493c652019-03-11 17:18:35234 unsigned next_domain_length = parser.ReadName(data.data(), nullptr);
[email protected]7e09a302013-06-26 04:12:30235
236 // If we did not succeed in getting the next domain or the data length
237 // is too short for reading the bitmap header, return.
238 if (next_domain_length == 0 || data.length() < next_domain_length + 2)
danakj22f90e72016-04-16 01:55:40239 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30240
241 struct BitmapHeader {
Avi Drissman13fc8932015-12-20 04:40:46242 uint8_t block_number; // The block number should be zero.
243 uint8_t length; // Bitmap length in bytes. Between 1 and 32.
[email protected]7e09a302013-06-26 04:12:30244 };
245
246 const BitmapHeader* header = reinterpret_cast<const BitmapHeader*>(
247 data.data() + next_domain_length);
248
249 // The block number must be zero in mDns-specific NSEC records. The bitmap
250 // length must be between 1 and 32.
251 if (header->block_number != 0 || header->length == 0 || header->length > 32)
danakj22f90e72016-04-16 01:55:40252 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30253
254 base::StringPiece bitmap_data = data.substr(next_domain_length + 2);
255
256 // Since we may only have one block, the data length must be exactly equal to
257 // the domain length plus bitmap size.
258 if (bitmap_data.length() != header->length)
danakj22f90e72016-04-16 01:55:40259 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30260
261 rdata->bitmap_.insert(rdata->bitmap_.begin(),
262 bitmap_data.begin(),
263 bitmap_data.end());
264
dchengc7eeda422015-12-26 03:56:48265 return rdata;
[email protected]7e09a302013-06-26 04:12:30266}
267
Avi Drissman13fc8932015-12-20 04:40:46268uint16_t NsecRecordRdata::Type() const {
[email protected]7e09a302013-06-26 04:12:30269 return NsecRecordRdata::kType;
270}
271
272bool NsecRecordRdata::IsEqual(const RecordRdata* other) const {
273 if (other->Type() != Type())
274 return false;
275 const NsecRecordRdata* nsec_other =
276 static_cast<const NsecRecordRdata*>(other);
277 return bitmap_ == nsec_other->bitmap_;
278}
279
280bool NsecRecordRdata::GetBit(unsigned i) const {
281 unsigned byte_num = i/8;
282 if (bitmap_.size() < byte_num + 1)
283 return false;
284
285 unsigned bit_num = 7 - i % 8;
286 return (bitmap_[byte_num] & (1 << bit_num)) != 0;
287}
288
Chris Watkins68b15032017-12-01 03:07:13289OptRecordRdata::OptRecordRdata() = default;
Rob Percivalc2b1a172017-09-25 13:30:42290
Chris Watkins68b15032017-12-01 03:07:13291OptRecordRdata::~OptRecordRdata() = default;
Rob Percivalc2b1a172017-09-25 13:30:42292
293// static
294std::unique_ptr<OptRecordRdata> OptRecordRdata::Create(
295 const base::StringPiece& data,
296 const DnsRecordParser& parser) {
297 std::unique_ptr<OptRecordRdata> rdata(new OptRecordRdata);
298 rdata->buf_.assign(data.begin(), data.end());
299
300 base::BigEndianReader reader(data.data(), data.size());
301 while (reader.remaining() > 0) {
302 uint16_t opt_code, opt_data_size;
303 base::StringPiece opt_data;
304
305 if (!(reader.ReadU16(&opt_code) && reader.ReadU16(&opt_data_size) &&
306 reader.ReadPiece(&opt_data, opt_data_size))) {
307 return std::unique_ptr<OptRecordRdata>();
308 }
309 rdata->opts_.push_back(Opt(opt_code, opt_data));
310 }
311
312 return rdata;
313}
314
315uint16_t OptRecordRdata::Type() const {
316 return OptRecordRdata::kType;
317}
318
319bool OptRecordRdata::IsEqual(const RecordRdata* other) const {
320 if (other->Type() != Type())
321 return false;
322 const OptRecordRdata* opt_other = static_cast<const OptRecordRdata*>(other);
323 return opt_other->opts_ == opts_;
324}
325
326void OptRecordRdata::AddOpt(const Opt& opt) {
327 base::StringPiece opt_data = opt.data();
328
329 // Resize buffer to accommodate new OPT.
330 const size_t orig_rdata_size = buf_.size();
331 buf_.resize(orig_rdata_size + Opt::kHeaderSize + opt_data.size());
332
333 // Start writing from the end of the existing rdata.
334 base::BigEndianWriter writer(buf_.data() + orig_rdata_size, buf_.size());
335 bool success = writer.WriteU16(opt.code()) &&
336 writer.WriteU16(opt_data.size()) &&
337 writer.WriteBytes(opt_data.data(), opt_data.size());
338 DCHECK(success);
339
340 opts_.push_back(opt);
341}
342
343OptRecordRdata::Opt::Opt(uint16_t code, base::StringPiece data) : code_(code) {
344 data.CopyToString(&data_);
345}
346
347bool OptRecordRdata::Opt::operator==(const OptRecordRdata::Opt& other) const {
348 return code_ == other.code_ && data_ == other.data_;
349}
350
[email protected]4e09d242013-05-02 03:19:35351} // namespace net