1 // Copyright 2011 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_DNS_QUERY_H_ 6 #define NET_DNS_DNS_QUERY_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <string> 13 14 #include "base/containers/span.h" 15 #include "base/memory/raw_ptr_exclusion.h" 16 #include "base/memory/scoped_refptr.h" 17 #include "base/strings/string_piece.h" 18 #include "net/base/net_export.h" 19 20 namespace base { 21 class BigEndianReader; 22 } // namespace base 23 24 namespace net { 25 26 class OptRecordRdata; 27 28 namespace dns_protocol { 29 struct Header; 30 } // namespace dns_protocol 31 32 class IOBufferWithSize; 33 34 // Represents on-the-wire DNS query message as an object. 35 class NET_EXPORT_PRIVATE DnsQuery { 36 public: 37 enum class PaddingStrategy { 38 // Query will not be padded. Recommended strategy when query will not be 39 // encrypted. 40 NONE, 41 42 // Query will be padded to the next multiple of 128 octets. Recommended 43 // strategy (per RFC 8467) when query will be encrypted, e.g. through 44 // DNS-over-HTTPS. 45 BLOCK_LENGTH_128, 46 }; 47 48 // Constructs a query message from |qname| which *MUST* be in a valid 49 // DNS name format, and |qtype|. The qclass is set to IN. 50 // If |opt_rdata| is not null, an OPT record will be added to the "Additional" 51 // section of the query. 52 DnsQuery(uint16_t id, 53 base::span<const uint8_t> qname, 54 uint16_t qtype, 55 const OptRecordRdata* opt_rdata = nullptr, 56 PaddingStrategy padding_strategy = PaddingStrategy::NONE); 57 58 // Constructs an empty query from a raw packet in |buffer|. If the raw packet 59 // represents a valid DNS query in the wire format (RFC 1035), Parse() will 60 // populate the empty query. 61 explicit DnsQuery(scoped_refptr<IOBufferWithSize> buffer); 62 63 // Copies are constructed with an independent cloned, not mirrored, buffer. 64 DnsQuery(const DnsQuery& query); 65 DnsQuery& operator=(const DnsQuery& query); 66 67 ~DnsQuery(); 68 69 // Clones |this| verbatim, with ID field of the header set to |id|. 70 std::unique_ptr<DnsQuery> CloneWithNewId(uint16_t id) const; 71 72 // Returns true and populates the query if the internally stored raw packet 73 // can be parsed. This should only be called when DnsQuery is constructed from 74 // the raw buffer. 75 // |valid_bytes| indicates the number of initialized bytes in the raw buffer. 76 // E.g. if the buffer holds a packet received from the network, the buffer may 77 // be allocated with the maximum size of a UDP packet, but |valid_bytes| 78 // indicates the number of bytes actually received from the network. If the 79 // parsing requires reading more than the number of initialized bytes, this 80 // method fails and returns false. 81 bool Parse(size_t valid_bytes); 82 83 // DnsQuery field accessors. 84 uint16_t id() const; 85 base::span<const uint8_t> qname() const; 86 uint16_t qtype() const; 87 88 // Returns the Question section of the query. Used when matching the 89 // response. 90 base::StringPiece question() const; 91 92 // Returns the size of the question section. 93 size_t question_size() const; 94 95 // IOBuffer accessor to be used for writing out the query. The buffer has 96 // the same byte layout as the DNS query wire format. io_buffer()97 IOBufferWithSize* io_buffer() const { return io_buffer_.get(); } 98 99 void set_flags(uint16_t flags); 100 101 private: 102 DnsQuery(const DnsQuery& orig, uint16_t id); 103 void CopyFrom(const DnsQuery& orig); 104 105 bool ReadHeader(base::BigEndianReader* reader, dns_protocol::Header* out); 106 // After read, |out| is in the DNS format, e.g. 107 // "\x03""www""\x08""chromium""\x03""com""\x00". Use DNSDomainToString to 108 // convert to the dotted format "www.chromium.com" with no trailing dot. 109 bool ReadName(base::BigEndianReader* reader, std::string* out); 110 111 // Size of the DNS name (*NOT* hostname) we are trying to resolve; used 112 // to calculate offsets. 113 size_t qname_size_ = 0; 114 115 // Contains query bytes to be consumed by higher level Write() call. 116 scoped_refptr<IOBufferWithSize> io_buffer_; 117 118 // Pointer to the dns header section. 119 // This field is not a raw_ptr<> because it was filtered by the rewriter for: 120 // #union 121 RAW_PTR_EXCLUSION dns_protocol::Header* header_ = nullptr; 122 }; 123 124 } // namespace net 125 126 #endif // NET_DNS_DNS_QUERY_H_ 127