• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "net/dns/record_rdata.h"
6 
7 #include "net/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"
11 
12 namespace net {
13 
14 static const size_t kSrvRecordMinimumSize = 6;
15 
RecordRdata()16 RecordRdata::RecordRdata() {
17 }
18 
SrvRecordRdata()19 SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) {
20 }
21 
~SrvRecordRdata()22 SrvRecordRdata::~SrvRecordRdata() {}
23 
24 // static
Create(const base::StringPiece & data,const DnsRecordParser & parser)25 scoped_ptr<SrvRecordRdata> SrvRecordRdata::Create(
26     const base::StringPiece& data,
27     const DnsRecordParser& parser) {
28   if (data.size() < kSrvRecordMinimumSize) return scoped_ptr<SrvRecordRdata>();
29 
30   scoped_ptr<SrvRecordRdata> rdata(new SrvRecordRdata);
31 
32   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_);
37 
38   if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(),
39                        &rdata->target_))
40     return scoped_ptr<SrvRecordRdata>();
41 
42   return rdata.Pass();
43 }
44 
Type() const45 uint16 SrvRecordRdata::Type() const {
46   return SrvRecordRdata::kType;
47 }
48 
IsEqual(const RecordRdata * other) const49 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_;
56 }
57 
ARecordRdata()58 ARecordRdata::ARecordRdata() {
59 }
60 
~ARecordRdata()61 ARecordRdata::~ARecordRdata() {
62 }
63 
64 // static
Create(const base::StringPiece & data,const DnsRecordParser & parser)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>();
70 
71   scoped_ptr<ARecordRdata> rdata(new ARecordRdata);
72 
73   rdata->address_.resize(kIPv4AddressSize);
74   for (unsigned i = 0; i < kIPv4AddressSize; ++i) {
75     rdata->address_[i] = data[i];
76   }
77 
78   return rdata.Pass();
79 }
80 
Type() const81 uint16 ARecordRdata::Type() const {
82   return ARecordRdata::kType;
83 }
84 
IsEqual(const RecordRdata * other) const85 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_;
89 }
90 
AAAARecordRdata()91 AAAARecordRdata::AAAARecordRdata() {
92 }
93 
~AAAARecordRdata()94 AAAARecordRdata::~AAAARecordRdata() {
95 }
96 
97 // static
Create(const base::StringPiece & data,const DnsRecordParser & parser)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>();
103 
104   scoped_ptr<AAAARecordRdata> rdata(new AAAARecordRdata);
105 
106   rdata->address_.resize(kIPv6AddressSize);
107   for (unsigned i = 0; i < kIPv6AddressSize; ++i) {
108     rdata->address_[i] = data[i];
109   }
110 
111   return rdata.Pass();
112 }
113 
Type() const114 uint16 AAAARecordRdata::Type() const {
115   return AAAARecordRdata::kType;
116 }
117 
IsEqual(const RecordRdata * other) const118 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_;
122 }
123 
CnameRecordRdata()124 CnameRecordRdata::CnameRecordRdata() {
125 }
126 
~CnameRecordRdata()127 CnameRecordRdata::~CnameRecordRdata() {
128 }
129 
130 // static
Create(const base::StringPiece & data,const DnsRecordParser & parser)131 scoped_ptr<CnameRecordRdata> CnameRecordRdata::Create(
132     const base::StringPiece& data,
133     const DnsRecordParser& parser) {
134   scoped_ptr<CnameRecordRdata> rdata(new CnameRecordRdata);
135 
136   if (!parser.ReadName(data.begin(), &rdata->cname_))
137     return scoped_ptr<CnameRecordRdata>();
138 
139   return rdata.Pass();
140 }
141 
Type() const142 uint16 CnameRecordRdata::Type() const {
143   return CnameRecordRdata::kType;
144 }
145 
IsEqual(const RecordRdata * other) const146 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_;
151 }
152 
PtrRecordRdata()153 PtrRecordRdata::PtrRecordRdata() {
154 }
155 
~PtrRecordRdata()156 PtrRecordRdata::~PtrRecordRdata() {
157 }
158 
159 // static
Create(const base::StringPiece & data,const DnsRecordParser & parser)160 scoped_ptr<PtrRecordRdata> PtrRecordRdata::Create(
161     const base::StringPiece& data,
162     const DnsRecordParser& parser) {
163   scoped_ptr<PtrRecordRdata> rdata(new PtrRecordRdata);
164 
165   if (!parser.ReadName(data.begin(), &rdata->ptrdomain_))
166     return scoped_ptr<PtrRecordRdata>();
167 
168   return rdata.Pass();
169 }
170 
Type() const171 uint16 PtrRecordRdata::Type() const {
172   return PtrRecordRdata::kType;
173 }
174 
IsEqual(const RecordRdata * other) const175 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_;
179 }
180 
TxtRecordRdata()181 TxtRecordRdata::TxtRecordRdata() {
182 }
183 
~TxtRecordRdata()184 TxtRecordRdata::~TxtRecordRdata() {
185 }
186 
187 // static
Create(const base::StringPiece & data,const DnsRecordParser & parser)188 scoped_ptr<TxtRecordRdata> TxtRecordRdata::Create(
189     const base::StringPiece& data,
190     const DnsRecordParser& parser) {
191   scoped_ptr<TxtRecordRdata> rdata(new TxtRecordRdata);
192 
193   for (size_t i = 0; i < data.size(); ) {
194     uint8 length = data[i];
195 
196     if (i + length >= data.size())
197       return scoped_ptr<TxtRecordRdata>();
198 
199     rdata->texts_.push_back(data.substr(i + 1, length).as_string());
200 
201     // Move to the next string.
202     i += length + 1;
203   }
204 
205   return rdata.Pass();
206 }
207 
Type() const208 uint16 TxtRecordRdata::Type() const {
209   return TxtRecordRdata::kType;
210 }
211 
IsEqual(const RecordRdata * other) const212 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_;
216 }
217 
NsecRecordRdata()218 NsecRecordRdata::NsecRecordRdata() {
219 }
220 
~NsecRecordRdata()221 NsecRecordRdata::~NsecRecordRdata() {
222 }
223 
224 // static
Create(const base::StringPiece & data,const DnsRecordParser & parser)225 scoped_ptr<NsecRecordRdata> NsecRecordRdata::Create(
226     const base::StringPiece& data,
227     const DnsRecordParser& parser) {
228   scoped_ptr<NsecRecordRdata> rdata(new NsecRecordRdata);
229 
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);
233 
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>();
238 
239   struct BitmapHeader {
240     uint8 block_number;  // The block number should be zero.
241     uint8 length;  // Bitmap length in bytes. Between 1 and 32.
242   };
243 
244   const BitmapHeader* header = reinterpret_cast<const BitmapHeader*>(
245       data.data() + next_domain_length);
246 
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>();
251 
252   base::StringPiece bitmap_data = data.substr(next_domain_length + 2);
253 
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>();
258 
259   rdata->bitmap_.insert(rdata->bitmap_.begin(),
260                         bitmap_data.begin(),
261                         bitmap_data.end());
262 
263   return rdata.Pass();
264 }
265 
Type() const266 uint16 NsecRecordRdata::Type() const {
267   return NsecRecordRdata::kType;
268 }
269 
IsEqual(const RecordRdata * other) const270 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_;
276 }
277 
GetBit(unsigned i) const278 bool NsecRecordRdata::GetBit(unsigned i) const {
279   unsigned byte_num = i/8;
280   if (bitmap_.size() < byte_num + 1)
281     return false;
282 
283   unsigned bit_num = 7 - i % 8;
284   return (bitmap_[byte_num] & (1 << bit_num)) != 0;
285 }
286 
287 }  // namespace net
288