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