Jason Jeremy Iman | a21be27 | 2020-10-21 17:53:45 +0900 | [diff] [blame] | 1 | // Copyright 2020 The Chromium OS 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 PATCHPANEL_DNS_DNS_QUERY_H_ |
| 6 | #define PATCHPANEL_DNS_DNS_QUERY_H_ |
| 7 | |
| 8 | #include <stddef.h> |
| 9 | #include <stdint.h> |
| 10 | |
| 11 | #include <memory> |
| 12 | #include <string> |
| 13 | |
| 14 | #include "base/macros.h" |
| 15 | #include "base/memory/ref_counted.h" |
| 16 | #include "base/strings/string_piece.h" |
Jason Jeremy Iman | 9df645a | 2020-11-09 04:37:09 +0900 | [diff] [blame] | 17 | #include "brillo/brillo_export.h" |
Jason Jeremy Iman | a21be27 | 2020-10-21 17:53:45 +0900 | [diff] [blame] | 18 | |
| 19 | namespace base { |
| 20 | class BigEndianReader; |
| 21 | } // namespace base |
| 22 | |
| 23 | namespace patchpanel { |
| 24 | |
| 25 | namespace dns_protocol { |
| 26 | struct Header; |
| 27 | } // namespace dns_protocol |
| 28 | |
| 29 | class IOBufferWithSize; |
| 30 | |
| 31 | // Represents on-the-wire DNS query message as an object. |
Jason Jeremy Iman | 9df645a | 2020-11-09 04:37:09 +0900 | [diff] [blame] | 32 | class BRILLO_EXPORT DnsQuery { |
Jason Jeremy Iman | a21be27 | 2020-10-21 17:53:45 +0900 | [diff] [blame] | 33 | public: |
| 34 | // Constructs an empty query from a raw packet in |buffer|. If the raw packet |
| 35 | // represents a valid DNS query in the wire format (RFC 1035), Parse() will |
| 36 | // populate the empty query. |
| 37 | explicit DnsQuery(scoped_refptr<IOBufferWithSize> buffer); |
| 38 | |
| 39 | ~DnsQuery(); |
| 40 | |
| 41 | // Returns true and populates the query if the internally stored raw packet |
| 42 | // can be parsed. This should only be called when DnsQuery is constructed from |
| 43 | // the raw buffer. |
| 44 | // |valid_bytes| indicates the number of initialized bytes in the raw buffer. |
| 45 | // E.g. if the buffer holds a packet received from the network, the buffer may |
| 46 | // be allocated with the maximum size of a UDP packet, but |valid_bytes| |
| 47 | // indicates the number of bytes actually received from the network. If the |
| 48 | // parsing requires reading more than the number of initialized bytes, this |
| 49 | // method fails and returns false. |
| 50 | bool Parse(size_t valid_bytes); |
| 51 | |
| 52 | // DnsQuery field accessors. |
| 53 | uint16_t id() const; |
| 54 | base::StringPiece qname() const; |
| 55 | uint16_t qtype() const; |
| 56 | |
| 57 | // Returns the Question section of the query. Used when matching the |
| 58 | // response. |
| 59 | base::StringPiece question() const; |
| 60 | |
| 61 | // Returns the size of the question section. |
| 62 | size_t question_size() const; |
| 63 | |
| 64 | // IOBuffer accessor to be used for writing out the query. The buffer has |
| 65 | // the same byte layout as the DNS query wire format. |
| 66 | IOBufferWithSize* io_buffer() const { return io_buffer_.get(); } |
| 67 | |
| 68 | private: |
| 69 | bool ReadHeader(base::BigEndianReader* reader, dns_protocol::Header* out); |
| 70 | // After read, |out| is in the DNS format, e.g. |
| 71 | // "\x03""www""\x08""chromium""\x03""com""\x00". Use DNSDomainToString to |
| 72 | // convert to the dotted format "www.chromium.com" with no trailing dot. |
| 73 | bool ReadName(base::BigEndianReader* reader, std::string* out); |
| 74 | |
| 75 | // Size of the DNS name (*NOT* hostname) we are trying to resolve; used |
| 76 | // to calculate offsets. |
| 77 | size_t qname_size_ = 0; |
| 78 | |
| 79 | // Contains query bytes to be consumed by higher level Write() call. |
| 80 | scoped_refptr<IOBufferWithSize> io_buffer_; |
| 81 | |
| 82 | // Pointer to the dns header section. |
| 83 | dns_protocol::Header* header_ = nullptr; |
| 84 | }; |
| 85 | |
| 86 | } // namespace patchpanel |
| 87 | |
| 88 | #endif // PATCHPANEL_DNS_DNS_QUERY_H_ |