/src/PcapPlusPlus/Packet++/header/Packet.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef PACKETPP_PACKET |
2 | | #define PACKETPP_PACKET |
3 | | |
4 | | #include "RawPacket.h" |
5 | | #include "Layer.h" |
6 | | #include <vector> |
7 | | |
8 | | /// @file |
9 | | |
10 | | /** |
11 | | * \namespace pcpp |
12 | | * \brief The main namespace for the PcapPlusPlus lib |
13 | | */ |
14 | | namespace pcpp |
15 | | { |
16 | | |
17 | | /** |
18 | | * @class Packet |
19 | | * This class represents a parsed packet. It contains the raw data (RawPacket instance), and a linked list of layers, each layer is a parsed |
20 | | * protocol that this packet contains. The layers linked list is ordered where the first layer is the lowest in the packet (currently it's always |
21 | | * Ethernet protocol as PcapPlusPlus supports only Ethernet packets), the next layer will be L2.5 or L3 (e.g VLAN, IPv4, IPv6, etc.), and so on. |
22 | | * etc.), etc. The last layer in the linked list will be the highest in the packet. |
23 | | * For example: for a standard HTTP request packet the layer will look like this: EthLayer -> IPv4Layer -> TcpLayer -> HttpRequestLayer <BR> |
24 | | * Packet instance isn't read only. The user can add or remove layers, update current layer, etc. |
25 | | */ |
26 | | class Packet |
27 | | { |
28 | | friend class Layer; |
29 | | private: |
30 | | RawPacket* m_RawPacket; |
31 | | Layer* m_FirstLayer; |
32 | | Layer* m_LastLayer; |
33 | | uint64_t m_ProtocolTypes; |
34 | | size_t m_MaxPacketLen; |
35 | | bool m_FreeRawPacket; |
36 | | bool m_CanReallocateData; |
37 | | |
38 | | public: |
39 | | |
40 | | /** |
41 | | * A constructor for creating a new packet (with no layers). |
42 | | * When using this constructor an empty raw buffer is allocated (with the size of maxPacketLen) and a new RawPacket is created |
43 | | * @param[in] maxPacketLen The expected packet length in bytes |
44 | | */ |
45 | | Packet(size_t maxPacketLen = 1); |
46 | | |
47 | | /** |
48 | | * A constructor for creating a new packet with a buffer that is pre-allocated by the user. |
49 | | * The packet is created empty (with no layers), which means the constructor doesn't parse the data in the buffer. |
50 | | * Instead, all of the raw data of this packet it written to this buffer: whenever a layer is added, it's data is written to this buffer. |
51 | | * The buffer isn't freed and it's content isn't erased when the packet object is deleted. |
52 | | * This constructor is useful when you already have a memory buffer and you want to create packet data in it. |
53 | | * @param[in] buffer A pointer to a pre-allocated memory buffer |
54 | | * @param[in] bufferSize The size of the buffer |
55 | | */ |
56 | | Packet(uint8_t* buffer, size_t bufferSize); |
57 | | |
58 | | /** |
59 | | * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network. |
60 | | * When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers |
61 | | * are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free |
62 | | * the instance of raw packet when the Packet is free or not |
63 | | * @param[in] rawPacket A pointer to the raw packet |
64 | | * @param[in] freeRawPacket Optional parameter. A flag indicating if the destructor should also call the raw packet destructor or not. Default value is false |
65 | | * @param[in] parseUntil Optional parameter. Parse the packet until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a |
66 | | * certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means don't take this |
67 | | * parameter into account |
68 | | * @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to |
69 | | * parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet. |
70 | | * Default value is ::OsiModelLayerUnknown which means don't take this parameter into account |
71 | | */ |
72 | | explicit Packet(RawPacket* rawPacket, bool freeRawPacket = false, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); |
73 | | |
74 | | /** |
75 | | * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network. |
76 | | * When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers |
77 | | * are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free |
78 | | * the instance of raw packet when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer |
79 | | * @param[in] rawPacket A pointer to the raw packet |
80 | | * @param[in] parseUntil Optional parameter. Parse the packet until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a |
81 | | * certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet |
82 | | */ |
83 | | Packet(RawPacket* rawPacket, ProtocolType parseUntil); |
84 | | |
85 | | /** |
86 | | * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network. |
87 | | * When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers |
88 | | * are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free |
89 | | * the instance of raw packet when the Packet is free or not. . This constructor should be used to parse the packet up to a certain layer in the OSI model |
90 | | * @param[in] rawPacket A pointer to the raw packet |
91 | | * @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to |
92 | | * parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet |
93 | | */ |
94 | | Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer); |
95 | | |
96 | | /** |
97 | | * A destructor for this class. Frees all layers allocated by this instance (Notice: it doesn't free layers that weren't allocated by this |
98 | | * class, for example layers that were added by addLayer() or insertLayer() ). In addition it frees the raw packet if it was allocated by |
99 | | * this instance (meaning if it was allocated by this instance constructor) |
100 | | */ |
101 | | virtual ~Packet() { destructPacketData(); } |
102 | | |
103 | | /** |
104 | | * A copy constructor for this class. This copy constructor copies all the raw data and re-create all layers. So when the original Packet |
105 | | * is being freed, no data will be lost in the copied instance |
106 | | * @param[in] other The instance to copy from |
107 | | */ |
108 | | Packet(const Packet& other) { copyDataFrom(other); } |
109 | | |
110 | | /** |
111 | | * Assignment operator overloading. It first frees all layers allocated by this instance (Notice: it doesn't free layers that weren't allocated by this |
112 | | * class, for example layers that were added by addLayer() or insertLayer() ). In addition it frees the raw packet if it was allocated by |
113 | | * this instance (meaning if it was allocated by this instance constructor). |
114 | | * Afterwards it copies the data from the other packet in the same way used in the copy constructor. |
115 | | * @param[in] other The instance to copy from |
116 | | */ |
117 | | Packet& operator=(const Packet& other); |
118 | | |
119 | | /** |
120 | | * Get a pointer to the Packet's RawPacket |
121 | | * @return A pointer to the Packet's RawPacket |
122 | | */ |
123 | | RawPacket* getRawPacket() const { return m_RawPacket; } |
124 | | |
125 | | /** |
126 | | * Set a RawPacket and re-construct all packet layers |
127 | | * @param[in] rawPacket Raw packet to set |
128 | | * @param[in] freeRawPacket A flag indicating if the destructor should also call the raw packet destructor or not |
129 | | * @param[in] parseUntil Parse the packet until it reaches this protocol. Can be useful for cases when you need to parse only up to a certain layer and want to avoid the |
130 | | * performance impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means don't take this parameter into account |
131 | | * @param[in] parseUntilLayer Parse the packet until certain layer in OSI model. Can be useful for cases when you need to parse only up to a certain layer and want to avoid the |
132 | | * performance impact and memory consumption of parsing the whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter into account |
133 | | */ |
134 | | void setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); |
135 | | |
136 | | /** |
137 | | * Get a pointer to the Packet's RawPacket in a read-only manner |
138 | | * @return A pointer to the Packet's RawPacket |
139 | | */ |
140 | | RawPacket* getRawPacketReadOnly() const { return m_RawPacket; } |
141 | | |
142 | | /** |
143 | | * Get a pointer to the first (lowest) layer in the packet |
144 | | * @return A pointer to the first (lowest) layer in the packet |
145 | | */ |
146 | | Layer* getFirstLayer() const { return m_FirstLayer; } |
147 | | |
148 | | /** |
149 | | * Get a pointer to the last (highest) layer in the packet |
150 | | * @return A pointer to the last (highest) layer in the packet |
151 | | */ |
152 | | Layer* getLastLayer() const { return m_LastLayer; } |
153 | | |
154 | | /** |
155 | | * Add a new layer as the last layer in the packet. This method gets a pointer to the new layer as a parameter |
156 | | * and attaches it to the packet. Notice after calling this method the input layer is attached to the packet so |
157 | | * every change you make in it affect the packet; Also it cannot be attached to other packets |
158 | | * @param[in] newLayer A pointer to the new layer to be added to the packet |
159 | | * @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default is false. |
160 | | * @return True if everything went well or false otherwise (an appropriate error log message will be printed in |
161 | | * such cases) |
162 | | */ |
163 | 0 | bool addLayer(Layer* newLayer, bool ownInPacket = false) { return insertLayer(m_LastLayer, newLayer, ownInPacket); } |
164 | | |
165 | | /** |
166 | | * Insert a new layer after an existing layer in the packet. This method gets a pointer to the new layer as a |
167 | | * parameter and attaches it to the packet. Notice after calling this method the input layer is attached to the |
168 | | * packet so every change you make in it affect the packet; Also it cannot be attached to other packets |
169 | | * @param[in] prevLayer A pointer to an existing layer in the packet which the new layer should followed by. If |
170 | | * this layer isn't attached to a packet and error will be printed to log and false will be returned |
171 | | * @param[in] newLayer A pointer to the new layer to be added to the packet |
172 | | * @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default is false. |
173 | | * @return True if everything went well or false otherwise (an appropriate error log message will be printed in |
174 | | * such cases) |
175 | | */ |
176 | | bool insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket = false); |
177 | | |
178 | | |
179 | | /** |
180 | | * Remove an existing layer from the packet. The layer to removed is identified by its type (protocol). If the |
181 | | * packet has multiple layers of the same type in the packet the user may specify the index of the layer to remove |
182 | | * (the default index is 0 - remove the first layer of this type). If the layer was allocated during packet creation |
183 | | * it will be deleted and any pointer to it will get invalid. However if the layer was allocated by the user and |
184 | | * manually added to the packet it will simply get detached from the packet, meaning the pointer to it will stay |
185 | | * valid and its data (that was removed from the packet) will be copied back to the layer. In that case it's |
186 | | * the user's responsibility to delete the layer instance |
187 | | * @param[in] layerType The layer type (protocol) to remove |
188 | | * @param[in] index If there are multiple layers of the same type, indicate which instance to remove. The default |
189 | | * value is 0, meaning remove the first layer of this type |
190 | | * @return True if everything went well or false otherwise (an appropriate error log message will be printed in |
191 | | * such cases) |
192 | | */ |
193 | | bool removeLayer(ProtocolType layerType, int index = 0); |
194 | | |
195 | | /** |
196 | | * Remove the first layer in the packet. The layer will be deleted if it was allocated during packet creation, or detached |
197 | | * if was allocated outside of the packet. Please refer to removeLayer() to get more info |
198 | | * @return True if layer removed successfully, or false if removing the layer failed or if there are no layers in the |
199 | | * packet. In any case of failure an appropriate error log message will be printed |
200 | | */ |
201 | | bool removeFirstLayer(); |
202 | | |
203 | | /** |
204 | | * Remove the last layer in the packet. The layer will be deleted if it was allocated during packet creation, or detached |
205 | | * if was allocated outside of the packet. Please refer to removeLayer() to get more info |
206 | | * @return True if layer removed successfully, or false if removing the layer failed or if there are no layers in the |
207 | | * packet. In any case of failure an appropriate error log message will be printed |
208 | | */ |
209 | | bool removeLastLayer(); |
210 | | |
211 | | /** |
212 | | * Remove all layers that come after a certain layer. All layers removed will be deleted if they were allocated during |
213 | | * packet creation or detached if were allocated outside of the packet, please refer to removeLayer() to get more info |
214 | | * @param[in] layer A pointer to the layer to begin removing from. Please note this layer will not be removed, only the |
215 | | * layers that come after it will be removed. Also, if removal of one layer failed, the method will return immediately and |
216 | | * the following layers won't be deleted |
217 | | * @return True if all layers were removed successfully, or false if failed to remove at least one layer. In any case of |
218 | | * failure an appropriate error log message will be printed |
219 | | */ |
220 | | bool removeAllLayersAfter(Layer* layer); |
221 | | |
222 | | /** |
223 | | * Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated from the |
224 | | * packet - e.g it will be removed from the layer chain of the packet and its data will be copied from the packet buffer |
225 | | * into an internal layer buffer. After a layer is detached, it can be added into another packet (but it's impossible to |
226 | | * attach a layer to multiple packets in the same time). After layer is detached, it's the user's responsibility to |
227 | | * delete it when it's not needed anymore |
228 | | * @param[in] layerType The layer type (protocol) to detach from the packet |
229 | | * @param[in] index If there are multiple layers of the same type, indicate which instance to detach. The default |
230 | | * value is 0, meaning detach the first layer of this type |
231 | | * @return A pointer to the detached layer or NULL if detaching process failed. In any case of failure an |
232 | | * appropriate error log message will be printed |
233 | | */ |
234 | | Layer* detachLayer(ProtocolType layerType, int index = 0); |
235 | | |
236 | | /** |
237 | | * Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated from the |
238 | | * packet - e.g it will be removed from the layer chain of the packet and its data will be copied from the packet buffer |
239 | | * into an internal layer buffer. After a layer is detached, it can be added into another packet (but it's impossible to |
240 | | * attach a layer to multiple packets at the same time). After layer is detached, it's the user's responsibility to |
241 | | * delete it when it's not needed anymore |
242 | | * @param[in] layer A pointer to the layer to detach |
243 | | * @return True if the layer was detached successfully, or false if something went wrong. In any case of failure an |
244 | | * appropriate error log message will be printed |
245 | | */ |
246 | | bool detachLayer(Layer* layer) { return removeLayer(layer, false); } |
247 | | |
248 | | /** |
249 | | * Get a pointer to the layer of a certain type (protocol). This method goes through the layers and returns a layer |
250 | | * that matches the give protocol type |
251 | | * @param[in] layerType The layer type (protocol) to fetch |
252 | | * @param[in] index If there are multiple layers of the same type, indicate which instance to fetch. The default |
253 | | * value is 0, meaning fetch the first layer of this type |
254 | | * @return A pointer to the layer or NULL if no such layer was found |
255 | | */ |
256 | | Layer* getLayerOfType(ProtocolType layerType, int index = 0) const; |
257 | | |
258 | | /** |
259 | | * A templated method to get a layer of a certain type (protocol). If no layer of such type is found, NULL is returned |
260 | | * @param[in] reverseOrder The optional parameter that indicates that the lookup should run in reverse order, the default value is false |
261 | | * @return A pointer to the layer of the requested type, NULL if not found |
262 | | */ |
263 | | template<class TLayer> |
264 | | TLayer* getLayerOfType(bool reverseOrder = false) const; |
265 | | |
266 | | /** |
267 | | * A templated method to get the first layer of a certain type (protocol), start searching from a certain layer. |
268 | | * For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) -> IPv4Layer |
269 | | * and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(3) will be returned |
270 | | * If no layer of such type is found, NULL is returned |
271 | | * @param[in] startLayer A pointer to the layer to start search from |
272 | | * @return A pointer to the layer of the requested type, NULL if not found |
273 | | */ |
274 | | template<class TLayer> |
275 | | TLayer* getNextLayerOfType(Layer* startLayer) const; |
276 | | |
277 | | /** |
278 | | * A templated method to get the first layer of a certain type (protocol), start searching from a certain layer. |
279 | | * For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) -> IPv4Layer |
280 | | * and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(1) will be returned |
281 | | * If no layer of such type is found, NULL is returned |
282 | | * @param[in] startLayer A pointer to the layer to start search from |
283 | | * @return A pointer to the layer of the requested type, NULL if not found |
284 | | */ |
285 | | template<class TLayer> |
286 | | TLayer* getPrevLayerOfType(Layer* startLayer) const; |
287 | | |
288 | | /** |
289 | | * Check whether the packet contains a certain protocol |
290 | | * @param[in] protocolType The protocol type to search |
291 | | * @return True if the packet contains the protocol, false otherwise |
292 | | */ |
293 | | bool isPacketOfType(ProtocolType protocolType) const { return m_ProtocolTypes & protocolType; } |
294 | | |
295 | | /** |
296 | | * Each layer can have fields that can be calculate automatically from other fields using Layer#computeCalculateFields(). This method forces all layers to calculate these |
297 | | * fields values |
298 | | */ |
299 | | void computeCalculateFields(); |
300 | | |
301 | | /** |
302 | | * Each layer can print a string representation of the layer most important data using Layer#toString(). This method aggregates this string from all layers and |
303 | | * print it to a complete string containing all packet's relevant data |
304 | | * @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set to false |
305 | | * @return A string containing most relevant data from all layers (looks like the packet description in Wireshark) |
306 | | */ |
307 | | std::string toString(bool timeAsLocalTime = true) const; |
308 | | |
309 | | /** |
310 | | * Similar to toString(), but instead of one string it outputs a list of strings, one string for every layer |
311 | | * @param[out] result A string vector that will contain all strings |
312 | | * @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set to false |
313 | | */ |
314 | | void toStringList(std::vector<std::string>& result, bool timeAsLocalTime = true) const; |
315 | | |
316 | | private: |
317 | | void copyDataFrom(const Packet& other); |
318 | | |
319 | | void destructPacketData(); |
320 | | |
321 | | bool extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend); |
322 | | bool shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten); |
323 | | |
324 | | void reallocateRawData(size_t newSize); |
325 | | |
326 | | bool removeLayer(Layer* layer, bool tryToDelete); |
327 | | |
328 | | std::string printPacketInfo(bool timeAsLocalTime) const; |
329 | | |
330 | | Layer* createFirstLayer(LinkLayerType linkType); |
331 | | }; // class Packet |
332 | | |
333 | | |
334 | | // implementation of inline methods |
335 | | |
336 | | template<class TLayer> |
337 | | TLayer* Packet::getLayerOfType(bool reverse) const |
338 | 0 | { |
339 | 0 | if (!reverse) |
340 | 0 | { |
341 | 0 | if (dynamic_cast<TLayer*>(getFirstLayer()) != NULL) |
342 | 0 | return dynamic_cast<TLayer*>(getFirstLayer()); |
343 | | |
344 | 0 | return getNextLayerOfType<TLayer>(getFirstLayer()); |
345 | 0 | } |
346 | | |
347 | | // lookup in reverse order |
348 | 0 | if (dynamic_cast<TLayer*>(getLastLayer()) != NULL) |
349 | 0 | return dynamic_cast<TLayer*>(getLastLayer()); |
350 | | |
351 | 0 | return getPrevLayerOfType<TLayer>(getLastLayer()); |
352 | 0 | } Unexecuted instantiation: pcpp::TcpLayer* pcpp::Packet::getLayerOfType<pcpp::TcpLayer>(bool) const Unexecuted instantiation: pcpp::UdpLayer* pcpp::Packet::getLayerOfType<pcpp::UdpLayer>(bool) const Unexecuted instantiation: pcpp::IPv6Layer* pcpp::Packet::getLayerOfType<pcpp::IPv6Layer>(bool) const |
353 | | |
354 | | template<class TLayer> |
355 | | TLayer* Packet::getNextLayerOfType(Layer* curLayer) const |
356 | 0 | { |
357 | 0 | if (curLayer == NULL) |
358 | 0 | return NULL; |
359 | | |
360 | 0 | curLayer = curLayer->getNextLayer(); |
361 | 0 | while ((curLayer != NULL) && (dynamic_cast<TLayer*>(curLayer) == NULL)) |
362 | 0 | { |
363 | 0 | curLayer = curLayer->getNextLayer(); |
364 | 0 | } |
365 | |
|
366 | 0 | return dynamic_cast<TLayer*>(curLayer); |
367 | 0 | } Unexecuted instantiation: pcpp::TcpLayer* pcpp::Packet::getNextLayerOfType<pcpp::TcpLayer>(pcpp::Layer*) const Unexecuted instantiation: pcpp::UdpLayer* pcpp::Packet::getNextLayerOfType<pcpp::UdpLayer>(pcpp::Layer*) const Unexecuted instantiation: pcpp::IPv6Layer* pcpp::Packet::getNextLayerOfType<pcpp::IPv6Layer>(pcpp::Layer*) const |
368 | | |
369 | | template<class TLayer> |
370 | | TLayer* Packet::getPrevLayerOfType(Layer* curLayer) const |
371 | 0 | { |
372 | 0 | if (curLayer == NULL) |
373 | 0 | return NULL; |
374 | | |
375 | 0 | curLayer = curLayer->getPrevLayer(); |
376 | 0 | while (curLayer != NULL && dynamic_cast<TLayer*>(curLayer) == NULL) |
377 | 0 | { |
378 | 0 | curLayer = curLayer->getPrevLayer(); |
379 | 0 | } |
380 | |
|
381 | 0 | return dynamic_cast<TLayer*>(curLayer); |
382 | 0 | } Unexecuted instantiation: pcpp::TcpLayer* pcpp::Packet::getPrevLayerOfType<pcpp::TcpLayer>(pcpp::Layer*) const Unexecuted instantiation: pcpp::UdpLayer* pcpp::Packet::getPrevLayerOfType<pcpp::UdpLayer>(pcpp::Layer*) const Unexecuted instantiation: pcpp::IPv6Layer* pcpp::Packet::getPrevLayerOfType<pcpp::IPv6Layer>(pcpp::Layer*) const |
383 | | |
384 | | } // namespace pcpp |
385 | | |
386 | | inline std::ostream& operator<<(std::ostream& os, const pcpp::Packet& packet) |
387 | | { |
388 | | os << packet.toString(); |
389 | | return os; |
390 | | } |
391 | | |
392 | | #endif /* PACKETPP_PACKET */ |