blob: 09d00914e95abd0c9eea1c6a018f5345ee5443fc [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2011 The Chromium Authors
agayev@chromium.orgb5810642011-06-03 21:26:492// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
agayev@chromium.org4b0112ab2011-07-22 15:58:205#ifndef NET_DNS_DNS_QUERY_H_
6#define NET_DNS_DNS_QUERY_H_
agayev@chromium.orgb5810642011-06-03 21:26:497
Avi Drissman13fc8932015-12-20 04:40:468#include <stddef.h>
9#include <stdint.h>
10
danakj22f90e72016-04-16 01:55:4011#include <memory>
Eric Orthbc28a522019-06-04 16:03:5612#include <string>
Md Hasibul Hasan7495cd72024-03-26 01:02:3213#include <string_view>
danakj22f90e72016-04-16 01:55:4014
Eric Orth0eeeef182022-12-01 23:49:5715#include "base/containers/span.h"
danakj1a2d0e32024-04-12 18:33:4016#include "base/containers/span_reader.h"
Ho Cheung7964ef32023-05-25 20:07:4417#include "base/memory/raw_ptr.h"
Lei Zhang58a1082452022-11-08 04:23:2018#include "base/memory/scoped_refptr.h"
danakj16923e22024-03-05 19:39:5519#include "net/base/io_buffer.h"
darin@chromium.org172da1b2011-08-12 15:52:2620#include "net/base/net_export.h"
agayev@chromium.orgb5810642011-06-03 21:26:4921
agayev@chromium.org784008312011-06-28 22:15:1722namespace net {
agayev@chromium.orgb5810642011-06-03 21:26:4923
Rob Percivalc2b1a172017-09-25 13:30:4224class OptRecordRdata;
25
tfarina0e534a82015-12-30 13:34:0626namespace dns_protocol {
27struct Header;
Qingsi Wangecd69252018-09-27 21:35:5528} // namespace dns_protocol
tfarina0e534a82015-12-30 13:34:0629
agayev@chromium.org4b0112ab2011-07-22 15:58:2030class IOBufferWithSize;
31
agayev@chromium.org168c4322011-06-09 18:05:1532// Represents on-the-wire DNS query message as an object.
darin@chromium.org172da1b2011-08-12 15:52:2633class NET_EXPORT_PRIVATE DnsQuery {
agayev@chromium.orgb5810642011-06-03 21:26:4934 public:
Eric Orthbc28a522019-06-04 16:03:5635 enum class PaddingStrategy {
36 // Query will not be padded. Recommended strategy when query will not be
37 // encrypted.
38 NONE,
39
40 // Query will be padded to the next multiple of 128 octets. Recommended
41 // strategy (per RFC 8467) when query will be encrypted, e.g. through
42 // DNS-over-HTTPS.
43 BLOCK_LENGTH_128,
44 };
45
agayev@chromium.org511d16512011-06-29 20:20:3846 // Constructs a query message from |qname| which *MUST* be in a valid
szym@chromium.org7556ea22011-12-08 19:29:1547 // DNS name format, and |qtype|. The qclass is set to IN.
Eric Orthbc28a522019-06-04 16:03:5648 // If |opt_rdata| is not null, an OPT record will be added to the "Additional"
Rob Percivalc2b1a172017-09-25 13:30:4249 // section of the query.
50 DnsQuery(uint16_t id,
Eric Orth0eeeef182022-12-01 23:49:5751 base::span<const uint8_t> qname,
Rob Percivalc2b1a172017-09-25 13:30:4252 uint16_t qtype,
Eric Orthbc28a522019-06-04 16:03:5653 const OptRecordRdata* opt_rdata = nullptr,
54 PaddingStrategy padding_strategy = PaddingStrategy::NONE);
Qingsi Wangecd69252018-09-27 21:35:5555
56 // Constructs an empty query from a raw packet in |buffer|. If the raw packet
57 // represents a valid DNS query in the wire format (RFC 1035), Parse() will
58 // populate the empty query.
Eric Orthbc28a522019-06-04 16:03:5659 explicit DnsQuery(scoped_refptr<IOBufferWithSize> buffer);
Qingsi Wangecd69252018-09-27 21:35:5560
Eric Orthbe910d402020-08-04 21:48:2461 // Copies are constructed with an independent cloned, not mirrored, buffer.
62 DnsQuery(const DnsQuery& query);
63 DnsQuery& operator=(const DnsQuery& query);
64
Tom Sepez145443a2024-11-05 23:54:0565 // Moves do not clone an independent buffer.
66 DnsQuery(DnsQuery&& query);
67 DnsQuery& operator=(DnsQuery&& query);
68
agayev@chromium.orgb5810642011-06-03 21:26:4969 ~DnsQuery();
70
szym@chromium.org7556ea22011-12-08 19:29:1571 // Clones |this| verbatim, with ID field of the header set to |id|.
danakj22f90e72016-04-16 01:55:4072 std::unique_ptr<DnsQuery> CloneWithNewId(uint16_t id) const;
agayev@chromium.orgb5810642011-06-03 21:26:4973
Qingsi Wangecd69252018-09-27 21:35:5574 // Returns true and populates the query if the internally stored raw packet
75 // can be parsed. This should only be called when DnsQuery is constructed from
76 // the raw buffer.
Matthew Dentonfa9af6a2018-10-18 20:44:1777 // |valid_bytes| indicates the number of initialized bytes in the raw buffer.
78 // E.g. if the buffer holds a packet received from the network, the buffer may
79 // be allocated with the maximum size of a UDP packet, but |valid_bytes|
80 // indicates the number of bytes actually received from the network. If the
81 // parsing requires reading more than the number of initialized bytes, this
82 // method fails and returns false.
83 bool Parse(size_t valid_bytes);
Qingsi Wangecd69252018-09-27 21:35:5584
agayev@chromium.org168c4322011-06-09 18:05:1585 // DnsQuery field accessors.
Avi Drissman13fc8932015-12-20 04:40:4686 uint16_t id() const;
Eric Orth0eeeef182022-12-01 23:49:5787 base::span<const uint8_t> qname() const;
Avi Drissman13fc8932015-12-20 04:40:4688 uint16_t qtype() const;
agayev@chromium.org168c4322011-06-09 18:05:1589
szym@chromium.org7556ea22011-12-08 19:29:1590 // Returns the Question section of the query. Used when matching the
91 // response.
Md Hasibul Hasan7495cd72024-03-26 01:02:3292 std::string_view question() const;
agayev@chromium.orgb5810642011-06-03 21:26:4993
Qingsi Wang65841072018-10-09 01:14:4594 // Returns the size of the question section.
Eric Orthbc28a522019-06-04 16:03:5695 size_t question_size() const;
Qingsi Wang65841072018-10-09 01:14:4596
Qingsi Wangecd69252018-09-27 21:35:5597 // IOBuffer accessor to be used for writing out the query. The buffer has
98 // the same byte layout as the DNS query wire format.
rsleevi@chromium.org90499482013-06-01 00:39:5099 IOBufferWithSize* io_buffer() const { return io_buffer_.get(); }
agayev@chromium.orgb5810642011-06-03 21:26:49100
Avi Drissman13fc8932015-12-20 04:40:46101 void set_flags(uint16_t flags);
noamsml@chromium.org245b164e2013-06-13 22:31:42102
agayev@chromium.orgb5810642011-06-03 21:26:49103 private:
Avi Drissman13fc8932015-12-20 04:40:46104 DnsQuery(const DnsQuery& orig, uint16_t id);
Eric Orthbe910d402020-08-04 21:48:24105 void CopyFrom(const DnsQuery& orig);
agayev@chromium.orgb5810642011-06-03 21:26:49106
danakj1a2d0e32024-04-12 18:33:40107 bool ReadHeader(base::SpanReader<const uint8_t>* reader,
108 dns_protocol::Header* out);
Qingsi Wangecd69252018-09-27 21:35:55109 // After read, |out| is in the DNS format, e.g.
110 // "\x03""www""\x08""chromium""\x03""com""\x00". Use DNSDomainToString to
111 // convert to the dotted format "www.chromium.com" with no trailing dot.
danakj1a2d0e32024-04-12 18:33:40112 bool ReadName(base::SpanReader<const uint8_t>* reader, std::string* out);
Qingsi Wangecd69252018-09-27 21:35:55113
danakj16923e22024-03-05 19:39:55114 // Returns the Header pointer into the `io_buffer_`. Only valid to call on a
115 // DNSQuery has a valid IOBuffer, so this never returns null.
116 //
117 // TODO(davidben): Dereferencing the returned pointer will be UB. The correct
118 // shape of this function would be to do a memcpy into/out of a Header to read
119 // out of/into the buffer.
120 const dns_protocol::Header* header_in_io_buffer() const {
121 CHECK(io_buffer_ && !io_buffer_->span().empty());
122 return reinterpret_cast<dns_protocol::Header*>(io_buffer_->span().data());
123 }
124 dns_protocol::Header* header_in_io_buffer() {
125 CHECK(io_buffer_ && !io_buffer_->span().empty());
126 return reinterpret_cast<dns_protocol::Header*>(io_buffer_->span().data());
127 }
128
agayev@chromium.org168c4322011-06-09 18:05:15129 // Size of the DNS name (*NOT* hostname) we are trying to resolve; used
130 // to calculate offsets.
Qingsi Wangecd69252018-09-27 21:35:55131 size_t qname_size_ = 0;
agayev@chromium.orgb5810642011-06-03 21:26:49132
133 // Contains query bytes to be consumed by higher level Write() call.
134 scoped_refptr<IOBufferWithSize> io_buffer_;
agayev@chromium.orgb5810642011-06-03 21:26:49135};
136
137} // namespace net
138
agayev@chromium.org4b0112ab2011-07-22 15:58:20139#endif // NET_DNS_DNS_QUERY_H_