blob: d413f4eda91b17206621b25b8e16225874e20a62 [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
[email protected]d9806a972014-02-26 18:14:577#include "base/big_endian.h"
eromanc9a6b722015-06-03 22:19:008#include "net/base/ip_address_number.h"
[email protected]4e09d242013-05-02 03:19:359#include "net/dns/dns_protocol.h"
10#include "net/dns/dns_response.h"
11
12namespace net {
13
14static const size_t kSrvRecordMinimumSize = 6;
15
16RecordRdata::RecordRdata() {
17}
18
19SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) {
20}
21
22SrvRecordRdata::~SrvRecordRdata() {}
23
24// static
danakj22f90e72016-04-16 01:55:4025std::unique_ptr<SrvRecordRdata> SrvRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:3526 const base::StringPiece& data,
27 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:4028 if (data.size() < kSrvRecordMinimumSize)
29 return std::unique_ptr<SrvRecordRdata>();
[email protected]4e09d242013-05-02 03:19:3530
danakj22f90e72016-04-16 01:55:4031 std::unique_ptr<SrvRecordRdata> rdata(new SrvRecordRdata);
[email protected]4e09d242013-05-02 03:19:3532
[email protected]d9806a972014-02-26 18:14:5733 base::BigEndianReader reader(data.data(), data.size());
[email protected]4e09d242013-05-02 03:19:3534 // 2 bytes for priority, 2 bytes for weight, 2 bytes for port.
35 reader.ReadU16(&rdata->priority_);
36 reader.ReadU16(&rdata->weight_);
37 reader.ReadU16(&rdata->port_);
38
39 if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(),
40 &rdata->target_))
danakj22f90e72016-04-16 01:55:4041 return std::unique_ptr<SrvRecordRdata>();
[email protected]4e09d242013-05-02 03:19:3542
dchengc7eeda422015-12-26 03:56:4843 return rdata;
[email protected]4e09d242013-05-02 03:19:3544}
45
Avi Drissman13fc8932015-12-20 04:40:4646uint16_t SrvRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:3647 return SrvRecordRdata::kType;
48}
49
50bool SrvRecordRdata::IsEqual(const RecordRdata* other) const {
51 if (other->Type() != Type()) return false;
52 const SrvRecordRdata* srv_other = static_cast<const SrvRecordRdata*>(other);
53 return weight_ == srv_other->weight_ &&
54 port_ == srv_other->port_ &&
55 priority_ == srv_other->priority_ &&
56 target_ == srv_other->target_;
57}
58
[email protected]4e09d242013-05-02 03:19:3559ARecordRdata::ARecordRdata() {
60}
61
62ARecordRdata::~ARecordRdata() {
63}
64
65// static
danakj22f90e72016-04-16 01:55:4066std::unique_ptr<ARecordRdata> ARecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:3567 const base::StringPiece& data,
68 const DnsRecordParser& parser) {
martijna23c8962016-03-04 18:18:5169 if (data.size() != IPAddress::kIPv4AddressSize)
danakj22f90e72016-04-16 01:55:4070 return std::unique_ptr<ARecordRdata>();
[email protected]4e09d242013-05-02 03:19:3571
danakj22f90e72016-04-16 01:55:4072 std::unique_ptr<ARecordRdata> rdata(new ARecordRdata);
martijna23c8962016-03-04 18:18:5173 rdata->address_ =
74 IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
dchengc7eeda422015-12-26 03:56:4875 return rdata;
[email protected]4e09d242013-05-02 03:19:3576}
77
Avi Drissman13fc8932015-12-20 04:40:4678uint16_t ARecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:3679 return ARecordRdata::kType;
80}
81
82bool ARecordRdata::IsEqual(const RecordRdata* other) const {
83 if (other->Type() != Type()) return false;
84 const ARecordRdata* a_other = static_cast<const ARecordRdata*>(other);
85 return address_ == a_other->address_;
86}
87
88AAAARecordRdata::AAAARecordRdata() {
89}
90
91AAAARecordRdata::~AAAARecordRdata() {
92}
93
94// static
danakj22f90e72016-04-16 01:55:4095std::unique_ptr<AAAARecordRdata> AAAARecordRdata::Create(
[email protected]f6a9add2013-05-23 00:56:3696 const base::StringPiece& data,
97 const DnsRecordParser& parser) {
martijna23c8962016-03-04 18:18:5198 if (data.size() != IPAddress::kIPv6AddressSize)
danakj22f90e72016-04-16 01:55:4099 return std::unique_ptr<AAAARecordRdata>();
[email protected]f6a9add2013-05-23 00:56:36100
danakj22f90e72016-04-16 01:55:40101 std::unique_ptr<AAAARecordRdata> rdata(new AAAARecordRdata);
martijna23c8962016-03-04 18:18:51102 rdata->address_ =
103 IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
dchengc7eeda422015-12-26 03:56:48104 return rdata;
[email protected]f6a9add2013-05-23 00:56:36105}
106
Avi Drissman13fc8932015-12-20 04:40:46107uint16_t AAAARecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36108 return AAAARecordRdata::kType;
109}
110
111bool AAAARecordRdata::IsEqual(const RecordRdata* other) const {
112 if (other->Type() != Type()) return false;
113 const AAAARecordRdata* a_other = static_cast<const AAAARecordRdata*>(other);
114 return address_ == a_other->address_;
115}
116
[email protected]4e09d242013-05-02 03:19:35117CnameRecordRdata::CnameRecordRdata() {
118}
119
120CnameRecordRdata::~CnameRecordRdata() {
121}
122
123// static
danakj22f90e72016-04-16 01:55:40124std::unique_ptr<CnameRecordRdata> CnameRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35125 const base::StringPiece& data,
126 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40127 std::unique_ptr<CnameRecordRdata> rdata(new CnameRecordRdata);
[email protected]4e09d242013-05-02 03:19:35128
129 if (!parser.ReadName(data.begin(), &rdata->cname_))
danakj22f90e72016-04-16 01:55:40130 return std::unique_ptr<CnameRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35131
dchengc7eeda422015-12-26 03:56:48132 return rdata;
[email protected]4e09d242013-05-02 03:19:35133}
134
Avi Drissman13fc8932015-12-20 04:40:46135uint16_t CnameRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36136 return CnameRecordRdata::kType;
137}
138
139bool CnameRecordRdata::IsEqual(const RecordRdata* other) const {
140 if (other->Type() != Type()) return false;
141 const CnameRecordRdata* cname_other =
142 static_cast<const CnameRecordRdata*>(other);
143 return cname_ == cname_other->cname_;
144}
145
[email protected]4e09d242013-05-02 03:19:35146PtrRecordRdata::PtrRecordRdata() {
147}
148
149PtrRecordRdata::~PtrRecordRdata() {
150}
151
152// static
danakj22f90e72016-04-16 01:55:40153std::unique_ptr<PtrRecordRdata> PtrRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35154 const base::StringPiece& data,
155 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40156 std::unique_ptr<PtrRecordRdata> rdata(new PtrRecordRdata);
[email protected]4e09d242013-05-02 03:19:35157
158 if (!parser.ReadName(data.begin(), &rdata->ptrdomain_))
danakj22f90e72016-04-16 01:55:40159 return std::unique_ptr<PtrRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35160
dchengc7eeda422015-12-26 03:56:48161 return rdata;
[email protected]4e09d242013-05-02 03:19:35162}
163
Avi Drissman13fc8932015-12-20 04:40:46164uint16_t PtrRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36165 return PtrRecordRdata::kType;
166}
167
168bool PtrRecordRdata::IsEqual(const RecordRdata* other) const {
169 if (other->Type() != Type()) return false;
170 const PtrRecordRdata* ptr_other = static_cast<const PtrRecordRdata*>(other);
171 return ptrdomain_ == ptr_other->ptrdomain_;
172}
173
[email protected]4e09d242013-05-02 03:19:35174TxtRecordRdata::TxtRecordRdata() {
175}
176
177TxtRecordRdata::~TxtRecordRdata() {
178}
179
180// static
danakj22f90e72016-04-16 01:55:40181std::unique_ptr<TxtRecordRdata> TxtRecordRdata::Create(
[email protected]4e09d242013-05-02 03:19:35182 const base::StringPiece& data,
183 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40184 std::unique_ptr<TxtRecordRdata> rdata(new TxtRecordRdata);
[email protected]4e09d242013-05-02 03:19:35185
186 for (size_t i = 0; i < data.size(); ) {
Avi Drissman13fc8932015-12-20 04:40:46187 uint8_t length = data[i];
[email protected]4e09d242013-05-02 03:19:35188
189 if (i + length >= data.size())
danakj22f90e72016-04-16 01:55:40190 return std::unique_ptr<TxtRecordRdata>();
[email protected]4e09d242013-05-02 03:19:35191
192 rdata->texts_.push_back(data.substr(i + 1, length).as_string());
193
194 // Move to the next string.
195 i += length + 1;
196 }
197
dchengc7eeda422015-12-26 03:56:48198 return rdata;
[email protected]4e09d242013-05-02 03:19:35199}
200
Avi Drissman13fc8932015-12-20 04:40:46201uint16_t TxtRecordRdata::Type() const {
[email protected]f6a9add2013-05-23 00:56:36202 return TxtRecordRdata::kType;
203}
204
205bool TxtRecordRdata::IsEqual(const RecordRdata* other) const {
206 if (other->Type() != Type()) return false;
207 const TxtRecordRdata* txt_other = static_cast<const TxtRecordRdata*>(other);
208 return texts_ == txt_other->texts_;
209}
210
[email protected]7e09a302013-06-26 04:12:30211NsecRecordRdata::NsecRecordRdata() {
212}
213
214NsecRecordRdata::~NsecRecordRdata() {
215}
216
217// static
danakj22f90e72016-04-16 01:55:40218std::unique_ptr<NsecRecordRdata> NsecRecordRdata::Create(
[email protected]7e09a302013-06-26 04:12:30219 const base::StringPiece& data,
220 const DnsRecordParser& parser) {
danakj22f90e72016-04-16 01:55:40221 std::unique_ptr<NsecRecordRdata> rdata(new NsecRecordRdata);
[email protected]7e09a302013-06-26 04:12:30222
223 // Read the "next domain". This part for the NSEC record format is
224 // ignored for mDNS, since it has no semantic meaning.
225 unsigned next_domain_length = parser.ReadName(data.data(), NULL);
226
227 // If we did not succeed in getting the next domain or the data length
228 // is too short for reading the bitmap header, return.
229 if (next_domain_length == 0 || data.length() < next_domain_length + 2)
danakj22f90e72016-04-16 01:55:40230 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30231
232 struct BitmapHeader {
Avi Drissman13fc8932015-12-20 04:40:46233 uint8_t block_number; // The block number should be zero.
234 uint8_t length; // Bitmap length in bytes. Between 1 and 32.
[email protected]7e09a302013-06-26 04:12:30235 };
236
237 const BitmapHeader* header = reinterpret_cast<const BitmapHeader*>(
238 data.data() + next_domain_length);
239
240 // The block number must be zero in mDns-specific NSEC records. The bitmap
241 // length must be between 1 and 32.
242 if (header->block_number != 0 || header->length == 0 || header->length > 32)
danakj22f90e72016-04-16 01:55:40243 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30244
245 base::StringPiece bitmap_data = data.substr(next_domain_length + 2);
246
247 // Since we may only have one block, the data length must be exactly equal to
248 // the domain length plus bitmap size.
249 if (bitmap_data.length() != header->length)
danakj22f90e72016-04-16 01:55:40250 return std::unique_ptr<NsecRecordRdata>();
[email protected]7e09a302013-06-26 04:12:30251
252 rdata->bitmap_.insert(rdata->bitmap_.begin(),
253 bitmap_data.begin(),
254 bitmap_data.end());
255
dchengc7eeda422015-12-26 03:56:48256 return rdata;
[email protected]7e09a302013-06-26 04:12:30257}
258
Avi Drissman13fc8932015-12-20 04:40:46259uint16_t NsecRecordRdata::Type() const {
[email protected]7e09a302013-06-26 04:12:30260 return NsecRecordRdata::kType;
261}
262
263bool NsecRecordRdata::IsEqual(const RecordRdata* other) const {
264 if (other->Type() != Type())
265 return false;
266 const NsecRecordRdata* nsec_other =
267 static_cast<const NsecRecordRdata*>(other);
268 return bitmap_ == nsec_other->bitmap_;
269}
270
271bool NsecRecordRdata::GetBit(unsigned i) const {
272 unsigned byte_num = i/8;
273 if (bitmap_.size() < byte_num + 1)
274 return false;
275
276 unsigned bit_num = 7 - i % 8;
277 return (bitmap_[byte_num] & (1 << bit_num)) != 0;
278}
279
[email protected]4e09d242013-05-02 03:19:35280} // namespace net