PcapPlusPlus  Next
TLVData.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "Layer.h"
4 #include "IpAddress.h"
5 #include <string.h>
6 #include <type_traits>
7 
9 
12 namespace pcpp
13 {
19  template <typename TRecType, typename TRecLen> class TLVRecord
20  {
21  protected:
23 #pragma pack(push, 1)
24  struct TLVRawData
25  {
27  TRecType recordType;
29  TRecLen recordLen;
31  uint8_t recordValue[];
32  };
33 #pragma pack(pop)
34 
35  TLVRawData* m_Data;
36 
37  public:
40  TLVRecord(uint8_t* recordRawData)
41  {
42  assign(recordRawData);
43  }
44 
48  TLVRecord(const TLVRecord& other)
49  {
50  m_Data = other.m_Data;
51  }
52 
54  virtual ~TLVRecord() = default;
55 
58  void assign(uint8_t* recordRawData)
59  {
60  m_Data = reinterpret_cast<TLVRawData*>(recordRawData);
61  }
62 
67  static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
68  {
69  return recordRawData != nullptr &&
70  tlvDataLen >= (sizeof(TLVRawData::recordType) + sizeof(TLVRawData::recordLen));
71  }
72 
77  TLVRecord& operator=(const TLVRecord& other)
78  {
79  m_Data = other.m_Data;
80  return *this;
81  }
82 
87  bool operator==(const TLVRecord& rhs) const
88  {
89  if (m_Data == rhs.m_Data)
90  return true;
91 
92  if (getTotalSize() != rhs.getTotalSize())
93  return false;
94 
95  if (isNull() || ((TLVRecord&)rhs).isNull())
96  return false;
97 
98  return (memcmp(m_Data, rhs.m_Data, getTotalSize()) == 0);
99  }
100 
104  bool operator!=(const TLVRecord& rhs) const
105  {
106  return !operator==(rhs);
107  }
108 
110  TRecType getType() const
111  {
112  if (m_Data == nullptr)
113  return 0;
114 
115  return m_Data->recordType;
116  }
117 
119  uint8_t* getValue() const
120  {
121  if (m_Data == nullptr)
122  return nullptr;
123 
124  return m_Data->recordValue;
125  }
126 
128  bool isNull() const
129  {
130  return (m_Data == nullptr);
131  }
132 
134  bool isNotNull() const
135  {
136  return (m_Data != nullptr);
137  }
138 
140  uint8_t* getRecordBasePtr() const
141  {
142  return reinterpret_cast<uint8_t*>(m_Data);
143  }
144 
147  {
148  if (!isNull())
149  {
150  delete[] m_Data;
151  m_Data = nullptr;
152  }
153  }
154 
163  template <typename T> T getValueAs(size_t offset = 0) const
164  {
165  static_assert(std::is_trivially_copyable<T>::value && std::is_default_constructible<T>::value &&
166  !std::is_pointer<T>::value,
167  "TLVRecord::getValueAs<T>() requires T to be a non-pointer, "
168  "default-constructible, trivially copyable type");
169 
170  if (getDataSize() < sizeof(T) + offset)
171  {
172  return T{};
173  }
174 
175  T result;
176  memcpy(&result, m_Data->recordValue + getValueOffset() + offset, sizeof(T));
177  return result;
178  }
179 
188  template <typename T> bool setValue(T newValue, int valueOffset = 0)
189  {
190  static_assert(std::is_trivially_copyable<T>::value && !std::is_pointer<T>::value,
191  "TLVRecord::setValue<T>() requires T to be a non-pointer, trivially copyable type");
192 
193  if (getDataSize() < sizeof(T))
194  {
195  return false;
196  }
197 
198  memcpy(m_Data->recordValue + getValueOffset() + valueOffset, &newValue, sizeof(T));
199  return true;
200  }
201 
203  virtual size_t getTotalSize() const = 0;
204 
206  virtual size_t getDataSize() const = 0;
207 
208  protected:
209  virtual size_t getValueOffset() const
210  {
211  return 0;
212  }
213  };
214 
218  template <typename TLVRecordType> class TLVRecordReader
219  {
220  private:
221  mutable size_t m_RecordCount;
222 
223  public:
226  {
227  m_RecordCount = static_cast<size_t>(-1);
228  }
229 
232  {
233  m_RecordCount = other.m_RecordCount;
234  }
235 
237  virtual ~TLVRecordReader() = default;
238 
242  {
243  m_RecordCount = other.m_RecordCount;
244  return *this;
245  }
246 
247  // cppcheck-suppress functionStatic
254  TLVRecordType getFirstTLVRecord(uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
255  {
256  TLVRecordType resRec(nullptr); // for NRVO optimization
257  if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen))
258  return resRec;
259 
260  resRec.assign(tlvDataBasePtr);
261  // resRec pointer is out-bounds of the TLV records memory
262  if (resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
263  resRec.assign(nullptr);
264 
265  // check if there are records at all and the total size is not zero
266  if (!resRec.isNull() && (tlvDataLen == 0 || resRec.getTotalSize() == 0))
267  resRec.assign(nullptr);
268 
269  return resRec;
270  }
271 
272  // cppcheck-suppress [constParameterReference, functionStatic]
280  TLVRecordType getNextTLVRecord(TLVRecordType& record, const uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
281  {
282  TLVRecordType resRec(nullptr); // for NRVO optimization
283 
284  if (record.isNull())
285  return resRec;
286 
287  if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(),
288  tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen -
289  record.getTotalSize()))
290  return resRec;
291 
292  resRec.assign(record.getRecordBasePtr() + record.getTotalSize());
293 
294  if (resRec.getTotalSize() == 0)
295  resRec.assign(nullptr);
296 
297  // resRec pointer is out-bounds of the TLV records memory
298  if ((resRec.getRecordBasePtr() - tlvDataBasePtr) < 0)
299  resRec.assign(nullptr);
300 
301  // resRec pointer is out-bounds of the TLV records memory
302  if (!resRec.isNull() && resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
303  resRec.assign(nullptr);
304 
305  return resRec;
306  }
307 
314  TLVRecordType getTLVRecord(uint32_t recordType, uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
315  {
316  TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
317  while (!curRec.isNull())
318  {
319  if (curRec.getType() == recordType)
320  {
321  return curRec;
322  }
323 
324  curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
325  }
326 
327  curRec.assign(nullptr);
328  return curRec; // for NRVO optimization
329  }
330 
338  size_t getTLVRecordCount(uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
339  {
340  if (m_RecordCount != static_cast<size_t>(-1))
341  return m_RecordCount;
342 
343  m_RecordCount = 0;
344  TLVRecordType curRec = getFirstTLVRecord(tlvDataBasePtr, tlvDataLen);
345  while (!curRec.isNull())
346  {
347  m_RecordCount++;
348  curRec = getNextTLVRecord(curRec, tlvDataBasePtr, tlvDataLen);
349  }
350 
351  return m_RecordCount;
352  }
353 
359  void changeTLVRecordCount(int changedBy)
360  {
361  if (m_RecordCount != static_cast<size_t>(-1))
362  m_RecordCount += changedBy;
363  }
364  };
365 
374  {
375  protected:
377 
378  TLVRecordBuilder(uint32_t recType, const uint8_t* recValue, uint8_t recValueLen);
379 
380  TLVRecordBuilder(uint32_t recType, uint8_t recValue);
381 
382  TLVRecordBuilder(uint32_t recType, uint16_t recValue);
383 
384  TLVRecordBuilder(uint32_t recType, uint32_t recValue);
385 
386  TLVRecordBuilder(uint32_t recType, const IPv4Address& recValue);
387 
388  TLVRecordBuilder(uint32_t recType, const std::string& recValue, bool valueIsHexString = false);
389 
390  TLVRecordBuilder(const TLVRecordBuilder& other);
391 
392  TLVRecordBuilder& operator=(const TLVRecordBuilder& other);
393 
394  virtual ~TLVRecordBuilder();
395 
396  void init(uint32_t recType, const uint8_t* recValue, size_t recValueLen);
397 
398  uint8_t* m_RecValue;
399  size_t m_RecValueLen;
400  uint32_t m_RecType;
401 
402  private:
403  void copyData(const TLVRecordBuilder& other);
404  };
405 } // namespace pcpp
Definition: IpAddress.h:30
Definition: TLVData.h:374
Definition: TLVData.h:20
TLVRecord(uint8_t *recordRawData)
Definition: TLVData.h:40
TLVRecord(const TLVRecord &other)
Definition: TLVData.h:48
virtual size_t getTotalSize() const =0
virtual ~TLVRecord()=default
A d'tor for this class, currently does nothing.
TRecType getType() const
Definition: TLVData.h:110
bool setValue(T newValue, int valueOffset=0)
Definition: TLVData.h:188
bool operator!=(const TLVRecord &rhs) const
Definition: TLVData.h:104
uint8_t * getRecordBasePtr() const
Definition: TLVData.h:140
uint8_t * getValue() const
Definition: TLVData.h:119
bool operator==(const TLVRecord &rhs) const
Definition: TLVData.h:87
static bool canAssign(const uint8_t *recordRawData, size_t tlvDataLen)
Definition: TLVData.h:67
virtual size_t getDataSize() const =0
bool isNotNull() const
Definition: TLVData.h:134
bool isNull() const
Definition: TLVData.h:128
T getValueAs(size_t offset=0) const
Definition: TLVData.h:163
TLVRecord & operator=(const TLVRecord &other)
Definition: TLVData.h:77
void purgeRecordData()
Free the memory of the TLV record raw data.
Definition: TLVData.h:146
void assign(uint8_t *recordRawData)
Definition: TLVData.h:58
Definition: TLVData.h:219
void changeTLVRecordCount(int changedBy)
Definition: TLVData.h:359
TLVRecordReader & operator=(const TLVRecordReader &other)
Definition: TLVData.h:241
virtual ~TLVRecordReader()=default
A d'tor for this class which currently does nothing.
TLVRecordType getTLVRecord(uint32_t recordType, uint8_t *tlvDataBasePtr, size_t tlvDataLen) const
Definition: TLVData.h:314
TLVRecordReader(const TLVRecordReader &other)
A default copy c'tor for this class.
Definition: TLVData.h:231
TLVRecordType getNextTLVRecord(TLVRecordType &record, const uint8_t *tlvDataBasePtr, size_t tlvDataLen) const
Definition: TLVData.h:280
TLVRecordReader()
A default c'tor for this class.
Definition: TLVData.h:225
TLVRecordType getFirstTLVRecord(uint8_t *tlvDataBasePtr, size_t tlvDataLen) const
Definition: TLVData.h:254
size_t getTLVRecordCount(uint8_t *tlvDataBasePtr, size_t tlvDataLen) const
Definition: TLVData.h:338
The main namespace for the PcapPlusPlus lib.
Definition: AssertionUtils.h:19
A struct representing the TLV construct.
Definition: TLVData.h:25
uint8_t recordValue[]
Record value (variable size)
Definition: TLVData.h:31
TRecType recordType
Record type.
Definition: TLVData.h:27
TRecLen recordLen
Record length in bytes.
Definition: TLVData.h:29