Probably broke Win7 Tests (dbg)(6). http://build.chromium.org/p/chromium.win/builders...
[chromium-blink-merge.git] / net / dns / record_rdata.cc
blob0c605593ab7d337b1edf18ebda380d1a0d6e0ead
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/dns/dns_protocol.h"
10 #include "net/dns/dns_response.h"
12 namespace net {
14 static const size_t kSrvRecordMinimumSize = 6;
16 RecordRdata::RecordRdata() {
19 SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) {
22 SrvRecordRdata::~SrvRecordRdata() {}
24 // static
25 scoped_ptr<SrvRecordRdata> SrvRecordRdata::Create(
26 const base::StringPiece& data,
27 const DnsRecordParser& parser) {
28 if (data.size() < kSrvRecordMinimumSize) return scoped_ptr<SrvRecordRdata>();
30 scoped_ptr<SrvRecordRdata> rdata(new SrvRecordRdata);
32 base::BigEndianReader reader(data.data(), data.size());
33 // 2 bytes for priority, 2 bytes for weight, 2 bytes for port.
34 reader.ReadU16(&rdata->priority_);
35 reader.ReadU16(&rdata->weight_);
36 reader.ReadU16(&rdata->port_);
38 if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(),
39 &rdata->target_))
40 return scoped_ptr<SrvRecordRdata>();
42 return rdata.Pass();
45 uint16 SrvRecordRdata::Type() const {
46 return SrvRecordRdata::kType;
49 bool SrvRecordRdata::IsEqual(const RecordRdata* other) const {
50 if (other->Type() != Type()) return false;
51 const SrvRecordRdata* srv_other = static_cast<const SrvRecordRdata*>(other);
52 return weight_ == srv_other->weight_ &&
53 port_ == srv_other->port_ &&
54 priority_ == srv_other->priority_ &&
55 target_ == srv_other->target_;
58 ARecordRdata::ARecordRdata() {
61 ARecordRdata::~ARecordRdata() {
64 // static
65 scoped_ptr<ARecordRdata> ARecordRdata::Create(
66 const base::StringPiece& data,
67 const DnsRecordParser& parser) {
68 if (data.size() != kIPv4AddressSize)
69 return scoped_ptr<ARecordRdata>();
71 scoped_ptr<ARecordRdata> rdata(new ARecordRdata);
73 rdata->address_.resize(kIPv4AddressSize);
74 for (unsigned i = 0; i < kIPv4AddressSize; ++i) {
75 rdata->address_[i] = data[i];
78 return rdata.Pass();
81 uint16 ARecordRdata::Type() const {
82 return ARecordRdata::kType;
85 bool ARecordRdata::IsEqual(const RecordRdata* other) const {
86 if (other->Type() != Type()) return false;
87 const ARecordRdata* a_other = static_cast<const ARecordRdata*>(other);
88 return address_ == a_other->address_;
91 AAAARecordRdata::AAAARecordRdata() {
94 AAAARecordRdata::~AAAARecordRdata() {
97 // static
98 scoped_ptr<AAAARecordRdata> AAAARecordRdata::Create(
99 const base::StringPiece& data,
100 const DnsRecordParser& parser) {
101 if (data.size() != kIPv6AddressSize)
102 return scoped_ptr<AAAARecordRdata>();
104 scoped_ptr<AAAARecordRdata> rdata(new AAAARecordRdata);
106 rdata->address_.resize(kIPv6AddressSize);
107 for (unsigned i = 0; i < kIPv6AddressSize; ++i) {
108 rdata->address_[i] = data[i];
111 return rdata.Pass();
114 uint16 AAAARecordRdata::Type() const {
115 return AAAARecordRdata::kType;
118 bool AAAARecordRdata::IsEqual(const RecordRdata* other) const {
119 if (other->Type() != Type()) return false;
120 const AAAARecordRdata* a_other = static_cast<const AAAARecordRdata*>(other);
121 return address_ == a_other->address_;
124 CnameRecordRdata::CnameRecordRdata() {
127 CnameRecordRdata::~CnameRecordRdata() {
130 // static
131 scoped_ptr<CnameRecordRdata> CnameRecordRdata::Create(
132 const base::StringPiece& data,
133 const DnsRecordParser& parser) {
134 scoped_ptr<CnameRecordRdata> rdata(new CnameRecordRdata);
136 if (!parser.ReadName(data.begin(), &rdata->cname_))
137 return scoped_ptr<CnameRecordRdata>();
139 return rdata.Pass();
142 uint16 CnameRecordRdata::Type() const {
143 return CnameRecordRdata::kType;
146 bool CnameRecordRdata::IsEqual(const RecordRdata* other) const {
147 if (other->Type() != Type()) return false;
148 const CnameRecordRdata* cname_other =
149 static_cast<const CnameRecordRdata*>(other);
150 return cname_ == cname_other->cname_;
153 PtrRecordRdata::PtrRecordRdata() {
156 PtrRecordRdata::~PtrRecordRdata() {
159 // static
160 scoped_ptr<PtrRecordRdata> PtrRecordRdata::Create(
161 const base::StringPiece& data,
162 const DnsRecordParser& parser) {
163 scoped_ptr<PtrRecordRdata> rdata(new PtrRecordRdata);
165 if (!parser.ReadName(data.begin(), &rdata->ptrdomain_))
166 return scoped_ptr<PtrRecordRdata>();
168 return rdata.Pass();
171 uint16 PtrRecordRdata::Type() const {
172 return PtrRecordRdata::kType;
175 bool PtrRecordRdata::IsEqual(const RecordRdata* other) const {
176 if (other->Type() != Type()) return false;
177 const PtrRecordRdata* ptr_other = static_cast<const PtrRecordRdata*>(other);
178 return ptrdomain_ == ptr_other->ptrdomain_;
181 TxtRecordRdata::TxtRecordRdata() {
184 TxtRecordRdata::~TxtRecordRdata() {
187 // static
188 scoped_ptr<TxtRecordRdata> TxtRecordRdata::Create(
189 const base::StringPiece& data,
190 const DnsRecordParser& parser) {
191 scoped_ptr<TxtRecordRdata> rdata(new TxtRecordRdata);
193 for (size_t i = 0; i < data.size(); ) {
194 uint8 length = data[i];
196 if (i + length >= data.size())
197 return scoped_ptr<TxtRecordRdata>();
199 rdata->texts_.push_back(data.substr(i + 1, length).as_string());
201 // Move to the next string.
202 i += length + 1;
205 return rdata.Pass();
208 uint16 TxtRecordRdata::Type() const {
209 return TxtRecordRdata::kType;
212 bool TxtRecordRdata::IsEqual(const RecordRdata* other) const {
213 if (other->Type() != Type()) return false;
214 const TxtRecordRdata* txt_other = static_cast<const TxtRecordRdata*>(other);
215 return texts_ == txt_other->texts_;
218 NsecRecordRdata::NsecRecordRdata() {
221 NsecRecordRdata::~NsecRecordRdata() {
224 // static
225 scoped_ptr<NsecRecordRdata> NsecRecordRdata::Create(
226 const base::StringPiece& data,
227 const DnsRecordParser& parser) {
228 scoped_ptr<NsecRecordRdata> rdata(new NsecRecordRdata);
230 // Read the "next domain". This part for the NSEC record format is
231 // ignored for mDNS, since it has no semantic meaning.
232 unsigned next_domain_length = parser.ReadName(data.data(), NULL);
234 // If we did not succeed in getting the next domain or the data length
235 // is too short for reading the bitmap header, return.
236 if (next_domain_length == 0 || data.length() < next_domain_length + 2)
237 return scoped_ptr<NsecRecordRdata>();
239 struct BitmapHeader {
240 uint8 block_number; // The block number should be zero.
241 uint8 length; // Bitmap length in bytes. Between 1 and 32.
244 const BitmapHeader* header = reinterpret_cast<const BitmapHeader*>(
245 data.data() + next_domain_length);
247 // The block number must be zero in mDns-specific NSEC records. The bitmap
248 // length must be between 1 and 32.
249 if (header->block_number != 0 || header->length == 0 || header->length > 32)
250 return scoped_ptr<NsecRecordRdata>();
252 base::StringPiece bitmap_data = data.substr(next_domain_length + 2);
254 // Since we may only have one block, the data length must be exactly equal to
255 // the domain length plus bitmap size.
256 if (bitmap_data.length() != header->length)
257 return scoped_ptr<NsecRecordRdata>();
259 rdata->bitmap_.insert(rdata->bitmap_.begin(),
260 bitmap_data.begin(),
261 bitmap_data.end());
263 return rdata.Pass();
266 uint16 NsecRecordRdata::Type() const {
267 return NsecRecordRdata::kType;
270 bool NsecRecordRdata::IsEqual(const RecordRdata* other) const {
271 if (other->Type() != Type())
272 return false;
273 const NsecRecordRdata* nsec_other =
274 static_cast<const NsecRecordRdata*>(other);
275 return bitmap_ == nsec_other->bitmap_;
278 bool NsecRecordRdata::GetBit(unsigned i) const {
279 unsigned byte_num = i/8;
280 if (bitmap_.size() < byte_num + 1)
281 return false;
283 unsigned bit_num = 7 - i % 8;
284 return (bitmap_[byte_num] & (1 << bit_num)) != 0;
287 } // namespace net