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 
187  void copyData(uint8_t* toArr) const;
188 
189  // implement abstract methods
190 
191  uint8_t* getDataPtr(size_t offset = 0) const override
192  {
193  return static_cast<uint8_t*>(m_Data + offset);
194  }
195 
196  // abstract methods
197 
199  virtual void parseNextLayer() = 0;
200 
202  virtual size_t getHeaderLen() const = 0;
203 
205  virtual void computeCalculateFields() = 0;
206 
209  virtual std::string toString() const = 0;
210 
212  virtual OsiModelLayer getOsiModelLayer() const = 0;
213 
214  protected:
215  uint8_t* m_Data;
216  size_t m_DataLen;
217  ProtocolType m_Protocol;
218  Layer* m_NextLayer;
219  Layer* m_PrevLayer;
220 
221  private:
222  internal::LayerAllocationInfo m_AllocationInfo;
223 
224  protected:
225  Layer() : m_Data(nullptr), m_DataLen(0), m_Protocol(UnknownProtocol), m_NextLayer(nullptr), m_PrevLayer(nullptr)
226  {}
227 
228  Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType protocol = UnknownProtocol)
229  : m_Data(data), m_DataLen(dataLen), m_Protocol(protocol), m_NextLayer(nullptr), m_PrevLayer(prevLayer),
230  m_AllocationInfo{ packet, false }
231  {}
232 
233  // Copy c'tor
234  Layer(const Layer& other);
235  Layer& operator=(const Layer& other);
236 
240  {
241  return m_AllocationInfo.attachedPacket;
242  }
243 
246  Packet const* getAttachedPacket() const
247  {
248  return m_AllocationInfo.attachedPacket;
249  }
250 
251  void setNextLayer(Layer* nextLayer)
252  {
253  m_NextLayer = nextLayer;
254  }
255  void setPrevLayer(Layer* prevLayer)
256  {
257  m_PrevLayer = prevLayer;
258  }
259 
260  virtual bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend);
261  virtual bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten);
262 
263  bool hasNextLayer() const
264  {
265  return m_NextLayer != nullptr;
266  }
267 
278  template <typename T, typename... Args>
279  Layer* constructNextLayer(uint8_t* data, size_t dataLen, Args&&... extraArgs)
280  {
281  return constructNextLayer<T>(data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
282  }
283 
292  template <typename T, typename... Args>
293  Layer* constructNextLayer(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
294  {
295  if (hasNextLayer())
296  {
297  throw std::runtime_error("Next layer already exists");
298  }
299 
300  Layer* newLayer = new T(data, dataLen, this, packet, std::forward<Args>(extraArgs)...);
301  setNextLayer(newLayer);
302  return newLayer;
303  }
304 
322  template <typename TFactory, typename... Args>
323  Layer* constructNextLayerFromFactory(TFactory factoryFn, uint8_t* data, size_t dataLen, Args&&... extraArgs)
324  {
325  return constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, getAttachedPacket(),
326  std::forward<Args>(extraArgs)...);
327  }
328 
345  template <typename TFactory, typename... Args>
346  Layer* constructNextLayerFromFactory(TFactory factoryFn, uint8_t* data, size_t dataLen, Packet* packet,
347  Args&&... extraArgs)
348  {
349  if (hasNextLayer())
350  {
351  throw std::runtime_error("Next layer already exists");
352  }
353 
354  // cppcheck-suppress redundantInitialization
355  Layer* newLayer = factoryFn(data, dataLen, this, packet, std::forward<Args>(extraArgs)...);
356  setNextLayer(newLayer);
357  return newLayer;
358  }
359 
373  template <typename T, typename... Args>
374  Layer* tryConstructNextLayer(uint8_t* data, size_t dataLen, Args&&... extraArgs)
375  {
376  return tryConstructNextLayer<T>(data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
377  }
378 
391  template <typename T, typename... Args>
392  Layer* tryConstructNextLayer(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
393  {
394  if (T::isDataValid(data, dataLen))
395  {
396  return constructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...);
397  }
398  return nullptr;
399  }
400 
417  template <typename T, typename TFallback, typename... Args>
418  Layer* tryConstructNextLayerWithFallback(uint8_t* data, size_t dataLen, Args&&... extraArgs)
419  {
420  return tryConstructNextLayerWithFallback<T, TFallback>(data, dataLen, getAttachedPacket(),
421  std::forward<Args>(extraArgs)...);
422  }
423 
439  template <typename T, typename TFallback, typename... Args>
440  Layer* tryConstructNextLayerWithFallback(uint8_t* data, size_t dataLen, Packet* packet, Args&&... extraArgs)
441  {
442  if (tryConstructNextLayer<T>(data, dataLen, packet, std::forward<Args>(extraArgs)...))
443  {
444  return m_NextLayer;
445  }
446 
447  return constructNextLayer<TFallback>(data, dataLen, packet);
448  }
449 
471  template <typename TFallback, typename TFactory, typename... Args>
472  Layer* tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t* data, size_t dataLen,
473  Args&&... extraArgs)
474  {
475  // Note that the fallback is first to allow template argument deduction of the factory type.
476  return tryConstructNextLayerFromFactoryWithFallback<TFallback, TFactory>(
477  factoryFn, data, dataLen, getAttachedPacket(), std::forward<Args>(extraArgs)...);
478  }
479 
500  template <typename TFallback, typename TFactory, typename... Args>
501  Layer* tryConstructNextLayerFromFactoryWithFallback(TFactory factoryFn, uint8_t* data, size_t dataLen,
502  Packet* packet, Args&&... extraArgs)
503  {
504  auto nextLayer = constructNextLayerFromFactory<TFactory>(factoryFn, data, dataLen, packet,
505  std::forward<Args>(extraArgs)...);
506  if (nextLayer != nullptr)
507  {
508  return nextLayer;
509  }
510 
511  // factory failed, construct fallback layer
512  return constructNextLayer<TFallback>(data, dataLen, packet);
513  }
514 
523  template <typename T> static bool canReinterpretAs(const uint8_t* data, size_t dataLen)
524  {
525  return data != nullptr && dataLen >= sizeof(T);
526  }
527  };
528 
529  inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer& layer)
530  {
531  os << layer.toString();
532  return os;
533  }
534 } // 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
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:323
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:501
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:191
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:346
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:472
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:279
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:293
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:418
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:239
Layer * getPrevLayer() const
Definition: Layer.h:131
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:440
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:523
Layer * tryConstructNextLayer(uint8_t *data, size_t dataLen, Args &&... extraArgs)
Definition: Layer.h:374
Packet const * getAttachedPacket() const
Get a pointer to the Packet this layer is attached to (if any).
Definition: Layer.h:246
~Layer() override
Layer * tryConstructNextLayer(uint8_t *data, size_t dataLen, Packet *packet, Args &&... extraArgs)
Definition: Layer.h:392
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