Home | History | Annotate | Download | only in dns
      1 // Copyright (c) 2012 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 #ifndef NET_DNS_DNS_RESPONSE_H_
      6 #define NET_DNS_DNS_RESPONSE_H_
      7 
      8 #include <string>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/strings/string_piece.h"
     13 #include "base/time/time.h"
     14 #include "net/base/net_export.h"
     15 #include "net/base/net_util.h"
     16 
     17 namespace net {
     18 
     19 class AddressList;
     20 class DnsQuery;
     21 class IOBufferWithSize;
     22 
     23 namespace dns_protocol {
     24 struct Header;
     25 }
     26 
     27 // Parsed resource record.
     28 struct NET_EXPORT_PRIVATE DnsResourceRecord {
     29   DnsResourceRecord();
     30   ~DnsResourceRecord();
     31 
     32   std::string name;  // in dotted form
     33   uint16 type;
     34   uint16 klass;
     35   uint32 ttl;
     36   base::StringPiece rdata;  // points to the original response buffer
     37 };
     38 
     39 // Iterator to walk over resource records of the DNS response packet.
     40 class NET_EXPORT_PRIVATE DnsRecordParser {
     41  public:
     42   // Construct an uninitialized iterator.
     43   DnsRecordParser();
     44 
     45   // Construct an iterator to process the |packet| of given |length|.
     46   // |offset| points to the beginning of the answer section.
     47   DnsRecordParser(const void* packet, size_t length, size_t offset);
     48 
     49   // Returns |true| if initialized.
     50   bool IsValid() const { return packet_ != NULL; }
     51 
     52   // Returns |true| if no more bytes remain in the packet.
     53   bool AtEnd() const { return cur_ == packet_ + length_; }
     54 
     55   // Returns current offset into the packet.
     56   size_t GetOffset() const { return cur_ - packet_; }
     57 
     58   // Parses a (possibly compressed) DNS name from the packet starting at
     59   // |pos|. Stores output (even partial) in |out| unless |out| is NULL. |out|
     60   // is stored in the dotted form, e.g., "example.com". Returns number of bytes
     61   // consumed or 0 on failure.
     62   // This is exposed to allow parsing compressed names within RRDATA for TYPEs
     63   // such as NS, CNAME, PTR, MX, SOA.
     64   // See RFC 1035 section 4.1.4.
     65   unsigned ReadName(const void* pos, std::string* out) const;
     66 
     67   // Parses the next resource record into |record|. Returns true if succeeded.
     68   bool ReadRecord(DnsResourceRecord* record);
     69 
     70   // Skip a question section, returns true if succeeded.
     71   bool SkipQuestion();
     72 
     73  private:
     74   const char* packet_;
     75   size_t length_;
     76   // Current offset within the packet.
     77   const char* cur_;
     78 };
     79 
     80 // Buffer-holder for the DNS response allowing easy access to the header fields
     81 // and resource records. After reading into |io_buffer| must call InitParse to
     82 // position the RR parser.
     83 class NET_EXPORT_PRIVATE DnsResponse {
     84  public:
     85   // Possible results from ParseToAddressList.
     86   enum Result {
     87     DNS_PARSE_OK = 0,
     88     DNS_MALFORMED_RESPONSE,    // DnsRecordParser failed before the end of
     89                                // packet.
     90     DNS_MALFORMED_CNAME,       // Could not parse CNAME out of RRDATA.
     91     DNS_NAME_MISMATCH,         // Got an address but no ordered chain of CNAMEs
     92                                // leads there.
     93     DNS_SIZE_MISMATCH,         // Got an address but size does not match.
     94     DNS_CNAME_AFTER_ADDRESS,   // Found CNAME after an address record.
     95     DNS_ADDRESS_TTL_MISMATCH,  // OBSOLETE. No longer used.
     96     DNS_NO_ADDRESSES,          // OBSOLETE. No longer used.
     97     // Only add new values here.
     98     DNS_PARSE_RESULT_MAX,      // Bounding value for histograms.
     99   };
    100 
    101   // Constructs a response buffer large enough to store one byte more than
    102   // largest possible response, to detect malformed responses.
    103   DnsResponse();
    104 
    105   // Constructs a response buffer of given length. Used for TCP transactions.
    106   explicit DnsResponse(size_t length);
    107 
    108   // Constructs a response from |data|. Used for testing purposes only!
    109   DnsResponse(const void* data, size_t length, size_t answer_offset);
    110 
    111   ~DnsResponse();
    112 
    113   // Internal buffer accessor into which actual bytes of response will be
    114   // read.
    115   IOBufferWithSize* io_buffer() { return io_buffer_.get(); }
    116 
    117   // Assuming the internal buffer holds |nbytes| bytes, returns true iff the
    118   // packet matches the |query| id and question.
    119   bool InitParse(int nbytes, const DnsQuery& query);
    120 
    121   // Assuming the internal buffer holds |nbytes| bytes, initialize the parser
    122   // without matching it against an existing query.
    123   bool InitParseWithoutQuery(int nbytes);
    124 
    125   // Returns true if response is valid, that is, after successful InitParse.
    126   bool IsValid() const;
    127 
    128   // All of the methods below are valid only if the response is valid.
    129 
    130   // Accessors for the header.
    131   uint16 flags() const;  // excluding rcode
    132   uint8 rcode() const;
    133 
    134   unsigned answer_count() const;
    135   unsigned additional_answer_count() const;
    136 
    137   // Accessors to the question. The qname is unparsed.
    138   base::StringPiece qname() const;
    139   uint16 qtype() const;
    140 
    141   // Returns qname in dotted format.
    142   std::string GetDottedName() const;
    143 
    144   // Returns an iterator to the resource records in the answer section.
    145   // The iterator is valid only in the scope of the DnsResponse.
    146   // This operation is idempotent.
    147   DnsRecordParser Parser() const;
    148 
    149   // Extracts an AddressList from this response. Returns SUCCESS if succeeded.
    150   // Otherwise returns a detailed error number.
    151   Result ParseToAddressList(AddressList* addr_list, base::TimeDelta* ttl) const;
    152 
    153  private:
    154   // Convenience for header access.
    155   const dns_protocol::Header* header() const;
    156 
    157   // Buffer into which response bytes are read.
    158   scoped_refptr<IOBufferWithSize> io_buffer_;
    159 
    160   // Iterator constructed after InitParse positioned at the answer section.
    161   // It is never updated afterwards, so can be used in accessors.
    162   DnsRecordParser parser_;
    163 
    164   DISALLOW_COPY_AND_ASSIGN(DnsResponse);
    165 };
    166 
    167 }  // namespace net
    168 
    169 #endif  // NET_DNS_DNS_RESPONSE_H_
    170