Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / dns / record_rdata.cc
blob193d91cb19db07c3ff067848a1acee2a935c6cfe
1 // 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.
5 #include "net/dns/record_rdata.h"
7 #include "base/big_endian.h"
8 #include "net/base/dns_util.h"
9 #include "net/base/ip_address_number.h"
10 #include "net/dns/dns_protocol.h"
11 #include "net/dns/dns_response.h"
13 namespace net {
15 static const size_t kSrvRecordMinimumSize = 6;
17 RecordRdata::RecordRdata() {
20 SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) {
23 SrvRecordRdata::~SrvRecordRdata() {}
25 // static
26 scoped_ptr<SrvRecordRdata> SrvRecordRdata::Create(
27 const base::StringPiece& data,
28 const DnsRecordParser& parser) {
29 if (data.size() < kSrvRecordMinimumSize) return scoped_ptr<SrvRecordRdata>();
31 scoped_ptr<SrvRecordRdata> rdata(new SrvRecordRdata);
33 base::BigEndianReader reader(data.data(), data.size());
34 // 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_);
39 if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(),
40 &rdata->target_))
41 return scoped_ptr<SrvRecordRdata>();
43 return rdata.Pass();
46 uint16 SrvRecordRdata::Type() const {
47 return SrvRecordRdata::kType;
50 bool 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_;
59 ARecordRdata::ARecordRdata() {
62 ARecordRdata::~ARecordRdata() {
65 // static
66 scoped_ptr<ARecordRdata> ARecordRdata::Create(
67 const base::StringPiece& data,
68 const DnsRecordParser& parser) {
69 if (data.size() != kIPv4AddressSize)
70 return scoped_ptr<ARecordRdata>();
72 scoped_ptr<ARecordRdata> rdata(new ARecordRdata);
74 rdata->address_.resize(kIPv4AddressSize);
75 for (unsigned i = 0; i < kIPv4AddressSize; ++i) {
76 rdata->address_[i] = data[i];
79 return rdata.Pass();
82 uint16 ARecordRdata::Type() const {
83 return ARecordRdata::kType;
86 bool ARecordRdata::IsEqual(const RecordRdata* other) const {
87 if (other->Type() != Type()) return false;
88 const ARecordRdata* a_other = static_cast<const ARecordRdata*>(other);
89 return address_ == a_other->address_;
92 AAAARecordRdata::AAAARecordRdata() {
95 AAAARecordRdata::~AAAARecordRdata() {
98 // static
99 scoped_ptr<AAAARecordRdata> AAAARecordRdata::Create(
100 const base::StringPiece& data,
101 const DnsRecordParser& parser) {
102 if (data.size() != kIPv6AddressSize)
103 return scoped_ptr<AAAARecordRdata>();
105 scoped_ptr<AAAARecordRdata> rdata(new AAAARecordRdata);
107 rdata->address_.resize(kIPv6AddressSize);
108 for (unsigned i = 0; i < kIPv6AddressSize; ++i) {
109 rdata->address_[i] = data[i];
112 return rdata.Pass();
115 uint16 AAAARecordRdata::Type() const {
116 return AAAARecordRdata::kType;
119 bool AAAARecordRdata::IsEqual(const RecordRdata* other) const {
120 if (other->Type() != Type()) return false;
121 const AAAARecordRdata* a_other = static_cast<const AAAARecordRdata*>(other);
122 return address_ == a_other->address_;
125 CnameRecordRdata::CnameRecordRdata() {
128 CnameRecordRdata::~CnameRecordRdata() {
131 // static
132 scoped_ptr<CnameRecordRdata> CnameRecordRdata::Create(
133 const base::StringPiece& data,
134 const DnsRecordParser& parser) {
135 scoped_ptr<CnameRecordRdata> rdata(new CnameRecordRdata);
137 if (!parser.ReadName(data.begin(), &rdata->cname_))
138 return scoped_ptr<CnameRecordRdata>();
140 return rdata.Pass();
143 uint16 CnameRecordRdata::Type() const {
144 return CnameRecordRdata::kType;
147 bool CnameRecordRdata::IsEqual(const RecordRdata* other) const {
148 if (other->Type() != Type()) return false;
149 const CnameRecordRdata* cname_other =
150 static_cast<const CnameRecordRdata*>(other);
151 return cname_ == cname_other->cname_;
154 PtrRecordRdata::PtrRecordRdata() {
157 PtrRecordRdata::~PtrRecordRdata() {
160 // static
161 scoped_ptr<PtrRecordRdata> PtrRecordRdata::Create(
162 const base::StringPiece& data,
163 const DnsRecordParser& parser) {
164 scoped_ptr<PtrRecordRdata> rdata(new PtrRecordRdata);
166 if (!parser.ReadName(data.begin(), &rdata->ptrdomain_))
167 return scoped_ptr<PtrRecordRdata>();
169 return rdata.Pass();
172 uint16 PtrRecordRdata::Type() const {
173 return PtrRecordRdata::kType;
176 bool PtrRecordRdata::IsEqual(const RecordRdata* other) const {
177 if (other->Type() != Type()) return false;
178 const PtrRecordRdata* ptr_other = static_cast<const PtrRecordRdata*>(other);
179 return ptrdomain_ == ptr_other->ptrdomain_;
182 TxtRecordRdata::TxtRecordRdata() {
185 TxtRecordRdata::~TxtRecordRdata() {
188 // static
189 scoped_ptr<TxtRecordRdata> TxtRecordRdata::Create(
190 const base::StringPiece& data,
191 const DnsRecordParser& parser) {
192 scoped_ptr<TxtRecordRdata> rdata(new TxtRecordRdata);
194 for (size_t i = 0; i < data.size(); ) {
195 uint8 length = data[i];
197 if (i + length >= data.size())
198 return scoped_ptr<TxtRecordRdata>();
200 rdata->texts_.push_back(data.substr(i + 1, length).as_string());
202 // Move to the next string.
203 i += length + 1;
206 return rdata.Pass();
209 uint16 TxtRecordRdata::Type() const {
210 return TxtRecordRdata::kType;
213 bool TxtRecordRdata::IsEqual(const RecordRdata* other) const {
214 if (other->Type() != Type()) return false;
215 const TxtRecordRdata* txt_other = static_cast<const TxtRecordRdata*>(other);
216 return texts_ == txt_other->texts_;
219 NsecRecordRdata::NsecRecordRdata() {
222 NsecRecordRdata::~NsecRecordRdata() {
225 // static
226 scoped_ptr<NsecRecordRdata> NsecRecordRdata::Create(
227 const base::StringPiece& data,
228 const DnsRecordParser& parser) {
229 scoped_ptr<NsecRecordRdata> rdata(new NsecRecordRdata);
231 // Read the "next domain". This part for the NSEC record format is
232 // ignored for mDNS, since it has no semantic meaning.
233 unsigned next_domain_length = parser.ReadName(data.data(), NULL);
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)
238 return scoped_ptr<NsecRecordRdata>();
240 struct BitmapHeader {
241 uint8 block_number; // The block number should be zero.
242 uint8 length; // Bitmap length in bytes. Between 1 and 32.
245 const BitmapHeader* header = reinterpret_cast<const BitmapHeader*>(
246 data.data() + next_domain_length);
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)
251 return scoped_ptr<NsecRecordRdata>();
253 base::StringPiece bitmap_data = data.substr(next_domain_length + 2);
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)
258 return scoped_ptr<NsecRecordRdata>();
260 rdata->bitmap_.insert(rdata->bitmap_.begin(),
261 bitmap_data.begin(),
262 bitmap_data.end());
264 return rdata.Pass();
267 uint16 NsecRecordRdata::Type() const {
268 return NsecRecordRdata::kType;
271 bool 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_;
279 bool NsecRecordRdata::GetBit(unsigned i) const {
280 unsigned byte_num = i/8;
281 if (bitmap_.size() < byte_num + 1)
282 return false;
284 unsigned bit_num = 7 - i % 8;
285 return (bitmap_[byte_num] & (1 << bit_num)) != 0;
288 } // namespace net