xref: /aosp_15_r20/external/cronet/net/dns/opt_record_rdata.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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