Coverage Report

Created: 2023-01-17 06:15

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