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