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 12namespace net { 13 14static const size_t kSrvRecordMinimumSize = 6; 15 16RecordRdata::RecordRdata() { 17} 18 19SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) { 20} 21 22SrvRecordRdata::~SrvRecordRdata() {} 23 24// static 25scoped_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 45uint16 SrvRecordRdata::Type() const { 46 return SrvRecordRdata::kType; 47} 48 49bool 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 58ARecordRdata::ARecordRdata() { 59} 60 61ARecordRdata::~ARecordRdata() { 62} 63 64// static 65scoped_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 81uint16 ARecordRdata::Type() const { 82 return ARecordRdata::kType; 83} 84 85bool 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 91AAAARecordRdata::AAAARecordRdata() { 92} 93 94AAAARecordRdata::~AAAARecordRdata() { 95} 96 97// static 98scoped_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 114uint16 AAAARecordRdata::Type() const { 115 return AAAARecordRdata::kType; 116} 117 118bool 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 124CnameRecordRdata::CnameRecordRdata() { 125} 126 127CnameRecordRdata::~CnameRecordRdata() { 128} 129 130// static 131scoped_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 142uint16 CnameRecordRdata::Type() const { 143 return CnameRecordRdata::kType; 144} 145 146bool 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 153PtrRecordRdata::PtrRecordRdata() { 154} 155 156PtrRecordRdata::~PtrRecordRdata() { 157} 158 159// static 160scoped_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 171uint16 PtrRecordRdata::Type() const { 172 return PtrRecordRdata::kType; 173} 174 175bool 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 181TxtRecordRdata::TxtRecordRdata() { 182} 183 184TxtRecordRdata::~TxtRecordRdata() { 185} 186 187// static 188scoped_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 208uint16 TxtRecordRdata::Type() const { 209 return TxtRecordRdata::kType; 210} 211 212bool 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 218NsecRecordRdata::NsecRecordRdata() { 219} 220 221NsecRecordRdata::~NsecRecordRdata() { 222} 223 224// static 225scoped_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 266uint16 NsecRecordRdata::Type() const { 267 return NsecRecordRdata::kType; 268} 269 270bool 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 278bool 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