Coverage Report

Created: 2023-01-17 06:15

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