dns_response.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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. #ifndef NET_DNS_DNS_RESPONSE_H_
  5. #define NET_DNS_DNS_RESPONSE_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <string>
  9. #include <vector>
  10. #include "base/memory/ref_counted.h"
  11. #include "base/strings/string_piece.h"
  12. #include "net/base/net_export.h"
  13. #include "net/dns/dns_response_result_extractor.h"
  14. #include "net/dns/public/dns_protocol.h"
  15. #include "third_party/abseil-cpp/absl/types/optional.h"
  16. namespace base {
  17. class BigEndianWriter;
  18. } // namespace base
  19. namespace net {
  20. class DnsQuery;
  21. class IOBuffer;
  22. namespace dns_protocol {
  23. struct Header;
  24. } // namespace dns_protocol
  25. // Structure representing a Resource Record as specified in RFC 1035, Section
  26. // 4.1.3.
  27. struct NET_EXPORT_PRIVATE DnsResourceRecord {
  28. DnsResourceRecord();
  29. DnsResourceRecord(const DnsResourceRecord& other);
  30. DnsResourceRecord(DnsResourceRecord&& other);
  31. ~DnsResourceRecord();
  32. DnsResourceRecord& operator=(const DnsResourceRecord& other);
  33. DnsResourceRecord& operator=(DnsResourceRecord&& other);
  34. // A helper to set |owned_rdata| that also sets |rdata| to point to it. The
  35. // |value| must be non-empty. See the definition of |owned_rdata| below.
  36. void SetOwnedRdata(std::string value);
  37. // NAME (variable length) + TYPE (2 bytes) + CLASS (2 bytes) + TTL (4 bytes) +
  38. // RDLENGTH (2 bytes) + RDATA (variable length)
  39. //
  40. // Uses |owned_rdata| for RDATA if non-empty.
  41. size_t CalculateRecordSize() const;
  42. std::string name; // in dotted form
  43. uint16_t type = 0;
  44. uint16_t klass = 0;
  45. uint32_t ttl = 0;
  46. // Points to the original response buffer or otherwise to |owned_rdata|.
  47. base::StringPiece rdata;
  48. // Used to construct a DnsResponse from data. This field is empty if |rdata|
  49. // points to the response buffer.
  50. std::string owned_rdata;
  51. };
  52. // Iterator to walk over resource records of the DNS response packet.
  53. class NET_EXPORT_PRIVATE DnsRecordParser {
  54. public:
  55. // Construct an uninitialized iterator.
  56. DnsRecordParser();
  57. // Construct an iterator to process the `packet` of given `length`.
  58. // `offset` points to the beginning of the answer section. `ReadRecord()` will
  59. // fail if called more than `num_records` times, no matter whether or not
  60. // there is additional data at the end of the buffer that may appear to be a
  61. // valid record.
  62. DnsRecordParser(const void* packet,
  63. size_t length,
  64. size_t offset,
  65. size_t num_records);
  66. // Returns |true| if initialized.
  67. bool IsValid() const { return packet_ != nullptr; }
  68. // Returns |true| if no more bytes remain in the packet.
  69. bool AtEnd() const { return cur_ == packet_ + length_; }
  70. // Returns current offset into the packet.
  71. size_t GetOffset() const { return cur_ - packet_; }
  72. // Parses a (possibly compressed) DNS name from the packet starting at
  73. // |pos|. Stores output (even partial) in |out| unless |out| is NULL. |out|
  74. // is stored in the dotted form, e.g., "example.com". Returns number of bytes
  75. // consumed or 0 on failure.
  76. // This is exposed to allow parsing compressed names within RRDATA for TYPEs
  77. // such as NS, CNAME, PTR, MX, SOA.
  78. // See RFC 1035 section 4.1.4.
  79. unsigned ReadName(const void* pos, std::string* out) const;
  80. // Parses the next resource record into |record|. Returns true if succeeded.
  81. bool ReadRecord(DnsResourceRecord* record);
  82. // Read a question section, returns true if succeeded. In `DnsResponse`,
  83. // expected to be called during parse, after which the current offset will be
  84. // after all questions.
  85. bool ReadQuestion(std::string& out_dotted_qname, uint16_t& out_qtype);
  86. private:
  87. const char* packet_ = nullptr;
  88. size_t length_ = 0;
  89. size_t num_records_ = 0;
  90. size_t num_records_parsed_ = 0;
  91. // Current offset within the packet.
  92. const char* cur_ = nullptr;
  93. };
  94. // Buffer-holder for the DNS response allowing easy access to the header fields
  95. // and resource records. After reading into |io_buffer| must call InitParse to
  96. // position the RR parser.
  97. class NET_EXPORT_PRIVATE DnsResponse {
  98. public:
  99. // Constructs a response buffer large enough to store one byte more than
  100. // largest possible response, to detect malformed responses.
  101. DnsResponse();
  102. // Constructs a response message from `answers` and the originating `query`.
  103. // After the successful construction, and the parser is also initialized.
  104. //
  105. // If `validate_records` is false, DCHECKs validating the correctness of
  106. // records will be skipped. Intended for tests to allow creation of malformed
  107. // responses.
  108. DnsResponse(uint16_t id,
  109. bool is_authoritative,
  110. const std::vector<DnsResourceRecord>& answers,
  111. const std::vector<DnsResourceRecord>& authority_records,
  112. const std::vector<DnsResourceRecord>& additional_records,
  113. const absl::optional<DnsQuery>& query,
  114. uint8_t rcode = dns_protocol::kRcodeNOERROR,
  115. bool validate_records = true);
  116. // Constructs a response buffer of given length. Used for TCP transactions.
  117. explicit DnsResponse(size_t length);
  118. // Constructs a response from the passed buffer.
  119. DnsResponse(scoped_refptr<IOBuffer> buffer, size_t size);
  120. // Constructs a response from |data|. Used for testing purposes only!
  121. DnsResponse(const void* data, size_t length, size_t answer_offset);
  122. static DnsResponse CreateEmptyNoDataResponse(uint16_t id,
  123. bool is_authoritative,
  124. base::StringPiece qname,
  125. uint16_t qtype);
  126. // Move-only.
  127. DnsResponse(DnsResponse&& other);
  128. DnsResponse& operator=(DnsResponse&& other);
  129. ~DnsResponse();
  130. // Internal buffer accessor into which actual bytes of response will be
  131. // read.
  132. IOBuffer* io_buffer() { return io_buffer_.get(); }
  133. const IOBuffer* io_buffer() const { return io_buffer_.get(); }
  134. // Size of the internal buffer.
  135. size_t io_buffer_size() const { return io_buffer_size_; }
  136. // Assuming the internal buffer holds |nbytes| bytes, returns true iff the
  137. // packet matches the |query| id and question. This should only be called if
  138. // the response is constructed from a raw buffer.
  139. bool InitParse(size_t nbytes, const DnsQuery& query);
  140. // Assuming the internal buffer holds |nbytes| bytes, initialize the parser
  141. // without matching it against an existing query. This should only be called
  142. // if the response is constructed from a raw buffer.
  143. bool InitParseWithoutQuery(size_t nbytes);
  144. // Does not require the response to be fully parsed and valid, but will return
  145. // nullopt if the ID is unknown. The ID will only be known if the response is
  146. // successfully constructed from data or if InitParse...() has been able to
  147. // parse at least as far as the ID (not necessarily a fully successful parse).
  148. absl::optional<uint16_t> id() const;
  149. // Returns true if response is valid, that is, after successful InitParse, or
  150. // after successful construction of a new response from data.
  151. bool IsValid() const;
  152. // All of the methods below are valid only if the response is valid.
  153. // Accessors for the header.
  154. uint16_t flags() const; // excluding rcode
  155. uint8_t rcode() const;
  156. unsigned question_count() const;
  157. unsigned answer_count() const;
  158. unsigned authority_count() const;
  159. unsigned additional_answer_count() const;
  160. const std::vector<uint16_t>& qtypes() const {
  161. DCHECK(parser_.IsValid());
  162. DCHECK_EQ(question_count(), qtypes_.size());
  163. return qtypes_;
  164. }
  165. const std::vector<std::string>& dotted_qnames() const {
  166. DCHECK(parser_.IsValid());
  167. DCHECK_EQ(question_count(), dotted_qnames_.size());
  168. return dotted_qnames_;
  169. }
  170. // Shortcuts to get qtype or qname for single-query responses. Should only be
  171. // used in cases where there is known to be exactly one question (e.g. because
  172. // that has been validated by `InitParse()`).
  173. uint16_t GetSingleQType() const;
  174. base::StringPiece GetSingleDottedName() const;
  175. // Returns an iterator to the resource records in the answer section.
  176. // The iterator is valid only in the scope of the DnsResponse.
  177. // This operation is idempotent.
  178. DnsRecordParser Parser() const;
  179. private:
  180. bool WriteHeader(base::BigEndianWriter* writer,
  181. const dns_protocol::Header& header);
  182. bool WriteQuestion(base::BigEndianWriter* writer, const DnsQuery& query);
  183. bool WriteRecord(base::BigEndianWriter* writer,
  184. const DnsResourceRecord& record,
  185. bool validate_record);
  186. bool WriteAnswer(base::BigEndianWriter* writer,
  187. const DnsResourceRecord& answer,
  188. const absl::optional<DnsQuery>& query,
  189. bool validate_record);
  190. // Convenience for header access.
  191. const dns_protocol::Header* header() const;
  192. // Buffer into which response bytes are read.
  193. scoped_refptr<IOBuffer> io_buffer_;
  194. // Size of the buffer.
  195. size_t io_buffer_size_;
  196. // Iterator constructed after InitParse positioned at the answer section.
  197. // It is never updated afterwards, so can be used in accessors.
  198. DnsRecordParser parser_;
  199. bool id_available_ = false;
  200. std::vector<std::string> dotted_qnames_;
  201. std::vector<uint16_t> qtypes_;
  202. };
  203. } // namespace net
  204. #endif // NET_DNS_DNS_RESPONSE_H_