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