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