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 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 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 288