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"
15 static const size_t kSrvRecordMinimumSize
= 6;
17 RecordRdata::RecordRdata() {
20 SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) {
23 SrvRecordRdata::~SrvRecordRdata() {}
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(),
41 return scoped_ptr
<SrvRecordRdata
>();
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() {
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
];
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() {
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
];
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() {
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
>();
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() {
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
>();
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() {
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.
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() {
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(),
267 uint16
NsecRecordRdata::Type() const {
268 return NsecRecordRdata::kType
;
271 bool NsecRecordRdata::IsEqual(const RecordRdata
* other
) const {
272 if (other
->Type() != Type())
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)
284 unsigned bit_num
= 7 - i
% 8;
285 return (bitmap_
[byte_num
] & (1 << bit_num
)) != 0;