/src/PcapPlusPlus/Packet++/header/DnsResourceData.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include "DeprecationUtils.h" |
4 | | #include "DnsResource.h" |
5 | | #include "IpAddress.h" |
6 | | #include <memory> |
7 | | #include <string> |
8 | | #include <vector> |
9 | | #include <stdint.h> |
10 | | |
11 | | /// @file |
12 | | |
13 | | /// @namespace pcpp |
14 | | /// @brief The main namespace for the PcapPlusPlus lib |
15 | | namespace pcpp |
16 | | { |
17 | | // forward declarations |
18 | | class IDnsResource; |
19 | | |
20 | | /// @class IDnsResourceData |
21 | | /// A wrapper class for storing DNS RR (resource record) data. This is the base class which introduces several |
22 | | /// abstract methods for derived classes to implement for setting and retrieving the stored data. Each derived class |
23 | | /// will store different type of DNS RR data and implement these methods accordingly (for example: IPv4/IPv6 |
24 | | /// addresses, MX data, hostnames, raw byte data etc.) |
25 | | class IDnsResourceData |
26 | | { |
27 | | protected: |
28 | | // unimplemented private copy c'tor |
29 | | IDnsResourceData(const IDnsResourceData& other); |
30 | | IDnsResourceData() |
31 | 0 | {} |
32 | | |
33 | | size_t decodeName(const char* encodedName, char* result, IDnsResource* dnsResource) const; |
34 | | void encodeName(const std::string& decodedName, char* result, size_t& resultLen, |
35 | | IDnsResource* dnsResource) const; |
36 | | |
37 | | public: |
38 | | /// A virtual d'tor, does nothing |
39 | 0 | virtual ~IDnsResourceData() = default; |
40 | | |
41 | | /// A templated method which takes a class that derives from IDnsResourceData as the template argument and |
42 | | /// checks whether this instance is of this type |
43 | | /// @return True if this instance is of the requested type, false otherwise |
44 | | template <class IDnsResourceDataType> bool isTypeOf() const |
45 | 0 | { |
46 | 0 | return dynamic_cast<const IDnsResourceDataType*>(this) != nullptr; |
47 | 0 | } Unexecuted instantiation: bool pcpp::IDnsResourceData::isTypeOf<pcpp::GenericDnsResourceData>() const Unexecuted instantiation: bool pcpp::IDnsResourceData::isTypeOf<pcpp::IPv4DnsResourceData>() const Unexecuted instantiation: bool pcpp::IDnsResourceData::isTypeOf<pcpp::IPv6DnsResourceData>() const Unexecuted instantiation: bool pcpp::IDnsResourceData::isTypeOf<pcpp::StringDnsResourceData>() const Unexecuted instantiation: bool pcpp::IDnsResourceData::isTypeOf<pcpp::MxDnsResourceData>() const |
48 | | |
49 | | /// A templated method which take a class that derives from IDnsResourceData as the template argument and tries |
50 | | /// to cast the current instance as that type |
51 | | /// @return A pointer to the current instance casted as the requested type or nullptr if this instance isn't of |
52 | | /// this type |
53 | | template <class IDnsResourceDataType> IDnsResourceDataType* castAs() |
54 | | { |
55 | | return dynamic_cast<IDnsResourceDataType*>(this); |
56 | | } |
57 | | |
58 | | /// @return A string that represents the current DNS RR data |
59 | | virtual std::string toString() const = 0; |
60 | | |
61 | | /// Serialize the DNS RR data into a byte vector |
62 | | /// @param[in] dnsResource A pointer to a DNS resource object where this DNS RR data will be stored, may be |
63 | | /// nullptr for data types that don't need it |
64 | | /// @return A vector with the serialized DNS RR data, or an empty vector if the data is invalid or couldn't |
65 | | /// be serialized |
66 | | virtual std::vector<uint8_t> toBytes(IDnsResource* dnsResource) const = 0; |
67 | | |
68 | | /// Convert the DNS RR data into a byte array. This is a convenience method that serializes the data using |
69 | | /// toBytes() and copies it into the given array |
70 | | /// @param[out] arr A pointer to a pre-allocated byte array where the result will be written to |
71 | | /// @param[out] arrLength A reference to a number where the result array length will be written to |
72 | | /// @param[in] dnsResource A pointer to a DNS resource object where this DNS RR data will be stored |
73 | | /// @return True if the DNS RR data was successfully converted into a byte array and written to the given array |
74 | | /// or false if stored DNS RR data is invalid or if it could not be written to the given array |
75 | | PCPP_DEPRECATED("Use toBytes() instead") |
76 | | bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; |
77 | | }; |
78 | | |
79 | | /// @class DnsResourceDataPtr |
80 | | /// A smart pointer class that holds pointers of type IDnsResourceData. This object is used in DnsResource#getData() |
81 | | class DnsResourceDataPtr : public std::unique_ptr<IDnsResourceData> |
82 | | { |
83 | | public: |
84 | | /// A c'tor to this class |
85 | | /// @param[in] ptr A pointer to IDnsResourceData |
86 | 0 | explicit DnsResourceDataPtr(IDnsResourceData* ptr) : std::unique_ptr<IDnsResourceData>(ptr) |
87 | 0 | {} |
88 | | |
89 | | /// A templated method which takes a class that derives from IDnsResourceData as the template argument and |
90 | | /// checks whether the pointer stored in this object is of this type |
91 | | /// @return True if the stored pointer is of the requested type, false otherwise |
92 | | template <class IDnsResourceDataType> bool isTypeOf() const |
93 | 0 | { |
94 | 0 | return get()->isTypeOf<IDnsResourceDataType>(); |
95 | 0 | } |
96 | | |
97 | | /// A templated method which take a class that derives from IDnsResourceData as the template argument and tries |
98 | | /// to cast the pointer stored in this object as that type |
99 | | /// @return A pointer to the stored pointer casted as the requested type or nullptr if it isn't of this type |
100 | | template <class IDnsResourceDataType> IDnsResourceDataType* castAs() |
101 | | { |
102 | | return get()->castAs<IDnsResourceDataType>(); |
103 | | } |
104 | | }; |
105 | | |
106 | | /// @class StringDnsResourceData |
107 | | /// A class that represents DNS RR string data, mainly used in DNS RRs that store hostnames (like CNAME, DNAME, NS, |
108 | | /// etc.) |
109 | | class StringDnsResourceData : public IDnsResourceData |
110 | | { |
111 | | private: |
112 | | std::string m_Data; |
113 | | |
114 | | public: |
115 | | /// A c'tor for this class |
116 | | /// @param[in] data The string data to store in this object. If this string represents a hostname it's possible |
117 | | /// to include a pointer to another string in the DNS layer (as explained here: |
118 | | /// http://www.zytrax.com/books/dns/ch15/#name). These pointers are often used to reduce the DNS packet size and |
119 | | /// avoid unnecessary duplications. The way to include pointers in a hostname string is to use the following |
120 | | /// format: 'some.domain.#{offset}' where '#{offset}' is the offset from the start of the DNS layer. For |
121 | | /// example: if the string 'yahoo.com' already appears in offset 12 in the packet and you want to set the DNS RR |
122 | | /// data as 'my.subdomain.yahoo.com' you may use the following string: 'my.subdomain.#12'. This will result in |
123 | | /// writing 'my.subdomain' and a pointer to offset 12 |
124 | | explicit StringDnsResourceData(const std::string& data) : m_Data(data) |
125 | 0 | {} |
126 | | |
127 | | StringDnsResourceData(const uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource); |
128 | | |
129 | 0 | ~StringDnsResourceData() override = default; |
130 | | |
131 | | /// Equality operator overload for this class that compares the strings stored in each object |
132 | | /// @param[in] other The object to compare with |
133 | | /// @return True if the string data is the same in both objects, false otherwise |
134 | | bool operator==(const StringDnsResourceData& other) const |
135 | 0 | { |
136 | 0 | return m_Data == other.m_Data; |
137 | 0 | } |
138 | | |
139 | | // implement abstract methods |
140 | | |
141 | | std::string toString() const override |
142 | 0 | { |
143 | 0 | return m_Data; |
144 | 0 | } |
145 | | std::vector<uint8_t> toBytes(IDnsResource* dnsResource) const override; |
146 | | }; |
147 | | |
148 | | /// @class IPv4DnsResourceData |
149 | | /// A class that represents DNS RR IPv4 data, mainly used in DNS RRs of type ::DNS_TYPE_A |
150 | | class IPv4DnsResourceData : public IDnsResourceData |
151 | | { |
152 | | private: |
153 | | IPv4Address m_Data; |
154 | | |
155 | | public: |
156 | | /// A c'tor for this class |
157 | | /// @param[in] dataPtr A byte array of size 4 that contains an IPv4 address (each byte represents 1 octet) |
158 | | /// @param[in] dataLen The byte array size, expected to be 4 |
159 | | IPv4DnsResourceData(const uint8_t* dataPtr, size_t dataLen); |
160 | | |
161 | | /// A c'tor for this class |
162 | | /// @param[in] addr The IPv4 address to store in this object |
163 | | explicit IPv4DnsResourceData(const IPv4Address& addr) : m_Data(addr) |
164 | 0 | {} |
165 | | |
166 | | /// A c'tor for this class |
167 | | /// @param[in] addrAsString A string representation of an IPv4 address to store in this object |
168 | | explicit IPv4DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) |
169 | 0 | {} |
170 | | |
171 | | /// Equality operator overload for this class that compares the IPv4 addresses stored in each object |
172 | | /// @param[in] other The object to compare with |
173 | | /// @return True if IPv4 addresses are the same in both objects, false otherwise |
174 | | bool operator==(const IPv4DnsResourceData& other) const |
175 | 0 | { |
176 | 0 | return m_Data == other.m_Data; |
177 | 0 | } |
178 | | |
179 | | /// @return The IPv4 address stored in this object |
180 | | IPv4Address getIpAddress() const |
181 | 0 | { |
182 | 0 | return m_Data; |
183 | 0 | } |
184 | | |
185 | | // implement abstract methods |
186 | | |
187 | | std::string toString() const override |
188 | 0 | { |
189 | 0 | return m_Data.toString(); |
190 | 0 | } |
191 | | std::vector<uint8_t> toBytes(IDnsResource* dnsResource) const override; |
192 | | }; |
193 | | |
194 | | /// @class IPv6DnsResourceData |
195 | | /// A class that represents DNS RR IPv6 data, mainly used in DNS RRs of type ::DNS_TYPE_AAAA |
196 | | class IPv6DnsResourceData : public IDnsResourceData |
197 | | { |
198 | | private: |
199 | | IPv6Address m_Data; |
200 | | |
201 | | public: |
202 | | /// A c'tor for this class |
203 | | /// @param[in] dataPtr A byte array of size 16 that contains an IPv6 address (each byte represents 1 octet) |
204 | | /// @param[in] dataLen The byte array size, expected to be 16 |
205 | | IPv6DnsResourceData(const uint8_t* dataPtr, size_t dataLen); |
206 | | |
207 | | /// A c'tor for this class |
208 | | /// @param[in] addr The IPv6 address to store in this object |
209 | | explicit IPv6DnsResourceData(const IPv6Address& addr) : m_Data(addr) |
210 | 0 | {} |
211 | | |
212 | | /// A c'tor for this class |
213 | | /// @param[in] addrAsString A string representation of an IPv6 address to store in this object |
214 | | explicit IPv6DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) |
215 | 0 | {} |
216 | | |
217 | | /// Equality operator overload for this class that compares the IPv6 addresses stored in each object |
218 | | /// @param[in] other The object to compare with |
219 | | /// @return True if IPv6 addresses are the same in both objects, false otherwise |
220 | | bool operator==(const IPv6DnsResourceData& other) const |
221 | 0 | { |
222 | 0 | return m_Data == other.m_Data; |
223 | 0 | } |
224 | | |
225 | | /// @return The IPv6 address stored in this object |
226 | | IPv6Address getIpAddress() const |
227 | 0 | { |
228 | 0 | return m_Data; |
229 | 0 | } |
230 | | |
231 | | // implement abstract methods |
232 | | |
233 | | std::string toString() const override |
234 | 0 | { |
235 | 0 | return m_Data.toString(); |
236 | 0 | } |
237 | | std::vector<uint8_t> toBytes(IDnsResource* dnsResource) const override; |
238 | | }; |
239 | | |
240 | | /// @class MxDnsResourceData |
241 | | /// A class that represents DNS RR mail exchange (MX) data, used in DNS RRs of type ::DNS_TYPE_MX |
242 | | class MxDnsResourceData : public IDnsResourceData |
243 | | { |
244 | | public: |
245 | | /// A struct that represents mail exchange (MX) data |
246 | | struct MxData |
247 | | { |
248 | | /// Preference value |
249 | | uint16_t preference = 0; |
250 | | /// Mail exchange hostname |
251 | | std::string mailExchange; |
252 | | }; |
253 | | |
254 | | /// A c'tor for this class |
255 | | /// @param[in] dataPtr A byte array that contains the raw MX data (as written in the DNS packet) |
256 | | /// @param[in] dataLen The byte array size |
257 | | /// @param[in] dnsResource A pointer to a DNS resource object where this DNS RR data will be stored |
258 | | MxDnsResourceData(uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource); |
259 | | |
260 | | /// A c'tor for this class |
261 | | /// @param[in] preference The MX preference value to store in this object |
262 | | /// @param[in] mailExchange The MX hostname value to store in this object. It's possible to include a pointer to |
263 | | /// another string in the DNS layer (as explained here: http://www.zytrax.com/books/dns/ch15/#name). These |
264 | | /// pointers are often used to reduce the DNS packet size and avoid unnecessary duplications. The way to include |
265 | | /// pointers in the hostname string is to use the following format: 'some.domain.#{offset}' where '#{offset}' is |
266 | | /// the offset from the start of the DNS layer. For example: if the string 'yahoo.com' already appears in offset |
267 | | /// 12 in the packet and you want to set the DNS RR data as 'my.subdomain.yahoo.com' you may use the following |
268 | | /// string: 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12 |
269 | | MxDnsResourceData(uint16_t preference, const std::string& mailExchange); |
270 | | |
271 | 0 | ~MxDnsResourceData() override = default; |
272 | | |
273 | | /// Equality operator overload for this class that compares the MX data stored in each object |
274 | | /// @param[in] other The object to compare with |
275 | | /// @return True if MX data is the same in both objects, meaning both preference and MX hostname are the same, |
276 | | /// false otherwise |
277 | | bool operator==(const MxDnsResourceData& other) const; |
278 | | |
279 | | /// @return The MX data stored in this object |
280 | | MxData getMxData() const |
281 | 0 | { |
282 | 0 | return m_Data; |
283 | 0 | } |
284 | | |
285 | | /// Set the MX data stored in this object |
286 | | /// @param[in] preference The MX preference value to store in this object |
287 | | /// @param[in] mailExchange The MX hostname value to store in this object |
288 | | void setMxData(uint16_t preference, std::string mailExchange); |
289 | | |
290 | | // implement abstract methods |
291 | | |
292 | | /// A string representation of the MX data stored in this object. The string format is as follows: |
293 | | /// 'pref: {preference_value}; mx: {mail_exchange_hostname_value}' |
294 | | std::string toString() const override; |
295 | | |
296 | | std::vector<uint8_t> toBytes(IDnsResource* dnsResource) const override; |
297 | | |
298 | | private: |
299 | | MxData m_Data; |
300 | | }; |
301 | | |
302 | | /// @class GenericDnsResourceData |
303 | | /// A class that represents generic DNS RR data which cannot be represented in any of the other classes. It stores |
304 | | /// the DNS RR data as byte array |
305 | | class GenericDnsResourceData : public IDnsResourceData |
306 | | { |
307 | | private: |
308 | | uint8_t* m_Data; |
309 | | size_t m_DataLen; |
310 | | |
311 | | public: |
312 | | /// A c'tor for this class |
313 | | /// @param[in] dataPtr A byte array that contains the raw data (as it written in the DNS packet). The data will |
314 | | /// be copied from this byte array to the object |
315 | | /// @param[in] dataLen The byte array size |
316 | | GenericDnsResourceData(const uint8_t* dataPtr, size_t dataLen); |
317 | | |
318 | | /// A c'tor for this class |
319 | | /// @param[in] dataAsHexString A hex string that represents the DNS RR data |
320 | | explicit GenericDnsResourceData(const std::string& dataAsHexString); |
321 | | |
322 | | /// A copy c'tor for this class |
323 | | /// @param[in] other The instance to copy from |
324 | | GenericDnsResourceData(const GenericDnsResourceData& other); |
325 | | |
326 | | ~GenericDnsResourceData() override |
327 | 0 | { |
328 | 0 | if (m_Data != nullptr) |
329 | 0 | delete[] m_Data; |
330 | 0 | } |
331 | | |
332 | | GenericDnsResourceData& operator=(const GenericDnsResourceData& other); |
333 | | |
334 | | /// Equality operator overload for this class that compares the raw data stored in each object |
335 | | /// @param[in] other The object to compare with |
336 | | /// @return True if data is the same in both objects, meaning byte streams are equal, false otherwise |
337 | | bool operator==(const GenericDnsResourceData& other) const; |
338 | | |
339 | | // implement abstract methods |
340 | | |
341 | | std::string toString() const override; |
342 | | std::vector<uint8_t> toBytes(IDnsResource* dnsResource) const override; |
343 | | }; |
344 | | |
345 | | } // namespace pcpp |