Home | History | Annotate | Download | only in dns
      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