/src/PcapPlusPlus/Packet++/header/DnsResource.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "DnsLayer.h" |
4 | | #include "DnsLayerEnums.h" |
5 | | #include "DnsResourceData.h" |
6 | | #include <stdio.h> |
7 | | #include <string> |
8 | | #include <stdint.h> |
9 | | |
10 | | /// @file |
11 | | |
12 | | /// @namespace pcpp |
13 | | /// @brief The main namespace for the PcapPlusPlus lib |
14 | | namespace pcpp |
15 | | { |
16 | | // forward declarations |
17 | | class DnsLayer; |
18 | | class IDnsResourceData; |
19 | | class DnsResourceDataPtr; |
20 | | |
21 | | /// @class IDnsResource |
22 | | /// An abstract class for representing all types of DNS records. This class gives access to all available record |
23 | | /// data such as DNS type, class, name, type of record, etc. The DnsLayer holds an instance of (inherited type of) |
24 | | /// this class for each DNS record in the DNS packet |
25 | | class IDnsResource |
26 | | { |
27 | | protected: |
28 | | friend class DnsLayer; |
29 | | friend class IDnsResourceData; |
30 | | |
31 | | protected: |
32 | | DnsLayer* m_DnsLayer; |
33 | | size_t m_OffsetInLayer; |
34 | | IDnsResource* m_NextResource; |
35 | | std::string m_DecodedName; |
36 | | size_t m_NameLength; |
37 | | uint8_t* m_ExternalRawData; |
38 | | |
39 | | IDnsResource(DnsLayer* dnsLayer, size_t offsetInLayer); |
40 | | |
41 | | IDnsResource(uint8_t* emptyRawData); |
42 | | |
43 | | size_t decodeName(const char* encodedName, char* result, int iteration = 1); |
44 | | void encodeName(const std::string& decodedName, char* result, size_t& resultLen); |
45 | | |
46 | | IDnsResource* getNextResource() const |
47 | 397k | { |
48 | 397k | return m_NextResource; |
49 | 397k | } |
50 | | void setNextResource(IDnsResource* next) |
51 | 112k | { |
52 | 112k | m_NextResource = next; |
53 | 112k | } |
54 | | |
55 | | uint8_t* getRawData() const; |
56 | | |
57 | | void setDnsLayer(DnsLayer* dnsLayer, size_t offsetInLayer); |
58 | | |
59 | | public: |
60 | 116k | virtual ~IDnsResource() = default; |
61 | | |
62 | | /// @return The DNS type of this record |
63 | | DnsType getDnsType() const; |
64 | | |
65 | | /// Set DNS type for this record |
66 | | /// @param[in] newType The type to set |
67 | | void setDnsType(DnsType newType); |
68 | | |
69 | | /// @return The DNS class of this record |
70 | | DnsClass getDnsClass() const; |
71 | | |
72 | | /// Set DNS class for this record |
73 | | /// @param[in] newClass The class to set |
74 | | void setDnsClass(DnsClass newClass); |
75 | | |
76 | | /// @return The name of this record |
77 | | const std::string& getName() const |
78 | 74.2k | { |
79 | 74.2k | return m_DecodedName; |
80 | 74.2k | } |
81 | | |
82 | | /// @return The record name's offset in the packet |
83 | | size_t getNameOffset() const |
84 | 0 | { |
85 | 0 | return m_OffsetInLayer; |
86 | 0 | } |
87 | | |
88 | | /// Set the name of this record. The input name can be a standard hostname (e.g 'google.com'), or it may contain |
89 | | /// a pointer to another string in the packet (as explained here: http://www.zytrax.com/books/dns/ch15/#name). |
90 | | /// The pointer is used to reduce the DNS packet size and avoid unnecessary duplications. In case you |
91 | | /// want to use a pointer in your string you should use the following format: 'some.domain.#{offset}' where |
92 | | /// '#{offset}' is a the offset from the start of the layer. For example: if the string 'yahoo.com' already |
93 | | /// appears in offset 12 in the packet and you want to set the name of the current record to |
94 | | /// 'my.subdomain.yahoo.com' you may use the following string: 'my.subdomain.#12'. This will result in writing |
95 | | /// 'my.subdomain' and a pointer to offset 12.<BR> Please notice the new name can be shorter or longer of the |
96 | | /// old name, so this method can cause the packet to be shorten or extended |
97 | | /// @param[in] newName The name to set |
98 | | /// @return True if name was set successfully or false if input string is malformed or if an error occurred |
99 | | bool setName(const std::string& newName); |
100 | | |
101 | | // abstract methods |
102 | | |
103 | | /// @return The total size in bytes of this record |
104 | | virtual size_t getSize() const = 0; |
105 | | |
106 | | /// @return The type of this record (query, answer, authority, additional) |
107 | | virtual DnsResourceType getType() const = 0; |
108 | | }; |
109 | | |
110 | | /// @class DnsQuery |
111 | | /// Representing a DNS query record |
112 | | class DnsQuery : public IDnsResource |
113 | | { |
114 | | friend class DnsLayer; |
115 | | |
116 | | private: |
117 | 45.2k | DnsQuery(DnsLayer* dnsLayer, size_t offsetInLayer) : IDnsResource(dnsLayer, offsetInLayer) |
118 | 45.2k | {} |
119 | | |
120 | 6.52k | explicit DnsQuery(uint8_t* emptyRawData) : IDnsResource(emptyRawData) |
121 | 6.52k | {} |
122 | | |
123 | | public: |
124 | | ~DnsQuery() override = default; |
125 | | |
126 | | // implementation of abstract methods |
127 | | size_t getSize() const override |
128 | 95.5k | { |
129 | 95.5k | return m_NameLength + 2 * sizeof(uint16_t); |
130 | 95.5k | } |
131 | | DnsResourceType getType() const override |
132 | 52.8k | { |
133 | 52.8k | return DnsQueryType; |
134 | 52.8k | } |
135 | | }; |
136 | | |
137 | | /// @class DnsResource |
138 | | /// Representing DNS record other than DNS query |
139 | | class DnsResource : public IDnsResource |
140 | | { |
141 | | friend class DnsLayer; |
142 | | |
143 | | private: |
144 | | DnsResourceType m_ResourceType; |
145 | | |
146 | | DnsResource(DnsLayer* dnsLayer, size_t offsetInLayer, DnsResourceType resourceType) |
147 | 44.9k | : IDnsResource(dnsLayer, offsetInLayer) |
148 | 44.9k | { |
149 | 44.9k | m_ResourceType = resourceType; |
150 | 44.9k | } |
151 | | |
152 | | DnsResource(uint8_t* emptyRawData, DnsResourceType resType) |
153 | 19.5k | : IDnsResource(emptyRawData), m_ResourceType(resType) |
154 | 19.5k | {} |
155 | | |
156 | | public: |
157 | | ~DnsResource() override = default; |
158 | | |
159 | | /// @return The time-to-leave value for this record |
160 | | uint32_t getTTL() const; |
161 | | |
162 | | /// Set time-to-leave value for this record |
163 | | /// @param[in] newTTL The new TTL value to set |
164 | | void setTTL(uint32_t newTTL); |
165 | | |
166 | | /// @return The data length value for this record (taken from the "data length" field of the record) |
167 | | size_t getDataLength() const; |
168 | | |
169 | | /// @return A smart pointer to an IDnsResourceData object that contains the DNS resource data. It is guaranteed |
170 | | /// that the smart pointer will always point to an object and never to nullptr. The specific object type depends |
171 | | /// on the DNS type of this record:<BR> |
172 | | /// - For type A (::DNS_TYPE_A): the return value is a smart pointer to IPv4DnsResourceData object that contains |
173 | | /// the IPv4 address<BR> |
174 | | /// - For type AAAA (::DNS_TYPE_AAAA): the return value is a smart pointer to IPv6DnsResourceData object that |
175 | | /// contains the IPv6 address<BR> |
176 | | /// - For types NS, CNAME, DNAME, PTR (::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR): the |
177 | | /// return value is a smart pointer to StringDnsResourceData object that contains the name<BR> |
178 | | /// - For type MX (::DNS_TYPE_MX): the return value is a smart pointer to MxDnsResourceData object that contains |
179 | | /// the MX data (preference and mail exchange name)<BR> |
180 | | /// - For all other types: the return value is a smart pointer to GenericDnsResourceData which contains a byte |
181 | | /// array of the data |
182 | | DnsResourceDataPtr getData() const; |
183 | | |
184 | | /// @return The offset of data in the DNS layer |
185 | | size_t getDataOffset() const; |
186 | | |
187 | | /// Set resource data. The given IDnsResourceData input object is validated against the DNS type of the |
188 | | /// resource. For example: if DNS type is A and data isn't of type IPv4DnsResourceData (which contains the IPv4 |
189 | | /// address) a log error will be printed and the method will return false. This method currently supports the |
190 | | /// following DNS types:<BR> |
191 | | /// - ::DNS_TYPE_A (IPv4 address) - data is expected to be a pointer to IPv4DnsResourceData with a valid IPv4 |
192 | | /// address |
193 | | /// - ::DNS_TYPE_AAAA (IPv6 address) - data is expected to be a pointer to IPv6DnsResourceData with a valid IPv6 |
194 | | /// address |
195 | | /// - ::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR (name data) - data is expected to be a |
196 | | /// pointer to StringDnsResourceData object that contains a host name, e.g: 'www.google.com' |
197 | | /// - ::DNS_TYPE_MX (MX data) - data is expected to be a pointer to MxDnsResourceData object that contains the |
198 | | /// MX data |
199 | | /// - else: data is expected to be a pointer to GenericDnsResourceData object that contains a valid hex string |
200 | | /// (valid hex string means a string which has an even number of characters representing a valid hex data. e.g: |
201 | | /// '0d0a45569a9b') |
202 | | /// @param[in] data The pointer to the data object, as described above |
203 | | /// @return True if data was properly set or false if data is illegal or method couldn't extend or shorted the |
204 | | /// packet (appropriate error log is printed in all cases) |
205 | | bool setData(IDnsResourceData* data); |
206 | | |
207 | | /// Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. |
208 | | /// This method enables the user to receive these bytes |
209 | | /// @return The value stored in this place |
210 | | uint16_t getCustomDnsClass() const; |
211 | | |
212 | | /// Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. |
213 | | /// This method enables the user to set these bytes |
214 | | /// @param[in] customValue The value to set |
215 | | void setCustomDnsClass(uint16_t customValue); |
216 | | |
217 | | // implementation of abstract methods |
218 | | size_t getSize() const override |
219 | 136k | { |
220 | 136k | return m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t) + getDataLength(); |
221 | 136k | } |
222 | | DnsResourceType getType() const override |
223 | 129k | { |
224 | 129k | return m_ResourceType; |
225 | 129k | } |
226 | | }; |
227 | | |
228 | | } // namespace pcpp |