Coverage Report

Created: 2024-02-25 06:29

/src/PcapPlusPlus/Packet++/header/TLVData.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "Layer.h"
4
#include "IpAddress.h"
5
#include <string.h>
6
7
/// @file
8
9
/**
10
 * \namespace pcpp
11
 * \brief The main namespace for the PcapPlusPlus lib
12
 */
13
namespace pcpp
14
{
15
  /**
16
   * @class TLVRecord
17
   * A wrapper class for a Type-Length-Value (TLV) record. This class does not create or modify TLV records, but rather
18
   * serves as a wrapper and provides useful methods for retrieving data from them. This class has several abstract methods
19
   * that should be implemented in derived classes. These methods are for record length value calculation (the 'L' in TLV)
20
   * which is implemented differently in different protocols
21
   */
22
  template<typename TRecType, typename TRecLen>
23
  class TLVRecord
24
  {
25
  protected:
26
27
    /** A struct representing the TLV construct */
28
    struct TLVRawData
29
    {
30
      /** Record type */
31
      TRecType recordType;
32
      /** Record length in bytes */
33
      TRecLen recordLen;
34
      /** Record value (variable size) */
35
      uint8_t recordValue[];
36
    };
37
38
    TLVRawData* m_Data;
39
40
  public:
41
42
    /**
43
     * A c'tor for this class that gets a pointer to the TLV record raw data (byte array)
44
     * @param[in] recordRawData A pointer to the TLV record raw data
45
     */
46
    TLVRecord(uint8_t* recordRawData)
47
856k
    {
48
856k
      assign(recordRawData);
49
856k
    }
pcpp::TLVRecord<unsigned char, unsigned char>::TLVRecord(unsigned char*)
Line
Count
Source
47
844k
    {
48
844k
      assign(recordRawData);
49
844k
    }
pcpp::TLVRecord<unsigned short, unsigned short>::TLVRecord(unsigned char*)
Line
Count
Source
47
12.0k
    {
48
12.0k
      assign(recordRawData);
49
12.0k
    }
50
51
    /**
52
     * A copy c'tor for this class. This copy c'tor doesn't copy the TLV data, but only the pointer to it,
53
     * which means that after calling it both the old and the new instance will point to the same TLV raw data
54
     * @param[in] other The TLVRecord instance to copy from
55
     */
56
    TLVRecord(const TLVRecord& other)
57
246k
    {
58
246k
      m_Data = other.m_Data;
59
246k
    }
pcpp::TLVRecord<unsigned short, unsigned short>::TLVRecord(pcpp::TLVRecord<unsigned short, unsigned short> const&)
Line
Count
Source
57
2.58k
    {
58
2.58k
      m_Data = other.m_Data;
59
2.58k
    }
pcpp::TLVRecord<unsigned char, unsigned char>::TLVRecord(pcpp::TLVRecord<unsigned char, unsigned char> const&)
Line
Count
Source
57
244k
    {
58
244k
      m_Data = other.m_Data;
59
244k
    }
60
61
    /**
62
     * A d'tor for this class, currently does nothing
63
     */
64
1.10M
    virtual ~TLVRecord() { }
pcpp::TLVRecord<unsigned char, unsigned char>::~TLVRecord()
Line
Count
Source
64
1.08M
    virtual ~TLVRecord() { }
pcpp::TLVRecord<unsigned short, unsigned short>::~TLVRecord()
Line
Count
Source
64
14.6k
    virtual ~TLVRecord() { }
65
66
    /**
67
     * Assign a pointer to the TLV record raw data (byte array)
68
     * @param[in] recordRawData A pointer to the TLV record raw data
69
     */
70
    void assign(uint8_t* recordRawData)
71
1.53M
    {
72
1.53M
      m_Data = (TLVRawData*)recordRawData;
73
1.53M
    }
pcpp::TLVRecord<unsigned char, unsigned char>::assign(unsigned char*)
Line
Count
Source
71
1.50M
    {
72
1.50M
      m_Data = (TLVRawData*)recordRawData;
73
1.50M
    }
pcpp::TLVRecord<unsigned short, unsigned short>::assign(unsigned char*)
Line
Count
Source
71
29.7k
    {
72
29.7k
      m_Data = (TLVRawData*)recordRawData;
73
29.7k
    }
74
75
    /**
76
     * Check if a pointer can be assigned to the TLV record data
77
     * @param[in] recordRawData A pointer to the TLV record raw data
78
     * @param[in] tlvDataLen The size of the TLV record raw data
79
     * @return True if data is valid and can be assigned
80
     */
81
    static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
82
136k
    {
83
136k
      return recordRawData != nullptr && tlvDataLen >= (sizeof(TLVRawData::recordType) + sizeof(TLVRawData::recordLen));
84
136k
    }
pcpp::TLVRecord<unsigned char, unsigned char>::canAssign(unsigned char const*, unsigned long)
Line
Count
Source
82
123k
    {
83
123k
      return recordRawData != nullptr && tlvDataLen >= (sizeof(TLVRawData::recordType) + sizeof(TLVRawData::recordLen));
84
123k
    }
pcpp::TLVRecord<unsigned short, unsigned short>::canAssign(unsigned char const*, unsigned long)
Line
Count
Source
82
12.0k
    {
83
12.0k
      return recordRawData != nullptr && tlvDataLen >= (sizeof(TLVRawData::recordType) + sizeof(TLVRawData::recordLen));
84
12.0k
    }
85
86
    /**
87
     * Overload of the assignment operator. This operator doesn't copy the TLV data, but rather copies the pointer to it,
88
     * which means that after calling it both the old and the new instance will point to the same TLV raw data
89
     * @param[in] other The TLVRecord instance to assign
90
     */
91
    TLVRecord& operator=(const TLVRecord& other)
92
503k
    {
93
503k
      m_Data = other.m_Data;
94
503k
      return *this;
95
503k
    }
pcpp::TLVRecord<unsigned short, unsigned short>::operator=(pcpp::TLVRecord<unsigned short, unsigned short> const&)
Line
Count
Source
92
6.85k
    {
93
6.85k
      m_Data = other.m_Data;
94
6.85k
      return *this;
95
6.85k
    }
pcpp::TLVRecord<unsigned char, unsigned char>::operator=(pcpp::TLVRecord<unsigned char, unsigned char> const&)
Line
Count
Source
92
496k
    {
93
496k
      m_Data = other.m_Data;
94
496k
      return *this;
95
496k
    }
96
97
    /**
98
     * Overload of the equality operator. Two record are equal if both of them point to the same data, or if they point
99
     * to different data but their total size is equal and the raw data they both contain is similar.
100
     * @param[in] rhs The object to compare to
101
     * @return True if both objects are equal, false otherwise
102
     */
103
    bool operator==(const TLVRecord& rhs) const
104
    {
105
      if (m_Data == rhs.m_Data)
106
        return true;
107
108
      if (getTotalSize() != rhs.getTotalSize())
109
        return false;
110
111
      if (isNull() || ((TLVRecord&)rhs).isNull())
112
        return false;
113
114
      return (memcmp(m_Data, rhs.m_Data, getTotalSize()) == 0);
115
    }
116
117
    /**
118
     * Overload of the not equal operator.
119
     * @param[in] rhs The object to compare to
120
     * @return True if objects are not equal, false otherwise
121
     */
122
    bool operator!=(const TLVRecord& rhs) const
123
    {
124
      return !operator==(rhs);
125
    }
126
127
    /**
128
     * @return The type field of the record (the 'T' in __Type__-Length-Value)
129
     */
130
302k
    TRecType getType() const {
131
302k
      if (m_Data == nullptr)
132
0
        return 0;
133
134
302k
      return m_Data->recordType;
135
302k
    }
136
137
    /**
138
     * @return A pointer to the value of the record as byte array (the 'V' in Type-Length- __Value__)
139
     */
140
746
    uint8_t* getValue() const {
141
746
      if (m_Data == nullptr)
142
0
        return nullptr;
143
144
746
      return m_Data->recordValue;
145
746
    }
146
147
    /**
148
     * @return True if the TLV record raw data is NULL, false otherwise
149
     */
150
1.87M
    bool isNull() const { return (m_Data == nullptr); }
pcpp::TLVRecord<unsigned char, unsigned char>::isNull() const
Line
Count
Source
150
1.84M
    bool isNull() const { return (m_Data == nullptr); }
pcpp::TLVRecord<unsigned short, unsigned short>::isNull() const
Line
Count
Source
150
26.3k
    bool isNull() const { return (m_Data == nullptr); }
151
152
    /**
153
     * @return True if the TLV record raw data is not NULL, false otherwise
154
     */
155
143k
    bool isNotNull() const { return (m_Data != nullptr); }
156
157
    /**
158
     * @return A pointer to the TLV record raw data byte stream
159
     */
160
2.58M
    uint8_t* getRecordBasePtr() const { return (uint8_t*)m_Data; }
pcpp::TLVRecord<unsigned char, unsigned char>::getRecordBasePtr() const
Line
Count
Source
160
2.54M
    uint8_t* getRecordBasePtr() const { return (uint8_t*)m_Data; }
pcpp::TLVRecord<unsigned short, unsigned short>::getRecordBasePtr() const
Line
Count
Source
160
38.2k
    uint8_t* getRecordBasePtr() const { return (uint8_t*)m_Data; }
161
162
    /**
163
     * Free the memory of the TLV record raw data
164
     */
165
    void purgeRecordData()
166
41.8k
    {
167
41.8k
      if (!isNull())
168
41.8k
      {
169
41.8k
        delete [] m_Data;
170
41.8k
        m_Data = nullptr;
171
41.8k
      }
172
41.8k
    }
pcpp::TLVRecord<unsigned char, unsigned char>::purgeRecordData()
Line
Count
Source
166
41.8k
    {
167
41.8k
      if (!isNull())
168
41.8k
      {
169
41.8k
        delete [] m_Data;
170
41.8k
        m_Data = nullptr;
171
41.8k
      }
172
41.8k
    }
Unexecuted instantiation: pcpp::TLVRecord<unsigned short, unsigned short>::purgeRecordData()
173
174
    /**
175
     * A templated method to retrieve the record data as a certain type T. For example, if record data is 4B long
176
     * (integer) then this method should be used as getValueAs<int>() and it will return the record data as an integer.<BR>
177
     * Notice this return value is a copy of the data, not a pointer to the actual data
178
     * @param[in] offset The offset in the record data to start reading the value from. Useful for cases when you want
179
     * to read some of the data that doesn't start at offset 0. This is an optional parameter and the default value
180
     * is 0, meaning start reading the value at the beginning of the record data
181
     * @return The record data as type T
182
     */
183
    template<typename T>
184
    T getValueAs(size_t offset = 0) const
185
7.53k
    {
186
7.53k
      if (getDataSize() - offset < sizeof(T))
187
1.99k
        return 0;
188
189
5.54k
      T result;
190
5.54k
      memcpy(&result, m_Data->recordValue + offset, sizeof(T));
191
5.54k
      return result;
192
7.53k
    }
unsigned int pcpp::TLVRecord<unsigned char, unsigned char>::getValueAs<unsigned int>(unsigned long) const
Line
Count
Source
185
2.01k
    {
186
2.01k
      if (getDataSize() - offset < sizeof(T))
187
1.99k
        return 0;
188
189
13
      T result;
190
13
      memcpy(&result, m_Data->recordValue + offset, sizeof(T));
191
13
      return result;
192
2.01k
    }
unsigned char pcpp::TLVRecord<unsigned char, unsigned char>::getValueAs<unsigned char>(unsigned long) const
Line
Count
Source
185
5.52k
    {
186
5.52k
      if (getDataSize() - offset < sizeof(T))
187
0
        return 0;
188
189
5.52k
      T result;
190
5.52k
      memcpy(&result, m_Data->recordValue + offset, sizeof(T));
191
5.52k
      return result;
192
5.52k
    }
193
194
    /**
195
     * A templated method to copy data of type T into the TLV record data. For example: if record data is 4[Bytes] long use
196
     * this method with \<int\> to set an integer value into the record data: setValue<int>(num)
197
     * @param[in] newValue The value of type T to copy to the record data
198
     * @param[in] valueOffset An optional parameter that specifies where to start setting the record data (default set to 0). For example:
199
     * if record data is 20 bytes long and you only need to set the 4 last bytes as integer then use this method like this:
200
     * setValue<int>(num, 16)
201
     * @return True if value was set successfully or false if the size of T is larger than the record data size
202
     */
203
    template<typename T>
204
    bool setValue(T newValue, int valueOffset = 0)
205
0
    {
206
0
      if (getDataSize() < sizeof(T))
207
0
        return false;
208
209
0
      memcpy(m_Data->recordValue + valueOffset, &newValue, sizeof(T));
210
0
      return true;
211
0
    }
Unexecuted instantiation: bool pcpp::TLVRecord<unsigned char, unsigned char>::setValue<unsigned int>(unsigned int, int)
Unexecuted instantiation: bool pcpp::TLVRecord<unsigned char, unsigned char>::setValue<unsigned char>(unsigned char, int)
212
213
    /**
214
     * @return The total size of the TLV record (in bytes)
215
     */
216
    virtual size_t getTotalSize() const = 0;
217
218
    /**
219
     * @return The size of the record value (meaning the size of the 'V' part in TLV)
220
     */
221
    virtual size_t getDataSize() const = 0;
222
  };
223
224
225
  /**
226
   * @class TLVRecordReader
227
   * A class for reading TLV records data out of a byte stream. This class contains helper methods for retrieving and
228
   * counting TLV records. This is a template class that expects template argument class derived from TLVRecord.
229
   */
230
  template<typename TLVRecordType>
231
  class TLVRecordReader
232
  {
233
  private:
234
    mutable size_t m_RecordCount;
235
236
  public:
237
238
    /**
239
     * A default c'tor for this class
240
     */
241
1.64M
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::DhcpOption>::TLVRecordReader()
Line
Count
Source
241
11.0k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::DhcpV6Option>::TLVRecordReader()
Line
Count
Source
241
7.94k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::IPv4Option>::TLVRecordReader()
Line
Count
Source
241
871k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::NflogTlv>::TLVRecordReader()
Line
Count
Source
241
2.88k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::PPPoEDiscoveryLayer::PPPoETag>::TLVRecordReader()
Line
Count
Source
241
6.01k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::TcpOption>::TLVRecordReader()
Line
Count
Source
241
728k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::RadiusAttribute>::TLVRecordReader()
Line
Count
Source
241
1.37k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::NdpOption>::TLVRecordReader()
Line
Count
Source
241
2.87k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
pcpp::TLVRecordReader<pcpp::IPv6TLVOptionHeader::IPv6Option>::TLVRecordReader()
Line
Count
Source
241
15.3k
    TLVRecordReader() { m_RecordCount = (size_t)-1; }
242
243
    /**
244
     * A default copy c'tor for this class
245
     */
246
    TLVRecordReader(const TLVRecordReader& other)
247
    {
248
      m_RecordCount = other.m_RecordCount;
249
    }
250
251
    /**
252
     * A d'tor for this class which currently does nothing
253
     */
254
1.64M
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::TcpOption>::~TLVRecordReader()
Line
Count
Source
254
728k
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::DhcpOption>::~TLVRecordReader()
Line
Count
Source
254
11.0k
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::DhcpV6Option>::~TLVRecordReader()
Line
Count
Source
254
7.94k
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::IPv4Option>::~TLVRecordReader()
Line
Count
Source
254
871k
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::IPv6TLVOptionHeader::IPv6Option>::~TLVRecordReader()
Line
Count
Source
254
15.3k
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::NflogTlv>::~TLVRecordReader()
Line
Count
Source
254
2.88k
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::PPPoEDiscoveryLayer::PPPoETag>::~TLVRecordReader()
Line
Count
Source
254
6.01k
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::RadiusAttribute>::~TLVRecordReader()
Line
Count
Source
254
1.37k
    virtual ~TLVRecordReader() { }
pcpp::TLVRecordReader<pcpp::NdpOption>::~TLVRecordReader()
Line
Count
Source
254
2.87k
    virtual ~TLVRecordReader() { }
255
256
    /**
257
     * Overload of the assignment operator for this class
258
     * @param[in] other The TLVRecordReader instance to assign
259
     */
260
    TLVRecordReader& operator=(const TLVRecordReader& other)
261
124k
    {
262
124k
      m_RecordCount = other.m_RecordCount;
263
124k
      return *this;
264
124k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv4Option>::operator=(pcpp::TLVRecordReader<pcpp::IPv4Option> const&)
pcpp::TLVRecordReader<pcpp::TcpOption>::operator=(pcpp::TLVRecordReader<pcpp::TcpOption> const&)
Line
Count
Source
261
124k
    {
262
124k
      m_RecordCount = other.m_RecordCount;
263
124k
      return *this;
264
124k
    }
265
266
    /**
267
     * Get the first TLV record out of a byte stream
268
     * @param[in] tlvDataBasePtr A pointer to the TLV data byte stream
269
     * @param[in] tlvDataLen The TLV data byte stream length
270
     * @return An instance of type TLVRecordType that contains the first TLV record. If tlvDataBasePtr is NULL or
271
     * tlvDataLen is zero the returned TLVRecordType instance will be logically NULL, meaning TLVRecordType.isNull() will
272
     * return true
273
     */
274
    TLVRecordType getFirstTLVRecord(uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
275
189k
    {
276
189k
      TLVRecordType resRec(NULL); // for NRVO optimization
277
189k
      if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen))
278
78.7k
        return resRec;
279
280
110k
      resRec.assign(tlvDataBasePtr);
281
      // resRec pointer is out-bounds of the TLV records memory
282
110k
      if (resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
283
3.50k
        resRec.assign(NULL);
284
285
      // check if there are records at all and the total size is not zero
286
110k
      if (!resRec.isNull() && (tlvDataLen == 0 || resRec.getTotalSize() == 0))
287
2.86k
        resRec.assign(NULL);
288
289
110k
      return resRec;
290
189k
    }
pcpp::TLVRecordReader<pcpp::DhcpOption>::getFirstTLVRecord(unsigned char*, unsigned long) const
Line
Count
Source
275
12.1k
    {
276
12.1k
      TLVRecordType resRec(NULL); // for NRVO optimization
277
12.1k
      if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen))
278
0
        return resRec;
279
280
12.1k
      resRec.assign(tlvDataBasePtr);
281
      // resRec pointer is out-bounds of the TLV records memory
282
12.1k
      if (resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
283
70
        resRec.assign(NULL);
284
285
      // check if there are records at all and the total size is not zero
286
12.1k
      if (!resRec.isNull() && (tlvDataLen == 0 || resRec.getTotalSize() == 0))
287
0
        resRec.assign(NULL);
288
289
12.1k
      return resRec;
290
12.1k
    }
pcpp::TLVRecordReader<pcpp::DhcpV6Option>::getFirstTLVRecord(unsigned char*, unsigned long) const
Line
Count
Source
275
5.18k
    {
276
5.18k
      TLVRecordType resRec(NULL); // for NRVO optimization
277
5.18k
      if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen))
278
0
        return resRec;
279
280
5.18k
      resRec.assign(tlvDataBasePtr);
281
      // resRec pointer is out-bounds of the TLV records memory
282
5.18k
      if (resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
283
313
        resRec.assign(NULL);
284
285
      // check if there are records at all and the total size is not zero
286
5.18k
      if (!resRec.isNull() && (tlvDataLen == 0 || resRec.getTotalSize() == 0))
287
0
        resRec.assign(NULL);
288
289
5.18k
      return resRec;
290
5.18k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv4Option>::getFirstTLVRecord(unsigned char*, unsigned long) const
pcpp::TLVRecordReader<pcpp::TcpOption>::getFirstTLVRecord(unsigned char*, unsigned long) const
Line
Count
Source
275
166k
    {
276
166k
      TLVRecordType resRec(NULL); // for NRVO optimization
277
166k
      if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen))
278
76.0k
        return resRec;
279
280
90.3k
      resRec.assign(tlvDataBasePtr);
281
      // resRec pointer is out-bounds of the TLV records memory
282
90.3k
      if (resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
283
2.95k
        resRec.assign(NULL);
284
285
      // check if there are records at all and the total size is not zero
286
90.3k
      if (!resRec.isNull() && (tlvDataLen == 0 || resRec.getTotalSize() == 0))
287
2.49k
        resRec.assign(NULL);
288
289
90.3k
      return resRec;
290
166k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv6TLVOptionHeader::IPv6Option>::getFirstTLVRecord(unsigned char*, unsigned long) const
pcpp::TLVRecordReader<pcpp::NdpOption>::getFirstTLVRecord(unsigned char*, unsigned long) const
Line
Count
Source
275
2.18k
    {
276
2.18k
      TLVRecordType resRec(NULL); // for NRVO optimization
277
2.18k
      if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen))
278
684
        return resRec;
279
280
1.49k
      resRec.assign(tlvDataBasePtr);
281
      // resRec pointer is out-bounds of the TLV records memory
282
1.49k
      if (resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
283
2
        resRec.assign(NULL);
284
285
      // check if there are records at all and the total size is not zero
286
1.49k
      if (!resRec.isNull() && (tlvDataLen == 0 || resRec.getTotalSize() == 0))
287
2
        resRec.assign(NULL);
288
289
1.49k
      return resRec;
290
2.18k
    }
pcpp::TLVRecordReader<pcpp::NflogTlv>::getFirstTLVRecord(unsigned char*, unsigned long) const
Line
Count
Source
275
3.70k
    {
276
3.70k
      TLVRecordType resRec(NULL); // for NRVO optimization
277
3.70k
      if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen))
278
2.01k
        return resRec;
279
280
1.69k
      resRec.assign(tlvDataBasePtr);
281
      // resRec pointer is out-bounds of the TLV records memory
282
1.69k
      if (resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
283
165
        resRec.assign(NULL);
284
285
      // check if there are records at all and the total size is not zero
286
1.69k
      if (!resRec.isNull() && (tlvDataLen == 0 || resRec.getTotalSize() == 0))
287
369
        resRec.assign(NULL);
288
289
1.69k
      return resRec;
290
3.70k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::PPPoEDiscoveryLayer::PPPoETag>::getFirstTLVRecord(unsigned char*, unsigned long) const
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::RadiusAttribute>::getFirstTLVRecord(unsigned char*, unsigned long) const
291
292
    /**
293
     * Get a TLV record that follows a given TLV record in a byte stream
294
     * @param[in] record A given TLV record
295
     * @param[in] tlvDataBasePtr A pointer to the TLV data byte stream
296
     * @param[in] tlvDataLen The TLV data byte stream length
297
     * @return An instance of type TLVRecordType that wraps the record following the record given as input. If the
298
     * input record.isNull() is true or if the next record is out of bounds of the byte stream, a logical NULL instance
299
     * of TLVRecordType will be returned, meaning TLVRecordType.isNull() will return true
300
     */
301
    TLVRecordType getNextTLVRecord(TLVRecordType& record, const uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
302
505k
    {
303
505k
      TLVRecordType resRec(NULL); // for NRVO optimization
304
305
505k
      if (record.isNull())
306
0
        return resRec;
307
308
505k
      if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - record.getTotalSize()))
309
41.8k
        return resRec;
310
311
464k
      resRec.assign(record.getRecordBasePtr() + record.getTotalSize());
312
313
464k
      if (resRec.getTotalSize() == 0)
314
1.31k
        resRec.assign(NULL);
315
316
      // resRec pointer is out-bounds of the TLV records memory
317
464k
      if ((resRec.getRecordBasePtr() - tlvDataBasePtr) < 0)
318
1.31k
        resRec.assign(NULL);
319
320
      // resRec pointer is out-bounds of the TLV records memory
321
464k
      if (!resRec.isNull() && resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
322
11.7k
        resRec.assign(NULL);
323
324
464k
      return resRec;
325
505k
    }
pcpp::TLVRecordReader<pcpp::DhcpOption>::getNextTLVRecord(pcpp::DhcpOption&, unsigned char const*, unsigned long) const
Line
Count
Source
302
335k
    {
303
335k
      TLVRecordType resRec(NULL); // for NRVO optimization
304
305
335k
      if (record.isNull())
306
0
        return resRec;
307
308
335k
      if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - record.getTotalSize()))
309
5.92k
        return resRec;
310
311
329k
      resRec.assign(record.getRecordBasePtr() + record.getTotalSize());
312
313
329k
      if (resRec.getTotalSize() == 0)
314
0
        resRec.assign(NULL);
315
316
      // resRec pointer is out-bounds of the TLV records memory
317
329k
      if ((resRec.getRecordBasePtr() - tlvDataBasePtr) < 0)
318
0
        resRec.assign(NULL);
319
320
      // resRec pointer is out-bounds of the TLV records memory
321
329k
      if (!resRec.isNull() && resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
322
232
        resRec.assign(NULL);
323
324
329k
      return resRec;
325
335k
    }
pcpp::TLVRecordReader<pcpp::DhcpV6Option>::getNextTLVRecord(pcpp::DhcpV6Option&, unsigned char const*, unsigned long) const
Line
Count
Source
302
6.85k
    {
303
6.85k
      TLVRecordType resRec(NULL); // for NRVO optimization
304
305
6.85k
      if (record.isNull())
306
0
        return resRec;
307
308
6.85k
      if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - record.getTotalSize()))
309
398
        return resRec;
310
311
6.45k
      resRec.assign(record.getRecordBasePtr() + record.getTotalSize());
312
313
6.45k
      if (resRec.getTotalSize() == 0)
314
0
        resRec.assign(NULL);
315
316
      // resRec pointer is out-bounds of the TLV records memory
317
6.45k
      if ((resRec.getRecordBasePtr() - tlvDataBasePtr) < 0)
318
0
        resRec.assign(NULL);
319
320
      // resRec pointer is out-bounds of the TLV records memory
321
6.45k
      if (!resRec.isNull() && resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
322
4.28k
        resRec.assign(NULL);
323
324
6.45k
      return resRec;
325
6.85k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv4Option>::getNextTLVRecord(pcpp::IPv4Option&, unsigned char const*, unsigned long) const
pcpp::TLVRecordReader<pcpp::TcpOption>::getNextTLVRecord(pcpp::TcpOption&, unsigned char const*, unsigned long) const
Line
Count
Source
302
161k
    {
303
161k
      TLVRecordType resRec(NULL); // for NRVO optimization
304
305
161k
      if (record.isNull())
306
0
        return resRec;
307
308
161k
      if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - record.getTotalSize()))
309
35.3k
        return resRec;
310
311
125k
      resRec.assign(record.getRecordBasePtr() + record.getTotalSize());
312
313
125k
      if (resRec.getTotalSize() == 0)
314
710
        resRec.assign(NULL);
315
316
      // resRec pointer is out-bounds of the TLV records memory
317
125k
      if ((resRec.getRecordBasePtr() - tlvDataBasePtr) < 0)
318
710
        resRec.assign(NULL);
319
320
      // resRec pointer is out-bounds of the TLV records memory
321
125k
      if (!resRec.isNull() && resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
322
6.99k
        resRec.assign(NULL);
323
324
125k
      return resRec;
325
161k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv6TLVOptionHeader::IPv6Option>::getNextTLVRecord(pcpp::IPv6TLVOptionHeader::IPv6Option&, unsigned char const*, unsigned long) const
pcpp::TLVRecordReader<pcpp::NdpOption>::getNextTLVRecord(pcpp::NdpOption&, unsigned char const*, unsigned long) const
Line
Count
Source
302
2
    {
303
2
      TLVRecordType resRec(NULL); // for NRVO optimization
304
305
2
      if (record.isNull())
306
0
        return resRec;
307
308
2
      if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - record.getTotalSize()))
309
2
        return resRec;
310
311
0
      resRec.assign(record.getRecordBasePtr() + record.getTotalSize());
312
313
0
      if (resRec.getTotalSize() == 0)
314
0
        resRec.assign(NULL);
315
316
      // resRec pointer is out-bounds of the TLV records memory
317
0
      if ((resRec.getRecordBasePtr() - tlvDataBasePtr) < 0)
318
0
        resRec.assign(NULL);
319
320
      // resRec pointer is out-bounds of the TLV records memory
321
0
      if (!resRec.isNull() && resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
322
0
        resRec.assign(NULL);
323
324
0
      return resRec;
325
2
    }
pcpp::TLVRecordReader<pcpp::NflogTlv>::getNextTLVRecord(pcpp::NflogTlv&, unsigned char const*, unsigned long) const
Line
Count
Source
302
2.18k
    {
303
2.18k
      TLVRecordType resRec(NULL); // for NRVO optimization
304
305
2.18k
      if (record.isNull())
306
0
        return resRec;
307
308
2.18k
      if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - record.getTotalSize()))
309
93
        return resRec;
310
311
2.09k
      resRec.assign(record.getRecordBasePtr() + record.getTotalSize());
312
313
2.09k
      if (resRec.getTotalSize() == 0)
314
600
        resRec.assign(NULL);
315
316
      // resRec pointer is out-bounds of the TLV records memory
317
2.09k
      if ((resRec.getRecordBasePtr() - tlvDataBasePtr) < 0)
318
600
        resRec.assign(NULL);
319
320
      // resRec pointer is out-bounds of the TLV records memory
321
2.09k
      if (!resRec.isNull() && resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
322
198
        resRec.assign(NULL);
323
324
2.09k
      return resRec;
325
2.18k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::PPPoEDiscoveryLayer::PPPoETag>::getNextTLVRecord(pcpp::PPPoEDiscoveryLayer::PPPoETag&, unsigned char const*, unsigned long) const
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::RadiusAttribute>::getNextTLVRecord(pcpp::RadiusAttribute&, unsigned char const*, unsigned long) const
326
327
    /**
328
     * Search for the first TLV record that corresponds to a given record type (the 'T' in __Type__-Length-Value)
329
     * @param[in] recordType The record type to search for
330
     * @param[in] tlvDataBasePtr A pointer to the TLV data byte stream
331
     * @param[in] tlvDataLen The TLV data byte stream length
332
     * @return An instance of type TLVRecordType that contains the result record. If record was not found a logical
333
     * NULL instance of TLVRecordType will be returned, meaning TLVRecordType.isNull() will return true
334
     */
335
    TLVRecordType getTLVRecord(uint32_t recordType, uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
336
138k
    {
337
138k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
338
293k
      while (!curRec.isNull())
339
204k
      {
340
204k
        if (curRec.getType() == recordType)
341
49.6k
        {
342
49.6k
          return curRec;
343
49.6k
        }
344
345
154k
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
346
154k
      }
347
348
89.2k
      curRec.assign(NULL);
349
89.2k
      return curRec; // for NRVO optimization
350
138k
    }
pcpp::TLVRecordReader<pcpp::DhcpOption>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
Line
Count
Source
336
8.09k
    {
337
8.09k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
338
141k
      while (!curRec.isNull())
339
139k
      {
340
139k
        if (curRec.getType() == recordType)
341
5.90k
        {
342
5.90k
          return curRec;
343
5.90k
        }
344
345
133k
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
346
133k
      }
347
348
2.19k
      curRec.assign(NULL);
349
2.19k
      return curRec; // for NRVO optimization
350
8.09k
    }
pcpp::TLVRecordReader<pcpp::DhcpV6Option>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
Line
Count
Source
336
1.62k
    {
337
1.62k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
338
3.30k
      while (!curRec.isNull())
339
1.87k
      {
340
1.87k
        if (curRec.getType() == recordType)
341
193
        {
342
193
          return curRec;
343
193
        }
344
345
1.68k
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
346
1.68k
      }
347
348
1.43k
      curRec.assign(NULL);
349
1.43k
      return curRec; // for NRVO optimization
350
1.62k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv4Option>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
pcpp::TLVRecordReader<pcpp::TcpOption>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
Line
Count
Source
336
124k
    {
337
124k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
338
142k
      while (!curRec.isNull())
339
59.9k
      {
340
59.9k
        if (curRec.getType() == recordType)
341
41.8k
        {
342
41.8k
          return curRec;
343
41.8k
        }
344
345
18.1k
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
346
18.1k
      }
347
348
82.8k
      curRec.assign(NULL);
349
82.8k
      return curRec; // for NRVO optimization
350
124k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv6TLVOptionHeader::IPv6Option>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
pcpp::TLVRecordReader<pcpp::NdpOption>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
Line
Count
Source
336
2.18k
    {
337
2.18k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
338
2.18k
      while (!curRec.isNull())
339
1.49k
      {
340
1.49k
        if (curRec.getType() == recordType)
341
1.49k
        {
342
1.49k
          return curRec;
343
1.49k
        }
344
345
2
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
346
2
      }
347
348
690
      curRec.assign(NULL);
349
690
      return curRec; // for NRVO optimization
350
2.18k
    }
pcpp::TLVRecordReader<pcpp::NflogTlv>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
Line
Count
Source
336
2.29k
    {
337
2.29k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
338
3.75k
      while (!curRec.isNull())
339
1.65k
      {
340
1.65k
        if (curRec.getType() == recordType)
341
201
        {
342
201
          return curRec;
343
201
        }
344
345
1.45k
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
346
1.45k
      }
347
348
2.09k
      curRec.assign(NULL);
349
2.09k
      return curRec; // for NRVO optimization
350
2.29k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::PPPoEDiscoveryLayer::PPPoETag>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::RadiusAttribute>::getTLVRecord(unsigned int, unsigned char*, unsigned long) const
351
352
    /**
353
     * Get the TLV record count in a given TLV data byte stream. For efficiency purposes the count is being cached
354
     * so only the first call to this method will go over all the TLV records, while all consequent calls will return
355
     * the cached number. This implies that if there is a change in the number of records, it's the user's responsibility
356
     * to call changeTLVRecordCount() with the record count change
357
     * @param[in] tlvDataBasePtr A pointer to the TLV data byte stream
358
     * @param[in] tlvDataLen The TLV data byte stream length
359
     * @return The TLV record count
360
     */
361
    size_t getTLVRecordCount(uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
362
111k
    {
363
111k
      if (m_RecordCount != (size_t)-1)
364
107k
        return m_RecordCount;
365
366
3.96k
      m_RecordCount = 0;
367
3.96k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
368
107k
      while (!curRec.isNull())
369
103k
      {
370
103k
        m_RecordCount++;
371
103k
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
372
103k
      }
373
374
3.96k
      return m_RecordCount;
375
111k
    }
pcpp::TLVRecordReader<pcpp::DhcpOption>::getTLVRecordCount(unsigned char*, unsigned long) const
Line
Count
Source
362
105k
    {
363
105k
      if (m_RecordCount != (size_t)-1)
364
103k
        return m_RecordCount;
365
366
2.02k
      m_RecordCount = 0;
367
2.02k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
368
103k
      while (!curRec.isNull())
369
101k
      {
370
101k
        m_RecordCount++;
371
101k
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
372
101k
      }
373
374
2.02k
      return m_RecordCount;
375
105k
    }
pcpp::TLVRecordReader<pcpp::DhcpV6Option>::getTLVRecordCount(unsigned char*, unsigned long) const
Line
Count
Source
362
6.14k
    {
363
6.14k
      if (m_RecordCount != (size_t)-1)
364
4.21k
        return m_RecordCount;
365
366
1.93k
      m_RecordCount = 0;
367
1.93k
      TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
368
4.52k
      while (!curRec.isNull())
369
2.58k
      {
370
2.58k
        m_RecordCount++;
371
2.58k
        curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
372
2.58k
      }
373
374
1.93k
      return m_RecordCount;
375
6.14k
    }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv4Option>::getTLVRecordCount(unsigned char*, unsigned long) const
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::TcpOption>::getTLVRecordCount(unsigned char*, unsigned long) const
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv6TLVOptionHeader::IPv6Option>::getTLVRecordCount(unsigned char*, unsigned long) const
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::NdpOption>::getTLVRecordCount(unsigned char*, unsigned long) const
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::PPPoEDiscoveryLayer::PPPoETag>::getTLVRecordCount(unsigned char*, unsigned long) const
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::RadiusAttribute>::getTLVRecordCount(unsigned char*, unsigned long) const
376
377
    /**
378
     * As described in getTLVRecordCount(), the TLV record count is being cached for efficiency purposes. So if the
379
     * number of TLV records change, it's the user's responsibility to call this method with the number of TLV records
380
     * being added or removed. If records were added the change should be a positive number, or a negative number
381
     * if records were removed
382
     * @param[in] changedBy Number of records that were added or removed
383
     */
384
41.8k
    void changeTLVRecordCount(int changedBy) { if (m_RecordCount != (size_t)-1) m_RecordCount += changedBy; }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::DhcpOption>::changeTLVRecordCount(int)
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::DhcpV6Option>::changeTLVRecordCount(int)
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv4Option>::changeTLVRecordCount(int)
pcpp::TLVRecordReader<pcpp::TcpOption>::changeTLVRecordCount(int)
Line
Count
Source
384
41.8k
    void changeTLVRecordCount(int changedBy) { if (m_RecordCount != (size_t)-1) m_RecordCount += changedBy; }
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::IPv6TLVOptionHeader::IPv6Option>::changeTLVRecordCount(int)
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::NdpOption>::changeTLVRecordCount(int)
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::PPPoEDiscoveryLayer::PPPoETag>::changeTLVRecordCount(int)
Unexecuted instantiation: pcpp::TLVRecordReader<pcpp::RadiusAttribute>::changeTLVRecordCount(int)
385
  };
386
387
388
  /**
389
   * @class TLVRecordBuilder
390
   * A base class for building Type-Length-Value (TLV) records. This builder receives the record parameters in its c'tor,
391
   * builds the record raw buffer and provides a method to build a TLVRecord object out of it. Please notice this is
392
   * a base class that lacks the capability of actually building TLVRecord objects and also cannot be instantiated. The
393
   * reason for that is that different protocols build TLV records in different ways, so these missing capabilities will
394
   * be implemented by the derived classes which are specific to each protocol. This class only provides the common
395
   * infrastructure that will be used by them
396
   */
397
  class TLVRecordBuilder
398
  {
399
  protected:
400
401
    TLVRecordBuilder();
402
403
    TLVRecordBuilder(uint32_t recType, const uint8_t* recValue, uint8_t recValueLen);
404
405
    TLVRecordBuilder(uint32_t recType, uint8_t recValue);
406
407
    TLVRecordBuilder(uint32_t recType, uint16_t recValue);
408
409
    TLVRecordBuilder(uint32_t recType, uint32_t recValue);
410
411
    TLVRecordBuilder(uint32_t recType, const IPv4Address& recValue);
412
413
    TLVRecordBuilder(uint32_t recType, const std::string& recValue, bool valueIsHexString = false);
414
415
    TLVRecordBuilder(const TLVRecordBuilder& other);
416
417
    TLVRecordBuilder& operator=(const TLVRecordBuilder& other);
418
419
    virtual ~TLVRecordBuilder();
420
421
    void init(uint32_t recType, const uint8_t* recValue, size_t recValueLen);
422
423
    uint8_t* m_RecValue;
424
    size_t m_RecValueLen;
425
    uint32_t m_RecType;
426
427
  private:
428
429
    void copyData(const TLVRecordBuilder& other);
430
  };
431
}