Coverage Report

Created: 2024-02-25 06:29

/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
/**
13
 * \namespace pcpp
14
 * \brief The main namespace for the PcapPlusPlus lib
15
 */
16
namespace pcpp
17
{
18
  // forward declarations
19
  class DnsLayer;
20
  class IDnsResourceData;
21
  class DnsResourceDataPtr;
22
23
24
  /**
25
   * @class IDnsResource
26
   * An abstract class for representing all types of DNS records. This class gives access to all available record data such as DNS type, class,
27
   * name, type of record, etc. The DnsLayer holds an instance of (inherited type of) this class for each DNS record in the DNS packet
28
   */
29
  class IDnsResource
30
  {
31
  protected:
32
    friend class DnsLayer;
33
    friend class IDnsResourceData;
34
35
  protected:
36
    DnsLayer* m_DnsLayer;
37
    size_t m_OffsetInLayer;
38
    IDnsResource* m_NextResource;
39
    std::string m_DecodedName;
40
    size_t m_NameLength;
41
    uint8_t* m_ExternalRawData;
42
43
    IDnsResource(DnsLayer* dnsLayer, size_t offsetInLayer);
44
45
    IDnsResource(uint8_t* emptyRawData);
46
47
    size_t decodeName(const char* encodedName, char* result, int iteration = 1);
48
    void encodeName(const std::string& decodedName, char* result, size_t& resultLen);
49
50
1.92M
    IDnsResource* getNextResource() const { return m_NextResource; }
51
540k
    void setNexResource(IDnsResource* next) { m_NextResource = next; }
52
53
    uint8_t* getRawData() const;
54
55
    void setDnsLayer(DnsLayer* dnsLayer, size_t offsetInLayer);
56
57
  public:
58
59
536k
    virtual ~IDnsResource() {}
60
61
    /**
62
     * @return The DNS type of this record
63
     */
64
    DnsType getDnsType() const;
65
66
    /**
67
     * Set DNS type for this record
68
     * @param[in] newType The type to set
69
     */
70
    void setDnsType(DnsType newType);
71
72
    /**
73
     * @return The DNS class of this record
74
     */
75
    DnsClass getDnsClass() const;
76
77
    /**
78
     * Set DNS class for this record
79
     * @param[in] newClass The class to set
80
     */
81
    void setDnsClass(DnsClass newClass);
82
83
    /**
84
     * @return The name of this record
85
     */
86
316k
    const std::string& getName() const { return m_DecodedName; }
87
88
    /**
89
     * @return The record name's offset in the packet
90
     */
91
0
    size_t getNameOffset() const { return m_OffsetInLayer; }
92
93
    /**
94
     * Set the name of this record. The input name can be a standard hostname (e.g 'google.com'), or it may contain
95
     * a pointer to another string in the packet (as explained here: http://www.zytrax.com/books/dns/ch15/#name).
96
     * The pointer is used to reduce the DNS packet size and avoid unnecessary duplications. In case you
97
     * want to use a pointer in your string you should use the following format: 'some.domain.#{offset}' where '#{offset}'
98
     * is a the offset from the start of the layer. For example: if the string 'yahoo.com' already appears in offset
99
     * 12 in the packet and you want to set the name of the current record to 'my.subdomain.yahoo.com' you may use
100
     * the following string: 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12.<BR>
101
     * Please notice the new name can be shorter or longer of the old name, so this method can cause the packet to be
102
     * shorten or extended
103
     * @param[in] newName The name to set
104
     * @return True if name was set successfully or false if input string is malformed or if an error occurred
105
     */
106
    bool setName(const std::string& newName);
107
108
109
    // abstract methods
110
111
    /**
112
     * @return The total size in bytes of this record
113
     */
114
    virtual size_t getSize() const = 0;
115
116
    /**
117
     * @return The type of this record (query, answer, authority, additional)
118
     */
119
    virtual DnsResourceType getType() const = 0;
120
  };
121
122
123
  /**
124
   * @class DnsQuery
125
   * Representing a DNS query record
126
   */
127
  class DnsQuery : public IDnsResource
128
  {
129
    friend class DnsLayer;
130
131
  private:
132
210k
    DnsQuery(DnsLayer* dnsLayer, size_t offsetInLayer) : IDnsResource(dnsLayer, offsetInLayer) {}
133
134
24.9k
    explicit DnsQuery(uint8_t* emptyRawData) : IDnsResource(emptyRawData) {}
135
136
  public:
137
0
    virtual ~DnsQuery() {}
138
139
    // implementation of abstract methods
140
425k
    virtual size_t getSize() const { return m_NameLength + 2 * sizeof(uint16_t); }
141
248k
    virtual DnsResourceType getType() const { return DnsQueryType; }
142
  };
143
144
145
  /**
146
   * @class DnsResource
147
   * Representing DNS record other than DNS query
148
   */
149
  class DnsResource : public IDnsResource
150
  {
151
    friend class DnsLayer;
152
153
  private:
154
    DnsResourceType m_ResourceType;
155
156
226k
    DnsResource(DnsLayer* dnsLayer, size_t offsetInLayer, DnsResourceType resourceType) : IDnsResource(dnsLayer, offsetInLayer) { m_ResourceType = resourceType; }
157
158
74.7k
    DnsResource(uint8_t* emptyRawData, DnsResourceType resType) : IDnsResource(emptyRawData), m_ResourceType(resType) {}
159
160
  public:
161
0
    virtual ~DnsResource() {}
162
163
    /**
164
     * @return The time-to-leave value for this record
165
     */
166
    uint32_t getTTL() const;
167
168
    /**
169
     * Set time-to-leave value for this record
170
     * @param[in] newTTL The new TTL value to set
171
     */
172
    void setTTL(uint32_t newTTL);
173
174
    /**
175
     * @return The data length value for this record (taken from the "data length" field of the record)
176
     */
177
    size_t getDataLength() const;
178
179
    /**
180
     * @return A smart pointer to an IDnsResourceData object that contains the DNS resource data. It is guaranteed that the
181
     * smart pointer will always point to an object and never to NULL. The specific object type depends on the DNS type of this record:<BR>
182
     * - For type A (::DNS_TYPE_A): the return value is a smart pointer to IPv4DnsResourceData object that contains the IPv4 address<BR>
183
     * - For type AAAA (::DNS_TYPE_AAAA): the return value is a smart pointer to IPv6DnsResourceData object that contains the IPv6 address<BR>
184
     * - For types NS, CNAME, DNAME, PTR (::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR): the return value is
185
     *   a smart pointer to StringDnsResourceData object that contains the name<BR>
186
     * - For type MX (::DNS_TYPE_MX): the return value is a smart pointer to MxDnsResourceData object that contains the MX data (preference and
187
     *   mail exchange name)<BR>
188
     * - For all other types: the return value is a smart pointer to GenericDnsResourceData which contains a byte array of the data
189
     */
190
    DnsResourceDataPtr getData() const;
191
192
    /**
193
     * @return The offset of data in the DNS layer
194
     */
195
    size_t getDataOffset() const;
196
197
    /**
198
     * Set resource data. The given IDnsResourceData input object is validated against the DNS type of the resource. For example: if DNS type is A
199
     * and data isn't of type IPv4DnsResourceData (which contains the IPv4 address) a log error will be printed and the method will return false.
200
     * This method currently supports the following DNS types:<BR>
201
     * - ::DNS_TYPE_A (IPv4 address) - data is expected to be a pointer to IPv4DnsResourceData with a valid IPv4 address
202
     * - ::DNS_TYPE_AAAA (IPv6 address) - data is expected to be a pointer to IPv6DnsResourceData with a valid IPv6 address
203
     * - ::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR (name data) - data is expected to be a pointer to StringDnsResourceData
204
     *   object that contains a host name, e.g: 'www.google.com'
205
     * - ::DNS_TYPE_MX (MX data) - data is expected to be a pointer to MxDnsResourceData object that contains the MX data
206
     * - else: data is expected to be a pointer to GenericDnsResourceData object that contains a valid hex string (valid hex string means a string
207
     *   which has an even number of characters representing a valid hex data. e.g: '0d0a45569a9b')
208
     * @param[in] data The pointer to the data object, as described above
209
     * @return True if data was properly set or false if data is illegal or method couldn't extend or shorted the packet (appropriate error log is
210
     * printed in all cases)
211
     */
212
    bool setData(IDnsResourceData* data);
213
214
    /**
215
     * Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the
216
     * user to receive these bytes
217
     * @return The value stored in this place
218
     */
219
    uint16_t getCustomDnsClass() const;
220
221
    /**
222
     * Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the
223
     * user to set these bytes
224
     * @param[in] customValue The value to set
225
     */
226
    void setCustomDnsClass(uint16_t customValue);
227
228
    // implementation of abstract methods
229
601k
    virtual size_t getSize() const { return m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t) + getDataLength(); }
230
568k
    virtual DnsResourceType getType() const { return m_ResourceType; }
231
232
  };
233
234
}