OLD | NEW |
| (Empty) |
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 "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 | |
16 RecordRdata::RecordRdata() { | |
17 } | |
18 | |
19 SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) { | |
20 } | |
21 | |
22 SrvRecordRdata::~SrvRecordRdata() {} | |
23 | |
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>(); | |
29 | |
30 scoped_ptr<SrvRecordRdata> rdata(new SrvRecordRdata); | |
31 | |
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_); | |
37 | |
38 if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(), | |
39 &rdata->target_)) | |
40 return scoped_ptr<SrvRecordRdata>(); | |
41 | |
42 return rdata.Pass(); | |
43 } | |
44 | |
45 uint16 SrvRecordRdata::Type() const { | |
46 return SrvRecordRdata::kType; | |
47 } | |
48 | |
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_; | |
56 } | |
57 | |
58 ARecordRdata::ARecordRdata() { | |
59 } | |
60 | |
61 ARecordRdata::~ARecordRdata() { | |
62 } | |
63 | |
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>(); | |
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 | |
81 uint16 ARecordRdata::Type() const { | |
82 return ARecordRdata::kType; | |
83 } | |
84 | |
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_; | |
89 } | |
90 | |
91 AAAARecordRdata::AAAARecordRdata() { | |
92 } | |
93 | |
94 AAAARecordRdata::~AAAARecordRdata() { | |
95 } | |
96 | |
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>(); | |
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 | |
114 uint16 AAAARecordRdata::Type() const { | |
115 return AAAARecordRdata::kType; | |
116 } | |
117 | |
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_; | |
122 } | |
123 | |
124 CnameRecordRdata::CnameRecordRdata() { | |
125 } | |
126 | |
127 CnameRecordRdata::~CnameRecordRdata() { | |
128 } | |
129 | |
130 // static | |
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 | |
142 uint16 CnameRecordRdata::Type() const { | |
143 return CnameRecordRdata::kType; | |
144 } | |
145 | |
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_; | |
151 } | |
152 | |
153 PtrRecordRdata::PtrRecordRdata() { | |
154 } | |
155 | |
156 PtrRecordRdata::~PtrRecordRdata() { | |
157 } | |
158 | |
159 // static | |
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 | |
171 uint16 PtrRecordRdata::Type() const { | |
172 return PtrRecordRdata::kType; | |
173 } | |
174 | |
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_; | |
179 } | |
180 | |
181 TxtRecordRdata::TxtRecordRdata() { | |
182 } | |
183 | |
184 TxtRecordRdata::~TxtRecordRdata() { | |
185 } | |
186 | |
187 // static | |
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 | |
208 uint16 TxtRecordRdata::Type() const { | |
209 return TxtRecordRdata::kType; | |
210 } | |
211 | |
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_; | |
216 } | |
217 | |
218 NsecRecordRdata::NsecRecordRdata() { | |
219 } | |
220 | |
221 NsecRecordRdata::~NsecRecordRdata() { | |
222 } | |
223 | |
224 // static | |
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 | |
266 uint16 NsecRecordRdata::Type() const { | |
267 return NsecRecordRdata::kType; | |
268 } | |
269 | |
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_; | |
276 } | |
277 | |
278 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 | |
OLD | NEW |