2 * Routines for TCP packet disassembly
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include <epan/packet.h>
14 #include <epan/capture_dissectors.h>
15 #include <epan/exceptions.h>
16 #include <epan/addr_resolv.h>
17 #include <epan/ipproto.h>
18 #include <epan/expert.h>
19 #include <epan/ip_opts.h>
20 #include <epan/follow.h>
21 #include <epan/prefs.h>
22 #include <epan/show_exception.h>
23 #include <epan/conversation_table.h>
24 #include <epan/conversation_filter.h>
25 #include <epan/sequence_analysis.h>
26 #include <epan/reassemble.h>
27 #include <epan/decode_as.h>
28 #include <epan/exported_pdu.h>
29 #include <epan/in_cksum.h>
30 #include <epan/proto_data.h>
32 #include <epan/unit_strings.h>
34 #include <wsutil/array.h>
35 #include <wsutil/utf8_entities.h>
36 #include <wsutil/str_util.h>
37 #include <wsutil/wsgcrypt.h>
38 #include <wsutil/pint.h>
39 #include <wsutil/ws_assert.h>
41 #include "packet-tcp.h"
43 void proto_register_tcp(void);
44 void proto_reg_handoff_tcp(void);
45 static void conversation_completeness_fill(char*, uint32_t);
48 static int tcp_follow_tap
;
50 static int exported_pdu_tap
;
52 /* Place TCP summary in proto tree */
53 static bool tcp_summary_in_tree
= true;
55 static inline uint64_t keep_32msb_of_uint64(uint64_t nb
) {
56 return (nb
>> 32) << 32;
59 #define MPTCP_DSS_FLAG_DATA_ACK_PRESENT 0x01
60 #define MPTCP_DSS_FLAG_DATA_ACK_8BYTES 0x02
61 #define MPTCP_DSS_FLAG_MAPPING_PRESENT 0x04
62 #define MPTCP_DSS_FLAG_DSN_8BYTES 0x08
63 #define MPTCP_DSS_FLAG_DATA_FIN_PRESENT 0x10
66 * Flag to control whether to check the TCP checksum.
68 * In at least some Solaris network traces, there are packets with bad
69 * TCP checksums, but the traffic appears to indicate that the packets
70 * *were* received; the packets were probably sent by the host on which
71 * the capture was being done, on a network interface to which
72 * checksumming was offloaded, so that DLPI supplied an un-checksummed
73 * packet to the capture program but a checksummed packet got put onto
76 static bool tcp_check_checksum
;
79 * Window scaling values to be used when not known (set as a preference) */
80 enum scaling_window_value
{
81 WindowScaling_NotKnown
=-1,
100 * Analysis overriding values to be used when not satisfied by the automatic
101 * result. (Accessed through preferences but not stored as a preference)
103 enum override_analysis_value
{
104 OverrideAnalysis_0
=0,
112 * Using enum instead of boolean make API easier
114 enum mptcp_dsn_conversion
{
120 #define MPTCP_TCPRST_FLAG_T_PRESENT 0x1
121 #define MPTCP_TCPRST_FLAG_W_PRESENT 0x2
122 #define MPTCP_TCPRST_FLAG_V_PRESENT 0x4
123 #define MPTCP_TCPRST_FLAG_U_PRESENT 0x8
125 static const value_string mp_tcprst_reasons
[] = {
126 { 0x0, "Unspecified error" },
127 { 0x1, "MPTCP-specific error" },
128 { 0x2, "Lack of resources" },
129 { 0x3, "Administratively prohibited" },
130 { 0x4, "Too much outstanding data" },
131 { 0x5, "Unacceptable performance" },
132 { 0x6, "Middlebox interference" },
136 static int tcp_default_window_scaling
= (int)WindowScaling_NotKnown
;
138 static int tcp_default_override_analysis
= (int)OverrideAnalysis_0
;
140 static int proto_tcp
;
142 static int proto_icmp
;
144 static int proto_tcp_option_nop
;
145 static int proto_tcp_option_eol
;
146 static int proto_tcp_option_timestamp
;
147 static int proto_tcp_option_mss
;
148 static int proto_tcp_option_wscale
;
149 static int proto_tcp_option_sack_perm
;
150 static int proto_tcp_option_sack
;
151 static int proto_tcp_option_echo
;
152 static int proto_tcp_option_echoreply
;
153 static int proto_tcp_option_cc
;
154 static int proto_tcp_option_cc_new
;
155 static int proto_tcp_option_cc_echo
;
156 static int proto_tcp_option_md5
;
157 static int proto_tcp_option_ao
;
158 static int proto_tcp_option_scps
;
159 static int proto_tcp_option_snack
;
160 static int proto_tcp_option_scpsrec
;
161 static int proto_tcp_option_scpscor
;
162 static int proto_tcp_option_qs
;
163 static int proto_tcp_option_user_to
;
164 static int proto_tcp_option_tfo
;
165 static int proto_tcp_option_acc_ecn
;
166 static int proto_tcp_option_rvbd_probe
;
167 static int proto_tcp_option_rvbd_trpy
;
168 static int proto_tcp_option_exp
;
169 static int proto_tcp_option_unknown
;
170 static int proto_mptcp
;
172 static int hf_tcp_srcport
;
173 static int hf_tcp_dstport
;
174 static int hf_tcp_port
;
175 static int hf_tcp_stream
;
176 static int hf_tcp_stream_pnum
;
177 static int hf_tcp_completeness
;
178 static int hf_tcp_completeness_syn
;
179 static int hf_tcp_completeness_syn_ack
;
180 static int hf_tcp_completeness_ack
;
181 static int hf_tcp_completeness_data
;
182 static int hf_tcp_completeness_fin
;
183 static int hf_tcp_completeness_rst
;
184 static int hf_tcp_completeness_str
;
185 static int hf_tcp_seq
;
186 static int hf_tcp_seq_abs
;
187 static int hf_tcp_nxtseq
;
188 static int hf_tcp_ack
;
189 static int hf_tcp_ack_abs
;
190 static int hf_tcp_hdr_len
;
191 static int hf_tcp_flags
;
192 static int hf_tcp_flags_res
;
193 static int hf_tcp_flags_ae
;
194 static int hf_tcp_flags_cwr
;
195 static int hf_tcp_flags_ece
;
196 static int hf_tcp_flags_ace
;
197 static int hf_tcp_flags_urg
;
198 static int hf_tcp_flags_ack
;
199 static int hf_tcp_flags_push
;
200 static int hf_tcp_flags_reset
;
201 static int hf_tcp_flags_syn
;
202 static int hf_tcp_flags_fin
;
203 static int hf_tcp_flags_str
;
204 static int hf_tcp_window_size_value
;
205 static int hf_tcp_window_size
;
206 static int hf_tcp_window_size_scalefactor
;
207 static int hf_tcp_checksum
;
208 static int hf_tcp_checksum_status
;
209 static int hf_tcp_checksum_calculated
;
210 static int hf_tcp_len
;
211 static int hf_tcp_urgent_pointer
;
212 static int hf_tcp_analysis
;
213 static int hf_tcp_analysis_flags
;
214 static int hf_tcp_analysis_bytes_in_flight
;
215 static int hf_tcp_analysis_push_bytes_sent
;
216 static int hf_tcp_analysis_acks_frame
;
217 static int hf_tcp_analysis_ack_rtt
;
218 static int hf_tcp_analysis_first_rtt
;
219 static int hf_tcp_analysis_rto
;
220 static int hf_tcp_analysis_rto_frame
;
221 static int hf_tcp_analysis_duplicate_ack
;
222 static int hf_tcp_analysis_duplicate_ack_num
;
223 static int hf_tcp_analysis_duplicate_ack_frame
;
224 static int hf_tcp_continuation_to
;
225 static int hf_tcp_pdu_time
;
226 static int hf_tcp_pdu_size
;
227 static int hf_tcp_pdu_last_frame
;
228 static int hf_tcp_reassembled_in
;
229 static int hf_tcp_reassembled_length
;
230 static int hf_tcp_reassembled_data
;
231 static int hf_tcp_segments
;
232 static int hf_tcp_segment
;
233 static int hf_tcp_segment_overlap
;
234 static int hf_tcp_segment_overlap_conflict
;
235 static int hf_tcp_segment_multiple_tails
;
236 static int hf_tcp_segment_too_long_fragment
;
237 static int hf_tcp_segment_error
;
238 static int hf_tcp_segment_count
;
239 static int hf_tcp_options
;
240 static int hf_tcp_option_kind
;
241 static int hf_tcp_option_len
;
242 static int hf_tcp_option_mss_val
;
243 static int hf_tcp_option_wscale_shift
;
244 static int hf_tcp_option_wscale_multiplier
;
245 static int hf_tcp_option_sack_sle
;
246 static int hf_tcp_option_sack_sre
;
247 static int hf_tcp_option_sack_range_count
;
248 static int hf_tcp_option_sack_dsack_le
;
249 static int hf_tcp_option_sack_dsack_re
;
250 static int hf_tcp_option_echo
;
251 static int hf_tcp_option_timestamp_tsval
;
252 static int hf_tcp_option_timestamp_tsecr
;
253 static int hf_tcp_option_cc
;
254 static int hf_tcp_option_md5_digest
;
255 static int hf_tcp_option_ao_keyid
;
256 static int hf_tcp_option_ao_rnextkeyid
;
257 static int hf_tcp_option_ao_mac
;
258 static int hf_tcp_option_qs_rate
;
259 static int hf_tcp_option_qs_ttl_diff
;
260 static int hf_tcp_option_tarr_rate
;
261 static int hf_tcp_option_tarr_reserved
;
262 static int hf_tcp_option_acc_ecn_ee0b
;
263 static int hf_tcp_option_acc_ecn_eceb
;
264 static int hf_tcp_option_acc_ecn_ee1b
;
265 static int hf_tcp_option_exp_data
;
266 static int hf_tcp_option_exp_exid
;
267 static int hf_tcp_option_unknown_payload
;
269 static int hf_tcp_option_rvbd_probe_version1
;
270 static int hf_tcp_option_rvbd_probe_version2
;
271 static int hf_tcp_option_rvbd_probe_type1
;
272 static int hf_tcp_option_rvbd_probe_type2
;
273 static int hf_tcp_option_rvbd_probe_prober
;
274 static int hf_tcp_option_rvbd_probe_proxy
;
275 static int hf_tcp_option_rvbd_probe_client
;
276 static int hf_tcp_option_rvbd_probe_proxy_port
;
277 static int hf_tcp_option_rvbd_probe_appli_ver
;
278 static int hf_tcp_option_rvbd_probe_storeid
;
279 static int hf_tcp_option_rvbd_probe_flags
;
280 static int hf_tcp_option_rvbd_probe_flag_last_notify
;
281 static int hf_tcp_option_rvbd_probe_flag_server_connected
;
282 static int hf_tcp_option_rvbd_probe_flag_not_cfe
;
283 static int hf_tcp_option_rvbd_probe_flag_sslcert
;
284 static int hf_tcp_option_rvbd_probe_flag_probe_cache
;
286 static int hf_tcp_option_rvbd_trpy_flags
;
287 static int hf_tcp_option_rvbd_trpy_flag_mode
;
288 static int hf_tcp_option_rvbd_trpy_flag_oob
;
289 static int hf_tcp_option_rvbd_trpy_flag_chksum
;
290 static int hf_tcp_option_rvbd_trpy_flag_fw_rst
;
291 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_inner
;
292 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_probe
;
293 static int hf_tcp_option_rvbd_trpy_src
;
294 static int hf_tcp_option_rvbd_trpy_dst
;
295 static int hf_tcp_option_rvbd_trpy_src_port
;
296 static int hf_tcp_option_rvbd_trpy_dst_port
;
297 static int hf_tcp_option_rvbd_trpy_client_port
;
299 static int hf_tcp_option_mptcp_flags
;
300 static int hf_tcp_option_mptcp_backup_flag
;
301 static int hf_tcp_option_mptcp_checksum_flag
;
302 static int hf_tcp_option_mptcp_B_flag
;
303 static int hf_tcp_option_mptcp_C_flag
;
304 static int hf_tcp_option_mptcp_H_v0_flag
;
305 static int hf_tcp_option_mptcp_H_v1_flag
;
306 static int hf_tcp_option_mptcp_F_flag
;
307 static int hf_tcp_option_mptcp_m_flag
;
308 static int hf_tcp_option_mptcp_M_flag
;
309 static int hf_tcp_option_mptcp_a_flag
;
310 static int hf_tcp_option_mptcp_A_flag
;
311 static int hf_tcp_option_mptcp_U_flag
;
312 static int hf_tcp_option_mptcp_V_flag
;
313 static int hf_tcp_option_mptcp_W_flag
;
314 static int hf_tcp_option_mptcp_T_flag
;
315 static int hf_tcp_option_mptcp_tcprst_reason
;
316 static int hf_tcp_option_mptcp_reserved_v0_flag
;
317 static int hf_tcp_option_mptcp_reserved_v1_flag
;
318 static int hf_tcp_option_mptcp_subtype
;
319 static int hf_tcp_option_mptcp_version
;
320 static int hf_tcp_option_mptcp_reserved
;
321 static int hf_tcp_option_mptcp_address_id
;
322 static int hf_tcp_option_mptcp_recv_token
;
323 static int hf_tcp_option_mptcp_sender_key
;
324 static int hf_tcp_option_mptcp_recv_key
;
325 static int hf_tcp_option_mptcp_sender_rand
;
326 static int hf_tcp_option_mptcp_sender_trunc_hmac
;
327 static int hf_tcp_option_mptcp_sender_hmac
;
328 static int hf_tcp_option_mptcp_addaddr_trunc_hmac
;
329 static int hf_tcp_option_mptcp_data_ack_raw
;
330 static int hf_tcp_option_mptcp_data_seq_no_raw
;
331 static int hf_tcp_option_mptcp_subflow_seq_no
;
332 static int hf_tcp_option_mptcp_data_lvl_len
;
333 static int hf_tcp_option_mptcp_checksum
;
334 static int hf_tcp_option_mptcp_ipver
;
335 static int hf_tcp_option_mptcp_echo
;
336 static int hf_tcp_option_mptcp_ipv4
;
337 static int hf_tcp_option_mptcp_ipv6
;
338 static int hf_tcp_option_mptcp_port
;
339 static int hf_mptcp_expected_idsn
;
341 static int hf_mptcp_dsn
;
342 static int hf_mptcp_rawdsn64
;
343 static int hf_mptcp_dss_dsn
;
344 static int hf_mptcp_ack
;
345 static int hf_mptcp_stream
;
346 static int hf_mptcp_expected_token
;
347 static int hf_mptcp_analysis
;
348 static int hf_mptcp_analysis_master
;
349 static int hf_mptcp_analysis_subflows
;
350 static int hf_mptcp_number_of_removed_addresses
;
351 static int hf_mptcp_related_mapping
;
352 static int hf_mptcp_reinjection_of
;
353 static int hf_mptcp_reinjected_in
;
356 static int hf_tcp_option_fast_open_cookie_request
;
357 static int hf_tcp_option_fast_open_cookie
;
359 static int hf_tcp_ts_relative
;
360 static int hf_tcp_ts_delta
;
361 static int hf_tcp_option_scps_vector
;
362 static int hf_tcp_option_scps_binding
;
363 static int hf_tcp_option_scps_binding_len
;
364 static int hf_tcp_scpsoption_flags_bets
;
365 static int hf_tcp_scpsoption_flags_snack1
;
366 static int hf_tcp_scpsoption_flags_snack2
;
367 static int hf_tcp_scpsoption_flags_compress
;
368 static int hf_tcp_scpsoption_flags_nlts
;
369 static int hf_tcp_scpsoption_flags_reserved
;
370 static int hf_tcp_scpsoption_connection_id
;
371 static int hf_tcp_option_snack_offset
;
372 static int hf_tcp_option_snack_size
;
373 static int hf_tcp_option_snack_le
;
374 static int hf_tcp_option_snack_re
;
375 static int hf_tcp_option_user_to_granularity
;
376 static int hf_tcp_option_user_to_val
;
377 static int hf_tcp_proc_src_uid
;
378 static int hf_tcp_proc_src_pid
;
379 static int hf_tcp_proc_src_uname
;
380 static int hf_tcp_proc_src_cmd
;
381 static int hf_tcp_proc_dst_uid
;
382 static int hf_tcp_proc_dst_pid
;
383 static int hf_tcp_proc_dst_uname
;
384 static int hf_tcp_proc_dst_cmd
;
385 static int hf_tcp_segment_data
;
386 static int hf_tcp_payload
;
387 static int hf_tcp_reset_cause
;
388 static int hf_tcp_fin_retransmission
;
389 static int hf_tcp_option_rvbd_probe_reserved
;
390 static int hf_tcp_option_scps_binding_data
;
391 static int hf_tcp_syncookie_time
;
392 static int hf_tcp_syncookie_mss
;
393 static int hf_tcp_syncookie_hash
;
394 static int hf_tcp_syncookie_option_timestamp
;
395 static int hf_tcp_syncookie_option_ecn
;
396 static int hf_tcp_syncookie_option_sack
;
397 static int hf_tcp_syncookie_option_wscale
;
398 static int hf_tcp_ns_reset_window_error_code
;
401 static int ett_tcp_completeness
;
402 static int ett_tcp_flags
;
403 static int ett_tcp_options
;
404 static int ett_tcp_option_timestamp
;
405 static int ett_tcp_option_mss
;
406 static int ett_tcp_option_wscale
;
407 static int ett_tcp_option_sack
;
408 static int ett_tcp_option_snack
;
409 static int ett_tcp_option_scps
;
410 static int ett_tcp_scpsoption_flags
;
411 static int ett_tcp_option_scps_extended
;
412 static int ett_tcp_option_user_to
;
413 static int ett_tcp_option_exp
;
414 static int ett_tcp_option_acc_ecn
;
415 static int ett_tcp_option_sack_perm
;
416 static int ett_tcp_analysis
;
417 static int ett_tcp_analysis_faults
;
418 static int ett_tcp_timestamps
;
419 static int ett_tcp_segments
;
420 static int ett_tcp_segment
;
421 static int ett_tcp_checksum
;
422 static int ett_tcp_process_info
;
423 static int ett_tcp_option_mptcp
;
424 static int ett_tcp_opt_rvbd_probe
;
425 static int ett_tcp_opt_rvbd_probe_flags
;
426 static int ett_tcp_opt_rvbd_trpy
;
427 static int ett_tcp_opt_rvbd_trpy_flags
;
428 static int ett_tcp_opt_echo
;
429 static int ett_tcp_opt_cc
;
430 static int ett_tcp_opt_md5
;
431 static int ett_tcp_opt_ao
;
432 static int ett_tcp_opt_qs
;
433 static int ett_tcp_opt_recbound
;
434 static int ett_tcp_opt_scpscor
;
435 static int ett_tcp_unknown_opt
;
436 static int ett_tcp_option_other
;
437 static int ett_tcp_syncookie
;
438 static int ett_tcp_syncookie_option
;
439 static int ett_mptcp_analysis
;
440 static int ett_mptcp_analysis_subflows
;
442 static expert_field ei_tcp_opt_len_invalid
;
443 static expert_field ei_tcp_analysis_retransmission
;
444 static expert_field ei_tcp_analysis_fast_retransmission
;
445 static expert_field ei_tcp_analysis_spurious_retransmission
;
446 static expert_field ei_tcp_analysis_out_of_order
;
447 static expert_field ei_tcp_analysis_reused_ports
;
448 static expert_field ei_tcp_analysis_lost_packet
;
449 static expert_field ei_tcp_analysis_ack_lost_packet
;
450 static expert_field ei_tcp_analysis_window_update
;
451 static expert_field ei_tcp_analysis_window_full
;
452 static expert_field ei_tcp_analysis_keep_alive
;
453 static expert_field ei_tcp_analysis_keep_alive_ack
;
454 static expert_field ei_tcp_analysis_duplicate_ack
;
455 static expert_field ei_tcp_analysis_zero_window_probe
;
456 static expert_field ei_tcp_analysis_zero_window
;
457 static expert_field ei_tcp_analysis_zero_window_probe_ack
;
458 static expert_field ei_tcp_analysis_tfo_syn
;
459 static expert_field ei_tcp_analysis_tfo_ack
;
460 static expert_field ei_tcp_analysis_tfo_ignored
;
461 static expert_field ei_tcp_analysis_partial_ack
;
462 static expert_field ei_tcp_scps_capable
;
463 static expert_field ei_tcp_option_sack_dsack
;
464 static expert_field ei_tcp_option_snack_sequence
;
465 static expert_field ei_tcp_option_wscale_shift_invalid
;
466 static expert_field ei_tcp_option_mss_absent
;
467 static expert_field ei_tcp_option_mss_present
;
468 static expert_field ei_tcp_option_sack_perm_absent
;
469 static expert_field ei_tcp_option_sack_perm_present
;
470 static expert_field ei_tcp_short_segment
;
471 static expert_field ei_tcp_ack_nonzero
;
472 static expert_field ei_tcp_connection_synack
;
473 static expert_field ei_tcp_connection_syn
;
474 static expert_field ei_tcp_connection_fin
;
475 static expert_field ei_tcp_connection_rst
;
476 static expert_field ei_tcp_connection_fin_active
;
477 static expert_field ei_tcp_connection_fin_passive
;
478 static expert_field ei_tcp_checksum_ffff
;
479 static expert_field ei_tcp_checksum_partial
;
480 static expert_field ei_tcp_checksum_bad
;
481 static expert_field ei_tcp_urgent_pointer_non_zero
;
482 static expert_field ei_tcp_suboption_malformed
;
483 static expert_field ei_tcp_nop
;
484 static expert_field ei_tcp_non_zero_bytes_after_eol
;
485 static expert_field ei_tcp_bogus_header_length
;
487 /* static expert_field ei_mptcp_analysis_unexpected_idsn; */
488 static expert_field ei_mptcp_analysis_echoed_key_mismatch
;
489 static expert_field ei_mptcp_analysis_missing_algorithm
;
490 static expert_field ei_mptcp_analysis_unsupported_algorithm
;
491 static expert_field ei_mptcp_infinite_mapping
;
492 static expert_field ei_mptcp_mapping_missing
;
493 /* static expert_field ei_mptcp_stream_incomplete; */
494 /* static expert_field ei_mptcp_analysis_dsn_out_of_order; */
496 /* Some protocols such as encrypted DCE/RPCoverHTTP have dependencies
497 * from one PDU to the next PDU and require that they are called in sequence.
498 * These protocols would not be able to handle PDUs coming out of order
499 * or for example when a PDU is seen twice, like for retransmissions.
500 * This preference can be set for such protocols to make sure that we don't
501 * invoke the subdissectors for retransmitted or out-of-order segments.
503 static bool tcp_no_subdissector_on_error
= true;
505 /* Enable buffering of out-of-order TCP segments before passing it to a
506 * subdissector (depends on "tcp_desegment"). */
507 static bool tcp_reassemble_out_of_order
;
510 * FF: https://www.rfc-editor.org/rfc/rfc6994.html
511 * With this flag set we assume the option structure for experimental
512 * codepoints (253, 254) has an Experiment Identifier (ExID), which is
513 * the first 16-bit field after the Kind and Length.
514 * The ExID is used to differentiate different experiments and thus will
515 * be used in data dissection.
517 static bool tcp_exp_options_rfc6994
= true;
520 * This flag indicates which of Fast Retransmission or Out-of-Order
521 * interpretation should supersede when analyzing an ambiguous packet as
522 * things are not always clear. The user is authorized to change this
524 * When set, we keep the historical interpretation (Fast RT > OOO)
526 static bool tcp_fastrt_precedence
= true;
528 /* Process info, currently discovered via IPFIX */
529 static bool tcp_display_process_info
;
531 /* Read the sequence number as syn cookie */
532 static bool read_seq_as_syn_cookie
;
537 #define TCPOPT_NOP 1 /* Padding */
538 #define TCPOPT_EOL 0 /* End of options */
539 #define TCPOPT_MSS 2 /* Segment size negotiating */
540 #define TCPOPT_WINDOW 3 /* Window scaling */
541 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
542 #define TCPOPT_SACK 5 /* SACK Block */
543 #define TCPOPT_ECHO 6
544 #define TCPOPT_ECHOREPLY 7
545 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
547 #define TCPOPT_CCNEW 12
548 #define TCPOPT_CCECHO 13
549 #define TCPOPT_MD5 19 /* RFC2385 */
550 #define TCPOPT_SCPS 20 /* SCPS Capabilities */
551 #define TCPOPT_SNACK 21 /* SCPS SNACK */
552 #define TCPOPT_RECBOUND 22 /* SCPS Record Boundary */
553 #define TCPOPT_CORREXP 23 /* SCPS Corruption Experienced */
554 #define TCPOPT_QS 27 /* RFC4782 Quick-Start Response */
555 #define TCPOPT_USER_TO 28 /* RFC5482 User Timeout Option */
556 #define TCPOPT_AO 29 /* RFC5925 The TCP Authentication Option */
557 #define TCPOPT_MPTCP 30 /* RFC6824 Multipath TCP */
558 #define TCPOPT_TFO 34 /* RFC7413 TCP Fast Open Cookie */
559 #define TCPOPT_ACC_ECN_0 0xac /* draft-ietf-tcpm-accurate-ecn */
560 #define TCPOPT_ACC_ECN_1 0xae /* draft-ietf-tcpm-accurate-ecn */
561 #define TCPOPT_EXP_FD 0xfd /* Experimental, reserved */
562 #define TCPOPT_EXP_FE 0xfe /* Experimental, reserved */
563 /* Non IANA registered option numbers */
564 #define TCPOPT_RVBD_PROBE 76 /* Riverbed probe option */
565 #define TCPOPT_RVBD_TRPY 78 /* Riverbed transparency option */
570 #define TCPOLEN_MSS 4
571 #define TCPOLEN_WINDOW 3
572 #define TCPOLEN_SACK_PERM 2
573 #define TCPOLEN_SACK_MIN 2
574 #define TCPOLEN_ECHO 6
575 #define TCPOLEN_ECHOREPLY 6
576 #define TCPOLEN_TIMESTAMP 10
578 #define TCPOLEN_CCNEW 6
579 #define TCPOLEN_CCECHO 6
580 #define TCPOLEN_MD5 18
581 #define TCPOLEN_SCPS 4
582 #define TCPOLEN_SNACK 6
583 #define TCPOLEN_RECBOUND 2
584 #define TCPOLEN_CORREXP 2
586 #define TCPOLEN_USER_TO 4
587 #define TCPOLEN_MPTCP_MIN 3
588 #define TCPOLEN_TFO_MIN 2
589 #define TCPOLEN_RVBD_PROBE_MIN 3
590 #define TCPOLEN_RVBD_TRPY_MIN 16
591 #define TCPOLEN_EXP_MIN 4
594 * TCP Experimental Option Experiment Identifiers (TCP ExIDs)
595 * See: https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-exids
596 * Wireshark only supports 16-bit ExIDs
599 #define TCPEXID_TARR 0x00ac
600 #define TCPEXID_HOST_ID 0x0348
601 #define TCPEXID_ASC 0x0a0d
602 #define TCPEXID_CAPABILITY 0x0ca0
603 #define TCPEXID_EDO 0x0ed0
604 #define TCPEXID_ENO 0x454e
605 #define TCPEXID_SNO 0x5323
606 #define TCPEXID_TS_INTERVAL 0x75ec /* 32-bit ExID: 0x75ecffee */
607 #define TCPEXID_ACC_ECN_0 0xacc0
608 #define TCPEXID_ACC_ECN_1 0xacc1
609 #define TCPEXID_ACC_ECN 0xacce
610 #define TCPEXID_SMC_R 0xe2d4 /* 32-bit ExID: 0xe2d4c3d9 */
611 #define TCPEXID_FO 0xf989
612 #define TCPEXID_LOW_LATENCY 0xf990
615 * Multipath TCP subtypes
617 #define TCPOPT_MPTCP_MP_CAPABLE 0x0 /* Multipath TCP Multipath Capable */
618 #define TCPOPT_MPTCP_MP_JOIN 0x1 /* Multipath TCP Join Connection */
619 #define TCPOPT_MPTCP_DSS 0x2 /* Multipath TCP Data Sequence Signal */
620 #define TCPOPT_MPTCP_ADD_ADDR 0x3 /* Multipath TCP Add Address */
621 #define TCPOPT_MPTCP_REMOVE_ADDR 0x4 /* Multipath TCP Remove Address */
622 #define TCPOPT_MPTCP_MP_PRIO 0x5 /* Multipath TCP Change Subflow Priority */
623 #define TCPOPT_MPTCP_MP_FAIL 0x6 /* Multipath TCP Fallback */
624 #define TCPOPT_MPTCP_MP_FASTCLOSE 0x7 /* Multipath TCP Fast Close */
625 #define TCPOPT_MPTCP_MP_TCPRST 0x8 /* Multipath TCP Reset */
628 * Conversation Completeness values
630 #define TCP_COMPLETENESS_SYNSENT 0x01 /* TCP SYN SENT */
631 #define TCP_COMPLETENESS_SYNACK 0x02 /* TCP SYN ACK */
632 #define TCP_COMPLETENESS_ACK 0x04 /* TCP ACK */
633 #define TCP_COMPLETENESS_DATA 0x08 /* TCP data */
634 #define TCP_COMPLETENESS_FIN 0x10 /* TCP FIN */
635 #define TCP_COMPLETENESS_RST 0x20 /* TCP RST */
637 static const true_false_string tcp_option_user_to_granularity
= {
641 static const value_string tcp_option_kind_vs
[] = {
642 { TCPOPT_EOL
, "End of Option List" },
643 { TCPOPT_NOP
, "No-Operation" },
644 { TCPOPT_MSS
, "Maximum Segment Size" },
645 { TCPOPT_WINDOW
, "Window Scale" },
646 { TCPOPT_SACK_PERM
, "SACK Permitted" },
647 { TCPOPT_SACK
, "SACK" },
648 { TCPOPT_ECHO
, "Echo" },
649 { TCPOPT_ECHOREPLY
, "Echo Reply" },
650 { TCPOPT_TIMESTAMP
, "Time Stamp Option" },
651 { 9, "Partial Order Connection Permitted" },
652 { 10, "Partial Order Service Profile" },
654 { TCPOPT_CCNEW
, "CC.NEW" },
655 { TCPOPT_CCECHO
, "CC.ECHO" },
656 { 14, "TCP Alternate Checksum Request" },
657 { 15, "TCP Alternate Checksum Data" },
660 { 18, "Trailer Checksum Option" },
661 { TCPOPT_MD5
, "MD5 Signature Option" },
662 { TCPOPT_SCPS
, "SCPS Capabilities" },
663 { TCPOPT_SNACK
, "Selective Negative Acknowledgements" },
664 { TCPOPT_RECBOUND
, "Record Boundaries" },
665 { TCPOPT_CORREXP
, "Corruption experienced" },
667 { 25, "Unassigned" },
668 { 26, "TCP Compression Filter" },
669 { TCPOPT_QS
, "Quick-Start Response" },
670 { TCPOPT_USER_TO
, "User Timeout Option" },
671 { TCPOPT_AO
, "The TCP Authentication Option" },
672 { TCPOPT_MPTCP
, "Multipath TCP" },
673 { TCPOPT_TFO
, "TCP Fast Open Cookie" },
674 { TCPOPT_RVBD_PROBE
, "Riverbed Probe" },
675 { TCPOPT_RVBD_TRPY
, "Riverbed Transparency" },
676 { TCPOPT_ACC_ECN_0
, "Accurate ECN Order 0" },
677 { TCPOPT_ACC_ECN_1
, "Accurate ECN Order 1" },
678 { TCPOPT_EXP_FD
, "RFC3692-style Experiment 1" },
679 { TCPOPT_EXP_FE
, "RFC3692-style Experiment 2" },
682 static value_string_ext tcp_option_kind_vs_ext
= VALUE_STRING_EXT_INIT(tcp_option_kind_vs
);
684 static const value_string tcp_exid_vs
[] = {
685 { TCPEXID_TARR
, "TCP ACK Rate Request" },
686 { TCPEXID_HOST_ID
, "Host ID" },
687 { TCPEXID_ASC
, "Autonomous System Compensation" },
688 { TCPEXID_CAPABILITY
, "Capability Option" },
689 { TCPEXID_EDO
, "Extended Data Offset" },
690 { TCPEXID_ENO
, "Encryption Negotiation" },
691 { TCPEXID_SNO
, "Service Number" },
692 { TCPEXID_TS_INTERVAL
, "Timestamp Interval" },
693 { TCPEXID_ACC_ECN_0
, "Accurate ECN - Order 0" },
694 { TCPEXID_ACC_ECN_1
, "Accurate ECN - Order 1" },
695 { TCPEXID_ACC_ECN
, "Accurate ECN" },
696 { TCPEXID_SMC_R
, "Shared Memory communications over RMDA protocol" },
697 { TCPEXID_FO
, "Fast Open" },
698 { TCPEXID_LOW_LATENCY
, "Low Latency" },
702 /* not all of the hf_fields below make sense for TCP but we have to provide
703 them anyways to comply with the API (which was aimed for IP fragment
705 static const fragment_items tcp_segment_items
= {
710 &hf_tcp_segment_overlap
,
711 &hf_tcp_segment_overlap_conflict
,
712 &hf_tcp_segment_multiple_tails
,
713 &hf_tcp_segment_too_long_fragment
,
714 &hf_tcp_segment_error
,
715 &hf_tcp_segment_count
,
716 &hf_tcp_reassembled_in
,
717 &hf_tcp_reassembled_length
,
718 &hf_tcp_reassembled_data
,
723 static const value_string mptcp_subtype_vs
[] = {
724 { TCPOPT_MPTCP_MP_CAPABLE
, "Multipath Capable" },
725 { TCPOPT_MPTCP_MP_JOIN
, "Join Connection" },
726 { TCPOPT_MPTCP_DSS
, "Data Sequence Signal" },
727 { TCPOPT_MPTCP_ADD_ADDR
, "Add Address"},
728 { TCPOPT_MPTCP_REMOVE_ADDR
, "Remove Address" },
729 { TCPOPT_MPTCP_MP_PRIO
, "Change Subflow Priority" },
730 { TCPOPT_MPTCP_MP_FAIL
, "TCP Fallback" },
731 { TCPOPT_MPTCP_MP_FASTCLOSE
, "Fast Close" },
732 { TCPOPT_MPTCP_MP_TCPRST
, "TCP Reset" },
736 /* Source https://support.citrix.com/article/CTX200852/citrix-adc-netscaler-reset-codes-reference
737 Dates of source: Created: 31 Mar 2015 | Modified: 21 Jan 2023
738 Date of last dictionary update: 2024/07/11
739 NOTE: When updating don't just overwrite the dictionary, the definitions below are more polished than the ones in the CTX. */
740 static const value_string netscaler_reset_window_error_code_vals
[] = {
741 { 8196, "SSL bad record." },
742 { 8201, "NSDBG_RST_SSTRAY: This reset code is triggered when packets are received on a socket that has already been closed. For example, if a client computer continues transmitting after receiving a RST code for other reasons, then it receives this RST code for the subsequent packets." },
743 { 8202, "NSDBG_RST_CSTRAY: This code is triggered when the NetScaler appliance receives data through a connection, which does not have a PCB, and its SYN cookie has expired." },
744 { 8204, "Client retransmitted SYN with the wrong sequence number." },
745 { 8205, "ACK number in the final ACK from peer during connection establishment is wrong." },
746 { 8206, "Received a bad packet in TCPS_SYN_SENT state (non RST packet). Usually happens if the 4 tuples are reused and you receive packet from the old connection." },
747 { 8207, "Received SYN on established connection which is within the window. Protects from spoofing attacks." },
748 { 8208, "Resets the connection when you receive more than the configured value of duplicate retransmissions." },
749 { 8209, "Could not allocate memory for the packet, system out of memory." },
750 { 8210, "HTTP DoS protection feature error, bad client request." },
751 { 8211, "NSDBG_RST_ZSSSR: This code refers to an idle timeout or a zombie timeout. This code is set by the zombie connection cleanup routine, a connection has timed out. When the status of a service is down, existing TCP connections to that service are reset with this code (TCP window size 9300/9301, zombie timer). If the NetScaler appliance receives a segment from one of these connections, which is already reset, send another reset (TCP window size 8201, stray packet)." },
752 { 8212, "Stray packet (no listening service or listening service is present but SYN cookie does not match or there is no corresponding connection information). 8212 is specifically for SYN stray packets." },
753 { 8213, "Sure Connect feature, bad client sending post on connection which is closing." },
754 { 8214, "MSS sent in SYN exceeded the MSS corresponding to NIC MTU and/or VLAN MTU." },
755 { 9100, "NSDBG_RST_ORP: This code refers to an orphan HTTP connection. Probably, a connection where data is initially seen either from the server or client, but stopped because of some reason, without closing the TCP session. It indicates that the client request was not properly terminated. Therefore, the NetScaler appliance waits for the request to be completed. After a timeout, the NetScaler appliance resets the connection with the code 9100." },
756 { 9201, "HTTP connection multiplexing error. Server sent response packets belonging to previous transaction." },
757 { 9202, "NSDBG_RST_LERRCDM: CDM refers to Check Data Mixing. This reset code is set when there is a TCP sequence mismatch in the first data packet, arriving from a recently reused server connection." },
758 { 9203, "NSDBG_RST_CLT_CHK_MIX: This code refers to the server sending a FIN for a previous client over a reused connection." },
759 { 9205, "NSDBG_RST_CHUNK_FAIL: This code indicates that the NetScaler appliance experienced issues with the chunked encoding in the HTTP response from the server." },
760 { 9206, "HTTP tracking failed due to invalid HTTP request/response header." },
761 { 9207, "Invalid header reassembly parsing." },
762 { 9208, "Incomplete response processing error, see incompHdrDelay setting httpprofiles." },
763 { 9209, "Chunk tracking failed." },
764 { 9210, "Corrupt packets." },
765 { 9212, "HTTP Invalid request." },
766 { 9214, "Cache res store failed." },
767 { 9216, "Cache async no memory." },
768 { 9217, "HTTP state machine error because of more than content length body." },
769 { 9218, "Terminated due to extra orphan data." },
770 { 9219, "NSB allocation failure." },
771 { 9220, "Cannot allocate new NSB and so many other reasons." },
772 { 9221, "vurl comes with a domain shard that’s no longer valid." },
773 { 9222, "This is sent when the response is RFC non-compliant. The issue is caused by both Content-Length and Transfer-Encoding in response being invalid, which may lead to a variety of attacks and leads to the reset." },
774 { 9300, "NSDBG_RST_ZSSSR: This code refers to an idle timeout or a zombie timeout. This code is set by the zombie connection cleanup routine, a connection has timed out. When the status of a service is down, existing TCP connections to that service are reset with this code (TCP window size 9300/9301, zombie timer). If the NetScaler appliance receives a segment from one of these connections, which is already reset, send another reset (TCP window size 8201, stray packet)." },
775 { 9301, "NSDBG_RST_ZSSSR: This code refers to an idle timeout or a zombie timeout. This code is set by the zombie connection cleanup routine, a connection has timed out. When the status of a service is down, existing TCP connections to that service are reset with this code (TCP window size 9300/9301, zombie timer). If the NetScaler appliance receives a segment from one of these connections, which is already reset, send another reset (TCP window size 8201, stray packet)." },
776 { 9302, "NSDBG_RST_ZSSSR: This code refers to an idle timeout or a zombie timeout. This code is set by the zombie connection cleanup routine, a connection has timed out. When the status of a service is down, existing TCP connections to that service are reset with this code (TCP window size 9300/9301, zombie timer). If the NetScaler appliance receives a segment from one of these connections, which is already reset, send another reset (TCP window size 8201, stray packet)." },
777 { 9303, "NSDBG_RST_ZSSSR: This code refers to an idle timeout or a zombie timeout. This code is set by the zombie connection cleanup routine, a connection has timed out. When the status of a service is down, existing TCP connections to that service are reset with this code (TCP window size 9300/9301, zombie timer). If the NetScaler appliance receives a segment from one of these connections, which is already reset, send another reset (TCP window size 8201, stray packet)." },
778 { 9304, "NSDBG_RST_LINK_GIVEUPS: This reset code might be part of a backend-persistence mechanism, which is used to free resources on the NetScaler. By default, the NetScaler uses a zero window probe 7 times before giving up and resetting the connection. By disabling this mechanism, the appliance holds the sessions without this limit. The following is the command to disable the persistence probe limit: root@ns# nsapimgr -ys limited_persistprobe=0 The default value is 1, which limits to 7 probes, which is around 2 minutes. Setting the value to zero disables it and keeps the session open as long as the server sends an ACK signal in response to the probes." },
779 { 9305, "Server sent back ACK to our SYN (ACK number did not match)." },
780 { 9306, "TCP buffering is undone due to duplicate TPCB enablement." },
781 { 9307, "Small window protection feature resetting the connection." },
782 { 9308, "Small window protection feature resetting the connection." },
783 { 9309, "Small window protection feature resetting the connection." },
784 { 9310, "TCP KA probing failed." },
785 { 9311, "DHT retry failed." },
786 { 9400, "Reset server connection which are in reusepool and are not reusable because of TCP or Session level properties. Usually this is done when we need to open new connections but there is limit on connection we can open to the server and there are some already built up connections which are not reusable." },
787 { 9401, "When you reach maximum system capacity flushing existing connections based time order to accommodate new connections. Or when we remove an configured entity which as associated connections those connection will be reset." },
788 { 9450, "SQL HS failed." },
789 { 9451, "SQL response failed." },
790 { 9452, "SQL request list failed." },
791 { 9453, "SQL UNK not linked." },
792 { 9454, "SQL NSB hold failed." },
793 { 9455, "SQL Server First Packet." },
794 { 9456, "SQL Login response before request." },
795 { 9457, "SQL server login failed." },
796 { 9458, "SQL no memory." },
797 { 9459, "SQL bad server." },
798 { 9460, "SQL link failed." },
799 { 9600, "Reset when Number of packets with Sequence ACK mismatch > nscfg_max_orphan_pkts." },
800 { 9601, "Reset when Number of data packets with Sequence ACK mismatch > nscfg_max_orphan_pkts." },
801 { 9602, "When SSL VPN CS probe limit exceeded." },
802 { 9700, "NSDBG_RST_PASS: This code indicates that the NetScaler appliance receives a TCP RST code from either the client or the server, and is transferring it. For example, the back end server sends a RST code, and the NetScaler appliance forwards it to the client with this code." },
803 { 9701, "NSDBG_RST_NEST / NSDBG_RST_ACK_PASS: The NetScaler software release 9.1 and the later versions, this code indicates #define NSBE_DBG_RST_ACK_PASS. It indicates that a RST code was forwarded as in the preceding RST code 9700, and the ACK flag was also set." },
804 { 9702, "The data received after FIN is received." },
805 { 9704, "Reset when NSB dropped due to hold limit or error in transaction etc." },
806 { 9800, "NSDBG_RST_PROBE: This connections used for monitoring the service are reset due to timeout." },
807 { 9810, "When responses match the configured NAI status code." },
808 { 9811, "NSDBG_RST_ERRHANDLER: This reset code is used with SSL. After sending a Fatal Alert, the NetScaler sends a RST packet with this error code. If the client does not display any supported ciphers to the NetScaler appliance, the appliance sends a Fatal Alert and then this RST packet." },
809 { 9812, "Connection flushing because existing IP address is removed from the configuration." },
810 { 9813, "Closing the SSF connection." },
811 { 9814, "NSDBG_RST_PETRIGGER: This reset code is used when a request or response matches a Policy Engine policy, whose action is RESET." },
812 { 9816, "Bad SSL record." },
813 { 9817, "SSL connection received at the time of bound certificate changing (configuration change)." },
814 { 9818, "Bad SSL header value." },
815 { 9819, "Reset on failing to allocate memory for SPCB." },
816 { 9820, "SSL card operation failed." },
817 { 9821, "SSL feature disabled, reset the connection." },
818 { 9822, "SSL cipher changed, flush the connection created for old cipher." },
819 { 9823, "Reset when the NSC_AAAC cookie is malformed in a request or /vpn/apilogin.html request does not have a query part, memory allocation failures in certificate processing." },
820 { 9824, "Reset on AAA orphan connections." },
821 { 9825, "DBG_WRONG_GSLBRECDLEN: This code is a GSLB MEP error reset code, typically between mixed versions." },
822 { 9826, "Not enough memory for NET buffers." },
823 { 9827, "Reset on SSL config change." },
824 { 9829, "Reset on GSLB other site down or out of reach." },
825 { 9830, "Reset on sessions matching ACL DENY rule." },
826 { 9831, "Use it if no application data exist, but required." },
827 { 9832, "Application error." },
828 { 9833, "Fatal SSL error." },
829 { 9834, "Reset while flushing all SPCB, during FIPS or HSM init." },
830 { 9835, "DTLS record too large." },
831 { 9836, "DTLS record zero length." },
832 { 9837, "SSLV2 record too large." },
833 { 9838, "NSBE_DBG_RST_SSL_BAD_RECORD: This code refers to error looking up SSL record when handling a request or a response." },
834 { 9839, "SSL MAX NSB hold limit reached." },
835 { 9841, "SSL/DTLS split packet failure." },
836 { 9842, "SSL NSB allocation failure." },
837 { 9843, "Monitor wide IP probe." },
838 { 9844, "SSL reneg max NSB limit reached or alloc failure." },
839 { 9845, "Reset on Appsec policy." },
840 { 9846, "Delta compression aborted or failed." },
841 { 9847, "Delta compression aborted or failed." },
842 { 9848, "Reset on connection accepted during configuration change(SSL)." },
843 { 9849, "Reset on GSLB conflict due to misconfiguration." },
844 { 9850, "DNS TCP connection untrackable due to failure of compact NSB, etc." },
845 { 9851, "DNS TCP failure (invalid payload, length, etc)." },
846 { 9852, "RTSP (ALG) session handling error." },
847 { 9853, "MSSQL Auth response error." },
848 { 9854, "Indirect GSLB sites tried to establish connection" },
849 { 9855, "For HTTP/SSL vservers, SO (Surge Queue Overflow.) threshold has reached." },
850 { 9856, "Reset on Appfw ASYNC failure." },
851 { 9857, "Reset on Flushing HTTP waiting PCB." },
852 { 9858, "Reset on Rechunk abort." },
853 { 9859, "A new client connection request was made deferrable by server on the label." },
854 { 9860, "The pcb->link of this connection was cleaned for some reason, so resetting this PCB." },
855 { 9861, "Connection on a push vserver, when push disabled on client vserver." },
856 { 9862, "Reset to Client as it resulted in duplicate server connection." },
857 { 9863, "Reset to old connection when new connection is established and old one is still not freed." },
858 { 9864, "CVPN HINFO restore failed." },
859 { 9865, "CVPN MCMX error." },
860 { 9866, "URL policy transform error." },
861 { 9868, "MSSQL login errors." },
862 { 9870, "SQL login parse error." },
863 { 9871, "MSSQL memory allocation failure." },
864 { 9872, "Websocket upgrade request dropped due to websocket disabled in http profile." },
865 { 9873, "Agsvc MCMX failure." },
866 { 9874, "NSB hold limit reached." },
867 { 9875, "Client connection is closed, send RST to server." },
868 { 9876, "One to many link failed." },
869 { 9877, "Reset for CEA on client PCB." },
870 { 9878, "CEA untrackable, send RST to Client." },
871 { 9879, "Parsing failed." },
872 { 9880, "Memory alloc failure." },
873 { 9881, "Reset on Diameter message without CE." },
874 { 9882, "Reset to Client if no pending requests." },
875 { 9883, "Link PCB fail reset to client on CEA." },
876 { 9884, "Reset to Server PCB." },
877 { 9885, "SIP Content header is missing. | Diameter reset on bad ACK." },
878 { 9886, "Reset on VPN ng binding miss." },
879 { 9887, "Reset on failed to send a request to broker (VPN)." },
880 { 9888, "Reset to AAA client if Cluster sync in progress." },
881 { 9889, "Reset on missing dynamic processing context (LUA)." },
882 { 9890, "Rewrite feature disabled when blocked on response side." },
883 { 9900, "PI reset." },
884 { 9901, "Cache buffer large data error." },
885 { 9902, "HTML injection connection abort." },
886 { 9903, "GSLB feature is disabled. Donot accept any connections and close any existing ones." },
887 { 9904, "Reset on AAA error." },
888 { 9905, "Database not responding." },
889 { 9906, "Local GSLB sites have been removed, send RST." },
890 { 9911, "HTTP incomplete due to no available memory." },
891 { 9912, "HTTP link incomplete due to no available memory." },
892 { 9913, "Send RST for SPDY errors." },
893 { 9914, "Cache Response error/AAA." },
894 { 9915, "Speedy split packet at header failed." },
895 { 9951, "SSL incomplete record." },
896 { 9952, "Reset on SSL FATAL ALERT RCVD." },
897 { 9953, "Reset on triggering of timeout action." },
898 { 9956, "QOS incomplete POST handling error." },
899 { 9957, "AppQoS Persistent service is down." },
900 { 9958, "Not used+C187:C199." },
901 { 9959, "Not used." },
902 { 9960, "MPTCP options error." },
903 { 9961, "MP join SYN reset." },
904 { 9962, "MP join FINAL ACK reset." },
905 { 9963, "MPTCP checksum failure." },
906 { 9964, "Invalid Client or NS key." },
907 { 9965, "MPTCP, established SF replaced." },
908 { 9966, "MPTCP RSSF filter failure." },
909 { 9967, "MPTCP plain ACK fallback failure." },
910 { 9968, "MPTCP fast close received." },
911 { 9969, "MPTCP, if NS in fallback mode, DSS should only for infinite map." },
912 { 9970, "BW Connection Close." },
913 { 9971, "MPTCP invalid/bad MAP." },
914 { 9972, "MPTCP reset if multiple SFs are present." },
915 { 9973, "Reset on rest of SF after fallback to infinite map as only one SF should be present." },
916 { 9974, "RST terminated at TCP layer." },
917 { 9975, "PCB waitQ insertion failed." },
918 { 9976, "MPTCP MAX retries on KA probes has reached." },
919 { 9977, "MPTCP token collision is found." },
920 { 9978, "MPTCP SYN retries reached MAXretries." },
921 { 9979, "MPTCP subflow FIN received or any other signals received on pre est SF." },
922 { 9980, "Reset on MPTCP close." },
923 { 9981, "Closing auditlog connection." },
924 { 9982, "invalid syn/ack/seq is received for NS's SYN+TFOC+DATA." },
925 { 9983, "MPTCP invalid payload size." },
926 { 10000, "ICA parse error." },
927 { 10001, "ICA link parse error." },
928 { 10002, "ICA no available memory." },
929 { 10003, "ICA link no available memory." },
930 { 10004, "Kill an ICA connection." },
931 { 10005, "MPTCP SYN retries reached MAXretries." },
932 { 10006, "Kill an RDP connection." },
933 { 10016, "SMPP no memory available." },
934 { 10017, "SMPP reset if no pending requests." },
935 { 10018, "SMPP unknown error." },
936 { 10019, "SMPP: Bind to client failed." },
937 { 10020, "SMPP: NSB hold limit reached." },
938 { 10022, "SMPP: Bind response on client." },
939 { 10023, "SMPP: Parsing failed." },
940 { 10024, "SMPP: link failed." },
941 { 10026, "SMPP: MSG without bind or not request message after bind." },
942 { 10027, "SSL: HSM operation failed." },
943 { 10028, "SSL: HSM error client." },
944 { 10029, "SSL: Hit the ratelimit." },
945 { 10030, "Connection breached maximum packet credits configured." },
946 { 10032, "SIPALG: Header parsing failed." },
947 { 10033, "SIPALG: Body parsing failed." },
948 { 10034, "SIPALG: SIP header failure." },
949 { 10035, "SIPALG: SDP header failure." },
950 { 10036, "SIPALG: Remaining IP replacement failure." },
951 { 10037, "SIPALG: Length replacement failure." },
952 { 10038, "SIPALG: BA insertion failed." },
953 { 10039, "SIPALG: DHT failure." },
954 { 10040, "SIPALG: Post translation ops failed." },
955 { 10042, "SIPALG: Pre translation ops failed." },
959 static dissector_table_t subdissector_table
;
960 static dissector_table_t tcp_option_table
;
961 static heur_dissector_list_t heur_subdissector_list
;
962 static dissector_handle_t data_handle
;
963 static dissector_handle_t tcp_handle
;
964 static dissector_handle_t sport_handle
;
965 static dissector_handle_t tcp_opt_unknown_handle
;
966 static capture_dissector_handle_t tcp_cap_handle
;
968 static uint32_t tcp_stream_count
;
969 static uint32_t mptcp_stream_count
;
974 * Maps an MPTCP token to a mptcp_analysis structure
975 * Collisions are not handled
977 static wmem_tree_t
*mptcp_tokens
;
979 static int * const tcp_option_mptcp_capable_v0_flags
[] = {
980 &hf_tcp_option_mptcp_checksum_flag
,
981 &hf_tcp_option_mptcp_B_flag
,
982 &hf_tcp_option_mptcp_H_v0_flag
,
983 &hf_tcp_option_mptcp_reserved_v0_flag
,
987 static int * const tcp_option_mptcp_capable_v1_flags
[] = {
988 &hf_tcp_option_mptcp_checksum_flag
,
989 &hf_tcp_option_mptcp_B_flag
,
990 &hf_tcp_option_mptcp_C_flag
,
991 &hf_tcp_option_mptcp_H_v1_flag
,
992 &hf_tcp_option_mptcp_reserved_v1_flag
,
996 static int * const tcp_option_mptcp_join_flags
[] = {
997 &hf_tcp_option_mptcp_backup_flag
,
1001 static int * const tcp_option_mptcp_dss_flags
[] = {
1002 &hf_tcp_option_mptcp_F_flag
,
1003 &hf_tcp_option_mptcp_m_flag
,
1004 &hf_tcp_option_mptcp_M_flag
,
1005 &hf_tcp_option_mptcp_a_flag
,
1006 &hf_tcp_option_mptcp_A_flag
,
1010 static int * const tcp_option_mptcp_tcprst_flags
[] = {
1011 &hf_tcp_option_mptcp_U_flag
,
1012 &hf_tcp_option_mptcp_V_flag
,
1013 &hf_tcp_option_mptcp_W_flag
,
1014 &hf_tcp_option_mptcp_T_flag
,
1018 static const unit_name_string units_64bit_version
= { " (64bits version)", NULL
};
1021 tcp_get_ace(const struct tcpheader
*tcph
)
1026 if (tcph
->th_flags
& TH_AE
) {
1029 if (tcph
->th_flags
& TH_CWR
) {
1032 if (tcph
->th_flags
& TH_ECE
) {
1039 tcp_flags_to_str(wmem_allocator_t
*scope
, const struct tcpheader
*tcph
)
1041 static const char flags
[][4] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECE", "CWR", "AE" };
1042 static const char digit
[][2] = { "0", "1", "2", "3", "4", "5", "6", "7" };
1043 const int maxlength
= 64; /* upper bounds, max 53B: 8 * 3 + 2 + strlen("Reserved") + 9 * 2 + 1 */
1050 buf
= pbuf
= (char *) wmem_alloc(scope
, maxlength
);
1053 for (i
= 0; i
< (tcph
->th_use_ace
? 6 : 9); i
++) {
1054 if (tcph
->th_flags
& (1 << i
)) {
1056 pbuf
= g_stpcpy(pbuf
, ", ");
1057 pbuf
= g_stpcpy(pbuf
, flags
[i
]);
1060 if (tcph
->th_use_ace
) {
1061 ace
= tcp_get_ace(tcph
);
1062 pbuf
= g_stpcpy(pbuf
, ", ACE=");
1063 pbuf
= g_stpcpy(pbuf
, digit
[ace
]);
1066 if (tcph
->th_flags
& TH_RES
) {
1068 pbuf
= g_stpcpy(pbuf
, ", ");
1069 g_stpcpy(pbuf
, "Reserved");
1073 g_stpcpy(pbuf
, "<None>");
1079 tcp_flags_to_str_first_letter(wmem_allocator_t
*scope
, const struct tcpheader
*tcph
)
1081 wmem_strbuf_t
*buf
= wmem_strbuf_new(scope
, "");
1083 const unsigned flags_count
= 12;
1084 static const char first_letters
[] = "RRRACEUAPRSF";
1085 static const char digits
[] = "01234567";
1087 /* upper three bytes are marked as reserved ('R'). */
1088 for (i
= 0; i
< flags_count
; i
++) {
1089 if (tcph
->th_use_ace
&& 3 <= i
&& i
<= 5) {
1091 wmem_strbuf_append_c(buf
, digits
[tcp_get_ace(tcph
)]);
1093 wmem_strbuf_append_c(buf
, '-');
1096 if (((tcph
->th_flags
>> (flags_count
- 1 - i
)) & 1)) {
1097 wmem_strbuf_append_c(buf
, first_letters
[i
]);
1099 wmem_strbuf_append(buf
, UTF8_MIDDLE_DOT
);
1104 return wmem_strbuf_finalize(buf
);
1108 * Print the first letter of each flag set, or the dot character otherwise
1111 completeness_flags_to_str_first_letter(wmem_allocator_t
*scope
, uint8_t flags
)
1113 wmem_strbuf_t
*buf
= wmem_strbuf_new(scope
, "");
1115 if( flags
& TCP_COMPLETENESS_RST
)
1116 wmem_strbuf_append(buf
, "R");
1118 wmem_strbuf_append(buf
, UTF8_MIDDLE_DOT
);
1120 if( flags
& TCP_COMPLETENESS_FIN
)
1121 wmem_strbuf_append(buf
, "F");
1123 wmem_strbuf_append(buf
, UTF8_MIDDLE_DOT
);
1125 if( flags
& TCP_COMPLETENESS_DATA
)
1126 wmem_strbuf_append(buf
, "D");
1128 wmem_strbuf_append(buf
, UTF8_MIDDLE_DOT
);
1130 if( flags
& TCP_COMPLETENESS_ACK
)
1131 wmem_strbuf_append(buf
, "A");
1133 wmem_strbuf_append(buf
, UTF8_MIDDLE_DOT
);
1135 if( flags
& TCP_COMPLETENESS_SYNACK
)
1136 wmem_strbuf_append(buf
, "S");
1138 wmem_strbuf_append(buf
, UTF8_MIDDLE_DOT
);
1140 if( flags
& TCP_COMPLETENESS_SYNSENT
)
1141 wmem_strbuf_append(buf
, "S");
1143 wmem_strbuf_append(buf
, UTF8_MIDDLE_DOT
);
1145 return wmem_strbuf_finalize(buf
);
1149 tcp_src_prompt(packet_info
*pinfo
, char *result
)
1151 uint32_t port
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_tcp_srcport
, pinfo
->curr_layer_num
));
1153 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "source (%u%s)", port
, UTF8_RIGHTWARDS_ARROW
);
1157 tcp_src_value(packet_info
*pinfo
)
1159 return p_get_proto_data(pinfo
->pool
, pinfo
, hf_tcp_srcport
, pinfo
->curr_layer_num
);
1163 tcp_dst_prompt(packet_info
*pinfo
, char *result
)
1165 uint32_t port
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_tcp_dstport
, pinfo
->curr_layer_num
));
1167 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW
, port
);
1171 tcp_dst_value(packet_info
*pinfo
)
1173 return p_get_proto_data(pinfo
->pool
, pinfo
, hf_tcp_dstport
, pinfo
->curr_layer_num
);
1177 tcp_both_prompt(packet_info
*pinfo
, char *result
)
1179 uint32_t srcport
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_tcp_srcport
, pinfo
->curr_layer_num
)),
1180 destport
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_tcp_dstport
, pinfo
->curr_layer_num
));
1181 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "both (%u%s%u)", srcport
, UTF8_LEFT_RIGHT_ARROW
, destport
);
1184 static const char* tcp_conv_get_filter_type(conv_item_t
* conv
, conv_filter_type_e filter
)
1187 if (filter
== CONV_FT_SRC_PORT
)
1188 return "tcp.srcport";
1190 if (filter
== CONV_FT_DST_PORT
)
1191 return "tcp.dstport";
1193 if (filter
== CONV_FT_ANY_PORT
)
1197 return CONV_FILTER_INVALID
;
1200 if (filter
== CONV_FT_SRC_ADDRESS
) {
1201 if (conv
->src_address
.type
== AT_IPv4
)
1203 if (conv
->src_address
.type
== AT_IPv6
)
1207 if (filter
== CONV_FT_DST_ADDRESS
) {
1208 if (conv
->dst_address
.type
== AT_IPv4
)
1210 if (conv
->dst_address
.type
== AT_IPv6
)
1214 if (filter
== CONV_FT_ANY_ADDRESS
) {
1215 if (conv
->src_address
.type
== AT_IPv4
)
1217 if (conv
->src_address
.type
== AT_IPv6
)
1221 return CONV_FILTER_INVALID
;
1224 static ct_dissector_info_t tcp_ct_dissector_info
= {&tcp_conv_get_filter_type
};
1227 * callback function for conversation stats
1229 static int tcp_conv_cb_update(conversation_t
*conv
)
1231 struct tcp_analysis
*tcpd
;
1232 tcpd
=get_tcp_conversation_data_idempotent(conv
);
1234 return tcpd
->flow1
.flow_count
+ tcpd
->flow2
.flow_count
;
1239 static tap_packet_status
1240 tcpip_conversation_packet(void *pct
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *vip
, tap_flags_t flags
)
1242 conv_hash_t
*hash
= (conv_hash_t
*) pct
;
1243 hash
->flags
= flags
;
1245 const struct tcpheader
*tcphdr
=(const struct tcpheader
*)vip
;
1247 add_conversation_table_data_extended(hash
, &tcphdr
->ip_src
, &tcphdr
->ip_dst
, tcphdr
->th_sport
, tcphdr
->th_dport
, (conv_id_t
) tcphdr
->th_stream
, 1, pinfo
->fd
->pkt_len
,
1248 &pinfo
->rel_ts
, &pinfo
->abs_ts
, &tcp_ct_dissector_info
, CONVERSATION_TCP
, (uint32_t)pinfo
->num
, tcp_conv_cb_update
);
1251 return TAP_PACKET_REDRAW
;
1254 static tap_packet_status
1255 mptcpip_conversation_packet(void *pct
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *vip
, tap_flags_t flags
)
1257 conv_hash_t
*hash
= (conv_hash_t
*) pct
;
1258 hash
->flags
= flags
;
1260 const struct tcp_analysis
*tcpd
=(const struct tcp_analysis
*)vip
;
1261 const mptcp_meta_flow_t
*meta
=(const mptcp_meta_flow_t
*)tcpd
->fwd
->mptcp_subflow
->meta
;
1263 add_conversation_table_data_with_conv_id(hash
, &meta
->ip_src
, &meta
->ip_dst
,
1264 meta
->sport
, meta
->dport
, (conv_id_t
) tcpd
->mptcp_analysis
->stream
, 1, pinfo
->fd
->pkt_len
,
1265 &pinfo
->rel_ts
, &pinfo
->abs_ts
, &tcp_ct_dissector_info
, CONVERSATION_TCP
);
1267 return TAP_PACKET_REDRAW
;
1270 static const char* tcp_endpoint_get_filter_type(endpoint_item_t
* endpoint
, conv_filter_type_e filter
)
1272 if (filter
== CONV_FT_SRC_PORT
)
1273 return "tcp.srcport";
1275 if (filter
== CONV_FT_DST_PORT
)
1276 return "tcp.dstport";
1278 if (filter
== CONV_FT_ANY_PORT
)
1282 return CONV_FILTER_INVALID
;
1285 if (filter
== CONV_FT_SRC_ADDRESS
) {
1286 if (endpoint
->myaddress
.type
== AT_IPv4
)
1288 if (endpoint
->myaddress
.type
== AT_IPv6
)
1292 if (filter
== CONV_FT_DST_ADDRESS
) {
1293 if (endpoint
->myaddress
.type
== AT_IPv4
)
1295 if (endpoint
->myaddress
.type
== AT_IPv6
)
1299 if (filter
== CONV_FT_ANY_ADDRESS
) {
1300 if (endpoint
->myaddress
.type
== AT_IPv4
)
1302 if (endpoint
->myaddress
.type
== AT_IPv6
)
1306 return CONV_FILTER_INVALID
;
1309 static et_dissector_info_t tcp_endpoint_dissector_info
= {&tcp_endpoint_get_filter_type
};
1311 static tap_packet_status
1312 tcpip_endpoint_packet(void *pit
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *vip
, tap_flags_t flags
)
1314 conv_hash_t
*hash
= (conv_hash_t
*) pit
;
1315 hash
->flags
= flags
;
1317 const struct tcpheader
*tcphdr
=(const struct tcpheader
*)vip
;
1319 /* Take two "add" passes per packet, adding for each direction, ensures that all
1320 packets are counted properly (even if address is sending to itself)
1321 XXX - this could probably be done more efficiently inside endpoint_table */
1322 add_endpoint_table_data(hash
, &tcphdr
->ip_src
, tcphdr
->th_sport
, true, 1, pinfo
->fd
->pkt_len
, &tcp_endpoint_dissector_info
, ENDPOINT_TCP
);
1323 add_endpoint_table_data(hash
, &tcphdr
->ip_dst
, tcphdr
->th_dport
, false, 1, pinfo
->fd
->pkt_len
, &tcp_endpoint_dissector_info
, ENDPOINT_TCP
);
1325 return TAP_PACKET_REDRAW
;
1329 tcp_filter_valid(packet_info
*pinfo
, void *user_data _U_
)
1331 return proto_is_frame_protocol(pinfo
->layers
, "tcp");
1335 tcp_build_filter_by_id(packet_info
*pinfo
, void *user_data _U_
)
1337 return ws_strdup_printf("tcp.stream eq %d", pinfo
->stream_id
);
1341 /****************************************************************************/
1342 /* whenever a TCP packet is seen by the tap listener */
1343 /* Add a new tcp frame into the graph */
1344 static tap_packet_status
1345 tcp_seq_analysis_packet( void *ptr
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *tcp_info
, tap_flags_t tapflags _U_
)
1347 seq_analysis_info_t
*sainfo
= (seq_analysis_info_t
*) ptr
;
1348 const struct tcpheader
*tcph
= (const struct tcpheader
*)tcp_info
;
1350 seq_analysis_item_t
*sai
= sequence_analysis_create_sai_with_addresses(pinfo
, sainfo
);
1353 return TAP_PACKET_DONT_REDRAW
;
1355 sai
->frame_number
= pinfo
->num
;
1357 sai
->port_src
=pinfo
->srcport
;
1358 sai
->port_dst
=pinfo
->destport
;
1360 flags
= tcp_flags_to_str(NULL
, tcph
);
1362 if ((tcph
->th_have_seglen
)&&(tcph
->th_seglen
!=0)){
1363 sai
->frame_label
= ws_strdup_printf("%s - Len: %u",flags
, tcph
->th_seglen
);
1366 sai
->frame_label
= g_strdup(flags
);
1369 wmem_free(NULL
, flags
);
1371 if (tcph
->th_flags
& TH_ACK
)
1372 sai
->comment
= ws_strdup_printf("Seq = %u Ack = %u",tcph
->th_seq
, tcph
->th_ack
);
1374 sai
->comment
= ws_strdup_printf("Seq = %u",tcph
->th_seq
);
1376 sai
->line_style
= 1;
1377 sai
->conv_num
= (uint16_t) tcph
->th_stream
;
1378 sai
->display
= true;
1380 g_queue_push_tail(sainfo
->items
, sai
);
1382 return TAP_PACKET_REDRAW
;
1386 char *tcp_follow_conv_filter(epan_dissect_t
*edt _U_
, packet_info
*pinfo
, unsigned *stream
, unsigned *sub_stream _U_
)
1388 conversation_t
*conv
;
1389 struct tcp_analysis
*tcpd
;
1391 /* XXX: Since TCP doesn't use the endpoint API, we can only look
1392 * up using the current pinfo addresses and ports. We don't want
1393 * to create a new conversation or new TCP stream.
1394 * Eventually the endpoint API should support storing multiple
1395 * endpoints and TCP should be changed to use the endpoint API.
1397 conv
= find_conversation_strat(pinfo
, CONVERSATION_TCP
, 0);
1398 if (((pinfo
->net_src
.type
== AT_IPv4
&& pinfo
->net_dst
.type
== AT_IPv4
) ||
1399 (pinfo
->net_src
.type
== AT_IPv6
&& pinfo
->net_dst
.type
== AT_IPv6
))
1400 && (pinfo
->ptype
== PT_TCP
) &&
1403 /* TCP over IPv4/6 */
1404 tcpd
=get_tcp_conversation_data(conv
, pinfo
);
1408 *stream
= tcpd
->stream
;
1409 return ws_strdup_printf("tcp.stream eq %u", tcpd
->stream
);
1415 char *tcp_follow_index_filter(unsigned stream
, unsigned sub_stream _U_
)
1417 return ws_strdup_printf("tcp.stream eq %u", stream
);
1420 char *tcp_follow_address_filter(address
*src_addr
, address
*dst_addr
, int src_port
, int dst_port
)
1422 const char *ip_version
= src_addr
->type
== AT_IPv6
? "v6" : "";
1423 char src_addr_str
[WS_INET6_ADDRSTRLEN
];
1424 char dst_addr_str
[WS_INET6_ADDRSTRLEN
];
1426 address_to_str_buf(src_addr
, src_addr_str
, sizeof(src_addr_str
));
1427 address_to_str_buf(dst_addr
, dst_addr_str
, sizeof(dst_addr_str
));
1429 return ws_strdup_printf("((ip%s.src eq %s and tcp.srcport eq %d) and "
1430 "(ip%s.dst eq %s and tcp.dstport eq %d))"
1432 "((ip%s.src eq %s and tcp.srcport eq %d) and "
1433 "(ip%s.dst eq %s and tcp.dstport eq %d))",
1434 ip_version
, src_addr_str
, src_port
,
1435 ip_version
, dst_addr_str
, dst_port
,
1436 ip_version
, dst_addr_str
, dst_port
,
1437 ip_version
, src_addr_str
, src_port
);
1441 typedef struct tcp_follow_tap_data
1444 struct tcpheader
* tcph
;
1445 struct tcp_analysis
*tcpd
;
1447 } tcp_follow_tap_data_t
;
1450 * Tries to apply segments from fragments list to the reconstructed payload.
1451 * Fragments that can be appended to the end of the payload will be applied (and
1452 * removed from the list). Fragments that should have been received (according
1453 * to the ack number) will also be appended to the payload (preceded by some
1454 * dummy data to mark packet loss if any).
1456 * Returns true if one fragment has been applied or false if no more fragments
1457 * can be added to the payload (there might still be unacked fragments with
1458 * missing segments before them).
1461 check_follow_fragments(follow_info_t
*follow_info
, bool is_server
, uint32_t acknowledged
, uint32_t packet_num
, bool use_ack
)
1463 GList
*fragment_entry
;
1464 follow_record_t
*fragment
, *follow_record
;
1465 uint32_t lowest_seq
= 0;
1468 fragment_entry
= g_list_first(follow_info
->fragments
[is_server
]);
1469 if (fragment_entry
== NULL
)
1472 fragment
= (follow_record_t
*)fragment_entry
->data
;
1473 lowest_seq
= fragment
->seq
;
1475 for (; fragment_entry
!= NULL
; fragment_entry
= g_list_next(fragment_entry
))
1477 fragment
= (follow_record_t
*)fragment_entry
->data
;
1479 if( GT_SEQ(lowest_seq
, fragment
->seq
) ) {
1480 lowest_seq
= fragment
->seq
;
1483 if( LT_SEQ(fragment
->seq
, follow_info
->seq
[is_server
]) ) {
1485 /* this sequence number seems dated, but
1486 check the end to make sure it has no more
1487 info than we have already seen */
1488 newseq
= fragment
->seq
+ fragment
->data
->len
;
1489 if( GT_SEQ(newseq
, follow_info
->seq
[is_server
]) ) {
1492 /* this one has more than we have seen. let's get the
1493 payload that we have not seen. This happens when
1494 part of this frame has been retransmitted */
1496 new_pos
= follow_info
->seq
[is_server
] - fragment
->seq
;
1498 if ( fragment
->data
->len
> new_pos
) {
1499 uint32_t new_frag_size
= fragment
->data
->len
- new_pos
;
1501 follow_record
= g_new0(follow_record_t
,1);
1503 follow_record
->is_server
= is_server
;
1504 follow_record
->packet_num
= fragment
->packet_num
;
1505 follow_record
->abs_ts
= fragment
->abs_ts
;
1506 follow_record
->seq
= follow_info
->seq
[is_server
] + new_frag_size
;
1508 follow_record
->data
= g_byte_array_append(g_byte_array_new(),
1509 fragment
->data
->data
+ new_pos
,
1512 follow_info
->payload
= g_list_prepend(follow_info
->payload
, follow_record
);
1515 follow_info
->seq
[is_server
] += (fragment
->data
->len
- new_pos
);
1518 /* Remove the fragment from the list as the "new" part of it
1519 * has been processed or its data has been seen already in
1520 * another packet. */
1521 g_byte_array_free(fragment
->data
, true);
1523 follow_info
->fragments
[is_server
] = g_list_delete_link(follow_info
->fragments
[is_server
], fragment_entry
);
1527 if( EQ_SEQ(fragment
->seq
, follow_info
->seq
[is_server
]) ) {
1528 /* this fragment fits the stream */
1529 if( fragment
->data
->len
> 0 ) {
1530 follow_info
->payload
= g_list_prepend(follow_info
->payload
, fragment
);
1533 follow_info
->seq
[is_server
] += fragment
->data
->len
;
1534 follow_info
->fragments
[is_server
] = g_list_delete_link(follow_info
->fragments
[is_server
], fragment_entry
);
1539 if( use_ack
&& GT_SEQ(acknowledged
, lowest_seq
) ) {
1540 /* There are frames missing in the capture file that were seen
1541 * by the receiving host. Add dummy stream chunk with the data
1542 * "[xxx bytes missing in capture file]".
1544 dummy_str
= ws_strdup_printf("[%d bytes missing in capture file]",
1545 (int)(lowest_seq
- follow_info
->seq
[is_server
]) );
1546 // XXX the dummy replacement could be larger than the actual missing bytes.
1548 follow_record
= g_new0(follow_record_t
,1);
1550 follow_record
->data
= g_byte_array_append(g_byte_array_new(),
1551 (unsigned char*)dummy_str
,
1552 (unsigned)strlen(dummy_str
)+1);
1554 follow_record
->is_server
= is_server
;
1555 follow_record
->packet_num
= packet_num
;
1556 follow_record
->seq
= lowest_seq
;
1558 follow_info
->seq
[is_server
] = lowest_seq
;
1559 follow_info
->payload
= g_list_prepend(follow_info
->payload
, follow_record
);
1566 static tap_packet_status
1567 follow_tcp_tap_listener(void *tapdata
, packet_info
*pinfo
,
1568 epan_dissect_t
*edt _U_
, const void *data
, tap_flags_t flags _U_
)
1570 follow_record_t
*follow_record
;
1571 follow_info_t
*follow_info
= (follow_info_t
*)tapdata
;
1572 const tcp_follow_tap_data_t
*follow_data
= (const tcp_follow_tap_data_t
*)data
;
1574 uint32_t sequence
= follow_data
->tcph
->th_seq
;
1575 uint32_t length
= follow_data
->tcph
->th_have_seglen
1576 ? follow_data
->tcph
->th_seglen
1578 uint32_t data_offset
= 0;
1579 uint32_t data_length
= tvb_captured_length(follow_data
->tvb
);
1581 if (follow_data
->tcph
->th_flags
& TH_SYN
) {
1585 if (follow_info
->client_port
== 0) {
1586 follow_info
->client_port
= pinfo
->srcport
;
1587 copy_address(&follow_info
->client_ip
, &pinfo
->src
);
1588 follow_info
->server_port
= pinfo
->destport
;
1589 copy_address(&follow_info
->server_ip
, &pinfo
->dst
);
1592 is_server
= !(addresses_equal(&follow_info
->client_ip
, &pinfo
->src
) && follow_info
->client_port
== pinfo
->srcport
);
1594 /* Check whether this frame ACKs fragments in flow from the other direction.
1595 * This happens when frames are not in the capture file, but were actually
1596 * seen by the receiving host (Fixes bug 592).
1598 if (follow_info
->fragments
[!is_server
] != NULL
) {
1599 while (check_follow_fragments(follow_info
, !is_server
, follow_data
->tcph
->th_ack
, pinfo
->fd
->num
, true));
1603 * If this is the first segment of this stream, initialize the next expected
1604 * sequence number. If there is any data, it will be added below.
1606 if (follow_info
->bytes_written
[is_server
] == 0 && follow_info
->seq
[is_server
] == 0) {
1607 follow_info
->seq
[is_server
] = sequence
;
1610 /* We have already seen this src (and received some segments), let's figure
1611 * out whether this segment extends the stream or overlaps a previous gap. */
1612 if (LT_SEQ(sequence
, follow_info
->seq
[is_server
])) {
1613 /* This sequence number seems dated, but check the end in case it was a
1614 * retransmission with more data. */
1615 uint32_t nextseq
= sequence
+ length
;
1616 if (GT_SEQ(nextseq
, follow_info
->seq
[is_server
])) {
1617 /* The begin of the segment was already seen, try to add the
1618 * remaining data that we have not seen to the payload. */
1619 data_offset
= follow_info
->seq
[is_server
] - sequence
;
1620 if (data_length
<= data_offset
) {
1623 data_length
-= data_offset
;
1626 sequence
= follow_info
->seq
[is_server
];
1627 length
= nextseq
- follow_info
->seq
[is_server
];
1631 * Ignore segments that have no new data (either because it was empty, or
1632 * because it was fully overlapping with previously received data).
1634 if (data_length
== 0 || LT_SEQ(sequence
, follow_info
->seq
[is_server
])) {
1635 return TAP_PACKET_DONT_REDRAW
;
1638 follow_record
= g_new0(follow_record_t
, 1);
1639 follow_record
->is_server
= is_server
;
1640 follow_record
->packet_num
= pinfo
->fd
->num
;
1641 follow_record
->abs_ts
= pinfo
->fd
->abs_ts
;
1642 follow_record
->seq
= sequence
; /* start of fragment, used by check_follow_fragments. */
1643 follow_record
->data
= g_byte_array_append(g_byte_array_new(),
1644 tvb_get_ptr(follow_data
->tvb
, data_offset
, data_length
),
1647 if (EQ_SEQ(sequence
, follow_info
->seq
[is_server
])) {
1648 /* The segment overlaps or extends the previous end of stream. */
1649 follow_info
->seq
[is_server
] += length
;
1650 follow_info
->bytes_written
[is_server
] += follow_record
->data
->len
;
1651 follow_info
->payload
= g_list_prepend(follow_info
->payload
, follow_record
);
1653 /* done with the packet, see if it caused a fragment to fit */
1654 while(check_follow_fragments(follow_info
, is_server
, 0, pinfo
->fd
->num
, false));
1656 /* Out of order packet (more preceding segments are expected). */
1657 follow_info
->fragments
[is_server
] = g_list_append(follow_info
->fragments
[is_server
], follow_record
);
1659 return TAP_PACKET_DONT_REDRAW
;
1662 #define EXP_PDU_TCP_INFO_DATA_LEN 20
1663 #define EXP_PDU_TCP_INFO_VERSION 1
1664 #define EXP_PDU_TAG_TCP_STREAM_ID_LEN 4
1666 static int exp_pdu_tcp_dissector_data_size(packet_info
*pinfo _U_
, void* data _U_
)
1668 return EXP_PDU_TCP_INFO_DATA_LEN
+4;
1671 static int exp_pdu_tcp_dissector_data_populate_data(packet_info
*pinfo _U_
, void* data
, uint8_t *tlv_buffer
, uint32_t buffer_size _U_
)
1673 struct tcpinfo
* dissector_data
= (struct tcpinfo
*)data
;
1675 phton16(&tlv_buffer
[0], EXP_PDU_TAG_TCP_INFO_DATA
);
1676 phton16(&tlv_buffer
[2], EXP_PDU_TCP_INFO_DATA_LEN
); /* tag length */
1677 phton16(&tlv_buffer
[4], EXP_PDU_TCP_INFO_VERSION
);
1678 phton32(&tlv_buffer
[6], dissector_data
->seq
);
1679 phton32(&tlv_buffer
[10], dissector_data
->nxtseq
);
1680 phton32(&tlv_buffer
[14], dissector_data
->lastackseq
);
1681 tlv_buffer
[18] = dissector_data
->is_reassembled
;
1682 phton16(&tlv_buffer
[19], dissector_data
->flags
);
1683 phton16(&tlv_buffer
[21], dissector_data
->urgent_pointer
);
1685 return exp_pdu_tcp_dissector_data_size(pinfo
, data
);
1689 handle_export_pdu_check_desegmentation(packet_info
*pinfo
, tvbuff_t
*tvb
)
1691 /* Check to see if the tvb we're planning on exporting PDUs from was
1692 * dissected fully, or whether it requested further desegmentation.
1693 * This should only matter on the first pass (so in one-pass tshark.)
1695 if (pinfo
->can_desegment
> 0 && pinfo
->desegment_len
!= 0) {
1696 /* Desegmentation was requested. How much did we desegment here?
1697 * The rest, presumably, will be handled in another frame.
1699 if (pinfo
->desegment_offset
== 0) {
1700 /* We couldn't, in fact, dissect any of it. */
1703 tvb
= tvb_new_subset_length(tvb
, 0, pinfo
->desegment_offset
);
1709 handle_export_pdu_dissection_table(packet_info
*pinfo
, tvbuff_t
*tvb
, uint32_t port
, struct tcpinfo
*tcpinfo
)
1711 if (have_tap_listener(exported_pdu_tap
)) {
1712 tvb
= handle_export_pdu_check_desegmentation(pinfo
, tvb
);
1716 exp_pdu_data_item_t exp_pdu_data_table_value
= {exp_pdu_data_dissector_table_num_value_size
, exp_pdu_data_dissector_table_num_value_populate_data
, NULL
};
1717 exp_pdu_data_item_t exp_pdu_data_dissector_data
= {exp_pdu_tcp_dissector_data_size
, exp_pdu_tcp_dissector_data_populate_data
, NULL
};
1719 const exp_pdu_data_item_t
*tcp_exp_pdu_items
[] = {
1720 &exp_pdu_data_src_ip
,
1721 &exp_pdu_data_dst_ip
,
1722 &exp_pdu_data_port_type
,
1723 &exp_pdu_data_src_port
,
1724 &exp_pdu_data_dst_port
,
1725 &exp_pdu_data_orig_frame_num
,
1726 &exp_pdu_data_table_value
,
1727 &exp_pdu_data_dissector_data
,
1731 exp_pdu_data_t
*exp_pdu_data
;
1733 exp_pdu_data_table_value
.data
= GUINT_TO_POINTER(port
);
1734 exp_pdu_data_dissector_data
.data
= tcpinfo
;
1736 exp_pdu_data
= export_pdu_create_tags(pinfo
, "tcp.port", EXP_PDU_TAG_DISSECTOR_TABLE_NAME
, tcp_exp_pdu_items
);
1737 exp_pdu_data
->tvb_captured_length
= tvb_captured_length(tvb
);
1738 exp_pdu_data
->tvb_reported_length
= tvb_reported_length(tvb
);
1739 exp_pdu_data
->pdu_tvb
= tvb
;
1741 /* match uint is restored after calling dissector, so in order to have the right value in exported PDU
1742 * we need to set it here.
1744 tap_queue_packet(exported_pdu_tap
, pinfo
, exp_pdu_data
);
1749 handle_export_pdu_heuristic(packet_info
*pinfo
, tvbuff_t
*tvb
, heur_dtbl_entry_t
*hdtbl_entry
, struct tcpinfo
*tcpinfo
)
1751 exp_pdu_data_t
*exp_pdu_data
= NULL
;
1753 if (have_tap_listener(exported_pdu_tap
)) {
1754 tvb
= handle_export_pdu_check_desegmentation(pinfo
, tvb
);
1758 if ((!hdtbl_entry
->enabled
) ||
1759 (hdtbl_entry
->protocol
!= NULL
&& !proto_is_protocol_enabled(hdtbl_entry
->protocol
))) {
1760 exp_pdu_data
= export_pdu_create_common_tags(pinfo
, "data", EXP_PDU_TAG_DISSECTOR_NAME
);
1761 } else if (hdtbl_entry
->protocol
!= NULL
) {
1762 exp_pdu_data_item_t exp_pdu_data_dissector_data
= {exp_pdu_tcp_dissector_data_size
, exp_pdu_tcp_dissector_data_populate_data
, NULL
};
1763 const exp_pdu_data_item_t
*tcp_exp_pdu_items
[] = {
1764 &exp_pdu_data_src_ip
,
1765 &exp_pdu_data_dst_ip
,
1766 &exp_pdu_data_port_type
,
1767 &exp_pdu_data_src_port
,
1768 &exp_pdu_data_dst_port
,
1769 &exp_pdu_data_orig_frame_num
,
1770 &exp_pdu_data_dissector_data
,
1774 exp_pdu_data_dissector_data
.data
= tcpinfo
;
1776 exp_pdu_data
= export_pdu_create_tags(pinfo
, hdtbl_entry
->short_name
, EXP_PDU_TAG_HEUR_DISSECTOR_NAME
, tcp_exp_pdu_items
);
1779 if (exp_pdu_data
!= NULL
) {
1780 exp_pdu_data
->tvb_captured_length
= tvb_captured_length(tvb
);
1781 exp_pdu_data
->tvb_reported_length
= tvb_reported_length(tvb
);
1782 exp_pdu_data
->pdu_tvb
= tvb
;
1784 tap_queue_packet(exported_pdu_tap
, pinfo
, exp_pdu_data
);
1790 handle_export_pdu_conversation(packet_info
*pinfo
, tvbuff_t
*tvb
, int src_port
, int dst_port
, struct tcpinfo
*tcpinfo
)
1792 if (have_tap_listener(exported_pdu_tap
)) {
1793 tvb
= handle_export_pdu_check_desegmentation(pinfo
, tvb
);
1797 conversation_t
*conversation
= find_conversation(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, CONVERSATION_TCP
, src_port
, dst_port
, 0);
1798 if (conversation
!= NULL
)
1800 dissector_handle_t handle
= (dissector_handle_t
)wmem_tree_lookup32_le(conversation
->dissector_tree
, pinfo
->num
);
1803 exp_pdu_data_item_t exp_pdu_data_dissector_data
= {exp_pdu_tcp_dissector_data_size
, exp_pdu_tcp_dissector_data_populate_data
, NULL
};
1804 const exp_pdu_data_item_t
*tcp_exp_pdu_items
[] = {
1805 &exp_pdu_data_src_ip
,
1806 &exp_pdu_data_dst_ip
,
1807 &exp_pdu_data_port_type
,
1808 &exp_pdu_data_src_port
,
1809 &exp_pdu_data_dst_port
,
1810 &exp_pdu_data_orig_frame_num
,
1811 &exp_pdu_data_dissector_data
,
1815 exp_pdu_data_t
*exp_pdu_data
;
1817 exp_pdu_data_dissector_data
.data
= tcpinfo
;
1819 exp_pdu_data
= export_pdu_create_tags(pinfo
, dissector_handle_get_dissector_name(handle
), EXP_PDU_TAG_DISSECTOR_NAME
, tcp_exp_pdu_items
);
1820 exp_pdu_data
->tvb_captured_length
= tvb_captured_length(tvb
);
1821 exp_pdu_data
->tvb_reported_length
= tvb_reported_length(tvb
);
1822 exp_pdu_data
->pdu_tvb
= tvb
;
1824 tap_queue_packet(exported_pdu_tap
, pinfo
, exp_pdu_data
);
1831 * display the TCP Conversation Completeness
1832 * we of course pay much attention on complete conversations but also incomplete ones which
1833 * have a regular start, as in practice we are often looking for such thing
1835 static void conversation_completeness_fill(char *buf
, uint32_t value
)
1838 case TCP_COMPLETENESS_SYNSENT
:
1839 snprintf(buf
, ITEM_LABEL_LENGTH
, "Incomplete, SYN_SENT (%u)", value
);
1841 case (TCP_COMPLETENESS_SYNSENT
|
1842 TCP_COMPLETENESS_SYNACK
):
1843 snprintf(buf
, ITEM_LABEL_LENGTH
, "Incomplete, CLIENT_ESTABLISHED (%u)", value
);
1845 case (TCP_COMPLETENESS_SYNSENT
|
1846 TCP_COMPLETENESS_SYNACK
|
1847 TCP_COMPLETENESS_ACK
):
1848 snprintf(buf
, ITEM_LABEL_LENGTH
, "Incomplete, ESTABLISHED (%u)", value
);
1850 case (TCP_COMPLETENESS_SYNSENT
|
1851 TCP_COMPLETENESS_SYNACK
|
1852 TCP_COMPLETENESS_ACK
|
1853 TCP_COMPLETENESS_DATA
):
1854 snprintf(buf
, ITEM_LABEL_LENGTH
, "Incomplete, DATA (%u)", value
);
1856 case (TCP_COMPLETENESS_SYNSENT
|
1857 TCP_COMPLETENESS_SYNACK
|
1858 TCP_COMPLETENESS_ACK
|
1859 TCP_COMPLETENESS_DATA
|
1860 TCP_COMPLETENESS_FIN
):
1861 case (TCP_COMPLETENESS_SYNSENT
|
1862 TCP_COMPLETENESS_SYNACK
|
1863 TCP_COMPLETENESS_ACK
|
1864 TCP_COMPLETENESS_DATA
|
1865 TCP_COMPLETENESS_RST
):
1866 case (TCP_COMPLETENESS_SYNSENT
|
1867 TCP_COMPLETENESS_SYNACK
|
1868 TCP_COMPLETENESS_ACK
|
1869 TCP_COMPLETENESS_DATA
|
1870 TCP_COMPLETENESS_FIN
|
1871 TCP_COMPLETENESS_RST
):
1872 snprintf(buf
, ITEM_LABEL_LENGTH
, "Complete, WITH_DATA (%u)", value
);
1874 case (TCP_COMPLETENESS_SYNSENT
|
1875 TCP_COMPLETENESS_SYNACK
|
1876 TCP_COMPLETENESS_ACK
|
1877 TCP_COMPLETENESS_FIN
):
1878 case (TCP_COMPLETENESS_SYNSENT
|
1879 TCP_COMPLETENESS_SYNACK
|
1880 TCP_COMPLETENESS_ACK
|
1881 TCP_COMPLETENESS_RST
):
1882 case (TCP_COMPLETENESS_SYNSENT
|
1883 TCP_COMPLETENESS_SYNACK
|
1884 TCP_COMPLETENESS_ACK
|
1885 TCP_COMPLETENESS_FIN
|
1886 TCP_COMPLETENESS_RST
):
1887 snprintf(buf
, ITEM_LABEL_LENGTH
, "Complete, NO_DATA (%u)", value
);
1890 snprintf(buf
, ITEM_LABEL_LENGTH
, "Incomplete (%u)", value
);
1895 /* TCP structs and definitions */
1897 /* **************************************************************************
1898 * RTT, relative sequence numbers, window scaling & etc.
1899 * **************************************************************************/
1900 static bool tcp_analyze_seq
= true;
1901 static bool tcp_relative_seq
= true;
1902 static bool tcp_track_bytes_in_flight
= true;
1903 static bool tcp_bif_seq_based
;
1904 static bool tcp_calculate_ts
= true;
1906 static bool tcp_analyze_mptcp
= true;
1907 static bool mptcp_relative_seq
= true;
1908 static bool mptcp_analyze_mappings
;
1909 static bool mptcp_intersubflows_retransmission
;
1912 #define TCP_A_RETRANSMISSION 0x0001
1913 #define TCP_A_LOST_PACKET 0x0002
1914 #define TCP_A_ACK_LOST_PACKET 0x0004
1915 #define TCP_A_KEEP_ALIVE 0x0008
1916 #define TCP_A_DUPLICATE_ACK 0x0010
1917 #define TCP_A_ZERO_WINDOW 0x0020
1918 #define TCP_A_ZERO_WINDOW_PROBE 0x0040
1919 #define TCP_A_ZERO_WINDOW_PROBE_ACK 0x0080
1920 #define TCP_A_KEEP_ALIVE_ACK 0x0100
1921 #define TCP_A_OUT_OF_ORDER 0x0200
1922 #define TCP_A_FAST_RETRANSMISSION 0x0400
1923 #define TCP_A_WINDOW_UPDATE 0x0800
1924 #define TCP_A_WINDOW_FULL 0x1000
1925 #define TCP_A_REUSED_PORTS 0x2000
1926 #define TCP_A_SPURIOUS_RETRANSMISSION 0x4000
1928 /* This flag for desegment_tcp to exclude segments with previously
1929 * seen sequence numbers.
1930 * It is from the perspective of Wireshark's reassembler, whereas
1931 * the other flags above are from the perspective of the sender.
1932 * (E.g., TCP_A_RETRANSMISSION or TCP_A_SPURIOUS_RETRANSMISSION
1933 * can be set even when first appearance in the capture file.)
1935 #define TCP_A_OLD_DATA 0x8000
1937 /* Static TCP flags. Set in tcp_flow_t:static_flags */
1938 #define TCP_S_BASE_SEQ_SET 0x01
1939 #define TCP_S_SAW_SYN 0x03
1940 #define TCP_S_SAW_SYNACK 0x05
1943 /* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */
1944 #define MPTCP_META_HAS_BASE_DSN_MSB 0x01
1945 #define MPTCP_META_HAS_KEY 0x03
1946 #define MPTCP_META_HAS_TOKEN 0x04
1947 #define MPTCP_META_HAS_ADDRESSES 0x08
1949 /* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */
1950 #define MPTCP_SUBFLOW_HAS_NONCE 0x01
1951 #define MPTCP_SUBFLOW_HAS_ADDRESS_ID 0x02
1953 /* MPTCP meta analysis related */
1954 #define MPTCP_META_CHECKSUM_REQUIRED 0x0002
1956 /* if we have no key for this connection, some conversion become impossible,
1961 mptcp_convert_dsn(uint64_t dsn
, mptcp_meta_flow_t
*meta
, enum mptcp_dsn_conversion conv
, bool relative
, uint64_t *result
) {
1965 /* if relative is set then we need the 64 bits version anyway
1966 * we assume no wrapping was done on the 32 lsb so this may be wrong for elephant flows
1968 if(conv
== DSN_CONV_32_TO_64
|| relative
) {
1970 if(!(meta
->static_flags
& MPTCP_META_HAS_BASE_DSN_MSB
)) {
1971 /* can't do those without the expected_idsn based on the key */
1976 if(conv
== DSN_CONV_32_TO_64
) {
1977 *result
= keep_32msb_of_uint64(meta
->base_dsn
) | dsn
;
1981 *result
-= meta
->base_dsn
;
1984 if(conv
== DSN_CONV_64_TO_32
) {
1985 *result
= (uint32_t) *result
;
1993 process_tcp_payload(tvbuff_t
*tvb
, volatile int offset
, packet_info
*pinfo
,
1994 proto_tree
*tree
, proto_tree
*tcp_tree
, int src_port
, int dst_port
,
1995 uint32_t seq
, uint32_t nxtseq
, bool is_tcp_segment
,
1996 struct tcp_analysis
*tcpd
, struct tcpinfo
*tcpinfo
);
1999 static struct tcp_analysis
*
2000 init_tcp_conversation_data(packet_info
*pinfo
, int direction
)
2002 struct tcp_analysis
*tcpd
;
2004 /* Initialize the tcp protocol data structure to add to the tcp conversation */
2005 tcpd
=wmem_new0(wmem_file_scope(), struct tcp_analysis
);
2006 tcpd
->flow1
.win_scale
= (direction
>= 0) ? pinfo
->src_win_scale
: pinfo
->dst_win_scale
;
2007 tcpd
->flow1
.window
= UINT32_MAX
;
2008 tcpd
->flow1
.multisegment_pdus
=wmem_tree_new(wmem_file_scope());
2010 tcpd
->flow2
.window
= UINT32_MAX
;
2011 tcpd
->flow2
.win_scale
= (direction
>= 0) ? pinfo
->dst_win_scale
: pinfo
->src_win_scale
;
2012 tcpd
->flow2
.multisegment_pdus
=wmem_tree_new(wmem_file_scope());
2014 if (tcp_reassemble_out_of_order
) {
2015 tcpd
->flow1
.ooo_segments
=wmem_list_new(wmem_file_scope());
2016 tcpd
->flow2
.ooo_segments
=wmem_list_new(wmem_file_scope());
2019 /* Only allocate the data if its actually going to be analyzed */
2020 if (tcp_analyze_seq
)
2022 tcpd
->flow1
.tcp_analyze_seq_info
= wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t
);
2023 tcpd
->flow2
.tcp_analyze_seq_info
= wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t
);
2025 /* Only allocate the data if its actually going to be displayed */
2026 if (tcp_display_process_info
)
2028 tcpd
->flow1
.process_info
= wmem_new0(wmem_file_scope(), struct tcp_process_info_t
);
2029 tcpd
->flow2
.process_info
= wmem_new0(wmem_file_scope(), struct tcp_process_info_t
);
2032 tcpd
->acked_table
=wmem_tree_new(wmem_file_scope());
2033 tcpd
->ts_first
.secs
=pinfo
->abs_ts
.secs
;
2034 tcpd
->ts_first
.nsecs
=pinfo
->abs_ts
.nsecs
;
2035 nstime_set_zero(&tcpd
->ts_mru_syn
);
2036 nstime_set_zero(&tcpd
->ts_first_rtt
);
2037 tcpd
->ts_prev
.secs
=pinfo
->abs_ts
.secs
;
2038 tcpd
->ts_prev
.nsecs
=pinfo
->abs_ts
.nsecs
;
2039 tcpd
->flow1
.valid_bif
= true;
2040 tcpd
->flow2
.valid_bif
= true;
2041 tcpd
->flow1
.push_bytes_sent
= 0;
2042 tcpd
->flow2
.push_bytes_sent
= 0;
2043 tcpd
->flow1
.push_set_last
= false;
2044 tcpd
->flow2
.push_set_last
= false;
2045 tcpd
->flow1
.closing_initiator
= false;
2046 tcpd
->flow2
.closing_initiator
= false;
2047 tcpd
->stream
= tcp_stream_count
++;
2048 tcpd
->server_port
= 0;
2049 tcpd
->tfo_syn_data
= false;
2050 tcpd
->flow_direction
= 0;
2051 tcpd
->flow1
.flow_count
= 0;
2052 tcpd
->flow2
.flow_count
= 0;
2057 /* setup meta as well */
2059 mptcp_init_subflow(tcp_flow_t
*flow
)
2061 struct mptcp_subflow
*sf
= wmem_new0(wmem_file_scope(), struct mptcp_subflow
);
2063 DISSECTOR_ASSERT(flow
->mptcp_subflow
== 0);
2064 flow
->mptcp_subflow
= sf
;
2065 sf
->ssn2dsn_mappings
= wmem_itree_new(wmem_file_scope());
2066 sf
->dsn2packet_map
= wmem_itree_new(wmem_file_scope());
2070 /* add a new subflow to an mptcp connection */
2072 mptcp_attach_subflow(struct mptcp_analysis
* mptcpd
, struct tcp_analysis
* tcpd
) {
2074 if(!wmem_list_find(mptcpd
->subflows
, tcpd
)) {
2075 wmem_list_prepend(mptcpd
->subflows
, tcpd
);
2078 /* in case we merge 2 mptcp connections */
2079 tcpd
->mptcp_analysis
= mptcpd
;
2082 struct tcp_analysis
*
2083 get_tcp_conversation_data_idempotent(conversation_t
*conv
)
2085 struct tcp_analysis
*tcpd
;
2087 /* Get the data for this conversation */
2088 tcpd
=(struct tcp_analysis
*)conversation_get_proto_data(conv
, proto_tcp
);
2093 struct tcp_analysis
*
2094 get_tcp_conversation_data(conversation_t
*conv
, packet_info
*pinfo
)
2097 struct tcp_analysis
*tcpd
;
2098 bool clear_ta
= true;
2100 /* Did the caller supply the conversation pointer? */
2102 /* If the caller didn't supply a conversation, don't
2103 * clear the analysis, it may be needed */
2105 conv
= find_or_create_conversation(pinfo
);
2108 /* Get the data for this conversation */
2109 tcpd
=(struct tcp_analysis
*)conversation_get_proto_data(conv
, proto_tcp
);
2111 direction
= cmp_address(&pinfo
->src
, &pinfo
->dst
);
2112 /* if the addresses are equal, match the ports instead */
2113 if (direction
== 0) {
2114 direction
= (pinfo
->srcport
> pinfo
->destport
) ? 1 : -1;
2116 /* If the conversation was just created or it matched a
2117 * conversation with template options, tcpd will not
2118 * have been initialized. So, initialize
2119 * a new tcpd structure for the conversation.
2122 tcpd
= init_tcp_conversation_data(pinfo
, direction
);
2123 conversation_add_proto_data(conv
, proto_tcp
, tcpd
);
2130 /* check direction and get ua lists */
2132 tcpd
->fwd
=&(tcpd
->flow1
);
2133 tcpd
->rev
=&(tcpd
->flow2
);
2135 tcpd
->fwd
=&(tcpd
->flow2
);
2136 tcpd
->rev
=&(tcpd
->flow1
);
2145 /* Attach process info to a flow */
2146 /* XXX - We depend on the TCP dissector finding the conversation first */
2148 add_tcp_process_info(uint32_t frame_num
, address
*local_addr
, address
*remote_addr
, uint16_t local_port
, uint16_t remote_port
, uint32_t uid
, uint32_t pid
, char *username
, char *command
) {
2149 conversation_t
*conv
;
2150 struct tcp_analysis
*tcpd
;
2151 tcp_flow_t
*flow
= NULL
;
2153 if (!tcp_display_process_info
)
2156 conv
= find_conversation(frame_num
, local_addr
, remote_addr
, CONVERSATION_TCP
, local_port
, remote_port
, 0);
2161 tcpd
= (struct tcp_analysis
*)conversation_get_proto_data(conv
, proto_tcp
);
2166 if (cmp_address(local_addr
, conversation_key_addr1(conv
->key_ptr
)) == 0 && local_port
== conversation_key_port1(conv
->key_ptr
)) {
2167 flow
= &tcpd
->flow1
;
2168 } else if (cmp_address(remote_addr
, conversation_key_addr1(conv
->key_ptr
)) == 0 && remote_port
== conversation_key_port1(conv
->key_ptr
)) {
2169 flow
= &tcpd
->flow2
;
2171 if (!flow
|| (flow
->process_info
&& flow
->process_info
->command
)) {
2175 if (flow
->process_info
== NULL
)
2176 flow
->process_info
= wmem_new0(wmem_file_scope(), struct tcp_process_info_t
);
2178 flow
->process_info
->process_uid
= uid
;
2179 flow
->process_info
->process_pid
= pid
;
2180 flow
->process_info
->username
= wmem_strdup(wmem_file_scope(), username
);
2181 flow
->process_info
->command
= wmem_strdup(wmem_file_scope(), command
);
2184 /* Return the current stream count */
2185 uint32_t get_tcp_stream_count(void)
2187 return tcp_stream_count
;
2190 /* Return the mptcp current stream count */
2191 uint32_t get_mptcp_stream_count(void)
2193 return mptcp_stream_count
;
2196 /* Calculate the timestamps relative to this conversation */
2198 tcp_calculate_timestamps(packet_info
*pinfo
, struct tcp_analysis
*tcpd
,
2199 struct tcp_per_packet_data_t
*tcppd
)
2202 tcppd
= wmem_new(wmem_file_scope(), struct tcp_per_packet_data_t
);
2203 p_add_proto_data(wmem_file_scope(), pinfo
, proto_tcp
, pinfo
->curr_layer_num
, tcppd
);
2209 /* pre-increment so packet numbers start at 1 */
2210 tcppd
->pnum
= ++tcpd
->pnum
;
2212 nstime_delta(&tcppd
->ts_del
, &pinfo
->abs_ts
, &tcpd
->ts_prev
);
2213 tcppd
->tcp_snd_manual_analysis
= 0;
2215 tcpd
->ts_prev
.secs
=pinfo
->abs_ts
.secs
;
2216 tcpd
->ts_prev
.nsecs
=pinfo
->abs_ts
.nsecs
;
2219 /* Add a subtree with the timestamps relative to this conversation */
2221 tcp_print_timestamps(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*parent_tree
, struct tcp_analysis
*tcpd
, struct tcp_per_packet_data_t
*tcppd
)
2230 tree
=proto_tree_add_subtree(parent_tree
, tvb
, 0, 0, ett_tcp_timestamps
, &item
, "Timestamps");
2231 proto_item_set_generated(item
);
2233 nstime_delta(&ts
, &pinfo
->abs_ts
, &tcpd
->ts_first
);
2234 item
= proto_tree_add_time(tree
, hf_tcp_ts_relative
, tvb
, 0, 0, &ts
);
2235 proto_item_set_generated(item
);
2238 tcppd
= (struct tcp_per_packet_data_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_tcp
, pinfo
->curr_layer_num
);
2241 item
= proto_tree_add_time(tree
, hf_tcp_ts_delta
, tvb
, 0, 0,
2243 proto_item_set_generated(item
);
2248 print_pdu_tracking_data(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*tcp_tree
, struct tcp_multisegment_pdu
*msp
)
2252 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[Continuation to #%u] ", msp
->first_frame
);
2253 item
=proto_tree_add_uint(tcp_tree
, hf_tcp_continuation_to
,
2254 tvb
, 0, 0, msp
->first_frame
);
2255 proto_item_set_generated(item
);
2258 /* if we know that a PDU starts inside this segment, return the adjusted
2259 offset to where that PDU starts or just return offset back
2260 and let TCP try to find out what it can about this segment
2263 scan_for_next_pdu(tvbuff_t
*tvb
, proto_tree
*tcp_tree
, packet_info
*pinfo
, int offset
, uint32_t seq
, uint32_t nxtseq
, wmem_tree_t
*multisegment_pdus
)
2265 struct tcp_multisegment_pdu
*msp
=NULL
;
2267 if(!pinfo
->fd
->visited
) {
2268 msp
=(struct tcp_multisegment_pdu
*)wmem_tree_lookup32_le(multisegment_pdus
, seq
-1);
2270 /* If this is a continuation of a PDU started in a
2271 * previous segment we need to update the last_frame
2274 if(seq
>msp
->seq
&& seq
<msp
->nxtpdu
) {
2275 msp
->last_frame
=pinfo
->num
;
2276 msp
->last_frame_time
=pinfo
->abs_ts
;
2277 print_pdu_tracking_data(pinfo
, tvb
, tcp_tree
, msp
);
2280 /* If this segment is completely within a previous PDU
2281 * then we just skip this packet
2283 if(seq
>msp
->seq
&& nxtseq
<=msp
->nxtpdu
) {
2286 if(seq
<msp
->nxtpdu
&& nxtseq
>msp
->nxtpdu
) {
2287 offset
+=msp
->nxtpdu
-seq
;
2293 /* First we try to find the start and transfer time for a PDU.
2294 * We only print this for the very first segment of a PDU
2295 * and only for PDUs spanning multiple segments.
2296 * Se we look for if there was any multisegment PDU started
2297 * just BEFORE the end of this segment. I.e. either inside this
2298 * segment or in a previous segment.
2299 * Since this might also match PDUs that are completely within
2300 * this segment we also verify that the found PDU does span
2301 * beyond the end of this segment.
2303 msp
=(struct tcp_multisegment_pdu
*)wmem_tree_lookup32_le(multisegment_pdus
, nxtseq
-1);
2305 if(pinfo
->num
==msp
->first_frame
) {
2309 item
=proto_tree_add_uint(tcp_tree
, hf_tcp_pdu_last_frame
, tvb
, 0, 0, msp
->last_frame
);
2310 proto_item_set_generated(item
);
2312 nstime_delta(&ns
, &msp
->last_frame_time
, &pinfo
->abs_ts
);
2313 item
= proto_tree_add_time(tcp_tree
, hf_tcp_pdu_time
,
2315 proto_item_set_generated(item
);
2319 /* Second we check if this segment is part of a PDU started
2320 * prior to the segment (seq-1)
2322 msp
=(struct tcp_multisegment_pdu
*)wmem_tree_lookup32_le(multisegment_pdus
, seq
-1);
2324 /* If this segment is completely within a previous PDU
2325 * then we just skip this packet
2327 if(seq
>msp
->seq
&& nxtseq
<=msp
->nxtpdu
) {
2328 print_pdu_tracking_data(pinfo
, tvb
, tcp_tree
, msp
);
2332 if(seq
<msp
->nxtpdu
&& nxtseq
>msp
->nxtpdu
) {
2333 offset
+=msp
->nxtpdu
-seq
;
2342 /* if we saw a PDU that extended beyond the end of the segment,
2343 use this function to remember where the next pdu starts
2345 struct tcp_multisegment_pdu
*
2346 pdu_store_sequencenumber_of_next_pdu(packet_info
*pinfo
, uint32_t seq
, uint32_t nxtpdu
, wmem_tree_t
*multisegment_pdus
)
2348 struct tcp_multisegment_pdu
*msp
;
2350 msp
=wmem_new(wmem_file_scope(), struct tcp_multisegment_pdu
);
2353 msp
->first_frame
=pinfo
->num
;
2354 msp
->first_frame_with_seq
=pinfo
->num
;
2355 msp
->last_frame
=pinfo
->num
;
2356 msp
->last_frame_time
=pinfo
->abs_ts
;
2358 wmem_tree_insert32(multisegment_pdus
, seq
, (void *)msp
);
2359 /*ws_warning("pdu_store_sequencenumber_of_next_pdu: seq %u", seq);*/
2363 /* This is called for SYN and SYN+ACK packets and the purpose is to verify
2364 * that we have seen window scaling in both directions.
2365 * If we can't find window scaling being set in both directions
2366 * that means it was present in the SYN but not in the SYN+ACK
2367 * (or the SYN was missing) and then we disable the window scaling
2368 * for this tcp session.
2371 verify_tcp_window_scaling(bool is_synack
, struct tcp_analysis
*tcpd
)
2373 if( tcpd
->fwd
->win_scale
==-1 ) {
2374 /* We know window scaling will not be used as:
2375 * a) this is the SYN and it does not have the WS option
2376 * (we set the reverse win_scale also in case we miss
2378 * b) this is the SYN/ACK and either the SYN packet has not
2379 * been seen or it did have the WS option. As the SYN/ACK
2380 * does not have the WS option, window scaling will not be used.
2382 * Setting win_scale to -2 to indicate that we can
2383 * trust the window_size value in the TCP header.
2385 tcpd
->fwd
->win_scale
= -2;
2386 tcpd
->rev
->win_scale
= -2;
2388 } else if( is_synack
&& tcpd
->rev
->win_scale
==-2 ) {
2389 /* The SYN/ACK has the WS option, while the SYN did not,
2390 * this should not happen, but the endpoints will not
2391 * have used window scaling, so we will neither
2393 tcpd
->fwd
->win_scale
= -2;
2397 /* given a tcpd, returns the mptcp_subflow that sides with meta */
2398 static struct mptcp_subflow
*
2399 mptcp_select_subflow_from_meta(const struct tcp_analysis
*tcpd
, const mptcp_meta_flow_t
*meta
)
2401 /* select the tcp_flow with appropriate direction */
2402 if( tcpd
->flow1
.mptcp_subflow
->meta
== meta
) {
2403 return tcpd
->flow1
.mptcp_subflow
;
2406 return tcpd
->flow2
.mptcp_subflow
;
2410 /* if we saw a window scaling option, store it for future reference
2413 pdu_store_window_scale_option(uint8_t ws
, struct tcp_analysis
*tcpd
)
2416 tcpd
->fwd
->win_scale
=ws
;
2419 /* when this function returns, it will (if createflag) populate the ta pointer.
2422 tcp_analyze_get_acked_struct(uint32_t frame
, uint32_t seq
, uint32_t ack
, bool createflag
, struct tcp_analysis
*tcpd
)
2425 wmem_tree_key_t key
[4];
2428 key
[0].key
= &frame
;
2443 tcpd
->ta
= (struct tcp_acked
*)wmem_tree_lookup32_array(tcpd
->acked_table
, key
);
2444 if((!tcpd
->ta
) && createflag
) {
2445 tcpd
->ta
= wmem_new0(wmem_file_scope(), struct tcp_acked
);
2446 wmem_tree_insert32_array(tcpd
->acked_table
, key
, (void *)tcpd
->ta
);
2452 /* fwd contains a list of all segments processed but not yet ACKed in the
2453 * same direction as the current segment.
2454 * rev contains a list of all segments received but not yet ACKed in the
2455 * opposite direction to the current segment.
2457 * New segments are always added to the head of the fwd/rev lists.
2459 * Changes below should be synced with ChAdvTCPAnalysis in the User's
2460 * Guide: doc/wsug_src/WSUG_chapter_advanced.adoc
2463 tcp_analyze_sequence_number(packet_info
*pinfo
, uint32_t seq
, uint32_t ack
, uint32_t seglen
, uint16_t flags
, uint32_t window
, struct tcp_analysis
*tcpd
, struct tcp_per_packet_data_t
*tcppd
)
2465 tcp_unacked_t
*ual
=NULL
;
2466 tcp_unacked_t
*prevual
=NULL
;
2470 printf("\nanalyze_sequence numbers frame:%u\n",pinfo
->num
);
2471 printf("FWD list lastflags:0x%04x base_seq:%u: nextseq:%u lastack:%u\n",tcpd
->fwd
->lastsegmentflags
,tcpd
->fwd
->base_seq
,tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
,tcpd
->rev
->tcp_analyze_seq_info
->lastack
);
2472 for(ual
=tcpd
->fwd
->tcp_analyze_seq_info
->segments
; ual
; ual
=ual
->next
)
2473 printf("Frame:%d Seq:%u Nextseq:%u\n",ual
->frame
,ual
->seq
,ual
->nextseq
);
2474 printf("REV list lastflags:0x%04x base_seq:%u nextseq:%u lastack:%u\n",tcpd
->rev
->lastsegmentflags
,tcpd
->rev
->base_seq
,tcpd
->rev
->tcp_analyze_seq_info
->nextseq
,tcpd
->fwd
->tcp_analyze_seq_info
->lastack
);
2475 for(ual
=tcpd
->rev
->tcp_analyze_seq_info
->segments
; ual
; ual
=ual
->next
)
2476 printf("Frame:%d Seq:%u Nextseq:%u\n",ual
->frame
,ual
->seq
,ual
->nextseq
);
2483 if( flags
& TH_ACK
) {
2484 tcpd
->rev
->valid_bif
= 1;
2487 /* ZERO WINDOW PROBE
2488 * it is a zero window probe if
2489 * the sequence number is the next expected one
2490 * the window in the other direction is 0
2491 * the segment is exactly 1 byte
2494 && seq
==tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
2495 && tcpd
->rev
->window
==0 ) {
2497 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2499 tcpd
->ta
->flags
|=TCP_A_ZERO_WINDOW_PROBE
;
2505 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
2508 && (flags
&(TH_RST
|TH_FIN
|TH_SYN
))==0 ) {
2510 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2512 tcpd
->ta
->flags
|=TCP_A_ZERO_WINDOW
;
2517 * If this segment is beyond the last seen nextseq we must
2518 * have missed some previous segment
2520 * We only check for this if we have actually seen segments prior to this
2522 * RST packets are not checked for this.
2524 if( tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
2525 && GT_SEQ(seq
, tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
)
2526 && (flags
&(TH_RST
))==0 ) {
2528 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2530 tcpd
->ta
->flags
|=TCP_A_LOST_PACKET
;
2532 /* Disable BiF until an ACK is seen in the other direction */
2533 tcpd
->fwd
->valid_bif
= 0;
2538 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
2539 * to what should be the next sequence number.
2540 * SYN/FIN/RST segments are never keepalives
2542 if( (seglen
==0||seglen
==1)
2543 && seq
==(tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
-1)
2544 && (flags
&(TH_SYN
|TH_FIN
|TH_RST
))==0 ) {
2546 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2548 tcpd
->ta
->flags
|=TCP_A_KEEP_ALIVE
;
2552 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
2553 * the previous seen segment and with a new window value
2557 && window
!=tcpd
->fwd
->window
2558 && seq
==tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
2559 && ack
==tcpd
->fwd
->tcp_analyze_seq_info
->lastack
2560 && (flags
&(TH_SYN
|TH_FIN
|TH_RST
))==0 ) {
2562 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2564 tcpd
->ta
->flags
|=TCP_A_WINDOW_UPDATE
;
2569 * If we know the window scaling
2570 * and if this segment contains data and goes all the way to the
2571 * edge of the advertised window
2572 * then we mark it as WINDOW FULL
2573 * SYN/RST/FIN packets are never WINDOW FULL
2576 && tcpd
->rev
->win_scale
!=-1
2577 && (seq
+seglen
)==(tcpd
->rev
->tcp_analyze_seq_info
->lastack
+(tcpd
->rev
->window
<<(tcpd
->rev
->is_first_ack
?0:(tcpd
->rev
->win_scale
==-2?0:tcpd
->rev
->win_scale
))))
2578 && (flags
&(TH_SYN
|TH_FIN
|TH_RST
))==0 ) {
2580 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2582 tcpd
->ta
->flags
|=TCP_A_WINDOW_FULL
;
2587 * It is a keepalive ack if it repeats the previous ACK and if
2588 * the last segment in the reverse direction was a keepalive
2592 && window
==tcpd
->fwd
->window
2593 && seq
==tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
2594 && ack
==tcpd
->fwd
->tcp_analyze_seq_info
->lastack
2595 && (tcpd
->rev
->lastsegmentflags
&TCP_A_KEEP_ALIVE
)
2596 && (flags
&(TH_SYN
|TH_FIN
|TH_RST
))==0 ) {
2598 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2600 tcpd
->ta
->flags
|=TCP_A_KEEP_ALIVE_ACK
;
2605 /* ZERO WINDOW PROBE ACK
2606 * It is a zerowindowprobe ack if it repeats the previous ACK and if
2607 * the last segment in the reverse direction was a zerowindowprobe
2608 * It also repeats the previous zero window indication
2612 && window
==tcpd
->fwd
->window
2613 && seq
==tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
2614 && (ack
==tcpd
->fwd
->tcp_analyze_seq_info
->lastack
|| EQ_SEQ(ack
,tcpd
->fwd
->tcp_analyze_seq_info
->lastack
+1))
2615 && (tcpd
->rev
->lastsegmentflags
&TCP_A_ZERO_WINDOW_PROBE
)
2616 && (flags
&(TH_SYN
|TH_FIN
|TH_RST
))==0 ) {
2618 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2620 tcpd
->ta
->flags
|=TCP_A_ZERO_WINDOW_PROBE_ACK
;
2622 /* Some receivers consume that extra byte brought in the PROBE,
2623 * but it was too early to know that during the WINDOW PROBE analysis.
2624 * Do it now by moving the rev nextseq & maxseqtobeacked.
2627 if(EQ_SEQ(ack
,tcpd
->fwd
->tcp_analyze_seq_info
->lastack
+1)) {
2628 tcpd
->rev
->tcp_analyze_seq_info
->nextseq
=ack
;
2629 tcpd
->rev
->tcp_analyze_seq_info
->maxseqtobeacked
=ack
;
2636 * It is a duplicate ack if window/seq/ack is the same as the previous
2637 * segment and if the segment length is 0
2641 && window
==tcpd
->fwd
->window
2642 && seq
==tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
2643 && ack
==tcpd
->fwd
->tcp_analyze_seq_info
->lastack
2644 && (flags
&(TH_SYN
|TH_FIN
|TH_RST
))==0 ) {
2646 /* MPTCP tolerates duplicate acks in some circumstances, see RFC 8684 4. */
2647 if(tcpd
->mptcp_analysis
&& (tcpd
->mptcp_analysis
->mp_operations
!=tcpd
->fwd
->mp_operations
)) {
2648 /* just ignore this DUPLICATE ACK */
2650 tcpd
->fwd
->tcp_analyze_seq_info
->dupacknum
++;
2653 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2655 tcpd
->ta
->flags
|=TCP_A_DUPLICATE_ACK
;
2656 tcpd
->ta
->dupack_num
=tcpd
->fwd
->tcp_analyze_seq_info
->dupacknum
;
2657 tcpd
->ta
->dupack_frame
=tcpd
->fwd
->tcp_analyze_seq_info
->lastnondupack
;
2664 /* If the ack number changed we must reset the dupack counters */
2665 if( ack
!= tcpd
->fwd
->tcp_analyze_seq_info
->lastack
) {
2666 tcpd
->fwd
->tcp_analyze_seq_info
->lastnondupack
=pinfo
->num
;
2667 tcpd
->fwd
->tcp_analyze_seq_info
->dupacknum
=0;
2671 /* ACKED LOST PACKET
2672 * If this segment acks beyond the 'max seq to be acked' in the other direction
2673 * then that means we have missed packets going in the
2675 * It might also indicate we are resuming from a Zero Window,
2676 * where a Probe is just followed by an ACK opening again the window.
2679 * We only check this if we have actually seen some seq numbers
2680 * in the other direction.
2682 if( tcpd
->rev
->tcp_analyze_seq_info
->maxseqtobeacked
2683 && GT_SEQ(ack
, tcpd
->rev
->tcp_analyze_seq_info
->maxseqtobeacked
)
2684 && (flags
&(TH_ACK
))!=0 ) {
2686 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2689 /* resuming from a Zero Window Probe which re-opens the window,
2690 * mark it as a Window Update
2692 if(EQ_SEQ(ack
,tcpd
->fwd
->tcp_analyze_seq_info
->lastack
+1)
2693 && (seq
==tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
)
2694 && (tcpd
->rev
->lastsegmentflags
&TCP_A_ZERO_WINDOW_PROBE
) ) {
2695 tcpd
->rev
->tcp_analyze_seq_info
->nextseq
=ack
;
2696 tcpd
->rev
->tcp_analyze_seq_info
->maxseqtobeacked
=ack
;
2697 tcpd
->ta
->flags
|=TCP_A_WINDOW_UPDATE
;
2699 /* real ACKED LOST PACKET */
2701 /* We ensure there is no matching packet waiting in the unacked list,
2702 * and take this opportunity to push the tail further than this single packet
2705 uint32_t tail_le
= 0, tail_re
= 0;
2706 for(ual
=tcpd
->rev
->tcp_analyze_seq_info
->segments
; ual
; ual
=ual
->next
) {
2708 if(tail_le
== tail_re
) { /* init edge values */
2710 tail_re
= ual
->nextseq
;
2713 /* Only look at what happens above the current ACK value,
2714 * as what happened before is definetely ACKed here and can be
2715 * safely ignored. */
2716 if(GE_SEQ(ual
->seq
,ack
)) {
2718 /* if the left edge is contiguous, move the tail leftward */
2719 if(EQ_SEQ(ual
->nextseq
,tail_le
)) {
2723 /* otherwise, we have isolated segments above what is being ACKed here,
2724 * and we reinit the tails with the current values */
2727 tail_re
= ual
->nextseq
; // move the end tail
2732 /* a tail was found and we can push the maxseqtobeacked further */
2733 if(EQ_SEQ(ack
,tail_le
) && GT_SEQ(tail_re
, ack
)) {
2734 tcpd
->rev
->tcp_analyze_seq_info
->maxseqtobeacked
=tail_re
;
2737 /* otherwise, just take into account the value being ACKed now */
2739 tcpd
->rev
->tcp_analyze_seq_info
->maxseqtobeacked
=ack
;
2742 tcpd
->ta
->flags
|=TCP_A_ACK_LOST_PACKET
;
2747 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
2748 * If the segment contains data (or is a SYN or a FIN) and
2749 * if it does not advance the sequence number, it must be one
2751 * Only test for this if we know what the seq number should be
2752 * (tcpd->fwd->nextseq)
2754 * Note that a simple KeepAlive is not a retransmission
2756 bool seq_not_advanced
= tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
2757 && (LT_SEQ(seq
, tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
));
2759 if (seglen
>0 || flags
&(TH_SYN
|TH_FIN
)) {
2764 if(tcpd
->ta
&& (tcpd
->ta
->flags
&TCP_A_KEEP_ALIVE
) ) {
2765 goto finished_checking_retransmission_type
;
2768 /* This segment is *not* considered a retransmission/out-of-order if
2769 * the segment length is larger than one (it really adds new data)
2770 * the sequence number is one less than the previous nextseq and
2771 * (the previous segment is possibly a zero window probe)
2773 * We should still try to flag Spurious Retransmissions though.
2775 if (seglen
> 1 && tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
- 1 == seq
) {
2776 seq_not_advanced
= false;
2779 /* Check for spurious retransmission. If the current seq + segment length
2780 * is less than or equal to the current lastack, the packet contains
2781 * duplicate data and may be considered spurious.
2784 && tcpd
->rev
->tcp_analyze_seq_info
->lastack
2785 && LE_SEQ(seq
+ seglen
, tcpd
->rev
->tcp_analyze_seq_info
->lastack
) ) {
2787 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2789 tcpd
->ta
->flags
|=TCP_A_SPURIOUS_RETRANSMISSION
;
2790 goto finished_checking_retransmission_type
;
2793 nextseq
= seq
+seglen
;
2795 if(!seq_not_advanced
)
2796 goto finished_checking_retransmission_type
;
2798 /* Some OOO vs Retrans interpretations can be wrong when the capture needs a reorder.
2799 * Avoid such cases by enforcing the delta to 0 when the order seems bad, instead of
2800 * calculating an absurd value.
2802 if(pinfo
->abs_ts
.secs
> tcpd
->rev
->tcp_analyze_seq_info
->lastacktime
.secs
) {
2804 t
= (pinfo
->abs_ts
.secs
- tcpd
->rev
->tcp_analyze_seq_info
->lastacktime
.secs
)*1000000000;
2805 t
+= pinfo
->abs_ts
.nsecs
- tcpd
->rev
->tcp_analyze_seq_info
->lastacktime
.nsecs
;
2807 else if( (pinfo
->abs_ts
.secs
== tcpd
->rev
->tcp_analyze_seq_info
->lastacktime
.secs
) &&
2808 (pinfo
->abs_ts
.nsecs
> tcpd
->rev
->tcp_analyze_seq_info
->lastacktime
.nsecs
) ) {
2809 t
= pinfo
->abs_ts
.nsecs
- tcpd
->rev
->tcp_analyze_seq_info
->lastacktime
.nsecs
;
2815 bool precedence_count
= tcp_fastrt_precedence
;
2817 if (precedence_count
) {
2818 /* If there were >=2 duplicate ACKs in the reverse direction
2819 * (there might be duplicate acks missing from the trace)
2820 * and if this sequence number matches those ACKs
2821 * and if the packet occurs within 20ms of the last
2823 * then this is a fast retransmission
2826 && tcpd
->rev
->tcp_analyze_seq_info
->dupacknum
>=2
2827 && tcpd
->rev
->tcp_analyze_seq_info
->lastack
==seq
) {
2829 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2831 tcpd
->ta
->flags
|=TCP_A_FAST_RETRANSMISSION
;
2832 goto finished_checking_retransmission_type
;
2835 /* Look for this segment in reported SACK ranges,
2836 * if not present this might very well be a FAST Retrans,
2837 * when the conditions above (timing, number of retrans) are still true */
2839 && tcpd
->rev
->tcp_analyze_seq_info
->dupacknum
>=2
2840 && tcpd
->rev
->tcp_analyze_seq_info
->num_sack_ranges
> 0) {
2842 bool is_sacked
= false;
2844 while( !is_sacked
&& i
<tcpd
->rev
->tcp_analyze_seq_info
->num_sack_ranges
) {
2845 is_sacked
= ((seq
>= tcpd
->rev
->tcp_analyze_seq_info
->sack_left_edge
[i
])
2846 && (nextseq
<= tcpd
->rev
->tcp_analyze_seq_info
->sack_right_edge
[i
]));
2850 /* fine, it's probably a Fast Retrans triggered by the SACK sender algo */
2853 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2854 tcpd
->ta
->flags
|=TCP_A_FAST_RETRANSMISSION
;
2855 goto finished_checking_retransmission_type
;
2859 precedence_count
=!precedence_count
;
2861 /* If the segment came relatively close since the segment with the highest
2862 * seen sequence number and it doesn't look like a retransmission
2863 * then it is an OUT-OF-ORDER segment.
2865 if (tcpd
->ts_first_rtt
.nsecs
== 0 && tcpd
->ts_first_rtt
.secs
== 0) {
2866 ooo_thres
= 3000000;
2868 ooo_thres
= tcpd
->ts_first_rtt
.nsecs
+ tcpd
->ts_first_rtt
.secs
*1000000000;
2871 /* If the segment is already seen and waiting to be acknowledged, ignore the
2872 * Fast-Retrans/OOO debate and go ahead, as it only can be an ordinary Retrans.
2873 * Fast-Retrans/Retrans are never ambiguous in the context of packets seen but
2874 * this code could be moved above.
2875 * See Issues 13284, 13843
2876 * XXX: if compared packets have different sizes, it's not handled yet
2878 bool pk_already_seen
= false;
2879 ual
= tcpd
->fwd
->tcp_analyze_seq_info
->segments
;
2881 if(GE_SEQ(seq
,ual
->seq
) && LE_SEQ(seq
+seglen
,ual
->nextseq
)) {
2882 pk_already_seen
= true;
2888 if(t
< ooo_thres
&& !pk_already_seen
) {
2889 /* ordinary OOO with SEQ numbers and lengths clearly stating the situation */
2890 if( tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
!= (seq
+ seglen
+ (flags
&(TH_SYN
|TH_FIN
) ? 1 : 0))) {
2892 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2895 tcpd
->ta
->flags
|=TCP_A_OUT_OF_ORDER
;
2896 goto finished_checking_retransmission_type
;
2899 /* facing an OOO closing a series of disordered packets,
2900 all preceded by a pure ACK. See issue 17214 */
2901 if(tcpd
->fwd
->tcp_analyze_seq_info
->lastacklen
== 0) {
2903 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2906 tcpd
->ta
->flags
|=TCP_A_OUT_OF_ORDER
;
2907 goto finished_checking_retransmission_type
;
2911 precedence_count
=!precedence_count
;
2913 } while (precedence_count
!=tcp_fastrt_precedence
) ;
2915 /* Then it has to be a generic retransmission */
2917 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
2919 tcpd
->ta
->flags
|=TCP_A_RETRANSMISSION
;
2922 * worst case scenario: if we don't have better than a recent packet,
2923 * use it as the reference for RTO
2925 nstime_delta(&tcpd
->ta
->rto_ts
, &pinfo
->abs_ts
, &tcpd
->fwd
->tcp_analyze_seq_info
->nextseqtime
);
2926 tcpd
->ta
->rto_frame
=tcpd
->fwd
->tcp_analyze_seq_info
->nextseqframe
;
2929 * better case scenario: if we have a list of the previous unacked packets,
2930 * go back to the eldest one, which in theory is likely to be the one retransmitted here.
2931 * It's not always the perfect match, particularly when original captured packet used LSO
2932 * We may parse this list and try to find an obvious matching packet present in the
2933 * capture. If such packet is actually missing, we'll reach the list first entry.
2934 * See : issue #12259
2935 * See : issue #17714
2937 ual
= tcpd
->fwd
->tcp_analyze_seq_info
->segments
;
2939 if(GE_SEQ(ual
->seq
, seq
)) {
2940 nstime_delta(&tcpd
->ta
->rto_ts
, &pinfo
->abs_ts
, &ual
->ts
);
2941 tcpd
->ta
->rto_frame
=ual
->frame
;
2947 finished_checking_retransmission_type
:
2949 /* Override the TCP sequence analysis with the value given
2950 * manually by the user. This only applies to flagged packets.
2952 if(tcppd
&& tcpd
->ta
&&
2953 (tcppd
->tcp_snd_manual_analysis
>0) &&
2954 (tcpd
->ta
->flags
& TCP_A_RETRANSMISSION
||
2955 tcpd
->ta
->flags
& TCP_A_OUT_OF_ORDER
||
2956 tcpd
->ta
->flags
& TCP_A_FAST_RETRANSMISSION
||
2957 tcpd
->ta
->flags
& TCP_A_SPURIOUS_RETRANSMISSION
)) {
2959 /* clean flags set during the automatic analysis */
2960 tcpd
->ta
->flags
&= ~(TCP_A_RETRANSMISSION
|
2962 TCP_A_FAST_RETRANSMISSION
|
2963 TCP_A_SPURIOUS_RETRANSMISSION
);
2965 /* set the corresponding flag chosen by the user */
2966 switch(tcppd
->tcp_snd_manual_analysis
) {
2968 /* the user asked for an empty overriding, which
2969 * means removing any previous value, thus restoring
2970 * the automatic analysis.
2975 tcpd
->ta
->flags
|=TCP_A_OUT_OF_ORDER
;
2979 tcpd
->ta
->flags
|=TCP_A_RETRANSMISSION
;
2983 tcpd
->ta
->flags
|=TCP_A_FAST_RETRANSMISSION
;
2987 tcpd
->ta
->flags
|=TCP_A_SPURIOUS_RETRANSMISSION
;
2991 /* there is no expected default case */
2996 nextseq
= seq
+seglen
;
2997 if ((seglen
|| flags
&(TH_SYN
|TH_FIN
)) && tcpd
->fwd
->tcp_analyze_seq_info
->segment_count
< TCP_MAX_UNACKED_SEGMENTS
) {
2998 /* Add this new sequence number to the fwd list. But only if there
2999 * aren't "too many" unacked segments (e.g., we're not seeing the ACKs).
3001 ual
= wmem_new(wmem_file_scope(), tcp_unacked_t
);
3002 ual
->next
=tcpd
->fwd
->tcp_analyze_seq_info
->segments
;
3003 tcpd
->fwd
->tcp_analyze_seq_info
->segments
=ual
;
3004 tcpd
->fwd
->tcp_analyze_seq_info
->segment_count
++;
3005 ual
->frame
=pinfo
->num
;
3007 ual
->ts
=pinfo
->abs_ts
;
3009 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
3010 if( (flags
&(TH_SYN
|TH_FIN
)) ) {
3013 ual
->nextseq
=nextseq
;
3016 /* Every time we are moving the highest number seen,
3017 * we are also tracking the segment length then we will know for sure,
3018 * later, if this was a pure ACK or an ordinary data packet. */
3019 if(!tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
3020 || GT_SEQ(nextseq
, tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
+ (flags
&(TH_SYN
|TH_FIN
) ? 1 : 0))) {
3021 tcpd
->fwd
->tcp_analyze_seq_info
->lastacklen
=seglen
;
3024 /* Store the highest number seen so far for nextseq so we can detect
3025 * when we receive segments that arrive with a "hole"
3026 * If we don't have anything since before, just store what we got.
3027 * ZeroWindowProbes are special and don't really advance the nextseq
3029 if(GT_SEQ(nextseq
, tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
) || !tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
) {
3030 if( !tcpd
->ta
|| !(tcpd
->ta
->flags
&TCP_A_ZERO_WINDOW_PROBE
) ) {
3031 tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
=nextseq
;
3032 tcpd
->fwd
->tcp_analyze_seq_info
->nextseqframe
=pinfo
->num
;
3033 tcpd
->fwd
->tcp_analyze_seq_info
->nextseqtime
.secs
=pinfo
->abs_ts
.secs
;
3034 tcpd
->fwd
->tcp_analyze_seq_info
->nextseqtime
.nsecs
=pinfo
->abs_ts
.nsecs
;
3036 /* Count the flows turns by checking all packets carrying real data
3037 * Packets not ordered are ignored.
3040 !(tcpd
->ta
->flags
& TCP_A_RETRANSMISSION
||
3041 tcpd
->ta
->flags
& TCP_A_OUT_OF_ORDER
||
3042 tcpd
->ta
->flags
& TCP_A_FAST_RETRANSMISSION
||
3043 tcpd
->ta
->flags
& TCP_A_SPURIOUS_RETRANSMISSION
)) {
3046 /* check direction */
3048 direction
=cmp_address(&pinfo
->src
, &pinfo
->dst
);
3050 /* if the addresses are equal, match the ports instead */
3052 direction
= (pinfo
->srcport
> pinfo
->destport
) ? 1 : -1;
3055 /* invert the direction and increment the counter */
3056 if(direction
!= tcpd
->flow_direction
) {
3057 tcpd
->flow_direction
= direction
;
3058 tcpd
->fwd
->flow_count
++;
3060 /* if the direction was not reversed, maybe are we
3061 * facing the first flow ? Yes, if the counter still equals 0.
3064 if(tcpd
->fwd
->flow_count
==0) {
3065 tcpd
->fwd
->flow_count
++;
3073 /* Store the highest continuous seq number seen so far for 'max seq to be acked',
3074 * so we can detect TCP_A_ACK_LOST_PACKET condition.
3075 * If this ever happens, this boundary value can "jump" further in order to
3076 * avoid duplicating multiple messages for the very same lost packet. See later
3077 * how ACKED LOST PACKET are handled.
3078 * Zero Window Probes are logically left out at this moment, but if their data
3079 * really were to be ack'ed, then it will be done later when analyzing their
3080 * Probe ACK (be it a real Probe ACK, or an ordinary ACK moving the RCV Window).
3082 if(EQ_SEQ(seq
, tcpd
->fwd
->tcp_analyze_seq_info
->maxseqtobeacked
) || !tcpd
->fwd
->tcp_analyze_seq_info
->maxseqtobeacked
) {
3083 if( !tcpd
->ta
|| !(tcpd
->ta
->flags
&TCP_A_ZERO_WINDOW_PROBE
) ) {
3084 tcpd
->fwd
->tcp_analyze_seq_info
->maxseqtobeacked
=tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
;
3089 /* remember what the ack/window is so we can track window updates and retransmissions */
3090 tcpd
->fwd
->window
=window
;
3091 tcpd
->fwd
->tcp_analyze_seq_info
->lastack
=ack
;
3092 tcpd
->fwd
->tcp_analyze_seq_info
->lastacktime
.secs
=pinfo
->abs_ts
.secs
;
3093 tcpd
->fwd
->tcp_analyze_seq_info
->lastacktime
.nsecs
=pinfo
->abs_ts
.nsecs
;
3095 /* remember the MPTCP operations if any */
3096 if( tcpd
->mptcp_analysis
) {
3097 tcpd
->fwd
->mp_operations
=tcpd
->mptcp_analysis
->mp_operations
;
3100 /* if there were any flags set for this segment we need to remember them
3101 * we only remember the flags for the very last segment though.
3104 tcpd
->fwd
->lastsegmentflags
=tcpd
->ta
->flags
;
3106 tcpd
->fwd
->lastsegmentflags
=0;
3110 /* remove all segments this ACKs and we don't need to keep around any more
3113 ual
= tcpd
->rev
->tcp_analyze_seq_info
->segments
;
3115 tcp_unacked_t
*tmpual
;
3117 /* If this ack matches the segment, process accordingly */
3118 if(ack
==ual
->nextseq
) {
3119 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
3120 tcpd
->ta
->frame_acked
=ual
->frame
;
3121 nstime_delta(&tcpd
->ta
->ts
, &pinfo
->abs_ts
, &ual
->ts
);
3122 /* mark it as a full segment ACK */
3123 tcpd
->ta
->partial_ack
=0;
3125 /* If this acknowledges part of the segment, adjust the segment info for the acked part.
3126 * This typically happens in the context of GSO/GRO or Retransmissions with
3127 * segment repackaging (elsewhere called repacketization). For the user, looking at the
3128 * previous packets for any Retransmission or at the SYN MSS Option presence would
3129 * answer what case is precisely encountered.
3131 else if (GT_SEQ(ack
, ual
->seq
) && LE_SEQ(ack
, ual
->nextseq
)) {
3133 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
3134 tcpd
->ta
->frame_acked
=ual
->frame
;
3135 nstime_delta(&tcpd
->ta
->ts
, &pinfo
->abs_ts
, &ual
->ts
);
3137 /* mark it as a partial segment ACK
3139 * XXX - This mark is used later to create an Expert Note,
3140 * but other ways of tracking these packets are possible:
3141 * for example a similar indication to ta->frame_acked
3142 * would help differentiating the SEQ/ACK analysis messages.
3143 * Also, a TCP Analysis Flag could be added, but doesn't seem
3144 * essential yet, as matching packets can be selected with
3145 * 'tcp.analysis.partial_ack'.
3147 tcpd
->ta
->partial_ack
=1;
3150 /* If this acknowledges a segment prior to this one, leave this segment alone and move on */
3151 else if (GT_SEQ(ual
->nextseq
,ack
)) {
3157 /* This segment is old, or an exact match. Delete the segment from the list */
3160 if (tcpd
->rev
->scps_capable
) {
3161 /* Track largest segment successfully sent for SNACK analysis*/
3162 if ((ual
->nextseq
- ual
->seq
) > tcpd
->fwd
->maxsizeacked
) {
3163 tcpd
->fwd
->maxsizeacked
= (ual
->nextseq
- ual
->seq
);
3168 tcpd
->rev
->tcp_analyze_seq_info
->segments
= tmpual
;
3171 prevual
->next
= tmpual
;
3173 wmem_free(wmem_file_scope(), ual
);
3175 tcpd
->rev
->tcp_analyze_seq_info
->segment_count
--;
3178 /* how many bytes of data are there in flight after this frame
3180 * The historical evaluation is done from the payload seen in the
3181 * segments captured. Another method deduced from the SEQ numbers
3182 * is introduced with issue 7703, but not used by default now. The
3183 * method is chosen by the user preference tcp_bif_seq_based.
3185 if(tcp_track_bytes_in_flight
) {
3186 uint32_t in_flight
, delivered
= 0;
3188 * "don't repeat yourself" boolean, for the shared part
3189 * between both methods
3191 bool dry_bif_handling
= false;
3194 * historical calculation method based on payloads, which is
3195 * by now still the default.
3197 if(!tcp_bif_seq_based
) {
3198 ual
=tcpd
->fwd
->tcp_analyze_seq_info
->segments
;
3200 if (seglen
!=0 && ual
&& tcpd
->fwd
->valid_bif
) {
3201 uint32_t first_seq
, last_seq
;
3203 dry_bif_handling
= true;
3205 first_seq
= ual
->seq
- tcpd
->fwd
->base_seq
;
3206 last_seq
= ual
->nextseq
- tcpd
->fwd
->base_seq
;
3208 if ((ual
->nextseq
-tcpd
->fwd
->base_seq
)>last_seq
) {
3209 last_seq
= ual
->nextseq
-tcpd
->fwd
->base_seq
;
3211 if ((ual
->seq
-tcpd
->fwd
->base_seq
)<first_seq
) {
3212 first_seq
= ual
->seq
-tcpd
->fwd
->base_seq
;
3216 in_flight
= last_seq
-first_seq
;
3218 } else { /* calculation based on SEQ numbers (see issue 7703) */
3219 if (seglen
!=0 && tcpd
->fwd
->tcp_analyze_seq_info
&& tcpd
->fwd
->valid_bif
) {
3221 dry_bif_handling
= true;
3223 in_flight
= tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
3224 - tcpd
->rev
->tcp_analyze_seq_info
->lastack
;
3227 if(dry_bif_handling
) {
3228 /* subtract any SACK block */
3229 if(tcpd
->rev
->tcp_analyze_seq_info
->num_sack_ranges
> 0) {
3231 for(i
= 0; i
<tcpd
->rev
->tcp_analyze_seq_info
->num_sack_ranges
; i
++) {
3232 delivered
+= (tcpd
->rev
->tcp_analyze_seq_info
->sack_right_edge
[i
] -
3233 tcpd
->rev
->tcp_analyze_seq_info
->sack_left_edge
[i
]);
3235 in_flight
-= delivered
;
3238 if (in_flight
>0 && in_flight
<2000000000) {
3240 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, true, tcpd
);
3242 tcpd
->ta
->bytes_in_flight
= in_flight
;
3243 /* Decrement in_flight bytes by one when we have a SYN or FIN bit
3244 * flag set as it is only virtual.
3246 if (flags
&(TH_SYN
|TH_FIN
)) {
3247 tcpd
->ta
->bytes_in_flight
-= 1;
3251 if((flags
& TH_PUSH
) && !tcpd
->fwd
->push_set_last
) {
3252 tcpd
->fwd
->push_bytes_sent
+= seglen
;
3253 tcpd
->fwd
->push_set_last
= true;
3254 } else if ((flags
& TH_PUSH
) && tcpd
->fwd
->push_set_last
) {
3255 tcpd
->fwd
->push_bytes_sent
= seglen
;
3256 tcpd
->fwd
->push_set_last
= true;
3257 } else if (tcpd
->fwd
->push_set_last
) {
3258 tcpd
->fwd
->push_bytes_sent
= seglen
;
3259 tcpd
->fwd
->push_set_last
= false;
3261 tcpd
->fwd
->push_bytes_sent
+= seglen
;
3264 tcp_analyze_get_acked_struct(pinfo
->fd
->num
, seq
, ack
, true, tcpd
);
3266 tcpd
->ta
->push_bytes_sent
= tcpd
->fwd
->push_bytes_sent
;
3273 * Prints results of the sequence number analysis concerning tcp segments
3274 * retransmitted or out-of-order
3277 tcp_sequence_number_analysis_print_retransmission(packet_info
* pinfo
,
3279 proto_tree
* flags_tree
, proto_item
* flags_item
,
3280 struct tcp_acked
*ta
3283 /* TCP Retransmission */
3284 if (ta
->flags
& TCP_A_RETRANSMISSION
) {
3285 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_retransmission
);
3287 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[TCP Retransmission] ");
3289 if (ta
->rto_ts
.secs
|| ta
->rto_ts
.nsecs
) {
3290 flags_item
= proto_tree_add_time(flags_tree
, hf_tcp_analysis_rto
,
3291 tvb
, 0, 0, &ta
->rto_ts
);
3292 proto_item_set_generated(flags_item
);
3293 flags_item
=proto_tree_add_uint(flags_tree
, hf_tcp_analysis_rto_frame
,
3294 tvb
, 0, 0, ta
->rto_frame
);
3295 proto_item_set_generated(flags_item
);
3298 /* TCP Fast Retransmission */
3299 if (ta
->flags
& TCP_A_FAST_RETRANSMISSION
) {
3300 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_fast_retransmission
);
3301 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_retransmission
);
3302 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
,
3303 "[TCP Fast Retransmission] ");
3305 /* TCP Spurious Retransmission */
3306 if (ta
->flags
& TCP_A_SPURIOUS_RETRANSMISSION
) {
3307 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_spurious_retransmission
);
3308 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_retransmission
);
3309 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
,
3310 "[TCP Spurious Retransmission] ");
3313 /* TCP Out-Of-Order */
3314 if (ta
->flags
& TCP_A_OUT_OF_ORDER
) {
3315 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_out_of_order
);
3316 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[TCP Out-Of-Order] ");
3320 /* Prints results of the sequence number analysis concerning reused ports */
3322 tcp_sequence_number_analysis_print_reused(packet_info
* pinfo
,
3323 proto_item
* flags_item
,
3324 struct tcp_acked
*ta
3327 /* TCP Ports Reused */
3328 if (ta
->flags
& TCP_A_REUSED_PORTS
) {
3329 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_reused_ports
);
3330 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
,
3331 "[TCP Port numbers reused] ");
3335 /* Prints results of the sequence number analysis concerning lost tcp segments */
3337 tcp_sequence_number_analysis_print_lost(packet_info
* pinfo
,
3338 proto_item
* flags_item
,
3339 struct tcp_acked
*ta
3342 /* TCP Lost Segment */
3343 if (ta
->flags
& TCP_A_LOST_PACKET
) {
3344 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_lost_packet
);
3345 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
,
3346 "[TCP Previous segment not captured] ");
3348 /* TCP Ack lost segment */
3349 if (ta
->flags
& TCP_A_ACK_LOST_PACKET
) {
3350 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_ack_lost_packet
);
3351 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
,
3352 "[TCP ACKed unseen segment] ");
3356 /* Prints results of the sequence number analysis concerning tcp window */
3358 tcp_sequence_number_analysis_print_window(packet_info
* pinfo
,
3359 proto_item
* flags_item
,
3360 struct tcp_acked
*ta
3363 /* TCP Window Update */
3364 if (ta
->flags
& TCP_A_WINDOW_UPDATE
) {
3365 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_window_update
);
3366 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[TCP Window Update] ");
3368 /* TCP Full Window */
3369 if (ta
->flags
& TCP_A_WINDOW_FULL
) {
3370 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_window_full
);
3371 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[TCP Window Full] ");
3375 /* Prints results of the sequence number analysis concerning tcp keepalive */
3377 tcp_sequence_number_analysis_print_keepalive(packet_info
* pinfo
,
3378 proto_item
* flags_item
,
3379 struct tcp_acked
*ta
3383 if (ta
->flags
& TCP_A_KEEP_ALIVE
) {
3384 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_keep_alive
);
3385 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[TCP Keep-Alive] ");
3387 /* TCP Ack Keep Alive */
3388 if (ta
->flags
& TCP_A_KEEP_ALIVE_ACK
) {
3389 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_keep_alive_ack
);
3390 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[TCP Keep-Alive ACK] ");
3394 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
3396 tcp_sequence_number_analysis_print_duplicate(packet_info
* pinfo
,
3398 proto_tree
* flags_tree
,
3399 struct tcp_acked
*ta
,
3403 proto_item
* flags_item
;
3405 /* TCP Duplicate ACK */
3406 if (ta
->dupack_num
) {
3407 if (ta
->flags
& TCP_A_DUPLICATE_ACK
) {
3408 flags_item
=proto_tree_add_none_format(flags_tree
,
3409 hf_tcp_analysis_duplicate_ack
,
3411 "This is a TCP duplicate ack"
3413 proto_item_set_generated(flags_item
);
3414 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
,
3415 "[TCP Dup ACK %u#%u] ",
3421 flags_item
=proto_tree_add_uint(tree
, hf_tcp_analysis_duplicate_ack_num
,
3422 tvb
, 0, 0, ta
->dupack_num
);
3423 proto_item_set_generated(flags_item
);
3424 flags_item
=proto_tree_add_uint(tree
, hf_tcp_analysis_duplicate_ack_frame
,
3425 tvb
, 0, 0, ta
->dupack_frame
);
3426 proto_item_set_generated(flags_item
);
3427 expert_add_info_format(pinfo
, flags_item
, &ei_tcp_analysis_duplicate_ack
, "Duplicate ACK (#%u)", ta
->dupack_num
);
3431 /* Prints results of the sequence number analysis concerning tcp zero window */
3433 tcp_sequence_number_analysis_print_zero_window(packet_info
* pinfo
,
3434 proto_item
* flags_item
,
3435 struct tcp_acked
*ta
3438 /* TCP Zero Window Probe */
3439 if (ta
->flags
& TCP_A_ZERO_WINDOW_PROBE
) {
3440 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_zero_window_probe
);
3441 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[TCP ZeroWindowProbe] ");
3443 /* TCP Zero Window */
3444 if (ta
->flags
&TCP_A_ZERO_WINDOW
) {
3445 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_zero_window
);
3446 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[TCP ZeroWindow] ");
3448 /* TCP Zero Window Probe Ack */
3449 if (ta
->flags
& TCP_A_ZERO_WINDOW_PROBE_ACK
) {
3450 expert_add_info(pinfo
, flags_item
, &ei_tcp_analysis_zero_window_probe_ack
);
3451 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
,
3452 "[TCP ZeroWindowProbeAck] ");
3457 /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */
3459 tcp_sequence_number_analysis_print_bytes_in_flight(packet_info
* pinfo _U_
,
3461 proto_tree
* flags_tree
,
3462 struct tcp_acked
*ta
3465 proto_item
* flags_item
;
3467 if (tcp_track_bytes_in_flight
) {
3468 flags_item
=proto_tree_add_uint(flags_tree
,
3469 hf_tcp_analysis_bytes_in_flight
,
3470 tvb
, 0, 0, ta
->bytes_in_flight
);
3472 proto_item_set_generated(flags_item
);
3476 /* Generate the initial data sequence number and MPTCP connection token from the key. */
3478 mptcp_cryptodata_sha1(const uint64_t key
, uint32_t *token
, uint64_t *idsn
)
3480 uint8_t digest_buf
[HASH_SHA1_LENGTH
];
3481 uint64_t pseudokey
= GUINT64_TO_BE(key
);
3485 gcry_md_hash_buffer(GCRY_MD_SHA1
, digest_buf
, (const uint8_t *)&pseudokey
, 8);
3487 /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */
3488 memcpy(&_token
, digest_buf
, sizeof(_token
));
3489 *token
= GUINT32_FROM_BE(_token
);
3490 memcpy(&_isdn
, digest_buf
+ HASH_SHA1_LENGTH
- sizeof(_isdn
), sizeof(_isdn
));
3491 *idsn
= GUINT64_FROM_BE(_isdn
);
3494 /* Generate the initial data sequence number and MPTCP connection token from the key. */
3496 mptcp_cryptodata_sha256(const uint64_t key
, uint32_t *token
, uint64_t *idsn
)
3498 uint8_t digest_buf
[HASH_SHA2_256_LENGTH
];
3499 uint64_t pseudokey
= GUINT64_TO_BE(key
);
3503 gcry_md_hash_buffer(GCRY_MD_SHA256
, digest_buf
, (const uint8_t *)&pseudokey
, 8);
3505 /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */
3506 memcpy(&_token
, digest_buf
, sizeof(_token
));
3507 *token
= GUINT32_FROM_BE(_token
);
3508 memcpy(&_isdn
, digest_buf
+ HASH_SHA2_256_LENGTH
- sizeof(_isdn
), sizeof(_isdn
));
3509 *idsn
= GUINT64_FROM_BE(_isdn
);
3513 /* Print formatted list of tcp stream ids that are part of the connection */
3515 mptcp_analysis_add_subflows(packet_info
*pinfo
, tvbuff_t
*tvb
,
3516 proto_tree
*parent_tree
, struct mptcp_analysis
* mptcpd
)
3518 wmem_list_frame_t
*it
;
3521 wmem_strbuf_t
*val
= wmem_strbuf_new(pinfo
->pool
, "");
3523 /* for the analysis, we set each subflow tcp stream id */
3524 for(it
= wmem_list_head(mptcpd
->subflows
); it
!= NULL
; it
= wmem_list_frame_next(it
)) {
3525 struct tcp_analysis
*sf
= (struct tcp_analysis
*)wmem_list_frame_data(it
);
3526 wmem_strbuf_append_printf(val
, "%u ", sf
->stream
);
3529 item
= proto_tree_add_string(parent_tree
, hf_mptcp_analysis_subflows
, tvb
, 0, 0, wmem_strbuf_get_str(val
));
3530 proto_item_set_generated(item
);
3533 /* Compute raw dsn if relative tcp seq covered by DSS mapping */
3535 mptcp_map_relssn_to_rawdsn(mptcp_dss_mapping_t
*mapping
, uint32_t relssn
, uint64_t *dsn
)
3537 if( (relssn
< mapping
->ssn_low
) || (relssn
> mapping
->ssn_high
)) {
3541 *dsn
= mapping
->rawdsn
+ (relssn
- mapping
->ssn_low
);
3546 /* Add duplicated data */
3547 static mptcp_dsn2packet_mapping_t
*
3548 mptcp_add_duplicated_dsn(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
, struct mptcp_subflow
*subflow
,
3549 uint64_t rawdsn64low
, uint64_t rawdsn64high
3552 wmem_list_t
*results
= NULL
;
3553 wmem_list_frame_t
*packet_it
= NULL
;
3554 mptcp_dsn2packet_mapping_t
*packet
= NULL
;
3555 proto_item
*item
= NULL
;
3557 results
= wmem_itree_find_intervals(subflow
->dsn2packet_map
,
3563 for(packet_it
= wmem_list_head(results
);
3565 packet_it
= wmem_list_frame_next(packet_it
))
3568 packet
= (mptcp_dsn2packet_mapping_t
*) wmem_list_frame_data(packet_it
);
3569 DISSECTOR_ASSERT(packet
);
3571 if(pinfo
->num
> packet
->frame
) {
3572 item
= proto_tree_add_uint(tree
, hf_mptcp_reinjection_of
, tvb
, 0, 0, packet
->frame
);
3575 item
= proto_tree_add_uint(tree
, hf_mptcp_reinjected_in
, tvb
, 0, 0, packet
->frame
);
3577 proto_item_set_generated(item
);
3584 /* Lookup mappings that describe the packet and then converts the tcp seq number
3585 * into the MPTCP Data Sequence Number (DSN)
3588 mptcp_analysis_dsn_lookup(packet_info
*pinfo
, tvbuff_t
*tvb
,
3589 proto_tree
*parent_tree
, struct tcp_analysis
* tcpd
, struct tcpheader
* tcph
, mptcp_per_packet_data_t
*mptcppd
)
3591 struct mptcp_analysis
* mptcpd
= tcpd
->mptcp_analysis
;
3592 proto_item
*item
= NULL
;
3593 mptcp_dss_mapping_t
*mapping
= NULL
;
3595 uint64_t rawdsn
= 0;
3596 enum mptcp_dsn_conversion convert
;
3598 if(!mptcp_analyze_mappings
)
3600 /* abort analysis */
3604 /* for this to work, we need to know the original seq number from the SYN, not from a subsequent packet
3605 * hence, we abort if we didn't capture the SYN
3607 if(!(tcpd
->fwd
->static_flags
& ~TCP_S_BASE_SEQ_SET
& (TCP_S_SAW_SYN
| TCP_S_SAW_SYNACK
))) {
3611 /* if seq not relative yet, we compute it */
3612 relseq
= (tcp_relative_seq
) ? tcph
->th_seq
: tcph
->th_seq
- tcpd
->fwd
->base_seq
;
3614 DISSECTOR_ASSERT(mptcpd
);
3615 DISSECTOR_ASSERT(mptcppd
);
3617 /* in case of a SYN, there is no mapping covering the DSN */
3618 if(tcph
->th_flags
& TH_SYN
) {
3620 rawdsn
= tcpd
->fwd
->mptcp_subflow
->meta
->base_dsn
;
3621 convert
= DSN_CONV_NONE
;
3623 /* if it's a non-syn packet without data (just used to convey TCP options)
3624 * then there would be no mappings */
3625 else if(relseq
== 1 && tcph
->th_seglen
== 0) {
3626 rawdsn
= tcpd
->fwd
->mptcp_subflow
->meta
->base_dsn
+ 1;
3627 convert
= DSN_CONV_NONE
;
3631 wmem_list_frame_t
*dss_it
= NULL
;
3632 wmem_list_t
*results
= NULL
;
3633 uint32_t ssn_low
= relseq
;
3634 uint32_t seglen
= tcph
->th_seglen
;
3636 results
= wmem_itree_find_intervals(tcpd
->fwd
->mptcp_subflow
->ssn2dsn_mappings
,
3639 (seglen
) ? ssn_low
+ seglen
- 1 : ssn_low
3641 dss_it
= wmem_list_head(results
); /* assume it's always ok */
3643 mapping
= (mptcp_dss_mapping_t
*) wmem_list_frame_data(dss_it
);
3645 if(dss_it
== NULL
|| mapping
== NULL
) {
3646 expert_add_info(pinfo
, parent_tree
, &ei_mptcp_mapping_missing
);
3650 mptcppd
->mapping
= mapping
;
3653 DISSECTOR_ASSERT(mapping
);
3655 /* Finds mappings that cover the sent data and adds them to the dissection tree */
3656 for(dss_it
= wmem_list_head(results
);
3658 dss_it
= wmem_list_frame_next(dss_it
))
3660 mapping
= (mptcp_dss_mapping_t
*) wmem_list_frame_data(dss_it
);
3661 DISSECTOR_ASSERT(mapping
);
3663 item
= proto_tree_add_uint(parent_tree
, hf_mptcp_related_mapping
, tvb
, 0, 0, mapping
->frame
);
3664 proto_item_set_generated(item
);
3668 convert
= (mapping
->extended_dsn
) ? DSN_CONV_NONE
: DSN_CONV_32_TO_64
;
3669 DISSECTOR_ASSERT(mptcp_map_relssn_to_rawdsn(mapping
, relseq
, &rawdsn
));
3672 /* Make sure we have the 64bit raw DSN */
3673 if(mptcp_convert_dsn(rawdsn
, tcpd
->fwd
->mptcp_subflow
->meta
,
3674 convert
, false, &tcph
->th_mptcp
->mh_rawdsn64
)) {
3676 /* always display the rawdsn64 (helpful for debug) */
3677 item
= proto_tree_add_uint64(parent_tree
, hf_mptcp_rawdsn64
, tvb
, 0, 0, tcph
->th_mptcp
->mh_rawdsn64
);
3679 /* converts to relative if required */
3680 if (mptcp_relative_seq
3681 && mptcp_convert_dsn(tcph
->th_mptcp
->mh_rawdsn64
, tcpd
->fwd
->mptcp_subflow
->meta
, DSN_CONV_NONE
, true, &tcph
->th_mptcp
->mh_dsn
)) {
3682 item
= proto_tree_add_uint64(parent_tree
, hf_mptcp_dsn
, tvb
, 0, 0, tcph
->th_mptcp
->mh_dsn
);
3683 proto_item_append_text(item
, " (Relative)");
3686 /* register dsn->packet mapping */
3687 if(mptcp_intersubflows_retransmission
3688 && !PINFO_FD_VISITED(pinfo
)
3689 && tcph
->th_seglen
> 0
3691 mptcp_dsn2packet_mapping_t
*packet
= 0;
3692 packet
= wmem_new0(wmem_file_scope(), mptcp_dsn2packet_mapping_t
);
3693 packet
->frame
= pinfo
->fd
->num
;
3694 packet
->subflow
= tcpd
;
3696 wmem_itree_insert(tcpd
->fwd
->mptcp_subflow
->dsn2packet_map
,
3697 tcph
->th_mptcp
->mh_rawdsn64
,
3698 tcph
->th_mptcp
->mh_rawdsn64
+ (tcph
->th_seglen
- 1 ),
3702 proto_item_set_generated(item
);
3704 /* We can do this only if rawdsn64 is valid !
3705 if enabled, look for overlapping mappings on other subflows */
3706 if(mptcp_intersubflows_retransmission
3707 && tcph
->th_have_seglen
3708 && tcph
->th_seglen
) {
3710 wmem_list_frame_t
*subflow_it
= NULL
;
3712 /* results should be some kind of list in case 2 DSS are needed to cover this packet */
3713 for(subflow_it
= wmem_list_head(mptcpd
->subflows
); subflow_it
!= NULL
; subflow_it
= wmem_list_frame_next(subflow_it
)) {
3714 struct tcp_analysis
*sf_tcpd
= (struct tcp_analysis
*)wmem_list_frame_data(subflow_it
);
3715 struct mptcp_subflow
*sf
= mptcp_select_subflow_from_meta(sf_tcpd
, tcpd
->fwd
->mptcp_subflow
->meta
);
3717 /* for current subflow */
3718 if (sf
== tcpd
->fwd
->mptcp_subflow
) {
3719 /* skip, this is the current subflow */
3721 /* in case there were retransmissions on other subflows */
3723 mptcp_add_duplicated_dsn(pinfo
, parent_tree
, tvb
, sf
,
3724 tcph
->th_mptcp
->mh_rawdsn64
,
3725 tcph
->th_mptcp
->mh_rawdsn64
+ tcph
->th_seglen
-1);
3731 /* could not get the rawdsn64, ignore and continue */
3737 /* Print subflow list */
3739 mptcp_add_analysis_subtree(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*parent_tree
,
3740 struct tcp_analysis
*tcpd
, struct mptcp_analysis
*mptcpd
, struct tcpheader
* tcph
)
3743 proto_item
*item
= NULL
;
3744 proto_tree
*tree
= NULL
;
3745 mptcp_per_packet_data_t
*mptcppd
= NULL
;
3747 if(mptcpd
== NULL
) {
3751 item
=proto_tree_add_item(parent_tree
, hf_mptcp_analysis
, tvb
, 0, 0, ENC_NA
);
3752 proto_item_set_generated(item
);
3753 tree
=proto_item_add_subtree(item
, ett_mptcp_analysis
);
3754 proto_item_set_generated(tree
);
3756 /* set field with mptcp stream */
3757 if(mptcpd
->master
) {
3759 item
= proto_tree_add_boolean_format_value(tree
, hf_mptcp_analysis_master
, tvb
, 0,
3760 0, (mptcpd
->master
->stream
== tcpd
->stream
) ? true : false
3761 , "Master is tcp stream %u", mptcpd
->master
->stream
3766 item
= proto_tree_add_boolean(tree
, hf_mptcp_analysis_master
, tvb
, 0,
3770 proto_item_set_generated(item
);
3772 #if 0 // nbOptionsChanged is currently unused.
3773 /* store the TCP Options related to MPTCP then we will avoid false DUP ACKs later */
3774 uint8_t nbOptionsChanged
= 0;
3775 if((tcpd
->mptcp_analysis
->mp_operations
&(0x01))!=tcph
->th_mptcp
->mh_mpc
) {
3776 tcpd
->mptcp_analysis
->mp_operations
|= 0x01;
3779 if((tcpd
->mptcp_analysis
->mp_operations
&(0x02))!=tcph
->th_mptcp
->mh_join
) {
3780 tcpd
->mptcp_analysis
->mp_operations
|= 0x02;
3783 if((tcpd
->mptcp_analysis
->mp_operations
&(0x04))!=tcph
->th_mptcp
->mh_dss
) {
3784 tcpd
->mptcp_analysis
->mp_operations
|= 0x04;
3787 if((tcpd
->mptcp_analysis
->mp_operations
&(0x08))!=tcph
->th_mptcp
->mh_add
) {
3788 tcpd
->mptcp_analysis
->mp_operations
|= 0x08;
3791 if((tcpd
->mptcp_analysis
->mp_operations
&(0x10))!=tcph
->th_mptcp
->mh_remove
) {
3792 tcpd
->mptcp_analysis
->mp_operations
|= 0x10;
3795 if((tcpd
->mptcp_analysis
->mp_operations
&(0x20))!=tcph
->th_mptcp
->mh_prio
) {
3796 tcpd
->mptcp_analysis
->mp_operations
|= 0x20;
3799 if((tcpd
->mptcp_analysis
->mp_operations
&(0x40))!=tcph
->th_mptcp
->mh_fail
) {
3800 tcpd
->mptcp_analysis
->mp_operations
|= 0x40;
3803 if((tcpd
->mptcp_analysis
->mp_operations
&(0x80))!=tcph
->th_mptcp
->mh_fastclose
) {
3804 tcpd
->mptcp_analysis
->mp_operations
|= 0x80;
3807 /* we could track MPTCP option changes here, with nbOptionsChanged */
3810 item
= proto_tree_add_uint(tree
, hf_mptcp_stream
, tvb
, 0, 0, mptcpd
->stream
);
3811 proto_item_set_generated(item
);
3813 /* retrieve saved analysis of packets, else create it */
3814 mptcppd
= (mptcp_per_packet_data_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_mptcp
, pinfo
->curr_layer_num
);
3816 mptcppd
= (mptcp_per_packet_data_t
*)wmem_new0(wmem_file_scope(), mptcp_per_packet_data_t
);
3817 p_add_proto_data(wmem_file_scope(), pinfo
, proto_mptcp
, pinfo
->curr_layer_num
, mptcppd
);
3820 /* Print formatted list of tcp stream ids that are part of the connection */
3821 mptcp_analysis_add_subflows(pinfo
, tvb
, tree
, mptcpd
);
3823 /* Converts TCP seq number into its MPTCP DSN */
3824 mptcp_analysis_dsn_lookup(pinfo
, tvb
, tree
, tcpd
, tcph
, mptcppd
);
3830 tcp_sequence_number_analysis_print_push_bytes_sent(packet_info
* pinfo _U_
,
3832 proto_tree
* flags_tree
,
3833 struct tcp_acked
*ta
3836 proto_item
* flags_item
;
3838 if (tcp_track_bytes_in_flight
) {
3839 flags_item
=proto_tree_add_uint(flags_tree
,
3840 hf_tcp_analysis_push_bytes_sent
,
3841 tvb
, 0, 0, ta
->push_bytes_sent
);
3843 proto_item_set_generated(flags_item
);
3848 tcp_print_sequence_number_analysis(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*parent_tree
,
3849 struct tcp_analysis
*tcpd
, uint32_t seq
, uint32_t ack
)
3851 struct tcp_acked
*ta
= NULL
;
3854 proto_tree
*flags_tree
=NULL
;
3860 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, ack
, false, tcpd
);
3867 item
=proto_tree_add_item(parent_tree
, hf_tcp_analysis
, tvb
, 0, 0, ENC_NA
);
3868 proto_item_set_generated(item
);
3869 tree
=proto_item_add_subtree(item
, ett_tcp_analysis
);
3871 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
3872 data we actually have */
3873 if(ta
->frame_acked
) {
3874 item
= proto_tree_add_uint(tree
, hf_tcp_analysis_acks_frame
,
3875 tvb
, 0, 0, ta
->frame_acked
);
3876 proto_item_set_generated(item
);
3878 if(ta
->partial_ack
) {
3879 expert_add_info(pinfo
, item
, &ei_tcp_analysis_partial_ack
);
3882 /* only display RTT if we actually have something we are acking */
3883 if( ta
->ts
.secs
|| ta
->ts
.nsecs
) {
3884 item
= proto_tree_add_time(tree
, hf_tcp_analysis_ack_rtt
,
3885 tvb
, 0, 0, &ta
->ts
);
3886 proto_item_set_generated(item
);
3889 if (!nstime_is_zero(&tcpd
->ts_first_rtt
)) {
3890 item
= proto_tree_add_time(tree
, hf_tcp_analysis_first_rtt
,
3891 tvb
, 0, 0, &(tcpd
->ts_first_rtt
));
3892 proto_item_set_generated(item
);
3895 if(ta
->bytes_in_flight
) {
3896 /* print results for amount of data in flight */
3897 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo
, tvb
, tree
, ta
);
3898 tcp_sequence_number_analysis_print_push_bytes_sent(pinfo
, tvb
, tree
, ta
);
3902 item
= proto_tree_add_item(tree
, hf_tcp_analysis_flags
, tvb
, 0, 0, ENC_NA
);
3903 proto_item_set_generated(item
);
3904 flags_tree
=proto_item_add_subtree(item
, ett_tcp_analysis
);
3906 /* print results for reused tcp ports */
3907 tcp_sequence_number_analysis_print_reused(pinfo
, item
, ta
);
3909 /* print results for retransmission and out-of-order segments */
3910 tcp_sequence_number_analysis_print_retransmission(pinfo
, tvb
, flags_tree
, item
, ta
);
3912 /* print results for lost tcp segments */
3913 tcp_sequence_number_analysis_print_lost(pinfo
, item
, ta
);
3915 /* print results for tcp window information */
3916 tcp_sequence_number_analysis_print_window(pinfo
, item
, ta
);
3918 /* print results for tcp keep alive information */
3919 tcp_sequence_number_analysis_print_keepalive(pinfo
, item
, ta
);
3921 /* print results for tcp duplicate acks */
3922 tcp_sequence_number_analysis_print_duplicate(pinfo
, tvb
, flags_tree
, ta
, tree
);
3924 /* print results for tcp zero window */
3925 tcp_sequence_number_analysis_print_zero_window(pinfo
, item
, ta
);
3932 print_tcp_fragment_tree(fragment_head
*ipfd_head
, proto_tree
*tree
, proto_tree
*tcp_tree
, packet_info
*pinfo
, tvbuff_t
*next_tvb
)
3934 proto_item
*tcp_tree_item
, *frag_tree_item
;
3937 * The subdissector thought it was completely
3938 * desegmented (although the stuff at the
3939 * end may, in turn, require desegmentation),
3940 * so we show a tree with all segments.
3942 show_fragment_tree(ipfd_head
, &tcp_segment_items
,
3943 tree
, pinfo
, next_tvb
, &frag_tree_item
);
3945 * The toplevel fragment subtree is now
3946 * behind all desegmented data; move it
3947 * right behind the TCP tree.
3949 tcp_tree_item
= proto_tree_get_parent(tcp_tree
);
3950 if(frag_tree_item
&& tcp_tree_item
) {
3951 proto_tree_move_item(tree
, tcp_tree_item
, frag_tree_item
);
3955 /* **************************************************************************
3956 * End of tcp sequence number analysis
3957 * **************************************************************************/
3960 /* Minimum TCP header length. */
3961 #define TCPH_MIN_LEN 20
3963 /* Desegmentation of TCP streams */
3965 /* The primary ID is the first frame of a multisegment PDU, which is
3966 * most likely unique in the capture (unlike sequence numbers which
3967 * can be re-used, especially when relative sequence numbers are enabled).
3968 * However, frames can have multiple PDUs with certain encapsulations like
3969 * GSE or MPE over DVB BaseBand Frames.
3972 typedef struct _tcp_endpoint
{
3982 save_endpoint(packet_info
*pinfo
, tcp_endpoint_t
*a
)
3984 copy_address_shallow(&a
->src_addr
, &pinfo
->src
);
3985 copy_address_shallow(&a
->dst_addr
, &pinfo
->dst
);
3986 a
->ptype
= pinfo
->ptype
;
3987 a
->src_port
= pinfo
->srcport
;
3988 a
->dst_port
= pinfo
->destport
;
3992 restore_endpoint(packet_info
*pinfo
, tcp_endpoint_t
*a
)
3994 copy_address_shallow(&pinfo
->src
, &a
->src_addr
);
3995 copy_address_shallow(&pinfo
->dst
, &a
->dst_addr
);
3996 pinfo
->ptype
= a
->ptype
;
3997 pinfo
->srcport
= a
->src_port
;
3998 pinfo
->destport
= a
->dst_port
;
4001 typedef struct _tcp_segment_key
{
4006 uint32_t id
; /* msp->first_frame */
4007 uint32_t seq
; /* msp->seq */
4011 tcp_segment_hash(const void *k
)
4013 const tcp_segment_key
* key
= (const tcp_segment_key
*) k
;
4018 /* In most captures there is only one fragment per id / first_frame,
4019 so we only use it in the hash as an optimization.
4022 for (i = 0; i < key->src.len; i++)
4023 hash_val += key->src_addr.data[i];
4024 for (i = 0; i < key->dst.len; i++)
4025 hash_val += key->dst_addr.data[i];
4026 hash_val += key->src_port;
4027 hash_val += key->dst_port;
4028 hash_val += key->seq;
4035 tcp_segment_equal(const void *k1
, const void *k2
)
4037 const tcp_segment_key
* key1
= (const tcp_segment_key
*) k1
;
4038 const tcp_segment_key
* key2
= (const tcp_segment_key
*) k2
;
4041 * key.id is the first item to compare since it's the item most
4042 * likely to differ between sessions, thus short-circuiting
4043 * the comparison of addresses and ports.
4045 return (key1
->id
== key2
->id
) &&
4046 (addresses_equal(&key1
->src_addr
, &key2
->src_addr
)) &&
4047 (addresses_equal(&key1
->dst_addr
, &key2
->dst_addr
)) &&
4048 (key1
->src_port
== key2
->src_port
) &&
4049 (key1
->dst_port
== key2
->dst_port
) &&
4050 (key1
->seq
== key2
->seq
);
4054 * Create a fragment key for temporary use; it can point to non-
4055 * persistent data, and so must only be used to look up and
4056 * delete entries, not to add them.
4059 tcp_segment_temporary_key(const packet_info
*pinfo
, const uint32_t id
,
4062 struct tcp_multisegment_pdu
*msp
= (struct tcp_multisegment_pdu
*)data
;
4063 DISSECTOR_ASSERT(msp
);
4064 tcp_segment_key
*key
= g_slice_new(tcp_segment_key
);
4067 * Do a shallow copy of the addresses.
4069 copy_address_shallow(&key
->src_addr
, &pinfo
->src
);
4070 copy_address_shallow(&key
->dst_addr
, &pinfo
->dst
);
4071 key
->src_port
= pinfo
->srcport
;
4072 key
->dst_port
= pinfo
->destport
;
4074 key
->seq
= msp
->seq
;
4080 * Create a fragment key for permanent use; it must point to persistent
4081 * data, so that it can be used to add entries.
4084 tcp_segment_persistent_key(const packet_info
*pinfo
,
4085 const uint32_t id
, const void *data
)
4087 struct tcp_multisegment_pdu
*msp
= (struct tcp_multisegment_pdu
*)data
;
4088 DISSECTOR_ASSERT(msp
);
4089 tcp_segment_key
*key
= g_slice_new(tcp_segment_key
);
4092 * Do a deep copy of the addresses.
4094 copy_address(&key
->src_addr
, &pinfo
->src
);
4095 copy_address(&key
->dst_addr
, &pinfo
->dst
);
4096 key
->src_port
= pinfo
->srcport
;
4097 key
->dst_port
= pinfo
->destport
;
4099 key
->seq
= msp
->seq
;
4105 tcp_segment_free_temporary_key(void *ptr
)
4107 tcp_segment_key
*key
= (tcp_segment_key
*)ptr
;
4108 g_slice_free(tcp_segment_key
, key
);
4112 tcp_segment_free_persistent_key(void *ptr
)
4114 tcp_segment_key
*key
= (tcp_segment_key
*)ptr
;
4118 * Free up the copies of the addresses from the old key.
4120 free_address(&key
->src_addr
);
4121 free_address(&key
->dst_addr
);
4123 g_slice_free(tcp_segment_key
, key
);
4127 const reassembly_table_functions
4128 tcp_reassembly_table_functions
= {
4131 tcp_segment_temporary_key
,
4132 tcp_segment_persistent_key
,
4133 tcp_segment_free_temporary_key
,
4134 tcp_segment_free_persistent_key
4137 static reassembly_table tcp_reassembly_table
;
4139 /* functions to trace tcp segments */
4140 /* Enable desegmenting of TCP streams */
4141 static bool tcp_desegment
= true;
4143 /* Returns the maximum contiguous sequence number of the reassembly associated
4144 * with the msp *if* a new fragment were added ending in the given maxnextseq.
4145 * The new fragment is from the current frame and may not have been added yet.
4148 find_maxnextseq(packet_info
*pinfo
, struct tcp_multisegment_pdu
*msp
, uint32_t maxnextseq
)
4150 fragment_head
*fd_head
;
4152 DISSECTOR_ASSERT(msp
);
4154 fd_head
= fragment_get(&tcp_reassembly_table
, pinfo
, msp
->first_frame
, msp
);
4155 /* msp implies existence of fragments, this should never be NULL. */
4156 DISSECTOR_ASSERT(fd_head
);
4158 /* Find length of contiguous fragments.
4159 * Start with the first gap, but the new fragment is allowed to
4161 uint32_t max_len
= maxnextseq
- msp
->seq
;
4162 fragment_item
* frag
= (fd_head
->first_gap
) ? fd_head
->first_gap
: fd_head
->next
;
4163 for (; frag
&& frag
->offset
<= max_len
; frag
= frag
->next
) {
4164 max_len
= MAX(max_len
, frag
->offset
+ frag
->len
);
4167 return max_len
+ msp
->seq
;
4170 static struct tcp_multisegment_pdu
*
4171 split_msp(packet_info
*pinfo
, struct tcp_multisegment_pdu
*msp
, struct tcp_analysis
*tcpd
)
4173 fragment_head
*fd_head
;
4174 uint32_t first_frame
= 0;
4175 uint32_t last_frame
= 0;
4176 const uint32_t split_offset
= pinfo
->desegment_offset
;
4178 fd_head
= fragment_get(&tcp_reassembly_table
, pinfo
, msp
->first_frame
, msp
);
4179 /* This is for splitting defragmented MSPs, so fd_head should exist
4180 * and be defragmented. This also ensures that fd_i->tvb_data exists.
4182 DISSECTOR_ASSERT(fd_head
&& fd_head
->flags
& FD_DEFRAGMENTED
);
4184 fragment_item
*fd_i
, *first_frag
= NULL
;
4186 /* The fragment list is sorted in offset order, but not nec. frame order
4187 * or end offset order due to out of order reassembly and possible overlap.
4188 * fd_i->offset < split_offset - some bytes are before the split
4189 * fd_i->offset + fd_i->len >= split_offset - some bytes are after split
4190 * Look through all the fragments that have some data before the split point.
4192 for (fd_i
= fd_head
->next
; fd_i
&& (fd_i
->offset
< split_offset
); fd_i
= fd_i
->next
) {
4193 if (last_frame
< fd_i
->frame
) {
4194 last_frame
= fd_i
->frame
;
4196 if (fd_i
->offset
+ fd_i
->len
>= split_offset
) {
4197 if (first_frag
== NULL
) {
4199 first_frame
= fd_i
->frame
;
4200 } else if (fd_i
->frame
< first_frame
) {
4201 first_frame
= fd_i
->frame
;
4206 /* Now look through all the remaining fragments that only have bytes after
4209 for (; fd_i
; fd_i
= fd_i
->next
) {
4210 uint32_t frag_end
= fd_i
->offset
+ fd_i
->len
;
4211 if (split_offset
<= frag_end
&& fd_i
->frame
< first_frame
) {
4212 first_frame
= fd_i
->frame
;
4216 /* We only call this when the frame the fragments were reassembled in
4217 * (which is the current frame) includes some data before the split
4218 * point, so that it won't change and we can be consistent dissecting
4219 * between passes. We also should have at least some data after the
4220 * split point (because the subdissector claimed there was undissected
4223 DISSECTOR_ASSERT(fd_head
->reassembled_in
== last_frame
);
4224 DISSECTOR_ASSERT(first_frag
!= NULL
);
4226 uint32_t new_seq
= msp
->seq
+ pinfo
->desegment_offset
;
4227 struct tcp_multisegment_pdu
*newmsp
;
4228 newmsp
= pdu_store_sequencenumber_of_next_pdu(pinfo
, new_seq
,
4229 new_seq
+1, tcpd
->fwd
->multisegment_pdus
);
4230 newmsp
->first_frame
= first_frame
;
4231 newmsp
->nxtpdu
= msp
->nxtpdu
;
4233 /* XXX: Could do the adding the new fragments in fragment_truncate */
4234 for (fd_i
= first_frag
; fd_i
; fd_i
= fd_i
->next
) {
4235 uint32_t frag_offset
= fd_i
->offset
;
4236 uint32_t frag_len
= fd_i
->len
;
4237 /* Check for some unusual out of order overlapping segment situations. */
4238 if (split_offset
< frag_offset
+ frag_len
) {
4239 if (fd_i
->offset
< split_offset
) {
4240 frag_offset
= split_offset
;
4241 frag_len
-= (split_offset
- fd_i
->offset
);
4243 fragment_add_out_of_order(&tcp_reassembly_table
, fd_head
->tvb_data
,
4244 frag_offset
, pinfo
, first_frame
, newmsp
,
4245 frag_offset
- split_offset
, frag_len
, true, fd_i
->frame
);
4249 fragment_truncate(&tcp_reassembly_table
, pinfo
, msp
->first_frame
, msp
, split_offset
);
4250 msp
->nxtpdu
= msp
->seq
+ split_offset
;
4252 /* The newmsp nxtpdu will be adjusted after leaving this function. */
4256 typedef struct _ooo_segment_item
{
4264 compare_ooo_segment_item(const void *a
, const void *b
)
4266 const ooo_segment_item
*fd_a
= a
;
4267 const ooo_segment_item
*fd_b
= b
;
4269 /* We only insert segments into this list that satisfy
4270 * LT_SEQ(tcpd->fwd->maxnextseq, seq), for the current value
4271 * of maxnextseq (removing segments when maxnextseq is advanced)
4272 * so these rollover-aware comparisons are transitive over the
4273 * domain (never greater than 2^31).
4275 if (LT_SEQ(fd_a
->seq
, fd_b
->seq
))
4278 if (GT_SEQ(fd_a
->seq
, fd_b
->seq
))
4281 if (fd_a
->frame
< fd_b
->frame
)
4284 if (fd_a
->frame
> fd_b
->frame
)
4290 /* Search through our list of out of order segments and add the ones that are
4291 * now contiguous onto a MSP until we use them all or reach another gap.
4293 * If the MSP parameter is a incomplete, returns it with any OOO segments added.
4294 * If the MSP parameter is NULL or complete, returns a newly created MSP with
4295 * OOO segments added, or NULL if there were no segments to add.
4297 static struct tcp_multisegment_pdu
*
4298 msp_add_out_of_order(packet_info
*pinfo
, struct tcp_multisegment_pdu
*msp
, struct tcp_analysis
*tcpd
, uint32_t seq
)
4301 /* Whether a previous MSP exists with missing segments. */
4302 bool has_unfinished_msp
= msp
&& !(msp
->flags
& MSP_FLAGS_GOT_ALL_SEGMENTS
);
4303 bool updated_maxnextseq
= false;
4306 uint32_t maxnextseq
= find_maxnextseq(pinfo
, msp
, tcpd
->fwd
->maxnextseq
);
4307 if (LE_SEQ(tcpd
->fwd
->maxnextseq
, maxnextseq
)) {
4308 tcpd
->fwd
->maxnextseq
= maxnextseq
;
4310 updated_maxnextseq
= true;
4312 wmem_list_frame_t
*curr_entry
;
4313 curr_entry
= wmem_list_head(tcpd
->fwd
->ooo_segments
);
4314 ooo_segment_item
*fd
;
4316 while (curr_entry
) {
4317 fd
= (ooo_segment_item
*)wmem_list_frame_data(curr_entry
);
4318 if (LT_SEQ(tcpd
->fwd
->maxnextseq
, fd
->seq
)) {
4319 /* There might be segments already added to the msp that now extend
4320 * the maximum contiguous sequence number. Check for them. */
4321 if (msp
&& !updated_maxnextseq
) {
4322 tcpd
->fwd
->maxnextseq
= find_maxnextseq(pinfo
, msp
, tcpd
->fwd
->maxnextseq
);
4323 updated_maxnextseq
= true;
4325 if (LT_SEQ(tcpd
->fwd
->maxnextseq
, fd
->seq
)) {
4329 /* We have filled in the gap, so this out of order
4330 * segment is now contiguous and can be processed along
4331 * with the segment we just received.
4333 tcpd
->fwd
->maxnextseq
= fd
->seq
+ fd
->len
;
4334 tvb_data
= tvb_new_real_data(fd
->data
, fd
->len
, fd
->len
);
4335 if (has_unfinished_msp
) {
4337 /* Increase the expected MSP size if necessary. Yes, the
4338 * subdissector may have told us that a PDU ended here, but we
4339 * might have enough newly contiguous data to dissect another
4340 * PDU past that, and we should send that to the subdissector
4342 if (LT_SEQ(msp
->nxtpdu
, fd
->seq
+ fd
->len
)) {
4343 msp
->nxtpdu
= fd
->seq
+ fd
->len
;
4345 /* Add this OOO segment to the unfinished MSP */
4346 fragment_add_out_of_order(&tcp_reassembly_table
,
4348 pinfo
, msp
->first_frame
, msp
,
4349 fd
->seq
- msp
->seq
, fd
->len
,
4350 msp
->nxtpdu
, fd
->frame
);
4352 /* No MSP in progress, so create one starting
4353 * at the sequence number of segment received
4354 * in this frame. Note that we will be adding
4355 * the first segment below, and this is the frame
4356 * of the first segment, so first_frame_with_seq
4357 * is already correct (and unnecessary) and
4358 * we don't need MSP_FLAGS_MISSING_FIRST_SEGMENT. */
4359 msp
= pdu_store_sequencenumber_of_next_pdu(pinfo
,
4360 seq
, fd
->seq
+ fd
->len
,
4361 tcpd
->fwd
->multisegment_pdus
);
4362 fragment_add_out_of_order(&tcp_reassembly_table
,
4363 tvb_data
, 0, pinfo
, msp
->first_frame
,
4364 msp
, fd
->seq
- msp
->seq
, fd
->len
,
4365 msp
->nxtpdu
, fd
->frame
);
4366 has_unfinished_msp
= true;
4368 updated_maxnextseq
= false;
4370 wmem_list_remove_frame(tcpd
->fwd
->ooo_segments
, curr_entry
);
4371 curr_entry
= wmem_list_head(tcpd
->fwd
->ooo_segments
);
4374 /* There might be segments already added to the msp that now extend
4375 * the maximum contiguous sequence number. Check for them. */
4376 if (msp
&& !updated_maxnextseq
) {
4377 tcpd
->fwd
->maxnextseq
= find_maxnextseq(pinfo
, msp
, tcpd
->fwd
->maxnextseq
);
4383 desegment_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
4384 uint32_t seq
, uint32_t nxtseq
,
4385 uint32_t sport
, uint32_t dport
,
4386 proto_tree
*tree
, proto_tree
*tcp_tree
,
4387 struct tcp_analysis
*tcpd
, struct tcpinfo
*tcpinfo
)
4389 fragment_head
*ipfd_head
;
4390 int last_fragment_len
;
4391 bool must_desegment
;
4392 bool called_dissector
;
4394 int another_pdu_follows
;
4399 struct tcp_multisegment_pdu
*msp
;
4400 bool cleared_writable
= col_get_writable(pinfo
->cinfo
, COL_PROTOCOL
);
4401 bool first_pdu
= true;
4402 const bool reassemble_ooo
= tcp_analyze_seq
&& tcp_desegment
&& tcp_reassemble_out_of_order
&& tcpd
&& tcpd
->fwd
->ooo_segments
;
4404 tcp_endpoint_t orig_endpoint
, new_endpoint
;
4406 save_endpoint(pinfo
, &orig_endpoint
);
4407 save_endpoint(pinfo
, &new_endpoint
);
4411 last_fragment_len
= 0;
4412 must_desegment
= false;
4413 called_dissector
= false;
4415 another_pdu_follows
= 0;
4419 * Initialize these to assume no desegmentation.
4420 * If that's not the case, these will be set appropriately
4421 * by the subdissector.
4423 pinfo
->desegment_offset
= 0;
4424 pinfo
->desegment_len
= 0;
4427 * Initialize this to assume that this segment will just be
4428 * added to the middle of a desegmented chunk of data, so
4429 * that we should show it all as data.
4430 * If that's not the case, it will be set appropriately.
4432 deseg_offset
= offset
;
4435 * TODO: Some notes on current limitations with TCP desegmentation:
4437 * This function can be called with either relative or absolute sequence
4438 * numbers; the ??_SEQ macros are called for comparisons to deal with
4439 * with sequence number rollover. (With relative sequence numbers, if
4440 * early TCP segments are received out of order before the SYN it can be
4441 * possible for rollover to occur at the very beginning of a connection.)
4443 * However, multi-segment PDU lookup does not work for MSPs that span
4444 * TCP sequence number rollover, and desegmentation fails.
4446 * When there is a single TCP connection that is longer than 4 GiB and
4447 * thus sequence numbers are reused, multi-segment PDU lookup and
4448 * retransmission identification does not work. (Bug 10503).
4450 * Distinguishing between sequence number reuse on a very long connection
4451 * and sequence number reuse due to retransmission is difficult. Right
4452 * now very long connections are just not handled as the rarer case.
4453 * Perhaps retransmission identification could be entirely left up to TCP
4454 * analysis (if enabled, not done at all if disabled), instead of TCP
4455 * analysis results only used to supplement work here?
4457 * TCP sequence analysis can set TCP_A_RETRANSMISSION in cases where
4458 * we still need to process the segment anyway because something other
4459 * than the sequence number is different from the prior segment. That
4460 * includes "retransmitted but with additional data" (Bug 13523) and
4461 * "retransmitted due to bad checksum" (especially if checksum verification
4464 * "Reassemble out-of-order segments" uses its own method of detecting
4465 * retranmission, but uses more memory and CPU, and when used, a TCP stream
4466 * that has missing segments that are never retransmitted stop processing
4467 * after the missing segment.
4469 * If multiple TCP/IP packets are encapsulated in the same frame (such
4470 * as with GSE, which has very long Baseband Frames) this causes issues:
4472 * If a subdissector reports that it can handle a payload, but needs
4473 * more data (pinfo->desegment_len > 0) and did not actually dissect
4474 * any of it (pinfo->desegment_offset == 0), on the first pass it
4475 * still adds layers to the frame. On subsequent passes, the MSP created
4476 * (or extended) in the first pass means that the subdissector won't be
4477 * called at all. If there are other protocols contained in the frame
4478 * that are dissected on the second pass they will have different
4479 * layer numbers than in the first pass, which can disturb proto_data
4480 * lookup, reassembly, etc. (Bug 16109 describes this for TLS.)
4485 if (reassemble_ooo
) {
4486 /* If we are reassembling out of order, we can do this retransmission
4487 * check. Anything before the latest consecutive sequence number we've
4488 * already processed is a retransmission (from the perspective of has
4489 * been passed to subdissectors; the judgment of TCP Sequence Analysis
4490 * may be different, because it considers RTO and ACKs and so forth).
4492 * XXX: If these segments are part of incomplete MSPs, we pass them
4493 * to the reassembly code which tests for overlap conflicts.
4494 * For those which are part of completed reassemblies or not part
4495 * of MSPs, we just don't process them. The former would throw a
4496 * ReassemblyError, which is likely acceptable in the case of
4497 * retransmission of the same segment but not if retransmitted with
4498 * additional data, where we'd need to catch the exception to
4499 * process the extra data. For ones that were not added to MSPs at
4500 * all, we can't do much. (Bug #13061)
4502 * Retransmissions of out of order segments after our latest
4503 * consecutive sequence number will all be stored and then eventually
4504 * put on multisegment PDUs and go to the reassembler, which should
4505 * be able to handle retransmission, as those are still incomplete.
4508 msp
= (struct tcp_multisegment_pdu
*)wmem_tree_lookup32_le(tcpd
->fwd
->multisegment_pdus
, seq
);
4510 bool has_unfinished_msp
= false;
4511 if (msp
&& LE_SEQ(msp
->seq
, seq
) && GT_SEQ(msp
->nxtpdu
, seq
) && !(msp
->flags
& MSP_FLAGS_GOT_ALL_SEGMENTS
)) {
4512 has_unfinished_msp
= true;
4515 if (!PINFO_FD_VISITED(pinfo
) && first_pdu
) {
4516 if (tcpd
->fwd
->maxnextseq
&& LT_SEQ(seq
, tcpd
->fwd
->maxnextseq
) && !has_unfinished_msp
) {
4518 tcp_analyze_get_acked_struct(pinfo
->num
, seq
, tcpinfo
->lastackseq
, true, tcpd
);
4520 tcpd
->ta
->flags
|= TCP_A_OLD_DATA
;
4521 if (GT_SEQ(nxtseq
, tcpd
->fwd
->maxnextseq
)) {
4522 tcpd
->ta
->new_data_seq
= tcpd
->fwd
->maxnextseq
;
4524 tcpd
->ta
->new_data_seq
= nxtseq
;
4529 if(tcpd
->ta
&& first_pdu
) {
4530 if((tcpd
->ta
->flags
&TCP_A_OLD_DATA
) == TCP_A_OLD_DATA
) {
4531 nbytes
= tcpd
->ta
->new_data_seq
- seq
;
4533 proto_tree_add_bytes_format(tcp_tree
, hf_tcp_segment_data
, tvb
,
4534 offset
, nbytes
, NULL
,
4535 "Retransmitted TCP segment data (%u byte%s)",
4536 nbytes
, plurality(nbytes
, "", "s"));
4539 seq
= tcpd
->ta
->new_data_seq
;
4541 if (tvb_captured_length_remaining(tvb
, offset
) > 0)
4548 /* Have we seen this PDU before (and is it the start of a multi-
4551 * If the sequence number was seen before, it is part of a
4552 * retransmission if the whole segment fits within the MSP.
4553 * (But if this is this frame was already visited and the first frame of
4554 * the MSP matches the current frame, then it is not a retransmission,
4555 * but the start of a new MSP.)
4557 * If only part of the segment fits in the MSP, then either:
4558 * - The previous segment included with the MSP was a Zero Window Probe
4559 * with one byte of data and the subdissector just asked for one more
4560 * byte. Do not mark it as retransmission (Bug 15427).
4561 * - Data was actually being retransmitted, but with additional data
4562 * (Bug 13523). Do not mark it as retransmission to handle the extra
4563 * bytes. (NOTE Due to the TCP_A_RETRANSMISSION check below, such
4564 * extra data will still be ignored.)
4565 * - The MSP contains multiple segments, but the subdissector finished
4566 * reassembly using a subset of the final segment (thus "msp->nxtpdu"
4567 * is smaller than the nxtseq of the previous segment). If that final
4568 * segment was retransmitted, then "nxtseq > msp->nxtpdu".
4569 * Unfortunately that will *not* be marked as retransmission here.
4570 * The next TCP_A_RETRANSMISSION hopefully takes care of it though.
4572 * Only shortcircuit here when the first segment of the MSP is known,
4573 * and when this first segment is not one to complete the MSP.
4575 if ((msp
= (struct tcp_multisegment_pdu
*)wmem_tree_lookup32(tcpd
->fwd
->multisegment_pdus
, seq
)) &&
4576 nxtseq
<= msp
->nxtpdu
&&
4577 !(msp
->flags
& MSP_FLAGS_MISSING_FIRST_SEGMENT
) && msp
->last_frame
!= pinfo
->num
) {
4579 bool is_retransmission
= false;
4581 /* Yes. This could be because we've dissected this frame before
4582 * or because this is a retransmission of a previously-seen
4583 * segment. Either way, we don't need to hand it off to the
4584 * subdissector and we certainly don't want to re-add it to the
4585 * multisegment_pdus list: if we did, subsequent lookups would
4586 * find this retransmission instead of the original transmission
4587 * (breaking desegmentation if we'd already linked other segments
4588 * to the original transmission's entry).
4590 * Cases to handle here:
4591 * - In-order stream, pinfo->num matches begin of MSP.
4592 * - In-order stream, but pinfo->num does not match the begin of the
4593 * MSP. Must be a retransmission.
4594 * - OoO stream where this segment fills the gap in the begin of the
4595 * MSP. msp->first_frame is the start where the gap was detected
4596 * (and does NOT match pinfo->num).
4599 if (msp
->first_frame
== pinfo
->num
|| msp
->first_frame_with_seq
== pinfo
->num
) {
4602 str
= "Retransmitted ";
4603 is_retransmission
= true;
4604 /* TCP analysis already flags this (in COL_INFO) as a retransmission--if it's enabled */
4607 /* Fix for bug 3264: look up ipfd for this (first) segment,
4608 so can add tcp.reassembled_in generated field on this code path. */
4609 if (!is_retransmission
) {
4610 ipfd_head
= fragment_get(&tcp_reassembly_table
, pinfo
, msp
->first_frame
, msp
);
4612 if (ipfd_head
->reassembled_in
!= 0) {
4613 item
= proto_tree_add_uint(tcp_tree
, hf_tcp_reassembled_in
, tvb
, 0,
4614 0, ipfd_head
->reassembled_in
);
4615 proto_item_set_generated(item
);
4618 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "[TCP PDU reassembled in %u]",
4619 ipfd_head
->reassembled_in
);
4625 nbytes
= tvb_reported_length_remaining(tvb
, offset
);
4627 proto_tree_add_bytes_format(tcp_tree
, hf_tcp_segment_data
, tvb
, offset
,
4628 nbytes
, NULL
, "%sTCP segment data (%u byte%s)", str
, nbytes
,
4629 plurality(nbytes
, "", "s"));
4633 /* Else, find the most previous PDU starting before this sequence number */
4635 msp
= (struct tcp_multisegment_pdu
*)wmem_tree_lookup32_le(tcpd
->fwd
->multisegment_pdus
, seq
-1);
4638 bool has_unfinished_msp
= false;
4639 if (msp
&& LE_SEQ(msp
->seq
, seq
) && GT_SEQ(msp
->nxtpdu
, seq
) && !(msp
->flags
& MSP_FLAGS_GOT_ALL_SEGMENTS
)) {
4640 has_unfinished_msp
= true;
4643 /* The above code only finds retransmission if the PDU boundaries and the seq coincide
4644 * If we have sequence analysis active use the TCP_A_RETRANSMISSION flag.
4645 * XXXX Could the above code be improved?
4648 /* If we have an unfinished MSP that this segment belongs to
4649 * or if the sequence number is newer than anything we've seen,
4650 * then this is Out of Order from the reassembly perspective
4651 * and we want to process it anyway.
4653 if (!PINFO_FD_VISITED(pinfo
) && tcpd
->fwd
->maxnextseq
&& LE_SEQ(seq
, tcpd
->fwd
->maxnextseq
) && !has_unfinished_msp
) {
4654 /* Otherwise, if TCP Analysis calls the segment a
4655 * Spurious Retransmission or Retransmission, ignore it
4656 * here and on future passes.
4658 * XXX: There are still some cases where TCP Analysis
4659 * marks segments as Retransmissions when they are
4660 * Out of Order from this perspective (#10725, #13843)
4662 if((tcpd
->ta
->flags
&TCP_A_SPURIOUS_RETRANSMISSION
) == TCP_A_SPURIOUS_RETRANSMISSION
||
4663 (tcpd
->ta
->flags
& TCP_A_RETRANSMISSION
) == TCP_A_RETRANSMISSION
||
4664 (tcpd
->ta
->flags
& TCP_A_FAST_RETRANSMISSION
) == TCP_A_FAST_RETRANSMISSION
) {
4665 tcpd
->ta
->flags
|= TCP_A_OLD_DATA
;
4668 if((tcpd
->ta
->flags
&TCP_A_OLD_DATA
) == TCP_A_OLD_DATA
) {
4669 const char* str
= "Retransmitted ";
4670 nbytes
= tvb_reported_length_remaining(tvb
, offset
);
4671 proto_tree_add_bytes_format(tcp_tree
, hf_tcp_segment_data
, tvb
, offset
,
4672 nbytes
, NULL
, "%sTCP segment data (%u byte%s)", str
, nbytes
,
4673 plurality(nbytes
, "", "s"));
4680 if (reassemble_ooo
&& tcpd
&& !(tcpd
->fwd
->flags
& TCP_FLOW_REASSEMBLE_UNTIL_FIN
)) {
4681 if (!PINFO_FD_VISITED(pinfo
)) {
4682 /* If there is a gap between this segment and any previous ones
4683 * (that is, seqno is larger than the maximum expected seqno), then
4684 * it is possibly an out-of-order segment. The very first segment
4685 * is expected to be in-order though (otherwise captures starting
4686 * in midst of a connection would never be reassembled).
4687 * (maxnextseq is 0 if we have not seen a SYN packet, even with
4688 * absolute sequence numbers.)
4690 * Do not bother checking for OoO segments for streams that are
4691 * reassembled at FIN, the order of segments before FIN does not
4692 * matter as reordering and reassembly occurs at FIN.
4695 if (tcpd
->fwd
->maxnextseq
) {
4696 /* Segments may be missing due to packet loss (assume later
4697 * retransmission) or out-of-order (assume it appears later).
4699 * XXX: It would be nice to handle captures that have both
4700 * out-of-order packets and some lost packets that are
4701 * never retransmitted. But using the reverse flow ACK
4702 * (like follow_tcp_tap_listener) or using a known end of
4703 * a MSP (that we haven't fully received yet) to process a
4704 * segment that starts right afterwards would both break the
4705 * promise of in-order delivery, if a missing packet did arrive
4706 * later, which is a problem for any state-based dissector
4710 /* Whether the new segment has a gap from our latest contiguous
4711 * sequence number. */
4712 has_gap
= LT_SEQ(tcpd
->fwd
->maxnextseq
, seq
);
4716 /* Update the maximum expected seqno if no SYN packet was seen
4717 * before, or if the new segment succeeds previous segments. */
4718 tcpd
->fwd
->maxnextseq
= nxtseq
;
4720 /* If there is no gap, look for any OOO packets that are now
4722 msp
= msp_add_out_of_order(pinfo
, msp
, tcpd
, seq
);
4725 /* If we have visited this frame before, look for the frame in the
4726 * list of unused out of order segments. Since we know the gap will
4727 * never be filled, we could pass it to the subdissector, but
4728 * we want to be consistent between passes.
4730 ooo_segment_item
*fd
;
4731 fd
= wmem_new0(pinfo
->pool
, ooo_segment_item
);
4732 fd
->frame
= pinfo
->num
;
4734 fd
->len
= nxtseq
- seq
;
4735 if (wmem_list_find_custom(tcpd
->fwd
->ooo_segments
, fd
, compare_ooo_segment_item
)) {
4741 /* If we are not processing out of order, update the max nextseq value if
4742 * is later than our current value (or our first value.)
4744 if (!reassemble_ooo
&& tcpd
&& !(tcpd
->fwd
->flags
& TCP_FLOW_REASSEMBLE_UNTIL_FIN
)) {
4745 if (!PINFO_FD_VISITED(pinfo
)) {
4746 if (LT_SEQ(tcpd
->fwd
->maxnextseq
, nxtseq
) || tcpd
->fwd
->maxnextseq
== 0) {
4747 tcpd
->fwd
->maxnextseq
= nxtseq
;
4752 if (msp
&& LE_SEQ(msp
->seq
, seq
) && GT_SEQ(msp
->nxtpdu
, seq
)) {
4755 if (!PINFO_FD_VISITED(pinfo
)) {
4756 msp
->last_frame
=pinfo
->num
;
4757 msp
->last_frame_time
=pinfo
->abs_ts
;
4760 /* OK, this PDU was found, which means the segment continues
4761 * a higher-level PDU and that we must desegment it.
4763 if (msp
->flags
&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
) {
4764 /* The dissector asked for the entire segment */
4765 len
= tvb_captured_length_remaining(tvb
, offset
);
4767 /* Wraparound is possible, so subtraction does not
4768 * distribute across MIN(x, y)
4770 len
= MIN(nxtseq
- seq
, msp
->nxtpdu
- seq
);
4772 last_fragment_len
= len
;
4775 if (reassemble_ooo
&& tcpd
&& !(tcpd
->fwd
->flags
& TCP_FLOW_REASSEMBLE_UNTIL_FIN
)) {
4777 * If the previous segment requested more data (setting
4778 * FD_PARTIAL_REASSEMBLY as the next segment length is unknown), but
4779 * subsequently an OoO segment was received (for an earlier hole),
4780 * then "fragment_add" would truncate the reassembled PDU to the end
4781 * of this OoO segment. To prevent that, explicitly specify the MSP
4782 * length before calling "fragment_add".
4784 * When a subdissector requests reassembly at the end of the
4785 * connection (DESEGMENT_UNTIL_FIN), then it is not
4786 * possible for an earlier segment to complete reassembly
4787 * (more_frags for fragment_add is always true). Thus we do not
4788 * have to worry about increasing the fragment length here.
4790 fragment_reset_tot_len(&tcp_reassembly_table
, pinfo
,
4791 msp
->first_frame
, msp
,
4792 MAX(seq
+ len
, msp
->nxtpdu
) - msp
->seq
);
4795 ipfd_head
= fragment_add(&tcp_reassembly_table
, tvb
, offset
,
4796 pinfo
, msp
->first_frame
, msp
,
4797 seq
- msp
->seq
, len
,
4798 (LT_SEQ (nxtseq
,msp
->nxtpdu
)) );
4800 if (!PINFO_FD_VISITED(pinfo
) && ipfd_head
4801 && msp
->flags
& MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
) {
4802 msp
->flags
&= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
);
4804 /* If we consumed the entire segment there is no
4805 * other pdu starting anywhere inside this segment.
4806 * So update nxtpdu to point at least to the start
4807 * of the next segment.
4808 * (If the subdissector asks for even more data we
4809 * will advance nxtpdu even further later down in
4812 if (LT_SEQ(msp
->nxtpdu
, nxtseq
)) {
4813 msp
->nxtpdu
= nxtseq
;
4817 if (reassemble_ooo
&& !PINFO_FD_VISITED(pinfo
)) {
4818 /* Remember when all segments are ready to avoid subsequent
4819 * out-of-order packets from extending this MSP. If a subsdissector
4820 * needs more segments, the flag will be cleared below. */
4822 msp
->flags
|= MSP_FLAGS_GOT_ALL_SEGMENTS
;
4826 if( (msp
->nxtpdu
< nxtseq
)
4827 && (msp
->nxtpdu
>= seq
)
4829 another_pdu_follows
=msp
->nxtpdu
- seq
;
4831 } else if (has_gap
) {
4832 /* This is an OOO segment with a gap and past the known end of
4833 * the current MSP, if any. We don't know for certain which MSP
4834 * it belongs to, and the reassembly functions don't let us remove
4835 * fragment items added by mistake. Keep it around in a separate
4836 * structure, and add it later.
4838 * On the second and later passes, we know that this gap will
4839 * never be filled in, so we could hand the segment to the
4840 * subdissector anyway. However, we want dissection to be
4841 * consistent between passes.
4843 if (!PINFO_FD_VISITED(pinfo
)) {
4844 ooo_segment_item
*fd
;
4845 fd
= wmem_new0(wmem_file_scope(), ooo_segment_item
);
4846 fd
->frame
= pinfo
->num
;
4848 fd
->len
= nxtseq
- seq
;
4849 /* We only enter here if dissect_tcp set can_desegment,
4850 * which means that these bytes exist. */
4851 fd
->data
= tvb_memdup(wmem_file_scope(), tvb
, offset
, fd
->len
);
4852 wmem_list_append_sorted(tcpd
->fwd
->ooo_segments
, fd
, compare_ooo_segment_item
);
4856 /* This segment was not found in our table, so it doesn't
4857 * contain a continuation of a higher-level PDU.
4858 * Call the normal subdissector.
4862 * Supply the sequence number of this segment. We set this here
4863 * because this segment could be after another in the same packet,
4864 * in which case seq was incremented at the end of the loop.
4868 process_tcp_payload(tvb
, offset
, pinfo
, tree
, tcp_tree
,
4869 sport
, dport
, 0, 0, false, tcpd
, tcpinfo
);
4871 /* Unless it failed to dissect any data at all, the subdissector
4872 * might have changed the addresses and/or ports. Save them, and
4873 * set them back to the original values temporarily so that the
4874 * fragment functions work correctly (including in any later PDU.)
4876 * (If we didn't dissect any data, the subdissector *shouldn't*
4877 * have changed the addresses or ports, so don't save them, but
4878 * restore them just in case.)
4880 if (!(pinfo
->desegment_len
&& pinfo
->desegment_offset
== 0)) {
4881 save_endpoint(pinfo
, &new_endpoint
);
4883 restore_endpoint(pinfo
, &orig_endpoint
);
4884 called_dissector
= true;
4886 /* Did the subdissector ask us to desegment some more data
4887 * before it could handle the packet?
4888 * If so we'll have to handle that later.
4890 if(pinfo
->desegment_len
) {
4891 must_desegment
= true;
4894 * Set "deseg_offset" to the offset in "tvb"
4895 * of the first byte of data that the
4896 * subdissector didn't process.
4898 deseg_offset
= offset
+ pinfo
->desegment_offset
;
4901 /* Either no desegmentation is necessary, or this is
4902 * segment contains the beginning but not the end of
4903 * a higher-level PDU and thus isn't completely
4910 /* is it completely desegmented? */
4913 * Yes, we think it is.
4914 * We only call subdissector for the last segment.
4915 * Note that the last segment may include more than what
4918 if (ipfd_head
->reassembled_in
== pinfo
->num
&& ipfd_head
->reas_in_layer_num
== pinfo
->curr_layer_num
) {
4920 * OK, this is the last segment.
4921 * Let's call the subdissector with the desegmented
4926 /* create a new TVB structure for desegmented data */
4927 next_tvb
= tvb_new_chain(tvb
, ipfd_head
->tvb_data
);
4929 /* add desegmented data to the data source list */
4930 add_new_data_source(pinfo
, next_tvb
, "Reassembled TCP");
4933 * Supply the sequence number of the first of the
4934 * reassembled bytes.
4936 tcpinfo
->seq
= msp
->seq
;
4938 /* indicate that this is reassembled data */
4939 tcpinfo
->is_reassembled
= true;
4941 /* call subdissector */
4942 process_tcp_payload(next_tvb
, 0, pinfo
, tree
, tcp_tree
, sport
,
4943 dport
, 0, 0, false, tcpd
, tcpinfo
);
4945 /* Unless it failed to dissect any data at all, the subdissector
4946 * might have changed the addresses and/or ports. Save them, and
4947 * set them back to the original values temporarily so that the
4948 * fragment functions work correctly (including in any later PDU.)
4950 * (If we didn't dissect any data, the subdissector *shouldn't*
4951 * have changed the addresses or ports, so don't save them, but
4952 * restore them just in case.)
4954 if (!(pinfo
->desegment_len
&& pinfo
->desegment_offset
== 0)) {
4955 save_endpoint(pinfo
, &new_endpoint
);
4957 restore_endpoint(pinfo
, &orig_endpoint
);
4958 called_dissector
= true;
4961 * OK, did the subdissector think it was completely
4962 * desegmented, or does it think we need even more
4965 if (pinfo
->desegment_len
) {
4967 * "desegment_len" isn't 0, so it needs more data
4968 * to fully dissect the current MSP. msp->nxtpdu was
4969 * not accurate and needs to be updated.
4971 * This can happen if a dissector asked for one
4972 * more segment (but didn't know exactly how much data)
4973 * or if segments were added out of order.
4975 * This is opposed to the current MSP being completely
4976 * desegmented, but the stuff at the end of the
4977 * current frame past last_fragment_len starting a new
4978 * higher-level PDU that may also need desegmentation.
4979 * That case is handled on the next loop.
4981 * We want to keep the same dissection and protocol layer
4982 * numbers on subsequent passes.
4984 * If "desegment_offset" is 0, then nothing in the reassembled
4985 * TCP segments was dissected, so remove the data source.
4987 if (pinfo
->desegment_offset
== 0) {
4988 if (reassemble_ooo
&& !PINFO_FD_VISITED(pinfo
)) {
4989 msp
->flags
&= ~MSP_FLAGS_GOT_ALL_SEGMENTS
;
4991 remove_last_data_source(pinfo
);
4992 fragment_set_partial_reassembly(&tcp_reassembly_table
,
4993 pinfo
, msp
->first_frame
,
4996 /* If "desegment_offset" is not 0, then a PDU in the
4997 * reassembled segments was dissected, but some stuff
4998 * that was added previously is part of a later PDU.
5000 if (LE_SEQ(msp
->seq
+ pinfo
->desegment_offset
, seq
)) {
5001 /* If we don't use anything from the current frame's
5002 * segment, then we can't split the msp. The frames of
5003 * the earlier PDU weren't reassembled until now, so
5004 * they need to point to a reassembled_in frame here
5007 * Since this segment is the first of newly contiguous
5008 * segments, this means the subdissector is asking for
5009 * fewer bytes than it did before.
5010 * XXX: Report this as a dissector bug?
5012 if (reassemble_ooo
&& !PINFO_FD_VISITED(pinfo
)) {
5013 msp
->flags
&= ~MSP_FLAGS_GOT_ALL_SEGMENTS
;
5015 fragment_set_partial_reassembly(&tcp_reassembly_table
,
5016 pinfo
, msp
->first_frame
,
5019 /* If we did use bytes from the current segment, then
5020 * we want to split the MSP; the earlier part is
5021 * dissected in this frame on the first pass, so for
5022 * consistency we want to do so on future passes, but
5023 * the latter part we cannot dissect until later.
5024 * We only need to do this on the first pass; split_msp
5025 * truncates the msp so we don't get here a second
5028 /* nxtpdu adjustment for the new msp is the same. */
5029 if (!PINFO_FD_VISITED(pinfo
)) {
5030 /* We don't need to clear MSP_FLAGS_GOT_ALL_SEGMENTS
5031 * since we are spliting the MSP.
5033 msp
= split_msp(pinfo
, msp
, tcpd
);
5035 print_tcp_fragment_tree(ipfd_head
, tree
, tcp_tree
, pinfo
, next_tvb
);
5039 if (!PINFO_FD_VISITED(pinfo
)) {
5040 /* Update msp->nxtpdu to point to the new next
5042 * We only do this on the first pass, though we shouldn't
5043 * get here on a second pass (since we truncated the msp.)
5045 if (pinfo
->desegment_len
== DESEGMENT_ONE_MORE_SEGMENT
) {
5046 /* We want reassembly of at least one
5047 * more segment so set the nxtpdu
5048 * boundary to one byte into the next
5050 * This means that the next segment
5051 * will complete reassembly even if it
5052 * is only one single byte in length.
5053 * If this is an OoO segment, then increment
5056 msp
->nxtpdu
= MAX(seq
+ tvb_reported_length_remaining(tvb
, offset
), msp
->nxtpdu
) + 1;
5057 msp
->flags
|= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
;
5058 } else if (pinfo
->desegment_len
== DESEGMENT_UNTIL_FIN
) {
5059 tcpd
->fwd
->flags
|= TCP_FLOW_REASSEMBLE_UNTIL_FIN
;
5060 /* This is not the first segment, and we thought the
5061 * reassembly would be done now, but now know we must
5062 * desgment until FIN. (E.g., HTTP Response with headers
5063 * split across segments, and no Content-Length or
5064 * Transfer-Encoding (RFC 7230, Section 3.3.3, case 7.)
5065 * For the same reasons as below when we encounter
5066 * DESEGMENT_UNTIL_FIN on the first segment, give
5067 * msp->nxtpdu a big (but not too big) offset so
5068 * reassembly will pick up the segments later.
5070 msp
->nxtpdu
= msp
->seq
+ 0x40000000;
5072 if (seq
+ last_fragment_len
>= msp
->nxtpdu
) {
5073 /* This is the segment (overlapping) the end of
5076 msp
->nxtpdu
= seq
+ last_fragment_len
+ pinfo
->desegment_len
;
5078 /* This is a segment before the end of the MSP, so
5079 * it must be an out-of-order segment that completed
5080 * the MSP. The requested additional data is
5081 * relative to that end.
5083 msp
->nxtpdu
+= pinfo
->desegment_len
;
5088 /* Since we need at least some more data
5089 * there can be no pdu following in the
5090 * tail of this segment.
5092 another_pdu_follows
= 0;
5093 offset
+= last_fragment_len
;
5094 seq
+= last_fragment_len
;
5095 if (tvb_captured_length_remaining(tvb
, offset
) > 0)
5099 * Show the stuff in this TCP segment as
5100 * just raw TCP segment data.
5102 nbytes
= another_pdu_follows
> 0
5103 ? another_pdu_follows
5104 : tvb_reported_length_remaining(tvb
, offset
);
5105 proto_tree_add_bytes_format(tcp_tree
, hf_tcp_segment_data
, tvb
, offset
,
5106 nbytes
, NULL
, "TCP segment data (%u byte%s)", nbytes
,
5107 plurality(nbytes
, "", "s"));
5109 print_tcp_fragment_tree(ipfd_head
, tree
, tcp_tree
, pinfo
, next_tvb
);
5114 if (must_desegment
) {
5116 * The sequence number at which the stuff to be desegmented
5117 * starts is the sequence number of the byte at an offset
5118 * of "deseg_offset" into "tvb".
5120 * The sequence number of the byte at an offset of "offset"
5121 * is "seq", i.e. the starting sequence number of this
5122 * segment, so the sequence number of the byte at
5123 * "deseg_offset" is "seq + (deseg_offset - offset)".
5125 deseg_seq
= seq
+ (deseg_offset
- offset
);
5127 /* We have to create some structures in our table but
5128 * this is something we only do the first time we see this
5130 if (!PINFO_FD_VISITED(pinfo
)) {
5131 /* If the dissector requested "reassemble until FIN"
5132 * just set this flag for the flow and let reassembly
5133 * proceed at normal. We will check/pick up these
5134 * reassembled PDUs later down in dissect_tcp() when checking
5137 if (tcpd
&& pinfo
->desegment_len
== DESEGMENT_UNTIL_FIN
) {
5138 tcpd
->fwd
->flags
|= TCP_FLOW_REASSEMBLE_UNTIL_FIN
;
5140 if (tcpd
&& ((nxtseq
- deseg_seq
) <= 1024*1024)) {
5141 if(pinfo
->desegment_len
== DESEGMENT_ONE_MORE_SEGMENT
) {
5142 /* The subdissector asked to reassemble using the
5143 * entire next segment.
5144 * Just ask reassembly for one more byte
5145 * but set this msp flag so we can pick it up
5148 msp
= pdu_store_sequencenumber_of_next_pdu(pinfo
, deseg_seq
,
5149 nxtseq
+1, tcpd
->fwd
->multisegment_pdus
);
5150 msp
->flags
|= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
;
5151 } else if (pinfo
->desegment_len
== DESEGMENT_UNTIL_FIN
) {
5153 * The subdissector asked to reassemble at the end of the
5154 * connection. That will be done in dissect_tcp, but here we
5155 * have to ask reassembly to collect all future segments.
5156 * Note that TCP_FLOW_REASSEMBLE_UNTIL_FIN was set before,
5157 * this ensures that OoO detection is skipped.
5158 * The exact nxtpdu offset does not matter, but it should be
5159 * smaller than half of the maximum 32-bit unsigned integer
5160 * to allow detection of sequence number wraparound, and
5161 * larger than the largest possible stream size. Hopefully
5162 * 1GiB (0x40000000 bytes) should be enough.
5164 msp
= pdu_store_sequencenumber_of_next_pdu(pinfo
, deseg_seq
,
5165 nxtseq
+0x40000000, tcpd
->fwd
->multisegment_pdus
);
5167 msp
= pdu_store_sequencenumber_of_next_pdu(pinfo
,
5168 deseg_seq
, nxtseq
+pinfo
->desegment_len
, tcpd
->fwd
->multisegment_pdus
);
5171 /* add this segment as the first one for this new pdu */
5172 fragment_add(&tcp_reassembly_table
, tvb
, deseg_offset
,
5173 pinfo
, msp
->first_frame
, msp
,
5174 0, nxtseq
- deseg_seq
,
5175 LT_SEQ(nxtseq
, msp
->nxtpdu
));
5178 /* If this is not the first time we have seen the packet, then
5179 * the MSP should already be created. Retrieve it to see if we
5180 * know what later frame the PDU is reassembled in.
5182 if (tcpd
&& (msp
= (struct tcp_multisegment_pdu
*)wmem_tree_lookup32(tcpd
->fwd
->multisegment_pdus
, deseg_seq
))) {
5183 ipfd_head
= fragment_get(&tcp_reassembly_table
, pinfo
, msp
->first_frame
, msp
);
5188 if (!called_dissector
|| pinfo
->desegment_len
!= 0) {
5189 if (ipfd_head
!= NULL
&& ipfd_head
->reassembled_in
!= 0 &&
5190 ipfd_head
->reassembled_in
!= pinfo
->num
&&
5191 !(ipfd_head
->flags
& FD_PARTIAL_REASSEMBLY
)) {
5193 * We know what other frame this PDU is reassembled in;
5194 * let the user know.
5196 item
= proto_tree_add_uint(tcp_tree
, hf_tcp_reassembled_in
, tvb
, 0,
5197 0, ipfd_head
->reassembled_in
);
5198 proto_item_set_generated(item
);
5202 * Either we didn't call the subdissector at all (i.e.,
5203 * this is a segment that contains the middle of a
5204 * higher-level PDU, but contains neither the beginning
5205 * nor the end), or the subdissector couldn't dissect it
5206 * all, as some data was missing (i.e., it set
5207 * "pinfo->desegment_len" to the amount of additional
5210 if (pinfo
->desegment_offset
== 0) {
5212 * It couldn't, in fact, dissect any of it (the
5213 * first byte it couldn't dissect is at an offset
5214 * of "pinfo->desegment_offset" from the beginning
5215 * of the payload, and that's 0).
5216 * Just mark this as TCP.
5218 if (first_pdu
&& ipfd_head
!= NULL
&& ipfd_head
->reassembled_in
!= 0) {
5219 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " ", "[TCP PDU reassembled in %u]",
5220 ipfd_head
->reassembled_in
);
5225 * Show what's left in the packet as just raw TCP segment
5226 * data. (It's possible that another PDU follows in the case
5227 * of an out of order frame that is part of two MSPs.)
5228 * XXX - remember what protocol the last subdissector
5229 * was, and report it as a continuation of that, instead?
5231 nbytes
= another_pdu_follows
? another_pdu_follows
: tvb_reported_length_remaining(tvb
, deseg_offset
);
5233 proto_tree_add_bytes_format(tcp_tree
, hf_tcp_segment_data
, tvb
, deseg_offset
,
5234 nbytes
, NULL
, "TCP segment data (%u byte%s)", nbytes
,
5235 plurality(nbytes
, "", "s"));
5237 pinfo
->can_desegment
= 0;
5238 pinfo
->desegment_offset
= 0;
5239 pinfo
->desegment_len
= 0;
5241 if(another_pdu_follows
) {
5242 /* there was another pdu following this one. */
5243 pinfo
->can_desegment
= 2;
5244 /* we also have to prevent the dissector from changing the
5245 * PROTOCOL and INFO columns since what follows may be an
5246 * incomplete PDU and we don't want it be changed back from
5247 * <Protocol> to <TCP>
5249 col_set_fence(pinfo
->cinfo
, COL_INFO
);
5250 cleared_writable
|= col_get_writable(pinfo
->cinfo
, COL_PROTOCOL
);
5251 col_set_writable(pinfo
->cinfo
, COL_PROTOCOL
, false);
5253 offset
+= another_pdu_follows
;
5254 seq
+= another_pdu_follows
;
5257 /* remove any blocking set above otherwise the
5258 * proto,colinfo tap will break
5260 if(cleared_writable
) {
5261 col_set_writable(pinfo
->cinfo
, COL_PROTOCOL
, true);
5266 /* Restore the addresses and ports to whatever they were after
5267 * the last segment that successfully dissected some data, if any.
5269 restore_endpoint(pinfo
, &new_endpoint
);
5273 tcp_dissect_pdus(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
5274 bool proto_desegment
, unsigned fixed_len
,
5275 unsigned (*get_pdu_len
)(packet_info
*, tvbuff_t
*, int, void*),
5276 dissector_t dissect_pdu
, void* dissector_data
)
5278 volatile int offset
= 0;
5280 unsigned captured_length_remaining
;
5281 volatile unsigned plen
;
5284 proto_item
*item
=NULL
;
5285 const char *saved_proto
;
5286 uint8_t curr_layer_num
;
5287 wmem_list_frame_t
*frame
;
5289 tcp_endpoint_t orig_endpoint
;
5291 save_endpoint(pinfo
, &orig_endpoint
);
5293 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
5295 * We use "tvb_ensure_captured_length_remaining()" to make
5296 * sure there actually *is* data remaining. The protocol
5297 * we're handling could conceivably consists of a sequence of
5298 * fixed-length PDUs, and therefore the "get_pdu_len" routine
5299 * might not actually fetch anything from the tvbuff, and thus
5300 * might not cause an exception to be thrown if we've run past
5301 * the end of the tvbuff.
5303 * This means we're guaranteed that "captured_length_remaining" is positive.
5305 captured_length_remaining
= tvb_ensure_captured_length_remaining(tvb
, offset
);
5308 * Can we do reassembly?
5310 if (proto_desegment
&& pinfo
->can_desegment
) {
5312 * Yes - is the fixed-length part of the PDU split across segment
5315 if (captured_length_remaining
< fixed_len
) {
5317 * Yes. Tell the TCP dissector where the data for this message
5318 * starts in the data it handed us and that we need "some more
5319 * data." Don't tell it exactly how many bytes we need because
5320 * if/when we ask for even more (after the header) that will
5323 pinfo
->desegment_offset
= offset
;
5324 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
5330 * Get the length of the PDU.
5332 plen
= (*get_pdu_len
)(pinfo
, tvb
, offset
, dissector_data
);
5335 * Support protocols which have a variable length which cannot
5336 * always be determined within the given fixed_len.
5339 * If another segment was requested but we can't do reassembly,
5340 * abort and warn about the unreassembled packet.
5342 THROW_ON(!(proto_desegment
&& pinfo
->can_desegment
), FragmentBoundsError
);
5344 * Tell the TCP dissector where the data for this message
5345 * starts in the data it handed us, and that we need one
5346 * more segment, and return.
5348 pinfo
->desegment_offset
= offset
;
5349 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
5352 if (plen
< fixed_len
) {
5356 * 1) the length value extracted from the fixed-length portion
5357 * doesn't include the fixed-length portion's length, and
5358 * was so large that, when the fixed-length portion's
5359 * length was added to it, the total length overflowed;
5361 * 2) the length value extracted from the fixed-length portion
5362 * includes the fixed-length portion's length, and the value
5363 * was less than the fixed-length portion's length, i.e. it
5366 * Report this as a bounds error.
5368 show_reported_bounds_error(tvb
, pinfo
, tree
);
5372 /* give a hint to TCP where the next PDU starts
5373 * so that it can attempt to find it in case it starts
5374 * somewhere in the middle of a segment.
5376 if(!pinfo
->fd
->visited
&& tcp_analyze_seq
) {
5377 unsigned remaining_bytes
;
5378 remaining_bytes
= tvb_reported_length_remaining(tvb
, offset
);
5379 if(plen
>remaining_bytes
) {
5380 pinfo
->want_pdu_tracking
=2;
5381 pinfo
->bytes_until_next_pdu
=plen
-remaining_bytes
;
5386 * Can we do reassembly?
5388 if (proto_desegment
&& pinfo
->can_desegment
) {
5390 * Yes - is the PDU split across segment boundaries?
5392 if (captured_length_remaining
< plen
) {
5394 * Yes. Tell the TCP dissector where the data for this message
5395 * starts in the data it handed us, and how many more bytes we
5398 pinfo
->desegment_offset
= offset
;
5399 pinfo
->desegment_len
= plen
- captured_length_remaining
;
5404 curr_layer_num
= pinfo
->curr_layer_num
-1;
5405 frame
= wmem_list_frame_prev(wmem_list_tail(pinfo
->layers
));
5406 while (frame
&& (proto_tcp
!= (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame
)))) {
5407 frame
= wmem_list_frame_prev(frame
);
5411 if (captured_length_remaining
>= plen
|| there are more packets
)
5415 * Display the PDU length as a field
5417 item
=proto_tree_add_uint((proto_tree
*)p_get_proto_data(pinfo
->pool
, pinfo
, proto_tcp
, curr_layer_num
),
5419 tvb
, offset
, plen
, plen
);
5420 proto_item_set_generated(item
);
5423 item
= proto_tree_add_expert_format((proto_tree
*)p_get_proto_data(pinfo
->pool
, pinfo
, proto_tcp
, curr_layer_num
),
5425 "PDU Size: %u cut short at %u",plen
,captured_length_remaining
);
5426 proto_item_set_generated(item
);
5431 * Construct a tvbuff containing the amount of the payload we have
5432 * available. Make its reported length the amount of data in the PDU.
5434 length
= captured_length_remaining
;
5437 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, length
, plen
);
5438 if (!(proto_desegment
&& pinfo
->can_desegment
)) {
5439 if (plen
> length
) {
5440 /* If we can't do reassembly but the PDU is split across
5441 * segment boundaries, mark the tvbuff as a fragment so
5442 * we throw FragmentBoundsError instead of malformed
5445 tvb_set_fragment(next_tvb
);
5453 * If it gets an error that means there's no point in
5454 * dissecting any more PDUs, rethrow the exception in
5457 * If it gets any other error, report it and continue, as that
5458 * means that PDU got an error, but that doesn't mean we should
5459 * stop dissecting PDUs within this frame or chunk of reassembled
5462 saved_proto
= pinfo
->current_proto
;
5463 restore_endpoint(pinfo
, &orig_endpoint
);
5465 (*dissect_pdu
)(next_tvb
, pinfo
, tree
, dissector_data
);
5467 CATCH_NONFATAL_ERRORS
{
5468 show_exception(tvb
, pinfo
, tree
, EXCEPT_CODE
, GET_MESSAGE
);
5471 * Restore the saved protocol as well; we do this after
5472 * show_exception(), so that the "Malformed packet" indication
5473 * shows the protocol for which dissection failed.
5475 pinfo
->current_proto
= saved_proto
;
5480 * Step to the next PDU.
5481 * Make sure we don't overflow.
5483 offset_before
= offset
;
5485 if (offset
<= offset_before
)
5491 tcp_info_append_uint(packet_info
*pinfo
, const char *abbrev
, uint32_t val
)
5493 /* fstr(" %s=%u", abbrev, val) */
5494 col_append_str_uint(pinfo
->cinfo
, COL_INFO
, abbrev
, val
, " ");
5498 tcp_info_append_hex_uint(packet_info
*pinfo
, const char *abbrev
, uint32_t val
)
5500 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s=%X", abbrev
, val
);
5504 tcp_option_len_check(proto_item
* length_item
, packet_info
*pinfo
, unsigned len
, unsigned optlen
)
5506 if (len
!= optlen
) {
5507 /* Bogus - option length isn't what it's supposed to be for this option. */
5508 expert_add_info_format(pinfo
, length_item
, &ei_tcp_opt_len_invalid
,
5509 "option length should be %u", optlen
);
5517 dissect_tcpopt_unknown(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
5520 proto_tree
*exp_tree
;
5521 int offset
= 0, optlen
= tvb_reported_length(tvb
);
5523 item
= proto_tree_add_item(tree
, proto_tcp_option_unknown
, tvb
, offset
, -1, ENC_NA
);
5524 exp_tree
= proto_item_add_subtree(item
, ett_tcp_unknown_opt
);
5526 proto_tree_add_item(exp_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5527 proto_tree_add_item(exp_tree
, hf_tcp_option_len
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
5529 proto_tree_add_item(exp_tree
, hf_tcp_option_unknown_payload
, tvb
, offset
+ 2, optlen
- 2, ENC_NA
);
5531 return tvb_captured_length(tvb
);
5535 dissect_tcpopt_default_option(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int proto
, int ett
)
5538 proto_tree
*exp_tree
;
5539 proto_item
*length_item
;
5542 item
= proto_tree_add_item(tree
, proto
, tvb
, offset
, -1, ENC_NA
);
5543 exp_tree
= proto_item_add_subtree(item
, ett
);
5545 proto_tree_add_item(exp_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5546 length_item
= proto_tree_add_item(exp_tree
, hf_tcp_option_len
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
5548 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), 2))
5549 return tvb_captured_length(tvb
);
5551 return tvb_captured_length(tvb
);
5555 dissect_tcpopt_recbound(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
5557 return dissect_tcpopt_default_option(tvb
, pinfo
, tree
, proto_tcp_option_scpsrec
, ett_tcp_opt_recbound
);
5561 dissect_tcpopt_correxp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
5563 return dissect_tcpopt_default_option(tvb
, pinfo
, tree
, proto_tcp_option_scpscor
, ett_tcp_opt_scpscor
);
5567 dissect_tcpopt_tfo_payload(tvbuff_t
*tvb
, int offset
, unsigned optlen
,
5568 packet_info
*pinfo
, proto_tree
*exp_tree
, void *data
)
5571 struct tcpheader
*tcph
= (struct tcpheader
*)data
;
5572 struct tcp_analysis
*tcpd
;
5575 /* Fast Open Cookie Request */
5576 proto_tree_add_item(exp_tree
, hf_tcp_option_fast_open_cookie_request
,
5577 tvb
, offset
, 2, ENC_NA
);
5578 col_append_str(pinfo
->cinfo
, COL_INFO
, " TFO=R");
5579 } else if (optlen
> 2) {
5580 /* Fast Open Cookie */
5581 ti
= proto_tree_add_item(exp_tree
, hf_tcp_option_fast_open_cookie
,
5582 tvb
, offset
+ 2, optlen
- 2, ENC_NA
);
5583 col_append_str(pinfo
->cinfo
, COL_INFO
, " TFO=C");
5584 if ((tcph
->th_flags
& (TH_SYN
|TH_ACK
)) == TH_SYN
) {
5585 expert_add_info(pinfo
, ti
, &ei_tcp_analysis_tfo_syn
);
5587 /* Is this a SYN with data and the cookie? */
5588 if (tcph
->th_have_seglen
&& tcph
->th_seglen
) {
5589 tcpd
= get_tcp_conversation_data(NULL
, pinfo
);
5591 tcpd
->tfo_syn_data
= true;
5599 dissect_tcpopt_tfo(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
5602 proto_tree
*exp_tree
;
5605 item
= proto_tree_add_item(tree
, proto_tcp_option_tfo
, tvb
, offset
, -1, ENC_NA
);
5606 exp_tree
= proto_item_add_subtree(item
, ett_tcp_option_exp
);
5607 proto_tree_add_item(exp_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5608 proto_tree_add_item(exp_tree
, hf_tcp_option_len
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
5610 dissect_tcpopt_tfo_payload(tvb
, offset
, tvb_reported_length(tvb
), pinfo
, exp_tree
, data
);
5611 return tvb_captured_length(tvb
);
5615 * TCP ACK Rate Request option is based on
5616 * https://datatracker.ietf.org/doc/html/draft-gomez-tcpm-ack-rate-request-06
5619 #define TCPOPT_TARR_RATE_MASK 0xfe
5620 #define TCPOPT_TARR_RESERVED_MASK 0x01
5621 #define TCPOPT_TARR_RATE_SHIFT 1
5624 dissect_tcpopt_tarr_data(tvbuff_t
*tvb
, int data_offset
, unsigned data_len
,
5625 packet_info
*pinfo
, proto_tree
*tree
, proto_item
*item
, void *data _U_
)
5631 col_append_str(pinfo
->cinfo
, COL_INFO
, " TARR");
5634 rate
= (tvb_get_uint8(tvb
, data_offset
) & TCPOPT_TARR_RATE_MASK
) >> TCPOPT_TARR_RATE_SHIFT
;
5635 proto_tree_add_item(tree
, hf_tcp_option_tarr_rate
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
5636 proto_tree_add_item(tree
, hf_tcp_option_tarr_reserved
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
5637 tcp_info_append_uint(pinfo
, "TARR", rate
);
5638 proto_item_append_text(item
, " %u", rate
);
5644 dissect_tcpopt_acc_ecn_data(tvbuff_t
*tvb
, int data_offset
, unsigned data_len
,
5645 bool is_order_0
, packet_info
*pinfo
, proto_tree
*tree
, proto_item
*item
, void *data _U_
)
5647 struct tcp_analysis
*tcpd
;
5648 uint32_t ee0b
, eceb
, ee1b
;
5652 col_append_str(pinfo
->cinfo
, COL_INFO
, " AccECN");
5656 ee0b
= tvb_get_uint24(tvb
, data_offset
, ENC_BIG_ENDIAN
);
5657 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_ee0b
, tvb
, data_offset
, 3, ENC_BIG_ENDIAN
);
5658 proto_item_append_text(item
, " (Order 0): EE0B %u", ee0b
);
5659 tcp_info_append_uint(pinfo
, "EE0B", ee0b
);
5661 ee1b
= tvb_get_uint24(tvb
, data_offset
, ENC_BIG_ENDIAN
);
5662 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_ee1b
, tvb
, data_offset
, 3, ENC_BIG_ENDIAN
);
5663 proto_item_append_text(item
, " (Order 1): EE1B %u", ee1b
);
5664 tcp_info_append_uint(pinfo
, "EE1B", ee1b
);
5669 ee0b
= tvb_get_uint24(tvb
, data_offset
, ENC_BIG_ENDIAN
);
5670 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_ee0b
, tvb
, data_offset
, 3, ENC_BIG_ENDIAN
);
5671 tcp_info_append_uint(pinfo
, "EE0B", ee0b
);
5673 ee1b
= tvb_get_uint24(tvb
, data_offset
, ENC_BIG_ENDIAN
);
5674 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_ee1b
, tvb
, data_offset
, 3, ENC_BIG_ENDIAN
);
5675 tcp_info_append_uint(pinfo
, "EE1B", ee1b
);
5677 eceb
= tvb_get_uint24(tvb
, data_offset
+ 3, ENC_BIG_ENDIAN
);
5678 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_eceb
, tvb
, data_offset
+ 3, 3, ENC_BIG_ENDIAN
);
5679 tcp_info_append_uint(pinfo
, "ECEB", eceb
);
5681 proto_item_append_text(item
, " (Order 0): EE0B %u, ECEB %u", ee0b
, eceb
);
5683 proto_item_append_text(item
, " (Order 1): EE1B %u, ECEB %u", ee1b
, eceb
);
5688 ee0b
= tvb_get_uint24(tvb
, data_offset
, ENC_BIG_ENDIAN
);
5689 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_ee0b
, tvb
, data_offset
, 3, ENC_BIG_ENDIAN
);
5690 tcp_info_append_uint(pinfo
, "EE0B", ee0b
);
5692 ee1b
= tvb_get_uint24(tvb
, data_offset
, ENC_BIG_ENDIAN
);
5693 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_ee1b
, tvb
, data_offset
, 3, ENC_BIG_ENDIAN
);
5694 tcp_info_append_uint(pinfo
, "EE1B", ee1b
);
5696 eceb
= tvb_get_uint24(tvb
, data_offset
+ 3, ENC_BIG_ENDIAN
);
5697 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_eceb
, tvb
, data_offset
+ 3, 3, ENC_BIG_ENDIAN
);
5698 tcp_info_append_uint(pinfo
, "ECEB", eceb
);
5700 ee1b
= tvb_get_uint24(tvb
, data_offset
+ 6, ENC_BIG_ENDIAN
);
5701 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_ee1b
, tvb
, data_offset
+ 6, 3, ENC_BIG_ENDIAN
);
5702 tcp_info_append_uint(pinfo
, "EE1B", ee1b
);
5703 proto_item_append_text(item
, " (Order 0): EE0B %u, ECEB %u, EE1B %u", ee0b
, eceb
, ee1b
);
5705 ee0b
= tvb_get_uint24(tvb
, data_offset
+ 6, ENC_BIG_ENDIAN
);
5706 proto_tree_add_item(tree
, hf_tcp_option_acc_ecn_ee0b
, tvb
, data_offset
+ 6, 3, ENC_BIG_ENDIAN
);
5707 tcp_info_append_uint(pinfo
, "EE0B", ee0b
);
5708 proto_item_append_text(item
, " (Order 1): EE1B %u, ECEB %u, EE0B %u", ee1b
, eceb
, ee0b
);
5712 tcpd
= get_tcp_conversation_data(NULL
, pinfo
);
5714 tcpd
->had_acc_ecn_option
= true;
5719 dissect_tcpopt_acc_ecn(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
5721 proto_item
*length_item
, *item
;
5722 proto_tree
*acc_ecn_tree
;
5724 uint8_t kind
, length
;
5727 item
= proto_tree_add_item(tree
, proto_tcp_option_acc_ecn
, tvb
, offset
, -1, ENC_NA
);
5728 acc_ecn_tree
= proto_item_add_subtree(item
, ett_tcp_option_acc_ecn
);
5729 kind
= tvb_get_uint8(tvb
, offset
);
5730 proto_tree_add_item(acc_ecn_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5732 length
= tvb_get_uint8(tvb
, offset
);
5733 length_item
= proto_tree_add_item(acc_ecn_tree
, hf_tcp_option_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5735 if (length
!= 2 && length
!= 5 && length
!= 8 && length
!= 11) {
5736 expert_add_info_format(pinfo
, length_item
, &ei_tcp_opt_len_invalid
,
5737 "option length should be 2, 5, 8, or 11 instead of %u", length
);
5739 dissect_tcpopt_acc_ecn_data(tvb
, offset
, length
- 2, kind
== TCPOPT_ACC_ECN_0
, pinfo
, acc_ecn_tree
, item
, data
);
5741 return tvb_captured_length(tvb
);
5745 dissect_tcpopt_exp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
5747 proto_item
*item
, *length_item
;
5748 proto_tree
*exp_tree
;
5751 int offset
= 0, optlen
= tvb_reported_length(tvb
);
5753 item
= proto_tree_add_item(tree
, proto_tcp_option_exp
, tvb
, offset
, -1, ENC_NA
);
5754 exp_tree
= proto_item_add_subtree(item
, ett_tcp_option_exp
);
5755 proto_tree_add_item(exp_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5756 kind
= tvb_get_uint8(tvb
, offset
);
5757 length_item
= proto_tree_add_item(exp_tree
, hf_tcp_option_len
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
5758 if (tcp_exp_options_rfc6994
) {
5759 if (optlen
>= TCPOLEN_EXP_MIN
) {
5760 exid
= tvb_get_ntohs(tvb
, offset
+ 2);
5761 proto_tree_add_item(exp_tree
, hf_tcp_option_exp_exid
, tvb
,
5762 offset
+ 2, 2, ENC_BIG_ENDIAN
);
5763 proto_item_append_text(item
, ": %s", val_to_str_const(exid
, tcp_exid_vs
, "Unknown"));
5766 if (optlen
!= 4 && optlen
!= 5) {
5767 expert_add_info_format(pinfo
, length_item
, &ei_tcp_opt_len_invalid
,
5768 "option length should be 4 or 5 instead of %d",
5771 dissect_tcpopt_tarr_data(tvb
, offset
+ 4, optlen
- 4,
5772 pinfo
, exp_tree
, item
, data
);
5775 case 0xACC0: /* draft-ietf-tcpm-accurate-ecn-20 */
5777 if (optlen
!= 4 && optlen
!= 7 && optlen
!= 10 && optlen
!= 13) {
5778 expert_add_info_format(pinfo
, length_item
, &ei_tcp_opt_len_invalid
,
5779 "option length should be 4, 7, 10, or 13 instead of %d",
5782 proto_item_append_text(item
, ": Accurate ECN");
5783 dissect_tcpopt_acc_ecn_data(tvb
, offset
+ 4, optlen
- 4,
5784 exid
== 0xACC0, pinfo
, exp_tree
,
5789 dissect_tcpopt_tfo_payload(tvb
, offset
+ 2, optlen
- 2, pinfo
, exp_tree
, data
);
5792 if (optlen
> TCPOLEN_EXP_MIN
) {
5793 proto_tree_add_item(exp_tree
, hf_tcp_option_exp_data
, tvb
,
5794 offset
+ TCPOLEN_EXP_MIN
,
5795 optlen
- TCPOLEN_EXP_MIN
, ENC_NA
);
5797 tcp_info_append_hex_uint(pinfo
, "ExID", exid
);
5801 expert_add_info_format(pinfo
, length_item
, &ei_tcp_opt_len_invalid
,
5802 "option length %u smaller than 4", optlen
);
5805 proto_tree_add_item(exp_tree
, hf_tcp_option_exp_data
, tvb
,
5806 offset
+ 2, optlen
- 2, ENC_NA
);
5807 tcp_info_append_uint(pinfo
, "Exp", (kind
== TCPOPT_EXP_FD
) ? 1 : 2);
5809 return tvb_captured_length(tvb
);
5813 dissect_tcpopt_sack_perm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
5816 proto_tree
*exp_tree
;
5817 proto_item
*length_item
;
5819 struct tcpheader
*tcph
= (struct tcpheader
*)data
;
5821 item
= proto_tree_add_item(tree
, proto_tcp_option_sack_perm
, tvb
, offset
, -1, ENC_NA
);
5822 exp_tree
= proto_item_add_subtree(item
, ett_tcp_option_sack_perm
);
5824 if (!(tcph
->th_flags
& TH_SYN
))
5826 expert_add_info(pinfo
, item
, &ei_tcp_option_sack_perm_present
);
5829 proto_tree_add_item(exp_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5830 length_item
= proto_tree_add_item(exp_tree
, hf_tcp_option_len
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
5832 col_append_str(pinfo
->cinfo
, COL_INFO
, " SACK_PERM");
5834 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), TCPOLEN_SACK_PERM
))
5835 return tvb_captured_length(tvb
);
5837 return tvb_captured_length(tvb
);
5841 dissect_tcpopt_mss(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
5844 proto_tree
*exp_tree
;
5845 proto_item
*length_item
;
5847 struct tcpheader
*tcph
= (struct tcpheader
*)data
;
5850 item
= proto_tree_add_item(tree
, proto_tcp_option_mss
, tvb
, offset
, -1, ENC_NA
);
5851 exp_tree
= proto_item_add_subtree(item
, ett_tcp_option_mss
);
5853 if (!(tcph
->th_flags
& TH_SYN
))
5855 expert_add_info(pinfo
, item
, &ei_tcp_option_mss_present
);
5858 proto_tree_add_item(exp_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5859 length_item
= proto_tree_add_item(exp_tree
, hf_tcp_option_len
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
5861 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), TCPOLEN_MSS
))
5862 return tvb_captured_length(tvb
);
5864 proto_tree_add_item_ret_uint(exp_tree
, hf_tcp_option_mss_val
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
, &mss
);
5865 proto_item_append_text(item
, ": %u bytes", mss
);
5866 tcp_info_append_uint(pinfo
, "MSS", mss
);
5868 return tvb_captured_length(tvb
);
5871 /* The window scale extension is defined in RFC 1323 */
5873 dissect_tcpopt_wscale(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
5877 proto_item
*wscale_pi
, *shift_pi
, *gen_pi
;
5878 proto_tree
*wscale_tree
;
5879 proto_item
*length_item
;
5881 struct tcp_analysis
*tcpd
;
5883 /* find the conversation for this TCP session and its stored data */
5884 conversation_t
*stratconv
= find_conversation_strat(pinfo
, CONVERSATION_TCP
, 0);
5885 tcpd
=get_tcp_conversation_data_idempotent(stratconv
);
5887 wscale_pi
= proto_tree_add_item(tree
, proto_tcp_option_wscale
, tvb
, offset
, -1, ENC_NA
);
5888 wscale_tree
= proto_item_add_subtree(wscale_pi
, ett_tcp_option_wscale
);
5890 proto_tree_add_item(wscale_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5893 length_item
= proto_tree_add_item(wscale_tree
, hf_tcp_option_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
5896 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), TCPOLEN_WINDOW
))
5897 return tvb_captured_length(tvb
);
5899 shift_pi
= proto_tree_add_item_ret_uint(wscale_tree
, hf_tcp_option_wscale_shift
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &shift
);
5901 /* RFC 1323: "If a Window Scale option is received with a shift.cnt
5902 * value exceeding 14, the TCP should log the error but use 14 instead
5903 * of the specified value." */
5905 expert_add_info(pinfo
, shift_pi
, &ei_tcp_option_wscale_shift_invalid
);
5908 gen_pi
= proto_tree_add_uint(wscale_tree
, hf_tcp_option_wscale_multiplier
, tvb
,
5909 offset
, 1, 1 << shift
);
5910 proto_item_set_generated(gen_pi
);
5911 val
= tvb_get_uint8(tvb
, offset
);
5913 proto_item_append_text(wscale_pi
, ": %u (multiply by %u)", val
, 1 << shift
);
5915 tcp_info_append_uint(pinfo
, "WS", 1 << shift
);
5917 if(!pinfo
->fd
->visited
) {
5918 pdu_store_window_scale_option(shift
, tcpd
);
5921 return tvb_captured_length(tvb
);
5925 dissect_tcpopt_sack(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
5927 proto_tree
*field_tree
= NULL
;
5928 proto_item
*tf
, *ti
;
5929 uint32_t leftedge
, rightedge
;
5930 struct tcp_analysis
*tcpd
=NULL
;
5931 struct tcpheader
*tcph
= (struct tcpheader
*)data
;
5932 uint32_t base_ack
=0;
5933 unsigned num_sack_ranges
= 0;
5936 int optlen
= tvb_reported_length(tvb
);
5939 * SEQ analysis is the condition for both relative analysis obviously,
5940 * and SACK handling for the in-flight update
5942 if(tcp_analyze_seq
) {
5943 /* find the conversation for this TCP session and its stored data */
5944 conversation_t
*stratconv
= find_conversation_strat(pinfo
, CONVERSATION_TCP
, 0);
5945 tcpd
=get_tcp_conversation_data_idempotent(stratconv
);
5948 if (tcp_relative_seq
) {
5949 base_ack
=tcpd
->rev
->base_seq
;
5953 * initialize the number of SACK blocks to 0, it will be
5954 * updated some lines later
5956 if (tcp_track_bytes_in_flight
&& tcpd
->fwd
->tcp_analyze_seq_info
) {
5957 tcpd
->fwd
->tcp_analyze_seq_info
->num_sack_ranges
= 0;
5962 /* Late discovery of a 'false' Window Update in presence of SACK option,
5963 * which means we are dealing with a Dup ACK rather than a Window Update.
5964 * Classify accordingly by removing the UPDATE and adding the DUP flags.
5965 * Mostly a copy/paste from tcp_analyze_sequence_number(), ensure consistency
5966 * whenever the latter changes.
5969 if( tcp_analyze_seq
&& tcpd
&& tcpd
->ta
&& tcpd
->ta
->flags
&TCP_A_WINDOW_UPDATE
) {
5971 /* MPTCP tolerates duplicate acks in some circumstances, see RFC 8684 4. */
5972 if(tcpd
->mptcp_analysis
&& (tcpd
->mptcp_analysis
->mp_operations
!=tcpd
->fwd
->mp_operations
)) {
5973 /* just ignore this DUPLICATE ACK */
5975 /* no initialization required of the tcpd->ta as this code would
5976 * be unreachable otherwise
5978 tcpd
->ta
->flags
&= ~TCP_A_WINDOW_UPDATE
;
5979 tcpd
->ta
->flags
|= TCP_A_DUPLICATE_ACK
;
5981 if (tcpd
->fwd
->tcp_analyze_seq_info
) {
5982 tcpd
->fwd
->tcp_analyze_seq_info
->dupacknum
++;
5984 tcpd
->ta
->dupack_num
=tcpd
->fwd
->tcp_analyze_seq_info
->dupacknum
;
5985 tcpd
->ta
->dupack_frame
=tcpd
->fwd
->tcp_analyze_seq_info
->lastnondupack
;
5990 ti
= proto_tree_add_item(tree
, proto_tcp_option_sack
, tvb
, offset
, -1, ENC_NA
);
5991 field_tree
= proto_item_add_subtree(ti
, ett_tcp_option_sack
);
5993 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
5994 offset
, 1, ENC_BIG_ENDIAN
);
5995 proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
5996 offset
+ 1, 1, ENC_BIG_ENDIAN
);
5998 offset
+= 2; /* skip past type and length */
5999 optlen
-= 2; /* subtract size of type and length */
6001 sackoffset
= offset
;
6002 while (optlen
> 0) {
6004 proto_tree_add_expert(field_tree
, pinfo
, &ei_tcp_suboption_malformed
, tvb
, offset
, optlen
);
6007 leftedge
= tvb_get_ntohl(tvb
, offset
)-base_ack
;
6008 proto_tree_add_uint_format(field_tree
, hf_tcp_option_sack_sle
, tvb
,
6009 offset
, 4, leftedge
,
6010 "left edge = %u%s", leftedge
,
6011 (tcp_analyze_seq
&& tcp_relative_seq
) ? " (relative)" : "");
6014 proto_tree_add_expert(field_tree
, pinfo
, &ei_tcp_suboption_malformed
, tvb
, offset
, optlen
);
6017 /* XXX - check whether it goes past end of packet */
6018 rightedge
= tvb_get_ntohl(tvb
, offset
+ 4)-base_ack
;
6020 proto_tree_add_uint_format(field_tree
, hf_tcp_option_sack_sre
, tvb
,
6021 offset
+4, 4, rightedge
,
6022 "right edge = %u%s", rightedge
,
6023 (tcp_analyze_seq
&& tcp_relative_seq
) ? " (relative)" : "");
6024 tcp_info_append_uint(pinfo
, "SLE", leftedge
);
6025 tcp_info_append_uint(pinfo
, "SRE", rightedge
);
6027 /* Store blocks for BiF analysis */
6028 if (tcp_analyze_seq
&& tcpd
&& tcpd
->fwd
->tcp_analyze_seq_info
&& tcp_track_bytes_in_flight
&& num_sack_ranges
< MAX_TCP_SACK_RANGES
) {
6029 tcpd
->fwd
->tcp_analyze_seq_info
->sack_left_edge
[num_sack_ranges
] = leftedge
;
6030 tcpd
->fwd
->tcp_analyze_seq_info
->sack_right_edge
[num_sack_ranges
++] = rightedge
;
6031 tcpd
->fwd
->tcp_analyze_seq_info
->num_sack_ranges
= num_sack_ranges
;
6034 /* Update tap info */
6035 if (tcph
!= NULL
&& (tcph
->num_sack_ranges
< MAX_TCP_SACK_RANGES
)) {
6036 tcph
->sack_left_edge
[tcph
->num_sack_ranges
] = leftedge
;
6037 tcph
->sack_right_edge
[tcph
->num_sack_ranges
] = rightedge
;
6038 tcph
->num_sack_ranges
++;
6041 proto_item_append_text(field_tree
, " %u-%u", leftedge
, rightedge
);
6046 /* Show number of SACK ranges in this option as a generated field */
6047 tf
= proto_tree_add_uint(field_tree
, hf_tcp_option_sack_range_count
,
6048 tvb
, 0, 0, num_sack_ranges
);
6049 proto_item_set_generated(tf
);
6051 /* RFC 2883 "An Extension to the Selective Acknowledgement (SACK) Option for TCP" aka "D-SACK"
6053 * Conditions: Either the first sack-block is inside the already acknowledged range or
6054 * the first sack block is inside the second sack block.
6057 * (1) A D-SACK block is only used to report a duplicate contiguous sequence of data received by
6058 * the receiver in the most recent packet.
6060 if (tcph
!= NULL
&& (
6061 LE_SEQ(tcph
->sack_right_edge
[0], tcph
->th_ack
) ||
6062 (tcph
->num_sack_ranges
> 1 &&
6063 LT_SEQ(tcph
->sack_left_edge
[1], tcph
->sack_right_edge
[0]) &&
6064 GE_SEQ(tcph
->sack_right_edge
[1], tcph
->sack_right_edge
[0]))
6066 leftedge
= tvb_get_ntohl(tvb
, sackoffset
)-base_ack
;
6067 tf
= proto_tree_add_uint_format(field_tree
, hf_tcp_option_sack_dsack_le
, tvb
, sackoffset
, 4, leftedge
,
6068 "D-SACK Left Edge = %u%s", leftedge
, (tcp_analyze_seq
&& tcp_relative_seq
) ? " (relative)" : "");
6069 proto_item_set_generated(tf
);
6070 rightedge
= tvb_get_ntohl(tvb
, sackoffset
+4)-base_ack
;
6071 tf
= proto_tree_add_uint_format(field_tree
, hf_tcp_option_sack_dsack_re
, tvb
, sackoffset
+4, 4, rightedge
,
6072 "D-SACK Right Edge = %u%s", rightedge
, (tcp_analyze_seq
&& tcp_relative_seq
) ? " (relative)" : "");
6073 proto_item_set_generated(tf
);
6074 proto_tree_add_expert(field_tree
, pinfo
, &ei_tcp_option_sack_dsack
, tvb
, sackoffset
, 8);
6077 return tvb_captured_length(tvb
);
6081 dissect_tcpopt_echo(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
6083 proto_tree
*field_tree
;
6085 proto_item
*length_item
;
6089 item
= proto_tree_add_item(tree
, proto_tcp_option_echo
, tvb
, offset
, -1, ENC_NA
);
6090 field_tree
= proto_item_add_subtree(item
, ett_tcp_opt_echo
);
6092 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
6093 offset
, 1, ENC_BIG_ENDIAN
);
6094 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
6095 offset
+ 1, 1, ENC_BIG_ENDIAN
);
6097 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), TCPOLEN_ECHO
))
6098 return tvb_captured_length(tvb
);
6100 proto_tree_add_item_ret_uint(field_tree
, hf_tcp_option_echo
, tvb
,
6101 offset
+ 2, 4, ENC_BIG_ENDIAN
, &echo
);
6103 proto_item_append_text(item
, ": %u", echo
);
6104 tcp_info_append_uint(pinfo
, "ECHO", echo
);
6106 return tvb_captured_length(tvb
);
6109 /* If set, do not put the TCP timestamp information on the summary line */
6110 static bool tcp_ignore_timestamps
;
6113 dissect_tcpopt_timestamp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
6115 proto_item
*ti
, *tsval_ti
;
6116 proto_tree
*ts_tree
;
6117 proto_item
*length_item
;
6119 uint32_t ts_val
, ts_ecr
;
6120 int len
= tvb_reported_length(tvb
);
6122 ti
= proto_tree_add_item(tree
, proto_tcp_option_timestamp
, tvb
, offset
, -1, ENC_NA
);
6123 ts_tree
= proto_item_add_subtree(ti
, ett_tcp_option_timestamp
);
6125 proto_tree_add_item(ts_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
6128 length_item
= proto_tree_add_item(ts_tree
, hf_tcp_option_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
6131 if (!tcp_option_len_check(length_item
, pinfo
, len
, TCPOLEN_TIMESTAMP
))
6132 return tvb_captured_length(tvb
);
6134 tsval_ti
= proto_tree_add_item_ret_uint(ts_tree
, hf_tcp_option_timestamp_tsval
, tvb
, offset
,
6135 4, ENC_BIG_ENDIAN
, &ts_val
);
6137 proto_tree_add_item_ret_uint(ts_tree
, hf_tcp_option_timestamp_tsecr
, tvb
, offset
+ 4,
6138 4, ENC_BIG_ENDIAN
, &ts_ecr
);
6140 proto_item_append_text(ti
, ": TSval %u, TSecr %u", ts_val
, ts_ecr
);
6141 if (tcp_ignore_timestamps
== false) {
6142 tcp_info_append_uint(pinfo
, "TSval", ts_val
);
6143 tcp_info_append_uint(pinfo
, "TSecr", ts_ecr
);
6146 if (read_seq_as_syn_cookie
) {
6147 proto_item_append_text(ti
, " (syn cookie)");
6148 proto_item
* syncookie_ti
= proto_item_add_subtree(tsval_ti
, ett_tcp_syncookie_option
);
6149 uint32_t timestamp
= tvb_get_bits32(tvb
, offset
* 8, 26, ENC_NA
) << 6;
6150 proto_tree_add_uint_bits_format_value(syncookie_ti
, hf_tcp_syncookie_option_timestamp
, tvb
, offset
* 8,
6151 26, timestamp
, ENC_TIME_SECS
, "%s", abs_time_secs_to_str(pinfo
->pool
, timestamp
, ABSOLUTE_TIME_LOCAL
, true));
6152 proto_tree_add_bits_item(syncookie_ti
, hf_tcp_syncookie_option_ecn
, tvb
, offset
* 8 + 26, 1, ENC_NA
);
6153 proto_tree_add_bits_item(syncookie_ti
, hf_tcp_syncookie_option_sack
, tvb
, offset
* 8 + 27, 1, ENC_NA
);
6154 proto_tree_add_bits_item(syncookie_ti
, hf_tcp_syncookie_option_wscale
, tvb
, offset
* 8 + 28, 4, ENC_NA
);
6157 return tvb_captured_length(tvb
);
6160 static struct mptcp_analysis
*
6161 mptcp_alloc_analysis(struct tcp_analysis
* tcpd
) {
6163 struct mptcp_analysis
* mptcpd
;
6165 DISSECTOR_ASSERT(tcpd
->mptcp_analysis
== 0);
6167 mptcpd
= (struct mptcp_analysis
*)wmem_new0(wmem_file_scope(), struct mptcp_analysis
);
6168 mptcpd
->subflows
= wmem_list_new(wmem_file_scope());
6170 mptcpd
->stream
= mptcp_stream_count
++;
6171 tcpd
->mptcp_analysis
= mptcpd
;
6173 memset(&mptcpd
->meta_flow
, 0, 2*sizeof(mptcp_meta_flow_t
));
6175 /* arbitrary assignment. Callers may override this */
6176 tcpd
->fwd
->mptcp_subflow
->meta
= &mptcpd
->meta_flow
[0];
6177 tcpd
->rev
->mptcp_subflow
->meta
= &mptcpd
->meta_flow
[1];
6183 /* will create necessary structure if fails to find a match on the token */
6184 static struct mptcp_analysis
*
6185 mptcp_get_meta_from_token(struct tcp_analysis
* tcpd
, tcp_flow_t
*tcp_flow
, uint32_t token
) {
6187 struct mptcp_analysis
* result
= NULL
;
6188 struct mptcp_analysis
* mptcpd
= tcpd
->mptcp_analysis
;
6189 uint8_t assignedMetaId
= 0; /* array id < 2 */
6191 DISSECTOR_ASSERT(tcp_flow
== tcpd
->fwd
|| tcp_flow
== tcpd
->rev
);
6195 /* if token already set for this meta */
6196 if( tcp_flow
->mptcp_subflow
->meta
&& (tcp_flow
->mptcp_subflow
->meta
->static_flags
& MPTCP_META_HAS_TOKEN
)) {
6200 /* else look for a registered meta with this token */
6201 result
= (struct mptcp_analysis
*)wmem_tree_lookup32(mptcp_tokens
, token
);
6203 /* if token already registered than just share it across TCP connections */
6206 mptcp_attach_subflow(mptcpd
, tcpd
);
6209 /* we create it if this connection */
6211 /* don't care which meta to choose assign each meta to a direction */
6212 mptcpd
= mptcp_alloc_analysis(tcpd
);
6213 mptcp_attach_subflow(mptcpd
, tcpd
);
6217 /* already exists, thus some meta may already have been configured */
6218 if(mptcpd
->meta_flow
[0].static_flags
& MPTCP_META_HAS_TOKEN
) {
6221 else if(mptcpd
->meta_flow
[1].static_flags
& MPTCP_META_HAS_TOKEN
) {
6225 DISSECTOR_ASSERT_NOT_REACHED();
6227 tcp_flow
->mptcp_subflow
->meta
= &mptcpd
->meta_flow
[assignedMetaId
];
6229 DISSECTOR_ASSERT(tcp_flow
->mptcp_subflow
->meta
);
6231 tcp_flow
->mptcp_subflow
->meta
->token
= token
;
6232 tcp_flow
->mptcp_subflow
->meta
->static_flags
|= MPTCP_META_HAS_TOKEN
;
6234 wmem_tree_insert32(mptcp_tokens
, token
, mptcpd
);
6237 DISSECTOR_ASSERT(mptcpd
);
6240 /* compute the meta id assigned to tcp_flow */
6241 assignedMetaId
= (tcp_flow
->mptcp_subflow
->meta
== &mptcpd
->meta_flow
[0]) ? 0 : 1;
6243 /* computes the metaId tcpd->fwd should be assigned to */
6244 assignedMetaId
= (tcp_flow
== tcpd
->fwd
) ? assignedMetaId
: (assignedMetaId
+1) %2;
6246 tcpd
->fwd
->mptcp_subflow
->meta
= &mptcpd
->meta_flow
[ (assignedMetaId
) ];
6247 tcpd
->rev
->mptcp_subflow
->meta
= &mptcpd
->meta_flow
[ (assignedMetaId
+1) %2];
6252 /* setup from_key */
6254 struct mptcp_analysis
*
6255 get_or_create_mptcpd_from_key(struct tcp_analysis
* tcpd
, tcp_flow_t
*fwd
, uint8_t version
, uint64_t key
, uint8_t hmac_algo _U_
) {
6258 uint64_t expected_idsn
= 0;
6259 struct mptcp_analysis
* mptcpd
= tcpd
->mptcp_analysis
;
6261 if(fwd
->mptcp_subflow
->meta
&& (fwd
->mptcp_subflow
->meta
->static_flags
& MPTCP_META_HAS_KEY
)) {
6265 /* MPTCP v0 only standardizes SHA1, and v1 SHA256. */
6267 mptcp_cryptodata_sha1(key
, &token
, &expected_idsn
);
6268 else if (version
== 1)
6269 mptcp_cryptodata_sha256(key
, &token
, &expected_idsn
);
6271 mptcpd
= mptcp_get_meta_from_token(tcpd
, fwd
, token
);
6273 DISSECTOR_ASSERT(fwd
->mptcp_subflow
->meta
);
6275 fwd
->mptcp_subflow
->meta
->version
= version
;
6276 fwd
->mptcp_subflow
->meta
->key
= key
;
6277 fwd
->mptcp_subflow
->meta
->static_flags
|= MPTCP_META_HAS_KEY
;
6278 fwd
->mptcp_subflow
->meta
->base_dsn
= expected_idsn
;
6282 /* record this mapping */
6284 void analyze_mapping(struct tcp_analysis
*tcpd
, packet_info
*pinfo
, uint16_t len
, uint64_t dsn
, bool extended
, uint32_t ssn
) {
6286 /* store mapping only if analysis is enabled and mapping is not unlimited */
6287 if (!mptcp_analyze_mappings
|| !len
) {
6291 if (PINFO_FD_VISITED(pinfo
)) {
6295 /* register SSN range described by the mapping into a subflow interval_tree */
6296 mptcp_dss_mapping_t
*mapping
= NULL
;
6297 mapping
= wmem_new0(wmem_file_scope(), mptcp_dss_mapping_t
);
6299 mapping
->rawdsn
= dsn
;
6300 mapping
->extended_dsn
= extended
;
6301 mapping
->frame
= pinfo
->fd
->num
;
6302 mapping
->ssn_low
= ssn
;
6303 mapping
->ssn_high
= ssn
+ len
- 1;
6305 wmem_itree_insert(tcpd
->fwd
->mptcp_subflow
->ssn2dsn_mappings
,
6313 * The TCP Extensions for Multipath Operation with Multiple Addresses
6314 * are defined in RFC 6824
6316 * https://tools.ietf.org/html/rfc6824
6318 * Author: Andrei Maruseac <andrei.maruseac@intel.com>
6319 * Matthieu Coudron <matthieu.coudron@lip6.fr>
6321 * This function just generates the mptcpheader, i.e. the generation of
6322 * datastructures is delayed/delegated to mptcp_analyze
6325 dissect_tcpopt_mptcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
6327 proto_item
*item
,*main_item
;
6328 proto_tree
*mptcp_tree
;
6334 int optlen
= tvb_reported_length(tvb
);
6335 int start_offset
= offset
;
6336 struct tcp_analysis
*tcpd
= NULL
;
6337 struct mptcp_analysis
* mptcpd
= NULL
;
6338 struct tcpheader
*tcph
= (struct tcpheader
*)data
;
6340 /* There may be several MPTCP options per packet, don't duplicate the structure */
6341 struct mptcpheader
* mph
= tcph
->th_mptcp
;
6344 mph
= wmem_new0(pinfo
->pool
, struct mptcpheader
);
6345 tcph
->th_mptcp
= mph
;
6348 tcpd
=get_tcp_conversation_data(NULL
,pinfo
);
6349 mptcpd
=tcpd
->mptcp_analysis
;
6351 /* seeing an MPTCP packet on the subflow automatically qualifies it as an mptcp subflow */
6352 if(!tcpd
->fwd
->mptcp_subflow
) {
6353 mptcp_init_subflow(tcpd
->fwd
);
6355 if(!tcpd
->rev
->mptcp_subflow
) {
6356 mptcp_init_subflow(tcpd
->rev
);
6359 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MPTCP");
6360 main_item
= proto_tree_add_item(tree
, proto_mptcp
, tvb
, offset
, -1, ENC_NA
);
6361 mptcp_tree
= proto_item_add_subtree(main_item
, ett_tcp_option_mptcp
);
6363 proto_tree_add_item(mptcp_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
6366 proto_tree_add_item(mptcp_tree
, hf_tcp_option_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
6369 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_subtype
, tvb
,
6370 offset
, 1, ENC_BIG_ENDIAN
);
6372 subtype
= tvb_get_uint8(tvb
, offset
) >> 4;
6373 proto_item_append_text(main_item
, ": %s", val_to_str(subtype
, mptcp_subtype_vs
, "Unknown (%d)"));
6375 /** preemptively allocate mptcpd when subtype won't allow to find a meta */
6376 if(!mptcpd
&& (subtype
> TCPOPT_MPTCP_MP_JOIN
)) {
6377 mptcpd
= mptcp_alloc_analysis(tcpd
);
6381 case TCPOPT_MPTCP_MP_CAPABLE
:
6384 proto_tree_add_item_ret_uint(mptcp_tree
, hf_tcp_option_mptcp_version
, tvb
,
6385 offset
, 1, ENC_BIG_ENDIAN
, &version
);
6388 item
= proto_tree_add_bitmask(mptcp_tree
, tvb
, offset
, hf_tcp_option_mptcp_flags
,
6389 ett_tcp_option_mptcp
,
6390 version
== 1 ? tcp_option_mptcp_capable_v1_flags
: tcp_option_mptcp_capable_v0_flags
,
6392 mph
->mh_capable_flags
= tvb_get_uint8(tvb
, offset
);
6393 if ((mph
->mh_capable_flags
& MPTCP_CAPABLE_CRYPTO_MASK
) == 0) {
6394 expert_add_info(pinfo
, item
, &ei_mptcp_analysis_missing_algorithm
);
6396 if ((mph
->mh_capable_flags
& MPTCP_CAPABLE_CRYPTO_MASK
) != MPTCP_HMAC_SHA
) {
6397 expert_add_info(pinfo
, item
, &ei_mptcp_analysis_unsupported_algorithm
);
6401 /* optlen == 12 => SYN or SYN/ACK; optlen == 20 => ACK;
6402 * optlen == 22 => ACK + data (v1 only);
6403 * optlen == 24 => ACK + data + csum (v1 only)
6405 if (optlen
== 12 || optlen
== 20 || optlen
== 22 || optlen
== 24) {
6407 mph
->mh_key
= tvb_get_ntoh64(tvb
,offset
);
6408 proto_tree_add_uint64(mptcp_tree
, hf_tcp_option_mptcp_sender_key
, tvb
, offset
, 8, mph
->mh_key
);
6411 mptcpd
= get_or_create_mptcpd_from_key(tcpd
, tcpd
->fwd
, version
, mph
->mh_key
, mph
->mh_capable_flags
& MPTCP_CAPABLE_CRYPTO_MASK
);
6412 mptcpd
->master
= tcpd
;
6414 item
= proto_tree_add_uint(mptcp_tree
,
6415 hf_mptcp_expected_token
, tvb
, offset
, 0, tcpd
->fwd
->mptcp_subflow
->meta
->token
);
6416 proto_item_set_generated(item
);
6418 item
= proto_tree_add_uint64(mptcp_tree
,
6419 hf_mptcp_expected_idsn
, tvb
, offset
, 0, tcpd
->fwd
->mptcp_subflow
->meta
->base_dsn
);
6420 proto_item_set_generated(item
);
6422 /* last ACK of 3WHS, repeats both keys */
6424 uint64_t recv_key
= tvb_get_ntoh64(tvb
,offset
);
6425 proto_tree_add_uint64(mptcp_tree
, hf_tcp_option_mptcp_recv_key
, tvb
, offset
, 8, recv_key
);
6428 if(tcpd
->rev
->mptcp_subflow
->meta
6429 && (tcpd
->rev
->mptcp_subflow
->meta
->static_flags
& MPTCP_META_HAS_KEY
)) {
6431 /* compare the echoed key with the server key */
6432 if(tcpd
->rev
->mptcp_subflow
->meta
->key
!= recv_key
) {
6433 expert_add_info(pinfo
, item
, &ei_mptcp_analysis_echoed_key_mismatch
);
6437 mptcpd
= get_or_create_mptcpd_from_key(tcpd
, tcpd
->rev
, version
, recv_key
, mph
->mh_capable_flags
& MPTCP_CAPABLE_CRYPTO_MASK
);
6441 /* MPTCP v1 ACK + data, contains data_len and optional checksum */
6443 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_data_lvl_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
6444 mph
->mh_dss_length
= tvb_get_ntohs(tvb
,offset
);
6447 if (mph
->mh_dss_length
== 0) {
6448 expert_add_info(pinfo
, mptcp_tree
, &ei_mptcp_infinite_mapping
);
6451 /* when data len is present, this MP_CAPABLE also carries an implicit mapping ... */
6452 analyze_mapping(tcpd
, pinfo
, mph
->mh_dss_length
, tcpd
->fwd
->mptcp_subflow
->meta
->base_dsn
+ 1, true, tcph
->th_seq
);
6454 /* ... with optional checksum */
6457 proto_tree_add_checksum(mptcp_tree
, tvb
, offset
, hf_tcp_option_mptcp_checksum
, -1, NULL
, pinfo
, 0, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
6463 case TCPOPT_MPTCP_MP_JOIN
:
6464 mph
->mh_join
= true;
6465 if(optlen
!= 12 && !mptcpd
) {
6466 mptcpd
= mptcp_alloc_analysis(tcpd
);
6472 proto_tree_add_bitmask(mptcp_tree
, tvb
, offset
, hf_tcp_option_mptcp_flags
,
6473 ett_tcp_option_mptcp
, tcp_option_mptcp_join_flags
,
6476 tcpd
->fwd
->mptcp_subflow
->address_id
= tvb_get_uint8(tvb
, offset
);
6477 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_address_id
, tvb
, offset
,
6481 proto_tree_add_item_ret_uint(mptcp_tree
, hf_tcp_option_mptcp_recv_token
, tvb
, offset
,
6482 4, ENC_BIG_ENDIAN
, &mph
->mh_token
);
6485 mptcpd
= mptcp_get_meta_from_token(tcpd
, tcpd
->rev
, mph
->mh_token
);
6486 if (tcpd
->fwd
->mptcp_subflow
->meta
->version
== 1) {
6487 mptcp_meta_flow_t
*tmp
= tcpd
->fwd
->mptcp_subflow
->meta
;
6489 /* if the negotiated version is v1 the first key was exchanged on SYN/ACK packet: we must swap the meta */
6490 tcpd
->fwd
->mptcp_subflow
->meta
= tcpd
->rev
->mptcp_subflow
->meta
;
6491 tcpd
->rev
->mptcp_subflow
->meta
= tmp
;
6494 proto_tree_add_item_ret_uint(mptcp_tree
, hf_tcp_option_mptcp_sender_rand
, tvb
, offset
,
6495 4, ENC_BIG_ENDIAN
, &tcpd
->fwd
->mptcp_subflow
->nonce
);
6501 case 16: /* Syn/Ack */
6502 proto_tree_add_bitmask(mptcp_tree
, tvb
, offset
, hf_tcp_option_mptcp_flags
,
6503 ett_tcp_option_mptcp
, tcp_option_mptcp_join_flags
,
6507 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_address_id
, tvb
, offset
,
6511 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_sender_trunc_hmac
, tvb
, offset
,
6515 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_sender_rand
, tvb
, offset
,
6520 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_reserved
, tvb
, offset
,
6524 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_sender_hmac
, tvb
, offset
,
6533 /* display only *raw* values since it is harder to guess a correct value than for TCP.
6534 One needs to enable mptcp_analysis to get more interesting data
6536 case TCPOPT_MPTCP_DSS
:
6540 mph
->mh_dss_flags
= tvb_get_uint8(tvb
, offset
) & 0x1F;
6542 proto_tree_add_bitmask(mptcp_tree
, tvb
, offset
, hf_tcp_option_mptcp_flags
,
6543 ett_tcp_option_mptcp
, tcp_option_mptcp_dss_flags
,
6547 /* displays "raw" DataAck , ie does not convert it to its 64 bits form
6548 to do so you need to enable
6550 if (mph
->mh_dss_flags
& MPTCP_DSS_FLAG_DATA_ACK_PRESENT
) {
6555 if (mph
->mh_dss_flags
& MPTCP_DSS_FLAG_DATA_ACK_8BYTES
) {
6557 mph
->mh_dss_rawack
= tvb_get_ntoh64(tvb
,offset
);
6558 proto_tree_add_uint64_format_value(mptcp_tree
, hf_tcp_option_mptcp_data_ack_raw
, tvb
, offset
, 8, mph
->mh_dss_rawack
, "%" PRIu64
" (64bits)", mph
->mh_dss_rawack
);
6563 mph
->mh_dss_rawack
= tvb_get_ntohl(tvb
,offset
);
6564 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_data_ack_raw
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
6568 if(mptcp_convert_dsn(mph
->mh_dss_rawack
, tcpd
->rev
->mptcp_subflow
->meta
,
6569 (mph
->mh_dss_flags
& MPTCP_DSS_FLAG_DATA_ACK_8BYTES
) ? DSN_CONV_NONE
: DSN_CONV_32_TO_64
, mptcp_relative_seq
, &dack64
)) {
6570 item
= proto_tree_add_uint64(mptcp_tree
, hf_mptcp_ack
, tvb
, 0, 0, dack64
);
6571 if (mptcp_relative_seq
) {
6572 proto_item_append_text(item
, " (Relative)");
6575 proto_item_set_generated(item
);
6578 /* ignore and continue */
6583 /* Mapping present */
6584 if (mph
->mh_dss_flags
& MPTCP_DSS_FLAG_MAPPING_PRESENT
) {
6588 if (mph
->mh_dss_flags
& MPTCP_DSS_FLAG_DSN_8BYTES
) {
6590 dsn
= tvb_get_ntoh64(tvb
,offset
);
6591 proto_tree_add_uint64_format_value(mptcp_tree
, hf_tcp_option_mptcp_data_seq_no_raw
, tvb
, offset
, 8, dsn
, "%" PRIu64
" (64bits version)", dsn
);
6593 /* if we have the opportunity to complete the 32 Most Significant Bits of the
6596 if(!(tcpd
->fwd
->mptcp_subflow
->meta
->static_flags
& MPTCP_META_HAS_BASE_DSN_MSB
)) {
6597 tcpd
->fwd
->mptcp_subflow
->meta
->static_flags
|= MPTCP_META_HAS_BASE_DSN_MSB
;
6598 tcpd
->fwd
->mptcp_subflow
->meta
->base_dsn
|= (dsn
& (uint32_t) 0);
6602 dsn
= tvb_get_ntohl(tvb
,offset
);
6603 proto_tree_add_uint64_format_value(mptcp_tree
, hf_tcp_option_mptcp_data_seq_no_raw
, tvb
, offset
, 4, dsn
, "%" PRIu64
" (32bits version)", dsn
);
6606 mph
->mh_dss_rawdsn
= dsn
;
6608 proto_tree_add_item_ret_uint(mptcp_tree
, hf_tcp_option_mptcp_subflow_seq_no
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &mph
->mh_dss_ssn
);
6611 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_data_lvl_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
6612 mph
->mh_dss_length
= tvb_get_ntohs(tvb
,offset
);
6615 if(mph
->mh_dss_length
== 0) {
6616 expert_add_info(pinfo
, mptcp_tree
, &ei_mptcp_infinite_mapping
);
6619 /* print head & tail dsn */
6620 if(mptcp_convert_dsn(mph
->mh_dss_rawdsn
, tcpd
->fwd
->mptcp_subflow
->meta
,
6621 (mph
->mh_dss_flags
& MPTCP_DSS_FLAG_DATA_ACK_8BYTES
) ? DSN_CONV_NONE
: DSN_CONV_32_TO_64
, mptcp_relative_seq
, &dsn
)) {
6622 item
= proto_tree_add_uint64(mptcp_tree
, hf_mptcp_dss_dsn
, tvb
, 0, 0, dsn
);
6623 if (mptcp_relative_seq
) {
6624 proto_item_append_text(item
, " (Relative)");
6627 proto_item_set_generated(item
);
6630 /* ignore and continue */
6633 analyze_mapping(tcpd
, pinfo
, mph
->mh_dss_length
, mph
->mh_dss_rawdsn
, mph
->mh_dss_flags
& MPTCP_DSS_FLAG_DATA_ACK_8BYTES
, mph
->mh_dss_ssn
);
6635 if ((int)optlen
>= offset
-start_offset
+4)
6637 proto_tree_add_checksum(mptcp_tree
, tvb
, offset
, hf_tcp_option_mptcp_checksum
, -1, NULL
, pinfo
, 0, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
6642 case TCPOPT_MPTCP_ADD_ADDR
:
6644 ipver
= tvb_get_uint8(tvb
, offset
) & 0x0F;
6645 if (ipver
== 4 || ipver
== 6)
6646 proto_tree_add_item(mptcp_tree
,
6647 hf_tcp_option_mptcp_ipver
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
6649 proto_tree_add_item(mptcp_tree
,
6650 hf_tcp_option_mptcp_echo
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
6653 proto_tree_add_item(mptcp_tree
,
6654 hf_tcp_option_mptcp_address_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
6657 if (optlen
== 8 || optlen
== 10 || optlen
== 16 || optlen
== 18) {
6658 proto_tree_add_item(mptcp_tree
,
6659 hf_tcp_option_mptcp_ipv4
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
6663 if (optlen
== 20 || optlen
== 22 || optlen
== 28 || optlen
== 30) {
6664 proto_tree_add_item(mptcp_tree
,
6665 hf_tcp_option_mptcp_ipv6
, tvb
, offset
, 16, ENC_NA
);
6669 if (optlen
== 10 || optlen
== 18 || optlen
== 22 || optlen
== 30) {
6670 proto_tree_add_item(mptcp_tree
,
6671 hf_tcp_option_mptcp_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
6675 if (optlen
== 16 || optlen
== 18 || optlen
== 28 || optlen
== 30) {
6676 proto_tree_add_item(mptcp_tree
,
6677 hf_tcp_option_mptcp_addaddr_trunc_hmac
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
6681 case TCPOPT_MPTCP_REMOVE_ADDR
:
6682 mph
->mh_remove
= true;
6683 item
= proto_tree_add_uint(mptcp_tree
, hf_mptcp_number_of_removed_addresses
, tvb
, start_offset
+2,
6685 proto_item_set_generated(item
);
6687 while(offset
< start_offset
+ (int)optlen
) {
6688 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_address_id
, tvb
, offset
,
6694 case TCPOPT_MPTCP_MP_PRIO
:
6695 mph
->mh_prio
= true;
6696 proto_tree_add_bitmask(mptcp_tree
, tvb
, offset
, hf_tcp_option_mptcp_flags
,
6697 ett_tcp_option_mptcp
, tcp_option_mptcp_join_flags
,
6702 proto_tree_add_item(mptcp_tree
,
6703 hf_tcp_option_mptcp_address_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
6707 case TCPOPT_MPTCP_MP_FAIL
:
6708 mph
->mh_fail
= true;
6709 proto_tree_add_item(mptcp_tree
,
6710 hf_tcp_option_mptcp_reserved
, tvb
, offset
,2, ENC_BIG_ENDIAN
);
6713 proto_tree_add_item(mptcp_tree
,
6714 hf_tcp_option_mptcp_data_seq_no_raw
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
6717 case TCPOPT_MPTCP_MP_FASTCLOSE
:
6718 mph
->mh_fastclose
= true;
6719 proto_tree_add_item(mptcp_tree
,
6720 hf_tcp_option_mptcp_reserved
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
6723 proto_tree_add_item(mptcp_tree
,
6724 hf_tcp_option_mptcp_recv_key
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
6725 mph
->mh_key
= tvb_get_ntoh64(tvb
,offset
);
6728 case TCPOPT_MPTCP_MP_TCPRST
:
6729 mph
->mh_tcprst
= true;
6730 proto_tree_add_bitmask(mptcp_tree
, tvb
, offset
, hf_tcp_option_mptcp_flags
,
6731 ett_tcp_option_mptcp
, tcp_option_mptcp_tcprst_flags
,
6734 proto_tree_add_item(mptcp_tree
, hf_tcp_option_mptcp_tcprst_reason
, tvb
, offset
, 1,
6742 if ((mptcpd
!= NULL
) && (tcpd
->mptcp_analysis
!= NULL
)) {
6744 /* if mptcpd just got allocated, remember the initial addresses
6745 * which will serve as identifiers for the conversation filter
6747 if(tcpd
->fwd
->mptcp_subflow
->meta
->ip_src
.len
== 0) {
6749 copy_address_wmem(wmem_file_scope(), &tcpd
->fwd
->mptcp_subflow
->meta
->ip_src
, &tcph
->ip_src
);
6750 copy_address_wmem(wmem_file_scope(), &tcpd
->fwd
->mptcp_subflow
->meta
->ip_dst
, &tcph
->ip_dst
);
6752 copy_address_shallow(&tcpd
->rev
->mptcp_subflow
->meta
->ip_src
, &tcpd
->fwd
->mptcp_subflow
->meta
->ip_dst
);
6753 copy_address_shallow(&tcpd
->rev
->mptcp_subflow
->meta
->ip_dst
, &tcpd
->fwd
->mptcp_subflow
->meta
->ip_src
);
6755 tcpd
->fwd
->mptcp_subflow
->meta
->sport
= tcph
->th_sport
;
6756 tcpd
->fwd
->mptcp_subflow
->meta
->dport
= tcph
->th_dport
;
6759 mph
->mh_stream
= tcpd
->mptcp_analysis
->stream
;
6762 return tvb_captured_length(tvb
);
6766 dissect_tcpopt_cc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
6768 proto_tree
*field_tree
;
6770 proto_item
*length_item
;
6774 item
= proto_tree_add_item(tree
, proto_tcp_option_cc
, tvb
, offset
, -1, ENC_NA
);
6775 field_tree
= proto_item_add_subtree(item
, ett_tcp_opt_cc
);
6777 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
6778 offset
, 1, ENC_BIG_ENDIAN
);
6779 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
6780 offset
+ 1, 1, ENC_BIG_ENDIAN
);
6782 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), TCPOLEN_CC
))
6783 return tvb_captured_length(tvb
);
6785 proto_tree_add_item_ret_uint(field_tree
, hf_tcp_option_cc
, tvb
,
6786 offset
+ 2, 4, ENC_BIG_ENDIAN
, &cc
);
6788 tcp_info_append_uint(pinfo
, "CC", cc
);
6789 return tvb_captured_length(tvb
);
6793 dissect_tcpopt_md5(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
6795 proto_tree
*field_tree
;
6797 proto_item
*length_item
;
6798 int offset
= 0, optlen
= tvb_reported_length(tvb
);
6800 item
= proto_tree_add_item(tree
, proto_tcp_option_md5
, tvb
, offset
, -1, ENC_NA
);
6801 field_tree
= proto_item_add_subtree(item
, ett_tcp_opt_md5
);
6803 col_append_lstr(pinfo
->cinfo
, COL_INFO
, " MD5", COL_ADD_LSTR_TERMINATOR
);
6804 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
6805 offset
, 1, ENC_BIG_ENDIAN
);
6806 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
6807 offset
+ 1, 1, ENC_BIG_ENDIAN
);
6809 if (!tcp_option_len_check(length_item
, pinfo
, optlen
, TCPOLEN_MD5
))
6810 return tvb_captured_length(tvb
);
6812 proto_tree_add_item(field_tree
, hf_tcp_option_md5_digest
, tvb
,
6813 offset
+ 2, optlen
- 2, ENC_NA
);
6815 return tvb_captured_length(tvb
);
6819 dissect_tcpopt_ao(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
6821 proto_tree
*field_tree
;
6823 proto_item
*length_item
;
6824 int offset
= 0, optlen
= tvb_reported_length(tvb
);
6826 item
= proto_tree_add_item(tree
, proto_tcp_option_ao
, tvb
, offset
, -1, ENC_NA
);
6827 field_tree
= proto_item_add_subtree(item
, ett_tcp_opt_ao
);
6829 col_append_lstr(pinfo
->cinfo
, COL_INFO
, "TCP AO", COL_ADD_LSTR_TERMINATOR
);
6830 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
6831 offset
, 1, ENC_BIG_ENDIAN
);
6832 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
6833 offset
+ 1, 1, ENC_BIG_ENDIAN
);
6836 expert_add_info_format(pinfo
, length_item
, &ei_tcp_opt_len_invalid
,
6837 "option length should be >= than 4");
6838 return tvb_captured_length(tvb
);
6841 proto_tree_add_item(field_tree
, hf_tcp_option_ao_keyid
, tvb
,
6842 offset
+ 2, 1, ENC_NA
);
6844 proto_tree_add_item(field_tree
, hf_tcp_option_ao_rnextkeyid
, tvb
,
6845 offset
+ 3, 1, ENC_NA
);
6848 proto_tree_add_item(field_tree
, hf_tcp_option_ao_mac
, tvb
,
6849 offset
+ 4, optlen
- 4, ENC_NA
);
6851 return tvb_captured_length(tvb
);
6855 dissect_tcpopt_qs(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
6857 proto_tree
*field_tree
;
6859 proto_item
*length_item
;
6863 item
= proto_tree_add_item(tree
, proto_tcp_option_qs
, tvb
, offset
, -1, ENC_NA
);
6864 field_tree
= proto_item_add_subtree(item
, ett_tcp_opt_qs
);
6866 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
6867 offset
, 1, ENC_BIG_ENDIAN
);
6868 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
6869 offset
+ 1, 1, ENC_BIG_ENDIAN
);
6871 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), TCPOLEN_QS
))
6872 return tvb_captured_length(tvb
);
6874 rate
= tvb_get_uint8(tvb
, offset
+ 2) & 0x0f;
6875 col_append_lstr(pinfo
->cinfo
, COL_INFO
,
6876 " QSresp=", val_to_str_ext_const(rate
, &qs_rate_vals_ext
, "Unknown"),
6877 COL_ADD_LSTR_TERMINATOR
);
6878 proto_tree_add_item(field_tree
, hf_tcp_option_qs_rate
, tvb
,
6879 offset
+ 2, 1, ENC_BIG_ENDIAN
);
6880 proto_tree_add_item(field_tree
, hf_tcp_option_qs_ttl_diff
, tvb
,
6881 offset
+ 3, 1, ENC_BIG_ENDIAN
);
6883 return tvb_captured_length(tvb
);
6887 dissect_tcpopt_scps(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
6889 struct tcp_analysis
*tcpd
;
6890 proto_tree
*field_tree
= NULL
;
6893 proto_item
*tf
= NULL
, *item
;
6894 proto_tree
*flags_tree
= NULL
;
6897 int offset
= 0, optlen
= tvb_reported_length(tvb
);
6899 conversation_t
*stratconv
= find_conversation_strat(pinfo
, CONVERSATION_TCP
, 0);
6900 tcpd
=get_tcp_conversation_data_idempotent(stratconv
);
6902 /* check direction and get ua lists */
6903 direction
=cmp_address(&pinfo
->src
, &pinfo
->dst
);
6905 /* if the addresses are equal, match the ports instead */
6907 direction
= (pinfo
->srcport
> pinfo
->destport
) ? 1 : -1;
6911 flow
=&(tcpd
->flow1
);
6913 flow
=&(tcpd
->flow2
);
6915 item
= proto_tree_add_item(tree
, proto_tcp_option_scps
,
6916 tvb
, offset
, -1, ENC_NA
);
6917 field_tree
= proto_item_add_subtree(item
, ett_tcp_option_scps
);
6919 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
6920 offset
, 1, ENC_BIG_ENDIAN
);
6921 proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
6922 offset
+ 1, 1, ENC_BIG_ENDIAN
);
6924 /* If the option length == 4, this is a real SCPS capability option
6925 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
6926 * (SCPS-TP)" Section 3.2.3 for definition.
6929 tf
= proto_tree_add_item(field_tree
, hf_tcp_option_scps_vector
, tvb
,
6930 offset
+ 2, 1, ENC_BIG_ENDIAN
);
6931 flags_tree
= proto_item_add_subtree(tf
, ett_tcp_scpsoption_flags
);
6932 proto_tree_add_item(flags_tree
, hf_tcp_scpsoption_flags_bets
, tvb
,
6933 offset
+ 2, 1, ENC_BIG_ENDIAN
);
6934 proto_tree_add_item(flags_tree
, hf_tcp_scpsoption_flags_snack1
, tvb
,
6935 offset
+ 2, 1, ENC_BIG_ENDIAN
);
6936 proto_tree_add_item(flags_tree
, hf_tcp_scpsoption_flags_snack2
, tvb
,
6937 offset
+ 2, 1, ENC_BIG_ENDIAN
);
6938 proto_tree_add_item(flags_tree
, hf_tcp_scpsoption_flags_compress
, tvb
,
6939 offset
+ 2, 1, ENC_BIG_ENDIAN
);
6940 proto_tree_add_item(flags_tree
, hf_tcp_scpsoption_flags_nlts
, tvb
,
6941 offset
+ 2, 1, ENC_BIG_ENDIAN
);
6942 proto_tree_add_item(flags_tree
, hf_tcp_scpsoption_flags_reserved
, tvb
,
6943 offset
+ 2, 1, ENC_BIG_ENDIAN
);
6944 capvector
= tvb_get_uint8(tvb
, offset
+ 2);
6959 bool anyflag
= false;
6962 col_append_str(pinfo
->cinfo
, COL_INFO
, " SCPS[");
6963 for (i
= 0; i
< array_length(capvecs
); i
++) {
6964 if (capvector
& capvecs
[i
].mask
) {
6965 proto_item_append_text(tf
, "%s%s", anyflag
? ", " : " (",
6967 col_append_lstr(pinfo
->cinfo
, COL_INFO
,
6968 anyflag
? ", " : "",
6970 COL_ADD_LSTR_TERMINATOR
);
6974 col_append_str(pinfo
->cinfo
, COL_INFO
, "]");
6975 proto_item_append_text(tf
, ")");
6978 proto_tree_add_item(field_tree
, hf_tcp_scpsoption_connection_id
, tvb
,
6979 offset
+ 3, 1, ENC_BIG_ENDIAN
);
6980 connid
= tvb_get_uint8(tvb
, offset
+ 3);
6981 flow
->scps_capable
= true;
6984 tcp_info_append_uint(pinfo
, "Connection ID", connid
);
6986 /* The option length != 4, so this is an infamous "extended capabilities
6987 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
6988 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
6990 * As the format of this option is only partially defined (it is
6991 * a community (or more likely vendor) defined format beyond that, so
6992 * at least for now, we only parse the standardized portion of the option.
6994 uint8_t local_offset
= 2;
6995 uint8_t binding_space
;
6996 uint8_t extended_cap_length
;
6998 if (!flow
->scps_capable
) {
6999 /* There was no SCPS capabilities option preceding this */
7000 proto_item_set_text(item
,
7001 "Illegal SCPS Extended Capabilities (%u bytes)",
7004 proto_item_set_text(item
,
7005 "SCPS Extended Capabilities (%u bytes)",
7008 /* There may be multiple binding spaces included in a single option,
7009 * so we will semi-parse each of the stacked binding spaces - skipping
7010 * over the octets following the binding space identifier and length.
7012 while (optlen
> local_offset
) {
7014 /* 1st octet is Extended Capability Binding Space */
7015 binding_space
= tvb_get_uint8(tvb
, (offset
+ local_offset
));
7017 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
7018 * As defined by the specification, this length is exclusive of the
7019 * octets containing the extended capability type and length
7021 extended_cap_length
=
7022 (tvb_get_uint8(tvb
, (offset
+ local_offset
+ 1)) >> 4);
7024 /* Convert the extended capabilities length into bytes for display */
7025 extended_cap_length
= (extended_cap_length
<< 1);
7027 proto_tree_add_item(field_tree
, hf_tcp_option_scps_binding
, tvb
, offset
+ local_offset
, 1, ENC_BIG_ENDIAN
);
7028 proto_tree_add_uint(field_tree
, hf_tcp_option_scps_binding_len
, tvb
, offset
+ local_offset
+ 1, 1, extended_cap_length
);
7030 /* Step past the binding space and length octets */
7033 proto_tree_add_item(field_tree
, hf_tcp_option_scps_binding_data
, tvb
, offset
+ local_offset
, extended_cap_length
, ENC_NA
);
7035 tcp_info_append_uint(pinfo
, "EXCAP", binding_space
);
7037 /* Step past the Extended capability data
7038 * Treat the extended capability data area as opaque;
7039 * If one desires to parse the extended capability data
7040 * (say, in a vendor aware build of wireshark), it would
7041 * be triggered here.
7043 local_offset
+= extended_cap_length
;
7048 return tvb_captured_length(tvb
);
7052 dissect_tcpopt_user_to(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
7055 proto_tree
*field_tree
;
7056 proto_item
*length_item
;
7060 tf
= proto_tree_add_item(tree
, proto_tcp_option_user_to
, tvb
, offset
, -1, ENC_NA
);
7061 field_tree
= proto_item_add_subtree(tf
, ett_tcp_option_user_to
);
7063 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
7064 offset
, 1, ENC_BIG_ENDIAN
);
7065 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
7066 offset
+ 1, 1, ENC_BIG_ENDIAN
);
7068 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), TCPOLEN_USER_TO
))
7069 return tvb_captured_length(tvb
);
7071 proto_tree_add_item(field_tree
, hf_tcp_option_user_to_granularity
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
7072 to
= tvb_get_ntohs(tvb
, offset
+ 2) & 0x7FFF;
7073 proto_tree_add_item(field_tree
, hf_tcp_option_user_to_val
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
7075 tcp_info_append_uint(pinfo
, "USER_TO", to
);
7076 return tvb_captured_length(tvb
);
7079 /* This is called for SYN+ACK packets and the purpose is to verify that
7080 * the SCPS capabilities option has been successfully negotiated for the flow.
7081 * If the SCPS capabilities option was offered by only one party, the
7082 * proactively set scps_capable attribute of the flow (set upon seeing
7083 * the first instance of the SCPS option) is revoked.
7086 verify_scps(packet_info
*pinfo
, proto_item
*tf_syn
, struct tcp_analysis
*tcpd
)
7091 if ((!(tcpd
->flow1
.scps_capable
)) || (!(tcpd
->flow2
.scps_capable
))) {
7092 tcpd
->flow1
.scps_capable
= false;
7093 tcpd
->flow2
.scps_capable
= false;
7095 expert_add_info(pinfo
, tf_syn
, &ei_tcp_scps_capable
);
7100 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
7101 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
7104 dissect_tcpopt_snack(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
7106 struct tcp_analysis
*tcpd
=NULL
;
7107 uint32_t relative_hole_offset
;
7108 uint32_t relative_hole_size
;
7109 uint16_t base_mss
= 0;
7111 uint32_t hole_start
;
7114 proto_item
*hidden_item
, *tf
;
7115 proto_tree
*field_tree
;
7116 proto_item
*length_item
;
7118 tf
= proto_tree_add_item(tree
, proto_tcp_option_snack
, tvb
, offset
, -1, ENC_NA
);
7119 field_tree
= proto_item_add_subtree(tf
, ett_tcp_option_snack
);
7121 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
7122 offset
, 1, ENC_BIG_ENDIAN
);
7123 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
7124 offset
+ 1, 1, ENC_BIG_ENDIAN
);
7126 if (!tcp_option_len_check(length_item
, pinfo
, tvb_reported_length(tvb
), TCPOLEN_SNACK
))
7127 return tvb_captured_length(tvb
);
7129 conversation_t
*stratconv
= find_conversation_strat(pinfo
, CONVERSATION_TCP
, 0);
7130 tcpd
=get_tcp_conversation_data_idempotent(stratconv
);
7132 /* The SNACK option reports missing data with a granularity of segments. */
7133 proto_tree_add_item_ret_uint(field_tree
, hf_tcp_option_snack_offset
,
7134 tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
, &relative_hole_offset
);
7136 proto_tree_add_item_ret_uint(field_tree
, hf_tcp_option_snack_size
,
7137 tvb
, offset
+ 4, 2, ENC_BIG_ENDIAN
, &relative_hole_size
);
7139 ack
= tvb_get_ntohl(tvb
, 8);
7141 if (tcp_analyze_seq
&& tcp_relative_seq
) {
7142 ack
-= tcpd
->rev
->base_seq
;
7145 /* To aid analysis, we can use a simple but generally effective heuristic
7146 * to report the most likely boundaries of the missing data. If the
7147 * flow is scps_capable, we track the maximum sized segment that was
7148 * acknowledged by the receiver and use that as the reporting granularity.
7149 * This may be different from the negotiated MTU due to PMTUD or flows
7150 * that do not send max-sized segments.
7152 base_mss
= tcpd
->fwd
->maxsizeacked
;
7155 /* Scale the reported offset and hole size by the largest segment acked */
7156 hole_start
= ack
+ (base_mss
* relative_hole_offset
);
7157 hole_end
= hole_start
+ (base_mss
* relative_hole_size
);
7159 hidden_item
= proto_tree_add_uint(field_tree
, hf_tcp_option_snack_le
,
7160 tvb
, offset
+ 2, 2, hole_start
);
7161 proto_item_set_hidden(hidden_item
);
7163 hidden_item
= proto_tree_add_uint(field_tree
, hf_tcp_option_snack_re
,
7164 tvb
, offset
+ 4, 2, hole_end
);
7165 proto_item_set_hidden(hidden_item
);
7167 proto_tree_add_expert_format(field_tree
, pinfo
, &ei_tcp_option_snack_sequence
, tvb
, offset
+2, 4,
7168 "SNACK Sequence %u - %u%s", hole_start
, hole_end
, ((tcp_analyze_seq
&& tcp_relative_seq
) ? " (relative)" : ""));
7170 tcp_info_append_uint(pinfo
, "SNLE", hole_start
);
7171 tcp_info_append_uint(pinfo
, "SNRE", hole_end
);
7174 return tvb_captured_length(tvb
);
7179 PROBE_VERSION_UNSPEC
= 0,
7180 PROBE_VERSION_1
= 1,
7181 PROBE_VERSION_2
= 2,
7185 /* Probe type definition. */
7193 PROBE_RESPONSE_SH
= 5,
7194 PROBE_QUERY_INFO
= 6,
7195 PROBE_RESPONSE_INFO
= 7,
7196 PROBE_QUERY_INFO_SH
= 8,
7197 PROBE_QUERY_INFO_SID
= 9,
7202 static const value_string rvbd_probe_type_vs
[] = {
7203 { PROBE_QUERY
, "Probe Query" },
7204 { PROBE_RESPONSE
, "Probe Response" },
7205 { PROBE_INTERNAL
, "Probe Internal" },
7206 { PROBE_TRACE
, "Probe Trace" },
7207 { PROBE_QUERY_SH
, "Probe Query SH" },
7208 { PROBE_RESPONSE_SH
, "Probe Response SH" },
7209 { PROBE_QUERY_INFO
, "Probe Query Info" },
7210 { PROBE_RESPONSE_INFO
, "Probe Response Info" },
7211 { PROBE_QUERY_INFO_SH
, "Probe Query Info SH" },
7212 { PROBE_QUERY_INFO_SID
, "Probe Query Info Store ID" },
7213 { PROBE_RST
, "Probe Reset" },
7217 #define PROBE_OPTLEN_OFFSET 1
7219 #define PROBE_VERSION_TYPE_OFFSET 2
7220 #define PROBE_V1_RESERVED_OFFSET 3
7221 #define PROBE_V1_PROBER_OFFSET 4
7222 #define PROBE_V1_APPLI_VERSION_OFFSET 8
7223 #define PROBE_V1_PROXY_ADDR_OFFSET 8
7224 #define PROBE_V1_PROXY_PORT_OFFSET 12
7225 #define PROBE_V1_SH_CLIENT_ADDR_OFFSET 8
7226 #define PROBE_V1_SH_PROXY_ADDR_OFFSET 12
7227 #define PROBE_V1_SH_PROXY_PORT_OFFSET 16
7229 #define PROBE_V2_INFO_OFFSET 3
7231 #define PROBE_V2_INFO_CLIENT_ADDR_OFFSET 4
7232 #define PROBE_V2_INFO_STOREID_OFFSET 4
7234 #define PROBE_VERSION_MASK 0x01
7236 /* Probe Query Extra Info flags */
7237 #define RVBD_FLAGS_PROBE_LAST 0x01
7238 #define RVBD_FLAGS_PROBE_NCFE 0x04
7240 /* Probe Response Extra Info flags */
7241 #define RVBD_FLAGS_PROBE_SERVER 0x01
7242 #define RVBD_FLAGS_PROBE_SSLCERT 0x02
7243 #define RVBD_FLAGS_PROBE 0x10
7245 typedef struct rvbd_option_data
7249 uint8_t probe_flags
;
7254 rvbd_probe_decode_version_type(const uint8_t vt
, uint8_t *ver
, uint8_t *type
)
7256 if (vt
& PROBE_VERSION_MASK
) {
7257 *ver
= PROBE_VERSION_1
;
7260 *ver
= PROBE_VERSION_2
;
7266 rvbd_probe_resp_add_info(proto_item
*pitem
, packet_info
*pinfo
, tvbuff_t
*tvb
, int ip_offset
, uint16_t port
)
7268 proto_item_append_text(pitem
, ", Server Steelhead: %s:%u", tvb_ip_to_str(pinfo
->pool
, tvb
, ip_offset
), port
);
7270 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "SA+, ");
7274 dissect_tcpopt_rvbd_probe(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
7277 proto_tree
*field_tree
;
7279 proto_item
*length_item
;
7281 optlen
= tvb_reported_length(tvb
);
7282 struct tcpheader
*tcph
= (struct tcpheader
*)data
;
7284 pitem
= proto_tree_add_item(tree
, proto_tcp_option_rvbd_probe
, tvb
, offset
, -1, ENC_NA
);
7285 field_tree
= proto_item_add_subtree(pitem
, ett_tcp_opt_rvbd_probe
);
7287 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
7288 offset
, 1, ENC_BIG_ENDIAN
);
7289 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
7290 offset
+ 1, 1, ENC_BIG_ENDIAN
);
7292 if (optlen
< TCPOLEN_RVBD_PROBE_MIN
) {
7293 /* Bogus - option length is less than what it's supposed to be for
7295 expert_add_info_format(pinfo
, length_item
, &ei_tcp_opt_len_invalid
,
7296 "option length should be >= %u)",
7297 TCPOLEN_RVBD_PROBE_MIN
);
7298 return tvb_captured_length(tvb
);
7301 rvbd_probe_decode_version_type(
7302 tvb_get_uint8(tvb
, offset
+ PROBE_VERSION_TYPE_OFFSET
),
7305 proto_item_append_text(pitem
, ": %s", val_to_str_const(type
, rvbd_probe_type_vs
, "Probe Unknown"));
7307 if (type
>= PROBE_TYPE_MAX
)
7308 return tvb_captured_length(tvb
);
7310 if (ver
== PROBE_VERSION_1
) {
7313 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_type1
, tvb
,
7314 offset
+ PROBE_VERSION_TYPE_OFFSET
, 1, ENC_BIG_ENDIAN
);
7315 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_version1
, tvb
,
7316 offset
+ PROBE_VERSION_TYPE_OFFSET
, 1, ENC_BIG_ENDIAN
);
7318 if (type
== PROBE_INTERNAL
)
7319 return offset
+ PROBE_VERSION_TYPE_OFFSET
;
7321 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_reserved
, tvb
, offset
+ PROBE_V1_RESERVED_OFFSET
, 1, ENC_BIG_ENDIAN
);
7323 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_prober
, tvb
,
7324 offset
+ PROBE_V1_PROBER_OFFSET
, 4, ENC_BIG_ENDIAN
);
7329 case PROBE_QUERY_SH
:
7332 rvbd_option_data
* option_data
;
7333 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_appli_ver
, tvb
,
7334 offset
+ PROBE_V1_APPLI_VERSION_OFFSET
, 2,
7337 proto_item_append_text(pitem
, ", CSH IP: %s", tvb_ip_to_str(pinfo
->pool
, tvb
, offset
+ PROBE_V1_PROBER_OFFSET
));
7339 option_data
= (rvbd_option_data
*)p_get_proto_data(pinfo
->pool
, pinfo
, proto_tcp_option_rvbd_probe
, pinfo
->curr_layer_num
);
7340 if (option_data
== NULL
)
7342 option_data
= wmem_new0(pinfo
->pool
, rvbd_option_data
);
7343 p_add_proto_data(pinfo
->pool
, pinfo
, proto_tcp_option_rvbd_probe
, pinfo
->curr_layer_num
, option_data
);
7346 option_data
->valid
= true;
7347 option_data
->type
= type
;
7352 case PROBE_RESPONSE
:
7353 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_proxy
, tvb
,
7354 offset
+ PROBE_V1_PROXY_ADDR_OFFSET
, 4, ENC_BIG_ENDIAN
);
7356 port
= tvb_get_ntohs(tvb
, offset
+ PROBE_V1_PROXY_PORT_OFFSET
);
7357 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_proxy_port
, tvb
,
7358 offset
+ PROBE_V1_PROXY_PORT_OFFSET
, 2, ENC_BIG_ENDIAN
);
7360 rvbd_probe_resp_add_info(pitem
, pinfo
, tvb
, offset
+ PROBE_V1_PROXY_ADDR_OFFSET
, port
);
7363 case PROBE_RESPONSE_SH
:
7364 proto_tree_add_item(field_tree
,
7365 hf_tcp_option_rvbd_probe_client
, tvb
,
7366 offset
+ PROBE_V1_SH_CLIENT_ADDR_OFFSET
, 4,
7369 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_proxy
, tvb
,
7370 offset
+ PROBE_V1_SH_PROXY_ADDR_OFFSET
, 4, ENC_BIG_ENDIAN
);
7372 port
= tvb_get_ntohs(tvb
, offset
+ PROBE_V1_SH_PROXY_PORT_OFFSET
);
7373 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_proxy_port
, tvb
,
7374 offset
+ PROBE_V1_SH_PROXY_PORT_OFFSET
, 2, ENC_BIG_ENDIAN
);
7376 rvbd_probe_resp_add_info(pitem
, pinfo
, tvb
, offset
+ PROBE_V1_SH_PROXY_ADDR_OFFSET
, port
);
7380 else if (ver
== PROBE_VERSION_2
) {
7382 proto_item
*flag_pi
;
7383 proto_tree
*flag_tree
;
7386 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_type2
, tvb
,
7387 offset
+ PROBE_VERSION_TYPE_OFFSET
, 1, ENC_BIG_ENDIAN
);
7389 proto_tree_add_uint_format_value(
7390 field_tree
, hf_tcp_option_rvbd_probe_version2
, tvb
,
7391 offset
+ PROBE_VERSION_TYPE_OFFSET
, 1, ver
, "%u", ver
);
7392 /* Use version1 for filtering purposes because version2 packet
7393 value is 0, but filtering is usually done for value 2 */
7394 ver_pi
= proto_tree_add_uint(field_tree
, hf_tcp_option_rvbd_probe_version1
, tvb
,
7395 offset
+ PROBE_VERSION_TYPE_OFFSET
, 1, ver
);
7396 proto_item_set_hidden(ver_pi
);
7400 case PROBE_QUERY_INFO
:
7401 case PROBE_QUERY_INFO_SH
:
7402 case PROBE_QUERY_INFO_SID
:
7403 flags
= tvb_get_uint8(tvb
, offset
+ PROBE_V2_INFO_OFFSET
);
7404 flag_pi
= proto_tree_add_uint(field_tree
, hf_tcp_option_rvbd_probe_flags
,
7405 tvb
, offset
+ PROBE_V2_INFO_OFFSET
,
7408 flag_tree
= proto_item_add_subtree(flag_pi
, ett_tcp_opt_rvbd_probe_flags
);
7409 proto_tree_add_item(flag_tree
,
7410 hf_tcp_option_rvbd_probe_flag_not_cfe
,
7411 tvb
, offset
+ PROBE_V2_INFO_OFFSET
, 1, ENC_BIG_ENDIAN
);
7412 proto_tree_add_item(flag_tree
,
7413 hf_tcp_option_rvbd_probe_flag_last_notify
,
7414 tvb
, offset
+ PROBE_V2_INFO_OFFSET
, 1, ENC_BIG_ENDIAN
);
7418 case PROBE_QUERY_INFO
:
7420 rvbd_option_data
* option_data
= (rvbd_option_data
*)p_get_proto_data(pinfo
->pool
, pinfo
, proto_tcp_option_rvbd_probe
, pinfo
->curr_layer_num
);
7421 if (option_data
== NULL
)
7423 option_data
= wmem_new0(pinfo
->pool
, rvbd_option_data
);
7424 p_add_proto_data(pinfo
->pool
, pinfo
, proto_tcp_option_rvbd_probe
, pinfo
->curr_layer_num
, option_data
);
7427 option_data
->probe_flags
= flags
;
7430 case PROBE_QUERY_INFO_SH
:
7431 proto_tree_add_item(flag_tree
,
7432 hf_tcp_option_rvbd_probe_client
, tvb
,
7433 offset
+ PROBE_V2_INFO_CLIENT_ADDR_OFFSET
,
7436 case PROBE_QUERY_INFO_SID
:
7437 proto_tree_add_item(flag_tree
,
7438 hf_tcp_option_rvbd_probe_storeid
, tvb
,
7439 offset
+ PROBE_V2_INFO_STOREID_OFFSET
,
7444 if (type
!= PROBE_QUERY_INFO_SID
&&
7446 (tcph
->th_flags
& (TH_SYN
|TH_ACK
)) == (TH_SYN
|TH_ACK
) &&
7447 (flags
& RVBD_FLAGS_PROBE_LAST
)) {
7448 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "SA++, ");
7453 case PROBE_RESPONSE_INFO
:
7454 flag_pi
= proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_flags
,
7455 tvb
, offset
+ PROBE_V2_INFO_OFFSET
,
7458 flag_tree
= proto_item_add_subtree(flag_pi
, ett_tcp_opt_rvbd_probe_flags
);
7459 proto_tree_add_item(flag_tree
,
7460 hf_tcp_option_rvbd_probe_flag_probe_cache
,
7461 tvb
, offset
+ PROBE_V2_INFO_OFFSET
, 1, ENC_BIG_ENDIAN
);
7462 proto_tree_add_item(flag_tree
,
7463 hf_tcp_option_rvbd_probe_flag_sslcert
,
7464 tvb
, offset
+ PROBE_V2_INFO_OFFSET
, 1, ENC_BIG_ENDIAN
);
7465 proto_tree_add_item(flag_tree
,
7466 hf_tcp_option_rvbd_probe_flag_server_connected
,
7467 tvb
, offset
+ PROBE_V2_INFO_OFFSET
, 1, ENC_BIG_ENDIAN
);
7471 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_probe_flags
,
7472 tvb
, offset
+ PROBE_V2_INFO_OFFSET
,
7478 return tvb_captured_length(tvb
);
7482 TRPY_OPTNUM_OFFSET
= 0,
7483 TRPY_OPTLEN_OFFSET
= 1,
7485 TRPY_OPTIONS_OFFSET
= 2,
7486 TRPY_SRC_ADDR_OFFSET
= 4,
7487 TRPY_DST_ADDR_OFFSET
= 8,
7488 TRPY_SRC_PORT_OFFSET
= 12,
7489 TRPY_DST_PORT_OFFSET
= 14,
7490 TRPY_CLIENT_PORT_OFFSET
= 16
7494 #define RVBD_FLAGS_TRPY_MODE 0x0001
7495 #define RVBD_FLAGS_TRPY_OOB 0x0002
7496 #define RVBD_FLAGS_TRPY_CHKSUM 0x0004
7497 #define RVBD_FLAGS_TRPY_FW_RST 0x0100
7498 #define RVBD_FLAGS_TRPY_FW_RST_INNER 0x0200
7499 #define RVBD_FLAGS_TRPY_FW_RST_PROBE 0x0400
7501 static const true_false_string trpy_mode_str
= {
7502 "Port Transparency",
7507 dissect_tcpopt_rvbd_trpy(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
7509 proto_tree
*field_tree
;
7511 proto_item
*length_item
;
7512 uint16_t sport
, dport
, flags
;
7514 optlen
= tvb_reported_length(tvb
);
7515 static int * const rvbd_trpy_flags
[] = {
7516 &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe
,
7517 &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner
,
7518 &hf_tcp_option_rvbd_trpy_flag_fw_rst
,
7519 &hf_tcp_option_rvbd_trpy_flag_chksum
,
7520 &hf_tcp_option_rvbd_trpy_flag_oob
,
7521 &hf_tcp_option_rvbd_trpy_flag_mode
,
7525 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "TRPY, ");
7527 pitem
= proto_tree_add_item(tree
, proto_tcp_option_rvbd_trpy
, tvb
, offset
, -1, ENC_NA
);
7528 field_tree
= proto_item_add_subtree(pitem
, ett_tcp_opt_rvbd_trpy
);
7530 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
,
7531 offset
, 1, ENC_BIG_ENDIAN
);
7532 length_item
= proto_tree_add_item(field_tree
, hf_tcp_option_len
, tvb
,
7533 offset
+ 1, 1, ENC_BIG_ENDIAN
);
7535 if (!tcp_option_len_check(length_item
, pinfo
, optlen
, TCPOLEN_RVBD_TRPY_MIN
))
7536 return tvb_captured_length(tvb
);
7538 flags
= tvb_get_ntohs(tvb
, offset
+ TRPY_OPTIONS_OFFSET
);
7539 proto_tree_add_bitmask_with_flags(field_tree
, tvb
, offset
+ TRPY_OPTIONS_OFFSET
, hf_tcp_option_rvbd_trpy_flags
,
7540 ett_tcp_opt_rvbd_trpy_flags
, rvbd_trpy_flags
, ENC_NA
, BMT_NO_APPEND
);
7542 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_trpy_src
,
7543 tvb
, offset
+ TRPY_SRC_ADDR_OFFSET
, 4, ENC_BIG_ENDIAN
);
7545 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_trpy_dst
,
7546 tvb
, offset
+ TRPY_DST_ADDR_OFFSET
, 4, ENC_BIG_ENDIAN
);
7548 sport
= tvb_get_ntohs(tvb
, offset
+ TRPY_SRC_PORT_OFFSET
);
7549 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_trpy_src_port
,
7550 tvb
, offset
+ TRPY_SRC_PORT_OFFSET
, 2, ENC_BIG_ENDIAN
);
7552 dport
= tvb_get_ntohs(tvb
, offset
+ TRPY_DST_PORT_OFFSET
);
7553 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_trpy_dst_port
,
7554 tvb
, offset
+ TRPY_DST_PORT_OFFSET
, 2, ENC_BIG_ENDIAN
);
7556 proto_item_append_text(pitem
, " %s:%u -> %s:%u",
7557 tvb_ip_to_str(pinfo
->pool
, tvb
, offset
+ TRPY_SRC_ADDR_OFFSET
), sport
,
7558 tvb_ip_to_str(pinfo
->pool
, tvb
, offset
+ TRPY_DST_ADDR_OFFSET
), dport
);
7560 /* Client port only set on SYN: optlen == 18 */
7561 if ((flags
& RVBD_FLAGS_TRPY_OOB
) && (optlen
> TCPOLEN_RVBD_TRPY_MIN
))
7562 proto_tree_add_item(field_tree
, hf_tcp_option_rvbd_trpy_client_port
,
7563 tvb
, offset
+ TRPY_CLIENT_PORT_OFFSET
, 2, ENC_BIG_ENDIAN
);
7565 /* Despite that we have the right TCP ports for other protocols,
7566 * the data is related to the Riverbed Optimization Protocol and
7567 * not understandable by normal protocol dissectors. If the sport
7568 * protocol is available then use that, otherwise just output it
7571 if (sport_handle
!= NULL
) {
7572 conversation_t
*conversation
;
7573 conversation
= find_or_create_conversation(pinfo
);
7574 if (conversation_get_dissector(conversation
, pinfo
->num
) != sport_handle
) {
7575 conversation_set_dissector(conversation
, sport_handle
);
7577 } else if (data_handle
!= NULL
) {
7578 conversation_t
*conversation
;
7579 conversation
= find_or_create_conversation(pinfo
);
7580 if (conversation_get_dissector(conversation
, pinfo
->num
) != data_handle
) {
7581 conversation_set_dissector(conversation
, data_handle
);
7585 return tvb_captured_length(tvb
);
7588 /* Started as a copy of dissect_ip_tcp_options(), but was changed to support
7589 options as a dissector table */
7591 tcp_dissect_options(tvbuff_t
*tvb
, int offset
, unsigned length
,
7592 packet_info
*pinfo
, proto_tree
*opt_tree
,
7593 proto_item
*opt_item
, void * data
)
7596 unsigned optlen
, nop_count
= 0;
7597 proto_tree
*field_tree
;
7599 dissector_handle_t option_dissector
;
7601 struct tcpheader
*tcph
= (struct tcpheader
*)data
;
7602 bool mss_seen
= false;
7603 bool eol_seen
= false;
7604 bool sack_perm_seen
= false;
7606 while (length
> 0) {
7607 opt
= tvb_get_uint8(tvb
, offset
);
7608 if (eol_seen
&& opt
!= TCPOPT_EOL
) {
7609 proto_tree_add_expert_format(opt_tree
, pinfo
, &ei_tcp_non_zero_bytes_after_eol
, tvb
, offset
, length
,
7610 "Non-zero header padding");
7613 --length
; /* account for type byte */
7614 if ((opt
== TCPOPT_EOL
) || (opt
== TCPOPT_NOP
)) {
7616 proto_item
* field_item
;
7618 /* We assume that the only options with no length are EOL and
7619 NOP options, so that we can treat unknown options as having
7620 a minimum length of 2, and at least be able to move on to
7621 the next option by using the length in the option. */
7622 if (opt
== TCPOPT_EOL
) {
7623 local_proto
= proto_tcp_option_eol
;
7625 } else if (opt
== TCPOPT_NOP
) {
7626 local_proto
= proto_tcp_option_nop
;
7628 if (opt_item
&& (nop_count
== 0 || offset
% 4)) {
7629 /* Count number of NOP in a row within a uint32 */
7632 if (nop_count
== 4) {
7633 expert_add_info(pinfo
, opt_item
, &ei_tcp_nop
);
7639 DISSECTOR_ASSERT_NOT_REACHED();
7642 field_item
= proto_tree_add_item(opt_tree
, local_proto
, tvb
, offset
, 1, ENC_NA
);
7643 field_tree
= proto_item_add_subtree(field_item
, ett_tcp_option_other
);
7644 proto_tree_add_item(field_tree
, hf_tcp_option_kind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
7645 proto_item_append_text(proto_tree_get_parent(opt_tree
), ", %s", proto_get_protocol_short_name(find_protocol_by_id(local_proto
)));
7648 option_dissector
= dissector_get_uint_handle(tcp_option_table
, opt
);
7649 if (option_dissector
== NULL
) {
7650 name
= wmem_strdup_printf(pinfo
->pool
, "Unknown (0x%02x)", opt
);
7651 option_dissector
= tcp_opt_unknown_handle
;
7653 name
= dissector_handle_get_protocol_short_name(option_dissector
);
7656 /* Option has a length. Is it in the packet? */
7658 /* Bogus - packet must at least include option code byte and
7660 proto_tree_add_expert_format(opt_tree
, pinfo
, &ei_tcp_opt_len_invalid
, tvb
, offset
, 1,
7661 "%s (length byte past end of options)", name
);
7665 optlen
= tvb_get_uint8(tvb
, offset
+ 1); /* total including type, len */
7666 --length
; /* account for length byte */
7669 /* Bogus - option length is too short to include option code and
7671 proto_tree_add_expert_format(opt_tree
, pinfo
, &ei_tcp_opt_len_invalid
, tvb
, offset
, 2,
7672 "%s (with too-short option length = %u byte%s)",
7673 name
, optlen
, plurality(optlen
, "", "s"));
7675 } else if (optlen
- 2 > length
) {
7676 /* Bogus - option goes past the end of the header. */
7677 proto_tree_add_expert_format(opt_tree
, pinfo
, &ei_tcp_opt_len_invalid
, tvb
, offset
, length
,
7678 "%s (option length = %u byte%s says option goes past end of options)",
7679 name
, optlen
, plurality(optlen
, "", "s"));
7683 if (opt
== TCPOPT_MSS
)
7686 } else if (opt
== TCPOPT_SACK_PERM
)
7688 sack_perm_seen
= true;
7691 next_tvb
= tvb_new_subset_length(tvb
, offset
, optlen
);
7692 call_dissector_with_data(option_dissector
, next_tvb
, pinfo
, opt_tree
/* tree */, data
);
7693 proto_item_append_text(proto_tree_get_parent(opt_tree
), ", %s", name
);
7696 length
-= (optlen
-2); //already accounted for type and len bytes
7700 if (tcph
->th_flags
& TH_SYN
)
7702 if (mss_seen
== false)
7704 expert_add_info(pinfo
, opt_item
, &ei_tcp_option_mss_absent
);
7706 if (sack_perm_seen
== false)
7708 expert_add_info(pinfo
, opt_item
, &ei_tcp_option_sack_perm_absent
);
7713 /* Determine if there is a sub-dissector and call it; return true
7714 if there was a sub-dissector, false otherwise.
7716 This has been separated into a stand alone routine to other protocol
7717 dissectors can call to it, e.g., SOCKS. */
7719 static bool try_heuristic_first
;
7722 /* this function can be called with tcpd==NULL as from the msproxy dissector */
7724 decode_tcp_ports(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
7725 proto_tree
*tree
, int src_port
, int dst_port
,
7726 struct tcp_analysis
*tcpd
, struct tcpinfo
*tcpinfo
)
7729 int low_port
, high_port
;
7730 int save_desegment_offset
;
7731 bool try_low_port
, try_high_port
, try_server_port
;
7732 uint32_t save_desegment_len
;
7733 heur_dtbl_entry_t
*hdtbl_entry
;
7734 exp_pdu_data_t
*exp_pdu_data
;
7736 /* Don't call subdissectors for keepalives. Even though they do contain
7737 * payload "data", it's just garbage. Display any data the keepalive
7738 * packet might contain though.
7740 if(tcpd
&& tcpd
->ta
) {
7741 if(tcpd
->ta
->flags
&TCP_A_KEEP_ALIVE
) {
7742 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
7743 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
7748 if (tcp_no_subdissector_on_error
&& !(tcp_desegment
&& tcp_reassemble_out_of_order
) &&
7749 tcpd
&& tcpd
->ta
&& tcpd
->ta
->flags
& (TCP_A_RETRANSMISSION
| TCP_A_FAST_RETRANSMISSION
|
7750 TCP_A_SPURIOUS_RETRANSMISSION
| TCP_A_OUT_OF_ORDER
)) {
7751 /* Don't try to dissect a retransmission high chance that it will mess
7752 * subdissectors for protocols that require in-order delivery of the
7753 * PDUs. (i.e. DCE/RPCoverHTTP and encryption)
7754 * If OoO reassembly is enabled and if this segment was previously lost,
7755 * then this retransmission could have finished reassembly, so continue.
7756 * XXX should this option be removed? "tcp_reassemble_out_of_order"
7757 * should have addressed the above in-order requirement.
7761 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
7763 save_desegment_offset
= pinfo
->desegment_offset
;
7764 save_desegment_len
= pinfo
->desegment_len
;
7766 /* determine if this packet is part of a conversation and call dissector */
7767 /* for the conversation if available */
7769 if (try_conversation_dissector(&pinfo
->src
, &pinfo
->dst
, CONVERSATION_TCP
,
7770 src_port
, dst_port
, next_tvb
, pinfo
, tree
, tcpinfo
, 0)) {
7771 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7772 handle_export_pdu_conversation(pinfo
, next_tvb
, src_port
, dst_port
, tcpinfo
);
7776 /* If the user has manually configured one of the server, low, or high
7777 * ports to a dissector other than the default (via Decode As or the
7778 * preferences associated with Decode As), try those first, in that order.
7780 try_server_port
= false;
7781 if (tcpd
&& tcpd
->server_port
!= 0) {
7782 if (dissector_is_uint_changed(subdissector_table
, tcpd
->server_port
)) {
7783 if (dissector_try_uint_new(subdissector_table
, tcpd
->server_port
, next_tvb
, pinfo
, tree
, true, tcpinfo
)) {
7784 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7785 handle_export_pdu_dissection_table(pinfo
, next_tvb
, tcpd
->server_port
, tcpinfo
);
7789 /* The default; try it later */
7790 try_server_port
= true;
7794 if (src_port
> dst_port
) {
7795 low_port
= dst_port
;
7796 high_port
= src_port
;
7798 low_port
= src_port
;
7799 high_port
= dst_port
;
7802 try_low_port
= false;
7803 if (low_port
!= 0) {
7804 if (dissector_is_uint_changed(subdissector_table
, low_port
)) {
7805 if (dissector_try_uint_new(subdissector_table
, low_port
, next_tvb
, pinfo
, tree
, true, tcpinfo
)) {
7806 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7807 handle_export_pdu_dissection_table(pinfo
, next_tvb
, low_port
, tcpinfo
);
7811 /* The default; try it later */
7812 try_low_port
= true;
7816 try_high_port
= false;
7817 if (high_port
!= 0) {
7818 if (dissector_is_uint_changed(subdissector_table
, high_port
)) {
7819 if (dissector_try_uint_new(subdissector_table
, high_port
, next_tvb
, pinfo
, tree
, true, tcpinfo
)) {
7820 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7821 handle_export_pdu_dissection_table(pinfo
, next_tvb
, high_port
, tcpinfo
);
7825 /* The default; try it later */
7826 try_high_port
= true;
7830 if (try_heuristic_first
) {
7831 /* do lookup with the heuristic subdissector table */
7832 if (dissector_try_heuristic(heur_subdissector_list
, next_tvb
, pinfo
, tree
, &hdtbl_entry
, tcpinfo
)) {
7833 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7834 handle_export_pdu_heuristic(pinfo
, next_tvb
, hdtbl_entry
, tcpinfo
);
7839 /* Do lookups with the subdissector table.
7840 Try the server port captured on the SYN or SYN|ACK packet. After that
7841 try the port number with the lower value first, followed by the
7842 port number with the higher value. This means that, for packets
7843 where a dissector is registered for *both* port numbers:
7845 1) we pick the same dissector for traffic going in both directions;
7847 2) we prefer the port number that's more likely to be the right
7848 one (as that prefers well-known ports to reserved ports);
7850 although there is, of course, no guarantee that any such strategy
7851 will always pick the right port number.
7853 XXX - we ignore port numbers of 0, as some dissectors use a port
7854 number of 0 to disable the port. */
7856 if (try_server_port
&&
7857 dissector_try_uint_new(subdissector_table
, tcpd
->server_port
, next_tvb
, pinfo
, tree
, true, tcpinfo
)) {
7858 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7859 handle_export_pdu_dissection_table(pinfo
, next_tvb
, tcpd
->server_port
, tcpinfo
);
7864 dissector_try_uint_new(subdissector_table
, low_port
, next_tvb
, pinfo
, tree
, true, tcpinfo
)) {
7865 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7866 handle_export_pdu_dissection_table(pinfo
, next_tvb
, low_port
, tcpinfo
);
7869 if (try_high_port
&&
7870 dissector_try_uint_new(subdissector_table
, high_port
, next_tvb
, pinfo
, tree
, true, tcpinfo
)) {
7871 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7872 handle_export_pdu_dissection_table(pinfo
, next_tvb
, high_port
, tcpinfo
);
7876 if (!try_heuristic_first
) {
7877 /* do lookup with the heuristic subdissector table */
7878 if (dissector_try_heuristic(heur_subdissector_list
, next_tvb
, pinfo
, tree
, &hdtbl_entry
, tcpinfo
)) {
7879 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7880 handle_export_pdu_heuristic(pinfo
, next_tvb
, hdtbl_entry
, tcpinfo
);
7886 * heuristic / conversation / port registered dissectors rejected the packet;
7887 * make sure they didn't also request desegmentation (we could just override
7888 * the request, but rejecting a packet *and* requesting desegmentation is a sign
7889 * of the dissector's code needing clearer thought, so we fail so that the
7890 * problem is made more obvious).
7892 DISSECTOR_ASSERT(save_desegment_offset
== pinfo
->desegment_offset
&&
7893 save_desegment_len
== pinfo
->desegment_len
);
7895 /* Oh, well, we don't know this; dissect it as data. */
7896 call_dissector(data_handle
,next_tvb
, pinfo
, tree
);
7898 pinfo
->want_pdu_tracking
-= !!(pinfo
->want_pdu_tracking
);
7899 if (have_tap_listener(exported_pdu_tap
)) {
7900 exp_pdu_data
= export_pdu_create_common_tags(pinfo
, "data", EXP_PDU_TAG_DISSECTOR_NAME
);
7901 exp_pdu_data
->tvb_captured_length
= tvb_captured_length(next_tvb
);
7902 exp_pdu_data
->tvb_reported_length
= tvb_reported_length(next_tvb
);
7903 exp_pdu_data
->pdu_tvb
= next_tvb
;
7905 tap_queue_packet(exported_pdu_tap
, pinfo
, exp_pdu_data
);
7911 process_tcp_payload(tvbuff_t
*tvb
, volatile int offset
, packet_info
*pinfo
,
7912 proto_tree
*tree
, proto_tree
*tcp_tree
, int src_port
, int dst_port
,
7913 uint32_t seq
, uint32_t nxtseq
, bool is_tcp_segment
,
7914 struct tcp_analysis
*tcpd
, struct tcpinfo
*tcpinfo
)
7916 pinfo
->want_pdu_tracking
=0;
7919 if(is_tcp_segment
) {
7920 /*qqq see if it is an unaligned PDU */
7921 if(tcpd
&& tcp_analyze_seq
&& (!tcp_desegment
)) {
7923 offset
=scan_for_next_pdu(tvb
, tcp_tree
, pinfo
, offset
,
7924 seq
, nxtseq
, tcpd
->fwd
->multisegment_pdus
);
7928 /* if offset is -1 this means that this segment is known
7929 * to be fully inside a previously detected pdu
7930 * so we don't even need to try to dissect it either.
7933 decode_tcp_ports(tvb
, offset
, pinfo
, tree
, src_port
,
7934 dst_port
, tcpd
, tcpinfo
) ) {
7936 * We succeeded in handing off to a subdissector.
7938 * Is this a TCP segment or a reassembled chunk of
7941 if(is_tcp_segment
) {
7942 /* if !visited, check want_pdu_tracking and
7943 store it in table */
7944 if(tcpd
&& (!pinfo
->fd
->visited
) &&
7945 tcp_analyze_seq
&& pinfo
->want_pdu_tracking
) {
7947 pdu_store_sequencenumber_of_next_pdu(
7950 nxtseq
+pinfo
->bytes_until_next_pdu
,
7951 tcpd
->fwd
->multisegment_pdus
);
7958 /* We got an exception. At this point the dissection is
7959 * completely aborted and execution will be transferred back
7960 * to (probably) the frame dissector.
7961 * Here we have to place whatever we want the dissector
7962 * to do before aborting the tcp dissection.
7965 * Is this a TCP segment or a reassembled chunk of TCP
7968 if(is_tcp_segment
) {
7970 * It's from a TCP segment.
7972 * if !visited, check want_pdu_tracking and store it
7975 if(tcpd
&& (!pinfo
->fd
->visited
) && tcp_analyze_seq
&& pinfo
->want_pdu_tracking
) {
7977 pdu_store_sequencenumber_of_next_pdu(pinfo
,
7979 nxtseq
+pinfo
->bytes_until_next_pdu
,
7980 tcpd
->fwd
->multisegment_pdus
);
7990 dissect_tcp_payload(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, uint32_t seq
,
7991 uint32_t nxtseq
, uint32_t sport
, uint32_t dport
,
7992 proto_tree
*tree
, proto_tree
*tcp_tree
,
7993 struct tcp_analysis
*tcpd
, struct tcpinfo
*tcpinfo
)
7996 bool save_fragmented
;
7998 nbytes
= tvb_reported_length_remaining(tvb
, offset
);
7999 proto_tree_add_bytes_format(tcp_tree
, hf_tcp_payload
, tvb
, offset
,
8000 -1, NULL
, "TCP payload (%u byte%s)", nbytes
,
8001 plurality(nbytes
, "", "s"));
8003 /* Can we desegment this segment? */
8004 if (pinfo
->can_desegment
) {
8006 desegment_tcp(tvb
, pinfo
, offset
, seq
, nxtseq
, sport
, dport
, tree
,
8007 tcp_tree
, tcpd
, tcpinfo
);
8009 /* No - just call the subdissector.
8010 Mark this as fragmented, so if somebody throws an exception,
8011 we don't report it as a malformed frame. */
8012 save_fragmented
= pinfo
->fragmented
;
8013 pinfo
->fragmented
= true;
8015 process_tcp_payload(tvb
, offset
, pinfo
, tree
, tcp_tree
, sport
, dport
,
8016 seq
, nxtseq
, true, tcpd
, tcpinfo
);
8017 pinfo
->fragmented
= save_fragmented
;
8022 capture_tcp(const unsigned char *pd
, int offset
, int len
, capture_packet_info_t
*cpinfo
, const union wtap_pseudo_header
*pseudo_header
)
8024 uint16_t src_port
, dst_port
, low_port
, high_port
;
8026 if (!BYTES_ARE_IN_FRAME(offset
, len
, 4))
8029 capture_dissector_increment_count(cpinfo
, proto_tcp
);
8031 src_port
= pntoh16(&pd
[offset
]);
8032 dst_port
= pntoh16(&pd
[offset
+2]);
8034 if (src_port
> dst_port
) {
8035 low_port
= dst_port
;
8036 high_port
= src_port
;
8038 low_port
= src_port
;
8039 high_port
= dst_port
;
8042 if (low_port
!= 0 &&
8043 try_capture_dissector("tcp.port", low_port
, pd
, offset
+20, len
, cpinfo
, pseudo_header
))
8046 if (high_port
!= 0 &&
8047 try_capture_dissector("tcp.port", high_port
, pd
, offset
+20, len
, cpinfo
, pseudo_header
))
8050 /* We've at least identified one type of packet, so this shouldn't be "other" */
8054 typedef struct _tcp_tap_cleanup_t
{
8057 struct tcpheader
*tcph
;
8059 } tcp_tap_cleanup_t
;
8061 static void tcp_tap_cleanup(void *data
)
8063 tcp_tap_cleanup_t
*cleanup
= (tcp_tap_cleanup_t
*)data
;
8065 tap_queue_packet(tcp_tap
, cleanup
->pinfo
, cleanup
->tcph
);
8069 dissect_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
8071 uint8_t th_off_x2
; /* combines th_off and th_x2 */
8074 proto_tree
*tcp_tree
= NULL
, *field_tree
= NULL
;
8075 proto_item
*ti
= NULL
, *tf
, *hidden_item
;
8076 proto_item
*options_item
, *hide_seqack_abs_item
;
8077 proto_tree
*options_tree
;
8079 char *flags_str
, *flags_str_first_letter
;
8081 uint32_t nxtseq
= 0;
8082 unsigned reported_len
;
8085 uint16_t computed_cksum
;
8086 uint16_t real_window
;
8087 unsigned captured_length_remaining
;
8089 struct tcpinfo tcpinfo
;
8090 struct tcpheader
*tcph
;
8091 proto_item
*tf_syn
= NULL
, *tf_fin
= NULL
, *tf_rst
= NULL
, *scaled_pi
;
8092 conversation_t
*conv
=NULL
;
8093 struct tcp_analysis
*tcpd
=NULL
;
8094 struct tcp_per_packet_data_t
*tcppd
=NULL
;
8096 proto_tree
*checksum_tree
;
8097 bool icmp_ip
= false;
8098 uint8_t conversation_completeness
= 0;
8099 bool conversation_is_new
= false;
8102 tcph
= wmem_new0(pinfo
->pool
, struct tcpheader
);
8103 tcph
->th_sport
= tvb_get_ntohs(tvb
, offset
);
8104 tcph
->th_dport
= tvb_get_ntohs(tvb
, offset
+ 2);
8105 copy_address_shallow(&tcph
->ip_src
, &pinfo
->src
);
8106 copy_address_shallow(&tcph
->ip_dst
, &pinfo
->dst
);
8108 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TCP");
8109 col_clear(pinfo
->cinfo
, COL_INFO
);
8110 col_append_ports(pinfo
->cinfo
, COL_INFO
, PT_TCP
, tcph
->th_sport
, tcph
->th_dport
);
8113 ti
= proto_tree_add_item(tree
, proto_tcp
, tvb
, 0, -1, ENC_NA
);
8114 if (tcp_summary_in_tree
) {
8115 proto_item_append_text(ti
, ", Src Port: %s, Dst Port: %s",
8116 port_with_resolution_to_str(pinfo
->pool
, PT_TCP
, tcph
->th_sport
),
8117 port_with_resolution_to_str(pinfo
->pool
, PT_TCP
, tcph
->th_dport
));
8119 tcp_tree
= proto_item_add_subtree(ti
, ett_tcp
);
8120 p_add_proto_data(pinfo
->pool
, pinfo
, proto_tcp
, pinfo
->curr_layer_num
, tcp_tree
);
8122 proto_tree_add_item(tcp_tree
, hf_tcp_srcport
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
8123 proto_tree_add_item(tcp_tree
, hf_tcp_dstport
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
8124 hidden_item
= proto_tree_add_item(tcp_tree
, hf_tcp_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
8125 proto_item_set_hidden(hidden_item
);
8126 hidden_item
= proto_tree_add_item(tcp_tree
, hf_tcp_port
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
8127 proto_item_set_hidden(hidden_item
);
8129 /* If we're dissecting the headers of a TCP packet in an ICMP packet
8130 * then go ahead and put the sequence numbers in the tree now (because
8131 * they won't be put in later because the ICMP packet only contains up
8132 * to the sequence number).
8133 * We should only need to do this for IPv4 since IPv6 will hopefully
8134 * carry enough TCP payload for this dissector to put the sequence
8135 * numbers in via the regular code path.
8138 wmem_list_frame_t
*frame
;
8139 frame
= wmem_list_frame_prev(wmem_list_tail(pinfo
->layers
));
8140 if (proto_ip
== (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame
))) {
8141 frame
= wmem_list_frame_prev(frame
);
8142 if (proto_icmp
== (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame
))) {
8143 proto_tree_add_item(tcp_tree
, hf_tcp_seq
, tvb
, offset
+ 4, 4, ENC_BIG_ENDIAN
);
8150 /* Set the source and destination port numbers as soon as we get them,
8151 so that they're available to the "Follow TCP Stream" code even if
8152 we throw an exception dissecting the rest of the TCP header. */
8153 pinfo
->ptype
= PT_TCP
;
8154 pinfo
->srcport
= tcph
->th_sport
;
8155 pinfo
->destport
= tcph
->th_dport
;
8157 p_add_proto_data(pinfo
->pool
, pinfo
, hf_tcp_srcport
, pinfo
->curr_layer_num
, GUINT_TO_POINTER(tcph
->th_sport
));
8158 p_add_proto_data(pinfo
->pool
, pinfo
, hf_tcp_dstport
, pinfo
->curr_layer_num
, GUINT_TO_POINTER(tcph
->th_dport
));
8160 tcph
->th_rawseq
= tvb_get_ntohl(tvb
, offset
+ 4);
8161 tcph
->th_seq
= tcph
->th_rawseq
;
8162 tcph
->th_rawack
= tvb_get_ntohl(tvb
, offset
+ 8);
8163 tcph
->th_ack
= tcph
->th_rawack
;
8164 th_off_x2
= tvb_get_uint8(tvb
, offset
+ 12);
8165 tcpinfo
.flags
= tcph
->th_flags
= tvb_get_ntohs(tvb
, offset
+ 12) & TH_MASK
;
8166 tcph
->th_hlen
= hi_nibble(th_off_x2
) * 4; /* TCP header length, in bytes */
8168 /* find(or create if needed) the conversation for this tcp session
8169 * This is a slight deviation from find_or_create_conversation so it's
8170 * done manually. This is done to avoid conversation overlapping when
8171 * reusing ports (see issue 15097), as find_or_create_conversation automatically
8172 * extends the conversation found. This extension is done later.
8175 conv
= find_conversation_strat(pinfo
, CONVERSATION_TCP
, 0);
8177 conv
=conversation_new_strat(pinfo
, CONVERSATION_TCP
, 0);
8178 conversation_is_new
= true;
8181 tcpd
=get_tcp_conversation_data(conv
,pinfo
);
8183 if (!PINFO_FD_VISITED(pinfo
)) {
8184 /* If this is a SYN packet, then check if its seq-nr is different
8185 * from the base_seq of the retrieved conversation. If this is the
8186 * case, create a new conversation with the same addresses and ports
8187 * and set the TA_PORTS_REUSED flag. (XXX: There is a small chance
8188 * that this is an old duplicate SYN received after the connection
8189 * is ESTABLISHED on both sides, the other side will respond with
8190 * an appropriate ACK, and this SYN ought to be ignored rather than
8191 * create a new conversation.)
8193 * If the seq-nr is the same as the base_seq, it might be a simple
8194 * retransmission, reattempting a handshake that was reset (due
8195 * to a half-open connection) with the same sequence number, or
8196 * (unlikely) a new connection that happens to use the same sequence
8197 * number as the previous one (#18333).
8199 * If we have received a RST or FIN on the retrieved conversation,
8200 * we can detect that unlikely case, and create a new conversation
8201 * in order to clear out the follow info, sequence analysis,
8202 * desegmentation, etc.
8203 * If not, it's probably a retransmission, and will be marked
8204 * as one later, but restore some flow values to reduce the
8205 * sequence analysis warnings if our capture file is missing a RST
8206 * or FIN segment that was present on the network.
8208 * XXX - Is this affected by MPTCP which can use multiple SYNs?
8210 if (tcpd
!= NULL
&& (tcph
->th_flags
& (TH_SYN
|TH_ACK
)) == TH_SYN
) {
8211 if (tcpd
->fwd
->static_flags
& TCP_S_BASE_SEQ_SET
) {
8212 if(tcph
->th_seq
!=tcpd
->fwd
->base_seq
|| (tcpd
->conversation_completeness
& TCP_COMPLETENESS_RST
) || (tcpd
->conversation_completeness
& TCP_COMPLETENESS_FIN
)) {
8213 conv
=conversation_new_strat(pinfo
, CONVERSATION_TCP
, 0);
8214 tcpd
=get_tcp_conversation_data(conv
,pinfo
);
8217 tcp_analyze_get_acked_struct(pinfo
->num
, tcph
->th_seq
, tcph
->th_ack
, true, tcpd
);
8218 tcpd
->ta
->flags
|=TCP_A_REUSED_PORTS
;
8220 /* As above, a new conversation starting with a SYN implies conversation completeness value 1 */
8221 conversation_is_new
= true;
8224 * Sometimes we need to restore the nextseq value.
8225 * As stated in RFC 793 3.4 a RST packet might be
8226 * sent with SEQ being equal to the ACK received,
8227 * thus breaking our flow monitoring. (issue 17616)
8229 if(tcp_analyze_seq
&& tcpd
->fwd
->tcp_analyze_seq_info
) {
8230 tcpd
->fwd
->tcp_analyze_seq_info
->nextseq
= tcpd
->fwd
->tcp_analyze_seq_info
->maxseqtobeacked
;
8234 tcp_analyze_get_acked_struct(pinfo
->num
, tcph
->th_seq
, tcph
->th_ack
, true, tcpd
);
8238 * TCP_S_BASE_SEQ_SET being not set, we are dealing with a new conversation,
8239 * either created ad hoc above (general case), or by a higher protocol such as FTP.
8240 * Track this information, as the Completeness value will be initialized later.
8243 conversation_is_new
= true;
8245 tcpd
->had_acc_ecn_setup_syn
= (tcph
->th_flags
& (TH_AE
|TH_CWR
|TH_ECE
)) == (TH_AE
|TH_CWR
|TH_ECE
);
8248 /* Handle cases of a SYN/ACK packet where there's evidence of a new
8249 * conversation but the capture is missing the SYN packet of the
8252 * If this is a SYN/ACK packet, then check if its seq-nr is different
8253 * from the base_seq of the retrieved conversation. If this is the
8254 * case, create a new conversation as above with a SYN packet, and set
8255 * the TA_PORTS_REUSED flag and override the base seq.
8256 * If the seq-nr is the same as the base_seq, then do nothing so it
8257 * will be marked as a retransmission later, unless we have received
8258 * a RST or FIN on the conversation (in which case this is the case
8259 * of a RST followed by the same initial sequence number being picked.)
8261 * If this is an unacceptable SYN-ACK and the other side believes that
8262 * the conversation is ESTABLISHED, it will be replied to with an
8263 * empty ACK with the current sequence number (according to the other
8264 * side.) See RFC 9293 3.5.2. This *probably* leads to a situation where
8265 * the side sending this SYN-ACK then issues a RST, because the two
8266 * sides have different ideas about the connection state. It's not clear
8267 * how to handle the annoying edge case where A sends a SYN, B responds
8268 * with a SYN-ACK that A intends to accept, but before A can finish
8269 * the handshake B responds with another SYN-ACK _with a different seq-nr_
8270 * instead of retransmitting, then A responds accepting the first SYN-ACK,
8271 * and then B goes on happily using the sequence number from the first
8272 * SYN-ACK, forgetting all about the second one it sent instead of sending
8273 * a RST. In such a case we'll have changed the seq-nr to the new one
8274 * and/or set up a new conversation instead of just ignoring that SYN-ACK.
8276 * XXX - Is this affected by MPTCP which can use multiple SYNs?
8278 if (tcpd
!= NULL
&& (tcph
->th_flags
& (TH_SYN
|TH_ACK
)) == (TH_SYN
|TH_ACK
)) {
8279 if ((tcpd
->fwd
->static_flags
& TCP_S_BASE_SEQ_SET
) &&
8280 (tcph
->th_seq
!= tcpd
->fwd
->base_seq
||
8281 (tcpd
->conversation_completeness
& TCP_COMPLETENESS_RST
) ||
8282 (tcpd
->conversation_completeness
& TCP_COMPLETENESS_FIN
))) {
8283 /* the retrieved conversation might have a different base_seq (issue 16944) */
8285 conv
=conversation_new_strat(pinfo
, CONVERSATION_TCP
, 0);
8286 tcpd
=get_tcp_conversation_data(conv
,pinfo
);
8289 tcp_analyze_get_acked_struct(pinfo
->num
, tcph
->th_seq
, tcph
->th_ack
, true, tcpd
);
8290 tcpd
->ta
->flags
|=TCP_A_REUSED_PORTS
;
8292 /* As above, a new conversation */
8293 conversation_is_new
= true;
8295 tcpd
->had_acc_ecn_setup_syn_ack
= ((tcph
->th_flags
& (TH_AE
|TH_CWR
)) == TH_CWR
) ||
8296 ((tcph
->th_flags
& (TH_AE
|TH_ECE
)) == TH_AE
);
8299 /* Do we need to calculate timestamps relative to the tcp-stream? */
8300 if (tcp_calculate_ts
) {
8301 tcppd
= (struct tcp_per_packet_data_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_tcp
, pinfo
->curr_layer_num
);
8303 /* Calculate the timestamps relative to this conversation */
8304 tcp_calculate_timestamps(pinfo
, tcpd
, tcppd
);
8309 item
= proto_tree_add_uint(tcp_tree
, hf_tcp_stream
, tvb
, offset
, 0, tcpd
->stream
);
8310 proto_item_set_generated(item
);
8311 tcpinfo
.stream
= tcpd
->stream
;
8314 item
= proto_tree_add_uint(tcp_tree
, hf_tcp_stream_pnum
, tvb
, offset
, 0, tcppd
->pnum
);
8315 proto_item_set_generated(item
);
8318 /* Display the completeness of this TCP conversation */
8319 static int* const completeness_fields
[] = {
8320 &hf_tcp_completeness_rst
,
8321 &hf_tcp_completeness_fin
,
8322 &hf_tcp_completeness_data
,
8323 &hf_tcp_completeness_ack
,
8324 &hf_tcp_completeness_syn_ack
,
8325 &hf_tcp_completeness_syn
,
8328 item
= proto_tree_add_bitmask_value_with_flags(tcp_tree
, NULL
, 0,
8329 hf_tcp_completeness
, ett_tcp_completeness
, completeness_fields
,
8330 tcpd
->conversation_completeness
, BMT_NO_APPEND
);
8331 proto_item_set_generated(item
);
8332 field_tree
= proto_item_add_subtree(item
, ett_tcp_completeness
);
8334 flags_str_first_letter
= tcpd
->conversation_completeness_str
;
8335 item
= proto_tree_add_string(field_tree
, hf_tcp_completeness_str
, tvb
, 0, 0, flags_str_first_letter
);
8336 proto_item_set_generated(item
);
8338 /* Copy the stream index into the header as well to make it available
8341 tcph
->th_stream
= tcpd
->stream
;
8343 /* Copy the stream index into pinfo as well to make it available
8344 * to callback functions (essentially conversation following events in GUI)
8346 pinfo
->stream_id
= tcpd
->stream
;
8348 /* initialize the SACK blocks seen to 0 */
8349 if(tcp_analyze_seq
&& tcpd
->fwd
->tcp_analyze_seq_info
) {
8350 tcpd
->fwd
->tcp_analyze_seq_info
->num_sack_ranges
= 0;
8354 /* is there any manual analysis waiting ? */
8355 if(pinfo
->fd
->tcp_snd_manual_analysis
> 0) {
8356 tcppd
= (struct tcp_per_packet_data_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_tcp
, pinfo
->curr_layer_num
);
8357 tcppd
->tcp_snd_manual_analysis
= pinfo
->fd
->tcp_snd_manual_analysis
;
8360 /* We have have the absolute sequence numbers (we would have thrown an
8361 * exception if not) and tcpd, so set relative sequence numbers now. */
8363 /* XXX - Why not in an error packet? */
8364 if (tcpd
!= NULL
&& !pinfo
->flags
.in_error_pkt
) {
8365 /* initialize base_seq numbers if needed */
8366 if (!(pinfo
->fd
->visited
)) {
8367 /* if this is the first segment for this list we need to store the
8369 * We use TCP_S_SAW_SYN/SYNACK to distinguish between client and server
8371 * Start relative seq and ack numbers at 1 if this
8372 * is not a SYN packet. This makes the relative
8373 * seq/ack numbers to be displayed correctly in the
8374 * event that the SYN or SYN/ACK packet is not seen
8375 * (this solves bug 1542)
8377 if( !(tcpd
->fwd
->static_flags
& TCP_S_BASE_SEQ_SET
)) {
8378 if(tcph
->th_flags
& TH_SYN
) {
8379 tcpd
->fwd
->base_seq
= tcph
->th_seq
;
8380 tcpd
->fwd
->static_flags
|= (tcph
->th_flags
& TH_ACK
) ? TCP_S_SAW_SYNACK
: TCP_S_SAW_SYN
;
8383 tcpd
->fwd
->base_seq
= tcph
->th_seq
-1;
8385 tcpd
->fwd
->static_flags
|= TCP_S_BASE_SEQ_SET
;
8388 /* Only store reverse sequence if this isn't the SYN
8389 * There's no guarantee that the ACK field of a SYN
8390 * contains zeros; get the ISN from the first segment
8391 * with the ACK bit set instead (usually the SYN/ACK).
8393 * If the SYN and SYN/ACK were received out-of-order,
8394 * the ISN is ack-1. If we missed the SYN/ACK, but got
8395 * the last ACK of the 3WHS, the ISN is ack-1. For all
8396 * other packets the ISN is unknown, so ack-1 is
8397 * as good a guess as ack.
8399 if( !(tcpd
->rev
->static_flags
& TCP_S_BASE_SEQ_SET
) && (tcph
->th_flags
& TH_ACK
) ) {
8400 tcpd
->rev
->base_seq
= tcph
->th_ack
-1;
8401 tcpd
->rev
->static_flags
|= TCP_S_BASE_SEQ_SET
;
8404 if (tcp_analyze_seq
&& tcp_relative_seq
) {
8405 tcph
->th_seq
-= tcpd
->fwd
->base_seq
;
8406 if (tcph
->th_flags
& TH_ACK
) {
8407 tcph
->th_ack
-= tcpd
->rev
->base_seq
;
8413 * If we've been handed an IP fragment, we don't know how big the TCP
8414 * segment is, so don't do anything that requires that we know that.
8416 * The same applies if we're part of an error packet. (XXX - if the
8417 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
8418 * header says it is" length in the tvbuff, we could use that; such
8419 * a length might also be useful for handling packets where the IP
8420 * length is bigger than the actual data available in the frame; the
8421 * dissectors should trust that length, and then throw a
8422 * ReportedBoundsError exception when they go past the end of the frame.)
8424 * We also can't determine the segment length if the reported length
8425 * of the TCP packet is less than the TCP header length.
8427 reported_len
= tvb_reported_length(tvb
);
8429 if (!pinfo
->fragmented
&& !pinfo
->flags
.in_error_pkt
) {
8430 if (reported_len
< tcph
->th_hlen
) {
8431 proto_tree_add_expert_format(tcp_tree
, pinfo
, &ei_tcp_short_segment
, tvb
, offset
, 0,
8432 "Short segment. Segment/fragment does not contain a full TCP header"
8433 " (might be NMAP or someone else deliberately sending unusual packets)");
8434 tcph
->th_have_seglen
= false;
8438 /* Compute the length of data in this segment. */
8439 tcph
->th_seglen
= reported_len
- tcph
->th_hlen
;
8440 tcph
->th_have_seglen
= true;
8442 pi
= proto_tree_add_uint(ti
, hf_tcp_len
, tvb
, 0, 0, tcph
->th_seglen
);
8443 proto_item_set_generated(pi
);
8445 /* handle TCP seq# analysis parse all new segments we see */
8446 /* We need the window size to perform sequence analysis.
8447 * (Zero is a possible value treated specially. */
8448 if(tcp_analyze_seq
&& tvb_bytes_exist(tvb
, offset
+ 14, 2)) {
8450 /* Get it on every pass so that dissection is the same. */
8451 tcph
->th_win
= tvb_get_ntohs(tvb
, offset
+ 14);
8453 if(!(pinfo
->fd
->visited
)) {
8454 tcp_analyze_sequence_number(pinfo
, tcph
->th_rawseq
, tcph
->th_rawack
, tcph
->th_seglen
, tcph
->th_flags
, tcph
->th_win
, tcpd
, tcppd
);
8458 /* Compute the sequence number of next octet after this segment. */
8459 nxtseq
= tcph
->th_seq
+ tcph
->th_seglen
;
8462 tcph
->th_have_seglen
= false;
8465 * Decode the ECN related flags as ACE if it is not a SYN segment,
8466 * and an AccECN-setup SYN and SYN ACK have been observed, or an
8467 * AccECN option was observed (this covers the case where Wireshark
8468 * did not observe the initial handshake).
8470 tcph
->th_use_ace
= (tcph
->th_flags
& TH_SYN
) == 0 &&
8472 ((tcpd
->had_acc_ecn_setup_syn
&& tcpd
->had_acc_ecn_setup_syn_ack
) ||
8473 tcpd
->had_acc_ecn_option
);
8474 flags_str
= tcp_flags_to_str(pinfo
->pool
, tcph
);
8475 flags_str_first_letter
= tcp_flags_to_str_first_letter(pinfo
->pool
, tcph
);
8477 col_append_lstr(pinfo
->cinfo
, COL_INFO
,
8478 " [", flags_str
, "]",
8479 COL_ADD_LSTR_TERMINATOR
);
8480 tcp_info_append_uint(pinfo
, "Seq", tcph
->th_seq
);
8481 if (tcph
->th_flags
&TH_ACK
)
8482 tcp_info_append_uint(pinfo
, "Ack", tcph
->th_ack
);
8484 if (tcp_summary_in_tree
) {
8485 proto_item_append_text(ti
, ", Seq: %u", tcph
->th_seq
);
8489 if(tcp_relative_seq
&& tcp_analyze_seq
) {
8490 proto_tree_add_uint_format_value(tcp_tree
, hf_tcp_seq
, tvb
, offset
+ 4, 4, tcph
->th_seq
, "%u (relative sequence number)", tcph
->th_seq
);
8491 item
= proto_tree_add_uint(tcp_tree
, hf_tcp_seq_abs
, tvb
, offset
+ 4, 4, tcph
->th_rawseq
);
8492 if (read_seq_as_syn_cookie
) {
8493 proto_item
* syncookie_ti
= NULL
;
8494 proto_item_append_text(item
, " (syn cookie)");
8495 syncookie_ti
= proto_item_add_subtree(item
, ett_tcp_syncookie
);
8496 proto_tree_add_bits_item(syncookie_ti
, hf_tcp_syncookie_time
, tvb
, (offset
+ 4) * 8, 5, ENC_NA
);
8497 proto_tree_add_bits_item(syncookie_ti
, hf_tcp_syncookie_mss
, tvb
, (offset
+ 4) * 8 + 5, 3, ENC_NA
);
8498 proto_tree_add_item(syncookie_ti
, hf_tcp_syncookie_hash
, tvb
, offset
+ 4 + 1, 3, ENC_NA
);
8502 proto_tree_add_uint(tcp_tree
, hf_tcp_seq
, tvb
, offset
+ 4, 4, tcph
->th_seq
);
8503 hide_seqack_abs_item
= proto_tree_add_uint(tcp_tree
, hf_tcp_seq_abs
, tvb
, offset
+ 4, 4, tcph
->th_rawseq
);
8504 proto_item_set_hidden(hide_seqack_abs_item
);
8508 if (tcph
->th_hlen
< TCPH_MIN_LEN
) {
8509 /* Give up at this point; we put the source and destination port in
8510 the tree, before fetching the header length, so that they'll
8511 show up if this is in the failing packet in an ICMP error packet,
8512 but it's now time to give up if the header length is bogus. */
8513 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", bogus TCP header length (%u, must be at least %u)",
8514 tcph
->th_hlen
, TCPH_MIN_LEN
);
8516 tf
= proto_tree_add_uint_bits_format_value(tcp_tree
, hf_tcp_hdr_len
, tvb
, (offset
+ 12) << 3, 4, tcph
->th_hlen
,
8517 ENC_BIG_ENDIAN
, "%u bytes (%u)", tcph
->th_hlen
, tcph
->th_hlen
>> 2);
8518 expert_add_info_format(pinfo
, tf
, &ei_tcp_bogus_header_length
,
8519 "Bogus TCP header length (%u, must be at least %u)", tcph
->th_hlen
, TCPH_MIN_LEN
);
8523 /* Now we certainly have enough information to be willing to send
8524 * the header information to the tap. The options can add information
8525 * about the SACKs, but the other taps don't really *require* that.
8526 * Add a CLEANUP function so that the tap_queue_packet gets called
8527 * if any exception is thrown.
8529 * XXX - We haven't necessarily retrieved the window size yet. We'll
8530 * try to do so before sending it to the tap, but if the header is
8531 * truncated to 14 octets, the taps will receive a window size of 0.
8532 * Can they handle it with minimal problems?
8535 tcp_tap_cleanup_t
*cleanup
= wmem_new(pinfo
->pool
, tcp_tap_cleanup_t
);
8536 cleanup
->pinfo
= pinfo
;
8537 cleanup
->tcph
= tcph
;
8538 CLEANUP_PUSH(tcp_tap_cleanup
, cleanup
);
8540 /* initialize or move forward the conversation completeness */
8542 if(conversation_is_new
) { /* pure SYN must be sought in new conversations only */
8543 if((tcph
->th_flags
&(TH_SYN
|TH_ACK
))==TH_SYN
) {
8544 conversation_completeness
|= TCP_COMPLETENESS_SYNSENT
;
8545 if(tcph
->th_seglen
> 0) { /* TCP Fast Open */
8546 conversation_completeness
|= TCP_COMPLETENESS_DATA
;
8551 /* Explicitly and immediately move forward the conversation last_frame,
8552 * although it would one way or another be changed later
8553 * in the conversation helper functions.
8555 if (!(pinfo
->fd
->visited
)) {
8556 if (pinfo
->num
> conv
->last_frame
) {
8557 conv
->last_frame
= pinfo
->num
;
8561 conversation_completeness
= tcpd
->conversation_completeness
;
8565 if((tcph
->th_flags
&(TH_SYN
|TH_ACK
))==(TH_SYN
|TH_ACK
)) {
8566 conversation_completeness
|= TCP_COMPLETENESS_SYNACK
;
8570 if((tcph
->th_flags
&(TH_SYN
|TH_ACK
))==(TH_ACK
)) {
8571 if(tcph
->th_seglen
>0) { /* transporting some data */
8572 conversation_completeness
|= TCP_COMPLETENESS_DATA
;
8574 else { /* pure ACK */
8575 conversation_completeness
|= TCP_COMPLETENESS_ACK
;
8580 if((tcph
->th_flags
&(TH_FIN
|TH_ACK
))==(TH_FIN
|TH_ACK
)) {
8581 conversation_completeness
|= TCP_COMPLETENESS_FIN
;
8585 /* XXX: A RST segment should be validated (RFC 9293 3.5.3),
8586 * and if not valid should not change the conversation state.
8588 if(tcph
->th_flags
&(TH_RST
)) {
8589 conversation_completeness
|= TCP_COMPLETENESS_RST
;
8592 /* Store the completeness at the conversation level,
8593 * both as numerical and as Flag First Letters string, to avoid
8594 * computing many times the same thing.
8596 if (tcpd
->conversation_completeness
) {
8597 if (tcpd
->conversation_completeness
!= conversation_completeness
) {
8598 tcpd
->conversation_completeness
= conversation_completeness
;
8599 tcpd
->conversation_completeness_str
= completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd
->conversation_completeness
) ;
8603 tcpd
->conversation_completeness
= conversation_completeness
;
8604 tcpd
->conversation_completeness_str
= completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd
->conversation_completeness
) ;
8608 if (tcp_summary_in_tree
) {
8609 if(tcph
->th_flags
&TH_ACK
) {
8610 proto_item_append_text(ti
, ", Ack: %u", tcph
->th_ack
);
8612 if (tcph
->th_have_seglen
)
8613 proto_item_append_text(ti
, ", Len: %u", tcph
->th_seglen
);
8615 proto_item_set_len(ti
, tcph
->th_hlen
);
8616 if (tcph
->th_have_seglen
) {
8617 if(tcp_relative_seq
&& tcp_analyze_seq
) {
8618 if (tcph
->th_flags
&(TH_SYN
|TH_FIN
)) {
8619 tf
=proto_tree_add_uint_format_value(tcp_tree
, hf_tcp_nxtseq
, tvb
, offset
, 0, nxtseq
+ 1, "%u (relative sequence number)", nxtseq
+ 1);
8621 tf
=proto_tree_add_uint_format_value(tcp_tree
, hf_tcp_nxtseq
, tvb
, offset
, 0, nxtseq
, "%u (relative sequence number)", nxtseq
);
8624 if (tcph
->th_flags
&(TH_SYN
|TH_FIN
)) {
8625 tf
=proto_tree_add_uint(tcp_tree
, hf_tcp_nxtseq
, tvb
, offset
, 0, nxtseq
+ 1);
8627 tf
=proto_tree_add_uint(tcp_tree
, hf_tcp_nxtseq
, tvb
, offset
, 0, nxtseq
);
8630 proto_item_set_generated(tf
);
8633 tf
= proto_tree_add_uint(tcp_tree
, hf_tcp_ack
, tvb
, offset
+ 8, 4, tcph
->th_ack
);
8634 hide_seqack_abs_item
= proto_tree_add_uint(tcp_tree
, hf_tcp_ack_abs
, tvb
, offset
+ 8, 4, tcph
->th_rawack
);
8635 if (tcph
->th_flags
& TH_ACK
) {
8636 if (tcp_relative_seq
&& tcp_analyze_seq
) {
8637 proto_item_append_text(tf
, " (relative ack number)");
8639 proto_item_set_hidden(hide_seqack_abs_item
);
8641 if ((tcph
->th_flags
& TH_SYN
) && tcp_analyze_seq
) {
8642 if ((tcp_relative_seq
&& tcph
->th_ack
> 1) ||
8643 (!tcp_relative_seq
&& tcpd
&& (tcph
->th_ack
- tcpd
->rev
->base_seq
) > 1)) {
8644 expert_add_info(pinfo
, tf
, &ei_tcp_analysis_tfo_ack
);
8645 } else if (tcpd
&& tcpd
->tfo_syn_data
) {
8646 expert_add_info(pinfo
, tf
, &ei_tcp_analysis_tfo_ignored
);
8650 /* Note if the ACK field is non-zero */
8651 if (tvb_get_ntohl(tvb
, offset
+8) != 0) {
8652 expert_add_info(pinfo
, tf
, &ei_tcp_ack_nonzero
);
8657 // This should be consistent with ip.hdr_len.
8658 proto_tree_add_uint_bits_format_value(tcp_tree
, hf_tcp_hdr_len
, tvb
, (offset
+ 12) << 3, 4, tcph
->th_hlen
,
8659 ENC_BIG_ENDIAN
, "%u bytes (%u)", tcph
->th_hlen
, tcph
->th_hlen
>>2);
8660 tf
= proto_tree_add_uint_format(tcp_tree
, hf_tcp_flags
, tvb
, offset
+ 12, 2,
8661 tcph
->th_flags
, "Flags: 0x%03x (%s)", tcph
->th_flags
, flags_str
);
8662 field_tree
= proto_item_add_subtree(tf
, ett_tcp_flags
);
8663 proto_tree_add_boolean(field_tree
, hf_tcp_flags_res
, tvb
, offset
+ 12, 1, tcph
->th_flags
);
8664 if (tcph
->th_use_ace
) {
8665 ace
= tcp_get_ace(tcph
);
8666 proto_tree_add_uint_format(field_tree
, hf_tcp_flags_ace
, tvb
, 12, 2, ace
,
8667 "...%c %c%c.. .... = ACE: %u",
8668 ace
& 0x04 ? '1' : '0',
8669 ace
& 0x02 ? '1' : '0',
8670 ace
& 0x01 ? '1' : '0',
8673 proto_tree_add_boolean(field_tree
, hf_tcp_flags_ae
, tvb
, offset
+ 12, 1, tcph
->th_flags
);
8674 proto_tree_add_boolean(field_tree
, hf_tcp_flags_cwr
, tvb
, offset
+ 13, 1, tcph
->th_flags
);
8675 proto_tree_add_boolean(field_tree
, hf_tcp_flags_ece
, tvb
, offset
+ 13, 1, tcph
->th_flags
);
8677 proto_tree_add_boolean(field_tree
, hf_tcp_flags_urg
, tvb
, offset
+ 13, 1, tcph
->th_flags
);
8678 proto_tree_add_boolean(field_tree
, hf_tcp_flags_ack
, tvb
, offset
+ 13, 1, tcph
->th_flags
);
8679 proto_tree_add_boolean(field_tree
, hf_tcp_flags_push
, tvb
, offset
+ 13, 1, tcph
->th_flags
);
8680 tf_rst
= proto_tree_add_boolean(field_tree
, hf_tcp_flags_reset
, tvb
, offset
+ 13, 1, tcph
->th_flags
);
8681 tf_syn
= proto_tree_add_boolean(field_tree
, hf_tcp_flags_syn
, tvb
, offset
+ 13, 1, tcph
->th_flags
);
8682 tf_fin
= proto_tree_add_boolean(field_tree
, hf_tcp_flags_fin
, tvb
, offset
+ 13, 1, tcph
->th_flags
);
8684 tf
= proto_tree_add_string(field_tree
, hf_tcp_flags_str
, tvb
, offset
+ 12, 2, flags_str_first_letter
);
8685 proto_item_set_generated(tf
);
8688 if(tcph
->th_flags
& TH_SYN
) {
8689 if(tcph
->th_flags
& TH_ACK
) {
8690 expert_add_info_format(pinfo
, tf_syn
, &ei_tcp_connection_synack
,
8691 "Connection establish acknowledge (SYN+ACK): server port %u", tcph
->th_sport
);
8692 /* Save the server port to help determine dissector used */
8693 tcpd
->server_port
= tcph
->th_sport
;
8696 expert_add_info_format(pinfo
, tf_syn
, &ei_tcp_connection_syn
,
8697 "Connection establish request (SYN): server port %u", tcph
->th_dport
);
8698 /* Save the server port to help determine dissector used */
8699 tcpd
->server_port
= tcph
->th_dport
;
8700 tcpd
->ts_mru_syn
= pinfo
->abs_ts
;
8702 /* Remember where the next segment will start. */
8703 if (tcp_desegment
&& tcp_reassemble_out_of_order
&& tcpd
&& !PINFO_FD_VISITED(pinfo
)) {
8704 if (tcpd
->fwd
->maxnextseq
== 0) {
8705 tcpd
->fwd
->maxnextseq
= tcph
->th_seq
+ 1;
8708 /* Initialize the is_first_ack */
8709 tcpd
->fwd
->is_first_ack
= true;
8711 if(tcph
->th_flags
& TH_FIN
) {
8712 /* XXX - find a way to know the server port and output only that one */
8713 expert_add_info(pinfo
, tf_fin
, &ei_tcp_connection_fin
);
8715 /* Track closing initiator.
8716 If it was not already closed by the reverse flow, it means we are the first */
8717 if(!tcpd
->rev
->closing_initiator
) {
8718 tcpd
->fwd
->closing_initiator
= true;
8719 expert_add_info(pinfo
, tf
, &ei_tcp_connection_fin_active
);
8721 expert_add_info(pinfo
, tf
, &ei_tcp_connection_fin_passive
);
8724 if(tcph
->th_flags
& TH_RST
){
8725 /* XXX - find a way to know the server port and output only that one */
8726 expert_add_info(pinfo
, tf_rst
, &ei_tcp_connection_rst
);
8730 && (tcph
->th_flags
& (TH_SYN
|TH_ACK
)) == TH_ACK
8731 && !nstime_is_zero(&tcpd
->ts_mru_syn
)
8732 && nstime_is_zero(&tcpd
->ts_first_rtt
)) {
8733 /* If all of the following:
8734 * - we care (the pref is set)
8735 * - this is a pure ACK
8736 * - we have a timestamp for the most-recently-transmitted SYN
8737 * - we haven't seen a pure ACK yet (no ts_first_rtt stored)
8738 * then assume it's the last part of the handshake and store the initial
8741 nstime_delta(&(tcpd
->ts_first_rtt
), &(pinfo
->abs_ts
), &(tcpd
->ts_mru_syn
));
8745 * Remember if we have already seen at least one ACK,
8746 * then we can neutralize the Window Scale side-effect at the beginning (issue 14690)
8749 && (tcph
->th_flags
& (TH_SYN
|TH_ACK
)) == TH_ACK
) {
8750 if(tcpd
->fwd
->is_first_ack
) {
8751 tcpd
->fwd
->is_first_ack
= false;
8755 tcph
->th_win
= tvb_get_ntohs(tvb
, offset
+ 14);
8756 real_window
= tcph
->th_win
;
8757 /* re-calculate window size based on scaling factor */
8758 if (!(tcph
->th_flags
&TH_SYN
)) { /* SYNs are never scaled */
8759 if (tcpd
&& (tcpd
->fwd
->win_scale
>=0)) {
8760 (tcph
->th_win
)<<=tcpd
->fwd
->win_scale
;
8762 else if (tcpd
&& (tcpd
->fwd
->win_scale
== -1)) {
8763 /* i.e. Unknown, but wasn't signalled with no scaling, so use preference setting instead! */
8764 if (tcp_default_window_scaling
>=0) {
8765 (tcph
->th_win
)<<=tcp_default_window_scaling
;
8770 tcp_info_append_uint(pinfo
, "Win", tcph
->th_win
);
8773 /* As discussed in bug 5541, it is better to use two separate
8774 * fields for the real and calculated window size.
8776 proto_tree_add_uint(tcp_tree
, hf_tcp_window_size_value
, tvb
, offset
+ 14, 2, real_window
);
8777 if(tcph
->th_flags
& TH_RST
){
8778 /* Check if the window value of this reset packet is in the NetScaler error code range */
8779 const char *tcp_ns_reset_window_error_descr
= try_val_to_str(real_window
, netscaler_reset_window_error_code_vals
);
8780 if (tcp_ns_reset_window_error_descr
!= NULL
) { /* If its in the Netscaler range, add tree */
8781 item
= proto_tree_add_string(tcp_tree
, hf_tcp_ns_reset_window_error_code
, tvb
,
8782 offset
+ 14, 2, tcp_ns_reset_window_error_descr
);
8783 proto_item_set_generated(item
);
8786 scaled_pi
= proto_tree_add_uint(tcp_tree
, hf_tcp_window_size
, tvb
, offset
+ 14, 2, tcph
->th_win
);
8787 proto_item_set_generated(scaled_pi
);
8789 if( !(tcph
->th_flags
&TH_SYN
) && tcpd
) {
8790 switch (tcpd
->fwd
->win_scale
) {
8795 int16_t win_scale
= tcpd
->fwd
->win_scale
;
8796 bool override_with_pref
= false;
8798 /* Use preference setting (if set) */
8799 if (tcp_default_window_scaling
!= WindowScaling_NotKnown
) {
8800 win_scale
= (1 << tcp_default_window_scaling
);
8801 override_with_pref
= true;
8804 scaled_pi
= proto_tree_add_int_format_value(tcp_tree
, hf_tcp_window_size_scalefactor
, tvb
, offset
+ 14, 2,
8805 win_scale
, "%d (%s)",
8807 (override_with_pref
) ? "missing - taken from preference" : "unknown");
8808 proto_item_set_generated(scaled_pi
);
8813 /* No window scaling used */
8814 scaled_pi
= proto_tree_add_int_format_value(tcp_tree
, hf_tcp_window_size_scalefactor
, tvb
, offset
+ 14, 2, tcpd
->fwd
->win_scale
, "%d (no window scaling used)", tcpd
->fwd
->win_scale
);
8815 proto_item_set_generated(scaled_pi
);
8819 /* Scaling from signalled value */
8820 scaled_pi
= proto_tree_add_int_format_value(tcp_tree
, hf_tcp_window_size_scalefactor
, tvb
, offset
+ 14, 2, 1<<tcpd
->fwd
->win_scale
, "%d", 1<<tcpd
->fwd
->win_scale
);
8821 proto_item_set_generated(scaled_pi
);
8826 /* Supply the sequence number of the first byte and of the first byte
8827 after the segment. */
8828 tcpinfo
.seq
= tcph
->th_seq
;
8829 tcpinfo
.nxtseq
= nxtseq
;
8830 tcpinfo
.lastackseq
= tcph
->th_ack
;
8832 /* Assume we'll pass un-reassembled data to subdissectors. */
8833 tcpinfo
.is_reassembled
= false;
8836 * Assume, initially, that we can't desegment.
8838 pinfo
->can_desegment
= 0;
8839 th_sum
= tvb_get_ntohs(tvb
, offset
+ 16);
8840 if (!pinfo
->fragmented
&& tvb_bytes_exist(tvb
, 0, reported_len
)) {
8841 /* The packet isn't part of an un-reassembled fragmented datagram
8842 and isn't truncated. This means we have all the data, and thus
8843 can checksum it and, unless it's being returned in an error
8844 packet, are willing to allow subdissectors to request reassembly
8847 if (tcp_check_checksum
) {
8848 /* We haven't turned checksum checking off; checksum it. */
8850 /* Set up the fields of the pseudo-header. */
8851 SET_CKSUM_VEC_PTR(cksum_vec
[0], (const uint8_t *)pinfo
->src
.data
, pinfo
->src
.len
);
8852 SET_CKSUM_VEC_PTR(cksum_vec
[1], (const uint8_t *)pinfo
->dst
.data
, pinfo
->dst
.len
);
8853 switch (pinfo
->src
.type
) {
8856 phdr
[0] = g_htonl((IP_PROTO_TCP
<<16) + reported_len
);
8857 SET_CKSUM_VEC_PTR(cksum_vec
[2], (const uint8_t *)phdr
, 4);
8861 phdr
[0] = g_htonl(reported_len
);
8862 phdr
[1] = g_htonl(IP_PROTO_TCP
);
8863 SET_CKSUM_VEC_PTR(cksum_vec
[2], (const uint8_t *)phdr
, 8);
8867 /* TCP runs only atop IPv4 and IPv6.... */
8868 DISSECTOR_ASSERT_NOT_REACHED();
8871 /* See discussion in packet-udp.c of partial checksums used in
8872 * checksum offloading in Linux and Windows (and possibly others.)
8874 uint16_t partial_cksum
;
8875 SET_CKSUM_VEC_TVB(cksum_vec
[3], tvb
, offset
, reported_len
);
8876 computed_cksum
= in_cksum_ret_partial(cksum_vec
, 4, &partial_cksum
);
8877 if (computed_cksum
== 0 && th_sum
== 0xffff) {
8878 item
= proto_tree_add_uint_format_value(tcp_tree
, hf_tcp_checksum
, tvb
,
8879 offset
+ 16, 2, th_sum
,
8880 "0x%04x [should be 0x0000 (see RFC 1624)]", th_sum
);
8882 checksum_tree
= proto_item_add_subtree(item
, ett_tcp_checksum
);
8883 item
= proto_tree_add_uint(checksum_tree
, hf_tcp_checksum_calculated
, tvb
,
8884 offset
+ 16, 2, 0x0000);
8885 proto_item_set_generated(item
);
8886 /* XXX - What should this special status be? */
8887 item
= proto_tree_add_uint(checksum_tree
, hf_tcp_checksum_status
, tvb
,
8888 offset
+ 16, 0, PROTO_CHECKSUM_E_BAD
);
8889 proto_item_set_generated(item
);
8890 expert_add_info(pinfo
, item
, &ei_tcp_checksum_ffff
);
8892 col_append_str(pinfo
->cinfo
, COL_INFO
, " [TCP CHECKSUM 0xFFFF]");
8894 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
8895 desegment_ok
= true;
8897 proto_item
* calc_item
;
8898 uint16_t shouldbe_cksum
= in_cksum_shouldbe(th_sum
, computed_cksum
);
8899 if (computed_cksum
!= 0 && th_sum
== g_htons(partial_cksum
)) {
8900 /* Don't use PROTO_CHECKSUM_IN_CKSUM because we expect the value
8901 * to match what we pass in. */
8902 item
= proto_tree_add_checksum(tcp_tree
, tvb
, offset
+16, hf_tcp_checksum
, hf_tcp_checksum_status
, &ei_tcp_checksum_bad
, pinfo
, g_htons(partial_cksum
),
8903 ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
);
8904 proto_item_append_text(item
, " (matches partial checksum, not 0x%04x, likely caused by \"TCP checksum offload\")", shouldbe_cksum
);
8905 expert_add_info(pinfo
, item
, &ei_tcp_checksum_partial
);
8907 /* XXX Add a new status, e.g. PROTO_CHECKSUM_E_PARTIAL? */
8909 item
= proto_tree_add_checksum(tcp_tree
, tvb
, offset
+16, hf_tcp_checksum
, hf_tcp_checksum_status
, &ei_tcp_checksum_bad
, pinfo
, computed_cksum
,
8910 ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
|PROTO_CHECKSUM_IN_CKSUM
);
8912 checksum_tree
= proto_item_add_subtree(item
, ett_tcp_checksum
);
8913 calc_item
= proto_tree_add_uint(checksum_tree
, hf_tcp_checksum_calculated
, tvb
,
8914 offset
+ 16, 2, shouldbe_cksum
);
8915 proto_item_set_generated(calc_item
);
8917 /* Checksum is valid, so we're willing to desegment it. */
8918 if (computed_cksum
== 0) {
8919 desegment_ok
= true;
8921 proto_item_append_text(item
, "(maybe caused by \"TCP checksum offload\"?)");
8923 /* Checksum is invalid, so we're not willing to desegment it. */
8924 desegment_ok
= false;
8925 pinfo
->noreassembly_reason
= " [incorrect TCP checksum]";
8926 col_append_str(pinfo
->cinfo
, COL_INFO
, " [TCP CHECKSUM INCORRECT]");
8930 proto_tree_add_checksum(tcp_tree
, tvb
, offset
+16, hf_tcp_checksum
, hf_tcp_checksum_status
, &ei_tcp_checksum_bad
, pinfo
, 0,
8931 ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
8933 /* We didn't check the checksum, and don't care if it's valid,
8934 so we're willing to desegment it. */
8935 desegment_ok
= true;
8938 /* We don't have all the packet data, so we can't checksum it... */
8939 proto_tree_add_checksum(tcp_tree
, tvb
, offset
+16, hf_tcp_checksum
, hf_tcp_checksum_status
, &ei_tcp_checksum_bad
, pinfo
, 0,
8940 ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
8942 /* ...and aren't willing to desegment it. */
8943 desegment_ok
= false;
8947 /* We're willing to desegment this. Is desegmentation enabled? */
8948 if (tcp_desegment
) {
8949 /* Yes - is this segment being returned in an error packet? */
8950 if (!pinfo
->flags
.in_error_pkt
) {
8951 /* No - indicate that we will desegment.
8952 We do NOT want to desegment segments returned in error
8953 packets, as they're not part of a TCP connection. */
8954 pinfo
->can_desegment
= 2;
8959 item
= proto_tree_add_item_ret_uint(tcp_tree
, hf_tcp_urgent_pointer
, tvb
, offset
+ 18, 2, ENC_BIG_ENDIAN
, &th_urp
);
8961 if (IS_TH_URG(tcph
->th_flags
)) {
8962 /* Export the urgent pointer, for the benefit of protocols such as
8964 tcpinfo
.urgent_pointer
= (uint16_t)th_urp
;
8965 tcp_info_append_uint(pinfo
, "Urg", th_urp
);
8968 /* Note if the urgent pointer field is non-zero */
8969 expert_add_info(pinfo
, item
, &ei_tcp_urgent_pointer_non_zero
);
8973 if (tcph
->th_have_seglen
)
8974 tcp_info_append_uint(pinfo
, "Len", tcph
->th_seglen
);
8976 /* If there's more than just the fixed-length header (20 bytes), create
8977 a protocol tree item for the options. (We already know there's
8978 not less than the fixed-length header - we checked that above.)
8980 We ensure that we don't throw an exception here, so that we can
8981 do some analysis before we dissect the options and possibly
8982 throw an exception. (Trying to avoid throwing an exception when
8983 dissecting options is not something we should do.) */
8984 optlen
= tcph
->th_hlen
- TCPH_MIN_LEN
; /* length of options, in bytes */
8985 options_item
= NULL
;
8986 options_tree
= NULL
;
8988 unsigned bc
= (unsigned)tvb_captured_length_remaining(tvb
, offset
+ 20);
8990 if (tcp_tree
!= NULL
) {
8991 options_item
= proto_tree_add_item(tcp_tree
, hf_tcp_options
, tvb
, offset
+ 20,
8992 bc
< optlen
? bc
: optlen
, ENC_NA
);
8993 proto_item_set_text(options_item
, "Options: (%u bytes)", optlen
);
8994 options_tree
= proto_item_add_subtree(options_item
, ett_tcp_options
);
8998 tcph
->num_sack_ranges
= 0;
9000 /* handle conversation timestamps */
9001 if(tcp_calculate_ts
) {
9002 tcp_print_timestamps(pinfo
, tvb
, tcp_tree
, tcpd
, tcppd
);
9005 /* Now dissect the options. */
9007 rvbd_option_data
* option_data
;
9009 tcp_dissect_options(tvb
, offset
+ 20, optlen
,
9010 pinfo
, options_tree
,
9011 options_item
, tcph
);
9013 /* Do some post evaluation of some Riverbed probe options in the list */
9014 option_data
= (rvbd_option_data
*)p_get_proto_data(pinfo
->pool
, pinfo
, proto_tcp_option_rvbd_probe
, pinfo
->curr_layer_num
);
9015 if (option_data
!= NULL
)
9017 if (option_data
->valid
)
9019 /* Distinguish S+ from S+* */
9020 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "S%s, ",
9021 option_data
->type
== PROBE_TRACE
? "#" :
9022 (option_data
->probe_flags
& RVBD_FLAGS_PROBE_NCFE
) ? "+*" : "+");
9028 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
9029 if(tcp_analyze_seq
) {
9030 uint32_t use_seq
= tcph
->th_seq
;
9031 uint32_t use_ack
= tcph
->th_ack
;
9032 /* May need to recover absolute values here... */
9033 if (tcp_relative_seq
) {
9034 use_seq
+= tcpd
->fwd
->base_seq
;
9035 if (tcph
->th_flags
& TH_ACK
) {
9036 use_ack
+= tcpd
->rev
->base_seq
;
9039 tcp_print_sequence_number_analysis(pinfo
, tvb
, tcp_tree
, tcpd
, use_seq
, use_ack
);
9042 if(!pinfo
->fd
->visited
) {
9043 if((tcph
->th_flags
& TH_SYN
)==TH_SYN
) {
9044 /* Check the validity of the window scale value
9046 verify_tcp_window_scaling((tcph
->th_flags
&TH_ACK
)==TH_ACK
,tcpd
);
9049 if((tcph
->th_flags
& (TH_SYN
|TH_ACK
))==(TH_SYN
|TH_ACK
)) {
9050 /* If the SYN or the SYN+ACK offered SCPS capabilities,
9051 * validate the flow's bidirectional scps capabilities.
9052 * The or protects against broken implementations offering
9053 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
9055 if(tcpd
&& ((tcpd
->rev
->scps_capable
) || (tcpd
->fwd
->scps_capable
))) {
9056 verify_scps(pinfo
, tf_syn
, tcpd
);
9062 if (tcph
->th_mptcp
) {
9064 if (tcp_analyze_mptcp
) {
9065 mptcp_add_analysis_subtree(pinfo
, tvb
, tcp_tree
, tcpd
, tcpd
->mptcp_analysis
, tcph
);
9069 /* Skip over header + options */
9070 offset
+= tcph
->th_hlen
;
9072 /* Check the packet length to see if there's more data
9073 (it could be an ACK-only packet) */
9074 captured_length_remaining
= tvb_captured_length_remaining(tvb
, offset
);
9076 if (tcph
->th_have_seglen
) {
9077 if(have_tap_listener(tcp_follow_tap
)) {
9078 tcp_follow_tap_data_t
* follow_data
= wmem_new0(pinfo
->pool
, tcp_follow_tap_data_t
);
9080 follow_data
->tvb
= tvb_new_subset_remaining(tvb
, offset
);
9081 follow_data
->tcph
= tcph
;
9082 follow_data
->tcpd
= tcpd
;
9084 tap_queue_packet(tcp_follow_tap
, pinfo
, follow_data
);
9088 /* Nothing more to add to tcph, go ahead and send to the taps. */
9089 CLEANUP_CALL_AND_POP
;
9091 /* if it is an MPTCP packet */
9092 if(tcpd
->mptcp_analysis
) {
9093 tap_queue_packet(mptcp_tap
, pinfo
, tcpd
);
9096 /* If we're reassembling something whose length isn't known
9097 * beforehand, and that runs all the way to the end of
9098 * the data stream, a FIN indicates the end of the data
9099 * stream and thus the completion of reassembly, so we
9100 * need to explicitly check for that here.
9102 if(tcph
->th_have_seglen
&& tcpd
&& (tcph
->th_flags
& TH_FIN
)
9103 && pinfo
->can_desegment
9104 && (tcpd
->fwd
->flags
&TCP_FLOW_REASSEMBLE_UNTIL_FIN
) ) {
9105 struct tcp_multisegment_pdu
*msp
;
9107 /* Is this the FIN that ended the data stream or is it a
9108 * retransmission of that FIN?
9110 if (tcpd
->fwd
->fin
== 0 || tcpd
->fwd
->fin
== pinfo
->num
) {
9111 /* Either we haven't seen a FIN for this flow or we
9112 * have and it's this frame. Note that this is the FIN
9113 * for this flow, terminate reassembly and dissect the
9115 tcpd
->fwd
->fin
= pinfo
->num
;
9116 msp
=(struct tcp_multisegment_pdu
*)wmem_tree_lookup32_le(tcpd
->fwd
->multisegment_pdus
, tcph
->th_seq
);
9118 fragment_head
*ipfd_head
;
9120 ipfd_head
= fragment_add(&tcp_reassembly_table
, tvb
, offset
,
9121 pinfo
, msp
->first_frame
, msp
,
9122 tcph
->th_seq
- msp
->seq
,
9125 if(ipfd_head
&& ipfd_head
->reassembled_in
== pinfo
->num
&& ipfd_head
->reas_in_layer_num
== pinfo
->curr_layer_num
) {
9128 /* create a new TVB structure for desegmented data
9129 * datalen-1 to strip the dummy FIN byte off
9131 next_tvb
= tvb_new_chain(tvb
, ipfd_head
->tvb_data
);
9133 /* add desegmented data to the data source list */
9134 add_new_data_source(pinfo
, next_tvb
, "Reassembled TCP");
9136 /* Show details of the reassembly */
9137 print_tcp_fragment_tree(ipfd_head
, tree
, tcp_tree
, pinfo
, next_tvb
);
9139 /* call the payload dissector
9140 * but make sure we don't offer desegmentation any more
9142 pinfo
->can_desegment
= 0;
9144 process_tcp_payload(next_tvb
, 0, pinfo
, tree
, tcp_tree
, tcph
->th_sport
, tcph
->th_dport
, tcph
->th_seq
,
9145 nxtseq
, false, tcpd
, &tcpinfo
);
9147 return tvb_captured_length(tvb
);
9151 /* Yes. This is a retransmission of the final FIN (or it's
9152 * the final FIN transmitted via a different path).
9153 * XXX - we need to flag retransmissions a bit better.
9155 proto_tree_add_uint(tcp_tree
, hf_tcp_fin_retransmission
, tvb
, 0, 0, tcpd
->fwd
->fin
);
9159 if (tcp_display_process_info
&& tcpd
&& ((tcpd
->fwd
&& tcpd
->fwd
->process_info
&& tcpd
->fwd
->process_info
->command
) ||
9160 (tcpd
->rev
&& tcpd
->rev
->process_info
&& tcpd
->rev
->process_info
->command
))) {
9161 field_tree
= proto_tree_add_subtree(tcp_tree
, tvb
, offset
, 0, ett_tcp_process_info
, &ti
, "Process Information");
9162 proto_item_set_generated(ti
);
9163 if (tcpd
->fwd
&& tcpd
->fwd
->process_info
&& tcpd
->fwd
->process_info
->command
) {
9164 proto_tree_add_uint(field_tree
, hf_tcp_proc_dst_uid
, tvb
, 0, 0, tcpd
->fwd
->process_info
->process_uid
);
9165 proto_tree_add_uint(field_tree
, hf_tcp_proc_dst_pid
, tvb
, 0, 0, tcpd
->fwd
->process_info
->process_pid
);
9166 proto_tree_add_string(field_tree
, hf_tcp_proc_dst_uname
, tvb
, 0, 0, tcpd
->fwd
->process_info
->username
);
9167 proto_tree_add_string(field_tree
, hf_tcp_proc_dst_cmd
, tvb
, 0, 0, tcpd
->fwd
->process_info
->command
);
9169 if (tcpd
->rev
&& tcpd
->rev
->process_info
&& tcpd
->rev
->process_info
->command
) {
9170 proto_tree_add_uint(field_tree
, hf_tcp_proc_src_uid
, tvb
, 0, 0, tcpd
->rev
->process_info
->process_uid
);
9171 proto_tree_add_uint(field_tree
, hf_tcp_proc_src_pid
, tvb
, 0, 0, tcpd
->rev
->process_info
->process_pid
);
9172 proto_tree_add_string(field_tree
, hf_tcp_proc_src_uname
, tvb
, 0, 0, tcpd
->rev
->process_info
->username
);
9173 proto_tree_add_string(field_tree
, hf_tcp_proc_src_cmd
, tvb
, 0, 0, tcpd
->rev
->process_info
->command
);
9178 * XXX - what, if any, of this should we do if this is included in an
9179 * error packet? It might be nice to see the details of the packet
9180 * that caused the ICMP error, but it might not be nice to have the
9181 * dissector update state based on it.
9182 * Also, we probably don't want to run TCP taps on those packets.
9184 if (captured_length_remaining
!= 0) {
9185 if (tcph
->th_flags
& TH_RST
) {
9189 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
9191 * A TCP SHOULD allow a received RST segment to include data.
9194 * It has been suggested that a RST segment could contain
9195 * ASCII text that encoded and explained the cause of the
9196 * RST. No standard has yet been established for such
9199 * so for segments with RST we just display the data as text.
9201 proto_tree_add_item(tcp_tree
, hf_tcp_reset_cause
, tvb
, offset
, captured_length_remaining
, ENC_NA
|ENC_ASCII
);
9203 /* When we have a frame with TCP SYN bit set and segmented TCP payload we need
9204 * to increment seq and nxtseq to detect the overlapping byte(s). This is to fix Bug 9882.
9206 if(tcph
->th_flags
& TH_SYN
) {
9207 dissect_tcp_payload(tvb
, pinfo
, offset
, tcph
->th_seq
+ 1, nxtseq
+ 1,
9208 tcph
->th_sport
, tcph
->th_dport
, tree
, tcp_tree
, tcpd
, &tcpinfo
);
9210 dissect_tcp_payload(tvb
, pinfo
, offset
, tcph
->th_seq
, nxtseq
,
9211 tcph
->th_sport
, tcph
->th_dport
, tree
, tcp_tree
, tcpd
, &tcpinfo
);
9215 return tvb_captured_length(tvb
);
9221 tcp_stream_count
= 0;
9224 mptcp_stream_count
= 0;
9225 mptcp_tokens
= wmem_tree_new(wmem_file_scope());
9229 proto_register_tcp(void)
9231 static hf_register_info hf
[] = {
9234 { "Source Port", "tcp.srcport", FT_UINT16
, BASE_PT_TCP
, NULL
, 0x0,
9238 { "Destination Port", "tcp.dstport", FT_UINT16
, BASE_PT_TCP
, NULL
, 0x0,
9242 { "Source or Destination Port", "tcp.port", FT_UINT16
, BASE_PT_TCP
, NULL
, 0x0,
9246 { "Stream index", "tcp.stream", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9249 { &hf_tcp_stream_pnum
,
9250 { "Stream Packet Number", "tcp.stream.pnum", FT_UINT32
, BASE_DEC
,
9252 "Relative packet number in this TCP stream", HFILL
}},
9254 { &hf_tcp_completeness
,
9255 { "Conversation completeness", "tcp.completeness", FT_UINT8
,
9256 BASE_CUSTOM
, CF_FUNC(conversation_completeness_fill
), 0x0,
9257 "The completeness of the conversation capture", HFILL
}},
9259 { &hf_tcp_completeness_syn
,
9260 { "SYN", "tcp.completeness.syn", FT_BOOLEAN
, 8,
9261 TFS(&tfs_present_absent
), TCP_COMPLETENESS_SYNSENT
,
9262 "Conversation has a SYN packet", HFILL
}},
9264 { &hf_tcp_completeness_syn_ack
,
9265 { "SYN-ACK", "tcp.completeness.syn-ack", FT_BOOLEAN
, 8,
9266 TFS(&tfs_present_absent
), TCP_COMPLETENESS_SYNACK
,
9267 "Conversation has a SYN-ACK packet", HFILL
}},
9269 { &hf_tcp_completeness_ack
,
9270 { "ACK", "tcp.completeness.ack", FT_BOOLEAN
, 8,
9271 TFS(&tfs_present_absent
), TCP_COMPLETENESS_ACK
,
9272 "Conversation has an ACK packet", HFILL
}},
9274 { &hf_tcp_completeness_data
,
9275 { "Data", "tcp.completeness.data", FT_BOOLEAN
, 8,
9276 TFS(&tfs_present_absent
), TCP_COMPLETENESS_DATA
,
9277 "Conversation has payload DATA", HFILL
}},
9279 { &hf_tcp_completeness_fin
,
9280 { "FIN", "tcp.completeness.fin", FT_BOOLEAN
, 8,
9281 TFS(&tfs_present_absent
), TCP_COMPLETENESS_FIN
,
9282 "Conversation has a FIN packet", HFILL
}},
9284 { &hf_tcp_completeness_rst
,
9285 { "RST", "tcp.completeness.rst", FT_BOOLEAN
, 8,
9286 TFS(&tfs_present_absent
), TCP_COMPLETENESS_RST
,
9287 "Conversation has a RST packet", HFILL
}},
9289 { &hf_tcp_completeness_str
,
9290 { "Completeness Flags", "tcp.completeness.str", FT_STRING
, BASE_NONE
, NULL
, 0x0,
9294 { "Sequence Number", "tcp.seq", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9298 { "Sequence Number (raw)", "tcp.seq_raw", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9299 "This shows the raw value of the sequence number", HFILL
}},
9302 { "Next Sequence Number", "tcp.nxtseq", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9306 { "Acknowledgment Number", "tcp.ack", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9310 { "Acknowledgment number (raw)", "tcp.ack_raw", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9311 "This shows the raw value of the acknowledgment number", HFILL
} },
9313 // "Data Offset" in https://tools.ietf.org/html/rfc793#section-3.1 and
9314 // "Data offset" in https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
9316 { "Header Length", "tcp.hdr_len", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
9317 "Data offset in 32-bit words", HFILL
}},
9320 { "Flags", "tcp.flags", FT_UINT16
, BASE_HEX
, NULL
, TH_MASK
,
9323 { &hf_tcp_flags_res
,
9324 { "Reserved", "tcp.flags.res", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_RES
,
9325 "Three reserved bits (must be zero)", HFILL
}},
9328 { "Accurate ECN", "tcp.flags.ae", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_AE
,
9331 { &hf_tcp_flags_cwr
,
9332 { "Congestion Window Reduced", "tcp.flags.cwr", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_CWR
,
9335 { &hf_tcp_flags_ece
,
9336 { "ECN-Echo", "tcp.flags.ece", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_ECE
,
9339 { &hf_tcp_flags_ace
,
9340 { "ACE", "tcp.flags.ace", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
9343 { &hf_tcp_flags_urg
,
9344 { "Urgent", "tcp.flags.urg", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_URG
,
9347 { &hf_tcp_flags_ack
,
9348 { "Acknowledgment", "tcp.flags.ack", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_ACK
,
9351 { &hf_tcp_flags_push
,
9352 { "Push", "tcp.flags.push", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_PUSH
,
9355 { &hf_tcp_flags_reset
,
9356 { "Reset", "tcp.flags.reset", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_RST
,
9359 { &hf_tcp_flags_syn
,
9360 { "Syn", "tcp.flags.syn", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_SYN
,
9363 { &hf_tcp_flags_fin
,
9364 { "Fin", "tcp.flags.fin", FT_BOOLEAN
, 12, TFS(&tfs_set_notset
), TH_FIN
,
9367 { &hf_tcp_flags_str
,
9368 { "TCP Flags", "tcp.flags.str", FT_STRING
, BASE_NONE
, NULL
, 0x0,
9371 { &hf_tcp_window_size_value
,
9372 { "Window", "tcp.window_size_value", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
9373 "The window size value from the TCP header", HFILL
}},
9375 /* 32 bits so we can present some values adjusted to window scaling */
9376 { &hf_tcp_window_size
,
9377 { "Calculated window size", "tcp.window_size", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9378 "The scaled window size (if scaling has been used)", HFILL
}},
9380 { &hf_tcp_window_size_scalefactor
,
9381 { "Window size scaling factor", "tcp.window_size_scalefactor", FT_INT32
, BASE_DEC
, NULL
, 0x0,
9382 "The window size scaling factor (-1 when unknown, -2 when no scaling is used)", HFILL
}},
9385 { "Checksum", "tcp.checksum", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
9386 "Details at: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL
}},
9388 { &hf_tcp_checksum_status
,
9389 { "Checksum Status", "tcp.checksum.status", FT_UINT8
, BASE_NONE
, VALS(proto_checksum_vals
), 0x0,
9392 { &hf_tcp_checksum_calculated
,
9393 { "Calculated Checksum", "tcp.checksum_calculated", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
9394 "The expected TCP checksum field as calculated from the TCP segment", HFILL
}},
9397 { "SEQ/ACK analysis", "tcp.analysis", FT_NONE
, BASE_NONE
, NULL
, 0x0,
9398 "This frame has some of the TCP analysis shown", HFILL
}},
9400 { &hf_tcp_analysis_flags
,
9401 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE
, BASE_NONE
, NULL
, 0x0,
9402 "This frame has some of the TCP analysis flags set", HFILL
}},
9404 { &hf_tcp_analysis_duplicate_ack
,
9405 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE
, BASE_NONE
, NULL
, 0x0,
9406 "This is a duplicate ACK", HFILL
}},
9408 { &hf_tcp_analysis_duplicate_ack_num
,
9409 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9410 "This is duplicate ACK number #", HFILL
}},
9412 { &hf_tcp_analysis_duplicate_ack_frame
,
9413 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_DUP_ACK
), 0x0,
9414 "This is a duplicate to the ACK in frame #", HFILL
}},
9416 { &hf_tcp_continuation_to
,
9417 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
9418 "This is a continuation to the PDU in frame #", HFILL
}},
9421 { "TCP Segment Len", "tcp.len", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9424 { &hf_tcp_analysis_acks_frame
,
9425 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_ACK
), 0x0,
9426 "Which previous segment is this an ACK for", HFILL
}},
9428 { &hf_tcp_analysis_bytes_in_flight
,
9429 { "Bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9430 "How many bytes are now in flight for this connection", HFILL
}},
9432 { &hf_tcp_analysis_push_bytes_sent
,
9433 { "Bytes sent since last PSH flag", "tcp.analysis.push_bytes_sent", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9434 "How many bytes have been sent since the last PSH flag", HFILL
}},
9436 { &hf_tcp_analysis_ack_rtt
,
9437 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
9438 "How long time it took to ACK the segment (RTT)", HFILL
}},
9440 { &hf_tcp_analysis_first_rtt
,
9441 { "iRTT", "tcp.analysis.initial_rtt", FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
9442 "How long it took for the SYN to ACK handshake (iRTT)", HFILL
}},
9444 { &hf_tcp_analysis_rto
,
9445 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
9446 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL
}},
9448 { &hf_tcp_analysis_rto_frame
,
9449 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
9450 "This is the frame we measure the RTO from", HFILL
}},
9452 { &hf_tcp_urgent_pointer
,
9453 { "Urgent Pointer", "tcp.urgent_pointer", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
9456 { &hf_tcp_segment_overlap
,
9457 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
9458 "Segment overlaps with other segments", HFILL
}},
9460 { &hf_tcp_segment_overlap_conflict
,
9461 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
9462 "Overlapping segments contained conflicting data", HFILL
}},
9464 { &hf_tcp_segment_multiple_tails
,
9465 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
9466 "Several tails were found when reassembling the pdu", HFILL
}},
9468 { &hf_tcp_segment_too_long_fragment
,
9469 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
9470 "Segment contained data past end of the pdu", HFILL
}},
9472 { &hf_tcp_segment_error
,
9473 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
9474 "Reassembling error due to illegal segments", HFILL
}},
9476 { &hf_tcp_segment_count
,
9477 { "Segment count", "tcp.segment.count", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9481 { "TCP Segment", "tcp.segment", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
9485 { "Reassembled TCP Segments", "tcp.segments", FT_NONE
, BASE_NONE
, NULL
, 0x0,
9488 { &hf_tcp_reassembled_in
,
9489 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
9490 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL
}},
9492 { &hf_tcp_reassembled_length
,
9493 { "Reassembled TCP length", "tcp.reassembled.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
9494 "The total length of the reassembled payload", HFILL
}},
9496 { &hf_tcp_reassembled_data
,
9497 { "Reassembled TCP Data", "tcp.reassembled.data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
9498 "The reassembled payload", HFILL
}},
9500 { &hf_tcp_option_kind
,
9501 { "Kind", "tcp.option_kind", FT_UINT8
,
9502 BASE_DEC
|BASE_EXT_STRING
, &tcp_option_kind_vs_ext
, 0x0, "This TCP option's kind", HFILL
}},
9504 { &hf_tcp_option_len
,
9505 { "Length", "tcp.option_len", FT_UINT8
,
9506 BASE_DEC
, NULL
, 0x0, "Length of this TCP option in bytes (including kind and length fields)", HFILL
}},
9509 { "TCP Options", "tcp.options", FT_BYTES
,
9510 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9512 { &hf_tcp_option_mss_val
,
9513 { "MSS Value", "tcp.options.mss_val", FT_UINT16
,
9514 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9516 { &hf_tcp_option_wscale_shift
,
9517 { "Shift count", "tcp.options.wscale.shift", FT_UINT8
,
9518 BASE_DEC
, NULL
, 0x0, "Logarithmically encoded power of 2 scale factor", HFILL
}},
9520 { &hf_tcp_option_wscale_multiplier
,
9521 { "Multiplier", "tcp.options.wscale.multiplier", FT_UINT16
,
9522 BASE_DEC
, NULL
, 0x0, "Multiply segment window size by this for scaled window size", HFILL
}},
9524 { &hf_tcp_option_exp_data
,
9525 { "Data", "tcp.options.experimental.data", FT_BYTES
,
9526 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9528 { &hf_tcp_option_exp_exid
,
9529 { "Experiment Identifier", "tcp.options.experimental.exid", FT_UINT16
,
9530 BASE_HEX
, &tcp_exid_vs
, 0x0, NULL
, HFILL
}},
9532 { &hf_tcp_option_unknown_payload
,
9533 { "Payload", "tcp.options.unknown.payload", FT_BYTES
,
9534 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9536 { &hf_tcp_option_sack_sle
,
9537 {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32
,
9538 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9540 { &hf_tcp_option_sack_sre
,
9541 {"TCP SACK Right Edge", "tcp.options.sack_re", FT_UINT32
,
9542 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9544 { &hf_tcp_option_sack_range_count
,
9545 { "TCP SACK Count", "tcp.options.sack.count", FT_UINT8
,
9546 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9548 { &hf_tcp_option_sack_dsack_le
,
9549 {"TCP D-SACK Left Edge", "tcp.options.sack.dsack_le", FT_UINT32
,
9550 BASE_DEC
, NULL
, 0x0, "Duplicate SACK Left Edge", HFILL
}},
9552 { &hf_tcp_option_sack_dsack_re
,
9553 {"TCP D-SACK Right Edge", "tcp.options.sack.dsack_re", FT_UINT32
,
9554 BASE_DEC
, NULL
, 0x0, "Duplicate SACK Right Edge", HFILL
}},
9556 { &hf_tcp_option_echo
,
9557 { "TCP Echo Option", "tcp.options.echo_value", FT_UINT32
,
9558 BASE_DEC
, NULL
, 0x0, "TCP Sack Echo", HFILL
}},
9560 { &hf_tcp_option_timestamp_tsval
,
9561 { "Timestamp value", "tcp.options.timestamp.tsval", FT_UINT32
,
9562 BASE_DEC
, NULL
, 0x0, "Value of sending machine's timestamp clock", HFILL
}},
9564 { &hf_tcp_option_timestamp_tsecr
,
9565 { "Timestamp echo reply", "tcp.options.timestamp.tsecr", FT_UINT32
,
9566 BASE_DEC
, NULL
, 0x0, "Echoed timestamp from remote machine", HFILL
}},
9568 { &hf_tcp_option_mptcp_subtype
,
9569 { "Multipath TCP subtype", "tcp.options.mptcp.subtype", FT_UINT8
,
9570 BASE_DEC
, VALS(mptcp_subtype_vs
), 0xF0, NULL
, HFILL
}},
9572 { &hf_tcp_option_mptcp_version
,
9573 { "Multipath TCP version", "tcp.options.mptcp.version", FT_UINT8
,
9574 BASE_DEC
, NULL
, 0x0F, NULL
, HFILL
}},
9576 { &hf_tcp_option_mptcp_reserved
,
9577 { "Reserved", "tcp.options.mptcp.reserved", FT_UINT16
,
9578 BASE_HEX
, NULL
, 0x0FFF, NULL
, HFILL
}},
9580 { &hf_tcp_option_mptcp_flags
,
9581 { "Multipath TCP flags", "tcp.options.mptcp.flags", FT_UINT8
,
9582 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
9584 { &hf_tcp_option_mptcp_backup_flag
,
9585 { "Backup flag", "tcp.options.mptcp.backup.flag", FT_UINT8
,
9586 BASE_DEC
, NULL
, 0x01, NULL
, HFILL
}},
9588 { &hf_tcp_option_mptcp_checksum_flag
,
9589 { "Checksum required", "tcp.options.mptcp.checksumreq.flags", FT_UINT8
,
9590 BASE_DEC
, NULL
, MPTCP_CHECKSUM_MASK
, NULL
, HFILL
}},
9592 { &hf_tcp_option_mptcp_B_flag
,
9593 { "Extensibility", "tcp.options.mptcp.extensibility.flag", FT_UINT8
,
9594 BASE_DEC
, NULL
, 0x40, NULL
, HFILL
}},
9596 { &hf_tcp_option_mptcp_C_flag
,
9597 { "Do not attempt to establish new subflows to this address and port", "tcp.options.mptcp.nomoresubflows.flag", FT_UINT8
,
9598 BASE_DEC
, NULL
, 0x20, NULL
, HFILL
}},
9600 { &hf_tcp_option_mptcp_H_v0_flag
,
9601 { "Use HMAC-SHA1", "tcp.options.mptcp.sha1.flag", FT_UINT8
,
9602 BASE_DEC
, NULL
, 0x01, NULL
, HFILL
}},
9604 { &hf_tcp_option_mptcp_H_v1_flag
,
9605 { "Use HMAC-SHA256", "tcp.options.mptcp.sha256.flag", FT_UINT8
,
9606 BASE_DEC
, NULL
, 0x01, NULL
, HFILL
}},
9608 { &hf_tcp_option_mptcp_F_flag
,
9609 { "DATA_FIN", "tcp.options.mptcp.datafin.flag", FT_UINT8
,
9610 BASE_DEC
, NULL
, MPTCP_DSS_FLAG_DATA_FIN_PRESENT
, NULL
, HFILL
}},
9612 { &hf_tcp_option_mptcp_m_flag
,
9613 { "Data Sequence Number is 8 octets", "tcp.options.mptcp.dseqn8.flag", FT_UINT8
,
9614 BASE_DEC
, NULL
, MPTCP_DSS_FLAG_DSN_8BYTES
, NULL
, HFILL
}},
9616 { &hf_tcp_option_mptcp_M_flag
,
9617 { "Data Sequence Number, Subflow Sequence Number, Data-level Length, Checksum present", "tcp.options.mptcp.dseqnpresent.flag", FT_UINT8
,
9618 BASE_DEC
, NULL
, MPTCP_DSS_FLAG_MAPPING_PRESENT
, NULL
, HFILL
}},
9620 { &hf_tcp_option_mptcp_a_flag
,
9621 { "Data ACK is 8 octets", "tcp.options.mptcp.dataack8.flag", FT_UINT8
,
9622 BASE_DEC
, NULL
, MPTCP_DSS_FLAG_DATA_ACK_8BYTES
, NULL
, HFILL
}},
9624 { &hf_tcp_option_mptcp_A_flag
,
9625 { "Data ACK is present", "tcp.options.mptcp.dataackpresent.flag", FT_UINT8
,
9626 BASE_DEC
, NULL
, MPTCP_DSS_FLAG_DATA_ACK_PRESENT
, NULL
, HFILL
}},
9628 { &hf_tcp_option_mptcp_reserved_v0_flag
,
9629 { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8
,
9630 BASE_HEX
, NULL
, 0x3E, NULL
, HFILL
}},
9632 { &hf_tcp_option_mptcp_reserved_v1_flag
,
9633 { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8
,
9634 BASE_HEX
, NULL
, 0x1E, NULL
, HFILL
}},
9636 { &hf_tcp_option_mptcp_U_flag
,
9637 { "Flag U", "tcp.options.mptcp.flag_U.flag", FT_BOOLEAN
,
9638 4, TFS(&tfs_set_notset
), MPTCP_TCPRST_FLAG_U_PRESENT
, NULL
, HFILL
}},
9640 { &hf_tcp_option_mptcp_V_flag
,
9641 { "Flag V", "tcp.options.mptcp.flag_V.flag", FT_BOOLEAN
,
9642 4, TFS(&tfs_set_notset
), MPTCP_TCPRST_FLAG_V_PRESENT
, NULL
, HFILL
}},
9644 { &hf_tcp_option_mptcp_W_flag
,
9645 { "Flag W", "tcp.options.mptcp.flag_W.flag", FT_BOOLEAN
,
9646 4, TFS(&tfs_set_notset
), MPTCP_TCPRST_FLAG_W_PRESENT
, NULL
, HFILL
}},
9648 { &hf_tcp_option_mptcp_T_flag
,
9649 { "Transient", "tcp.options.mptcp.flag_T.flag", FT_BOOLEAN
,
9650 4, TFS(&tfs_set_notset
), MPTCP_TCPRST_FLAG_T_PRESENT
, NULL
, HFILL
}},
9652 { &hf_tcp_option_mptcp_tcprst_reason
,
9653 { "TCPRST Reason", "tcp.options.mptcp.rst_reason", FT_UINT8
,
9654 BASE_HEX
, VALS(mp_tcprst_reasons
), 0x0, "Multipath TCPRST Reason Code", HFILL
}},
9656 { &hf_tcp_option_mptcp_address_id
,
9657 { "Address ID", "tcp.options.mptcp.addrid", FT_UINT8
,
9658 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9660 { &hf_tcp_option_mptcp_sender_key
,
9661 { "Sender's Key", "tcp.options.mptcp.sendkey", FT_UINT64
,
9662 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9664 { &hf_tcp_option_mptcp_recv_key
,
9665 { "Receiver's Key", "tcp.options.mptcp.recvkey", FT_UINT64
,
9666 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9668 { &hf_tcp_option_mptcp_recv_token
,
9669 { "Receiver's Token", "tcp.options.mptcp.recvtok", FT_UINT32
,
9670 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9672 { &hf_tcp_option_mptcp_sender_rand
,
9673 { "Sender's Random Number", "tcp.options.mptcp.sendrand", FT_UINT32
,
9674 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9676 { &hf_tcp_option_mptcp_sender_trunc_hmac
,
9677 { "Sender's Truncated HMAC", "tcp.options.mptcp.sendtrunchmac", FT_UINT64
,
9678 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9680 { &hf_tcp_option_mptcp_sender_hmac
,
9681 { "Sender's HMAC", "tcp.options.mptcp.sendhmac", FT_BYTES
,
9682 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9684 { &hf_tcp_option_mptcp_addaddr_trunc_hmac
,
9685 { "Truncated HMAC", "tcp.options.mptcp.addaddrtrunchmac", FT_UINT64
,
9686 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9688 { &hf_tcp_option_mptcp_data_ack_raw
,
9689 { "Original MPTCP Data ACK", "tcp.options.mptcp.rawdataack", FT_UINT64
,
9690 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9692 { &hf_tcp_option_mptcp_data_seq_no_raw
,
9693 { "Data Sequence Number", "tcp.options.mptcp.rawdataseqno", FT_UINT64
,
9694 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9696 { &hf_tcp_option_mptcp_subflow_seq_no
,
9697 { "Subflow Sequence Number", "tcp.options.mptcp.subflowseqno", FT_UINT32
,
9698 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9700 { &hf_tcp_option_mptcp_data_lvl_len
,
9701 { "Data-level Length", "tcp.options.mptcp.datalvllen", FT_UINT16
,
9702 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9704 { &hf_tcp_option_mptcp_checksum
,
9705 { "Checksum", "tcp.options.mptcp.checksum", FT_UINT16
,
9706 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
9708 { &hf_tcp_option_mptcp_ipver
,
9709 { "IP version", "tcp.options.mptcp.ipver", FT_UINT8
,
9710 BASE_DEC
, NULL
, 0x0F, NULL
, HFILL
}},
9712 { &hf_tcp_option_mptcp_echo
,
9713 { "Echo", "tcp.options.mptcp.echo", FT_UINT8
,
9714 BASE_DEC
, NULL
, 0x01, NULL
, HFILL
}},
9716 { &hf_tcp_option_mptcp_ipv4
,
9717 { "Advertised IPv4 Address", "tcp.options.mptcp.ipv4", FT_IPv4
,
9718 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9720 { &hf_tcp_option_mptcp_ipv6
,
9721 { "Advertised IPv6 Address", "tcp.options.mptcp.ipv6", FT_IPv6
,
9722 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9724 { &hf_tcp_option_mptcp_port
,
9725 { "Advertised port", "tcp.options.mptcp.port", FT_UINT16
,
9726 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9728 { &hf_tcp_option_cc
,
9729 { "TCP CC Option", "tcp.options.cc_value", FT_UINT32
, BASE_DEC
,
9730 NULL
, 0x0, NULL
, HFILL
}},
9732 { &hf_tcp_option_md5_digest
,
9733 { "MD5 digest", "tcp.options.md5.digest", FT_BYTES
, BASE_NONE
,
9734 NULL
, 0x0, NULL
, HFILL
}},
9736 { &hf_tcp_option_ao_keyid
,
9737 { "AO KeyID", "tcp.options.ao.keyid", FT_UINT8
, BASE_DEC
,
9738 NULL
, 0x0, NULL
, HFILL
}},
9740 { &hf_tcp_option_ao_rnextkeyid
,
9741 { "AO RNextKeyID", "tcp.options.ao.rnextkeyid", FT_UINT8
, BASE_DEC
,
9742 NULL
, 0x0, NULL
, HFILL
}},
9744 { &hf_tcp_option_ao_mac
,
9745 { "AO MAC", "tcp.options.ao.mac", FT_BYTES
, BASE_NONE
,
9746 NULL
, 0x0, NULL
, HFILL
}},
9748 { &hf_tcp_option_qs_rate
,
9749 { "QS Rate", "tcp.options.qs.rate", FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
,
9750 &qs_rate_vals_ext
, 0x0F, NULL
, HFILL
}},
9752 { &hf_tcp_option_qs_ttl_diff
,
9753 { "QS Rate", "tcp.options.qs.ttl_diff", FT_UINT8
, BASE_DEC
,
9754 NULL
, 0x0, NULL
, HFILL
}},
9756 { &hf_tcp_option_tarr_rate
,
9757 { "TARR Rate", "tcp.options.tarr.rate", FT_UINT8
, BASE_DEC
,
9758 NULL
, TCPOPT_TARR_RATE_MASK
, NULL
, HFILL
}},
9760 { &hf_tcp_option_tarr_reserved
,
9761 { "TARR Reserved", "tcp.options.tar.reserved", FT_UINT8
, BASE_DEC
,
9762 NULL
, TCPOPT_TARR_RESERVED_MASK
, NULL
, HFILL
}},
9764 { &hf_tcp_option_acc_ecn_ee0b
,
9765 { "Accurate ECN Echo ECT(0) Byte Counter", "tcp.options.acc_ecn.ee0b",
9766 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
9769 { &hf_tcp_option_acc_ecn_eceb
,
9770 { "Accurate ECN Echo CE Byte Counter", "tcp.options.acc_ecn.eceb",
9771 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
9774 { &hf_tcp_option_acc_ecn_ee1b
,
9775 { "Accurate ECN Echo ECT(1) Byte Counter", "tcp.options.acc_ecn.ee1b",
9776 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
9779 { &hf_tcp_option_scps_vector
,
9780 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
9781 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
9784 { &hf_tcp_option_scps_binding
,
9785 { "Binding Space (Community) ID",
9786 "tcp.options.scps.binding.id",
9787 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
9788 "TCP SCPS Extended Binding Space (Community) ID", HFILL
}},
9790 { &hf_tcp_option_scps_binding_len
,
9791 { "Extended Capability Length",
9792 "tcp.options.scps.binding.len",
9793 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
9794 "TCP SCPS Extended Capability Length in bytes", HFILL
}},
9796 { &hf_tcp_option_snack_offset
,
9797 { "TCP SNACK Offset", "tcp.options.snack.offset",
9798 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
9801 { &hf_tcp_option_snack_size
,
9802 { "TCP SNACK Size", "tcp.options.snack.size",
9803 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
9806 { &hf_tcp_option_snack_le
,
9807 { "TCP SNACK Left Edge", "tcp.options.snack.le",
9808 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
9811 { &hf_tcp_option_snack_re
,
9812 { "TCP SNACK Right Edge", "tcp.options.snack.re",
9813 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
9816 { &hf_tcp_scpsoption_flags_bets
,
9817 { "Partial Reliability Capable (BETS)",
9818 "tcp.options.scpsflags.bets", FT_BOOLEAN
, 8,
9819 TFS(&tfs_set_notset
), 0x80, NULL
, HFILL
}},
9821 { &hf_tcp_scpsoption_flags_snack1
,
9822 { "Short Form SNACK Capable (SNACK1)",
9823 "tcp.options.scpsflags.snack1", FT_BOOLEAN
, 8,
9824 TFS(&tfs_set_notset
), 0x40, NULL
, HFILL
}},
9826 { &hf_tcp_scpsoption_flags_snack2
,
9827 { "Long Form SNACK Capable (SNACK2)",
9828 "tcp.options.scpsflags.snack2", FT_BOOLEAN
, 8,
9829 TFS(&tfs_set_notset
), 0x20, NULL
, HFILL
}},
9831 { &hf_tcp_scpsoption_flags_compress
,
9832 { "Lossless Header Compression (COMP)",
9833 "tcp.options.scpsflags.compress", FT_BOOLEAN
, 8,
9834 TFS(&tfs_set_notset
), 0x10, NULL
, HFILL
}},
9836 { &hf_tcp_scpsoption_flags_nlts
,
9837 { "Network Layer Timestamp (NLTS)",
9838 "tcp.options.scpsflags.nlts", FT_BOOLEAN
, 8,
9839 TFS(&tfs_set_notset
), 0x8, NULL
, HFILL
}},
9841 { &hf_tcp_scpsoption_flags_reserved
,
9843 "tcp.options.scpsflags.reserved", FT_UINT8
, BASE_DEC
,
9844 NULL
, 0x7, NULL
, HFILL
}},
9846 { &hf_tcp_scpsoption_connection_id
,
9848 "tcp.options.scps.binding",
9849 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
9850 "TCP SCPS Connection ID", HFILL
}},
9852 { &hf_tcp_option_user_to_granularity
,
9853 { "Granularity", "tcp.options.user_to_granularity", FT_BOOLEAN
,
9854 16, TFS(&tcp_option_user_to_granularity
), 0x8000, "TCP User Timeout Granularity", HFILL
}},
9856 { &hf_tcp_option_user_to_val
,
9857 { "User Timeout", "tcp.options.user_to_val", FT_UINT16
,
9858 BASE_DEC
, NULL
, 0x7FFF, "TCP User Timeout Value", HFILL
}},
9860 { &hf_tcp_option_rvbd_probe_type1
,
9861 { "Type", "tcp.options.rvbd.probe.type1",
9862 FT_UINT8
, BASE_DEC
, NULL
, 0xF0, NULL
, HFILL
}},
9864 { &hf_tcp_option_rvbd_probe_type2
,
9865 { "Type", "tcp.options.rvbd.probe.type2",
9866 FT_UINT8
, BASE_DEC
, NULL
, 0xFE, NULL
, HFILL
}},
9868 { &hf_tcp_option_rvbd_probe_version1
,
9869 { "Version", "tcp.options.rvbd.probe.version",
9870 FT_UINT8
, BASE_DEC
, NULL
, 0x0F, NULL
, HFILL
}},
9872 { &hf_tcp_option_rvbd_probe_version2
,
9873 { "Version", "tcp.options.rvbd.probe.version_raw",
9874 FT_UINT8
, BASE_DEC
, NULL
, 0x01, "Version 2 Raw Value", HFILL
}},
9876 { &hf_tcp_option_rvbd_probe_prober
,
9877 { "CSH IP", "tcp.options.rvbd.probe.prober",
9878 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9880 { &hf_tcp_option_rvbd_probe_proxy
,
9881 { "SSH IP", "tcp.options.rvbd.probe.proxy.ip",
9882 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9884 { &hf_tcp_option_rvbd_probe_proxy_port
,
9885 { "SSH Port", "tcp.options.rvbd.probe.proxy.port",
9886 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9888 { &hf_tcp_option_rvbd_probe_appli_ver
,
9889 { "Application Version", "tcp.options.rvbd.probe.appli_ver",
9890 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9892 { &hf_tcp_option_rvbd_probe_client
,
9893 { "Client IP", "tcp.options.rvbd.probe.client.ip",
9894 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9896 { &hf_tcp_option_rvbd_probe_storeid
,
9897 { "CFE Store ID", "tcp.options.rvbd.probe.storeid",
9898 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9900 { &hf_tcp_option_rvbd_probe_flags
,
9901 { "Probe Flags", "tcp.options.rvbd.probe.flags",
9902 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
9904 { &hf_tcp_option_rvbd_probe_flag_not_cfe
,
9905 { "Not CFE", "tcp.options.rvbd.probe.flags.notcfe",
9906 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RVBD_FLAGS_PROBE_NCFE
,
9909 { &hf_tcp_option_rvbd_probe_flag_last_notify
,
9910 { "Last Notify", "tcp.options.rvbd.probe.flags.last",
9911 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RVBD_FLAGS_PROBE_LAST
,
9914 { &hf_tcp_option_rvbd_probe_flag_probe_cache
,
9915 { "Disable Probe Cache on CSH", "tcp.options.rvbd.probe.flags.probe",
9916 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RVBD_FLAGS_PROBE
,
9919 { &hf_tcp_option_rvbd_probe_flag_sslcert
,
9920 { "SSL Enabled", "tcp.options.rvbd.probe.flags.ssl",
9921 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RVBD_FLAGS_PROBE_SSLCERT
,
9924 { &hf_tcp_option_rvbd_probe_flag_server_connected
,
9925 { "SSH outer to server established", "tcp.options.rvbd.probe.flags.server",
9926 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RVBD_FLAGS_PROBE_SERVER
,
9929 { &hf_tcp_option_rvbd_trpy_flags
,
9930 { "Transparency Options", "tcp.options.rvbd.trpy.flags",
9931 FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
9933 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe
,
9934 { "Enable FW traversal feature", "tcp.options.rvbd.trpy.flags.fw_rst_probe",
9935 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
),
9936 RVBD_FLAGS_TRPY_FW_RST_PROBE
,
9937 "Reset state created by probe on the nexthop firewall",
9940 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner
,
9941 { "Enable Inner FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst_inner",
9942 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
),
9943 RVBD_FLAGS_TRPY_FW_RST_INNER
,
9944 "Reset state created by transparent inner on all firewalls"
9945 " before passing connection through",
9948 { &hf_tcp_option_rvbd_trpy_flag_fw_rst
,
9949 { "Enable Transparency FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst",
9950 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
),
9951 RVBD_FLAGS_TRPY_FW_RST
,
9952 "Reset state created by probe on all firewalls before "
9953 "establishing transparent inner connection", HFILL
}},
9955 { &hf_tcp_option_rvbd_trpy_flag_chksum
,
9956 { "Reserved", "tcp.options.rvbd.trpy.flags.chksum",
9957 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
),
9958 RVBD_FLAGS_TRPY_CHKSUM
, NULL
, HFILL
}},
9960 { &hf_tcp_option_rvbd_trpy_flag_oob
,
9961 { "Out of band connection", "tcp.options.rvbd.trpy.flags.oob",
9962 FT_BOOLEAN
, 16, TFS(&tfs_set_notset
),
9963 RVBD_FLAGS_TRPY_OOB
, NULL
, HFILL
}},
9965 { &hf_tcp_option_rvbd_trpy_flag_mode
,
9966 { "Transparency Mode", "tcp.options.rvbd.trpy.flags.mode",
9967 FT_BOOLEAN
, 16, TFS(&trpy_mode_str
),
9968 RVBD_FLAGS_TRPY_MODE
, NULL
, HFILL
}},
9970 { &hf_tcp_option_rvbd_trpy_src
,
9971 { "Src SH IP Addr", "tcp.options.rvbd.trpy.src.ip",
9972 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9974 { &hf_tcp_option_rvbd_trpy_dst
,
9975 { "Dst SH IP Addr", "tcp.options.rvbd.trpy.dst.ip",
9976 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9978 { &hf_tcp_option_rvbd_trpy_src_port
,
9979 { "Src SH Inner Port", "tcp.options.rvbd.trpy.src.port",
9980 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9982 { &hf_tcp_option_rvbd_trpy_dst_port
,
9983 { "Dst SH Inner Port", "tcp.options.rvbd.trpy.dst.port",
9984 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9986 { &hf_tcp_option_rvbd_trpy_client_port
,
9987 { "Out of band connection Client Port", "tcp.options.rvbd.trpy.client.port",
9988 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
9990 { &hf_tcp_option_fast_open_cookie_request
,
9991 { "Fast Open Cookie Request", "tcp.options.tfo.request", FT_NONE
,
9992 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9994 { &hf_tcp_option_fast_open_cookie
,
9995 { "Fast Open Cookie", "tcp.options.tfo.cookie", FT_BYTES
,
9996 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
9999 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
10000 "How long time has passed until the last frame of this PDU", HFILL
}},
10002 { &hf_tcp_pdu_size
,
10003 { "PDU Size", "tcp.pdu.size", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
10004 "The size of this PDU", HFILL
}},
10006 { &hf_tcp_pdu_last_frame
,
10007 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
10008 "This is the last frame of the PDU starting in this segment", HFILL
}},
10010 { &hf_tcp_ts_relative
,
10011 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
10012 "Time relative to first frame in this TCP stream", HFILL
}},
10014 { &hf_tcp_ts_delta
,
10015 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
10016 "Time delta from previous frame in this TCP stream", HFILL
}},
10018 { &hf_tcp_proc_src_uid
,
10019 { "Source process user ID", "tcp.proc.srcuid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
10022 { &hf_tcp_proc_src_pid
,
10023 { "Source process ID", "tcp.proc.srcpid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
10026 { &hf_tcp_proc_src_uname
,
10027 { "Source process user name", "tcp.proc.srcuname", FT_STRING
, BASE_NONE
, NULL
, 0x0,
10030 { &hf_tcp_proc_src_cmd
,
10031 { "Source process name", "tcp.proc.srccmd", FT_STRING
, BASE_NONE
, NULL
, 0x0,
10032 "Source process command name", HFILL
}},
10034 { &hf_tcp_proc_dst_uid
,
10035 { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
10038 { &hf_tcp_proc_dst_pid
,
10039 { "Destination process ID", "tcp.proc.dstpid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
10042 { &hf_tcp_proc_dst_uname
,
10043 { "Destination process user name", "tcp.proc.dstuname", FT_STRING
, BASE_NONE
, NULL
, 0x0,
10046 { &hf_tcp_proc_dst_cmd
,
10047 { "Destination process name", "tcp.proc.dstcmd", FT_STRING
, BASE_NONE
, NULL
, 0x0,
10048 "Destination process command name", HFILL
}},
10050 { &hf_tcp_segment_data
,
10051 { "TCP segment data", "tcp.segment_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
10052 "A data segment used in reassembly of an upper-layer protocol (ULP)", HFILL
}},
10055 { "TCP payload", "tcp.payload", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
10056 "The TCP payload of this packet", HFILL
}},
10058 { &hf_tcp_option_scps_binding_data
,
10059 { "Binding Space Data", "tcp.options.scps.binding.data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
10062 { &hf_tcp_option_rvbd_probe_reserved
,
10063 { "Reserved", "tcp.options.rvbd.probe.reserved", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
10066 { &hf_tcp_fin_retransmission
,
10067 { "Retransmission of FIN from frame", "tcp.fin_retransmission", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
10070 { &hf_tcp_reset_cause
,
10071 { "Reset cause", "tcp.reset_cause", FT_STRING
, BASE_NONE
, NULL
, 0x0,
10074 { &hf_tcp_syncookie_time
,
10075 { "SYN Cookie Time", "tcp.syncookie.time", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
10078 { &hf_tcp_syncookie_mss
,
10079 { "SYN Cookie Maximum Segment Size", "tcp.syncookie.mss", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
10082 { &hf_tcp_syncookie_hash
,
10083 { "SYN Cookie hash", "tcp.syncookie.hash", FT_UINT24
, BASE_HEX
, NULL
, 0x0,
10086 { &hf_tcp_syncookie_option_timestamp
,
10087 { "SYN Cookie Timestamp", "tcp.options.timestamp.tsval.syncookie.timestamp", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
10090 { &hf_tcp_syncookie_option_ecn
,
10091 { "SYN Cookie ECN", "tcp.options.timestamp.tsval.syncookie.ecn", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
10094 { &hf_tcp_syncookie_option_sack
,
10095 { "SYN Cookie SACK", "tcp.options.timestamp.tsval.syncookie.sack", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
10098 { &hf_tcp_syncookie_option_wscale
,
10099 { "SYN Cookie WScale", "tcp.options.timestamp.tsval.syncookie.wscale", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
10102 { &hf_tcp_ns_reset_window_error_code
,
10103 { "NetScaler TCP Reset Window Error Code", "tcp.nstrace.rst.window_error_code", FT_STRING
, BASE_NONE
, NULL
, 0x0,
10107 static int *ett
[] = {
10109 &ett_tcp_completeness
,
10112 &ett_tcp_option_timestamp
,
10113 &ett_tcp_option_mptcp
,
10114 &ett_tcp_option_wscale
,
10115 &ett_tcp_option_sack
,
10116 &ett_tcp_option_snack
,
10117 &ett_tcp_option_scps
,
10118 &ett_tcp_scpsoption_flags
,
10119 &ett_tcp_option_scps_extended
,
10120 &ett_tcp_option_user_to
,
10121 &ett_tcp_option_exp
,
10122 &ett_tcp_option_acc_ecn
,
10123 &ett_tcp_option_sack_perm
,
10124 &ett_tcp_option_mss
,
10125 &ett_tcp_opt_rvbd_probe
,
10126 &ett_tcp_opt_rvbd_probe_flags
,
10127 &ett_tcp_opt_rvbd_trpy
,
10128 &ett_tcp_opt_rvbd_trpy_flags
,
10134 &ett_tcp_analysis_faults
,
10136 &ett_tcp_timestamps
,
10140 &ett_tcp_process_info
,
10141 &ett_tcp_unknown_opt
,
10142 &ett_tcp_opt_recbound
,
10143 &ett_tcp_opt_scpscor
,
10144 &ett_tcp_option_other
,
10145 &ett_tcp_syncookie
,
10146 &ett_tcp_syncookie_option
10149 static int *mptcp_ett
[] = {
10150 &ett_mptcp_analysis
,
10151 &ett_mptcp_analysis_subflows
10154 static const enum_val_t window_scaling_vals
[] = {
10155 {"not-known", "Not known", WindowScaling_NotKnown
},
10156 {"0", "0 (no scaling)", WindowScaling_0
},
10157 {"1", "1 (multiply by 2)", WindowScaling_1
},
10158 {"2", "2 (multiply by 4)", WindowScaling_2
},
10159 {"3", "3 (multiply by 8)", WindowScaling_3
},
10160 {"4", "4 (multiply by 16)", WindowScaling_4
},
10161 {"5", "5 (multiply by 32)", WindowScaling_5
},
10162 {"6", "6 (multiply by 64)", WindowScaling_6
},
10163 {"7", "7 (multiply by 128)", WindowScaling_7
},
10164 {"8", "8 (multiply by 256)", WindowScaling_8
},
10165 {"9", "9 (multiply by 512)", WindowScaling_9
},
10166 {"10", "10 (multiply by 1024)", WindowScaling_10
},
10167 {"11", "11 (multiply by 2048)", WindowScaling_11
},
10168 {"12", "12 (multiply by 4096)", WindowScaling_12
},
10169 {"13", "13 (multiply by 8192)", WindowScaling_13
},
10170 {"14", "14 (multiply by 16384)", WindowScaling_14
},
10174 static const enum_val_t override_analysis_vals
[] = {
10175 {"0", "0 (none)", OverrideAnalysis_0
},
10176 {"1", "1 (Out-of-Order)", OverrideAnalysis_1
},
10177 {"2", "2 (Retransmission)", OverrideAnalysis_2
},
10178 {"3", "3 (Fast Retransmission)", OverrideAnalysis_3
},
10179 {"4", "4 (Spurious Retransmission)",OverrideAnalysis_4
},
10183 static ei_register_info ei
[] = {
10184 { &ei_tcp_opt_len_invalid
, { "tcp.option.len.invalid", PI_SEQUENCE
, PI_NOTE
, "Invalid length for option", EXPFILL
}},
10185 { &ei_tcp_analysis_retransmission
, { "tcp.analysis.retransmission", PI_SEQUENCE
, PI_NOTE
, "This frame is a (suspected) retransmission", EXPFILL
}},
10186 { &ei_tcp_analysis_fast_retransmission
, { "tcp.analysis.fast_retransmission", PI_SEQUENCE
, PI_NOTE
, "This frame is a (suspected) fast retransmission", EXPFILL
}},
10187 { &ei_tcp_analysis_spurious_retransmission
, { "tcp.analysis.spurious_retransmission", PI_SEQUENCE
, PI_NOTE
, "This frame is a (suspected) spurious retransmission", EXPFILL
}},
10188 { &ei_tcp_analysis_out_of_order
, { "tcp.analysis.out_of_order", PI_SEQUENCE
, PI_WARN
, "This frame is a (suspected) out-of-order segment", EXPFILL
}},
10189 { &ei_tcp_analysis_reused_ports
, { "tcp.analysis.reused_ports", PI_SEQUENCE
, PI_NOTE
, "A new tcp session is started with the same ports as an earlier session in this trace", EXPFILL
}},
10190 { &ei_tcp_analysis_lost_packet
, { "tcp.analysis.lost_segment", PI_SEQUENCE
, PI_WARN
, "Previous segment(s) not captured (common at capture start)", EXPFILL
}},
10191 { &ei_tcp_analysis_ack_lost_packet
, { "tcp.analysis.ack_lost_segment", PI_SEQUENCE
, PI_WARN
, "ACKed segment that wasn't captured (common at capture start)", EXPFILL
}},
10192 { &ei_tcp_analysis_window_update
, { "tcp.analysis.window_update", PI_SEQUENCE
, PI_CHAT
, "TCP window update", EXPFILL
}},
10193 { &ei_tcp_analysis_window_full
, { "tcp.analysis.window_full", PI_SEQUENCE
, PI_WARN
, "TCP window specified by the receiver is now completely full", EXPFILL
}},
10194 { &ei_tcp_analysis_keep_alive
, { "tcp.analysis.keep_alive", PI_SEQUENCE
, PI_NOTE
, "TCP keep-alive segment", EXPFILL
}},
10195 { &ei_tcp_analysis_keep_alive_ack
, { "tcp.analysis.keep_alive_ack", PI_SEQUENCE
, PI_NOTE
, "ACK to a TCP keep-alive segment", EXPFILL
}},
10196 { &ei_tcp_analysis_duplicate_ack
, { "tcp.analysis.duplicate_ack", PI_SEQUENCE
, PI_NOTE
, "Duplicate ACK", EXPFILL
}},
10197 { &ei_tcp_analysis_zero_window_probe
, { "tcp.analysis.zero_window_probe", PI_SEQUENCE
, PI_NOTE
, "TCP Zero Window Probe", EXPFILL
}},
10198 { &ei_tcp_analysis_zero_window
, { "tcp.analysis.zero_window", PI_SEQUENCE
, PI_WARN
, "TCP Zero Window segment", EXPFILL
}},
10199 { &ei_tcp_analysis_zero_window_probe_ack
, { "tcp.analysis.zero_window_probe_ack", PI_SEQUENCE
, PI_NOTE
, "ACK to a TCP Zero Window Probe", EXPFILL
}},
10200 { &ei_tcp_analysis_tfo_syn
, { "tcp.analysis.tfo_syn", PI_SEQUENCE
, PI_NOTE
, "TCP SYN with TFO Cookie", EXPFILL
}},
10201 { &ei_tcp_analysis_tfo_ack
, { "tcp.analysis.tfo_ack", PI_SEQUENCE
, PI_NOTE
, "TCP SYN-ACK accepting TFO data", EXPFILL
}},
10202 { &ei_tcp_analysis_tfo_ignored
, { "tcp.analysis.tfo_ignored", PI_SEQUENCE
, PI_NOTE
, "TCP SYN-ACK ignoring TFO data", EXPFILL
}},
10203 { &ei_tcp_analysis_partial_ack
, { "tcp.analysis.partial_ack", PI_SEQUENCE
, PI_NOTE
, "Partial Acknowledgement of a segment", EXPFILL
}},
10204 { &ei_tcp_connection_fin_active
, { "tcp.connection.fin_active", PI_SEQUENCE
, PI_NOTE
, "This frame initiates the connection closing", EXPFILL
}},
10205 { &ei_tcp_connection_fin_passive
, { "tcp.connection.fin_passive", PI_SEQUENCE
, PI_NOTE
, "This frame undergoes the connection closing", EXPFILL
}},
10206 { &ei_tcp_scps_capable
, { "tcp.analysis.scps_capable", PI_SEQUENCE
, PI_NOTE
, "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated", EXPFILL
}},
10207 { &ei_tcp_option_sack_dsack
, { "tcp.options.sack.dsack", PI_SEQUENCE
, PI_WARN
, "D-SACK Sequence", EXPFILL
}},
10208 { &ei_tcp_option_snack_sequence
, { "tcp.options.snack.sequence", PI_SEQUENCE
, PI_NOTE
, "SNACK Sequence", EXPFILL
}},
10209 { &ei_tcp_option_wscale_shift_invalid
, { "tcp.options.wscale.shift.invalid", PI_PROTOCOL
, PI_WARN
, "Window scale shift exceeds 14", EXPFILL
}},
10210 { &ei_tcp_option_mss_absent
, { "tcp.options.mss.absent", PI_PROTOCOL
, PI_NOTE
, "The SYN packet does not contain a MSS option", EXPFILL
}},
10211 { &ei_tcp_option_mss_present
, { "tcp.options.mss.present", PI_PROTOCOL
, PI_WARN
, "The non-SYN packet does contain a MSS option", EXPFILL
}},
10212 { &ei_tcp_option_sack_perm_absent
, { "tcp.options.sack_perm.absent", PI_PROTOCOL
, PI_NOTE
, "The SYN packet does not contain a SACK PERM option", EXPFILL
}},
10213 { &ei_tcp_option_sack_perm_present
, { "tcp.options.sack_perm.present", PI_PROTOCOL
, PI_WARN
, "The non-SYN packet does contain a SACK PERM option", EXPFILL
}},
10214 { &ei_tcp_short_segment
, { "tcp.short_segment", PI_MALFORMED
, PI_WARN
, "Short segment", EXPFILL
}},
10215 { &ei_tcp_ack_nonzero
, { "tcp.ack.nonzero", PI_PROTOCOL
, PI_NOTE
, "The acknowledgment number field is nonzero while the ACK flag is not set", EXPFILL
}},
10216 { &ei_tcp_connection_synack
, { "tcp.connection.synack", PI_SEQUENCE
, PI_CHAT
, "Connection establish acknowledge (SYN+ACK)", EXPFILL
}},
10217 { &ei_tcp_connection_syn
, { "tcp.connection.syn", PI_SEQUENCE
, PI_CHAT
, "Connection establish request (SYN)", EXPFILL
}},
10218 { &ei_tcp_connection_fin
, { "tcp.connection.fin", PI_SEQUENCE
, PI_CHAT
, "Connection finish (FIN)", EXPFILL
}},
10219 /* According to RFCs, RST is an indication of an error. Some applications use it
10220 * to terminate a connection as well, which is a misbehavior (see e.g. rfc3360)
10222 { &ei_tcp_connection_rst
, { "tcp.connection.rst", PI_SEQUENCE
, PI_WARN
, "Connection reset (RST)", EXPFILL
}},
10223 { &ei_tcp_checksum_ffff
, { "tcp.checksum.ffff", PI_CHECKSUM
, PI_WARN
, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)", EXPFILL
}},
10224 { &ei_tcp_checksum_partial
, { "tcp.checksum.partial", PI_CHECKSUM
, PI_NOTE
, "Partial (pseudo header) checksum (likely caused by \"TCP checksum offload\")", EXPFILL
}},
10225 { &ei_tcp_checksum_bad
, { "tcp.checksum_bad.expert", PI_CHECKSUM
, PI_ERROR
, "Bad checksum", EXPFILL
}},
10226 { &ei_tcp_urgent_pointer_non_zero
, { "tcp.urgent_pointer.non_zero", PI_PROTOCOL
, PI_NOTE
, "The urgent pointer field is nonzero while the URG flag is not set", EXPFILL
}},
10227 { &ei_tcp_suboption_malformed
, { "tcp.suboption_malformed", PI_MALFORMED
, PI_ERROR
, "suboption would go past end of option", EXPFILL
}},
10228 { &ei_tcp_nop
, { "tcp.nop", PI_PROTOCOL
, PI_WARN
, "4 NOP in a row - a router may have removed some options", EXPFILL
}},
10229 { &ei_tcp_non_zero_bytes_after_eol
, { "tcp.non_zero_bytes_after_eol", PI_PROTOCOL
, PI_ERROR
, "Non zero bytes in option space after EOL option", EXPFILL
}},
10230 { &ei_tcp_bogus_header_length
, { "tcp.bogus_header_length", PI_PROTOCOL
, PI_ERROR
, "Bogus TCP Header length", EXPFILL
}},
10233 static ei_register_info mptcp_ei
[] = {
10235 { &ei_mptcp_analysis_unexpected_idsn
, { "mptcp.connection.unexpected_idsn", PI_PROTOCOL
, PI_NOTE
, "Unexpected initial sequence number", EXPFILL
}},
10237 { &ei_mptcp_analysis_echoed_key_mismatch
, { "mptcp.connection.echoed_key_mismatch", PI_PROTOCOL
, PI_WARN
, "The echoed key in the ACK of the MPTCP handshake does not match the key of the SYN/ACK", EXPFILL
}},
10238 { &ei_mptcp_analysis_missing_algorithm
, { "mptcp.connection.missing_algorithm", PI_PROTOCOL
, PI_WARN
, "No crypto algorithm specified", EXPFILL
}},
10239 { &ei_mptcp_analysis_unsupported_algorithm
, { "mptcp.connection.unsupported_algorithm", PI_PROTOCOL
, PI_WARN
, "Unsupported algorithm", EXPFILL
}},
10240 { &ei_mptcp_infinite_mapping
, { "mptcp.dss.infinite_mapping", PI_PROTOCOL
, PI_WARN
, "Fallback to infinite mapping", EXPFILL
}},
10241 { &ei_mptcp_mapping_missing
, { "mptcp.dss.missing_mapping", PI_PROTOCOL
, PI_WARN
, "No mapping available", EXPFILL
}},
10243 { &ei_mptcp_stream_incomplete
, { "mptcp.incomplete", PI_PROTOCOL
, PI_WARN
, "Everything was not captured", EXPFILL
}},
10244 { &ei_mptcp_analysis_dsn_out_of_order
, { "mptcp.analysis.dsn.out_of_order", PI_PROTOCOL
, PI_WARN
, "Out of order dsn", EXPFILL
}},
10248 static hf_register_info mptcp_hf
[] = {
10250 { "Multipath TCP Data ACK", "mptcp.ack", FT_UINT64
,
10251 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
10254 { "Data Sequence Number", "mptcp.dsn", FT_UINT64
, BASE_DEC
, NULL
, 0x0,
10255 "Data Sequence Number mapped to this TCP sequence number", HFILL
}},
10257 { &hf_mptcp_rawdsn64
,
10258 { "Raw Data Sequence Number", "mptcp.rawdsn64", FT_UINT64
, BASE_DEC
, NULL
, 0x0,
10259 "Data Sequence Number mapped to this TCP sequence number", HFILL
}},
10261 { &hf_mptcp_dss_dsn
,
10262 { "DSS Data Sequence Number", "mptcp.dss.dsn", FT_UINT64
,
10263 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
10265 { &hf_mptcp_expected_idsn
,
10266 { "Subflow expected IDSN", "mptcp.expected_idsn", FT_UINT64
,
10267 BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_64bit_version
), 0x0, NULL
, HFILL
}},
10269 { &hf_mptcp_analysis
,
10270 { "MPTCP analysis", "mptcp.analysis", FT_NONE
, BASE_NONE
, NULL
, 0x0,
10271 "This frame has some of the MPTCP analysis shown", HFILL
}},
10273 { &hf_mptcp_related_mapping
,
10274 { "Related mapping", "mptcp.related_mapping", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
10275 "Packet in which current packet DSS mapping was sent", HFILL
}},
10277 { &hf_mptcp_reinjection_of
,
10278 { "Reinjection of", "mptcp.reinjection_of", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
10279 "This is a retransmission of data sent on another subflow", HFILL
}},
10281 { &hf_mptcp_reinjected_in
,
10282 { "Data reinjected in", "mptcp.reinjected_in", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
10283 "This was retransmitted on another subflow", HFILL
}},
10285 { &hf_mptcp_analysis_subflows
,
10286 { "TCP subflow stream id(s)", "mptcp.analysis.subflows", FT_STRING
, BASE_NONE
, NULL
, 0x0,
10287 "List all TCP connections mapped to this MPTCP connection", HFILL
}},
10289 { &hf_mptcp_stream
,
10290 { "Stream index", "mptcp.stream", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
10293 { &hf_mptcp_number_of_removed_addresses
,
10294 { "Number of removed addresses", "mptcp.rm_addr.count", FT_UINT8
,
10295 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
10297 { &hf_mptcp_expected_token
,
10298 { "Subflow token generated from key", "mptcp.expected_token", FT_UINT32
,
10299 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
10301 { &hf_mptcp_analysis_master
,
10302 { "Master flow", "mptcp.master", FT_BOOLEAN
, BASE_NONE
,
10303 NULL
, 0x0, NULL
, HFILL
}}
10307 static build_valid_func tcp_da_src_values
[1] = {tcp_src_value
};
10308 static build_valid_func tcp_da_dst_values
[1] = {tcp_dst_value
};
10309 static build_valid_func tcp_da_both_values
[2] = {tcp_src_value
, tcp_dst_value
};
10310 static decode_as_value_t tcp_da_values
[3] = {{tcp_src_prompt
, 1, tcp_da_src_values
}, {tcp_dst_prompt
, 1, tcp_da_dst_values
}, {tcp_both_prompt
, 2, tcp_da_both_values
}};
10311 static decode_as_t tcp_da
= {"tcp", "tcp.port", 3, 2, tcp_da_values
, "TCP", "port(s) as",
10312 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
10314 module_t
*tcp_module
;
10315 module_t
*mptcp_module
;
10316 expert_module_t
* expert_tcp
;
10317 expert_module_t
* expert_mptcp
;
10319 proto_tcp
= proto_register_protocol("Transmission Control Protocol", "TCP", "tcp");
10320 tcp_handle
= register_dissector("tcp", dissect_tcp
, proto_tcp
);
10321 tcp_cap_handle
= register_capture_dissector("tcp", capture_tcp
, proto_tcp
);
10322 proto_register_field_array(proto_tcp
, hf
, array_length(hf
));
10323 proto_register_subtree_array(ett
, array_length(ett
));
10324 expert_tcp
= expert_register_protocol(proto_tcp
);
10325 expert_register_field_array(expert_tcp
, ei
, array_length(ei
));
10327 /* subdissector code */
10328 subdissector_table
= register_dissector_table("tcp.port",
10329 "TCP port", proto_tcp
, FT_UINT16
, BASE_DEC
);
10330 heur_subdissector_list
= register_heur_dissector_list_with_description("tcp", "TCP heuristic", proto_tcp
);
10331 tcp_option_table
= register_dissector_table("tcp.option",
10332 "TCP Options", proto_tcp
, FT_UINT8
, BASE_DEC
);
10334 /* Register TCP options as their own protocols so we can get the name of the option */
10335 proto_tcp_option_nop
= proto_register_protocol_in_name_only("TCP Option - No-Operation (NOP)", "No-Operation (NOP)", "tcp.options.nop", proto_tcp
, FT_BYTES
);
10336 proto_tcp_option_eol
= proto_register_protocol_in_name_only("TCP Option - End of Option List (EOL)", "End of Option List (EOL)", "tcp.options.eol", proto_tcp
, FT_BYTES
);
10337 proto_tcp_option_timestamp
= proto_register_protocol_in_name_only("TCP Option - Timestamps", "Timestamps", "tcp.options.timestamp", proto_tcp
, FT_BYTES
);
10338 proto_tcp_option_mss
= proto_register_protocol_in_name_only("TCP Option - Maximum segment size", "Maximum segment size", "tcp.options.mss", proto_tcp
, FT_BYTES
);
10339 proto_tcp_option_wscale
= proto_register_protocol_in_name_only("TCP Option - Window scale", "Window scale", "tcp.options.wscale", proto_tcp
, FT_BYTES
);
10340 proto_tcp_option_sack_perm
= proto_register_protocol_in_name_only("TCP Option - SACK permitted", "SACK permitted", "tcp.options.sack_perm", proto_tcp
, FT_BYTES
);
10341 proto_tcp_option_sack
= proto_register_protocol_in_name_only("TCP Option - SACK", "SACK", "tcp.options.sack", proto_tcp
, FT_BYTES
);
10342 proto_tcp_option_echo
= proto_register_protocol_in_name_only("TCP Option - Echo", "Echo", "tcp.options.echo", proto_tcp
, FT_BYTES
);
10343 proto_tcp_option_echoreply
= proto_register_protocol_in_name_only("TCP Option - Echo reply", "Echo reply", "tcp.options.echoreply", proto_tcp
, FT_BYTES
);
10344 proto_tcp_option_cc
= proto_register_protocol_in_name_only("TCP Option - CC", "CC", "tcp.options.cc", proto_tcp
, FT_BYTES
);
10345 proto_tcp_option_cc_new
= proto_register_protocol_in_name_only("TCP Option - CC.NEW", "CC.NEW", "tcp.options.ccnew", proto_tcp
, FT_BYTES
);
10346 proto_tcp_option_cc_echo
= proto_register_protocol_in_name_only("TCP Option - CC.ECHO", "CC.ECHO", "tcp.options.ccecho", proto_tcp
, FT_BYTES
);
10347 proto_tcp_option_ao
= proto_register_protocol_in_name_only("TCP Option - TCP AO", "TCP AO", "tcp.options.ao", proto_tcp
, FT_BYTES
);
10348 proto_tcp_option_md5
= proto_register_protocol_in_name_only("TCP Option - TCP MD5 signature", "TCP MD5 signature", "tcp.options.md5", proto_tcp
, FT_BYTES
);
10349 proto_tcp_option_scps
= proto_register_protocol_in_name_only("TCP Option - SCPS capabilities", "SCPS capabilities", "tcp.options.scps", proto_tcp
, FT_BYTES
);
10350 proto_tcp_option_snack
= proto_register_protocol_in_name_only("TCP Option - Selective Negative Acknowledgment", "Selective Negative Acknowledgment", "tcp.options.snack", proto_tcp
, FT_BYTES
);
10351 proto_tcp_option_scpsrec
= proto_register_protocol_in_name_only("TCP Option - SCPS record boundary", "SCPS record boundary", "tcp.options.scpsrec", proto_tcp
, FT_BYTES
);
10352 proto_tcp_option_scpscor
= proto_register_protocol_in_name_only("TCP Option - SCPS corruption experienced", "SCPS corruption experienced", "tcp.options.scpscor", proto_tcp
, FT_BYTES
);
10353 proto_tcp_option_qs
= proto_register_protocol_in_name_only("TCP Option - Quick-Start", "Quick-Start", "tcp.options.qs", proto_tcp
, FT_BYTES
);
10354 proto_tcp_option_user_to
= proto_register_protocol_in_name_only("TCP Option - User Timeout", "User Timeout", "tcp.options.user_to", proto_tcp
, FT_BYTES
);
10355 proto_tcp_option_tfo
= proto_register_protocol_in_name_only("TCP Option - TCP Fast Open", "TCP Fast Open", "tcp.options.tfo", proto_tcp
, FT_BYTES
);
10356 proto_tcp_option_acc_ecn
= proto_register_protocol_in_name_only("TCP Option - Accurate ECN", "Accurate ECN", "tcp.options.acc_ecn", proto_tcp
, FT_BYTES
);
10357 proto_tcp_option_rvbd_probe
= proto_register_protocol_in_name_only("TCP Option - Riverbed Probe", "Riverbed Probe", "tcp.options.rvbd.probe", proto_tcp
, FT_BYTES
);
10358 proto_tcp_option_rvbd_trpy
= proto_register_protocol_in_name_only("TCP Option - Riverbed Transparency", "Riverbed Transparency", "tcp.options.rvbd.trpy", proto_tcp
, FT_BYTES
);
10359 proto_tcp_option_exp
= proto_register_protocol_in_name_only("TCP Option - Experimental", "Experimental", "tcp.options.experimental", proto_tcp
, FT_BYTES
);
10360 proto_tcp_option_unknown
= proto_register_protocol_in_name_only("TCP Option - Unknown", "Unknown", "tcp.options.unknown", proto_tcp
, FT_BYTES
);
10362 register_capture_dissector_table("tcp.port", "TCP");
10364 /* Register configuration preferences */
10365 tcp_module
= prefs_register_protocol(proto_tcp
, NULL
);
10366 prefs_register_bool_preference(tcp_module
, "summary_in_tree",
10367 "Show TCP summary in protocol tree",
10368 "Whether the TCP summary line should be shown in the protocol tree",
10369 &tcp_summary_in_tree
);
10370 prefs_register_bool_preference(tcp_module
, "check_checksum",
10371 "Validate the TCP checksum if possible",
10372 "Whether to validate the TCP checksum or not. "
10373 "(Invalid checksums will cause reassembly, if enabled, to fail.)",
10374 &tcp_check_checksum
);
10375 prefs_register_bool_preference(tcp_module
, "desegment_tcp_streams",
10376 "Allow subdissector to reassemble TCP streams",
10377 "Whether subdissector can request TCP streams to be reassembled",
10379 prefs_register_bool_preference(tcp_module
, "reassemble_out_of_order",
10380 "Reassemble out-of-order segments",
10381 "Whether out-of-order segments should be buffered and reordered before passing it to a subdissector. "
10382 "To use this option you must also enable \"Allow subdissector to reassemble TCP streams\".",
10383 &tcp_reassemble_out_of_order
);
10384 prefs_register_bool_preference(tcp_module
, "analyze_sequence_numbers",
10385 "Analyze TCP sequence numbers",
10386 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
10388 prefs_register_bool_preference(tcp_module
, "relative_sequence_numbers",
10389 "Relative sequence numbers (Requires \"Analyze TCP sequence numbers\")",
10390 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
10391 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
10392 &tcp_relative_seq
);
10394 prefs_register_custom_preference_TCP_Analysis(tcp_module
, "default_override_analysis",
10395 "Force interpretation to selected packet(s)",
10396 "Override the default analysis with this value for the selected packet",
10397 &tcp_default_override_analysis
, override_analysis_vals
, false);
10399 prefs_register_enum_preference(tcp_module
, "default_window_scaling",
10400 "Scaling factor to use when not available from capture",
10401 "Make the TCP dissector use this scaling factor for streams where the signalled scaling factor "
10402 "is not visible in the capture",
10403 &tcp_default_window_scaling
, window_scaling_vals
, false);
10405 /* Presumably a retired, unconditional version of what has been added back with the preference above... */
10406 prefs_register_obsolete_preference(tcp_module
, "window_scaling");
10408 prefs_register_bool_preference(tcp_module
, "track_bytes_in_flight",
10409 "Track number of bytes in flight",
10410 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "
10411 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
10412 "This takes a lot of memory but allows you to track how much data are in flight at a time and graphing it in io-graphs",
10413 &tcp_track_bytes_in_flight
);
10414 prefs_register_bool_preference(tcp_module
, "bif_seq_based",
10415 "Evaluate bytes in flight based on sequence numbers",
10416 "Evaluate BiF on actual sequence numbers or use the historical method based on payloads (default). "
10417 "This option has no effect if not used with \"Track number of bytes in flight\". ",
10418 &tcp_bif_seq_based
);
10419 prefs_register_bool_preference(tcp_module
, "calculate_timestamps",
10420 "Calculate stream packet number and timestamps",
10421 "Calculate relative packet number and timestamps relative to the first frame and the previous frame in the tcp conversation",
10422 &tcp_calculate_ts
);
10423 prefs_register_bool_preference(tcp_module
, "try_heuristic_first",
10424 "Try heuristic sub-dissectors first",
10425 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
10426 &try_heuristic_first
);
10427 prefs_register_bool_preference(tcp_module
, "ignore_tcp_timestamps",
10428 "Ignore TCP Timestamps in summary",
10429 "Do not place the TCP Timestamps in the summary line",
10430 &tcp_ignore_timestamps
);
10431 prefs_register_bool_preference(tcp_module
, "fastrt_supersedes_ooo",
10432 "Fast Retransmission supersedes Out-of-Order interpretation",
10433 "When interpreting ambiguous packets, give precedence to Fast Retransmission or OOO ",
10434 &tcp_fastrt_precedence
);
10436 prefs_register_bool_preference(tcp_module
, "no_subdissector_on_error",
10437 "Do not call subdissectors for error packets",
10438 "Do not call any subdissectors for Retransmitted or OutOfOrder segments",
10439 &tcp_no_subdissector_on_error
);
10441 prefs_register_bool_preference(tcp_module
, "dissect_experimental_options_rfc6994",
10442 "TCP Experimental Options using the format of RFC 6994",
10443 "Assume TCP Experimental Options (253, 254) have an Experiment Identifier and use it for dissection",
10444 &tcp_exp_options_rfc6994
);
10446 prefs_register_bool_preference(tcp_module
, "display_process_info_from_ipfix",
10447 "Display process information via IPFIX",
10448 "Collect and store process information retrieved from IPFIX dissector",
10449 &tcp_display_process_info
);
10451 prefs_register_bool_preference(tcp_module
, "read_seq_as_syn_cookie",
10452 "Read the seq no. as syn cookie",
10453 "Read the sequence number as it was a syn cookie",
10454 &read_seq_as_syn_cookie
);
10456 register_init_routine(tcp_init
);
10457 reassembly_table_register(&tcp_reassembly_table
,
10458 &tcp_reassembly_table_functions
);
10460 register_decode_as(&tcp_da
);
10462 register_conversation_table(proto_tcp
, false, tcpip_conversation_packet
, tcpip_endpoint_packet
);
10463 register_conversation_filter("tcp", "TCP", tcp_filter_valid
, tcp_build_filter_by_id
, NULL
);
10465 register_seq_analysis("tcp", "TCP Flows", proto_tcp
, NULL
, TL_REQUIRES_NOTHING
, tcp_seq_analysis_packet
);
10467 /* considers MPTCP as a distinct protocol (even if it's a TCP option) */
10468 proto_mptcp
= proto_register_protocol("Multipath Transmission Control Protocol", "MPTCP", "mptcp");
10470 proto_register_field_array(proto_mptcp
, mptcp_hf
, array_length(mptcp_hf
));
10471 proto_register_subtree_array(mptcp_ett
, array_length(mptcp_ett
));
10473 /* Register configuration preferences */
10474 mptcp_module
= prefs_register_protocol(proto_mptcp
, NULL
);
10475 expert_mptcp
= expert_register_protocol(proto_tcp
);
10476 expert_register_field_array(expert_mptcp
, mptcp_ei
, array_length(mptcp_ei
));
10478 prefs_register_bool_preference(mptcp_module
, "analyze_mptcp",
10479 "Map TCP subflows to their respective MPTCP connections",
10480 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
10481 &tcp_analyze_mptcp
);
10483 prefs_register_bool_preference(mptcp_module
, "relative_sequence_numbers",
10484 "Display relative MPTCP sequence numbers.",
10485 "In case you don't capture the key, it will use the first DSN seen",
10486 &mptcp_relative_seq
);
10488 prefs_register_bool_preference(mptcp_module
, "analyze_mappings",
10489 "Deeper analysis of Data Sequence Signal (DSS)",
10490 "Scales logarithmically with the number of packets"
10491 "You need to capture the handshake for this to work."
10492 "\"Map TCP subflows to their respective MPTCP connections\"",
10493 &mptcp_analyze_mappings
);
10495 prefs_register_bool_preference(mptcp_module
, "intersubflows_retransmission",
10496 "Check for data duplication across subflows",
10497 "(Greedy algorithm: Scales linearly with number of subflows and"
10498 " logarithmic scaling with number of packets)"
10499 "You need to enable DSS mapping analysis for this option to work",
10500 &mptcp_intersubflows_retransmission
);
10502 register_conversation_table(proto_mptcp
, false, mptcpip_conversation_packet
, tcpip_endpoint_packet
);
10503 register_follow_stream(proto_tcp
, "tcp_follow", tcp_follow_conv_filter
, tcp_follow_index_filter
, tcp_follow_address_filter
,
10504 tcp_port_to_display
, follow_tcp_tap_listener
, get_tcp_stream_count
, NULL
);
10506 tcp_tap
= register_tap("tcp");
10507 tcp_follow_tap
= register_tap("tcp_follow");
10508 mptcp_tap
= register_tap("mptcp");
10512 proto_reg_handoff_tcp(void)
10514 dissector_add_uint("ip.proto", IP_PROTO_TCP
, tcp_handle
);
10515 dissector_add_for_decode_as_with_preference("udp.port", tcp_handle
);
10516 data_handle
= find_dissector("data");
10517 sport_handle
= find_dissector("sport");
10519 capture_dissector_add_uint("ip.proto", IP_PROTO_TCP
, tcp_cap_handle
);
10521 /* Create dissection function handles for all TCP options */
10522 dissector_add_uint("tcp.option", TCPOPT_TIMESTAMP
, create_dissector_handle( dissect_tcpopt_timestamp
, proto_tcp_option_timestamp
));
10523 dissector_add_uint("tcp.option", TCPOPT_MSS
, create_dissector_handle( dissect_tcpopt_mss
, proto_tcp_option_mss
));
10524 dissector_add_uint("tcp.option", TCPOPT_WINDOW
, create_dissector_handle( dissect_tcpopt_wscale
, proto_tcp_option_wscale
));
10525 dissector_add_uint("tcp.option", TCPOPT_SACK_PERM
, create_dissector_handle( dissect_tcpopt_sack_perm
, proto_tcp_option_sack_perm
));
10526 dissector_add_uint("tcp.option", TCPOPT_SACK
, create_dissector_handle( dissect_tcpopt_sack
, proto_tcp_option_sack
));
10527 dissector_add_uint("tcp.option", TCPOPT_ECHO
, create_dissector_handle( dissect_tcpopt_echo
, proto_tcp_option_echo
));
10528 dissector_add_uint("tcp.option", TCPOPT_ECHOREPLY
, create_dissector_handle( dissect_tcpopt_echo
, proto_tcp_option_echoreply
));
10529 dissector_add_uint("tcp.option", TCPOPT_CC
, create_dissector_handle( dissect_tcpopt_cc
, proto_tcp_option_cc
));
10530 dissector_add_uint("tcp.option", TCPOPT_CCNEW
, create_dissector_handle( dissect_tcpopt_cc
, proto_tcp_option_cc_new
));
10531 dissector_add_uint("tcp.option", TCPOPT_CCECHO
, create_dissector_handle( dissect_tcpopt_cc
, proto_tcp_option_cc_echo
));
10532 dissector_add_uint("tcp.option", TCPOPT_MD5
, create_dissector_handle( dissect_tcpopt_md5
, proto_tcp_option_md5
));
10533 dissector_add_uint("tcp.option", TCPOPT_AO
, create_dissector_handle( dissect_tcpopt_ao
, proto_tcp_option_ao
));
10534 dissector_add_uint("tcp.option", TCPOPT_SCPS
, create_dissector_handle( dissect_tcpopt_scps
, proto_tcp_option_scps
));
10535 dissector_add_uint("tcp.option", TCPOPT_SNACK
, create_dissector_handle( dissect_tcpopt_snack
, proto_tcp_option_snack
));
10536 dissector_add_uint("tcp.option", TCPOPT_RECBOUND
, create_dissector_handle( dissect_tcpopt_recbound
, proto_tcp_option_scpsrec
));
10537 dissector_add_uint("tcp.option", TCPOPT_CORREXP
, create_dissector_handle( dissect_tcpopt_correxp
, proto_tcp_option_scpscor
));
10538 dissector_add_uint("tcp.option", TCPOPT_QS
, create_dissector_handle( dissect_tcpopt_qs
, proto_tcp_option_qs
));
10539 dissector_add_uint("tcp.option", TCPOPT_USER_TO
, create_dissector_handle( dissect_tcpopt_user_to
, proto_tcp_option_user_to
));
10540 dissector_add_uint("tcp.option", TCPOPT_TFO
, create_dissector_handle( dissect_tcpopt_tfo
, proto_tcp_option_tfo
));
10541 dissector_add_uint("tcp.option", TCPOPT_RVBD_PROBE
, create_dissector_handle( dissect_tcpopt_rvbd_probe
, proto_tcp_option_rvbd_probe
));
10542 dissector_add_uint("tcp.option", TCPOPT_RVBD_TRPY
, create_dissector_handle( dissect_tcpopt_rvbd_trpy
, proto_tcp_option_rvbd_trpy
));
10543 dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_0
, create_dissector_handle( dissect_tcpopt_acc_ecn
, proto_tcp_option_acc_ecn
));
10544 dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_1
, create_dissector_handle( dissect_tcpopt_acc_ecn
, proto_tcp_option_acc_ecn
));
10545 dissector_add_uint("tcp.option", TCPOPT_EXP_FD
, create_dissector_handle( dissect_tcpopt_exp
, proto_tcp_option_exp
));
10546 dissector_add_uint("tcp.option", TCPOPT_EXP_FE
, create_dissector_handle( dissect_tcpopt_exp
, proto_tcp_option_exp
));
10547 dissector_add_uint("tcp.option", TCPOPT_MPTCP
, create_dissector_handle( dissect_tcpopt_mptcp
, proto_mptcp
));
10548 /* Common handle for all the unknown/unsupported TCP options */
10549 tcp_opt_unknown_handle
= create_dissector_handle( dissect_tcpopt_unknown
, proto_tcp_option_unknown
);
10551 exported_pdu_tap
= find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4
);
10553 proto_ip
= proto_get_id_by_filter_name("ip");
10554 proto_icmp
= proto_get_id_by_filter_name("icmp");
10561 * c-basic-offset: 4
10563 * indent-tabs-mode: nil
10566 * ex: set shiftwidth=4 tabstop=8 expandtab:
10567 * :indentSize=4:tabSize=8:noTabs=true: