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