opt_record_rdata.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright 2022 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_OPT_RECORD_RDATA_H_
  5. #define NET_DNS_OPT_RECORD_RDATA_H_
  6. #include <stdint.h>
  7. #include <map>
  8. #include <memory>
  9. #include <string>
  10. #include <vector>
  11. #include "base/strings/string_piece.h"
  12. #include "net/base/net_export.h"
  13. #include "net/dns/public/dns_protocol.h"
  14. #include "net/dns/record_rdata.h"
  15. namespace net {
  16. // OPT record format (https://tools.ietf.org/html/rfc6891):
  17. class NET_EXPORT_PRIVATE OptRecordRdata : public RecordRdata {
  18. public:
  19. static std::unique_ptr<OptRecordRdata> Create(base::StringPiece data);
  20. class NET_EXPORT_PRIVATE Opt {
  21. public:
  22. static constexpr size_t kHeaderSize = 4; // sizeof(code) + sizeof(size)
  23. Opt() = delete;
  24. explicit Opt(std::string data);
  25. Opt(const Opt& other) = delete;
  26. Opt& operator=(const Opt& other) = delete;
  27. Opt(Opt&& other) = delete;
  28. Opt& operator=(Opt&& other) = delete;
  29. virtual ~Opt() = default;
  30. bool operator==(const Opt& other) const;
  31. bool operator!=(const Opt& other) const;
  32. virtual uint16_t GetCode() const = 0;
  33. base::StringPiece data() const { return data_; }
  34. private:
  35. bool IsEqual(const Opt& other) const;
  36. std::string data_;
  37. };
  38. class NET_EXPORT_PRIVATE EdeOpt : public Opt {
  39. public:
  40. static const uint16_t kOptCode = dns_protocol::kEdnsExtendedDnsError;
  41. // The following errors are defined by in the IANA registry.
  42. // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#extended-dns-error-codes
  43. enum EdeInfoCode {
  44. kOtherError,
  45. kUnsupportedDnskeyAlgorithm,
  46. kUnsupportedDsDigestType,
  47. kStaleAnswer,
  48. kForgedAnswer,
  49. kDnssecIndeterminate,
  50. kDnssecBogus,
  51. kSignatureExpired,
  52. kSignatureNotYetValid,
  53. kDnskeyMissing,
  54. kRrsigsMissing,
  55. kNoZoneKeyBitSet,
  56. kNsecMissing,
  57. kCachedError,
  58. kNotReady,
  59. kBlocked,
  60. kCensored,
  61. kFiltered,
  62. kProhibited,
  63. kStaleNxdomainAnswer,
  64. kNotAuthoritative,
  65. kNotSupported,
  66. kNoReachableAuthority,
  67. kNetworkError,
  68. kInvalidData,
  69. kSignatureExpiredBeforeValid,
  70. kTooEarly,
  71. kUnsupportedNsec3IterationsValue,
  72. // Note: kUnrecognizedErrorCode is not defined by RFC 8914.
  73. // Used when error code does not match existing RFC error code.
  74. kUnrecognizedErrorCode
  75. };
  76. EdeOpt(uint16_t info_code, std::string extra_text);
  77. EdeOpt(const EdeOpt& other) = delete;
  78. EdeOpt& operator=(const EdeOpt& other) = delete;
  79. EdeOpt(EdeOpt&& other) = delete;
  80. EdeOpt& operator=(EdeOpt&& other) = delete;
  81. ~EdeOpt() override;
  82. // Attempts to parse an EDE option from `data`. Returns nullptr on failure.
  83. static std::unique_ptr<EdeOpt> Create(std::string data);
  84. uint16_t GetCode() const override;
  85. uint16_t info_code() const { return info_code_; }
  86. base::StringPiece extra_text() const { return extra_text_; }
  87. EdeInfoCode GetEnumFromInfoCode() const;
  88. // Convert a uint16_t to an EdeInfoCode enum.
  89. static EdeInfoCode GetEnumFromInfoCode(uint16_t info_code);
  90. private:
  91. EdeOpt();
  92. uint16_t info_code_;
  93. std::string extra_text_;
  94. };
  95. class NET_EXPORT_PRIVATE PaddingOpt : public Opt {
  96. public:
  97. static const uint16_t kOptCode = dns_protocol::kEdnsPadding;
  98. PaddingOpt() = delete;
  99. // Construct a PaddingOpt with the specified padding string.
  100. explicit PaddingOpt(std::string padding);
  101. // Constructs PaddingOpt with '\0' character padding of specified length.
  102. // Note: This padding_len only specifies the length of the data section.
  103. // Users must take into account the header length `Opt::kHeaderSize`
  104. explicit PaddingOpt(uint16_t padding_len);
  105. PaddingOpt(const PaddingOpt& other) = delete;
  106. PaddingOpt& operator=(const PaddingOpt& other) = delete;
  107. PaddingOpt(PaddingOpt&& other) = delete;
  108. PaddingOpt& operator=(PaddingOpt&& other) = delete;
  109. ~PaddingOpt() override;
  110. uint16_t GetCode() const override;
  111. };
  112. class NET_EXPORT_PRIVATE UnknownOpt : public Opt {
  113. public:
  114. UnknownOpt() = delete;
  115. UnknownOpt(const UnknownOpt& other) = delete;
  116. UnknownOpt& operator=(const UnknownOpt& other) = delete;
  117. UnknownOpt(UnknownOpt&& other) = delete;
  118. UnknownOpt& operator=(UnknownOpt&& other) = delete;
  119. ~UnknownOpt() override;
  120. // Create UnknownOpt with option code and data.
  121. // Cannot instantiate UnknownOpt directly in order to prevent Opt with
  122. // dedicated class class (ex. EdeOpt) from being stored in UnknownOpt.
  123. // object.
  124. // This method must purely be used for testing.
  125. // Only the parser can instantiate an UnknownOpt object (via friend
  126. // classes).
  127. static std::unique_ptr<UnknownOpt> CreateForTesting(uint16_t code,
  128. std::string data);
  129. uint16_t GetCode() const override;
  130. private:
  131. UnknownOpt(uint16_t code, std::string data);
  132. uint16_t code_;
  133. friend std::unique_ptr<OptRecordRdata> OptRecordRdata::Create(
  134. base::StringPiece data);
  135. };
  136. static constexpr uint16_t kOptsWithDedicatedClasses[] = {
  137. dns_protocol::kEdnsPadding, dns_protocol::kEdnsExtendedDnsError};
  138. static const uint16_t kType = dns_protocol::kTypeOPT;
  139. OptRecordRdata();
  140. OptRecordRdata(const OptRecordRdata&) = delete;
  141. OptRecordRdata& operator=(const OptRecordRdata&) = delete;
  142. OptRecordRdata(OptRecordRdata&& other) = delete;
  143. OptRecordRdata& operator=(OptRecordRdata&& other) = delete;
  144. ~OptRecordRdata() override;
  145. bool operator==(const OptRecordRdata& other) const;
  146. bool operator!=(const OptRecordRdata& other) const;
  147. // Checks whether two OptRecordRdata objects are equal. This comparison takes
  148. // into account the order of insertion. Two OptRecordRdata objects with
  149. // identical Opt records inserted in a different order will not be equal.
  150. bool IsEqual(const RecordRdata* other) const override;
  151. uint16_t Type() const override;
  152. const std::vector<char>& buf() const { return buf_; }
  153. const std::multimap<uint16_t, const std::unique_ptr<const Opt>>& opts()
  154. const {
  155. return opts_;
  156. }
  157. // Add specified Opt to rdata. Updates raw buffer as well.
  158. void AddOpt(const std::unique_ptr<Opt> opt);
  159. // Checks if an Opt with the specified opt_code is contained.
  160. bool ContainsOptCode(uint16_t opt_code) const;
  161. size_t OptCount() const { return opts_.size(); }
  162. // Returns all options sorted by option code, using insertion order to break
  163. // ties.
  164. std::vector<const Opt*> GetOpts() const;
  165. // Returns all EDE options in insertion order.
  166. std::vector<const EdeOpt*> GetEdeOpts() const;
  167. // Returns all Padding options in insertion order.
  168. std::vector<const PaddingOpt*> GetPaddingOpts() const;
  169. private:
  170. // Opt objects are stored in a multimap; key is the opt code.
  171. std::multimap<uint16_t, const std::unique_ptr<const Opt>> opts_;
  172. std::vector<char> buf_;
  173. };
  174. } // namespace net
  175. #endif // NET_DNS_OPT_RECORD_RDATA_H_