Coverage Report

Created: 2025-07-11 07:47

/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