/src/PcapPlusPlus/Packet++/src/Packet.cpp
Line | Count | Source |
1 | 141k | #define LOG_MODULE PacketLogModulePacket |
2 | | |
3 | | #include "Packet.h" |
4 | | #include "EthLayer.h" |
5 | | #include "EthDot3Layer.h" |
6 | | #include "SllLayer.h" |
7 | | #include "Sll2Layer.h" |
8 | | #include "NflogLayer.h" |
9 | | #include "NullLoopbackLayer.h" |
10 | | #include "IPv4Layer.h" |
11 | | #include "IPv6Layer.h" |
12 | | #include "CiscoHdlcLayer.h" |
13 | | #include "PayloadLayer.h" |
14 | | #include "PacketTrailerLayer.h" |
15 | | #include "Logger.h" |
16 | | #include <numeric> |
17 | | #include <sstream> |
18 | | #include <memory> |
19 | | #ifdef _MSC_VER |
20 | | # include <time.h> |
21 | | # include "SystemUtils.h" |
22 | | #endif |
23 | | |
24 | | namespace pcpp |
25 | | { |
26 | | |
27 | | Packet::Packet(size_t maxPacketLen, LinkLayerType linkType) |
28 | 0 | : m_RawPacket(nullptr), m_FirstLayer(nullptr), m_LastLayer(nullptr), m_MaxPacketLen(maxPacketLen), |
29 | 0 | m_FreeRawPacket(true), m_CanReallocateData(true) |
30 | 0 | { |
31 | 0 | timeval time; |
32 | 0 | gettimeofday(&time, nullptr); |
33 | 0 | uint8_t* data = new uint8_t[maxPacketLen]; |
34 | 0 | memset(data, 0, maxPacketLen); |
35 | 0 | m_RawPacket = new RawPacket(data, 0, time, true, linkType); |
36 | 0 | } |
37 | | |
38 | | Packet::Packet(uint8_t* buffer, size_t bufferSize, LinkLayerType linkType) |
39 | 0 | : m_RawPacket(nullptr), m_FirstLayer(nullptr), m_LastLayer(nullptr), m_MaxPacketLen(bufferSize), |
40 | 0 | m_FreeRawPacket(true), m_CanReallocateData(false) |
41 | 0 | { |
42 | 0 | timeval time; |
43 | 0 | gettimeofday(&time, nullptr); |
44 | 0 | memset(buffer, 0, bufferSize); |
45 | 0 | m_RawPacket = new RawPacket(buffer, 0, time, false, linkType); |
46 | 0 | } |
47 | | |
48 | | void Packet::setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil, |
49 | | OsiModelLayer parseUntilLayer) |
50 | 255k | { |
51 | 255k | destructPacketData(); |
52 | | |
53 | 255k | m_FirstLayer = nullptr; |
54 | 255k | m_LastLayer = nullptr; |
55 | 255k | m_MaxPacketLen = rawPacket->getRawDataLen(); |
56 | 255k | m_FreeRawPacket = freeRawPacket; |
57 | 255k | m_RawPacket = rawPacket; |
58 | 255k | m_CanReallocateData = true; |
59 | | |
60 | 255k | if (m_RawPacket == nullptr) |
61 | 0 | return; |
62 | | |
63 | 255k | parsePacket(PacketParseOptions{ parseUntil, parseUntilLayer }); |
64 | 255k | } |
65 | | |
66 | | void Packet::parsePacket(PacketParseOptions options, bool incrementalParsing) |
67 | 255k | { |
68 | 255k | if (m_RawPacket == nullptr) |
69 | 0 | { |
70 | 0 | throw std::runtime_error("Cannot parse packet: RawPacket is null"); |
71 | 0 | } |
72 | | |
73 | | // If we aren't doing an incremental parse, destroy all existing layers and start from scratch |
74 | 255k | if (!incrementalParsing) |
75 | 0 | { |
76 | 0 | destroyAllLayers(); |
77 | 0 | } |
78 | | |
79 | | // Flag indicating whether we are currently parsing new layers (as opposed to traversing already parsed ones). |
80 | 255k | bool parsingNewLayers = false; |
81 | | |
82 | | // If there is no first layer, create it based on the link layer type |
83 | 255k | if (m_FirstLayer == nullptr) |
84 | 255k | { |
85 | 255k | parsingNewLayers = true; |
86 | | |
87 | 255k | LinkLayerType linkType = m_RawPacket->getLinkLayerType(); |
88 | 255k | m_FirstLayer = createFirstLayer(linkType); |
89 | | |
90 | 255k | if (m_FirstLayer == nullptr) |
91 | 3.41k | { |
92 | 3.41k | PCPP_LOG_ERROR("Failed to create first layer! Possibly attempting to parse a RawPacket with no data."); |
93 | 3.41k | return; |
94 | 3.41k | } |
95 | | |
96 | | // Mark the first layer as allocated in the packet |
97 | 251k | m_FirstLayer->m_AllocationInfo.ownedByPacket = true; |
98 | 251k | } |
99 | | |
100 | 251k | Layer* parseStartLayer = m_FirstLayer; |
101 | | |
102 | | // Fast path: |
103 | | // If we are doing an incremental parse and we are not searching for a specific protocol type, |
104 | | // we can directly start from the last parsed layer. |
105 | 251k | if (m_LastLayer != nullptr && options.parseUntilProtocol == UnknownProtocol) |
106 | 0 | { |
107 | | // NOTE: Potential edge case, PacketTrailerLayer is considered DataLinkLayer. |
108 | | // If the user requested a higher OSI layer, this condition would not skip the parse. |
109 | | // The parse should still do nothing, as the trailer layer doesn't have a next layer, |
110 | | // but it will have to go through 1 extra iteration. |
111 | 0 | if (m_LastLayer->getOsiModelLayer() > options.parseUntilLayer) |
112 | 0 | { |
113 | | // Already past the OSI target layer, nothing to do |
114 | 0 | return; |
115 | 0 | } |
116 | | |
117 | 0 | parseStartLayer = m_LastLayer; |
118 | 0 | } |
119 | | |
120 | | // As the stop conditions are inclusive, the parse must go one layer further and then roll back if needed |
121 | 251k | bool rollbackLastLayer = false; |
122 | 251k | bool foundTargetProtocol = false; |
123 | 1.26M | for (auto* curLayer = parseStartLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
124 | 1.01M | { |
125 | | // If we are parsing new layers, update the last layer pointer |
126 | | // Otherwise we are just traversing already parsed layers |
127 | 1.01M | if (parsingNewLayers) |
128 | 1.01M | { |
129 | | // Mark the current layer as allocated in the packet, as it was just created |
130 | 1.01M | curLayer->m_AllocationInfo.ownedByPacket = true; |
131 | 1.01M | m_LastLayer = curLayer; |
132 | 1.01M | } |
133 | | |
134 | | // If the current layer is of a higher OSI layer than the target, stop parsing |
135 | 1.01M | if (curLayer->getOsiModelLayer() > options.parseUntilLayer) |
136 | 0 | { |
137 | | // If we are traversing already parsed layers, we don't want to roll back as they must be kept as is. |
138 | 0 | rollbackLastLayer = parsingNewLayers; |
139 | 0 | break; |
140 | 0 | } |
141 | | |
142 | | // If we are searching for a specific layer protocol, record when we find at least one target. |
143 | 1.01M | const bool matchesTarget = curLayer->isMemberOfProtocolFamily(options.parseUntilProtocol); |
144 | 1.01M | if (options.parseUntilProtocol != UnknownProtocol && matchesTarget) |
145 | 0 | { |
146 | 0 | foundTargetProtocol = true; |
147 | 0 | } |
148 | | |
149 | | // If we have found the target protocol already, we are parsing until we find a different protocol |
150 | 1.01M | if (foundTargetProtocol && !matchesTarget) |
151 | 0 | { |
152 | | // If we are traversing already parsed layers, we don't want to roll back as they must be kept as is. |
153 | 0 | rollbackLastLayer = parsingNewLayers; |
154 | 0 | break; |
155 | 0 | } |
156 | | |
157 | | // If the current layer doesn't have a next layer yet, parse it. |
158 | | // This is important for the case of a re-parse where some layers may already have been parsed |
159 | 1.01M | if (!curLayer->hasNextLayer()) |
160 | 1.01M | { |
161 | 1.01M | parsingNewLayers = true; // We are now parsing new layers. |
162 | | |
163 | | // Parse the next layer. This will update the next layer pointer of the current layer. |
164 | 1.01M | curLayer->parseNextLayer(); |
165 | 1.01M | } |
166 | 1.01M | } |
167 | | |
168 | | // Roll back one layer, if parsing with search condition as the conditions are inclusive. |
169 | | // Don't delete the first layer. If already past the target layer, treat the same as if the layer was found. |
170 | 251k | if (rollbackLastLayer && m_LastLayer != m_FirstLayer) |
171 | 0 | { |
172 | 0 | m_LastLayer = m_LastLayer->getPrevLayer(); |
173 | 0 | delete m_LastLayer->m_NextLayer; |
174 | 0 | m_LastLayer->m_NextLayer = nullptr; |
175 | 0 | } |
176 | | |
177 | | // If there is data left in the raw packet that doesn't belong to any layer, create a PacketTrailerLayer |
178 | 251k | if (m_LastLayer != nullptr && options.parseUntilProtocol == UnknownProtocol && |
179 | 251k | options.parseUntilLayer == OsiModelLayerUnknown) |
180 | 251k | { |
181 | | // find if there is data left in the raw packet that doesn't belong to any layer. In that case it's probably |
182 | | // a packet trailer. create a PacketTrailerLayer layer and add it at the end of the packet |
183 | 251k | int trailerLen = (int)((m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) - |
184 | 251k | (m_LastLayer->getData() + m_LastLayer->getDataLen())); |
185 | 251k | if (trailerLen > 0) |
186 | 23.9k | { |
187 | 23.9k | PacketTrailerLayer* trailerLayer = |
188 | 23.9k | new PacketTrailerLayer(static_cast<uint8_t*>(m_LastLayer->getData() + m_LastLayer->getDataLen()), |
189 | 23.9k | trailerLen, m_LastLayer, this); |
190 | | |
191 | 23.9k | trailerLayer->m_AllocationInfo.ownedByPacket = true; |
192 | 23.9k | m_LastLayer->setNextLayer(trailerLayer); |
193 | 23.9k | m_LastLayer = trailerLayer; |
194 | 23.9k | } |
195 | 251k | } |
196 | 251k | } |
197 | | |
198 | | Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) |
199 | 255k | { |
200 | 255k | m_FreeRawPacket = false; |
201 | 255k | m_RawPacket = nullptr; |
202 | 255k | m_FirstLayer = nullptr; |
203 | 255k | setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer); |
204 | 255k | } |
205 | | |
206 | | Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil) |
207 | 0 | { |
208 | 0 | m_FreeRawPacket = false; |
209 | 0 | m_RawPacket = nullptr; |
210 | 0 | m_FirstLayer = nullptr; |
211 | 0 | auto parseUntilFamily = static_cast<ProtocolTypeFamily>(parseUntil); |
212 | 0 | setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); |
213 | 0 | } |
214 | | |
215 | | Packet::Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily) |
216 | 0 | { |
217 | 0 | m_FreeRawPacket = false; |
218 | 0 | m_RawPacket = nullptr; |
219 | 0 | m_FirstLayer = nullptr; |
220 | 0 | setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); |
221 | 0 | } |
222 | | |
223 | | Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer) |
224 | 0 | { |
225 | 0 | m_FreeRawPacket = false; |
226 | 0 | m_RawPacket = nullptr; |
227 | 0 | m_FirstLayer = nullptr; |
228 | 0 | setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer); |
229 | 0 | } |
230 | | |
231 | | void Packet::destructPacketData() |
232 | 1.54M | { |
233 | 1.54M | destroyAllLayers(); |
234 | | |
235 | 1.54M | if (m_RawPacket != nullptr && m_FreeRawPacket) |
236 | 1.03M | { |
237 | 1.03M | delete m_RawPacket; |
238 | 1.03M | } |
239 | 1.54M | } |
240 | | |
241 | | void Packet::destroyAllLayers() |
242 | 1.54M | { |
243 | 1.54M | Layer* curLayer = m_FirstLayer; |
244 | 8.13M | while (curLayer != nullptr) |
245 | 6.59M | { |
246 | 6.59M | Layer* nextLayer = curLayer->getNextLayer(); |
247 | 6.59M | if (curLayer->m_AllocationInfo.ownedByPacket) |
248 | 6.59M | { |
249 | 6.59M | delete curLayer; |
250 | 6.59M | } |
251 | | |
252 | 6.59M | curLayer = nextLayer; |
253 | 6.59M | } |
254 | | |
255 | 1.54M | m_FirstLayer = nullptr; |
256 | 1.54M | m_LastLayer = nullptr; |
257 | 1.54M | } |
258 | | |
259 | | Packet& Packet::operator=(const Packet& other) |
260 | 0 | { |
261 | 0 | destructPacketData(); |
262 | |
|
263 | 0 | copyDataFrom(other); |
264 | |
|
265 | 0 | return *this; |
266 | 0 | } |
267 | | |
268 | | void Packet::copyDataFrom(const Packet& other) |
269 | 1.03M | { |
270 | 1.03M | m_RawPacket = new RawPacket(*(other.m_RawPacket)); |
271 | 1.03M | m_FreeRawPacket = true; |
272 | 1.03M | m_MaxPacketLen = other.m_MaxPacketLen; |
273 | 1.03M | m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType()); |
274 | 1.03M | m_LastLayer = m_FirstLayer; |
275 | 1.03M | m_CanReallocateData = true; |
276 | 1.03M | Layer* curLayer = m_FirstLayer; |
277 | 6.59M | while (curLayer != nullptr) |
278 | 5.55M | { |
279 | 5.55M | curLayer->parseNextLayer(); |
280 | 5.55M | curLayer->m_AllocationInfo.ownedByPacket = true; |
281 | 5.55M | curLayer = curLayer->getNextLayer(); |
282 | 5.55M | if (curLayer != nullptr) |
283 | 4.51M | m_LastLayer = curLayer; |
284 | 5.55M | } |
285 | 1.03M | } |
286 | | |
287 | | void Packet::reallocateRawData(size_t newSize) |
288 | 25.7k | { |
289 | 25.7k | PCPP_LOG_DEBUG("Allocating packet to new size: " << newSize); |
290 | | |
291 | | // allocate a new array with size newSize |
292 | 25.7k | m_MaxPacketLen = newSize; |
293 | | |
294 | | // set the new array to RawPacket |
295 | 25.7k | if (!m_RawPacket->reallocateData(m_MaxPacketLen)) |
296 | 0 | { |
297 | 0 | PCPP_LOG_ERROR("Couldn't reallocate data of raw packet to " << m_MaxPacketLen << " bytes"); |
298 | 0 | return; |
299 | 0 | } |
300 | | |
301 | | // set all data pointers in layers to the new array address |
302 | 25.7k | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
303 | | |
304 | 132k | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
305 | 106k | { |
306 | 106k | PCPP_LOG_DEBUG("Setting new data pointer to layer '" << typeid(curLayer).name() << "'"); |
307 | 106k | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
308 | 106k | dataPtr += curLayer->getHeaderLen(); |
309 | 106k | } |
310 | 25.7k | } |
311 | | |
312 | | bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket) |
313 | 0 | { |
314 | 0 | if (newLayer == nullptr) |
315 | 0 | { |
316 | 0 | PCPP_LOG_ERROR("Layer to add is nullptr"); |
317 | 0 | return false; |
318 | 0 | } |
319 | | |
320 | 0 | if (newLayer->isAllocatedToPacket()) |
321 | 0 | { |
322 | 0 | PCPP_LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet"); |
323 | 0 | return false; |
324 | 0 | } |
325 | | |
326 | 0 | if (prevLayer != nullptr && prevLayer->getProtocol() == PacketTrailer) |
327 | 0 | { |
328 | 0 | PCPP_LOG_ERROR("Cannot insert layer after packet trailer"); |
329 | 0 | return false; |
330 | 0 | } |
331 | | |
332 | 0 | size_t newLayerHeaderLen = newLayer->getHeaderLen(); |
333 | 0 | if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen) |
334 | 0 | { |
335 | 0 | if (!m_CanReallocateData) |
336 | 0 | { |
337 | 0 | PCPP_LOG_ERROR("With the new layer the packet will exceed the size of the pre-allocated buffer: " |
338 | 0 | << m_MaxPacketLen << " bytes"); |
339 | 0 | return false; |
340 | 0 | } |
341 | | // reallocate to maximum value of: twice the max size of the packet or max size + new required length |
342 | 0 | if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen * 2) |
343 | 0 | reallocateRawData(m_RawPacket->getRawDataLen() + newLayerHeaderLen + m_MaxPacketLen); |
344 | 0 | else |
345 | 0 | reallocateRawData(m_MaxPacketLen * 2); |
346 | 0 | } |
347 | | |
348 | | // insert layer data to raw packet |
349 | 0 | int indexToInsertData = 0; |
350 | 0 | if (prevLayer != nullptr) |
351 | 0 | indexToInsertData = prevLayer->m_Data + prevLayer->getHeaderLen() - m_RawPacket->getRawData(); |
352 | 0 | m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, newLayerHeaderLen); |
353 | | |
354 | | // delete previous layer data |
355 | 0 | delete[] newLayer->m_Data; |
356 | | |
357 | | // add layer to layers linked list |
358 | 0 | if (prevLayer != nullptr) |
359 | 0 | { |
360 | 0 | newLayer->setNextLayer(prevLayer->getNextLayer()); |
361 | 0 | newLayer->setPrevLayer(prevLayer); |
362 | 0 | prevLayer->setNextLayer(newLayer); |
363 | 0 | } |
364 | 0 | else // prevLayer == nullptr |
365 | 0 | { |
366 | 0 | newLayer->setNextLayer(m_FirstLayer); |
367 | 0 | if (m_FirstLayer != nullptr) |
368 | 0 | m_FirstLayer->setPrevLayer(newLayer); |
369 | 0 | m_FirstLayer = newLayer; |
370 | 0 | } |
371 | |
|
372 | 0 | if (newLayer->getNextLayer() == nullptr) |
373 | 0 | m_LastLayer = newLayer; |
374 | 0 | else |
375 | 0 | newLayer->getNextLayer()->setPrevLayer(newLayer); |
376 | | |
377 | | // Attach the layer to this packet. If ownInPacket is true, transfer ownership of the layer to the packet. |
378 | 0 | newLayer->m_AllocationInfo.attachPacket(this, ownInPacket); |
379 | | |
380 | | // re-calculate all layers data ptr and data length |
381 | | |
382 | | // first, get ptr and data length of the raw packet |
383 | 0 | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
384 | 0 | size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen()); |
385 | | |
386 | | // if a packet trailer exists, get its length |
387 | 0 | size_t packetTrailerLen = 0; |
388 | 0 | if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer) |
389 | 0 | packetTrailerLen = m_LastLayer->getDataLen(); |
390 | | |
391 | | // go over all layers from the first layer to the last layer and set the data ptr and data length for each one |
392 | 0 | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
393 | 0 | { |
394 | | // set data ptr to layer |
395 | 0 | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
396 | | |
397 | | // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers. |
398 | | // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the |
399 | | // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data |
400 | | // length |
401 | 0 | if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer) |
402 | 0 | curLayer->m_DataLen = dataLen; |
403 | 0 | else |
404 | 0 | curLayer->m_DataLen = dataLen - packetTrailerLen; |
405 | | |
406 | | // advance data ptr and data length |
407 | 0 | dataPtr += curLayer->getHeaderLen(); |
408 | 0 | dataLen -= curLayer->getHeaderLen(); |
409 | 0 | } |
410 | |
|
411 | 0 | return true; |
412 | 0 | } |
413 | | |
414 | | bool Packet::removeLayer(ProtocolType layerType, int index) |
415 | 0 | { |
416 | 0 | Layer* layerToRemove = getLayerOfType(layerType, index); |
417 | |
|
418 | 0 | if (layerToRemove != nullptr) |
419 | 0 | { |
420 | 0 | return removeLayer(layerToRemove, true); |
421 | 0 | } |
422 | 0 | else |
423 | 0 | { |
424 | 0 | PCPP_LOG_ERROR("Layer of the requested type was not found in packet"); |
425 | 0 | return false; |
426 | 0 | } |
427 | 0 | } |
428 | | |
429 | | bool Packet::removeFirstLayer() |
430 | 0 | { |
431 | 0 | Layer* firstLayer = getFirstLayer(); |
432 | 0 | if (firstLayer == nullptr) |
433 | 0 | { |
434 | 0 | PCPP_LOG_ERROR("Packet has no layers"); |
435 | 0 | return false; |
436 | 0 | } |
437 | | |
438 | 0 | return removeLayer(firstLayer, true); |
439 | 0 | } |
440 | | |
441 | | bool Packet::removeLastLayer() |
442 | 0 | { |
443 | 0 | Layer* lastLayer = getLastLayer(); |
444 | 0 | if (lastLayer == nullptr) |
445 | 0 | { |
446 | 0 | PCPP_LOG_ERROR("Packet has no layers"); |
447 | 0 | return false; |
448 | 0 | } |
449 | | |
450 | 0 | return removeLayer(lastLayer, true); |
451 | 0 | } |
452 | | |
453 | | bool Packet::removeAllLayersAfter(Layer* layer) |
454 | 0 | { |
455 | 0 | Layer* curLayer = layer->getNextLayer(); |
456 | 0 | while (curLayer != nullptr) |
457 | 0 | { |
458 | 0 | Layer* tempLayer = curLayer->getNextLayer(); |
459 | 0 | if (!removeLayer(curLayer, true)) |
460 | 0 | return false; |
461 | 0 | curLayer = tempLayer; |
462 | 0 | } |
463 | | |
464 | 0 | return true; |
465 | 0 | } |
466 | | |
467 | | Layer* Packet::detachLayer(ProtocolType layerType, int index) |
468 | 0 | { |
469 | 0 | Layer* layerToDetach = getLayerOfType(layerType, index); |
470 | |
|
471 | 0 | if (layerToDetach != nullptr) |
472 | 0 | { |
473 | 0 | if (removeLayer(layerToDetach, false)) |
474 | 0 | return layerToDetach; |
475 | 0 | else |
476 | 0 | return nullptr; |
477 | 0 | } |
478 | 0 | else |
479 | 0 | { |
480 | 0 | PCPP_LOG_ERROR("Layer of the requested type was not found in packet"); |
481 | 0 | return nullptr; |
482 | 0 | } |
483 | 0 | } |
484 | | |
485 | | bool Packet::removeLayer(Layer* layer, bool tryToDelete) |
486 | 0 | { |
487 | 0 | if (layer == nullptr) |
488 | 0 | { |
489 | 0 | PCPP_LOG_ERROR("Layer is nullptr"); |
490 | 0 | return false; |
491 | 0 | } |
492 | | |
493 | | // verify layer is allocated to a packet |
494 | 0 | if (!layer->isAllocatedToPacket()) |
495 | 0 | { |
496 | 0 | PCPP_LOG_ERROR("Layer isn't allocated to any packet"); |
497 | 0 | return false; |
498 | 0 | } |
499 | | |
500 | | // verify layer is allocated to *this* packet |
501 | 0 | Layer* curLayer = layer; |
502 | 0 | while (curLayer->m_PrevLayer != nullptr) |
503 | 0 | curLayer = curLayer->m_PrevLayer; |
504 | 0 | if (curLayer != m_FirstLayer) |
505 | 0 | { |
506 | 0 | PCPP_LOG_ERROR("Layer isn't allocated to this packet"); |
507 | 0 | return false; |
508 | 0 | } |
509 | | |
510 | | // before removing the layer's data, copy it so it can be later assigned as the removed layer's data |
511 | 0 | size_t headerLen = layer->getHeaderLen(); |
512 | 0 | size_t layerOldDataSize = headerLen; |
513 | 0 | auto layerOldData = std::make_unique<uint8_t[]>(layerOldDataSize); |
514 | 0 | memcpy(layerOldData.get(), layer->m_Data, layerOldDataSize); |
515 | | |
516 | | // remove data from raw packet |
517 | 0 | size_t numOfBytesToRemove = headerLen; |
518 | 0 | int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData(); |
519 | 0 | if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove)) |
520 | 0 | { |
521 | 0 | PCPP_LOG_ERROR("Couldn't remove data from packet"); |
522 | 0 | return false; |
523 | 0 | } |
524 | | |
525 | | // remove layer from layers linked list |
526 | 0 | if (layer->m_PrevLayer != nullptr) |
527 | 0 | layer->m_PrevLayer->setNextLayer(layer->m_NextLayer); |
528 | 0 | if (layer->m_NextLayer != nullptr) |
529 | 0 | layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer); |
530 | | |
531 | | // take care of head and tail ptrs |
532 | 0 | if (m_FirstLayer == layer) |
533 | 0 | m_FirstLayer = layer->m_NextLayer; |
534 | 0 | if (m_LastLayer == layer) |
535 | 0 | m_LastLayer = layer->m_PrevLayer; |
536 | 0 | layer->setNextLayer(nullptr); |
537 | 0 | layer->setPrevLayer(nullptr); |
538 | | |
539 | | // get packet trailer len if exists |
540 | 0 | size_t packetTrailerLen = 0; |
541 | 0 | if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer) |
542 | 0 | packetTrailerLen = m_LastLayer->getDataLen(); |
543 | | |
544 | | // re-calculate all layers data ptr and data length |
545 | | |
546 | | // first, get ptr and data length of the raw packet |
547 | 0 | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
548 | 0 | size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen()); |
549 | |
|
550 | 0 | curLayer = m_FirstLayer; |
551 | | |
552 | | // go over all layers from the first layer to the last layer and set the data ptr and data length for each one |
553 | 0 | while (curLayer != nullptr) |
554 | 0 | { |
555 | | // set data ptr to layer |
556 | 0 | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
557 | | |
558 | | // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers. |
559 | | // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the |
560 | | // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data |
561 | | // length |
562 | 0 | if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer) |
563 | 0 | curLayer->m_DataLen = dataLen; |
564 | 0 | else |
565 | 0 | curLayer->m_DataLen = dataLen - packetTrailerLen; |
566 | | |
567 | | // advance data ptr and data length |
568 | 0 | dataPtr += curLayer->getHeaderLen(); |
569 | 0 | dataLen -= curLayer->getHeaderLen(); |
570 | | |
571 | | // move to next layer |
572 | 0 | curLayer = curLayer->getNextLayer(); |
573 | 0 | } |
574 | | |
575 | | // if layer was allocated by this packet and tryToDelete flag is set, delete it |
576 | 0 | if (tryToDelete && layer->m_AllocationInfo.ownedByPacket) |
577 | 0 | { |
578 | 0 | delete layer; |
579 | 0 | } |
580 | | // if layer was not allocated by this packet or the tryToDelete is not set, detach it from the packet so it can |
581 | | // be reused |
582 | 0 | else |
583 | 0 | { |
584 | 0 | layer->m_AllocationInfo.detach(); |
585 | 0 | layer->m_Data = layerOldData.release(); |
586 | 0 | layer->m_DataLen = layerOldDataSize; |
587 | 0 | } |
588 | |
|
589 | 0 | return true; |
590 | 0 | } |
591 | | |
592 | | Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const |
593 | 0 | { |
594 | 0 | int curIndex = 0; |
595 | 0 | for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
596 | 0 | { |
597 | 0 | if (curLayer->getProtocol() != layerType) |
598 | 0 | continue; |
599 | | |
600 | 0 | if (curIndex == index) |
601 | 0 | return curLayer; |
602 | | |
603 | 0 | curIndex++; |
604 | 0 | } |
605 | | |
606 | 0 | return nullptr; |
607 | 0 | } |
608 | | |
609 | | bool Packet::isPacketOfType(ProtocolType protocolType) const |
610 | 17.6M | { |
611 | 110M | for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
612 | 93.5M | { |
613 | 93.5M | if (curLayer->getProtocol() == protocolType) |
614 | 1.08M | { |
615 | 1.08M | return true; |
616 | 1.08M | } |
617 | 93.5M | } |
618 | | |
619 | 16.5M | return false; |
620 | 17.6M | } |
621 | | |
622 | | bool Packet::isPacketOfType(ProtocolTypeFamily protocolTypeFamily) const |
623 | 4.14M | { |
624 | 4.14M | Layer* curLayer = getFirstLayer(); |
625 | 26.2M | while (curLayer != nullptr) |
626 | 22.1M | { |
627 | 22.1M | if (curLayer->isMemberOfProtocolFamily(protocolTypeFamily)) |
628 | 50.4k | { |
629 | 50.4k | return true; |
630 | 50.4k | } |
631 | 22.1M | curLayer = curLayer->getNextLayer(); |
632 | 22.1M | } |
633 | | |
634 | 4.09M | return false; |
635 | 4.14M | } |
636 | | |
637 | | bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend) |
638 | 98.1k | { |
639 | 98.1k | if (layer == nullptr) |
640 | 0 | { |
641 | 0 | PCPP_LOG_ERROR("Layer is nullptr"); |
642 | 0 | return false; |
643 | 0 | } |
644 | | |
645 | | // verify layer is allocated to this packet |
646 | 98.1k | if (!(layer->getAttachedPacket() == this)) |
647 | 0 | { |
648 | 0 | PCPP_LOG_ERROR("Layer isn't allocated to this packet"); |
649 | 0 | return false; |
650 | 0 | } |
651 | | |
652 | 98.1k | if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen) |
653 | 25.7k | { |
654 | 25.7k | if (!m_CanReallocateData) |
655 | 0 | { |
656 | 0 | PCPP_LOG_ERROR( |
657 | 0 | "With the layer extended size the packet will exceed the size of the pre-allocated buffer: " |
658 | 0 | << m_MaxPacketLen << " bytes"); |
659 | 0 | return false; |
660 | 0 | } |
661 | | // reallocate to maximum value of: twice the max size of the packet or max size + new required length |
662 | 25.7k | if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen * 2) |
663 | 19 | reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen); |
664 | 25.7k | else |
665 | 25.7k | reallocateRawData(m_MaxPacketLen * 2); |
666 | 25.7k | } |
667 | | |
668 | | // insert layer data to raw packet |
669 | 98.1k | int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData(); |
670 | | // passing nullptr to insertData will move the data by numOfBytesToExtend |
671 | | // no new data has to be created for this insertion which saves at least little time |
672 | | // this move operation occurs on already allocated memory, which is backed by the reallocation if's provided |
673 | | // above if offsetInLayer == layer->getHeaderLen() insertData will not move any data but only increase the |
674 | | // packet size by numOfBytesToExtend |
675 | 98.1k | m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend); |
676 | | |
677 | | // re-calculate all layers data ptr and data length |
678 | 98.1k | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
679 | | |
680 | | // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer |
681 | 98.1k | bool passedExtendedLayer = false; |
682 | 504k | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
683 | 407k | { |
684 | 407k | if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) |
685 | 1.20k | { |
686 | 1.20k | PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary"); |
687 | 1.20k | return false; |
688 | 1.20k | } |
689 | | |
690 | | // set the data ptr |
691 | 405k | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
692 | | |
693 | | // set a flag if arrived to the layer being extended |
694 | 405k | if (curLayer->getPrevLayer() == layer) |
695 | 7.48k | passedExtendedLayer = true; |
696 | | |
697 | | // change the data length only for layers who come before the extended layer. For layers who come after, |
698 | | // data length isn't changed |
699 | 405k | if (!passedExtendedLayer) |
700 | 396k | curLayer->m_DataLen += numOfBytesToExtend; |
701 | | |
702 | | // assuming header length of the layer that requested to be extended hasn't been enlarged yet |
703 | 405k | size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0); |
704 | 405k | dataPtr += headerLen; |
705 | 405k | } |
706 | | |
707 | 96.9k | return true; |
708 | 98.1k | } |
709 | | |
710 | | bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten) |
711 | 98.6k | { |
712 | 98.6k | if (layer == nullptr) |
713 | 0 | { |
714 | 0 | PCPP_LOG_ERROR("Layer is nullptr"); |
715 | 0 | return false; |
716 | 0 | } |
717 | | |
718 | | // verify layer is allocated to this packet |
719 | 98.6k | if (!(layer->getAttachedPacket() == this)) |
720 | 0 | { |
721 | 0 | PCPP_LOG_ERROR("Layer isn't allocated to this packet"); |
722 | 0 | return false; |
723 | 0 | } |
724 | | |
725 | | // remove data from raw packet |
726 | 98.6k | int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData(); |
727 | 98.6k | if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten)) |
728 | 0 | { |
729 | 0 | PCPP_LOG_ERROR("Couldn't remove data from packet"); |
730 | 0 | return false; |
731 | 0 | } |
732 | | |
733 | | // re-calculate all layers data ptr and data length |
734 | 98.6k | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
735 | | |
736 | | // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer |
737 | 98.6k | Layer* curLayer = m_FirstLayer; |
738 | 98.6k | bool passedExtendedLayer = false; |
739 | 508k | while (curLayer != nullptr) |
740 | 409k | { |
741 | 409k | if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) |
742 | 125 | { |
743 | 125 | PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary"); |
744 | 125 | return false; |
745 | 125 | } |
746 | | |
747 | | // set the data ptr |
748 | 409k | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
749 | | |
750 | | // set a flag if arrived to the layer being shortened |
751 | 409k | if (curLayer->getPrevLayer() == layer) |
752 | 8.35k | passedExtendedLayer = true; |
753 | | |
754 | 409k | size_t headerLen = curLayer->getHeaderLen(); |
755 | | |
756 | | // change the data length only for layers who come before the shortened layer. For layers who come after, |
757 | | // data length isn't changed |
758 | 409k | if (!passedExtendedLayer) |
759 | 399k | curLayer->m_DataLen -= numOfBytesToShorten; |
760 | | |
761 | | // assuming header length of the layer that requested to be extended hasn't been enlarged yet |
762 | 409k | headerLen -= (curLayer == layer ? numOfBytesToShorten : 0); |
763 | 409k | dataPtr += headerLen; |
764 | 409k | curLayer = curLayer->getNextLayer(); |
765 | 409k | } |
766 | | |
767 | 98.5k | return true; |
768 | 98.6k | } |
769 | | |
770 | | void Packet::computeCalculateFields() |
771 | 255k | { |
772 | | // calculated fields should be calculated from top layer to bottom layer |
773 | 1.29M | for (Layer* curLayer = m_LastLayer; curLayer != nullptr; curLayer = curLayer->getPrevLayer()) |
774 | 1.03M | { |
775 | 1.03M | curLayer->computeCalculateFields(); |
776 | 1.03M | } |
777 | 255k | } |
778 | | |
779 | | std::string Packet::printPacketInfo(bool timeAsLocalTime) const |
780 | 255k | { |
781 | 255k | std::ostringstream dataLenStream; |
782 | 255k | dataLenStream << m_RawPacket->getRawDataLen(); |
783 | | |
784 | | // convert raw packet timestamp to printable format |
785 | 255k | timespec timestamp = m_RawPacket->getPacketTimeStamp(); |
786 | 255k | time_t nowtime = timestamp.tv_sec; |
787 | 255k | struct tm* nowtm = nullptr; |
788 | 255k | #if __cplusplus > 199711L && !defined(_WIN32) |
789 | | // localtime_r and gmtime_r are thread-safe versions of localtime and gmtime, |
790 | | // but they're defined only in newer compilers (>= C++0x). |
791 | | // on Windows localtime and gmtime are already thread-safe so there is not need |
792 | | // to use localtime_r and gmtime_r |
793 | 255k | struct tm nowtm_r; |
794 | 255k | if (timeAsLocalTime) |
795 | 255k | nowtm = localtime_r(&nowtime, &nowtm_r); |
796 | 0 | else |
797 | 0 | nowtm = gmtime_r(&nowtime, &nowtm_r); |
798 | | |
799 | 255k | if (nowtm != nullptr) |
800 | 255k | nowtm = &nowtm_r; |
801 | | #else |
802 | | // on Window compilers localtime and gmtime are already thread safe. |
803 | | // in old compilers (< C++0x) gmtime_r and localtime_r were not defined so we have to fall back to localtime and |
804 | | // gmtime |
805 | | if (timeAsLocalTime) |
806 | | nowtm = localtime(&nowtime); |
807 | | else |
808 | | nowtm = gmtime(&nowtime); |
809 | | #endif |
810 | | |
811 | 255k | char buf[128]; |
812 | 255k | if (nowtm != nullptr) |
813 | 255k | { |
814 | 255k | char tmbuf[64]; |
815 | 255k | strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm); |
816 | 255k | snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec); |
817 | 255k | } |
818 | 0 | else |
819 | 0 | snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000000"); |
820 | | |
821 | 255k | return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf); |
822 | 255k | } |
823 | | |
824 | | Layer* Packet::createFirstLayer(LinkLayerType linkType) |
825 | 1.29M | { |
826 | 1.29M | size_t rawDataLen = (size_t)m_RawPacket->getRawDataLen(); |
827 | 1.29M | if (rawDataLen == 0) |
828 | 3.41k | return nullptr; |
829 | | |
830 | 1.28M | const uint8_t* rawData = m_RawPacket->getRawData(); |
831 | | |
832 | 1.28M | switch (linkType) |
833 | 1.28M | { |
834 | 1.23M | case LinkLayerType::LINKTYPE_ETHERNET: |
835 | 1.23M | { |
836 | 1.23M | if (EthLayer::isDataValid(rawData, rawDataLen)) |
837 | 1.21M | { |
838 | 1.21M | return new EthLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
839 | 1.21M | } |
840 | 11.3k | if (EthDot3Layer::isDataValid(rawData, rawDataLen)) |
841 | 10.9k | { |
842 | 10.9k | return new EthDot3Layer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
843 | 10.9k | } |
844 | 348 | break; |
845 | 11.3k | } |
846 | 23.2k | case LinkLayerType::LINKTYPE_LINUX_SLL: |
847 | 23.2k | { |
848 | 23.2k | return new SllLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
849 | 11.3k | } |
850 | 8.25k | case LinkLayerType::LINKTYPE_LINUX_SLL2: |
851 | 8.25k | { |
852 | 8.25k | if (Sll2Layer::isDataValid(rawData, rawDataLen)) |
853 | 8.02k | { |
854 | 8.02k | return new Sll2Layer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
855 | 8.02k | } |
856 | 230 | break; |
857 | 8.25k | } |
858 | 7.87k | case LinkLayerType::LINKTYPE_NULL: |
859 | 7.87k | { |
860 | 7.87k | if (NullLoopbackLayer::isDataValid(rawData, rawDataLen)) |
861 | 7.54k | { |
862 | 7.54k | return new NullLoopbackLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
863 | 7.54k | } |
864 | 332 | break; |
865 | 7.87k | } |
866 | 5.15k | case LinkLayerType::LINKTYPE_RAW: |
867 | 6.84k | case LinkLayerType::LINKTYPE_DLT_RAW1: |
868 | 8.24k | case LinkLayerType::LINKTYPE_DLT_RAW2: |
869 | 8.24k | { |
870 | 8.24k | uint8_t ipVer = rawData[0] & 0xf0; |
871 | 8.24k | if (ipVer == 0x40 && IPv4Layer::isDataValid(rawData, rawDataLen)) |
872 | 4.44k | { |
873 | 4.44k | return new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
874 | 4.44k | } |
875 | 3.80k | if (ipVer == 0x60 && IPv6Layer::isDataValid(rawData, rawDataLen)) |
876 | 3.43k | { |
877 | 3.43k | return new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
878 | 3.43k | } |
879 | 372 | break; |
880 | 3.80k | } |
881 | 4.48k | case LinkLayerType::LINKTYPE_IPV4: |
882 | 4.48k | { |
883 | 4.48k | if (IPv4Layer::isDataValid(rawData, rawDataLen)) |
884 | 4.21k | { |
885 | 4.21k | return new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
886 | 4.21k | } |
887 | 266 | break; |
888 | 4.48k | } |
889 | 266 | case LinkLayerType::LINKTYPE_IPV6: |
890 | 188 | { |
891 | 188 | if (IPv6Layer::isDataValid(rawData, rawDataLen)) |
892 | 106 | { |
893 | 106 | return new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
894 | 106 | } |
895 | 82 | break; |
896 | 188 | } |
897 | 2.06k | case LinkLayerType::LINKTYPE_NFLOG: |
898 | 2.06k | { |
899 | 2.06k | if (NflogLayer::isDataValid(rawData, rawDataLen)) |
900 | 2.05k | { |
901 | 2.05k | return new NflogLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
902 | 2.05k | } |
903 | 10 | break; |
904 | 2.06k | } |
905 | 1.92k | case LinkLayerType::LINKTYPE_C_HDLC: |
906 | 1.92k | { |
907 | 1.92k | if (CiscoHdlcLayer::isDataValid(rawData, rawDataLen)) |
908 | 1.73k | { |
909 | 1.73k | return new CiscoHdlcLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
910 | 1.73k | } |
911 | 192 | break; |
912 | 1.92k | } |
913 | 682 | default: |
914 | | // For all other link types, we don't have a specific layer. Just break and create a PayloadLayer |
915 | 682 | break; |
916 | 1.28M | } |
917 | | |
918 | | // unknown link type |
919 | 2.51k | return new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
920 | 1.28M | } |
921 | | |
922 | | std::string Packet::toString(bool timeAsLocalTime) const |
923 | 255k | { |
924 | 255k | std::vector<std::string> stringList; |
925 | 255k | toStringList(stringList, timeAsLocalTime); |
926 | 255k | return std::accumulate(stringList.begin(), stringList.end(), std::string(), |
927 | 1.29M | [](std::string a, const std::string& b) { return std::move(a) + b + '\n'; }); |
928 | 255k | } |
929 | | |
930 | | void Packet::toStringList(std::vector<std::string>& result, bool timeAsLocalTime) const |
931 | 255k | { |
932 | 255k | result.clear(); |
933 | 255k | result.push_back(printPacketInfo(timeAsLocalTime)); |
934 | | |
935 | 1.29M | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
936 | 1.03M | { |
937 | 1.03M | result.push_back(curLayer->toString()); |
938 | 1.03M | } |
939 | 255k | } |
940 | | |
941 | | } // namespace pcpp |