blob: 76c2215074d2712273094cd745114e40b9b06dbd [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
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_RESPONSE_H_
6#define NET_DNS_DNS_RESPONSE_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/memory/ref_counted.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010012#include "base/strings/string_piece.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000013#include "base/time.h"
14#include "net/base/net_export.h"
15#include "net/base/net_util.h"
16
17namespace net {
18
19class AddressList;
20class DnsQuery;
21class IOBufferWithSize;
22
23namespace dns_protocol {
24struct Header;
25}
26
27// Parsed resource record.
28struct NET_EXPORT_PRIVATE DnsResourceRecord {
29 DnsResourceRecord();
30 ~DnsResourceRecord();
31
32 std::string name; // in dotted form
33 uint16 type;
34 uint16 klass;
35 uint32 ttl;
36 base::StringPiece rdata; // points to the original response buffer
37};
38
39// Iterator to walk over resource records of the DNS response packet.
40class NET_EXPORT_PRIVATE DnsRecordParser {
41 public:
42 // Construct an uninitialized iterator.
43 DnsRecordParser();
44
45 // Construct an iterator to process the |packet| of given |length|.
46 // |offset| points to the beginning of the answer section.
47 DnsRecordParser(const void* packet, size_t length, size_t offset);
48
49 // Returns |true| if initialized.
50 bool IsValid() const { return packet_ != NULL; }
51
52 // Returns |true| if no more bytes remain in the packet.
53 bool AtEnd() const { return cur_ == packet_ + length_; }
54
55 // Returns current offset into the packet.
56 size_t GetOffset() const { return cur_ - packet_; }
57
58 // Parses a (possibly compressed) DNS name from the packet starting at
59 // |pos|. Stores output (even partial) in |out| unless |out| is NULL. |out|
60 // is stored in the dotted form, e.g., "example.com". Returns number of bytes
61 // consumed or 0 on failure.
62 // This is exposed to allow parsing compressed names within RRDATA for TYPEs
63 // such as NS, CNAME, PTR, MX, SOA.
64 // See RFC 1035 section 4.1.4.
65 unsigned ReadName(const void* pos, std::string* out) const;
66
67 // Parses the next resource record into |record|. Returns true if succeeded.
68 bool ReadRecord(DnsResourceRecord* record);
69
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010070 // Skip a question section, returns true if succeeded.
71 bool SkipQuestion();
72
Torne (Richard Coles)58218062012-11-14 11:43:16 +000073 private:
74 const char* packet_;
75 size_t length_;
76 // Current offset within the packet.
77 const char* cur_;
78};
79
80// Buffer-holder for the DNS response allowing easy access to the header fields
81// and resource records. After reading into |io_buffer| must call InitParse to
82// position the RR parser.
83class NET_EXPORT_PRIVATE DnsResponse {
84 public:
85 // Possible results from ParseToAddressList.
86 enum Result {
87 DNS_PARSE_OK = 0,
88 DNS_MALFORMED_RESPONSE, // DnsRecordParser failed before the end of
89 // packet.
90 DNS_MALFORMED_CNAME, // Could not parse CNAME out of RRDATA.
91 DNS_NAME_MISMATCH, // Got an address but no ordered chain of CNAMEs
92 // leads there.
93 DNS_SIZE_MISMATCH, // Got an address but size does not match.
94 DNS_CNAME_AFTER_ADDRESS, // Found CNAME after an address record.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000095 DNS_ADDRESS_TTL_MISMATCH, // OBSOLETE. No longer used.
Torne (Richard Coles)58218062012-11-14 11:43:16 +000096 DNS_NO_ADDRESSES, // OBSOLETE. No longer used.
97 // Only add new values here.
98 DNS_PARSE_RESULT_MAX, // Bounding value for histograms.
99 };
100
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000101 // Constructs a response buffer large enough to store one byte more than
102 // largest possible response, to detect malformed responses.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000103 DnsResponse();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000104
105 // Constructs a response buffer of given length. Used for TCP transactions.
106 explicit DnsResponse(size_t length);
107
108 // Constructs a response from |data|. Used for testing purposes only!
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000109 DnsResponse(const void* data, size_t length, size_t answer_offset);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000110
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000111 ~DnsResponse();
112
113 // Internal buffer accessor into which actual bytes of response will be
114 // read.
115 IOBufferWithSize* io_buffer() { return io_buffer_.get(); }
116
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000117 // Assuming the internal buffer holds |nbytes| bytes, returns true iff the
118 // packet matches the |query| id and question.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000119 bool InitParse(int nbytes, const DnsQuery& query);
120
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100121 // Assuming the internal buffer holds |nbytes| bytes, initialize the parser
122 // without matching it against an existing query.
123 bool InitParseWithoutQuery(int nbytes);
124
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000125 // Returns true if response is valid, that is, after successful InitParse.
126 bool IsValid() const;
127
128 // All of the methods below are valid only if the response is valid.
129
130 // Accessors for the header.
131 uint16 flags() const; // excluding rcode
132 uint8 rcode() const;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100133
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000134 unsigned answer_count() const;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100135 unsigned additional_answer_count() const;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000136
137 // Accessors to the question. The qname is unparsed.
138 base::StringPiece qname() const;
139 uint16 qtype() const;
140
141 // Returns qname in dotted format.
142 std::string GetDottedName() const;
143
144 // Returns an iterator to the resource records in the answer section.
145 // The iterator is valid only in the scope of the DnsResponse.
146 // This operation is idempotent.
147 DnsRecordParser Parser() const;
148
149 // Extracts an AddressList from this response. Returns SUCCESS if succeeded.
150 // Otherwise returns a detailed error number.
151 Result ParseToAddressList(AddressList* addr_list, base::TimeDelta* ttl) const;
152
153 private:
154 // Convenience for header access.
155 const dns_protocol::Header* header() const;
156
157 // Buffer into which response bytes are read.
158 scoped_refptr<IOBufferWithSize> io_buffer_;
159
160 // Iterator constructed after InitParse positioned at the answer section.
161 // It is never updated afterwards, so can be used in accessors.
162 DnsRecordParser parser_;
163
164 DISALLOW_COPY_AND_ASSIGN(DnsResponse);
165};
166
167} // namespace net
168
169#endif // NET_DNS_DNS_RESPONSE_H_