Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-tcp.c
bloba71a98d6e7865702091fc850fc30997a74d5e4cf
1 /* packet-tcp.c
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
9 */
11 #include "config.h"
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>
31 #include <epan/tfs.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);
47 static int tcp_tap;
48 static int tcp_follow_tap;
49 static int mptcp_tap;
50 static int exported_pdu_tap;
52 /* Place TCP summary in proto tree */
53 static bool tcp_summary_in_tree = true;
55 #define TCP_DEFAULT_CLIENTPORT_DISSECTORS "20"
56 static range_t *tcp_clientport_dissectors_range;
58 static inline uint64_t keep_32msb_of_uint64(uint64_t nb) {
59 return (nb >> 32) << 32;
62 #define MPTCP_DSS_FLAG_DATA_ACK_PRESENT 0x01
63 #define MPTCP_DSS_FLAG_DATA_ACK_8BYTES 0x02
64 #define MPTCP_DSS_FLAG_MAPPING_PRESENT 0x04
65 #define MPTCP_DSS_FLAG_DSN_8BYTES 0x08
66 #define MPTCP_DSS_FLAG_DATA_FIN_PRESENT 0x10
69 * Flag to control whether to check the TCP checksum.
71 * In at least some Solaris network traces, there are packets with bad
72 * TCP checksums, but the traffic appears to indicate that the packets
73 * *were* received; the packets were probably sent by the host on which
74 * the capture was being done, on a network interface to which
75 * checksumming was offloaded, so that DLPI supplied an un-checksummed
76 * packet to the capture program but a checksummed packet got put onto
77 * the wire.
79 static bool tcp_check_checksum;
82 * Window scaling values to be used when not known (set as a preference) */
83 enum scaling_window_value {
84 WindowScaling_NotKnown=-1,
85 WindowScaling_0=0,
86 WindowScaling_1,
87 WindowScaling_2,
88 WindowScaling_3,
89 WindowScaling_4,
90 WindowScaling_5,
91 WindowScaling_6,
92 WindowScaling_7,
93 WindowScaling_8,
94 WindowScaling_9,
95 WindowScaling_10,
96 WindowScaling_11,
97 WindowScaling_12,
98 WindowScaling_13,
99 WindowScaling_14
103 * Analysis overriding values to be used when not satisfied by the automatic
104 * result. (Accessed through preferences but not stored as a preference)
106 enum override_analysis_value {
107 OverrideAnalysis_0=0,
108 OverrideAnalysis_1,
109 OverrideAnalysis_2,
110 OverrideAnalysis_3,
111 OverrideAnalysis_4
115 * Using enum instead of boolean make API easier
117 enum mptcp_dsn_conversion {
118 DSN_CONV_64_TO_32,
119 DSN_CONV_32_TO_64,
120 DSN_CONV_NONE
123 #define MPTCP_TCPRST_FLAG_T_PRESENT 0x1
124 #define MPTCP_TCPRST_FLAG_W_PRESENT 0x2
125 #define MPTCP_TCPRST_FLAG_V_PRESENT 0x4
126 #define MPTCP_TCPRST_FLAG_U_PRESENT 0x8
128 static const value_string mp_tcprst_reasons[] = {
129 { 0x0, "Unspecified error" },
130 { 0x1, "MPTCP-specific error" },
131 { 0x2, "Lack of resources" },
132 { 0x3, "Administratively prohibited" },
133 { 0x4, "Too much outstanding data" },
134 { 0x5, "Unacceptable performance" },
135 { 0x6, "Middlebox interference" },
136 { 0, NULL },
139 static int tcp_default_window_scaling = (int)WindowScaling_NotKnown;
141 static int tcp_default_override_analysis = (int)OverrideAnalysis_0;
143 static int proto_tcp;
144 static int proto_ip;
145 static int proto_icmp;
147 static int proto_tcp_option_nop;
148 static int proto_tcp_option_eol;
149 static int proto_tcp_option_timestamp;
150 static int proto_tcp_option_mss;
151 static int proto_tcp_option_wscale;
152 static int proto_tcp_option_sack_perm;
153 static int proto_tcp_option_sack;
154 static int proto_tcp_option_echo;
155 static int proto_tcp_option_echoreply;
156 static int proto_tcp_option_cc;
157 static int proto_tcp_option_cc_new;
158 static int proto_tcp_option_cc_echo;
159 static int proto_tcp_option_md5;
160 static int proto_tcp_option_ao;
161 static int proto_tcp_option_scps;
162 static int proto_tcp_option_snack;
163 static int proto_tcp_option_scpsrec;
164 static int proto_tcp_option_scpscor;
165 static int proto_tcp_option_qs;
166 static int proto_tcp_option_user_to;
167 static int proto_tcp_option_tfo;
168 static int proto_tcp_option_acc_ecn;
169 static int proto_tcp_option_rvbd_probe;
170 static int proto_tcp_option_rvbd_trpy;
171 static int proto_tcp_option_exp;
172 static int proto_tcp_option_unknown;
173 static int proto_mptcp;
175 static int hf_tcp_srcport;
176 static int hf_tcp_dstport;
177 static int hf_tcp_port;
178 static int hf_tcp_stream;
179 static int hf_tcp_stream_pnum;
180 static int hf_tcp_completeness;
181 static int hf_tcp_completeness_syn;
182 static int hf_tcp_completeness_syn_ack;
183 static int hf_tcp_completeness_ack;
184 static int hf_tcp_completeness_data;
185 static int hf_tcp_completeness_fin;
186 static int hf_tcp_completeness_rst;
187 static int hf_tcp_completeness_str;
188 static int hf_tcp_seq;
189 static int hf_tcp_seq_abs;
190 static int hf_tcp_nxtseq;
191 static int hf_tcp_ack;
192 static int hf_tcp_ack_abs;
193 static int hf_tcp_hdr_len;
194 static int hf_tcp_flags;
195 static int hf_tcp_flags_res;
196 static int hf_tcp_flags_ae;
197 static int hf_tcp_flags_cwr;
198 static int hf_tcp_flags_ece;
199 static int hf_tcp_flags_ace;
200 static int hf_tcp_flags_urg;
201 static int hf_tcp_flags_ack;
202 static int hf_tcp_flags_push;
203 static int hf_tcp_flags_reset;
204 static int hf_tcp_flags_syn;
205 static int hf_tcp_flags_fin;
206 static int hf_tcp_flags_str;
207 static int hf_tcp_window_size_value;
208 static int hf_tcp_window_size;
209 static int hf_tcp_window_size_scalefactor;
210 static int hf_tcp_checksum;
211 static int hf_tcp_checksum_status;
212 static int hf_tcp_checksum_calculated;
213 static int hf_tcp_len;
214 static int hf_tcp_urgent_pointer;
215 static int hf_tcp_analysis;
216 static int hf_tcp_analysis_flags;
217 static int hf_tcp_analysis_bytes_in_flight;
218 static int hf_tcp_analysis_push_bytes_sent;
219 static int hf_tcp_analysis_acks_frame;
220 static int hf_tcp_analysis_ack_rtt;
221 static int hf_tcp_analysis_first_rtt;
222 static int hf_tcp_analysis_rto;
223 static int hf_tcp_analysis_rto_frame;
224 static int hf_tcp_analysis_duplicate_ack;
225 static int hf_tcp_analysis_duplicate_ack_num;
226 static int hf_tcp_analysis_duplicate_ack_frame;
227 static int hf_tcp_continuation_to;
228 static int hf_tcp_pdu_time;
229 static int hf_tcp_pdu_size;
230 static int hf_tcp_pdu_last_frame;
231 static int hf_tcp_reassembled_in;
232 static int hf_tcp_reassembled_length;
233 static int hf_tcp_reassembled_data;
234 static int hf_tcp_segments;
235 static int hf_tcp_segment;
236 static int hf_tcp_segment_overlap;
237 static int hf_tcp_segment_overlap_conflict;
238 static int hf_tcp_segment_multiple_tails;
239 static int hf_tcp_segment_too_long_fragment;
240 static int hf_tcp_segment_error;
241 static int hf_tcp_segment_count;
242 static int hf_tcp_options;
243 static int hf_tcp_option_kind;
244 static int hf_tcp_option_len;
245 static int hf_tcp_option_mss_val;
246 static int hf_tcp_option_wscale_shift;
247 static int hf_tcp_option_wscale_multiplier;
248 static int hf_tcp_option_sack_sle;
249 static int hf_tcp_option_sack_sre;
250 static int hf_tcp_option_sack_range_count;
251 static int hf_tcp_option_sack_dsack_le;
252 static int hf_tcp_option_sack_dsack_re;
253 static int hf_tcp_option_echo;
254 static int hf_tcp_option_timestamp_tsval;
255 static int hf_tcp_option_timestamp_tsecr;
256 static int hf_tcp_option_cc;
257 static int hf_tcp_option_md5_digest;
258 static int hf_tcp_option_ao_keyid;
259 static int hf_tcp_option_ao_rnextkeyid;
260 static int hf_tcp_option_ao_mac;
261 static int hf_tcp_option_qs_rate;
262 static int hf_tcp_option_qs_ttl_diff;
263 static int hf_tcp_option_tarr_rate;
264 static int hf_tcp_option_tarr_reserved;
265 static int hf_tcp_option_acc_ecn_ee0b;
266 static int hf_tcp_option_acc_ecn_eceb;
267 static int hf_tcp_option_acc_ecn_ee1b;
268 static int hf_tcp_option_exp_data;
269 static int hf_tcp_option_exp_exid;
270 static int hf_tcp_option_unknown_payload;
272 static int hf_tcp_option_rvbd_probe_version1;
273 static int hf_tcp_option_rvbd_probe_version2;
274 static int hf_tcp_option_rvbd_probe_type1;
275 static int hf_tcp_option_rvbd_probe_type2;
276 static int hf_tcp_option_rvbd_probe_prober;
277 static int hf_tcp_option_rvbd_probe_proxy;
278 static int hf_tcp_option_rvbd_probe_client;
279 static int hf_tcp_option_rvbd_probe_proxy_port;
280 static int hf_tcp_option_rvbd_probe_appli_ver;
281 static int hf_tcp_option_rvbd_probe_storeid;
282 static int hf_tcp_option_rvbd_probe_flags;
283 static int hf_tcp_option_rvbd_probe_flag_last_notify;
284 static int hf_tcp_option_rvbd_probe_flag_server_connected;
285 static int hf_tcp_option_rvbd_probe_flag_not_cfe;
286 static int hf_tcp_option_rvbd_probe_flag_sslcert;
287 static int hf_tcp_option_rvbd_probe_flag_probe_cache;
289 static int hf_tcp_option_rvbd_trpy_flags;
290 static int hf_tcp_option_rvbd_trpy_flag_mode;
291 static int hf_tcp_option_rvbd_trpy_flag_oob;
292 static int hf_tcp_option_rvbd_trpy_flag_chksum;
293 static int hf_tcp_option_rvbd_trpy_flag_fw_rst;
294 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_inner;
295 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_probe;
296 static int hf_tcp_option_rvbd_trpy_src;
297 static int hf_tcp_option_rvbd_trpy_dst;
298 static int hf_tcp_option_rvbd_trpy_src_port;
299 static int hf_tcp_option_rvbd_trpy_dst_port;
300 static int hf_tcp_option_rvbd_trpy_client_port;
302 static int hf_tcp_option_mptcp_flags;
303 static int hf_tcp_option_mptcp_backup_flag;
304 static int hf_tcp_option_mptcp_checksum_flag;
305 static int hf_tcp_option_mptcp_B_flag;
306 static int hf_tcp_option_mptcp_C_flag;
307 static int hf_tcp_option_mptcp_H_v0_flag;
308 static int hf_tcp_option_mptcp_H_v1_flag;
309 static int hf_tcp_option_mptcp_F_flag;
310 static int hf_tcp_option_mptcp_m_flag;
311 static int hf_tcp_option_mptcp_M_flag;
312 static int hf_tcp_option_mptcp_a_flag;
313 static int hf_tcp_option_mptcp_A_flag;
314 static int hf_tcp_option_mptcp_U_flag;
315 static int hf_tcp_option_mptcp_V_flag;
316 static int hf_tcp_option_mptcp_W_flag;
317 static int hf_tcp_option_mptcp_T_flag;
318 static int hf_tcp_option_mptcp_tcprst_reason;
319 static int hf_tcp_option_mptcp_reserved_v0_flag;
320 static int hf_tcp_option_mptcp_reserved_v1_flag;
321 static int hf_tcp_option_mptcp_subtype;
322 static int hf_tcp_option_mptcp_version;
323 static int hf_tcp_option_mptcp_reserved;
324 static int hf_tcp_option_mptcp_address_id;
325 static int hf_tcp_option_mptcp_recv_token;
326 static int hf_tcp_option_mptcp_sender_key;
327 static int hf_tcp_option_mptcp_recv_key;
328 static int hf_tcp_option_mptcp_sender_rand;
329 static int hf_tcp_option_mptcp_sender_trunc_hmac;
330 static int hf_tcp_option_mptcp_sender_hmac;
331 static int hf_tcp_option_mptcp_addaddr_trunc_hmac;
332 static int hf_tcp_option_mptcp_data_ack_raw;
333 static int hf_tcp_option_mptcp_data_seq_no_raw;
334 static int hf_tcp_option_mptcp_subflow_seq_no;
335 static int hf_tcp_option_mptcp_data_lvl_len;
336 static int hf_tcp_option_mptcp_checksum;
337 static int hf_tcp_option_mptcp_ipver;
338 static int hf_tcp_option_mptcp_echo;
339 static int hf_tcp_option_mptcp_ipv4;
340 static int hf_tcp_option_mptcp_ipv6;
341 static int hf_tcp_option_mptcp_port;
342 static int hf_mptcp_expected_idsn;
344 static int hf_mptcp_dsn;
345 static int hf_mptcp_rawdsn64;
346 static int hf_mptcp_dss_dsn;
347 static int hf_mptcp_ack;
348 static int hf_mptcp_stream;
349 static int hf_mptcp_expected_token;
350 static int hf_mptcp_analysis;
351 static int hf_mptcp_analysis_master;
352 static int hf_mptcp_analysis_subflows;
353 static int hf_mptcp_number_of_removed_addresses;
354 static int hf_mptcp_related_mapping;
355 static int hf_mptcp_reinjection_of;
356 static int hf_mptcp_reinjected_in;
359 static int hf_tcp_option_fast_open_cookie_request;
360 static int hf_tcp_option_fast_open_cookie;
362 static int hf_tcp_ts_relative;
363 static int hf_tcp_ts_delta;
364 static int hf_tcp_option_scps_vector;
365 static int hf_tcp_option_scps_binding;
366 static int hf_tcp_option_scps_binding_len;
367 static int hf_tcp_scpsoption_flags_bets;
368 static int hf_tcp_scpsoption_flags_snack1;
369 static int hf_tcp_scpsoption_flags_snack2;
370 static int hf_tcp_scpsoption_flags_compress;
371 static int hf_tcp_scpsoption_flags_nlts;
372 static int hf_tcp_scpsoption_flags_reserved;
373 static int hf_tcp_scpsoption_connection_id;
374 static int hf_tcp_option_snack_offset;
375 static int hf_tcp_option_snack_size;
376 static int hf_tcp_option_snack_le;
377 static int hf_tcp_option_snack_re;
378 static int hf_tcp_option_user_to_granularity;
379 static int hf_tcp_option_user_to_val;
380 static int hf_tcp_proc_src_uid;
381 static int hf_tcp_proc_src_pid;
382 static int hf_tcp_proc_src_uname;
383 static int hf_tcp_proc_src_cmd;
384 static int hf_tcp_proc_dst_uid;
385 static int hf_tcp_proc_dst_pid;
386 static int hf_tcp_proc_dst_uname;
387 static int hf_tcp_proc_dst_cmd;
388 static int hf_tcp_segment_data;
389 static int hf_tcp_payload;
390 static int hf_tcp_reset_cause;
391 static int hf_tcp_fin_retransmission;
392 static int hf_tcp_option_rvbd_probe_reserved;
393 static int hf_tcp_option_scps_binding_data;
394 static int hf_tcp_syncookie_time;
395 static int hf_tcp_syncookie_mss;
396 static int hf_tcp_syncookie_hash;
397 static int hf_tcp_syncookie_option_timestamp;
398 static int hf_tcp_syncookie_option_ecn;
399 static int hf_tcp_syncookie_option_sack;
400 static int hf_tcp_syncookie_option_wscale;
401 static int hf_tcp_ns_reset_window_error_code;
403 static int ett_tcp;
404 static int ett_tcp_completeness;
405 static int ett_tcp_flags;
406 static int ett_tcp_options;
407 static int ett_tcp_option_timestamp;
408 static int ett_tcp_option_mss;
409 static int ett_tcp_option_wscale;
410 static int ett_tcp_option_sack;
411 static int ett_tcp_option_snack;
412 static int ett_tcp_option_scps;
413 static int ett_tcp_scpsoption_flags;
414 static int ett_tcp_option_scps_extended;
415 static int ett_tcp_option_user_to;
416 static int ett_tcp_option_exp;
417 static int ett_tcp_option_acc_ecn;
418 static int ett_tcp_option_sack_perm;
419 static int ett_tcp_analysis;
420 static int ett_tcp_analysis_faults;
421 static int ett_tcp_timestamps;
422 static int ett_tcp_segments;
423 static int ett_tcp_segment;
424 static int ett_tcp_checksum;
425 static int ett_tcp_process_info;
426 static int ett_tcp_option_mptcp;
427 static int ett_tcp_opt_rvbd_probe;
428 static int ett_tcp_opt_rvbd_probe_flags;
429 static int ett_tcp_opt_rvbd_trpy;
430 static int ett_tcp_opt_rvbd_trpy_flags;
431 static int ett_tcp_opt_echo;
432 static int ett_tcp_opt_cc;
433 static int ett_tcp_opt_md5;
434 static int ett_tcp_opt_ao;
435 static int ett_tcp_opt_qs;
436 static int ett_tcp_opt_recbound;
437 static int ett_tcp_opt_scpscor;
438 static int ett_tcp_unknown_opt;
439 static int ett_tcp_option_other;
440 static int ett_tcp_syncookie;
441 static int ett_tcp_syncookie_option;
442 static int ett_mptcp_analysis;
443 static int ett_mptcp_analysis_subflows;
445 static expert_field ei_tcp_opt_len_invalid;
446 static expert_field ei_tcp_analysis_retransmission;
447 static expert_field ei_tcp_analysis_fast_retransmission;
448 static expert_field ei_tcp_analysis_spurious_retransmission;
449 static expert_field ei_tcp_analysis_out_of_order;
450 static expert_field ei_tcp_analysis_reused_ports;
451 static expert_field ei_tcp_analysis_lost_packet;
452 static expert_field ei_tcp_analysis_ack_lost_packet;
453 static expert_field ei_tcp_analysis_window_update;
454 static expert_field ei_tcp_analysis_window_full;
455 static expert_field ei_tcp_analysis_keep_alive;
456 static expert_field ei_tcp_analysis_keep_alive_ack;
457 static expert_field ei_tcp_analysis_duplicate_ack;
458 static expert_field ei_tcp_analysis_zero_window_probe;
459 static expert_field ei_tcp_analysis_zero_window;
460 static expert_field ei_tcp_analysis_zero_window_probe_ack;
461 static expert_field ei_tcp_analysis_tfo_syn;
462 static expert_field ei_tcp_analysis_tfo_ack;
463 static expert_field ei_tcp_analysis_tfo_ignored;
464 static expert_field ei_tcp_analysis_partial_ack;
465 static expert_field ei_tcp_analysis_ambiguous_ack;
466 static expert_field ei_tcp_scps_capable;
467 static expert_field ei_tcp_option_sack_dsack;
468 static expert_field ei_tcp_option_snack_sequence;
469 static expert_field ei_tcp_option_wscale_shift_invalid;
470 static expert_field ei_tcp_option_mss_absent;
471 static expert_field ei_tcp_option_mss_present;
472 static expert_field ei_tcp_option_mss_exceeded;
473 static expert_field ei_tcp_option_sack_perm_absent;
474 static expert_field ei_tcp_option_sack_perm_present;
475 static expert_field ei_tcp_short_segment;
476 static expert_field ei_tcp_ack_nonzero;
477 static expert_field ei_tcp_connection_synack;
478 static expert_field ei_tcp_connection_syn;
479 static expert_field ei_tcp_connection_fin;
480 static expert_field ei_tcp_connection_rst;
481 static expert_field ei_tcp_connection_fin_active;
482 static expert_field ei_tcp_connection_fin_passive;
483 static expert_field ei_tcp_checksum_ffff;
484 static expert_field ei_tcp_checksum_partial;
485 static expert_field ei_tcp_checksum_bad;
486 static expert_field ei_tcp_urgent_pointer_non_zero;
487 static expert_field ei_tcp_suboption_malformed;
488 static expert_field ei_tcp_nop;
489 static expert_field ei_tcp_non_zero_bytes_after_eol;
490 static expert_field ei_tcp_bogus_header_length;
492 /* static expert_field ei_mptcp_analysis_unexpected_idsn; */
493 static expert_field ei_mptcp_analysis_echoed_key_mismatch;
494 static expert_field ei_mptcp_analysis_missing_algorithm;
495 static expert_field ei_mptcp_analysis_unsupported_algorithm;
496 static expert_field ei_mptcp_infinite_mapping;
497 static expert_field ei_mptcp_mapping_missing;
498 /* static expert_field ei_mptcp_stream_incomplete; */
499 /* static expert_field ei_mptcp_analysis_dsn_out_of_order; */
501 /* Some protocols such as encrypted DCE/RPCoverHTTP have dependencies
502 * from one PDU to the next PDU and require that they are called in sequence.
503 * These protocols would not be able to handle PDUs coming out of order
504 * or for example when a PDU is seen twice, like for retransmissions.
505 * This preference can be set for such protocols to make sure that we don't
506 * invoke the subdissectors for retransmitted or out-of-order segments.
508 static bool tcp_no_subdissector_on_error = true;
510 /* Enable buffering of out-of-order TCP segments before passing it to a
511 * subdissector (depends on "tcp_desegment"). */
512 static bool tcp_reassemble_out_of_order;
515 * FF: https://www.rfc-editor.org/rfc/rfc6994.html
516 * With this flag set we assume the option structure for experimental
517 * codepoints (253, 254) has an Experiment Identifier (ExID), which is
518 * the first 16-bit field after the Kind and Length.
519 * The ExID is used to differentiate different experiments and thus will
520 * be used in data dissection.
522 static bool tcp_exp_options_rfc6994 = true;
525 * This flag indicates which of Fast Retransmission or Out-of-Order
526 * interpretation should supersede when analyzing an ambiguous packet as
527 * things are not always clear. The user is authorized to change this
528 * behavior.
529 * When set, we keep the historical interpretation (Fast RT > OOO)
531 static bool tcp_fastrt_precedence = true;
533 /* Process info, currently discovered via IPFIX */
534 static bool tcp_display_process_info;
536 /* Read the sequence number as syn cookie */
537 static bool read_seq_as_syn_cookie;
540 * TCP option
542 #define TCPOPT_NOP 1 /* Padding */
543 #define TCPOPT_EOL 0 /* End of options */
544 #define TCPOPT_MSS 2 /* Segment size negotiating */
545 #define TCPOPT_WINDOW 3 /* Window scaling */
546 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
547 #define TCPOPT_SACK 5 /* SACK Block */
548 #define TCPOPT_ECHO 6
549 #define TCPOPT_ECHOREPLY 7
550 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
551 #define TCPOPT_CC 11
552 #define TCPOPT_CCNEW 12
553 #define TCPOPT_CCECHO 13
554 #define TCPOPT_MD5 19 /* RFC2385 */
555 #define TCPOPT_SCPS 20 /* SCPS Capabilities */
556 #define TCPOPT_SNACK 21 /* SCPS SNACK */
557 #define TCPOPT_RECBOUND 22 /* SCPS Record Boundary */
558 #define TCPOPT_CORREXP 23 /* SCPS Corruption Experienced */
559 #define TCPOPT_QS 27 /* RFC4782 Quick-Start Response */
560 #define TCPOPT_USER_TO 28 /* RFC5482 User Timeout Option */
561 #define TCPOPT_AO 29 /* RFC5925 The TCP Authentication Option */
562 #define TCPOPT_MPTCP 30 /* RFC6824 Multipath TCP */
563 #define TCPOPT_TFO 34 /* RFC7413 TCP Fast Open Cookie */
564 #define TCPOPT_ACC_ECN_0 0xac /* draft-ietf-tcpm-accurate-ecn */
565 #define TCPOPT_ACC_ECN_1 0xae /* draft-ietf-tcpm-accurate-ecn */
566 #define TCPOPT_EXP_FD 0xfd /* Experimental, reserved */
567 #define TCPOPT_EXP_FE 0xfe /* Experimental, reserved */
568 /* Non IANA registered option numbers */
569 #define TCPOPT_RVBD_PROBE 76 /* Riverbed probe option */
570 #define TCPOPT_RVBD_TRPY 78 /* Riverbed transparency option */
573 * TCP option lengths
575 #define TCPOLEN_MSS 4
576 #define TCPOLEN_WINDOW 3
577 #define TCPOLEN_SACK_PERM 2
578 #define TCPOLEN_SACK_MIN 2
579 #define TCPOLEN_ECHO 6
580 #define TCPOLEN_ECHOREPLY 6
581 #define TCPOLEN_TIMESTAMP 10
582 #define TCPOLEN_CC 6
583 #define TCPOLEN_CCNEW 6
584 #define TCPOLEN_CCECHO 6
585 #define TCPOLEN_MD5 18
586 #define TCPOLEN_SCPS 4
587 #define TCPOLEN_SNACK 6
588 #define TCPOLEN_RECBOUND 2
589 #define TCPOLEN_CORREXP 2
590 #define TCPOLEN_QS 8
591 #define TCPOLEN_USER_TO 4
592 #define TCPOLEN_MPTCP_MIN 3
593 #define TCPOLEN_TFO_MIN 2
594 #define TCPOLEN_RVBD_PROBE_MIN 3
595 #define TCPOLEN_RVBD_TRPY_MIN 16
596 #define TCPOLEN_EXP_MIN 4
599 * TCP Experimental Option Experiment Identifiers (TCP ExIDs)
600 * See: https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-exids
601 * Wireshark only supports 16-bit ExIDs
604 #define TCPEXID_TARR 0x00ac
605 #define TCPEXID_HOST_ID 0x0348
606 #define TCPEXID_ASC 0x0a0d
607 #define TCPEXID_CAPABILITY 0x0ca0
608 #define TCPEXID_EDO 0x0ed0
609 #define TCPEXID_ENO 0x454e
610 #define TCPEXID_SNO 0x5323
611 #define TCPEXID_TS_INTERVAL 0x75ec /* 32-bit ExID: 0x75ecffee */
612 #define TCPEXID_ACC_ECN_0 0xacc0
613 #define TCPEXID_ACC_ECN_1 0xacc1
614 #define TCPEXID_ACC_ECN 0xacce
615 #define TCPEXID_SMC_R 0xe2d4 /* 32-bit ExID: 0xe2d4c3d9 */
616 #define TCPEXID_FO 0xf989
617 #define TCPEXID_LOW_LATENCY 0xf990
620 * Multipath TCP subtypes
622 #define TCPOPT_MPTCP_MP_CAPABLE 0x0 /* Multipath TCP Multipath Capable */
623 #define TCPOPT_MPTCP_MP_JOIN 0x1 /* Multipath TCP Join Connection */
624 #define TCPOPT_MPTCP_DSS 0x2 /* Multipath TCP Data Sequence Signal */
625 #define TCPOPT_MPTCP_ADD_ADDR 0x3 /* Multipath TCP Add Address */
626 #define TCPOPT_MPTCP_REMOVE_ADDR 0x4 /* Multipath TCP Remove Address */
627 #define TCPOPT_MPTCP_MP_PRIO 0x5 /* Multipath TCP Change Subflow Priority */
628 #define TCPOPT_MPTCP_MP_FAIL 0x6 /* Multipath TCP Fallback */
629 #define TCPOPT_MPTCP_MP_FASTCLOSE 0x7 /* Multipath TCP Fast Close */
630 #define TCPOPT_MPTCP_MP_TCPRST 0x8 /* Multipath TCP Reset */
633 * Conversation Completeness values
635 #define TCP_COMPLETENESS_SYNSENT 0x01 /* TCP SYN SENT */
636 #define TCP_COMPLETENESS_SYNACK 0x02 /* TCP SYN ACK */
637 #define TCP_COMPLETENESS_ACK 0x04 /* TCP ACK */
638 #define TCP_COMPLETENESS_DATA 0x08 /* TCP data */
639 #define TCP_COMPLETENESS_FIN 0x10 /* TCP FIN */
640 #define TCP_COMPLETENESS_RST 0x20 /* TCP RST */
642 static const true_false_string tcp_option_user_to_granularity = {
643 "Minutes", "Seconds"
646 static const value_string tcp_option_kind_vs[] = {
647 { TCPOPT_EOL, "End of Option List" },
648 { TCPOPT_NOP, "No-Operation" },
649 { TCPOPT_MSS, "Maximum Segment Size" },
650 { TCPOPT_WINDOW, "Window Scale" },
651 { TCPOPT_SACK_PERM, "SACK Permitted" },
652 { TCPOPT_SACK, "SACK" },
653 { TCPOPT_ECHO, "Echo" },
654 { TCPOPT_ECHOREPLY, "Echo Reply" },
655 { TCPOPT_TIMESTAMP, "Time Stamp Option" },
656 { 9, "Partial Order Connection Permitted" },
657 { 10, "Partial Order Service Profile" },
658 { TCPOPT_CC, "CC" },
659 { TCPOPT_CCNEW, "CC.NEW" },
660 { TCPOPT_CCECHO, "CC.ECHO" },
661 { 14, "TCP Alternate Checksum Request" },
662 { 15, "TCP Alternate Checksum Data" },
663 { 16, "Skeeter" },
664 { 17, "Bubba" },
665 { 18, "Trailer Checksum Option" },
666 { TCPOPT_MD5, "MD5 Signature Option" },
667 { TCPOPT_SCPS, "SCPS Capabilities" },
668 { TCPOPT_SNACK, "Selective Negative Acknowledgements" },
669 { TCPOPT_RECBOUND, "Record Boundaries" },
670 { TCPOPT_CORREXP, "Corruption experienced" },
671 { 24, "SNAP" },
672 { 25, "Unassigned" },
673 { 26, "TCP Compression Filter" },
674 { TCPOPT_QS, "Quick-Start Response" },
675 { TCPOPT_USER_TO, "User Timeout Option" },
676 { TCPOPT_AO, "The TCP Authentication Option" },
677 { TCPOPT_MPTCP, "Multipath TCP" },
678 { TCPOPT_TFO, "TCP Fast Open Cookie" },
679 { TCPOPT_RVBD_PROBE, "Riverbed Probe" },
680 { TCPOPT_RVBD_TRPY, "Riverbed Transparency" },
681 { TCPOPT_ACC_ECN_0, "Accurate ECN Order 0" },
682 { TCPOPT_ACC_ECN_1, "Accurate ECN Order 1" },
683 { TCPOPT_EXP_FD, "RFC3692-style Experiment 1" },
684 { TCPOPT_EXP_FE, "RFC3692-style Experiment 2" },
685 { 0, NULL }
687 static value_string_ext tcp_option_kind_vs_ext = VALUE_STRING_EXT_INIT(tcp_option_kind_vs);
689 static const value_string tcp_exid_vs[] = {
690 { TCPEXID_TARR, "TCP ACK Rate Request" },
691 { TCPEXID_HOST_ID, "Host ID" },
692 { TCPEXID_ASC, "Autonomous System Compensation" },
693 { TCPEXID_CAPABILITY, "Capability Option" },
694 { TCPEXID_EDO, "Extended Data Offset" },
695 { TCPEXID_ENO, "Encryption Negotiation" },
696 { TCPEXID_SNO, "Service Number" },
697 { TCPEXID_TS_INTERVAL, "Timestamp Interval" },
698 { TCPEXID_ACC_ECN_0, "Accurate ECN - Order 0" },
699 { TCPEXID_ACC_ECN_1, "Accurate ECN - Order 1" },
700 { TCPEXID_ACC_ECN, "Accurate ECN" },
701 { TCPEXID_SMC_R, "Shared Memory communications over RMDA protocol" },
702 { TCPEXID_FO, "Fast Open" },
703 { TCPEXID_LOW_LATENCY, "Low Latency" },
704 { 0, NULL }
707 /* not all of the hf_fields below make sense for TCP but we have to provide
708 them anyways to comply with the API (which was aimed for IP fragment
709 reassembly) */
710 static const fragment_items tcp_segment_items = {
711 &ett_tcp_segment,
712 &ett_tcp_segments,
713 &hf_tcp_segments,
714 &hf_tcp_segment,
715 &hf_tcp_segment_overlap,
716 &hf_tcp_segment_overlap_conflict,
717 &hf_tcp_segment_multiple_tails,
718 &hf_tcp_segment_too_long_fragment,
719 &hf_tcp_segment_error,
720 &hf_tcp_segment_count,
721 &hf_tcp_reassembled_in,
722 &hf_tcp_reassembled_length,
723 &hf_tcp_reassembled_data,
724 "Segments"
728 static const value_string mptcp_subtype_vs[] = {
729 { TCPOPT_MPTCP_MP_CAPABLE, "Multipath Capable" },
730 { TCPOPT_MPTCP_MP_JOIN, "Join Connection" },
731 { TCPOPT_MPTCP_DSS, "Data Sequence Signal" },
732 { TCPOPT_MPTCP_ADD_ADDR, "Add Address"},
733 { TCPOPT_MPTCP_REMOVE_ADDR, "Remove Address" },
734 { TCPOPT_MPTCP_MP_PRIO, "Change Subflow Priority" },
735 { TCPOPT_MPTCP_MP_FAIL, "TCP Fallback" },
736 { TCPOPT_MPTCP_MP_FASTCLOSE, "Fast Close" },
737 { TCPOPT_MPTCP_MP_TCPRST, "TCP Reset" },
738 { 0, NULL }
741 /* Source https://support.citrix.com/article/CTX200852/citrix-adc-netscaler-reset-codes-reference
742 Dates of source: Created: 31 Mar 2015 | Modified: 21 Jan 2023
743 Date of last dictionary update: 2024/07/11
744 NOTE: When updating don't just overwrite the dictionary, the definitions below are more polished than the ones in the CTX. */
745 static const value_string netscaler_reset_window_error_code_vals[] = {
746 { 8196, "SSL bad record." },
747 { 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." },
748 { 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." },
749 { 8204, "Client retransmitted SYN with the wrong sequence number." },
750 { 8205, "ACK number in the final ACK from peer during connection establishment is wrong." },
751 { 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." },
752 { 8207, "Received SYN on established connection which is within the window. Protects from spoofing attacks." },
753 { 8208, "Resets the connection when you receive more than the configured value of duplicate retransmissions." },
754 { 8209, "Could not allocate memory for the packet, system out of memory." },
755 { 8210, "HTTP DoS protection feature error, bad client request." },
756 { 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)." },
757 { 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." },
758 { 8213, "Sure Connect feature, bad client sending post on connection which is closing." },
759 { 8214, "MSS sent in SYN exceeded the MSS corresponding to NIC MTU and/or VLAN MTU." },
760 { 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." },
761 { 9201, "HTTP connection multiplexing error. Server sent response packets belonging to previous transaction." },
762 { 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." },
763 { 9203, "NSDBG_RST_CLT_CHK_MIX: This code refers to the server sending a FIN for a previous client over a reused connection." },
764 { 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." },
765 { 9206, "HTTP tracking failed due to invalid HTTP request/response header." },
766 { 9207, "Invalid header reassembly parsing." },
767 { 9208, "Incomplete response processing error, see incompHdrDelay setting httpprofiles." },
768 { 9209, "Chunk tracking failed." },
769 { 9210, "Corrupt packets." },
770 { 9212, "HTTP Invalid request." },
771 { 9214, "Cache res store failed." },
772 { 9216, "Cache async no memory." },
773 { 9217, "HTTP state machine error because of more than content length body." },
774 { 9218, "Terminated due to extra orphan data." },
775 { 9219, "NSB allocation failure." },
776 { 9220, "Cannot allocate new NSB and so many other reasons." },
777 { 9221, "vurl comes with a domain shard that’s no longer valid." },
778 { 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." },
779 { 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)." },
780 { 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)." },
781 { 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)." },
782 { 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)." },
783 { 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." },
784 { 9305, "Server sent back ACK to our SYN (ACK number did not match)." },
785 { 9306, "TCP buffering is undone due to duplicate TPCB enablement." },
786 { 9307, "Small window protection feature resetting the connection." },
787 { 9308, "Small window protection feature resetting the connection." },
788 { 9309, "Small window protection feature resetting the connection." },
789 { 9310, "TCP KA probing failed." },
790 { 9311, "DHT retry failed." },
791 { 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." },
792 { 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." },
793 { 9450, "SQL HS failed." },
794 { 9451, "SQL response failed." },
795 { 9452, "SQL request list failed." },
796 { 9453, "SQL UNK not linked." },
797 { 9454, "SQL NSB hold failed." },
798 { 9455, "SQL Server First Packet." },
799 { 9456, "SQL Login response before request." },
800 { 9457, "SQL server login failed." },
801 { 9458, "SQL no memory." },
802 { 9459, "SQL bad server." },
803 { 9460, "SQL link failed." },
804 { 9600, "Reset when Number of packets with Sequence ACK mismatch > nscfg_max_orphan_pkts." },
805 { 9601, "Reset when Number of data packets with Sequence ACK mismatch > nscfg_max_orphan_pkts." },
806 { 9602, "When SSL VPN CS probe limit exceeded." },
807 { 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." },
808 { 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." },
809 { 9702, "The data received after FIN is received." },
810 { 9704, "Reset when NSB dropped due to hold limit or error in transaction etc." },
811 { 9800, "NSDBG_RST_PROBE: This connections used for monitoring the service are reset due to timeout." },
812 { 9810, "When responses match the configured NAI status code." },
813 { 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." },
814 { 9812, "Connection flushing because existing IP address is removed from the configuration." },
815 { 9813, "Closing the SSF connection." },
816 { 9814, "NSDBG_RST_PETRIGGER: This reset code is used when a request or response matches a Policy Engine policy, whose action is RESET." },
817 { 9816, "Bad SSL record." },
818 { 9817, "SSL connection received at the time of bound certificate changing (configuration change)." },
819 { 9818, "Bad SSL header value." },
820 { 9819, "Reset on failing to allocate memory for SPCB." },
821 { 9820, "SSL card operation failed." },
822 { 9821, "SSL feature disabled, reset the connection." },
823 { 9822, "SSL cipher changed, flush the connection created for old cipher." },
824 { 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." },
825 { 9824, "Reset on AAA orphan connections." },
826 { 9825, "DBG_WRONG_GSLBRECDLEN: This code is a GSLB MEP error reset code, typically between mixed versions." },
827 { 9826, "Not enough memory for NET buffers." },
828 { 9827, "Reset on SSL config change." },
829 { 9829, "Reset on GSLB other site down or out of reach." },
830 { 9830, "Reset on sessions matching ACL DENY rule." },
831 { 9831, "Use it if no application data exist, but required." },
832 { 9832, "Application error." },
833 { 9833, "Fatal SSL error." },
834 { 9834, "Reset while flushing all SPCB, during FIPS or HSM init." },
835 { 9835, "DTLS record too large." },
836 { 9836, "DTLS record zero length." },
837 { 9837, "SSLV2 record too large." },
838 { 9838, "NSBE_DBG_RST_SSL_BAD_RECORD: This code refers to error looking up SSL record when handling a request or a response." },
839 { 9839, "SSL MAX NSB hold limit reached." },
840 { 9841, "SSL/DTLS split packet failure." },
841 { 9842, "SSL NSB allocation failure." },
842 { 9843, "Monitor wide IP probe." },
843 { 9844, "SSL reneg max NSB limit reached or alloc failure." },
844 { 9845, "Reset on Appsec policy." },
845 { 9846, "Delta compression aborted or failed." },
846 { 9847, "Delta compression aborted or failed." },
847 { 9848, "Reset on connection accepted during configuration change(SSL)." },
848 { 9849, "Reset on GSLB conflict due to misconfiguration." },
849 { 9850, "DNS TCP connection untrackable due to failure of compact NSB, etc." },
850 { 9851, "DNS TCP failure (invalid payload, length, etc)." },
851 { 9852, "RTSP (ALG) session handling error." },
852 { 9853, "MSSQL Auth response error." },
853 { 9854, "Indirect GSLB sites tried to establish connection" },
854 { 9855, "For HTTP/SSL vservers, SO (Surge Queue Overflow.) threshold has reached." },
855 { 9856, "Reset on Appfw ASYNC failure." },
856 { 9857, "Reset on Flushing HTTP waiting PCB." },
857 { 9858, "Reset on Rechunk abort." },
858 { 9859, "A new client connection request was made deferrable by server on the label." },
859 { 9860, "The pcb->link of this connection was cleaned for some reason, so resetting this PCB." },
860 { 9861, "Connection on a push vserver, when push disabled on client vserver." },
861 { 9862, "Reset to Client as it resulted in duplicate server connection." },
862 { 9863, "Reset to old connection when new connection is established and old one is still not freed." },
863 { 9864, "CVPN HINFO restore failed." },
864 { 9865, "CVPN MCMX error." },
865 { 9866, "URL policy transform error." },
866 { 9868, "MSSQL login errors." },
867 { 9870, "SQL login parse error." },
868 { 9871, "MSSQL memory allocation failure." },
869 { 9872, "Websocket upgrade request dropped due to websocket disabled in http profile." },
870 { 9873, "Agsvc MCMX failure." },
871 { 9874, "NSB hold limit reached." },
872 { 9875, "Client connection is closed, send RST to server." },
873 { 9876, "One to many link failed." },
874 { 9877, "Reset for CEA on client PCB." },
875 { 9878, "CEA untrackable, send RST to Client." },
876 { 9879, "Parsing failed." },
877 { 9880, "Memory alloc failure." },
878 { 9881, "Reset on Diameter message without CE." },
879 { 9882, "Reset to Client if no pending requests." },
880 { 9883, "Link PCB fail reset to client on CEA." },
881 { 9884, "Reset to Server PCB." },
882 { 9885, "SIP Content header is missing. | Diameter reset on bad ACK." },
883 { 9886, "Reset on VPN ng binding miss." },
884 { 9887, "Reset on failed to send a request to broker (VPN)." },
885 { 9888, "Reset to AAA client if Cluster sync in progress." },
886 { 9889, "Reset on missing dynamic processing context (LUA)." },
887 { 9890, "Rewrite feature disabled when blocked on response side." },
888 { 9900, "PI reset." },
889 { 9901, "Cache buffer large data error." },
890 { 9902, "HTML injection connection abort." },
891 { 9903, "GSLB feature is disabled. Do not accept any connections and close any existing ones." },
892 { 9904, "Reset on AAA error." },
893 { 9905, "Database not responding." },
894 { 9906, "Local GSLB sites have been removed, send RST." },
895 { 9911, "HTTP incomplete due to no available memory." },
896 { 9912, "HTTP link incomplete due to no available memory." },
897 { 9913, "Send RST for SPDY errors." },
898 { 9914, "Cache Response error/AAA." },
899 { 9915, "Speedy split packet at header failed." },
900 { 9951, "SSL incomplete record." },
901 { 9952, "Reset on SSL FATAL ALERT RCVD." },
902 { 9953, "Reset on triggering of timeout action." },
903 { 9956, "QOS incomplete POST handling error." },
904 { 9957, "AppQoS Persistent service is down." },
905 { 9958, "Not used+C187:C199." },
906 { 9959, "Not used." },
907 { 9960, "MPTCP options error." },
908 { 9961, "MP join SYN reset." },
909 { 9962, "MP join FINAL ACK reset." },
910 { 9963, "MPTCP checksum failure." },
911 { 9964, "Invalid Client or NS key." },
912 { 9965, "MPTCP, established SF replaced." },
913 { 9966, "MPTCP RSSF filter failure." },
914 { 9967, "MPTCP plain ACK fallback failure." },
915 { 9968, "MPTCP fast close received." },
916 { 9969, "MPTCP, if NS in fallback mode, DSS should only for infinite map." },
917 { 9970, "BW Connection Close." },
918 { 9971, "MPTCP invalid/bad MAP." },
919 { 9972, "MPTCP reset if multiple SFs are present." },
920 { 9973, "Reset on rest of SF after fallback to infinite map as only one SF should be present." },
921 { 9974, "RST terminated at TCP layer." },
922 { 9975, "PCB waitQ insertion failed." },
923 { 9976, "MPTCP MAX retries on KA probes has reached." },
924 { 9977, "MPTCP token collision is found." },
925 { 9978, "MPTCP SYN retries reached MAXretries." },
926 { 9979, "MPTCP subflow FIN received or any other signals received on pre est SF." },
927 { 9980, "Reset on MPTCP close." },
928 { 9981, "Closing auditlog connection." },
929 { 9982, "invalid syn/ack/seq is received for NS's SYN+TFOC+DATA." },
930 { 9983, "MPTCP invalid payload size." },
931 { 10000, "ICA parse error." },
932 { 10001, "ICA link parse error." },
933 { 10002, "ICA no available memory." },
934 { 10003, "ICA link no available memory." },
935 { 10004, "Kill an ICA connection." },
936 { 10005, "MPTCP SYN retries reached MAXretries." },
937 { 10006, "Kill an RDP connection." },
938 { 10016, "SMPP no memory available." },
939 { 10017, "SMPP reset if no pending requests." },
940 { 10018, "SMPP unknown error." },
941 { 10019, "SMPP: Bind to client failed." },
942 { 10020, "SMPP: NSB hold limit reached." },
943 { 10022, "SMPP: Bind response on client." },
944 { 10023, "SMPP: Parsing failed." },
945 { 10024, "SMPP: link failed." },
946 { 10026, "SMPP: MSG without bind or not request message after bind." },
947 { 10027, "SSL: HSM operation failed." },
948 { 10028, "SSL: HSM error client." },
949 { 10029, "SSL: Hit the ratelimit." },
950 { 10030, "Connection breached maximum packet credits configured." },
951 { 10032, "SIPALG: Header parsing failed." },
952 { 10033, "SIPALG: Body parsing failed." },
953 { 10034, "SIPALG: SIP header failure." },
954 { 10035, "SIPALG: SDP header failure." },
955 { 10036, "SIPALG: Remaining IP replacement failure." },
956 { 10037, "SIPALG: Length replacement failure." },
957 { 10038, "SIPALG: BA insertion failed." },
958 { 10039, "SIPALG: DHT failure." },
959 { 10040, "SIPALG: Post translation ops failed." },
960 { 10042, "SIPALG: Pre translation ops failed." },
961 { 0, NULL },
964 static dissector_table_t subdissector_table;
965 static dissector_table_t tcp_option_table;
966 static heur_dissector_list_t heur_subdissector_list;
967 static dissector_handle_t data_handle;
968 static dissector_handle_t tcp_handle;
969 static dissector_handle_t sport_handle;
970 static dissector_handle_t tcp_opt_unknown_handle;
971 static capture_dissector_handle_t tcp_cap_handle;
973 static uint32_t tcp_stream_count;
974 static uint32_t mptcp_stream_count;
979 * Maps an MPTCP token to a mptcp_analysis structure
980 * Collisions are not handled
982 static wmem_tree_t *mptcp_tokens;
984 static int * const tcp_option_mptcp_capable_v0_flags[] = {
985 &hf_tcp_option_mptcp_checksum_flag,
986 &hf_tcp_option_mptcp_B_flag,
987 &hf_tcp_option_mptcp_H_v0_flag,
988 &hf_tcp_option_mptcp_reserved_v0_flag,
989 NULL
992 static int * const tcp_option_mptcp_capable_v1_flags[] = {
993 &hf_tcp_option_mptcp_checksum_flag,
994 &hf_tcp_option_mptcp_B_flag,
995 &hf_tcp_option_mptcp_C_flag,
996 &hf_tcp_option_mptcp_H_v1_flag,
997 &hf_tcp_option_mptcp_reserved_v1_flag,
998 NULL
1001 static int * const tcp_option_mptcp_join_flags[] = {
1002 &hf_tcp_option_mptcp_backup_flag,
1003 NULL
1006 static int * const tcp_option_mptcp_dss_flags[] = {
1007 &hf_tcp_option_mptcp_F_flag,
1008 &hf_tcp_option_mptcp_m_flag,
1009 &hf_tcp_option_mptcp_M_flag,
1010 &hf_tcp_option_mptcp_a_flag,
1011 &hf_tcp_option_mptcp_A_flag,
1012 NULL
1015 static int * const tcp_option_mptcp_tcprst_flags[] = {
1016 &hf_tcp_option_mptcp_U_flag,
1017 &hf_tcp_option_mptcp_V_flag,
1018 &hf_tcp_option_mptcp_W_flag,
1019 &hf_tcp_option_mptcp_T_flag,
1020 NULL
1023 static const unit_name_string units_64bit_version = { " (64bits version)", NULL };
1025 static uint8_t
1026 tcp_get_ace(const struct tcpheader *tcph)
1028 uint8_t ace;
1030 ace = 0;
1031 if (tcph->th_flags & TH_AE) {
1032 ace += 4;
1034 if (tcph->th_flags & TH_CWR) {
1035 ace += 2;
1037 if (tcph->th_flags & TH_ECE) {
1038 ace += 1;
1040 return ace;
1043 static char *
1044 tcp_flags_to_str(wmem_allocator_t *scope, const struct tcpheader *tcph)
1046 static const char flags[][4] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECE", "CWR", "AE" };
1047 static const char digit[][2] = { "0", "1", "2", "3", "4", "5", "6", "7" };
1048 const int maxlength = 64; /* upper bounds, max 53B: 8 * 3 + 2 + strlen("Reserved") + 9 * 2 + 1 */
1050 char *pbuf;
1051 char *buf;
1052 uint8_t ace;
1053 int i;
1055 buf = pbuf = (char *) wmem_alloc(scope, maxlength);
1056 *pbuf = '\0';
1058 for (i = 0; i < (tcph->th_use_ace ? 6 : 9); i++) {
1059 if (tcph->th_flags & (1 << i)) {
1060 if (buf[0])
1061 pbuf = g_stpcpy(pbuf, ", ");
1062 pbuf = g_stpcpy(pbuf, flags[i]);
1065 if (tcph->th_use_ace) {
1066 ace = tcp_get_ace(tcph);
1067 pbuf = g_stpcpy(pbuf, ", ACE=");
1068 pbuf = g_stpcpy(pbuf, digit[ace]);
1071 if (tcph->th_flags & TH_RES) {
1072 if (buf[0])
1073 pbuf = g_stpcpy(pbuf, ", ");
1074 g_stpcpy(pbuf, "Reserved");
1077 if (buf[0] == '\0')
1078 g_stpcpy(pbuf, "<None>");
1080 return buf;
1083 static char *
1084 tcp_flags_to_str_first_letter(wmem_allocator_t *scope, const struct tcpheader *tcph)
1086 wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");
1087 unsigned i;
1088 const unsigned flags_count = 12;
1089 static const char first_letters[] = "RRRACEUAPRSF";
1090 static const char digits[] = "01234567";
1092 /* upper three bytes are marked as reserved ('R'). */
1093 for (i = 0; i < flags_count; i++) {
1094 if (tcph->th_use_ace && 3 <= i && i <= 5) {
1095 if (i == 4) {
1096 wmem_strbuf_append_c(buf, digits[tcp_get_ace(tcph)]);
1097 } else {
1098 wmem_strbuf_append_c(buf, '-');
1100 } else {
1101 if (((tcph->th_flags >> (flags_count - 1 - i)) & 1)) {
1102 wmem_strbuf_append_c(buf, first_letters[i]);
1103 } else {
1104 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1109 return wmem_strbuf_finalize(buf);
1113 * Print the first letter of each flag set, or the dot character otherwise
1115 static char *
1116 completeness_flags_to_str_first_letter(wmem_allocator_t *scope, uint8_t flags)
1118 wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");
1120 if( flags & TCP_COMPLETENESS_RST )
1121 wmem_strbuf_append(buf, "R");
1122 else
1123 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1125 if( flags & TCP_COMPLETENESS_FIN )
1126 wmem_strbuf_append(buf, "F");
1127 else
1128 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1130 if( flags & TCP_COMPLETENESS_DATA )
1131 wmem_strbuf_append(buf, "D");
1132 else
1133 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1135 if( flags & TCP_COMPLETENESS_ACK )
1136 wmem_strbuf_append(buf, "A");
1137 else
1138 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1140 if( flags & TCP_COMPLETENESS_SYNACK )
1141 wmem_strbuf_append(buf, "S");
1142 else
1143 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1145 if( flags & TCP_COMPLETENESS_SYNSENT )
1146 wmem_strbuf_append(buf, "S");
1147 else
1148 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1150 return wmem_strbuf_finalize(buf);
1153 static void
1154 tcp_src_prompt(packet_info *pinfo, char *result)
1156 uint32_t port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num));
1158 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "source (%u%s)", port, UTF8_RIGHTWARDS_ARROW);
1161 static void *
1162 tcp_src_value(packet_info *pinfo)
1164 return p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num);
1167 static void
1168 tcp_dst_prompt(packet_info *pinfo, char *result)
1170 uint32_t port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num));
1172 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW, port);
1175 static void *
1176 tcp_dst_value(packet_info *pinfo)
1178 return p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num);
1181 static void
1182 tcp_both_prompt(packet_info *pinfo, char *result)
1184 uint32_t srcport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num)),
1185 destport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num));
1186 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "both (%u%s%u)", srcport, UTF8_LEFT_RIGHT_ARROW, destport);
1189 static const char* tcp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
1192 if (filter == CONV_FT_SRC_PORT)
1193 return "tcp.srcport";
1195 if (filter == CONV_FT_DST_PORT)
1196 return "tcp.dstport";
1198 if (filter == CONV_FT_ANY_PORT)
1199 return "tcp.port";
1201 if(!conv) {
1202 return CONV_FILTER_INVALID;
1205 if (filter == CONV_FT_SRC_ADDRESS) {
1206 if (conv->src_address.type == AT_IPv4)
1207 return "ip.src";
1208 if (conv->src_address.type == AT_IPv6)
1209 return "ipv6.src";
1212 if (filter == CONV_FT_DST_ADDRESS) {
1213 if (conv->dst_address.type == AT_IPv4)
1214 return "ip.dst";
1215 if (conv->dst_address.type == AT_IPv6)
1216 return "ipv6.dst";
1219 if (filter == CONV_FT_ANY_ADDRESS) {
1220 if (conv->src_address.type == AT_IPv4)
1221 return "ip.addr";
1222 if (conv->src_address.type == AT_IPv6)
1223 return "ipv6.addr";
1226 return CONV_FILTER_INVALID;
1229 static ct_dissector_info_t tcp_ct_dissector_info = {&tcp_conv_get_filter_type};
1232 * callback function for conversation stats
1234 static int tcp_conv_cb_update(conversation_t *conv)
1236 struct tcp_analysis *tcpd;
1237 tcpd=get_tcp_conversation_data_idempotent(conv);
1238 if(tcpd)
1239 return tcpd->flow1.flow_count + tcpd->flow2.flow_count;
1240 else
1241 return 0;
1244 static tap_packet_status
1245 tcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
1247 conv_hash_t *hash = (conv_hash_t*) pct;
1248 hash->flags = flags;
1250 const struct tcpheader *tcphdr=(const struct tcpheader *)vip;
1252 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,
1253 &pinfo->rel_ts, &pinfo->abs_ts, &tcp_ct_dissector_info, CONVERSATION_TCP, (uint32_t)pinfo->num, tcp_conv_cb_update);
1256 return TAP_PACKET_REDRAW;
1259 static tap_packet_status
1260 mptcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
1262 conv_hash_t *hash = (conv_hash_t*) pct;
1263 hash->flags = flags;
1265 const struct tcp_analysis *tcpd=(const struct tcp_analysis *)vip;
1266 const mptcp_meta_flow_t *meta=(const mptcp_meta_flow_t *)tcpd->fwd->mptcp_subflow->meta;
1268 add_conversation_table_data_with_conv_id(hash, &meta->ip_src, &meta->ip_dst,
1269 meta->sport, meta->dport, (conv_id_t) tcpd->mptcp_analysis->stream, 1, pinfo->fd->pkt_len,
1270 &pinfo->rel_ts, &pinfo->abs_ts, &tcp_ct_dissector_info, CONVERSATION_TCP);
1272 return TAP_PACKET_REDRAW;
1275 static const char* tcp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter)
1277 if (filter == CONV_FT_SRC_PORT)
1278 return "tcp.srcport";
1280 if (filter == CONV_FT_DST_PORT)
1281 return "tcp.dstport";
1283 if (filter == CONV_FT_ANY_PORT)
1284 return "tcp.port";
1286 if(!endpoint) {
1287 return CONV_FILTER_INVALID;
1290 if (filter == CONV_FT_SRC_ADDRESS) {
1291 if (endpoint->myaddress.type == AT_IPv4)
1292 return "ip.src";
1293 if (endpoint->myaddress.type == AT_IPv6)
1294 return "ipv6.src";
1297 if (filter == CONV_FT_DST_ADDRESS) {
1298 if (endpoint->myaddress.type == AT_IPv4)
1299 return "ip.dst";
1300 if (endpoint->myaddress.type == AT_IPv6)
1301 return "ipv6.dst";
1304 if (filter == CONV_FT_ANY_ADDRESS) {
1305 if (endpoint->myaddress.type == AT_IPv4)
1306 return "ip.addr";
1307 if (endpoint->myaddress.type == AT_IPv6)
1308 return "ipv6.addr";
1311 return CONV_FILTER_INVALID;
1314 static et_dissector_info_t tcp_endpoint_dissector_info = {&tcp_endpoint_get_filter_type};
1316 static tap_packet_status
1317 tcpip_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
1319 conv_hash_t *hash = (conv_hash_t*) pit;
1320 hash->flags = flags;
1322 const struct tcpheader *tcphdr=(const struct tcpheader *)vip;
1324 /* Take two "add" passes per packet, adding for each direction, ensures that all
1325 packets are counted properly (even if address is sending to itself)
1326 XXX - this could probably be done more efficiently inside endpoint_table */
1327 add_endpoint_table_data(hash, &tcphdr->ip_src, tcphdr->th_sport, true, 1, pinfo->fd->pkt_len, &tcp_endpoint_dissector_info, ENDPOINT_TCP);
1328 add_endpoint_table_data(hash, &tcphdr->ip_dst, tcphdr->th_dport, false, 1, pinfo->fd->pkt_len, &tcp_endpoint_dissector_info, ENDPOINT_TCP);
1330 return TAP_PACKET_REDRAW;
1333 static bool
1334 tcp_filter_valid(packet_info *pinfo, void *user_data _U_)
1336 return proto_is_frame_protocol(pinfo->layers, "tcp");
1339 static char*
1340 tcp_build_filter_by_id(packet_info *pinfo, void *user_data _U_)
1342 return ws_strdup_printf("tcp.stream eq %d", pinfo->stream_id);
1346 /****************************************************************************/
1347 /* whenever a TCP packet is seen by the tap listener */
1348 /* Add a new tcp frame into the graph */
1349 static tap_packet_status
1350 tcp_seq_analysis_packet( void *ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *tcp_info, tap_flags_t tapflags _U_)
1352 seq_analysis_info_t *sainfo = (seq_analysis_info_t *) ptr;
1353 const struct tcpheader *tcph = (const struct tcpheader *)tcp_info;
1354 char* flags;
1355 seq_analysis_item_t *sai = sequence_analysis_create_sai_with_addresses(pinfo, sainfo);
1357 if (!sai)
1358 return TAP_PACKET_DONT_REDRAW;
1360 sai->frame_number = pinfo->num;
1362 sai->port_src=pinfo->srcport;
1363 sai->port_dst=pinfo->destport;
1365 flags = tcp_flags_to_str(NULL, tcph);
1367 if ((tcph->th_have_seglen)&&(tcph->th_seglen!=0)){
1368 sai->frame_label = ws_strdup_printf("%s - Len: %u",flags, tcph->th_seglen);
1370 else{
1371 sai->frame_label = g_strdup(flags);
1374 wmem_free(NULL, flags);
1376 if (tcph->th_flags & TH_ACK)
1377 sai->comment = ws_strdup_printf("Seq = %u Ack = %u",tcph->th_seq, tcph->th_ack);
1378 else
1379 sai->comment = ws_strdup_printf("Seq = %u",tcph->th_seq);
1381 sai->line_style = 1;
1382 sai->conv_num = (uint16_t) tcph->th_stream;
1383 sai->display = true;
1385 g_queue_push_tail(sainfo->items, sai);
1387 return TAP_PACKET_REDRAW;
1391 char *tcp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream _U_)
1393 conversation_t *conv;
1394 struct tcp_analysis *tcpd;
1396 /* XXX: Since TCP doesn't use the endpoint API, we can only look
1397 * up using the current pinfo addresses and ports. We don't want
1398 * to create a new conversation or new TCP stream.
1399 * Eventually the endpoint API should support storing multiple
1400 * endpoints and TCP should be changed to use the endpoint API.
1402 conv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
1403 if (((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) ||
1404 (pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6))
1405 && (pinfo->ptype == PT_TCP) &&
1406 conv != NULL)
1408 /* TCP over IPv4/6 */
1409 tcpd=get_tcp_conversation_data(conv, pinfo);
1410 if (tcpd == NULL)
1411 return NULL;
1413 *stream = tcpd->stream;
1414 return ws_strdup_printf("tcp.stream eq %u", tcpd->stream);
1417 return NULL;
1420 char *tcp_follow_index_filter(unsigned stream, unsigned sub_stream _U_)
1422 return ws_strdup_printf("tcp.stream eq %u", stream);
1425 char *tcp_follow_address_filter(address *src_addr, address *dst_addr, int src_port, int dst_port)
1427 const char *ip_version = src_addr->type == AT_IPv6 ? "v6" : "";
1428 char src_addr_str[WS_INET6_ADDRSTRLEN];
1429 char dst_addr_str[WS_INET6_ADDRSTRLEN];
1431 address_to_str_buf(src_addr, src_addr_str, sizeof(src_addr_str));
1432 address_to_str_buf(dst_addr, dst_addr_str, sizeof(dst_addr_str));
1434 return ws_strdup_printf("((ip%s.src eq %s and tcp.srcport eq %d) and "
1435 "(ip%s.dst eq %s and tcp.dstport eq %d))"
1436 " or "
1437 "((ip%s.src eq %s and tcp.srcport eq %d) and "
1438 "(ip%s.dst eq %s and tcp.dstport eq %d))",
1439 ip_version, src_addr_str, src_port,
1440 ip_version, dst_addr_str, dst_port,
1441 ip_version, dst_addr_str, dst_port,
1442 ip_version, src_addr_str, src_port);
1446 typedef struct tcp_follow_tap_data
1448 tvbuff_t *tvb;
1449 struct tcpheader* tcph;
1450 struct tcp_analysis *tcpd;
1452 } tcp_follow_tap_data_t;
1455 * Tries to apply segments from fragments list to the reconstructed payload.
1456 * Fragments that can be appended to the end of the payload will be applied (and
1457 * removed from the list). Fragments that should have been received (according
1458 * to the ack number) will also be appended to the payload (preceded by some
1459 * dummy data to mark packet loss if any).
1461 * Returns true if one fragment has been applied or false if no more fragments
1462 * can be added to the payload (there might still be unacked fragments with
1463 * missing segments before them).
1465 static bool
1466 check_follow_fragments(follow_info_t *follow_info, bool is_server, uint32_t acknowledged, uint32_t packet_num, bool use_ack)
1468 GList *fragment_entry;
1469 follow_record_t *fragment, *follow_record;
1470 uint32_t lowest_seq = 0;
1471 char *dummy_str;
1473 fragment_entry = g_list_first(follow_info->fragments[is_server]);
1474 if (fragment_entry == NULL)
1475 return false;
1477 fragment = (follow_record_t*)fragment_entry->data;
1478 lowest_seq = fragment->seq;
1480 for (; fragment_entry != NULL; fragment_entry = g_list_next(fragment_entry))
1482 fragment = (follow_record_t*)fragment_entry->data;
1484 if( GT_SEQ(lowest_seq, fragment->seq) ) {
1485 lowest_seq = fragment->seq;
1488 if( LT_SEQ(fragment->seq, follow_info->seq[is_server]) ) {
1489 uint32_t newseq;
1490 /* this sequence number seems dated, but
1491 check the end to make sure it has no more
1492 info than we have already seen */
1493 newseq = fragment->seq + fragment->data->len;
1494 if( GT_SEQ(newseq, follow_info->seq[is_server]) ) {
1495 uint32_t new_pos;
1497 /* this one has more than we have seen. let's get the
1498 payload that we have not seen. This happens when
1499 part of this frame has been retransmitted */
1501 new_pos = follow_info->seq[is_server] - fragment->seq;
1503 if ( fragment->data->len > new_pos ) {
1504 uint32_t new_frag_size = fragment->data->len - new_pos;
1506 follow_record = g_new0(follow_record_t,1);
1508 follow_record->is_server = is_server;
1509 follow_record->packet_num = fragment->packet_num;
1510 follow_record->abs_ts = fragment->abs_ts;
1511 follow_record->seq = follow_info->seq[is_server] + new_frag_size;
1513 follow_record->data = g_byte_array_append(g_byte_array_new(),
1514 fragment->data->data + new_pos,
1515 new_frag_size);
1517 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
1520 follow_info->seq[is_server] += (fragment->data->len - new_pos);
1523 /* Remove the fragment from the list as the "new" part of it
1524 * has been processed or its data has been seen already in
1525 * another packet. */
1526 g_byte_array_free(fragment->data, true);
1527 g_free(fragment);
1528 follow_info->fragments[is_server] = g_list_delete_link(follow_info->fragments[is_server], fragment_entry);
1529 return true;
1532 if( EQ_SEQ(fragment->seq, follow_info->seq[is_server]) ) {
1533 /* this fragment fits the stream */
1534 if( fragment->data->len > 0 ) {
1535 follow_info->payload = g_list_prepend(follow_info->payload, fragment);
1538 follow_info->seq[is_server] += fragment->data->len;
1539 follow_info->fragments[is_server] = g_list_delete_link(follow_info->fragments[is_server], fragment_entry);
1540 return true;
1544 if( use_ack && GT_SEQ(acknowledged, lowest_seq) ) {
1545 /* There are frames missing in the capture file that were seen
1546 * by the receiving host. Add dummy stream chunk with the data
1547 * "[xxx bytes missing in capture file]".
1549 dummy_str = ws_strdup_printf("[%d bytes missing in capture file]",
1550 (int)(lowest_seq - follow_info->seq[is_server]) );
1551 // XXX the dummy replacement could be larger than the actual missing bytes.
1553 follow_record = g_new0(follow_record_t,1);
1555 follow_record->data = g_byte_array_append(g_byte_array_new(),
1556 (unsigned char*)dummy_str,
1557 (unsigned)strlen(dummy_str)+1);
1558 g_free(dummy_str);
1559 follow_record->is_server = is_server;
1560 follow_record->packet_num = packet_num;
1561 follow_record->seq = lowest_seq;
1563 follow_info->seq[is_server] = lowest_seq;
1564 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
1565 return true;
1568 return false;
1571 static tap_packet_status
1572 follow_tcp_tap_listener(void *tapdata, packet_info *pinfo,
1573 epan_dissect_t *edt _U_, const void *data, tap_flags_t flags _U_)
1575 follow_record_t *follow_record;
1576 follow_info_t *follow_info = (follow_info_t *)tapdata;
1577 const tcp_follow_tap_data_t *follow_data = (const tcp_follow_tap_data_t *)data;
1578 bool is_server;
1579 uint32_t sequence = follow_data->tcph->th_seq;
1580 uint32_t length = follow_data->tcph->th_have_seglen
1581 ? follow_data->tcph->th_seglen
1582 : 0;
1583 uint32_t data_offset = 0;
1584 uint32_t data_length = tvb_captured_length(follow_data->tvb);
1586 if (follow_data->tcph->th_flags & TH_SYN) {
1587 sequence++;
1590 if (follow_info->client_port == 0) {
1591 follow_info->client_port = pinfo->srcport;
1592 copy_address(&follow_info->client_ip, &pinfo->src);
1593 follow_info->server_port = pinfo->destport;
1594 copy_address(&follow_info->server_ip, &pinfo->dst);
1597 is_server = !(addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport);
1599 /* Check whether this frame ACKs fragments in flow from the other direction.
1600 * This happens when frames are not in the capture file, but were actually
1601 * seen by the receiving host (Fixes bug 592).
1603 if (follow_info->fragments[!is_server] != NULL) {
1604 while (check_follow_fragments(follow_info, !is_server, follow_data->tcph->th_ack, pinfo->fd->num, true));
1608 * If this is the first segment of this stream, initialize the next expected
1609 * sequence number. If there is any data, it will be added below.
1611 if (follow_info->bytes_written[is_server] == 0 && follow_info->seq[is_server] == 0) {
1612 follow_info->seq[is_server] = sequence;
1615 /* We have already seen this src (and received some segments), let's figure
1616 * out whether this segment extends the stream or overlaps a previous gap. */
1617 if (LT_SEQ(sequence, follow_info->seq[is_server])) {
1618 /* This sequence number seems dated, but check the end in case it was a
1619 * retransmission with more data. */
1620 uint32_t nextseq = sequence + length;
1621 if (GT_SEQ(nextseq, follow_info->seq[is_server])) {
1622 /* The begin of the segment was already seen, try to add the
1623 * remaining data that we have not seen to the payload. */
1624 data_offset = follow_info->seq[is_server] - sequence;
1625 if (data_length <= data_offset) {
1626 data_length = 0;
1627 } else {
1628 data_length -= data_offset;
1631 sequence = follow_info->seq[is_server];
1632 length = nextseq - follow_info->seq[is_server];
1636 * Ignore segments that have no new data (either because it was empty, or
1637 * because it was fully overlapping with previously received data).
1639 if (data_length == 0 || LT_SEQ(sequence, follow_info->seq[is_server])) {
1640 return TAP_PACKET_DONT_REDRAW;
1643 follow_record = g_new0(follow_record_t, 1);
1644 follow_record->is_server = is_server;
1645 follow_record->packet_num = pinfo->fd->num;
1646 follow_record->abs_ts = pinfo->fd->abs_ts;
1647 follow_record->seq = sequence; /* start of fragment, used by check_follow_fragments. */
1648 follow_record->data = g_byte_array_append(g_byte_array_new(),
1649 tvb_get_ptr(follow_data->tvb, data_offset, data_length),
1650 data_length);
1652 if (EQ_SEQ(sequence, follow_info->seq[is_server])) {
1653 /* The segment overlaps or extends the previous end of stream. */
1654 follow_info->seq[is_server] += length;
1655 follow_info->bytes_written[is_server] += follow_record->data->len;
1656 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
1658 /* done with the packet, see if it caused a fragment to fit */
1659 while(check_follow_fragments(follow_info, is_server, 0, pinfo->fd->num, false));
1660 } else {
1661 /* Out of order packet (more preceding segments are expected). */
1662 follow_info->fragments[is_server] = g_list_append(follow_info->fragments[is_server], follow_record);
1664 return TAP_PACKET_DONT_REDRAW;
1667 #define EXP_PDU_TCP_INFO_DATA_LEN 20
1668 #define EXP_PDU_TCP_INFO_VERSION 1
1669 #define EXP_PDU_TAG_TCP_STREAM_ID_LEN 4
1671 static int exp_pdu_tcp_dissector_data_size(packet_info *pinfo _U_, void* data _U_)
1673 return EXP_PDU_TCP_INFO_DATA_LEN+4;
1676 static int exp_pdu_tcp_dissector_data_populate_data(packet_info *pinfo _U_, void* data, uint8_t *tlv_buffer, uint32_t buffer_size _U_)
1678 struct tcpinfo* dissector_data = (struct tcpinfo*)data;
1680 phton16(&tlv_buffer[0], EXP_PDU_TAG_TCP_INFO_DATA);
1681 phton16(&tlv_buffer[2], EXP_PDU_TCP_INFO_DATA_LEN); /* tag length */
1682 phton16(&tlv_buffer[4], EXP_PDU_TCP_INFO_VERSION);
1683 phton32(&tlv_buffer[6], dissector_data->seq);
1684 phton32(&tlv_buffer[10], dissector_data->nxtseq);
1685 phton32(&tlv_buffer[14], dissector_data->lastackseq);
1686 tlv_buffer[18] = dissector_data->is_reassembled;
1687 phton16(&tlv_buffer[19], dissector_data->flags);
1688 phton16(&tlv_buffer[21], dissector_data->urgent_pointer);
1690 return exp_pdu_tcp_dissector_data_size(pinfo, data);
1693 static tvbuff_t*
1694 handle_export_pdu_check_desegmentation(packet_info *pinfo, tvbuff_t *tvb)
1696 /* Check to see if the tvb we're planning on exporting PDUs from was
1697 * dissected fully, or whether it requested further desegmentation.
1698 * This should only matter on the first pass (so in one-pass tshark.)
1700 if (pinfo->can_desegment > 0 && pinfo->desegment_len != 0) {
1701 /* Desegmentation was requested. How much did we desegment here?
1702 * The rest, presumably, will be handled in another frame.
1704 if (pinfo->desegment_offset == 0) {
1705 /* We couldn't, in fact, dissect any of it. */
1706 return NULL;
1708 tvb = tvb_new_subset_length(tvb, 0, pinfo->desegment_offset);
1710 return tvb;
1713 static void
1714 handle_export_pdu_dissection_table(packet_info *pinfo, tvbuff_t *tvb, uint32_t port, struct tcpinfo *tcpinfo)
1716 if (have_tap_listener(exported_pdu_tap)) {
1717 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);
1718 if (tvb == NULL) {
1719 return;
1721 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};
1722 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL};
1724 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {
1725 &exp_pdu_data_src_ip,
1726 &exp_pdu_data_dst_ip,
1727 &exp_pdu_data_port_type,
1728 &exp_pdu_data_src_port,
1729 &exp_pdu_data_dst_port,
1730 &exp_pdu_data_orig_frame_num,
1731 &exp_pdu_data_table_value,
1732 &exp_pdu_data_dissector_data,
1733 NULL
1736 exp_pdu_data_t *exp_pdu_data;
1738 exp_pdu_data_table_value.data = GUINT_TO_POINTER(port);
1739 exp_pdu_data_dissector_data.data = tcpinfo;
1741 exp_pdu_data = export_pdu_create_tags(pinfo, "tcp.port", EXP_PDU_TAG_DISSECTOR_TABLE_NAME, tcp_exp_pdu_items);
1742 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
1743 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
1744 exp_pdu_data->pdu_tvb = tvb;
1746 /* match uint is restored after calling dissector, so in order to have the right value in exported PDU
1747 * we need to set it here.
1749 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
1753 static void
1754 handle_export_pdu_heuristic(packet_info *pinfo, tvbuff_t *tvb, heur_dtbl_entry_t *hdtbl_entry, struct tcpinfo *tcpinfo)
1756 exp_pdu_data_t *exp_pdu_data = NULL;
1758 if (have_tap_listener(exported_pdu_tap)) {
1759 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);
1760 if (tvb == NULL) {
1761 return;
1763 if ((!hdtbl_entry->enabled) ||
1764 (hdtbl_entry->protocol != NULL && !proto_is_protocol_enabled(hdtbl_entry->protocol))) {
1765 exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME);
1766 } else if (hdtbl_entry->protocol != NULL) {
1767 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL};
1768 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {
1769 &exp_pdu_data_src_ip,
1770 &exp_pdu_data_dst_ip,
1771 &exp_pdu_data_port_type,
1772 &exp_pdu_data_src_port,
1773 &exp_pdu_data_dst_port,
1774 &exp_pdu_data_orig_frame_num,
1775 &exp_pdu_data_dissector_data,
1776 NULL
1779 exp_pdu_data_dissector_data.data = tcpinfo;
1781 exp_pdu_data = export_pdu_create_tags(pinfo, hdtbl_entry->short_name, EXP_PDU_TAG_HEUR_DISSECTOR_NAME, tcp_exp_pdu_items);
1784 if (exp_pdu_data != NULL) {
1785 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
1786 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
1787 exp_pdu_data->pdu_tvb = tvb;
1789 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
1794 static void
1795 handle_export_pdu_conversation(packet_info *pinfo, tvbuff_t *tvb, int src_port, int dst_port, struct tcpinfo *tcpinfo)
1797 if (have_tap_listener(exported_pdu_tap)) {
1798 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);
1799 if (tvb == NULL) {
1800 return;
1802 conversation_t *conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, src_port, dst_port, 0);
1803 if (conversation != NULL)
1805 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num);
1806 if (handle != NULL)
1808 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL};
1809 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {
1810 &exp_pdu_data_src_ip,
1811 &exp_pdu_data_dst_ip,
1812 &exp_pdu_data_port_type,
1813 &exp_pdu_data_src_port,
1814 &exp_pdu_data_dst_port,
1815 &exp_pdu_data_orig_frame_num,
1816 &exp_pdu_data_dissector_data,
1817 NULL
1820 exp_pdu_data_t *exp_pdu_data;
1822 exp_pdu_data_dissector_data.data = tcpinfo;
1824 exp_pdu_data = export_pdu_create_tags(pinfo, dissector_handle_get_dissector_name(handle), EXP_PDU_TAG_DISSECTOR_NAME, tcp_exp_pdu_items);
1825 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
1826 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
1827 exp_pdu_data->pdu_tvb = tvb;
1829 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
1836 * display the TCP Conversation Completeness
1837 * we of course pay much attention on complete conversations but also incomplete ones which
1838 * have a regular start, as in practice we are often looking for such thing
1840 static void conversation_completeness_fill(char *buf, uint32_t value)
1842 switch(value) {
1843 case TCP_COMPLETENESS_SYNSENT:
1844 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete, SYN_SENT (%u)", value);
1845 break;
1846 case (TCP_COMPLETENESS_SYNSENT|
1847 TCP_COMPLETENESS_SYNACK):
1848 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete, CLIENT_ESTABLISHED (%u)", value);
1849 break;
1850 case (TCP_COMPLETENESS_SYNSENT|
1851 TCP_COMPLETENESS_SYNACK|
1852 TCP_COMPLETENESS_ACK):
1853 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete, ESTABLISHED (%u)", value);
1854 break;
1855 case (TCP_COMPLETENESS_SYNSENT|
1856 TCP_COMPLETENESS_SYNACK|
1857 TCP_COMPLETENESS_ACK|
1858 TCP_COMPLETENESS_DATA):
1859 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete, DATA (%u)", value);
1860 break;
1861 case (TCP_COMPLETENESS_SYNSENT|
1862 TCP_COMPLETENESS_SYNACK|
1863 TCP_COMPLETENESS_ACK|
1864 TCP_COMPLETENESS_DATA|
1865 TCP_COMPLETENESS_FIN):
1866 case (TCP_COMPLETENESS_SYNSENT|
1867 TCP_COMPLETENESS_SYNACK|
1868 TCP_COMPLETENESS_ACK|
1869 TCP_COMPLETENESS_DATA|
1870 TCP_COMPLETENESS_RST):
1871 case (TCP_COMPLETENESS_SYNSENT|
1872 TCP_COMPLETENESS_SYNACK|
1873 TCP_COMPLETENESS_ACK|
1874 TCP_COMPLETENESS_DATA|
1875 TCP_COMPLETENESS_FIN|
1876 TCP_COMPLETENESS_RST):
1877 snprintf(buf, ITEM_LABEL_LENGTH, "Complete, WITH_DATA (%u)", value);
1878 break;
1879 case (TCP_COMPLETENESS_SYNSENT|
1880 TCP_COMPLETENESS_SYNACK|
1881 TCP_COMPLETENESS_ACK|
1882 TCP_COMPLETENESS_FIN):
1883 case (TCP_COMPLETENESS_SYNSENT|
1884 TCP_COMPLETENESS_SYNACK|
1885 TCP_COMPLETENESS_ACK|
1886 TCP_COMPLETENESS_RST):
1887 case (TCP_COMPLETENESS_SYNSENT|
1888 TCP_COMPLETENESS_SYNACK|
1889 TCP_COMPLETENESS_ACK|
1890 TCP_COMPLETENESS_FIN|
1891 TCP_COMPLETENESS_RST):
1892 snprintf(buf, ITEM_LABEL_LENGTH, "Complete, NO_DATA (%u)", value);
1893 break;
1894 default:
1895 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete (%u)", value);
1896 break;
1900 /* TCP structs and definitions */
1902 /* **************************************************************************
1903 * RTT, relative sequence numbers, window scaling & etc.
1904 * **************************************************************************/
1905 static bool tcp_analyze_seq = true;
1906 static bool tcp_relative_seq = true;
1907 static bool tcp_track_bytes_in_flight = true;
1908 static bool tcp_bif_seq_based;
1909 static bool tcp_calculate_ts = true;
1911 static bool tcp_analyze_mptcp = true;
1912 static bool mptcp_relative_seq = true;
1913 static bool mptcp_analyze_mappings;
1914 static bool mptcp_intersubflows_retransmission;
1917 #define TCP_A_RETRANSMISSION 0x0001
1918 #define TCP_A_LOST_PACKET 0x0002
1919 #define TCP_A_ACK_LOST_PACKET 0x0004
1920 #define TCP_A_KEEP_ALIVE 0x0008
1921 #define TCP_A_DUPLICATE_ACK 0x0010
1922 #define TCP_A_ZERO_WINDOW 0x0020
1923 #define TCP_A_ZERO_WINDOW_PROBE 0x0040
1924 #define TCP_A_ZERO_WINDOW_PROBE_ACK 0x0080
1925 #define TCP_A_KEEP_ALIVE_ACK 0x0100
1926 #define TCP_A_OUT_OF_ORDER 0x0200
1927 #define TCP_A_FAST_RETRANSMISSION 0x0400
1928 #define TCP_A_WINDOW_UPDATE 0x0800
1929 #define TCP_A_WINDOW_FULL 0x1000
1930 #define TCP_A_REUSED_PORTS 0x2000
1931 #define TCP_A_SPURIOUS_RETRANSMISSION 0x4000
1933 /* This flag for desegment_tcp to exclude segments with previously
1934 * seen sequence numbers.
1935 * It is from the perspective of Wireshark's reassembler, whereas
1936 * the other flags above are from the perspective of the sender.
1937 * (E.g., TCP_A_RETRANSMISSION or TCP_A_SPURIOUS_RETRANSMISSION
1938 * can be set even when first appearance in the capture file.)
1940 #define TCP_A_OLD_DATA 0x8000
1942 /* Static TCP flags. Set in tcp_flow_t:static_flags */
1943 #define TCP_S_BASE_SEQ_SET 0x01
1944 #define TCP_S_SAW_SYN 0x03
1945 #define TCP_S_SAW_SYNACK 0x05
1948 /* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */
1949 #define MPTCP_META_HAS_BASE_DSN_MSB 0x01
1950 #define MPTCP_META_HAS_KEY 0x03
1951 #define MPTCP_META_HAS_TOKEN 0x04
1952 #define MPTCP_META_HAS_ADDRESSES 0x08
1954 /* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */
1955 #define MPTCP_SUBFLOW_HAS_NONCE 0x01
1956 #define MPTCP_SUBFLOW_HAS_ADDRESS_ID 0x02
1958 /* MPTCP meta analysis related */
1959 #define MPTCP_META_CHECKSUM_REQUIRED 0x0002
1961 /* if we have no key for this connection, some conversion become impossible,
1962 * thus return false
1964 static
1965 bool
1966 mptcp_convert_dsn(uint64_t dsn, mptcp_meta_flow_t *meta, enum mptcp_dsn_conversion conv, bool relative, uint64_t *result ) {
1968 *result = dsn;
1970 /* if relative is set then we need the 64 bits version anyway
1971 * we assume no wrapping was done on the 32 lsb so this may be wrong for elephant flows
1973 if(conv == DSN_CONV_32_TO_64 || relative) {
1975 if(!(meta->static_flags & MPTCP_META_HAS_BASE_DSN_MSB)) {
1976 /* can't do those without the expected_idsn based on the key */
1977 return false;
1981 if(conv == DSN_CONV_32_TO_64) {
1982 *result = keep_32msb_of_uint64(meta->base_dsn) | dsn;
1985 if(relative) {
1986 *result -= meta->base_dsn;
1989 if(conv == DSN_CONV_64_TO_32) {
1990 *result = (uint32_t) *result;
1993 return true;
1997 static void
1998 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
1999 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
2000 uint32_t seq, uint32_t nxtseq, bool is_tcp_segment,
2001 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo);
2004 static struct tcp_analysis *
2005 init_tcp_conversation_data(packet_info *pinfo, int direction)
2007 struct tcp_analysis *tcpd;
2009 /* Initialize the tcp protocol data structure to add to the tcp conversation */
2010 tcpd=wmem_new0(wmem_file_scope(), struct tcp_analysis);
2011 tcpd->flow1.win_scale = (direction >= 0) ? pinfo->src_win_scale : pinfo->dst_win_scale;
2012 tcpd->flow1.window = UINT32_MAX;
2013 tcpd->flow1.multisegment_pdus=wmem_tree_new(wmem_file_scope());
2015 tcpd->flow2.window = UINT32_MAX;
2016 tcpd->flow2.win_scale = (direction >= 0) ? pinfo->dst_win_scale : pinfo->src_win_scale;
2017 tcpd->flow2.multisegment_pdus=wmem_tree_new(wmem_file_scope());
2019 if (tcp_reassemble_out_of_order) {
2020 tcpd->flow1.ooo_segments=wmem_list_new(wmem_file_scope());
2021 tcpd->flow2.ooo_segments=wmem_list_new(wmem_file_scope());
2024 /* Only allocate the data if its actually going to be analyzed */
2025 if (tcp_analyze_seq)
2027 tcpd->flow1.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t);
2028 tcpd->flow2.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t);
2030 /* Only allocate the data if its actually going to be displayed */
2031 if (tcp_display_process_info)
2033 tcpd->flow1.process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t);
2034 tcpd->flow2.process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t);
2037 tcpd->acked_table=wmem_tree_new(wmem_file_scope());
2038 tcpd->ts_first.secs=pinfo->abs_ts.secs;
2039 tcpd->ts_first.nsecs=pinfo->abs_ts.nsecs;
2040 nstime_set_zero(&tcpd->ts_mru_syn);
2041 nstime_set_zero(&tcpd->ts_first_rtt);
2042 tcpd->ts_prev.secs=pinfo->abs_ts.secs;
2043 tcpd->ts_prev.nsecs=pinfo->abs_ts.nsecs;
2044 tcpd->flow1.closing_initiator = false;
2045 tcpd->flow2.closing_initiator = false;
2046 tcpd->stream = tcp_stream_count++;
2047 tcpd->server_port = 0;
2048 tcpd->tfo_syn_data = false;
2049 tcpd->flow_direction = 0;
2050 tcpd->flow1.flow_count = 0;
2051 tcpd->flow2.flow_count = 0;
2052 tcpd->flow1.mss = -1;
2053 tcpd->flow2.mss = -1;
2055 return tcpd;
2058 /* setup meta as well */
2059 static void
2060 mptcp_init_subflow(tcp_flow_t *flow)
2062 struct mptcp_subflow *sf = wmem_new0(wmem_file_scope(), struct mptcp_subflow);
2064 DISSECTOR_ASSERT(flow->mptcp_subflow == 0);
2065 flow->mptcp_subflow = sf;
2066 sf->ssn2dsn_mappings = wmem_itree_new(wmem_file_scope());
2067 sf->dsn2packet_map = wmem_itree_new(wmem_file_scope());
2071 /* add a new subflow to an mptcp connection */
2072 static void
2073 mptcp_attach_subflow(struct mptcp_analysis* mptcpd, struct tcp_analysis* tcpd) {
2075 if(!wmem_list_find(mptcpd->subflows, tcpd)) {
2076 wmem_list_prepend(mptcpd->subflows, tcpd);
2079 /* in case we merge 2 mptcp connections */
2080 tcpd->mptcp_analysis = mptcpd;
2083 struct tcp_analysis *
2084 get_tcp_conversation_data_idempotent(conversation_t *conv)
2086 struct tcp_analysis *tcpd;
2088 /* Get the data for this conversation */
2089 tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
2091 return tcpd;
2094 struct tcp_analysis *
2095 get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)
2097 int direction;
2098 struct tcp_analysis *tcpd;
2099 bool clear_ta = true;
2101 /* Did the caller supply the conversation pointer? */
2102 if( conv==NULL ) {
2103 /* If the caller didn't supply a conversation, don't
2104 * clear the analysis, it may be needed */
2105 clear_ta = false;
2106 conv = find_or_create_conversation(pinfo);
2109 /* Get the data for this conversation */
2110 tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
2112 direction = cmp_address(&pinfo->src, &pinfo->dst);
2113 /* if the addresses are equal, match the ports instead */
2114 if (direction == 0) {
2115 direction = (pinfo->srcport > pinfo->destport) ? 1 : -1;
2117 /* If the conversation was just created or it matched a
2118 * conversation with template options, tcpd will not
2119 * have been initialized. So, initialize
2120 * a new tcpd structure for the conversation.
2122 if (!tcpd) {
2123 tcpd = init_tcp_conversation_data(pinfo, direction);
2124 conversation_add_proto_data(conv, proto_tcp, tcpd);
2127 if (!tcpd) {
2128 return NULL;
2131 /* check direction and get ua lists */
2132 if(direction>=0) {
2133 tcpd->fwd=&(tcpd->flow1);
2134 tcpd->rev=&(tcpd->flow2);
2135 } else {
2136 tcpd->fwd=&(tcpd->flow2);
2137 tcpd->rev=&(tcpd->flow1);
2140 if (clear_ta) {
2141 tcpd->ta=NULL;
2143 return tcpd;
2146 /* Attach process info to a flow */
2147 /* XXX - We depend on the TCP dissector finding the conversation first */
2148 void
2149 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) {
2150 conversation_t *conv;
2151 struct tcp_analysis *tcpd;
2152 tcp_flow_t *flow = NULL;
2154 if (!tcp_display_process_info)
2155 return;
2157 conv = find_conversation(frame_num, local_addr, remote_addr, CONVERSATION_TCP, local_port, remote_port, 0);
2158 if (!conv) {
2159 return;
2162 tcpd = (struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
2163 if (!tcpd) {
2164 return;
2167 if (cmp_address(local_addr, conversation_key_addr1(conv->key_ptr)) == 0 && local_port == conversation_key_port1(conv->key_ptr)) {
2168 flow = &tcpd->flow1;
2169 } else if (cmp_address(remote_addr, conversation_key_addr1(conv->key_ptr)) == 0 && remote_port == conversation_key_port1(conv->key_ptr)) {
2170 flow = &tcpd->flow2;
2172 if (!flow || (flow->process_info && flow->process_info->command)) {
2173 return;
2176 if (flow->process_info == NULL)
2177 flow->process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t);
2179 flow->process_info->process_uid = uid;
2180 flow->process_info->process_pid = pid;
2181 flow->process_info->username = wmem_strdup(wmem_file_scope(), username);
2182 flow->process_info->command = wmem_strdup(wmem_file_scope(), command);
2185 /* Return the current stream count */
2186 uint32_t get_tcp_stream_count(void)
2188 return tcp_stream_count;
2191 /* Return the mptcp current stream count */
2192 uint32_t get_mptcp_stream_count(void)
2194 return mptcp_stream_count;
2197 /* Calculate the timestamps relative to this conversation */
2198 static void
2199 tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
2200 struct tcp_per_packet_data_t *tcppd)
2202 if( !tcppd ) {
2203 tcppd = wmem_new(wmem_file_scope(), struct tcp_per_packet_data_t);
2204 p_add_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num, tcppd);
2207 if (!tcpd)
2208 return;
2210 /* pre-increment so packet numbers start at 1 */
2211 tcppd->pnum = ++tcpd->pnum;
2213 nstime_delta(&tcppd->ts_del, &pinfo->abs_ts, &tcpd->ts_prev);
2214 tcppd->tcp_snd_manual_analysis = 0;
2216 tcpd->ts_prev.secs=pinfo->abs_ts.secs;
2217 tcpd->ts_prev.nsecs=pinfo->abs_ts.nsecs;
2220 /* Add a subtree with the timestamps relative to this conversation */
2221 static void
2222 tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
2224 proto_item *item;
2225 proto_tree *tree;
2226 nstime_t ts;
2228 if (!tcpd)
2229 return;
2231 tree=proto_tree_add_subtree(parent_tree, tvb, 0, 0, ett_tcp_timestamps, &item, "Timestamps");
2232 proto_item_set_generated(item);
2234 nstime_delta(&ts, &pinfo->abs_ts, &tcpd->ts_first);
2235 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);
2236 proto_item_set_generated(item);
2238 if( !tcppd )
2239 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
2241 if( tcppd ) {
2242 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,
2243 &tcppd->ts_del);
2244 proto_item_set_generated(item);
2248 static void
2249 print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)
2251 proto_item *item;
2253 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);
2254 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
2255 tvb, 0, 0, msp->first_frame);
2256 proto_item_set_generated(item);
2259 /* if we know that a PDU starts inside this segment, return the adjusted
2260 offset to where that PDU starts or just return offset back
2261 and let TCP try to find out what it can about this segment
2263 static int
2264 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)
2266 struct tcp_multisegment_pdu *msp=NULL;
2268 if(!pinfo->fd->visited) {
2269 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);
2270 if(msp) {
2271 /* If this is a continuation of a PDU started in a
2272 * previous segment we need to update the last_frame
2273 * variables.
2275 if(seq>msp->seq && seq<msp->nxtpdu) {
2276 msp->last_frame=pinfo->num;
2277 msp->last_frame_time=pinfo->abs_ts;
2278 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
2281 /* If this segment is completely within a previous PDU
2282 * then we just skip this packet
2284 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {
2285 return -1;
2287 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {
2288 offset+=msp->nxtpdu-seq;
2289 return offset;
2293 } else {
2294 /* First we try to find the start and transfer time for a PDU.
2295 * We only print this for the very first segment of a PDU
2296 * and only for PDUs spanning multiple segments.
2297 * Se we look for if there was any multisegment PDU started
2298 * just BEFORE the end of this segment. I.e. either inside this
2299 * segment or in a previous segment.
2300 * Since this might also match PDUs that are completely within
2301 * this segment we also verify that the found PDU does span
2302 * beyond the end of this segment.
2304 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, nxtseq-1);
2305 if(msp) {
2306 if(pinfo->num==msp->first_frame) {
2307 proto_item *item;
2308 nstime_t ns;
2310 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);
2311 proto_item_set_generated(item);
2313 nstime_delta(&ns, &msp->last_frame_time, &pinfo->abs_ts);
2314 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,
2315 tvb, 0, 0, &ns);
2316 proto_item_set_generated(item);
2320 /* Second we check if this segment is part of a PDU started
2321 * prior to the segment (seq-1)
2323 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);
2324 if(msp) {
2325 /* If this segment is completely within a previous PDU
2326 * then we just skip this packet
2328 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {
2329 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
2330 return -1;
2333 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {
2334 offset+=msp->nxtpdu-seq;
2335 return offset;
2340 return offset;
2343 /* if we saw a PDU that extended beyond the end of the segment,
2344 use this function to remember where the next pdu starts
2346 struct tcp_multisegment_pdu *
2347 pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, uint32_t seq, uint32_t nxtpdu, wmem_tree_t *multisegment_pdus)
2349 struct tcp_multisegment_pdu *msp;
2351 msp=wmem_new(wmem_file_scope(), struct tcp_multisegment_pdu);
2352 msp->nxtpdu=nxtpdu;
2353 msp->seq=seq;
2354 msp->first_frame=pinfo->num;
2355 msp->first_frame_with_seq=pinfo->num;
2356 msp->last_frame=pinfo->num;
2357 msp->last_frame_time=pinfo->abs_ts;
2358 msp->flags=0;
2359 wmem_tree_insert32(multisegment_pdus, seq, (void *)msp);
2360 /*ws_warning("pdu_store_sequencenumber_of_next_pdu: seq %u", seq);*/
2361 return msp;
2364 /* This is called for SYN and SYN+ACK packets and the purpose is to verify
2365 * that we have seen window scaling in both directions.
2366 * If we can't find window scaling being set in both directions
2367 * that means it was present in the SYN but not in the SYN+ACK
2368 * (or the SYN was missing) and then we disable the window scaling
2369 * for this tcp session.
2371 static void
2372 verify_tcp_window_scaling(bool is_synack, struct tcp_analysis *tcpd)
2374 if( tcpd->fwd->win_scale==-1 ) {
2375 /* We know window scaling will not be used as:
2376 * a) this is the SYN and it does not have the WS option
2377 * (we set the reverse win_scale also in case we miss
2378 * the SYN/ACK)
2379 * b) this is the SYN/ACK and either the SYN packet has not
2380 * been seen or it did have the WS option. As the SYN/ACK
2381 * does not have the WS option, window scaling will not be used.
2383 * Setting win_scale to -2 to indicate that we can
2384 * trust the window_size value in the TCP header.
2386 tcpd->fwd->win_scale = -2;
2387 tcpd->rev->win_scale = -2;
2389 } else if( is_synack && tcpd->rev->win_scale==-2 ) {
2390 /* The SYN/ACK has the WS option, while the SYN did not,
2391 * this should not happen, but the endpoints will not
2392 * have used window scaling, so we will neither
2394 tcpd->fwd->win_scale = -2;
2398 /* given a tcpd, returns the mptcp_subflow that sides with meta */
2399 static struct mptcp_subflow *
2400 mptcp_select_subflow_from_meta(const struct tcp_analysis *tcpd, const mptcp_meta_flow_t *meta)
2402 /* select the tcp_flow with appropriate direction */
2403 if( tcpd->flow1.mptcp_subflow->meta == meta) {
2404 return tcpd->flow1.mptcp_subflow;
2406 else {
2407 return tcpd->flow2.mptcp_subflow;
2411 /* if we saw a window scaling option, store it for future reference
2413 static void
2414 pdu_store_window_scale_option(uint8_t ws, struct tcp_analysis *tcpd)
2416 if (tcpd)
2417 tcpd->fwd->win_scale=ws;
2420 /* when this function returns, it will (if createflag) populate the ta pointer.
2422 static void
2423 tcp_analyze_get_acked_struct(uint32_t frame, uint32_t seq, uint32_t ack, bool createflag, struct tcp_analysis *tcpd)
2426 wmem_tree_key_t key[4];
2428 key[0].length = 1;
2429 key[0].key = &frame;
2431 key[1].length = 1;
2432 key[1].key = &seq;
2434 key[2].length = 1;
2435 key[2].key = &ack;
2437 key[3].length = 0;
2438 key[3].key = NULL;
2440 if (!tcpd) {
2441 return;
2444 tcpd->ta = (struct tcp_acked *)wmem_tree_lookup32_array(tcpd->acked_table, key);
2445 if((!tcpd->ta) && createflag) {
2446 tcpd->ta = wmem_new0(wmem_file_scope(), struct tcp_acked);
2447 wmem_tree_insert32_array(tcpd->acked_table, key, (void *)tcpd->ta);
2453 /* fwd contains a list of all segments processed but not yet ACKed in the
2454 * same direction as the current segment.
2455 * rev contains a list of all segments received but not yet ACKed in the
2456 * opposite direction to the current segment.
2458 * New segments are always added to the head of the fwd/rev lists.
2460 * Changes below should be synced with ChAdvTCPAnalysis in the User's
2461 * Guide: doc/wsug_src/WSUG_chapter_advanced.adoc
2463 static void
2464 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)
2466 tcp_unacked_t *ual=NULL;
2467 tcp_unacked_t *prevual=NULL;
2468 uint32_t nextseq;
2470 #if 0
2471 printf("\nanalyze_sequence numbers frame:%u\n",pinfo->num);
2472 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);
2473 for(ual=tcpd->fwd->tcp_analyze_seq_info->segments; ual; ual=ual->next)
2474 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);
2475 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);
2476 for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next)
2477 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);
2478 #endif
2480 if (!tcpd) {
2481 return;
2484 if( flags & TH_ACK ) {
2485 tcpd->rev->tcp_analyze_seq_info->valid_bif = true;
2488 /* ZERO WINDOW PROBE
2489 * it is a zero window probe if
2490 * the sequence number is the next expected one
2491 * the window in the other direction is 0
2492 * the segment is exactly 1 byte
2494 if( seglen==1
2495 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2496 && tcpd->rev->window==0 ) {
2497 if(!tcpd->ta) {
2498 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2500 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
2501 goto finished_fwd;
2505 /* ZERO WINDOW
2506 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
2508 if( window==0
2509 && (flags&(TH_RST|TH_FIN|TH_SYN))==0 ) {
2510 if(!tcpd->ta) {
2511 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2513 tcpd->ta->flags|=TCP_A_ZERO_WINDOW;
2517 /* LOST PACKET
2518 * If this segment is beyond the last seen nextseq we must
2519 * have missed some previous segment
2521 * We only check for this if we have actually seen segments prior to this
2522 * one.
2523 * RST packets are not checked for this.
2525 if( tcpd->fwd->tcp_analyze_seq_info->nextseq
2526 && GT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq)
2527 && (flags&(TH_RST))==0 ) {
2528 if(!tcpd->ta) {
2529 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2531 tcpd->ta->flags|=TCP_A_LOST_PACKET;
2533 /* Disable BiF until an ACK is seen in the other direction */
2534 tcpd->fwd->tcp_analyze_seq_info->valid_bif = false;
2538 /* KEEP ALIVE
2539 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
2540 * to what should be the next sequence number.
2541 * SYN/FIN/RST segments are never keepalives
2543 if( (seglen==0||seglen==1)
2544 && seq==(tcpd->fwd->tcp_analyze_seq_info->nextseq-1)
2545 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2546 if(!tcpd->ta) {
2547 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2549 tcpd->ta->flags|=TCP_A_KEEP_ALIVE;
2552 /* WINDOW UPDATE
2553 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
2554 * the previous seen segment and with a new window value
2556 if( seglen==0
2557 && window
2558 && window!=tcpd->fwd->window
2559 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2560 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
2561 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2562 if(!tcpd->ta) {
2563 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2565 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
2569 /* WINDOW FULL
2570 * If we know the window scaling
2571 * and if this segment contains data and goes all the way to the
2572 * edge of the advertised window
2573 * then we mark it as WINDOW FULL
2574 * SYN/RST/FIN packets are never WINDOW FULL
2576 if( seglen>0
2577 && tcpd->rev->win_scale!=-1
2578 && (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))))
2579 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2580 if(!tcpd->ta) {
2581 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2583 tcpd->ta->flags|=TCP_A_WINDOW_FULL;
2587 /* KEEP ALIVE ACK
2588 * It is a keepalive ack if it repeats the previous ACK and if
2589 * the last segment in the reverse direction was a keepalive
2591 if( seglen==0
2592 && window
2593 && window==tcpd->fwd->window
2594 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2595 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
2596 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
2597 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2598 if(!tcpd->ta) {
2599 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2601 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK;
2602 goto finished_fwd;
2606 /* ZERO WINDOW PROBE ACK
2607 * It is a zerowindowprobe ack if it repeats the previous ACK and if
2608 * the last segment in the reverse direction was a zerowindowprobe
2609 * It also repeats the previous zero window indication
2611 if( seglen==0
2612 && window==0
2613 && window==tcpd->fwd->window
2614 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2615 && (ack==tcpd->fwd->tcp_analyze_seq_info->lastack || EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1))
2616 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
2617 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2618 if(!tcpd->ta) {
2619 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2621 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
2623 /* Some receivers consume that extra byte brought in the PROBE,
2624 * but it was too early to know that during the WINDOW PROBE analysis.
2625 * Do it now by moving the rev nextseq & maxseqtobeacked.
2626 * See issue 10745.
2628 if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)) {
2629 tcpd->rev->tcp_analyze_seq_info->nextseq=ack;
2630 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
2632 goto finished_fwd;
2636 /* DUPLICATE ACK
2637 * It is a duplicate ack if window/seq/ack is the same as the previous
2638 * segment and if the segment length is 0
2640 if( seglen==0
2641 && window
2642 && window==tcpd->fwd->window
2643 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2644 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
2645 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2647 /* MPTCP tolerates duplicate acks in some circumstances, see RFC 8684 4. */
2648 if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) {
2649 /* just ignore this DUPLICATE ACK */
2650 } else {
2651 tcpd->fwd->tcp_analyze_seq_info->dupacknum++;
2653 if(!tcpd->ta) {
2654 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2656 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
2657 tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum;
2658 tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack;
2664 finished_fwd:
2665 /* If the ack number changed we must reset the dupack counters */
2666 if( ack != tcpd->fwd->tcp_analyze_seq_info->lastack ) {
2667 tcpd->fwd->tcp_analyze_seq_info->lastnondupack=pinfo->num;
2668 tcpd->fwd->tcp_analyze_seq_info->dupacknum=0;
2672 /* ACKED LOST PACKET
2673 * If this segment acks beyond the 'max seq to be acked' in the other direction
2674 * then that means we have missed packets going in the
2675 * other direction.
2676 * It might also indicate we are resuming from a Zero Window,
2677 * where a Probe is just followed by an ACK opening again the window.
2678 * See issue 8404.
2680 * We only check this if we have actually seen some seq numbers
2681 * in the other direction.
2683 if( tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked
2684 && GT_SEQ(ack, tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked )
2685 && (flags&(TH_ACK))!=0 ) {
2686 if(!tcpd->ta) {
2687 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2690 /* resuming from a Zero Window Probe which re-opens the window,
2691 * mark it as a Window Update
2693 if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)
2694 && (seq==tcpd->fwd->tcp_analyze_seq_info->nextseq)
2695 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE) ) {
2696 tcpd->rev->tcp_analyze_seq_info->nextseq=ack;
2697 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
2698 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
2700 /* real ACKED LOST PACKET */
2701 else {
2702 /* We ensure there is no matching packet waiting in the unacked list,
2703 * and take this opportunity to push the tail further than this single packet
2706 uint32_t tail_le = 0, tail_re = 0;
2707 for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next) {
2709 if(tail_le == tail_re) { /* init edge values */
2710 tail_le = ual->seq;
2711 tail_re = ual->nextseq;
2714 /* Only look at what happens above the current ACK value,
2715 * as what happened before is definetely ACKed here and can be
2716 * safely ignored. */
2717 if(GE_SEQ(ual->seq,ack)) {
2719 /* if the left edge is contiguous, move the tail leftward */
2720 if(EQ_SEQ(ual->nextseq,tail_le)) {
2721 tail_le = ual->seq;
2724 /* otherwise, we have isolated segments above what is being ACKed here,
2725 * and we reinit the tails with the current values */
2726 else {
2727 tail_le = ual->seq;
2728 tail_re = ual->nextseq; // move the end tail
2733 /* a tail was found and we can push the maxseqtobeacked further */
2734 if(EQ_SEQ(ack,tail_le) && GT_SEQ(tail_re, ack)) {
2735 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=tail_re;
2738 /* otherwise, just take into account the value being ACKed now */
2739 else {
2740 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
2743 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
2748 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
2749 * If the segment contains data (or is a SYN or a FIN) and
2750 * if it does not advance the sequence number, it must be one
2751 * of these three.
2752 * Only test for this if we know what the seq number should be
2753 * (tcpd->fwd->nextseq)
2755 * Note that a simple KeepAlive is not a retransmission
2757 bool seq_not_advanced = tcpd->fwd->tcp_analyze_seq_info->nextseq
2758 && (LT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq));
2760 if (seglen>0 || flags&(TH_SYN|TH_FIN)) {
2762 uint64_t t;
2763 uint64_t ooo_thres;
2765 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ) {
2766 goto finished_checking_retransmission_type;
2769 /* This segment is *not* considered a retransmission/out-of-order if
2770 * the segment length is larger than one (it really adds new data)
2771 * the sequence number is one less than the previous nextseq and
2772 * (the previous segment is possibly a zero window probe)
2774 * We should still try to flag Spurious Retransmissions though.
2776 if (seglen > 1 && tcpd->fwd->tcp_analyze_seq_info->nextseq - 1 == seq) {
2777 seq_not_advanced = false;
2780 /* Check for spurious retransmission. If the current seq + segment length
2781 * is less than or equal to the current lastack, the packet contains
2782 * duplicate data and may be considered spurious.
2784 if ( seglen > 0
2785 && tcpd->rev->tcp_analyze_seq_info->lastack
2786 && LE_SEQ(seq + seglen, tcpd->rev->tcp_analyze_seq_info->lastack) ) {
2787 if(!tcpd->ta){
2788 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2790 tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION;
2791 goto finished_checking_retransmission_type;
2794 nextseq = seq+seglen;
2796 if(!seq_not_advanced)
2797 goto finished_checking_retransmission_type;
2799 /* Some OOO vs Retrans interpretations can be wrong when the capture needs a reorder.
2800 * Avoid such cases by enforcing the delta to 0 when the order seems bad, instead of
2801 * calculating an absurd value.
2803 if(pinfo->abs_ts.secs > tcpd->rev->tcp_analyze_seq_info->lastacktime.secs) {
2804 /* regular case */
2805 t = (pinfo->abs_ts.secs - tcpd->rev->tcp_analyze_seq_info->lastacktime.secs)*1000000000;
2806 t += pinfo->abs_ts.nsecs - tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs;
2808 else if( (pinfo->abs_ts.secs == tcpd->rev->tcp_analyze_seq_info->lastacktime.secs) &&
2809 (pinfo->abs_ts.nsecs > tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs) ) {
2810 t = pinfo->abs_ts.nsecs - tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs;
2812 else {
2813 t = 0;
2816 bool precedence_count = tcp_fastrt_precedence;
2817 do {
2818 if (precedence_count) {
2819 /* If there were >=2 duplicate ACKs in the reverse direction
2820 * (there might be duplicate acks missing from the trace)
2821 * and if this sequence number matches those ACKs
2822 * and if the packet occurs within 20ms of the last
2823 * duplicate ack
2824 * then this is a fast retransmission
2826 if( t<20000000
2827 && tcpd->rev->tcp_analyze_seq_info->dupacknum>=2
2828 && tcpd->rev->tcp_analyze_seq_info->lastack==seq) {
2829 if(!tcpd->ta) {
2830 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2832 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
2833 goto finished_checking_retransmission_type;
2836 /* Look for this segment in reported SACK ranges,
2837 * if not present this might very well be a FAST Retrans,
2838 * when the conditions above (timing, number of retrans) are still true */
2839 if( t<20000000
2840 && tcpd->rev->tcp_analyze_seq_info->dupacknum>=2
2841 && tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) {
2843 bool is_sacked = false;
2844 int i=0;
2845 while( !is_sacked && i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges ) {
2846 is_sacked = ((seq >= tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i])
2847 && (nextseq <= tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i]));
2848 i++;
2851 /* fine, it's probably a Fast Retrans triggered by the SACK sender algo */
2852 if(!is_sacked) {
2853 if(!tcpd->ta)
2854 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2855 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
2856 goto finished_checking_retransmission_type;
2860 precedence_count=!precedence_count;
2861 } else {
2862 /* If the segment came relatively close since the segment with the highest
2863 * seen sequence number and it doesn't look like a retransmission
2864 * then it is an OUT-OF-ORDER segment.
2866 if (tcpd->ts_first_rtt.nsecs == 0 && tcpd->ts_first_rtt.secs == 0) {
2867 ooo_thres = 3000000;
2868 } else {
2869 ooo_thres = tcpd->ts_first_rtt.nsecs + tcpd->ts_first_rtt.secs*1000000000;
2872 /* If the segment is already seen and waiting to be acknowledged, ignore the
2873 * Fast-Retrans/OOO debate and go ahead, as it only can be an ordinary Retrans.
2874 * Fast-Retrans/Retrans are never ambiguous in the context of packets seen but
2875 * this code could be moved above.
2876 * See Issues 13284, 13843
2877 * XXX: if compared packets have different sizes, it's not handled yet
2879 bool pk_already_seen = false;
2880 ual = tcpd->fwd->tcp_analyze_seq_info->segments;
2881 while(ual) {
2882 if(GE_SEQ(seq,ual->seq) && LE_SEQ(seq+seglen,ual->nextseq)) {
2883 pk_already_seen = true;
2884 /* As we know this packet has retransmissions, we are marking it
2885 * as eligible to Karn's algo.
2887 ual->karn_flag = true;
2888 if(!tcpd->ta) {
2889 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2891 break;
2893 ual=ual->next;
2896 if(t < ooo_thres && !pk_already_seen) {
2897 /* ordinary OOO with SEQ numbers and lengths clearly stating the situation */
2898 if( tcpd->fwd->tcp_analyze_seq_info->nextseq != (seq + seglen + (flags&(TH_SYN|TH_FIN) ? 1 : 0))) {
2899 if(!tcpd->ta) {
2900 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2903 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
2904 goto finished_checking_retransmission_type;
2906 else {
2907 /* facing an OOO closing a series of disordered packets,
2908 all preceded by a pure ACK. See issue 17214 */
2909 if(tcpd->fwd->tcp_analyze_seq_info->lastacklen == 0) {
2910 if(!tcpd->ta) {
2911 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2914 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
2915 goto finished_checking_retransmission_type;
2919 precedence_count=!precedence_count;
2921 } while (precedence_count!=tcp_fastrt_precedence) ;
2923 /* Then it has to be a generic retransmission */
2924 if(!tcpd->ta) {
2925 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2927 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
2930 * worst case scenario: if we don't have better than a recent packet,
2931 * use it as the reference for RTO
2933 nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &tcpd->fwd->tcp_analyze_seq_info->nextseqtime);
2934 tcpd->ta->rto_frame=tcpd->fwd->tcp_analyze_seq_info->nextseqframe;
2937 * better case scenario: if we have a list of the previous unacked packets,
2938 * go back to the eldest one, which in theory is likely to be the one retransmitted here.
2939 * It's not always the perfect match, particularly when original captured packet used LSO
2940 * We may parse this list and try to find an obvious matching packet present in the
2941 * capture. If such packet is actually missing, we'll reach the list first entry.
2942 * See : issue #12259
2943 * See : issue #17714
2945 ual = tcpd->fwd->tcp_analyze_seq_info->segments;
2946 while(ual) {
2947 if(GE_SEQ(ual->seq, seq)) {
2948 nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &ual->ts );
2949 tcpd->ta->rto_frame=ual->frame;
2951 ual=ual->next;
2955 finished_checking_retransmission_type:
2957 /* Override the TCP sequence analysis with the value given
2958 * manually by the user. This only applies to flagged packets.
2960 if(tcppd && tcpd->ta &&
2961 (tcppd->tcp_snd_manual_analysis>0) &&
2962 (tcpd->ta->flags & TCP_A_RETRANSMISSION ||
2963 tcpd->ta->flags & TCP_A_OUT_OF_ORDER ||
2964 tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION ||
2965 tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION)) {
2967 /* clean flags set during the automatic analysis */
2968 tcpd->ta->flags &= ~(TCP_A_RETRANSMISSION|
2969 TCP_A_OUT_OF_ORDER|
2970 TCP_A_FAST_RETRANSMISSION|
2971 TCP_A_SPURIOUS_RETRANSMISSION);
2973 /* set the corresponding flag chosen by the user */
2974 switch(tcppd->tcp_snd_manual_analysis) {
2975 case 0:
2976 /* the user asked for an empty overriding, which
2977 * means removing any previous value, thus restoring
2978 * the automatic analysis.
2980 break;
2982 case 1:
2983 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
2984 break;
2986 case 2:
2987 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
2988 break;
2990 case 3:
2991 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
2992 break;
2994 case 4:
2995 tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION;
2996 break;
2998 default:
2999 /* there is no expected default case */
3000 break;
3004 nextseq = seq+seglen;
3005 if ((seglen || flags&(TH_SYN|TH_FIN)) && tcpd->fwd->tcp_analyze_seq_info->segment_count < TCP_MAX_UNACKED_SEGMENTS) {
3006 /* Add this new sequence number to the fwd list. But only if there
3007 * aren't "too many" unacked segments (e.g., we're not seeing the ACKs).
3009 ual = wmem_new(wmem_file_scope(), tcp_unacked_t);
3010 ual->next=tcpd->fwd->tcp_analyze_seq_info->segments;
3011 tcpd->fwd->tcp_analyze_seq_info->segments=ual;
3012 tcpd->fwd->tcp_analyze_seq_info->segment_count++;
3013 ual->frame=pinfo->num;
3014 ual->seq=seq;
3015 ual->ts=pinfo->abs_ts;
3017 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
3018 if( (flags&(TH_SYN|TH_FIN)) ) {
3019 nextseq+=1;
3022 /* All Retransmissions are marked for later Karn discovery.
3023 * It's very unlikely that we will ever meet a TCP client
3024 * that just acknowledges a Fast Retransmission segment without
3025 * jumping over and also acknowledging the ones that triggered
3026 * the fast retransmission. Or maybe under heavy load ?
3028 if(tcpd->ta &&
3029 (tcpd->ta->flags & TCP_A_RETRANSMISSION ||
3030 tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION ||
3031 tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION)) {
3032 ual->karn_flag=true;
3034 else {
3035 ual->karn_flag=false;
3038 ual->nextseq=nextseq;
3041 /* Every time we are moving the highest number seen,
3042 * we are also tracking the segment length then we will know for sure,
3043 * later, if this was a pure ACK or an ordinary data packet. */
3044 if(!tcpd->fwd->tcp_analyze_seq_info->nextseq
3045 || GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq + (flags&(TH_SYN|TH_FIN) ? 1 : 0))) {
3046 tcpd->fwd->tcp_analyze_seq_info->lastacklen=seglen;
3049 /* Store the highest number seen so far for nextseq so we can detect
3050 * when we receive segments that arrive with a "hole"
3051 * If we don't have anything since before, just store what we got.
3052 * ZeroWindowProbes are special and don't really advance the nextseq
3054 if(GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq) || !tcpd->fwd->tcp_analyze_seq_info->nextseq) {
3055 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
3056 tcpd->fwd->tcp_analyze_seq_info->nextseq=nextseq;
3057 tcpd->fwd->tcp_analyze_seq_info->nextseqframe=pinfo->num;
3058 tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs=pinfo->abs_ts.secs;
3059 tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs=pinfo->abs_ts.nsecs;
3061 /* Count the flows turns by checking all packets carrying real data
3062 * Packets not ordered are ignored.
3064 if((!tcpd->ta ) ||
3065 !(tcpd->ta->flags & TCP_A_RETRANSMISSION ||
3066 tcpd->ta->flags & TCP_A_OUT_OF_ORDER ||
3067 tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION ||
3068 tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION)) {
3070 if( seglen>0) {
3071 /* check direction */
3072 int8_t direction;
3073 direction=cmp_address(&pinfo->src, &pinfo->dst);
3075 /* if the addresses are equal, match the ports instead */
3076 if(direction==0) {
3077 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
3080 /* invert the direction and increment the counter */
3081 if(direction != tcpd->flow_direction) {
3082 tcpd->flow_direction = direction;
3083 tcpd->fwd->flow_count++;
3085 /* if the direction was not reversed, maybe are we
3086 * facing the first flow ? Yes, if the counter still equals 0.
3088 else {
3089 if(tcpd->fwd->flow_count==0) {
3090 tcpd->fwd->flow_count++;
3098 /* Store the highest continuous seq number seen so far for 'max seq to be acked',
3099 * so we can detect TCP_A_ACK_LOST_PACKET condition.
3100 * If this ever happens, this boundary value can "jump" further in order to
3101 * avoid duplicating multiple messages for the very same lost packet. See later
3102 * how ACKED LOST PACKET are handled.
3103 * Zero Window Probes are logically left out at this moment, but if their data
3104 * really were to be ack'ed, then it will be done later when analyzing their
3105 * Probe ACK (be it a real Probe ACK, or an ordinary ACK moving the RCV Window).
3107 if(EQ_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) || !tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) {
3108 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
3109 tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked=tcpd->fwd->tcp_analyze_seq_info->nextseq;
3114 /* remember what the ack/window is so we can track window updates and retransmissions */
3115 tcpd->fwd->window=window;
3116 tcpd->fwd->tcp_analyze_seq_info->lastack=ack;
3117 tcpd->fwd->tcp_analyze_seq_info->lastacktime.secs=pinfo->abs_ts.secs;
3118 tcpd->fwd->tcp_analyze_seq_info->lastacktime.nsecs=pinfo->abs_ts.nsecs;
3120 /* remember the MPTCP operations if any */
3121 if( tcpd->mptcp_analysis ) {
3122 tcpd->fwd->mp_operations=tcpd->mptcp_analysis->mp_operations;
3125 /* if there were any flags set for this segment we need to remember them
3126 * we only remember the flags for the very last segment though.
3128 if(tcpd->ta) {
3129 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;
3130 } else {
3131 tcpd->fwd->lastsegmentflags=0;
3135 /* remove all segments this ACKs and we don't need to keep around any more
3137 prevual = NULL;
3138 ual = tcpd->rev->tcp_analyze_seq_info->segments;
3139 while(ual) {
3140 tcp_unacked_t *tmpual;
3142 /* If this ack matches the segment, process accordingly */
3143 if(ack==ual->nextseq) {
3144 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
3145 tcpd->ta->frame_acked=ual->frame;
3146 nstime_delta(&tcpd->ta->ts, &pinfo->abs_ts, &ual->ts);
3147 /* mark it as a full segment ACK */
3148 tcpd->ta->partial_ack=0;
3150 if (tcppd) {
3151 if (ual->karn_flag) {
3152 tcpd->ta->iskarn=true;
3153 tcppd->karn_flag=true;
3155 else {
3156 tcpd->ta->iskarn=false;
3157 tcppd->karn_flag=false;
3161 /* If this acknowledges part of the segment, adjust the segment info for the acked part.
3162 * This typically happens in the context of GSO/GRO or Retransmissions with
3163 * segment repackaging (elsewhere called repacketization). For the user, looking at the
3164 * previous packets for any Retransmission or at the SYN MSS Option presence would
3165 * answer what case is precisely encountered.
3167 else if (GT_SEQ(ack, ual->seq) && LE_SEQ(ack, ual->nextseq)) {
3168 ual->seq = ack;
3169 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
3170 tcpd->ta->frame_acked=ual->frame;
3171 nstime_delta(&tcpd->ta->ts, &pinfo->abs_ts, &ual->ts);
3173 /* mark it as a partial segment ACK
3175 * XXX - This mark is used later to create an Expert Note,
3176 * but other ways of tracking these packets are possible:
3177 * for example a similar indication to ta->frame_acked
3178 * would help differentiating the SEQ/ACK analysis messages.
3179 * Also, a TCP Analysis Flag could be added, but doesn't seem
3180 * essential yet, as matching packets can be selected with
3181 * 'tcp.analysis.partial_ack'.
3183 tcpd->ta->partial_ack=1;
3185 /* identify ambiguous ACKs following Karn's definition
3187 if (tcppd) {
3188 if (ual->karn_flag) {
3189 tcpd->ta->iskarn=true;
3190 tcppd->karn_flag=true;
3192 else {
3193 tcpd->ta->iskarn=false;
3194 tcppd->karn_flag=false;
3198 continue;
3200 /* If this acknowledges a segment prior to this one, leave this segment alone and move on */
3201 else if (GT_SEQ(ual->nextseq,ack)) {
3202 prevual = ual;
3203 ual = ual->next;
3204 continue;
3207 /* This segment is old, or an exact match. Delete the segment from the list */
3208 tmpual=ual->next;
3210 if (tcpd->rev->scps_capable) {
3211 /* Track largest segment successfully sent for SNACK analysis*/
3212 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) {
3213 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);
3217 if (!prevual) {
3218 tcpd->rev->tcp_analyze_seq_info->segments = tmpual;
3220 else{
3221 prevual->next = tmpual;
3223 wmem_free(wmem_file_scope(), ual);
3224 ual = tmpual;
3225 tcpd->rev->tcp_analyze_seq_info->segment_count--;
3228 /* how many bytes of data are there in flight after this frame
3229 * was sent
3230 * The historical evaluation is done from the payload seen in the
3231 * segments captured. Another method deduced from the SEQ numbers
3232 * is introduced with issue 7703, but not used by default now. The
3233 * method is chosen by the user preference tcp_bif_seq_based.
3235 if(tcp_track_bytes_in_flight) {
3236 uint32_t in_flight, delivered = 0;
3238 * "don't repeat yourself" boolean, for the shared part
3239 * between both methods
3241 bool dry_bif_handling = false;
3244 * historical calculation method based on payloads, which is
3245 * by now still the default.
3247 if(!tcp_bif_seq_based) {
3248 ual=tcpd->fwd->tcp_analyze_seq_info->segments;
3250 if (seglen!=0 && ual && tcpd->fwd->tcp_analyze_seq_info->valid_bif) {
3251 uint32_t first_seq, last_seq;
3253 dry_bif_handling = true;
3255 first_seq = ual->seq - tcpd->fwd->base_seq;
3256 last_seq = ual->nextseq - tcpd->fwd->base_seq;
3257 while (ual) {
3258 if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) {
3259 last_seq = ual->nextseq-tcpd->fwd->base_seq;
3261 if ((ual->seq-tcpd->fwd->base_seq)<first_seq) {
3262 first_seq = ual->seq-tcpd->fwd->base_seq;
3264 ual = ual->next;
3266 in_flight = last_seq-first_seq;
3268 } else { /* calculation based on SEQ numbers (see issue 7703) */
3269 if (seglen!=0 && tcpd->fwd->tcp_analyze_seq_info && tcpd->fwd->tcp_analyze_seq_info->valid_bif) {
3271 dry_bif_handling = true;
3273 in_flight = tcpd->fwd->tcp_analyze_seq_info->nextseq
3274 - tcpd->rev->tcp_analyze_seq_info->lastack;
3277 if(dry_bif_handling) {
3278 /* subtract any SACK block */
3279 if(tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) {
3280 int i;
3281 for(i = 0; i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges; i++) {
3282 delivered += (tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i] -
3283 tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i]);
3285 in_flight -= delivered;
3288 if (in_flight>0 && in_flight<2000000000) {
3289 if(!tcpd->ta) {
3290 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
3292 tcpd->ta->bytes_in_flight = in_flight;
3293 /* Decrement in_flight bytes by one when we have a SYN or FIN bit
3294 * flag set as it is only virtual.
3296 if (flags&(TH_SYN|TH_FIN)) {
3297 tcpd->ta->bytes_in_flight -= 1;
3301 if((flags & TH_PUSH) && !tcpd->fwd->tcp_analyze_seq_info->push_set_last) {
3302 tcpd->fwd->tcp_analyze_seq_info->push_bytes_sent += seglen;
3303 tcpd->fwd->tcp_analyze_seq_info->push_set_last = true;
3304 } else if ((flags & TH_PUSH) && tcpd->fwd->tcp_analyze_seq_info->push_set_last) {
3305 tcpd->fwd->tcp_analyze_seq_info->push_bytes_sent = seglen;
3306 tcpd->fwd->tcp_analyze_seq_info->push_set_last = true;
3307 } else if (tcpd->fwd->tcp_analyze_seq_info->push_set_last) {
3308 tcpd->fwd->tcp_analyze_seq_info->push_bytes_sent = seglen;
3309 tcpd->fwd->tcp_analyze_seq_info->push_set_last = false;
3310 } else {
3311 tcpd->fwd->tcp_analyze_seq_info->push_bytes_sent += seglen;
3313 if(!tcpd->ta) {
3314 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, true, tcpd);
3316 tcpd->ta->push_bytes_sent = tcpd->fwd->tcp_analyze_seq_info->push_bytes_sent;
3323 * Prints results of the sequence number analysis concerning tcp segments
3324 * retransmitted or out-of-order
3326 static void
3327 tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,
3328 tvbuff_t * tvb,
3329 proto_tree * flags_tree, proto_item * flags_item,
3330 struct tcp_acked *ta
3333 /* TCP Retransmission */
3334 if (ta->flags & TCP_A_RETRANSMISSION) {
3335 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
3337 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
3339 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {
3340 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
3341 tvb, 0, 0, &ta->rto_ts);
3342 proto_item_set_generated(flags_item);
3343 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,
3344 tvb, 0, 0, ta->rto_frame);
3345 proto_item_set_generated(flags_item);
3348 /* TCP Fast Retransmission */
3349 if (ta->flags & TCP_A_FAST_RETRANSMISSION) {
3350 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_fast_retransmission);
3351 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
3352 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3353 "[TCP Fast Retransmission] ");
3355 /* TCP Spurious Retransmission */
3356 if (ta->flags & TCP_A_SPURIOUS_RETRANSMISSION) {
3357 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_spurious_retransmission);
3358 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
3359 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3360 "[TCP Spurious Retransmission] ");
3363 /* TCP Out-Of-Order */
3364 if (ta->flags & TCP_A_OUT_OF_ORDER) {
3365 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_out_of_order);
3366 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
3370 /* Prints results of the sequence number analysis concerning reused ports */
3371 static void
3372 tcp_sequence_number_analysis_print_reused(packet_info * pinfo,
3373 proto_item * flags_item,
3374 struct tcp_acked *ta
3377 /* TCP Ports Reused */
3378 if (ta->flags & TCP_A_REUSED_PORTS) {
3379 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_reused_ports);
3380 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3381 "[TCP Port numbers reused] ");
3385 /* Prints results of the sequence number analysis concerning lost tcp segments */
3386 static void
3387 tcp_sequence_number_analysis_print_lost(packet_info * pinfo,
3388 proto_item * flags_item,
3389 struct tcp_acked *ta
3392 /* TCP Lost Segment */
3393 if (ta->flags & TCP_A_LOST_PACKET) {
3394 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_lost_packet);
3395 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3396 "[TCP Previous segment not captured] ");
3398 /* TCP Ack lost segment */
3399 if (ta->flags & TCP_A_ACK_LOST_PACKET) {
3400 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_ack_lost_packet);
3401 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3402 "[TCP ACKed unseen segment] ");
3406 /* Prints results of the sequence number analysis concerning tcp window */
3407 static void
3408 tcp_sequence_number_analysis_print_window(packet_info * pinfo,
3409 proto_item * flags_item,
3410 struct tcp_acked *ta
3413 /* TCP Window Update */
3414 if (ta->flags & TCP_A_WINDOW_UPDATE) {
3415 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_update);
3416 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
3418 /* TCP Full Window */
3419 if (ta->flags & TCP_A_WINDOW_FULL) {
3420 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_full);
3421 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
3425 /* Prints results of the sequence number analysis concerning tcp keepalive */
3426 static void
3427 tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,
3428 proto_item * flags_item,
3429 struct tcp_acked *ta
3432 /*TCP Keep Alive */
3433 if (ta->flags & TCP_A_KEEP_ALIVE) {
3434 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive);
3435 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
3437 /* TCP Ack Keep Alive */
3438 if (ta->flags & TCP_A_KEEP_ALIVE_ACK) {
3439 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive_ack);
3440 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
3444 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
3445 static void
3446 tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,
3447 tvbuff_t * tvb,
3448 proto_tree * flags_tree,
3449 struct tcp_acked *ta,
3450 proto_tree * tree
3453 proto_item * flags_item;
3455 /* TCP Duplicate ACK */
3456 if (ta->dupack_num) {
3457 if (ta->flags & TCP_A_DUPLICATE_ACK ) {
3458 flags_item=proto_tree_add_none_format(flags_tree,
3459 hf_tcp_analysis_duplicate_ack,
3460 tvb, 0, 0,
3461 "This is a TCP duplicate ack"
3463 proto_item_set_generated(flags_item);
3464 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3465 "[TCP Dup ACK %u#%u] ",
3466 ta->dupack_frame,
3467 ta->dupack_num
3471 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
3472 tvb, 0, 0, ta->dupack_num);
3473 proto_item_set_generated(flags_item);
3474 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
3475 tvb, 0, 0, ta->dupack_frame);
3476 proto_item_set_generated(flags_item);
3477 expert_add_info_format(pinfo, flags_item, &ei_tcp_analysis_duplicate_ack, "Duplicate ACK (#%u)", ta->dupack_num);
3481 /* Prints results of the sequence number analysis concerning tcp zero window */
3482 static void
3483 tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,
3484 proto_item * flags_item,
3485 struct tcp_acked *ta
3488 /* TCP Zero Window Probe */
3489 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE) {
3490 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe);
3491 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
3493 /* TCP Zero Window */
3494 if (ta->flags&TCP_A_ZERO_WINDOW) {
3495 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window);
3496 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
3498 /* TCP Zero Window Probe Ack */
3499 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK) {
3500 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe_ack);
3501 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3502 "[TCP ZeroWindowProbeAck] ");
3507 /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */
3508 static void
3509 tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U_,
3510 tvbuff_t * tvb,
3511 proto_tree * flags_tree,
3512 struct tcp_acked *ta
3515 proto_item * flags_item;
3517 if (tcp_track_bytes_in_flight) {
3518 flags_item=proto_tree_add_uint(flags_tree,
3519 hf_tcp_analysis_bytes_in_flight,
3520 tvb, 0, 0, ta->bytes_in_flight);
3522 proto_item_set_generated(flags_item);
3526 /* Generate the initial data sequence number and MPTCP connection token from the key. */
3527 static void
3528 mptcp_cryptodata_sha1(const uint64_t key, uint32_t *token, uint64_t *idsn)
3530 uint8_t digest_buf[HASH_SHA1_LENGTH];
3531 uint64_t pseudokey = GUINT64_TO_BE(key);
3532 uint32_t _token;
3533 uint64_t _isdn;
3535 gcry_md_hash_buffer(GCRY_MD_SHA1, digest_buf, (const uint8_t *)&pseudokey, 8);
3537 /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */
3538 memcpy(&_token, digest_buf, sizeof(_token));
3539 *token = GUINT32_FROM_BE(_token);
3540 memcpy(&_isdn, digest_buf + HASH_SHA1_LENGTH - sizeof(_isdn), sizeof(_isdn));
3541 *idsn = GUINT64_FROM_BE(_isdn);
3544 /* Generate the initial data sequence number and MPTCP connection token from the key. */
3545 static void
3546 mptcp_cryptodata_sha256(const uint64_t key, uint32_t *token, uint64_t *idsn)
3548 uint8_t digest_buf[HASH_SHA2_256_LENGTH];
3549 uint64_t pseudokey = GUINT64_TO_BE(key);
3550 uint32_t _token;
3551 uint64_t _isdn;
3553 gcry_md_hash_buffer(GCRY_MD_SHA256, digest_buf, (const uint8_t *)&pseudokey, 8);
3555 /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */
3556 memcpy(&_token, digest_buf, sizeof(_token));
3557 *token = GUINT32_FROM_BE(_token);
3558 memcpy(&_isdn, digest_buf + HASH_SHA2_256_LENGTH - sizeof(_isdn), sizeof(_isdn));
3559 *idsn = GUINT64_FROM_BE(_isdn);
3563 /* Print formatted list of tcp stream ids that are part of the connection */
3564 static void
3565 mptcp_analysis_add_subflows(packet_info *pinfo, tvbuff_t *tvb,
3566 proto_tree *parent_tree, struct mptcp_analysis* mptcpd)
3568 wmem_list_frame_t *it;
3569 proto_item *item;
3571 wmem_strbuf_t *val = wmem_strbuf_new(pinfo->pool, "");
3573 /* for the analysis, we set each subflow tcp stream id */
3574 for(it = wmem_list_head(mptcpd->subflows); it != NULL; it = wmem_list_frame_next(it)) {
3575 struct tcp_analysis *sf = (struct tcp_analysis *)wmem_list_frame_data(it);
3576 wmem_strbuf_append_printf(val, "%u ", sf->stream);
3579 item = proto_tree_add_string(parent_tree, hf_mptcp_analysis_subflows, tvb, 0, 0, wmem_strbuf_get_str(val));
3580 proto_item_set_generated(item);
3583 /* Compute raw dsn if relative tcp seq covered by DSS mapping */
3584 static bool
3585 mptcp_map_relssn_to_rawdsn(mptcp_dss_mapping_t *mapping, uint32_t relssn, uint64_t *dsn)
3587 if( (relssn < mapping->ssn_low) || (relssn > mapping->ssn_high)) {
3588 return false;
3591 *dsn = mapping->rawdsn + (relssn - mapping->ssn_low);
3592 return true;
3596 /* Add duplicated data */
3597 static mptcp_dsn2packet_mapping_t *
3598 mptcp_add_duplicated_dsn(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, struct mptcp_subflow *subflow,
3599 uint64_t rawdsn64low, uint64_t rawdsn64high
3602 wmem_list_t *results = NULL;
3603 wmem_list_frame_t *packet_it = NULL;
3604 mptcp_dsn2packet_mapping_t *packet = NULL;
3605 proto_item *item = NULL;
3607 results = wmem_itree_find_intervals(subflow->dsn2packet_map,
3608 pinfo->pool,
3609 rawdsn64low,
3610 rawdsn64high
3613 for(packet_it = wmem_list_head(results);
3614 packet_it != NULL;
3615 packet_it = wmem_list_frame_next(packet_it))
3618 packet = (mptcp_dsn2packet_mapping_t *) wmem_list_frame_data(packet_it);
3619 DISSECTOR_ASSERT(packet);
3621 if(pinfo->num > packet->frame) {
3622 item = proto_tree_add_uint(tree, hf_mptcp_reinjection_of, tvb, 0, 0, packet->frame);
3624 else {
3625 item = proto_tree_add_uint(tree, hf_mptcp_reinjected_in, tvb, 0, 0, packet->frame);
3627 proto_item_set_generated(item);
3630 return packet;
3634 /* Lookup mappings that describe the packet and then converts the tcp seq number
3635 * into the MPTCP Data Sequence Number (DSN)
3637 static void
3638 mptcp_analysis_dsn_lookup(packet_info *pinfo , tvbuff_t *tvb,
3639 proto_tree *parent_tree, struct tcp_analysis* tcpd, struct tcpheader * tcph, mptcp_per_packet_data_t *mptcppd)
3641 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;
3642 proto_item *item = NULL;
3643 mptcp_dss_mapping_t *mapping = NULL;
3644 uint32_t relseq;
3645 uint64_t rawdsn = 0;
3646 enum mptcp_dsn_conversion convert;
3648 if(!mptcp_analyze_mappings)
3650 /* abort analysis */
3651 return;
3654 /* for this to work, we need to know the original seq number from the SYN, not from a subsequent packet
3655 * hence, we abort if we didn't capture the SYN
3657 if(!(tcpd->fwd->static_flags & ~TCP_S_BASE_SEQ_SET & (TCP_S_SAW_SYN | TCP_S_SAW_SYNACK))) {
3658 return;
3661 /* if seq not relative yet, we compute it */
3662 relseq = (tcp_relative_seq) ? tcph->th_seq : tcph->th_seq - tcpd->fwd->base_seq;
3664 DISSECTOR_ASSERT(mptcpd);
3665 DISSECTOR_ASSERT(mptcppd);
3667 /* in case of a SYN, there is no mapping covering the DSN */
3668 if(tcph->th_flags & TH_SYN) {
3670 rawdsn = tcpd->fwd->mptcp_subflow->meta->base_dsn;
3671 convert = DSN_CONV_NONE;
3673 /* if it's a non-syn packet without data (just used to convey TCP options)
3674 * then there would be no mappings */
3675 else if(relseq == 1 && tcph->th_seglen == 0) {
3676 rawdsn = tcpd->fwd->mptcp_subflow->meta->base_dsn + 1;
3677 convert = DSN_CONV_NONE;
3679 else {
3681 wmem_list_frame_t *dss_it = NULL;
3682 wmem_list_t *results = NULL;
3683 uint32_t ssn_low = relseq;
3684 uint32_t seglen = tcph->th_seglen;
3686 results = wmem_itree_find_intervals(tcpd->fwd->mptcp_subflow->ssn2dsn_mappings,
3687 pinfo->pool,
3688 ssn_low,
3689 (seglen) ? ssn_low + seglen - 1 : ssn_low
3691 dss_it = wmem_list_head(results); /* assume it's always ok */
3692 if(dss_it) {
3693 mapping = (mptcp_dss_mapping_t *) wmem_list_frame_data(dss_it);
3695 if(dss_it == NULL || mapping == NULL) {
3696 expert_add_info(pinfo, parent_tree, &ei_mptcp_mapping_missing);
3697 return;
3699 else {
3700 mptcppd->mapping = mapping;
3703 DISSECTOR_ASSERT(mapping);
3704 if(seglen) {
3705 /* Finds mappings that cover the sent data and adds them to the dissection tree */
3706 for(dss_it = wmem_list_head(results);
3707 dss_it != NULL;
3708 dss_it = wmem_list_frame_next(dss_it))
3710 mapping = (mptcp_dss_mapping_t *) wmem_list_frame_data(dss_it);
3711 DISSECTOR_ASSERT(mapping);
3713 item = proto_tree_add_uint(parent_tree, hf_mptcp_related_mapping, tvb, 0, 0, mapping->frame);
3714 proto_item_set_generated(item);
3718 convert = (mapping->extended_dsn) ? DSN_CONV_NONE : DSN_CONV_32_TO_64;
3719 DISSECTOR_ASSERT(mptcp_map_relssn_to_rawdsn(mapping, relseq, &rawdsn));
3722 /* Make sure we have the 64bit raw DSN */
3723 if(mptcp_convert_dsn(rawdsn, tcpd->fwd->mptcp_subflow->meta,
3724 convert, false, &tcph->th_mptcp->mh_rawdsn64)) {
3726 /* always display the rawdsn64 (helpful for debug) */
3727 item = proto_tree_add_uint64(parent_tree, hf_mptcp_rawdsn64, tvb, 0, 0, tcph->th_mptcp->mh_rawdsn64);
3729 /* converts to relative if required */
3730 if (mptcp_relative_seq
3731 && mptcp_convert_dsn(tcph->th_mptcp->mh_rawdsn64, tcpd->fwd->mptcp_subflow->meta, DSN_CONV_NONE, true, &tcph->th_mptcp->mh_dsn)) {
3732 item = proto_tree_add_uint64(parent_tree, hf_mptcp_dsn, tvb, 0, 0, tcph->th_mptcp->mh_dsn);
3733 proto_item_append_text(item, " (Relative)");
3736 /* register dsn->packet mapping */
3737 if(mptcp_intersubflows_retransmission
3738 && !PINFO_FD_VISITED(pinfo)
3739 && tcph->th_seglen > 0
3741 mptcp_dsn2packet_mapping_t *packet = 0;
3742 packet = wmem_new0(wmem_file_scope(), mptcp_dsn2packet_mapping_t);
3743 packet->frame = pinfo->fd->num;
3744 packet->subflow = tcpd;
3746 wmem_itree_insert(tcpd->fwd->mptcp_subflow->dsn2packet_map,
3747 tcph->th_mptcp->mh_rawdsn64,
3748 tcph->th_mptcp->mh_rawdsn64 + (tcph->th_seglen - 1 ),
3749 packet
3752 proto_item_set_generated(item);
3754 /* We can do this only if rawdsn64 is valid !
3755 if enabled, look for overlapping mappings on other subflows */
3756 if(mptcp_intersubflows_retransmission
3757 && tcph->th_have_seglen
3758 && tcph->th_seglen) {
3760 wmem_list_frame_t *subflow_it = NULL;
3762 /* results should be some kind of list in case 2 DSS are needed to cover this packet */
3763 for(subflow_it = wmem_list_head(mptcpd->subflows); subflow_it != NULL; subflow_it = wmem_list_frame_next(subflow_it)) {
3764 struct tcp_analysis *sf_tcpd = (struct tcp_analysis *)wmem_list_frame_data(subflow_it);
3765 struct mptcp_subflow *sf = mptcp_select_subflow_from_meta(sf_tcpd, tcpd->fwd->mptcp_subflow->meta);
3767 /* for current subflow */
3768 if (sf == tcpd->fwd->mptcp_subflow) {
3769 /* skip, this is the current subflow */
3771 /* in case there were retransmissions on other subflows */
3772 else {
3773 mptcp_add_duplicated_dsn(pinfo, parent_tree, tvb, sf,
3774 tcph->th_mptcp->mh_rawdsn64,
3775 tcph->th_mptcp->mh_rawdsn64 + tcph->th_seglen-1);
3780 else {
3781 /* could not get the rawdsn64, ignore and continue */
3787 /* Print subflow list */
3788 static void
3789 mptcp_add_analysis_subtree(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree,
3790 struct tcp_analysis *tcpd, struct mptcp_analysis *mptcpd, struct tcpheader * tcph)
3793 proto_item *item = NULL;
3794 proto_tree *tree = NULL;
3795 mptcp_per_packet_data_t *mptcppd = NULL;
3797 if(mptcpd == NULL) {
3798 return;
3801 item=proto_tree_add_item(parent_tree, hf_mptcp_analysis, tvb, 0, 0, ENC_NA);
3802 proto_item_set_generated(item);
3803 tree=proto_item_add_subtree(item, ett_mptcp_analysis);
3804 proto_item_set_generated(tree);
3806 /* set field with mptcp stream */
3807 if(mptcpd->master) {
3809 item = proto_tree_add_boolean_format_value(tree, hf_mptcp_analysis_master, tvb, 0,
3810 0, (mptcpd->master->stream == tcpd->stream) ? true : false
3811 , "Master is tcp stream %u", mptcpd->master->stream
3815 else {
3816 item = proto_tree_add_boolean(tree, hf_mptcp_analysis_master, tvb, 0,
3817 0, false);
3820 proto_item_set_generated(item);
3822 #if 0 // nbOptionsChanged is currently unused.
3823 /* store the TCP Options related to MPTCP then we will avoid false DUP ACKs later */
3824 uint8_t nbOptionsChanged = 0;
3825 if((tcpd->mptcp_analysis->mp_operations&(0x01))!=tcph->th_mptcp->mh_mpc) {
3826 tcpd->mptcp_analysis->mp_operations |= 0x01;
3827 nbOptionsChanged++;
3829 if((tcpd->mptcp_analysis->mp_operations&(0x02))!=tcph->th_mptcp->mh_join) {
3830 tcpd->mptcp_analysis->mp_operations |= 0x02;
3831 nbOptionsChanged++;
3833 if((tcpd->mptcp_analysis->mp_operations&(0x04))!=tcph->th_mptcp->mh_dss) {
3834 tcpd->mptcp_analysis->mp_operations |= 0x04;
3835 nbOptionsChanged++;
3837 if((tcpd->mptcp_analysis->mp_operations&(0x08))!=tcph->th_mptcp->mh_add) {
3838 tcpd->mptcp_analysis->mp_operations |= 0x08;
3839 nbOptionsChanged++;
3841 if((tcpd->mptcp_analysis->mp_operations&(0x10))!=tcph->th_mptcp->mh_remove) {
3842 tcpd->mptcp_analysis->mp_operations |= 0x10;
3843 nbOptionsChanged++;
3845 if((tcpd->mptcp_analysis->mp_operations&(0x20))!=tcph->th_mptcp->mh_prio) {
3846 tcpd->mptcp_analysis->mp_operations |= 0x20;
3847 nbOptionsChanged++;
3849 if((tcpd->mptcp_analysis->mp_operations&(0x40))!=tcph->th_mptcp->mh_fail) {
3850 tcpd->mptcp_analysis->mp_operations |= 0x40;
3851 nbOptionsChanged++;
3853 if((tcpd->mptcp_analysis->mp_operations&(0x80))!=tcph->th_mptcp->mh_fastclose) {
3854 tcpd->mptcp_analysis->mp_operations |= 0x80;
3855 nbOptionsChanged++;
3857 /* we could track MPTCP option changes here, with nbOptionsChanged */
3858 #endif
3860 item = proto_tree_add_uint(tree, hf_mptcp_stream, tvb, 0, 0, mptcpd->stream);
3861 proto_item_set_generated(item);
3863 /* retrieve saved analysis of packets, else create it */
3864 mptcppd = (mptcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mptcp, pinfo->curr_layer_num);
3865 if(!mptcppd) {
3866 mptcppd = (mptcp_per_packet_data_t *)wmem_new0(wmem_file_scope(), mptcp_per_packet_data_t);
3867 p_add_proto_data(wmem_file_scope(), pinfo, proto_mptcp, pinfo->curr_layer_num, mptcppd);
3870 /* Print formatted list of tcp stream ids that are part of the connection */
3871 mptcp_analysis_add_subflows(pinfo, tvb, tree, mptcpd);
3873 /* Converts TCP seq number into its MPTCP DSN */
3874 mptcp_analysis_dsn_lookup(pinfo, tvb, tree, tcpd, tcph, mptcppd);
3879 static void
3880 tcp_sequence_number_analysis_print_push_bytes_sent(packet_info * pinfo _U_,
3881 tvbuff_t * tvb,
3882 proto_tree * flags_tree,
3883 struct tcp_acked *ta
3886 proto_item * flags_item;
3888 if (tcp_track_bytes_in_flight) {
3889 flags_item=proto_tree_add_uint(flags_tree,
3890 hf_tcp_analysis_push_bytes_sent,
3891 tvb, 0, 0, ta->push_bytes_sent);
3893 proto_item_set_generated(flags_item);
3897 static void
3898 tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree,
3899 struct tcp_analysis *tcpd, uint32_t seq, uint32_t ack)
3901 struct tcp_acked *ta = NULL;
3902 proto_item *item;
3903 proto_tree *tree;
3904 proto_tree *flags_tree=NULL;
3906 if (!tcpd) {
3907 return;
3909 if(!tcpd->ta) {
3910 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, false, tcpd);
3912 ta=tcpd->ta;
3913 if(!ta) {
3914 return;
3917 item=proto_tree_add_item(parent_tree, hf_tcp_analysis, tvb, 0, 0, ENC_NA);
3918 proto_item_set_generated(item);
3919 tree=proto_item_add_subtree(item, ett_tcp_analysis);
3921 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
3922 data we actually have */
3923 if(ta->frame_acked) {
3926 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
3927 tvb, 0, 0, ta->frame_acked);
3928 proto_item_set_generated(item);
3930 if(ta->partial_ack) {
3931 expert_add_info(pinfo, item, &ei_tcp_analysis_partial_ack);
3934 if(ta->iskarn) {
3935 expert_add_info(pinfo, item, &ei_tcp_analysis_ambiguous_ack);
3938 /* only display RTT if we actually have something we are acking */
3939 if( ta->ts.secs || ta->ts.nsecs ) {
3940 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
3941 tvb, 0, 0, &ta->ts);
3942 proto_item_set_generated(item);
3945 if (!nstime_is_zero(&tcpd->ts_first_rtt)) {
3946 item = proto_tree_add_time(tree, hf_tcp_analysis_first_rtt,
3947 tvb, 0, 0, &(tcpd->ts_first_rtt));
3948 proto_item_set_generated(item);
3951 if(ta->bytes_in_flight) {
3952 /* print results for amount of data in flight */
3953 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta);
3954 tcp_sequence_number_analysis_print_push_bytes_sent(pinfo, tvb, tree, ta);
3957 if(ta->flags) {
3958 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, 0, ENC_NA);
3959 proto_item_set_generated(item);
3960 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);
3962 /* print results for reused tcp ports */
3963 tcp_sequence_number_analysis_print_reused(pinfo, item, ta);
3965 /* print results for retransmission and out-of-order segments */
3966 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, item, ta);
3968 /* print results for lost tcp segments */
3969 tcp_sequence_number_analysis_print_lost(pinfo, item, ta);
3971 /* print results for tcp window information */
3972 tcp_sequence_number_analysis_print_window(pinfo, item, ta);
3974 /* print results for tcp keep alive information */
3975 tcp_sequence_number_analysis_print_keepalive(pinfo, item, ta);
3977 /* print results for tcp duplicate acks */
3978 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);
3980 /* print results for tcp zero window */
3981 tcp_sequence_number_analysis_print_zero_window(pinfo, item, ta);
3987 static void
3988 print_tcp_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *tcp_tree, packet_info *pinfo, tvbuff_t *next_tvb)
3990 proto_item *tcp_tree_item, *frag_tree_item;
3993 * The subdissector thought it was completely
3994 * desegmented (although the stuff at the
3995 * end may, in turn, require desegmentation),
3996 * so we show a tree with all segments.
3998 show_fragment_tree(ipfd_head, &tcp_segment_items,
3999 tree, pinfo, next_tvb, &frag_tree_item);
4001 * The toplevel fragment subtree is now
4002 * behind all desegmented data; move it
4003 * right behind the TCP tree.
4005 tcp_tree_item = proto_tree_get_parent(tcp_tree);
4006 if(frag_tree_item && tcp_tree_item) {
4007 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);
4011 /* **************************************************************************
4012 * End of tcp sequence number analysis
4013 * **************************************************************************/
4016 /* Minimum TCP header length. */
4017 #define TCPH_MIN_LEN 20
4019 /* Desegmentation of TCP streams */
4021 /* The primary ID is the first frame of a multisegment PDU, which is
4022 * most likely unique in the capture (unlike sequence numbers which
4023 * can be re-used, especially when relative sequence numbers are enabled).
4024 * However, frames can have multiple PDUs with certain encapsulations like
4025 * GSE or MPE over DVB BaseBand Frames.
4028 typedef struct _tcp_endpoint {
4030 address src_addr;
4031 address dst_addr;
4032 port_type ptype;
4033 uint32_t src_port;
4034 uint32_t dst_port;
4035 } tcp_endpoint_t;
4037 static void
4038 save_endpoint(packet_info *pinfo, tcp_endpoint_t *a)
4040 copy_address_shallow(&a->src_addr, &pinfo->src);
4041 copy_address_shallow(&a->dst_addr, &pinfo->dst);
4042 a->ptype = pinfo->ptype;
4043 a->src_port = pinfo->srcport;
4044 a->dst_port = pinfo->destport;
4047 static void
4048 restore_endpoint(packet_info *pinfo, tcp_endpoint_t *a)
4050 copy_address_shallow(&pinfo->src, &a->src_addr);
4051 copy_address_shallow(&pinfo->dst, &a->dst_addr);
4052 pinfo->ptype = a->ptype;
4053 pinfo->srcport = a->src_port;
4054 pinfo->destport = a->dst_port;
4057 typedef struct _tcp_segment_key {
4058 address src_addr;
4059 address dst_addr;
4060 uint32_t src_port;
4061 uint32_t dst_port;
4062 uint32_t id; /* msp->first_frame */
4063 uint32_t seq; /* msp->seq */
4064 } tcp_segment_key;
4066 static unsigned
4067 tcp_segment_hash(const void *k)
4069 const tcp_segment_key* key = (const tcp_segment_key*) k;
4070 unsigned hash_val;
4072 hash_val = key->id;
4074 /* In most captures there is only one fragment per id / first_frame,
4075 so we only use it in the hash as an optimization.
4077 int i;
4078 for (i = 0; i < key->src.len; i++)
4079 hash_val += key->src_addr.data[i];
4080 for (i = 0; i < key->dst.len; i++)
4081 hash_val += key->dst_addr.data[i];
4082 hash_val += key->src_port;
4083 hash_val += key->dst_port;
4084 hash_val += key->seq;
4087 return hash_val;
4090 static int
4091 tcp_segment_equal(const void *k1, const void *k2)
4093 const tcp_segment_key* key1 = (const tcp_segment_key*) k1;
4094 const tcp_segment_key* key2 = (const tcp_segment_key*) k2;
4097 * key.id is the first item to compare since it's the item most
4098 * likely to differ between sessions, thus short-circuiting
4099 * the comparison of addresses and ports.
4101 return (key1->id == key2->id) &&
4102 (addresses_equal(&key1->src_addr, &key2->src_addr)) &&
4103 (addresses_equal(&key1->dst_addr, &key2->dst_addr)) &&
4104 (key1->src_port == key2->src_port) &&
4105 (key1->dst_port == key2->dst_port) &&
4106 (key1->seq == key2->seq);
4110 * Create a fragment key for temporary use; it can point to non-
4111 * persistent data, and so must only be used to look up and
4112 * delete entries, not to add them.
4114 static void *
4115 tcp_segment_temporary_key(const packet_info *pinfo, const uint32_t id,
4116 const void *data)
4118 struct tcp_multisegment_pdu *msp = (struct tcp_multisegment_pdu*)data;
4119 DISSECTOR_ASSERT(msp);
4120 tcp_segment_key *key = g_slice_new(tcp_segment_key);
4123 * Do a shallow copy of the addresses.
4125 copy_address_shallow(&key->src_addr, &pinfo->src);
4126 copy_address_shallow(&key->dst_addr, &pinfo->dst);
4127 key->src_port = pinfo->srcport;
4128 key->dst_port = pinfo->destport;
4129 key->id = id;
4130 key->seq = msp->seq;
4132 return (void *)key;
4136 * Create a fragment key for permanent use; it must point to persistent
4137 * data, so that it can be used to add entries.
4139 static void *
4140 tcp_segment_persistent_key(const packet_info *pinfo,
4141 const uint32_t id, const void *data)
4143 struct tcp_multisegment_pdu *msp = (struct tcp_multisegment_pdu*)data;
4144 DISSECTOR_ASSERT(msp);
4145 tcp_segment_key *key = g_slice_new(tcp_segment_key);
4148 * Do a deep copy of the addresses.
4150 copy_address(&key->src_addr, &pinfo->src);
4151 copy_address(&key->dst_addr, &pinfo->dst);
4152 key->src_port = pinfo->srcport;
4153 key->dst_port = pinfo->destport;
4154 key->id = id;
4155 key->seq = msp->seq;
4157 return (void *)key;
4160 static void
4161 tcp_segment_free_temporary_key(void *ptr)
4163 tcp_segment_key *key = (tcp_segment_key *)ptr;
4164 g_slice_free(tcp_segment_key, key);
4167 static void
4168 tcp_segment_free_persistent_key(void *ptr)
4170 tcp_segment_key *key = (tcp_segment_key *)ptr;
4172 if(key){
4174 * Free up the copies of the addresses from the old key.
4176 free_address(&key->src_addr);
4177 free_address(&key->dst_addr);
4179 g_slice_free(tcp_segment_key, key);
4183 const reassembly_table_functions
4184 tcp_reassembly_table_functions = {
4185 tcp_segment_hash,
4186 tcp_segment_equal,
4187 tcp_segment_temporary_key,
4188 tcp_segment_persistent_key,
4189 tcp_segment_free_temporary_key,
4190 tcp_segment_free_persistent_key
4193 static reassembly_table tcp_reassembly_table;
4195 /* functions to trace tcp segments */
4196 /* Enable desegmenting of TCP streams */
4197 static bool tcp_desegment = true;
4199 /* Returns the maximum contiguous sequence number of the reassembly associated
4200 * with the msp *if* a new fragment were added ending in the given maxnextseq.
4201 * The new fragment is from the current frame and may not have been added yet.
4203 static uint32_t
4204 find_maxnextseq(packet_info *pinfo, struct tcp_multisegment_pdu *msp, uint32_t maxnextseq)
4206 fragment_head *fd_head;
4208 DISSECTOR_ASSERT(msp);
4210 fd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
4211 /* msp implies existence of fragments, this should never be NULL. */
4212 DISSECTOR_ASSERT(fd_head);
4214 /* Find length of contiguous fragments.
4215 * Start with the first gap, but the new fragment is allowed to
4216 * fill that gap. */
4217 uint32_t max_len = maxnextseq - msp->seq;
4218 fragment_item* frag = (fd_head->first_gap) ? fd_head->first_gap : fd_head->next;
4219 for (; frag && frag->offset <= max_len; frag = frag->next) {
4220 max_len = MAX(max_len, frag->offset + frag->len);
4223 return max_len + msp->seq;
4226 static struct tcp_multisegment_pdu*
4227 split_msp(packet_info *pinfo, struct tcp_multisegment_pdu *msp, struct tcp_analysis *tcpd)
4229 fragment_head *fd_head;
4230 uint32_t first_frame = 0;
4231 uint32_t last_frame = 0;
4232 const uint32_t split_offset = pinfo->desegment_offset;
4234 fd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
4235 /* This is for splitting defragmented MSPs, so fd_head should exist
4236 * and be defragmented. This also ensures that fd_i->tvb_data exists.
4238 DISSECTOR_ASSERT(fd_head && fd_head->flags & FD_DEFRAGMENTED);
4240 fragment_item *fd_i, *first_frag = NULL;
4242 /* The fragment list is sorted in offset order, but not nec. frame order
4243 * or end offset order due to out of order reassembly and possible overlap.
4244 * fd_i->offset < split_offset - some bytes are before the split
4245 * fd_i->offset + fd_i->len >= split_offset - some bytes are after split
4246 * Look through all the fragments that have some data before the split point.
4248 for (fd_i = fd_head->next; fd_i && (fd_i->offset < split_offset); fd_i = fd_i->next) {
4249 if (last_frame < fd_i->frame) {
4250 last_frame = fd_i->frame;
4252 if (fd_i->offset + fd_i->len >= split_offset) {
4253 if (first_frag == NULL) {
4254 first_frag = fd_i;
4255 first_frame = fd_i->frame;
4256 } else if (fd_i->frame < first_frame) {
4257 first_frame = fd_i->frame;
4262 /* Now look through all the remaining fragments that only have bytes after
4263 * the split.
4265 for (; fd_i; fd_i = fd_i->next) {
4266 uint32_t frag_end = fd_i->offset + fd_i->len;
4267 if (split_offset <= frag_end && fd_i->frame < first_frame) {
4268 first_frame = fd_i->frame;
4272 /* We only call this when the frame the fragments were reassembled in
4273 * (which is the current frame) includes some data before the split
4274 * point, so that it won't change and we can be consistent dissecting
4275 * between passes. We also should have at least some data after the
4276 * split point (because the subdissector claimed there was undissected
4277 * data.)
4279 DISSECTOR_ASSERT(fd_head->reassembled_in == last_frame);
4280 DISSECTOR_ASSERT(first_frag != NULL);
4282 uint32_t new_seq = msp->seq + pinfo->desegment_offset;
4283 struct tcp_multisegment_pdu *newmsp;
4284 newmsp = pdu_store_sequencenumber_of_next_pdu(pinfo, new_seq,
4285 new_seq+1, tcpd->fwd->multisegment_pdus);
4286 newmsp->first_frame = first_frame;
4287 newmsp->nxtpdu = msp->nxtpdu;
4289 /* XXX: Could do the adding the new fragments in fragment_truncate */
4290 for (fd_i = first_frag; fd_i; fd_i = fd_i->next) {
4291 uint32_t frag_offset = fd_i->offset;
4292 uint32_t frag_len = fd_i->len;
4293 /* Check for some unusual out of order overlapping segment situations. */
4294 if (split_offset < frag_offset + frag_len) {
4295 if (fd_i->offset < split_offset) {
4296 frag_offset = split_offset;
4297 frag_len -= (split_offset - fd_i->offset);
4299 fragment_add_out_of_order(&tcp_reassembly_table, fd_head->tvb_data,
4300 frag_offset, pinfo, first_frame, newmsp,
4301 frag_offset - split_offset, frag_len, true, fd_i->frame);
4305 fragment_truncate(&tcp_reassembly_table, pinfo, msp->first_frame, msp, split_offset);
4306 msp->nxtpdu = msp->seq + split_offset;
4308 /* The newmsp nxtpdu will be adjusted after leaving this function. */
4309 return newmsp;
4312 typedef struct _ooo_segment_item {
4313 uint32_t frame;
4314 uint32_t seq;
4315 uint32_t len;
4316 uint8_t *data;
4317 } ooo_segment_item;
4319 static int
4320 compare_ooo_segment_item(const void *a, const void *b)
4322 const ooo_segment_item *fd_a = a;
4323 const ooo_segment_item *fd_b = b;
4325 /* We only insert segments into this list that satisfy
4326 * LT_SEQ(tcpd->fwd->maxnextseq, seq), for the current value
4327 * of maxnextseq (removing segments when maxnextseq is advanced)
4328 * so these rollover-aware comparisons are transitive over the
4329 * domain (never greater than 2^31).
4331 if (LT_SEQ(fd_a->seq, fd_b->seq))
4332 return -1;
4334 if (GT_SEQ(fd_a->seq, fd_b->seq))
4335 return 1;
4337 if (fd_a->frame < fd_b->frame)
4338 return -1;
4340 if (fd_a->frame > fd_b->frame)
4341 return 1;
4343 return 0;
4346 /* Search through our list of out of order segments and add the ones that are
4347 * now contiguous onto a MSP until we use them all or reach another gap.
4349 * If the MSP parameter is a incomplete, returns it with any OOO segments added.
4350 * If the MSP parameter is NULL or complete, returns a newly created MSP with
4351 * OOO segments added, or NULL if there were no segments to add.
4353 static struct tcp_multisegment_pdu *
4354 msp_add_out_of_order(packet_info *pinfo, struct tcp_multisegment_pdu *msp, struct tcp_analysis *tcpd, uint32_t seq)
4357 /* Whether a previous MSP exists with missing segments. */
4358 bool has_unfinished_msp = msp && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS);
4359 bool updated_maxnextseq = false;
4361 if (msp) {
4362 uint32_t maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);
4363 if (LE_SEQ(tcpd->fwd->maxnextseq, maxnextseq)) {
4364 tcpd->fwd->maxnextseq = maxnextseq;
4366 updated_maxnextseq = true;
4368 wmem_list_frame_t *curr_entry;
4369 curr_entry = wmem_list_head(tcpd->fwd->ooo_segments);
4370 ooo_segment_item *fd;
4371 tvbuff_t *tvb_data;
4372 while (curr_entry) {
4373 fd = (ooo_segment_item *)wmem_list_frame_data(curr_entry);
4374 if (LT_SEQ(tcpd->fwd->maxnextseq, fd->seq)) {
4375 /* There might be segments already added to the msp that now extend
4376 * the maximum contiguous sequence number. Check for them. */
4377 if (msp && !updated_maxnextseq) {
4378 tcpd->fwd->maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);
4379 updated_maxnextseq = true;
4381 if (LT_SEQ(tcpd->fwd->maxnextseq, fd->seq)) {
4382 break;
4385 /* We have filled in the gap, so this out of order
4386 * segment is now contiguous and can be processed along
4387 * with the segment we just received.
4389 tcpd->fwd->maxnextseq = fd->seq + fd->len;
4390 tvb_data = tvb_new_real_data(fd->data, fd->len, fd->len);
4391 if (has_unfinished_msp) {
4393 /* Increase the expected MSP size if necessary. Yes, the
4394 * subdissector may have told us that a PDU ended here, but we
4395 * might have enough newly contiguous data to dissect another
4396 * PDU past that, and we should send that to the subdissector
4397 * too. */
4398 if (LT_SEQ(msp->nxtpdu, fd->seq + fd->len)) {
4399 msp->nxtpdu = fd->seq + fd->len;
4401 /* Add this OOO segment to the unfinished MSP */
4402 fragment_add_out_of_order(&tcp_reassembly_table,
4403 tvb_data, 0,
4404 pinfo, msp->first_frame, msp,
4405 fd->seq - msp->seq, fd->len,
4406 msp->nxtpdu, fd->frame);
4407 } else {
4408 /* No MSP in progress, so create one starting
4409 * at the sequence number of segment received
4410 * in this frame. Note that we will be adding
4411 * the first segment below, and this is the frame
4412 * of the first segment, so first_frame_with_seq
4413 * is already correct (and unnecessary) and
4414 * we don't need MSP_FLAGS_MISSING_FIRST_SEGMENT. */
4415 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
4416 seq, fd->seq + fd->len,
4417 tcpd->fwd->multisegment_pdus);
4418 fragment_add_out_of_order(&tcp_reassembly_table,
4419 tvb_data, 0, pinfo, msp->first_frame,
4420 msp, fd->seq - msp->seq, fd->len,
4421 msp->nxtpdu, fd->frame);
4422 has_unfinished_msp = true;
4424 updated_maxnextseq = false;
4425 tvb_free(tvb_data);
4426 wmem_list_remove_frame(tcpd->fwd->ooo_segments, curr_entry);
4427 curr_entry = wmem_list_head(tcpd->fwd->ooo_segments);
4430 /* There might be segments already added to the msp that now extend
4431 * the maximum contiguous sequence number. Check for them. */
4432 if (msp && !updated_maxnextseq) {
4433 tcpd->fwd->maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);
4435 return msp;
4438 static void
4439 desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
4440 uint32_t seq, uint32_t nxtseq,
4441 uint32_t sport, uint32_t dport,
4442 proto_tree *tree, proto_tree *tcp_tree,
4443 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
4445 fragment_head *ipfd_head;
4446 int last_fragment_len;
4447 bool must_desegment;
4448 bool called_dissector;
4449 bool has_gap;
4450 int another_pdu_follows;
4451 int deseg_offset;
4452 uint32_t deseg_seq;
4453 int nbytes;
4454 proto_item *item;
4455 struct tcp_multisegment_pdu *msp;
4456 bool cleared_writable = col_get_writable(pinfo->cinfo, COL_PROTOCOL);
4457 bool first_pdu = true;
4458 const bool reassemble_ooo = tcp_analyze_seq && tcp_desegment && tcp_reassemble_out_of_order && tcpd && tcpd->fwd->ooo_segments;
4460 tcp_endpoint_t orig_endpoint, new_endpoint;
4462 save_endpoint(pinfo, &orig_endpoint);
4463 save_endpoint(pinfo, &new_endpoint);
4465 again:
4466 ipfd_head = NULL;
4467 last_fragment_len = 0;
4468 must_desegment = false;
4469 called_dissector = false;
4470 has_gap = false;
4471 another_pdu_follows = 0;
4472 msp = NULL;
4475 * Initialize these to assume no desegmentation.
4476 * If that's not the case, these will be set appropriately
4477 * by the subdissector.
4479 pinfo->desegment_offset = 0;
4480 pinfo->desegment_len = 0;
4483 * Initialize this to assume that this segment will just be
4484 * added to the middle of a desegmented chunk of data, so
4485 * that we should show it all as data.
4486 * If that's not the case, it will be set appropriately.
4488 deseg_offset = offset;
4491 * TODO: Some notes on current limitations with TCP desegmentation:
4493 * This function can be called with either relative or absolute sequence
4494 * numbers; the ??_SEQ macros are called for comparisons to deal with
4495 * with sequence number rollover. (With relative sequence numbers, if
4496 * early TCP segments are received out of order before the SYN it can be
4497 * possible for rollover to occur at the very beginning of a connection.)
4499 * However, multi-segment PDU lookup does not work for MSPs that span
4500 * TCP sequence number rollover, and desegmentation fails.
4502 * When there is a single TCP connection that is longer than 4 GiB and
4503 * thus sequence numbers are reused, multi-segment PDU lookup and
4504 * retransmission identification does not work. (Bug 10503).
4506 * Distinguishing between sequence number reuse on a very long connection
4507 * and sequence number reuse due to retransmission is difficult. Right
4508 * now very long connections are just not handled as the rarer case.
4509 * Perhaps retransmission identification could be entirely left up to TCP
4510 * analysis (if enabled, not done at all if disabled), instead of TCP
4511 * analysis results only used to supplement work here?
4513 * TCP sequence analysis can set TCP_A_RETRANSMISSION in cases where
4514 * we still need to process the segment anyway because something other
4515 * than the sequence number is different from the prior segment. That
4516 * includes "retransmitted but with additional data" (Bug 13523) and
4517 * "retransmitted due to bad checksum" (especially if checksum verification
4518 * is enabled.)
4520 * "Reassemble out-of-order segments" uses its own method of detecting
4521 * retranmission, but uses more memory and CPU, and when used, a TCP stream
4522 * that has missing segments that are never retransmitted stop processing
4523 * after the missing segment.
4525 * If multiple TCP/IP packets are encapsulated in the same frame (such
4526 * as with GSE, which has very long Baseband Frames) this causes issues:
4528 * If a subdissector reports that it can handle a payload, but needs
4529 * more data (pinfo->desegment_len > 0) and did not actually dissect
4530 * any of it (pinfo->desegment_offset == 0), on the first pass it
4531 * still adds layers to the frame. On subsequent passes, the MSP created
4532 * (or extended) in the first pass means that the subdissector won't be
4533 * called at all. If there are other protocols contained in the frame
4534 * that are dissected on the second pass they will have different
4535 * layer numbers than in the first pass, which can disturb proto_data
4536 * lookup, reassembly, etc. (Bug 16109 describes this for TLS.)
4539 if (tcpd) {
4541 if (reassemble_ooo) {
4542 /* If we are reassembling out of order, we can do this retransmission
4543 * check. Anything before the latest consecutive sequence number we've
4544 * already processed is a retransmission (from the perspective of has
4545 * been passed to subdissectors; the judgment of TCP Sequence Analysis
4546 * may be different, because it considers RTO and ACKs and so forth).
4548 * XXX: If these segments are part of incomplete MSPs, we pass them
4549 * to the reassembly code which tests for overlap conflicts.
4550 * For those which are part of completed reassemblies or not part
4551 * of MSPs, we just don't process them. The former would throw a
4552 * ReassemblyError, which is likely acceptable in the case of
4553 * retransmission of the same segment but not if retransmitted with
4554 * additional data, where we'd need to catch the exception to
4555 * process the extra data. For ones that were not added to MSPs at
4556 * all, we can't do much. (Bug #13061)
4558 * Retransmissions of out of order segments after our latest
4559 * consecutive sequence number will all be stored and then eventually
4560 * put on multisegment PDUs and go to the reassembler, which should
4561 * be able to handle retransmission, as those are still incomplete.
4564 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq);
4566 bool has_unfinished_msp = false;
4567 if (msp && LE_SEQ(msp->seq, seq) && GT_SEQ(msp->nxtpdu, seq) && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS)) {
4568 has_unfinished_msp = true;
4571 if (!PINFO_FD_VISITED(pinfo) && first_pdu) {
4572 if (tcpd->fwd->maxnextseq && LT_SEQ(seq, tcpd->fwd->maxnextseq) && !has_unfinished_msp) {
4573 if(!tcpd->ta) {
4574 tcp_analyze_get_acked_struct(pinfo->num, seq, tcpinfo->lastackseq, true, tcpd);
4576 tcpd->ta->flags |= TCP_A_OLD_DATA;
4577 if (GT_SEQ(nxtseq, tcpd->fwd->maxnextseq)) {
4578 tcpd->ta->new_data_seq = tcpd->fwd->maxnextseq;
4579 } else {
4580 tcpd->ta->new_data_seq = nxtseq;
4585 if(tcpd->ta && first_pdu) {
4586 if(tcpd->ta->flags&TCP_A_KEEP_ALIVE) {
4587 /* RFC 9293 3.8.4. TCP Keep-Alives
4588 * Keep-alive packets MUST only be sent when no sent data
4589 * is outstanding (no new or unacknowledged data.)
4590 * A multisegment PDU boundary can never span a keep-alive
4591 * (unlike a Zero Window Probe or retransmission); if
4592 * a MSP started at the same sequence number as this, then
4593 * most likely the first packet of the TCP stream seen was
4594 * also a keep-alive, couldn't be identified as one, and
4595 * was passed to the next dissector which treated it as
4596 * starting a MSP. (#20287)
4598 * This unfortunately doesn't help if this is somehow
4599 * a one-octet retransmission instead of a keep-alive.
4601 nbytes = tvb_reported_length_remaining(tvb, offset);
4602 /* This MUST be only 1 (we don't get here for zero). */
4603 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb,
4604 offset, nbytes, NULL,
4605 "TCP keep-alive garbage octet%s",
4606 plurality(nbytes, "", "s"));
4607 if (has_unfinished_msp && msp->seq == seq) {
4608 /* MSPs cannot span this (probably not an MSP at
4609 * all but another garbage octet) */
4610 msp->nxtpdu = nxtseq;
4612 goto clean_exit;
4615 if((tcpd->ta->flags&TCP_A_OLD_DATA) == TCP_A_OLD_DATA) {
4616 nbytes = tcpd->ta->new_data_seq - seq;
4618 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb,
4619 offset, nbytes, NULL,
4620 "Retransmitted TCP segment data (%u byte%s)",
4621 nbytes, plurality(nbytes, "", "s"));
4623 offset += nbytes;
4624 seq = tcpd->ta->new_data_seq;
4625 first_pdu = false;
4626 if (tvb_captured_length_remaining(tvb, offset) > 0)
4627 goto again;
4628 goto clean_exit;
4631 } else {
4633 /* Have we seen this PDU before (and is it the start of a multi-
4634 * segment PDU)?
4636 * If the sequence number was seen before, it is part of a
4637 * retransmission if the whole segment fits within the MSP.
4638 * (But if this is this frame was already visited and the first frame of
4639 * the MSP matches the current frame, then it is not a retransmission,
4640 * but the start of a new MSP.)
4642 * If only part of the segment fits in the MSP, then either:
4643 * - The previous segment included with the MSP was a Zero Window Probe
4644 * with one byte of data and the subdissector just asked for one more
4645 * byte. Do not mark it as retransmission (Bug 15427).
4646 * - Data was actually being retransmitted, but with additional data
4647 * (Bug 13523). Do not mark it as retransmission to handle the extra
4648 * bytes. (NOTE Due to the TCP_A_RETRANSMISSION check below, such
4649 * extra data will still be ignored.)
4650 * - The MSP contains multiple segments, but the subdissector finished
4651 * reassembly using a subset of the final segment (thus "msp->nxtpdu"
4652 * is smaller than the nxtseq of the previous segment). If that final
4653 * segment was retransmitted, then "nxtseq > msp->nxtpdu".
4654 * Unfortunately that will *not* be marked as retransmission here.
4655 * The next TCP_A_RETRANSMISSION hopefully takes care of it though.
4657 * Only shortcircuit here when the first segment of the MSP is known,
4658 * and when this first segment is not one to complete the MSP.
4660 if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, seq)) &&
4661 nxtseq <= msp->nxtpdu &&
4662 !(msp->flags & MSP_FLAGS_MISSING_FIRST_SEGMENT) && msp->last_frame != pinfo->num) {
4663 const char* str;
4664 bool is_retransmission = false;
4666 if(tcpd->ta && tcpd->ta->flags&TCP_A_KEEP_ALIVE) {
4667 /* Same logic as in the OOO processing case. */
4668 nbytes = tvb_reported_length_remaining(tvb, offset);
4669 /* This MUST be only 1 (we don't get here for zero). */
4670 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb,
4671 offset, nbytes, NULL,
4672 "TCP keep-alive garbage octet%s",
4673 plurality(nbytes, "", "s"));
4674 msp->nxtpdu = nxtseq;
4675 goto clean_exit;
4678 /* Yes. This could be because we've dissected this frame before
4679 * or because this is a retransmission of a previously-seen
4680 * segment. Either way, we don't need to hand it off to the
4681 * subdissector and we certainly don't want to re-add it to the
4682 * multisegment_pdus list: if we did, subsequent lookups would
4683 * find this retransmission instead of the original transmission
4684 * (breaking desegmentation if we'd already linked other segments
4685 * to the original transmission's entry).
4687 * Cases to handle here:
4688 * - In-order stream, pinfo->num matches begin of MSP.
4689 * - In-order stream, but pinfo->num does not match the begin of the
4690 * MSP. Must be a retransmission.
4691 * - OoO stream where this segment fills the gap in the begin of the
4692 * MSP. msp->first_frame is the start where the gap was detected
4693 * (and does NOT match pinfo->num).
4696 if (msp->first_frame == pinfo->num || msp->first_frame_with_seq == pinfo->num) {
4697 str = "";
4698 } else {
4699 str = "Retransmitted ";
4700 is_retransmission = true;
4701 /* TCP analysis already flags this (in COL_INFO) as a retransmission--if it's enabled */
4704 /* Fix for bug 3264: look up ipfd for this (first) segment,
4705 so can add tcp.reassembled_in generated field on this code path. */
4706 if (!is_retransmission) {
4707 ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
4708 if (ipfd_head) {
4709 if (ipfd_head->reassembled_in != 0) {
4710 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,
4711 0, ipfd_head->reassembled_in);
4712 proto_item_set_generated(item);
4714 if (first_pdu) {
4715 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[TCP PDU reassembled in %u]",
4716 ipfd_head->reassembled_in);
4722 nbytes = tvb_reported_length_remaining(tvb, offset);
4724 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
4725 nbytes, NULL, "%sTCP segment data (%u byte%s)", str, nbytes,
4726 plurality(nbytes, "", "s"));
4727 goto clean_exit;
4730 /* Else, find the most previous PDU starting before this sequence number */
4731 if (!msp) {
4732 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);
4735 bool has_unfinished_msp = false;
4736 if (msp && LE_SEQ(msp->seq, seq) && GT_SEQ(msp->nxtpdu, seq) && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS)) {
4737 has_unfinished_msp = true;
4740 /* The above code only finds retransmission if the PDU boundaries and the seq coincide
4741 * If we have sequence analysis active use the TCP_A_RETRANSMISSION flag.
4742 * XXXX Could the above code be improved?
4744 if(tcpd->ta) {
4745 /* If we have an unfinished MSP that this segment belongs to
4746 * or if the sequence number is newer than anything we've seen,
4747 * then this is Out of Order from the reassembly perspective
4748 * and we want to process it anyway.
4750 if (!PINFO_FD_VISITED(pinfo) && tcpd->fwd->maxnextseq && LE_SEQ(seq, tcpd->fwd->maxnextseq) && !has_unfinished_msp) {
4751 /* Otherwise, if TCP Analysis calls the segment a
4752 * Spurious Retransmission or Retransmission, ignore it
4753 * here and on future passes.
4754 * See issue 10289
4755 * XXX: There are still some cases where TCP Analysis
4756 * marks segments as Retransmissions when they are
4757 * Out of Order from this perspective (#10725, #13843)
4759 if((tcpd->ta->flags&TCP_A_SPURIOUS_RETRANSMISSION) == TCP_A_SPURIOUS_RETRANSMISSION ||
4760 (tcpd->ta->flags & TCP_A_RETRANSMISSION) == TCP_A_RETRANSMISSION ||
4761 (tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION) == TCP_A_FAST_RETRANSMISSION) {
4762 tcpd->ta->flags |= TCP_A_OLD_DATA;
4765 if((tcpd->ta->flags&TCP_A_OLD_DATA) == TCP_A_OLD_DATA) {
4766 const char* str = "Retransmitted ";
4767 nbytes = tvb_reported_length_remaining(tvb, offset);
4768 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
4769 nbytes, NULL, "%sTCP segment data (%u byte%s)", str, nbytes,
4770 plurality(nbytes, "", "s"));
4771 goto clean_exit;
4777 if (reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN)) {
4778 if (!PINFO_FD_VISITED(pinfo)) {
4779 /* If there is a gap between this segment and any previous ones
4780 * (that is, seqno is larger than the maximum expected seqno), then
4781 * it is possibly an out-of-order segment. The very first segment
4782 * is expected to be in-order though (otherwise captures starting
4783 * in midst of a connection would never be reassembled).
4784 * (maxnextseq is 0 if we have not seen a SYN packet, even with
4785 * absolute sequence numbers.)
4787 * Do not bother checking for OoO segments for streams that are
4788 * reassembled at FIN, the order of segments before FIN does not
4789 * matter as reordering and reassembly occurs at FIN.
4792 if (tcpd->fwd->maxnextseq) {
4793 /* Segments may be missing due to packet loss (assume later
4794 * retransmission) or out-of-order (assume it appears later).
4796 * XXX: It would be nice to handle captures that have both
4797 * out-of-order packets and some lost packets that are
4798 * never retransmitted. But using the reverse flow ACK
4799 * (like follow_tcp_tap_listener) or using a known end of
4800 * a MSP (that we haven't fully received yet) to process a
4801 * segment that starts right afterwards would both break the
4802 * promise of in-order delivery, if a missing packet did arrive
4803 * later, which is a problem for any state-based dissector
4804 * (including TLS.)
4807 /* Whether the new segment has a gap from our latest contiguous
4808 * sequence number. */
4809 has_gap = LT_SEQ(tcpd->fwd->maxnextseq, seq);
4812 if (!has_gap) {
4813 /* Update the maximum expected seqno if no SYN packet was seen
4814 * before, or if the new segment succeeds previous segments. */
4815 tcpd->fwd->maxnextseq = nxtseq;
4817 /* If there is no gap, look for any OOO packets that are now
4818 * contiguous. */
4819 msp = msp_add_out_of_order(pinfo, msp, tcpd, seq);
4821 } else {
4822 /* If we have visited this frame before, look for the frame in the
4823 * list of unused out of order segments. Since we know the gap will
4824 * never be filled, we could pass it to the subdissector, but
4825 * we want to be consistent between passes.
4827 ooo_segment_item *fd;
4828 fd = wmem_new0(pinfo->pool, ooo_segment_item);
4829 fd->frame = pinfo->num;
4830 fd->seq = seq;
4831 fd->len = nxtseq - seq;
4832 if (wmem_list_find_custom(tcpd->fwd->ooo_segments, fd, compare_ooo_segment_item)) {
4833 has_gap = true;
4838 /* If we are not processing out of order, update the max nextseq value if
4839 * is later than our current value (or our first value.)
4841 if (!reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN)) {
4842 if (!PINFO_FD_VISITED(pinfo)) {
4843 if (LT_SEQ(tcpd->fwd->maxnextseq, nxtseq) || tcpd->fwd->maxnextseq == 0) {
4844 tcpd->fwd->maxnextseq = nxtseq;
4849 if (msp && LE_SEQ(msp->seq, seq) && GT_SEQ(msp->nxtpdu, seq)) {
4850 int len;
4852 if (!PINFO_FD_VISITED(pinfo)) {
4853 msp->last_frame=pinfo->num;
4854 msp->last_frame_time=pinfo->abs_ts;
4857 /* OK, this PDU was found, which means the segment continues
4858 * a higher-level PDU and that we must desegment it.
4860 if (msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
4861 /* The dissector asked for the entire segment */
4862 len = tvb_captured_length_remaining(tvb, offset);
4863 } else {
4864 /* Wraparound is possible, so subtraction does not
4865 * distribute across MIN(x, y)
4867 len = MIN(nxtseq - seq, msp->nxtpdu - seq);
4869 last_fragment_len = len;
4872 if (reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN)) {
4874 * If the previous segment requested more data (setting
4875 * FD_PARTIAL_REASSEMBLY as the next segment length is unknown), but
4876 * subsequently an OoO segment was received (for an earlier hole),
4877 * then "fragment_add" would truncate the reassembled PDU to the end
4878 * of this OoO segment. To prevent that, explicitly specify the MSP
4879 * length before calling "fragment_add".
4881 * When a subdissector requests reassembly at the end of the
4882 * connection (DESEGMENT_UNTIL_FIN), then it is not
4883 * possible for an earlier segment to complete reassembly
4884 * (more_frags for fragment_add is always true). Thus we do not
4885 * have to worry about increasing the fragment length here.
4887 fragment_reset_tot_len(&tcp_reassembly_table, pinfo,
4888 msp->first_frame, msp,
4889 MAX(seq + len, msp->nxtpdu) - msp->seq);
4892 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,
4893 pinfo, msp->first_frame, msp,
4894 seq - msp->seq, len,
4895 (LT_SEQ (nxtseq,msp->nxtpdu)) );
4897 if (!PINFO_FD_VISITED(pinfo) && ipfd_head
4898 && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
4899 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
4901 /* If we consumed the entire segment there is no
4902 * other pdu starting anywhere inside this segment.
4903 * So update nxtpdu to point at least to the start
4904 * of the next segment.
4905 * (If the subdissector asks for even more data we
4906 * will advance nxtpdu even further later down in
4907 * the code.)
4909 if (LT_SEQ(msp->nxtpdu, nxtseq)) {
4910 msp->nxtpdu = nxtseq;
4914 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)) {
4915 /* Remember when all segments are ready to avoid subsequent
4916 * out-of-order packets from extending this MSP. If a subsdissector
4917 * needs more segments, the flag will be cleared below. */
4918 if (ipfd_head) {
4919 msp->flags |= MSP_FLAGS_GOT_ALL_SEGMENTS;
4923 if( (msp->nxtpdu < nxtseq)
4924 && (msp->nxtpdu >= seq)
4925 && (len > 0)) {
4926 another_pdu_follows=msp->nxtpdu - seq;
4928 } else if (has_gap) {
4929 /* This is an OOO segment with a gap and past the known end of
4930 * the current MSP, if any. We don't know for certain which MSP
4931 * it belongs to, and the reassembly functions don't let us remove
4932 * fragment items added by mistake. Keep it around in a separate
4933 * structure, and add it later.
4935 * On the second and later passes, we know that this gap will
4936 * never be filled in, so we could hand the segment to the
4937 * subdissector anyway. However, we want dissection to be
4938 * consistent between passes.
4940 if (!PINFO_FD_VISITED(pinfo)) {
4941 ooo_segment_item *fd;
4942 fd = wmem_new0(wmem_file_scope(), ooo_segment_item);
4943 fd->frame = pinfo->num;
4944 fd->seq = seq;
4945 fd->len = nxtseq - seq;
4946 /* We only enter here if dissect_tcp set can_desegment,
4947 * which means that these bytes exist. */
4948 fd->data = tvb_memdup(wmem_file_scope(), tvb, offset, fd->len);
4949 wmem_list_append_sorted(tcpd->fwd->ooo_segments, fd, compare_ooo_segment_item);
4951 ipfd_head = NULL;
4952 } else {
4953 /* This segment was not found in our table, so it doesn't
4954 * contain a continuation of a higher-level PDU.
4955 * Call the normal subdissector.
4959 * Supply the sequence number of this segment. We set this here
4960 * because this segment could be after another in the same packet,
4961 * in which case seq was incremented at the end of the loop.
4963 tcpinfo->seq = seq;
4965 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
4966 sport, dport, 0, 0, false, tcpd, tcpinfo);
4968 /* Unless it failed to dissect any data at all, the subdissector
4969 * might have changed the addresses and/or ports. Save them, and
4970 * set them back to the original values temporarily so that the
4971 * fragment functions work correctly (including in any later PDU.)
4973 * (If we didn't dissect any data, the subdissector *shouldn't*
4974 * have changed the addresses or ports, so don't save them, but
4975 * restore them just in case.)
4977 if (!(pinfo->desegment_len && pinfo->desegment_offset == 0)) {
4978 save_endpoint(pinfo, &new_endpoint);
4980 restore_endpoint(pinfo, &orig_endpoint);
4981 called_dissector = true;
4983 /* Did the subdissector ask us to desegment some more data
4984 * before it could handle the packet?
4985 * If so we'll have to handle that later.
4987 if(pinfo->desegment_len) {
4988 must_desegment = true;
4991 * Set "deseg_offset" to the offset in "tvb"
4992 * of the first byte of data that the
4993 * subdissector didn't process.
4995 deseg_offset = offset + pinfo->desegment_offset;
4998 /* Either no desegmentation is necessary, or this is
4999 * segment contains the beginning but not the end of
5000 * a higher-level PDU and thus isn't completely
5001 * desegmented.
5003 ipfd_head = NULL;
5007 /* is it completely desegmented? */
5008 if (ipfd_head) {
5010 * Yes, we think it is.
5011 * We only call subdissector for the last segment.
5012 * Note that the last segment may include more than what
5013 * we needed.
5015 if (ipfd_head->reassembled_in == pinfo->num && ipfd_head->reas_in_layer_num == pinfo->curr_layer_num) {
5017 * OK, this is the last segment.
5018 * Let's call the subdissector with the desegmented
5019 * data.
5021 tvbuff_t *next_tvb;
5023 /* create a new TVB structure for desegmented data */
5024 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
5026 /* add desegmented data to the data source list */
5027 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
5030 * Supply the sequence number of the first of the
5031 * reassembled bytes.
5033 tcpinfo->seq = msp->seq;
5035 /* indicate that this is reassembled data */
5036 tcpinfo->is_reassembled = true;
5038 /* call subdissector */
5039 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, sport,
5040 dport, 0, 0, false, tcpd, tcpinfo);
5042 /* Unless it failed to dissect any data at all, the subdissector
5043 * might have changed the addresses and/or ports. Save them, and
5044 * set them back to the original values temporarily so that the
5045 * fragment functions work correctly (including in any later PDU.)
5047 * (If we didn't dissect any data, the subdissector *shouldn't*
5048 * have changed the addresses or ports, so don't save them, but
5049 * restore them just in case.)
5051 if (!(pinfo->desegment_len && pinfo->desegment_offset == 0)) {
5052 save_endpoint(pinfo, &new_endpoint);
5054 restore_endpoint(pinfo, &orig_endpoint);
5055 called_dissector = true;
5058 * OK, did the subdissector think it was completely
5059 * desegmented, or does it think we need even more
5060 * data?
5062 if (pinfo->desegment_len) {
5064 * "desegment_len" isn't 0, so it needs more data
5065 * to fully dissect the current MSP. msp->nxtpdu was
5066 * not accurate and needs to be updated.
5068 * This can happen if a dissector asked for one
5069 * more segment (but didn't know exactly how much data)
5070 * or if segments were added out of order.
5072 * This is opposed to the current MSP being completely
5073 * desegmented, but the stuff at the end of the
5074 * current frame past last_fragment_len starting a new
5075 * higher-level PDU that may also need desegmentation.
5076 * That case is handled on the next loop.
5078 * We want to keep the same dissection and protocol layer
5079 * numbers on subsequent passes.
5081 * If "desegment_offset" is 0, then nothing in the reassembled
5082 * TCP segments was dissected, so remove the data source.
5084 if (pinfo->desegment_offset == 0) {
5085 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)) {
5086 msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS;
5088 remove_last_data_source(pinfo);
5089 fragment_set_partial_reassembly(&tcp_reassembly_table,
5090 pinfo, msp->first_frame,
5091 msp);
5092 } else {
5093 /* If "desegment_offset" is not 0, then a PDU in the
5094 * reassembled segments was dissected, but some stuff
5095 * that was added previously is part of a later PDU.
5097 if (LE_SEQ(msp->seq + pinfo->desegment_offset, seq)) {
5098 /* If we don't use anything from the current frame's
5099 * segment, then we can't split the msp. The frames of
5100 * the earlier PDU weren't reassembled until now, so
5101 * they need to point to a reassembled_in frame here
5102 * or later.
5104 * Since this segment is the first of newly contiguous
5105 * segments, this means the subdissector is asking for
5106 * fewer bytes than it did before.
5107 * XXX: Report this as a dissector bug?
5109 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)) {
5110 msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS;
5112 fragment_set_partial_reassembly(&tcp_reassembly_table,
5113 pinfo, msp->first_frame,
5114 msp);
5115 } else {
5116 /* If we did use bytes from the current segment, then
5117 * we want to split the MSP; the earlier part is
5118 * dissected in this frame on the first pass, so for
5119 * consistency we want to do so on future passes, but
5120 * the latter part we cannot dissect until later.
5121 * We only need to do this on the first pass; split_msp
5122 * truncates the msp so we don't get here a second
5123 * time.
5125 /* nxtpdu adjustment for the new msp is the same. */
5126 if (!PINFO_FD_VISITED(pinfo)) {
5127 /* We don't need to clear MSP_FLAGS_GOT_ALL_SEGMENTS
5128 * since we are spliting the MSP.
5130 msp = split_msp(pinfo, msp, tcpd);
5132 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
5136 if (!PINFO_FD_VISITED(pinfo)) {
5137 /* Update msp->nxtpdu to point to the new next
5138 * pdu boundary.
5139 * We only do this on the first pass, though we shouldn't
5140 * get here on a second pass (since we truncated the msp.)
5142 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
5143 /* We want reassembly of at least one
5144 * more segment so set the nxtpdu
5145 * boundary to one byte into the next
5146 * segment.
5147 * This means that the next segment
5148 * will complete reassembly even if it
5149 * is only one single byte in length.
5150 * If this is an OoO segment, then increment
5151 * the MSP end.
5153 msp->nxtpdu = MAX(seq + tvb_reported_length_remaining(tvb, offset), msp->nxtpdu) + 1;
5154 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
5155 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5156 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
5157 /* This is not the first segment, and we thought the
5158 * reassembly would be done now, but now know we must
5159 * desgment until FIN. (E.g., HTTP Response with headers
5160 * split across segments, and no Content-Length or
5161 * Transfer-Encoding (RFC 7230, Section 3.3.3, case 7.)
5162 * For the same reasons as below when we encounter
5163 * DESEGMENT_UNTIL_FIN on the first segment, give
5164 * msp->nxtpdu a big (but not too big) offset so
5165 * reassembly will pick up the segments later.
5167 msp->nxtpdu = msp->seq + 0x40000000;
5168 } else {
5169 if (seq + last_fragment_len >= msp->nxtpdu) {
5170 /* This is the segment (overlapping) the end of
5171 * the MSP.
5173 msp->nxtpdu = seq + last_fragment_len + pinfo->desegment_len;
5174 } else {
5175 /* This is a segment before the end of the MSP, so
5176 * it must be an out-of-order segment that completed
5177 * the MSP. The requested additional data is
5178 * relative to that end.
5180 msp->nxtpdu += pinfo->desegment_len;
5185 /* Since we need at least some more data
5186 * there can be no pdu following in the
5187 * tail of this segment.
5189 another_pdu_follows = 0;
5190 offset += last_fragment_len;
5191 seq += last_fragment_len;
5192 if (tvb_captured_length_remaining(tvb, offset) > 0)
5193 goto again;
5194 } else {
5196 * Show the stuff in this TCP segment as
5197 * just raw TCP segment data.
5199 nbytes = another_pdu_follows > 0
5200 ? another_pdu_follows
5201 : tvb_reported_length_remaining(tvb, offset);
5202 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
5203 nbytes, NULL, "TCP segment data (%u byte%s)", nbytes,
5204 plurality(nbytes, "", "s"));
5206 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
5211 if (must_desegment) {
5213 * The sequence number at which the stuff to be desegmented
5214 * starts is the sequence number of the byte at an offset
5215 * of "deseg_offset" into "tvb".
5217 * The sequence number of the byte at an offset of "offset"
5218 * is "seq", i.e. the starting sequence number of this
5219 * segment, so the sequence number of the byte at
5220 * "deseg_offset" is "seq + (deseg_offset - offset)".
5222 deseg_seq = seq + (deseg_offset - offset);
5224 /* We have to create some structures in our table but
5225 * this is something we only do the first time we see this
5226 * packet. */
5227 if (!PINFO_FD_VISITED(pinfo)) {
5228 /* If the dissector requested "reassemble until FIN"
5229 * just set this flag for the flow and let reassembly
5230 * proceed at normal. We will check/pick up these
5231 * reassembled PDUs later down in dissect_tcp() when checking
5232 * for the FIN flag.
5234 if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5235 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
5237 if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)) {
5238 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
5239 /* The subdissector asked to reassemble using the
5240 * entire next segment.
5241 * Just ask reassembly for one more byte
5242 * but set this msp flag so we can pick it up
5243 * above.
5245 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
5246 nxtseq+1, tcpd->fwd->multisegment_pdus);
5247 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
5248 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5250 * The subdissector asked to reassemble at the end of the
5251 * connection. That will be done in dissect_tcp, but here we
5252 * have to ask reassembly to collect all future segments.
5253 * Note that TCP_FLOW_REASSEMBLE_UNTIL_FIN was set before,
5254 * this ensures that OoO detection is skipped.
5255 * The exact nxtpdu offset does not matter, but it should be
5256 * smaller than half of the maximum 32-bit unsigned integer
5257 * to allow detection of sequence number wraparound, and
5258 * larger than the largest possible stream size. Hopefully
5259 * 1GiB (0x40000000 bytes) should be enough.
5261 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
5262 nxtseq+0x40000000, tcpd->fwd->multisegment_pdus);
5263 } else {
5264 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
5265 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
5268 /* add this segment as the first one for this new pdu */
5269 fragment_add(&tcp_reassembly_table, tvb, deseg_offset,
5270 pinfo, msp->first_frame, msp,
5271 0, nxtseq - deseg_seq,
5272 LT_SEQ(nxtseq, msp->nxtpdu));
5274 } else {
5275 /* If this is not the first time we have seen the packet, then
5276 * the MSP should already be created. Retrieve it to see if we
5277 * know what later frame the PDU is reassembled in.
5279 if (tcpd && (msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, deseg_seq))) {
5280 ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
5285 if (!called_dissector || pinfo->desegment_len != 0) {
5286 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
5287 ipfd_head->reassembled_in != pinfo->num &&
5288 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
5290 * We know what other frame this PDU is reassembled in;
5291 * let the user know.
5293 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,
5294 0, ipfd_head->reassembled_in);
5295 proto_item_set_generated(item);
5299 * Either we didn't call the subdissector at all (i.e.,
5300 * this is a segment that contains the middle of a
5301 * higher-level PDU, but contains neither the beginning
5302 * nor the end), or the subdissector couldn't dissect it
5303 * all, as some data was missing (i.e., it set
5304 * "pinfo->desegment_len" to the amount of additional
5305 * data it needs).
5307 if (pinfo->desegment_offset == 0) {
5309 * It couldn't, in fact, dissect any of it (the
5310 * first byte it couldn't dissect is at an offset
5311 * of "pinfo->desegment_offset" from the beginning
5312 * of the payload, and that's 0).
5313 * Just mark this as TCP.
5315 if (first_pdu && ipfd_head != NULL && ipfd_head->reassembled_in != 0) {
5316 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[TCP PDU reassembled in %u]",
5317 ipfd_head->reassembled_in);
5322 * Show what's left in the packet as just raw TCP segment
5323 * data. (It's possible that another PDU follows in the case
5324 * of an out of order frame that is part of two MSPs.)
5325 * XXX - remember what protocol the last subdissector
5326 * was, and report it as a continuation of that, instead?
5328 nbytes = another_pdu_follows ? another_pdu_follows : tvb_reported_length_remaining(tvb, deseg_offset);
5330 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, deseg_offset,
5331 nbytes, NULL, "TCP segment data (%u byte%s)", nbytes,
5332 plurality(nbytes, "", "s"));
5334 pinfo->can_desegment = 0;
5335 pinfo->desegment_offset = 0;
5336 pinfo->desegment_len = 0;
5338 if(another_pdu_follows) {
5339 /* there was another pdu following this one. */
5340 pinfo->can_desegment = 2;
5341 /* we also have to prevent the dissector from changing the
5342 * PROTOCOL and INFO columns since what follows may be an
5343 * incomplete PDU and we don't want it be changed back from
5344 * <Protocol> to <TCP>
5346 col_set_fence(pinfo->cinfo, COL_INFO);
5347 cleared_writable |= col_get_writable(pinfo->cinfo, COL_PROTOCOL);
5348 col_set_writable(pinfo->cinfo, COL_PROTOCOL, false);
5349 first_pdu = false;
5350 offset += another_pdu_follows;
5351 seq += another_pdu_follows;
5352 goto again;
5353 } else {
5354 /* remove any blocking set above otherwise the
5355 * proto,colinfo tap will break
5357 if(cleared_writable) {
5358 col_set_writable(pinfo->cinfo, COL_PROTOCOL, true);
5362 clean_exit:
5363 /* Restore the addresses and ports to whatever they were after
5364 * the last segment that successfully dissected some data, if any.
5366 restore_endpoint(pinfo, &new_endpoint);
5369 void
5370 tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5371 bool proto_desegment, unsigned fixed_len,
5372 unsigned (*get_pdu_len)(packet_info *, tvbuff_t *, int, void*),
5373 dissector_t dissect_pdu, void* dissector_data)
5375 volatile int offset = 0;
5376 int offset_before;
5377 unsigned captured_length_remaining;
5378 volatile unsigned plen;
5379 unsigned length;
5380 tvbuff_t *next_tvb;
5381 proto_item *item=NULL;
5382 const char *saved_proto;
5383 uint8_t curr_layer_num;
5384 wmem_list_frame_t *frame;
5386 tcp_endpoint_t orig_endpoint;
5388 save_endpoint(pinfo, &orig_endpoint);
5390 while (tvb_reported_length_remaining(tvb, offset) > 0) {
5392 * We use "tvb_ensure_captured_length_remaining()" to make
5393 * sure there actually *is* data remaining. The protocol
5394 * we're handling could conceivably consists of a sequence of
5395 * fixed-length PDUs, and therefore the "get_pdu_len" routine
5396 * might not actually fetch anything from the tvbuff, and thus
5397 * might not cause an exception to be thrown if we've run past
5398 * the end of the tvbuff.
5400 * This means we're guaranteed that "captured_length_remaining" is positive.
5402 captured_length_remaining = tvb_ensure_captured_length_remaining(tvb, offset);
5405 * Can we do reassembly?
5407 if (proto_desegment && pinfo->can_desegment) {
5409 * Yes - is the fixed-length part of the PDU split across segment
5410 * boundaries?
5412 if (captured_length_remaining < fixed_len) {
5414 * Yes. Tell the TCP dissector where the data for this message
5415 * starts in the data it handed us and that we need "some more
5416 * data." Don't tell it exactly how many bytes we need because
5417 * if/when we ask for even more (after the header) that will
5418 * break reassembly.
5420 pinfo->desegment_offset = offset;
5421 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
5422 return;
5427 * Get the length of the PDU.
5429 plen = (*get_pdu_len)(pinfo, tvb, offset, dissector_data);
5430 if (plen == 0) {
5432 * Support protocols which have a variable length which cannot
5433 * always be determined within the given fixed_len.
5436 * If another segment was requested but we can't do reassembly,
5437 * abort and warn about the unreassembled packet.
5439 THROW_ON(!(proto_desegment && pinfo->can_desegment), FragmentBoundsError);
5441 * Tell the TCP dissector where the data for this message
5442 * starts in the data it handed us, and that we need one
5443 * more segment, and return.
5445 pinfo->desegment_offset = offset;
5446 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
5447 return;
5449 if (plen < fixed_len) {
5451 * Either:
5453 * 1) the length value extracted from the fixed-length portion
5454 * doesn't include the fixed-length portion's length, and
5455 * was so large that, when the fixed-length portion's
5456 * length was added to it, the total length overflowed;
5458 * 2) the length value extracted from the fixed-length portion
5459 * includes the fixed-length portion's length, and the value
5460 * was less than the fixed-length portion's length, i.e. it
5461 * was bogus.
5463 * Report this as a bounds error.
5465 show_reported_bounds_error(tvb, pinfo, tree);
5466 return;
5469 /* give a hint to TCP where the next PDU starts
5470 * so that it can attempt to find it in case it starts
5471 * somewhere in the middle of a segment.
5473 if(!pinfo->fd->visited && tcp_analyze_seq) {
5474 unsigned remaining_bytes;
5475 remaining_bytes = tvb_reported_length_remaining(tvb, offset);
5476 if(plen>remaining_bytes) {
5477 pinfo->want_pdu_tracking=2;
5478 pinfo->bytes_until_next_pdu=plen-remaining_bytes;
5483 * Can we do reassembly?
5485 if (proto_desegment && pinfo->can_desegment) {
5487 * Yes - is the PDU split across segment boundaries?
5489 if (captured_length_remaining < plen) {
5491 * Yes. Tell the TCP dissector where the data for this message
5492 * starts in the data it handed us, and how many more bytes we
5493 * need, and return.
5495 pinfo->desegment_offset = offset;
5496 pinfo->desegment_len = plen - captured_length_remaining;
5497 return;
5501 curr_layer_num = pinfo->curr_layer_num-1;
5502 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
5503 while (frame && (proto_tcp != (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame)))) {
5504 frame = wmem_list_frame_prev(frame);
5505 curr_layer_num--;
5507 #if 0
5508 if (captured_length_remaining >= plen || there are more packets)
5510 #endif
5512 * Display the PDU length as a field
5514 item=proto_tree_add_uint((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_tcp, curr_layer_num),
5515 hf_tcp_pdu_size,
5516 tvb, offset, plen, plen);
5517 proto_item_set_generated(item);
5518 #if 0
5519 } else {
5520 item = proto_tree_add_expert_format((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_tcp, curr_layer_num),
5521 tvb, offset, -1,
5522 "PDU Size: %u cut short at %u",plen,captured_length_remaining);
5523 proto_item_set_generated(item);
5525 #endif
5528 * Construct a tvbuff containing the amount of the payload we have
5529 * available. Make its reported length the amount of data in the PDU.
5531 length = captured_length_remaining;
5532 if (length > plen)
5533 length = plen;
5534 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, plen);
5535 if (!(proto_desegment && pinfo->can_desegment)) {
5536 if (plen > length) {
5537 /* If we can't do reassembly but the PDU is split across
5538 * segment boundaries, mark the tvbuff as a fragment so
5539 * we throw FragmentBoundsError instead of malformed
5540 * errors.
5542 tvb_set_fragment(next_tvb);
5548 * Dissect the PDU.
5550 * If it gets an error that means there's no point in
5551 * dissecting any more PDUs, rethrow the exception in
5552 * question.
5554 * If it gets any other error, report it and continue, as that
5555 * means that PDU got an error, but that doesn't mean we should
5556 * stop dissecting PDUs within this frame or chunk of reassembled
5557 * data.
5559 saved_proto = pinfo->current_proto;
5560 restore_endpoint(pinfo, &orig_endpoint);
5561 TRY {
5562 (*dissect_pdu)(next_tvb, pinfo, tree, dissector_data);
5564 CATCH_NONFATAL_ERRORS {
5565 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
5568 * Restore the saved protocol as well; we do this after
5569 * show_exception(), so that the "Malformed packet" indication
5570 * shows the protocol for which dissection failed.
5572 pinfo->current_proto = saved_proto;
5574 ENDTRY;
5577 * Step to the next PDU.
5578 * Make sure we don't overflow.
5580 offset_before = offset;
5581 offset += plen;
5582 if (offset <= offset_before)
5583 break;
5587 static void
5588 tcp_info_append_uint(packet_info *pinfo, const char *abbrev, uint32_t val)
5590 /* fstr(" %s=%u", abbrev, val) */
5591 col_append_str_uint(pinfo->cinfo, COL_INFO, abbrev, val, " ");
5594 static void
5595 tcp_info_append_hex_uint(packet_info *pinfo, const char *abbrev, uint32_t val)
5597 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%X", abbrev, val);
5600 static bool
5601 tcp_option_len_check(proto_item* length_item, packet_info *pinfo, unsigned len, unsigned optlen)
5603 if (len != optlen) {
5604 /* Bogus - option length isn't what it's supposed to be for this option. */
5605 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5606 "option length should be %u", optlen);
5607 return false;
5610 return true;
5613 static int
5614 dissect_tcpopt_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
5616 proto_item *item;
5617 proto_tree *exp_tree;
5618 int offset = 0, optlen = tvb_reported_length(tvb);
5620 item = proto_tree_add_item(tree, proto_tcp_option_unknown, tvb, offset, -1, ENC_NA);
5621 exp_tree = proto_item_add_subtree(item, ett_tcp_unknown_opt);
5623 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5624 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5625 if (optlen > 2)
5626 proto_tree_add_item(exp_tree, hf_tcp_option_unknown_payload, tvb, offset + 2, optlen - 2, ENC_NA);
5628 return tvb_captured_length(tvb);
5631 static int
5632 dissect_tcpopt_default_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, int ett)
5634 proto_item *item;
5635 proto_tree *exp_tree;
5636 proto_item *length_item;
5637 int offset = 0;
5639 item = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA);
5640 exp_tree = proto_item_add_subtree(item, ett);
5642 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5643 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5645 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), 2))
5646 return tvb_captured_length(tvb);
5648 return tvb_captured_length(tvb);
5651 static int
5652 dissect_tcpopt_recbound(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5654 return dissect_tcpopt_default_option(tvb, pinfo, tree, proto_tcp_option_scpsrec, ett_tcp_opt_recbound);
5657 static int
5658 dissect_tcpopt_correxp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5660 return dissect_tcpopt_default_option(tvb, pinfo, tree, proto_tcp_option_scpscor, ett_tcp_opt_scpscor);
5663 static void
5664 dissect_tcpopt_tfo_payload(tvbuff_t *tvb, int offset, unsigned optlen,
5665 packet_info *pinfo, proto_tree *exp_tree, void *data)
5667 proto_item *ti;
5668 struct tcpheader *tcph = (struct tcpheader*)data;
5669 struct tcp_analysis *tcpd;
5671 if (optlen == 2) {
5672 /* Fast Open Cookie Request */
5673 proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie_request,
5674 tvb, offset, 2, ENC_NA);
5675 col_append_str(pinfo->cinfo, COL_INFO, " TFO=R");
5676 } else if (optlen > 2) {
5677 /* Fast Open Cookie */
5678 ti = proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie,
5679 tvb, offset + 2, optlen - 2, ENC_NA);
5680 col_append_str(pinfo->cinfo, COL_INFO, " TFO=C");
5681 if ((tcph->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) {
5682 expert_add_info(pinfo, ti, &ei_tcp_analysis_tfo_syn);
5684 /* Is this a SYN with data and the cookie? */
5685 if (tcph->th_have_seglen && tcph->th_seglen) {
5686 tcpd = get_tcp_conversation_data(NULL, pinfo);
5687 if (tcpd) {
5688 tcpd->tfo_syn_data = true;
5695 static int
5696 dissect_tcpopt_tfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5698 proto_item *item;
5699 proto_tree *exp_tree;
5700 int offset = 0;
5702 item = proto_tree_add_item(tree, proto_tcp_option_tfo, tvb, offset, -1, ENC_NA);
5703 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);
5704 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5705 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5707 dissect_tcpopt_tfo_payload(tvb, offset, tvb_reported_length(tvb), pinfo, exp_tree, data);
5708 return tvb_captured_length(tvb);
5712 * TCP ACK Rate Request option is based on
5713 * https://datatracker.ietf.org/doc/html/draft-gomez-tcpm-ack-rate-request-06
5716 #define TCPOPT_TARR_RATE_MASK 0xfe
5717 #define TCPOPT_TARR_RESERVED_MASK 0x01
5718 #define TCPOPT_TARR_RATE_SHIFT 1
5720 static void
5721 dissect_tcpopt_tarr_data(tvbuff_t *tvb, int data_offset, unsigned data_len,
5722 packet_info *pinfo, proto_tree *tree, proto_item *item, void *data _U_)
5724 uint8_t rate;
5726 switch (data_len) {
5727 case 0:
5728 col_append_str(pinfo->cinfo, COL_INFO, " TARR");
5729 break;
5730 case 1:
5731 rate = (tvb_get_uint8(tvb, data_offset) & TCPOPT_TARR_RATE_MASK) >> TCPOPT_TARR_RATE_SHIFT;
5732 proto_tree_add_item(tree, hf_tcp_option_tarr_rate, tvb, data_offset, 1, ENC_BIG_ENDIAN);
5733 proto_tree_add_item(tree, hf_tcp_option_tarr_reserved, tvb, data_offset, 1, ENC_BIG_ENDIAN);
5734 tcp_info_append_uint(pinfo, "TARR", rate);
5735 proto_item_append_text(item, " %u", rate);
5736 break;
5740 static void
5741 dissect_tcpopt_acc_ecn_data(tvbuff_t *tvb, int data_offset, unsigned data_len,
5742 bool is_order_0, packet_info *pinfo, proto_tree *tree, proto_item *item, void *data _U_)
5744 struct tcp_analysis *tcpd;
5745 uint32_t ee0b, eceb, ee1b;
5747 switch (data_len) {
5748 case 0:
5749 col_append_str(pinfo->cinfo, COL_INFO, " AccECN");
5750 break;
5751 case 3:
5752 if (is_order_0) {
5753 ee0b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5754 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5755 proto_item_append_text(item, " (Order 0): EE0B %u", ee0b);
5756 tcp_info_append_uint(pinfo, "EE0B", ee0b);
5757 } else {
5758 ee1b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5759 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5760 proto_item_append_text(item, " (Order 1): EE1B %u", ee1b);
5761 tcp_info_append_uint(pinfo, "EE1B", ee1b);
5763 break;
5764 case 6:
5765 if (is_order_0) {
5766 ee0b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5767 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5768 tcp_info_append_uint(pinfo, "EE0B", ee0b);
5769 } else {
5770 ee1b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5771 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5772 tcp_info_append_uint(pinfo, "EE1B", ee1b);
5774 eceb = tvb_get_uint24(tvb, data_offset + 3, ENC_BIG_ENDIAN);
5775 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_eceb, tvb, data_offset + 3, 3, ENC_BIG_ENDIAN);
5776 tcp_info_append_uint(pinfo, "ECEB", eceb);
5777 if (is_order_0) {
5778 proto_item_append_text(item, " (Order 0): EE0B %u, ECEB %u", ee0b, eceb);
5779 } else {
5780 proto_item_append_text(item, " (Order 1): EE1B %u, ECEB %u", ee1b, eceb);
5782 break;
5783 case 9:
5784 if (is_order_0) {
5785 ee0b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5786 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5787 tcp_info_append_uint(pinfo, "EE0B", ee0b);
5788 } else {
5789 ee1b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5790 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5791 tcp_info_append_uint(pinfo, "EE1B", ee1b);
5793 eceb = tvb_get_uint24(tvb, data_offset + 3, ENC_BIG_ENDIAN);
5794 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_eceb, tvb, data_offset + 3, 3, ENC_BIG_ENDIAN);
5795 tcp_info_append_uint(pinfo, "ECEB", eceb);
5796 if (is_order_0) {
5797 ee1b = tvb_get_uint24(tvb, data_offset + 6, ENC_BIG_ENDIAN);
5798 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset + 6, 3, ENC_BIG_ENDIAN);
5799 tcp_info_append_uint(pinfo, "EE1B", ee1b);
5800 proto_item_append_text(item, " (Order 0): EE0B %u, ECEB %u, EE1B %u", ee0b, eceb, ee1b);
5801 } else {
5802 ee0b = tvb_get_uint24(tvb, data_offset + 6, ENC_BIG_ENDIAN);
5803 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset + 6, 3, ENC_BIG_ENDIAN);
5804 tcp_info_append_uint(pinfo, "EE0B", ee0b);
5805 proto_item_append_text(item, " (Order 1): EE1B %u, ECEB %u, EE0B %u", ee1b, eceb, ee0b);
5807 break;
5809 tcpd = get_tcp_conversation_data(NULL, pinfo);
5810 if (tcpd != NULL) {
5811 tcpd->had_acc_ecn_option = true;
5815 static int
5816 dissect_tcpopt_acc_ecn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
5818 proto_item *length_item, *item;
5819 proto_tree *acc_ecn_tree;
5820 int offset;
5821 uint8_t kind, length;
5823 offset = 0;
5824 item = proto_tree_add_item(tree, proto_tcp_option_acc_ecn, tvb, offset, -1, ENC_NA);
5825 acc_ecn_tree = proto_item_add_subtree(item, ett_tcp_option_acc_ecn);
5826 kind = tvb_get_uint8(tvb, offset);
5827 proto_tree_add_item(acc_ecn_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5828 offset += 1;
5829 length = tvb_get_uint8(tvb, offset);
5830 length_item = proto_tree_add_item(acc_ecn_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
5831 offset += 1;
5832 if (length != 2 && length != 5 && length != 8 && length != 11) {
5833 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5834 "option length should be 2, 5, 8, or 11 instead of %u", length);
5835 } else {
5836 dissect_tcpopt_acc_ecn_data(tvb, offset, length - 2, kind == TCPOPT_ACC_ECN_0, pinfo, acc_ecn_tree, item, data);
5838 return tvb_captured_length(tvb);
5841 static int
5842 dissect_tcpopt_exp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5844 proto_item *item, *length_item;
5845 proto_tree *exp_tree;
5846 uint16_t exid;
5847 uint8_t kind;
5848 int offset = 0, optlen = tvb_reported_length(tvb);
5850 item = proto_tree_add_item(tree, proto_tcp_option_exp, tvb, offset, -1, ENC_NA);
5851 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);
5852 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5853 kind = tvb_get_uint8(tvb, offset);
5854 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5855 if (tcp_exp_options_rfc6994) {
5856 if (optlen >= TCPOLEN_EXP_MIN) {
5857 exid = tvb_get_ntohs(tvb, offset + 2);
5858 proto_tree_add_item(exp_tree, hf_tcp_option_exp_exid, tvb,
5859 offset + 2, 2, ENC_BIG_ENDIAN);
5860 proto_item_append_text(item, ": %s", val_to_str_const(exid, tcp_exid_vs, "Unknown"));
5861 switch (exid) {
5862 case TCPEXID_TARR:
5863 if (optlen != 4 && optlen != 5) {
5864 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5865 "option length should be 4 or 5 instead of %d",
5866 optlen);
5867 } else {
5868 dissect_tcpopt_tarr_data(tvb, offset + 4, optlen - 4,
5869 pinfo, exp_tree, item, data);
5871 break;
5872 case 0xACC0: /* draft-ietf-tcpm-accurate-ecn-20 */
5873 case 0xACC1:
5874 if (optlen != 4 && optlen != 7 && optlen != 10 && optlen != 13) {
5875 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5876 "option length should be 4, 7, 10, or 13 instead of %d",
5877 optlen);
5878 } else {
5879 proto_item_append_text(item, ": Accurate ECN");
5880 dissect_tcpopt_acc_ecn_data(tvb, offset + 4, optlen - 4,
5881 exid == 0xACC0, pinfo, exp_tree,
5882 item, data);
5884 break;
5885 case TCPEXID_FO:
5886 dissect_tcpopt_tfo_payload(tvb, offset + 2, optlen - 2, pinfo, exp_tree, data);
5887 break;
5888 default:
5889 if (optlen > TCPOLEN_EXP_MIN) {
5890 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,
5891 offset + TCPOLEN_EXP_MIN,
5892 optlen - TCPOLEN_EXP_MIN, ENC_NA);
5894 tcp_info_append_hex_uint(pinfo, "ExID", exid);
5895 break;
5897 } else {
5898 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5899 "option length %u smaller than 4", optlen);
5901 } else {
5902 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,
5903 offset + 2, optlen - 2, ENC_NA);
5904 tcp_info_append_uint(pinfo, "Exp", (kind == TCPOPT_EXP_FD) ? 1 : 2);
5906 return tvb_captured_length(tvb);
5909 static int
5910 dissect_tcpopt_sack_perm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
5912 proto_item *item;
5913 proto_tree *exp_tree;
5914 proto_item *length_item;
5915 int offset = 0;
5916 struct tcpheader *tcph = (struct tcpheader *)data;
5918 item = proto_tree_add_item(tree, proto_tcp_option_sack_perm, tvb, offset, -1, ENC_NA);
5919 exp_tree = proto_item_add_subtree(item, ett_tcp_option_sack_perm);
5921 if (!(tcph->th_flags & TH_SYN))
5923 expert_add_info(pinfo, item, &ei_tcp_option_sack_perm_present);
5926 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5927 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5929 col_append_str(pinfo->cinfo, COL_INFO, " SACK_PERM");
5931 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SACK_PERM))
5932 return tvb_captured_length(tvb);
5934 return tvb_captured_length(tvb);
5937 static int
5938 dissect_tcpopt_mss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
5940 proto_item *item;
5941 proto_tree *exp_tree;
5942 proto_item *length_item;
5943 int offset = 0;
5944 struct tcpheader *tcph = (struct tcpheader *)data;
5945 uint32_t mss;
5946 struct tcp_analysis *tcpd;
5948 /* find the conversation for this TCP session and its stored data */
5949 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
5950 tcpd=get_tcp_conversation_data_idempotent(stratconv);
5952 item = proto_tree_add_item(tree, proto_tcp_option_mss, tvb, offset, -1, ENC_NA);
5953 exp_tree = proto_item_add_subtree(item, ett_tcp_option_mss);
5955 if (!(tcph->th_flags & TH_SYN))
5957 expert_add_info(pinfo, item, &ei_tcp_option_mss_present);
5960 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5961 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5963 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_MSS))
5964 return tvb_captured_length(tvb);
5966 proto_tree_add_item_ret_uint(exp_tree, hf_tcp_option_mss_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN, &mss);
5967 proto_item_append_text(item, ": %u bytes", mss);
5968 tcp_info_append_uint(pinfo, "MSS", mss);
5970 /* Only SYN packets are supposed to have this option
5971 * XXX - we could restrict a bit more with seq_analyze */
5972 if( tcpd && (tcph->th_flags & TH_SYN) && !pinfo->fd->visited ) {
5973 tcpd->fwd->mss=mss;
5976 return tvb_captured_length(tvb);
5979 /* The window scale extension is defined in RFC 1323 */
5980 static int
5981 dissect_tcpopt_wscale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5983 uint8_t val;
5984 uint32_t shift;
5985 proto_item *wscale_pi, *shift_pi, *gen_pi;
5986 proto_tree *wscale_tree;
5987 proto_item *length_item;
5988 int offset = 0;
5989 struct tcp_analysis *tcpd;
5991 /* find the conversation for this TCP session and its stored data */
5992 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
5993 tcpd=get_tcp_conversation_data_idempotent(stratconv);
5995 wscale_pi = proto_tree_add_item(tree, proto_tcp_option_wscale, tvb, offset, -1, ENC_NA);
5996 wscale_tree = proto_item_add_subtree(wscale_pi, ett_tcp_option_wscale);
5998 proto_tree_add_item(wscale_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5999 offset += 1;
6001 length_item = proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
6002 offset += 1;
6004 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_WINDOW))
6005 return tvb_captured_length(tvb);
6007 shift_pi = proto_tree_add_item_ret_uint(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1, ENC_BIG_ENDIAN, &shift);
6008 if (shift > 14) {
6009 /* RFC 1323: "If a Window Scale option is received with a shift.cnt
6010 * value exceeding 14, the TCP should log the error but use 14 instead
6011 * of the specified value." */
6012 shift = 14;
6013 expert_add_info(pinfo, shift_pi, &ei_tcp_option_wscale_shift_invalid);
6016 gen_pi = proto_tree_add_uint(wscale_tree, hf_tcp_option_wscale_multiplier, tvb,
6017 offset, 1, 1 << shift);
6018 proto_item_set_generated(gen_pi);
6019 val = tvb_get_uint8(tvb, offset);
6021 proto_item_append_text(wscale_pi, ": %u (multiply by %u)", val, 1 << shift);
6023 tcp_info_append_uint(pinfo, "WS", 1 << shift);
6025 if(!pinfo->fd->visited) {
6026 pdu_store_window_scale_option(shift, tcpd);
6029 return tvb_captured_length(tvb);
6032 static int
6033 dissect_tcpopt_sack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
6035 proto_tree *field_tree = NULL;
6036 proto_item *tf, *ti;
6037 uint32_t leftedge, rightedge;
6038 struct tcp_analysis *tcpd=NULL;
6039 struct tcpheader *tcph = (struct tcpheader *)data;
6040 uint32_t base_ack=0;
6041 unsigned num_sack_ranges = 0;
6042 int offset = 0;
6043 int sackoffset;
6044 int optlen = tvb_reported_length(tvb);
6047 * SEQ analysis is the condition for both relative analysis obviously,
6048 * and SACK handling for the in-flight update
6050 if(tcp_analyze_seq) {
6051 /* find the conversation for this TCP session and its stored data */
6052 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
6053 tcpd=get_tcp_conversation_data_idempotent(stratconv);
6055 if (tcpd) {
6056 if (tcp_relative_seq) {
6057 base_ack=tcpd->rev->base_seq;
6061 * initialize the number of SACK blocks to 0, it will be
6062 * updated some lines later
6064 if (tcp_track_bytes_in_flight && tcpd->fwd->tcp_analyze_seq_info) {
6065 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = 0;
6070 /* Late discovery of a 'false' Window Update in presence of SACK option,
6071 * which means we are dealing with a Dup ACK rather than a Window Update.
6072 * Classify accordingly by removing the UPDATE and adding the DUP flags.
6073 * Mostly a copy/paste from tcp_analyze_sequence_number(), ensure consistency
6074 * whenever the latter changes.
6075 * see Issue #14937
6077 if( tcp_analyze_seq && tcpd && tcpd->ta && tcpd->ta->flags&TCP_A_WINDOW_UPDATE ) {
6079 /* MPTCP tolerates duplicate acks in some circumstances, see RFC 8684 4. */
6080 if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) {
6081 /* just ignore this DUPLICATE ACK */
6082 } else {
6083 /* no initialization required of the tcpd->ta as this code would
6084 * be unreachable otherwise
6086 tcpd->ta->flags &= ~TCP_A_WINDOW_UPDATE;
6087 tcpd->ta->flags |= TCP_A_DUPLICATE_ACK;
6089 if (tcpd->fwd->tcp_analyze_seq_info) {
6090 tcpd->fwd->tcp_analyze_seq_info->dupacknum++;
6092 tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum;
6093 tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack;
6098 ti = proto_tree_add_item(tree, proto_tcp_option_sack, tvb, offset, -1, ENC_NA);
6099 field_tree = proto_item_add_subtree(ti, ett_tcp_option_sack);
6101 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6102 offset, 1, ENC_BIG_ENDIAN);
6103 proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6104 offset + 1, 1, ENC_BIG_ENDIAN);
6106 offset += 2; /* skip past type and length */
6107 optlen -= 2; /* subtract size of type and length */
6109 sackoffset = offset;
6110 while (optlen > 0) {
6111 if (optlen < 4) {
6112 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_suboption_malformed, tvb, offset, optlen);
6113 break;
6115 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;
6116 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
6117 offset, 4, leftedge,
6118 "left edge = %u%s", leftedge,
6119 (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");
6120 optlen -= 4;
6121 if (optlen < 4) {
6122 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_suboption_malformed, tvb, offset, optlen);
6123 break;
6125 /* XXX - check whether it goes past end of packet */
6126 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;
6127 optlen -= 4;
6128 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
6129 offset+4, 4, rightedge,
6130 "right edge = %u%s", rightedge,
6131 (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");
6132 tcp_info_append_uint(pinfo, "SLE", leftedge);
6133 tcp_info_append_uint(pinfo, "SRE", rightedge);
6135 /* Store blocks for BiF analysis */
6136 if (tcp_analyze_seq && tcpd && tcpd->fwd->tcp_analyze_seq_info && tcp_track_bytes_in_flight && num_sack_ranges < MAX_TCP_SACK_RANGES) {
6137 tcpd->fwd->tcp_analyze_seq_info->sack_left_edge[num_sack_ranges] = leftedge;
6138 tcpd->fwd->tcp_analyze_seq_info->sack_right_edge[num_sack_ranges++] = rightedge;
6139 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = num_sack_ranges;
6142 /* Update tap info */
6143 if (tcph != NULL && (tcph->num_sack_ranges < MAX_TCP_SACK_RANGES)) {
6144 tcph->sack_left_edge[tcph->num_sack_ranges] = leftedge;
6145 tcph->sack_right_edge[tcph->num_sack_ranges] = rightedge;
6146 tcph->num_sack_ranges++;
6149 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);
6150 offset += 8;
6154 /* Show number of SACK ranges in this option as a generated field */
6155 tf = proto_tree_add_uint(field_tree, hf_tcp_option_sack_range_count,
6156 tvb, 0, 0, num_sack_ranges);
6157 proto_item_set_generated(tf);
6159 /* RFC 2883 "An Extension to the Selective Acknowledgement (SACK) Option for TCP" aka "D-SACK"
6160 * Section 4
6161 * Conditions: Either the first sack-block is inside the already acknowledged range or
6162 * the first sack block is inside the second sack block.
6164 * Maybe add later:
6165 * (1) A D-SACK block is only used to report a duplicate contiguous sequence of data received by
6166 * the receiver in the most recent packet.
6168 if (tcph != NULL && (
6169 LE_SEQ(tcph->sack_right_edge[0], tcph->th_ack) ||
6170 (tcph->num_sack_ranges > 1 &&
6171 LT_SEQ(tcph->sack_left_edge[1], tcph->sack_right_edge[0]) &&
6172 GE_SEQ(tcph->sack_right_edge[1], tcph->sack_right_edge[0]))
6173 )) {
6174 leftedge = tvb_get_ntohl(tvb, sackoffset)-base_ack;
6175 tf = proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_dsack_le, tvb, sackoffset, 4, leftedge,
6176 "D-SACK Left Edge = %u%s", leftedge, (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");
6177 proto_item_set_generated(tf);
6178 rightedge = tvb_get_ntohl(tvb, sackoffset+4)-base_ack;
6179 tf = proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_dsack_re, tvb, sackoffset+4, 4, rightedge,
6180 "D-SACK Right Edge = %u%s", rightedge, (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");
6181 proto_item_set_generated(tf);
6182 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_option_sack_dsack, tvb, sackoffset, 8);
6185 return tvb_captured_length(tvb);
6188 static int
6189 dissect_tcpopt_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6191 proto_tree *field_tree;
6192 proto_item *item;
6193 proto_item *length_item;
6194 uint32_t echo;
6195 int offset = 0;
6197 item = proto_tree_add_item(tree, proto_tcp_option_echo, tvb, offset, -1, ENC_NA);
6198 field_tree = proto_item_add_subtree(item, ett_tcp_opt_echo);
6200 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6201 offset, 1, ENC_BIG_ENDIAN);
6202 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6203 offset + 1, 1, ENC_BIG_ENDIAN);
6205 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_ECHO))
6206 return tvb_captured_length(tvb);
6208 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_echo, tvb,
6209 offset + 2, 4, ENC_BIG_ENDIAN, &echo);
6211 proto_item_append_text(item, ": %u", echo);
6212 tcp_info_append_uint(pinfo, "ECHO", echo);
6214 return tvb_captured_length(tvb);
6217 /* If set, do not put the TCP timestamp information on the summary line */
6218 static bool tcp_ignore_timestamps;
6220 static int
6221 dissect_tcpopt_timestamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6223 proto_item *ti, *tsval_ti;
6224 proto_tree *ts_tree;
6225 proto_item *length_item;
6226 int offset = 0;
6227 uint32_t ts_val, ts_ecr;
6228 int len = tvb_reported_length(tvb);
6230 ti = proto_tree_add_item(tree, proto_tcp_option_timestamp, tvb, offset, -1, ENC_NA);
6231 ts_tree = proto_item_add_subtree(ti, ett_tcp_option_timestamp);
6233 proto_tree_add_item(ts_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
6234 offset += 1;
6236 length_item = proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
6237 offset += 1;
6239 if (!tcp_option_len_check(length_item, pinfo, len, TCPOLEN_TIMESTAMP))
6240 return tvb_captured_length(tvb);
6242 tsval_ti = proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset,
6243 4, ENC_BIG_ENDIAN, &ts_val);
6245 proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset + 4,
6246 4, ENC_BIG_ENDIAN, &ts_ecr);
6248 proto_item_append_text(ti, ": TSval %u, TSecr %u", ts_val, ts_ecr);
6249 if (tcp_ignore_timestamps == false) {
6250 tcp_info_append_uint(pinfo, "TSval", ts_val);
6251 tcp_info_append_uint(pinfo, "TSecr", ts_ecr);
6254 if (read_seq_as_syn_cookie) {
6255 proto_item_append_text(ti, " (syn cookie)");
6256 proto_item* syncookie_ti = proto_item_add_subtree(tsval_ti, ett_tcp_syncookie_option);
6257 uint32_t timestamp = tvb_get_bits32(tvb, offset * 8, 26, ENC_NA) << 6;
6258 proto_tree_add_uint_bits_format_value(syncookie_ti, hf_tcp_syncookie_option_timestamp, tvb, offset * 8,
6259 26, timestamp, ENC_TIME_SECS, "%s", abs_time_secs_to_str(pinfo->pool, timestamp, ABSOLUTE_TIME_LOCAL, true));
6260 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_ecn, tvb, offset * 8 + 26, 1, ENC_NA);
6261 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_sack, tvb, offset * 8 + 27, 1, ENC_NA);
6262 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_wscale, tvb, offset * 8 + 28, 4, ENC_NA);
6265 return tvb_captured_length(tvb);
6268 static struct mptcp_analysis*
6269 mptcp_alloc_analysis(struct tcp_analysis* tcpd) {
6271 struct mptcp_analysis* mptcpd;
6273 DISSECTOR_ASSERT(tcpd->mptcp_analysis == 0);
6275 mptcpd = (struct mptcp_analysis*)wmem_new0(wmem_file_scope(), struct mptcp_analysis);
6276 mptcpd->subflows = wmem_list_new(wmem_file_scope());
6278 mptcpd->stream = mptcp_stream_count++;
6279 tcpd->mptcp_analysis = mptcpd;
6281 memset(&mptcpd->meta_flow, 0, 2*sizeof(mptcp_meta_flow_t));
6283 /* arbitrary assignment. Callers may override this */
6284 tcpd->fwd->mptcp_subflow->meta = &mptcpd->meta_flow[0];
6285 tcpd->rev->mptcp_subflow->meta = &mptcpd->meta_flow[1];
6287 return mptcpd;
6291 /* will create necessary structure if fails to find a match on the token */
6292 static struct mptcp_analysis*
6293 mptcp_get_meta_from_token(struct tcp_analysis* tcpd, tcp_flow_t *tcp_flow, uint32_t token) {
6295 struct mptcp_analysis* result = NULL;
6296 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;
6297 uint8_t assignedMetaId = 0; /* array id < 2 */
6299 DISSECTOR_ASSERT(tcp_flow == tcpd->fwd || tcp_flow == tcpd->rev);
6303 /* if token already set for this meta */
6304 if( tcp_flow->mptcp_subflow->meta && (tcp_flow->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_TOKEN)) {
6305 return mptcpd;
6308 /* else look for a registered meta with this token */
6309 result = (struct mptcp_analysis*)wmem_tree_lookup32(mptcp_tokens, token);
6311 /* if token already registered than just share it across TCP connections */
6312 if(result) {
6313 mptcpd = result;
6314 mptcp_attach_subflow(mptcpd, tcpd);
6316 else {
6317 /* we create it if this connection */
6318 if(!mptcpd) {
6319 /* don't care which meta to choose assign each meta to a direction */
6320 mptcpd = mptcp_alloc_analysis(tcpd);
6321 mptcp_attach_subflow(mptcpd, tcpd);
6323 else {
6325 /* already exists, thus some meta may already have been configured */
6326 if(mptcpd->meta_flow[0].static_flags & MPTCP_META_HAS_TOKEN) {
6327 assignedMetaId = 1;
6329 else if(mptcpd->meta_flow[1].static_flags & MPTCP_META_HAS_TOKEN) {
6330 assignedMetaId = 0;
6332 else {
6333 DISSECTOR_ASSERT_NOT_REACHED();
6335 tcp_flow->mptcp_subflow->meta = &mptcpd->meta_flow[assignedMetaId];
6337 DISSECTOR_ASSERT(tcp_flow->mptcp_subflow->meta);
6339 tcp_flow->mptcp_subflow->meta->token = token;
6340 tcp_flow->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_TOKEN;
6342 wmem_tree_insert32(mptcp_tokens, token, mptcpd);
6345 DISSECTOR_ASSERT(mptcpd);
6348 /* compute the meta id assigned to tcp_flow */
6349 assignedMetaId = (tcp_flow->mptcp_subflow->meta == &mptcpd->meta_flow[0]) ? 0 : 1;
6351 /* computes the metaId tcpd->fwd should be assigned to */
6352 assignedMetaId = (tcp_flow == tcpd->fwd) ? assignedMetaId : (assignedMetaId +1) %2;
6354 tcpd->fwd->mptcp_subflow->meta = &mptcpd->meta_flow[ (assignedMetaId) ];
6355 tcpd->rev->mptcp_subflow->meta = &mptcpd->meta_flow[ (assignedMetaId +1) %2];
6357 return mptcpd;
6360 /* setup from_key */
6361 static
6362 struct mptcp_analysis*
6363 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_) {
6365 uint32_t token = 0;
6366 uint64_t expected_idsn= 0;
6367 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;
6369 if(fwd->mptcp_subflow->meta && (fwd->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_KEY)) {
6370 return mptcpd;
6373 /* MPTCP v0 only standardizes SHA1, and v1 SHA256. */
6374 if (version == 0)
6375 mptcp_cryptodata_sha1(key, &token, &expected_idsn);
6376 else if (version == 1)
6377 mptcp_cryptodata_sha256(key, &token, &expected_idsn);
6379 mptcpd = mptcp_get_meta_from_token(tcpd, fwd, token);
6381 DISSECTOR_ASSERT(fwd->mptcp_subflow->meta);
6383 fwd->mptcp_subflow->meta->version = version;
6384 fwd->mptcp_subflow->meta->key = key;
6385 fwd->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_KEY;
6386 fwd->mptcp_subflow->meta->base_dsn = expected_idsn;
6387 return mptcpd;
6390 /* record this mapping */
6391 static
6392 void analyze_mapping(struct tcp_analysis *tcpd, packet_info *pinfo, uint16_t len, uint64_t dsn, bool extended, uint32_t ssn) {
6394 /* store mapping only if analysis is enabled and mapping is not unlimited */
6395 if (!mptcp_analyze_mappings || !len) {
6396 return;
6399 if (PINFO_FD_VISITED(pinfo)) {
6400 return;
6403 /* register SSN range described by the mapping into a subflow interval_tree */
6404 mptcp_dss_mapping_t *mapping = NULL;
6405 mapping = wmem_new0(wmem_file_scope(), mptcp_dss_mapping_t);
6407 mapping->rawdsn = dsn;
6408 mapping->extended_dsn = extended;
6409 mapping->frame = pinfo->fd->num;
6410 mapping->ssn_low = ssn;
6411 mapping->ssn_high = ssn + len - 1;
6413 wmem_itree_insert(tcpd->fwd->mptcp_subflow->ssn2dsn_mappings,
6414 mapping->ssn_low,
6415 mapping->ssn_high,
6416 mapping
6421 * The TCP Extensions for Multipath Operation with Multiple Addresses
6422 * are defined in RFC 6824
6424 * https://tools.ietf.org/html/rfc6824
6426 * Author: Andrei Maruseac <andrei.maruseac@intel.com>
6427 * Matthieu Coudron <matthieu.coudron@lip6.fr>
6429 * This function just generates the mptcpheader, i.e. the generation of
6430 * datastructures is delayed/delegated to mptcp_analyze
6432 static int
6433 dissect_tcpopt_mptcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
6435 proto_item *item,*main_item;
6436 proto_tree *mptcp_tree;
6438 uint32_t version;
6439 uint8_t subtype;
6440 uint8_t ipver;
6441 int offset = 0;
6442 int optlen = tvb_reported_length(tvb);
6443 int start_offset = offset;
6444 struct tcp_analysis *tcpd = NULL;
6445 struct mptcp_analysis* mptcpd = NULL;
6446 struct tcpheader *tcph = (struct tcpheader *)data;
6448 /* There may be several MPTCP options per packet, don't duplicate the structure */
6449 struct mptcpheader* mph = tcph->th_mptcp;
6451 if(!mph) {
6452 mph = wmem_new0(pinfo->pool, struct mptcpheader);
6453 tcph->th_mptcp = mph;
6456 tcpd=get_tcp_conversation_data(NULL,pinfo);
6457 mptcpd=tcpd->mptcp_analysis;
6459 /* seeing an MPTCP packet on the subflow automatically qualifies it as an mptcp subflow */
6460 if(!tcpd->fwd->mptcp_subflow) {
6461 mptcp_init_subflow(tcpd->fwd);
6463 if(!tcpd->rev->mptcp_subflow) {
6464 mptcp_init_subflow(tcpd->rev);
6467 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPTCP");
6468 main_item = proto_tree_add_item(tree, proto_mptcp, tvb, offset, -1, ENC_NA);
6469 mptcp_tree = proto_item_add_subtree(main_item, ett_tcp_option_mptcp);
6471 proto_tree_add_item(mptcp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
6472 offset += 1;
6474 proto_tree_add_item(mptcp_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
6475 offset += 1;
6477 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_subtype, tvb,
6478 offset, 1, ENC_BIG_ENDIAN);
6480 subtype = tvb_get_uint8(tvb, offset) >> 4;
6481 proto_item_append_text(main_item, ": %s", val_to_str(subtype, mptcp_subtype_vs, "Unknown (%d)"));
6483 /** preemptively allocate mptcpd when subtype won't allow to find a meta */
6484 if(!mptcpd && (subtype > TCPOPT_MPTCP_MP_JOIN)) {
6485 mptcpd = mptcp_alloc_analysis(tcpd);
6488 switch (subtype) {
6489 case TCPOPT_MPTCP_MP_CAPABLE:
6490 mph->mh_mpc = true;
6492 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_version, tvb,
6493 offset, 1, ENC_BIG_ENDIAN, &version);
6494 offset += 1;
6496 item = proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6497 ett_tcp_option_mptcp,
6498 version == 1 ? tcp_option_mptcp_capable_v1_flags : tcp_option_mptcp_capable_v0_flags,
6499 ENC_BIG_ENDIAN);
6500 mph->mh_capable_flags = tvb_get_uint8(tvb, offset);
6501 if ((mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK) == 0) {
6502 expert_add_info(pinfo, item, &ei_mptcp_analysis_missing_algorithm);
6504 if ((mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK) != MPTCP_HMAC_SHA) {
6505 expert_add_info(pinfo, item, &ei_mptcp_analysis_unsupported_algorithm);
6507 offset += 1;
6509 /* optlen == 12 => SYN or SYN/ACK; optlen == 20 => ACK;
6510 * optlen == 22 => ACK + data (v1 only);
6511 * optlen == 24 => ACK + data + csum (v1 only)
6513 if (optlen == 12 || optlen == 20 || optlen == 22 || optlen == 24) {
6515 mph->mh_key = tvb_get_ntoh64(tvb,offset);
6516 proto_tree_add_uint64(mptcp_tree, hf_tcp_option_mptcp_sender_key, tvb, offset, 8, mph->mh_key);
6517 offset += 8;
6519 mptcpd = get_or_create_mptcpd_from_key(tcpd, tcpd->fwd, version, mph->mh_key, mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK);
6520 mptcpd->master = tcpd;
6522 item = proto_tree_add_uint(mptcp_tree,
6523 hf_mptcp_expected_token, tvb, offset, 0, tcpd->fwd->mptcp_subflow->meta->token);
6524 proto_item_set_generated(item);
6526 item = proto_tree_add_uint64(mptcp_tree,
6527 hf_mptcp_expected_idsn, tvb, offset, 0, tcpd->fwd->mptcp_subflow->meta->base_dsn);
6528 proto_item_set_generated(item);
6530 /* last ACK of 3WHS, repeats both keys */
6531 if (optlen >= 20) {
6532 uint64_t recv_key = tvb_get_ntoh64(tvb,offset);
6533 proto_tree_add_uint64(mptcp_tree, hf_tcp_option_mptcp_recv_key, tvb, offset, 8, recv_key);
6534 offset += 8;
6536 if(tcpd->rev->mptcp_subflow->meta
6537 && (tcpd->rev->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_KEY)) {
6539 /* compare the echoed key with the server key */
6540 if(tcpd->rev->mptcp_subflow->meta->key != recv_key) {
6541 expert_add_info(pinfo, item, &ei_mptcp_analysis_echoed_key_mismatch);
6544 else {
6545 mptcpd = get_or_create_mptcpd_from_key(tcpd, tcpd->rev, version, recv_key, mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK);
6549 /* MPTCP v1 ACK + data, contains data_len and optional checksum */
6550 if (optlen >= 22) {
6551 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_lvl_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6552 mph->mh_dss_length = tvb_get_ntohs(tvb,offset);
6553 offset += 2;
6555 if (mph->mh_dss_length == 0) {
6556 expert_add_info(pinfo, mptcp_tree, &ei_mptcp_infinite_mapping);
6559 /* when data len is present, this MP_CAPABLE also carries an implicit mapping ... */
6560 analyze_mapping(tcpd, pinfo, mph->mh_dss_length, tcpd->fwd->mptcp_subflow->meta->base_dsn + 1, true, tcph->th_seq);
6562 /* ... with optional checksum */
6563 if (optlen == 24)
6565 proto_tree_add_checksum(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
6569 break;
6571 case TCPOPT_MPTCP_MP_JOIN:
6572 mph->mh_join = true;
6573 if(optlen != 12 && !mptcpd) {
6574 mptcpd = mptcp_alloc_analysis(tcpd);
6576 switch (optlen) {
6577 /* Syn */
6578 case 12:
6580 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6581 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,
6582 ENC_BIG_ENDIAN);
6583 offset += 1;
6584 tcpd->fwd->mptcp_subflow->address_id = tvb_get_uint8(tvb, offset);
6585 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,
6586 1, ENC_BIG_ENDIAN);
6587 offset += 1;
6589 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_recv_token, tvb, offset,
6590 4, ENC_BIG_ENDIAN, &mph->mh_token);
6591 offset += 4;
6593 mptcpd = mptcp_get_meta_from_token(tcpd, tcpd->rev, mph->mh_token);
6594 if (tcpd->fwd->mptcp_subflow->meta->version == 1) {
6595 mptcp_meta_flow_t *tmp = tcpd->fwd->mptcp_subflow->meta;
6597 /* if the negotiated version is v1 the first key was exchanged on SYN/ACK packet: we must swap the meta */
6598 tcpd->fwd->mptcp_subflow->meta = tcpd->rev->mptcp_subflow->meta;
6599 tcpd->rev->mptcp_subflow->meta = tmp;
6602 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_sender_rand, tvb, offset,
6603 4, ENC_BIG_ENDIAN, &tcpd->fwd->mptcp_subflow->nonce);
6606 break;
6609 case 16: /* Syn/Ack */
6610 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6611 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,
6612 ENC_BIG_ENDIAN);
6613 offset += 1;
6615 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,
6616 1, ENC_BIG_ENDIAN);
6617 offset += 1;
6619 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_trunc_hmac, tvb, offset,
6620 8, ENC_BIG_ENDIAN);
6621 offset += 8;
6623 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_rand, tvb, offset,
6624 4, ENC_BIG_ENDIAN);
6625 break;
6627 case 24: /* Ack */
6628 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_reserved, tvb, offset,
6629 2, ENC_BIG_ENDIAN);
6630 offset += 2;
6632 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_hmac, tvb, offset,
6633 20, ENC_NA);
6634 break;
6636 default:
6637 break;
6639 break;
6641 /* display only *raw* values since it is harder to guess a correct value than for TCP.
6642 One needs to enable mptcp_analysis to get more interesting data
6644 case TCPOPT_MPTCP_DSS:
6645 mph->mh_dss = true;
6647 offset += 1;
6648 mph->mh_dss_flags = tvb_get_uint8(tvb, offset) & 0x1F;
6650 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6651 ett_tcp_option_mptcp, tcp_option_mptcp_dss_flags,
6652 ENC_BIG_ENDIAN);
6653 offset += 1;
6655 /* displays "raw" DataAck , ie does not convert it to its 64 bits form
6656 to do so you need to enable
6658 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_PRESENT) {
6660 uint64_t dack64;
6662 /* 64bits ack */
6663 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES) {
6665 mph->mh_dss_rawack = tvb_get_ntoh64(tvb,offset);
6666 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);
6667 offset += 8;
6669 /* 32bits ack */
6670 else {
6671 mph->mh_dss_rawack = tvb_get_ntohl(tvb,offset);
6672 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_ack_raw, tvb, offset, 4, ENC_BIG_ENDIAN);
6673 offset += 4;
6676 if(mptcp_convert_dsn(mph->mh_dss_rawack, tcpd->rev->mptcp_subflow->meta,
6677 (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES) ? DSN_CONV_NONE : DSN_CONV_32_TO_64, mptcp_relative_seq, &dack64)) {
6678 item = proto_tree_add_uint64(mptcp_tree, hf_mptcp_ack, tvb, 0, 0, dack64);
6679 if (mptcp_relative_seq) {
6680 proto_item_append_text(item, " (Relative)");
6683 proto_item_set_generated(item);
6685 else {
6686 /* ignore and continue */
6691 /* Mapping present */
6692 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_MAPPING_PRESENT) {
6694 uint64_t dsn;
6696 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DSN_8BYTES) {
6698 dsn = tvb_get_ntoh64(tvb,offset);
6699 proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 8, dsn, "%" PRIu64 " (64bits version)", dsn);
6701 /* if we have the opportunity to complete the 32 Most Significant Bits of the
6704 if(!(tcpd->fwd->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_BASE_DSN_MSB)) {
6705 tcpd->fwd->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_BASE_DSN_MSB;
6706 tcpd->fwd->mptcp_subflow->meta->base_dsn |= (dsn & (uint32_t) 0);
6708 offset += 8;
6709 } else {
6710 dsn = tvb_get_ntohl(tvb,offset);
6711 proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 4, dsn, "%" PRIu64 " (32bits version)", dsn);
6712 offset += 4;
6714 mph->mh_dss_rawdsn = dsn;
6716 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);
6717 offset += 4;
6719 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_lvl_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6720 mph->mh_dss_length = tvb_get_ntohs(tvb,offset);
6721 offset += 2;
6723 if(mph->mh_dss_length == 0) {
6724 expert_add_info(pinfo, mptcp_tree, &ei_mptcp_infinite_mapping);
6727 /* print head & tail dsn */
6728 if(mptcp_convert_dsn(mph->mh_dss_rawdsn, tcpd->fwd->mptcp_subflow->meta,
6729 (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES) ? DSN_CONV_NONE : DSN_CONV_32_TO_64, mptcp_relative_seq, &dsn)) {
6730 item = proto_tree_add_uint64(mptcp_tree, hf_mptcp_dss_dsn, tvb, 0, 0, dsn);
6731 if (mptcp_relative_seq) {
6732 proto_item_append_text(item, " (Relative)");
6735 proto_item_set_generated(item);
6737 else {
6738 /* ignore and continue */
6741 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);
6743 if ((int)optlen >= offset-start_offset+4)
6745 proto_tree_add_checksum(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
6748 break;
6750 case TCPOPT_MPTCP_ADD_ADDR:
6751 mph->mh_add = true;
6752 ipver = tvb_get_uint8(tvb, offset) & 0x0F;
6753 if (ipver == 4 || ipver == 6)
6754 proto_tree_add_item(mptcp_tree,
6755 hf_tcp_option_mptcp_ipver, tvb, offset, 1, ENC_BIG_ENDIAN);
6756 else
6757 proto_tree_add_item(mptcp_tree,
6758 hf_tcp_option_mptcp_echo, tvb, offset, 1, ENC_BIG_ENDIAN);
6759 offset += 1;
6761 proto_tree_add_item(mptcp_tree,
6762 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN);
6763 offset += 1;
6765 if (optlen == 8 || optlen == 10 || optlen == 16 || optlen == 18) {
6766 proto_tree_add_item(mptcp_tree,
6767 hf_tcp_option_mptcp_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
6768 offset += 4;
6771 if (optlen == 20 || optlen == 22 || optlen == 28 || optlen == 30) {
6772 proto_tree_add_item(mptcp_tree,
6773 hf_tcp_option_mptcp_ipv6, tvb, offset, 16, ENC_NA);
6774 offset += 16;
6777 if (optlen == 10 || optlen == 18 || optlen == 22 || optlen == 30) {
6778 proto_tree_add_item(mptcp_tree,
6779 hf_tcp_option_mptcp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
6780 offset += 2;
6783 if (optlen == 16 || optlen == 18 || optlen == 28 || optlen == 30) {
6784 proto_tree_add_item(mptcp_tree,
6785 hf_tcp_option_mptcp_addaddr_trunc_hmac, tvb, offset, 8, ENC_BIG_ENDIAN);
6787 break;
6789 case TCPOPT_MPTCP_REMOVE_ADDR:
6790 mph->mh_remove = true;
6791 item = proto_tree_add_uint(mptcp_tree, hf_mptcp_number_of_removed_addresses, tvb, start_offset+2,
6792 1, optlen - 3);
6793 proto_item_set_generated(item);
6794 offset += 1;
6795 while(offset < start_offset + (int)optlen) {
6796 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,
6797 1, ENC_BIG_ENDIAN);
6798 offset += 1;
6800 break;
6802 case TCPOPT_MPTCP_MP_PRIO:
6803 mph->mh_prio = true;
6804 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6805 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,
6806 ENC_BIG_ENDIAN);
6807 offset += 1;
6809 if (optlen == 4) {
6810 proto_tree_add_item(mptcp_tree,
6811 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN);
6813 break;
6815 case TCPOPT_MPTCP_MP_FAIL:
6816 mph->mh_fail = true;
6817 proto_tree_add_item(mptcp_tree,
6818 hf_tcp_option_mptcp_reserved, tvb, offset,2, ENC_BIG_ENDIAN);
6819 offset += 2;
6821 proto_tree_add_item(mptcp_tree,
6822 hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 8, ENC_BIG_ENDIAN);
6823 break;
6825 case TCPOPT_MPTCP_MP_FASTCLOSE:
6826 mph->mh_fastclose = true;
6827 proto_tree_add_item(mptcp_tree,
6828 hf_tcp_option_mptcp_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
6829 offset += 2;
6831 proto_tree_add_item(mptcp_tree,
6832 hf_tcp_option_mptcp_recv_key, tvb, offset, 8, ENC_BIG_ENDIAN);
6833 mph->mh_key = tvb_get_ntoh64(tvb,offset);
6834 break;
6836 case TCPOPT_MPTCP_MP_TCPRST:
6837 mph->mh_tcprst = true;
6838 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6839 ett_tcp_option_mptcp, tcp_option_mptcp_tcprst_flags,
6840 ENC_BIG_ENDIAN);
6841 offset += 1;
6842 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_tcprst_reason, tvb, offset, 1,
6843 ENC_BIG_ENDIAN);
6844 break;
6846 default:
6847 break;
6850 if ((mptcpd != NULL) && (tcpd->mptcp_analysis != NULL)) {
6852 /* if mptcpd just got allocated, remember the initial addresses
6853 * which will serve as identifiers for the conversation filter
6855 if(tcpd->fwd->mptcp_subflow->meta->ip_src.len == 0) {
6857 copy_address_wmem(wmem_file_scope(), &tcpd->fwd->mptcp_subflow->meta->ip_src, &tcph->ip_src);
6858 copy_address_wmem(wmem_file_scope(), &tcpd->fwd->mptcp_subflow->meta->ip_dst, &tcph->ip_dst);
6860 copy_address_shallow(&tcpd->rev->mptcp_subflow->meta->ip_src, &tcpd->fwd->mptcp_subflow->meta->ip_dst);
6861 copy_address_shallow(&tcpd->rev->mptcp_subflow->meta->ip_dst, &tcpd->fwd->mptcp_subflow->meta->ip_src);
6863 tcpd->fwd->mptcp_subflow->meta->sport = tcph->th_sport;
6864 tcpd->fwd->mptcp_subflow->meta->dport = tcph->th_dport;
6867 mph->mh_stream = tcpd->mptcp_analysis->stream;
6870 return tvb_captured_length(tvb);
6873 static int
6874 dissect_tcpopt_cc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6876 proto_tree *field_tree;
6877 proto_item *item;
6878 proto_item *length_item;
6879 int offset = 0;
6880 uint32_t cc;
6882 item = proto_tree_add_item(tree, proto_tcp_option_cc, tvb, offset, -1, ENC_NA);
6883 field_tree = proto_item_add_subtree(item, ett_tcp_opt_cc);
6885 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6886 offset, 1, ENC_BIG_ENDIAN);
6887 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6888 offset + 1, 1, ENC_BIG_ENDIAN);
6890 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_CC))
6891 return tvb_captured_length(tvb);
6893 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_cc, tvb,
6894 offset + 2, 4, ENC_BIG_ENDIAN, &cc);
6896 tcp_info_append_uint(pinfo, "CC", cc);
6897 return tvb_captured_length(tvb);
6900 static int
6901 dissect_tcpopt_md5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6903 proto_tree *field_tree;
6904 proto_item *item;
6905 proto_item *length_item;
6906 int offset = 0, optlen = tvb_reported_length(tvb);
6908 item = proto_tree_add_item(tree, proto_tcp_option_md5, tvb, offset, -1, ENC_NA);
6909 field_tree = proto_item_add_subtree(item, ett_tcp_opt_md5);
6911 col_append_lstr(pinfo->cinfo, COL_INFO, " MD5", COL_ADD_LSTR_TERMINATOR);
6912 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6913 offset, 1, ENC_BIG_ENDIAN);
6914 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6915 offset + 1, 1, ENC_BIG_ENDIAN);
6917 if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_MD5))
6918 return tvb_captured_length(tvb);
6920 proto_tree_add_item(field_tree, hf_tcp_option_md5_digest, tvb,
6921 offset + 2, optlen - 2, ENC_NA);
6923 return tvb_captured_length(tvb);
6926 static int
6927 dissect_tcpopt_ao(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6929 proto_tree *field_tree;
6930 proto_item *item;
6931 proto_item *length_item;
6932 int offset = 0, optlen = tvb_reported_length(tvb);
6934 item = proto_tree_add_item(tree, proto_tcp_option_ao, tvb, offset, -1, ENC_NA);
6935 field_tree = proto_item_add_subtree(item, ett_tcp_opt_ao);
6937 col_append_lstr(pinfo->cinfo, COL_INFO, "TCP AO", COL_ADD_LSTR_TERMINATOR);
6938 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6939 offset, 1, ENC_BIG_ENDIAN);
6940 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6941 offset + 1, 1, ENC_BIG_ENDIAN);
6943 if (optlen < 4) {
6944 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
6945 "option length should be >= than 4");
6946 return tvb_captured_length(tvb);
6949 proto_tree_add_item(field_tree, hf_tcp_option_ao_keyid, tvb,
6950 offset + 2, 1, ENC_NA);
6952 proto_tree_add_item(field_tree, hf_tcp_option_ao_rnextkeyid, tvb,
6953 offset + 3, 1, ENC_NA);
6955 if (optlen > 4)
6956 proto_tree_add_item(field_tree, hf_tcp_option_ao_mac, tvb,
6957 offset + 4, optlen - 4, ENC_NA);
6959 return tvb_captured_length(tvb);
6962 static int
6963 dissect_tcpopt_qs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6965 proto_tree *field_tree;
6966 proto_item *item;
6967 proto_item *length_item;
6968 uint8_t rate;
6969 int offset = 0;
6971 item = proto_tree_add_item(tree, proto_tcp_option_qs, tvb, offset, -1, ENC_NA);
6972 field_tree = proto_item_add_subtree(item, ett_tcp_opt_qs);
6974 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6975 offset, 1, ENC_BIG_ENDIAN);
6976 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6977 offset + 1, 1, ENC_BIG_ENDIAN);
6979 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_QS))
6980 return tvb_captured_length(tvb);
6982 rate = tvb_get_uint8(tvb, offset + 2) & 0x0f;
6983 col_append_lstr(pinfo->cinfo, COL_INFO,
6984 " QSresp=", val_to_str_ext_const(rate, &qs_rate_vals_ext, "Unknown"),
6985 COL_ADD_LSTR_TERMINATOR);
6986 proto_tree_add_item(field_tree, hf_tcp_option_qs_rate, tvb,
6987 offset + 2, 1, ENC_BIG_ENDIAN);
6988 proto_tree_add_item(field_tree, hf_tcp_option_qs_ttl_diff, tvb,
6989 offset + 3, 1, ENC_BIG_ENDIAN);
6991 return tvb_captured_length(tvb);
6994 static int
6995 dissect_tcpopt_scps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6997 struct tcp_analysis *tcpd;
6998 proto_tree *field_tree = NULL;
6999 tcp_flow_t *flow;
7000 int direction;
7001 proto_item *tf = NULL, *item;
7002 proto_tree *flags_tree = NULL;
7003 uint8_t capvector;
7004 uint8_t connid;
7005 int offset = 0, optlen = tvb_reported_length(tvb);
7007 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
7008 tcpd=get_tcp_conversation_data_idempotent(stratconv);
7010 /* check direction and get ua lists */
7011 direction=cmp_address(&pinfo->src, &pinfo->dst);
7013 /* if the addresses are equal, match the ports instead */
7014 if(direction==0) {
7015 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
7018 if(direction>=0)
7019 flow =&(tcpd->flow1);
7020 else
7021 flow =&(tcpd->flow2);
7023 item = proto_tree_add_item(tree, proto_tcp_option_scps,
7024 tvb, offset, -1, ENC_NA);
7025 field_tree = proto_item_add_subtree(item, ett_tcp_option_scps);
7027 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7028 offset, 1, ENC_BIG_ENDIAN);
7029 proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7030 offset + 1, 1, ENC_BIG_ENDIAN);
7032 /* If the option length == 4, this is a real SCPS capability option
7033 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
7034 * (SCPS-TP)" Section 3.2.3 for definition.
7036 if (optlen == 4) {
7037 tf = proto_tree_add_item(field_tree, hf_tcp_option_scps_vector, tvb,
7038 offset + 2, 1, ENC_BIG_ENDIAN);
7039 flags_tree = proto_item_add_subtree(tf, ett_tcp_scpsoption_flags);
7040 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_bets, tvb,
7041 offset + 2, 1, ENC_BIG_ENDIAN);
7042 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack1, tvb,
7043 offset + 2, 1, ENC_BIG_ENDIAN);
7044 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack2, tvb,
7045 offset + 2, 1, ENC_BIG_ENDIAN);
7046 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_compress, tvb,
7047 offset + 2, 1, ENC_BIG_ENDIAN);
7048 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_nlts, tvb,
7049 offset + 2, 1, ENC_BIG_ENDIAN);
7050 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_reserved, tvb,
7051 offset + 2, 1, ENC_BIG_ENDIAN);
7052 capvector = tvb_get_uint8(tvb, offset + 2);
7054 if (capvector) {
7055 struct capvec
7057 uint8_t mask;
7058 const char *str;
7059 } capvecs[] = {
7060 {0x80, "BETS"},
7061 {0x40, "SNACK1"},
7062 {0x20, "SNACK2"},
7063 {0x10, "COMP"},
7064 {0x08, "NLTS"},
7065 {0x07, "RESERVED"}
7067 bool anyflag = false;
7068 unsigned i;
7070 col_append_str(pinfo->cinfo, COL_INFO, " SCPS[");
7071 for (i = 0; i < array_length(capvecs); i++) {
7072 if (capvector & capvecs[i].mask) {
7073 proto_item_append_text(tf, "%s%s", anyflag ? ", " : " (",
7074 capvecs[i].str);
7075 col_append_lstr(pinfo->cinfo, COL_INFO,
7076 anyflag ? ", " : "",
7077 capvecs[i].str,
7078 COL_ADD_LSTR_TERMINATOR);
7079 anyflag = true;
7082 col_append_str(pinfo->cinfo, COL_INFO, "]");
7083 proto_item_append_text(tf, ")");
7086 proto_tree_add_item(field_tree, hf_tcp_scpsoption_connection_id, tvb,
7087 offset + 3, 1, ENC_BIG_ENDIAN);
7088 connid = tvb_get_uint8(tvb, offset + 3);
7089 flow->scps_capable = true;
7091 if (connid)
7092 tcp_info_append_uint(pinfo, "Connection ID", connid);
7093 } else {
7094 /* The option length != 4, so this is an infamous "extended capabilities
7095 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
7096 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
7098 * As the format of this option is only partially defined (it is
7099 * a community (or more likely vendor) defined format beyond that, so
7100 * at least for now, we only parse the standardized portion of the option.
7102 uint8_t local_offset = 2;
7103 uint8_t binding_space;
7104 uint8_t extended_cap_length;
7106 if (!flow->scps_capable) {
7107 /* There was no SCPS capabilities option preceding this */
7108 proto_item_set_text(item,
7109 "Illegal SCPS Extended Capabilities (%u bytes)",
7110 optlen);
7111 } else {
7112 proto_item_set_text(item,
7113 "SCPS Extended Capabilities (%u bytes)",
7114 optlen);
7116 /* There may be multiple binding spaces included in a single option,
7117 * so we will semi-parse each of the stacked binding spaces - skipping
7118 * over the octets following the binding space identifier and length.
7120 while (optlen > local_offset) {
7122 /* 1st octet is Extended Capability Binding Space */
7123 binding_space = tvb_get_uint8(tvb, (offset + local_offset));
7125 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
7126 * As defined by the specification, this length is exclusive of the
7127 * octets containing the extended capability type and length
7129 extended_cap_length =
7130 (tvb_get_uint8(tvb, (offset + local_offset + 1)) >> 4);
7132 /* Convert the extended capabilities length into bytes for display */
7133 extended_cap_length = (extended_cap_length << 1);
7135 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding, tvb, offset + local_offset, 1, ENC_BIG_ENDIAN);
7136 proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding_len, tvb, offset + local_offset + 1, 1, extended_cap_length);
7138 /* Step past the binding space and length octets */
7139 local_offset += 2;
7141 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding_data, tvb, offset + local_offset, extended_cap_length, ENC_NA);
7143 tcp_info_append_uint(pinfo, "EXCAP", binding_space);
7145 /* Step past the Extended capability data
7146 * Treat the extended capability data area as opaque;
7147 * If one desires to parse the extended capability data
7148 * (say, in a vendor aware build of wireshark), it would
7149 * be triggered here.
7151 local_offset += extended_cap_length;
7156 return tvb_captured_length(tvb);
7159 static int
7160 dissect_tcpopt_user_to(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
7162 proto_item *tf;
7163 proto_tree *field_tree;
7164 proto_item *length_item;
7165 uint16_t to;
7166 int offset = 0;
7168 tf = proto_tree_add_item(tree, proto_tcp_option_user_to, tvb, offset, -1, ENC_NA);
7169 field_tree = proto_item_add_subtree(tf, ett_tcp_option_user_to);
7171 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7172 offset, 1, ENC_BIG_ENDIAN);
7173 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7174 offset + 1, 1, ENC_BIG_ENDIAN);
7176 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_USER_TO))
7177 return tvb_captured_length(tvb);
7179 proto_tree_add_item(field_tree, hf_tcp_option_user_to_granularity, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
7180 to = tvb_get_ntohs(tvb, offset + 2) & 0x7FFF;
7181 proto_tree_add_item(field_tree, hf_tcp_option_user_to_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
7183 tcp_info_append_uint(pinfo, "USER_TO", to);
7184 return tvb_captured_length(tvb);
7187 /* This is called for SYN+ACK packets and the purpose is to verify that
7188 * the SCPS capabilities option has been successfully negotiated for the flow.
7189 * If the SCPS capabilities option was offered by only one party, the
7190 * proactively set scps_capable attribute of the flow (set upon seeing
7191 * the first instance of the SCPS option) is revoked.
7193 static void
7194 verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd)
7196 tf_syn = 0x0;
7198 if(tcpd) {
7199 if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) {
7200 tcpd->flow1.scps_capable = false;
7201 tcpd->flow2.scps_capable = false;
7202 } else {
7203 expert_add_info(pinfo, tf_syn, &ei_tcp_scps_capable);
7208 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
7209 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
7211 static int
7212 dissect_tcpopt_snack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
7214 struct tcp_analysis *tcpd=NULL;
7215 uint32_t relative_hole_offset;
7216 uint32_t relative_hole_size;
7217 uint16_t base_mss = 0;
7218 uint32_t ack;
7219 uint32_t hole_start;
7220 uint32_t hole_end;
7221 int offset = 0;
7222 proto_item *hidden_item, *tf;
7223 proto_tree *field_tree;
7224 proto_item *length_item;
7226 tf = proto_tree_add_item(tree, proto_tcp_option_snack, tvb, offset, -1, ENC_NA);
7227 field_tree = proto_item_add_subtree(tf, ett_tcp_option_snack);
7229 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7230 offset, 1, ENC_BIG_ENDIAN);
7231 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7232 offset + 1, 1, ENC_BIG_ENDIAN);
7234 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SNACK))
7235 return tvb_captured_length(tvb);
7237 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
7238 tcpd=get_tcp_conversation_data_idempotent(stratconv);
7240 /* The SNACK option reports missing data with a granularity of segments. */
7241 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_snack_offset,
7242 tvb, offset + 2, 2, ENC_BIG_ENDIAN, &relative_hole_offset);
7244 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_snack_size,
7245 tvb, offset + 4, 2, ENC_BIG_ENDIAN, &relative_hole_size);
7247 ack = tvb_get_ntohl(tvb, 8);
7249 if (tcp_analyze_seq && tcp_relative_seq) {
7250 ack -= tcpd->rev->base_seq;
7253 /* To aid analysis, we can use a simple but generally effective heuristic
7254 * to report the most likely boundaries of the missing data. If the
7255 * flow is scps_capable, we track the maximum sized segment that was
7256 * acknowledged by the receiver and use that as the reporting granularity.
7257 * This may be different from the negotiated MTU due to PMTUD or flows
7258 * that do not send max-sized segments.
7260 base_mss = tcpd->fwd->maxsizeacked;
7262 if (base_mss) {
7263 /* Scale the reported offset and hole size by the largest segment acked */
7264 hole_start = ack + (base_mss * relative_hole_offset);
7265 hole_end = hole_start + (base_mss * relative_hole_size);
7267 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_snack_le,
7268 tvb, offset + 2, 2, hole_start);
7269 proto_item_set_hidden(hidden_item);
7271 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_snack_re,
7272 tvb, offset + 4, 2, hole_end);
7273 proto_item_set_hidden(hidden_item);
7275 proto_tree_add_expert_format(field_tree, pinfo, &ei_tcp_option_snack_sequence, tvb, offset+2, 4,
7276 "SNACK Sequence %u - %u%s", hole_start, hole_end, ((tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : ""));
7278 tcp_info_append_uint(pinfo, "SNLE", hole_start);
7279 tcp_info_append_uint(pinfo, "SNRE", hole_end);
7282 return tvb_captured_length(tvb);
7285 enum
7287 PROBE_VERSION_UNSPEC = 0,
7288 PROBE_VERSION_1 = 1,
7289 PROBE_VERSION_2 = 2,
7290 PROBE_VERSION_MAX
7293 /* Probe type definition. */
7294 enum
7296 PROBE_QUERY = 0,
7297 PROBE_RESPONSE = 1,
7298 PROBE_INTERNAL = 2,
7299 PROBE_TRACE = 3,
7300 PROBE_QUERY_SH = 4,
7301 PROBE_RESPONSE_SH = 5,
7302 PROBE_QUERY_INFO = 6,
7303 PROBE_RESPONSE_INFO = 7,
7304 PROBE_QUERY_INFO_SH = 8,
7305 PROBE_QUERY_INFO_SID = 9,
7306 PROBE_RST = 10,
7307 PROBE_TYPE_MAX
7310 static const value_string rvbd_probe_type_vs[] = {
7311 { PROBE_QUERY, "Probe Query" },
7312 { PROBE_RESPONSE, "Probe Response" },
7313 { PROBE_INTERNAL, "Probe Internal" },
7314 { PROBE_TRACE, "Probe Trace" },
7315 { PROBE_QUERY_SH, "Probe Query SH" },
7316 { PROBE_RESPONSE_SH, "Probe Response SH" },
7317 { PROBE_QUERY_INFO, "Probe Query Info" },
7318 { PROBE_RESPONSE_INFO, "Probe Response Info" },
7319 { PROBE_QUERY_INFO_SH, "Probe Query Info SH" },
7320 { PROBE_QUERY_INFO_SID, "Probe Query Info Store ID" },
7321 { PROBE_RST, "Probe Reset" },
7322 { 0, NULL }
7325 #define PROBE_OPTLEN_OFFSET 1
7327 #define PROBE_VERSION_TYPE_OFFSET 2
7328 #define PROBE_V1_RESERVED_OFFSET 3
7329 #define PROBE_V1_PROBER_OFFSET 4
7330 #define PROBE_V1_APPLI_VERSION_OFFSET 8
7331 #define PROBE_V1_PROXY_ADDR_OFFSET 8
7332 #define PROBE_V1_PROXY_PORT_OFFSET 12
7333 #define PROBE_V1_SH_CLIENT_ADDR_OFFSET 8
7334 #define PROBE_V1_SH_PROXY_ADDR_OFFSET 12
7335 #define PROBE_V1_SH_PROXY_PORT_OFFSET 16
7337 #define PROBE_V2_INFO_OFFSET 3
7339 #define PROBE_V2_INFO_CLIENT_ADDR_OFFSET 4
7340 #define PROBE_V2_INFO_STOREID_OFFSET 4
7342 #define PROBE_VERSION_MASK 0x01
7344 /* Probe Query Extra Info flags */
7345 #define RVBD_FLAGS_PROBE_LAST 0x01
7346 #define RVBD_FLAGS_PROBE_NCFE 0x04
7348 /* Probe Response Extra Info flags */
7349 #define RVBD_FLAGS_PROBE_SERVER 0x01
7350 #define RVBD_FLAGS_PROBE_SSLCERT 0x02
7351 #define RVBD_FLAGS_PROBE 0x10
7353 typedef struct rvbd_option_data
7355 bool valid;
7356 uint8_t type;
7357 uint8_t probe_flags;
7359 } rvbd_option_data;
7361 static void
7362 rvbd_probe_decode_version_type(const uint8_t vt, uint8_t *ver, uint8_t *type)
7364 if (vt & PROBE_VERSION_MASK) {
7365 *ver = PROBE_VERSION_1;
7366 *type = vt >> 4;
7367 } else {
7368 *ver = PROBE_VERSION_2;
7369 *type = vt >> 1;
7373 static void
7374 rvbd_probe_resp_add_info(proto_item *pitem, packet_info *pinfo, tvbuff_t *tvb, int ip_offset, uint16_t port)
7376 proto_item_append_text(pitem, ", Server Steelhead: %s:%u", tvb_ip_to_str(pinfo->pool, tvb, ip_offset), port);
7378 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA+, ");
7381 static int
7382 dissect_tcpopt_rvbd_probe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
7384 uint8_t ver, type;
7385 proto_tree *field_tree;
7386 proto_item *pitem;
7387 proto_item *length_item;
7388 int offset = 0,
7389 optlen = tvb_reported_length(tvb);
7390 struct tcpheader *tcph = (struct tcpheader*)data;
7392 pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_probe, tvb, offset, -1, ENC_NA);
7393 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe);
7395 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7396 offset, 1, ENC_BIG_ENDIAN);
7397 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7398 offset + 1, 1, ENC_BIG_ENDIAN);
7400 if (optlen < TCPOLEN_RVBD_PROBE_MIN) {
7401 /* Bogus - option length is less than what it's supposed to be for
7402 this option. */
7403 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
7404 "option length should be >= %u)",
7405 TCPOLEN_RVBD_PROBE_MIN);
7406 return tvb_captured_length(tvb);
7409 rvbd_probe_decode_version_type(
7410 tvb_get_uint8(tvb, offset + PROBE_VERSION_TYPE_OFFSET),
7411 &ver, &type);
7413 proto_item_append_text(pitem, ": %s", val_to_str_const(type, rvbd_probe_type_vs, "Probe Unknown"));
7415 if (type >= PROBE_TYPE_MAX)
7416 return tvb_captured_length(tvb);
7418 if (ver == PROBE_VERSION_1) {
7419 uint16_t port;
7421 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type1, tvb,
7422 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
7423 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
7424 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
7426 if (type == PROBE_INTERNAL)
7427 return offset + PROBE_VERSION_TYPE_OFFSET;
7429 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_reserved, tvb, offset + PROBE_V1_RESERVED_OFFSET, 1, ENC_BIG_ENDIAN);
7431 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_prober, tvb,
7432 offset + PROBE_V1_PROBER_OFFSET, 4, ENC_BIG_ENDIAN);
7434 switch (type) {
7436 case PROBE_QUERY:
7437 case PROBE_QUERY_SH:
7438 case PROBE_TRACE:
7440 rvbd_option_data* option_data;
7441 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_appli_ver, tvb,
7442 offset + PROBE_V1_APPLI_VERSION_OFFSET, 2,
7443 ENC_BIG_ENDIAN);
7445 proto_item_append_text(pitem, ", CSH IP: %s", tvb_ip_to_str(pinfo->pool, tvb, offset + PROBE_V1_PROBER_OFFSET));
7447 option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);
7448 if (option_data == NULL)
7450 option_data = wmem_new0(pinfo->pool, rvbd_option_data);
7451 p_add_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num, option_data);
7454 option_data->valid = true;
7455 option_data->type = type;
7458 break;
7460 case PROBE_RESPONSE:
7461 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
7462 offset + PROBE_V1_PROXY_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
7464 port = tvb_get_ntohs(tvb, offset + PROBE_V1_PROXY_PORT_OFFSET);
7465 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
7466 offset + PROBE_V1_PROXY_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7468 rvbd_probe_resp_add_info(pitem, pinfo, tvb, offset + PROBE_V1_PROXY_ADDR_OFFSET, port);
7469 break;
7471 case PROBE_RESPONSE_SH:
7472 proto_tree_add_item(field_tree,
7473 hf_tcp_option_rvbd_probe_client, tvb,
7474 offset + PROBE_V1_SH_CLIENT_ADDR_OFFSET, 4,
7475 ENC_BIG_ENDIAN);
7477 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
7478 offset + PROBE_V1_SH_PROXY_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
7480 port = tvb_get_ntohs(tvb, offset + PROBE_V1_SH_PROXY_PORT_OFFSET);
7481 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
7482 offset + PROBE_V1_SH_PROXY_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7484 rvbd_probe_resp_add_info(pitem, pinfo, tvb, offset + PROBE_V1_SH_PROXY_ADDR_OFFSET, port);
7485 break;
7488 else if (ver == PROBE_VERSION_2) {
7489 proto_item *ver_pi;
7490 proto_item *flag_pi;
7491 proto_tree *flag_tree;
7492 uint8_t flags;
7494 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type2, tvb,
7495 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
7497 proto_tree_add_uint_format_value(
7498 field_tree, hf_tcp_option_rvbd_probe_version2, tvb,
7499 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver, "%u", ver);
7500 /* Use version1 for filtering purposes because version2 packet
7501 value is 0, but filtering is usually done for value 2 */
7502 ver_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
7503 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver);
7504 proto_item_set_hidden(ver_pi);
7506 switch (type) {
7508 case PROBE_QUERY_INFO:
7509 case PROBE_QUERY_INFO_SH:
7510 case PROBE_QUERY_INFO_SID:
7511 flags = tvb_get_uint8(tvb, offset + PROBE_V2_INFO_OFFSET);
7512 flag_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_flags,
7513 tvb, offset + PROBE_V2_INFO_OFFSET,
7514 1, flags);
7516 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
7517 proto_tree_add_item(flag_tree,
7518 hf_tcp_option_rvbd_probe_flag_not_cfe,
7519 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7520 proto_tree_add_item(flag_tree,
7521 hf_tcp_option_rvbd_probe_flag_last_notify,
7522 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7524 switch (type)
7526 case PROBE_QUERY_INFO:
7528 rvbd_option_data* option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);
7529 if (option_data == NULL)
7531 option_data = wmem_new0(pinfo->pool, rvbd_option_data);
7532 p_add_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num, option_data);
7535 option_data->probe_flags = flags;
7537 break;
7538 case PROBE_QUERY_INFO_SH:
7539 proto_tree_add_item(flag_tree,
7540 hf_tcp_option_rvbd_probe_client, tvb,
7541 offset + PROBE_V2_INFO_CLIENT_ADDR_OFFSET,
7542 4, ENC_BIG_ENDIAN);
7543 break;
7544 case PROBE_QUERY_INFO_SID:
7545 proto_tree_add_item(flag_tree,
7546 hf_tcp_option_rvbd_probe_storeid, tvb,
7547 offset + PROBE_V2_INFO_STOREID_OFFSET,
7548 4, ENC_BIG_ENDIAN);
7549 break;
7552 if (type != PROBE_QUERY_INFO_SID &&
7553 tcph != NULL &&
7554 (tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK) &&
7555 (flags & RVBD_FLAGS_PROBE_LAST)) {
7556 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA++, ");
7559 break;
7561 case PROBE_RESPONSE_INFO:
7562 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
7563 tvb, offset + PROBE_V2_INFO_OFFSET,
7564 1, ENC_BIG_ENDIAN);
7566 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
7567 proto_tree_add_item(flag_tree,
7568 hf_tcp_option_rvbd_probe_flag_probe_cache,
7569 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7570 proto_tree_add_item(flag_tree,
7571 hf_tcp_option_rvbd_probe_flag_sslcert,
7572 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7573 proto_tree_add_item(flag_tree,
7574 hf_tcp_option_rvbd_probe_flag_server_connected,
7575 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7576 break;
7578 case PROBE_RST:
7579 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
7580 tvb, offset + PROBE_V2_INFO_OFFSET,
7581 1, ENC_BIG_ENDIAN);
7582 break;
7586 return tvb_captured_length(tvb);
7589 enum {
7590 TRPY_OPTNUM_OFFSET = 0,
7591 TRPY_OPTLEN_OFFSET = 1,
7593 TRPY_OPTIONS_OFFSET = 2,
7594 TRPY_SRC_ADDR_OFFSET = 4,
7595 TRPY_DST_ADDR_OFFSET = 8,
7596 TRPY_SRC_PORT_OFFSET = 12,
7597 TRPY_DST_PORT_OFFSET = 14,
7598 TRPY_CLIENT_PORT_OFFSET = 16
7601 /* Trpy Flags */
7602 #define RVBD_FLAGS_TRPY_MODE 0x0001
7603 #define RVBD_FLAGS_TRPY_OOB 0x0002
7604 #define RVBD_FLAGS_TRPY_CHKSUM 0x0004
7605 #define RVBD_FLAGS_TRPY_FW_RST 0x0100
7606 #define RVBD_FLAGS_TRPY_FW_RST_INNER 0x0200
7607 #define RVBD_FLAGS_TRPY_FW_RST_PROBE 0x0400
7609 static const true_false_string trpy_mode_str = {
7610 "Port Transparency",
7611 "Full Transparency"
7614 static int
7615 dissect_tcpopt_rvbd_trpy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
7617 proto_tree *field_tree;
7618 proto_item *pitem;
7619 proto_item *length_item;
7620 uint16_t sport, dport, flags;
7621 int offset = 0,
7622 optlen = tvb_reported_length(tvb);
7623 static int * const rvbd_trpy_flags[] = {
7624 &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
7625 &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
7626 &hf_tcp_option_rvbd_trpy_flag_fw_rst,
7627 &hf_tcp_option_rvbd_trpy_flag_chksum,
7628 &hf_tcp_option_rvbd_trpy_flag_oob,
7629 &hf_tcp_option_rvbd_trpy_flag_mode,
7630 NULL
7633 col_prepend_fstr(pinfo->cinfo, COL_INFO, "TRPY, ");
7635 pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_trpy, tvb, offset, -1, ENC_NA);
7636 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_trpy);
7638 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7639 offset, 1, ENC_BIG_ENDIAN);
7640 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7641 offset + 1, 1, ENC_BIG_ENDIAN);
7643 if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_RVBD_TRPY_MIN))
7644 return tvb_captured_length(tvb);
7646 flags = tvb_get_ntohs(tvb, offset + TRPY_OPTIONS_OFFSET);
7647 proto_tree_add_bitmask_with_flags(field_tree, tvb, offset + TRPY_OPTIONS_OFFSET, hf_tcp_option_rvbd_trpy_flags,
7648 ett_tcp_opt_rvbd_trpy_flags, rvbd_trpy_flags, ENC_NA, BMT_NO_APPEND);
7650 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src,
7651 tvb, offset + TRPY_SRC_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
7653 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst,
7654 tvb, offset + TRPY_DST_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
7656 sport = tvb_get_ntohs(tvb, offset + TRPY_SRC_PORT_OFFSET);
7657 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src_port,
7658 tvb, offset + TRPY_SRC_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7660 dport = tvb_get_ntohs(tvb, offset + TRPY_DST_PORT_OFFSET);
7661 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst_port,
7662 tvb, offset + TRPY_DST_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7664 proto_item_append_text(pitem, " %s:%u -> %s:%u",
7665 tvb_ip_to_str(pinfo->pool, tvb, offset + TRPY_SRC_ADDR_OFFSET), sport,
7666 tvb_ip_to_str(pinfo->pool, tvb, offset + TRPY_DST_ADDR_OFFSET), dport);
7668 /* Client port only set on SYN: optlen == 18 */
7669 if ((flags & RVBD_FLAGS_TRPY_OOB) && (optlen > TCPOLEN_RVBD_TRPY_MIN))
7670 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_client_port,
7671 tvb, offset + TRPY_CLIENT_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7673 /* Despite that we have the right TCP ports for other protocols,
7674 * the data is related to the Riverbed Optimization Protocol and
7675 * not understandable by normal protocol dissectors. If the sport
7676 * protocol is available then use that, otherwise just output it
7677 * as a hex-dump.
7679 if (sport_handle != NULL) {
7680 conversation_t *conversation;
7681 conversation = find_or_create_conversation(pinfo);
7682 if (conversation_get_dissector(conversation, pinfo->num) != sport_handle) {
7683 conversation_set_dissector(conversation, sport_handle);
7685 } else if (data_handle != NULL) {
7686 conversation_t *conversation;
7687 conversation = find_or_create_conversation(pinfo);
7688 if (conversation_get_dissector(conversation, pinfo->num) != data_handle) {
7689 conversation_set_dissector(conversation, data_handle);
7693 return tvb_captured_length(tvb);
7696 /* Started as a copy of dissect_ip_tcp_options(), but was changed to support
7697 options as a dissector table */
7698 static void
7699 tcp_dissect_options(tvbuff_t *tvb, int offset, unsigned length,
7700 packet_info *pinfo, proto_tree *opt_tree,
7701 proto_item *opt_item, void * data)
7703 unsigned char opt;
7704 unsigned optlen, nop_count = 0;
7705 proto_tree *field_tree;
7706 const char *name;
7707 dissector_handle_t option_dissector;
7708 tvbuff_t *next_tvb;
7709 struct tcpheader *tcph = (struct tcpheader *)data;
7710 bool mss_seen = false;
7711 bool eol_seen = false;
7712 bool sack_perm_seen = false;
7714 while (length > 0) {
7715 opt = tvb_get_uint8(tvb, offset);
7716 if (eol_seen && opt != TCPOPT_EOL) {
7717 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_non_zero_bytes_after_eol, tvb, offset, length,
7718 "Non-zero header padding");
7719 return;
7721 --length; /* account for type byte */
7722 if ((opt == TCPOPT_EOL) || (opt == TCPOPT_NOP)) {
7723 int local_proto;
7724 proto_item* field_item;
7726 /* We assume that the only options with no length are EOL and
7727 NOP options, so that we can treat unknown options as having
7728 a minimum length of 2, and at least be able to move on to
7729 the next option by using the length in the option. */
7730 if (opt == TCPOPT_EOL) {
7731 local_proto = proto_tcp_option_eol;
7732 eol_seen = true;
7733 } else if (opt == TCPOPT_NOP) {
7734 local_proto = proto_tcp_option_nop;
7736 if (opt_item && (nop_count == 0 || offset % 4)) {
7737 /* Count number of NOP in a row within a uint32 */
7738 nop_count++;
7740 if (nop_count == 4) {
7741 expert_add_info(pinfo, opt_item, &ei_tcp_nop);
7743 } else {
7744 nop_count = 0;
7746 } else {
7747 DISSECTOR_ASSERT_NOT_REACHED();
7750 field_item = proto_tree_add_item(opt_tree, local_proto, tvb, offset, 1, ENC_NA);
7751 field_tree = proto_item_add_subtree(field_item, ett_tcp_option_other);
7752 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
7753 proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", proto_get_protocol_short_name(find_protocol_by_id(local_proto)));
7754 offset += 1;
7755 } else {
7756 option_dissector = dissector_get_uint_handle(tcp_option_table, opt);
7757 if (option_dissector == NULL) {
7758 name = wmem_strdup_printf(pinfo->pool, "Unknown (0x%02x)", opt);
7759 option_dissector = tcp_opt_unknown_handle;
7760 } else {
7761 name = dissector_handle_get_protocol_short_name(option_dissector);
7764 /* Option has a length. Is it in the packet? */
7765 if (length == 0) {
7766 /* Bogus - packet must at least include option code byte and
7767 length byte! */
7768 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, 1,
7769 "%s (length byte past end of options)", name);
7770 return;
7773 optlen = tvb_get_uint8(tvb, offset + 1); /* total including type, len */
7774 --length; /* account for length byte */
7776 if (optlen < 2) {
7777 /* Bogus - option length is too short to include option code and
7778 option length. */
7779 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, 2,
7780 "%s (with too-short option length = %u byte%s)",
7781 name, optlen, plurality(optlen, "", "s"));
7782 return;
7783 } else if (optlen - 2 > length) {
7784 /* Bogus - option goes past the end of the header. */
7785 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, length,
7786 "%s (option length = %u byte%s says option goes past end of options)",
7787 name, optlen, plurality(optlen, "", "s"));
7788 return;
7791 if (opt == TCPOPT_MSS)
7793 mss_seen = true;
7794 } else if (opt == TCPOPT_SACK_PERM)
7796 sack_perm_seen = true;
7799 next_tvb = tvb_new_subset_length(tvb, offset, optlen);
7800 call_dissector_with_data(option_dissector, next_tvb, pinfo, opt_tree/* tree */, data);
7801 proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name);
7803 offset += optlen;
7804 length -= (optlen-2); //already accounted for type and len bytes
7808 if (tcph->th_flags & TH_SYN)
7810 if (mss_seen == false)
7812 expert_add_info(pinfo, opt_item, &ei_tcp_option_mss_absent);
7814 if (sack_perm_seen == false)
7816 expert_add_info(pinfo, opt_item, &ei_tcp_option_sack_perm_absent);
7821 /* Determine if there is a sub-dissector and call it; return true
7822 if there was a sub-dissector, false otherwise.
7824 This has been separated into a stand alone routine to other protocol
7825 dissectors can call to it, e.g., SOCKS. */
7827 static bool try_heuristic_first;
7830 /* this function can be called with tcpd==NULL as from the msproxy dissector */
7831 bool
7832 decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
7833 proto_tree *tree, int src_port, int dst_port,
7834 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
7836 tvbuff_t *next_tvb;
7837 int low_port, high_port;
7838 int save_desegment_offset;
7839 bool try_low_port, try_high_port, try_server_port;
7840 uint32_t save_desegment_len;
7841 heur_dtbl_entry_t *hdtbl_entry;
7842 exp_pdu_data_t *exp_pdu_data;
7844 /* Don't call subdissectors for keepalives. Even though they do contain
7845 * payload "data", it's just garbage. Display any data the keepalive
7846 * packet might contain though.
7848 if(tcpd && tcpd->ta) {
7849 if(tcpd->ta->flags&TCP_A_KEEP_ALIVE) {
7850 next_tvb = tvb_new_subset_remaining(tvb, offset);
7851 call_dissector(data_handle, next_tvb, pinfo, tree);
7852 return true;
7856 if (tcp_no_subdissector_on_error && !(tcp_desegment && tcp_reassemble_out_of_order) &&
7857 tcpd && tcpd->ta && tcpd->ta->flags & (TCP_A_RETRANSMISSION | TCP_A_FAST_RETRANSMISSION |
7858 TCP_A_SPURIOUS_RETRANSMISSION | TCP_A_OUT_OF_ORDER)) {
7859 /* Don't try to dissect a retransmission high chance that it will mess
7860 * subdissectors for protocols that require in-order delivery of the
7861 * PDUs. (i.e. DCE/RPCoverHTTP and encryption)
7862 * If OoO reassembly is enabled and if this segment was previously lost,
7863 * then this retransmission could have finished reassembly, so continue.
7864 * XXX should this option be removed? "tcp_reassemble_out_of_order"
7865 * should have addressed the above in-order requirement.
7867 return false;
7869 next_tvb = tvb_new_subset_remaining(tvb, offset);
7871 save_desegment_offset = pinfo->desegment_offset;
7872 save_desegment_len = pinfo->desegment_len;
7874 /* determine if this packet is part of a conversation and call dissector */
7875 /* for the conversation if available */
7877 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, CONVERSATION_TCP,
7878 src_port, dst_port, next_tvb, pinfo, tree, tcpinfo, 0)) {
7879 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7880 handle_export_pdu_conversation(pinfo, next_tvb, src_port, dst_port, tcpinfo);
7881 return true;
7884 /* If the user has manually configured one of the server, low, or high
7885 * ports to a dissector other than the default (via Decode As or the
7886 * preferences associated with Decode As), try those first, in that order.
7888 try_server_port = false;
7889 if (tcpd && tcpd->server_port != 0) {
7890 if (dissector_is_uint_changed(subdissector_table, tcpd->server_port)) {
7891 if (dissector_try_uint_with_data(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7892 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7893 handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo);
7894 return true;
7896 } else {
7897 /* The default; try it later */
7898 try_server_port = true;
7902 /* Prevent the client port number being used for selecting the dissector
7903 when we have seen the SYN or SYN/ACK (and therefor tcpd->server_port
7904 is defined)
7905 Use the preference Clientport dissectors to keep dissecting certain
7906 protocols based on the client port instead of the server port
7907 Port 20 for active ftp data transfers being the default. */
7908 if (tcpd && tcpd->server_port != 0) {
7909 if (dst_port == tcpd->server_port) {
7910 if (!(dissector_is_uint_changed(subdissector_table, src_port) ||
7911 value_is_in_range(tcp_clientport_dissectors_range, src_port) ) ) {
7912 src_port = 0;
7914 } else {
7915 if (!(dissector_is_uint_changed(subdissector_table, dst_port) ||
7916 value_is_in_range(tcp_clientport_dissectors_range, dst_port) ) ) {
7917 dst_port = 0;
7922 if (src_port > dst_port) {
7923 low_port = dst_port;
7924 high_port = src_port;
7925 } else {
7926 low_port = src_port;
7927 high_port = dst_port;
7930 try_low_port = false;
7931 if (low_port != 0) {
7932 if (dissector_is_uint_changed(subdissector_table, low_port)) {
7933 if (dissector_try_uint_with_data(subdissector_table, low_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7934 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7935 handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo);
7936 return true;
7938 } else {
7939 /* The default; try it later */
7940 try_low_port = true;
7944 try_high_port = false;
7945 if (high_port != 0) {
7946 if (dissector_is_uint_changed(subdissector_table, high_port)) {
7947 if (dissector_try_uint_with_data(subdissector_table, high_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7948 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7949 handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo);
7950 return true;
7952 } else {
7953 /* The default; try it later */
7954 try_high_port = true;
7958 if (try_heuristic_first) {
7959 /* do lookup with the heuristic subdissector table */
7960 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) {
7961 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7962 handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo);
7963 return true;
7967 /* Do lookups with the subdissector table.
7968 Try the server port captured on the SYN or SYN|ACK packet. After that
7969 try the port number with the lower value first, followed by the
7970 port number with the higher value. This means that, for packets
7971 where a dissector is registered for *both* port numbers:
7973 1) we pick the same dissector for traffic going in both directions;
7975 2) we prefer the port number that's more likely to be the right
7976 one (as that prefers well-known ports to reserved ports);
7978 although there is, of course, no guarantee that any such strategy
7979 will always pick the right port number.
7981 XXX - we ignore port numbers of 0, as some dissectors use a port
7982 number of 0 to disable the port. */
7984 if (try_server_port &&
7985 dissector_try_uint_with_data(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7986 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7987 handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo);
7988 return true;
7991 if (try_low_port &&
7992 dissector_try_uint_with_data(subdissector_table, low_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7993 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7994 handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo);
7995 return true;
7997 if (try_high_port &&
7998 dissector_try_uint_with_data(subdissector_table, high_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7999 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
8000 handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo);
8001 return true;
8004 if (!try_heuristic_first) {
8005 /* do lookup with the heuristic subdissector table */
8006 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) {
8007 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
8008 handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo);
8009 return true;
8014 * heuristic / conversation / port registered dissectors rejected the packet;
8015 * make sure they didn't also request desegmentation (we could just override
8016 * the request, but rejecting a packet *and* requesting desegmentation is a sign
8017 * of the dissector's code needing clearer thought, so we fail so that the
8018 * problem is made more obvious).
8020 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
8021 save_desegment_len == pinfo->desegment_len);
8023 /* Oh, well, we don't know this; dissect it as data. */
8024 call_dissector(data_handle,next_tvb, pinfo, tree);
8026 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
8027 if (have_tap_listener(exported_pdu_tap)) {
8028 exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME);
8029 exp_pdu_data->tvb_captured_length = tvb_captured_length(next_tvb);
8030 exp_pdu_data->tvb_reported_length = tvb_reported_length(next_tvb);
8031 exp_pdu_data->pdu_tvb = next_tvb;
8033 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
8035 return false;
8038 static void
8039 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
8040 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
8041 uint32_t seq, uint32_t nxtseq, bool is_tcp_segment,
8042 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
8044 pinfo->want_pdu_tracking=0;
8046 TRY {
8047 if(is_tcp_segment) {
8048 /*qqq see if it is an unaligned PDU */
8049 if(tcpd && tcp_analyze_seq && (!tcp_desegment)) {
8050 if(seq || nxtseq) {
8051 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
8052 seq, nxtseq, tcpd->fwd->multisegment_pdus);
8056 /* if offset is -1 this means that this segment is known
8057 * to be fully inside a previously detected pdu
8058 * so we don't even need to try to dissect it either.
8060 if( (offset!=-1) &&
8061 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
8062 dst_port, tcpd, tcpinfo) ) {
8064 * We succeeded in handing off to a subdissector.
8066 * Is this a TCP segment or a reassembled chunk of
8067 * TCP payload?
8069 if(is_tcp_segment) {
8070 /* if !visited, check want_pdu_tracking and
8071 store it in table */
8072 if(tcpd && (!pinfo->fd->visited) &&
8073 tcp_analyze_seq && pinfo->want_pdu_tracking) {
8074 if(seq || nxtseq) {
8075 pdu_store_sequencenumber_of_next_pdu(
8076 pinfo,
8077 seq,
8078 nxtseq+pinfo->bytes_until_next_pdu,
8079 tcpd->fwd->multisegment_pdus);
8085 CATCH_ALL {
8086 /* We got an exception. At this point the dissection is
8087 * completely aborted and execution will be transferred back
8088 * to (probably) the frame dissector.
8089 * Here we have to place whatever we want the dissector
8090 * to do before aborting the tcp dissection.
8093 * Is this a TCP segment or a reassembled chunk of TCP
8094 * payload?
8096 if(is_tcp_segment) {
8098 * It's from a TCP segment.
8100 * if !visited, check want_pdu_tracking and store it
8101 * in table
8103 if(tcpd && (!pinfo->fd->visited) && tcp_analyze_seq && pinfo->want_pdu_tracking) {
8104 if(seq || nxtseq) {
8105 pdu_store_sequencenumber_of_next_pdu(pinfo,
8106 seq,
8107 nxtseq+pinfo->bytes_until_next_pdu,
8108 tcpd->fwd->multisegment_pdus);
8112 RETHROW;
8114 ENDTRY;
8117 void
8118 dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, uint32_t seq,
8119 uint32_t nxtseq, uint32_t sport, uint32_t dport,
8120 proto_tree *tree, proto_tree *tcp_tree,
8121 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
8123 int nbytes;
8124 bool save_fragmented;
8126 nbytes = tvb_reported_length_remaining(tvb, offset);
8127 proto_tree_add_bytes_format(tcp_tree, hf_tcp_payload, tvb, offset,
8128 -1, NULL, "TCP payload (%u byte%s)", nbytes,
8129 plurality(nbytes, "", "s"));
8131 /* Can we desegment this segment? */
8132 if (pinfo->can_desegment) {
8133 /* Yes. */
8134 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
8135 tcp_tree, tcpd, tcpinfo);
8136 } else {
8137 /* No - just call the subdissector.
8138 Mark this as fragmented, so if somebody throws an exception,
8139 we don't report it as a malformed frame. */
8140 save_fragmented = pinfo->fragmented;
8141 pinfo->fragmented = true;
8143 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
8144 seq, nxtseq, true, tcpd, tcpinfo);
8145 pinfo->fragmented = save_fragmented;
8149 static bool
8150 capture_tcp(const unsigned char *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header)
8152 uint16_t src_port, dst_port, low_port, high_port;
8154 if (!BYTES_ARE_IN_FRAME(offset, len, 4))
8155 return false;
8157 capture_dissector_increment_count(cpinfo, proto_tcp);
8159 src_port = pntoh16(&pd[offset]);
8160 dst_port = pntoh16(&pd[offset+2]);
8162 if (src_port > dst_port) {
8163 low_port = dst_port;
8164 high_port = src_port;
8165 } else {
8166 low_port = src_port;
8167 high_port = dst_port;
8170 if (low_port != 0 &&
8171 try_capture_dissector("tcp.port", low_port, pd, offset+20, len, cpinfo, pseudo_header))
8172 return true;
8174 if (high_port != 0 &&
8175 try_capture_dissector("tcp.port", high_port, pd, offset+20, len, cpinfo, pseudo_header))
8176 return true;
8178 /* We've at least identified one type of packet, so this shouldn't be "other" */
8179 return true;
8182 typedef struct _tcp_tap_cleanup_t {
8184 packet_info *pinfo;
8185 struct tcpheader *tcph;
8187 } tcp_tap_cleanup_t;
8189 static void tcp_tap_cleanup(void *data)
8191 tcp_tap_cleanup_t *cleanup = (tcp_tap_cleanup_t *)data;
8193 tap_queue_packet(tcp_tap, cleanup->pinfo, cleanup->tcph);
8196 static int
8197 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
8199 uint8_t th_off_x2; /* combines th_off and th_x2 */
8200 uint16_t th_sum;
8201 uint32_t th_urp;
8202 proto_tree *tcp_tree = NULL, *field_tree = NULL;
8203 proto_item *ti = NULL, *tf, *hidden_item;
8204 proto_item *options_item, *hide_seqack_abs_item;
8205 proto_tree *options_tree;
8206 int offset = 0;
8207 char *flags_str, *flags_str_first_letter;
8208 unsigned optlen;
8209 uint32_t nxtseq = 0;
8210 unsigned reported_len;
8211 vec_t cksum_vec[4];
8212 uint32_t phdr[2];
8213 uint16_t computed_cksum;
8214 uint16_t real_window;
8215 unsigned captured_length_remaining;
8216 bool desegment_ok;
8217 struct tcpinfo tcpinfo;
8218 struct tcpheader *tcph;
8219 proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL, *scaled_pi;
8220 conversation_t *conv=NULL;
8221 struct tcp_analysis *tcpd=NULL;
8222 struct tcp_per_packet_data_t *tcppd=NULL;
8223 proto_item *item;
8224 proto_tree *checksum_tree;
8225 bool icmp_ip = false;
8226 uint8_t conversation_completeness = 0;
8227 bool conversation_is_new = false;
8228 uint8_t ace;
8230 tcph = wmem_new0(pinfo->pool, struct tcpheader);
8231 tcph->th_sport = tvb_get_ntohs(tvb, offset);
8232 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
8233 copy_address_shallow(&tcph->ip_src, &pinfo->src);
8234 copy_address_shallow(&tcph->ip_dst, &pinfo->dst);
8236 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
8237 col_clear(pinfo->cinfo, COL_INFO);
8238 col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, tcph->th_sport, tcph->th_dport);
8240 if (tree) {
8241 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, ENC_NA);
8242 if (tcp_summary_in_tree) {
8243 proto_item_append_text(ti, ", Src Port: %s, Dst Port: %s",
8244 port_with_resolution_to_str(pinfo->pool, PT_TCP, tcph->th_sport),
8245 port_with_resolution_to_str(pinfo->pool, PT_TCP, tcph->th_dport));
8247 tcp_tree = proto_item_add_subtree(ti, ett_tcp);
8248 p_add_proto_data(pinfo->pool, pinfo, proto_tcp, pinfo->curr_layer_num, tcp_tree);
8250 proto_tree_add_item(tcp_tree, hf_tcp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN);
8251 proto_tree_add_item(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
8252 hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
8253 proto_item_set_hidden(hidden_item);
8254 hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
8255 proto_item_set_hidden(hidden_item);
8257 /* If we're dissecting the headers of a TCP packet in an ICMP packet
8258 * then go ahead and put the sequence numbers in the tree now (because
8259 * they won't be put in later because the ICMP packet only contains up
8260 * to the sequence number).
8261 * We should only need to do this for IPv4 since IPv6 will hopefully
8262 * carry enough TCP payload for this dissector to put the sequence
8263 * numbers in via the regular code path.
8266 wmem_list_frame_t *frame;
8267 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
8268 if (proto_ip == (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame))) {
8269 frame = wmem_list_frame_prev(frame);
8270 if (proto_icmp == (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame))) {
8271 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
8272 icmp_ip = true;
8278 /* Set the source and destination port numbers as soon as we get them,
8279 so that they're available to the "Follow TCP Stream" code even if
8280 we throw an exception dissecting the rest of the TCP header. */
8281 pinfo->ptype = PT_TCP;
8282 pinfo->srcport = tcph->th_sport;
8283 pinfo->destport = tcph->th_dport;
8285 p_add_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num, GUINT_TO_POINTER(tcph->th_sport));
8286 p_add_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num, GUINT_TO_POINTER(tcph->th_dport));
8288 tcph->th_rawseq = tvb_get_ntohl(tvb, offset + 4);
8289 tcph->th_seq = tcph->th_rawseq;
8290 tcph->th_rawack = tvb_get_ntohl(tvb, offset + 8);
8291 tcph->th_ack = tcph->th_rawack;
8292 th_off_x2 = tvb_get_uint8(tvb, offset + 12);
8293 tcpinfo.flags = tcph->th_flags = tvb_get_ntohs(tvb, offset + 12) & TH_MASK;
8294 tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
8296 /* find(or create if needed) the conversation for this tcp session
8297 * This is a slight deviation from find_or_create_conversation so it's
8298 * done manually. This is done to avoid conversation overlapping when
8299 * reusing ports (see issue 15097), as find_or_create_conversation automatically
8300 * extends the conversation found. This extension is done later.
8303 conv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
8304 if(!conv) {
8305 conv=conversation_new_strat(pinfo, CONVERSATION_TCP, 0);
8306 conversation_is_new = true;
8309 tcpd=get_tcp_conversation_data(conv,pinfo);
8311 if (!PINFO_FD_VISITED(pinfo)) {
8312 /* If this is a SYN packet, then check if its seq-nr is different
8313 * from the base_seq of the retrieved conversation. If this is the
8314 * case, create a new conversation with the same addresses and ports
8315 * and set the TA_PORTS_REUSED flag. (XXX: There is a small chance
8316 * that this is an old duplicate SYN received after the connection
8317 * is ESTABLISHED on both sides, the other side will respond with
8318 * an appropriate ACK, and this SYN ought to be ignored rather than
8319 * create a new conversation.)
8321 * If the seq-nr is the same as the base_seq, it might be a simple
8322 * retransmission, reattempting a handshake that was reset (due
8323 * to a half-open connection) with the same sequence number, or
8324 * (unlikely) a new connection that happens to use the same sequence
8325 * number as the previous one (#18333).
8327 * If we have received a RST or FIN on the retrieved conversation,
8328 * we can detect that unlikely case, and create a new conversation
8329 * in order to clear out the follow info, sequence analysis,
8330 * desegmentation, etc.
8331 * If not, it's probably a retransmission, and will be marked
8332 * as one later, but restore some flow values to reduce the
8333 * sequence analysis warnings if our capture file is missing a RST
8334 * or FIN segment that was present on the network.
8336 * XXX - Is this affected by MPTCP which can use multiple SYNs?
8338 if (tcpd != NULL && (tcph->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) {
8339 if (tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET) {
8340 if(tcph->th_seq!=tcpd->fwd->base_seq || (tcpd->conversation_completeness & TCP_COMPLETENESS_RST) || (tcpd->conversation_completeness & TCP_COMPLETENESS_FIN)) {
8341 conv=conversation_new_strat(pinfo, CONVERSATION_TCP, 0);
8342 tcpd=get_tcp_conversation_data(conv,pinfo);
8344 if(!tcpd->ta)
8345 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, true, tcpd);
8346 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
8348 /* As above, a new conversation starting with a SYN implies conversation completeness value 1 */
8349 conversation_is_new = true;
8350 } else {
8352 * Sometimes we need to restore the nextseq value.
8353 * As stated in RFC 793 3.4 a RST packet might be
8354 * sent with SEQ being equal to the ACK received,
8355 * thus breaking our flow monitoring. (issue 17616)
8357 if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info) {
8358 tcpd->fwd->tcp_analyze_seq_info->nextseq = tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked;
8361 if(!tcpd->ta)
8362 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, true, tcpd);
8364 } else {
8366 * TCP_S_BASE_SEQ_SET being not set, we are dealing with a new conversation,
8367 * either created ad hoc above (general case), or by a higher protocol such as FTP.
8368 * Track this information, as the Completeness value will be initialized later.
8369 * See issue 19092.
8371 conversation_is_new = true;
8373 tcpd->had_acc_ecn_setup_syn = (tcph->th_flags & (TH_AE|TH_CWR|TH_ECE)) == (TH_AE|TH_CWR|TH_ECE);
8376 /* Handle cases of a SYN/ACK packet where there's evidence of a new
8377 * conversation but the capture is missing the SYN packet of the
8378 * new conversation.
8380 * If this is a SYN/ACK packet, then check if its seq-nr is different
8381 * from the base_seq of the retrieved conversation. If this is the
8382 * case, create a new conversation as above with a SYN packet, and set
8383 * the TA_PORTS_REUSED flag and override the base seq.
8384 * If the seq-nr is the same as the base_seq, then do nothing so it
8385 * will be marked as a retransmission later, unless we have received
8386 * a RST or FIN on the conversation (in which case this is the case
8387 * of a RST followed by the same initial sequence number being picked.)
8389 * If this is an unacceptable SYN-ACK and the other side believes that
8390 * the conversation is ESTABLISHED, it will be replied to with an
8391 * empty ACK with the current sequence number (according to the other
8392 * side.) See RFC 9293 3.5.2. This *probably* leads to a situation where
8393 * the side sending this SYN-ACK then issues a RST, because the two
8394 * sides have different ideas about the connection state. It's not clear
8395 * how to handle the annoying edge case where A sends a SYN, B responds
8396 * with a SYN-ACK that A intends to accept, but before A can finish
8397 * the handshake B responds with another SYN-ACK _with a different seq-nr_
8398 * instead of retransmitting, then A responds accepting the first SYN-ACK,
8399 * and then B goes on happily using the sequence number from the first
8400 * SYN-ACK, forgetting all about the second one it sent instead of sending
8401 * a RST. In such a case we'll have changed the seq-nr to the new one
8402 * and/or set up a new conversation instead of just ignoring that SYN-ACK.
8404 * XXX - Is this affected by MPTCP which can use multiple SYNs?
8406 if (tcpd != NULL && (tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
8407 if ((tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET) &&
8408 (tcph->th_seq != tcpd->fwd->base_seq ||
8409 (tcpd->conversation_completeness & TCP_COMPLETENESS_RST) ||
8410 (tcpd->conversation_completeness & TCP_COMPLETENESS_FIN))) {
8411 /* the retrieved conversation might have a different base_seq (issue 16944) */
8413 conv=conversation_new_strat(pinfo, CONVERSATION_TCP, 0);
8414 tcpd=get_tcp_conversation_data(conv,pinfo);
8416 if(!tcpd->ta)
8417 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, true, tcpd);
8418 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
8420 /* As above, a new conversation */
8421 conversation_is_new = true;
8423 tcpd->had_acc_ecn_setup_syn_ack = ((tcph->th_flags & (TH_AE|TH_CWR)) == TH_CWR) ||
8424 ((tcph->th_flags & (TH_AE|TH_ECE)) == TH_AE);
8427 /* Do we need to calculate timestamps relative to the tcp-stream? */
8428 if (tcp_calculate_ts) {
8429 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
8431 /* Calculate the timestamps relative to this conversation */
8432 tcp_calculate_timestamps(pinfo, tcpd, tcppd);
8436 if (tcpd) {
8437 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, tcpd->stream);
8438 proto_item_set_generated(item);
8439 tcpinfo.stream = tcpd->stream;
8441 if (tcppd) {
8442 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream_pnum, tvb, offset, 0, tcppd->pnum);
8443 proto_item_set_generated(item);
8446 /* Display the completeness of this TCP conversation */
8447 static int* const completeness_fields[] = {
8448 &hf_tcp_completeness_rst,
8449 &hf_tcp_completeness_fin,
8450 &hf_tcp_completeness_data,
8451 &hf_tcp_completeness_ack,
8452 &hf_tcp_completeness_syn_ack,
8453 &hf_tcp_completeness_syn,
8454 NULL};
8456 item = proto_tree_add_bitmask_value_with_flags(tcp_tree, NULL, 0,
8457 hf_tcp_completeness, ett_tcp_completeness, completeness_fields,
8458 tcpd->conversation_completeness, BMT_NO_APPEND);
8459 proto_item_set_generated(item);
8460 field_tree = proto_item_add_subtree(item, ett_tcp_completeness);
8462 flags_str_first_letter = tcpd->conversation_completeness_str;
8463 item = proto_tree_add_string(field_tree, hf_tcp_completeness_str, tvb, 0, 0, flags_str_first_letter);
8464 proto_item_set_generated(item);
8466 /* Copy the stream index into the header as well to make it available
8467 * to tap listeners.
8469 tcph->th_stream = tcpd->stream;
8471 /* Copy the stream index into pinfo as well to make it available
8472 * to callback functions (essentially conversation following events in GUI)
8474 pinfo->stream_id = tcpd->stream;
8476 /* initialize the SACK blocks seen to 0 */
8477 if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info) {
8478 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = 0;
8482 /* is there any manual analysis waiting ? */
8483 if(pinfo->fd->tcp_snd_manual_analysis > 0) {
8484 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
8485 tcppd->tcp_snd_manual_analysis = pinfo->fd->tcp_snd_manual_analysis;
8488 /* We have have the absolute sequence numbers (we would have thrown an
8489 * exception if not) and tcpd, so set relative sequence numbers now. */
8491 /* XXX - Why not in an error packet? */
8492 if (tcpd != NULL && !pinfo->flags.in_error_pkt) {
8493 /* initialize base_seq numbers if needed */
8494 if (!(pinfo->fd->visited)) {
8495 /* if this is the first segment for this list we need to store the
8496 * base_seq
8497 * We use TCP_S_SAW_SYN/SYNACK to distinguish between client and server
8499 * Start relative seq and ack numbers at 1 if this
8500 * is not a SYN packet. This makes the relative
8501 * seq/ack numbers to be displayed correctly in the
8502 * event that the SYN or SYN/ACK packet is not seen
8503 * (this solves bug 1542)
8505 if( !(tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET)) {
8506 if(tcph->th_flags & TH_SYN) {
8507 tcpd->fwd->base_seq = tcph->th_seq;
8508 tcpd->fwd->static_flags |= (tcph->th_flags & TH_ACK) ? TCP_S_SAW_SYNACK : TCP_S_SAW_SYN;
8510 else {
8511 tcpd->fwd->base_seq = tcph->th_seq-1;
8513 tcpd->fwd->static_flags |= TCP_S_BASE_SEQ_SET;
8516 /* Only store reverse sequence if this isn't the SYN
8517 * There's no guarantee that the ACK field of a SYN
8518 * contains zeros; get the ISN from the first segment
8519 * with the ACK bit set instead (usually the SYN/ACK).
8521 * If the SYN and SYN/ACK were received out-of-order,
8522 * the ISN is ack-1. If we missed the SYN/ACK, but got
8523 * the last ACK of the 3WHS, the ISN is ack-1. For all
8524 * other packets the ISN is unknown, so ack-1 is
8525 * as good a guess as ack.
8527 if( !(tcpd->rev->static_flags & TCP_S_BASE_SEQ_SET) && (tcph->th_flags & TH_ACK) ) {
8528 tcpd->rev->base_seq = tcph->th_ack-1;
8529 tcpd->rev->static_flags |= TCP_S_BASE_SEQ_SET;
8532 if (tcp_analyze_seq && tcp_relative_seq) {
8533 tcph->th_seq -= tcpd->fwd->base_seq;
8534 if (tcph->th_flags & TH_ACK) {
8535 tcph->th_ack -= tcpd->rev->base_seq;
8541 * If we've been handed an IP fragment, we don't know how big the TCP
8542 * segment is, so don't do anything that requires that we know that.
8544 * The same applies if we're part of an error packet. (XXX - if the
8545 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
8546 * header says it is" length in the tvbuff, we could use that; such
8547 * a length might also be useful for handling packets where the IP
8548 * length is bigger than the actual data available in the frame; the
8549 * dissectors should trust that length, and then throw a
8550 * ReportedBoundsError exception when they go past the end of the frame.)
8552 * We also can't determine the segment length if the reported length
8553 * of the TCP packet is less than the TCP header length.
8555 reported_len = tvb_reported_length(tvb);
8557 if (!pinfo->fragmented && !pinfo->flags.in_error_pkt) {
8558 if (reported_len < tcph->th_hlen) {
8559 proto_tree_add_expert_format(tcp_tree, pinfo, &ei_tcp_short_segment, tvb, offset, 0,
8560 "Short segment. Segment/fragment does not contain a full TCP header"
8561 " (might be NMAP or someone else deliberately sending unusual packets)");
8562 tcph->th_have_seglen = false;
8563 } else {
8564 proto_item *pi;
8566 /* Compute the length of data in this segment. */
8567 tcph->th_seglen = reported_len - tcph->th_hlen;
8568 tcph->th_have_seglen = true;
8570 pi = proto_tree_add_uint(ti, hf_tcp_len, tvb, 0, 0, tcph->th_seglen);
8571 proto_item_set_generated(pi);
8573 /* handle TCP seq# analysis parse all new segments we see */
8574 /* We need the window size to perform sequence analysis.
8575 * (Zero is a possible value treated specially. */
8576 if(tcp_analyze_seq && tvb_bytes_exist(tvb, offset + 14, 2)) {
8578 /* Get it on every pass so that dissection is the same. */
8579 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
8581 if(!(pinfo->fd->visited)) {
8582 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
8583 tcp_analyze_sequence_number(pinfo, tcph->th_rawseq, tcph->th_rawack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd, tcppd);
8585 /* load the tcppd data as it may contain 'volatile' data such as Karn's indications */
8586 else {
8587 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
8591 /* Compute the sequence number of next octet after this segment. */
8592 nxtseq = tcph->th_seq + tcph->th_seglen;
8594 } else
8595 tcph->th_have_seglen = false;
8598 * Decode the ECN related flags as ACE if it is not a SYN segment,
8599 * and an AccECN-setup SYN and SYN ACK have been observed, or an
8600 * AccECN option was observed (this covers the case where Wireshark
8601 * did not observe the initial handshake).
8603 tcph->th_use_ace = (tcph->th_flags & TH_SYN) == 0 &&
8604 tcpd != NULL &&
8605 ((tcpd->had_acc_ecn_setup_syn && tcpd->had_acc_ecn_setup_syn_ack) ||
8606 tcpd->had_acc_ecn_option);
8607 flags_str = tcp_flags_to_str(pinfo->pool, tcph);
8608 flags_str_first_letter = tcp_flags_to_str_first_letter(pinfo->pool, tcph);
8610 col_append_lstr(pinfo->cinfo, COL_INFO,
8611 " [", flags_str, "]",
8612 COL_ADD_LSTR_TERMINATOR);
8613 tcp_info_append_uint(pinfo, "Seq", tcph->th_seq);
8614 if (tcph->th_flags&TH_ACK)
8615 tcp_info_append_uint(pinfo, "Ack", tcph->th_ack);
8617 if (tcp_summary_in_tree) {
8618 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
8621 if (!icmp_ip) {
8622 if(tcp_relative_seq && tcp_analyze_seq) {
8623 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);
8624 item = proto_tree_add_uint(tcp_tree, hf_tcp_seq_abs, tvb, offset + 4, 4, tcph->th_rawseq);
8625 if (read_seq_as_syn_cookie) {
8626 proto_item* syncookie_ti = NULL;
8627 proto_item_append_text(item, " (syn cookie)");
8628 syncookie_ti = proto_item_add_subtree(item, ett_tcp_syncookie);
8629 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_time, tvb, (offset + 4) * 8, 5, ENC_NA);
8630 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_mss, tvb, (offset + 4) * 8 + 5, 3, ENC_NA);
8631 proto_tree_add_item(syncookie_ti, hf_tcp_syncookie_hash, tvb, offset + 4 + 1, 3, ENC_NA);
8634 } else {
8635 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
8636 hide_seqack_abs_item = proto_tree_add_uint(tcp_tree, hf_tcp_seq_abs, tvb, offset + 4, 4, tcph->th_rawseq);
8637 proto_item_set_hidden(hide_seqack_abs_item);
8641 if (tcph->th_hlen < TCPH_MIN_LEN) {
8642 /* Give up at this point; we put the source and destination port in
8643 the tree, before fetching the header length, so that they'll
8644 show up if this is in the failing packet in an ICMP error packet,
8645 but it's now time to give up if the header length is bogus. */
8646 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
8647 tcph->th_hlen, TCPH_MIN_LEN);
8649 tf = proto_tree_add_uint_bits_format_value(tcp_tree, hf_tcp_hdr_len, tvb, (offset + 12) << 3, 4, tcph->th_hlen,
8650 ENC_BIG_ENDIAN, "%u bytes (%u)", tcph->th_hlen, tcph->th_hlen >> 2);
8651 expert_add_info_format(pinfo, tf, &ei_tcp_bogus_header_length,
8652 "Bogus TCP header length (%u, must be at least %u)", tcph->th_hlen, TCPH_MIN_LEN);
8653 return offset+12;
8656 if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info && tcppd) {
8657 tcph->flagkarn = tcppd->karn_flag;
8660 /* Now we certainly have enough information to be willing to send
8661 * the header information to the tap. The options can add information
8662 * about the SACKs, but the other taps don't really *require* that.
8663 * Add a CLEANUP function so that the tap_queue_packet gets called
8664 * if any exception is thrown.
8666 * XXX - We haven't necessarily retrieved the window size yet. We'll
8667 * try to do so before sending it to the tap, but if the header is
8668 * truncated to 14 octets, the taps will receive a window size of 0.
8669 * Can they handle it with minimal problems?
8672 tcp_tap_cleanup_t *cleanup = wmem_new(pinfo->pool, tcp_tap_cleanup_t);
8673 cleanup->pinfo = pinfo;
8674 cleanup->tcph = tcph;
8675 CLEANUP_PUSH(tcp_tap_cleanup, cleanup);
8677 /* initialize or move forward the conversation completeness */
8678 if(tcpd) {
8679 if(conversation_is_new) { /* pure SYN must be sought in new conversations only */
8680 if((tcph->th_flags&(TH_SYN|TH_ACK))==TH_SYN) {
8681 conversation_completeness |= TCP_COMPLETENESS_SYNSENT;
8682 if(tcph->th_seglen > 0) { /* TCP Fast Open */
8683 conversation_completeness |= TCP_COMPLETENESS_DATA;
8687 else {
8688 /* Explicitly and immediately move forward the conversation last_frame,
8689 * although it would one way or another be changed later
8690 * in the conversation helper functions.
8692 if (!(pinfo->fd->visited)) {
8693 if (pinfo->num > conv->last_frame) {
8694 conv->last_frame = pinfo->num;
8698 conversation_completeness = tcpd->conversation_completeness ;
8701 /* SYN-ACK */
8702 if((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
8703 conversation_completeness |= TCP_COMPLETENESS_SYNACK;
8706 /* ACKs */
8707 if((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_ACK)) {
8708 if(tcph->th_seglen>0) { /* transporting some data */
8709 conversation_completeness |= TCP_COMPLETENESS_DATA;
8711 else { /* pure ACK */
8712 conversation_completeness |= TCP_COMPLETENESS_ACK;
8716 /* FIN-ACK */
8717 if((tcph->th_flags&(TH_FIN|TH_ACK))==(TH_FIN|TH_ACK)) {
8718 conversation_completeness |= TCP_COMPLETENESS_FIN;
8721 /* RST */
8722 /* XXX: A RST segment should be validated (RFC 9293 3.5.3),
8723 * and if not valid should not change the conversation state.
8725 if(tcph->th_flags&(TH_RST)) {
8726 conversation_completeness |= TCP_COMPLETENESS_RST;
8729 /* Store the completeness at the conversation level,
8730 * both as numerical and as Flag First Letters string, to avoid
8731 * computing many times the same thing.
8733 if (tcpd->conversation_completeness) {
8734 if (tcpd->conversation_completeness != conversation_completeness) {
8735 tcpd->conversation_completeness = conversation_completeness;
8736 tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ;
8739 else {
8740 tcpd->conversation_completeness = conversation_completeness;
8741 tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ;
8745 if (tcp_summary_in_tree) {
8746 if(tcph->th_flags&TH_ACK) {
8747 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
8749 if (tcph->th_have_seglen)
8750 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
8752 proto_item_set_len(ti, tcph->th_hlen);
8753 if (tcph->th_have_seglen) {
8754 if(tcp_relative_seq && tcp_analyze_seq) {
8755 if (tcph->th_flags&(TH_SYN|TH_FIN)) {
8756 tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq + 1, "%u (relative sequence number)", nxtseq + 1);
8757 } else {
8758 tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "%u (relative sequence number)", nxtseq);
8760 } else {
8761 if (tcph->th_flags&(TH_SYN|TH_FIN)) {
8762 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq + 1);
8763 } else {
8764 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
8767 proto_item_set_generated(tf);
8770 tf = proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
8771 hide_seqack_abs_item = proto_tree_add_uint(tcp_tree, hf_tcp_ack_abs, tvb, offset + 8, 4, tcph->th_rawack);
8772 if (tcph->th_flags & TH_ACK) {
8773 if (tcp_relative_seq && tcp_analyze_seq) {
8774 proto_item_append_text(tf, " (relative ack number)");
8775 } else {
8776 proto_item_set_hidden(hide_seqack_abs_item);
8778 if ((tcph->th_flags & TH_SYN) && tcp_analyze_seq) {
8779 if ((tcp_relative_seq && tcph->th_ack > 1) ||
8780 (!tcp_relative_seq && tcpd && (tcph->th_ack - tcpd->rev->base_seq) > 1)) {
8781 expert_add_info(pinfo, tf, &ei_tcp_analysis_tfo_ack);
8782 } else if (tcpd && tcpd->tfo_syn_data) {
8783 expert_add_info(pinfo, tf, &ei_tcp_analysis_tfo_ignored);
8786 } else {
8787 /* Note if the ACK field is non-zero */
8788 if (tvb_get_ntohl(tvb, offset+8) != 0) {
8789 expert_add_info(pinfo, tf, &ei_tcp_ack_nonzero);
8793 if (tree) {
8794 // This should be consistent with ip.hdr_len.
8795 proto_tree_add_uint_bits_format_value(tcp_tree, hf_tcp_hdr_len, tvb, (offset + 12) << 3, 4, tcph->th_hlen,
8796 ENC_BIG_ENDIAN, "%u bytes (%u)", tcph->th_hlen, tcph->th_hlen>>2);
8797 tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 12, 2,
8798 tcph->th_flags, "Flags: 0x%03x (%s)", tcph->th_flags, flags_str);
8799 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
8800 proto_tree_add_boolean(field_tree, hf_tcp_flags_res, tvb, offset + 12, 1, tcph->th_flags);
8801 if (tcph->th_use_ace) {
8802 ace = tcp_get_ace(tcph);
8803 proto_tree_add_uint_format(field_tree, hf_tcp_flags_ace, tvb, 12, 2, ace,
8804 "...%c %c%c.. .... = ACE: %u",
8805 ace & 0x04 ? '1' : '0',
8806 ace & 0x02 ? '1' : '0',
8807 ace & 0x01 ? '1' : '0',
8808 ace);
8809 } else {
8810 proto_tree_add_boolean(field_tree, hf_tcp_flags_ae, tvb, offset + 12, 1, tcph->th_flags);
8811 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
8812 proto_tree_add_boolean(field_tree, hf_tcp_flags_ece, tvb, offset + 13, 1, tcph->th_flags);
8814 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
8815 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
8816 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
8817 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
8818 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
8819 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
8821 tf = proto_tree_add_string(field_tree, hf_tcp_flags_str, tvb, offset + 12, 2, flags_str_first_letter);
8822 proto_item_set_generated(tf);
8825 if(tcph->th_flags & TH_SYN) {
8826 if(tcph->th_flags & TH_ACK) {
8827 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_synack,
8828 "Connection establish acknowledge (SYN+ACK): server port %u", tcph->th_sport);
8829 /* Save the server port to help determine dissector used */
8830 tcpd->server_port = tcph->th_sport;
8832 else {
8833 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_syn,
8834 "Connection establish request (SYN): server port %u", tcph->th_dport);
8835 /* Save the server port to help determine dissector used */
8836 tcpd->server_port = tcph->th_dport;
8837 tcpd->ts_mru_syn = pinfo->abs_ts;
8839 /* Remember where the next segment will start. */
8840 if (tcp_desegment && tcp_reassemble_out_of_order && tcpd && !PINFO_FD_VISITED(pinfo)) {
8841 if (tcpd->fwd->maxnextseq == 0) {
8842 tcpd->fwd->maxnextseq = tcph->th_seq + 1;
8845 /* Initialize the is_first_ack */
8846 tcpd->fwd->is_first_ack = true;
8848 if(tcph->th_flags & TH_FIN) {
8849 /* XXX - find a way to know the server port and output only that one */
8850 expert_add_info(pinfo, tf_fin, &ei_tcp_connection_fin);
8852 /* Track closing initiator.
8853 If it was not already closed by the reverse flow, it means we are the first */
8854 if(!tcpd->rev->closing_initiator) {
8855 tcpd->fwd->closing_initiator = true;
8856 expert_add_info(pinfo, tf, &ei_tcp_connection_fin_active);
8857 } else {
8858 expert_add_info(pinfo, tf, &ei_tcp_connection_fin_passive);
8861 if(tcph->th_flags & TH_RST){
8862 /* XXX - find a way to know the server port and output only that one */
8863 expert_add_info(pinfo, tf_rst, &ei_tcp_connection_rst);
8866 if(tcp_analyze_seq
8867 && (tcph->th_flags & (TH_SYN|TH_ACK)) == TH_ACK
8868 && !nstime_is_zero(&tcpd->ts_mru_syn)
8869 && nstime_is_zero(&tcpd->ts_first_rtt)) {
8870 /* If all of the following:
8871 * - we care (the pref is set)
8872 * - this is a pure ACK
8873 * - we have a timestamp for the most-recently-transmitted SYN
8874 * - we haven't seen a pure ACK yet (no ts_first_rtt stored)
8875 * then assume it's the last part of the handshake and store the initial
8876 * RTT time
8878 nstime_delta(&(tcpd->ts_first_rtt), &(pinfo->abs_ts), &(tcpd->ts_mru_syn));
8882 * Remember if we have already seen at least one ACK,
8883 * then we can neutralize the Window Scale side-effect at the beginning (issue 14690)
8885 if(tcp_analyze_seq
8886 && (tcph->th_flags & (TH_SYN|TH_ACK)) == TH_ACK) {
8887 if(tcpd->fwd->is_first_ack) {
8888 tcpd->fwd->is_first_ack = false;
8892 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
8893 real_window = tcph->th_win;
8894 /* re-calculate window size based on scaling factor */
8895 if (!(tcph->th_flags&TH_SYN)) { /* SYNs are never scaled */
8896 if (tcpd && (tcpd->fwd->win_scale>=0)) {
8897 (tcph->th_win)<<=tcpd->fwd->win_scale;
8899 else if (tcpd && (tcpd->fwd->win_scale == -1)) {
8900 /* i.e. Unknown, but wasn't signalled with no scaling, so use preference setting instead! */
8901 if (tcp_default_window_scaling>=0) {
8902 (tcph->th_win)<<=tcp_default_window_scaling;
8907 tcp_info_append_uint(pinfo, "Win", tcph->th_win);
8909 if (tree) {
8910 /* As discussed in bug 5541, it is better to use two separate
8911 * fields for the real and calculated window size.
8913 proto_tree_add_uint(tcp_tree, hf_tcp_window_size_value, tvb, offset + 14, 2, real_window);
8914 if(tcph->th_flags & TH_RST){
8915 /* Check if the window value of this reset packet is in the NetScaler error code range */
8916 const char *tcp_ns_reset_window_error_descr = try_val_to_str(real_window, netscaler_reset_window_error_code_vals);
8917 if (tcp_ns_reset_window_error_descr != NULL) { /* If its in the Netscaler range, add tree */
8918 item = proto_tree_add_string(tcp_tree, hf_tcp_ns_reset_window_error_code, tvb,
8919 offset + 14, 2, tcp_ns_reset_window_error_descr);
8920 proto_item_set_generated(item);
8923 scaled_pi = proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win);
8924 proto_item_set_generated(scaled_pi);
8926 if( !(tcph->th_flags&TH_SYN) && tcpd ) {
8927 switch (tcpd->fwd->win_scale) {
8929 case -1:
8930 /* Unknown */
8932 int16_t win_scale = tcpd->fwd->win_scale;
8933 bool override_with_pref = false;
8935 /* Use preference setting (if set) */
8936 if (tcp_default_window_scaling != WindowScaling_NotKnown) {
8937 win_scale = (1 << tcp_default_window_scaling);
8938 override_with_pref = true;
8941 scaled_pi = proto_tree_add_int_format_value(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2,
8942 win_scale, "%d (%s)",
8943 win_scale,
8944 (override_with_pref) ? "missing - taken from preference" : "unknown");
8945 proto_item_set_generated(scaled_pi);
8947 break;
8949 case -2:
8950 /* No window scaling used */
8951 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);
8952 proto_item_set_generated(scaled_pi);
8953 break;
8955 default:
8956 /* Scaling from signalled value */
8957 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);
8958 proto_item_set_generated(scaled_pi);
8963 /* Supply the sequence number of the first byte and of the first byte
8964 after the segment. */
8965 tcpinfo.seq = tcph->th_seq;
8966 tcpinfo.nxtseq = nxtseq;
8967 tcpinfo.lastackseq = tcph->th_ack;
8969 /* Assume we'll pass un-reassembled data to subdissectors. */
8970 tcpinfo.is_reassembled = false;
8973 * Assume, initially, that we can't desegment.
8975 pinfo->can_desegment = 0;
8976 th_sum = tvb_get_ntohs(tvb, offset + 16);
8977 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
8978 /* The packet isn't part of an un-reassembled fragmented datagram
8979 and isn't truncated. This means we have all the data, and thus
8980 can checksum it and, unless it's being returned in an error
8981 packet, are willing to allow subdissectors to request reassembly
8982 on it. */
8984 if (tcp_check_checksum) {
8985 /* We haven't turned checksum checking off; checksum it. */
8987 /* Set up the fields of the pseudo-header. */
8988 SET_CKSUM_VEC_PTR(cksum_vec[0], (const uint8_t *)pinfo->src.data, pinfo->src.len);
8989 SET_CKSUM_VEC_PTR(cksum_vec[1], (const uint8_t *)pinfo->dst.data, pinfo->dst.len);
8990 switch (pinfo->src.type) {
8992 case AT_IPv4:
8993 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
8994 SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *)phdr, 4);
8995 break;
8997 case AT_IPv6:
8998 phdr[0] = g_htonl(reported_len);
8999 phdr[1] = g_htonl(IP_PROTO_TCP);
9000 SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *)phdr, 8);
9001 break;
9003 default:
9004 /* TCP runs only atop IPv4 and IPv6.... */
9005 DISSECTOR_ASSERT_NOT_REACHED();
9006 break;
9008 /* See discussion in packet-udp.c of partial checksums used in
9009 * checksum offloading in Linux and Windows (and possibly others.)
9011 uint16_t partial_cksum;
9012 SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, offset, reported_len);
9013 computed_cksum = in_cksum_ret_partial(cksum_vec, 4, &partial_cksum);
9014 if (computed_cksum == 0 && th_sum == 0xffff) {
9015 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
9016 offset + 16, 2, th_sum,
9017 "0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);
9019 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
9020 item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_calculated, tvb,
9021 offset + 16, 2, 0x0000);
9022 proto_item_set_generated(item);
9023 /* XXX - What should this special status be? */
9024 item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_status, tvb,
9025 offset + 16, 0, PROTO_CHECKSUM_E_BAD);
9026 proto_item_set_generated(item);
9027 expert_add_info(pinfo, item, &ei_tcp_checksum_ffff);
9029 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");
9031 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
9032 desegment_ok = true;
9033 } else {
9034 proto_item* calc_item;
9035 uint16_t shouldbe_cksum = in_cksum_shouldbe(th_sum, computed_cksum);
9036 if (computed_cksum != 0 && th_sum == g_htons(partial_cksum)) {
9037 /* Don't use PROTO_CHECKSUM_IN_CKSUM because we expect the value
9038 * to match what we pass in. */
9039 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),
9040 ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
9041 proto_item_append_text(item, " (matches partial checksum, not 0x%04x, likely caused by \"TCP checksum offload\")", shouldbe_cksum);
9042 expert_add_info(pinfo, item, &ei_tcp_checksum_partial);
9043 computed_cksum = 0;
9044 /* XXX Add a new status, e.g. PROTO_CHECKSUM_E_PARTIAL? */
9045 } else {
9046 item = proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, computed_cksum,
9047 ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
9049 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
9050 calc_item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_calculated, tvb,
9051 offset + 16, 2, shouldbe_cksum);
9052 proto_item_set_generated(calc_item);
9054 /* Checksum is valid, so we're willing to desegment it. */
9055 if (computed_cksum == 0) {
9056 desegment_ok = true;
9057 } else {
9058 proto_item_append_text(item, "(maybe caused by \"TCP checksum offload\"?)");
9060 /* Checksum is invalid, so we're not willing to desegment it. */
9061 desegment_ok = false;
9062 pinfo->noreassembly_reason = " [incorrect TCP checksum]";
9063 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");
9066 } else {
9067 proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, 0,
9068 ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
9070 /* We didn't check the checksum, and don't care if it's valid,
9071 so we're willing to desegment it. */
9072 desegment_ok = true;
9074 } else {
9075 /* We don't have all the packet data, so we can't checksum it... */
9076 proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, 0,
9077 ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
9079 /* ...and aren't willing to desegment it. */
9080 desegment_ok = false;
9083 if (desegment_ok) {
9084 /* We're willing to desegment this. Is desegmentation enabled? */
9085 if (tcp_desegment) {
9086 /* Yes - is this segment being returned in an error packet? */
9087 if (!pinfo->flags.in_error_pkt) {
9088 /* No - indicate that we will desegment.
9089 We do NOT want to desegment segments returned in error
9090 packets, as they're not part of a TCP connection. */
9091 pinfo->can_desegment = 2;
9096 item = proto_tree_add_item_ret_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, ENC_BIG_ENDIAN, &th_urp);
9098 if (IS_TH_URG(tcph->th_flags)) {
9099 /* Export the urgent pointer, for the benefit of protocols such as
9100 rlogin. */
9101 tcpinfo.urgent_pointer = (uint16_t)th_urp;
9102 tcp_info_append_uint(pinfo, "Urg", th_urp);
9103 } else {
9104 if (th_urp) {
9105 /* Note if the urgent pointer field is non-zero */
9106 expert_add_info(pinfo, item, &ei_tcp_urgent_pointer_non_zero);
9110 if (tcph->th_have_seglen)
9111 tcp_info_append_uint(pinfo, "Len", tcph->th_seglen);
9113 /* If there's more than just the fixed-length header (20 bytes), create
9114 a protocol tree item for the options. (We already know there's
9115 not less than the fixed-length header - we checked that above.)
9117 We ensure that we don't throw an exception here, so that we can
9118 do some analysis before we dissect the options and possibly
9119 throw an exception. (Trying to avoid throwing an exception when
9120 dissecting options is not something we should do.) */
9121 optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
9122 options_item = NULL;
9123 options_tree = NULL;
9124 if (optlen != 0) {
9125 unsigned bc = (unsigned)tvb_captured_length_remaining(tvb, offset + 20);
9127 if (tcp_tree != NULL) {
9128 options_item = proto_tree_add_item(tcp_tree, hf_tcp_options, tvb, offset + 20,
9129 bc < optlen ? bc : optlen, ENC_NA);
9130 proto_item_set_text(options_item, "Options: (%u bytes)", optlen);
9131 options_tree = proto_item_add_subtree(options_item, ett_tcp_options);
9135 tcph->num_sack_ranges = 0;
9137 /* handle conversation timestamps */
9138 if(tcp_calculate_ts) {
9139 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
9142 /* Now dissect the options. */
9143 if (optlen) {
9144 rvbd_option_data* option_data;
9146 tcp_dissect_options(tvb, offset + 20, optlen,
9147 pinfo, options_tree,
9148 options_item, tcph);
9150 /* Do some post evaluation of some Riverbed probe options in the list */
9151 option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);
9152 if (option_data != NULL)
9154 if (option_data->valid)
9156 /* Distinguish S+ from S+* */
9157 col_prepend_fstr(pinfo->cinfo, COL_INFO, "S%s, ",
9158 option_data->type == PROBE_TRACE ? "#" :
9159 (option_data->probe_flags & RVBD_FLAGS_PROBE_NCFE) ? "+*" : "+");
9165 /* Handle default MSS values for IPv4 and IPv6
9166 * If MSS is still -1 after dissecting the options,
9167 * apply the default values (as per RFC 9293).
9169 if(tcp_analyze_seq && conversation_is_new &&
9170 !pinfo->fd->visited &&
9171 tcpd->fwd->mss==-1) {
9173 switch(pinfo->src.type) {
9174 case AT_IPv4:
9175 tcpd->fwd->mss = 536;
9176 tcpd->rev->mss = 536;
9177 break;
9178 case AT_IPv6:
9179 tcpd->fwd->mss = 1220;
9180 tcpd->rev->mss = 1220;
9181 break;
9182 default:
9183 DISSECTOR_ASSERT_NOT_REACHED();
9184 break;
9188 /* If SYN (and hence MSS value) for that direction is missing,
9189 * the default MSS value might not be realistic */
9190 if (tcph->th_have_seglen && tcph->th_seglen>(uint32_t)tcpd->fwd->mss) {
9191 expert_add_info(pinfo, NULL, &ei_tcp_option_mss_exceeded);
9194 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
9195 if(tcp_analyze_seq) {
9196 uint32_t use_seq = tcph->th_seq;
9197 uint32_t use_ack = tcph->th_ack;
9198 /* May need to recover absolute values here... */
9199 if (tcp_relative_seq) {
9200 use_seq += tcpd->fwd->base_seq;
9201 if (tcph->th_flags & TH_ACK) {
9202 use_ack += tcpd->rev->base_seq;
9205 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd, use_seq, use_ack);
9208 if(!pinfo->fd->visited) {
9209 if((tcph->th_flags & TH_SYN)==TH_SYN) {
9210 /* Check the validity of the window scale value
9212 verify_tcp_window_scaling((tcph->th_flags&TH_ACK)==TH_ACK,tcpd);
9215 if((tcph->th_flags & (TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
9216 /* If the SYN or the SYN+ACK offered SCPS capabilities,
9217 * validate the flow's bidirectional scps capabilities.
9218 * The or protects against broken implementations offering
9219 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
9221 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {
9222 verify_scps(pinfo, tf_syn, tcpd);
9228 if (tcph->th_mptcp) {
9230 if (tcp_analyze_mptcp) {
9231 mptcp_add_analysis_subtree(pinfo, tvb, tcp_tree, tcpd, tcpd->mptcp_analysis, tcph );
9235 /* Skip over header + options */
9236 offset += tcph->th_hlen;
9238 /* Check the packet length to see if there's more data
9239 (it could be an ACK-only packet) */
9240 captured_length_remaining = tvb_captured_length_remaining(tvb, offset);
9242 if (tcph->th_have_seglen) {
9243 if(have_tap_listener(tcp_follow_tap)) {
9244 tcp_follow_tap_data_t* follow_data = wmem_new0(pinfo->pool, tcp_follow_tap_data_t);
9246 follow_data->tvb = tvb_new_subset_remaining(tvb, offset);
9247 follow_data->tcph = tcph;
9248 follow_data->tcpd = tcpd;
9250 tap_queue_packet(tcp_follow_tap, pinfo, follow_data);
9254 /* Nothing more to add to tcph, go ahead and send to the taps. */
9255 CLEANUP_CALL_AND_POP;
9257 /* if it is an MPTCP packet */
9258 if(tcpd->mptcp_analysis) {
9259 tap_queue_packet(mptcp_tap, pinfo, tcpd);
9262 /* If we're reassembling something whose length isn't known
9263 * beforehand, and that runs all the way to the end of
9264 * the data stream, a FIN indicates the end of the data
9265 * stream and thus the completion of reassembly, so we
9266 * need to explicitly check for that here.
9268 if(tcph->th_have_seglen && tcpd && (tcph->th_flags & TH_FIN)
9269 && pinfo->can_desegment
9270 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ) {
9271 struct tcp_multisegment_pdu *msp;
9273 /* Is this the FIN that ended the data stream or is it a
9274 * retransmission of that FIN?
9276 if (tcpd->fwd->fin == 0 || tcpd->fwd->fin == pinfo->num) {
9277 /* Either we haven't seen a FIN for this flow or we
9278 * have and it's this frame. Note that this is the FIN
9279 * for this flow, terminate reassembly and dissect the
9280 * results. */
9281 tcpd->fwd->fin = pinfo->num;
9282 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq);
9283 if(msp) {
9284 fragment_head *ipfd_head;
9286 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,
9287 pinfo, msp->first_frame, msp,
9288 tcph->th_seq - msp->seq,
9289 tcph->th_seglen,
9290 false );
9291 if(ipfd_head && ipfd_head->reassembled_in == pinfo->num && ipfd_head->reas_in_layer_num == pinfo->curr_layer_num) {
9292 tvbuff_t *next_tvb;
9294 /* create a new TVB structure for desegmented data
9295 * datalen-1 to strip the dummy FIN byte off
9297 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
9299 /* add desegmented data to the data source list */
9300 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
9302 /* Show details of the reassembly */
9303 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
9305 /* call the payload dissector
9306 * but make sure we don't offer desegmentation any more
9308 pinfo->can_desegment = 0;
9310 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq,
9311 nxtseq, false, tcpd, &tcpinfo);
9313 return tvb_captured_length(tvb);
9316 } else {
9317 /* Yes. This is a retransmission of the final FIN (or it's
9318 * the final FIN transmitted via a different path).
9319 * XXX - we need to flag retransmissions a bit better.
9321 proto_tree_add_uint(tcp_tree, hf_tcp_fin_retransmission, tvb, 0, 0, tcpd->fwd->fin);
9325 if (tcp_display_process_info && tcpd && ((tcpd->fwd && tcpd->fwd->process_info && tcpd->fwd->process_info->command) ||
9326 (tcpd->rev && tcpd->rev->process_info && tcpd->rev->process_info->command))) {
9327 field_tree = proto_tree_add_subtree(tcp_tree, tvb, offset, 0, ett_tcp_process_info, &ti, "Process Information");
9328 proto_item_set_generated(ti);
9329 if (tcpd->fwd && tcpd->fwd->process_info && tcpd->fwd->process_info->command) {
9330 proto_tree_add_uint(field_tree, hf_tcp_proc_dst_uid, tvb, 0, 0, tcpd->fwd->process_info->process_uid);
9331 proto_tree_add_uint(field_tree, hf_tcp_proc_dst_pid, tvb, 0, 0, tcpd->fwd->process_info->process_pid);
9332 proto_tree_add_string(field_tree, hf_tcp_proc_dst_uname, tvb, 0, 0, tcpd->fwd->process_info->username);
9333 proto_tree_add_string(field_tree, hf_tcp_proc_dst_cmd, tvb, 0, 0, tcpd->fwd->process_info->command);
9335 if (tcpd->rev && tcpd->rev->process_info && tcpd->rev->process_info->command) {
9336 proto_tree_add_uint(field_tree, hf_tcp_proc_src_uid, tvb, 0, 0, tcpd->rev->process_info->process_uid);
9337 proto_tree_add_uint(field_tree, hf_tcp_proc_src_pid, tvb, 0, 0, tcpd->rev->process_info->process_pid);
9338 proto_tree_add_string(field_tree, hf_tcp_proc_src_uname, tvb, 0, 0, tcpd->rev->process_info->username);
9339 proto_tree_add_string(field_tree, hf_tcp_proc_src_cmd, tvb, 0, 0, tcpd->rev->process_info->command);
9344 * XXX - what, if any, of this should we do if this is included in an
9345 * error packet? It might be nice to see the details of the packet
9346 * that caused the ICMP error, but it might not be nice to have the
9347 * dissector update state based on it.
9348 * Also, we probably don't want to run TCP taps on those packets.
9350 if (captured_length_remaining != 0) {
9351 if (tcph->th_flags & TH_RST) {
9353 * RFC1122 says:
9355 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
9357 * A TCP SHOULD allow a received RST segment to include data.
9359 * DISCUSSION
9360 * It has been suggested that a RST segment could contain
9361 * ASCII text that encoded and explained the cause of the
9362 * RST. No standard has yet been established for such
9363 * data.
9365 * so for segments with RST we just display the data as text.
9367 proto_tree_add_item(tcp_tree, hf_tcp_reset_cause, tvb, offset, captured_length_remaining, ENC_NA|ENC_ASCII);
9368 } else {
9369 /* When we have a frame with TCP SYN bit set and segmented TCP payload we need
9370 * to increment seq and nxtseq to detect the overlapping byte(s). This is to fix Bug 9882.
9372 if(tcph->th_flags & TH_SYN) {
9373 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq + 1, nxtseq + 1,
9374 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo);
9375 } else {
9376 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
9377 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo);
9381 return tvb_captured_length(tvb);
9384 static void
9385 tcp_init(void)
9387 tcp_stream_count = 0;
9389 /* MPTCP init */
9390 mptcp_stream_count = 0;
9391 mptcp_tokens = wmem_tree_new(wmem_file_scope());
9394 void
9395 proto_register_tcp(void)
9397 static hf_register_info hf[] = {
9399 { &hf_tcp_srcport,
9400 { "Source Port", "tcp.srcport", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
9401 NULL, HFILL }},
9403 { &hf_tcp_dstport,
9404 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
9405 NULL, HFILL }},
9407 { &hf_tcp_port,
9408 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
9409 NULL, HFILL }},
9411 { &hf_tcp_stream,
9412 { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
9413 NULL, HFILL }},
9415 { &hf_tcp_stream_pnum,
9416 { "Stream Packet Number", "tcp.stream.pnum", FT_UINT32, BASE_DEC,
9417 NULL, 0x0,
9418 "Relative packet number in this TCP stream", HFILL }},
9420 { &hf_tcp_completeness,
9421 { "Conversation completeness", "tcp.completeness", FT_UINT8,
9422 BASE_CUSTOM, CF_FUNC(conversation_completeness_fill), 0x0,
9423 "The completeness of the conversation capture", HFILL }},
9425 { &hf_tcp_completeness_syn,
9426 { "SYN", "tcp.completeness.syn", FT_BOOLEAN, 8,
9427 TFS(&tfs_present_absent), TCP_COMPLETENESS_SYNSENT,
9428 "Conversation has a SYN packet", HFILL}},
9430 { &hf_tcp_completeness_syn_ack,
9431 { "SYN-ACK", "tcp.completeness.syn-ack", FT_BOOLEAN, 8,
9432 TFS(&tfs_present_absent), TCP_COMPLETENESS_SYNACK,
9433 "Conversation has a SYN-ACK packet", HFILL}},
9435 { &hf_tcp_completeness_ack,
9436 { "ACK", "tcp.completeness.ack", FT_BOOLEAN, 8,
9437 TFS(&tfs_present_absent), TCP_COMPLETENESS_ACK,
9438 "Conversation has an ACK packet", HFILL}},
9440 { &hf_tcp_completeness_data,
9441 { "Data", "tcp.completeness.data", FT_BOOLEAN, 8,
9442 TFS(&tfs_present_absent), TCP_COMPLETENESS_DATA,
9443 "Conversation has payload DATA", HFILL}},
9445 { &hf_tcp_completeness_fin,
9446 { "FIN", "tcp.completeness.fin", FT_BOOLEAN, 8,
9447 TFS(&tfs_present_absent), TCP_COMPLETENESS_FIN,
9448 "Conversation has a FIN packet", HFILL}},
9450 { &hf_tcp_completeness_rst,
9451 { "RST", "tcp.completeness.rst", FT_BOOLEAN, 8,
9452 TFS(&tfs_present_absent), TCP_COMPLETENESS_RST,
9453 "Conversation has a RST packet", HFILL}},
9455 { &hf_tcp_completeness_str,
9456 { "Completeness Flags", "tcp.completeness.str", FT_STRING, BASE_NONE, NULL, 0x0,
9457 NULL, HFILL }},
9459 { &hf_tcp_seq,
9460 { "Sequence Number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
9461 NULL, HFILL }},
9463 { &hf_tcp_seq_abs,
9464 { "Sequence Number (raw)", "tcp.seq_raw", FT_UINT32, BASE_DEC, NULL, 0x0,
9465 "This shows the raw value of the sequence number", HFILL }},
9467 { &hf_tcp_nxtseq,
9468 { "Next Sequence Number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
9469 NULL, HFILL }},
9471 { &hf_tcp_ack,
9472 { "Acknowledgment Number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
9473 NULL, HFILL }},
9475 { &hf_tcp_ack_abs,
9476 { "Acknowledgment number (raw)", "tcp.ack_raw", FT_UINT32, BASE_DEC, NULL, 0x0,
9477 "This shows the raw value of the acknowledgment number", HFILL } },
9479 // "Data Offset" in https://tools.ietf.org/html/rfc793#section-3.1 and
9480 // "Data offset" in https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
9481 { &hf_tcp_hdr_len,
9482 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
9483 "Data offset in 32-bit words", HFILL }},
9485 { &hf_tcp_flags,
9486 { "Flags", "tcp.flags", FT_UINT16, BASE_HEX, NULL, TH_MASK,
9487 NULL, HFILL }},
9489 { &hf_tcp_flags_res,
9490 { "Reserved", "tcp.flags.res", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RES,
9491 "Three reserved bits (must be zero)", HFILL }},
9493 { &hf_tcp_flags_ae,
9494 { "Accurate ECN", "tcp.flags.ae", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_AE,
9495 NULL, HFILL }},
9497 { &hf_tcp_flags_cwr,
9498 { "Congestion Window Reduced", "tcp.flags.cwr", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_CWR,
9499 NULL, HFILL }},
9501 { &hf_tcp_flags_ece,
9502 { "ECN-Echo", "tcp.flags.ece", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ECE,
9503 NULL, HFILL }},
9505 { &hf_tcp_flags_ace,
9506 { "ACE", "tcp.flags.ace", FT_UINT8, BASE_DEC, NULL, 0x0,
9507 NULL, HFILL }},
9509 { &hf_tcp_flags_urg,
9510 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_URG,
9511 NULL, HFILL }},
9513 { &hf_tcp_flags_ack,
9514 { "Acknowledgment", "tcp.flags.ack", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ACK,
9515 NULL, HFILL }},
9517 { &hf_tcp_flags_push,
9518 { "Push", "tcp.flags.push", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_PUSH,
9519 NULL, HFILL }},
9521 { &hf_tcp_flags_reset,
9522 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RST,
9523 NULL, HFILL }},
9525 { &hf_tcp_flags_syn,
9526 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_SYN,
9527 NULL, HFILL }},
9529 { &hf_tcp_flags_fin,
9530 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_FIN,
9531 NULL, HFILL }},
9533 { &hf_tcp_flags_str,
9534 { "TCP Flags", "tcp.flags.str", FT_STRING, BASE_NONE, NULL, 0x0,
9535 NULL, HFILL }},
9537 { &hf_tcp_window_size_value,
9538 { "Window", "tcp.window_size_value", FT_UINT16, BASE_DEC, NULL, 0x0,
9539 "The window size value from the TCP header", HFILL }},
9541 /* 32 bits so we can present some values adjusted to window scaling */
9542 { &hf_tcp_window_size,
9543 { "Calculated window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
9544 "The scaled window size (if scaling has been used)", HFILL }},
9546 { &hf_tcp_window_size_scalefactor,
9547 { "Window size scaling factor", "tcp.window_size_scalefactor", FT_INT32, BASE_DEC, NULL, 0x0,
9548 "The window size scaling factor (-1 when unknown, -2 when no scaling is used)", HFILL }},
9550 { &hf_tcp_checksum,
9551 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
9552 "Details at: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
9554 { &hf_tcp_checksum_status,
9555 { "Checksum Status", "tcp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
9556 NULL, HFILL }},
9558 { &hf_tcp_checksum_calculated,
9559 { "Calculated Checksum", "tcp.checksum_calculated", FT_UINT16, BASE_HEX, NULL, 0x0,
9560 "The expected TCP checksum field as calculated from the TCP segment", HFILL }},
9562 { &hf_tcp_analysis,
9563 { "SEQ/ACK analysis", "tcp.analysis", FT_NONE, BASE_NONE, NULL, 0x0,
9564 "This frame has some of the TCP analysis shown", HFILL }},
9566 { &hf_tcp_analysis_flags,
9567 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
9568 "This frame has some of the TCP analysis flags set", HFILL }},
9570 { &hf_tcp_analysis_duplicate_ack,
9571 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
9572 "This is a duplicate ACK", HFILL }},
9574 { &hf_tcp_analysis_duplicate_ack_num,
9575 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
9576 "This is duplicate ACK number #", HFILL }},
9578 { &hf_tcp_analysis_duplicate_ack_frame,
9579 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_DUP_ACK), 0x0,
9580 "This is a duplicate to the ACK in frame #", HFILL }},
9582 { &hf_tcp_continuation_to,
9583 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9584 "This is a continuation to the PDU in frame #", HFILL }},
9586 { &hf_tcp_len,
9587 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
9588 NULL, HFILL}},
9590 { &hf_tcp_analysis_acks_frame,
9591 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0,
9592 "Which previous segment is this an ACK for", HFILL}},
9594 { &hf_tcp_analysis_bytes_in_flight,
9595 { "Bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL, 0x0,
9596 "How many bytes are now in flight for this connection", HFILL}},
9598 { &hf_tcp_analysis_push_bytes_sent,
9599 { "Bytes sent since last PSH flag", "tcp.analysis.push_bytes_sent", FT_UINT32, BASE_DEC, NULL, 0x0,
9600 "How many bytes have been sent since the last PSH flag", HFILL}},
9602 { &hf_tcp_analysis_ack_rtt,
9603 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
9604 "How long time it took to ACK the segment (RTT)", HFILL}},
9606 { &hf_tcp_analysis_first_rtt,
9607 { "iRTT", "tcp.analysis.initial_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
9608 "How long it took for the SYN to ACK handshake (iRTT)", HFILL}},
9610 { &hf_tcp_analysis_rto,
9611 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
9612 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL}},
9614 { &hf_tcp_analysis_rto_frame,
9615 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9616 "This is the frame we measure the RTO from", HFILL }},
9618 { &hf_tcp_urgent_pointer,
9619 { "Urgent Pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
9620 NULL, HFILL }},
9622 { &hf_tcp_segment_overlap,
9623 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9624 "Segment overlaps with other segments", HFILL }},
9626 { &hf_tcp_segment_overlap_conflict,
9627 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9628 "Overlapping segments contained conflicting data", HFILL }},
9630 { &hf_tcp_segment_multiple_tails,
9631 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9632 "Several tails were found when reassembling the pdu", HFILL }},
9634 { &hf_tcp_segment_too_long_fragment,
9635 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9636 "Segment contained data past end of the pdu", HFILL }},
9638 { &hf_tcp_segment_error,
9639 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9640 "Reassembling error due to illegal segments", HFILL }},
9642 { &hf_tcp_segment_count,
9643 { "Segment count", "tcp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
9644 NULL, HFILL }},
9646 { &hf_tcp_segment,
9647 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9648 NULL, HFILL }},
9650 { &hf_tcp_segments,
9651 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
9652 NULL, HFILL }},
9654 { &hf_tcp_reassembled_in,
9655 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9656 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
9658 { &hf_tcp_reassembled_length,
9659 { "Reassembled TCP length", "tcp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
9660 "The total length of the reassembled payload", HFILL }},
9662 { &hf_tcp_reassembled_data,
9663 { "Reassembled TCP Data", "tcp.reassembled.data", FT_BYTES, BASE_NONE, NULL, 0x0,
9664 "The reassembled payload", HFILL }},
9666 { &hf_tcp_option_kind,
9667 { "Kind", "tcp.option_kind", FT_UINT8,
9668 BASE_DEC|BASE_EXT_STRING, &tcp_option_kind_vs_ext, 0x0, "This TCP option's kind", HFILL }},
9670 { &hf_tcp_option_len,
9671 { "Length", "tcp.option_len", FT_UINT8,
9672 BASE_DEC, NULL, 0x0, "Length of this TCP option in bytes (including kind and length fields)", HFILL }},
9674 { &hf_tcp_options,
9675 { "TCP Options", "tcp.options", FT_BYTES,
9676 BASE_NONE, NULL, 0x0, NULL, HFILL }},
9678 { &hf_tcp_option_mss_val,
9679 { "MSS Value", "tcp.options.mss_val", FT_UINT16,
9680 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9682 { &hf_tcp_option_wscale_shift,
9683 { "Shift count", "tcp.options.wscale.shift", FT_UINT8,
9684 BASE_DEC, NULL, 0x0, "Logarithmically encoded power of 2 scale factor", HFILL}},
9686 { &hf_tcp_option_wscale_multiplier,
9687 { "Multiplier", "tcp.options.wscale.multiplier", FT_UINT16,
9688 BASE_DEC, NULL, 0x0, "Multiply segment window size by this for scaled window size", HFILL}},
9690 { &hf_tcp_option_exp_data,
9691 { "Data", "tcp.options.experimental.data", FT_BYTES,
9692 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9694 { &hf_tcp_option_exp_exid,
9695 { "Experiment Identifier", "tcp.options.experimental.exid", FT_UINT16,
9696 BASE_HEX, &tcp_exid_vs, 0x0, NULL, HFILL}},
9698 { &hf_tcp_option_unknown_payload,
9699 { "Payload", "tcp.options.unknown.payload", FT_BYTES,
9700 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9702 { &hf_tcp_option_sack_sle,
9703 {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32,
9704 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9706 { &hf_tcp_option_sack_sre,
9707 {"TCP SACK Right Edge", "tcp.options.sack_re", FT_UINT32,
9708 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9710 { &hf_tcp_option_sack_range_count,
9711 { "TCP SACK Count", "tcp.options.sack.count", FT_UINT8,
9712 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9714 { &hf_tcp_option_sack_dsack_le,
9715 {"TCP D-SACK Left Edge", "tcp.options.sack.dsack_le", FT_UINT32,
9716 BASE_DEC, NULL, 0x0, "Duplicate SACK Left Edge", HFILL}},
9718 { &hf_tcp_option_sack_dsack_re,
9719 {"TCP D-SACK Right Edge", "tcp.options.sack.dsack_re", FT_UINT32,
9720 BASE_DEC, NULL, 0x0, "Duplicate SACK Right Edge", HFILL}},
9722 { &hf_tcp_option_echo,
9723 { "TCP Echo Option", "tcp.options.echo_value", FT_UINT32,
9724 BASE_DEC, NULL, 0x0, "TCP Sack Echo", HFILL}},
9726 { &hf_tcp_option_timestamp_tsval,
9727 { "Timestamp value", "tcp.options.timestamp.tsval", FT_UINT32,
9728 BASE_DEC, NULL, 0x0, "Value of sending machine's timestamp clock", HFILL}},
9730 { &hf_tcp_option_timestamp_tsecr,
9731 { "Timestamp echo reply", "tcp.options.timestamp.tsecr", FT_UINT32,
9732 BASE_DEC, NULL, 0x0, "Echoed timestamp from remote machine", HFILL}},
9734 { &hf_tcp_option_mptcp_subtype,
9735 { "Multipath TCP subtype", "tcp.options.mptcp.subtype", FT_UINT8,
9736 BASE_DEC, VALS(mptcp_subtype_vs), 0xF0, NULL, HFILL}},
9738 { &hf_tcp_option_mptcp_version,
9739 { "Multipath TCP version", "tcp.options.mptcp.version", FT_UINT8,
9740 BASE_DEC, NULL, 0x0F, NULL, HFILL}},
9742 { &hf_tcp_option_mptcp_reserved,
9743 { "Reserved", "tcp.options.mptcp.reserved", FT_UINT16,
9744 BASE_HEX, NULL, 0x0FFF, NULL, HFILL}},
9746 { &hf_tcp_option_mptcp_flags,
9747 { "Multipath TCP flags", "tcp.options.mptcp.flags", FT_UINT8,
9748 BASE_HEX, NULL, 0x0, NULL, HFILL}},
9750 { &hf_tcp_option_mptcp_backup_flag,
9751 { "Backup flag", "tcp.options.mptcp.backup.flag", FT_UINT8,
9752 BASE_DEC, NULL, 0x01, NULL, HFILL}},
9754 { &hf_tcp_option_mptcp_checksum_flag,
9755 { "Checksum required", "tcp.options.mptcp.checksumreq.flags", FT_UINT8,
9756 BASE_DEC, NULL, MPTCP_CHECKSUM_MASK, NULL, HFILL}},
9758 { &hf_tcp_option_mptcp_B_flag,
9759 { "Extensibility", "tcp.options.mptcp.extensibility.flag", FT_UINT8,
9760 BASE_DEC, NULL, 0x40, NULL, HFILL}},
9762 { &hf_tcp_option_mptcp_C_flag,
9763 { "Do not attempt to establish new subflows to this address and port", "tcp.options.mptcp.nomoresubflows.flag", FT_UINT8,
9764 BASE_DEC, NULL, 0x20, NULL, HFILL}},
9766 { &hf_tcp_option_mptcp_H_v0_flag,
9767 { "Use HMAC-SHA1", "tcp.options.mptcp.sha1.flag", FT_UINT8,
9768 BASE_DEC, NULL, 0x01, NULL, HFILL}},
9770 { &hf_tcp_option_mptcp_H_v1_flag,
9771 { "Use HMAC-SHA256", "tcp.options.mptcp.sha256.flag", FT_UINT8,
9772 BASE_DEC, NULL, 0x01, NULL, HFILL}},
9774 { &hf_tcp_option_mptcp_F_flag,
9775 { "DATA_FIN", "tcp.options.mptcp.datafin.flag", FT_UINT8,
9776 BASE_DEC, NULL, MPTCP_DSS_FLAG_DATA_FIN_PRESENT, NULL, HFILL}},
9778 { &hf_tcp_option_mptcp_m_flag,
9779 { "Data Sequence Number is 8 octets", "tcp.options.mptcp.dseqn8.flag", FT_UINT8,
9780 BASE_DEC, NULL, MPTCP_DSS_FLAG_DSN_8BYTES, NULL, HFILL}},
9782 { &hf_tcp_option_mptcp_M_flag,
9783 { "Data Sequence Number, Subflow Sequence Number, Data-level Length, Checksum present", "tcp.options.mptcp.dseqnpresent.flag", FT_UINT8,
9784 BASE_DEC, NULL, MPTCP_DSS_FLAG_MAPPING_PRESENT, NULL, HFILL}},
9786 { &hf_tcp_option_mptcp_a_flag,
9787 { "Data ACK is 8 octets", "tcp.options.mptcp.dataack8.flag", FT_UINT8,
9788 BASE_DEC, NULL, MPTCP_DSS_FLAG_DATA_ACK_8BYTES, NULL, HFILL}},
9790 { &hf_tcp_option_mptcp_A_flag,
9791 { "Data ACK is present", "tcp.options.mptcp.dataackpresent.flag", FT_UINT8,
9792 BASE_DEC, NULL, MPTCP_DSS_FLAG_DATA_ACK_PRESENT, NULL, HFILL}},
9794 { &hf_tcp_option_mptcp_reserved_v0_flag,
9795 { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8,
9796 BASE_HEX, NULL, 0x3E, NULL, HFILL}},
9798 { &hf_tcp_option_mptcp_reserved_v1_flag,
9799 { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8,
9800 BASE_HEX, NULL, 0x1E, NULL, HFILL}},
9802 { &hf_tcp_option_mptcp_U_flag,
9803 { "Flag U", "tcp.options.mptcp.flag_U.flag", FT_BOOLEAN,
9804 4, TFS(&tfs_set_notset), MPTCP_TCPRST_FLAG_U_PRESENT, NULL, HFILL}},
9806 { &hf_tcp_option_mptcp_V_flag,
9807 { "Flag V", "tcp.options.mptcp.flag_V.flag", FT_BOOLEAN,
9808 4, TFS(&tfs_set_notset), MPTCP_TCPRST_FLAG_V_PRESENT, NULL, HFILL}},
9810 { &hf_tcp_option_mptcp_W_flag,
9811 { "Flag W", "tcp.options.mptcp.flag_W.flag", FT_BOOLEAN,
9812 4, TFS(&tfs_set_notset), MPTCP_TCPRST_FLAG_W_PRESENT, NULL, HFILL}},
9814 { &hf_tcp_option_mptcp_T_flag,
9815 { "Transient", "tcp.options.mptcp.flag_T.flag", FT_BOOLEAN,
9816 4, TFS(&tfs_set_notset), MPTCP_TCPRST_FLAG_T_PRESENT, NULL, HFILL}},
9818 { &hf_tcp_option_mptcp_tcprst_reason,
9819 { "TCPRST Reason", "tcp.options.mptcp.rst_reason", FT_UINT8,
9820 BASE_HEX, VALS(mp_tcprst_reasons), 0x0, "Multipath TCPRST Reason Code", HFILL}},
9822 { &hf_tcp_option_mptcp_address_id,
9823 { "Address ID", "tcp.options.mptcp.addrid", FT_UINT8,
9824 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9826 { &hf_tcp_option_mptcp_sender_key,
9827 { "Sender's Key", "tcp.options.mptcp.sendkey", FT_UINT64,
9828 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9830 { &hf_tcp_option_mptcp_recv_key,
9831 { "Receiver's Key", "tcp.options.mptcp.recvkey", FT_UINT64,
9832 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9834 { &hf_tcp_option_mptcp_recv_token,
9835 { "Receiver's Token", "tcp.options.mptcp.recvtok", FT_UINT32,
9836 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9838 { &hf_tcp_option_mptcp_sender_rand,
9839 { "Sender's Random Number", "tcp.options.mptcp.sendrand", FT_UINT32,
9840 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9842 { &hf_tcp_option_mptcp_sender_trunc_hmac,
9843 { "Sender's Truncated HMAC", "tcp.options.mptcp.sendtrunchmac", FT_UINT64,
9844 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9846 { &hf_tcp_option_mptcp_sender_hmac,
9847 { "Sender's HMAC", "tcp.options.mptcp.sendhmac", FT_BYTES,
9848 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9850 { &hf_tcp_option_mptcp_addaddr_trunc_hmac,
9851 { "Truncated HMAC", "tcp.options.mptcp.addaddrtrunchmac", FT_UINT64,
9852 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9854 { &hf_tcp_option_mptcp_data_ack_raw,
9855 { "Original MPTCP Data ACK", "tcp.options.mptcp.rawdataack", FT_UINT64,
9856 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9858 { &hf_tcp_option_mptcp_data_seq_no_raw,
9859 { "Data Sequence Number", "tcp.options.mptcp.rawdataseqno", FT_UINT64,
9860 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9862 { &hf_tcp_option_mptcp_subflow_seq_no,
9863 { "Subflow Sequence Number", "tcp.options.mptcp.subflowseqno", FT_UINT32,
9864 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9866 { &hf_tcp_option_mptcp_data_lvl_len,
9867 { "Data-level Length", "tcp.options.mptcp.datalvllen", FT_UINT16,
9868 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9870 { &hf_tcp_option_mptcp_checksum,
9871 { "Checksum", "tcp.options.mptcp.checksum", FT_UINT16,
9872 BASE_HEX, NULL, 0x0, NULL, HFILL}},
9874 { &hf_tcp_option_mptcp_ipver,
9875 { "IP version", "tcp.options.mptcp.ipver", FT_UINT8,
9876 BASE_DEC, NULL, 0x0F, NULL, HFILL}},
9878 { &hf_tcp_option_mptcp_echo,
9879 { "Echo", "tcp.options.mptcp.echo", FT_UINT8,
9880 BASE_DEC, NULL, 0x01, NULL, HFILL}},
9882 { &hf_tcp_option_mptcp_ipv4,
9883 { "Advertised IPv4 Address", "tcp.options.mptcp.ipv4", FT_IPv4,
9884 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9886 { &hf_tcp_option_mptcp_ipv6,
9887 { "Advertised IPv6 Address", "tcp.options.mptcp.ipv6", FT_IPv6,
9888 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9890 { &hf_tcp_option_mptcp_port,
9891 { "Advertised port", "tcp.options.mptcp.port", FT_UINT16,
9892 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9894 { &hf_tcp_option_cc,
9895 { "TCP CC Option", "tcp.options.cc_value", FT_UINT32, BASE_DEC,
9896 NULL, 0x0, NULL, HFILL}},
9898 { &hf_tcp_option_md5_digest,
9899 { "MD5 digest", "tcp.options.md5.digest", FT_BYTES, BASE_NONE,
9900 NULL, 0x0, NULL, HFILL}},
9902 { &hf_tcp_option_ao_keyid,
9903 { "AO KeyID", "tcp.options.ao.keyid", FT_UINT8, BASE_DEC,
9904 NULL, 0x0, NULL, HFILL}},
9906 { &hf_tcp_option_ao_rnextkeyid,
9907 { "AO RNextKeyID", "tcp.options.ao.rnextkeyid", FT_UINT8, BASE_DEC,
9908 NULL, 0x0, NULL, HFILL}},
9910 { &hf_tcp_option_ao_mac,
9911 { "AO MAC", "tcp.options.ao.mac", FT_BYTES, BASE_NONE,
9912 NULL, 0x0, NULL, HFILL}},
9914 { &hf_tcp_option_qs_rate,
9915 { "QS Rate", "tcp.options.qs.rate", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
9916 &qs_rate_vals_ext, 0x0F, NULL, HFILL}},
9918 { &hf_tcp_option_qs_ttl_diff,
9919 { "QS Rate", "tcp.options.qs.ttl_diff", FT_UINT8, BASE_DEC,
9920 NULL, 0x0, NULL, HFILL}},
9922 { &hf_tcp_option_tarr_rate,
9923 { "TARR Rate", "tcp.options.tarr.rate", FT_UINT8, BASE_DEC,
9924 NULL, TCPOPT_TARR_RATE_MASK, NULL, HFILL}},
9926 { &hf_tcp_option_tarr_reserved,
9927 { "TARR Reserved", "tcp.options.tar.reserved", FT_UINT8, BASE_DEC,
9928 NULL, TCPOPT_TARR_RESERVED_MASK, NULL, HFILL}},
9930 { &hf_tcp_option_acc_ecn_ee0b,
9931 { "Accurate ECN Echo ECT(0) Byte Counter", "tcp.options.acc_ecn.ee0b",
9932 FT_UINT24, BASE_DEC, NULL, 0x0,
9933 NULL, HFILL}},
9935 { &hf_tcp_option_acc_ecn_eceb,
9936 { "Accurate ECN Echo CE Byte Counter", "tcp.options.acc_ecn.eceb",
9937 FT_UINT24, BASE_DEC, NULL, 0x0,
9938 NULL, HFILL}},
9940 { &hf_tcp_option_acc_ecn_ee1b,
9941 { "Accurate ECN Echo ECT(1) Byte Counter", "tcp.options.acc_ecn.ee1b",
9942 FT_UINT24, BASE_DEC, NULL, 0x0,
9943 NULL, HFILL}},
9945 { &hf_tcp_option_scps_vector,
9946 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
9947 FT_UINT8, BASE_HEX, NULL, 0x0,
9948 NULL, HFILL}},
9950 { &hf_tcp_option_scps_binding,
9951 { "Binding Space (Community) ID",
9952 "tcp.options.scps.binding.id",
9953 FT_UINT8, BASE_DEC, NULL, 0x0,
9954 "TCP SCPS Extended Binding Space (Community) ID", HFILL}},
9956 { &hf_tcp_option_scps_binding_len,
9957 { "Extended Capability Length",
9958 "tcp.options.scps.binding.len",
9959 FT_UINT8, BASE_DEC, NULL, 0x0,
9960 "TCP SCPS Extended Capability Length in bytes", HFILL}},
9962 { &hf_tcp_option_snack_offset,
9963 { "TCP SNACK Offset", "tcp.options.snack.offset",
9964 FT_UINT16, BASE_DEC, NULL, 0x0,
9965 NULL, HFILL}},
9967 { &hf_tcp_option_snack_size,
9968 { "TCP SNACK Size", "tcp.options.snack.size",
9969 FT_UINT16, BASE_DEC, NULL, 0x0,
9970 NULL, HFILL}},
9972 { &hf_tcp_option_snack_le,
9973 { "TCP SNACK Left Edge", "tcp.options.snack.le",
9974 FT_UINT16, BASE_DEC, NULL, 0x0,
9975 NULL, HFILL}},
9977 { &hf_tcp_option_snack_re,
9978 { "TCP SNACK Right Edge", "tcp.options.snack.re",
9979 FT_UINT16, BASE_DEC, NULL, 0x0,
9980 NULL, HFILL}},
9982 { &hf_tcp_scpsoption_flags_bets,
9983 { "Partial Reliability Capable (BETS)",
9984 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,
9985 TFS(&tfs_set_notset), 0x80, NULL, HFILL }},
9987 { &hf_tcp_scpsoption_flags_snack1,
9988 { "Short Form SNACK Capable (SNACK1)",
9989 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,
9990 TFS(&tfs_set_notset), 0x40, NULL, HFILL }},
9992 { &hf_tcp_scpsoption_flags_snack2,
9993 { "Long Form SNACK Capable (SNACK2)",
9994 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,
9995 TFS(&tfs_set_notset), 0x20, NULL, HFILL }},
9997 { &hf_tcp_scpsoption_flags_compress,
9998 { "Lossless Header Compression (COMP)",
9999 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,
10000 TFS(&tfs_set_notset), 0x10, NULL, HFILL }},
10002 { &hf_tcp_scpsoption_flags_nlts,
10003 { "Network Layer Timestamp (NLTS)",
10004 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,
10005 TFS(&tfs_set_notset), 0x8, NULL, HFILL }},
10007 { &hf_tcp_scpsoption_flags_reserved,
10008 { "Reserved",
10009 "tcp.options.scpsflags.reserved", FT_UINT8, BASE_DEC,
10010 NULL, 0x7, NULL, HFILL }},
10012 { &hf_tcp_scpsoption_connection_id,
10013 { "Connection ID",
10014 "tcp.options.scps.binding",
10015 FT_UINT8, BASE_DEC, NULL, 0x0,
10016 "TCP SCPS Connection ID", HFILL}},
10018 { &hf_tcp_option_user_to_granularity,
10019 { "Granularity", "tcp.options.user_to_granularity", FT_BOOLEAN,
10020 16, TFS(&tcp_option_user_to_granularity), 0x8000, "TCP User Timeout Granularity", HFILL}},
10022 { &hf_tcp_option_user_to_val,
10023 { "User Timeout", "tcp.options.user_to_val", FT_UINT16,
10024 BASE_DEC, NULL, 0x7FFF, "TCP User Timeout Value", HFILL}},
10026 { &hf_tcp_option_rvbd_probe_type1,
10027 { "Type", "tcp.options.rvbd.probe.type1",
10028 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
10030 { &hf_tcp_option_rvbd_probe_type2,
10031 { "Type", "tcp.options.rvbd.probe.type2",
10032 FT_UINT8, BASE_DEC, NULL, 0xFE, NULL, HFILL }},
10034 { &hf_tcp_option_rvbd_probe_version1,
10035 { "Version", "tcp.options.rvbd.probe.version",
10036 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
10038 { &hf_tcp_option_rvbd_probe_version2,
10039 { "Version", "tcp.options.rvbd.probe.version_raw",
10040 FT_UINT8, BASE_DEC, NULL, 0x01, "Version 2 Raw Value", HFILL }},
10042 { &hf_tcp_option_rvbd_probe_prober,
10043 { "CSH IP", "tcp.options.rvbd.probe.prober",
10044 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
10046 { &hf_tcp_option_rvbd_probe_proxy,
10047 { "SSH IP", "tcp.options.rvbd.probe.proxy.ip",
10048 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
10050 { &hf_tcp_option_rvbd_probe_proxy_port,
10051 { "SSH Port", "tcp.options.rvbd.probe.proxy.port",
10052 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
10054 { &hf_tcp_option_rvbd_probe_appli_ver,
10055 { "Application Version", "tcp.options.rvbd.probe.appli_ver",
10056 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
10058 { &hf_tcp_option_rvbd_probe_client,
10059 { "Client IP", "tcp.options.rvbd.probe.client.ip",
10060 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
10062 { &hf_tcp_option_rvbd_probe_storeid,
10063 { "CFE Store ID", "tcp.options.rvbd.probe.storeid",
10064 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
10066 { &hf_tcp_option_rvbd_probe_flags,
10067 { "Probe Flags", "tcp.options.rvbd.probe.flags",
10068 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
10070 { &hf_tcp_option_rvbd_probe_flag_not_cfe,
10071 { "Not CFE", "tcp.options.rvbd.probe.flags.notcfe",
10072 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_NCFE,
10073 NULL, HFILL }},
10075 { &hf_tcp_option_rvbd_probe_flag_last_notify,
10076 { "Last Notify", "tcp.options.rvbd.probe.flags.last",
10077 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_LAST,
10078 NULL, HFILL }},
10080 { &hf_tcp_option_rvbd_probe_flag_probe_cache,
10081 { "Disable Probe Cache on CSH", "tcp.options.rvbd.probe.flags.probe",
10082 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE,
10083 NULL, HFILL }},
10085 { &hf_tcp_option_rvbd_probe_flag_sslcert,
10086 { "SSL Enabled", "tcp.options.rvbd.probe.flags.ssl",
10087 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SSLCERT,
10088 NULL, HFILL }},
10090 { &hf_tcp_option_rvbd_probe_flag_server_connected,
10091 { "SSH outer to server established", "tcp.options.rvbd.probe.flags.server",
10092 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SERVER,
10093 NULL, HFILL }},
10095 { &hf_tcp_option_rvbd_trpy_flags,
10096 { "Transparency Options", "tcp.options.rvbd.trpy.flags",
10097 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
10099 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
10100 { "Enable FW traversal feature", "tcp.options.rvbd.trpy.flags.fw_rst_probe",
10101 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
10102 RVBD_FLAGS_TRPY_FW_RST_PROBE,
10103 "Reset state created by probe on the nexthop firewall",
10104 HFILL }},
10106 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
10107 { "Enable Inner FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst_inner",
10108 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
10109 RVBD_FLAGS_TRPY_FW_RST_INNER,
10110 "Reset state created by transparent inner on all firewalls"
10111 " before passing connection through",
10112 HFILL }},
10114 { &hf_tcp_option_rvbd_trpy_flag_fw_rst,
10115 { "Enable Transparency FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst",
10116 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
10117 RVBD_FLAGS_TRPY_FW_RST,
10118 "Reset state created by probe on all firewalls before "
10119 "establishing transparent inner connection", HFILL }},
10121 { &hf_tcp_option_rvbd_trpy_flag_chksum,
10122 { "Reserved", "tcp.options.rvbd.trpy.flags.chksum",
10123 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
10124 RVBD_FLAGS_TRPY_CHKSUM, NULL, HFILL }},
10126 { &hf_tcp_option_rvbd_trpy_flag_oob,
10127 { "Out of band connection", "tcp.options.rvbd.trpy.flags.oob",
10128 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
10129 RVBD_FLAGS_TRPY_OOB, NULL, HFILL }},
10131 { &hf_tcp_option_rvbd_trpy_flag_mode,
10132 { "Transparency Mode", "tcp.options.rvbd.trpy.flags.mode",
10133 FT_BOOLEAN, 16, TFS(&trpy_mode_str),
10134 RVBD_FLAGS_TRPY_MODE, NULL, HFILL }},
10136 { &hf_tcp_option_rvbd_trpy_src,
10137 { "Src SH IP Addr", "tcp.options.rvbd.trpy.src.ip",
10138 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
10140 { &hf_tcp_option_rvbd_trpy_dst,
10141 { "Dst SH IP Addr", "tcp.options.rvbd.trpy.dst.ip",
10142 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
10144 { &hf_tcp_option_rvbd_trpy_src_port,
10145 { "Src SH Inner Port", "tcp.options.rvbd.trpy.src.port",
10146 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
10148 { &hf_tcp_option_rvbd_trpy_dst_port,
10149 { "Dst SH Inner Port", "tcp.options.rvbd.trpy.dst.port",
10150 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
10152 { &hf_tcp_option_rvbd_trpy_client_port,
10153 { "Out of band connection Client Port", "tcp.options.rvbd.trpy.client.port",
10154 FT_UINT16, BASE_DEC, NULL , 0x0, NULL, HFILL }},
10156 { &hf_tcp_option_fast_open_cookie_request,
10157 { "Fast Open Cookie Request", "tcp.options.tfo.request", FT_NONE,
10158 BASE_NONE, NULL, 0x0, NULL, HFILL }},
10160 { &hf_tcp_option_fast_open_cookie,
10161 { "Fast Open Cookie", "tcp.options.tfo.cookie", FT_BYTES,
10162 BASE_NONE, NULL, 0x0, NULL, HFILL}},
10164 { &hf_tcp_pdu_time,
10165 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
10166 "How long time has passed until the last frame of this PDU", HFILL}},
10168 { &hf_tcp_pdu_size,
10169 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL, 0x0,
10170 "The size of this PDU", HFILL}},
10172 { &hf_tcp_pdu_last_frame,
10173 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
10174 "This is the last frame of the PDU starting in this segment", HFILL }},
10176 { &hf_tcp_ts_relative,
10177 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
10178 "Time relative to first frame in this TCP stream", HFILL}},
10180 { &hf_tcp_ts_delta,
10181 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
10182 "Time delta from previous frame in this TCP stream", HFILL}},
10184 { &hf_tcp_proc_src_uid,
10185 { "Source process user ID", "tcp.proc.srcuid", FT_UINT32, BASE_DEC, NULL, 0x0,
10186 NULL, HFILL}},
10188 { &hf_tcp_proc_src_pid,
10189 { "Source process ID", "tcp.proc.srcpid", FT_UINT32, BASE_DEC, NULL, 0x0,
10190 NULL, HFILL}},
10192 { &hf_tcp_proc_src_uname,
10193 { "Source process user name", "tcp.proc.srcuname", FT_STRING, BASE_NONE, NULL, 0x0,
10194 NULL, HFILL}},
10196 { &hf_tcp_proc_src_cmd,
10197 { "Source process name", "tcp.proc.srccmd", FT_STRING, BASE_NONE, NULL, 0x0,
10198 "Source process command name", HFILL}},
10200 { &hf_tcp_proc_dst_uid,
10201 { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32, BASE_DEC, NULL, 0x0,
10202 NULL, HFILL}},
10204 { &hf_tcp_proc_dst_pid,
10205 { "Destination process ID", "tcp.proc.dstpid", FT_UINT32, BASE_DEC, NULL, 0x0,
10206 NULL, HFILL}},
10208 { &hf_tcp_proc_dst_uname,
10209 { "Destination process user name", "tcp.proc.dstuname", FT_STRING, BASE_NONE, NULL, 0x0,
10210 NULL, HFILL}},
10212 { &hf_tcp_proc_dst_cmd,
10213 { "Destination process name", "tcp.proc.dstcmd", FT_STRING, BASE_NONE, NULL, 0x0,
10214 "Destination process command name", HFILL}},
10216 { &hf_tcp_segment_data,
10217 { "TCP segment data", "tcp.segment_data", FT_BYTES, BASE_NONE, NULL, 0x0,
10218 "A data segment used in reassembly of an upper-layer protocol (ULP)", HFILL}},
10220 { &hf_tcp_payload,
10221 { "TCP payload", "tcp.payload", FT_BYTES, BASE_NONE, NULL, 0x0,
10222 "The TCP payload of this packet", HFILL}},
10224 { &hf_tcp_option_scps_binding_data,
10225 { "Binding Space Data", "tcp.options.scps.binding.data", FT_BYTES, BASE_NONE, NULL, 0x0,
10226 NULL, HFILL }},
10228 { &hf_tcp_option_rvbd_probe_reserved,
10229 { "Reserved", "tcp.options.rvbd.probe.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
10230 NULL, HFILL }},
10232 { &hf_tcp_fin_retransmission,
10233 { "Retransmission of FIN from frame", "tcp.fin_retransmission", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
10234 NULL, HFILL }},
10236 { &hf_tcp_reset_cause,
10237 { "Reset cause", "tcp.reset_cause", FT_STRING, BASE_NONE, NULL, 0x0,
10238 NULL, HFILL }},
10240 { &hf_tcp_syncookie_time,
10241 { "SYN Cookie Time", "tcp.syncookie.time", FT_UINT8, BASE_DEC, NULL, 0x0,
10242 NULL, HFILL }},
10244 { &hf_tcp_syncookie_mss,
10245 { "SYN Cookie Maximum Segment Size", "tcp.syncookie.mss", FT_UINT8, BASE_DEC, NULL, 0x0,
10246 NULL, HFILL }},
10248 { &hf_tcp_syncookie_hash,
10249 { "SYN Cookie hash", "tcp.syncookie.hash", FT_UINT24, BASE_HEX, NULL, 0x0,
10250 NULL, HFILL }},
10252 { &hf_tcp_syncookie_option_timestamp,
10253 { "SYN Cookie Timestamp", "tcp.options.timestamp.tsval.syncookie.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
10254 NULL, HFILL }},
10256 { &hf_tcp_syncookie_option_ecn,
10257 { "SYN Cookie ECN", "tcp.options.timestamp.tsval.syncookie.ecn", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
10258 NULL, HFILL }},
10260 { &hf_tcp_syncookie_option_sack,
10261 { "SYN Cookie SACK", "tcp.options.timestamp.tsval.syncookie.sack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
10262 NULL, HFILL }},
10264 { &hf_tcp_syncookie_option_wscale,
10265 { "SYN Cookie WScale", "tcp.options.timestamp.tsval.syncookie.wscale", FT_UINT8, BASE_DEC, NULL, 0x0,
10266 NULL, HFILL }},
10268 { &hf_tcp_ns_reset_window_error_code,
10269 { "NetScaler TCP Reset Window Error Code", "tcp.nstrace.rst.window_error_code", FT_STRING, BASE_NONE, NULL, 0x0,
10270 NULL, HFILL }},
10273 static int *ett[] = {
10274 &ett_tcp,
10275 &ett_tcp_completeness,
10276 &ett_tcp_flags,
10277 &ett_tcp_options,
10278 &ett_tcp_option_timestamp,
10279 &ett_tcp_option_mptcp,
10280 &ett_tcp_option_wscale,
10281 &ett_tcp_option_sack,
10282 &ett_tcp_option_snack,
10283 &ett_tcp_option_scps,
10284 &ett_tcp_scpsoption_flags,
10285 &ett_tcp_option_scps_extended,
10286 &ett_tcp_option_user_to,
10287 &ett_tcp_option_exp,
10288 &ett_tcp_option_acc_ecn,
10289 &ett_tcp_option_sack_perm,
10290 &ett_tcp_option_mss,
10291 &ett_tcp_opt_rvbd_probe,
10292 &ett_tcp_opt_rvbd_probe_flags,
10293 &ett_tcp_opt_rvbd_trpy,
10294 &ett_tcp_opt_rvbd_trpy_flags,
10295 &ett_tcp_opt_echo,
10296 &ett_tcp_opt_cc,
10297 &ett_tcp_opt_md5,
10298 &ett_tcp_opt_ao,
10299 &ett_tcp_opt_qs,
10300 &ett_tcp_analysis_faults,
10301 &ett_tcp_analysis,
10302 &ett_tcp_timestamps,
10303 &ett_tcp_segments,
10304 &ett_tcp_segment,
10305 &ett_tcp_checksum,
10306 &ett_tcp_process_info,
10307 &ett_tcp_unknown_opt,
10308 &ett_tcp_opt_recbound,
10309 &ett_tcp_opt_scpscor,
10310 &ett_tcp_option_other,
10311 &ett_tcp_syncookie,
10312 &ett_tcp_syncookie_option
10315 static int *mptcp_ett[] = {
10316 &ett_mptcp_analysis,
10317 &ett_mptcp_analysis_subflows
10320 static const enum_val_t window_scaling_vals[] = {
10321 {"not-known", "Not known", WindowScaling_NotKnown},
10322 {"0", "0 (no scaling)", WindowScaling_0},
10323 {"1", "1 (multiply by 2)", WindowScaling_1},
10324 {"2", "2 (multiply by 4)", WindowScaling_2},
10325 {"3", "3 (multiply by 8)", WindowScaling_3},
10326 {"4", "4 (multiply by 16)", WindowScaling_4},
10327 {"5", "5 (multiply by 32)", WindowScaling_5},
10328 {"6", "6 (multiply by 64)", WindowScaling_6},
10329 {"7", "7 (multiply by 128)", WindowScaling_7},
10330 {"8", "8 (multiply by 256)", WindowScaling_8},
10331 {"9", "9 (multiply by 512)", WindowScaling_9},
10332 {"10", "10 (multiply by 1024)", WindowScaling_10},
10333 {"11", "11 (multiply by 2048)", WindowScaling_11},
10334 {"12", "12 (multiply by 4096)", WindowScaling_12},
10335 {"13", "13 (multiply by 8192)", WindowScaling_13},
10336 {"14", "14 (multiply by 16384)", WindowScaling_14},
10337 {NULL, NULL, -1}
10340 static const enum_val_t override_analysis_vals[] = {
10341 {"0", "0 (none)", OverrideAnalysis_0},
10342 {"1", "1 (Out-of-Order)", OverrideAnalysis_1},
10343 {"2", "2 (Retransmission)", OverrideAnalysis_2},
10344 {"3", "3 (Fast Retransmission)", OverrideAnalysis_3},
10345 {"4", "4 (Spurious Retransmission)",OverrideAnalysis_4},
10346 {NULL, NULL, -1}
10349 static ei_register_info ei[] = {
10350 { &ei_tcp_opt_len_invalid, { "tcp.option.len.invalid", PI_SEQUENCE, PI_NOTE, "Invalid length for option", EXPFILL }},
10351 { &ei_tcp_analysis_retransmission, { "tcp.analysis.retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) retransmission", EXPFILL }},
10352 { &ei_tcp_analysis_fast_retransmission, { "tcp.analysis.fast_retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) fast retransmission", EXPFILL }},
10353 { &ei_tcp_analysis_spurious_retransmission, { "tcp.analysis.spurious_retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) spurious retransmission", EXPFILL }},
10354 { &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 }},
10355 { &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 }},
10356 { &ei_tcp_analysis_lost_packet, { "tcp.analysis.lost_segment", PI_SEQUENCE, PI_WARN, "Previous segment(s) not captured (common at capture start)", EXPFILL }},
10357 { &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 }},
10358 { &ei_tcp_analysis_window_update, { "tcp.analysis.window_update", PI_SEQUENCE, PI_CHAT, "TCP window update", EXPFILL }},
10359 { &ei_tcp_analysis_window_full, { "tcp.analysis.window_full", PI_SEQUENCE, PI_WARN, "TCP window specified by the receiver is now completely full", EXPFILL }},
10360 { &ei_tcp_analysis_keep_alive, { "tcp.analysis.keep_alive", PI_SEQUENCE, PI_NOTE, "TCP keep-alive segment", EXPFILL }},
10361 { &ei_tcp_analysis_keep_alive_ack, { "tcp.analysis.keep_alive_ack", PI_SEQUENCE, PI_NOTE, "ACK to a TCP keep-alive segment", EXPFILL }},
10362 { &ei_tcp_analysis_duplicate_ack, { "tcp.analysis.duplicate_ack", PI_SEQUENCE, PI_NOTE, "Duplicate ACK", EXPFILL }},
10363 { &ei_tcp_analysis_zero_window_probe, { "tcp.analysis.zero_window_probe", PI_SEQUENCE, PI_NOTE, "TCP Zero Window Probe", EXPFILL }},
10364 { &ei_tcp_analysis_zero_window, { "tcp.analysis.zero_window", PI_SEQUENCE, PI_WARN, "TCP Zero Window segment", EXPFILL }},
10365 { &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 }},
10366 { &ei_tcp_analysis_tfo_syn, { "tcp.analysis.tfo_syn", PI_SEQUENCE, PI_NOTE, "TCP SYN with TFO Cookie", EXPFILL }},
10367 { &ei_tcp_analysis_tfo_ack, { "tcp.analysis.tfo_ack", PI_SEQUENCE, PI_NOTE, "TCP SYN-ACK accepting TFO data", EXPFILL }},
10368 { &ei_tcp_analysis_tfo_ignored, { "tcp.analysis.tfo_ignored", PI_SEQUENCE, PI_NOTE, "TCP SYN-ACK ignoring TFO data", EXPFILL }},
10369 { &ei_tcp_analysis_partial_ack, { "tcp.analysis.partial_ack", PI_SEQUENCE, PI_NOTE, "Partial Acknowledgement of a segment", EXPFILL }},
10370 { &ei_tcp_analysis_ambiguous_ack, { "tcp.analysis.ambiguous_ack", PI_SEQUENCE, PI_NOTE, "Ambiguous ACK following Karn's definition", EXPFILL }},
10371 { &ei_tcp_connection_fin_active, { "tcp.connection.fin_active", PI_SEQUENCE, PI_NOTE, "This frame initiates the connection closing", EXPFILL }},
10372 { &ei_tcp_connection_fin_passive, { "tcp.connection.fin_passive", PI_SEQUENCE, PI_NOTE, "This frame undergoes the connection closing", EXPFILL }},
10373 { &ei_tcp_scps_capable, { "tcp.analysis.scps_capable", PI_SEQUENCE, PI_NOTE, "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated", EXPFILL }},
10374 { &ei_tcp_option_sack_dsack, { "tcp.options.sack.dsack", PI_SEQUENCE, PI_WARN, "D-SACK Sequence", EXPFILL }},
10375 { &ei_tcp_option_snack_sequence, { "tcp.options.snack.sequence", PI_SEQUENCE, PI_NOTE, "SNACK Sequence", EXPFILL }},
10376 { &ei_tcp_option_wscale_shift_invalid, { "tcp.options.wscale.shift.invalid", PI_PROTOCOL, PI_WARN, "Window scale shift exceeds 14", EXPFILL }},
10377 { &ei_tcp_option_mss_absent, { "tcp.options.mss.absent", PI_PROTOCOL, PI_NOTE, "The SYN packet does not contain a MSS option", EXPFILL }},
10378 { &ei_tcp_option_mss_present, { "tcp.options.mss.present", PI_PROTOCOL, PI_WARN, "The non-SYN packet does contain a MSS option", EXPFILL }},
10379 { &ei_tcp_option_mss_exceeded, { "tcp.options.mss.exceeded", PI_PROTOCOL, PI_NOTE, "This packet's length exceeds MSS (common with TSO or incomplete conversations)", EXPFILL }},
10380 { &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 }},
10381 { &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 }},
10382 { &ei_tcp_short_segment, { "tcp.short_segment", PI_MALFORMED, PI_WARN, "Short segment", EXPFILL }},
10383 { &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 }},
10384 { &ei_tcp_connection_synack, { "tcp.connection.synack", PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK)", EXPFILL }},
10385 { &ei_tcp_connection_syn, { "tcp.connection.syn", PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN)", EXPFILL }},
10386 { &ei_tcp_connection_fin, { "tcp.connection.fin", PI_SEQUENCE, PI_CHAT, "Connection finish (FIN)", EXPFILL }},
10387 /* According to RFCs, RST is an indication of an error. Some applications use it
10388 * to terminate a connection as well, which is a misbehavior (see e.g. rfc3360)
10390 { &ei_tcp_connection_rst, { "tcp.connection.rst", PI_SEQUENCE, PI_WARN, "Connection reset (RST)", EXPFILL }},
10391 { &ei_tcp_checksum_ffff, { "tcp.checksum.ffff", PI_CHECKSUM, PI_WARN, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)", EXPFILL }},
10392 { &ei_tcp_checksum_partial, { "tcp.checksum.partial", PI_CHECKSUM, PI_NOTE, "Partial (pseudo header) checksum (likely caused by \"TCP checksum offload\")", EXPFILL }},
10393 { &ei_tcp_checksum_bad, { "tcp.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
10394 { &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 }},
10395 { &ei_tcp_suboption_malformed, { "tcp.suboption_malformed", PI_MALFORMED, PI_ERROR, "suboption would go past end of option", EXPFILL }},
10396 { &ei_tcp_nop, { "tcp.nop", PI_PROTOCOL, PI_WARN, "4 NOP in a row - a router may have removed some options", EXPFILL }},
10397 { &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 }},
10398 { &ei_tcp_bogus_header_length, { "tcp.bogus_header_length", PI_PROTOCOL, PI_ERROR, "Bogus TCP Header length", EXPFILL }},
10401 static ei_register_info mptcp_ei[] = {
10402 #if 0
10403 { &ei_mptcp_analysis_unexpected_idsn, { "mptcp.connection.unexpected_idsn", PI_PROTOCOL, PI_NOTE, "Unexpected initial sequence number", EXPFILL }},
10404 #endif
10405 { &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 }},
10406 { &ei_mptcp_analysis_missing_algorithm, { "mptcp.connection.missing_algorithm", PI_PROTOCOL, PI_WARN, "No crypto algorithm specified", EXPFILL }},
10407 { &ei_mptcp_analysis_unsupported_algorithm, { "mptcp.connection.unsupported_algorithm", PI_PROTOCOL, PI_WARN, "Unsupported algorithm", EXPFILL }},
10408 { &ei_mptcp_infinite_mapping, { "mptcp.dss.infinite_mapping", PI_PROTOCOL, PI_WARN, "Fallback to infinite mapping", EXPFILL }},
10409 { &ei_mptcp_mapping_missing, { "mptcp.dss.missing_mapping", PI_PROTOCOL, PI_WARN, "No mapping available", EXPFILL }},
10410 #if 0
10411 { &ei_mptcp_stream_incomplete, { "mptcp.incomplete", PI_PROTOCOL, PI_WARN, "Everything was not captured", EXPFILL }},
10412 { &ei_mptcp_analysis_dsn_out_of_order, { "mptcp.analysis.dsn.out_of_order", PI_PROTOCOL, PI_WARN, "Out of order dsn", EXPFILL }},
10413 #endif
10416 static hf_register_info mptcp_hf[] = {
10417 { &hf_mptcp_ack,
10418 { "Multipath TCP Data ACK", "mptcp.ack", FT_UINT64,
10419 BASE_DEC, NULL, 0x0, NULL, HFILL}},
10421 { &hf_mptcp_dsn,
10422 { "Data Sequence Number", "mptcp.dsn", FT_UINT64, BASE_DEC, NULL, 0x0,
10423 "Data Sequence Number mapped to this TCP sequence number", HFILL}},
10425 { &hf_mptcp_rawdsn64,
10426 { "Raw Data Sequence Number", "mptcp.rawdsn64", FT_UINT64, BASE_DEC, NULL, 0x0,
10427 "Data Sequence Number mapped to this TCP sequence number", HFILL}},
10429 { &hf_mptcp_dss_dsn,
10430 { "DSS Data Sequence Number", "mptcp.dss.dsn", FT_UINT64,
10431 BASE_DEC, NULL, 0x0, NULL, HFILL}},
10433 { &hf_mptcp_expected_idsn,
10434 { "Subflow expected IDSN", "mptcp.expected_idsn", FT_UINT64,
10435 BASE_DEC|BASE_UNIT_STRING, UNS(&units_64bit_version), 0x0, NULL, HFILL}},
10437 { &hf_mptcp_analysis,
10438 { "MPTCP analysis", "mptcp.analysis", FT_NONE, BASE_NONE, NULL, 0x0,
10439 "This frame has some of the MPTCP analysis shown", HFILL }},
10441 { &hf_mptcp_related_mapping,
10442 { "Related mapping", "mptcp.related_mapping", FT_FRAMENUM , BASE_NONE, NULL, 0x0,
10443 "Packet in which current packet DSS mapping was sent", HFILL }},
10445 { &hf_mptcp_reinjection_of,
10446 { "Reinjection of", "mptcp.reinjection_of", FT_FRAMENUM , BASE_NONE, NULL, 0x0,
10447 "This is a retransmission of data sent on another subflow", HFILL }},
10449 { &hf_mptcp_reinjected_in,
10450 { "Data reinjected in", "mptcp.reinjected_in", FT_FRAMENUM , BASE_NONE, NULL, 0x0,
10451 "This was retransmitted on another subflow", HFILL }},
10453 { &hf_mptcp_analysis_subflows,
10454 { "TCP subflow stream id(s)", "mptcp.analysis.subflows", FT_STRING, BASE_NONE, NULL, 0x0,
10455 "List all TCP connections mapped to this MPTCP connection", HFILL }},
10457 { &hf_mptcp_stream,
10458 { "Stream index", "mptcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
10459 NULL, HFILL }},
10461 { &hf_mptcp_number_of_removed_addresses,
10462 { "Number of removed addresses", "mptcp.rm_addr.count", FT_UINT8,
10463 BASE_DEC, NULL, 0x0, NULL, HFILL}},
10465 { &hf_mptcp_expected_token,
10466 { "Subflow token generated from key", "mptcp.expected_token", FT_UINT32,
10467 BASE_DEC, NULL, 0x0, NULL, HFILL}},
10469 { &hf_mptcp_analysis_master,
10470 { "Master flow", "mptcp.master", FT_BOOLEAN, BASE_NONE,
10471 NULL, 0x0, NULL, HFILL}}
10475 static build_valid_func tcp_da_src_values[1] = {tcp_src_value};
10476 static build_valid_func tcp_da_dst_values[1] = {tcp_dst_value};
10477 static build_valid_func tcp_da_both_values[2] = {tcp_src_value, tcp_dst_value};
10478 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}};
10479 static decode_as_t tcp_da = {"tcp", "tcp.port", 3, 2, tcp_da_values, "TCP", "port(s) as",
10480 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
10482 module_t *tcp_module;
10483 module_t *mptcp_module;
10484 expert_module_t* expert_tcp;
10485 expert_module_t* expert_mptcp;
10487 proto_tcp = proto_register_protocol("Transmission Control Protocol", "TCP", "tcp");
10488 tcp_handle = register_dissector("tcp", dissect_tcp, proto_tcp);
10489 tcp_cap_handle = register_capture_dissector("tcp", capture_tcp, proto_tcp);
10490 proto_register_field_array(proto_tcp, hf, array_length(hf));
10491 proto_register_subtree_array(ett, array_length(ett));
10492 expert_tcp = expert_register_protocol(proto_tcp);
10493 expert_register_field_array(expert_tcp, ei, array_length(ei));
10495 /* subdissector code */
10496 subdissector_table = register_dissector_table("tcp.port",
10497 "TCP port", proto_tcp, FT_UINT16, BASE_DEC);
10498 heur_subdissector_list = register_heur_dissector_list_with_description("tcp", "TCP heuristic", proto_tcp);
10499 tcp_option_table = register_dissector_table("tcp.option",
10500 "TCP Options", proto_tcp, FT_UINT8, BASE_DEC);
10502 /* Register TCP options as their own protocols so we can get the name of the option */
10503 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);
10504 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);
10505 proto_tcp_option_timestamp = proto_register_protocol_in_name_only("TCP Option - Timestamps", "Timestamps", "tcp.options.timestamp", proto_tcp, FT_BYTES);
10506 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);
10507 proto_tcp_option_wscale = proto_register_protocol_in_name_only("TCP Option - Window scale", "Window scale", "tcp.options.wscale", proto_tcp, FT_BYTES);
10508 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);
10509 proto_tcp_option_sack = proto_register_protocol_in_name_only("TCP Option - SACK", "SACK", "tcp.options.sack", proto_tcp, FT_BYTES);
10510 proto_tcp_option_echo = proto_register_protocol_in_name_only("TCP Option - Echo", "Echo", "tcp.options.echo", proto_tcp, FT_BYTES);
10511 proto_tcp_option_echoreply = proto_register_protocol_in_name_only("TCP Option - Echo reply", "Echo reply", "tcp.options.echoreply", proto_tcp, FT_BYTES);
10512 proto_tcp_option_cc = proto_register_protocol_in_name_only("TCP Option - CC", "CC", "tcp.options.cc", proto_tcp, FT_BYTES);
10513 proto_tcp_option_cc_new = proto_register_protocol_in_name_only("TCP Option - CC.NEW", "CC.NEW", "tcp.options.ccnew", proto_tcp, FT_BYTES);
10514 proto_tcp_option_cc_echo = proto_register_protocol_in_name_only("TCP Option - CC.ECHO", "CC.ECHO", "tcp.options.ccecho", proto_tcp, FT_BYTES);
10515 proto_tcp_option_ao = proto_register_protocol_in_name_only("TCP Option - TCP AO", "TCP AO", "tcp.options.ao", proto_tcp, FT_BYTES);
10516 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);
10517 proto_tcp_option_scps = proto_register_protocol_in_name_only("TCP Option - SCPS capabilities", "SCPS capabilities", "tcp.options.scps", proto_tcp, FT_BYTES);
10518 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);
10519 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);
10520 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);
10521 proto_tcp_option_qs = proto_register_protocol_in_name_only("TCP Option - Quick-Start", "Quick-Start", "tcp.options.qs", proto_tcp, FT_BYTES);
10522 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);
10523 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);
10524 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);
10525 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);
10526 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);
10527 proto_tcp_option_exp = proto_register_protocol_in_name_only("TCP Option - Experimental", "Experimental", "tcp.options.experimental", proto_tcp, FT_BYTES);
10528 proto_tcp_option_unknown = proto_register_protocol_in_name_only("TCP Option - Unknown", "Unknown", "tcp.options.unknown", proto_tcp, FT_BYTES);
10530 register_capture_dissector_table("tcp.port", "TCP");
10532 /* Register configuration preferences */
10533 tcp_module = prefs_register_protocol(proto_tcp, NULL);
10534 prefs_register_bool_preference(tcp_module, "summary_in_tree",
10535 "Show TCP summary in protocol tree",
10536 "Whether the TCP summary line should be shown in the protocol tree",
10537 &tcp_summary_in_tree);
10538 prefs_register_bool_preference(tcp_module, "check_checksum",
10539 "Validate the TCP checksum if possible",
10540 "Whether to validate the TCP checksum or not. "
10541 "(Invalid checksums will cause reassembly, if enabled, to fail.)",
10542 &tcp_check_checksum);
10543 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
10544 "Allow subdissector to reassemble TCP streams",
10545 "Whether subdissector can request TCP streams to be reassembled",
10546 &tcp_desegment);
10547 prefs_register_bool_preference(tcp_module, "reassemble_out_of_order",
10548 "Reassemble out-of-order segments",
10549 "Whether out-of-order segments should be buffered and reordered before passing it to a subdissector. "
10550 "To use this option you must also enable \"Allow subdissector to reassemble TCP streams\".",
10551 &tcp_reassemble_out_of_order);
10552 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
10553 "Analyze TCP sequence numbers",
10554 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
10555 &tcp_analyze_seq);
10556 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
10557 "Relative sequence numbers (Requires \"Analyze TCP sequence numbers\")",
10558 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
10559 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
10560 &tcp_relative_seq);
10562 prefs_register_custom_preference_TCP_Analysis(tcp_module, "default_override_analysis",
10563 "Force interpretation to selected packet(s)",
10564 "Override the default analysis with this value for the selected packet",
10565 &tcp_default_override_analysis, override_analysis_vals, false);
10567 prefs_register_enum_preference(tcp_module, "default_window_scaling",
10568 "Scaling factor to use when not available from capture",
10569 "Make the TCP dissector use this scaling factor for streams where the signalled scaling factor "
10570 "is not visible in the capture",
10571 &tcp_default_window_scaling, window_scaling_vals, false);
10573 /* Presumably a retired, unconditional version of what has been added back with the preference above... */
10574 prefs_register_obsolete_preference(tcp_module, "window_scaling");
10576 prefs_register_bool_preference(tcp_module, "track_bytes_in_flight",
10577 "Track number of bytes in flight",
10578 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "
10579 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
10580 "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",
10581 &tcp_track_bytes_in_flight);
10582 prefs_register_bool_preference(tcp_module, "bif_seq_based",
10583 "Evaluate bytes in flight based on sequence numbers",
10584 "Evaluate BiF on actual sequence numbers or use the historical method based on payloads (default). "
10585 "This option has no effect if not used with \"Track number of bytes in flight\". ",
10586 &tcp_bif_seq_based);
10587 prefs_register_bool_preference(tcp_module, "calculate_timestamps",
10588 "Calculate stream packet number and timestamps",
10589 "Calculate relative packet number and timestamps relative to the first frame and the previous frame in the tcp conversation",
10590 &tcp_calculate_ts);
10591 prefs_register_bool_preference(tcp_module, "try_heuristic_first",
10592 "Try heuristic sub-dissectors first",
10593 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
10594 &try_heuristic_first);
10595 prefs_register_bool_preference(tcp_module, "ignore_tcp_timestamps",
10596 "Ignore TCP Timestamps in summary",
10597 "Do not place the TCP Timestamps in the summary line",
10598 &tcp_ignore_timestamps);
10599 prefs_register_bool_preference(tcp_module, "fastrt_supersedes_ooo",
10600 "Fast Retransmission supersedes Out-of-Order interpretation",
10601 "When interpreting ambiguous packets, give precedence to Fast Retransmission or OOO ",
10602 &tcp_fastrt_precedence);
10604 prefs_register_bool_preference(tcp_module, "no_subdissector_on_error",
10605 "Do not call subdissectors for error packets",
10606 "Do not call any subdissectors for Retransmitted or OutOfOrder segments",
10607 &tcp_no_subdissector_on_error);
10609 prefs_register_bool_preference(tcp_module, "dissect_experimental_options_rfc6994",
10610 "TCP Experimental Options using the format of RFC 6994",
10611 "Assume TCP Experimental Options (253, 254) have an Experiment Identifier and use it for dissection",
10612 &tcp_exp_options_rfc6994);
10614 prefs_register_bool_preference(tcp_module, "display_process_info_from_ipfix",
10615 "Display process information via IPFIX",
10616 "Collect and store process information retrieved from IPFIX dissector",
10617 &tcp_display_process_info);
10619 prefs_register_bool_preference(tcp_module, "read_seq_as_syn_cookie",
10620 "Read the seq no. as syn cookie",
10621 "Read the sequence number as it was a syn cookie",
10622 &read_seq_as_syn_cookie);
10624 register_init_routine(tcp_init);
10625 reassembly_table_register(&tcp_reassembly_table,
10626 &tcp_reassembly_table_functions);
10628 register_decode_as(&tcp_da);
10630 register_conversation_table(proto_tcp, false, tcpip_conversation_packet, tcpip_endpoint_packet);
10631 register_conversation_filter("tcp", "TCP", tcp_filter_valid, tcp_build_filter_by_id, NULL);
10633 register_seq_analysis("tcp", "TCP Flows", proto_tcp, NULL, TL_REQUIRES_NOTHING, tcp_seq_analysis_packet);
10635 /* considers MPTCP as a distinct protocol (even if it's a TCP option) */
10636 proto_mptcp = proto_register_protocol("Multipath Transmission Control Protocol", "MPTCP", "mptcp");
10638 proto_register_field_array(proto_mptcp, mptcp_hf, array_length(mptcp_hf));
10639 proto_register_subtree_array(mptcp_ett, array_length(mptcp_ett));
10641 /* Register configuration preferences */
10642 mptcp_module = prefs_register_protocol(proto_mptcp, NULL);
10643 expert_mptcp = expert_register_protocol(proto_tcp);
10644 expert_register_field_array(expert_mptcp, mptcp_ei, array_length(mptcp_ei));
10646 prefs_register_bool_preference(mptcp_module, "analyze_mptcp",
10647 "Map TCP subflows to their respective MPTCP connections",
10648 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
10649 &tcp_analyze_mptcp);
10651 prefs_register_bool_preference(mptcp_module, "relative_sequence_numbers",
10652 "Display relative MPTCP sequence numbers.",
10653 "In case you don't capture the key, it will use the first DSN seen",
10654 &mptcp_relative_seq);
10656 prefs_register_bool_preference(mptcp_module, "analyze_mappings",
10657 "Deeper analysis of Data Sequence Signal (DSS)",
10658 "Scales logarithmically with the number of packets"
10659 "You need to capture the handshake for this to work."
10660 "\"Map TCP subflows to their respective MPTCP connections\"",
10661 &mptcp_analyze_mappings);
10663 prefs_register_bool_preference(mptcp_module, "intersubflows_retransmission",
10664 "Check for data duplication across subflows",
10665 "(Greedy algorithm: Scales linearly with number of subflows and"
10666 " logarithmic scaling with number of packets)"
10667 "You need to enable DSS mapping analysis for this option to work",
10668 &mptcp_intersubflows_retransmission);
10670 range_convert_str(wmem_epan_scope(), &tcp_clientport_dissectors_range, TCP_DEFAULT_CLIENTPORT_DISSECTORS, 65535);
10671 prefs_register_range_preference(tcp_module, "clientport_dissectors", "Client port dissectors",
10672 "Ports for which the dissector will to be chosen based on the client port instead of the server port",
10673 &tcp_clientport_dissectors_range, 65535);
10675 register_conversation_table(proto_mptcp, false, mptcpip_conversation_packet, tcpip_endpoint_packet);
10676 register_follow_stream(proto_tcp, "tcp_follow", tcp_follow_conv_filter, tcp_follow_index_filter, tcp_follow_address_filter,
10677 tcp_port_to_display, follow_tcp_tap_listener, get_tcp_stream_count, NULL);
10679 tcp_tap = register_tap("tcp");
10680 tcp_follow_tap = register_tap("tcp_follow");
10681 mptcp_tap = register_tap("mptcp");
10684 void
10685 proto_reg_handoff_tcp(void)
10687 dissector_add_uint("ip.proto", IP_PROTO_TCP, tcp_handle);
10688 dissector_add_for_decode_as_with_preference("udp.port", tcp_handle);
10689 data_handle = find_dissector("data");
10690 sport_handle = find_dissector("sport");
10692 capture_dissector_add_uint("ip.proto", IP_PROTO_TCP, tcp_cap_handle);
10694 /* Create dissection function handles for all TCP options */
10695 dissector_add_uint("tcp.option", TCPOPT_TIMESTAMP, create_dissector_handle( dissect_tcpopt_timestamp, proto_tcp_option_timestamp ));
10696 dissector_add_uint("tcp.option", TCPOPT_MSS, create_dissector_handle( dissect_tcpopt_mss, proto_tcp_option_mss ));
10697 dissector_add_uint("tcp.option", TCPOPT_WINDOW, create_dissector_handle( dissect_tcpopt_wscale, proto_tcp_option_wscale ));
10698 dissector_add_uint("tcp.option", TCPOPT_SACK_PERM, create_dissector_handle( dissect_tcpopt_sack_perm, proto_tcp_option_sack_perm ));
10699 dissector_add_uint("tcp.option", TCPOPT_SACK, create_dissector_handle( dissect_tcpopt_sack, proto_tcp_option_sack ));
10700 dissector_add_uint("tcp.option", TCPOPT_ECHO, create_dissector_handle( dissect_tcpopt_echo, proto_tcp_option_echo ));
10701 dissector_add_uint("tcp.option", TCPOPT_ECHOREPLY, create_dissector_handle( dissect_tcpopt_echo, proto_tcp_option_echoreply ));
10702 dissector_add_uint("tcp.option", TCPOPT_CC, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc ));
10703 dissector_add_uint("tcp.option", TCPOPT_CCNEW, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc_new ));
10704 dissector_add_uint("tcp.option", TCPOPT_CCECHO, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc_echo ));
10705 dissector_add_uint("tcp.option", TCPOPT_MD5, create_dissector_handle( dissect_tcpopt_md5, proto_tcp_option_md5 ));
10706 dissector_add_uint("tcp.option", TCPOPT_AO, create_dissector_handle( dissect_tcpopt_ao, proto_tcp_option_ao ));
10707 dissector_add_uint("tcp.option", TCPOPT_SCPS, create_dissector_handle( dissect_tcpopt_scps, proto_tcp_option_scps ));
10708 dissector_add_uint("tcp.option", TCPOPT_SNACK, create_dissector_handle( dissect_tcpopt_snack, proto_tcp_option_snack ));
10709 dissector_add_uint("tcp.option", TCPOPT_RECBOUND, create_dissector_handle( dissect_tcpopt_recbound, proto_tcp_option_scpsrec ));
10710 dissector_add_uint("tcp.option", TCPOPT_CORREXP, create_dissector_handle( dissect_tcpopt_correxp, proto_tcp_option_scpscor ));
10711 dissector_add_uint("tcp.option", TCPOPT_QS, create_dissector_handle( dissect_tcpopt_qs, proto_tcp_option_qs ));
10712 dissector_add_uint("tcp.option", TCPOPT_USER_TO, create_dissector_handle( dissect_tcpopt_user_to, proto_tcp_option_user_to ));
10713 dissector_add_uint("tcp.option", TCPOPT_TFO, create_dissector_handle( dissect_tcpopt_tfo, proto_tcp_option_tfo ));
10714 dissector_add_uint("tcp.option", TCPOPT_RVBD_PROBE, create_dissector_handle( dissect_tcpopt_rvbd_probe, proto_tcp_option_rvbd_probe ));
10715 dissector_add_uint("tcp.option", TCPOPT_RVBD_TRPY, create_dissector_handle( dissect_tcpopt_rvbd_trpy, proto_tcp_option_rvbd_trpy ));
10716 dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_0, create_dissector_handle( dissect_tcpopt_acc_ecn, proto_tcp_option_acc_ecn ));
10717 dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_1, create_dissector_handle( dissect_tcpopt_acc_ecn, proto_tcp_option_acc_ecn ));
10718 dissector_add_uint("tcp.option", TCPOPT_EXP_FD, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp ));
10719 dissector_add_uint("tcp.option", TCPOPT_EXP_FE, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp ));
10720 dissector_add_uint("tcp.option", TCPOPT_MPTCP, create_dissector_handle( dissect_tcpopt_mptcp, proto_mptcp ));
10721 /* Common handle for all the unknown/unsupported TCP options */
10722 tcp_opt_unknown_handle = create_dissector_handle( dissect_tcpopt_unknown, proto_tcp_option_unknown );
10724 exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4);
10726 proto_ip = proto_get_id_by_filter_name("ip");
10727 proto_icmp = proto_get_id_by_filter_name("icmp");
10731 * Editor modelines
10733 * Local Variables:
10734 * c-basic-offset: 4
10735 * tab-width: 8
10736 * indent-tabs-mode: nil
10737 * End:
10739 * ex: set shiftwidth=4 tabstop=8 expandtab:
10740 * :indentSize=4:tabSize=8:noTabs=true: