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 <string>
7 #include <stdexcept>
8 #include <utility>
9 
11 
14 namespace pcpp
15 {
16 
21  {
22  public:
26  virtual uint8_t* getDataPtr(size_t offset = 0) const = 0;
27 
28  virtual ~IDataContainer() = default;
29  };
30 
31  class Packet;
32 
33  namespace internal
34  {
37  {
50  Packet* attachedPacket = nullptr;
51 
59  bool ownedByPacket = false;
60 
66  void attachPacket(Packet* packet, bool managed, bool force = false)
67  {
68  if (!force && attachedPacket != nullptr)
69  {
70  throw std::runtime_error("Layer is already attached to a Packet");
71  }
72 
73  attachedPacket = packet;
74  ownedByPacket = managed;
75  }
76 
78  void detach()
79  {
80  attachedPacket = nullptr;
81  ownedByPacket = false;
82  }
83  };
84  } // namespace internal
85 
114  class Layer : public IDataContainer
115  {
116  friend class Packet;
117 
118  public:
121  ~Layer() override;
122 
125  {
126  return m_NextLayer;
127  }
128 
131  {
132  return m_PrevLayer;
133  }
134 
137  {
138  return m_Protocol;
139  }
140 
144  bool isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const;
145 
147  uint8_t* getData() const
148  {
149  return m_Data;
150  }
151 
153  size_t getDataLen() const
154  {
155  return m_DataLen;
156  }
157 
159  uint8_t* getLayerPayload() const
160  {
161  return m_Data + getHeaderLen();
162  }
163 
165  size_t getLayerPayloadSize() const
166  {
167  return m_DataLen - getHeaderLen();
168  }
169 
179  bool isAllocatedToPacket() const
180  {
181  return m_AllocationInfo.attachedPacket != nullptr;
182  }
183 
186  void copyData(uint8_t* toArr) const;
187 
188  // implement abstract methods
189 
190  uint8_t* getDataPtr(size_t offset = 0) const override
191  {
192  return static_cast<uint8_t*>(m_Data + offset);
193  }
194 
195  // abstract methods
196 
198  virtual void parseNextLayer() = 0;
199 
201  virtual size_t getHeaderLen() const = 0;
202 
204  virtual void computeCalculateFields() = 0;
205 
208  virtual std::string toString() const = 0;
209 
211  virtual OsiModelLayer getOsiModelLayer() const = 0;
212 
213  protected:
214  uint8_t* m_Data;
215  size_t m_DataLen;
216  ProtocolType m_Protocol;
217  Layer* m_NextLayer;
218  Layer* m_PrevLayer;
219 
220  private:
221  internal::LayerAllocationInfo m_AllocationInfo;
222 
223  protected:
224  Layer() : m_Data(nullptr), m_DataLen(0), m_Protocol(UnknownProtocol), m_NextLayer(nullptr), m_PrevLayer(nullptr)
225  {}
226 
227  Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType protocol = UnknownProtocol)
228  : m_Data(data), m_DataLen(dataLen), m_Protocol(protocol), m_NextLayer(nullptr), m_PrevLayer(prevLayer),
229  m_AllocationInfo{ packet, false }
230  {}
231 
232  // Copy c'tor
233  Layer(const Layer& other);
234  Layer& operator=(const Layer& other);
235 
239  {
240  return m_AllocationInfo.attachedPacket;
241  }
242 
245  Packet const* getAttachedPacket() const
246  {
247  return m_AllocationInfo.attachedPacket;
248  }
249 
250  void setNextLayer(Layer* nextLayer)
251  {
252  m_NextLayer = nextLayer;
253  }
254  void setPrevLayer(Layer* prevLayer)
255  {
256  m_PrevLayer = prevLayer;
257  }
258 
259  virtual bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend);
260  virtual bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten);
261 
262  bool hasNextLayer() const
263  {
264  return m_NextLayer != nullptr;
265  }
266 
277  template <typename T, typename... Args>
278  Layer* constructNextLayer(uint8_t* data, size_t dataLen, Args&&... extraArgs)
279  {
280  return constructNextLayer<T>(data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
281  }
282 
291  template <typename T, typename... Args>
292  Layer* constructNextLayer(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
293  {
294  if (hasNextLayer())
295  {
296  throw std::runtime_error("Next layer already exists");
297  }
298 
299  Layer* newLayer = new T(data, dataLen, this, packet, std::forward<Args>(extraArgs)...);
300  setNextLayer(newLayer);
301  return newLayer;
302  }
303 
321  template <typename TFactory, typename... Args>
322  Layer* constructNextLayerFromFactory(TFactory factoryFn, uint8_t* data, size_t dataLen, Args&&... extraArgs)
323  {
324  return constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, getAttachedPacket(),
325  std::forward<Args>(extraArgs)...);
326  }
327 
344  template <typename TFactory, typename... Args>
345  Layer* constructNextLayerFromFactory(TFactory factoryFn, uint8_t* data, size_t dataLen, Packet* packet,
346  Args&&... extraArgs)
347  {
348  if (hasNextLayer())
349  {
350  throw std::runtime_error("Next layer already exists");
351  }
352 
353  // cppcheck-suppress redundantInitialization
354  Layer* newLayer = factoryFn(data, dataLen, this, packet, std::forward<Args>(extraArgs)...);
355  setNextLayer(newLayer);
356  return newLayer;
357  }
358 
372  template <typename T, typename... Args>
373  Layer* tryConstructNextLayer(uint8_t* data, size_t dataLen, Args&&... extraArgs)
374  {
375  return tryConstructNextLayer<T>(data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
376  }
377 
390  template <typename T, typename... Args>
391  Layer* tryConstructNextLayer(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
392  {
393  if (T::isDataValid(data, dataLen))
394  {
395  return constructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...);
396  }
397  return nullptr;
398  }
399 
416  template <typename T, typename TFallback, typename... Args>
417  Layer* tryConstructNextLayerWithFallback(uint8_t* data, size_t dataLen, Args&&... extraArgs)
418  {
419  return tryConstructNextLayerWithFallback<T, TFallback>(data, dataLen, getAttachedPacket(),
420  std::forward<Args>(extraArgs)...);
421  }
422 
438  template <typename T, typename TFallback, typename... Args>
439  Layer* tryConstructNextLayerWithFallback(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
440  {
441  if (tryConstructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...))
442  {
443  return m_NextLayer;
444  }
445 
446  return constructNextLayer<TFallback>(data, dataLen, packet);
447  }
448 
470  template <typename TFallback, typename TFactory, typename... Args>
471  Layer* tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t* data, size_t dataLen,
472  Args&&... extraArgs)
473  {
474  // Note that the fallback is first to allow template argument deduction of the factory type.
475  return tryConstructNextLayerFromFactoryWithFallback<TFallback, TFactory>(
476  factoryFn, data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
477  }
478 
499  template <typename TFallback, typename TFactory, typename... Args>
500  Layer* tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t* data, size_t dataLen,
501  Packet* packet, Args&&... extraArgs)
502  {
503  auto nextLayer = constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, packet,
504  std::forward<Args>(extraArgs)...);
505  if (nextLayer != nullptr)
506  {
507  return nextLayer;
508  }
509 
510  // factory failed, construct fallback layer
511  return constructNextLayer<TFallback>(data, dataLen, packet);
512  }
513 
522  template <typename T> static bool canReinterpretAs(const uint8_t* data, size_t dataLen)
523  {
524  return data != nullptr && dataLen >= sizeof(T);
525  }
526  };
527 
528  inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer& layer)
529  {
530  os << layer.toString();
531  return os;
532  }
533 } // namespace pcpp
Definition: Layer.h:21
virtual uint8_t * getDataPtr(size_t offset=0) const =0
Definition: Layer.h:115
void copyData(uint8_t *toArr) const
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:322
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:500
uint8_t * getLayerPayload() const
Definition: Layer.h:159
virtual std::string toString() const =0
size_t getDataLen() const
Definition: Layer.h:153
uint8_t * getDataPtr(size_t offset=0) const override
Definition: Layer.h:190
uint8_t * getData() const
Definition: Layer.h:147
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:345
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:471
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:278
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:292
bool isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const
Layer * getNextLayer() const
Definition: Layer.h:124
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:417
bool isAllocatedToPacket() const
Definition: Layer.h:179
Packet * getAttachedPacket()
Get a pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:238
Layer * getPrevLayer() const
Definition: Layer.h:130
ProtocolType getProtocol() const
Definition: Layer.h:136
size_t getLayerPayloadSize() const
Definition: Layer.h:165
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:439
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:522
Layer * tryConstructNextLayer(uint8_t *data, size_t dataLen, Args &&... extraArgs)
Definition: Layer.h:373
Packet const * getAttachedPacket() const
Get a pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:245
~Layer() override
Layer * tryConstructNextLayer(uint8_t *data, size_t dataLen, Packet *packet, Args &&... extraArgs)
Definition: Layer.h:391
virtual OsiModelLayer getOsiModelLayer() const =0
Definition: Packet.h:22
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:261
Holds information about a Layer's data and object ownership.
Definition: Layer.h:37
Packet * attachedPacket
Pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:50
bool ownedByPacket
Controls if the layer object is considered owned by the attached Packet.
Definition: Layer.h:59
void detach()
Clears the attachment to any Packet, resetting to unmanaged state.
Definition: Layer.h:78
void attachPacket(Packet *packet, bool managed, bool force=false)
Sets the state of attachment to a specified Packet.
Definition: Layer.h:66