Coverage Report

Created: 2024-02-25 06:29

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