/src/PcapPlusPlus/Packet++/header/Packet.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include "RawPacket.h" |
4 | | #include "Layer.h" |
5 | | #include "Serializers.h" |
6 | | #include <vector> |
7 | | |
8 | | /// @file |
9 | | |
10 | | /// @namespace pcpp |
11 | | /// @brief The main namespace for the PcapPlusPlus lib |
12 | | namespace pcpp |
13 | | { |
14 | | /// @brief Options struct for configuring packet parsing behavior. |
15 | | /// |
16 | | /// The parsing options are combined. If multiple stop conditions are specified, parsing stops |
17 | | /// as soon as any condition is met. |
18 | | struct PacketParseOptions |
19 | | { |
20 | | /// @brief Defines the protocol type up to and including which the packet should be parsed (inclusive). |
21 | | /// |
22 | | /// For large packets where only the lower layers are of interest, this option can be used to limit the parsing |
23 | | /// procedure to the desired protocol. The packet is parsed until the specified protocol is reached and |
24 | | /// consumed. Layers beyond this protocol are not parsed, which can improve performance and reduce |
25 | | /// memory usage. |
26 | | /// |
27 | | /// @remarks If multiple consecutive layers of the same protocol type exist, parsing stops after exhausting the |
28 | | /// first contiguous sequence of that protocol type. This matters for protocols that may appear multiple times |
29 | | /// in succession within a packet (e.g. BgpLayer). |
30 | | ProtocolTypeFamily parseUntilProtocol = UnknownProtocol; |
31 | | |
32 | | /// @brief Defines an OSI model layer up to and including which the packet should be parsed (inclusive). |
33 | | /// |
34 | | /// For large packets where only the lower layers are of interest, this option can be used to limit the parsing |
35 | | /// procedure to the desired OSI layer. The packet is parsed until all layers belonging to the specified OSI |
36 | | /// layer are consumed. Layers beyond that are ignored, which can improve performance and reduce memory usage. |
37 | | OsiModelLayer parseUntilLayer = OsiModelLayerUnknown; |
38 | | }; |
39 | | |
40 | | /// @class Packet |
41 | | /// This class represents a parsed packet. It contains the raw data (RawPacket instance), and a linked list of |
42 | | /// layers, each layer is a parsed protocol that this packet contains. The layers linked list is ordered where the |
43 | | /// first layer is the lowest in the packet (currently it's always Ethernet protocol as PcapPlusPlus supports only |
44 | | /// Ethernet packets), the next layer will be L2.5 or L3 (e.g VLAN, IPv4, IPv6, etc.), and so on. etc.), etc. The |
45 | | /// last layer in the linked list will be the highest in the packet. For example: for a standard HTTP request packet |
46 | | /// the layer will look like this: EthLayer -> IPv4Layer -> TcpLayer -> HttpRequestLayer <BR> Packet instance isn't |
47 | | /// read only. The user can add or remove layers, update current layer, etc. |
48 | | class Packet |
49 | | { |
50 | | friend class Layer; |
51 | | |
52 | | private: |
53 | | RawPacket* m_RawPacket; |
54 | | Layer* m_FirstLayer; |
55 | | Layer* m_LastLayer; |
56 | | size_t m_MaxPacketLen; |
57 | | bool m_FreeRawPacket; |
58 | | bool m_CanReallocateData; |
59 | | |
60 | | public: |
61 | | /// A constructor for creating a new packet (with no layers). |
62 | | /// When using this constructor an empty raw buffer is allocated (with the size of maxPacketLen) and a new |
63 | | /// RawPacket is created |
64 | | /// @param[in] maxPacketLen The expected packet length in bytes |
65 | | /// @param[in] linkType The link type to use for this packet (the default is Ethernet) |
66 | | explicit Packet(size_t maxPacketLen = 1, LinkLayerType linkType = LINKTYPE_ETHERNET); |
67 | | |
68 | | /// A constructor for creating a new packet with a buffer that is pre-allocated by the user. |
69 | | /// The packet is created empty (with no layers), which means the constructor doesn't parse the data in the |
70 | | /// buffer. Instead, all of the raw data of this packet it written to this buffer: whenever a layer is added, |
71 | | /// it's data is written to this buffer. The buffer isn't freed and it's content isn't erased when the packet |
72 | | /// object is deleted. This constructor is useful when you already have a memory buffer and you want to create |
73 | | /// packet data in it. |
74 | | /// @param[in] buffer A pointer to a pre-allocated memory buffer |
75 | | /// @param[in] bufferSize The size of the buffer |
76 | | /// @param[in] linkType The link type to use for this packet (the default is Ethernet) |
77 | | Packet(uint8_t* buffer, size_t bufferSize, LinkLayerType linkType = LINKTYPE_ETHERNET); |
78 | | |
79 | | /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets |
80 | | /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't |
81 | | /// copied) and the RawPacket is parsed, meaning all layers are created and linked to each other in the right |
82 | | /// order. In this overload of the constructor the user can specify whether to free the instance of raw packet |
83 | | /// when the Packet is free or not |
84 | | /// @param[in] rawPacket A pointer to the raw packet |
85 | | /// @param[in] freeRawPacket Optional parameter. A flag indicating if the destructor should also call the raw |
86 | | /// packet destructor or not. Default value is false |
87 | | /// @param[in] parseUntil Optional parameter. Parse the packet until you reach a certain protocol (inclusive). |
88 | | /// Can be useful for cases when you need to parse only up to a certain layer and want to avoid the performance |
89 | | /// impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means |
90 | | /// don't take this parameter into account |
91 | | /// @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI |
92 | | /// model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer (for |
93 | | /// example transport layer) and want to avoid the performance impact and memory consumption of parsing the |
94 | | /// whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter into account |
95 | | explicit Packet(RawPacket* rawPacket, bool freeRawPacket = false, ProtocolType parseUntil = UnknownProtocol, |
96 | | OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); |
97 | | |
98 | | /// @copydoc Packet(RawPacket*, bool, ProtocolType, OsiModelLayer) |
99 | | explicit Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil, |
100 | | OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); |
101 | | |
102 | | /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets |
103 | | /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't |
104 | | /// copied) and the RawPacket is parsed, meaning all layers are created and linked to each other in the right |
105 | | /// order. In this overload of the constructor the user can specify whether to free the instance of raw packet |
106 | | /// when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer |
107 | | /// @param[in] rawPacket A pointer to the raw packet |
108 | | /// @param[in] parseUntil Parse the packet until you reach a certain protocol (inclusive). Can be useful for |
109 | | /// cases when you need to parse only up to a certain layer and want to avoid the performance impact and memory |
110 | | /// consumption of parsing the whole packet |
111 | | explicit Packet(RawPacket* rawPacket, ProtocolType parseUntil); |
112 | | |
113 | | /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets |
114 | | /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't |
115 | | /// copied) and the RawPacket is parsed, meaning all layers are created and linked to each other in the right |
116 | | /// order. In this overload of the constructor the user can specify whether to free the instance of raw packet |
117 | | /// when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer |
118 | | /// @param[in] rawPacket A pointer to the raw packet |
119 | | /// @param[in] parseUntilFamily Parse the packet until you reach a certain protocol family (inclusive). Can be |
120 | | /// useful for cases when you need to parse only up to a certain layer and want to avoid the performance impact |
121 | | /// and memory consumption of parsing the whole packet |
122 | | explicit Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily); |
123 | | |
124 | | /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets |
125 | | /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't |
126 | | /// copied) and the RawPacket is parsed, meaning all layers are created and linked to each other in the right |
127 | | /// order. In this overload of the constructor the user can specify whether to free the instance of raw packet |
128 | | /// when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer in |
129 | | /// the OSI model |
130 | | /// @param[in] rawPacket A pointer to the raw packet |
131 | | /// @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI |
132 | | /// model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer (for |
133 | | /// example transport layer) and want to avoid the performance impact and memory consumption of parsing the |
134 | | /// whole packet |
135 | | explicit Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer); |
136 | | |
137 | | /// A destructor for this class. Frees all layers allocated by this instance (Notice: it doesn't free layers |
138 | | /// that weren't allocated by this class, for example layers that were added by addLayer() or insertLayer() ). |
139 | | /// In addition it frees the raw packet if it was allocated by this instance (meaning if it was allocated by |
140 | | /// this instance constructor) |
141 | | virtual ~Packet() |
142 | 0 | { |
143 | 0 | destructPacketData(); |
144 | 0 | } |
145 | | |
146 | | /// A copy constructor for this class. This copy constructor copies all the raw data and re-create all layers. |
147 | | /// So when the original Packet is being freed, no data will be lost in the copied instance |
148 | | /// @param[in] other The instance to copy from |
149 | | Packet(const Packet& other) |
150 | 0 | { |
151 | 0 | copyDataFrom(other); |
152 | 0 | } |
153 | | |
154 | | /// Assignment operator overloading. It first frees all layers allocated by this instance (Notice: it doesn't |
155 | | /// free layers that weren't allocated by this class, for example layers that were added by addLayer() or |
156 | | /// insertLayer() ). In addition it frees the raw packet if it was allocated by this instance (meaning if it was |
157 | | /// allocated by this instance constructor). Afterwards it copies the data from the other packet in the same way |
158 | | /// used in the copy constructor. |
159 | | /// @param[in] other The instance to copy from |
160 | | Packet& operator=(const Packet& other); |
161 | | |
162 | | /// Get a pointer to the Packet's RawPacket |
163 | | /// @return A pointer to the Packet's RawPacket |
164 | | RawPacket* getRawPacket() const |
165 | 0 | { |
166 | 0 | return m_RawPacket; |
167 | 0 | } |
168 | | |
169 | | /// Set a RawPacket and re-construct all packet layers |
170 | | /// @param[in] rawPacket Raw packet to set |
171 | | /// @param[in] freeRawPacket A flag indicating if the destructor should also call the raw packet destructor or |
172 | | /// not |
173 | | /// @param[in] parseUntil Parse the packet until it reaches this protocol. Can be useful for cases when you need |
174 | | /// to parse only up to a certain layer and want to avoid the performance impact and memory consumption of |
175 | | /// parsing the whole packet. Default value is ::UnknownProtocol which means don't take this parameter into |
176 | | /// account |
177 | | /// @param[in] parseUntilLayer Parse the packet until certain layer in OSI model. Can be useful for cases when |
178 | | /// you need to parse only up to a certain layer and want to avoid the performance impact and memory consumption |
179 | | /// of parsing the whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter |
180 | | /// into account |
181 | | void setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil = UnknownProtocol, |
182 | | OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); |
183 | | |
184 | | /// @brief Parse the packet according to the provided options. |
185 | | /// |
186 | | /// The packet is parsed according to the specified options, constructing the layer hierarchy if it does not |
187 | | /// exist. If the packet has already been parsed, it will be re-parsed based on the new options. |
188 | | /// |
189 | | /// If @p incrementalParsing is true, the procedure will reuse existing layers where possible, only creating new |
190 | | /// layers for previously unparsed data. Otherwise, all existing layers are discarded and the packet is parsed |
191 | | /// from scratch. |
192 | | /// |
193 | | /// @param[in] options Parsing options to configure the parsing behavior. |
194 | | /// @param[in] incrementalParsing If 'true', incremental parsing is performed, reusing existing layers where |
195 | | /// possible. |
196 | | /// @throws std::runtime_error if there is no RawPacket associated with this Packet instance. |
197 | | void parsePacket(PacketParseOptions options, bool incrementalParsing = true); |
198 | | |
199 | | /// Get a pointer to the Packet's RawPacket in a read-only manner |
200 | | /// @return A pointer to the Packet's RawPacket |
201 | | const RawPacket* getRawPacketReadOnly() const |
202 | 0 | { |
203 | 0 | return m_RawPacket; |
204 | 0 | } |
205 | | |
206 | | /// Get a pointer to the first (lowest) layer in the packet |
207 | | /// @return A pointer to the first (lowest) layer in the packet |
208 | | Layer* getFirstLayer() const |
209 | 0 | { |
210 | 0 | return m_FirstLayer; |
211 | 0 | } |
212 | | |
213 | | /// Get a pointer to the last (highest) layer in the packet |
214 | | /// @return A pointer to the last (highest) layer in the packet |
215 | | Layer* getLastLayer() const |
216 | 0 | { |
217 | 0 | return m_LastLayer; |
218 | 0 | } |
219 | | |
220 | | /// Add a new layer as the last layer in the packet. This method gets a pointer to the new layer as a parameter |
221 | | /// and attaches it to the packet. Notice after calling this method the input layer is attached to the packet so |
222 | | /// every change you make in it affect the packet; Also it cannot be attached to other packets |
223 | | /// @param[in] newLayer A pointer to the new layer to be added to the packet |
224 | | /// @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default |
225 | | /// is false. |
226 | | /// @return True if everything went well or false otherwise (an appropriate error log message will be printed in |
227 | | /// such cases) |
228 | | bool addLayer(Layer* newLayer, bool ownInPacket = false) |
229 | 0 | { |
230 | 0 | return insertLayer(m_LastLayer, newLayer, ownInPacket); |
231 | 0 | } |
232 | | |
233 | | /// Insert a new layer after an existing layer in the packet. This method gets a pointer to the new layer as a |
234 | | /// parameter and attaches it to the packet. Notice after calling this method the input layer is attached to the |
235 | | /// packet so every change you make in it affect the packet; Also it cannot be attached to other packets |
236 | | /// @param[in] prevLayer A pointer to an existing layer in the packet which the new layer should followed by. If |
237 | | /// this layer isn't attached to a packet and error will be printed to log and false will be returned |
238 | | /// @param[in] newLayer A pointer to the new layer to be added to the packet |
239 | | /// @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default |
240 | | /// is false. |
241 | | /// @return True if everything went well or false otherwise (an appropriate error log message will be printed in |
242 | | /// such cases) |
243 | | bool insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket = false); |
244 | | |
245 | | /// Remove an existing layer from the packet. The layer to removed is identified by its type (protocol). If the |
246 | | /// packet has multiple layers of the same type in the packet the user may specify the index of the layer to |
247 | | /// remove (the default index is 0 - remove the first layer of this type). If the layer was allocated during |
248 | | /// packet creation it will be deleted and any pointer to it will get invalid. However if the layer was |
249 | | /// allocated by the user and manually added to the packet it will simply get detached from the packet, meaning |
250 | | /// the pointer to it will stay valid and its data (that was removed from the packet) will be copied back to the |
251 | | /// layer. In that case it's the user's responsibility to delete the layer instance |
252 | | /// @param[in] layerType The layer type (protocol) to remove |
253 | | /// @param[in] index If there are multiple layers of the same type, indicate which instance to remove. The |
254 | | /// default value is 0, meaning remove the first layer of this type |
255 | | /// @return True if everything went well or false otherwise (an appropriate error log message will be printed in |
256 | | /// such cases) |
257 | | bool removeLayer(ProtocolType layerType, int index = 0); |
258 | | |
259 | | /// Remove the first layer in the packet. The layer will be deleted if it was allocated during packet creation, |
260 | | /// or detached if was allocated outside of the packet. Please refer to removeLayer() to get more info |
261 | | /// @return True if layer removed successfully, or false if removing the layer failed or if there are no layers |
262 | | /// in the packet. In any case of failure an appropriate error log message will be printed |
263 | | bool removeFirstLayer(); |
264 | | |
265 | | /// Remove the last layer in the packet. The layer will be deleted if it was allocated during packet creation, |
266 | | /// or detached if was allocated outside of the packet. Please refer to removeLayer() to get more info |
267 | | /// @return True if layer removed successfully, or false if removing the layer failed or if there are no layers |
268 | | /// in the packet. In any case of failure an appropriate error log message will be printed |
269 | | bool removeLastLayer(); |
270 | | |
271 | | /// Remove all layers that come after a certain layer. All layers removed will be deleted if they were allocated |
272 | | /// during packet creation or detached if were allocated outside of the packet, please refer to removeLayer() to |
273 | | /// get more info |
274 | | /// @param[in] layer A pointer to the layer to begin removing from. Please note this layer will not be removed, |
275 | | /// only the layers that come after it will be removed. Also, if removal of one layer failed, the method will |
276 | | /// return immediately and the following layers won't be deleted |
277 | | /// @return True if all layers were removed successfully, or false if failed to remove at least one layer. In |
278 | | /// any case of failure an appropriate error log message will be printed |
279 | | bool removeAllLayersAfter(Layer* layer); |
280 | | |
281 | | /// Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated |
282 | | /// from the packet - e.g it will be removed from the layer chain of the packet and its data will be copied from |
283 | | /// the packet buffer into an internal layer buffer. After a layer is detached, it can be added into another |
284 | | /// packet (but it's impossible to attach a layer to multiple packets in the same time). After layer is |
285 | | /// detached, it's the user's responsibility to delete it when it's not needed anymore |
286 | | /// @param[in] layerType The layer type (protocol) to detach from the packet |
287 | | /// @param[in] index If there are multiple layers of the same type, indicate which instance to detach. The |
288 | | /// default value is 0, meaning detach the first layer of this type |
289 | | /// @return A pointer to the detached layer or nullptr if detaching process failed. In any case of failure an |
290 | | /// appropriate error log message will be printed |
291 | | Layer* detachLayer(ProtocolType layerType, int index = 0); |
292 | | |
293 | | /// Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated |
294 | | /// from the packet - e.g it will be removed from the layer chain of the packet and its data will be copied from |
295 | | /// the packet buffer into an internal layer buffer. After a layer is detached, it can be added into another |
296 | | /// packet (but it's impossible to attach a layer to multiple packets at the same time). After layer is |
297 | | /// detached, it's the user's responsibility to delete it when it's not needed anymore |
298 | | /// @param[in] layer A pointer to the layer to detach |
299 | | /// @return True if the layer was detached successfully, or false if something went wrong. In any case of |
300 | | /// failure an appropriate error log message will be printed |
301 | | bool detachLayer(Layer* layer) |
302 | 0 | { |
303 | 0 | return removeLayer(layer, false); |
304 | 0 | } |
305 | | |
306 | | /// Get a pointer to the layer of a certain type (protocol). This method goes through the layers and returns a |
307 | | /// layer that matches the give protocol type |
308 | | /// @param[in] layerType The layer type (protocol) to fetch |
309 | | /// @param[in] index If there are multiple layers of the same type, indicate which instance to fetch. The |
310 | | /// default value is 0, meaning fetch the first layer of this type |
311 | | /// @return A pointer to the layer or nullptr if no such layer was found |
312 | | Layer* getLayerOfType(ProtocolType layerType, int index = 0) const; |
313 | | |
314 | | /// A templated method to get a layer of a certain type (protocol). If no layer of such type is found, nullptr |
315 | | /// is returned |
316 | | /// @param[in] reverseOrder The optional parameter that indicates that the lookup should run in reverse order, |
317 | | /// the default value is false |
318 | | /// @return A pointer to the layer of the requested type, nullptr if not found |
319 | | template <class TLayer> TLayer* getLayerOfType(bool reverseOrder = false) const; |
320 | | |
321 | | /// A templated method to get the first layer of a certain type (protocol), start searching from a certain |
322 | | /// layer. For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) -> |
323 | | /// IPv4Layer and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(3) |
324 | | /// will be returned If no layer of such type is found, nullptr is returned |
325 | | /// @param[in] startLayer A pointer to the layer to start search from |
326 | | /// @return A pointer to the layer of the requested type, nullptr if not found |
327 | | template <class TLayer> TLayer* getNextLayerOfType(Layer* startLayer) const; |
328 | | |
329 | | /// A templated method to get the first layer of a certain type (protocol), start searching from a certain |
330 | | /// layer. For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) -> |
331 | | /// IPv4Layer and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(1) |
332 | | /// will be returned If no layer of such type is found, nullptr is returned |
333 | | /// @param[in] startLayer A pointer to the layer to start search from |
334 | | /// @return A pointer to the layer of the requested type, nullptr if not found |
335 | | template <class TLayer> TLayer* getPrevLayerOfType(Layer* startLayer) const; |
336 | | |
337 | | /// Check whether the packet contains a layer of a certain protocol |
338 | | /// @param[in] protocolType The protocol type to search |
339 | | /// @return True if the packet contains a layer of a certain protocol, false otherwise |
340 | | bool isPacketOfType(ProtocolType protocolType) const; |
341 | | |
342 | | /// Check whether the packet contains a layer of a certain protocol family |
343 | | /// @param[in] protocolTypeFamily The protocol type family to search |
344 | | /// @return True if the packet contains a layer of a certain protocol family, false otherwise |
345 | | bool isPacketOfType(ProtocolTypeFamily protocolTypeFamily) const; |
346 | | |
347 | | /// Each layer can have fields that can be calculate automatically from other fields using |
348 | | /// Layer#computeCalculateFields(). This method forces all layers to calculate these fields values |
349 | | void computeCalculateFields(); |
350 | | |
351 | | /// Each layer can print a string representation of the layer most important data using Layer#toString(). This |
352 | | /// method aggregates this string from all layers and print it to a complete string containing all packet's |
353 | | /// relevant data |
354 | | /// @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set |
355 | | /// to false |
356 | | /// @return A string containing most relevant data from all layers (looks like the packet description in |
357 | | /// Wireshark) |
358 | | std::string toString(bool timeAsLocalTime = true) const; |
359 | | |
360 | | /// Similar to toString(), but instead of one string it outputs a list of strings, one string for every layer |
361 | | /// @param[out] result A string vector that will contain all strings |
362 | | /// @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set |
363 | | /// to false |
364 | | void toStringList(std::vector<std::string>& result, bool timeAsLocalTime = true) const; |
365 | | |
366 | | /// @struct SerializedFields |
367 | | /// Field descriptors for the fields serialized by Packet::serialize(). |
368 | | struct SerializedFields |
369 | | { |
370 | | /// @struct TimestampObject |
371 | | /// Field descriptors for the packet timestamp. |
372 | | struct TimestampObject : ObjectFieldDescriptor<TimestampObject> |
373 | | { |
374 | | using ObjectFieldDescriptor::ObjectFieldDescriptor; |
375 | | |
376 | | /// @return A vector containing all timestamp field descriptors. |
377 | | static std::vector<FieldDescriptor> all() |
378 | 0 | { |
379 | 0 | return { Sec, NSec }; |
380 | 0 | } |
381 | | |
382 | | /// Field descriptor for the timestamp seconds. |
383 | | static const FieldDescriptor Sec; |
384 | | |
385 | | /// Field descriptor for the timestamp nanoseconds. |
386 | | static const FieldDescriptor NSec; |
387 | | }; |
388 | | |
389 | | /// @return A vector containing all packet field descriptors. |
390 | | static std::vector<FieldDescriptor> all() |
391 | 0 | { |
392 | 0 | return { Timestamp, FrameLength, LinkLayer, LinkLayerName, Layers }; |
393 | 0 | } |
394 | | |
395 | | /// Field descriptor for the packet timestamp. |
396 | | static const TimestampObject Timestamp; |
397 | | |
398 | | /// Field descriptor for the packet frame length. |
399 | | static const FieldDescriptor FrameLength; |
400 | | |
401 | | /// Field descriptor for the packet link layer type. |
402 | | static const FieldDescriptor LinkLayer; |
403 | | |
404 | | /// Field descriptor for the packet link layer name. |
405 | | static const FieldDescriptor LinkLayerName; |
406 | | |
407 | | /// Field descriptor for the packet layers. |
408 | | static const FieldDescriptor Layers; |
409 | | }; |
410 | | |
411 | | /// Serialize the packet using the provided serializer. |
412 | | /// @param[in] serializer The serializer to use. |
413 | | void serialize(ISerializer& serializer) const; |
414 | | |
415 | | private: |
416 | | void copyDataFrom(const Packet& other); |
417 | | |
418 | | void destructPacketData(); |
419 | | void destroyAllLayers(); |
420 | | |
421 | | bool extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend); |
422 | | bool shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten); |
423 | | |
424 | | void reallocateRawData(size_t newSize); |
425 | | |
426 | | bool removeLayer(Layer* layer, bool tryToDelete); |
427 | | |
428 | | std::string printPacketInfo(bool timeAsLocalTime) const; |
429 | | |
430 | | Layer* createFirstLayer(LinkLayerType linkType); |
431 | | |
432 | | template <typename TLayer, typename NextLayerFn> |
433 | | static TLayer* searchLayerStackForType(Layer* startLayer, NextLayerFn nextLayerFn, bool skipFirst); |
434 | | }; // class Packet |
435 | | |
436 | | // implementation of inline methods |
437 | | |
438 | | template <class TLayer> TLayer* Packet::getLayerOfType(bool reverse) const |
439 | | { |
440 | | if (!reverse) |
441 | | { |
442 | | return searchLayerStackForType<TLayer>( |
443 | | m_FirstLayer, [](Layer* layer) { return layer->getNextLayer(); }, false); |
444 | | } |
445 | | |
446 | | // lookup in reverse order |
447 | | return searchLayerStackForType<TLayer>(m_LastLayer, [](Layer* layer) { return layer->getPrevLayer(); }, false); |
448 | | } |
449 | | |
450 | | template <class TLayer> TLayer* Packet::getNextLayerOfType(Layer* curLayer) const |
451 | | { |
452 | | return searchLayerStackForType<TLayer>(curLayer, [](Layer* layer) { return layer->getNextLayer(); }, true); |
453 | | } |
454 | | |
455 | | template <class TLayer> TLayer* Packet::getPrevLayerOfType(Layer* curLayer) const |
456 | | { |
457 | | return searchLayerStackForType<TLayer>(curLayer, [](Layer* layer) { return layer->getPrevLayer(); }, true); |
458 | | } |
459 | | |
460 | | template <typename TLayer, typename NextLayerFn> |
461 | | TLayer* Packet::searchLayerStackForType(Layer* curLayer, NextLayerFn nextLayerFn, bool skipFirst) |
462 | | { |
463 | | if (curLayer == nullptr) |
464 | | return nullptr; |
465 | | |
466 | | if (skipFirst) |
467 | | { |
468 | | curLayer = nextLayerFn(curLayer); |
469 | | } |
470 | | |
471 | | while (curLayer != nullptr) |
472 | | { |
473 | | auto* curLayerCasted = dynamic_cast<TLayer*>(curLayer); |
474 | | if (curLayerCasted != nullptr) |
475 | | return curLayerCasted; |
476 | | |
477 | | curLayer = nextLayerFn(curLayer); |
478 | | } |
479 | | |
480 | | return nullptr; |
481 | | } |
482 | | |
483 | | inline std::ostream& operator<<(std::ostream& os, const pcpp::Packet& packet) |
484 | 0 | { |
485 | 0 | os << packet.toString(); |
486 | 0 | return os; |
487 | 0 | } |
488 | | } // namespace pcpp |