/src/PcapPlusPlus/Packet++/header/TcpLayer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "Layer.h" |
4 | | #include "TLVData.h" |
5 | | #include <string.h> |
6 | | |
7 | | /// @file |
8 | | |
9 | | /** |
10 | | * \namespace pcpp |
11 | | * \brief The main namespace for the PcapPlusPlus lib |
12 | | */ |
13 | | namespace pcpp |
14 | | { |
15 | | |
16 | | /** |
17 | | * @struct tcphdr |
18 | | * Represents an TCP protocol header |
19 | | */ |
20 | | #pragma pack(push,1) |
21 | | struct tcphdr |
22 | | { |
23 | | /** Source TCP port */ |
24 | | uint16_t portSrc; |
25 | | /** Destination TCP port */ |
26 | | uint16_t portDst; |
27 | | /** Sequence number */ |
28 | | uint32_t sequenceNumber; |
29 | | /** Acknowledgment number */ |
30 | | uint32_t ackNumber; |
31 | | #if (BYTE_ORDER == LITTLE_ENDIAN) |
32 | | uint16_t reserved:4, |
33 | | /** Specifies the size of the TCP header in 32-bit words */ |
34 | | dataOffset:4, |
35 | | /** FIN flag */ |
36 | | finFlag:1, |
37 | | /** SYN flag */ |
38 | | synFlag:1, |
39 | | /** RST flag */ |
40 | | rstFlag:1, |
41 | | /** PSH flag */ |
42 | | pshFlag:1, |
43 | | /** ACK flag */ |
44 | | ackFlag:1, |
45 | | /** URG flag */ |
46 | | urgFlag:1, |
47 | | /** ECE flag */ |
48 | | eceFlag:1, |
49 | | /** CWR flag */ |
50 | | cwrFlag:1; |
51 | | #elif (BYTE_ORDER == BIG_ENDIAN) |
52 | | /** Specifies the size of the TCP header in 32-bit words */ |
53 | | uint16_t dataOffset:4, |
54 | | reserved:4, |
55 | | /** CWR flag */ |
56 | | cwrFlag:1, |
57 | | /** ECE flag */ |
58 | | eceFlag:1, |
59 | | /** URG flag */ |
60 | | urgFlag:1, |
61 | | /** ACK flag */ |
62 | | ackFlag:1, |
63 | | /** PSH flag */ |
64 | | pshFlag:1, |
65 | | /** RST flag */ |
66 | | rstFlag:1, |
67 | | /** SYN flag */ |
68 | | synFlag:1, |
69 | | /** FIN flag */ |
70 | | finFlag:1; |
71 | | #else |
72 | | #error "Endian is not LE nor BE..." |
73 | | #endif |
74 | | /** The size of the receive window, which specifies the number of window size units (by default, bytes) */ |
75 | | uint16_t windowSize; |
76 | | /** The 16-bit checksum field is used for error-checking of the header and data */ |
77 | | uint16_t headerChecksum; |
78 | | /** If the URG flag (@ref tcphdr#urgFlag) is set, then this 16-bit field is an offset from the sequence number indicating the last urgent data byte */ |
79 | | uint16_t urgentPointer; |
80 | | }; |
81 | | #pragma pack(pop) |
82 | | |
83 | | |
84 | | /** |
85 | | * TCP options types |
86 | | */ |
87 | | enum TcpOptionType : uint8_t |
88 | | { |
89 | | /** Padding */ |
90 | | PCPP_TCPOPT_NOP = 1, |
91 | | /** End of options */ |
92 | | PCPP_TCPOPT_EOL = 0, |
93 | | /** Segment size negotiating */ |
94 | | TCPOPT_MSS = 2, |
95 | | /** Window scaling */ |
96 | | PCPP_TCPOPT_WINDOW = 3, |
97 | | /** SACK Permitted */ |
98 | | TCPOPT_SACK_PERM = 4, |
99 | | /** SACK Block */ |
100 | | PCPP_TCPOPT_SACK = 5, |
101 | | /** Echo (obsoleted by option ::PCPP_TCPOPT_TIMESTAMP) */ |
102 | | TCPOPT_ECHO = 6, |
103 | | /** Echo Reply (obsoleted by option ::PCPP_TCPOPT_TIMESTAMP) */ |
104 | | TCPOPT_ECHOREPLY = 7, |
105 | | /** TCP Timestamps */ |
106 | | PCPP_TCPOPT_TIMESTAMP = 8, |
107 | | /** CC (obsolete) */ |
108 | | TCPOPT_CC = 11, |
109 | | /** CC.NEW (obsolete) */ |
110 | | TCPOPT_CCNEW = 12, |
111 | | /** CC.ECHO(obsolete) */ |
112 | | TCPOPT_CCECHO = 13, |
113 | | /** MD5 Signature Option */ |
114 | | TCPOPT_MD5 = 19, |
115 | | /** Multipath TCP */ |
116 | | TCPOPT_MPTCP = 0x1e, |
117 | | /** SCPS Capabilities */ |
118 | | TCPOPT_SCPS = 20, |
119 | | /** SCPS SNACK */ |
120 | | TCPOPT_SNACK = 21, |
121 | | /** SCPS Record Boundary */ |
122 | | TCPOPT_RECBOUND = 22, |
123 | | /** SCPS Corruption Experienced */ |
124 | | TCPOPT_CORREXP = 23, |
125 | | /** Quick-Start Response */ |
126 | | TCPOPT_QS = 27, |
127 | | /** User Timeout Option (also, other known unauthorized use) */ |
128 | | TCPOPT_USER_TO = 28, |
129 | | /** RFC3692-style Experiment 1 (also improperly used for shipping products) */ |
130 | | TCPOPT_EXP_FD = 0xfd, |
131 | | /** RFC3692-style Experiment 2 (also improperly used for shipping products) */ |
132 | | TCPOPT_EXP_FE = 0xfe, |
133 | | /** Riverbed probe option, non IANA registered option number */ |
134 | | TCPOPT_RVBD_PROBE = 76, |
135 | | /** Riverbed transparency option, non IANA registered option number */ |
136 | | TCPOPT_RVBD_TRPY = 78, |
137 | | /** Unknown option */ |
138 | | TCPOPT_Unknown = 255 |
139 | | }; |
140 | | |
141 | | |
142 | | // TCP option lengths |
143 | | |
144 | | /** pcpp::PCPP_TCPOPT_NOP length */ |
145 | | #define PCPP_TCPOLEN_NOP 1 |
146 | | /** pcpp::PCPP_TCPOPT_EOL length */ |
147 | | #define PCPP_TCPOLEN_EOL 1 |
148 | | /** pcpp::TCPOPT_MSS length */ |
149 | | #define PCPP_TCPOLEN_MSS 4 |
150 | | /** pcpp::PCPP_TCPOPT_WINDOW length */ |
151 | | #define PCPP_TCPOLEN_WINDOW 3 |
152 | | /** pcpp::TCPOPT_SACK_PERM length */ |
153 | | #define PCPP_TCPOLEN_SACK_PERM 2 |
154 | | /** pcpp::PCPP_TCPOPT_SACK length */ |
155 | | #define PCPP_TCPOLEN_SACK_MIN 2 |
156 | | /** pcpp::TCPOPT_ECHO length */ |
157 | | #define PCPP_TCPOLEN_ECHO 6 |
158 | | /** pcpp::TCPOPT_ECHOREPLY length */ |
159 | | #define PCPP_TCPOLEN_ECHOREPLY 6 |
160 | | /** pcpp::PCPP_TCPOPT_TIMESTAMP length */ |
161 | | #define PCPP_TCPOLEN_TIMESTAMP 10 |
162 | | /** pcpp::TCPOPT_CC length */ |
163 | | #define PCPP_TCPOLEN_CC 6 |
164 | | /** pcpp::TCPOPT_CCNEW length */ |
165 | | #define PCPP_TCPOLEN_CCNEW 6 |
166 | | /** pcpp::TCPOPT_CCECHO length */ |
167 | | #define PCPP_TCPOLEN_CCECHO 6 |
168 | | /** pcpp::TCPOPT_MD5 length */ |
169 | | #define PCPP_TCPOLEN_MD5 18 |
170 | | /** pcpp::TCPOPT_MPTCP length */ |
171 | | #define PCPP_TCPOLEN_MPTCP_MIN 8 |
172 | | /** pcpp::TCPOPT_SCPS length */ |
173 | | #define PCPP_TCPOLEN_SCPS 4 |
174 | | /** pcpp::TCPOPT_SNACK length */ |
175 | | #define PCPP_TCPOLEN_SNACK 6 |
176 | | /** pcpp::TCPOPT_RECBOUND length */ |
177 | | #define PCPP_TCPOLEN_RECBOUND 2 |
178 | | /** pcpp::TCPOPT_CORREXP length */ |
179 | | #define PCPP_TCPOLEN_CORREXP 2 |
180 | | /** pcpp::TCPOPT_QS length */ |
181 | | #define PCPP_TCPOLEN_QS 8 |
182 | | /** pcpp::TCPOPT_USER_TO length */ |
183 | | #define PCPP_TCPOLEN_USER_TO 4 |
184 | | /** pcpp::TCPOPT_RVBD_PROBE length */ |
185 | | #define PCPP_TCPOLEN_RVBD_PROBE_MIN 3 |
186 | | /** pcpp::TCPOPT_RVBD_TRPY length */ |
187 | | #define PCPP_TCPOLEN_RVBD_TRPY_MIN 16 |
188 | | /** pcpp::TCPOPT_EXP_FD and pcpp::TCPOPT_EXP_FE length */ |
189 | | #define PCPP_TCPOLEN_EXP_MIN 2 |
190 | | |
191 | | |
192 | | |
193 | | /** |
194 | | * @class TcpOption |
195 | | * A wrapper class for TCP options. This class does not create or modify TCP option records, but rather |
196 | | * serves as a wrapper and provides useful methods for retrieving data from them |
197 | | */ |
198 | | class TcpOption : public TLVRecord<uint8_t, uint8_t> |
199 | | { |
200 | | public: |
201 | | |
202 | | /** |
203 | | * A c'tor for this class that gets a pointer to the option raw data (byte array) |
204 | | * @param[in] optionRawData A pointer to the TCP option raw data |
205 | | */ |
206 | 494k | explicit TcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) { } |
207 | | |
208 | | /** |
209 | | * A d'tor for this class, currently does nothing |
210 | | */ |
211 | 0 | ~TcpOption() { } |
212 | | |
213 | | /** |
214 | | * @return TCP option type casted as pcpp::TcpOptionType enum. If the data is null a value |
215 | | * of ::TCPOPT_Unknown is returned |
216 | | */ |
217 | | TcpOptionType getTcpOptionType() const |
218 | 0 | { |
219 | 0 | return getTcpOptionType(m_Data); |
220 | 0 | } |
221 | | |
222 | | /** |
223 | | * Check if a pointer can be assigned to the TLV record data |
224 | | * @param[in] recordRawData A pointer to the TLV record raw data |
225 | | * @param[in] tlvDataLen The size of the TLV record raw data |
226 | | * @return True if data is valid and can be assigned |
227 | | */ |
228 | | static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen) |
229 | 327k | { |
230 | 327k | const auto* data = reinterpret_cast<const TLVRawData*>(recordRawData); |
231 | 327k | if (data == nullptr) |
232 | 0 | return false; |
233 | | |
234 | 327k | if (tlvDataLen < sizeof(TLVRawData::recordType)) |
235 | 110k | return false; |
236 | | |
237 | 217k | const auto recordType = getTcpOptionType(data); |
238 | 217k | if (recordType == TcpOptionType::PCPP_TCPOPT_NOP || recordType == TcpOptionType::PCPP_TCPOPT_EOL) |
239 | 136k | return true; |
240 | | |
241 | 81.4k | return TLVRecord<uint8_t, uint8_t>::canAssign(recordRawData, tlvDataLen); |
242 | 217k | } |
243 | | |
244 | | // implement abstract methods |
245 | | |
246 | | size_t getTotalSize() const |
247 | 1.18M | { |
248 | 1.18M | if (m_Data == nullptr) |
249 | 0 | return 0; |
250 | | |
251 | 1.18M | const auto recordType = getTcpOptionType(m_Data); |
252 | 1.18M | if (recordType == TcpOptionType::PCPP_TCPOPT_NOP || recordType == TcpOptionType::PCPP_TCPOPT_EOL) |
253 | 811k | return sizeof(uint8_t); |
254 | | |
255 | 375k | return static_cast<size_t>(m_Data->recordLen); |
256 | 1.18M | } |
257 | | |
258 | | size_t getDataSize() const |
259 | 0 | { |
260 | 0 | if (m_Data == nullptr) |
261 | 0 | return 0; |
262 | | |
263 | 0 | const auto recordType = getTcpOptionType(m_Data); |
264 | 0 | if (recordType == TcpOptionType::PCPP_TCPOPT_NOP || recordType == TcpOptionType::PCPP_TCPOPT_EOL) |
265 | 0 | return 0; |
266 | | |
267 | 0 | return static_cast<size_t>(m_Data->recordLen) - (2*sizeof(uint8_t)); |
268 | 0 | } |
269 | | |
270 | | private: |
271 | | static TcpOptionType getTcpOptionType(const TLVRawData* optionRawData) |
272 | 1.40M | { |
273 | 1.40M | if (optionRawData == nullptr) |
274 | 0 | return TcpOptionType::TCPOPT_Unknown; |
275 | | |
276 | 1.40M | return static_cast<TcpOptionType>(optionRawData->recordType); |
277 | 1.40M | } |
278 | | }; |
279 | | |
280 | | |
281 | | /** |
282 | | * @class TcpOptionBuilder |
283 | | * A class for building TCP option records. This builder receives the TCP option parameters in its c'tor, |
284 | | * builds the TCP option raw buffer and provides a build() method to get a TcpOption object out of it |
285 | | */ |
286 | | class TcpOptionBuilder : public TLVRecordBuilder |
287 | | { |
288 | | |
289 | | public: |
290 | | |
291 | | /** |
292 | | * An enum to describe NOP and EOL TCP options. Used in one of this class's c'tors |
293 | | */ |
294 | | enum NopEolOptionTypes : uint8_t |
295 | | { |
296 | | /** NOP TCP option */ |
297 | | NOP, |
298 | | /** EOL TCP option */ |
299 | | EOL |
300 | | }; |
301 | | |
302 | | /** |
303 | | * A c'tor for building TCP options which their value is a byte array. The TcpOption object can be later |
304 | | * retrieved by calling build() |
305 | | * @param[in] optionType TCP option type |
306 | | * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way. |
307 | | * @param[in] optionValueLen Option value length in bytes |
308 | | */ |
309 | | TcpOptionBuilder(TcpOptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen) : |
310 | 0 | TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) {} |
311 | | |
312 | | /** |
313 | | * A c'tor for building TCP options which have a 1-byte value. The TcpOption object can be later retrieved |
314 | | * by calling build() |
315 | | * @param[in] optionType TCP option type |
316 | | * @param[in] optionValue A 1-byte option value |
317 | | */ |
318 | | TcpOptionBuilder(TcpOptionType optionType, uint8_t optionValue) : |
319 | 0 | TLVRecordBuilder((uint8_t)optionType, optionValue) {} |
320 | | |
321 | | /** |
322 | | * A c'tor for building TCP options which have a 2-byte value. The TcpOption object can be later retrieved |
323 | | * by calling build() |
324 | | * @param[in] optionType TCP option type |
325 | | * @param[in] optionValue A 2-byte option value |
326 | | */ |
327 | | TcpOptionBuilder(TcpOptionType optionType, uint16_t optionValue) : |
328 | 0 | TLVRecordBuilder((uint8_t)optionType, optionValue) {} |
329 | | |
330 | | /** |
331 | | * A c'tor for building TCP options which have a 4-byte value. The TcpOption object can be later retrieved |
332 | | * by calling build() |
333 | | * @param[in] optionType TCP option type |
334 | | * @param[in] optionValue A 4-byte option value |
335 | | */ |
336 | | TcpOptionBuilder(TcpOptionType optionType, uint32_t optionValue) : |
337 | 0 | TLVRecordBuilder((uint8_t)optionType, optionValue) {} |
338 | | |
339 | | /** |
340 | | * A c'tor for building TCP NOP and EOL options. These option types are special in that they contain only 1 byte |
341 | | * which is the TCP option type (NOP or EOL). The TcpOption object can be later retrieved |
342 | | * by calling build() |
343 | | * @param[in] optionType An enum value indicating which option type to build (NOP or EOL) |
344 | | */ |
345 | | explicit TcpOptionBuilder(NopEolOptionTypes optionType); |
346 | | |
347 | | /** |
348 | | * Build the TcpOption object out of the parameters defined in the c'tor |
349 | | * @return The TcpOption object |
350 | | */ |
351 | | TcpOption build() const; |
352 | | }; |
353 | | |
354 | | |
355 | | /** |
356 | | * @class TcpLayer |
357 | | * Represents a TCP (Transmission Control Protocol) protocol layer |
358 | | */ |
359 | | class TcpLayer : public Layer |
360 | | { |
361 | | public: |
362 | | /** |
363 | | * A constructor that creates the layer from an existing packet raw data |
364 | | * @param[in] data A pointer to the raw data (will be casted to @ref tcphdr) |
365 | | * @param[in] dataLen Size of the data in bytes |
366 | | * @param[in] prevLayer A pointer to the previous layer |
367 | | * @param[in] packet A pointer to the Packet instance where layer will be stored in |
368 | | */ |
369 | | TcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
370 | | |
371 | | /** |
372 | | * A constructor that allocates a new TCP header with zero TCP options |
373 | | */ |
374 | | TcpLayer(); |
375 | | |
376 | | /** |
377 | | * A constructor that allocates a new TCP header with source port and destination port and zero TCP options |
378 | | * @param[in] portSrc Source port |
379 | | * @param[in] portDst Destination port |
380 | | */ |
381 | | TcpLayer(uint16_t portSrc, uint16_t portDst); |
382 | | |
383 | 728k | ~TcpLayer() {} |
384 | | |
385 | | /** |
386 | | * A copy constructor that copy the entire header from the other TcpLayer (including TCP options) |
387 | | */ |
388 | | TcpLayer(const TcpLayer& other); |
389 | | |
390 | | /** |
391 | | * An assignment operator that first delete all data from current layer and then copy the entire header from the other TcpLayer (including TCP options) |
392 | | */ |
393 | | TcpLayer& operator=(const TcpLayer& other); |
394 | | |
395 | | /** |
396 | | * Get a pointer to the TCP header. Notice this points directly to the data, so every change will change the actual packet data |
397 | | * @return A pointer to the @ref tcphdr |
398 | | */ |
399 | 3.46M | tcphdr* getTcpHeader() const { return (tcphdr*)m_Data; } |
400 | | |
401 | | /** |
402 | | * @return TCP source port |
403 | | */ |
404 | | uint16_t getSrcPort() const; |
405 | | |
406 | | /** |
407 | | * @return TCP destination port |
408 | | */ |
409 | | uint16_t getDstPort() const; |
410 | | |
411 | | /** |
412 | | * Get a TCP option by type |
413 | | * @param[in] option TCP option type to retrieve |
414 | | * @return An TcpOption object that contains the first option that matches this type, or logical NULL |
415 | | * (TcpOption#isNull() == true) if no such option found |
416 | | */ |
417 | | TcpOption getTcpOption(TcpOptionType option) const; |
418 | | |
419 | | /** |
420 | | * @return The first TCP option in the packet. If the current layer contains no options the returned value will contain |
421 | | * a logical NULL (TcpOption#isNull() == true) |
422 | | */ |
423 | | TcpOption getFirstTcpOption() const; |
424 | | |
425 | | /** |
426 | | * Get the TCP option that comes after a given option. If the given option was the last one, the |
427 | | * returned value will contain a logical NULL (TcpOption#isNull() == true) |
428 | | * @param[in] tcpOption A TCP option object that exists in the current layer |
429 | | * @return A TcpOption object that contains the TCP option data that comes next, or logical NULL if the given |
430 | | * TCP option: (1) was the last one; or (2) contains a logical NULL; or (3) doesn't belong to this packet |
431 | | */ |
432 | | TcpOption getNextTcpOption(TcpOption& tcpOption) const; |
433 | | |
434 | | /** |
435 | | * @return The number of TCP options in this layer |
436 | | */ |
437 | | size_t getTcpOptionCount() const; |
438 | | |
439 | | /** |
440 | | * Add a new TCP option at the end of the layer (after the last TCP option) |
441 | | * @param[in] optionBuilder A TcpOptionBuilder object that contains the TCP option data to be added |
442 | | * @return A TcpOption object that contains the newly added TCP option data or logical NULL |
443 | | * (TcpOption#isNull() == true) if addition failed. In case of a failure a corresponding error message will be |
444 | | * printed to log |
445 | | */ |
446 | | TcpOption addTcpOption(const TcpOptionBuilder& optionBuilder); |
447 | | |
448 | | /** |
449 | | * Add a new TCP option after an existing one |
450 | | * @param[in] optionBuilder A TcpOptionBuilder object that contains the requested TCP option data to be added |
451 | | * @param[in] prevOptionType The TCP option which the newly added option should come after. This is an optional parameter which |
452 | | * gets a default value of ::TCPOPT_Unknown if omitted, which means the new option will be added as the first option in the layer |
453 | | * @return A TcpOption object containing the newly added TCP option data or logical NULL |
454 | | * (TcpOption#isNull() == true) if addition failed. In case of a failure a corresponding error message will be |
455 | | * printed to log |
456 | | */ |
457 | | TcpOption addTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionType prevOptionType = TCPOPT_Unknown); |
458 | | |
459 | | /** |
460 | | * Remove an existing TCP option from the layer. TCP option is found by type |
461 | | * @param[in] optionType The TCP option type to remove |
462 | | * @return True if TCP option was removed or false if type wasn't found or if removal failed (in each case a proper error |
463 | | * will be written to log) |
464 | | */ |
465 | | bool removeTcpOption(TcpOptionType optionType); |
466 | | |
467 | | /** |
468 | | * Remove all TCP options in this layer |
469 | | * @return True if all TCP options were successfully removed or false if removal failed for some reason |
470 | | * (a proper error will be written to log) |
471 | | */ |
472 | | bool removeAllTcpOptions(); |
473 | | |
474 | | |
475 | | /** |
476 | | * Calculate the checksum from header and data and possibly write the result to @ref tcphdr#headerChecksum |
477 | | * @param[in] writeResultToPacket If set to true then checksum result will be written to @ref tcphdr#headerChecksum |
478 | | * @return The checksum result |
479 | | */ |
480 | | uint16_t calculateChecksum(bool writeResultToPacket); |
481 | | |
482 | | /** |
483 | | * The static method makes validation of input data |
484 | | * @param[in] data The pointer to the beginning of byte stream of TCP packet |
485 | | * @param[in] dataLen The length of byte stream |
486 | | * @return True if the data is valid and can represent a TCP packet |
487 | | */ |
488 | | static inline bool isDataValid(const uint8_t* data, size_t dataLen); |
489 | | |
490 | | // implement abstract methods |
491 | | |
492 | | /** |
493 | | * Currently identifies the following next layers: HttpRequestLayer, HttpResponseLayer. Otherwise sets PayloadLayer |
494 | | */ |
495 | | void parseNextLayer(); |
496 | | |
497 | | /** |
498 | | * @return Size of @ref tcphdr + all TCP options |
499 | | */ |
500 | 1.44M | size_t getHeaderLen() const { return getTcpHeader()->dataOffset*4 ;} |
501 | | |
502 | | /** |
503 | | * Calculate @ref tcphdr#headerChecksum field |
504 | | */ |
505 | | void computeCalculateFields(); |
506 | | |
507 | | std::string toString() const; |
508 | | |
509 | 124k | OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; } |
510 | | |
511 | | private: |
512 | | |
513 | | TLVRecordReader<TcpOption> m_OptionReader; |
514 | | int m_NumOfTrailingBytes; |
515 | | |
516 | | void initLayer(); |
517 | 309k | uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(tcphdr); } |
518 | | TcpOption addTcpOptionAt(const TcpOptionBuilder& optionBuilder, int offset); |
519 | | void adjustTcpOptionTrailer(size_t totalOptSize); |
520 | | void copyLayerData(const TcpLayer& other); |
521 | | }; |
522 | | |
523 | | |
524 | | // implementation of inline methods |
525 | | |
526 | | bool TcpLayer::isDataValid(const uint8_t* data, size_t dataLen) |
527 | 614k | { |
528 | 614k | const tcphdr* hdr = reinterpret_cast<const tcphdr*>(data); |
529 | 614k | return dataLen >= sizeof(tcphdr) |
530 | 614k | && hdr->dataOffset >= 5 /* the minimum TCP header size */ |
531 | 614k | && dataLen >= hdr->dataOffset * sizeof(uint32_t); |
532 | 614k | } |
533 | | } // namespace pcpp |