/src/PcapPlusPlus/Packet++/src/Packet.cpp
Line | Count | Source |
1 | 77.4k | #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 | 191k | { |
51 | 191k | destructPacketData(); |
52 | | |
53 | 191k | m_FirstLayer = nullptr; |
54 | 191k | m_LastLayer = nullptr; |
55 | 191k | m_MaxPacketLen = rawPacket->getRawDataLen(); |
56 | 191k | m_FreeRawPacket = freeRawPacket; |
57 | 191k | m_RawPacket = rawPacket; |
58 | 191k | m_CanReallocateData = true; |
59 | | |
60 | 191k | if (m_RawPacket == nullptr) |
61 | 0 | return; |
62 | | |
63 | 191k | parsePacket(PacketParseOptions{ parseUntil, parseUntilLayer }); |
64 | 191k | } |
65 | | |
66 | | void Packet::parsePacket(PacketParseOptions options, bool incrementalParsing) |
67 | 191k | { |
68 | 191k | 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 | 191k | 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 | 191k | bool parsingNewLayers = false; |
81 | | |
82 | | // If there is no first layer, create it based on the link layer type |
83 | 191k | if (m_FirstLayer == nullptr) |
84 | 191k | { |
85 | 191k | parsingNewLayers = true; |
86 | | |
87 | 191k | LinkLayerType linkType = m_RawPacket->getLinkLayerType(); |
88 | 191k | m_FirstLayer = createFirstLayer(linkType); |
89 | | |
90 | 191k | if (m_FirstLayer == nullptr) |
91 | 1.93k | { |
92 | 1.93k | PCPP_LOG_ERROR("Failed to create first layer! Possibly attempting to parse a RawPacket with no data."); |
93 | 1.93k | return; |
94 | 1.93k | } |
95 | | |
96 | | // Mark the first layer as allocated in the packet |
97 | 189k | m_FirstLayer->m_AllocationInfo.ownedByPacket = true; |
98 | 189k | } |
99 | | |
100 | 189k | 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 | 189k | 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 | 189k | bool rollbackLastLayer = false; |
122 | 189k | bool foundTargetProtocol = false; |
123 | 942k | for (auto* curLayer = parseStartLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
124 | 752k | { |
125 | | // If we are parsing new layers, update the last layer pointer |
126 | | // Otherwise we are just traversing already parsed layers |
127 | 752k | if (parsingNewLayers) |
128 | 752k | { |
129 | | // Mark the current layer as allocated in the packet, as it was just created |
130 | 752k | curLayer->m_AllocationInfo.ownedByPacket = true; |
131 | 752k | m_LastLayer = curLayer; |
132 | 752k | } |
133 | | |
134 | | // If the current layer is of a higher OSI layer than the target, stop parsing |
135 | 752k | 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 | 752k | const bool matchesTarget = curLayer->isMemberOfProtocolFamily(options.parseUntilProtocol); |
144 | 752k | 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 | 752k | 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 | 752k | if (!curLayer->hasNextLayer()) |
160 | 752k | { |
161 | 752k | 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 | 752k | curLayer->parseNextLayer(); |
165 | 752k | } |
166 | 752k | } |
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 | 189k | 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 | 189k | if (m_LastLayer != nullptr && options.parseUntilProtocol == UnknownProtocol && |
179 | 189k | options.parseUntilLayer == OsiModelLayerUnknown) |
180 | 189k | { |
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 | 189k | int trailerLen = (int)((m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) - |
184 | 189k | (m_LastLayer->getData() + m_LastLayer->getDataLen())); |
185 | 189k | if (trailerLen > 0) |
186 | 19.9k | { |
187 | 19.9k | PacketTrailerLayer* trailerLayer = |
188 | 19.9k | new PacketTrailerLayer(static_cast<uint8_t*>(m_LastLayer->getData() + m_LastLayer->getDataLen()), |
189 | 19.9k | trailerLen, m_LastLayer, this); |
190 | | |
191 | 19.9k | trailerLayer->m_AllocationInfo.ownedByPacket = true; |
192 | 19.9k | m_LastLayer->setNextLayer(trailerLayer); |
193 | 19.9k | m_LastLayer = trailerLayer; |
194 | 19.9k | } |
195 | 189k | } |
196 | 189k | } |
197 | | |
198 | | Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) |
199 | 191k | : Packet(rawPacket, freeRawPacket, static_cast<ProtocolTypeFamily>(parseUntil), parseUntilLayer) |
200 | 191k | {} |
201 | | |
202 | | Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil, |
203 | | OsiModelLayer parseUntilLayer) |
204 | 191k | { |
205 | 191k | m_FreeRawPacket = false; |
206 | 191k | m_RawPacket = nullptr; |
207 | 191k | m_FirstLayer = nullptr; |
208 | 191k | setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer); |
209 | 191k | } |
210 | | |
211 | | Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil) |
212 | 0 | { |
213 | 0 | m_FreeRawPacket = false; |
214 | 0 | m_RawPacket = nullptr; |
215 | 0 | m_FirstLayer = nullptr; |
216 | 0 | auto parseUntilFamily = static_cast<ProtocolTypeFamily>(parseUntil); |
217 | 0 | setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); |
218 | 0 | } |
219 | | |
220 | | Packet::Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily) |
221 | 0 | { |
222 | 0 | m_FreeRawPacket = false; |
223 | 0 | m_RawPacket = nullptr; |
224 | 0 | m_FirstLayer = nullptr; |
225 | 0 | setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); |
226 | 0 | } |
227 | | |
228 | | Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer) |
229 | 0 | { |
230 | 0 | m_FreeRawPacket = false; |
231 | 0 | m_RawPacket = nullptr; |
232 | 0 | m_FirstLayer = nullptr; |
233 | 0 | setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer); |
234 | 0 | } |
235 | | |
236 | | void Packet::destructPacketData() |
237 | 1.15M | { |
238 | 1.15M | destroyAllLayers(); |
239 | | |
240 | 1.15M | if (m_RawPacket != nullptr && m_FreeRawPacket) |
241 | 772k | { |
242 | 772k | delete m_RawPacket; |
243 | 772k | } |
244 | 1.15M | } |
245 | | |
246 | | void Packet::destroyAllLayers() |
247 | 1.15M | { |
248 | 1.15M | Layer* curLayer = m_FirstLayer; |
249 | 5.55M | while (curLayer != nullptr) |
250 | 4.40M | { |
251 | 4.40M | Layer* nextLayer = curLayer->getNextLayer(); |
252 | 4.40M | if (curLayer->m_AllocationInfo.ownedByPacket) |
253 | 4.40M | { |
254 | 4.40M | delete curLayer; |
255 | 4.40M | } |
256 | | |
257 | 4.40M | curLayer = nextLayer; |
258 | 4.40M | } |
259 | | |
260 | 1.15M | m_FirstLayer = nullptr; |
261 | 1.15M | m_LastLayer = nullptr; |
262 | 1.15M | } |
263 | | |
264 | | Packet& Packet::operator=(const Packet& other) |
265 | 0 | { |
266 | 0 | destructPacketData(); |
267 | |
|
268 | 0 | copyDataFrom(other); |
269 | |
|
270 | 0 | return *this; |
271 | 0 | } |
272 | | |
273 | | void Packet::copyDataFrom(const Packet& other) |
274 | 772k | { |
275 | 772k | m_RawPacket = new RawPacket(*(other.m_RawPacket)); |
276 | 772k | m_FreeRawPacket = true; |
277 | 772k | m_MaxPacketLen = other.m_MaxPacketLen; |
278 | 772k | m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType()); |
279 | 772k | m_LastLayer = m_FirstLayer; |
280 | 772k | m_CanReallocateData = true; |
281 | 772k | Layer* curLayer = m_FirstLayer; |
282 | 4.40M | while (curLayer != nullptr) |
283 | 3.62M | { |
284 | 3.62M | curLayer->parseNextLayer(); |
285 | 3.62M | curLayer->m_AllocationInfo.ownedByPacket = true; |
286 | 3.62M | curLayer = curLayer->getNextLayer(); |
287 | 3.62M | if (curLayer != nullptr) |
288 | 2.85M | m_LastLayer = curLayer; |
289 | 3.62M | } |
290 | 772k | } |
291 | | |
292 | | void Packet::reallocateRawData(size_t newSize) |
293 | 13.5k | { |
294 | 13.5k | PCPP_LOG_DEBUG("Allocating packet to new size: " << newSize); |
295 | | |
296 | | // allocate a new array with size newSize |
297 | 13.5k | m_MaxPacketLen = newSize; |
298 | | |
299 | | // set the new array to RawPacket |
300 | 13.5k | if (!m_RawPacket->reallocateData(m_MaxPacketLen)) |
301 | 0 | { |
302 | 0 | PCPP_LOG_ERROR("Couldn't reallocate data of raw packet to " << m_MaxPacketLen << " bytes"); |
303 | 0 | return; |
304 | 0 | } |
305 | | |
306 | | // set all data pointers in layers to the new array address |
307 | 13.5k | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
308 | | |
309 | 69.3k | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
310 | 55.7k | { |
311 | 55.7k | PCPP_LOG_DEBUG("Setting new data pointer to layer '" << typeid(curLayer).name() << "'"); |
312 | 55.7k | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
313 | 55.7k | dataPtr += curLayer->getHeaderLen(); |
314 | 55.7k | } |
315 | 13.5k | } |
316 | | |
317 | | bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket) |
318 | 0 | { |
319 | 0 | if (newLayer == nullptr) |
320 | 0 | { |
321 | 0 | PCPP_LOG_ERROR("Layer to add is nullptr"); |
322 | 0 | return false; |
323 | 0 | } |
324 | | |
325 | 0 | if (newLayer->isAllocatedToPacket()) |
326 | 0 | { |
327 | 0 | PCPP_LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet"); |
328 | 0 | return false; |
329 | 0 | } |
330 | | |
331 | 0 | if (prevLayer != nullptr && prevLayer->getProtocol() == PacketTrailer) |
332 | 0 | { |
333 | 0 | PCPP_LOG_ERROR("Cannot insert layer after packet trailer"); |
334 | 0 | return false; |
335 | 0 | } |
336 | | |
337 | 0 | size_t newLayerHeaderLen = newLayer->getHeaderLen(); |
338 | 0 | if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen) |
339 | 0 | { |
340 | 0 | if (!m_CanReallocateData) |
341 | 0 | { |
342 | 0 | PCPP_LOG_ERROR("With the new layer the packet will exceed the size of the pre-allocated buffer: " |
343 | 0 | << m_MaxPacketLen << " bytes"); |
344 | 0 | return false; |
345 | 0 | } |
346 | | // reallocate to maximum value of: twice the max size of the packet or max size + new required length |
347 | 0 | if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen * 2) |
348 | 0 | reallocateRawData(m_RawPacket->getRawDataLen() + newLayerHeaderLen + m_MaxPacketLen); |
349 | 0 | else |
350 | 0 | reallocateRawData(m_MaxPacketLen * 2); |
351 | 0 | } |
352 | | |
353 | | // insert layer data to raw packet |
354 | 0 | int indexToInsertData = 0; |
355 | 0 | if (prevLayer != nullptr) |
356 | 0 | indexToInsertData = prevLayer->m_Data + prevLayer->getHeaderLen() - m_RawPacket->getRawData(); |
357 | 0 | m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, newLayerHeaderLen); |
358 | | |
359 | | // delete previous layer data |
360 | 0 | delete[] newLayer->m_Data; |
361 | | |
362 | | // add layer to layers linked list |
363 | 0 | if (prevLayer != nullptr) |
364 | 0 | { |
365 | 0 | newLayer->setNextLayer(prevLayer->getNextLayer()); |
366 | 0 | newLayer->setPrevLayer(prevLayer); |
367 | 0 | prevLayer->setNextLayer(newLayer); |
368 | 0 | } |
369 | 0 | else // prevLayer == nullptr |
370 | 0 | { |
371 | 0 | newLayer->setNextLayer(m_FirstLayer); |
372 | 0 | if (m_FirstLayer != nullptr) |
373 | 0 | m_FirstLayer->setPrevLayer(newLayer); |
374 | 0 | m_FirstLayer = newLayer; |
375 | 0 | } |
376 | |
|
377 | 0 | if (newLayer->getNextLayer() == nullptr) |
378 | 0 | m_LastLayer = newLayer; |
379 | 0 | else |
380 | 0 | newLayer->getNextLayer()->setPrevLayer(newLayer); |
381 | | |
382 | | // Attach the layer to this packet. If ownInPacket is true, transfer ownership of the layer to the packet. |
383 | 0 | newLayer->m_AllocationInfo.attachPacket(this, ownInPacket); |
384 | | |
385 | | // re-calculate all layers data ptr and data length |
386 | | |
387 | | // first, get ptr and data length of the raw packet |
388 | 0 | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
389 | 0 | size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen()); |
390 | | |
391 | | // if a packet trailer exists, get its length |
392 | 0 | size_t packetTrailerLen = 0; |
393 | 0 | if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer) |
394 | 0 | packetTrailerLen = m_LastLayer->getDataLen(); |
395 | | |
396 | | // go over all layers from the first layer to the last layer and set the data ptr and data length for each one |
397 | 0 | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
398 | 0 | { |
399 | | // set data ptr to layer |
400 | 0 | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
401 | | |
402 | | // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers. |
403 | | // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the |
404 | | // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data |
405 | | // length |
406 | 0 | if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer) |
407 | 0 | curLayer->m_DataLen = dataLen; |
408 | 0 | else |
409 | 0 | curLayer->m_DataLen = dataLen - packetTrailerLen; |
410 | | |
411 | | // advance data ptr and data length |
412 | 0 | dataPtr += curLayer->getHeaderLen(); |
413 | 0 | dataLen -= curLayer->getHeaderLen(); |
414 | 0 | } |
415 | |
|
416 | 0 | return true; |
417 | 0 | } |
418 | | |
419 | | bool Packet::removeLayer(ProtocolType layerType, int index) |
420 | 0 | { |
421 | 0 | Layer* layerToRemove = getLayerOfType(layerType, index); |
422 | |
|
423 | 0 | if (layerToRemove != nullptr) |
424 | 0 | { |
425 | 0 | return removeLayer(layerToRemove, true); |
426 | 0 | } |
427 | 0 | else |
428 | 0 | { |
429 | 0 | PCPP_LOG_ERROR("Layer of the requested type was not found in packet"); |
430 | 0 | return false; |
431 | 0 | } |
432 | 0 | } |
433 | | |
434 | | bool Packet::removeFirstLayer() |
435 | 0 | { |
436 | 0 | Layer* firstLayer = getFirstLayer(); |
437 | 0 | if (firstLayer == nullptr) |
438 | 0 | { |
439 | 0 | PCPP_LOG_ERROR("Packet has no layers"); |
440 | 0 | return false; |
441 | 0 | } |
442 | | |
443 | 0 | return removeLayer(firstLayer, true); |
444 | 0 | } |
445 | | |
446 | | bool Packet::removeLastLayer() |
447 | 0 | { |
448 | 0 | Layer* lastLayer = getLastLayer(); |
449 | 0 | if (lastLayer == nullptr) |
450 | 0 | { |
451 | 0 | PCPP_LOG_ERROR("Packet has no layers"); |
452 | 0 | return false; |
453 | 0 | } |
454 | | |
455 | 0 | return removeLayer(lastLayer, true); |
456 | 0 | } |
457 | | |
458 | | bool Packet::removeAllLayersAfter(Layer* layer) |
459 | 0 | { |
460 | 0 | Layer* curLayer = layer->getNextLayer(); |
461 | 0 | while (curLayer != nullptr) |
462 | 0 | { |
463 | 0 | Layer* tempLayer = curLayer->getNextLayer(); |
464 | 0 | if (!removeLayer(curLayer, true)) |
465 | 0 | return false; |
466 | 0 | curLayer = tempLayer; |
467 | 0 | } |
468 | | |
469 | 0 | return true; |
470 | 0 | } |
471 | | |
472 | | Layer* Packet::detachLayer(ProtocolType layerType, int index) |
473 | 0 | { |
474 | 0 | Layer* layerToDetach = getLayerOfType(layerType, index); |
475 | |
|
476 | 0 | if (layerToDetach != nullptr) |
477 | 0 | { |
478 | 0 | if (removeLayer(layerToDetach, false)) |
479 | 0 | return layerToDetach; |
480 | 0 | else |
481 | 0 | return nullptr; |
482 | 0 | } |
483 | 0 | else |
484 | 0 | { |
485 | 0 | PCPP_LOG_ERROR("Layer of the requested type was not found in packet"); |
486 | 0 | return nullptr; |
487 | 0 | } |
488 | 0 | } |
489 | | |
490 | | bool Packet::removeLayer(Layer* layer, bool tryToDelete) |
491 | 0 | { |
492 | 0 | if (layer == nullptr) |
493 | 0 | { |
494 | 0 | PCPP_LOG_ERROR("Layer is nullptr"); |
495 | 0 | return false; |
496 | 0 | } |
497 | | |
498 | | // verify layer is allocated to a packet |
499 | 0 | if (!layer->isAllocatedToPacket()) |
500 | 0 | { |
501 | 0 | PCPP_LOG_ERROR("Layer isn't allocated to any packet"); |
502 | 0 | return false; |
503 | 0 | } |
504 | | |
505 | | // verify layer is allocated to *this* packet |
506 | 0 | Layer* curLayer = layer; |
507 | 0 | while (curLayer->m_PrevLayer != nullptr) |
508 | 0 | curLayer = curLayer->m_PrevLayer; |
509 | 0 | if (curLayer != m_FirstLayer) |
510 | 0 | { |
511 | 0 | PCPP_LOG_ERROR("Layer isn't allocated to this packet"); |
512 | 0 | return false; |
513 | 0 | } |
514 | | |
515 | | // before removing the layer's data, copy it so it can be later assigned as the removed layer's data |
516 | 0 | size_t headerLen = layer->getHeaderLen(); |
517 | 0 | size_t layerOldDataSize = headerLen; |
518 | 0 | auto layerOldData = std::make_unique<uint8_t[]>(layerOldDataSize); |
519 | 0 | memcpy(layerOldData.get(), layer->m_Data, layerOldDataSize); |
520 | | |
521 | | // remove data from raw packet |
522 | 0 | size_t numOfBytesToRemove = headerLen; |
523 | 0 | int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData(); |
524 | 0 | if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove)) |
525 | 0 | { |
526 | 0 | PCPP_LOG_ERROR("Couldn't remove data from packet"); |
527 | 0 | return false; |
528 | 0 | } |
529 | | |
530 | | // remove layer from layers linked list |
531 | 0 | if (layer->m_PrevLayer != nullptr) |
532 | 0 | layer->m_PrevLayer->setNextLayer(layer->m_NextLayer); |
533 | 0 | if (layer->m_NextLayer != nullptr) |
534 | 0 | layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer); |
535 | | |
536 | | // take care of head and tail ptrs |
537 | 0 | if (m_FirstLayer == layer) |
538 | 0 | m_FirstLayer = layer->m_NextLayer; |
539 | 0 | if (m_LastLayer == layer) |
540 | 0 | m_LastLayer = layer->m_PrevLayer; |
541 | 0 | layer->setNextLayer(nullptr); |
542 | 0 | layer->setPrevLayer(nullptr); |
543 | | |
544 | | // get packet trailer len if exists |
545 | 0 | size_t packetTrailerLen = 0; |
546 | 0 | if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer) |
547 | 0 | packetTrailerLen = m_LastLayer->getDataLen(); |
548 | | |
549 | | // re-calculate all layers data ptr and data length |
550 | | |
551 | | // first, get ptr and data length of the raw packet |
552 | 0 | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
553 | 0 | size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen()); |
554 | |
|
555 | 0 | curLayer = m_FirstLayer; |
556 | | |
557 | | // go over all layers from the first layer to the last layer and set the data ptr and data length for each one |
558 | 0 | while (curLayer != nullptr) |
559 | 0 | { |
560 | | // set data ptr to layer |
561 | 0 | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
562 | | |
563 | | // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers. |
564 | | // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the |
565 | | // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data |
566 | | // length |
567 | 0 | if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer) |
568 | 0 | curLayer->m_DataLen = dataLen; |
569 | 0 | else |
570 | 0 | curLayer->m_DataLen = dataLen - packetTrailerLen; |
571 | | |
572 | | // advance data ptr and data length |
573 | 0 | dataPtr += curLayer->getHeaderLen(); |
574 | 0 | dataLen -= curLayer->getHeaderLen(); |
575 | | |
576 | | // move to next layer |
577 | 0 | curLayer = curLayer->getNextLayer(); |
578 | 0 | } |
579 | | |
580 | | // if layer was allocated by this packet and tryToDelete flag is set, delete it |
581 | 0 | if (tryToDelete && layer->m_AllocationInfo.ownedByPacket) |
582 | 0 | { |
583 | 0 | delete layer; |
584 | 0 | } |
585 | | // if layer was not allocated by this packet or the tryToDelete is not set, detach it from the packet so it can |
586 | | // be reused |
587 | 0 | else |
588 | 0 | { |
589 | 0 | layer->m_AllocationInfo.detach(); |
590 | 0 | layer->m_Data = layerOldData.release(); |
591 | 0 | layer->m_DataLen = layerOldDataSize; |
592 | 0 | } |
593 | |
|
594 | 0 | return true; |
595 | 0 | } |
596 | | |
597 | | Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const |
598 | 0 | { |
599 | 0 | int curIndex = 0; |
600 | 0 | for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
601 | 0 | { |
602 | 0 | if (curLayer->getProtocol() != layerType) |
603 | 0 | continue; |
604 | | |
605 | 0 | if (curIndex == index) |
606 | 0 | return curLayer; |
607 | | |
608 | 0 | curIndex++; |
609 | 0 | } |
610 | | |
611 | 0 | return nullptr; |
612 | 0 | } |
613 | | |
614 | | bool Packet::isPacketOfType(ProtocolType protocolType) const |
615 | 13.1M | { |
616 | 73.1M | for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
617 | 60.8M | { |
618 | 60.8M | if (curLayer->getProtocol() == protocolType) |
619 | 838k | { |
620 | 838k | return true; |
621 | 838k | } |
622 | 60.8M | } |
623 | | |
624 | 12.2M | return false; |
625 | 13.1M | } |
626 | | |
627 | | bool Packet::isPacketOfType(ProtocolTypeFamily protocolTypeFamily) const |
628 | 3.09M | { |
629 | 3.09M | Layer* curLayer = getFirstLayer(); |
630 | 17.4M | while (curLayer != nullptr) |
631 | 14.4M | { |
632 | 14.4M | if (curLayer->isMemberOfProtocolFamily(protocolTypeFamily)) |
633 | 79.2k | { |
634 | 79.2k | return true; |
635 | 79.2k | } |
636 | 14.3M | curLayer = curLayer->getNextLayer(); |
637 | 14.3M | } |
638 | | |
639 | 3.01M | return false; |
640 | 3.09M | } |
641 | | |
642 | | bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend) |
643 | 49.2k | { |
644 | 49.2k | if (layer == nullptr) |
645 | 0 | { |
646 | 0 | PCPP_LOG_ERROR("Layer is nullptr"); |
647 | 0 | return false; |
648 | 0 | } |
649 | | |
650 | | // verify layer is allocated to this packet |
651 | 49.2k | if (!(layer->getAttachedPacket() == this)) |
652 | 0 | { |
653 | 0 | PCPP_LOG_ERROR("Layer isn't allocated to this packet"); |
654 | 0 | return false; |
655 | 0 | } |
656 | | |
657 | 49.2k | if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen) |
658 | 13.5k | { |
659 | 13.5k | if (!m_CanReallocateData) |
660 | 0 | { |
661 | 0 | PCPP_LOG_ERROR( |
662 | 0 | "With the layer extended size the packet will exceed the size of the pre-allocated buffer: " |
663 | 0 | << m_MaxPacketLen << " bytes"); |
664 | 0 | return false; |
665 | 0 | } |
666 | | // reallocate to maximum value of: twice the max size of the packet or max size + new required length |
667 | 13.5k | if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen * 2) |
668 | 444 | reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen); |
669 | 13.0k | else |
670 | 13.0k | reallocateRawData(m_MaxPacketLen * 2); |
671 | 13.5k | } |
672 | | |
673 | | // insert layer data to raw packet |
674 | 49.2k | int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData(); |
675 | | // passing nullptr to insertData will move the data by numOfBytesToExtend |
676 | | // no new data has to be created for this insertion which saves at least little time |
677 | | // this move operation occurs on already allocated memory, which is backed by the reallocation if's provided |
678 | | // above if offsetInLayer == layer->getHeaderLen() insertData will not move any data but only increase the |
679 | | // packet size by numOfBytesToExtend |
680 | 49.2k | m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend); |
681 | | |
682 | | // re-calculate all layers data ptr and data length |
683 | 49.2k | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
684 | | |
685 | | // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer |
686 | 49.2k | bool passedExtendedLayer = false; |
687 | 273k | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
688 | 226k | { |
689 | 226k | if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) |
690 | 1.83k | { |
691 | 1.83k | PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary"); |
692 | 1.83k | return false; |
693 | 1.83k | } |
694 | | |
695 | | // set the data ptr |
696 | 224k | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
697 | | |
698 | | // set a flag if arrived to the layer being extended |
699 | 224k | if (curLayer->getPrevLayer() == layer) |
700 | 9.78k | passedExtendedLayer = true; |
701 | | |
702 | | // change the data length only for layers who come before the extended layer. For layers who come after, |
703 | | // data length isn't changed |
704 | 224k | if (!passedExtendedLayer) |
705 | 205k | curLayer->m_DataLen += numOfBytesToExtend; |
706 | | |
707 | | // assuming header length of the layer that requested to be extended hasn't been enlarged yet |
708 | 224k | size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0); |
709 | 224k | dataPtr += headerLen; |
710 | 224k | } |
711 | | |
712 | 47.4k | return true; |
713 | 49.2k | } |
714 | | |
715 | | bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten) |
716 | 51.6k | { |
717 | 51.6k | if (layer == nullptr) |
718 | 0 | { |
719 | 0 | PCPP_LOG_ERROR("Layer is nullptr"); |
720 | 0 | return false; |
721 | 0 | } |
722 | | |
723 | | // verify layer is allocated to this packet |
724 | 51.6k | if (!(layer->getAttachedPacket() == this)) |
725 | 0 | { |
726 | 0 | PCPP_LOG_ERROR("Layer isn't allocated to this packet"); |
727 | 0 | return false; |
728 | 0 | } |
729 | | |
730 | | // remove data from raw packet |
731 | 51.6k | int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData(); |
732 | 51.6k | if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten)) |
733 | 6 | { |
734 | 6 | PCPP_LOG_ERROR("Couldn't remove data from packet"); |
735 | 6 | return false; |
736 | 6 | } |
737 | | |
738 | | // re-calculate all layers data ptr and data length |
739 | 51.6k | const uint8_t* dataPtr = m_RawPacket->getRawData(); |
740 | | |
741 | | // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer |
742 | 51.6k | bool passedExtendedLayer = false; |
743 | 305k | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
744 | 254k | { |
745 | 254k | if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) |
746 | 313 | { |
747 | 313 | PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary"); |
748 | 313 | return false; |
749 | 313 | } |
750 | | |
751 | | // set the data ptr |
752 | 253k | curLayer->m_Data = const_cast<uint8_t*>(dataPtr); |
753 | | |
754 | | // set a flag if arrived to the layer being shortened |
755 | 253k | if (curLayer->getPrevLayer() == layer) |
756 | 14.7k | passedExtendedLayer = true; |
757 | | |
758 | 253k | size_t headerLen = curLayer->getHeaderLen(); |
759 | | |
760 | | // change the data length only for layers who come before the shortened layer. For layers who come after, |
761 | | // data length isn't changed |
762 | 253k | if (!passedExtendedLayer) |
763 | 223k | curLayer->m_DataLen -= numOfBytesToShorten; |
764 | | |
765 | | // assuming header length of the layer that requested to be extended hasn't been enlarged yet |
766 | 253k | headerLen -= (curLayer == layer ? numOfBytesToShorten : 0); |
767 | 253k | dataPtr += headerLen; |
768 | 253k | } |
769 | | |
770 | 51.3k | return true; |
771 | 51.6k | } |
772 | | |
773 | | void Packet::computeCalculateFields() |
774 | 191k | { |
775 | | // calculated fields should be calculated from top layer to bottom layer |
776 | 964k | for (Layer* curLayer = m_LastLayer; curLayer != nullptr; curLayer = curLayer->getPrevLayer()) |
777 | 772k | { |
778 | 772k | curLayer->computeCalculateFields(); |
779 | 772k | } |
780 | 191k | } |
781 | | |
782 | | std::string Packet::printPacketInfo(bool timeAsLocalTime) const |
783 | 191k | { |
784 | 191k | std::ostringstream dataLenStream; |
785 | 191k | dataLenStream << m_RawPacket->getRawDataLen(); |
786 | | |
787 | | // convert raw packet timestamp to printable format |
788 | 191k | timespec timestamp = m_RawPacket->getPacketTimeStamp(); |
789 | 191k | time_t nowtime = timestamp.tv_sec; |
790 | 191k | struct tm* nowtm = nullptr; |
791 | 191k | #if __cplusplus > 199711L && !defined(_WIN32) |
792 | | // localtime_r and gmtime_r are thread-safe versions of localtime and gmtime, |
793 | | // but they're defined only in newer compilers (>= C++0x). |
794 | | // on Windows localtime and gmtime are already thread-safe so there is not need |
795 | | // to use localtime_r and gmtime_r |
796 | 191k | struct tm nowtm_r; |
797 | 191k | if (timeAsLocalTime) |
798 | 191k | nowtm = localtime_r(&nowtime, &nowtm_r); |
799 | 0 | else |
800 | 0 | nowtm = gmtime_r(&nowtime, &nowtm_r); |
801 | | |
802 | 191k | if (nowtm != nullptr) |
803 | 191k | nowtm = &nowtm_r; |
804 | | #else |
805 | | // on Window compilers localtime and gmtime are already thread safe. |
806 | | // in old compilers (< C++0x) gmtime_r and localtime_r were not defined so we have to fall back to localtime and |
807 | | // gmtime |
808 | | if (timeAsLocalTime) |
809 | | nowtm = localtime(&nowtime); |
810 | | else |
811 | | nowtm = gmtime(&nowtime); |
812 | | #endif |
813 | | |
814 | 191k | char buf[128]; |
815 | 191k | if (nowtm != nullptr) |
816 | 191k | { |
817 | 191k | char tmbuf[64]; |
818 | 191k | strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm); |
819 | 191k | snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec); |
820 | 191k | } |
821 | 0 | else |
822 | 0 | snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000000"); |
823 | | |
824 | 191k | return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf); |
825 | 191k | } |
826 | | |
827 | | Layer* Packet::createFirstLayer(LinkLayerType linkType) |
828 | 964k | { |
829 | 964k | size_t rawDataLen = (size_t)m_RawPacket->getRawDataLen(); |
830 | 964k | if (rawDataLen == 0) |
831 | 1.93k | return nullptr; |
832 | | |
833 | 962k | const uint8_t* rawData = m_RawPacket->getRawData(); |
834 | | |
835 | 962k | switch (linkType) |
836 | 962k | { |
837 | 881k | case LinkLayerType::LINKTYPE_ETHERNET: |
838 | 881k | { |
839 | 881k | if (EthLayer::isDataValid(rawData, rawDataLen)) |
840 | 872k | { |
841 | 872k | return new EthLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
842 | 872k | } |
843 | 9.30k | if (EthDot3Layer::isDataValid(rawData, rawDataLen)) |
844 | 9.22k | { |
845 | 9.22k | return new EthDot3Layer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
846 | 9.22k | } |
847 | 80 | break; |
848 | 9.30k | } |
849 | 13.3k | case LinkLayerType::LINKTYPE_LINUX_SLL: |
850 | 13.3k | { |
851 | 13.3k | return new SllLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
852 | 9.30k | } |
853 | 7.67k | case LinkLayerType::LINKTYPE_LINUX_SLL2: |
854 | 7.67k | { |
855 | 7.67k | if (Sll2Layer::isDataValid(rawData, rawDataLen)) |
856 | 7.67k | { |
857 | 7.67k | return new Sll2Layer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
858 | 7.67k | } |
859 | 2 | break; |
860 | 7.67k | } |
861 | 12.9k | case LinkLayerType::LINKTYPE_NULL: |
862 | 12.9k | { |
863 | 12.9k | if (NullLoopbackLayer::isDataValid(rawData, rawDataLen)) |
864 | 12.6k | { |
865 | 12.6k | return new NullLoopbackLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
866 | 12.6k | } |
867 | 268 | break; |
868 | 12.9k | } |
869 | 6.97k | case LinkLayerType::LINKTYPE_RAW: |
870 | 11.7k | case LinkLayerType::LINKTYPE_DLT_RAW1: |
871 | 13.8k | case LinkLayerType::LINKTYPE_DLT_RAW2: |
872 | 13.8k | { |
873 | 13.8k | uint8_t ipVer = rawData[0] & 0xf0; |
874 | 13.8k | if (ipVer == 0x40 && IPv4Layer::isDataValid(rawData, rawDataLen)) |
875 | 11.0k | { |
876 | 11.0k | return new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
877 | 11.0k | } |
878 | 2.85k | if (ipVer == 0x60 && IPv6Layer::isDataValid(rawData, rawDataLen)) |
879 | 2.35k | { |
880 | 2.35k | return new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
881 | 2.35k | } |
882 | 500 | break; |
883 | 2.85k | } |
884 | 29.1k | case LinkLayerType::LINKTYPE_IPV4: |
885 | 29.1k | { |
886 | 29.1k | if (IPv4Layer::isDataValid(rawData, rawDataLen)) |
887 | 28.9k | { |
888 | 28.9k | return new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
889 | 28.9k | } |
890 | 208 | break; |
891 | 29.1k | } |
892 | 208 | case LinkLayerType::LINKTYPE_IPV6: |
893 | 128 | { |
894 | 128 | if (IPv6Layer::isDataValid(rawData, rawDataLen)) |
895 | 0 | { |
896 | 0 | return new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
897 | 0 | } |
898 | 128 | break; |
899 | 128 | } |
900 | 2.37k | case LinkLayerType::LINKTYPE_NFLOG: |
901 | 2.37k | { |
902 | 2.37k | if (NflogLayer::isDataValid(rawData, rawDataLen)) |
903 | 2.37k | { |
904 | 2.37k | return new NflogLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
905 | 2.37k | } |
906 | 0 | break; |
907 | 2.37k | } |
908 | 691 | case LinkLayerType::LINKTYPE_C_HDLC: |
909 | 691 | { |
910 | 691 | if (CiscoHdlcLayer::isDataValid(rawData, rawDataLen)) |
911 | 531 | { |
912 | 531 | return new CiscoHdlcLayer(const_cast<uint8_t*>(rawData), rawDataLen, this); |
913 | 531 | } |
914 | 160 | break; |
915 | 691 | } |
916 | 160 | default: |
917 | | // For all other link types, we don't have a specific layer. Just break and create a PayloadLayer |
918 | 0 | break; |
919 | 962k | } |
920 | | |
921 | | // unknown link type |
922 | 1.34k | return new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this); |
923 | 962k | } |
924 | | |
925 | | std::string Packet::toString(bool timeAsLocalTime) const |
926 | 191k | { |
927 | 191k | std::vector<std::string> stringList; |
928 | 191k | toStringList(stringList, timeAsLocalTime); |
929 | 191k | return std::accumulate(stringList.begin(), stringList.end(), std::string(), |
930 | 964k | [](std::string a, const std::string& b) { return std::move(a) + b + '\n'; }); |
931 | 191k | } |
932 | | |
933 | | void Packet::toStringList(std::vector<std::string>& result, bool timeAsLocalTime) const |
934 | 191k | { |
935 | 191k | result.clear(); |
936 | 191k | result.push_back(printPacketInfo(timeAsLocalTime)); |
937 | | |
938 | 964k | for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
939 | 772k | { |
940 | 772k | result.push_back(curLayer->toString()); |
941 | 772k | } |
942 | 191k | } |
943 | | |
944 | | const FieldDescriptor Packet::SerializedFields::TimestampObject::Sec{ 0, "sec" }; |
945 | | const FieldDescriptor Packet::SerializedFields::TimestampObject::NSec{ 1, "nsec" }; |
946 | | const Packet::SerializedFields::TimestampObject Packet::SerializedFields::Timestamp{ 0, "timestamp" }; |
947 | | const FieldDescriptor Packet::SerializedFields::FrameLength{ 1, "frameLength" }; |
948 | | const FieldDescriptor Packet::SerializedFields::LinkLayer{ 2, "linkLayer" }; |
949 | | const FieldDescriptor Packet::SerializedFields::LinkLayerName{ 3, "linkLayerName" }; |
950 | | const FieldDescriptor Packet::SerializedFields::Layers{ 4, "layers" }; |
951 | | const FieldDescriptor PacketObject{ 0, "packet" }; |
952 | | |
953 | | void Packet::serialize(ISerializer& serializer) const |
954 | 0 | { |
955 | 0 | auto rawPacket = getRawPacket(); |
956 | 0 | timespec ts = rawPacket->getPacketTimeStamp(); |
957 | |
|
958 | 0 | auto packetObject = serializer.writeObject(PacketObject); |
959 | 0 | { |
960 | 0 | auto timestamp = packetObject.writeObject(SerializedFields::Timestamp); |
961 | 0 | timestamp.writeField(SerializedFields::TimestampObject::Sec, static_cast<uint64_t>(ts.tv_sec)); |
962 | 0 | timestamp.writeField(SerializedFields::TimestampObject::NSec, static_cast<uint64_t>(ts.tv_nsec)); |
963 | 0 | } |
964 | 0 | packetObject.writeField(SerializedFields::FrameLength, rawPacket->getFrameLength()); |
965 | 0 | auto linkLayer = rawPacket->getLinkLayerType(); |
966 | 0 | packetObject.writeField(SerializedFields::LinkLayer, static_cast<uint16_t>(linkLayer)); |
967 | 0 | packetObject.writeField(SerializedFields::LinkLayerName, linkLayerToString(linkLayer)); |
968 | |
|
969 | 0 | auto layersArray = packetObject.writeArray(SerializedFields::Layers); |
970 | 0 | for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) |
971 | 0 | { |
972 | 0 | curLayer->serialize(layersArray); |
973 | 0 | } |
974 | 0 | } |
975 | | |
976 | | } // namespace pcpp |