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 <ostream>
7 #include <string>
8 #include <stdexcept>
9 #include <utility>
10 
12 
15 namespace pcpp
16 {
17 
22  {
23  public:
27  virtual uint8_t* getDataPtr(size_t offset = 0) const = 0;
28 
29  virtual ~IDataContainer() = default;
30  };
31 
32  class Packet;
33 
34  namespace internal
35  {
38  {
51  Packet* attachedPacket = nullptr;
52 
60  bool ownedByPacket = false;
61 
67  void attachPacket(Packet* packet, bool managed, bool force = false)
68  {
69  if (!force && attachedPacket != nullptr)
70  {
71  throw std::runtime_error("Layer is already attached to a Packet");
72  }
73 
74  attachedPacket = packet;
75  ownedByPacket = managed;
76  }
77 
79  void detach()
80  {
81  attachedPacket = nullptr;
82  ownedByPacket = false;
83  }
84  };
85  } // namespace internal
86 
115  class Layer : public IDataContainer
116  {
117  friend class Packet;
118 
119  public:
122  ~Layer() override;
123 
126  {
127  return m_NextLayer;
128  }
129 
132  {
133  return m_PrevLayer;
134  }
135 
138  {
139  return m_Protocol;
140  }
141 
145  bool isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const;
146 
148  uint8_t* getData() const
149  {
150  return m_Data;
151  }
152 
154  size_t getDataLen() const
155  {
156  return m_DataLen;
157  }
158 
160  uint8_t* getLayerPayload() const
161  {
162  return m_Data + getHeaderLen();
163  }
164 
166  size_t getLayerPayloadSize() const
167  {
168  return m_DataLen - getHeaderLen();
169  }
170 
180  bool isAllocatedToPacket() const
181  {
182  return m_AllocationInfo.attachedPacket != nullptr;
183  }
184 
193  void copyData(uint8_t* toArr) const;
194 
206  size_t copyData(uint8_t* dest, size_t destSize) const;
207 
208  // implement abstract methods
209 
210  uint8_t* getDataPtr(size_t offset = 0) const override
211  {
212  return static_cast<uint8_t*>(m_Data + offset);
213  }
214 
215  // abstract methods
216 
218  virtual void parseNextLayer() = 0;
219 
221  virtual size_t getHeaderLen() const = 0;
222 
224  virtual void computeCalculateFields() = 0;
225 
228  virtual std::string toString() const = 0;
229 
231  virtual OsiModelLayer getOsiModelLayer() const = 0;
232 
233  protected:
234  uint8_t* m_Data;
235  size_t m_DataLen;
236  ProtocolType m_Protocol;
237  Layer* m_NextLayer;
238  Layer* m_PrevLayer;
239 
240  private:
241  internal::LayerAllocationInfo m_AllocationInfo;
242 
243  protected:
244  Layer() : m_Data(nullptr), m_DataLen(0), m_Protocol(UnknownProtocol), m_NextLayer(nullptr), m_PrevLayer(nullptr)
245  {}
246 
247  Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType protocol = UnknownProtocol)
248  : m_Data(data), m_DataLen(dataLen), m_Protocol(protocol), m_NextLayer(nullptr), m_PrevLayer(prevLayer),
249  m_AllocationInfo{ packet, false }
250  {}
251 
252  // Copy c'tor
253  Layer(const Layer& other);
254  Layer& operator=(const Layer& other);
255 
259  {
260  return m_AllocationInfo.attachedPacket;
261  }
262 
265  Packet const* getAttachedPacket() const
266  {
267  return m_AllocationInfo.attachedPacket;
268  }
269 
270  void setNextLayer(Layer* nextLayer)
271  {
272  m_NextLayer = nextLayer;
273  }
274  void setPrevLayer(Layer* prevLayer)
275  {
276  m_PrevLayer = prevLayer;
277  }
278 
279  // ------ Memory Control Methods -----
280  // Used by derived classes to request buffer size changes.
281 
293  void allocData(size_t dataLen, bool zeroInit = true);
294 
295  virtual bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend);
296  virtual bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten);
297 
298  bool hasNextLayer() const
299  {
300  return m_NextLayer != nullptr;
301  }
302 
313  template <typename T, typename... Args>
314  Layer* constructNextLayer(uint8_t* data, size_t dataLen, Args&&... extraArgs)
315  {
316  return constructNextLayer<T>(data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
317  }
318 
327  template <typename T, typename... Args>
328  Layer* constructNextLayer(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
329  {
330  if (hasNextLayer())
331  {
332  throw std::runtime_error("Next layer already exists");
333  }
334 
335  Layer* newLayer = new T(data, dataLen, this, packet, std::forward<Args>(extraArgs)...);
336  setNextLayer(newLayer);
337  return newLayer;
338  }
339 
357  template <typename TFactory, typename... Args>
358  Layer* constructNextLayerFromFactory(TFactory factoryFn, uint8_t* data, size_t dataLen, Args&&... extraArgs)
359  {
360  return constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, getAttachedPacket(),
361  std::forward<Args>(extraArgs)...);
362  }
363 
380  template <typename TFactory, typename... Args>
381  Layer* constructNextLayerFromFactory(TFactory factoryFn, uint8_t* data, size_t dataLen, Packet* packet,
382  Args&&... extraArgs)
383  {
384  if (hasNextLayer())
385  {
386  throw std::runtime_error("Next layer already exists");
387  }
388 
389  // cppcheck-suppress redundantInitialization
390  Layer* newLayer = factoryFn(data, dataLen, this, packet, std::forward<Args>(extraArgs)...);
391  setNextLayer(newLayer);
392  return newLayer;
393  }
394 
408  template <typename T, typename... Args>
409  Layer* tryConstructNextLayer(uint8_t* data, size_t dataLen, Args&&... extraArgs)
410  {
411  return tryConstructNextLayer<T>(data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
412  }
413 
426  template <typename T, typename... Args>
427  Layer* tryConstructNextLayer(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
428  {
429  if (T::isDataValid(data, dataLen))
430  {
431  return constructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...);
432  }
433  return nullptr;
434  }
435 
452  template <typename T, typename TFallback, typename... Args>
453  Layer* tryConstructNextLayerWithFallback(uint8_t* data, size_t dataLen, Args&&... extraArgs)
454  {
455  return tryConstructNextLayerWithFallback<T, TFallback>(data, dataLen, getAttachedPacket(),
456  std::forward<Args>(extraArgs)...);
457  }
458 
474  template <typename T, typename TFallback, typename... Args>
475  Layer* tryConstructNextLayerWithFallback(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
476  {
477  if (tryConstructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...))
478  {
479  return m_NextLayer;
480  }
481 
482  return constructNextLayer<TFallback>(data, dataLen, packet);
483  }
484 
506  template <typename TFallback, typename TFactory, typename... Args>
507  Layer* tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t* data, size_t dataLen,
508  Args&&... extraArgs)
509  {
510  // Note that the fallback is first to allow template argument deduction of the factory type.
511  return tryConstructNextLayerFromFactoryWithFallback<TFallback, TFactory>(
512  factoryFn, data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
513  }
514 
535  template <typename TFallback, typename TFactory, typename... Args>
536  Layer* tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t* data, size_t dataLen,
537  Packet* packet, Args&&... extraArgs)
538  {
539  auto nextLayer = constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, packet,
540  std::forward<Args>(extraArgs)...);
541  if (nextLayer != nullptr)
542  {
543  return nextLayer;
544  }
545 
546  // factory failed, construct fallback layer
547  return constructNextLayer<TFallback>(data, dataLen, packet);
548  }
549 
558  template <typename T> static bool canReinterpretAs(const uint8_t* data, size_t dataLen)
559  {
560  return data != nullptr && dataLen >= sizeof(T);
561  }
562  };
563 
564  inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer& layer)
565  {
566  os << layer.toString();
567  return os;
568  }
569 } // namespace pcpp
Definition: Layer.h:22
virtual uint8_t * getDataPtr(size_t offset=0) const =0
Definition: Layer.h:116
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:358
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:536
uint8_t * getLayerPayload() const
Definition: Layer.h:160
virtual std::string toString() const =0
size_t getDataLen() const
Definition: Layer.h:154
uint8_t * getDataPtr(size_t offset=0) const override
Definition: Layer.h:210
uint8_t * getData() const
Definition: Layer.h:148
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:381
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:507
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:314
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:328
bool isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const
Layer * getNextLayer() const
Definition: Layer.h:125
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:453
bool isAllocatedToPacket() const
Definition: Layer.h:180
Packet * getAttachedPacket()
Get a pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:258
Layer * getPrevLayer() const
Definition: Layer.h:131
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:137
size_t getLayerPayloadSize() const
Definition: Layer.h:166
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:475
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:558
Layer * tryConstructNextLayer(uint8_t *data, size_t dataLen, Args &&... extraArgs)
Definition: Layer.h:409
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:265
~Layer() override
Layer * tryConstructNextLayer(uint8_t *data, size_t dataLen, Packet *packet, Args &&... extraArgs)
Definition: Layer.h:427
virtual OsiModelLayer getOsiModelLayer() const =0
Definition: Packet.h:48
uint8_t ProtocolType
Definition: ProtocolType.h:35
uint32_t ProtocolTypeFamily
Definition: ProtocolType.h:39
const ProtocolType UnknownProtocol
Unknown protocol (or unsupported by PcapPlusPlus)
Definition: ProtocolType.h:42
The main namespace for the PcapPlusPlus lib.
Definition: AssertionUtils.h:19
OsiModelLayer
An enum representing OSI model layers.
Definition: ProtocolType.h:267
Holds information about a Layer's data and object ownership.
Definition: Layer.h:38
Packet * attachedPacket
Pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:51
bool ownedByPacket
Controls if the layer object is considered owned by the attached Packet.
Definition: Layer.h:60
void detach()
Clears the attachment to any Packet, resetting to unmanaged state.
Definition: Layer.h:79
void attachPacket(Packet *packet, bool managed, bool force=false)
Sets the state of attachment to a specified Packet.
Definition: Layer.h:67