/src/PcapPlusPlus/Packet++/src/TcpLayer.cpp
Line | Count | Source |
1 | 479k | #define LOG_MODULE PacketLogModuleTcpLayer |
2 | | |
3 | | #include "EndianPortable.h" |
4 | | #include "TcpLayer.h" |
5 | | #include "IPv4Layer.h" |
6 | | #include "IPv6Layer.h" |
7 | | #include "PayloadLayer.h" |
8 | | #include "HttpLayer.h" |
9 | | #include "SSLLayer.h" |
10 | | #include "SipLayer.h" |
11 | | #include "BgpLayer.h" |
12 | | #include "SSHLayer.h" |
13 | | #include "DnsLayer.h" |
14 | | #include "DoIpLayer.h" |
15 | | #include "TelnetLayer.h" |
16 | | #include "TpktLayer.h" |
17 | | #include "FtpLayer.h" |
18 | | #include "SomeIpLayer.h" |
19 | | #include "SmtpLayer.h" |
20 | | #include "LdapLayer.h" |
21 | | #include "GtpLayer.h" |
22 | | #include "ModbusLayer.h" |
23 | | #include "PacketUtils.h" |
24 | | #include "Logger.h" |
25 | | #include "DeprecationUtils.h" |
26 | | #include <sstream> |
27 | | |
28 | | namespace pcpp |
29 | | { |
30 | | |
31 | 310k | #define TCPOPT_DUMMY 0xff |
32 | | |
33 | | /// ~~~~~~~~~~~~~~~~ |
34 | | /// TcpOptionBuilder |
35 | | /// ~~~~~~~~~~~~~~~~ |
36 | | |
37 | | TcpOptionBuilder::TcpOptionBuilder(NopEolOptionTypes optionType) |
38 | 0 | { |
39 | 0 | switch (optionType) |
40 | 0 | { |
41 | 0 | case EOL: |
42 | 0 | init(static_cast<uint8_t>(PCPP_TCPOPT_EOL), nullptr, 0); |
43 | 0 | break; |
44 | 0 | case NOP: |
45 | 0 | default: |
46 | 0 | init(static_cast<uint8_t>(PCPP_TCPOPT_NOP), nullptr, 0); |
47 | 0 | break; |
48 | 0 | } |
49 | 0 | } |
50 | | |
51 | | TcpOptionBuilder::TcpOptionBuilder(const NopEolOptionEnumType optionType) |
52 | 149k | { |
53 | 149k | switch (optionType) |
54 | 149k | { |
55 | 0 | case NopEolOptionEnumType::Eol: |
56 | 0 | init(static_cast<uint8_t>(TcpOptionEnumType::Eol), nullptr, 0); |
57 | 0 | break; |
58 | 149k | case NopEolOptionEnumType::Nop: |
59 | 149k | default: |
60 | 149k | init(static_cast<uint8_t>(TcpOptionEnumType::Nop), nullptr, 0); |
61 | 149k | break; |
62 | 149k | } |
63 | 149k | } |
64 | | |
65 | | TcpOption TcpOptionBuilder::build() const |
66 | 59.3k | { |
67 | 59.3k | uint8_t recType = static_cast<uint8_t>(m_RecType); |
68 | 59.3k | size_t optionSize = m_RecValueLen + 2 * sizeof(uint8_t); |
69 | | |
70 | 59.3k | if (recType == static_cast<uint8_t>(TcpOptionEnumType::Eol) || |
71 | 59.3k | recType == static_cast<uint8_t>(TcpOptionEnumType::Nop)) |
72 | 59.3k | { |
73 | 59.3k | if (m_RecValueLen != 0) |
74 | 0 | { |
75 | 0 | PCPP_LOG_ERROR( |
76 | 0 | "TCP NOP and TCP EOL options are 1-byte long and don't have option value. Tried to set option value of size " |
77 | 0 | << m_RecValueLen); |
78 | 0 | return TcpOption(nullptr); |
79 | 0 | } |
80 | | |
81 | 59.3k | optionSize = 1; |
82 | 59.3k | } |
83 | | |
84 | 59.3k | uint8_t* recordBuffer = new uint8_t[optionSize]; |
85 | 59.3k | memset(recordBuffer, 0, optionSize); |
86 | 59.3k | recordBuffer[0] = recType; |
87 | 59.3k | if (optionSize > 1) |
88 | 0 | { |
89 | 0 | recordBuffer[1] = static_cast<uint8_t>(optionSize); |
90 | 0 | if (optionSize > 2 && m_RecValue != nullptr) |
91 | 0 | memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); |
92 | 0 | } |
93 | | |
94 | 59.3k | return TcpOption(recordBuffer); |
95 | 59.3k | } |
96 | | |
97 | | /// ~~~~~~~~ |
98 | | /// TcpLayer |
99 | | /// ~~~~~~~~ |
100 | | |
101 | | uint16_t TcpLayer::getSrcPort() const |
102 | 985k | { |
103 | 985k | return be16toh(getTcpHeader()->portSrc); |
104 | 985k | } |
105 | | |
106 | | uint16_t TcpLayer::getDstPort() const |
107 | 985k | { |
108 | 985k | return be16toh(getTcpHeader()->portDst); |
109 | 985k | } |
110 | | |
111 | | TcpOption TcpLayer::getTcpOption(const TcpOptionEnumType option) const |
112 | 149k | { |
113 | 149k | return m_OptionReader.getTLVRecord(static_cast<uint8_t>(option), getOptionsBasePtr(), |
114 | 149k | getHeaderLen() - sizeof(tcphdr)); |
115 | 149k | } |
116 | | |
117 | | TcpOption TcpLayer::getFirstTcpOption() const |
118 | 59.3k | { |
119 | 59.3k | return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); |
120 | 59.3k | } |
121 | | |
122 | | TcpOption TcpLayer::getNextTcpOption(TcpOption& tcpOption) const |
123 | 195k | { |
124 | 195k | TcpOption nextOpt = |
125 | 195k | m_OptionReader.getNextTLVRecord(tcpOption, getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); |
126 | 195k | if (nextOpt.isNotNull() && nextOpt.getType() == TCPOPT_DUMMY) |
127 | 39 | return TcpOption(nullptr); |
128 | | |
129 | 195k | return nextOpt; |
130 | 195k | } |
131 | | |
132 | | size_t TcpLayer::getTcpOptionCount() const |
133 | 0 | { |
134 | 0 | return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); |
135 | 0 | } |
136 | | |
137 | | TcpOption TcpLayer::addTcpOption(const TcpOptionBuilder& optionBuilder) |
138 | 0 | { |
139 | 0 | return addTcpOptionAt(optionBuilder, getHeaderLen() - m_NumOfTrailingBytes); |
140 | 0 | } |
141 | | |
142 | | TcpOption TcpLayer::insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder, |
143 | | const TcpOptionEnumType prevOptionType) |
144 | 149k | { |
145 | 149k | int offset = 0; |
146 | | |
147 | 149k | if (prevOptionType == TcpOptionEnumType::Unknown) |
148 | 0 | { |
149 | 0 | offset = sizeof(tcphdr); |
150 | 0 | } |
151 | 149k | else |
152 | 149k | { |
153 | 149k | const TcpOption prevOpt = getTcpOption(prevOptionType); |
154 | 149k | if (prevOpt.isNull()) |
155 | 90.2k | { |
156 | 90.2k | PCPP_LOG_ERROR("Previous option of type " << static_cast<int>(prevOptionType) |
157 | 90.2k | << " not found, cannot add a new TCP option"); |
158 | 90.2k | return TcpOption(nullptr); |
159 | 90.2k | } |
160 | | |
161 | 59.3k | offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; |
162 | 59.3k | } |
163 | | |
164 | 59.3k | return addTcpOptionAt(optionBuilder, offset); |
165 | 149k | } |
166 | | |
167 | | bool TcpLayer::removeTcpOption(const TcpOptionEnumType optionType) |
168 | 0 | { |
169 | 0 | const TcpOption opt = getTcpOption(optionType); |
170 | 0 | if (opt.isNull()) |
171 | 0 | { |
172 | 0 | return false; |
173 | 0 | } |
174 | | |
175 | | // calculate total TCP option size |
176 | 0 | TcpOption curOpt = getFirstTcpOption(); |
177 | 0 | size_t totalOptSize = 0; |
178 | 0 | while (!curOpt.isNull()) |
179 | 0 | { |
180 | 0 | totalOptSize += curOpt.getTotalSize(); |
181 | 0 | curOpt = getNextTcpOption(curOpt); |
182 | 0 | } |
183 | 0 | totalOptSize -= opt.getTotalSize(); |
184 | |
|
185 | 0 | int offset = opt.getRecordBasePtr() - m_Data; |
186 | |
|
187 | 0 | if (!shortenLayer(offset, opt.getTotalSize())) |
188 | 0 | { |
189 | 0 | return false; |
190 | 0 | } |
191 | | |
192 | 0 | adjustTcpOptionTrailer(totalOptSize); |
193 | |
|
194 | 0 | m_OptionReader.changeTLVRecordCount(-1); |
195 | |
|
196 | 0 | return true; |
197 | 0 | } |
198 | | |
199 | | bool TcpLayer::removeAllTcpOptions() |
200 | 0 | { |
201 | 0 | const int offset = sizeof(tcphdr); |
202 | |
|
203 | 0 | if (!shortenLayer(offset, getHeaderLen() - offset)) |
204 | 0 | return false; |
205 | | |
206 | 0 | getTcpHeader()->dataOffset = sizeof(tcphdr) / 4; |
207 | 0 | m_NumOfTrailingBytes = 0; |
208 | 0 | m_OptionReader.changeTLVRecordCount(0 - getTcpOptionCount()); |
209 | 0 | return true; |
210 | 0 | } |
211 | | |
212 | | TcpOption TcpLayer::addTcpOptionAt(const TcpOptionBuilder& optionBuilder, const int offset) |
213 | 59.3k | { |
214 | 59.3k | TcpOption newOption = optionBuilder.build(); |
215 | 59.3k | if (newOption.isNull()) |
216 | 0 | return newOption; |
217 | | |
218 | | // calculate total TCP option size |
219 | 59.3k | TcpOption curOpt = getFirstTcpOption(); |
220 | 59.3k | size_t totalOptSize = 0; |
221 | 254k | while (!curOpt.isNull()) |
222 | 195k | { |
223 | 195k | totalOptSize += curOpt.getTotalSize(); |
224 | 195k | curOpt = getNextTcpOption(curOpt); |
225 | 195k | } |
226 | 59.3k | totalOptSize += newOption.getTotalSize(); |
227 | | |
228 | 59.3k | size_t sizeToExtend = newOption.getTotalSize(); |
229 | | |
230 | 59.3k | if (!extendLayer(offset, sizeToExtend)) |
231 | 0 | { |
232 | 0 | PCPP_LOG_ERROR("Could not extend TcpLayer in [" << sizeToExtend << "] bytes"); |
233 | 0 | newOption.purgeRecordData(); |
234 | 0 | return TcpOption(nullptr); |
235 | 0 | } |
236 | | |
237 | 59.3k | memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize()); |
238 | | |
239 | 59.3k | newOption.purgeRecordData(); |
240 | | |
241 | 59.3k | adjustTcpOptionTrailer(totalOptSize); |
242 | | |
243 | 59.3k | m_OptionReader.changeTLVRecordCount(1); |
244 | | |
245 | 59.3k | uint8_t* newOptPtr = m_Data + offset; |
246 | | |
247 | 59.3k | return TcpOption(newOptPtr); |
248 | 59.3k | } |
249 | | |
250 | | void TcpLayer::adjustTcpOptionTrailer(const size_t totalOptSize) |
251 | 59.3k | { |
252 | 59.3k | int newNumberOfTrailingBytes = 0; |
253 | 233k | while ((totalOptSize + newNumberOfTrailingBytes) % 4 != 0) |
254 | 174k | newNumberOfTrailingBytes++; |
255 | | |
256 | 59.3k | if (newNumberOfTrailingBytes < m_NumOfTrailingBytes) |
257 | 0 | shortenLayer(sizeof(tcphdr) + totalOptSize, m_NumOfTrailingBytes - newNumberOfTrailingBytes - 1); |
258 | 59.3k | else if (newNumberOfTrailingBytes > m_NumOfTrailingBytes) |
259 | 58.7k | extendLayer(sizeof(tcphdr) + totalOptSize, newNumberOfTrailingBytes - m_NumOfTrailingBytes); |
260 | | |
261 | 59.3k | m_NumOfTrailingBytes = newNumberOfTrailingBytes; |
262 | | |
263 | 233k | for (int i = 0; i < m_NumOfTrailingBytes; i++) |
264 | 174k | m_Data[sizeof(tcphdr) + totalOptSize + i] = TCPOPT_DUMMY; |
265 | | |
266 | 59.3k | getTcpHeader()->dataOffset = (sizeof(tcphdr) + totalOptSize + m_NumOfTrailingBytes) / 4; |
267 | 59.3k | } |
268 | | |
269 | | uint16_t TcpLayer::calculateChecksum(const bool writeResultToPacket) |
270 | 149k | { |
271 | 149k | tcphdr* tcpHdr = getTcpHeader(); |
272 | 149k | uint16_t checksumRes = 0; |
273 | 149k | const uint16_t currChecksumValue = tcpHdr->headerChecksum; |
274 | | |
275 | 149k | if (m_PrevLayer != nullptr) |
276 | 149k | { |
277 | 149k | tcpHdr->headerChecksum = 0; |
278 | 149k | PCPP_LOG_DEBUG("TCP data len = " << m_DataLen); |
279 | | |
280 | 149k | if (m_PrevLayer->getProtocol() == IPv4) |
281 | 102k | { |
282 | 102k | const IPv4Address srcIP = static_cast<IPv4Layer*>(m_PrevLayer)->getSrcIPv4Address(); |
283 | 102k | const IPv4Address dstIP = static_cast<IPv4Layer*>(m_PrevLayer)->getDstIPv4Address(); |
284 | | |
285 | 102k | checksumRes = |
286 | 102k | pcpp::computePseudoHdrChecksum(reinterpret_cast<uint8_t*>(tcpHdr), getDataLen(), |
287 | 102k | IPAddress::IPv4AddressType, PACKETPP_IPPROTO_TCP, srcIP, dstIP); |
288 | | |
289 | 102k | PCPP_LOG_DEBUG("calculated IPv4 TCP checksum = 0x" << std::uppercase << std::hex << checksumRes); |
290 | 102k | } |
291 | 46.9k | else if (m_PrevLayer->getProtocol() == IPv6) |
292 | 46.9k | { |
293 | 46.9k | const IPv6Address srcIP = static_cast<IPv6Layer*>(m_PrevLayer)->getSrcIPv6Address(); |
294 | 46.9k | const IPv6Address dstIP = static_cast<IPv6Layer*>(m_PrevLayer)->getDstIPv6Address(); |
295 | | |
296 | 46.9k | checksumRes = computePseudoHdrChecksum(reinterpret_cast<uint8_t*>(tcpHdr), getDataLen(), |
297 | 46.9k | IPAddress::IPv6AddressType, PACKETPP_IPPROTO_TCP, srcIP, dstIP); |
298 | | |
299 | 46.9k | PCPP_LOG_DEBUG("calculated IPv6 TCP checksum = 0xX" << std::uppercase << std::hex << checksumRes); |
300 | 46.9k | } |
301 | 149k | } |
302 | | |
303 | 149k | if (writeResultToPacket) |
304 | 149k | tcpHdr->headerChecksum = htobe16(checksumRes); |
305 | 0 | else |
306 | 0 | tcpHdr->headerChecksum = currChecksumValue; |
307 | | |
308 | 149k | return checksumRes; |
309 | 149k | } |
310 | | |
311 | | void TcpLayer::initLayer() |
312 | 0 | { |
313 | 0 | m_DataLen = sizeof(tcphdr); |
314 | 0 | m_Data = new uint8_t[m_DataLen]; |
315 | 0 | memset(m_Data, 0, m_DataLen); |
316 | 0 | m_Protocol = TCP; |
317 | 0 | m_NumOfTrailingBytes = 0; |
318 | 0 | getTcpHeader()->dataOffset = sizeof(tcphdr) / 4; |
319 | 0 | } |
320 | | |
321 | | TcpLayer::TcpLayer(uint8_t* data, const size_t dataLen, Layer* prevLayer, Packet* packet) |
322 | 774k | : Layer(data, dataLen, prevLayer, packet, TCP) |
323 | 774k | { |
324 | 774k | m_NumOfTrailingBytes = 0; |
325 | 774k | } |
326 | | |
327 | | TcpLayer::TcpLayer() |
328 | 0 | { |
329 | 0 | initLayer(); |
330 | 0 | } |
331 | | |
332 | | TcpLayer::TcpLayer(const uint16_t portSrc, const uint16_t portDst) |
333 | 0 | { |
334 | 0 | initLayer(); |
335 | 0 | getTcpHeader()->portDst = htobe16(portDst); |
336 | 0 | getTcpHeader()->portSrc = htobe16(portSrc); |
337 | 0 | } |
338 | | |
339 | | void TcpLayer::copyLayerData(const TcpLayer& other) |
340 | 149k | { |
341 | 149k | m_OptionReader = other.m_OptionReader; |
342 | 149k | m_NumOfTrailingBytes = other.m_NumOfTrailingBytes; |
343 | 149k | } |
344 | | |
345 | 149k | TcpLayer::TcpLayer(const TcpLayer& other) : Layer(other) |
346 | 149k | { |
347 | 149k | copyLayerData(other); |
348 | 149k | } |
349 | | |
350 | | TcpLayer& TcpLayer::operator=(const TcpLayer& other) |
351 | 0 | { |
352 | 0 | Layer::operator=(other); |
353 | |
|
354 | 0 | copyLayerData(other); |
355 | |
|
356 | 0 | return *this; |
357 | 0 | } |
358 | | |
359 | | void TcpLayer::parseNextLayer() |
360 | 774k | { |
361 | 774k | const size_t headerLen = getHeaderLen(); |
362 | 774k | if (m_DataLen <= headerLen) |
363 | 87.8k | return; |
364 | | |
365 | 686k | uint8_t* payload = m_Data + headerLen; |
366 | 686k | const size_t payloadLen = m_DataLen - headerLen; |
367 | 686k | const uint16_t portDst = getDstPort(); |
368 | 686k | const uint16_t portSrc = getSrcPort(); |
369 | 686k | const char* payloadChar = reinterpret_cast<const char*>(payload); |
370 | | |
371 | 686k | if (HttpMessage::isHttpPort(portDst) && |
372 | 115k | HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) |
373 | 96.0k | { |
374 | 96.0k | constructNextLayer<HttpRequestLayer>(payload, payloadLen, getAttachedPacket()); |
375 | 96.0k | } |
376 | 590k | else if (HttpMessage::isHttpPort(portSrc) && |
377 | 24.7k | HttpResponseFirstLine::parseVersion(payloadChar, payloadLen) != HttpVersion::HttpVersionUnknown && |
378 | 15.0k | !HttpResponseFirstLine::parseStatusCode(payloadChar, payloadLen).isUnsupportedCode()) |
379 | 14.6k | { |
380 | 14.6k | constructNextLayer<HttpResponseLayer>(payload, payloadLen, getAttachedPacket()); |
381 | 14.6k | } |
382 | 575k | else if (SSLLayer::IsSSLMessage(portSrc, portDst, payload, payloadLen)) |
383 | 260k | { |
384 | 260k | constructNextLayerFromFactory(SSLLayer::createSSLMessage, payload, payloadLen); |
385 | 260k | } |
386 | 315k | else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc)) |
387 | 719 | { |
388 | 719 | if (SipRequestFirstLine::parseMethod(payloadChar, payloadLen) != SipRequestLayer::SipMethodUnknown) |
389 | 0 | { |
390 | 0 | constructNextLayer<SipRequestLayer>(payload, payloadLen, getAttachedPacket()); |
391 | 0 | } |
392 | 719 | else if (SipResponseFirstLine::parseStatusCode(payloadChar, payloadLen) != |
393 | 719 | SipResponseLayer::SipStatusCodeUnknown) |
394 | 28 | { |
395 | 28 | constructNextLayer<SipResponseLayer>(payload, payloadLen, getAttachedPacket()); |
396 | 28 | } |
397 | 691 | else |
398 | 691 | { |
399 | 691 | constructNextLayer<PayloadLayer>(payload, payloadLen, getAttachedPacket()); |
400 | 691 | } |
401 | 719 | } |
402 | 314k | else if (BgpLayer::isBgpPort(portSrc, portDst)) |
403 | 29.7k | { |
404 | 29.7k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(BgpLayer::parseBgpLayer, payload, payloadLen); |
405 | 29.7k | } |
406 | 284k | else if (SSHLayer::isSSHPort(portSrc, portDst)) |
407 | 8.94k | { |
408 | 8.94k | constructNextLayerFromFactory(SSHLayer::createSSHMessage, payload, payloadLen); |
409 | 8.94k | } |
410 | 275k | else if (DnsLayer::isDataValid(payload, payloadLen, true) && |
411 | 214k | (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc))) |
412 | 2.17k | { |
413 | 2.17k | constructNextLayer<DnsOverTcpLayer>(payload, payloadLen, getAttachedPacket()); |
414 | 2.17k | } |
415 | 273k | else if (TelnetLayer::isDataValid(payload, payloadLen) && |
416 | 273k | (TelnetLayer::isTelnetPort(portDst) || TelnetLayer::isTelnetPort(portSrc))) |
417 | 9.36k | { |
418 | 9.36k | constructNextLayer<TelnetLayer>(payload, payloadLen, getAttachedPacket()); |
419 | 9.36k | } |
420 | 264k | else if (FtpLayer::isFtpPort(portSrc) && FtpLayer::isDataValid(payload, payloadLen)) |
421 | 9.11k | { |
422 | 9.11k | constructNextLayer<FtpResponseLayer>(payload, payloadLen, getAttachedPacket()); |
423 | 9.11k | } |
424 | 255k | else if (FtpLayer::isFtpPort(portDst) && FtpLayer::isDataValid(payload, payloadLen)) |
425 | 4.55k | { |
426 | 4.55k | constructNextLayer<FtpRequestLayer>(payload, payloadLen, getAttachedPacket()); |
427 | 4.55k | } |
428 | 250k | else if (FtpLayer::isFtpDataPort(portSrc) || FtpLayer::isFtpDataPort(portDst)) |
429 | 1.20k | { |
430 | 1.20k | constructNextLayer<FtpDataLayer>(payload, payloadLen, getAttachedPacket()); |
431 | 1.20k | } |
432 | 249k | else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) && |
433 | 190 | (DoIpLayer::isDataValid(payload, payloadLen))) |
434 | 0 | { |
435 | 0 | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(DoIpLayer::parseDoIpLayer, payload, payloadLen); |
436 | 0 | } |
437 | 249k | else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) |
438 | 300 | { |
439 | 300 | constructNextLayerFromFactory(SomeIpLayer::parseSomeIpLayer, payload, payloadLen); |
440 | 300 | } |
441 | 249k | else if (TpktLayer::isDataValid(payload, payloadLen) && TpktLayer::isTpktPort(portSrc, portDst)) |
442 | 10.6k | { |
443 | 10.6k | constructNextLayer<TpktLayer>(payload, payloadLen, getAttachedPacket()); |
444 | 10.6k | } |
445 | 238k | else if (SmtpLayer::isSmtpPort(portSrc) && SmtpLayer::isDataValid(payload, payloadLen)) |
446 | 6.19k | { |
447 | 6.19k | constructNextLayer<SmtpResponseLayer>(payload, payloadLen, getAttachedPacket()); |
448 | 6.19k | } |
449 | 232k | else if (SmtpLayer::isSmtpPort(portDst) && SmtpLayer::isDataValid(payload, payloadLen)) |
450 | 8.55k | { |
451 | 8.55k | constructNextLayer<SmtpRequestLayer>(payload, payloadLen, getAttachedPacket()); |
452 | 8.55k | } |
453 | 223k | else if (LdapLayer::isLdapPort(portDst) || LdapLayer::isLdapPort(portSrc)) |
454 | 7.18k | { |
455 | 7.18k | tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(LdapLayer::parseLdapMessage, payload, |
456 | 7.18k | payloadLen); |
457 | 7.18k | } |
458 | 216k | else if ((GtpV2Layer::isGTPv2Port(portDst) || GtpV2Layer::isGTPv2Port(portSrc)) && |
459 | 50 | GtpV2Layer::isDataValid(payload, payloadLen)) |
460 | 25 | { |
461 | 25 | constructNextLayer<GtpV2Layer>(payload, payloadLen, getAttachedPacket()); |
462 | 25 | } |
463 | 216k | else if (ModbusLayer::isModbusPort(portDst)) |
464 | 1.96k | { |
465 | 1.96k | constructNextLayer<ModbusLayer>(payload, payloadLen, getAttachedPacket()); |
466 | 1.96k | } |
467 | 214k | else |
468 | 214k | { |
469 | 214k | constructNextLayer<PayloadLayer>(payload, payloadLen, getAttachedPacket()); |
470 | 214k | } |
471 | 686k | } |
472 | | |
473 | | void TcpLayer::computeCalculateFields() |
474 | 149k | { |
475 | 149k | tcphdr* tcpHdr = getTcpHeader(); |
476 | | |
477 | 149k | tcpHdr->dataOffset = getHeaderLen() >> 2; |
478 | 149k | calculateChecksum(true); |
479 | 149k | } |
480 | | |
481 | | std::string TcpLayer::toString() const |
482 | 299k | { |
483 | 299k | const tcphdr* hdr = getTcpHeader(); |
484 | 299k | std::string result = "TCP Layer, "; |
485 | 299k | if (hdr->synFlag) |
486 | 32.6k | { |
487 | 32.6k | if (hdr->ackFlag) |
488 | 9.31k | result += "[SYN, ACK], "; |
489 | 23.3k | else |
490 | 23.3k | result += "[SYN], "; |
491 | 32.6k | } |
492 | 266k | else if (hdr->finFlag) |
493 | 8.47k | { |
494 | 8.47k | if (hdr->ackFlag) |
495 | 7.43k | result += "[FIN, ACK], "; |
496 | 1.04k | else |
497 | 1.04k | result += "[FIN], "; |
498 | 8.47k | } |
499 | 257k | else if (hdr->ackFlag) |
500 | 251k | result += "[ACK], "; |
501 | | |
502 | 299k | std::ostringstream srcPortStream; |
503 | 299k | srcPortStream << getSrcPort(); |
504 | 299k | std::ostringstream dstPortStream; |
505 | 299k | dstPortStream << getDstPort(); |
506 | 299k | result += "Src port: " + srcPortStream.str() + ", Dst port: " + dstPortStream.str(); |
507 | | |
508 | 299k | return result; |
509 | 299k | } |
510 | | |
511 | | /// ~~~~~~~~ |
512 | | /// TcpLayer Deprecated Code |
513 | | /// ~~~~~~~~ |
514 | | |
515 | | DISABLE_WARNING_PUSH |
516 | | DISABLE_WARNING_DEPRECATED |
517 | | TcpOption TcpLayer::addTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionType prevOptionType) |
518 | 0 | { |
519 | 0 | int offset = 0; |
520 | |
|
521 | 0 | if (prevOptionType == TcpOptionType::TCPOPT_Unknown) |
522 | 0 | { |
523 | 0 | offset = sizeof(tcphdr); |
524 | 0 | } |
525 | 0 | else |
526 | 0 | { |
527 | 0 | TcpOption prevOpt = getTcpOption(prevOptionType); |
528 | 0 | if (prevOpt.isNull()) |
529 | 0 | { |
530 | 0 | PCPP_LOG_ERROR("Previous option of type " << static_cast<int>(prevOptionType) |
531 | 0 | << " not found, cannot add a new TCP option"); |
532 | 0 | return TcpOption(nullptr); |
533 | 0 | } |
534 | | |
535 | 0 | offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; |
536 | 0 | } |
537 | | |
538 | 0 | return addTcpOptionAt(optionBuilder, offset); |
539 | 0 | } |
540 | | |
541 | | TcpOption TcpLayer::getTcpOption(TcpOptionType option) const |
542 | 0 | { |
543 | 0 | return m_OptionReader.getTLVRecord(static_cast<uint8_t>(option), getOptionsBasePtr(), |
544 | 0 | getHeaderLen() - sizeof(tcphdr)); |
545 | 0 | } |
546 | | |
547 | | bool TcpLayer::removeTcpOption(TcpOptionType optionType) |
548 | 0 | { |
549 | 0 | TcpOption opt = getTcpOption(optionType); |
550 | 0 | if (opt.isNull()) |
551 | 0 | { |
552 | 0 | return false; |
553 | 0 | } |
554 | | |
555 | | // calculate total TCP option size |
556 | 0 | TcpOption curOpt = getFirstTcpOption(); |
557 | 0 | size_t totalOptSize = 0; |
558 | 0 | while (!curOpt.isNull()) |
559 | 0 | { |
560 | 0 | totalOptSize += curOpt.getTotalSize(); |
561 | 0 | curOpt = getNextTcpOption(curOpt); |
562 | 0 | } |
563 | 0 | totalOptSize -= opt.getTotalSize(); |
564 | |
|
565 | 0 | int offset = opt.getRecordBasePtr() - m_Data; |
566 | |
|
567 | 0 | if (!shortenLayer(offset, opt.getTotalSize())) |
568 | 0 | { |
569 | 0 | return false; |
570 | 0 | } |
571 | | |
572 | 0 | adjustTcpOptionTrailer(totalOptSize); |
573 | |
|
574 | 0 | m_OptionReader.changeTLVRecordCount(-1); |
575 | |
|
576 | 0 | return true; |
577 | 0 | } |
578 | | DISABLE_WARNING_POP |
579 | | |
580 | | } // namespace pcpp |