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