PcapPlusPlus  Next
Layer.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <stdint.h>
4 #include <stdio.h>
5 #include "ProtocolType.h"
6 #include "Serializers.h"
7 #include <ostream>
8 #include <string>
9 #include <stdexcept>
10 #include <utility>
11 
13 
16 namespace pcpp
17 {
18 
23  {
24  public:
28  virtual uint8_t* getDataPtr(size_t offset = 0) const = 0;
29 
30  virtual ~IDataContainer() = default;
31  };
32 
33  class Packet;
34 
35  namespace internal
36  {
39  {
52  Packet* attachedPacket = nullptr;
53 
61  bool ownedByPacket = false;
62 
68  void attachPacket(Packet* packet, bool managed, bool force = false)
69  {
70  if (!force && attachedPacket != nullptr)
71  {
72  throw std::runtime_error("Layer is already attached to a Packet");
73  }
74 
75  attachedPacket = packet;
76  ownedByPacket = managed;
77  }
78 
80  void detach()
81  {
82  attachedPacket = nullptr;
83  ownedByPacket = false;
84  }
85  };
86  } // namespace internal
87 
116  class Layer : public IDataContainer
117  {
118  friend class Packet;
119 
120  public:
123  ~Layer() override;
124 
127  {
128  return m_NextLayer;
129  }
130 
133  {
134  return m_PrevLayer;
135  }
136 
139  {
140  return m_Protocol;
141  }
142 
146  bool isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const;
147 
149  uint8_t* getData() const
150  {
151  return m_Data;
152  }
153 
155  size_t getDataLen() const
156  {
157  return m_DataLen;
158  }
159 
161  uint8_t* getLayerPayload() const
162  {
163  return m_Data + getHeaderLen();
164  }
165 
167  size_t getLayerPayloadSize() const
168  {
169  return m_DataLen - getHeaderLen();
170  }
171 
181  bool isAllocatedToPacket() const
182  {
183  return m_AllocationInfo.attachedPacket != nullptr;
184  }
185 
194  void copyData(uint8_t* toArr) const;
195 
207  size_t copyData(uint8_t* dest, size_t destSize) const;
208 
212  {
214  static std::vector<FieldDescriptor> all()
215  {
216  return { ProtocolName, ProtocolId, Length };
217  }
218 
221 
224 
226  static const FieldDescriptor Length;
227 
229  static constexpr uint16_t MaxID = 1;
230  };
231 
234  void serialize(ISerializer& serializer) const;
235 
236  // implement abstract methods
237 
238  uint8_t* getDataPtr(size_t offset = 0) const override
239  {
240  return static_cast<uint8_t*>(m_Data + offset);
241  }
242 
243  // abstract methods
244 
246  virtual void parseNextLayer() = 0;
247 
249  virtual size_t getHeaderLen() const = 0;
250 
252  virtual void computeCalculateFields() = 0;
253 
256  virtual std::string toString() const = 0;
257 
259  virtual OsiModelLayer getOsiModelLayer() const = 0;
260 
261  protected:
262  uint8_t* m_Data;
263  size_t m_DataLen;
264  ProtocolType m_Protocol;
265  Layer* m_NextLayer;
266  Layer* m_PrevLayer;
267 
268  private:
269  internal::LayerAllocationInfo m_AllocationInfo;
270 
271  protected:
272  Layer() : m_Data(nullptr), m_DataLen(0), m_Protocol(UnknownProtocol), m_NextLayer(nullptr), m_PrevLayer(nullptr)
273  {}
274 
275  Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType protocol = UnknownProtocol)
276  : m_Data(data), m_DataLen(dataLen), m_Protocol(protocol), m_NextLayer(nullptr), m_PrevLayer(prevLayer),
277  m_AllocationInfo{ packet, false }
278  {}
279 
280  // Copy c'tor
281  Layer(const Layer& other);
282  Layer& operator=(const Layer& other);
283 
287  {
288  return m_AllocationInfo.attachedPacket;
289  }
290 
293  Packet const* getAttachedPacket() const
294  {
295  return m_AllocationInfo.attachedPacket;
296  }
297 
298  void setNextLayer(Layer* nextLayer)
299  {
300  m_NextLayer = nextLayer;
301  }
302  void setPrevLayer(Layer* prevLayer)
303  {
304  m_PrevLayer = prevLayer;
305  }
306 
307  // ------ Memory Control Methods -----
308  // Used by derived classes to request buffer size changes.
309 
321  void allocData(size_t dataLen, bool zeroInit = true);
322 
323  virtual bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend);
324  virtual bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten);
325 
326  bool hasNextLayer() const
327  {
328  return m_NextLayer != nullptr;
329  }
330 
341  template <typename T, typename... Args>
342  Layer* constructNextLayer(uint8_t* data, size_t dataLen, Args&&... extraArgs)
343  {
344  return constructNextLayer<T>(data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
345  }
346 
355  template <typename T, typename... Args>
356  Layer* constructNextLayer(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
357  {
358  if (hasNextLayer())
359  {
360  throw std::runtime_error("Next layer already exists");
361  }
362 
363  Layer* newLayer = new T(data, dataLen, this, packet, std::forward<Args>(extraArgs)...);
364  setNextLayer(newLayer);
365  return newLayer;
366  }
367 
385  template <typename TFactory, typename... Args>
386  Layer* constructNextLayerFromFactory(TFactory factoryFn, uint8_t* data, size_t dataLen, Args&&... extraArgs)
387  {
388  return constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, getAttachedPacket(),
389  std::forward<Args>(extraArgs)...);
390  }
391 
408  template <typename TFactory, typename... Args>
409  Layer* constructNextLayerFromFactory(TFactory factoryFn, uint8_t* data, size_t dataLen, Packet* packet,
410  Args&&... extraArgs)
411  {
412  if (hasNextLayer())
413  {
414  throw std::runtime_error("Next layer already exists");
415  }
416 
417  // cppcheck-suppress redundantInitialization
418  Layer* newLayer = factoryFn(data, dataLen, this, packet, std::forward<Args>(extraArgs)...);
419  setNextLayer(newLayer);
420  return newLayer;
421  }
422 
436  template <typename T, typename... Args>
437  Layer* tryConstructNextLayer(uint8_t* data, size_t dataLen, Args&&... extraArgs)
438  {
439  return tryConstructNextLayer<T>(data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
440  }
441 
454  template <typename T, typename... Args>
455  Layer* tryConstructNextLayer(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
456  {
457  if (T::isDataValid(data, dataLen))
458  {
459  return constructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...);
460  }
461  return nullptr;
462  }
463 
480  template <typename T, typename TFallback, typename... Args>
481  Layer* tryConstructNextLayerWithFallback(uint8_t* data, size_t dataLen, Args&&... extraArgs)
482  {
483  return tryConstructNextLayerWithFallback<T, TFallback>(data, dataLen, getAttachedPacket(),
484  std::forward<Args>(extraArgs)...);
485  }
486 
502  template <typename T, typename TFallback, typename... Args>
503  Layer* tryConstructNextLayerWithFallback(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
504  {
505  if (tryConstructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...))
506  {
507  return m_NextLayer;
508  }
509 
510  return constructNextLayer<TFallback>(data, dataLen, packet);
511  }
512 
534  template <typename TFallback, typename TFactory, typename... Args>
535  Layer* tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t* data, size_t dataLen,
536  Args&&... extraArgs)
537  {
538  // Note that the fallback is first to allow template argument deduction of the factory type.
539  return tryConstructNextLayerFromFactoryWithFallback<TFallback, TFactory>(
540  factoryFn, data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
541  }
542 
563  template <typename TFallback, typename TFactory, typename... Args>
564  Layer* tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t* data, size_t dataLen,
565  Packet* packet, Args&&... extraArgs)
566  {
567  auto nextLayer = constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, packet,
568  std::forward<Args>(extraArgs)...);
569  if (nextLayer != nullptr)
570  {
571  return nextLayer;
572  }
573 
574  // factory failed, construct fallback layer
575  return constructNextLayer<TFallback>(data, dataLen, packet);
576  }
577 
586  template <typename T> static bool canReinterpretAs(const uint8_t* data, size_t dataLen)
587  {
588  return data != nullptr && dataLen >= sizeof(T);
589  }
590 
596  virtual void serializeLayer(ObjectScope& serializer) const
597  {}
598  };
599 
600  inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer& layer)
601  {
602  os << layer.toString();
603  return os;
604  }
605 } // namespace pcpp
Definition: Layer.h:23
virtual uint8_t * getDataPtr(size_t offset=0) const =0
Definition: Serializers.h:78
Definition: Layer.h:117
void copyData(uint8_t *toArr) const
Copy the raw data of this layer to another array.
Layer * constructNextLayerFromFactory(TFactory factoryFn, uint8_t *data, size_t dataLen, Args &&... extraArgs)
Construct the next layer in the protocol stack using a factory functor.
Definition: Layer.h:386
Layer * tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t *data, size_t dataLen, Packet *packet, Args &&... extraArgs)
Try to construct the next layer in the protocol stack using a factory functor with a fallback option.
Definition: Layer.h:564
uint8_t * getLayerPayload() const
Definition: Layer.h:161
virtual std::string toString() const =0
size_t getDataLen() const
Definition: Layer.h:155
uint8_t * getDataPtr(size_t offset=0) const override
Definition: Layer.h:238
uint8_t * getData() const
Definition: Layer.h:149
Layer * constructNextLayerFromFactory(TFactory factoryFn, uint8_t *data, size_t dataLen, Packet *packet, Args &&... extraArgs)
Construct the next layer in the protocol stack using a factory functor.
Definition: Layer.h:409
Layer * tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t *data, size_t dataLen, Args &&... extraArgs)
Try to construct the next layer in the protocol stack using a factory functor with a fallback option.
Definition: Layer.h:535
Layer * constructNextLayer(uint8_t *data, size_t dataLen, Args &&... extraArgs)
Construct the next layer in the protocol stack. No validation is performed on the data.
Definition: Layer.h:342
virtual void parseNextLayer()=0
Each layer is responsible for parsing the next layer.
Layer * constructNextLayer(uint8_t *data, size_t dataLen, Packet *packet, Args &&... extraArgs)
Definition: Layer.h:356
bool isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const
Layer * getNextLayer() const
Definition: Layer.h:126
Layer * tryConstructNextLayerWithFallback(uint8_t *data, size_t dataLen, Args &&... extraArgs)
Try to construct the next layer in the protocol stack with a fallback option.
Definition: Layer.h:481
void serialize(ISerializer &serializer) const
virtual void serializeLayer(ObjectScope &serializer) const
Definition: Layer.h:596
bool isAllocatedToPacket() const
Definition: Layer.h:181
Packet * getAttachedPacket()
Get a pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:286
Layer * getPrevLayer() const
Definition: Layer.h:132
void allocData(size_t dataLen, bool zeroInit=true)
Requests the layer to allocate a new data buffer of the specified length.
ProtocolType getProtocol() const
Definition: Layer.h:138
size_t getLayerPayloadSize() const
Definition: Layer.h:167
virtual void computeCalculateFields()=0
Each layer can compute field values automatically using this method. This is an abstract method.
Layer * tryConstructNextLayerWithFallback(uint8_t *data, size_t dataLen, Packet *packet, Args &&... extraArgs)
Definition: Layer.h:503
virtual size_t getHeaderLen() const =0
static bool canReinterpretAs(const uint8_t *data, size_t dataLen)
Check if the data is large enough to reinterpret as a type.
Definition: Layer.h:586
Layer * tryConstructNextLayer(uint8_t *data, size_t dataLen, Args &&... extraArgs)
Definition: Layer.h:437
size_t copyData(uint8_t *dest, size_t destSize) const
Copy the raw data of this layer to another array, with a specified maximum size.
Packet const * getAttachedPacket() const
Get a pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:293
~Layer() override
Layer * tryConstructNextLayer(uint8_t *data, size_t dataLen, Packet *packet, Args &&... extraArgs)
Definition: Layer.h:455
virtual OsiModelLayer getOsiModelLayer() const =0
Definition: Serializers.h:230
Definition: Packet.h:49
uint8_t ProtocolType
Definition: ProtocolType.h:38
uint32_t ProtocolTypeFamily
Definition: ProtocolType.h:42
const ProtocolType UnknownProtocol
Unknown protocol (or unsupported by PcapPlusPlus)
Definition: ProtocolType.h:45
The main namespace for the PcapPlusPlus lib.
Definition: AssertionUtils.h:19
OsiModelLayer
An enum representing OSI model layers.
Definition: ProtocolType.h:420
Definition: Serializers.h:18
Definition: Layer.h:212
static std::vector< FieldDescriptor > all()
Definition: Layer.h:214
static const FieldDescriptor ProtocolId
Field descriptor for the layer protocol ID.
Definition: Layer.h:223
static const FieldDescriptor ProtocolName
Field descriptor for the layer protocol name.
Definition: Layer.h:220
static constexpr uint16_t MaxID
Maximum field ID used by the layer.
Definition: Layer.h:229
static const FieldDescriptor Length
Field descriptor for the layer length.
Definition: Layer.h:226
Holds information about a Layer's data and object ownership.
Definition: Layer.h:39
Packet * attachedPacket
Pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:52
bool ownedByPacket
Controls if the layer object is considered owned by the attached Packet.
Definition: Layer.h:61
void detach()
Clears the attachment to any Packet, resetting to unmanaged state.
Definition: Layer.h:80
void attachPacket(Packet *packet, bool managed, bool force=false)
Sets the state of attachment to a specified Packet.
Definition: Layer.h:68