Coverage Report

Created: 2025-07-11 07:47

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