epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-tcp.c
blob97522a86c65323df1adbf99082387a06549bb631
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_scps_capable;
466 static expert_field ei_tcp_option_sack_dsack;
467 static expert_field ei_tcp_option_snack_sequence;
468 static expert_field ei_tcp_option_wscale_shift_invalid;
469 static expert_field ei_tcp_option_mss_absent;
470 static expert_field ei_tcp_option_mss_present;
471 static expert_field ei_tcp_option_sack_perm_absent;
472 static expert_field ei_tcp_option_sack_perm_present;
473 static expert_field ei_tcp_short_segment;
474 static expert_field ei_tcp_ack_nonzero;
475 static expert_field ei_tcp_connection_synack;
476 static expert_field ei_tcp_connection_syn;
477 static expert_field ei_tcp_connection_fin;
478 static expert_field ei_tcp_connection_rst;
479 static expert_field ei_tcp_connection_fin_active;
480 static expert_field ei_tcp_connection_fin_passive;
481 static expert_field ei_tcp_checksum_ffff;
482 static expert_field ei_tcp_checksum_partial;
483 static expert_field ei_tcp_checksum_bad;
484 static expert_field ei_tcp_urgent_pointer_non_zero;
485 static expert_field ei_tcp_suboption_malformed;
486 static expert_field ei_tcp_nop;
487 static expert_field ei_tcp_non_zero_bytes_after_eol;
488 static expert_field ei_tcp_bogus_header_length;
490 /* static expert_field ei_mptcp_analysis_unexpected_idsn; */
491 static expert_field ei_mptcp_analysis_echoed_key_mismatch;
492 static expert_field ei_mptcp_analysis_missing_algorithm;
493 static expert_field ei_mptcp_analysis_unsupported_algorithm;
494 static expert_field ei_mptcp_infinite_mapping;
495 static expert_field ei_mptcp_mapping_missing;
496 /* static expert_field ei_mptcp_stream_incomplete; */
497 /* static expert_field ei_mptcp_analysis_dsn_out_of_order; */
499 /* Some protocols such as encrypted DCE/RPCoverHTTP have dependencies
500 * from one PDU to the next PDU and require that they are called in sequence.
501 * These protocols would not be able to handle PDUs coming out of order
502 * or for example when a PDU is seen twice, like for retransmissions.
503 * This preference can be set for such protocols to make sure that we don't
504 * invoke the subdissectors for retransmitted or out-of-order segments.
506 static bool tcp_no_subdissector_on_error = true;
508 /* Enable buffering of out-of-order TCP segments before passing it to a
509 * subdissector (depends on "tcp_desegment"). */
510 static bool tcp_reassemble_out_of_order;
513 * FF: https://www.rfc-editor.org/rfc/rfc6994.html
514 * With this flag set we assume the option structure for experimental
515 * codepoints (253, 254) has an Experiment Identifier (ExID), which is
516 * the first 16-bit field after the Kind and Length.
517 * The ExID is used to differentiate different experiments and thus will
518 * be used in data dissection.
520 static bool tcp_exp_options_rfc6994 = true;
523 * This flag indicates which of Fast Retransmission or Out-of-Order
524 * interpretation should supersede when analyzing an ambiguous packet as
525 * things are not always clear. The user is authorized to change this
526 * behavior.
527 * When set, we keep the historical interpretation (Fast RT > OOO)
529 static bool tcp_fastrt_precedence = true;
531 /* Process info, currently discovered via IPFIX */
532 static bool tcp_display_process_info;
534 /* Read the sequence number as syn cookie */
535 static bool read_seq_as_syn_cookie;
538 * TCP option
540 #define TCPOPT_NOP 1 /* Padding */
541 #define TCPOPT_EOL 0 /* End of options */
542 #define TCPOPT_MSS 2 /* Segment size negotiating */
543 #define TCPOPT_WINDOW 3 /* Window scaling */
544 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
545 #define TCPOPT_SACK 5 /* SACK Block */
546 #define TCPOPT_ECHO 6
547 #define TCPOPT_ECHOREPLY 7
548 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
549 #define TCPOPT_CC 11
550 #define TCPOPT_CCNEW 12
551 #define TCPOPT_CCECHO 13
552 #define TCPOPT_MD5 19 /* RFC2385 */
553 #define TCPOPT_SCPS 20 /* SCPS Capabilities */
554 #define TCPOPT_SNACK 21 /* SCPS SNACK */
555 #define TCPOPT_RECBOUND 22 /* SCPS Record Boundary */
556 #define TCPOPT_CORREXP 23 /* SCPS Corruption Experienced */
557 #define TCPOPT_QS 27 /* RFC4782 Quick-Start Response */
558 #define TCPOPT_USER_TO 28 /* RFC5482 User Timeout Option */
559 #define TCPOPT_AO 29 /* RFC5925 The TCP Authentication Option */
560 #define TCPOPT_MPTCP 30 /* RFC6824 Multipath TCP */
561 #define TCPOPT_TFO 34 /* RFC7413 TCP Fast Open Cookie */
562 #define TCPOPT_ACC_ECN_0 0xac /* draft-ietf-tcpm-accurate-ecn */
563 #define TCPOPT_ACC_ECN_1 0xae /* draft-ietf-tcpm-accurate-ecn */
564 #define TCPOPT_EXP_FD 0xfd /* Experimental, reserved */
565 #define TCPOPT_EXP_FE 0xfe /* Experimental, reserved */
566 /* Non IANA registered option numbers */
567 #define TCPOPT_RVBD_PROBE 76 /* Riverbed probe option */
568 #define TCPOPT_RVBD_TRPY 78 /* Riverbed transparency option */
571 * TCP option lengths
573 #define TCPOLEN_MSS 4
574 #define TCPOLEN_WINDOW 3
575 #define TCPOLEN_SACK_PERM 2
576 #define TCPOLEN_SACK_MIN 2
577 #define TCPOLEN_ECHO 6
578 #define TCPOLEN_ECHOREPLY 6
579 #define TCPOLEN_TIMESTAMP 10
580 #define TCPOLEN_CC 6
581 #define TCPOLEN_CCNEW 6
582 #define TCPOLEN_CCECHO 6
583 #define TCPOLEN_MD5 18
584 #define TCPOLEN_SCPS 4
585 #define TCPOLEN_SNACK 6
586 #define TCPOLEN_RECBOUND 2
587 #define TCPOLEN_CORREXP 2
588 #define TCPOLEN_QS 8
589 #define TCPOLEN_USER_TO 4
590 #define TCPOLEN_MPTCP_MIN 3
591 #define TCPOLEN_TFO_MIN 2
592 #define TCPOLEN_RVBD_PROBE_MIN 3
593 #define TCPOLEN_RVBD_TRPY_MIN 16
594 #define TCPOLEN_EXP_MIN 4
597 * TCP Experimental Option Experiment Identifiers (TCP ExIDs)
598 * See: https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-exids
599 * Wireshark only supports 16-bit ExIDs
602 #define TCPEXID_TARR 0x00ac
603 #define TCPEXID_HOST_ID 0x0348
604 #define TCPEXID_ASC 0x0a0d
605 #define TCPEXID_CAPABILITY 0x0ca0
606 #define TCPEXID_EDO 0x0ed0
607 #define TCPEXID_ENO 0x454e
608 #define TCPEXID_SNO 0x5323
609 #define TCPEXID_TS_INTERVAL 0x75ec /* 32-bit ExID: 0x75ecffee */
610 #define TCPEXID_ACC_ECN_0 0xacc0
611 #define TCPEXID_ACC_ECN_1 0xacc1
612 #define TCPEXID_ACC_ECN 0xacce
613 #define TCPEXID_SMC_R 0xe2d4 /* 32-bit ExID: 0xe2d4c3d9 */
614 #define TCPEXID_FO 0xf989
615 #define TCPEXID_LOW_LATENCY 0xf990
618 * Multipath TCP subtypes
620 #define TCPOPT_MPTCP_MP_CAPABLE 0x0 /* Multipath TCP Multipath Capable */
621 #define TCPOPT_MPTCP_MP_JOIN 0x1 /* Multipath TCP Join Connection */
622 #define TCPOPT_MPTCP_DSS 0x2 /* Multipath TCP Data Sequence Signal */
623 #define TCPOPT_MPTCP_ADD_ADDR 0x3 /* Multipath TCP Add Address */
624 #define TCPOPT_MPTCP_REMOVE_ADDR 0x4 /* Multipath TCP Remove Address */
625 #define TCPOPT_MPTCP_MP_PRIO 0x5 /* Multipath TCP Change Subflow Priority */
626 #define TCPOPT_MPTCP_MP_FAIL 0x6 /* Multipath TCP Fallback */
627 #define TCPOPT_MPTCP_MP_FASTCLOSE 0x7 /* Multipath TCP Fast Close */
628 #define TCPOPT_MPTCP_MP_TCPRST 0x8 /* Multipath TCP Reset */
631 * Conversation Completeness values
633 #define TCP_COMPLETENESS_SYNSENT 0x01 /* TCP SYN SENT */
634 #define TCP_COMPLETENESS_SYNACK 0x02 /* TCP SYN ACK */
635 #define TCP_COMPLETENESS_ACK 0x04 /* TCP ACK */
636 #define TCP_COMPLETENESS_DATA 0x08 /* TCP data */
637 #define TCP_COMPLETENESS_FIN 0x10 /* TCP FIN */
638 #define TCP_COMPLETENESS_RST 0x20 /* TCP RST */
640 static const true_false_string tcp_option_user_to_granularity = {
641 "Minutes", "Seconds"
644 static const value_string tcp_option_kind_vs[] = {
645 { TCPOPT_EOL, "End of Option List" },
646 { TCPOPT_NOP, "No-Operation" },
647 { TCPOPT_MSS, "Maximum Segment Size" },
648 { TCPOPT_WINDOW, "Window Scale" },
649 { TCPOPT_SACK_PERM, "SACK Permitted" },
650 { TCPOPT_SACK, "SACK" },
651 { TCPOPT_ECHO, "Echo" },
652 { TCPOPT_ECHOREPLY, "Echo Reply" },
653 { TCPOPT_TIMESTAMP, "Time Stamp Option" },
654 { 9, "Partial Order Connection Permitted" },
655 { 10, "Partial Order Service Profile" },
656 { TCPOPT_CC, "CC" },
657 { TCPOPT_CCNEW, "CC.NEW" },
658 { TCPOPT_CCECHO, "CC.ECHO" },
659 { 14, "TCP Alternate Checksum Request" },
660 { 15, "TCP Alternate Checksum Data" },
661 { 16, "Skeeter" },
662 { 17, "Bubba" },
663 { 18, "Trailer Checksum Option" },
664 { TCPOPT_MD5, "MD5 Signature Option" },
665 { TCPOPT_SCPS, "SCPS Capabilities" },
666 { TCPOPT_SNACK, "Selective Negative Acknowledgements" },
667 { TCPOPT_RECBOUND, "Record Boundaries" },
668 { TCPOPT_CORREXP, "Corruption experienced" },
669 { 24, "SNAP" },
670 { 25, "Unassigned" },
671 { 26, "TCP Compression Filter" },
672 { TCPOPT_QS, "Quick-Start Response" },
673 { TCPOPT_USER_TO, "User Timeout Option" },
674 { TCPOPT_AO, "The TCP Authentication Option" },
675 { TCPOPT_MPTCP, "Multipath TCP" },
676 { TCPOPT_TFO, "TCP Fast Open Cookie" },
677 { TCPOPT_RVBD_PROBE, "Riverbed Probe" },
678 { TCPOPT_RVBD_TRPY, "Riverbed Transparency" },
679 { TCPOPT_ACC_ECN_0, "Accurate ECN Order 0" },
680 { TCPOPT_ACC_ECN_1, "Accurate ECN Order 1" },
681 { TCPOPT_EXP_FD, "RFC3692-style Experiment 1" },
682 { TCPOPT_EXP_FE, "RFC3692-style Experiment 2" },
683 { 0, NULL }
685 static value_string_ext tcp_option_kind_vs_ext = VALUE_STRING_EXT_INIT(tcp_option_kind_vs);
687 static const value_string tcp_exid_vs[] = {
688 { TCPEXID_TARR, "TCP ACK Rate Request" },
689 { TCPEXID_HOST_ID, "Host ID" },
690 { TCPEXID_ASC, "Autonomous System Compensation" },
691 { TCPEXID_CAPABILITY, "Capability Option" },
692 { TCPEXID_EDO, "Extended Data Offset" },
693 { TCPEXID_ENO, "Encryption Negotiation" },
694 { TCPEXID_SNO, "Service Number" },
695 { TCPEXID_TS_INTERVAL, "Timestamp Interval" },
696 { TCPEXID_ACC_ECN_0, "Accurate ECN - Order 0" },
697 { TCPEXID_ACC_ECN_1, "Accurate ECN - Order 1" },
698 { TCPEXID_ACC_ECN, "Accurate ECN" },
699 { TCPEXID_SMC_R, "Shared Memory communications over RMDA protocol" },
700 { TCPEXID_FO, "Fast Open" },
701 { TCPEXID_LOW_LATENCY, "Low Latency" },
702 { 0, NULL }
705 /* not all of the hf_fields below make sense for TCP but we have to provide
706 them anyways to comply with the API (which was aimed for IP fragment
707 reassembly) */
708 static const fragment_items tcp_segment_items = {
709 &ett_tcp_segment,
710 &ett_tcp_segments,
711 &hf_tcp_segments,
712 &hf_tcp_segment,
713 &hf_tcp_segment_overlap,
714 &hf_tcp_segment_overlap_conflict,
715 &hf_tcp_segment_multiple_tails,
716 &hf_tcp_segment_too_long_fragment,
717 &hf_tcp_segment_error,
718 &hf_tcp_segment_count,
719 &hf_tcp_reassembled_in,
720 &hf_tcp_reassembled_length,
721 &hf_tcp_reassembled_data,
722 "Segments"
726 static const value_string mptcp_subtype_vs[] = {
727 { TCPOPT_MPTCP_MP_CAPABLE, "Multipath Capable" },
728 { TCPOPT_MPTCP_MP_JOIN, "Join Connection" },
729 { TCPOPT_MPTCP_DSS, "Data Sequence Signal" },
730 { TCPOPT_MPTCP_ADD_ADDR, "Add Address"},
731 { TCPOPT_MPTCP_REMOVE_ADDR, "Remove Address" },
732 { TCPOPT_MPTCP_MP_PRIO, "Change Subflow Priority" },
733 { TCPOPT_MPTCP_MP_FAIL, "TCP Fallback" },
734 { TCPOPT_MPTCP_MP_FASTCLOSE, "Fast Close" },
735 { TCPOPT_MPTCP_MP_TCPRST, "TCP Reset" },
736 { 0, NULL }
739 /* Source https://support.citrix.com/article/CTX200852/citrix-adc-netscaler-reset-codes-reference
740 Dates of source: Created: 31 Mar 2015 | Modified: 21 Jan 2023
741 Date of last dictionary update: 2024/07/11
742 NOTE: When updating don't just overwrite the dictionary, the definitions below are more polished than the ones in the CTX. */
743 static const value_string netscaler_reset_window_error_code_vals[] = {
744 { 8196, "SSL bad record." },
745 { 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." },
746 { 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." },
747 { 8204, "Client retransmitted SYN with the wrong sequence number." },
748 { 8205, "ACK number in the final ACK from peer during connection establishment is wrong." },
749 { 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." },
750 { 8207, "Received SYN on established connection which is within the window. Protects from spoofing attacks." },
751 { 8208, "Resets the connection when you receive more than the configured value of duplicate retransmissions." },
752 { 8209, "Could not allocate memory for the packet, system out of memory." },
753 { 8210, "HTTP DoS protection feature error, bad client request." },
754 { 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)." },
755 { 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." },
756 { 8213, "Sure Connect feature, bad client sending post on connection which is closing." },
757 { 8214, "MSS sent in SYN exceeded the MSS corresponding to NIC MTU and/or VLAN MTU." },
758 { 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." },
759 { 9201, "HTTP connection multiplexing error. Server sent response packets belonging to previous transaction." },
760 { 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." },
761 { 9203, "NSDBG_RST_CLT_CHK_MIX: This code refers to the server sending a FIN for a previous client over a reused connection." },
762 { 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." },
763 { 9206, "HTTP tracking failed due to invalid HTTP request/response header." },
764 { 9207, "Invalid header reassembly parsing." },
765 { 9208, "Incomplete response processing error, see incompHdrDelay setting httpprofiles." },
766 { 9209, "Chunk tracking failed." },
767 { 9210, "Corrupt packets." },
768 { 9212, "HTTP Invalid request." },
769 { 9214, "Cache res store failed." },
770 { 9216, "Cache async no memory." },
771 { 9217, "HTTP state machine error because of more than content length body." },
772 { 9218, "Terminated due to extra orphan data." },
773 { 9219, "NSB allocation failure." },
774 { 9220, "Cannot allocate new NSB and so many other reasons." },
775 { 9221, "vurl comes with a domain shard that’s no longer valid." },
776 { 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." },
777 { 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)." },
778 { 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)." },
779 { 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)." },
780 { 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)." },
781 { 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." },
782 { 9305, "Server sent back ACK to our SYN (ACK number did not match)." },
783 { 9306, "TCP buffering is undone due to duplicate TPCB enablement." },
784 { 9307, "Small window protection feature resetting the connection." },
785 { 9308, "Small window protection feature resetting the connection." },
786 { 9309, "Small window protection feature resetting the connection." },
787 { 9310, "TCP KA probing failed." },
788 { 9311, "DHT retry failed." },
789 { 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." },
790 { 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." },
791 { 9450, "SQL HS failed." },
792 { 9451, "SQL response failed." },
793 { 9452, "SQL request list failed." },
794 { 9453, "SQL UNK not linked." },
795 { 9454, "SQL NSB hold failed." },
796 { 9455, "SQL Server First Packet." },
797 { 9456, "SQL Login response before request." },
798 { 9457, "SQL server login failed." },
799 { 9458, "SQL no memory." },
800 { 9459, "SQL bad server." },
801 { 9460, "SQL link failed." },
802 { 9600, "Reset when Number of packets with Sequence ACK mismatch > nscfg_max_orphan_pkts." },
803 { 9601, "Reset when Number of data packets with Sequence ACK mismatch > nscfg_max_orphan_pkts." },
804 { 9602, "When SSL VPN CS probe limit exceeded." },
805 { 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." },
806 { 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." },
807 { 9702, "The data received after FIN is received." },
808 { 9704, "Reset when NSB dropped due to hold limit or error in transaction etc." },
809 { 9800, "NSDBG_RST_PROBE: This connections used for monitoring the service are reset due to timeout." },
810 { 9810, "When responses match the configured NAI status code." },
811 { 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." },
812 { 9812, "Connection flushing because existing IP address is removed from the configuration." },
813 { 9813, "Closing the SSF connection." },
814 { 9814, "NSDBG_RST_PETRIGGER: This reset code is used when a request or response matches a Policy Engine policy, whose action is RESET." },
815 { 9816, "Bad SSL record." },
816 { 9817, "SSL connection received at the time of bound certificate changing (configuration change)." },
817 { 9818, "Bad SSL header value." },
818 { 9819, "Reset on failing to allocate memory for SPCB." },
819 { 9820, "SSL card operation failed." },
820 { 9821, "SSL feature disabled, reset the connection." },
821 { 9822, "SSL cipher changed, flush the connection created for old cipher." },
822 { 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." },
823 { 9824, "Reset on AAA orphan connections." },
824 { 9825, "DBG_WRONG_GSLBRECDLEN: This code is a GSLB MEP error reset code, typically between mixed versions." },
825 { 9826, "Not enough memory for NET buffers." },
826 { 9827, "Reset on SSL config change." },
827 { 9829, "Reset on GSLB other site down or out of reach." },
828 { 9830, "Reset on sessions matching ACL DENY rule." },
829 { 9831, "Use it if no application data exist, but required." },
830 { 9832, "Application error." },
831 { 9833, "Fatal SSL error." },
832 { 9834, "Reset while flushing all SPCB, during FIPS or HSM init." },
833 { 9835, "DTLS record too large." },
834 { 9836, "DTLS record zero length." },
835 { 9837, "SSLV2 record too large." },
836 { 9838, "NSBE_DBG_RST_SSL_BAD_RECORD: This code refers to error looking up SSL record when handling a request or a response." },
837 { 9839, "SSL MAX NSB hold limit reached." },
838 { 9841, "SSL/DTLS split packet failure." },
839 { 9842, "SSL NSB allocation failure." },
840 { 9843, "Monitor wide IP probe." },
841 { 9844, "SSL reneg max NSB limit reached or alloc failure." },
842 { 9845, "Reset on Appsec policy." },
843 { 9846, "Delta compression aborted or failed." },
844 { 9847, "Delta compression aborted or failed." },
845 { 9848, "Reset on connection accepted during configuration change(SSL)." },
846 { 9849, "Reset on GSLB conflict due to misconfiguration." },
847 { 9850, "DNS TCP connection untrackable due to failure of compact NSB, etc." },
848 { 9851, "DNS TCP failure (invalid payload, length, etc)." },
849 { 9852, "RTSP (ALG) session handling error." },
850 { 9853, "MSSQL Auth response error." },
851 { 9854, "Indirect GSLB sites tried to establish connection" },
852 { 9855, "For HTTP/SSL vservers, SO (Surge Queue Overflow.) threshold has reached." },
853 { 9856, "Reset on Appfw ASYNC failure." },
854 { 9857, "Reset on Flushing HTTP waiting PCB." },
855 { 9858, "Reset on Rechunk abort." },
856 { 9859, "A new client connection request was made deferrable by server on the label." },
857 { 9860, "The pcb->link of this connection was cleaned for some reason, so resetting this PCB." },
858 { 9861, "Connection on a push vserver, when push disabled on client vserver." },
859 { 9862, "Reset to Client as it resulted in duplicate server connection." },
860 { 9863, "Reset to old connection when new connection is established and old one is still not freed." },
861 { 9864, "CVPN HINFO restore failed." },
862 { 9865, "CVPN MCMX error." },
863 { 9866, "URL policy transform error." },
864 { 9868, "MSSQL login errors." },
865 { 9870, "SQL login parse error." },
866 { 9871, "MSSQL memory allocation failure." },
867 { 9872, "Websocket upgrade request dropped due to websocket disabled in http profile." },
868 { 9873, "Agsvc MCMX failure." },
869 { 9874, "NSB hold limit reached." },
870 { 9875, "Client connection is closed, send RST to server." },
871 { 9876, "One to many link failed." },
872 { 9877, "Reset for CEA on client PCB." },
873 { 9878, "CEA untrackable, send RST to Client." },
874 { 9879, "Parsing failed." },
875 { 9880, "Memory alloc failure." },
876 { 9881, "Reset on Diameter message without CE." },
877 { 9882, "Reset to Client if no pending requests." },
878 { 9883, "Link PCB fail reset to client on CEA." },
879 { 9884, "Reset to Server PCB." },
880 { 9885, "SIP Content header is missing. | Diameter reset on bad ACK." },
881 { 9886, "Reset on VPN ng binding miss." },
882 { 9887, "Reset on failed to send a request to broker (VPN)." },
883 { 9888, "Reset to AAA client if Cluster sync in progress." },
884 { 9889, "Reset on missing dynamic processing context (LUA)." },
885 { 9890, "Rewrite feature disabled when blocked on response side." },
886 { 9900, "PI reset." },
887 { 9901, "Cache buffer large data error." },
888 { 9902, "HTML injection connection abort." },
889 { 9903, "GSLB feature is disabled. Donot accept any connections and close any existing ones." },
890 { 9904, "Reset on AAA error." },
891 { 9905, "Database not responding." },
892 { 9906, "Local GSLB sites have been removed, send RST." },
893 { 9911, "HTTP incomplete due to no available memory." },
894 { 9912, "HTTP link incomplete due to no available memory." },
895 { 9913, "Send RST for SPDY errors." },
896 { 9914, "Cache Response error/AAA." },
897 { 9915, "Speedy split packet at header failed." },
898 { 9951, "SSL incomplete record." },
899 { 9952, "Reset on SSL FATAL ALERT RCVD." },
900 { 9953, "Reset on triggering of timeout action." },
901 { 9956, "QOS incomplete POST handling error." },
902 { 9957, "AppQoS Persistent service is down." },
903 { 9958, "Not used+C187:C199." },
904 { 9959, "Not used." },
905 { 9960, "MPTCP options error." },
906 { 9961, "MP join SYN reset." },
907 { 9962, "MP join FINAL ACK reset." },
908 { 9963, "MPTCP checksum failure." },
909 { 9964, "Invalid Client or NS key." },
910 { 9965, "MPTCP, established SF replaced." },
911 { 9966, "MPTCP RSSF filter failure." },
912 { 9967, "MPTCP plain ACK fallback failure." },
913 { 9968, "MPTCP fast close received." },
914 { 9969, "MPTCP, if NS in fallback mode, DSS should only for infinite map." },
915 { 9970, "BW Connection Close." },
916 { 9971, "MPTCP invalid/bad MAP." },
917 { 9972, "MPTCP reset if multiple SFs are present." },
918 { 9973, "Reset on rest of SF after fallback to infinite map as only one SF should be present." },
919 { 9974, "RST terminated at TCP layer." },
920 { 9975, "PCB waitQ insertion failed." },
921 { 9976, "MPTCP MAX retries on KA probes has reached." },
922 { 9977, "MPTCP token collision is found." },
923 { 9978, "MPTCP SYN retries reached MAXretries." },
924 { 9979, "MPTCP subflow FIN received or any other signals received on pre est SF." },
925 { 9980, "Reset on MPTCP close." },
926 { 9981, "Closing auditlog connection." },
927 { 9982, "invalid syn/ack/seq is received for NS's SYN+TFOC+DATA." },
928 { 9983, "MPTCP invalid payload size." },
929 { 10000, "ICA parse error." },
930 { 10001, "ICA link parse error." },
931 { 10002, "ICA no available memory." },
932 { 10003, "ICA link no available memory." },
933 { 10004, "Kill an ICA connection." },
934 { 10005, "MPTCP SYN retries reached MAXretries." },
935 { 10006, "Kill an RDP connection." },
936 { 10016, "SMPP no memory available." },
937 { 10017, "SMPP reset if no pending requests." },
938 { 10018, "SMPP unknown error." },
939 { 10019, "SMPP: Bind to client failed." },
940 { 10020, "SMPP: NSB hold limit reached." },
941 { 10022, "SMPP: Bind response on client." },
942 { 10023, "SMPP: Parsing failed." },
943 { 10024, "SMPP: link failed." },
944 { 10026, "SMPP: MSG without bind or not request message after bind." },
945 { 10027, "SSL: HSM operation failed." },
946 { 10028, "SSL: HSM error client." },
947 { 10029, "SSL: Hit the ratelimit." },
948 { 10030, "Connection breached maximum packet credits configured." },
949 { 10032, "SIPALG: Header parsing failed." },
950 { 10033, "SIPALG: Body parsing failed." },
951 { 10034, "SIPALG: SIP header failure." },
952 { 10035, "SIPALG: SDP header failure." },
953 { 10036, "SIPALG: Remaining IP replacement failure." },
954 { 10037, "SIPALG: Length replacement failure." },
955 { 10038, "SIPALG: BA insertion failed." },
956 { 10039, "SIPALG: DHT failure." },
957 { 10040, "SIPALG: Post translation ops failed." },
958 { 10042, "SIPALG: Pre translation ops failed." },
959 { 0, NULL },
962 static dissector_table_t subdissector_table;
963 static dissector_table_t tcp_option_table;
964 static heur_dissector_list_t heur_subdissector_list;
965 static dissector_handle_t data_handle;
966 static dissector_handle_t tcp_handle;
967 static dissector_handle_t sport_handle;
968 static dissector_handle_t tcp_opt_unknown_handle;
969 static capture_dissector_handle_t tcp_cap_handle;
971 static uint32_t tcp_stream_count;
972 static uint32_t mptcp_stream_count;
977 * Maps an MPTCP token to a mptcp_analysis structure
978 * Collisions are not handled
980 static wmem_tree_t *mptcp_tokens;
982 static int * const tcp_option_mptcp_capable_v0_flags[] = {
983 &hf_tcp_option_mptcp_checksum_flag,
984 &hf_tcp_option_mptcp_B_flag,
985 &hf_tcp_option_mptcp_H_v0_flag,
986 &hf_tcp_option_mptcp_reserved_v0_flag,
987 NULL
990 static int * const tcp_option_mptcp_capable_v1_flags[] = {
991 &hf_tcp_option_mptcp_checksum_flag,
992 &hf_tcp_option_mptcp_B_flag,
993 &hf_tcp_option_mptcp_C_flag,
994 &hf_tcp_option_mptcp_H_v1_flag,
995 &hf_tcp_option_mptcp_reserved_v1_flag,
996 NULL
999 static int * const tcp_option_mptcp_join_flags[] = {
1000 &hf_tcp_option_mptcp_backup_flag,
1001 NULL
1004 static int * const tcp_option_mptcp_dss_flags[] = {
1005 &hf_tcp_option_mptcp_F_flag,
1006 &hf_tcp_option_mptcp_m_flag,
1007 &hf_tcp_option_mptcp_M_flag,
1008 &hf_tcp_option_mptcp_a_flag,
1009 &hf_tcp_option_mptcp_A_flag,
1010 NULL
1013 static int * const tcp_option_mptcp_tcprst_flags[] = {
1014 &hf_tcp_option_mptcp_U_flag,
1015 &hf_tcp_option_mptcp_V_flag,
1016 &hf_tcp_option_mptcp_W_flag,
1017 &hf_tcp_option_mptcp_T_flag,
1018 NULL
1021 static const unit_name_string units_64bit_version = { " (64bits version)", NULL };
1023 static uint8_t
1024 tcp_get_ace(const struct tcpheader *tcph)
1026 uint8_t ace;
1028 ace = 0;
1029 if (tcph->th_flags & TH_AE) {
1030 ace += 4;
1032 if (tcph->th_flags & TH_CWR) {
1033 ace += 2;
1035 if (tcph->th_flags & TH_ECE) {
1036 ace += 1;
1038 return ace;
1041 static char *
1042 tcp_flags_to_str(wmem_allocator_t *scope, const struct tcpheader *tcph)
1044 static const char flags[][4] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECE", "CWR", "AE" };
1045 static const char digit[][2] = { "0", "1", "2", "3", "4", "5", "6", "7" };
1046 const int maxlength = 64; /* upper bounds, max 53B: 8 * 3 + 2 + strlen("Reserved") + 9 * 2 + 1 */
1048 char *pbuf;
1049 char *buf;
1050 uint8_t ace;
1051 int i;
1053 buf = pbuf = (char *) wmem_alloc(scope, maxlength);
1054 *pbuf = '\0';
1056 for (i = 0; i < (tcph->th_use_ace ? 6 : 9); i++) {
1057 if (tcph->th_flags & (1 << i)) {
1058 if (buf[0])
1059 pbuf = g_stpcpy(pbuf, ", ");
1060 pbuf = g_stpcpy(pbuf, flags[i]);
1063 if (tcph->th_use_ace) {
1064 ace = tcp_get_ace(tcph);
1065 pbuf = g_stpcpy(pbuf, ", ACE=");
1066 pbuf = g_stpcpy(pbuf, digit[ace]);
1069 if (tcph->th_flags & TH_RES) {
1070 if (buf[0])
1071 pbuf = g_stpcpy(pbuf, ", ");
1072 g_stpcpy(pbuf, "Reserved");
1075 if (buf[0] == '\0')
1076 g_stpcpy(pbuf, "<None>");
1078 return buf;
1081 static char *
1082 tcp_flags_to_str_first_letter(wmem_allocator_t *scope, const struct tcpheader *tcph)
1084 wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");
1085 unsigned i;
1086 const unsigned flags_count = 12;
1087 static const char first_letters[] = "RRRACEUAPRSF";
1088 static const char digits[] = "01234567";
1090 /* upper three bytes are marked as reserved ('R'). */
1091 for (i = 0; i < flags_count; i++) {
1092 if (tcph->th_use_ace && 3 <= i && i <= 5) {
1093 if (i == 4) {
1094 wmem_strbuf_append_c(buf, digits[tcp_get_ace(tcph)]);
1095 } else {
1096 wmem_strbuf_append_c(buf, '-');
1098 } else {
1099 if (((tcph->th_flags >> (flags_count - 1 - i)) & 1)) {
1100 wmem_strbuf_append_c(buf, first_letters[i]);
1101 } else {
1102 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1107 return wmem_strbuf_finalize(buf);
1111 * Print the first letter of each flag set, or the dot character otherwise
1113 static char *
1114 completeness_flags_to_str_first_letter(wmem_allocator_t *scope, uint8_t flags)
1116 wmem_strbuf_t *buf = wmem_strbuf_new(scope, "");
1118 if( flags & TCP_COMPLETENESS_RST )
1119 wmem_strbuf_append(buf, "R");
1120 else
1121 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1123 if( flags & TCP_COMPLETENESS_FIN )
1124 wmem_strbuf_append(buf, "F");
1125 else
1126 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1128 if( flags & TCP_COMPLETENESS_DATA )
1129 wmem_strbuf_append(buf, "D");
1130 else
1131 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1133 if( flags & TCP_COMPLETENESS_ACK )
1134 wmem_strbuf_append(buf, "A");
1135 else
1136 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1138 if( flags & TCP_COMPLETENESS_SYNACK )
1139 wmem_strbuf_append(buf, "S");
1140 else
1141 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1143 if( flags & TCP_COMPLETENESS_SYNSENT )
1144 wmem_strbuf_append(buf, "S");
1145 else
1146 wmem_strbuf_append(buf, UTF8_MIDDLE_DOT);
1148 return wmem_strbuf_finalize(buf);
1151 static void
1152 tcp_src_prompt(packet_info *pinfo, char *result)
1154 uint32_t port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num));
1156 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "source (%u%s)", port, UTF8_RIGHTWARDS_ARROW);
1159 static void *
1160 tcp_src_value(packet_info *pinfo)
1162 return p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num);
1165 static void
1166 tcp_dst_prompt(packet_info *pinfo, char *result)
1168 uint32_t port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num));
1170 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW, port);
1173 static void *
1174 tcp_dst_value(packet_info *pinfo)
1176 return p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num);
1179 static void
1180 tcp_both_prompt(packet_info *pinfo, char *result)
1182 uint32_t srcport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num)),
1183 destport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num));
1184 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "both (%u%s%u)", srcport, UTF8_LEFT_RIGHT_ARROW, destport);
1187 static const char* tcp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
1190 if (filter == CONV_FT_SRC_PORT)
1191 return "tcp.srcport";
1193 if (filter == CONV_FT_DST_PORT)
1194 return "tcp.dstport";
1196 if (filter == CONV_FT_ANY_PORT)
1197 return "tcp.port";
1199 if(!conv) {
1200 return CONV_FILTER_INVALID;
1203 if (filter == CONV_FT_SRC_ADDRESS) {
1204 if (conv->src_address.type == AT_IPv4)
1205 return "ip.src";
1206 if (conv->src_address.type == AT_IPv6)
1207 return "ipv6.src";
1210 if (filter == CONV_FT_DST_ADDRESS) {
1211 if (conv->dst_address.type == AT_IPv4)
1212 return "ip.dst";
1213 if (conv->dst_address.type == AT_IPv6)
1214 return "ipv6.dst";
1217 if (filter == CONV_FT_ANY_ADDRESS) {
1218 if (conv->src_address.type == AT_IPv4)
1219 return "ip.addr";
1220 if (conv->src_address.type == AT_IPv6)
1221 return "ipv6.addr";
1224 return CONV_FILTER_INVALID;
1227 static ct_dissector_info_t tcp_ct_dissector_info = {&tcp_conv_get_filter_type};
1230 * callback function for conversation stats
1232 static int tcp_conv_cb_update(conversation_t *conv)
1234 struct tcp_analysis *tcpd;
1235 tcpd=get_tcp_conversation_data_idempotent(conv);
1236 if(tcpd)
1237 return tcpd->flow1.flow_count + tcpd->flow2.flow_count;
1238 else
1239 return 0;
1242 static tap_packet_status
1243 tcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
1245 conv_hash_t *hash = (conv_hash_t*) pct;
1246 hash->flags = flags;
1248 const struct tcpheader *tcphdr=(const struct tcpheader *)vip;
1250 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,
1251 &pinfo->rel_ts, &pinfo->abs_ts, &tcp_ct_dissector_info, CONVERSATION_TCP, (uint32_t)pinfo->num, tcp_conv_cb_update);
1254 return TAP_PACKET_REDRAW;
1257 static tap_packet_status
1258 mptcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
1260 conv_hash_t *hash = (conv_hash_t*) pct;
1261 hash->flags = flags;
1263 const struct tcp_analysis *tcpd=(const struct tcp_analysis *)vip;
1264 const mptcp_meta_flow_t *meta=(const mptcp_meta_flow_t *)tcpd->fwd->mptcp_subflow->meta;
1266 add_conversation_table_data_with_conv_id(hash, &meta->ip_src, &meta->ip_dst,
1267 meta->sport, meta->dport, (conv_id_t) tcpd->mptcp_analysis->stream, 1, pinfo->fd->pkt_len,
1268 &pinfo->rel_ts, &pinfo->abs_ts, &tcp_ct_dissector_info, CONVERSATION_TCP);
1270 return TAP_PACKET_REDRAW;
1273 static const char* tcp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter)
1275 if (filter == CONV_FT_SRC_PORT)
1276 return "tcp.srcport";
1278 if (filter == CONV_FT_DST_PORT)
1279 return "tcp.dstport";
1281 if (filter == CONV_FT_ANY_PORT)
1282 return "tcp.port";
1284 if(!endpoint) {
1285 return CONV_FILTER_INVALID;
1288 if (filter == CONV_FT_SRC_ADDRESS) {
1289 if (endpoint->myaddress.type == AT_IPv4)
1290 return "ip.src";
1291 if (endpoint->myaddress.type == AT_IPv6)
1292 return "ipv6.src";
1295 if (filter == CONV_FT_DST_ADDRESS) {
1296 if (endpoint->myaddress.type == AT_IPv4)
1297 return "ip.dst";
1298 if (endpoint->myaddress.type == AT_IPv6)
1299 return "ipv6.dst";
1302 if (filter == CONV_FT_ANY_ADDRESS) {
1303 if (endpoint->myaddress.type == AT_IPv4)
1304 return "ip.addr";
1305 if (endpoint->myaddress.type == AT_IPv6)
1306 return "ipv6.addr";
1309 return CONV_FILTER_INVALID;
1312 static et_dissector_info_t tcp_endpoint_dissector_info = {&tcp_endpoint_get_filter_type};
1314 static tap_packet_status
1315 tcpip_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
1317 conv_hash_t *hash = (conv_hash_t*) pit;
1318 hash->flags = flags;
1320 const struct tcpheader *tcphdr=(const struct tcpheader *)vip;
1322 /* Take two "add" passes per packet, adding for each direction, ensures that all
1323 packets are counted properly (even if address is sending to itself)
1324 XXX - this could probably be done more efficiently inside endpoint_table */
1325 add_endpoint_table_data(hash, &tcphdr->ip_src, tcphdr->th_sport, true, 1, pinfo->fd->pkt_len, &tcp_endpoint_dissector_info, ENDPOINT_TCP);
1326 add_endpoint_table_data(hash, &tcphdr->ip_dst, tcphdr->th_dport, false, 1, pinfo->fd->pkt_len, &tcp_endpoint_dissector_info, ENDPOINT_TCP);
1328 return TAP_PACKET_REDRAW;
1331 static bool
1332 tcp_filter_valid(packet_info *pinfo, void *user_data _U_)
1334 return proto_is_frame_protocol(pinfo->layers, "tcp");
1337 static char*
1338 tcp_build_filter_by_id(packet_info *pinfo, void *user_data _U_)
1340 return ws_strdup_printf("tcp.stream eq %d", pinfo->stream_id);
1344 /****************************************************************************/
1345 /* whenever a TCP packet is seen by the tap listener */
1346 /* Add a new tcp frame into the graph */
1347 static tap_packet_status
1348 tcp_seq_analysis_packet( void *ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *tcp_info, tap_flags_t tapflags _U_)
1350 seq_analysis_info_t *sainfo = (seq_analysis_info_t *) ptr;
1351 const struct tcpheader *tcph = (const struct tcpheader *)tcp_info;
1352 char* flags;
1353 seq_analysis_item_t *sai = sequence_analysis_create_sai_with_addresses(pinfo, sainfo);
1355 if (!sai)
1356 return TAP_PACKET_DONT_REDRAW;
1358 sai->frame_number = pinfo->num;
1360 sai->port_src=pinfo->srcport;
1361 sai->port_dst=pinfo->destport;
1363 flags = tcp_flags_to_str(NULL, tcph);
1365 if ((tcph->th_have_seglen)&&(tcph->th_seglen!=0)){
1366 sai->frame_label = ws_strdup_printf("%s - Len: %u",flags, tcph->th_seglen);
1368 else{
1369 sai->frame_label = g_strdup(flags);
1372 wmem_free(NULL, flags);
1374 if (tcph->th_flags & TH_ACK)
1375 sai->comment = ws_strdup_printf("Seq = %u Ack = %u",tcph->th_seq, tcph->th_ack);
1376 else
1377 sai->comment = ws_strdup_printf("Seq = %u",tcph->th_seq);
1379 sai->line_style = 1;
1380 sai->conv_num = (uint16_t) tcph->th_stream;
1381 sai->display = true;
1383 g_queue_push_tail(sainfo->items, sai);
1385 return TAP_PACKET_REDRAW;
1389 char *tcp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream _U_)
1391 conversation_t *conv;
1392 struct tcp_analysis *tcpd;
1394 /* XXX: Since TCP doesn't use the endpoint API, we can only look
1395 * up using the current pinfo addresses and ports. We don't want
1396 * to create a new conversation or new TCP stream.
1397 * Eventually the endpoint API should support storing multiple
1398 * endpoints and TCP should be changed to use the endpoint API.
1400 conv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
1401 if (((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) ||
1402 (pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6))
1403 && (pinfo->ptype == PT_TCP) &&
1404 conv != NULL)
1406 /* TCP over IPv4/6 */
1407 tcpd=get_tcp_conversation_data(conv, pinfo);
1408 if (tcpd == NULL)
1409 return NULL;
1411 *stream = tcpd->stream;
1412 return ws_strdup_printf("tcp.stream eq %u", tcpd->stream);
1415 return NULL;
1418 char *tcp_follow_index_filter(unsigned stream, unsigned sub_stream _U_)
1420 return ws_strdup_printf("tcp.stream eq %u", stream);
1423 char *tcp_follow_address_filter(address *src_addr, address *dst_addr, int src_port, int dst_port)
1425 const char *ip_version = src_addr->type == AT_IPv6 ? "v6" : "";
1426 char src_addr_str[WS_INET6_ADDRSTRLEN];
1427 char dst_addr_str[WS_INET6_ADDRSTRLEN];
1429 address_to_str_buf(src_addr, src_addr_str, sizeof(src_addr_str));
1430 address_to_str_buf(dst_addr, dst_addr_str, sizeof(dst_addr_str));
1432 return ws_strdup_printf("((ip%s.src eq %s and tcp.srcport eq %d) and "
1433 "(ip%s.dst eq %s and tcp.dstport eq %d))"
1434 " or "
1435 "((ip%s.src eq %s and tcp.srcport eq %d) and "
1436 "(ip%s.dst eq %s and tcp.dstport eq %d))",
1437 ip_version, src_addr_str, src_port,
1438 ip_version, dst_addr_str, dst_port,
1439 ip_version, dst_addr_str, dst_port,
1440 ip_version, src_addr_str, src_port);
1444 typedef struct tcp_follow_tap_data
1446 tvbuff_t *tvb;
1447 struct tcpheader* tcph;
1448 struct tcp_analysis *tcpd;
1450 } tcp_follow_tap_data_t;
1453 * Tries to apply segments from fragments list to the reconstructed payload.
1454 * Fragments that can be appended to the end of the payload will be applied (and
1455 * removed from the list). Fragments that should have been received (according
1456 * to the ack number) will also be appended to the payload (preceded by some
1457 * dummy data to mark packet loss if any).
1459 * Returns true if one fragment has been applied or false if no more fragments
1460 * can be added to the payload (there might still be unacked fragments with
1461 * missing segments before them).
1463 static bool
1464 check_follow_fragments(follow_info_t *follow_info, bool is_server, uint32_t acknowledged, uint32_t packet_num, bool use_ack)
1466 GList *fragment_entry;
1467 follow_record_t *fragment, *follow_record;
1468 uint32_t lowest_seq = 0;
1469 char *dummy_str;
1471 fragment_entry = g_list_first(follow_info->fragments[is_server]);
1472 if (fragment_entry == NULL)
1473 return false;
1475 fragment = (follow_record_t*)fragment_entry->data;
1476 lowest_seq = fragment->seq;
1478 for (; fragment_entry != NULL; fragment_entry = g_list_next(fragment_entry))
1480 fragment = (follow_record_t*)fragment_entry->data;
1482 if( GT_SEQ(lowest_seq, fragment->seq) ) {
1483 lowest_seq = fragment->seq;
1486 if( LT_SEQ(fragment->seq, follow_info->seq[is_server]) ) {
1487 uint32_t newseq;
1488 /* this sequence number seems dated, but
1489 check the end to make sure it has no more
1490 info than we have already seen */
1491 newseq = fragment->seq + fragment->data->len;
1492 if( GT_SEQ(newseq, follow_info->seq[is_server]) ) {
1493 uint32_t new_pos;
1495 /* this one has more than we have seen. let's get the
1496 payload that we have not seen. This happens when
1497 part of this frame has been retransmitted */
1499 new_pos = follow_info->seq[is_server] - fragment->seq;
1501 if ( fragment->data->len > new_pos ) {
1502 uint32_t new_frag_size = fragment->data->len - new_pos;
1504 follow_record = g_new0(follow_record_t,1);
1506 follow_record->is_server = is_server;
1507 follow_record->packet_num = fragment->packet_num;
1508 follow_record->abs_ts = fragment->abs_ts;
1509 follow_record->seq = follow_info->seq[is_server] + new_frag_size;
1511 follow_record->data = g_byte_array_append(g_byte_array_new(),
1512 fragment->data->data + new_pos,
1513 new_frag_size);
1515 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
1518 follow_info->seq[is_server] += (fragment->data->len - new_pos);
1521 /* Remove the fragment from the list as the "new" part of it
1522 * has been processed or its data has been seen already in
1523 * another packet. */
1524 g_byte_array_free(fragment->data, true);
1525 g_free(fragment);
1526 follow_info->fragments[is_server] = g_list_delete_link(follow_info->fragments[is_server], fragment_entry);
1527 return true;
1530 if( EQ_SEQ(fragment->seq, follow_info->seq[is_server]) ) {
1531 /* this fragment fits the stream */
1532 if( fragment->data->len > 0 ) {
1533 follow_info->payload = g_list_prepend(follow_info->payload, fragment);
1536 follow_info->seq[is_server] += fragment->data->len;
1537 follow_info->fragments[is_server] = g_list_delete_link(follow_info->fragments[is_server], fragment_entry);
1538 return true;
1542 if( use_ack && GT_SEQ(acknowledged, lowest_seq) ) {
1543 /* There are frames missing in the capture file that were seen
1544 * by the receiving host. Add dummy stream chunk with the data
1545 * "[xxx bytes missing in capture file]".
1547 dummy_str = ws_strdup_printf("[%d bytes missing in capture file]",
1548 (int)(lowest_seq - follow_info->seq[is_server]) );
1549 // XXX the dummy replacement could be larger than the actual missing bytes.
1551 follow_record = g_new0(follow_record_t,1);
1553 follow_record->data = g_byte_array_append(g_byte_array_new(),
1554 (unsigned char*)dummy_str,
1555 (unsigned)strlen(dummy_str)+1);
1556 g_free(dummy_str);
1557 follow_record->is_server = is_server;
1558 follow_record->packet_num = packet_num;
1559 follow_record->seq = lowest_seq;
1561 follow_info->seq[is_server] = lowest_seq;
1562 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
1563 return true;
1566 return false;
1569 static tap_packet_status
1570 follow_tcp_tap_listener(void *tapdata, packet_info *pinfo,
1571 epan_dissect_t *edt _U_, const void *data, tap_flags_t flags _U_)
1573 follow_record_t *follow_record;
1574 follow_info_t *follow_info = (follow_info_t *)tapdata;
1575 const tcp_follow_tap_data_t *follow_data = (const tcp_follow_tap_data_t *)data;
1576 bool is_server;
1577 uint32_t sequence = follow_data->tcph->th_seq;
1578 uint32_t length = follow_data->tcph->th_have_seglen
1579 ? follow_data->tcph->th_seglen
1580 : 0;
1581 uint32_t data_offset = 0;
1582 uint32_t data_length = tvb_captured_length(follow_data->tvb);
1584 if (follow_data->tcph->th_flags & TH_SYN) {
1585 sequence++;
1588 if (follow_info->client_port == 0) {
1589 follow_info->client_port = pinfo->srcport;
1590 copy_address(&follow_info->client_ip, &pinfo->src);
1591 follow_info->server_port = pinfo->destport;
1592 copy_address(&follow_info->server_ip, &pinfo->dst);
1595 is_server = !(addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport);
1597 /* Check whether this frame ACKs fragments in flow from the other direction.
1598 * This happens when frames are not in the capture file, but were actually
1599 * seen by the receiving host (Fixes bug 592).
1601 if (follow_info->fragments[!is_server] != NULL) {
1602 while (check_follow_fragments(follow_info, !is_server, follow_data->tcph->th_ack, pinfo->fd->num, true));
1606 * If this is the first segment of this stream, initialize the next expected
1607 * sequence number. If there is any data, it will be added below.
1609 if (follow_info->bytes_written[is_server] == 0 && follow_info->seq[is_server] == 0) {
1610 follow_info->seq[is_server] = sequence;
1613 /* We have already seen this src (and received some segments), let's figure
1614 * out whether this segment extends the stream or overlaps a previous gap. */
1615 if (LT_SEQ(sequence, follow_info->seq[is_server])) {
1616 /* This sequence number seems dated, but check the end in case it was a
1617 * retransmission with more data. */
1618 uint32_t nextseq = sequence + length;
1619 if (GT_SEQ(nextseq, follow_info->seq[is_server])) {
1620 /* The begin of the segment was already seen, try to add the
1621 * remaining data that we have not seen to the payload. */
1622 data_offset = follow_info->seq[is_server] - sequence;
1623 if (data_length <= data_offset) {
1624 data_length = 0;
1625 } else {
1626 data_length -= data_offset;
1629 sequence = follow_info->seq[is_server];
1630 length = nextseq - follow_info->seq[is_server];
1634 * Ignore segments that have no new data (either because it was empty, or
1635 * because it was fully overlapping with previously received data).
1637 if (data_length == 0 || LT_SEQ(sequence, follow_info->seq[is_server])) {
1638 return TAP_PACKET_DONT_REDRAW;
1641 follow_record = g_new0(follow_record_t, 1);
1642 follow_record->is_server = is_server;
1643 follow_record->packet_num = pinfo->fd->num;
1644 follow_record->abs_ts = pinfo->fd->abs_ts;
1645 follow_record->seq = sequence; /* start of fragment, used by check_follow_fragments. */
1646 follow_record->data = g_byte_array_append(g_byte_array_new(),
1647 tvb_get_ptr(follow_data->tvb, data_offset, data_length),
1648 data_length);
1650 if (EQ_SEQ(sequence, follow_info->seq[is_server])) {
1651 /* The segment overlaps or extends the previous end of stream. */
1652 follow_info->seq[is_server] += length;
1653 follow_info->bytes_written[is_server] += follow_record->data->len;
1654 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
1656 /* done with the packet, see if it caused a fragment to fit */
1657 while(check_follow_fragments(follow_info, is_server, 0, pinfo->fd->num, false));
1658 } else {
1659 /* Out of order packet (more preceding segments are expected). */
1660 follow_info->fragments[is_server] = g_list_append(follow_info->fragments[is_server], follow_record);
1662 return TAP_PACKET_DONT_REDRAW;
1665 #define EXP_PDU_TCP_INFO_DATA_LEN 20
1666 #define EXP_PDU_TCP_INFO_VERSION 1
1667 #define EXP_PDU_TAG_TCP_STREAM_ID_LEN 4
1669 static int exp_pdu_tcp_dissector_data_size(packet_info *pinfo _U_, void* data _U_)
1671 return EXP_PDU_TCP_INFO_DATA_LEN+4;
1674 static int exp_pdu_tcp_dissector_data_populate_data(packet_info *pinfo _U_, void* data, uint8_t *tlv_buffer, uint32_t buffer_size _U_)
1676 struct tcpinfo* dissector_data = (struct tcpinfo*)data;
1678 phton16(&tlv_buffer[0], EXP_PDU_TAG_TCP_INFO_DATA);
1679 phton16(&tlv_buffer[2], EXP_PDU_TCP_INFO_DATA_LEN); /* tag length */
1680 phton16(&tlv_buffer[4], EXP_PDU_TCP_INFO_VERSION);
1681 phton32(&tlv_buffer[6], dissector_data->seq);
1682 phton32(&tlv_buffer[10], dissector_data->nxtseq);
1683 phton32(&tlv_buffer[14], dissector_data->lastackseq);
1684 tlv_buffer[18] = dissector_data->is_reassembled;
1685 phton16(&tlv_buffer[19], dissector_data->flags);
1686 phton16(&tlv_buffer[21], dissector_data->urgent_pointer);
1688 return exp_pdu_tcp_dissector_data_size(pinfo, data);
1691 static tvbuff_t*
1692 handle_export_pdu_check_desegmentation(packet_info *pinfo, tvbuff_t *tvb)
1694 /* Check to see if the tvb we're planning on exporting PDUs from was
1695 * dissected fully, or whether it requested further desegmentation.
1696 * This should only matter on the first pass (so in one-pass tshark.)
1698 if (pinfo->can_desegment > 0 && pinfo->desegment_len != 0) {
1699 /* Desegmentation was requested. How much did we desegment here?
1700 * The rest, presumably, will be handled in another frame.
1702 if (pinfo->desegment_offset == 0) {
1703 /* We couldn't, in fact, dissect any of it. */
1704 return NULL;
1706 tvb = tvb_new_subset_length(tvb, 0, pinfo->desegment_offset);
1708 return tvb;
1711 static void
1712 handle_export_pdu_dissection_table(packet_info *pinfo, tvbuff_t *tvb, uint32_t port, struct tcpinfo *tcpinfo)
1714 if (have_tap_listener(exported_pdu_tap)) {
1715 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);
1716 if (tvb == NULL) {
1717 return;
1719 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};
1720 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL};
1722 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {
1723 &exp_pdu_data_src_ip,
1724 &exp_pdu_data_dst_ip,
1725 &exp_pdu_data_port_type,
1726 &exp_pdu_data_src_port,
1727 &exp_pdu_data_dst_port,
1728 &exp_pdu_data_orig_frame_num,
1729 &exp_pdu_data_table_value,
1730 &exp_pdu_data_dissector_data,
1731 NULL
1734 exp_pdu_data_t *exp_pdu_data;
1736 exp_pdu_data_table_value.data = GUINT_TO_POINTER(port);
1737 exp_pdu_data_dissector_data.data = tcpinfo;
1739 exp_pdu_data = export_pdu_create_tags(pinfo, "tcp.port", EXP_PDU_TAG_DISSECTOR_TABLE_NAME, tcp_exp_pdu_items);
1740 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
1741 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
1742 exp_pdu_data->pdu_tvb = tvb;
1744 /* match uint is restored after calling dissector, so in order to have the right value in exported PDU
1745 * we need to set it here.
1747 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
1751 static void
1752 handle_export_pdu_heuristic(packet_info *pinfo, tvbuff_t *tvb, heur_dtbl_entry_t *hdtbl_entry, struct tcpinfo *tcpinfo)
1754 exp_pdu_data_t *exp_pdu_data = NULL;
1756 if (have_tap_listener(exported_pdu_tap)) {
1757 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);
1758 if (tvb == NULL) {
1759 return;
1761 if ((!hdtbl_entry->enabled) ||
1762 (hdtbl_entry->protocol != NULL && !proto_is_protocol_enabled(hdtbl_entry->protocol))) {
1763 exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME);
1764 } else if (hdtbl_entry->protocol != NULL) {
1765 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL};
1766 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {
1767 &exp_pdu_data_src_ip,
1768 &exp_pdu_data_dst_ip,
1769 &exp_pdu_data_port_type,
1770 &exp_pdu_data_src_port,
1771 &exp_pdu_data_dst_port,
1772 &exp_pdu_data_orig_frame_num,
1773 &exp_pdu_data_dissector_data,
1774 NULL
1777 exp_pdu_data_dissector_data.data = tcpinfo;
1779 exp_pdu_data = export_pdu_create_tags(pinfo, hdtbl_entry->short_name, EXP_PDU_TAG_HEUR_DISSECTOR_NAME, tcp_exp_pdu_items);
1782 if (exp_pdu_data != NULL) {
1783 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
1784 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
1785 exp_pdu_data->pdu_tvb = tvb;
1787 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
1792 static void
1793 handle_export_pdu_conversation(packet_info *pinfo, tvbuff_t *tvb, int src_port, int dst_port, struct tcpinfo *tcpinfo)
1795 if (have_tap_listener(exported_pdu_tap)) {
1796 tvb = handle_export_pdu_check_desegmentation(pinfo, tvb);
1797 if (tvb == NULL) {
1798 return;
1800 conversation_t *conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, src_port, dst_port, 0);
1801 if (conversation != NULL)
1803 dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num);
1804 if (handle != NULL)
1806 exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL};
1807 const exp_pdu_data_item_t *tcp_exp_pdu_items[] = {
1808 &exp_pdu_data_src_ip,
1809 &exp_pdu_data_dst_ip,
1810 &exp_pdu_data_port_type,
1811 &exp_pdu_data_src_port,
1812 &exp_pdu_data_dst_port,
1813 &exp_pdu_data_orig_frame_num,
1814 &exp_pdu_data_dissector_data,
1815 NULL
1818 exp_pdu_data_t *exp_pdu_data;
1820 exp_pdu_data_dissector_data.data = tcpinfo;
1822 exp_pdu_data = export_pdu_create_tags(pinfo, dissector_handle_get_dissector_name(handle), EXP_PDU_TAG_DISSECTOR_NAME, tcp_exp_pdu_items);
1823 exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
1824 exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
1825 exp_pdu_data->pdu_tvb = tvb;
1827 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
1834 * display the TCP Conversation Completeness
1835 * we of course pay much attention on complete conversations but also incomplete ones which
1836 * have a regular start, as in practice we are often looking for such thing
1838 static void conversation_completeness_fill(char *buf, uint32_t value)
1840 switch(value) {
1841 case TCP_COMPLETENESS_SYNSENT:
1842 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete, SYN_SENT (%u)", value);
1843 break;
1844 case (TCP_COMPLETENESS_SYNSENT|
1845 TCP_COMPLETENESS_SYNACK):
1846 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete, CLIENT_ESTABLISHED (%u)", value);
1847 break;
1848 case (TCP_COMPLETENESS_SYNSENT|
1849 TCP_COMPLETENESS_SYNACK|
1850 TCP_COMPLETENESS_ACK):
1851 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete, ESTABLISHED (%u)", value);
1852 break;
1853 case (TCP_COMPLETENESS_SYNSENT|
1854 TCP_COMPLETENESS_SYNACK|
1855 TCP_COMPLETENESS_ACK|
1856 TCP_COMPLETENESS_DATA):
1857 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete, DATA (%u)", value);
1858 break;
1859 case (TCP_COMPLETENESS_SYNSENT|
1860 TCP_COMPLETENESS_SYNACK|
1861 TCP_COMPLETENESS_ACK|
1862 TCP_COMPLETENESS_DATA|
1863 TCP_COMPLETENESS_FIN):
1864 case (TCP_COMPLETENESS_SYNSENT|
1865 TCP_COMPLETENESS_SYNACK|
1866 TCP_COMPLETENESS_ACK|
1867 TCP_COMPLETENESS_DATA|
1868 TCP_COMPLETENESS_RST):
1869 case (TCP_COMPLETENESS_SYNSENT|
1870 TCP_COMPLETENESS_SYNACK|
1871 TCP_COMPLETENESS_ACK|
1872 TCP_COMPLETENESS_DATA|
1873 TCP_COMPLETENESS_FIN|
1874 TCP_COMPLETENESS_RST):
1875 snprintf(buf, ITEM_LABEL_LENGTH, "Complete, WITH_DATA (%u)", value);
1876 break;
1877 case (TCP_COMPLETENESS_SYNSENT|
1878 TCP_COMPLETENESS_SYNACK|
1879 TCP_COMPLETENESS_ACK|
1880 TCP_COMPLETENESS_FIN):
1881 case (TCP_COMPLETENESS_SYNSENT|
1882 TCP_COMPLETENESS_SYNACK|
1883 TCP_COMPLETENESS_ACK|
1884 TCP_COMPLETENESS_RST):
1885 case (TCP_COMPLETENESS_SYNSENT|
1886 TCP_COMPLETENESS_SYNACK|
1887 TCP_COMPLETENESS_ACK|
1888 TCP_COMPLETENESS_FIN|
1889 TCP_COMPLETENESS_RST):
1890 snprintf(buf, ITEM_LABEL_LENGTH, "Complete, NO_DATA (%u)", value);
1891 break;
1892 default:
1893 snprintf(buf, ITEM_LABEL_LENGTH, "Incomplete (%u)", value);
1894 break;
1898 /* TCP structs and definitions */
1900 /* **************************************************************************
1901 * RTT, relative sequence numbers, window scaling & etc.
1902 * **************************************************************************/
1903 static bool tcp_analyze_seq = true;
1904 static bool tcp_relative_seq = true;
1905 static bool tcp_track_bytes_in_flight = true;
1906 static bool tcp_bif_seq_based;
1907 static bool tcp_calculate_ts = true;
1909 static bool tcp_analyze_mptcp = true;
1910 static bool mptcp_relative_seq = true;
1911 static bool mptcp_analyze_mappings;
1912 static bool mptcp_intersubflows_retransmission;
1915 #define TCP_A_RETRANSMISSION 0x0001
1916 #define TCP_A_LOST_PACKET 0x0002
1917 #define TCP_A_ACK_LOST_PACKET 0x0004
1918 #define TCP_A_KEEP_ALIVE 0x0008
1919 #define TCP_A_DUPLICATE_ACK 0x0010
1920 #define TCP_A_ZERO_WINDOW 0x0020
1921 #define TCP_A_ZERO_WINDOW_PROBE 0x0040
1922 #define TCP_A_ZERO_WINDOW_PROBE_ACK 0x0080
1923 #define TCP_A_KEEP_ALIVE_ACK 0x0100
1924 #define TCP_A_OUT_OF_ORDER 0x0200
1925 #define TCP_A_FAST_RETRANSMISSION 0x0400
1926 #define TCP_A_WINDOW_UPDATE 0x0800
1927 #define TCP_A_WINDOW_FULL 0x1000
1928 #define TCP_A_REUSED_PORTS 0x2000
1929 #define TCP_A_SPURIOUS_RETRANSMISSION 0x4000
1931 /* This flag for desegment_tcp to exclude segments with previously
1932 * seen sequence numbers.
1933 * It is from the perspective of Wireshark's reassembler, whereas
1934 * the other flags above are from the perspective of the sender.
1935 * (E.g., TCP_A_RETRANSMISSION or TCP_A_SPURIOUS_RETRANSMISSION
1936 * can be set even when first appearance in the capture file.)
1938 #define TCP_A_OLD_DATA 0x8000
1940 /* Static TCP flags. Set in tcp_flow_t:static_flags */
1941 #define TCP_S_BASE_SEQ_SET 0x01
1942 #define TCP_S_SAW_SYN 0x03
1943 #define TCP_S_SAW_SYNACK 0x05
1946 /* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */
1947 #define MPTCP_META_HAS_BASE_DSN_MSB 0x01
1948 #define MPTCP_META_HAS_KEY 0x03
1949 #define MPTCP_META_HAS_TOKEN 0x04
1950 #define MPTCP_META_HAS_ADDRESSES 0x08
1952 /* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */
1953 #define MPTCP_SUBFLOW_HAS_NONCE 0x01
1954 #define MPTCP_SUBFLOW_HAS_ADDRESS_ID 0x02
1956 /* MPTCP meta analysis related */
1957 #define MPTCP_META_CHECKSUM_REQUIRED 0x0002
1959 /* if we have no key for this connection, some conversion become impossible,
1960 * thus return false
1962 static
1963 bool
1964 mptcp_convert_dsn(uint64_t dsn, mptcp_meta_flow_t *meta, enum mptcp_dsn_conversion conv, bool relative, uint64_t *result ) {
1966 *result = dsn;
1968 /* if relative is set then we need the 64 bits version anyway
1969 * we assume no wrapping was done on the 32 lsb so this may be wrong for elephant flows
1971 if(conv == DSN_CONV_32_TO_64 || relative) {
1973 if(!(meta->static_flags & MPTCP_META_HAS_BASE_DSN_MSB)) {
1974 /* can't do those without the expected_idsn based on the key */
1975 return false;
1979 if(conv == DSN_CONV_32_TO_64) {
1980 *result = keep_32msb_of_uint64(meta->base_dsn) | dsn;
1983 if(relative) {
1984 *result -= meta->base_dsn;
1987 if(conv == DSN_CONV_64_TO_32) {
1988 *result = (uint32_t) *result;
1991 return true;
1995 static void
1996 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
1997 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
1998 uint32_t seq, uint32_t nxtseq, bool is_tcp_segment,
1999 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo);
2002 static struct tcp_analysis *
2003 init_tcp_conversation_data(packet_info *pinfo, int direction)
2005 struct tcp_analysis *tcpd;
2007 /* Initialize the tcp protocol data structure to add to the tcp conversation */
2008 tcpd=wmem_new0(wmem_file_scope(), struct tcp_analysis);
2009 tcpd->flow1.win_scale = (direction >= 0) ? pinfo->src_win_scale : pinfo->dst_win_scale;
2010 tcpd->flow1.window = UINT32_MAX;
2011 tcpd->flow1.multisegment_pdus=wmem_tree_new(wmem_file_scope());
2013 tcpd->flow2.window = UINT32_MAX;
2014 tcpd->flow2.win_scale = (direction >= 0) ? pinfo->dst_win_scale : pinfo->src_win_scale;
2015 tcpd->flow2.multisegment_pdus=wmem_tree_new(wmem_file_scope());
2017 if (tcp_reassemble_out_of_order) {
2018 tcpd->flow1.ooo_segments=wmem_list_new(wmem_file_scope());
2019 tcpd->flow2.ooo_segments=wmem_list_new(wmem_file_scope());
2022 /* Only allocate the data if its actually going to be analyzed */
2023 if (tcp_analyze_seq)
2025 tcpd->flow1.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t);
2026 tcpd->flow2.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t);
2028 /* Only allocate the data if its actually going to be displayed */
2029 if (tcp_display_process_info)
2031 tcpd->flow1.process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t);
2032 tcpd->flow2.process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t);
2035 tcpd->acked_table=wmem_tree_new(wmem_file_scope());
2036 tcpd->ts_first.secs=pinfo->abs_ts.secs;
2037 tcpd->ts_first.nsecs=pinfo->abs_ts.nsecs;
2038 nstime_set_zero(&tcpd->ts_mru_syn);
2039 nstime_set_zero(&tcpd->ts_first_rtt);
2040 tcpd->ts_prev.secs=pinfo->abs_ts.secs;
2041 tcpd->ts_prev.nsecs=pinfo->abs_ts.nsecs;
2042 tcpd->flow1.valid_bif = true;
2043 tcpd->flow2.valid_bif = true;
2044 tcpd->flow1.push_bytes_sent = 0;
2045 tcpd->flow2.push_bytes_sent = 0;
2046 tcpd->flow1.push_set_last = false;
2047 tcpd->flow2.push_set_last = false;
2048 tcpd->flow1.closing_initiator = false;
2049 tcpd->flow2.closing_initiator = false;
2050 tcpd->stream = tcp_stream_count++;
2051 tcpd->server_port = 0;
2052 tcpd->tfo_syn_data = false;
2053 tcpd->flow_direction = 0;
2054 tcpd->flow1.flow_count = 0;
2055 tcpd->flow2.flow_count = 0;
2057 return tcpd;
2060 /* setup meta as well */
2061 static void
2062 mptcp_init_subflow(tcp_flow_t *flow)
2064 struct mptcp_subflow *sf = wmem_new0(wmem_file_scope(), struct mptcp_subflow);
2066 DISSECTOR_ASSERT(flow->mptcp_subflow == 0);
2067 flow->mptcp_subflow = sf;
2068 sf->ssn2dsn_mappings = wmem_itree_new(wmem_file_scope());
2069 sf->dsn2packet_map = wmem_itree_new(wmem_file_scope());
2073 /* add a new subflow to an mptcp connection */
2074 static void
2075 mptcp_attach_subflow(struct mptcp_analysis* mptcpd, struct tcp_analysis* tcpd) {
2077 if(!wmem_list_find(mptcpd->subflows, tcpd)) {
2078 wmem_list_prepend(mptcpd->subflows, tcpd);
2081 /* in case we merge 2 mptcp connections */
2082 tcpd->mptcp_analysis = mptcpd;
2085 struct tcp_analysis *
2086 get_tcp_conversation_data_idempotent(conversation_t *conv)
2088 struct tcp_analysis *tcpd;
2090 /* Get the data for this conversation */
2091 tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
2093 return tcpd;
2096 struct tcp_analysis *
2097 get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)
2099 int direction;
2100 struct tcp_analysis *tcpd;
2101 bool clear_ta = true;
2103 /* Did the caller supply the conversation pointer? */
2104 if( conv==NULL ) {
2105 /* If the caller didn't supply a conversation, don't
2106 * clear the analysis, it may be needed */
2107 clear_ta = false;
2108 conv = find_or_create_conversation(pinfo);
2111 /* Get the data for this conversation */
2112 tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
2114 direction = cmp_address(&pinfo->src, &pinfo->dst);
2115 /* if the addresses are equal, match the ports instead */
2116 if (direction == 0) {
2117 direction = (pinfo->srcport > pinfo->destport) ? 1 : -1;
2119 /* If the conversation was just created or it matched a
2120 * conversation with template options, tcpd will not
2121 * have been initialized. So, initialize
2122 * a new tcpd structure for the conversation.
2124 if (!tcpd) {
2125 tcpd = init_tcp_conversation_data(pinfo, direction);
2126 conversation_add_proto_data(conv, proto_tcp, tcpd);
2129 if (!tcpd) {
2130 return NULL;
2133 /* check direction and get ua lists */
2134 if(direction>=0) {
2135 tcpd->fwd=&(tcpd->flow1);
2136 tcpd->rev=&(tcpd->flow2);
2137 } else {
2138 tcpd->fwd=&(tcpd->flow2);
2139 tcpd->rev=&(tcpd->flow1);
2142 if (clear_ta) {
2143 tcpd->ta=NULL;
2145 return tcpd;
2148 /* Attach process info to a flow */
2149 /* XXX - We depend on the TCP dissector finding the conversation first */
2150 void
2151 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) {
2152 conversation_t *conv;
2153 struct tcp_analysis *tcpd;
2154 tcp_flow_t *flow = NULL;
2156 if (!tcp_display_process_info)
2157 return;
2159 conv = find_conversation(frame_num, local_addr, remote_addr, CONVERSATION_TCP, local_port, remote_port, 0);
2160 if (!conv) {
2161 return;
2164 tcpd = (struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
2165 if (!tcpd) {
2166 return;
2169 if (cmp_address(local_addr, conversation_key_addr1(conv->key_ptr)) == 0 && local_port == conversation_key_port1(conv->key_ptr)) {
2170 flow = &tcpd->flow1;
2171 } else if (cmp_address(remote_addr, conversation_key_addr1(conv->key_ptr)) == 0 && remote_port == conversation_key_port1(conv->key_ptr)) {
2172 flow = &tcpd->flow2;
2174 if (!flow || (flow->process_info && flow->process_info->command)) {
2175 return;
2178 if (flow->process_info == NULL)
2179 flow->process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t);
2181 flow->process_info->process_uid = uid;
2182 flow->process_info->process_pid = pid;
2183 flow->process_info->username = wmem_strdup(wmem_file_scope(), username);
2184 flow->process_info->command = wmem_strdup(wmem_file_scope(), command);
2187 /* Return the current stream count */
2188 uint32_t get_tcp_stream_count(void)
2190 return tcp_stream_count;
2193 /* Return the mptcp current stream count */
2194 uint32_t get_mptcp_stream_count(void)
2196 return mptcp_stream_count;
2199 /* Calculate the timestamps relative to this conversation */
2200 static void
2201 tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
2202 struct tcp_per_packet_data_t *tcppd)
2204 if( !tcppd ) {
2205 tcppd = wmem_new(wmem_file_scope(), struct tcp_per_packet_data_t);
2206 p_add_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num, tcppd);
2209 if (!tcpd)
2210 return;
2212 /* pre-increment so packet numbers start at 1 */
2213 tcppd->pnum = ++tcpd->pnum;
2215 nstime_delta(&tcppd->ts_del, &pinfo->abs_ts, &tcpd->ts_prev);
2216 tcppd->tcp_snd_manual_analysis = 0;
2218 tcpd->ts_prev.secs=pinfo->abs_ts.secs;
2219 tcpd->ts_prev.nsecs=pinfo->abs_ts.nsecs;
2222 /* Add a subtree with the timestamps relative to this conversation */
2223 static void
2224 tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
2226 proto_item *item;
2227 proto_tree *tree;
2228 nstime_t ts;
2230 if (!tcpd)
2231 return;
2233 tree=proto_tree_add_subtree(parent_tree, tvb, 0, 0, ett_tcp_timestamps, &item, "Timestamps");
2234 proto_item_set_generated(item);
2236 nstime_delta(&ts, &pinfo->abs_ts, &tcpd->ts_first);
2237 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);
2238 proto_item_set_generated(item);
2240 if( !tcppd )
2241 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
2243 if( tcppd ) {
2244 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,
2245 &tcppd->ts_del);
2246 proto_item_set_generated(item);
2250 static void
2251 print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)
2253 proto_item *item;
2255 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);
2256 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
2257 tvb, 0, 0, msp->first_frame);
2258 proto_item_set_generated(item);
2261 /* if we know that a PDU starts inside this segment, return the adjusted
2262 offset to where that PDU starts or just return offset back
2263 and let TCP try to find out what it can about this segment
2265 static int
2266 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)
2268 struct tcp_multisegment_pdu *msp=NULL;
2270 if(!pinfo->fd->visited) {
2271 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);
2272 if(msp) {
2273 /* If this is a continuation of a PDU started in a
2274 * previous segment we need to update the last_frame
2275 * variables.
2277 if(seq>msp->seq && seq<msp->nxtpdu) {
2278 msp->last_frame=pinfo->num;
2279 msp->last_frame_time=pinfo->abs_ts;
2280 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
2283 /* If this segment is completely within a previous PDU
2284 * then we just skip this packet
2286 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {
2287 return -1;
2289 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {
2290 offset+=msp->nxtpdu-seq;
2291 return offset;
2295 } else {
2296 /* First we try to find the start and transfer time for a PDU.
2297 * We only print this for the very first segment of a PDU
2298 * and only for PDUs spanning multiple segments.
2299 * Se we look for if there was any multisegment PDU started
2300 * just BEFORE the end of this segment. I.e. either inside this
2301 * segment or in a previous segment.
2302 * Since this might also match PDUs that are completely within
2303 * this segment we also verify that the found PDU does span
2304 * beyond the end of this segment.
2306 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, nxtseq-1);
2307 if(msp) {
2308 if(pinfo->num==msp->first_frame) {
2309 proto_item *item;
2310 nstime_t ns;
2312 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);
2313 proto_item_set_generated(item);
2315 nstime_delta(&ns, &msp->last_frame_time, &pinfo->abs_ts);
2316 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,
2317 tvb, 0, 0, &ns);
2318 proto_item_set_generated(item);
2322 /* Second we check if this segment is part of a PDU started
2323 * prior to the segment (seq-1)
2325 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);
2326 if(msp) {
2327 /* If this segment is completely within a previous PDU
2328 * then we just skip this packet
2330 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {
2331 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
2332 return -1;
2335 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {
2336 offset+=msp->nxtpdu-seq;
2337 return offset;
2342 return offset;
2345 /* if we saw a PDU that extended beyond the end of the segment,
2346 use this function to remember where the next pdu starts
2348 struct tcp_multisegment_pdu *
2349 pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, uint32_t seq, uint32_t nxtpdu, wmem_tree_t *multisegment_pdus)
2351 struct tcp_multisegment_pdu *msp;
2353 msp=wmem_new(wmem_file_scope(), struct tcp_multisegment_pdu);
2354 msp->nxtpdu=nxtpdu;
2355 msp->seq=seq;
2356 msp->first_frame=pinfo->num;
2357 msp->first_frame_with_seq=pinfo->num;
2358 msp->last_frame=pinfo->num;
2359 msp->last_frame_time=pinfo->abs_ts;
2360 msp->flags=0;
2361 wmem_tree_insert32(multisegment_pdus, seq, (void *)msp);
2362 /*ws_warning("pdu_store_sequencenumber_of_next_pdu: seq %u", seq);*/
2363 return msp;
2366 /* This is called for SYN and SYN+ACK packets and the purpose is to verify
2367 * that we have seen window scaling in both directions.
2368 * If we can't find window scaling being set in both directions
2369 * that means it was present in the SYN but not in the SYN+ACK
2370 * (or the SYN was missing) and then we disable the window scaling
2371 * for this tcp session.
2373 static void
2374 verify_tcp_window_scaling(bool is_synack, struct tcp_analysis *tcpd)
2376 if( tcpd->fwd->win_scale==-1 ) {
2377 /* We know window scaling will not be used as:
2378 * a) this is the SYN and it does not have the WS option
2379 * (we set the reverse win_scale also in case we miss
2380 * the SYN/ACK)
2381 * b) this is the SYN/ACK and either the SYN packet has not
2382 * been seen or it did have the WS option. As the SYN/ACK
2383 * does not have the WS option, window scaling will not be used.
2385 * Setting win_scale to -2 to indicate that we can
2386 * trust the window_size value in the TCP header.
2388 tcpd->fwd->win_scale = -2;
2389 tcpd->rev->win_scale = -2;
2391 } else if( is_synack && tcpd->rev->win_scale==-2 ) {
2392 /* The SYN/ACK has the WS option, while the SYN did not,
2393 * this should not happen, but the endpoints will not
2394 * have used window scaling, so we will neither
2396 tcpd->fwd->win_scale = -2;
2400 /* given a tcpd, returns the mptcp_subflow that sides with meta */
2401 static struct mptcp_subflow *
2402 mptcp_select_subflow_from_meta(const struct tcp_analysis *tcpd, const mptcp_meta_flow_t *meta)
2404 /* select the tcp_flow with appropriate direction */
2405 if( tcpd->flow1.mptcp_subflow->meta == meta) {
2406 return tcpd->flow1.mptcp_subflow;
2408 else {
2409 return tcpd->flow2.mptcp_subflow;
2413 /* if we saw a window scaling option, store it for future reference
2415 static void
2416 pdu_store_window_scale_option(uint8_t ws, struct tcp_analysis *tcpd)
2418 if (tcpd)
2419 tcpd->fwd->win_scale=ws;
2422 /* when this function returns, it will (if createflag) populate the ta pointer.
2424 static void
2425 tcp_analyze_get_acked_struct(uint32_t frame, uint32_t seq, uint32_t ack, bool createflag, struct tcp_analysis *tcpd)
2428 wmem_tree_key_t key[4];
2430 key[0].length = 1;
2431 key[0].key = &frame;
2433 key[1].length = 1;
2434 key[1].key = &seq;
2436 key[2].length = 1;
2437 key[2].key = &ack;
2439 key[3].length = 0;
2440 key[3].key = NULL;
2442 if (!tcpd) {
2443 return;
2446 tcpd->ta = (struct tcp_acked *)wmem_tree_lookup32_array(tcpd->acked_table, key);
2447 if((!tcpd->ta) && createflag) {
2448 tcpd->ta = wmem_new0(wmem_file_scope(), struct tcp_acked);
2449 wmem_tree_insert32_array(tcpd->acked_table, key, (void *)tcpd->ta);
2455 /* fwd contains a list of all segments processed but not yet ACKed in the
2456 * same direction as the current segment.
2457 * rev contains a list of all segments received but not yet ACKed in the
2458 * opposite direction to the current segment.
2460 * New segments are always added to the head of the fwd/rev lists.
2462 * Changes below should be synced with ChAdvTCPAnalysis in the User's
2463 * Guide: doc/wsug_src/WSUG_chapter_advanced.adoc
2465 static void
2466 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)
2468 tcp_unacked_t *ual=NULL;
2469 tcp_unacked_t *prevual=NULL;
2470 uint32_t nextseq;
2472 #if 0
2473 printf("\nanalyze_sequence numbers frame:%u\n",pinfo->num);
2474 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);
2475 for(ual=tcpd->fwd->tcp_analyze_seq_info->segments; ual; ual=ual->next)
2476 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);
2477 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);
2478 for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next)
2479 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);
2480 #endif
2482 if (!tcpd) {
2483 return;
2486 if( flags & TH_ACK ) {
2487 tcpd->rev->valid_bif = 1;
2490 /* ZERO WINDOW PROBE
2491 * it is a zero window probe if
2492 * the sequence number is the next expected one
2493 * the window in the other direction is 0
2494 * the segment is exactly 1 byte
2496 if( seglen==1
2497 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2498 && tcpd->rev->window==0 ) {
2499 if(!tcpd->ta) {
2500 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2502 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
2503 goto finished_fwd;
2507 /* ZERO WINDOW
2508 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
2510 if( window==0
2511 && (flags&(TH_RST|TH_FIN|TH_SYN))==0 ) {
2512 if(!tcpd->ta) {
2513 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2515 tcpd->ta->flags|=TCP_A_ZERO_WINDOW;
2519 /* LOST PACKET
2520 * If this segment is beyond the last seen nextseq we must
2521 * have missed some previous segment
2523 * We only check for this if we have actually seen segments prior to this
2524 * one.
2525 * RST packets are not checked for this.
2527 if( tcpd->fwd->tcp_analyze_seq_info->nextseq
2528 && GT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq)
2529 && (flags&(TH_RST))==0 ) {
2530 if(!tcpd->ta) {
2531 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2533 tcpd->ta->flags|=TCP_A_LOST_PACKET;
2535 /* Disable BiF until an ACK is seen in the other direction */
2536 tcpd->fwd->valid_bif = 0;
2540 /* KEEP ALIVE
2541 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
2542 * to what should be the next sequence number.
2543 * SYN/FIN/RST segments are never keepalives
2545 if( (seglen==0||seglen==1)
2546 && seq==(tcpd->fwd->tcp_analyze_seq_info->nextseq-1)
2547 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2548 if(!tcpd->ta) {
2549 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2551 tcpd->ta->flags|=TCP_A_KEEP_ALIVE;
2554 /* WINDOW UPDATE
2555 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
2556 * the previous seen segment and with a new window value
2558 if( seglen==0
2559 && window
2560 && window!=tcpd->fwd->window
2561 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2562 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
2563 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2564 if(!tcpd->ta) {
2565 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2567 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
2571 /* WINDOW FULL
2572 * If we know the window scaling
2573 * and if this segment contains data and goes all the way to the
2574 * edge of the advertised window
2575 * then we mark it as WINDOW FULL
2576 * SYN/RST/FIN packets are never WINDOW FULL
2578 if( seglen>0
2579 && tcpd->rev->win_scale!=-1
2580 && (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))))
2581 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2582 if(!tcpd->ta) {
2583 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2585 tcpd->ta->flags|=TCP_A_WINDOW_FULL;
2589 /* KEEP ALIVE ACK
2590 * It is a keepalive ack if it repeats the previous ACK and if
2591 * the last segment in the reverse direction was a keepalive
2593 if( seglen==0
2594 && window
2595 && window==tcpd->fwd->window
2596 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2597 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
2598 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
2599 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2600 if(!tcpd->ta) {
2601 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2603 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK;
2604 goto finished_fwd;
2608 /* ZERO WINDOW PROBE ACK
2609 * It is a zerowindowprobe ack if it repeats the previous ACK and if
2610 * the last segment in the reverse direction was a zerowindowprobe
2611 * It also repeats the previous zero window indication
2613 if( seglen==0
2614 && window==0
2615 && window==tcpd->fwd->window
2616 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2617 && (ack==tcpd->fwd->tcp_analyze_seq_info->lastack || EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1))
2618 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
2619 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2620 if(!tcpd->ta) {
2621 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2623 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
2625 /* Some receivers consume that extra byte brought in the PROBE,
2626 * but it was too early to know that during the WINDOW PROBE analysis.
2627 * Do it now by moving the rev nextseq & maxseqtobeacked.
2628 * See issue 10745.
2630 if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)) {
2631 tcpd->rev->tcp_analyze_seq_info->nextseq=ack;
2632 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
2634 goto finished_fwd;
2638 /* DUPLICATE ACK
2639 * It is a duplicate ack if window/seq/ack is the same as the previous
2640 * segment and if the segment length is 0
2642 if( seglen==0
2643 && window
2644 && window==tcpd->fwd->window
2645 && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq
2646 && ack==tcpd->fwd->tcp_analyze_seq_info->lastack
2647 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
2649 /* MPTCP tolerates duplicate acks in some circumstances, see RFC 8684 4. */
2650 if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) {
2651 /* just ignore this DUPLICATE ACK */
2652 } else {
2653 tcpd->fwd->tcp_analyze_seq_info->dupacknum++;
2655 if(!tcpd->ta) {
2656 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2658 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
2659 tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum;
2660 tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack;
2666 finished_fwd:
2667 /* If the ack number changed we must reset the dupack counters */
2668 if( ack != tcpd->fwd->tcp_analyze_seq_info->lastack ) {
2669 tcpd->fwd->tcp_analyze_seq_info->lastnondupack=pinfo->num;
2670 tcpd->fwd->tcp_analyze_seq_info->dupacknum=0;
2674 /* ACKED LOST PACKET
2675 * If this segment acks beyond the 'max seq to be acked' in the other direction
2676 * then that means we have missed packets going in the
2677 * other direction.
2678 * It might also indicate we are resuming from a Zero Window,
2679 * where a Probe is just followed by an ACK opening again the window.
2680 * See issue 8404.
2682 * We only check this if we have actually seen some seq numbers
2683 * in the other direction.
2685 if( tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked
2686 && GT_SEQ(ack, tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked )
2687 && (flags&(TH_ACK))!=0 ) {
2688 if(!tcpd->ta) {
2689 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2692 /* resuming from a Zero Window Probe which re-opens the window,
2693 * mark it as a Window Update
2695 if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)
2696 && (seq==tcpd->fwd->tcp_analyze_seq_info->nextseq)
2697 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE) ) {
2698 tcpd->rev->tcp_analyze_seq_info->nextseq=ack;
2699 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
2700 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
2702 /* real ACKED LOST PACKET */
2703 else {
2704 /* We ensure there is no matching packet waiting in the unacked list,
2705 * and take this opportunity to push the tail further than this single packet
2708 uint32_t tail_le = 0, tail_re = 0;
2709 for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next) {
2711 if(tail_le == tail_re) { /* init edge values */
2712 tail_le = ual->seq;
2713 tail_re = ual->nextseq;
2716 /* Only look at what happens above the current ACK value,
2717 * as what happened before is definetely ACKed here and can be
2718 * safely ignored. */
2719 if(GE_SEQ(ual->seq,ack)) {
2721 /* if the left edge is contiguous, move the tail leftward */
2722 if(EQ_SEQ(ual->nextseq,tail_le)) {
2723 tail_le = ual->seq;
2726 /* otherwise, we have isolated segments above what is being ACKed here,
2727 * and we reinit the tails with the current values */
2728 else {
2729 tail_le = ual->seq;
2730 tail_re = ual->nextseq; // move the end tail
2735 /* a tail was found and we can push the maxseqtobeacked further */
2736 if(EQ_SEQ(ack,tail_le) && GT_SEQ(tail_re, ack)) {
2737 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=tail_re;
2740 /* otherwise, just take into account the value being ACKed now */
2741 else {
2742 tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack;
2745 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
2750 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
2751 * If the segment contains data (or is a SYN or a FIN) and
2752 * if it does not advance the sequence number, it must be one
2753 * of these three.
2754 * Only test for this if we know what the seq number should be
2755 * (tcpd->fwd->nextseq)
2757 * Note that a simple KeepAlive is not a retransmission
2759 bool seq_not_advanced = tcpd->fwd->tcp_analyze_seq_info->nextseq
2760 && (LT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq));
2762 if (seglen>0 || flags&(TH_SYN|TH_FIN)) {
2764 uint64_t t;
2765 uint64_t ooo_thres;
2767 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ) {
2768 goto finished_checking_retransmission_type;
2771 /* This segment is *not* considered a retransmission/out-of-order if
2772 * the segment length is larger than one (it really adds new data)
2773 * the sequence number is one less than the previous nextseq and
2774 * (the previous segment is possibly a zero window probe)
2776 * We should still try to flag Spurious Retransmissions though.
2778 if (seglen > 1 && tcpd->fwd->tcp_analyze_seq_info->nextseq - 1 == seq) {
2779 seq_not_advanced = false;
2782 /* Check for spurious retransmission. If the current seq + segment length
2783 * is less than or equal to the current lastack, the packet contains
2784 * duplicate data and may be considered spurious.
2786 if ( seglen > 0
2787 && tcpd->rev->tcp_analyze_seq_info->lastack
2788 && LE_SEQ(seq + seglen, tcpd->rev->tcp_analyze_seq_info->lastack) ) {
2789 if(!tcpd->ta){
2790 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2792 tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION;
2793 goto finished_checking_retransmission_type;
2796 nextseq = seq+seglen;
2798 if(!seq_not_advanced)
2799 goto finished_checking_retransmission_type;
2801 /* Some OOO vs Retrans interpretations can be wrong when the capture needs a reorder.
2802 * Avoid such cases by enforcing the delta to 0 when the order seems bad, instead of
2803 * calculating an absurd value.
2805 if(pinfo->abs_ts.secs > tcpd->rev->tcp_analyze_seq_info->lastacktime.secs) {
2806 /* regular case */
2807 t = (pinfo->abs_ts.secs - tcpd->rev->tcp_analyze_seq_info->lastacktime.secs)*1000000000;
2808 t += pinfo->abs_ts.nsecs - tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs;
2810 else if( (pinfo->abs_ts.secs == tcpd->rev->tcp_analyze_seq_info->lastacktime.secs) &&
2811 (pinfo->abs_ts.nsecs > tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs) ) {
2812 t = pinfo->abs_ts.nsecs - tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs;
2814 else {
2815 t = 0;
2818 bool precedence_count = tcp_fastrt_precedence;
2819 do {
2820 if (precedence_count) {
2821 /* If there were >=2 duplicate ACKs in the reverse direction
2822 * (there might be duplicate acks missing from the trace)
2823 * and if this sequence number matches those ACKs
2824 * and if the packet occurs within 20ms of the last
2825 * duplicate ack
2826 * then this is a fast retransmission
2828 if( t<20000000
2829 && tcpd->rev->tcp_analyze_seq_info->dupacknum>=2
2830 && tcpd->rev->tcp_analyze_seq_info->lastack==seq) {
2831 if(!tcpd->ta) {
2832 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2834 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
2835 goto finished_checking_retransmission_type;
2838 /* Look for this segment in reported SACK ranges,
2839 * if not present this might very well be a FAST Retrans,
2840 * when the conditions above (timing, number of retrans) are still true */
2841 if( t<20000000
2842 && tcpd->rev->tcp_analyze_seq_info->dupacknum>=2
2843 && tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) {
2845 bool is_sacked = false;
2846 int i=0;
2847 while( !is_sacked && i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges ) {
2848 is_sacked = ((seq >= tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i])
2849 && (nextseq <= tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i]));
2850 i++;
2853 /* fine, it's probably a Fast Retrans triggered by the SACK sender algo */
2854 if(!is_sacked) {
2855 if(!tcpd->ta)
2856 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2857 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
2858 goto finished_checking_retransmission_type;
2862 precedence_count=!precedence_count;
2863 } else {
2864 /* If the segment came relatively close since the segment with the highest
2865 * seen sequence number and it doesn't look like a retransmission
2866 * then it is an OUT-OF-ORDER segment.
2868 if (tcpd->ts_first_rtt.nsecs == 0 && tcpd->ts_first_rtt.secs == 0) {
2869 ooo_thres = 3000000;
2870 } else {
2871 ooo_thres = tcpd->ts_first_rtt.nsecs + tcpd->ts_first_rtt.secs*1000000000;
2874 /* If the segment is already seen and waiting to be acknowledged, ignore the
2875 * Fast-Retrans/OOO debate and go ahead, as it only can be an ordinary Retrans.
2876 * Fast-Retrans/Retrans are never ambiguous in the context of packets seen but
2877 * this code could be moved above.
2878 * See Issues 13284, 13843
2879 * XXX: if compared packets have different sizes, it's not handled yet
2881 bool pk_already_seen = false;
2882 ual = tcpd->fwd->tcp_analyze_seq_info->segments;
2883 while(ual) {
2884 if(GE_SEQ(seq,ual->seq) && LE_SEQ(seq+seglen,ual->nextseq)) {
2885 pk_already_seen = true;
2886 break;
2888 ual=ual->next;
2891 if(t < ooo_thres && !pk_already_seen) {
2892 /* ordinary OOO with SEQ numbers and lengths clearly stating the situation */
2893 if( tcpd->fwd->tcp_analyze_seq_info->nextseq != (seq + seglen + (flags&(TH_SYN|TH_FIN) ? 1 : 0))) {
2894 if(!tcpd->ta) {
2895 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2898 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
2899 goto finished_checking_retransmission_type;
2901 else {
2902 /* facing an OOO closing a series of disordered packets,
2903 all preceded by a pure ACK. See issue 17214 */
2904 if(tcpd->fwd->tcp_analyze_seq_info->lastacklen == 0) {
2905 if(!tcpd->ta) {
2906 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2909 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
2910 goto finished_checking_retransmission_type;
2914 precedence_count=!precedence_count;
2916 } while (precedence_count!=tcp_fastrt_precedence) ;
2918 /* Then it has to be a generic retransmission */
2919 if(!tcpd->ta) {
2920 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
2922 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
2925 * worst case scenario: if we don't have better than a recent packet,
2926 * use it as the reference for RTO
2928 nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &tcpd->fwd->tcp_analyze_seq_info->nextseqtime);
2929 tcpd->ta->rto_frame=tcpd->fwd->tcp_analyze_seq_info->nextseqframe;
2932 * better case scenario: if we have a list of the previous unacked packets,
2933 * go back to the eldest one, which in theory is likely to be the one retransmitted here.
2934 * It's not always the perfect match, particularly when original captured packet used LSO
2935 * We may parse this list and try to find an obvious matching packet present in the
2936 * capture. If such packet is actually missing, we'll reach the list first entry.
2937 * See : issue #12259
2938 * See : issue #17714
2940 ual = tcpd->fwd->tcp_analyze_seq_info->segments;
2941 while(ual) {
2942 if(GE_SEQ(ual->seq, seq)) {
2943 nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &ual->ts );
2944 tcpd->ta->rto_frame=ual->frame;
2946 ual=ual->next;
2950 finished_checking_retransmission_type:
2952 /* Override the TCP sequence analysis with the value given
2953 * manually by the user. This only applies to flagged packets.
2955 if(tcppd && tcpd->ta &&
2956 (tcppd->tcp_snd_manual_analysis>0) &&
2957 (tcpd->ta->flags & TCP_A_RETRANSMISSION ||
2958 tcpd->ta->flags & TCP_A_OUT_OF_ORDER ||
2959 tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION ||
2960 tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION)) {
2962 /* clean flags set during the automatic analysis */
2963 tcpd->ta->flags &= ~(TCP_A_RETRANSMISSION|
2964 TCP_A_OUT_OF_ORDER|
2965 TCP_A_FAST_RETRANSMISSION|
2966 TCP_A_SPURIOUS_RETRANSMISSION);
2968 /* set the corresponding flag chosen by the user */
2969 switch(tcppd->tcp_snd_manual_analysis) {
2970 case 0:
2971 /* the user asked for an empty overriding, which
2972 * means removing any previous value, thus restoring
2973 * the automatic analysis.
2975 break;
2977 case 1:
2978 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
2979 break;
2981 case 2:
2982 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
2983 break;
2985 case 3:
2986 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
2987 break;
2989 case 4:
2990 tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION;
2991 break;
2993 default:
2994 /* there is no expected default case */
2995 break;
2999 nextseq = seq+seglen;
3000 if ((seglen || flags&(TH_SYN|TH_FIN)) && tcpd->fwd->tcp_analyze_seq_info->segment_count < TCP_MAX_UNACKED_SEGMENTS) {
3001 /* Add this new sequence number to the fwd list. But only if there
3002 * aren't "too many" unacked segments (e.g., we're not seeing the ACKs).
3004 ual = wmem_new(wmem_file_scope(), tcp_unacked_t);
3005 ual->next=tcpd->fwd->tcp_analyze_seq_info->segments;
3006 tcpd->fwd->tcp_analyze_seq_info->segments=ual;
3007 tcpd->fwd->tcp_analyze_seq_info->segment_count++;
3008 ual->frame=pinfo->num;
3009 ual->seq=seq;
3010 ual->ts=pinfo->abs_ts;
3012 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
3013 if( (flags&(TH_SYN|TH_FIN)) ) {
3014 nextseq+=1;
3016 ual->nextseq=nextseq;
3019 /* Every time we are moving the highest number seen,
3020 * we are also tracking the segment length then we will know for sure,
3021 * later, if this was a pure ACK or an ordinary data packet. */
3022 if(!tcpd->fwd->tcp_analyze_seq_info->nextseq
3023 || GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq + (flags&(TH_SYN|TH_FIN) ? 1 : 0))) {
3024 tcpd->fwd->tcp_analyze_seq_info->lastacklen=seglen;
3027 /* Store the highest number seen so far for nextseq so we can detect
3028 * when we receive segments that arrive with a "hole"
3029 * If we don't have anything since before, just store what we got.
3030 * ZeroWindowProbes are special and don't really advance the nextseq
3032 if(GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq) || !tcpd->fwd->tcp_analyze_seq_info->nextseq) {
3033 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
3034 tcpd->fwd->tcp_analyze_seq_info->nextseq=nextseq;
3035 tcpd->fwd->tcp_analyze_seq_info->nextseqframe=pinfo->num;
3036 tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs=pinfo->abs_ts.secs;
3037 tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs=pinfo->abs_ts.nsecs;
3039 /* Count the flows turns by checking all packets carrying real data
3040 * Packets not ordered are ignored.
3042 if((!tcpd->ta ) ||
3043 !(tcpd->ta->flags & TCP_A_RETRANSMISSION ||
3044 tcpd->ta->flags & TCP_A_OUT_OF_ORDER ||
3045 tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION ||
3046 tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION)) {
3048 if( seglen>0) {
3049 /* check direction */
3050 int8_t direction;
3051 direction=cmp_address(&pinfo->src, &pinfo->dst);
3053 /* if the addresses are equal, match the ports instead */
3054 if(direction==0) {
3055 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
3058 /* invert the direction and increment the counter */
3059 if(direction != tcpd->flow_direction) {
3060 tcpd->flow_direction = direction;
3061 tcpd->fwd->flow_count++;
3063 /* if the direction was not reversed, maybe are we
3064 * facing the first flow ? Yes, if the counter still equals 0.
3066 else {
3067 if(tcpd->fwd->flow_count==0) {
3068 tcpd->fwd->flow_count++;
3076 /* Store the highest continuous seq number seen so far for 'max seq to be acked',
3077 * so we can detect TCP_A_ACK_LOST_PACKET condition.
3078 * If this ever happens, this boundary value can "jump" further in order to
3079 * avoid duplicating multiple messages for the very same lost packet. See later
3080 * how ACKED LOST PACKET are handled.
3081 * Zero Window Probes are logically left out at this moment, but if their data
3082 * really were to be ack'ed, then it will be done later when analyzing their
3083 * Probe ACK (be it a real Probe ACK, or an ordinary ACK moving the RCV Window).
3085 if(EQ_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) || !tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) {
3086 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
3087 tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked=tcpd->fwd->tcp_analyze_seq_info->nextseq;
3092 /* remember what the ack/window is so we can track window updates and retransmissions */
3093 tcpd->fwd->window=window;
3094 tcpd->fwd->tcp_analyze_seq_info->lastack=ack;
3095 tcpd->fwd->tcp_analyze_seq_info->lastacktime.secs=pinfo->abs_ts.secs;
3096 tcpd->fwd->tcp_analyze_seq_info->lastacktime.nsecs=pinfo->abs_ts.nsecs;
3098 /* remember the MPTCP operations if any */
3099 if( tcpd->mptcp_analysis ) {
3100 tcpd->fwd->mp_operations=tcpd->mptcp_analysis->mp_operations;
3103 /* if there were any flags set for this segment we need to remember them
3104 * we only remember the flags for the very last segment though.
3106 if(tcpd->ta) {
3107 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;
3108 } else {
3109 tcpd->fwd->lastsegmentflags=0;
3113 /* remove all segments this ACKs and we don't need to keep around any more
3115 prevual = NULL;
3116 ual = tcpd->rev->tcp_analyze_seq_info->segments;
3117 while(ual) {
3118 tcp_unacked_t *tmpual;
3120 /* If this ack matches the segment, process accordingly */
3121 if(ack==ual->nextseq) {
3122 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
3123 tcpd->ta->frame_acked=ual->frame;
3124 nstime_delta(&tcpd->ta->ts, &pinfo->abs_ts, &ual->ts);
3125 /* mark it as a full segment ACK */
3126 tcpd->ta->partial_ack=0;
3128 /* If this acknowledges part of the segment, adjust the segment info for the acked part.
3129 * This typically happens in the context of GSO/GRO or Retransmissions with
3130 * segment repackaging (elsewhere called repacketization). For the user, looking at the
3131 * previous packets for any Retransmission or at the SYN MSS Option presence would
3132 * answer what case is precisely encountered.
3134 else if (GT_SEQ(ack, ual->seq) && LE_SEQ(ack, ual->nextseq)) {
3135 ual->seq = ack;
3136 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
3137 tcpd->ta->frame_acked=ual->frame;
3138 nstime_delta(&tcpd->ta->ts, &pinfo->abs_ts, &ual->ts);
3140 /* mark it as a partial segment ACK
3142 * XXX - This mark is used later to create an Expert Note,
3143 * but other ways of tracking these packets are possible:
3144 * for example a similar indication to ta->frame_acked
3145 * would help differentiating the SEQ/ACK analysis messages.
3146 * Also, a TCP Analysis Flag could be added, but doesn't seem
3147 * essential yet, as matching packets can be selected with
3148 * 'tcp.analysis.partial_ack'.
3150 tcpd->ta->partial_ack=1;
3151 continue;
3153 /* If this acknowledges a segment prior to this one, leave this segment alone and move on */
3154 else if (GT_SEQ(ual->nextseq,ack)) {
3155 prevual = ual;
3156 ual = ual->next;
3157 continue;
3160 /* This segment is old, or an exact match. Delete the segment from the list */
3161 tmpual=ual->next;
3163 if (tcpd->rev->scps_capable) {
3164 /* Track largest segment successfully sent for SNACK analysis*/
3165 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) {
3166 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);
3170 if (!prevual) {
3171 tcpd->rev->tcp_analyze_seq_info->segments = tmpual;
3173 else{
3174 prevual->next = tmpual;
3176 wmem_free(wmem_file_scope(), ual);
3177 ual = tmpual;
3178 tcpd->rev->tcp_analyze_seq_info->segment_count--;
3181 /* how many bytes of data are there in flight after this frame
3182 * was sent
3183 * The historical evaluation is done from the payload seen in the
3184 * segments captured. Another method deduced from the SEQ numbers
3185 * is introduced with issue 7703, but not used by default now. The
3186 * method is chosen by the user preference tcp_bif_seq_based.
3188 if(tcp_track_bytes_in_flight) {
3189 uint32_t in_flight, delivered = 0;
3191 * "don't repeat yourself" boolean, for the shared part
3192 * between both methods
3194 bool dry_bif_handling = false;
3197 * historical calculation method based on payloads, which is
3198 * by now still the default.
3200 if(!tcp_bif_seq_based) {
3201 ual=tcpd->fwd->tcp_analyze_seq_info->segments;
3203 if (seglen!=0 && ual && tcpd->fwd->valid_bif) {
3204 uint32_t first_seq, last_seq;
3206 dry_bif_handling = true;
3208 first_seq = ual->seq - tcpd->fwd->base_seq;
3209 last_seq = ual->nextseq - tcpd->fwd->base_seq;
3210 while (ual) {
3211 if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) {
3212 last_seq = ual->nextseq-tcpd->fwd->base_seq;
3214 if ((ual->seq-tcpd->fwd->base_seq)<first_seq) {
3215 first_seq = ual->seq-tcpd->fwd->base_seq;
3217 ual = ual->next;
3219 in_flight = last_seq-first_seq;
3221 } else { /* calculation based on SEQ numbers (see issue 7703) */
3222 if (seglen!=0 && tcpd->fwd->tcp_analyze_seq_info && tcpd->fwd->valid_bif) {
3224 dry_bif_handling = true;
3226 in_flight = tcpd->fwd->tcp_analyze_seq_info->nextseq
3227 - tcpd->rev->tcp_analyze_seq_info->lastack;
3230 if(dry_bif_handling) {
3231 /* subtract any SACK block */
3232 if(tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) {
3233 int i;
3234 for(i = 0; i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges; i++) {
3235 delivered += (tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i] -
3236 tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i]);
3238 in_flight -= delivered;
3241 if (in_flight>0 && in_flight<2000000000) {
3242 if(!tcpd->ta) {
3243 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, true, tcpd);
3245 tcpd->ta->bytes_in_flight = in_flight;
3246 /* Decrement in_flight bytes by one when we have a SYN or FIN bit
3247 * flag set as it is only virtual.
3249 if (flags&(TH_SYN|TH_FIN)) {
3250 tcpd->ta->bytes_in_flight -= 1;
3254 if((flags & TH_PUSH) && !tcpd->fwd->push_set_last) {
3255 tcpd->fwd->push_bytes_sent += seglen;
3256 tcpd->fwd->push_set_last = true;
3257 } else if ((flags & TH_PUSH) && tcpd->fwd->push_set_last) {
3258 tcpd->fwd->push_bytes_sent = seglen;
3259 tcpd->fwd->push_set_last = true;
3260 } else if (tcpd->fwd->push_set_last) {
3261 tcpd->fwd->push_bytes_sent = seglen;
3262 tcpd->fwd->push_set_last = false;
3263 } else {
3264 tcpd->fwd->push_bytes_sent += seglen;
3266 if(!tcpd->ta) {
3267 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, true, tcpd);
3269 tcpd->ta->push_bytes_sent = tcpd->fwd->push_bytes_sent;
3276 * Prints results of the sequence number analysis concerning tcp segments
3277 * retransmitted or out-of-order
3279 static void
3280 tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,
3281 tvbuff_t * tvb,
3282 proto_tree * flags_tree, proto_item * flags_item,
3283 struct tcp_acked *ta
3286 /* TCP Retransmission */
3287 if (ta->flags & TCP_A_RETRANSMISSION) {
3288 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
3290 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
3292 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {
3293 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
3294 tvb, 0, 0, &ta->rto_ts);
3295 proto_item_set_generated(flags_item);
3296 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,
3297 tvb, 0, 0, ta->rto_frame);
3298 proto_item_set_generated(flags_item);
3301 /* TCP Fast Retransmission */
3302 if (ta->flags & TCP_A_FAST_RETRANSMISSION) {
3303 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_fast_retransmission);
3304 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
3305 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3306 "[TCP Fast Retransmission] ");
3308 /* TCP Spurious Retransmission */
3309 if (ta->flags & TCP_A_SPURIOUS_RETRANSMISSION) {
3310 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_spurious_retransmission);
3311 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
3312 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3313 "[TCP Spurious Retransmission] ");
3316 /* TCP Out-Of-Order */
3317 if (ta->flags & TCP_A_OUT_OF_ORDER) {
3318 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_out_of_order);
3319 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
3323 /* Prints results of the sequence number analysis concerning reused ports */
3324 static void
3325 tcp_sequence_number_analysis_print_reused(packet_info * pinfo,
3326 proto_item * flags_item,
3327 struct tcp_acked *ta
3330 /* TCP Ports Reused */
3331 if (ta->flags & TCP_A_REUSED_PORTS) {
3332 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_reused_ports);
3333 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3334 "[TCP Port numbers reused] ");
3338 /* Prints results of the sequence number analysis concerning lost tcp segments */
3339 static void
3340 tcp_sequence_number_analysis_print_lost(packet_info * pinfo,
3341 proto_item * flags_item,
3342 struct tcp_acked *ta
3345 /* TCP Lost Segment */
3346 if (ta->flags & TCP_A_LOST_PACKET) {
3347 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_lost_packet);
3348 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3349 "[TCP Previous segment not captured] ");
3351 /* TCP Ack lost segment */
3352 if (ta->flags & TCP_A_ACK_LOST_PACKET) {
3353 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_ack_lost_packet);
3354 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3355 "[TCP ACKed unseen segment] ");
3359 /* Prints results of the sequence number analysis concerning tcp window */
3360 static void
3361 tcp_sequence_number_analysis_print_window(packet_info * pinfo,
3362 proto_item * flags_item,
3363 struct tcp_acked *ta
3366 /* TCP Window Update */
3367 if (ta->flags & TCP_A_WINDOW_UPDATE) {
3368 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_update);
3369 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
3371 /* TCP Full Window */
3372 if (ta->flags & TCP_A_WINDOW_FULL) {
3373 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_full);
3374 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
3378 /* Prints results of the sequence number analysis concerning tcp keepalive */
3379 static void
3380 tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,
3381 proto_item * flags_item,
3382 struct tcp_acked *ta
3385 /*TCP Keep Alive */
3386 if (ta->flags & TCP_A_KEEP_ALIVE) {
3387 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive);
3388 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
3390 /* TCP Ack Keep Alive */
3391 if (ta->flags & TCP_A_KEEP_ALIVE_ACK) {
3392 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive_ack);
3393 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
3397 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
3398 static void
3399 tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,
3400 tvbuff_t * tvb,
3401 proto_tree * flags_tree,
3402 struct tcp_acked *ta,
3403 proto_tree * tree
3406 proto_item * flags_item;
3408 /* TCP Duplicate ACK */
3409 if (ta->dupack_num) {
3410 if (ta->flags & TCP_A_DUPLICATE_ACK ) {
3411 flags_item=proto_tree_add_none_format(flags_tree,
3412 hf_tcp_analysis_duplicate_ack,
3413 tvb, 0, 0,
3414 "This is a TCP duplicate ack"
3416 proto_item_set_generated(flags_item);
3417 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3418 "[TCP Dup ACK %u#%u] ",
3419 ta->dupack_frame,
3420 ta->dupack_num
3424 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
3425 tvb, 0, 0, ta->dupack_num);
3426 proto_item_set_generated(flags_item);
3427 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
3428 tvb, 0, 0, ta->dupack_frame);
3429 proto_item_set_generated(flags_item);
3430 expert_add_info_format(pinfo, flags_item, &ei_tcp_analysis_duplicate_ack, "Duplicate ACK (#%u)", ta->dupack_num);
3434 /* Prints results of the sequence number analysis concerning tcp zero window */
3435 static void
3436 tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,
3437 proto_item * flags_item,
3438 struct tcp_acked *ta
3441 /* TCP Zero Window Probe */
3442 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE) {
3443 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe);
3444 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
3446 /* TCP Zero Window */
3447 if (ta->flags&TCP_A_ZERO_WINDOW) {
3448 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window);
3449 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
3451 /* TCP Zero Window Probe Ack */
3452 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK) {
3453 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe_ack);
3454 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
3455 "[TCP ZeroWindowProbeAck] ");
3460 /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */
3461 static void
3462 tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U_,
3463 tvbuff_t * tvb,
3464 proto_tree * flags_tree,
3465 struct tcp_acked *ta
3468 proto_item * flags_item;
3470 if (tcp_track_bytes_in_flight) {
3471 flags_item=proto_tree_add_uint(flags_tree,
3472 hf_tcp_analysis_bytes_in_flight,
3473 tvb, 0, 0, ta->bytes_in_flight);
3475 proto_item_set_generated(flags_item);
3479 /* Generate the initial data sequence number and MPTCP connection token from the key. */
3480 static void
3481 mptcp_cryptodata_sha1(const uint64_t key, uint32_t *token, uint64_t *idsn)
3483 uint8_t digest_buf[HASH_SHA1_LENGTH];
3484 uint64_t pseudokey = GUINT64_TO_BE(key);
3485 uint32_t _token;
3486 uint64_t _isdn;
3488 gcry_md_hash_buffer(GCRY_MD_SHA1, digest_buf, (const uint8_t *)&pseudokey, 8);
3490 /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */
3491 memcpy(&_token, digest_buf, sizeof(_token));
3492 *token = GUINT32_FROM_BE(_token);
3493 memcpy(&_isdn, digest_buf + HASH_SHA1_LENGTH - sizeof(_isdn), sizeof(_isdn));
3494 *idsn = GUINT64_FROM_BE(_isdn);
3497 /* Generate the initial data sequence number and MPTCP connection token from the key. */
3498 static void
3499 mptcp_cryptodata_sha256(const uint64_t key, uint32_t *token, uint64_t *idsn)
3501 uint8_t digest_buf[HASH_SHA2_256_LENGTH];
3502 uint64_t pseudokey = GUINT64_TO_BE(key);
3503 uint32_t _token;
3504 uint64_t _isdn;
3506 gcry_md_hash_buffer(GCRY_MD_SHA256, digest_buf, (const uint8_t *)&pseudokey, 8);
3508 /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */
3509 memcpy(&_token, digest_buf, sizeof(_token));
3510 *token = GUINT32_FROM_BE(_token);
3511 memcpy(&_isdn, digest_buf + HASH_SHA2_256_LENGTH - sizeof(_isdn), sizeof(_isdn));
3512 *idsn = GUINT64_FROM_BE(_isdn);
3516 /* Print formatted list of tcp stream ids that are part of the connection */
3517 static void
3518 mptcp_analysis_add_subflows(packet_info *pinfo, tvbuff_t *tvb,
3519 proto_tree *parent_tree, struct mptcp_analysis* mptcpd)
3521 wmem_list_frame_t *it;
3522 proto_item *item;
3524 wmem_strbuf_t *val = wmem_strbuf_new(pinfo->pool, "");
3526 /* for the analysis, we set each subflow tcp stream id */
3527 for(it = wmem_list_head(mptcpd->subflows); it != NULL; it = wmem_list_frame_next(it)) {
3528 struct tcp_analysis *sf = (struct tcp_analysis *)wmem_list_frame_data(it);
3529 wmem_strbuf_append_printf(val, "%u ", sf->stream);
3532 item = proto_tree_add_string(parent_tree, hf_mptcp_analysis_subflows, tvb, 0, 0, wmem_strbuf_get_str(val));
3533 proto_item_set_generated(item);
3536 /* Compute raw dsn if relative tcp seq covered by DSS mapping */
3537 static bool
3538 mptcp_map_relssn_to_rawdsn(mptcp_dss_mapping_t *mapping, uint32_t relssn, uint64_t *dsn)
3540 if( (relssn < mapping->ssn_low) || (relssn > mapping->ssn_high)) {
3541 return false;
3544 *dsn = mapping->rawdsn + (relssn - mapping->ssn_low);
3545 return true;
3549 /* Add duplicated data */
3550 static mptcp_dsn2packet_mapping_t *
3551 mptcp_add_duplicated_dsn(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, struct mptcp_subflow *subflow,
3552 uint64_t rawdsn64low, uint64_t rawdsn64high
3555 wmem_list_t *results = NULL;
3556 wmem_list_frame_t *packet_it = NULL;
3557 mptcp_dsn2packet_mapping_t *packet = NULL;
3558 proto_item *item = NULL;
3560 results = wmem_itree_find_intervals(subflow->dsn2packet_map,
3561 pinfo->pool,
3562 rawdsn64low,
3563 rawdsn64high
3566 for(packet_it = wmem_list_head(results);
3567 packet_it != NULL;
3568 packet_it = wmem_list_frame_next(packet_it))
3571 packet = (mptcp_dsn2packet_mapping_t *) wmem_list_frame_data(packet_it);
3572 DISSECTOR_ASSERT(packet);
3574 if(pinfo->num > packet->frame) {
3575 item = proto_tree_add_uint(tree, hf_mptcp_reinjection_of, tvb, 0, 0, packet->frame);
3577 else {
3578 item = proto_tree_add_uint(tree, hf_mptcp_reinjected_in, tvb, 0, 0, packet->frame);
3580 proto_item_set_generated(item);
3583 return packet;
3587 /* Lookup mappings that describe the packet and then converts the tcp seq number
3588 * into the MPTCP Data Sequence Number (DSN)
3590 static void
3591 mptcp_analysis_dsn_lookup(packet_info *pinfo , tvbuff_t *tvb,
3592 proto_tree *parent_tree, struct tcp_analysis* tcpd, struct tcpheader * tcph, mptcp_per_packet_data_t *mptcppd)
3594 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;
3595 proto_item *item = NULL;
3596 mptcp_dss_mapping_t *mapping = NULL;
3597 uint32_t relseq;
3598 uint64_t rawdsn = 0;
3599 enum mptcp_dsn_conversion convert;
3601 if(!mptcp_analyze_mappings)
3603 /* abort analysis */
3604 return;
3607 /* for this to work, we need to know the original seq number from the SYN, not from a subsequent packet
3608 * hence, we abort if we didn't capture the SYN
3610 if(!(tcpd->fwd->static_flags & ~TCP_S_BASE_SEQ_SET & (TCP_S_SAW_SYN | TCP_S_SAW_SYNACK))) {
3611 return;
3614 /* if seq not relative yet, we compute it */
3615 relseq = (tcp_relative_seq) ? tcph->th_seq : tcph->th_seq - tcpd->fwd->base_seq;
3617 DISSECTOR_ASSERT(mptcpd);
3618 DISSECTOR_ASSERT(mptcppd);
3620 /* in case of a SYN, there is no mapping covering the DSN */
3621 if(tcph->th_flags & TH_SYN) {
3623 rawdsn = tcpd->fwd->mptcp_subflow->meta->base_dsn;
3624 convert = DSN_CONV_NONE;
3626 /* if it's a non-syn packet without data (just used to convey TCP options)
3627 * then there would be no mappings */
3628 else if(relseq == 1 && tcph->th_seglen == 0) {
3629 rawdsn = tcpd->fwd->mptcp_subflow->meta->base_dsn + 1;
3630 convert = DSN_CONV_NONE;
3632 else {
3634 wmem_list_frame_t *dss_it = NULL;
3635 wmem_list_t *results = NULL;
3636 uint32_t ssn_low = relseq;
3637 uint32_t seglen = tcph->th_seglen;
3639 results = wmem_itree_find_intervals(tcpd->fwd->mptcp_subflow->ssn2dsn_mappings,
3640 pinfo->pool,
3641 ssn_low,
3642 (seglen) ? ssn_low + seglen - 1 : ssn_low
3644 dss_it = wmem_list_head(results); /* assume it's always ok */
3645 if(dss_it) {
3646 mapping = (mptcp_dss_mapping_t *) wmem_list_frame_data(dss_it);
3648 if(dss_it == NULL || mapping == NULL) {
3649 expert_add_info(pinfo, parent_tree, &ei_mptcp_mapping_missing);
3650 return;
3652 else {
3653 mptcppd->mapping = mapping;
3656 DISSECTOR_ASSERT(mapping);
3657 if(seglen) {
3658 /* Finds mappings that cover the sent data and adds them to the dissection tree */
3659 for(dss_it = wmem_list_head(results);
3660 dss_it != NULL;
3661 dss_it = wmem_list_frame_next(dss_it))
3663 mapping = (mptcp_dss_mapping_t *) wmem_list_frame_data(dss_it);
3664 DISSECTOR_ASSERT(mapping);
3666 item = proto_tree_add_uint(parent_tree, hf_mptcp_related_mapping, tvb, 0, 0, mapping->frame);
3667 proto_item_set_generated(item);
3671 convert = (mapping->extended_dsn) ? DSN_CONV_NONE : DSN_CONV_32_TO_64;
3672 DISSECTOR_ASSERT(mptcp_map_relssn_to_rawdsn(mapping, relseq, &rawdsn));
3675 /* Make sure we have the 64bit raw DSN */
3676 if(mptcp_convert_dsn(rawdsn, tcpd->fwd->mptcp_subflow->meta,
3677 convert, false, &tcph->th_mptcp->mh_rawdsn64)) {
3679 /* always display the rawdsn64 (helpful for debug) */
3680 item = proto_tree_add_uint64(parent_tree, hf_mptcp_rawdsn64, tvb, 0, 0, tcph->th_mptcp->mh_rawdsn64);
3682 /* converts to relative if required */
3683 if (mptcp_relative_seq
3684 && mptcp_convert_dsn(tcph->th_mptcp->mh_rawdsn64, tcpd->fwd->mptcp_subflow->meta, DSN_CONV_NONE, true, &tcph->th_mptcp->mh_dsn)) {
3685 item = proto_tree_add_uint64(parent_tree, hf_mptcp_dsn, tvb, 0, 0, tcph->th_mptcp->mh_dsn);
3686 proto_item_append_text(item, " (Relative)");
3689 /* register dsn->packet mapping */
3690 if(mptcp_intersubflows_retransmission
3691 && !PINFO_FD_VISITED(pinfo)
3692 && tcph->th_seglen > 0
3694 mptcp_dsn2packet_mapping_t *packet = 0;
3695 packet = wmem_new0(wmem_file_scope(), mptcp_dsn2packet_mapping_t);
3696 packet->frame = pinfo->fd->num;
3697 packet->subflow = tcpd;
3699 wmem_itree_insert(tcpd->fwd->mptcp_subflow->dsn2packet_map,
3700 tcph->th_mptcp->mh_rawdsn64,
3701 tcph->th_mptcp->mh_rawdsn64 + (tcph->th_seglen - 1 ),
3702 packet
3705 proto_item_set_generated(item);
3707 /* We can do this only if rawdsn64 is valid !
3708 if enabled, look for overlapping mappings on other subflows */
3709 if(mptcp_intersubflows_retransmission
3710 && tcph->th_have_seglen
3711 && tcph->th_seglen) {
3713 wmem_list_frame_t *subflow_it = NULL;
3715 /* results should be some kind of list in case 2 DSS are needed to cover this packet */
3716 for(subflow_it = wmem_list_head(mptcpd->subflows); subflow_it != NULL; subflow_it = wmem_list_frame_next(subflow_it)) {
3717 struct tcp_analysis *sf_tcpd = (struct tcp_analysis *)wmem_list_frame_data(subflow_it);
3718 struct mptcp_subflow *sf = mptcp_select_subflow_from_meta(sf_tcpd, tcpd->fwd->mptcp_subflow->meta);
3720 /* for current subflow */
3721 if (sf == tcpd->fwd->mptcp_subflow) {
3722 /* skip, this is the current subflow */
3724 /* in case there were retransmissions on other subflows */
3725 else {
3726 mptcp_add_duplicated_dsn(pinfo, parent_tree, tvb, sf,
3727 tcph->th_mptcp->mh_rawdsn64,
3728 tcph->th_mptcp->mh_rawdsn64 + tcph->th_seglen-1);
3733 else {
3734 /* could not get the rawdsn64, ignore and continue */
3740 /* Print subflow list */
3741 static void
3742 mptcp_add_analysis_subtree(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree,
3743 struct tcp_analysis *tcpd, struct mptcp_analysis *mptcpd, struct tcpheader * tcph)
3746 proto_item *item = NULL;
3747 proto_tree *tree = NULL;
3748 mptcp_per_packet_data_t *mptcppd = NULL;
3750 if(mptcpd == NULL) {
3751 return;
3754 item=proto_tree_add_item(parent_tree, hf_mptcp_analysis, tvb, 0, 0, ENC_NA);
3755 proto_item_set_generated(item);
3756 tree=proto_item_add_subtree(item, ett_mptcp_analysis);
3757 proto_item_set_generated(tree);
3759 /* set field with mptcp stream */
3760 if(mptcpd->master) {
3762 item = proto_tree_add_boolean_format_value(tree, hf_mptcp_analysis_master, tvb, 0,
3763 0, (mptcpd->master->stream == tcpd->stream) ? true : false
3764 , "Master is tcp stream %u", mptcpd->master->stream
3768 else {
3769 item = proto_tree_add_boolean(tree, hf_mptcp_analysis_master, tvb, 0,
3770 0, false);
3773 proto_item_set_generated(item);
3775 #if 0 // nbOptionsChanged is currently unused.
3776 /* store the TCP Options related to MPTCP then we will avoid false DUP ACKs later */
3777 uint8_t nbOptionsChanged = 0;
3778 if((tcpd->mptcp_analysis->mp_operations&(0x01))!=tcph->th_mptcp->mh_mpc) {
3779 tcpd->mptcp_analysis->mp_operations |= 0x01;
3780 nbOptionsChanged++;
3782 if((tcpd->mptcp_analysis->mp_operations&(0x02))!=tcph->th_mptcp->mh_join) {
3783 tcpd->mptcp_analysis->mp_operations |= 0x02;
3784 nbOptionsChanged++;
3786 if((tcpd->mptcp_analysis->mp_operations&(0x04))!=tcph->th_mptcp->mh_dss) {
3787 tcpd->mptcp_analysis->mp_operations |= 0x04;
3788 nbOptionsChanged++;
3790 if((tcpd->mptcp_analysis->mp_operations&(0x08))!=tcph->th_mptcp->mh_add) {
3791 tcpd->mptcp_analysis->mp_operations |= 0x08;
3792 nbOptionsChanged++;
3794 if((tcpd->mptcp_analysis->mp_operations&(0x10))!=tcph->th_mptcp->mh_remove) {
3795 tcpd->mptcp_analysis->mp_operations |= 0x10;
3796 nbOptionsChanged++;
3798 if((tcpd->mptcp_analysis->mp_operations&(0x20))!=tcph->th_mptcp->mh_prio) {
3799 tcpd->mptcp_analysis->mp_operations |= 0x20;
3800 nbOptionsChanged++;
3802 if((tcpd->mptcp_analysis->mp_operations&(0x40))!=tcph->th_mptcp->mh_fail) {
3803 tcpd->mptcp_analysis->mp_operations |= 0x40;
3804 nbOptionsChanged++;
3806 if((tcpd->mptcp_analysis->mp_operations&(0x80))!=tcph->th_mptcp->mh_fastclose) {
3807 tcpd->mptcp_analysis->mp_operations |= 0x80;
3808 nbOptionsChanged++;
3810 /* we could track MPTCP option changes here, with nbOptionsChanged */
3811 #endif
3813 item = proto_tree_add_uint(tree, hf_mptcp_stream, tvb, 0, 0, mptcpd->stream);
3814 proto_item_set_generated(item);
3816 /* retrieve saved analysis of packets, else create it */
3817 mptcppd = (mptcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mptcp, pinfo->curr_layer_num);
3818 if(!mptcppd) {
3819 mptcppd = (mptcp_per_packet_data_t *)wmem_new0(wmem_file_scope(), mptcp_per_packet_data_t);
3820 p_add_proto_data(wmem_file_scope(), pinfo, proto_mptcp, pinfo->curr_layer_num, mptcppd);
3823 /* Print formatted list of tcp stream ids that are part of the connection */
3824 mptcp_analysis_add_subflows(pinfo, tvb, tree, mptcpd);
3826 /* Converts TCP seq number into its MPTCP DSN */
3827 mptcp_analysis_dsn_lookup(pinfo, tvb, tree, tcpd, tcph, mptcppd);
3832 static void
3833 tcp_sequence_number_analysis_print_push_bytes_sent(packet_info * pinfo _U_,
3834 tvbuff_t * tvb,
3835 proto_tree * flags_tree,
3836 struct tcp_acked *ta
3839 proto_item * flags_item;
3841 if (tcp_track_bytes_in_flight) {
3842 flags_item=proto_tree_add_uint(flags_tree,
3843 hf_tcp_analysis_push_bytes_sent,
3844 tvb, 0, 0, ta->push_bytes_sent);
3846 proto_item_set_generated(flags_item);
3850 static void
3851 tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree,
3852 struct tcp_analysis *tcpd, uint32_t seq, uint32_t ack)
3854 struct tcp_acked *ta = NULL;
3855 proto_item *item;
3856 proto_tree *tree;
3857 proto_tree *flags_tree=NULL;
3859 if (!tcpd) {
3860 return;
3862 if(!tcpd->ta) {
3863 tcp_analyze_get_acked_struct(pinfo->num, seq, ack, false, tcpd);
3865 ta=tcpd->ta;
3866 if(!ta) {
3867 return;
3870 item=proto_tree_add_item(parent_tree, hf_tcp_analysis, tvb, 0, 0, ENC_NA);
3871 proto_item_set_generated(item);
3872 tree=proto_item_add_subtree(item, ett_tcp_analysis);
3874 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
3875 data we actually have */
3876 if(ta->frame_acked) {
3877 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
3878 tvb, 0, 0, ta->frame_acked);
3879 proto_item_set_generated(item);
3881 if(ta->partial_ack) {
3882 expert_add_info(pinfo, item, &ei_tcp_analysis_partial_ack);
3885 /* only display RTT if we actually have something we are acking */
3886 if( ta->ts.secs || ta->ts.nsecs ) {
3887 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
3888 tvb, 0, 0, &ta->ts);
3889 proto_item_set_generated(item);
3892 if (!nstime_is_zero(&tcpd->ts_first_rtt)) {
3893 item = proto_tree_add_time(tree, hf_tcp_analysis_first_rtt,
3894 tvb, 0, 0, &(tcpd->ts_first_rtt));
3895 proto_item_set_generated(item);
3898 if(ta->bytes_in_flight) {
3899 /* print results for amount of data in flight */
3900 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta);
3901 tcp_sequence_number_analysis_print_push_bytes_sent(pinfo, tvb, tree, ta);
3904 if(ta->flags) {
3905 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, 0, ENC_NA);
3906 proto_item_set_generated(item);
3907 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);
3909 /* print results for reused tcp ports */
3910 tcp_sequence_number_analysis_print_reused(pinfo, item, ta);
3912 /* print results for retransmission and out-of-order segments */
3913 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, item, ta);
3915 /* print results for lost tcp segments */
3916 tcp_sequence_number_analysis_print_lost(pinfo, item, ta);
3918 /* print results for tcp window information */
3919 tcp_sequence_number_analysis_print_window(pinfo, item, ta);
3921 /* print results for tcp keep alive information */
3922 tcp_sequence_number_analysis_print_keepalive(pinfo, item, ta);
3924 /* print results for tcp duplicate acks */
3925 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);
3927 /* print results for tcp zero window */
3928 tcp_sequence_number_analysis_print_zero_window(pinfo, item, ta);
3934 static void
3935 print_tcp_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *tcp_tree, packet_info *pinfo, tvbuff_t *next_tvb)
3937 proto_item *tcp_tree_item, *frag_tree_item;
3940 * The subdissector thought it was completely
3941 * desegmented (although the stuff at the
3942 * end may, in turn, require desegmentation),
3943 * so we show a tree with all segments.
3945 show_fragment_tree(ipfd_head, &tcp_segment_items,
3946 tree, pinfo, next_tvb, &frag_tree_item);
3948 * The toplevel fragment subtree is now
3949 * behind all desegmented data; move it
3950 * right behind the TCP tree.
3952 tcp_tree_item = proto_tree_get_parent(tcp_tree);
3953 if(frag_tree_item && tcp_tree_item) {
3954 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);
3958 /* **************************************************************************
3959 * End of tcp sequence number analysis
3960 * **************************************************************************/
3963 /* Minimum TCP header length. */
3964 #define TCPH_MIN_LEN 20
3966 /* Desegmentation of TCP streams */
3968 /* The primary ID is the first frame of a multisegment PDU, which is
3969 * most likely unique in the capture (unlike sequence numbers which
3970 * can be re-used, especially when relative sequence numbers are enabled).
3971 * However, frames can have multiple PDUs with certain encapsulations like
3972 * GSE or MPE over DVB BaseBand Frames.
3975 typedef struct _tcp_endpoint {
3977 address src_addr;
3978 address dst_addr;
3979 port_type ptype;
3980 uint32_t src_port;
3981 uint32_t dst_port;
3982 } tcp_endpoint_t;
3984 static void
3985 save_endpoint(packet_info *pinfo, tcp_endpoint_t *a)
3987 copy_address_shallow(&a->src_addr, &pinfo->src);
3988 copy_address_shallow(&a->dst_addr, &pinfo->dst);
3989 a->ptype = pinfo->ptype;
3990 a->src_port = pinfo->srcport;
3991 a->dst_port = pinfo->destport;
3994 static void
3995 restore_endpoint(packet_info *pinfo, tcp_endpoint_t *a)
3997 copy_address_shallow(&pinfo->src, &a->src_addr);
3998 copy_address_shallow(&pinfo->dst, &a->dst_addr);
3999 pinfo->ptype = a->ptype;
4000 pinfo->srcport = a->src_port;
4001 pinfo->destport = a->dst_port;
4004 typedef struct _tcp_segment_key {
4005 address src_addr;
4006 address dst_addr;
4007 uint32_t src_port;
4008 uint32_t dst_port;
4009 uint32_t id; /* msp->first_frame */
4010 uint32_t seq; /* msp->seq */
4011 } tcp_segment_key;
4013 static unsigned
4014 tcp_segment_hash(const void *k)
4016 const tcp_segment_key* key = (const tcp_segment_key*) k;
4017 unsigned hash_val;
4019 hash_val = key->id;
4021 /* In most captures there is only one fragment per id / first_frame,
4022 so we only use it in the hash as an optimization.
4024 int i;
4025 for (i = 0; i < key->src.len; i++)
4026 hash_val += key->src_addr.data[i];
4027 for (i = 0; i < key->dst.len; i++)
4028 hash_val += key->dst_addr.data[i];
4029 hash_val += key->src_port;
4030 hash_val += key->dst_port;
4031 hash_val += key->seq;
4034 return hash_val;
4037 static int
4038 tcp_segment_equal(const void *k1, const void *k2)
4040 const tcp_segment_key* key1 = (const tcp_segment_key*) k1;
4041 const tcp_segment_key* key2 = (const tcp_segment_key*) k2;
4044 * key.id is the first item to compare since it's the item most
4045 * likely to differ between sessions, thus short-circuiting
4046 * the comparison of addresses and ports.
4048 return (key1->id == key2->id) &&
4049 (addresses_equal(&key1->src_addr, &key2->src_addr)) &&
4050 (addresses_equal(&key1->dst_addr, &key2->dst_addr)) &&
4051 (key1->src_port == key2->src_port) &&
4052 (key1->dst_port == key2->dst_port) &&
4053 (key1->seq == key2->seq);
4057 * Create a fragment key for temporary use; it can point to non-
4058 * persistent data, and so must only be used to look up and
4059 * delete entries, not to add them.
4061 static void *
4062 tcp_segment_temporary_key(const packet_info *pinfo, const uint32_t id,
4063 const void *data)
4065 struct tcp_multisegment_pdu *msp = (struct tcp_multisegment_pdu*)data;
4066 DISSECTOR_ASSERT(msp);
4067 tcp_segment_key *key = g_slice_new(tcp_segment_key);
4070 * Do a shallow copy of the addresses.
4072 copy_address_shallow(&key->src_addr, &pinfo->src);
4073 copy_address_shallow(&key->dst_addr, &pinfo->dst);
4074 key->src_port = pinfo->srcport;
4075 key->dst_port = pinfo->destport;
4076 key->id = id;
4077 key->seq = msp->seq;
4079 return (void *)key;
4083 * Create a fragment key for permanent use; it must point to persistent
4084 * data, so that it can be used to add entries.
4086 static void *
4087 tcp_segment_persistent_key(const packet_info *pinfo,
4088 const uint32_t id, const void *data)
4090 struct tcp_multisegment_pdu *msp = (struct tcp_multisegment_pdu*)data;
4091 DISSECTOR_ASSERT(msp);
4092 tcp_segment_key *key = g_slice_new(tcp_segment_key);
4095 * Do a deep copy of the addresses.
4097 copy_address(&key->src_addr, &pinfo->src);
4098 copy_address(&key->dst_addr, &pinfo->dst);
4099 key->src_port = pinfo->srcport;
4100 key->dst_port = pinfo->destport;
4101 key->id = id;
4102 key->seq = msp->seq;
4104 return (void *)key;
4107 static void
4108 tcp_segment_free_temporary_key(void *ptr)
4110 tcp_segment_key *key = (tcp_segment_key *)ptr;
4111 g_slice_free(tcp_segment_key, key);
4114 static void
4115 tcp_segment_free_persistent_key(void *ptr)
4117 tcp_segment_key *key = (tcp_segment_key *)ptr;
4119 if(key){
4121 * Free up the copies of the addresses from the old key.
4123 free_address(&key->src_addr);
4124 free_address(&key->dst_addr);
4126 g_slice_free(tcp_segment_key, key);
4130 const reassembly_table_functions
4131 tcp_reassembly_table_functions = {
4132 tcp_segment_hash,
4133 tcp_segment_equal,
4134 tcp_segment_temporary_key,
4135 tcp_segment_persistent_key,
4136 tcp_segment_free_temporary_key,
4137 tcp_segment_free_persistent_key
4140 static reassembly_table tcp_reassembly_table;
4142 /* functions to trace tcp segments */
4143 /* Enable desegmenting of TCP streams */
4144 static bool tcp_desegment = true;
4146 /* Returns the maximum contiguous sequence number of the reassembly associated
4147 * with the msp *if* a new fragment were added ending in the given maxnextseq.
4148 * The new fragment is from the current frame and may not have been added yet.
4150 static uint32_t
4151 find_maxnextseq(packet_info *pinfo, struct tcp_multisegment_pdu *msp, uint32_t maxnextseq)
4153 fragment_head *fd_head;
4155 DISSECTOR_ASSERT(msp);
4157 fd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
4158 /* msp implies existence of fragments, this should never be NULL. */
4159 DISSECTOR_ASSERT(fd_head);
4161 /* Find length of contiguous fragments.
4162 * Start with the first gap, but the new fragment is allowed to
4163 * fill that gap. */
4164 uint32_t max_len = maxnextseq - msp->seq;
4165 fragment_item* frag = (fd_head->first_gap) ? fd_head->first_gap : fd_head->next;
4166 for (; frag && frag->offset <= max_len; frag = frag->next) {
4167 max_len = MAX(max_len, frag->offset + frag->len);
4170 return max_len + msp->seq;
4173 static struct tcp_multisegment_pdu*
4174 split_msp(packet_info *pinfo, struct tcp_multisegment_pdu *msp, struct tcp_analysis *tcpd)
4176 fragment_head *fd_head;
4177 uint32_t first_frame = 0;
4178 uint32_t last_frame = 0;
4179 const uint32_t split_offset = pinfo->desegment_offset;
4181 fd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
4182 /* This is for splitting defragmented MSPs, so fd_head should exist
4183 * and be defragmented. This also ensures that fd_i->tvb_data exists.
4185 DISSECTOR_ASSERT(fd_head && fd_head->flags & FD_DEFRAGMENTED);
4187 fragment_item *fd_i, *first_frag = NULL;
4189 /* The fragment list is sorted in offset order, but not nec. frame order
4190 * or end offset order due to out of order reassembly and possible overlap.
4191 * fd_i->offset < split_offset - some bytes are before the split
4192 * fd_i->offset + fd_i->len >= split_offset - some bytes are after split
4193 * Look through all the fragments that have some data before the split point.
4195 for (fd_i = fd_head->next; fd_i && (fd_i->offset < split_offset); fd_i = fd_i->next) {
4196 if (last_frame < fd_i->frame) {
4197 last_frame = fd_i->frame;
4199 if (fd_i->offset + fd_i->len >= split_offset) {
4200 if (first_frag == NULL) {
4201 first_frag = fd_i;
4202 first_frame = fd_i->frame;
4203 } else if (fd_i->frame < first_frame) {
4204 first_frame = fd_i->frame;
4209 /* Now look through all the remaining fragments that only have bytes after
4210 * the split.
4212 for (; fd_i; fd_i = fd_i->next) {
4213 uint32_t frag_end = fd_i->offset + fd_i->len;
4214 if (split_offset <= frag_end && fd_i->frame < first_frame) {
4215 first_frame = fd_i->frame;
4219 /* We only call this when the frame the fragments were reassembled in
4220 * (which is the current frame) includes some data before the split
4221 * point, so that it won't change and we can be consistent dissecting
4222 * between passes. We also should have at least some data after the
4223 * split point (because the subdissector claimed there was undissected
4224 * data.)
4226 DISSECTOR_ASSERT(fd_head->reassembled_in == last_frame);
4227 DISSECTOR_ASSERT(first_frag != NULL);
4229 uint32_t new_seq = msp->seq + pinfo->desegment_offset;
4230 struct tcp_multisegment_pdu *newmsp;
4231 newmsp = pdu_store_sequencenumber_of_next_pdu(pinfo, new_seq,
4232 new_seq+1, tcpd->fwd->multisegment_pdus);
4233 newmsp->first_frame = first_frame;
4234 newmsp->nxtpdu = msp->nxtpdu;
4236 /* XXX: Could do the adding the new fragments in fragment_truncate */
4237 for (fd_i = first_frag; fd_i; fd_i = fd_i->next) {
4238 uint32_t frag_offset = fd_i->offset;
4239 uint32_t frag_len = fd_i->len;
4240 /* Check for some unusual out of order overlapping segment situations. */
4241 if (split_offset < frag_offset + frag_len) {
4242 if (fd_i->offset < split_offset) {
4243 frag_offset = split_offset;
4244 frag_len -= (split_offset - fd_i->offset);
4246 fragment_add_out_of_order(&tcp_reassembly_table, fd_head->tvb_data,
4247 frag_offset, pinfo, first_frame, newmsp,
4248 frag_offset - split_offset, frag_len, true, fd_i->frame);
4252 fragment_truncate(&tcp_reassembly_table, pinfo, msp->first_frame, msp, split_offset);
4253 msp->nxtpdu = msp->seq + split_offset;
4255 /* The newmsp nxtpdu will be adjusted after leaving this function. */
4256 return newmsp;
4259 typedef struct _ooo_segment_item {
4260 uint32_t frame;
4261 uint32_t seq;
4262 uint32_t len;
4263 uint8_t *data;
4264 } ooo_segment_item;
4266 static int
4267 compare_ooo_segment_item(const void *a, const void *b)
4269 const ooo_segment_item *fd_a = a;
4270 const ooo_segment_item *fd_b = b;
4272 /* We only insert segments into this list that satisfy
4273 * LT_SEQ(tcpd->fwd->maxnextseq, seq), for the current value
4274 * of maxnextseq (removing segments when maxnextseq is advanced)
4275 * so these rollover-aware comparisons are transitive over the
4276 * domain (never greater than 2^31).
4278 if (LT_SEQ(fd_a->seq, fd_b->seq))
4279 return -1;
4281 if (GT_SEQ(fd_a->seq, fd_b->seq))
4282 return 1;
4284 if (fd_a->frame < fd_b->frame)
4285 return -1;
4287 if (fd_a->frame > fd_b->frame)
4288 return 1;
4290 return 0;
4293 /* Search through our list of out of order segments and add the ones that are
4294 * now contiguous onto a MSP until we use them all or reach another gap.
4296 * If the MSP parameter is a incomplete, returns it with any OOO segments added.
4297 * If the MSP parameter is NULL or complete, returns a newly created MSP with
4298 * OOO segments added, or NULL if there were no segments to add.
4300 static struct tcp_multisegment_pdu *
4301 msp_add_out_of_order(packet_info *pinfo, struct tcp_multisegment_pdu *msp, struct tcp_analysis *tcpd, uint32_t seq)
4304 /* Whether a previous MSP exists with missing segments. */
4305 bool has_unfinished_msp = msp && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS);
4306 bool updated_maxnextseq = false;
4308 if (msp) {
4309 uint32_t maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);
4310 if (LE_SEQ(tcpd->fwd->maxnextseq, maxnextseq)) {
4311 tcpd->fwd->maxnextseq = maxnextseq;
4313 updated_maxnextseq = true;
4315 wmem_list_frame_t *curr_entry;
4316 curr_entry = wmem_list_head(tcpd->fwd->ooo_segments);
4317 ooo_segment_item *fd;
4318 tvbuff_t *tvb_data;
4319 while (curr_entry) {
4320 fd = (ooo_segment_item *)wmem_list_frame_data(curr_entry);
4321 if (LT_SEQ(tcpd->fwd->maxnextseq, fd->seq)) {
4322 /* There might be segments already added to the msp that now extend
4323 * the maximum contiguous sequence number. Check for them. */
4324 if (msp && !updated_maxnextseq) {
4325 tcpd->fwd->maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);
4326 updated_maxnextseq = true;
4328 if (LT_SEQ(tcpd->fwd->maxnextseq, fd->seq)) {
4329 break;
4332 /* We have filled in the gap, so this out of order
4333 * segment is now contiguous and can be processed along
4334 * with the segment we just received.
4336 tcpd->fwd->maxnextseq = fd->seq + fd->len;
4337 tvb_data = tvb_new_real_data(fd->data, fd->len, fd->len);
4338 if (has_unfinished_msp) {
4340 /* Increase the expected MSP size if necessary. Yes, the
4341 * subdissector may have told us that a PDU ended here, but we
4342 * might have enough newly contiguous data to dissect another
4343 * PDU past that, and we should send that to the subdissector
4344 * too. */
4345 if (LT_SEQ(msp->nxtpdu, fd->seq + fd->len)) {
4346 msp->nxtpdu = fd->seq + fd->len;
4348 /* Add this OOO segment to the unfinished MSP */
4349 fragment_add_out_of_order(&tcp_reassembly_table,
4350 tvb_data, 0,
4351 pinfo, msp->first_frame, msp,
4352 fd->seq - msp->seq, fd->len,
4353 msp->nxtpdu, fd->frame);
4354 } else {
4355 /* No MSP in progress, so create one starting
4356 * at the sequence number of segment received
4357 * in this frame. Note that we will be adding
4358 * the first segment below, and this is the frame
4359 * of the first segment, so first_frame_with_seq
4360 * is already correct (and unnecessary) and
4361 * we don't need MSP_FLAGS_MISSING_FIRST_SEGMENT. */
4362 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
4363 seq, fd->seq + fd->len,
4364 tcpd->fwd->multisegment_pdus);
4365 fragment_add_out_of_order(&tcp_reassembly_table,
4366 tvb_data, 0, pinfo, msp->first_frame,
4367 msp, fd->seq - msp->seq, fd->len,
4368 msp->nxtpdu, fd->frame);
4369 has_unfinished_msp = true;
4371 updated_maxnextseq = false;
4372 tvb_free(tvb_data);
4373 wmem_list_remove_frame(tcpd->fwd->ooo_segments, curr_entry);
4374 curr_entry = wmem_list_head(tcpd->fwd->ooo_segments);
4377 /* There might be segments already added to the msp that now extend
4378 * the maximum contiguous sequence number. Check for them. */
4379 if (msp && !updated_maxnextseq) {
4380 tcpd->fwd->maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq);
4382 return msp;
4385 static void
4386 desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
4387 uint32_t seq, uint32_t nxtseq,
4388 uint32_t sport, uint32_t dport,
4389 proto_tree *tree, proto_tree *tcp_tree,
4390 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
4392 fragment_head *ipfd_head;
4393 int last_fragment_len;
4394 bool must_desegment;
4395 bool called_dissector;
4396 bool has_gap;
4397 int another_pdu_follows;
4398 int deseg_offset;
4399 uint32_t deseg_seq;
4400 int nbytes;
4401 proto_item *item;
4402 struct tcp_multisegment_pdu *msp;
4403 bool cleared_writable = col_get_writable(pinfo->cinfo, COL_PROTOCOL);
4404 bool first_pdu = true;
4405 const bool reassemble_ooo = tcp_analyze_seq && tcp_desegment && tcp_reassemble_out_of_order && tcpd && tcpd->fwd->ooo_segments;
4407 tcp_endpoint_t orig_endpoint, new_endpoint;
4409 save_endpoint(pinfo, &orig_endpoint);
4410 save_endpoint(pinfo, &new_endpoint);
4412 again:
4413 ipfd_head = NULL;
4414 last_fragment_len = 0;
4415 must_desegment = false;
4416 called_dissector = false;
4417 has_gap = false;
4418 another_pdu_follows = 0;
4419 msp = NULL;
4422 * Initialize these to assume no desegmentation.
4423 * If that's not the case, these will be set appropriately
4424 * by the subdissector.
4426 pinfo->desegment_offset = 0;
4427 pinfo->desegment_len = 0;
4430 * Initialize this to assume that this segment will just be
4431 * added to the middle of a desegmented chunk of data, so
4432 * that we should show it all as data.
4433 * If that's not the case, it will be set appropriately.
4435 deseg_offset = offset;
4438 * TODO: Some notes on current limitations with TCP desegmentation:
4440 * This function can be called with either relative or absolute sequence
4441 * numbers; the ??_SEQ macros are called for comparisons to deal with
4442 * with sequence number rollover. (With relative sequence numbers, if
4443 * early TCP segments are received out of order before the SYN it can be
4444 * possible for rollover to occur at the very beginning of a connection.)
4446 * However, multi-segment PDU lookup does not work for MSPs that span
4447 * TCP sequence number rollover, and desegmentation fails.
4449 * When there is a single TCP connection that is longer than 4 GiB and
4450 * thus sequence numbers are reused, multi-segment PDU lookup and
4451 * retransmission identification does not work. (Bug 10503).
4453 * Distinguishing between sequence number reuse on a very long connection
4454 * and sequence number reuse due to retransmission is difficult. Right
4455 * now very long connections are just not handled as the rarer case.
4456 * Perhaps retransmission identification could be entirely left up to TCP
4457 * analysis (if enabled, not done at all if disabled), instead of TCP
4458 * analysis results only used to supplement work here?
4460 * TCP sequence analysis can set TCP_A_RETRANSMISSION in cases where
4461 * we still need to process the segment anyway because something other
4462 * than the sequence number is different from the prior segment. That
4463 * includes "retransmitted but with additional data" (Bug 13523) and
4464 * "retransmitted due to bad checksum" (especially if checksum verification
4465 * is enabled.)
4467 * "Reassemble out-of-order segments" uses its own method of detecting
4468 * retranmission, but uses more memory and CPU, and when used, a TCP stream
4469 * that has missing segments that are never retransmitted stop processing
4470 * after the missing segment.
4472 * If multiple TCP/IP packets are encapsulated in the same frame (such
4473 * as with GSE, which has very long Baseband Frames) this causes issues:
4475 * If a subdissector reports that it can handle a payload, but needs
4476 * more data (pinfo->desegment_len > 0) and did not actually dissect
4477 * any of it (pinfo->desegment_offset == 0), on the first pass it
4478 * still adds layers to the frame. On subsequent passes, the MSP created
4479 * (or extended) in the first pass means that the subdissector won't be
4480 * called at all. If there are other protocols contained in the frame
4481 * that are dissected on the second pass they will have different
4482 * layer numbers than in the first pass, which can disturb proto_data
4483 * lookup, reassembly, etc. (Bug 16109 describes this for TLS.)
4486 if (tcpd) {
4488 if (reassemble_ooo) {
4489 /* If we are reassembling out of order, we can do this retransmission
4490 * check. Anything before the latest consecutive sequence number we've
4491 * already processed is a retransmission (from the perspective of has
4492 * been passed to subdissectors; the judgment of TCP Sequence Analysis
4493 * may be different, because it considers RTO and ACKs and so forth).
4495 * XXX: If these segments are part of incomplete MSPs, we pass them
4496 * to the reassembly code which tests for overlap conflicts.
4497 * For those which are part of completed reassemblies or not part
4498 * of MSPs, we just don't process them. The former would throw a
4499 * ReassemblyError, which is likely acceptable in the case of
4500 * retransmission of the same segment but not if retransmitted with
4501 * additional data, where we'd need to catch the exception to
4502 * process the extra data. For ones that were not added to MSPs at
4503 * all, we can't do much. (Bug #13061)
4505 * Retransmissions of out of order segments after our latest
4506 * consecutive sequence number will all be stored and then eventually
4507 * put on multisegment PDUs and go to the reassembler, which should
4508 * be able to handle retransmission, as those are still incomplete.
4511 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq);
4513 bool has_unfinished_msp = false;
4514 if (msp && LE_SEQ(msp->seq, seq) && GT_SEQ(msp->nxtpdu, seq) && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS)) {
4515 has_unfinished_msp = true;
4518 if (!PINFO_FD_VISITED(pinfo) && first_pdu) {
4519 if (tcpd->fwd->maxnextseq && LT_SEQ(seq, tcpd->fwd->maxnextseq) && !has_unfinished_msp) {
4520 if(!tcpd->ta) {
4521 tcp_analyze_get_acked_struct(pinfo->num, seq, tcpinfo->lastackseq, true, tcpd);
4523 tcpd->ta->flags |= TCP_A_OLD_DATA;
4524 if (GT_SEQ(nxtseq, tcpd->fwd->maxnextseq)) {
4525 tcpd->ta->new_data_seq = tcpd->fwd->maxnextseq;
4526 } else {
4527 tcpd->ta->new_data_seq = nxtseq;
4532 if(tcpd->ta && first_pdu) {
4533 if((tcpd->ta->flags&TCP_A_OLD_DATA) == TCP_A_OLD_DATA) {
4534 nbytes = tcpd->ta->new_data_seq - seq;
4536 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb,
4537 offset, nbytes, NULL,
4538 "Retransmitted TCP segment data (%u byte%s)",
4539 nbytes, plurality(nbytes, "", "s"));
4541 offset += nbytes;
4542 seq = tcpd->ta->new_data_seq;
4543 first_pdu = false;
4544 if (tvb_captured_length_remaining(tvb, offset) > 0)
4545 goto again;
4546 goto clean_exit;
4549 } else {
4551 /* Have we seen this PDU before (and is it the start of a multi-
4552 * segment PDU)?
4554 * If the sequence number was seen before, it is part of a
4555 * retransmission if the whole segment fits within the MSP.
4556 * (But if this is this frame was already visited and the first frame of
4557 * the MSP matches the current frame, then it is not a retransmission,
4558 * but the start of a new MSP.)
4560 * If only part of the segment fits in the MSP, then either:
4561 * - The previous segment included with the MSP was a Zero Window Probe
4562 * with one byte of data and the subdissector just asked for one more
4563 * byte. Do not mark it as retransmission (Bug 15427).
4564 * - Data was actually being retransmitted, but with additional data
4565 * (Bug 13523). Do not mark it as retransmission to handle the extra
4566 * bytes. (NOTE Due to the TCP_A_RETRANSMISSION check below, such
4567 * extra data will still be ignored.)
4568 * - The MSP contains multiple segments, but the subdissector finished
4569 * reassembly using a subset of the final segment (thus "msp->nxtpdu"
4570 * is smaller than the nxtseq of the previous segment). If that final
4571 * segment was retransmitted, then "nxtseq > msp->nxtpdu".
4572 * Unfortunately that will *not* be marked as retransmission here.
4573 * The next TCP_A_RETRANSMISSION hopefully takes care of it though.
4575 * Only shortcircuit here when the first segment of the MSP is known,
4576 * and when this first segment is not one to complete the MSP.
4578 if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, seq)) &&
4579 nxtseq <= msp->nxtpdu &&
4580 !(msp->flags & MSP_FLAGS_MISSING_FIRST_SEGMENT) && msp->last_frame != pinfo->num) {
4581 const char* str;
4582 bool is_retransmission = false;
4584 /* Yes. This could be because we've dissected this frame before
4585 * or because this is a retransmission of a previously-seen
4586 * segment. Either way, we don't need to hand it off to the
4587 * subdissector and we certainly don't want to re-add it to the
4588 * multisegment_pdus list: if we did, subsequent lookups would
4589 * find this retransmission instead of the original transmission
4590 * (breaking desegmentation if we'd already linked other segments
4591 * to the original transmission's entry).
4593 * Cases to handle here:
4594 * - In-order stream, pinfo->num matches begin of MSP.
4595 * - In-order stream, but pinfo->num does not match the begin of the
4596 * MSP. Must be a retransmission.
4597 * - OoO stream where this segment fills the gap in the begin of the
4598 * MSP. msp->first_frame is the start where the gap was detected
4599 * (and does NOT match pinfo->num).
4602 if (msp->first_frame == pinfo->num || msp->first_frame_with_seq == pinfo->num) {
4603 str = "";
4604 } else {
4605 str = "Retransmitted ";
4606 is_retransmission = true;
4607 /* TCP analysis already flags this (in COL_INFO) as a retransmission--if it's enabled */
4610 /* Fix for bug 3264: look up ipfd for this (first) segment,
4611 so can add tcp.reassembled_in generated field on this code path. */
4612 if (!is_retransmission) {
4613 ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
4614 if (ipfd_head) {
4615 if (ipfd_head->reassembled_in != 0) {
4616 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,
4617 0, ipfd_head->reassembled_in);
4618 proto_item_set_generated(item);
4620 if (first_pdu) {
4621 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[TCP PDU reassembled in %u]",
4622 ipfd_head->reassembled_in);
4628 nbytes = tvb_reported_length_remaining(tvb, offset);
4630 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
4631 nbytes, NULL, "%sTCP segment data (%u byte%s)", str, nbytes,
4632 plurality(nbytes, "", "s"));
4633 goto clean_exit;
4636 /* Else, find the most previous PDU starting before this sequence number */
4637 if (!msp) {
4638 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);
4641 bool has_unfinished_msp = false;
4642 if (msp && LE_SEQ(msp->seq, seq) && GT_SEQ(msp->nxtpdu, seq) && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS)) {
4643 has_unfinished_msp = true;
4646 /* The above code only finds retransmission if the PDU boundaries and the seq coincide
4647 * If we have sequence analysis active use the TCP_A_RETRANSMISSION flag.
4648 * XXXX Could the above code be improved?
4650 if(tcpd->ta) {
4651 /* If we have an unfinished MSP that this segment belongs to
4652 * or if the sequence number is newer than anything we've seen,
4653 * then this is Out of Order from the reassembly perspective
4654 * and we want to process it anyway.
4656 if (!PINFO_FD_VISITED(pinfo) && tcpd->fwd->maxnextseq && LE_SEQ(seq, tcpd->fwd->maxnextseq) && !has_unfinished_msp) {
4657 /* Otherwise, if TCP Analysis calls the segment a
4658 * Spurious Retransmission or Retransmission, ignore it
4659 * here and on future passes.
4660 * See issue 10289
4661 * XXX: There are still some cases where TCP Analysis
4662 * marks segments as Retransmissions when they are
4663 * Out of Order from this perspective (#10725, #13843)
4665 if((tcpd->ta->flags&TCP_A_SPURIOUS_RETRANSMISSION) == TCP_A_SPURIOUS_RETRANSMISSION ||
4666 (tcpd->ta->flags & TCP_A_RETRANSMISSION) == TCP_A_RETRANSMISSION ||
4667 (tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION) == TCP_A_FAST_RETRANSMISSION) {
4668 tcpd->ta->flags |= TCP_A_OLD_DATA;
4671 if((tcpd->ta->flags&TCP_A_OLD_DATA) == TCP_A_OLD_DATA) {
4672 const char* str = "Retransmitted ";
4673 nbytes = tvb_reported_length_remaining(tvb, offset);
4674 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
4675 nbytes, NULL, "%sTCP segment data (%u byte%s)", str, nbytes,
4676 plurality(nbytes, "", "s"));
4677 goto clean_exit;
4683 if (reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN)) {
4684 if (!PINFO_FD_VISITED(pinfo)) {
4685 /* If there is a gap between this segment and any previous ones
4686 * (that is, seqno is larger than the maximum expected seqno), then
4687 * it is possibly an out-of-order segment. The very first segment
4688 * is expected to be in-order though (otherwise captures starting
4689 * in midst of a connection would never be reassembled).
4690 * (maxnextseq is 0 if we have not seen a SYN packet, even with
4691 * absolute sequence numbers.)
4693 * Do not bother checking for OoO segments for streams that are
4694 * reassembled at FIN, the order of segments before FIN does not
4695 * matter as reordering and reassembly occurs at FIN.
4698 if (tcpd->fwd->maxnextseq) {
4699 /* Segments may be missing due to packet loss (assume later
4700 * retransmission) or out-of-order (assume it appears later).
4702 * XXX: It would be nice to handle captures that have both
4703 * out-of-order packets and some lost packets that are
4704 * never retransmitted. But using the reverse flow ACK
4705 * (like follow_tcp_tap_listener) or using a known end of
4706 * a MSP (that we haven't fully received yet) to process a
4707 * segment that starts right afterwards would both break the
4708 * promise of in-order delivery, if a missing packet did arrive
4709 * later, which is a problem for any state-based dissector
4710 * (including TLS.)
4713 /* Whether the new segment has a gap from our latest contiguous
4714 * sequence number. */
4715 has_gap = LT_SEQ(tcpd->fwd->maxnextseq, seq);
4718 if (!has_gap) {
4719 /* Update the maximum expected seqno if no SYN packet was seen
4720 * before, or if the new segment succeeds previous segments. */
4721 tcpd->fwd->maxnextseq = nxtseq;
4723 /* If there is no gap, look for any OOO packets that are now
4724 * contiguous. */
4725 msp = msp_add_out_of_order(pinfo, msp, tcpd, seq);
4727 } else {
4728 /* If we have visited this frame before, look for the frame in the
4729 * list of unused out of order segments. Since we know the gap will
4730 * never be filled, we could pass it to the subdissector, but
4731 * we want to be consistent between passes.
4733 ooo_segment_item *fd;
4734 fd = wmem_new0(pinfo->pool, ooo_segment_item);
4735 fd->frame = pinfo->num;
4736 fd->seq = seq;
4737 fd->len = nxtseq - seq;
4738 if (wmem_list_find_custom(tcpd->fwd->ooo_segments, fd, compare_ooo_segment_item)) {
4739 has_gap = true;
4744 /* If we are not processing out of order, update the max nextseq value if
4745 * is later than our current value (or our first value.)
4747 if (!reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN)) {
4748 if (!PINFO_FD_VISITED(pinfo)) {
4749 if (LT_SEQ(tcpd->fwd->maxnextseq, nxtseq) || tcpd->fwd->maxnextseq == 0) {
4750 tcpd->fwd->maxnextseq = nxtseq;
4755 if (msp && LE_SEQ(msp->seq, seq) && GT_SEQ(msp->nxtpdu, seq)) {
4756 int len;
4758 if (!PINFO_FD_VISITED(pinfo)) {
4759 msp->last_frame=pinfo->num;
4760 msp->last_frame_time=pinfo->abs_ts;
4763 /* OK, this PDU was found, which means the segment continues
4764 * a higher-level PDU and that we must desegment it.
4766 if (msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
4767 /* The dissector asked for the entire segment */
4768 len = tvb_captured_length_remaining(tvb, offset);
4769 } else {
4770 /* Wraparound is possible, so subtraction does not
4771 * distribute across MIN(x, y)
4773 len = MIN(nxtseq - seq, msp->nxtpdu - seq);
4775 last_fragment_len = len;
4778 if (reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN)) {
4780 * If the previous segment requested more data (setting
4781 * FD_PARTIAL_REASSEMBLY as the next segment length is unknown), but
4782 * subsequently an OoO segment was received (for an earlier hole),
4783 * then "fragment_add" would truncate the reassembled PDU to the end
4784 * of this OoO segment. To prevent that, explicitly specify the MSP
4785 * length before calling "fragment_add".
4787 * When a subdissector requests reassembly at the end of the
4788 * connection (DESEGMENT_UNTIL_FIN), then it is not
4789 * possible for an earlier segment to complete reassembly
4790 * (more_frags for fragment_add is always true). Thus we do not
4791 * have to worry about increasing the fragment length here.
4793 fragment_reset_tot_len(&tcp_reassembly_table, pinfo,
4794 msp->first_frame, msp,
4795 MAX(seq + len, msp->nxtpdu) - msp->seq);
4798 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,
4799 pinfo, msp->first_frame, msp,
4800 seq - msp->seq, len,
4801 (LT_SEQ (nxtseq,msp->nxtpdu)) );
4803 if (!PINFO_FD_VISITED(pinfo) && ipfd_head
4804 && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
4805 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
4807 /* If we consumed the entire segment there is no
4808 * other pdu starting anywhere inside this segment.
4809 * So update nxtpdu to point at least to the start
4810 * of the next segment.
4811 * (If the subdissector asks for even more data we
4812 * will advance nxtpdu even further later down in
4813 * the code.)
4815 if (LT_SEQ(msp->nxtpdu, nxtseq)) {
4816 msp->nxtpdu = nxtseq;
4820 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)) {
4821 /* Remember when all segments are ready to avoid subsequent
4822 * out-of-order packets from extending this MSP. If a subsdissector
4823 * needs more segments, the flag will be cleared below. */
4824 if (ipfd_head) {
4825 msp->flags |= MSP_FLAGS_GOT_ALL_SEGMENTS;
4829 if( (msp->nxtpdu < nxtseq)
4830 && (msp->nxtpdu >= seq)
4831 && (len > 0)) {
4832 another_pdu_follows=msp->nxtpdu - seq;
4834 } else if (has_gap) {
4835 /* This is an OOO segment with a gap and past the known end of
4836 * the current MSP, if any. We don't know for certain which MSP
4837 * it belongs to, and the reassembly functions don't let us remove
4838 * fragment items added by mistake. Keep it around in a separate
4839 * structure, and add it later.
4841 * On the second and later passes, we know that this gap will
4842 * never be filled in, so we could hand the segment to the
4843 * subdissector anyway. However, we want dissection to be
4844 * consistent between passes.
4846 if (!PINFO_FD_VISITED(pinfo)) {
4847 ooo_segment_item *fd;
4848 fd = wmem_new0(wmem_file_scope(), ooo_segment_item);
4849 fd->frame = pinfo->num;
4850 fd->seq = seq;
4851 fd->len = nxtseq - seq;
4852 /* We only enter here if dissect_tcp set can_desegment,
4853 * which means that these bytes exist. */
4854 fd->data = tvb_memdup(wmem_file_scope(), tvb, offset, fd->len);
4855 wmem_list_append_sorted(tcpd->fwd->ooo_segments, fd, compare_ooo_segment_item);
4857 ipfd_head = NULL;
4858 } else {
4859 /* This segment was not found in our table, so it doesn't
4860 * contain a continuation of a higher-level PDU.
4861 * Call the normal subdissector.
4865 * Supply the sequence number of this segment. We set this here
4866 * because this segment could be after another in the same packet,
4867 * in which case seq was incremented at the end of the loop.
4869 tcpinfo->seq = seq;
4871 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
4872 sport, dport, 0, 0, false, tcpd, tcpinfo);
4874 /* Unless it failed to dissect any data at all, the subdissector
4875 * might have changed the addresses and/or ports. Save them, and
4876 * set them back to the original values temporarily so that the
4877 * fragment functions work correctly (including in any later PDU.)
4879 * (If we didn't dissect any data, the subdissector *shouldn't*
4880 * have changed the addresses or ports, so don't save them, but
4881 * restore them just in case.)
4883 if (!(pinfo->desegment_len && pinfo->desegment_offset == 0)) {
4884 save_endpoint(pinfo, &new_endpoint);
4886 restore_endpoint(pinfo, &orig_endpoint);
4887 called_dissector = true;
4889 /* Did the subdissector ask us to desegment some more data
4890 * before it could handle the packet?
4891 * If so we'll have to handle that later.
4893 if(pinfo->desegment_len) {
4894 must_desegment = true;
4897 * Set "deseg_offset" to the offset in "tvb"
4898 * of the first byte of data that the
4899 * subdissector didn't process.
4901 deseg_offset = offset + pinfo->desegment_offset;
4904 /* Either no desegmentation is necessary, or this is
4905 * segment contains the beginning but not the end of
4906 * a higher-level PDU and thus isn't completely
4907 * desegmented.
4909 ipfd_head = NULL;
4913 /* is it completely desegmented? */
4914 if (ipfd_head) {
4916 * Yes, we think it is.
4917 * We only call subdissector for the last segment.
4918 * Note that the last segment may include more than what
4919 * we needed.
4921 if (ipfd_head->reassembled_in == pinfo->num && ipfd_head->reas_in_layer_num == pinfo->curr_layer_num) {
4923 * OK, this is the last segment.
4924 * Let's call the subdissector with the desegmented
4925 * data.
4927 tvbuff_t *next_tvb;
4929 /* create a new TVB structure for desegmented data */
4930 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
4932 /* add desegmented data to the data source list */
4933 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
4936 * Supply the sequence number of the first of the
4937 * reassembled bytes.
4939 tcpinfo->seq = msp->seq;
4941 /* indicate that this is reassembled data */
4942 tcpinfo->is_reassembled = true;
4944 /* call subdissector */
4945 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, sport,
4946 dport, 0, 0, false, tcpd, tcpinfo);
4948 /* Unless it failed to dissect any data at all, the subdissector
4949 * might have changed the addresses and/or ports. Save them, and
4950 * set them back to the original values temporarily so that the
4951 * fragment functions work correctly (including in any later PDU.)
4953 * (If we didn't dissect any data, the subdissector *shouldn't*
4954 * have changed the addresses or ports, so don't save them, but
4955 * restore them just in case.)
4957 if (!(pinfo->desegment_len && pinfo->desegment_offset == 0)) {
4958 save_endpoint(pinfo, &new_endpoint);
4960 restore_endpoint(pinfo, &orig_endpoint);
4961 called_dissector = true;
4964 * OK, did the subdissector think it was completely
4965 * desegmented, or does it think we need even more
4966 * data?
4968 if (pinfo->desegment_len) {
4970 * "desegment_len" isn't 0, so it needs more data
4971 * to fully dissect the current MSP. msp->nxtpdu was
4972 * not accurate and needs to be updated.
4974 * This can happen if a dissector asked for one
4975 * more segment (but didn't know exactly how much data)
4976 * or if segments were added out of order.
4978 * This is opposed to the current MSP being completely
4979 * desegmented, but the stuff at the end of the
4980 * current frame past last_fragment_len starting a new
4981 * higher-level PDU that may also need desegmentation.
4982 * That case is handled on the next loop.
4984 * We want to keep the same dissection and protocol layer
4985 * numbers on subsequent passes.
4987 * If "desegment_offset" is 0, then nothing in the reassembled
4988 * TCP segments was dissected, so remove the data source.
4990 if (pinfo->desegment_offset == 0) {
4991 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)) {
4992 msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS;
4994 remove_last_data_source(pinfo);
4995 fragment_set_partial_reassembly(&tcp_reassembly_table,
4996 pinfo, msp->first_frame,
4997 msp);
4998 } else {
4999 /* If "desegment_offset" is not 0, then a PDU in the
5000 * reassembled segments was dissected, but some stuff
5001 * that was added previously is part of a later PDU.
5003 if (LE_SEQ(msp->seq + pinfo->desegment_offset, seq)) {
5004 /* If we don't use anything from the current frame's
5005 * segment, then we can't split the msp. The frames of
5006 * the earlier PDU weren't reassembled until now, so
5007 * they need to point to a reassembled_in frame here
5008 * or later.
5010 * Since this segment is the first of newly contiguous
5011 * segments, this means the subdissector is asking for
5012 * fewer bytes than it did before.
5013 * XXX: Report this as a dissector bug?
5015 if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)) {
5016 msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS;
5018 fragment_set_partial_reassembly(&tcp_reassembly_table,
5019 pinfo, msp->first_frame,
5020 msp);
5021 } else {
5022 /* If we did use bytes from the current segment, then
5023 * we want to split the MSP; the earlier part is
5024 * dissected in this frame on the first pass, so for
5025 * consistency we want to do so on future passes, but
5026 * the latter part we cannot dissect until later.
5027 * We only need to do this on the first pass; split_msp
5028 * truncates the msp so we don't get here a second
5029 * time.
5031 /* nxtpdu adjustment for the new msp is the same. */
5032 if (!PINFO_FD_VISITED(pinfo)) {
5033 /* We don't need to clear MSP_FLAGS_GOT_ALL_SEGMENTS
5034 * since we are spliting the MSP.
5036 msp = split_msp(pinfo, msp, tcpd);
5038 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
5042 if (!PINFO_FD_VISITED(pinfo)) {
5043 /* Update msp->nxtpdu to point to the new next
5044 * pdu boundary.
5045 * We only do this on the first pass, though we shouldn't
5046 * get here on a second pass (since we truncated the msp.)
5048 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
5049 /* We want reassembly of at least one
5050 * more segment so set the nxtpdu
5051 * boundary to one byte into the next
5052 * segment.
5053 * This means that the next segment
5054 * will complete reassembly even if it
5055 * is only one single byte in length.
5056 * If this is an OoO segment, then increment
5057 * the MSP end.
5059 msp->nxtpdu = MAX(seq + tvb_reported_length_remaining(tvb, offset), msp->nxtpdu) + 1;
5060 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
5061 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5062 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
5063 /* This is not the first segment, and we thought the
5064 * reassembly would be done now, but now know we must
5065 * desgment until FIN. (E.g., HTTP Response with headers
5066 * split across segments, and no Content-Length or
5067 * Transfer-Encoding (RFC 7230, Section 3.3.3, case 7.)
5068 * For the same reasons as below when we encounter
5069 * DESEGMENT_UNTIL_FIN on the first segment, give
5070 * msp->nxtpdu a big (but not too big) offset so
5071 * reassembly will pick up the segments later.
5073 msp->nxtpdu = msp->seq + 0x40000000;
5074 } else {
5075 if (seq + last_fragment_len >= msp->nxtpdu) {
5076 /* This is the segment (overlapping) the end of
5077 * the MSP.
5079 msp->nxtpdu = seq + last_fragment_len + pinfo->desegment_len;
5080 } else {
5081 /* This is a segment before the end of the MSP, so
5082 * it must be an out-of-order segment that completed
5083 * the MSP. The requested additional data is
5084 * relative to that end.
5086 msp->nxtpdu += pinfo->desegment_len;
5091 /* Since we need at least some more data
5092 * there can be no pdu following in the
5093 * tail of this segment.
5095 another_pdu_follows = 0;
5096 offset += last_fragment_len;
5097 seq += last_fragment_len;
5098 if (tvb_captured_length_remaining(tvb, offset) > 0)
5099 goto again;
5100 } else {
5102 * Show the stuff in this TCP segment as
5103 * just raw TCP segment data.
5105 nbytes = another_pdu_follows > 0
5106 ? another_pdu_follows
5107 : tvb_reported_length_remaining(tvb, offset);
5108 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
5109 nbytes, NULL, "TCP segment data (%u byte%s)", nbytes,
5110 plurality(nbytes, "", "s"));
5112 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
5117 if (must_desegment) {
5119 * The sequence number at which the stuff to be desegmented
5120 * starts is the sequence number of the byte at an offset
5121 * of "deseg_offset" into "tvb".
5123 * The sequence number of the byte at an offset of "offset"
5124 * is "seq", i.e. the starting sequence number of this
5125 * segment, so the sequence number of the byte at
5126 * "deseg_offset" is "seq + (deseg_offset - offset)".
5128 deseg_seq = seq + (deseg_offset - offset);
5130 /* We have to create some structures in our table but
5131 * this is something we only do the first time we see this
5132 * packet. */
5133 if (!PINFO_FD_VISITED(pinfo)) {
5134 /* If the dissector requested "reassemble until FIN"
5135 * just set this flag for the flow and let reassembly
5136 * proceed at normal. We will check/pick up these
5137 * reassembled PDUs later down in dissect_tcp() when checking
5138 * for the FIN flag.
5140 if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5141 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
5143 if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)) {
5144 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
5145 /* The subdissector asked to reassemble using the
5146 * entire next segment.
5147 * Just ask reassembly for one more byte
5148 * but set this msp flag so we can pick it up
5149 * above.
5151 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
5152 nxtseq+1, tcpd->fwd->multisegment_pdus);
5153 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
5154 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5156 * The subdissector asked to reassemble at the end of the
5157 * connection. That will be done in dissect_tcp, but here we
5158 * have to ask reassembly to collect all future segments.
5159 * Note that TCP_FLOW_REASSEMBLE_UNTIL_FIN was set before,
5160 * this ensures that OoO detection is skipped.
5161 * The exact nxtpdu offset does not matter, but it should be
5162 * smaller than half of the maximum 32-bit unsigned integer
5163 * to allow detection of sequence number wraparound, and
5164 * larger than the largest possible stream size. Hopefully
5165 * 1GiB (0x40000000 bytes) should be enough.
5167 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
5168 nxtseq+0x40000000, tcpd->fwd->multisegment_pdus);
5169 } else {
5170 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
5171 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
5174 /* add this segment as the first one for this new pdu */
5175 fragment_add(&tcp_reassembly_table, tvb, deseg_offset,
5176 pinfo, msp->first_frame, msp,
5177 0, nxtseq - deseg_seq,
5178 LT_SEQ(nxtseq, msp->nxtpdu));
5180 } else {
5181 /* If this is not the first time we have seen the packet, then
5182 * the MSP should already be created. Retrieve it to see if we
5183 * know what later frame the PDU is reassembled in.
5185 if (tcpd && (msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, deseg_seq))) {
5186 ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp);
5191 if (!called_dissector || pinfo->desegment_len != 0) {
5192 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
5193 ipfd_head->reassembled_in != pinfo->num &&
5194 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
5196 * We know what other frame this PDU is reassembled in;
5197 * let the user know.
5199 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,
5200 0, ipfd_head->reassembled_in);
5201 proto_item_set_generated(item);
5205 * Either we didn't call the subdissector at all (i.e.,
5206 * this is a segment that contains the middle of a
5207 * higher-level PDU, but contains neither the beginning
5208 * nor the end), or the subdissector couldn't dissect it
5209 * all, as some data was missing (i.e., it set
5210 * "pinfo->desegment_len" to the amount of additional
5211 * data it needs).
5213 if (pinfo->desegment_offset == 0) {
5215 * It couldn't, in fact, dissect any of it (the
5216 * first byte it couldn't dissect is at an offset
5217 * of "pinfo->desegment_offset" from the beginning
5218 * of the payload, and that's 0).
5219 * Just mark this as TCP.
5221 if (first_pdu && ipfd_head != NULL && ipfd_head->reassembled_in != 0) {
5222 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[TCP PDU reassembled in %u]",
5223 ipfd_head->reassembled_in);
5228 * Show what's left in the packet as just raw TCP segment
5229 * data. (It's possible that another PDU follows in the case
5230 * of an out of order frame that is part of two MSPs.)
5231 * XXX - remember what protocol the last subdissector
5232 * was, and report it as a continuation of that, instead?
5234 nbytes = another_pdu_follows ? another_pdu_follows : tvb_reported_length_remaining(tvb, deseg_offset);
5236 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, deseg_offset,
5237 nbytes, NULL, "TCP segment data (%u byte%s)", nbytes,
5238 plurality(nbytes, "", "s"));
5240 pinfo->can_desegment = 0;
5241 pinfo->desegment_offset = 0;
5242 pinfo->desegment_len = 0;
5244 if(another_pdu_follows) {
5245 /* there was another pdu following this one. */
5246 pinfo->can_desegment = 2;
5247 /* we also have to prevent the dissector from changing the
5248 * PROTOCOL and INFO columns since what follows may be an
5249 * incomplete PDU and we don't want it be changed back from
5250 * <Protocol> to <TCP>
5252 col_set_fence(pinfo->cinfo, COL_INFO);
5253 cleared_writable |= col_get_writable(pinfo->cinfo, COL_PROTOCOL);
5254 col_set_writable(pinfo->cinfo, COL_PROTOCOL, false);
5255 first_pdu = false;
5256 offset += another_pdu_follows;
5257 seq += another_pdu_follows;
5258 goto again;
5259 } else {
5260 /* remove any blocking set above otherwise the
5261 * proto,colinfo tap will break
5263 if(cleared_writable) {
5264 col_set_writable(pinfo->cinfo, COL_PROTOCOL, true);
5268 clean_exit:
5269 /* Restore the addresses and ports to whatever they were after
5270 * the last segment that successfully dissected some data, if any.
5272 restore_endpoint(pinfo, &new_endpoint);
5275 void
5276 tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5277 bool proto_desegment, unsigned fixed_len,
5278 unsigned (*get_pdu_len)(packet_info *, tvbuff_t *, int, void*),
5279 dissector_t dissect_pdu, void* dissector_data)
5281 volatile int offset = 0;
5282 int offset_before;
5283 unsigned captured_length_remaining;
5284 volatile unsigned plen;
5285 unsigned length;
5286 tvbuff_t *next_tvb;
5287 proto_item *item=NULL;
5288 const char *saved_proto;
5289 uint8_t curr_layer_num;
5290 wmem_list_frame_t *frame;
5292 tcp_endpoint_t orig_endpoint;
5294 save_endpoint(pinfo, &orig_endpoint);
5296 while (tvb_reported_length_remaining(tvb, offset) > 0) {
5298 * We use "tvb_ensure_captured_length_remaining()" to make
5299 * sure there actually *is* data remaining. The protocol
5300 * we're handling could conceivably consists of a sequence of
5301 * fixed-length PDUs, and therefore the "get_pdu_len" routine
5302 * might not actually fetch anything from the tvbuff, and thus
5303 * might not cause an exception to be thrown if we've run past
5304 * the end of the tvbuff.
5306 * This means we're guaranteed that "captured_length_remaining" is positive.
5308 captured_length_remaining = tvb_ensure_captured_length_remaining(tvb, offset);
5311 * Can we do reassembly?
5313 if (proto_desegment && pinfo->can_desegment) {
5315 * Yes - is the fixed-length part of the PDU split across segment
5316 * boundaries?
5318 if (captured_length_remaining < fixed_len) {
5320 * Yes. Tell the TCP dissector where the data for this message
5321 * starts in the data it handed us and that we need "some more
5322 * data." Don't tell it exactly how many bytes we need because
5323 * if/when we ask for even more (after the header) that will
5324 * break reassembly.
5326 pinfo->desegment_offset = offset;
5327 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
5328 return;
5333 * Get the length of the PDU.
5335 plen = (*get_pdu_len)(pinfo, tvb, offset, dissector_data);
5336 if (plen == 0) {
5338 * Support protocols which have a variable length which cannot
5339 * always be determined within the given fixed_len.
5342 * If another segment was requested but we can't do reassembly,
5343 * abort and warn about the unreassembled packet.
5345 THROW_ON(!(proto_desegment && pinfo->can_desegment), FragmentBoundsError);
5347 * Tell the TCP dissector where the data for this message
5348 * starts in the data it handed us, and that we need one
5349 * more segment, and return.
5351 pinfo->desegment_offset = offset;
5352 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
5353 return;
5355 if (plen < fixed_len) {
5357 * Either:
5359 * 1) the length value extracted from the fixed-length portion
5360 * doesn't include the fixed-length portion's length, and
5361 * was so large that, when the fixed-length portion's
5362 * length was added to it, the total length overflowed;
5364 * 2) the length value extracted from the fixed-length portion
5365 * includes the fixed-length portion's length, and the value
5366 * was less than the fixed-length portion's length, i.e. it
5367 * was bogus.
5369 * Report this as a bounds error.
5371 show_reported_bounds_error(tvb, pinfo, tree);
5372 return;
5375 /* give a hint to TCP where the next PDU starts
5376 * so that it can attempt to find it in case it starts
5377 * somewhere in the middle of a segment.
5379 if(!pinfo->fd->visited && tcp_analyze_seq) {
5380 unsigned remaining_bytes;
5381 remaining_bytes = tvb_reported_length_remaining(tvb, offset);
5382 if(plen>remaining_bytes) {
5383 pinfo->want_pdu_tracking=2;
5384 pinfo->bytes_until_next_pdu=plen-remaining_bytes;
5389 * Can we do reassembly?
5391 if (proto_desegment && pinfo->can_desegment) {
5393 * Yes - is the PDU split across segment boundaries?
5395 if (captured_length_remaining < plen) {
5397 * Yes. Tell the TCP dissector where the data for this message
5398 * starts in the data it handed us, and how many more bytes we
5399 * need, and return.
5401 pinfo->desegment_offset = offset;
5402 pinfo->desegment_len = plen - captured_length_remaining;
5403 return;
5407 curr_layer_num = pinfo->curr_layer_num-1;
5408 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
5409 while (frame && (proto_tcp != (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame)))) {
5410 frame = wmem_list_frame_prev(frame);
5411 curr_layer_num--;
5413 #if 0
5414 if (captured_length_remaining >= plen || there are more packets)
5416 #endif
5418 * Display the PDU length as a field
5420 item=proto_tree_add_uint((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_tcp, curr_layer_num),
5421 hf_tcp_pdu_size,
5422 tvb, offset, plen, plen);
5423 proto_item_set_generated(item);
5424 #if 0
5425 } else {
5426 item = proto_tree_add_expert_format((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_tcp, curr_layer_num),
5427 tvb, offset, -1,
5428 "PDU Size: %u cut short at %u",plen,captured_length_remaining);
5429 proto_item_set_generated(item);
5431 #endif
5434 * Construct a tvbuff containing the amount of the payload we have
5435 * available. Make its reported length the amount of data in the PDU.
5437 length = captured_length_remaining;
5438 if (length > plen)
5439 length = plen;
5440 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, plen);
5441 if (!(proto_desegment && pinfo->can_desegment)) {
5442 if (plen > length) {
5443 /* If we can't do reassembly but the PDU is split across
5444 * segment boundaries, mark the tvbuff as a fragment so
5445 * we throw FragmentBoundsError instead of malformed
5446 * errors.
5448 tvb_set_fragment(next_tvb);
5454 * Dissect the PDU.
5456 * If it gets an error that means there's no point in
5457 * dissecting any more PDUs, rethrow the exception in
5458 * question.
5460 * If it gets any other error, report it and continue, as that
5461 * means that PDU got an error, but that doesn't mean we should
5462 * stop dissecting PDUs within this frame or chunk of reassembled
5463 * data.
5465 saved_proto = pinfo->current_proto;
5466 restore_endpoint(pinfo, &orig_endpoint);
5467 TRY {
5468 (*dissect_pdu)(next_tvb, pinfo, tree, dissector_data);
5470 CATCH_NONFATAL_ERRORS {
5471 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
5474 * Restore the saved protocol as well; we do this after
5475 * show_exception(), so that the "Malformed packet" indication
5476 * shows the protocol for which dissection failed.
5478 pinfo->current_proto = saved_proto;
5480 ENDTRY;
5483 * Step to the next PDU.
5484 * Make sure we don't overflow.
5486 offset_before = offset;
5487 offset += plen;
5488 if (offset <= offset_before)
5489 break;
5493 static void
5494 tcp_info_append_uint(packet_info *pinfo, const char *abbrev, uint32_t val)
5496 /* fstr(" %s=%u", abbrev, val) */
5497 col_append_str_uint(pinfo->cinfo, COL_INFO, abbrev, val, " ");
5500 static void
5501 tcp_info_append_hex_uint(packet_info *pinfo, const char *abbrev, uint32_t val)
5503 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%X", abbrev, val);
5506 static bool
5507 tcp_option_len_check(proto_item* length_item, packet_info *pinfo, unsigned len, unsigned optlen)
5509 if (len != optlen) {
5510 /* Bogus - option length isn't what it's supposed to be for this option. */
5511 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5512 "option length should be %u", optlen);
5513 return false;
5516 return true;
5519 static int
5520 dissect_tcpopt_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_)
5522 proto_item *item;
5523 proto_tree *exp_tree;
5524 int offset = 0, optlen = tvb_reported_length(tvb);
5526 item = proto_tree_add_item(tree, proto_tcp_option_unknown, tvb, offset, -1, ENC_NA);
5527 exp_tree = proto_item_add_subtree(item, ett_tcp_unknown_opt);
5529 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5530 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5531 if (optlen > 2)
5532 proto_tree_add_item(exp_tree, hf_tcp_option_unknown_payload, tvb, offset + 2, optlen - 2, ENC_NA);
5534 return tvb_captured_length(tvb);
5537 static int
5538 dissect_tcpopt_default_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, int ett)
5540 proto_item *item;
5541 proto_tree *exp_tree;
5542 proto_item *length_item;
5543 int offset = 0;
5545 item = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA);
5546 exp_tree = proto_item_add_subtree(item, ett);
5548 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5549 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5551 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), 2))
5552 return tvb_captured_length(tvb);
5554 return tvb_captured_length(tvb);
5557 static int
5558 dissect_tcpopt_recbound(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5560 return dissect_tcpopt_default_option(tvb, pinfo, tree, proto_tcp_option_scpsrec, ett_tcp_opt_recbound);
5563 static int
5564 dissect_tcpopt_correxp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5566 return dissect_tcpopt_default_option(tvb, pinfo, tree, proto_tcp_option_scpscor, ett_tcp_opt_scpscor);
5569 static void
5570 dissect_tcpopt_tfo_payload(tvbuff_t *tvb, int offset, unsigned optlen,
5571 packet_info *pinfo, proto_tree *exp_tree, void *data)
5573 proto_item *ti;
5574 struct tcpheader *tcph = (struct tcpheader*)data;
5575 struct tcp_analysis *tcpd;
5577 if (optlen == 2) {
5578 /* Fast Open Cookie Request */
5579 proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie_request,
5580 tvb, offset, 2, ENC_NA);
5581 col_append_str(pinfo->cinfo, COL_INFO, " TFO=R");
5582 } else if (optlen > 2) {
5583 /* Fast Open Cookie */
5584 ti = proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie,
5585 tvb, offset + 2, optlen - 2, ENC_NA);
5586 col_append_str(pinfo->cinfo, COL_INFO, " TFO=C");
5587 if ((tcph->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) {
5588 expert_add_info(pinfo, ti, &ei_tcp_analysis_tfo_syn);
5590 /* Is this a SYN with data and the cookie? */
5591 if (tcph->th_have_seglen && tcph->th_seglen) {
5592 tcpd = get_tcp_conversation_data(NULL, pinfo);
5593 if (tcpd) {
5594 tcpd->tfo_syn_data = true;
5601 static int
5602 dissect_tcpopt_tfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5604 proto_item *item;
5605 proto_tree *exp_tree;
5606 int offset = 0;
5608 item = proto_tree_add_item(tree, proto_tcp_option_tfo, tvb, offset, -1, ENC_NA);
5609 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);
5610 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5611 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5613 dissect_tcpopt_tfo_payload(tvb, offset, tvb_reported_length(tvb), pinfo, exp_tree, data);
5614 return tvb_captured_length(tvb);
5618 * TCP ACK Rate Request option is based on
5619 * https://datatracker.ietf.org/doc/html/draft-gomez-tcpm-ack-rate-request-06
5622 #define TCPOPT_TARR_RATE_MASK 0xfe
5623 #define TCPOPT_TARR_RESERVED_MASK 0x01
5624 #define TCPOPT_TARR_RATE_SHIFT 1
5626 static void
5627 dissect_tcpopt_tarr_data(tvbuff_t *tvb, int data_offset, unsigned data_len,
5628 packet_info *pinfo, proto_tree *tree, proto_item *item, void *data _U_)
5630 uint8_t rate;
5632 switch (data_len) {
5633 case 0:
5634 col_append_str(pinfo->cinfo, COL_INFO, " TARR");
5635 break;
5636 case 1:
5637 rate = (tvb_get_uint8(tvb, data_offset) & TCPOPT_TARR_RATE_MASK) >> TCPOPT_TARR_RATE_SHIFT;
5638 proto_tree_add_item(tree, hf_tcp_option_tarr_rate, tvb, data_offset, 1, ENC_BIG_ENDIAN);
5639 proto_tree_add_item(tree, hf_tcp_option_tarr_reserved, tvb, data_offset, 1, ENC_BIG_ENDIAN);
5640 tcp_info_append_uint(pinfo, "TARR", rate);
5641 proto_item_append_text(item, " %u", rate);
5642 break;
5646 static void
5647 dissect_tcpopt_acc_ecn_data(tvbuff_t *tvb, int data_offset, unsigned data_len,
5648 bool is_order_0, packet_info *pinfo, proto_tree *tree, proto_item *item, void *data _U_)
5650 struct tcp_analysis *tcpd;
5651 uint32_t ee0b, eceb, ee1b;
5653 switch (data_len) {
5654 case 0:
5655 col_append_str(pinfo->cinfo, COL_INFO, " AccECN");
5656 break;
5657 case 3:
5658 if (is_order_0) {
5659 ee0b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5660 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5661 proto_item_append_text(item, " (Order 0): EE0B %u", ee0b);
5662 tcp_info_append_uint(pinfo, "EE0B", ee0b);
5663 } else {
5664 ee1b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5665 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5666 proto_item_append_text(item, " (Order 1): EE1B %u", ee1b);
5667 tcp_info_append_uint(pinfo, "EE1B", ee1b);
5669 break;
5670 case 6:
5671 if (is_order_0) {
5672 ee0b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5673 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5674 tcp_info_append_uint(pinfo, "EE0B", ee0b);
5675 } else {
5676 ee1b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5677 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5678 tcp_info_append_uint(pinfo, "EE1B", ee1b);
5680 eceb = tvb_get_uint24(tvb, data_offset + 3, ENC_BIG_ENDIAN);
5681 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_eceb, tvb, data_offset + 3, 3, ENC_BIG_ENDIAN);
5682 tcp_info_append_uint(pinfo, "ECEB", eceb);
5683 if (is_order_0) {
5684 proto_item_append_text(item, " (Order 0): EE0B %u, ECEB %u", ee0b, eceb);
5685 } else {
5686 proto_item_append_text(item, " (Order 1): EE1B %u, ECEB %u", ee1b, eceb);
5688 break;
5689 case 9:
5690 if (is_order_0) {
5691 ee0b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5692 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5693 tcp_info_append_uint(pinfo, "EE0B", ee0b);
5694 } else {
5695 ee1b = tvb_get_uint24(tvb, data_offset, ENC_BIG_ENDIAN);
5696 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN);
5697 tcp_info_append_uint(pinfo, "EE1B", ee1b);
5699 eceb = tvb_get_uint24(tvb, data_offset + 3, ENC_BIG_ENDIAN);
5700 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_eceb, tvb, data_offset + 3, 3, ENC_BIG_ENDIAN);
5701 tcp_info_append_uint(pinfo, "ECEB", eceb);
5702 if (is_order_0) {
5703 ee1b = tvb_get_uint24(tvb, data_offset + 6, ENC_BIG_ENDIAN);
5704 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset + 6, 3, ENC_BIG_ENDIAN);
5705 tcp_info_append_uint(pinfo, "EE1B", ee1b);
5706 proto_item_append_text(item, " (Order 0): EE0B %u, ECEB %u, EE1B %u", ee0b, eceb, ee1b);
5707 } else {
5708 ee0b = tvb_get_uint24(tvb, data_offset + 6, ENC_BIG_ENDIAN);
5709 proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset + 6, 3, ENC_BIG_ENDIAN);
5710 tcp_info_append_uint(pinfo, "EE0B", ee0b);
5711 proto_item_append_text(item, " (Order 1): EE1B %u, ECEB %u, EE0B %u", ee1b, eceb, ee0b);
5713 break;
5715 tcpd = get_tcp_conversation_data(NULL, pinfo);
5716 if (tcpd != NULL) {
5717 tcpd->had_acc_ecn_option = true;
5721 static int
5722 dissect_tcpopt_acc_ecn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
5724 proto_item *length_item, *item;
5725 proto_tree *acc_ecn_tree;
5726 int offset;
5727 uint8_t kind, length;
5729 offset = 0;
5730 item = proto_tree_add_item(tree, proto_tcp_option_acc_ecn, tvb, offset, -1, ENC_NA);
5731 acc_ecn_tree = proto_item_add_subtree(item, ett_tcp_option_acc_ecn);
5732 kind = tvb_get_uint8(tvb, offset);
5733 proto_tree_add_item(acc_ecn_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5734 offset += 1;
5735 length = tvb_get_uint8(tvb, offset);
5736 length_item = proto_tree_add_item(acc_ecn_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
5737 offset += 1;
5738 if (length != 2 && length != 5 && length != 8 && length != 11) {
5739 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5740 "option length should be 2, 5, 8, or 11 instead of %u", length);
5741 } else {
5742 dissect_tcpopt_acc_ecn_data(tvb, offset, length - 2, kind == TCPOPT_ACC_ECN_0, pinfo, acc_ecn_tree, item, data);
5744 return tvb_captured_length(tvb);
5747 static int
5748 dissect_tcpopt_exp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5750 proto_item *item, *length_item;
5751 proto_tree *exp_tree;
5752 uint16_t exid;
5753 uint8_t kind;
5754 int offset = 0, optlen = tvb_reported_length(tvb);
5756 item = proto_tree_add_item(tree, proto_tcp_option_exp, tvb, offset, -1, ENC_NA);
5757 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);
5758 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5759 kind = tvb_get_uint8(tvb, offset);
5760 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5761 if (tcp_exp_options_rfc6994) {
5762 if (optlen >= TCPOLEN_EXP_MIN) {
5763 exid = tvb_get_ntohs(tvb, offset + 2);
5764 proto_tree_add_item(exp_tree, hf_tcp_option_exp_exid, tvb,
5765 offset + 2, 2, ENC_BIG_ENDIAN);
5766 proto_item_append_text(item, ": %s", val_to_str_const(exid, tcp_exid_vs, "Unknown"));
5767 switch (exid) {
5768 case TCPEXID_TARR:
5769 if (optlen != 4 && optlen != 5) {
5770 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5771 "option length should be 4 or 5 instead of %d",
5772 optlen);
5773 } else {
5774 dissect_tcpopt_tarr_data(tvb, offset + 4, optlen - 4,
5775 pinfo, exp_tree, item, data);
5777 break;
5778 case 0xACC0: /* draft-ietf-tcpm-accurate-ecn-20 */
5779 case 0xACC1:
5780 if (optlen != 4 && optlen != 7 && optlen != 10 && optlen != 13) {
5781 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5782 "option length should be 4, 7, 10, or 13 instead of %d",
5783 optlen);
5784 } else {
5785 proto_item_append_text(item, ": Accurate ECN");
5786 dissect_tcpopt_acc_ecn_data(tvb, offset + 4, optlen - 4,
5787 exid == 0xACC0, pinfo, exp_tree,
5788 item, data);
5790 break;
5791 case TCPEXID_FO:
5792 dissect_tcpopt_tfo_payload(tvb, offset + 2, optlen - 2, pinfo, exp_tree, data);
5793 break;
5794 default:
5795 if (optlen > TCPOLEN_EXP_MIN) {
5796 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,
5797 offset + TCPOLEN_EXP_MIN,
5798 optlen - TCPOLEN_EXP_MIN, ENC_NA);
5800 tcp_info_append_hex_uint(pinfo, "ExID", exid);
5801 break;
5803 } else {
5804 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
5805 "option length %u smaller than 4", optlen);
5807 } else {
5808 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,
5809 offset + 2, optlen - 2, ENC_NA);
5810 tcp_info_append_uint(pinfo, "Exp", (kind == TCPOPT_EXP_FD) ? 1 : 2);
5812 return tvb_captured_length(tvb);
5815 static int
5816 dissect_tcpopt_sack_perm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
5818 proto_item *item;
5819 proto_tree *exp_tree;
5820 proto_item *length_item;
5821 int offset = 0;
5822 struct tcpheader *tcph = (struct tcpheader *)data;
5824 item = proto_tree_add_item(tree, proto_tcp_option_sack_perm, tvb, offset, -1, ENC_NA);
5825 exp_tree = proto_item_add_subtree(item, ett_tcp_option_sack_perm);
5827 if (!(tcph->th_flags & TH_SYN))
5829 expert_add_info(pinfo, item, &ei_tcp_option_sack_perm_present);
5832 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5833 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5835 col_append_str(pinfo->cinfo, COL_INFO, " SACK_PERM");
5837 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SACK_PERM))
5838 return tvb_captured_length(tvb);
5840 return tvb_captured_length(tvb);
5843 static int
5844 dissect_tcpopt_mss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
5846 proto_item *item;
5847 proto_tree *exp_tree;
5848 proto_item *length_item;
5849 int offset = 0;
5850 struct tcpheader *tcph = (struct tcpheader *)data;
5851 uint32_t mss;
5853 item = proto_tree_add_item(tree, proto_tcp_option_mss, tvb, offset, -1, ENC_NA);
5854 exp_tree = proto_item_add_subtree(item, ett_tcp_option_mss);
5856 if (!(tcph->th_flags & TH_SYN))
5858 expert_add_info(pinfo, item, &ei_tcp_option_mss_present);
5861 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5862 length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5864 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_MSS))
5865 return tvb_captured_length(tvb);
5867 proto_tree_add_item_ret_uint(exp_tree, hf_tcp_option_mss_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN, &mss);
5868 proto_item_append_text(item, ": %u bytes", mss);
5869 tcp_info_append_uint(pinfo, "MSS", mss);
5871 return tvb_captured_length(tvb);
5874 /* The window scale extension is defined in RFC 1323 */
5875 static int
5876 dissect_tcpopt_wscale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5878 uint8_t val;
5879 uint32_t shift;
5880 proto_item *wscale_pi, *shift_pi, *gen_pi;
5881 proto_tree *wscale_tree;
5882 proto_item *length_item;
5883 int offset = 0;
5884 struct tcp_analysis *tcpd;
5886 /* find the conversation for this TCP session and its stored data */
5887 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
5888 tcpd=get_tcp_conversation_data_idempotent(stratconv);
5890 wscale_pi = proto_tree_add_item(tree, proto_tcp_option_wscale, tvb, offset, -1, ENC_NA);
5891 wscale_tree = proto_item_add_subtree(wscale_pi, ett_tcp_option_wscale);
5893 proto_tree_add_item(wscale_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
5894 offset += 1;
5896 length_item = proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
5897 offset += 1;
5899 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_WINDOW))
5900 return tvb_captured_length(tvb);
5902 shift_pi = proto_tree_add_item_ret_uint(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1, ENC_BIG_ENDIAN, &shift);
5903 if (shift > 14) {
5904 /* RFC 1323: "If a Window Scale option is received with a shift.cnt
5905 * value exceeding 14, the TCP should log the error but use 14 instead
5906 * of the specified value." */
5907 shift = 14;
5908 expert_add_info(pinfo, shift_pi, &ei_tcp_option_wscale_shift_invalid);
5911 gen_pi = proto_tree_add_uint(wscale_tree, hf_tcp_option_wscale_multiplier, tvb,
5912 offset, 1, 1 << shift);
5913 proto_item_set_generated(gen_pi);
5914 val = tvb_get_uint8(tvb, offset);
5916 proto_item_append_text(wscale_pi, ": %u (multiply by %u)", val, 1 << shift);
5918 tcp_info_append_uint(pinfo, "WS", 1 << shift);
5920 if(!pinfo->fd->visited) {
5921 pdu_store_window_scale_option(shift, tcpd);
5924 return tvb_captured_length(tvb);
5927 static int
5928 dissect_tcpopt_sack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
5930 proto_tree *field_tree = NULL;
5931 proto_item *tf, *ti;
5932 uint32_t leftedge, rightedge;
5933 struct tcp_analysis *tcpd=NULL;
5934 struct tcpheader *tcph = (struct tcpheader *)data;
5935 uint32_t base_ack=0;
5936 unsigned num_sack_ranges = 0;
5937 int offset = 0;
5938 int sackoffset;
5939 int optlen = tvb_reported_length(tvb);
5942 * SEQ analysis is the condition for both relative analysis obviously,
5943 * and SACK handling for the in-flight update
5945 if(tcp_analyze_seq) {
5946 /* find the conversation for this TCP session and its stored data */
5947 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
5948 tcpd=get_tcp_conversation_data_idempotent(stratconv);
5950 if (tcpd) {
5951 if (tcp_relative_seq) {
5952 base_ack=tcpd->rev->base_seq;
5956 * initialize the number of SACK blocks to 0, it will be
5957 * updated some lines later
5959 if (tcp_track_bytes_in_flight && tcpd->fwd->tcp_analyze_seq_info) {
5960 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = 0;
5965 /* Late discovery of a 'false' Window Update in presence of SACK option,
5966 * which means we are dealing with a Dup ACK rather than a Window Update.
5967 * Classify accordingly by removing the UPDATE and adding the DUP flags.
5968 * Mostly a copy/paste from tcp_analyze_sequence_number(), ensure consistency
5969 * whenever the latter changes.
5970 * see Issue #14937
5972 if( tcp_analyze_seq && tcpd && tcpd->ta && tcpd->ta->flags&TCP_A_WINDOW_UPDATE ) {
5974 /* MPTCP tolerates duplicate acks in some circumstances, see RFC 8684 4. */
5975 if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) {
5976 /* just ignore this DUPLICATE ACK */
5977 } else {
5978 /* no initialization required of the tcpd->ta as this code would
5979 * be unreachable otherwise
5981 tcpd->ta->flags &= ~TCP_A_WINDOW_UPDATE;
5982 tcpd->ta->flags |= TCP_A_DUPLICATE_ACK;
5984 if (tcpd->fwd->tcp_analyze_seq_info) {
5985 tcpd->fwd->tcp_analyze_seq_info->dupacknum++;
5987 tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum;
5988 tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack;
5993 ti = proto_tree_add_item(tree, proto_tcp_option_sack, tvb, offset, -1, ENC_NA);
5994 field_tree = proto_item_add_subtree(ti, ett_tcp_option_sack);
5996 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
5997 offset, 1, ENC_BIG_ENDIAN);
5998 proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
5999 offset + 1, 1, ENC_BIG_ENDIAN);
6001 offset += 2; /* skip past type and length */
6002 optlen -= 2; /* subtract size of type and length */
6004 sackoffset = offset;
6005 while (optlen > 0) {
6006 if (optlen < 4) {
6007 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_suboption_malformed, tvb, offset, optlen);
6008 break;
6010 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;
6011 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
6012 offset, 4, leftedge,
6013 "left edge = %u%s", leftedge,
6014 (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");
6015 optlen -= 4;
6016 if (optlen < 4) {
6017 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_suboption_malformed, tvb, offset, optlen);
6018 break;
6020 /* XXX - check whether it goes past end of packet */
6021 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;
6022 optlen -= 4;
6023 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
6024 offset+4, 4, rightedge,
6025 "right edge = %u%s", rightedge,
6026 (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");
6027 tcp_info_append_uint(pinfo, "SLE", leftedge);
6028 tcp_info_append_uint(pinfo, "SRE", rightedge);
6030 /* Store blocks for BiF analysis */
6031 if (tcp_analyze_seq && tcpd && tcpd->fwd->tcp_analyze_seq_info && tcp_track_bytes_in_flight && num_sack_ranges < MAX_TCP_SACK_RANGES) {
6032 tcpd->fwd->tcp_analyze_seq_info->sack_left_edge[num_sack_ranges] = leftedge;
6033 tcpd->fwd->tcp_analyze_seq_info->sack_right_edge[num_sack_ranges++] = rightedge;
6034 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = num_sack_ranges;
6037 /* Update tap info */
6038 if (tcph != NULL && (tcph->num_sack_ranges < MAX_TCP_SACK_RANGES)) {
6039 tcph->sack_left_edge[tcph->num_sack_ranges] = leftedge;
6040 tcph->sack_right_edge[tcph->num_sack_ranges] = rightedge;
6041 tcph->num_sack_ranges++;
6044 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);
6045 offset += 8;
6049 /* Show number of SACK ranges in this option as a generated field */
6050 tf = proto_tree_add_uint(field_tree, hf_tcp_option_sack_range_count,
6051 tvb, 0, 0, num_sack_ranges);
6052 proto_item_set_generated(tf);
6054 /* RFC 2883 "An Extension to the Selective Acknowledgement (SACK) Option for TCP" aka "D-SACK"
6055 * Section 4
6056 * Conditions: Either the first sack-block is inside the already acknowledged range or
6057 * the first sack block is inside the second sack block.
6059 * Maybe add later:
6060 * (1) A D-SACK block is only used to report a duplicate contiguous sequence of data received by
6061 * the receiver in the most recent packet.
6063 if (tcph != NULL && (
6064 LE_SEQ(tcph->sack_right_edge[0], tcph->th_ack) ||
6065 (tcph->num_sack_ranges > 1 &&
6066 LT_SEQ(tcph->sack_left_edge[1], tcph->sack_right_edge[0]) &&
6067 GE_SEQ(tcph->sack_right_edge[1], tcph->sack_right_edge[0]))
6068 )) {
6069 leftedge = tvb_get_ntohl(tvb, sackoffset)-base_ack;
6070 tf = proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_dsack_le, tvb, sackoffset, 4, leftedge,
6071 "D-SACK Left Edge = %u%s", leftedge, (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");
6072 proto_item_set_generated(tf);
6073 rightedge = tvb_get_ntohl(tvb, sackoffset+4)-base_ack;
6074 tf = proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_dsack_re, tvb, sackoffset+4, 4, rightedge,
6075 "D-SACK Right Edge = %u%s", rightedge, (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "");
6076 proto_item_set_generated(tf);
6077 proto_tree_add_expert(field_tree, pinfo, &ei_tcp_option_sack_dsack, tvb, sackoffset, 8);
6080 return tvb_captured_length(tvb);
6083 static int
6084 dissect_tcpopt_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6086 proto_tree *field_tree;
6087 proto_item *item;
6088 proto_item *length_item;
6089 uint32_t echo;
6090 int offset = 0;
6092 item = proto_tree_add_item(tree, proto_tcp_option_echo, tvb, offset, -1, ENC_NA);
6093 field_tree = proto_item_add_subtree(item, ett_tcp_opt_echo);
6095 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6096 offset, 1, ENC_BIG_ENDIAN);
6097 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6098 offset + 1, 1, ENC_BIG_ENDIAN);
6100 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_ECHO))
6101 return tvb_captured_length(tvb);
6103 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_echo, tvb,
6104 offset + 2, 4, ENC_BIG_ENDIAN, &echo);
6106 proto_item_append_text(item, ": %u", echo);
6107 tcp_info_append_uint(pinfo, "ECHO", echo);
6109 return tvb_captured_length(tvb);
6112 /* If set, do not put the TCP timestamp information on the summary line */
6113 static bool tcp_ignore_timestamps;
6115 static int
6116 dissect_tcpopt_timestamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6118 proto_item *ti, *tsval_ti;
6119 proto_tree *ts_tree;
6120 proto_item *length_item;
6121 int offset = 0;
6122 uint32_t ts_val, ts_ecr;
6123 int len = tvb_reported_length(tvb);
6125 ti = proto_tree_add_item(tree, proto_tcp_option_timestamp, tvb, offset, -1, ENC_NA);
6126 ts_tree = proto_item_add_subtree(ti, ett_tcp_option_timestamp);
6128 proto_tree_add_item(ts_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
6129 offset += 1;
6131 length_item = proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
6132 offset += 1;
6134 if (!tcp_option_len_check(length_item, pinfo, len, TCPOLEN_TIMESTAMP))
6135 return tvb_captured_length(tvb);
6137 tsval_ti = proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset,
6138 4, ENC_BIG_ENDIAN, &ts_val);
6140 proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset + 4,
6141 4, ENC_BIG_ENDIAN, &ts_ecr);
6143 proto_item_append_text(ti, ": TSval %u, TSecr %u", ts_val, ts_ecr);
6144 if (tcp_ignore_timestamps == false) {
6145 tcp_info_append_uint(pinfo, "TSval", ts_val);
6146 tcp_info_append_uint(pinfo, "TSecr", ts_ecr);
6149 if (read_seq_as_syn_cookie) {
6150 proto_item_append_text(ti, " (syn cookie)");
6151 proto_item* syncookie_ti = proto_item_add_subtree(tsval_ti, ett_tcp_syncookie_option);
6152 uint32_t timestamp = tvb_get_bits32(tvb, offset * 8, 26, ENC_NA) << 6;
6153 proto_tree_add_uint_bits_format_value(syncookie_ti, hf_tcp_syncookie_option_timestamp, tvb, offset * 8,
6154 26, timestamp, ENC_TIME_SECS, "%s", abs_time_secs_to_str(pinfo->pool, timestamp, ABSOLUTE_TIME_LOCAL, true));
6155 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_ecn, tvb, offset * 8 + 26, 1, ENC_NA);
6156 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_sack, tvb, offset * 8 + 27, 1, ENC_NA);
6157 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_wscale, tvb, offset * 8 + 28, 4, ENC_NA);
6160 return tvb_captured_length(tvb);
6163 static struct mptcp_analysis*
6164 mptcp_alloc_analysis(struct tcp_analysis* tcpd) {
6166 struct mptcp_analysis* mptcpd;
6168 DISSECTOR_ASSERT(tcpd->mptcp_analysis == 0);
6170 mptcpd = (struct mptcp_analysis*)wmem_new0(wmem_file_scope(), struct mptcp_analysis);
6171 mptcpd->subflows = wmem_list_new(wmem_file_scope());
6173 mptcpd->stream = mptcp_stream_count++;
6174 tcpd->mptcp_analysis = mptcpd;
6176 memset(&mptcpd->meta_flow, 0, 2*sizeof(mptcp_meta_flow_t));
6178 /* arbitrary assignment. Callers may override this */
6179 tcpd->fwd->mptcp_subflow->meta = &mptcpd->meta_flow[0];
6180 tcpd->rev->mptcp_subflow->meta = &mptcpd->meta_flow[1];
6182 return mptcpd;
6186 /* will create necessary structure if fails to find a match on the token */
6187 static struct mptcp_analysis*
6188 mptcp_get_meta_from_token(struct tcp_analysis* tcpd, tcp_flow_t *tcp_flow, uint32_t token) {
6190 struct mptcp_analysis* result = NULL;
6191 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;
6192 uint8_t assignedMetaId = 0; /* array id < 2 */
6194 DISSECTOR_ASSERT(tcp_flow == tcpd->fwd || tcp_flow == tcpd->rev);
6198 /* if token already set for this meta */
6199 if( tcp_flow->mptcp_subflow->meta && (tcp_flow->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_TOKEN)) {
6200 return mptcpd;
6203 /* else look for a registered meta with this token */
6204 result = (struct mptcp_analysis*)wmem_tree_lookup32(mptcp_tokens, token);
6206 /* if token already registered than just share it across TCP connections */
6207 if(result) {
6208 mptcpd = result;
6209 mptcp_attach_subflow(mptcpd, tcpd);
6211 else {
6212 /* we create it if this connection */
6213 if(!mptcpd) {
6214 /* don't care which meta to choose assign each meta to a direction */
6215 mptcpd = mptcp_alloc_analysis(tcpd);
6216 mptcp_attach_subflow(mptcpd, tcpd);
6218 else {
6220 /* already exists, thus some meta may already have been configured */
6221 if(mptcpd->meta_flow[0].static_flags & MPTCP_META_HAS_TOKEN) {
6222 assignedMetaId = 1;
6224 else if(mptcpd->meta_flow[1].static_flags & MPTCP_META_HAS_TOKEN) {
6225 assignedMetaId = 0;
6227 else {
6228 DISSECTOR_ASSERT_NOT_REACHED();
6230 tcp_flow->mptcp_subflow->meta = &mptcpd->meta_flow[assignedMetaId];
6232 DISSECTOR_ASSERT(tcp_flow->mptcp_subflow->meta);
6234 tcp_flow->mptcp_subflow->meta->token = token;
6235 tcp_flow->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_TOKEN;
6237 wmem_tree_insert32(mptcp_tokens, token, mptcpd);
6240 DISSECTOR_ASSERT(mptcpd);
6243 /* compute the meta id assigned to tcp_flow */
6244 assignedMetaId = (tcp_flow->mptcp_subflow->meta == &mptcpd->meta_flow[0]) ? 0 : 1;
6246 /* computes the metaId tcpd->fwd should be assigned to */
6247 assignedMetaId = (tcp_flow == tcpd->fwd) ? assignedMetaId : (assignedMetaId +1) %2;
6249 tcpd->fwd->mptcp_subflow->meta = &mptcpd->meta_flow[ (assignedMetaId) ];
6250 tcpd->rev->mptcp_subflow->meta = &mptcpd->meta_flow[ (assignedMetaId +1) %2];
6252 return mptcpd;
6255 /* setup from_key */
6256 static
6257 struct mptcp_analysis*
6258 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_) {
6260 uint32_t token = 0;
6261 uint64_t expected_idsn= 0;
6262 struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis;
6264 if(fwd->mptcp_subflow->meta && (fwd->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_KEY)) {
6265 return mptcpd;
6268 /* MPTCP v0 only standardizes SHA1, and v1 SHA256. */
6269 if (version == 0)
6270 mptcp_cryptodata_sha1(key, &token, &expected_idsn);
6271 else if (version == 1)
6272 mptcp_cryptodata_sha256(key, &token, &expected_idsn);
6274 mptcpd = mptcp_get_meta_from_token(tcpd, fwd, token);
6276 DISSECTOR_ASSERT(fwd->mptcp_subflow->meta);
6278 fwd->mptcp_subflow->meta->version = version;
6279 fwd->mptcp_subflow->meta->key = key;
6280 fwd->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_KEY;
6281 fwd->mptcp_subflow->meta->base_dsn = expected_idsn;
6282 return mptcpd;
6285 /* record this mapping */
6286 static
6287 void analyze_mapping(struct tcp_analysis *tcpd, packet_info *pinfo, uint16_t len, uint64_t dsn, bool extended, uint32_t ssn) {
6289 /* store mapping only if analysis is enabled and mapping is not unlimited */
6290 if (!mptcp_analyze_mappings || !len) {
6291 return;
6294 if (PINFO_FD_VISITED(pinfo)) {
6295 return;
6298 /* register SSN range described by the mapping into a subflow interval_tree */
6299 mptcp_dss_mapping_t *mapping = NULL;
6300 mapping = wmem_new0(wmem_file_scope(), mptcp_dss_mapping_t);
6302 mapping->rawdsn = dsn;
6303 mapping->extended_dsn = extended;
6304 mapping->frame = pinfo->fd->num;
6305 mapping->ssn_low = ssn;
6306 mapping->ssn_high = ssn + len - 1;
6308 wmem_itree_insert(tcpd->fwd->mptcp_subflow->ssn2dsn_mappings,
6309 mapping->ssn_low,
6310 mapping->ssn_high,
6311 mapping
6316 * The TCP Extensions for Multipath Operation with Multiple Addresses
6317 * are defined in RFC 6824
6319 * https://tools.ietf.org/html/rfc6824
6321 * Author: Andrei Maruseac <andrei.maruseac@intel.com>
6322 * Matthieu Coudron <matthieu.coudron@lip6.fr>
6324 * This function just generates the mptcpheader, i.e. the generation of
6325 * datastructures is delayed/delegated to mptcp_analyze
6327 static int
6328 dissect_tcpopt_mptcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
6330 proto_item *item,*main_item;
6331 proto_tree *mptcp_tree;
6333 uint32_t version;
6334 uint8_t subtype;
6335 uint8_t ipver;
6336 int offset = 0;
6337 int optlen = tvb_reported_length(tvb);
6338 int start_offset = offset;
6339 struct tcp_analysis *tcpd = NULL;
6340 struct mptcp_analysis* mptcpd = NULL;
6341 struct tcpheader *tcph = (struct tcpheader *)data;
6343 /* There may be several MPTCP options per packet, don't duplicate the structure */
6344 struct mptcpheader* mph = tcph->th_mptcp;
6346 if(!mph) {
6347 mph = wmem_new0(pinfo->pool, struct mptcpheader);
6348 tcph->th_mptcp = mph;
6351 tcpd=get_tcp_conversation_data(NULL,pinfo);
6352 mptcpd=tcpd->mptcp_analysis;
6354 /* seeing an MPTCP packet on the subflow automatically qualifies it as an mptcp subflow */
6355 if(!tcpd->fwd->mptcp_subflow) {
6356 mptcp_init_subflow(tcpd->fwd);
6358 if(!tcpd->rev->mptcp_subflow) {
6359 mptcp_init_subflow(tcpd->rev);
6362 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPTCP");
6363 main_item = proto_tree_add_item(tree, proto_mptcp, tvb, offset, -1, ENC_NA);
6364 mptcp_tree = proto_item_add_subtree(main_item, ett_tcp_option_mptcp);
6366 proto_tree_add_item(mptcp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
6367 offset += 1;
6369 proto_tree_add_item(mptcp_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
6370 offset += 1;
6372 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_subtype, tvb,
6373 offset, 1, ENC_BIG_ENDIAN);
6375 subtype = tvb_get_uint8(tvb, offset) >> 4;
6376 proto_item_append_text(main_item, ": %s", val_to_str(subtype, mptcp_subtype_vs, "Unknown (%d)"));
6378 /** preemptively allocate mptcpd when subtype won't allow to find a meta */
6379 if(!mptcpd && (subtype > TCPOPT_MPTCP_MP_JOIN)) {
6380 mptcpd = mptcp_alloc_analysis(tcpd);
6383 switch (subtype) {
6384 case TCPOPT_MPTCP_MP_CAPABLE:
6385 mph->mh_mpc = true;
6387 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_version, tvb,
6388 offset, 1, ENC_BIG_ENDIAN, &version);
6389 offset += 1;
6391 item = proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6392 ett_tcp_option_mptcp,
6393 version == 1 ? tcp_option_mptcp_capable_v1_flags : tcp_option_mptcp_capable_v0_flags,
6394 ENC_BIG_ENDIAN);
6395 mph->mh_capable_flags = tvb_get_uint8(tvb, offset);
6396 if ((mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK) == 0) {
6397 expert_add_info(pinfo, item, &ei_mptcp_analysis_missing_algorithm);
6399 if ((mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK) != MPTCP_HMAC_SHA) {
6400 expert_add_info(pinfo, item, &ei_mptcp_analysis_unsupported_algorithm);
6402 offset += 1;
6404 /* optlen == 12 => SYN or SYN/ACK; optlen == 20 => ACK;
6405 * optlen == 22 => ACK + data (v1 only);
6406 * optlen == 24 => ACK + data + csum (v1 only)
6408 if (optlen == 12 || optlen == 20 || optlen == 22 || optlen == 24) {
6410 mph->mh_key = tvb_get_ntoh64(tvb,offset);
6411 proto_tree_add_uint64(mptcp_tree, hf_tcp_option_mptcp_sender_key, tvb, offset, 8, mph->mh_key);
6412 offset += 8;
6414 mptcpd = get_or_create_mptcpd_from_key(tcpd, tcpd->fwd, version, mph->mh_key, mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK);
6415 mptcpd->master = tcpd;
6417 item = proto_tree_add_uint(mptcp_tree,
6418 hf_mptcp_expected_token, tvb, offset, 0, tcpd->fwd->mptcp_subflow->meta->token);
6419 proto_item_set_generated(item);
6421 item = proto_tree_add_uint64(mptcp_tree,
6422 hf_mptcp_expected_idsn, tvb, offset, 0, tcpd->fwd->mptcp_subflow->meta->base_dsn);
6423 proto_item_set_generated(item);
6425 /* last ACK of 3WHS, repeats both keys */
6426 if (optlen >= 20) {
6427 uint64_t recv_key = tvb_get_ntoh64(tvb,offset);
6428 proto_tree_add_uint64(mptcp_tree, hf_tcp_option_mptcp_recv_key, tvb, offset, 8, recv_key);
6429 offset += 8;
6431 if(tcpd->rev->mptcp_subflow->meta
6432 && (tcpd->rev->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_KEY)) {
6434 /* compare the echoed key with the server key */
6435 if(tcpd->rev->mptcp_subflow->meta->key != recv_key) {
6436 expert_add_info(pinfo, item, &ei_mptcp_analysis_echoed_key_mismatch);
6439 else {
6440 mptcpd = get_or_create_mptcpd_from_key(tcpd, tcpd->rev, version, recv_key, mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK);
6444 /* MPTCP v1 ACK + data, contains data_len and optional checksum */
6445 if (optlen >= 22) {
6446 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_lvl_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6447 mph->mh_dss_length = tvb_get_ntohs(tvb,offset);
6448 offset += 2;
6450 if (mph->mh_dss_length == 0) {
6451 expert_add_info(pinfo, mptcp_tree, &ei_mptcp_infinite_mapping);
6454 /* when data len is present, this MP_CAPABLE also carries an implicit mapping ... */
6455 analyze_mapping(tcpd, pinfo, mph->mh_dss_length, tcpd->fwd->mptcp_subflow->meta->base_dsn + 1, true, tcph->th_seq);
6457 /* ... with optional checksum */
6458 if (optlen == 24)
6460 proto_tree_add_checksum(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
6464 break;
6466 case TCPOPT_MPTCP_MP_JOIN:
6467 mph->mh_join = true;
6468 if(optlen != 12 && !mptcpd) {
6469 mptcpd = mptcp_alloc_analysis(tcpd);
6471 switch (optlen) {
6472 /* Syn */
6473 case 12:
6475 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6476 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,
6477 ENC_BIG_ENDIAN);
6478 offset += 1;
6479 tcpd->fwd->mptcp_subflow->address_id = tvb_get_uint8(tvb, offset);
6480 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,
6481 1, ENC_BIG_ENDIAN);
6482 offset += 1;
6484 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_recv_token, tvb, offset,
6485 4, ENC_BIG_ENDIAN, &mph->mh_token);
6486 offset += 4;
6488 mptcpd = mptcp_get_meta_from_token(tcpd, tcpd->rev, mph->mh_token);
6489 if (tcpd->fwd->mptcp_subflow->meta->version == 1) {
6490 mptcp_meta_flow_t *tmp = tcpd->fwd->mptcp_subflow->meta;
6492 /* if the negotiated version is v1 the first key was exchanged on SYN/ACK packet: we must swap the meta */
6493 tcpd->fwd->mptcp_subflow->meta = tcpd->rev->mptcp_subflow->meta;
6494 tcpd->rev->mptcp_subflow->meta = tmp;
6497 proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_sender_rand, tvb, offset,
6498 4, ENC_BIG_ENDIAN, &tcpd->fwd->mptcp_subflow->nonce);
6501 break;
6504 case 16: /* Syn/Ack */
6505 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6506 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,
6507 ENC_BIG_ENDIAN);
6508 offset += 1;
6510 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,
6511 1, ENC_BIG_ENDIAN);
6512 offset += 1;
6514 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_trunc_hmac, tvb, offset,
6515 8, ENC_BIG_ENDIAN);
6516 offset += 8;
6518 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_rand, tvb, offset,
6519 4, ENC_BIG_ENDIAN);
6520 break;
6522 case 24: /* Ack */
6523 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_reserved, tvb, offset,
6524 2, ENC_BIG_ENDIAN);
6525 offset += 2;
6527 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_hmac, tvb, offset,
6528 20, ENC_NA);
6529 break;
6531 default:
6532 break;
6534 break;
6536 /* display only *raw* values since it is harder to guess a correct value than for TCP.
6537 One needs to enable mptcp_analysis to get more interesting data
6539 case TCPOPT_MPTCP_DSS:
6540 mph->mh_dss = true;
6542 offset += 1;
6543 mph->mh_dss_flags = tvb_get_uint8(tvb, offset) & 0x1F;
6545 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6546 ett_tcp_option_mptcp, tcp_option_mptcp_dss_flags,
6547 ENC_BIG_ENDIAN);
6548 offset += 1;
6550 /* displays "raw" DataAck , ie does not convert it to its 64 bits form
6551 to do so you need to enable
6553 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_PRESENT) {
6555 uint64_t dack64;
6557 /* 64bits ack */
6558 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES) {
6560 mph->mh_dss_rawack = tvb_get_ntoh64(tvb,offset);
6561 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);
6562 offset += 8;
6564 /* 32bits ack */
6565 else {
6566 mph->mh_dss_rawack = tvb_get_ntohl(tvb,offset);
6567 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_ack_raw, tvb, offset, 4, ENC_BIG_ENDIAN);
6568 offset += 4;
6571 if(mptcp_convert_dsn(mph->mh_dss_rawack, tcpd->rev->mptcp_subflow->meta,
6572 (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES) ? DSN_CONV_NONE : DSN_CONV_32_TO_64, mptcp_relative_seq, &dack64)) {
6573 item = proto_tree_add_uint64(mptcp_tree, hf_mptcp_ack, tvb, 0, 0, dack64);
6574 if (mptcp_relative_seq) {
6575 proto_item_append_text(item, " (Relative)");
6578 proto_item_set_generated(item);
6580 else {
6581 /* ignore and continue */
6586 /* Mapping present */
6587 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_MAPPING_PRESENT) {
6589 uint64_t dsn;
6591 if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DSN_8BYTES) {
6593 dsn = tvb_get_ntoh64(tvb,offset);
6594 proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 8, dsn, "%" PRIu64 " (64bits version)", dsn);
6596 /* if we have the opportunity to complete the 32 Most Significant Bits of the
6599 if(!(tcpd->fwd->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_BASE_DSN_MSB)) {
6600 tcpd->fwd->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_BASE_DSN_MSB;
6601 tcpd->fwd->mptcp_subflow->meta->base_dsn |= (dsn & (uint32_t) 0);
6603 offset += 8;
6604 } else {
6605 dsn = tvb_get_ntohl(tvb,offset);
6606 proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 4, dsn, "%" PRIu64 " (32bits version)", dsn);
6607 offset += 4;
6609 mph->mh_dss_rawdsn = dsn;
6611 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);
6612 offset += 4;
6614 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_lvl_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6615 mph->mh_dss_length = tvb_get_ntohs(tvb,offset);
6616 offset += 2;
6618 if(mph->mh_dss_length == 0) {
6619 expert_add_info(pinfo, mptcp_tree, &ei_mptcp_infinite_mapping);
6622 /* print head & tail dsn */
6623 if(mptcp_convert_dsn(mph->mh_dss_rawdsn, tcpd->fwd->mptcp_subflow->meta,
6624 (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES) ? DSN_CONV_NONE : DSN_CONV_32_TO_64, mptcp_relative_seq, &dsn)) {
6625 item = proto_tree_add_uint64(mptcp_tree, hf_mptcp_dss_dsn, tvb, 0, 0, dsn);
6626 if (mptcp_relative_seq) {
6627 proto_item_append_text(item, " (Relative)");
6630 proto_item_set_generated(item);
6632 else {
6633 /* ignore and continue */
6636 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);
6638 if ((int)optlen >= offset-start_offset+4)
6640 proto_tree_add_checksum(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
6643 break;
6645 case TCPOPT_MPTCP_ADD_ADDR:
6646 mph->mh_add = true;
6647 ipver = tvb_get_uint8(tvb, offset) & 0x0F;
6648 if (ipver == 4 || ipver == 6)
6649 proto_tree_add_item(mptcp_tree,
6650 hf_tcp_option_mptcp_ipver, tvb, offset, 1, ENC_BIG_ENDIAN);
6651 else
6652 proto_tree_add_item(mptcp_tree,
6653 hf_tcp_option_mptcp_echo, tvb, offset, 1, ENC_BIG_ENDIAN);
6654 offset += 1;
6656 proto_tree_add_item(mptcp_tree,
6657 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN);
6658 offset += 1;
6660 if (optlen == 8 || optlen == 10 || optlen == 16 || optlen == 18) {
6661 proto_tree_add_item(mptcp_tree,
6662 hf_tcp_option_mptcp_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
6663 offset += 4;
6666 if (optlen == 20 || optlen == 22 || optlen == 28 || optlen == 30) {
6667 proto_tree_add_item(mptcp_tree,
6668 hf_tcp_option_mptcp_ipv6, tvb, offset, 16, ENC_NA);
6669 offset += 16;
6672 if (optlen == 10 || optlen == 18 || optlen == 22 || optlen == 30) {
6673 proto_tree_add_item(mptcp_tree,
6674 hf_tcp_option_mptcp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
6675 offset += 2;
6678 if (optlen == 16 || optlen == 18 || optlen == 28 || optlen == 30) {
6679 proto_tree_add_item(mptcp_tree,
6680 hf_tcp_option_mptcp_addaddr_trunc_hmac, tvb, offset, 8, ENC_BIG_ENDIAN);
6682 break;
6684 case TCPOPT_MPTCP_REMOVE_ADDR:
6685 mph->mh_remove = true;
6686 item = proto_tree_add_uint(mptcp_tree, hf_mptcp_number_of_removed_addresses, tvb, start_offset+2,
6687 1, optlen - 3);
6688 proto_item_set_generated(item);
6689 offset += 1;
6690 while(offset < start_offset + (int)optlen) {
6691 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset,
6692 1, ENC_BIG_ENDIAN);
6693 offset += 1;
6695 break;
6697 case TCPOPT_MPTCP_MP_PRIO:
6698 mph->mh_prio = true;
6699 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6700 ett_tcp_option_mptcp, tcp_option_mptcp_join_flags,
6701 ENC_BIG_ENDIAN);
6702 offset += 1;
6704 if (optlen == 4) {
6705 proto_tree_add_item(mptcp_tree,
6706 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN);
6708 break;
6710 case TCPOPT_MPTCP_MP_FAIL:
6711 mph->mh_fail = true;
6712 proto_tree_add_item(mptcp_tree,
6713 hf_tcp_option_mptcp_reserved, tvb, offset,2, ENC_BIG_ENDIAN);
6714 offset += 2;
6716 proto_tree_add_item(mptcp_tree,
6717 hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 8, ENC_BIG_ENDIAN);
6718 break;
6720 case TCPOPT_MPTCP_MP_FASTCLOSE:
6721 mph->mh_fastclose = true;
6722 proto_tree_add_item(mptcp_tree,
6723 hf_tcp_option_mptcp_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
6724 offset += 2;
6726 proto_tree_add_item(mptcp_tree,
6727 hf_tcp_option_mptcp_recv_key, tvb, offset, 8, ENC_BIG_ENDIAN);
6728 mph->mh_key = tvb_get_ntoh64(tvb,offset);
6729 break;
6731 case TCPOPT_MPTCP_MP_TCPRST:
6732 mph->mh_tcprst = true;
6733 proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags,
6734 ett_tcp_option_mptcp, tcp_option_mptcp_tcprst_flags,
6735 ENC_BIG_ENDIAN);
6736 offset += 1;
6737 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_tcprst_reason, tvb, offset, 1,
6738 ENC_BIG_ENDIAN);
6739 break;
6741 default:
6742 break;
6745 if ((mptcpd != NULL) && (tcpd->mptcp_analysis != NULL)) {
6747 /* if mptcpd just got allocated, remember the initial addresses
6748 * which will serve as identifiers for the conversation filter
6750 if(tcpd->fwd->mptcp_subflow->meta->ip_src.len == 0) {
6752 copy_address_wmem(wmem_file_scope(), &tcpd->fwd->mptcp_subflow->meta->ip_src, &tcph->ip_src);
6753 copy_address_wmem(wmem_file_scope(), &tcpd->fwd->mptcp_subflow->meta->ip_dst, &tcph->ip_dst);
6755 copy_address_shallow(&tcpd->rev->mptcp_subflow->meta->ip_src, &tcpd->fwd->mptcp_subflow->meta->ip_dst);
6756 copy_address_shallow(&tcpd->rev->mptcp_subflow->meta->ip_dst, &tcpd->fwd->mptcp_subflow->meta->ip_src);
6758 tcpd->fwd->mptcp_subflow->meta->sport = tcph->th_sport;
6759 tcpd->fwd->mptcp_subflow->meta->dport = tcph->th_dport;
6762 mph->mh_stream = tcpd->mptcp_analysis->stream;
6765 return tvb_captured_length(tvb);
6768 static int
6769 dissect_tcpopt_cc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6771 proto_tree *field_tree;
6772 proto_item *item;
6773 proto_item *length_item;
6774 int offset = 0;
6775 uint32_t cc;
6777 item = proto_tree_add_item(tree, proto_tcp_option_cc, tvb, offset, -1, ENC_NA);
6778 field_tree = proto_item_add_subtree(item, ett_tcp_opt_cc);
6780 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6781 offset, 1, ENC_BIG_ENDIAN);
6782 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6783 offset + 1, 1, ENC_BIG_ENDIAN);
6785 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_CC))
6786 return tvb_captured_length(tvb);
6788 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_cc, tvb,
6789 offset + 2, 4, ENC_BIG_ENDIAN, &cc);
6791 tcp_info_append_uint(pinfo, "CC", cc);
6792 return tvb_captured_length(tvb);
6795 static int
6796 dissect_tcpopt_md5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6798 proto_tree *field_tree;
6799 proto_item *item;
6800 proto_item *length_item;
6801 int offset = 0, optlen = tvb_reported_length(tvb);
6803 item = proto_tree_add_item(tree, proto_tcp_option_md5, tvb, offset, -1, ENC_NA);
6804 field_tree = proto_item_add_subtree(item, ett_tcp_opt_md5);
6806 col_append_lstr(pinfo->cinfo, COL_INFO, " MD5", COL_ADD_LSTR_TERMINATOR);
6807 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6808 offset, 1, ENC_BIG_ENDIAN);
6809 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6810 offset + 1, 1, ENC_BIG_ENDIAN);
6812 if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_MD5))
6813 return tvb_captured_length(tvb);
6815 proto_tree_add_item(field_tree, hf_tcp_option_md5_digest, tvb,
6816 offset + 2, optlen - 2, ENC_NA);
6818 return tvb_captured_length(tvb);
6821 static int
6822 dissect_tcpopt_ao(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6824 proto_tree *field_tree;
6825 proto_item *item;
6826 proto_item *length_item;
6827 int offset = 0, optlen = tvb_reported_length(tvb);
6829 item = proto_tree_add_item(tree, proto_tcp_option_ao, tvb, offset, -1, ENC_NA);
6830 field_tree = proto_item_add_subtree(item, ett_tcp_opt_ao);
6832 col_append_lstr(pinfo->cinfo, COL_INFO, "TCP AO", COL_ADD_LSTR_TERMINATOR);
6833 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6834 offset, 1, ENC_BIG_ENDIAN);
6835 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6836 offset + 1, 1, ENC_BIG_ENDIAN);
6838 if (optlen < 4) {
6839 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
6840 "option length should be >= than 4");
6841 return tvb_captured_length(tvb);
6844 proto_tree_add_item(field_tree, hf_tcp_option_ao_keyid, tvb,
6845 offset + 2, 1, ENC_NA);
6847 proto_tree_add_item(field_tree, hf_tcp_option_ao_rnextkeyid, tvb,
6848 offset + 3, 1, ENC_NA);
6850 if (optlen > 4)
6851 proto_tree_add_item(field_tree, hf_tcp_option_ao_mac, tvb,
6852 offset + 4, optlen - 4, ENC_NA);
6854 return tvb_captured_length(tvb);
6857 static int
6858 dissect_tcpopt_qs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6860 proto_tree *field_tree;
6861 proto_item *item;
6862 proto_item *length_item;
6863 uint8_t rate;
6864 int offset = 0;
6866 item = proto_tree_add_item(tree, proto_tcp_option_qs, tvb, offset, -1, ENC_NA);
6867 field_tree = proto_item_add_subtree(item, ett_tcp_opt_qs);
6869 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6870 offset, 1, ENC_BIG_ENDIAN);
6871 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6872 offset + 1, 1, ENC_BIG_ENDIAN);
6874 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_QS))
6875 return tvb_captured_length(tvb);
6877 rate = tvb_get_uint8(tvb, offset + 2) & 0x0f;
6878 col_append_lstr(pinfo->cinfo, COL_INFO,
6879 " QSresp=", val_to_str_ext_const(rate, &qs_rate_vals_ext, "Unknown"),
6880 COL_ADD_LSTR_TERMINATOR);
6881 proto_tree_add_item(field_tree, hf_tcp_option_qs_rate, tvb,
6882 offset + 2, 1, ENC_BIG_ENDIAN);
6883 proto_tree_add_item(field_tree, hf_tcp_option_qs_ttl_diff, tvb,
6884 offset + 3, 1, ENC_BIG_ENDIAN);
6886 return tvb_captured_length(tvb);
6889 static int
6890 dissect_tcpopt_scps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
6892 struct tcp_analysis *tcpd;
6893 proto_tree *field_tree = NULL;
6894 tcp_flow_t *flow;
6895 int direction;
6896 proto_item *tf = NULL, *item;
6897 proto_tree *flags_tree = NULL;
6898 uint8_t capvector;
6899 uint8_t connid;
6900 int offset = 0, optlen = tvb_reported_length(tvb);
6902 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
6903 tcpd=get_tcp_conversation_data_idempotent(stratconv);
6905 /* check direction and get ua lists */
6906 direction=cmp_address(&pinfo->src, &pinfo->dst);
6908 /* if the addresses are equal, match the ports instead */
6909 if(direction==0) {
6910 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
6913 if(direction>=0)
6914 flow =&(tcpd->flow1);
6915 else
6916 flow =&(tcpd->flow2);
6918 item = proto_tree_add_item(tree, proto_tcp_option_scps,
6919 tvb, offset, -1, ENC_NA);
6920 field_tree = proto_item_add_subtree(item, ett_tcp_option_scps);
6922 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
6923 offset, 1, ENC_BIG_ENDIAN);
6924 proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
6925 offset + 1, 1, ENC_BIG_ENDIAN);
6927 /* If the option length == 4, this is a real SCPS capability option
6928 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
6929 * (SCPS-TP)" Section 3.2.3 for definition.
6931 if (optlen == 4) {
6932 tf = proto_tree_add_item(field_tree, hf_tcp_option_scps_vector, tvb,
6933 offset + 2, 1, ENC_BIG_ENDIAN);
6934 flags_tree = proto_item_add_subtree(tf, ett_tcp_scpsoption_flags);
6935 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_bets, tvb,
6936 offset + 2, 1, ENC_BIG_ENDIAN);
6937 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack1, tvb,
6938 offset + 2, 1, ENC_BIG_ENDIAN);
6939 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack2, tvb,
6940 offset + 2, 1, ENC_BIG_ENDIAN);
6941 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_compress, tvb,
6942 offset + 2, 1, ENC_BIG_ENDIAN);
6943 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_nlts, tvb,
6944 offset + 2, 1, ENC_BIG_ENDIAN);
6945 proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_reserved, tvb,
6946 offset + 2, 1, ENC_BIG_ENDIAN);
6947 capvector = tvb_get_uint8(tvb, offset + 2);
6949 if (capvector) {
6950 struct capvec
6952 uint8_t mask;
6953 const char *str;
6954 } capvecs[] = {
6955 {0x80, "BETS"},
6956 {0x40, "SNACK1"},
6957 {0x20, "SNACK2"},
6958 {0x10, "COMP"},
6959 {0x08, "NLTS"},
6960 {0x07, "RESERVED"}
6962 bool anyflag = false;
6963 unsigned i;
6965 col_append_str(pinfo->cinfo, COL_INFO, " SCPS[");
6966 for (i = 0; i < array_length(capvecs); i++) {
6967 if (capvector & capvecs[i].mask) {
6968 proto_item_append_text(tf, "%s%s", anyflag ? ", " : " (",
6969 capvecs[i].str);
6970 col_append_lstr(pinfo->cinfo, COL_INFO,
6971 anyflag ? ", " : "",
6972 capvecs[i].str,
6973 COL_ADD_LSTR_TERMINATOR);
6974 anyflag = true;
6977 col_append_str(pinfo->cinfo, COL_INFO, "]");
6978 proto_item_append_text(tf, ")");
6981 proto_tree_add_item(field_tree, hf_tcp_scpsoption_connection_id, tvb,
6982 offset + 3, 1, ENC_BIG_ENDIAN);
6983 connid = tvb_get_uint8(tvb, offset + 3);
6984 flow->scps_capable = true;
6986 if (connid)
6987 tcp_info_append_uint(pinfo, "Connection ID", connid);
6988 } else {
6989 /* The option length != 4, so this is an infamous "extended capabilities
6990 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
6991 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
6993 * As the format of this option is only partially defined (it is
6994 * a community (or more likely vendor) defined format beyond that, so
6995 * at least for now, we only parse the standardized portion of the option.
6997 uint8_t local_offset = 2;
6998 uint8_t binding_space;
6999 uint8_t extended_cap_length;
7001 if (!flow->scps_capable) {
7002 /* There was no SCPS capabilities option preceding this */
7003 proto_item_set_text(item,
7004 "Illegal SCPS Extended Capabilities (%u bytes)",
7005 optlen);
7006 } else {
7007 proto_item_set_text(item,
7008 "SCPS Extended Capabilities (%u bytes)",
7009 optlen);
7011 /* There may be multiple binding spaces included in a single option,
7012 * so we will semi-parse each of the stacked binding spaces - skipping
7013 * over the octets following the binding space identifier and length.
7015 while (optlen > local_offset) {
7017 /* 1st octet is Extended Capability Binding Space */
7018 binding_space = tvb_get_uint8(tvb, (offset + local_offset));
7020 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
7021 * As defined by the specification, this length is exclusive of the
7022 * octets containing the extended capability type and length
7024 extended_cap_length =
7025 (tvb_get_uint8(tvb, (offset + local_offset + 1)) >> 4);
7027 /* Convert the extended capabilities length into bytes for display */
7028 extended_cap_length = (extended_cap_length << 1);
7030 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding, tvb, offset + local_offset, 1, ENC_BIG_ENDIAN);
7031 proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding_len, tvb, offset + local_offset + 1, 1, extended_cap_length);
7033 /* Step past the binding space and length octets */
7034 local_offset += 2;
7036 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding_data, tvb, offset + local_offset, extended_cap_length, ENC_NA);
7038 tcp_info_append_uint(pinfo, "EXCAP", binding_space);
7040 /* Step past the Extended capability data
7041 * Treat the extended capability data area as opaque;
7042 * If one desires to parse the extended capability data
7043 * (say, in a vendor aware build of wireshark), it would
7044 * be triggered here.
7046 local_offset += extended_cap_length;
7051 return tvb_captured_length(tvb);
7054 static int
7055 dissect_tcpopt_user_to(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
7057 proto_item *tf;
7058 proto_tree *field_tree;
7059 proto_item *length_item;
7060 uint16_t to;
7061 int offset = 0;
7063 tf = proto_tree_add_item(tree, proto_tcp_option_user_to, tvb, offset, -1, ENC_NA);
7064 field_tree = proto_item_add_subtree(tf, ett_tcp_option_user_to);
7066 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7067 offset, 1, ENC_BIG_ENDIAN);
7068 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7069 offset + 1, 1, ENC_BIG_ENDIAN);
7071 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_USER_TO))
7072 return tvb_captured_length(tvb);
7074 proto_tree_add_item(field_tree, hf_tcp_option_user_to_granularity, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
7075 to = tvb_get_ntohs(tvb, offset + 2) & 0x7FFF;
7076 proto_tree_add_item(field_tree, hf_tcp_option_user_to_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
7078 tcp_info_append_uint(pinfo, "USER_TO", to);
7079 return tvb_captured_length(tvb);
7082 /* This is called for SYN+ACK packets and the purpose is to verify that
7083 * the SCPS capabilities option has been successfully negotiated for the flow.
7084 * If the SCPS capabilities option was offered by only one party, the
7085 * proactively set scps_capable attribute of the flow (set upon seeing
7086 * the first instance of the SCPS option) is revoked.
7088 static void
7089 verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd)
7091 tf_syn = 0x0;
7093 if(tcpd) {
7094 if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) {
7095 tcpd->flow1.scps_capable = false;
7096 tcpd->flow2.scps_capable = false;
7097 } else {
7098 expert_add_info(pinfo, tf_syn, &ei_tcp_scps_capable);
7103 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
7104 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
7106 static int
7107 dissect_tcpopt_snack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
7109 struct tcp_analysis *tcpd=NULL;
7110 uint32_t relative_hole_offset;
7111 uint32_t relative_hole_size;
7112 uint16_t base_mss = 0;
7113 uint32_t ack;
7114 uint32_t hole_start;
7115 uint32_t hole_end;
7116 int offset = 0;
7117 proto_item *hidden_item, *tf;
7118 proto_tree *field_tree;
7119 proto_item *length_item;
7121 tf = proto_tree_add_item(tree, proto_tcp_option_snack, tvb, offset, -1, ENC_NA);
7122 field_tree = proto_item_add_subtree(tf, ett_tcp_option_snack);
7124 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7125 offset, 1, ENC_BIG_ENDIAN);
7126 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7127 offset + 1, 1, ENC_BIG_ENDIAN);
7129 if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SNACK))
7130 return tvb_captured_length(tvb);
7132 conversation_t *stratconv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
7133 tcpd=get_tcp_conversation_data_idempotent(stratconv);
7135 /* The SNACK option reports missing data with a granularity of segments. */
7136 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_snack_offset,
7137 tvb, offset + 2, 2, ENC_BIG_ENDIAN, &relative_hole_offset);
7139 proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_snack_size,
7140 tvb, offset + 4, 2, ENC_BIG_ENDIAN, &relative_hole_size);
7142 ack = tvb_get_ntohl(tvb, 8);
7144 if (tcp_analyze_seq && tcp_relative_seq) {
7145 ack -= tcpd->rev->base_seq;
7148 /* To aid analysis, we can use a simple but generally effective heuristic
7149 * to report the most likely boundaries of the missing data. If the
7150 * flow is scps_capable, we track the maximum sized segment that was
7151 * acknowledged by the receiver and use that as the reporting granularity.
7152 * This may be different from the negotiated MTU due to PMTUD or flows
7153 * that do not send max-sized segments.
7155 base_mss = tcpd->fwd->maxsizeacked;
7157 if (base_mss) {
7158 /* Scale the reported offset and hole size by the largest segment acked */
7159 hole_start = ack + (base_mss * relative_hole_offset);
7160 hole_end = hole_start + (base_mss * relative_hole_size);
7162 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_snack_le,
7163 tvb, offset + 2, 2, hole_start);
7164 proto_item_set_hidden(hidden_item);
7166 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_snack_re,
7167 tvb, offset + 4, 2, hole_end);
7168 proto_item_set_hidden(hidden_item);
7170 proto_tree_add_expert_format(field_tree, pinfo, &ei_tcp_option_snack_sequence, tvb, offset+2, 4,
7171 "SNACK Sequence %u - %u%s", hole_start, hole_end, ((tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : ""));
7173 tcp_info_append_uint(pinfo, "SNLE", hole_start);
7174 tcp_info_append_uint(pinfo, "SNRE", hole_end);
7177 return tvb_captured_length(tvb);
7180 enum
7182 PROBE_VERSION_UNSPEC = 0,
7183 PROBE_VERSION_1 = 1,
7184 PROBE_VERSION_2 = 2,
7185 PROBE_VERSION_MAX
7188 /* Probe type definition. */
7189 enum
7191 PROBE_QUERY = 0,
7192 PROBE_RESPONSE = 1,
7193 PROBE_INTERNAL = 2,
7194 PROBE_TRACE = 3,
7195 PROBE_QUERY_SH = 4,
7196 PROBE_RESPONSE_SH = 5,
7197 PROBE_QUERY_INFO = 6,
7198 PROBE_RESPONSE_INFO = 7,
7199 PROBE_QUERY_INFO_SH = 8,
7200 PROBE_QUERY_INFO_SID = 9,
7201 PROBE_RST = 10,
7202 PROBE_TYPE_MAX
7205 static const value_string rvbd_probe_type_vs[] = {
7206 { PROBE_QUERY, "Probe Query" },
7207 { PROBE_RESPONSE, "Probe Response" },
7208 { PROBE_INTERNAL, "Probe Internal" },
7209 { PROBE_TRACE, "Probe Trace" },
7210 { PROBE_QUERY_SH, "Probe Query SH" },
7211 { PROBE_RESPONSE_SH, "Probe Response SH" },
7212 { PROBE_QUERY_INFO, "Probe Query Info" },
7213 { PROBE_RESPONSE_INFO, "Probe Response Info" },
7214 { PROBE_QUERY_INFO_SH, "Probe Query Info SH" },
7215 { PROBE_QUERY_INFO_SID, "Probe Query Info Store ID" },
7216 { PROBE_RST, "Probe Reset" },
7217 { 0, NULL }
7220 #define PROBE_OPTLEN_OFFSET 1
7222 #define PROBE_VERSION_TYPE_OFFSET 2
7223 #define PROBE_V1_RESERVED_OFFSET 3
7224 #define PROBE_V1_PROBER_OFFSET 4
7225 #define PROBE_V1_APPLI_VERSION_OFFSET 8
7226 #define PROBE_V1_PROXY_ADDR_OFFSET 8
7227 #define PROBE_V1_PROXY_PORT_OFFSET 12
7228 #define PROBE_V1_SH_CLIENT_ADDR_OFFSET 8
7229 #define PROBE_V1_SH_PROXY_ADDR_OFFSET 12
7230 #define PROBE_V1_SH_PROXY_PORT_OFFSET 16
7232 #define PROBE_V2_INFO_OFFSET 3
7234 #define PROBE_V2_INFO_CLIENT_ADDR_OFFSET 4
7235 #define PROBE_V2_INFO_STOREID_OFFSET 4
7237 #define PROBE_VERSION_MASK 0x01
7239 /* Probe Query Extra Info flags */
7240 #define RVBD_FLAGS_PROBE_LAST 0x01
7241 #define RVBD_FLAGS_PROBE_NCFE 0x04
7243 /* Probe Response Extra Info flags */
7244 #define RVBD_FLAGS_PROBE_SERVER 0x01
7245 #define RVBD_FLAGS_PROBE_SSLCERT 0x02
7246 #define RVBD_FLAGS_PROBE 0x10
7248 typedef struct rvbd_option_data
7250 bool valid;
7251 uint8_t type;
7252 uint8_t probe_flags;
7254 } rvbd_option_data;
7256 static void
7257 rvbd_probe_decode_version_type(const uint8_t vt, uint8_t *ver, uint8_t *type)
7259 if (vt & PROBE_VERSION_MASK) {
7260 *ver = PROBE_VERSION_1;
7261 *type = vt >> 4;
7262 } else {
7263 *ver = PROBE_VERSION_2;
7264 *type = vt >> 1;
7268 static void
7269 rvbd_probe_resp_add_info(proto_item *pitem, packet_info *pinfo, tvbuff_t *tvb, int ip_offset, uint16_t port)
7271 proto_item_append_text(pitem, ", Server Steelhead: %s:%u", tvb_ip_to_str(pinfo->pool, tvb, ip_offset), port);
7273 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA+, ");
7276 static int
7277 dissect_tcpopt_rvbd_probe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
7279 uint8_t ver, type;
7280 proto_tree *field_tree;
7281 proto_item *pitem;
7282 proto_item *length_item;
7283 int offset = 0,
7284 optlen = tvb_reported_length(tvb);
7285 struct tcpheader *tcph = (struct tcpheader*)data;
7287 pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_probe, tvb, offset, -1, ENC_NA);
7288 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe);
7290 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7291 offset, 1, ENC_BIG_ENDIAN);
7292 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7293 offset + 1, 1, ENC_BIG_ENDIAN);
7295 if (optlen < TCPOLEN_RVBD_PROBE_MIN) {
7296 /* Bogus - option length is less than what it's supposed to be for
7297 this option. */
7298 expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid,
7299 "option length should be >= %u)",
7300 TCPOLEN_RVBD_PROBE_MIN);
7301 return tvb_captured_length(tvb);
7304 rvbd_probe_decode_version_type(
7305 tvb_get_uint8(tvb, offset + PROBE_VERSION_TYPE_OFFSET),
7306 &ver, &type);
7308 proto_item_append_text(pitem, ": %s", val_to_str_const(type, rvbd_probe_type_vs, "Probe Unknown"));
7310 if (type >= PROBE_TYPE_MAX)
7311 return tvb_captured_length(tvb);
7313 if (ver == PROBE_VERSION_1) {
7314 uint16_t port;
7316 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type1, tvb,
7317 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
7318 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
7319 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
7321 if (type == PROBE_INTERNAL)
7322 return offset + PROBE_VERSION_TYPE_OFFSET;
7324 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_reserved, tvb, offset + PROBE_V1_RESERVED_OFFSET, 1, ENC_BIG_ENDIAN);
7326 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_prober, tvb,
7327 offset + PROBE_V1_PROBER_OFFSET, 4, ENC_BIG_ENDIAN);
7329 switch (type) {
7331 case PROBE_QUERY:
7332 case PROBE_QUERY_SH:
7333 case PROBE_TRACE:
7335 rvbd_option_data* option_data;
7336 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_appli_ver, tvb,
7337 offset + PROBE_V1_APPLI_VERSION_OFFSET, 2,
7338 ENC_BIG_ENDIAN);
7340 proto_item_append_text(pitem, ", CSH IP: %s", tvb_ip_to_str(pinfo->pool, tvb, offset + PROBE_V1_PROBER_OFFSET));
7342 option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);
7343 if (option_data == NULL)
7345 option_data = wmem_new0(pinfo->pool, rvbd_option_data);
7346 p_add_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num, option_data);
7349 option_data->valid = true;
7350 option_data->type = type;
7353 break;
7355 case PROBE_RESPONSE:
7356 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
7357 offset + PROBE_V1_PROXY_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
7359 port = tvb_get_ntohs(tvb, offset + PROBE_V1_PROXY_PORT_OFFSET);
7360 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
7361 offset + PROBE_V1_PROXY_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7363 rvbd_probe_resp_add_info(pitem, pinfo, tvb, offset + PROBE_V1_PROXY_ADDR_OFFSET, port);
7364 break;
7366 case PROBE_RESPONSE_SH:
7367 proto_tree_add_item(field_tree,
7368 hf_tcp_option_rvbd_probe_client, tvb,
7369 offset + PROBE_V1_SH_CLIENT_ADDR_OFFSET, 4,
7370 ENC_BIG_ENDIAN);
7372 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
7373 offset + PROBE_V1_SH_PROXY_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
7375 port = tvb_get_ntohs(tvb, offset + PROBE_V1_SH_PROXY_PORT_OFFSET);
7376 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
7377 offset + PROBE_V1_SH_PROXY_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7379 rvbd_probe_resp_add_info(pitem, pinfo, tvb, offset + PROBE_V1_SH_PROXY_ADDR_OFFSET, port);
7380 break;
7383 else if (ver == PROBE_VERSION_2) {
7384 proto_item *ver_pi;
7385 proto_item *flag_pi;
7386 proto_tree *flag_tree;
7387 uint8_t flags;
7389 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type2, tvb,
7390 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
7392 proto_tree_add_uint_format_value(
7393 field_tree, hf_tcp_option_rvbd_probe_version2, tvb,
7394 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver, "%u", ver);
7395 /* Use version1 for filtering purposes because version2 packet
7396 value is 0, but filtering is usually done for value 2 */
7397 ver_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
7398 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver);
7399 proto_item_set_hidden(ver_pi);
7401 switch (type) {
7403 case PROBE_QUERY_INFO:
7404 case PROBE_QUERY_INFO_SH:
7405 case PROBE_QUERY_INFO_SID:
7406 flags = tvb_get_uint8(tvb, offset + PROBE_V2_INFO_OFFSET);
7407 flag_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_flags,
7408 tvb, offset + PROBE_V2_INFO_OFFSET,
7409 1, flags);
7411 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
7412 proto_tree_add_item(flag_tree,
7413 hf_tcp_option_rvbd_probe_flag_not_cfe,
7414 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7415 proto_tree_add_item(flag_tree,
7416 hf_tcp_option_rvbd_probe_flag_last_notify,
7417 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7419 switch (type)
7421 case PROBE_QUERY_INFO:
7423 rvbd_option_data* option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);
7424 if (option_data == NULL)
7426 option_data = wmem_new0(pinfo->pool, rvbd_option_data);
7427 p_add_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num, option_data);
7430 option_data->probe_flags = flags;
7432 break;
7433 case PROBE_QUERY_INFO_SH:
7434 proto_tree_add_item(flag_tree,
7435 hf_tcp_option_rvbd_probe_client, tvb,
7436 offset + PROBE_V2_INFO_CLIENT_ADDR_OFFSET,
7437 4, ENC_BIG_ENDIAN);
7438 break;
7439 case PROBE_QUERY_INFO_SID:
7440 proto_tree_add_item(flag_tree,
7441 hf_tcp_option_rvbd_probe_storeid, tvb,
7442 offset + PROBE_V2_INFO_STOREID_OFFSET,
7443 4, ENC_BIG_ENDIAN);
7444 break;
7447 if (type != PROBE_QUERY_INFO_SID &&
7448 tcph != NULL &&
7449 (tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK) &&
7450 (flags & RVBD_FLAGS_PROBE_LAST)) {
7451 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA++, ");
7454 break;
7456 case PROBE_RESPONSE_INFO:
7457 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
7458 tvb, offset + PROBE_V2_INFO_OFFSET,
7459 1, ENC_BIG_ENDIAN);
7461 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
7462 proto_tree_add_item(flag_tree,
7463 hf_tcp_option_rvbd_probe_flag_probe_cache,
7464 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7465 proto_tree_add_item(flag_tree,
7466 hf_tcp_option_rvbd_probe_flag_sslcert,
7467 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7468 proto_tree_add_item(flag_tree,
7469 hf_tcp_option_rvbd_probe_flag_server_connected,
7470 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
7471 break;
7473 case PROBE_RST:
7474 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
7475 tvb, offset + PROBE_V2_INFO_OFFSET,
7476 1, ENC_BIG_ENDIAN);
7477 break;
7481 return tvb_captured_length(tvb);
7484 enum {
7485 TRPY_OPTNUM_OFFSET = 0,
7486 TRPY_OPTLEN_OFFSET = 1,
7488 TRPY_OPTIONS_OFFSET = 2,
7489 TRPY_SRC_ADDR_OFFSET = 4,
7490 TRPY_DST_ADDR_OFFSET = 8,
7491 TRPY_SRC_PORT_OFFSET = 12,
7492 TRPY_DST_PORT_OFFSET = 14,
7493 TRPY_CLIENT_PORT_OFFSET = 16
7496 /* Trpy Flags */
7497 #define RVBD_FLAGS_TRPY_MODE 0x0001
7498 #define RVBD_FLAGS_TRPY_OOB 0x0002
7499 #define RVBD_FLAGS_TRPY_CHKSUM 0x0004
7500 #define RVBD_FLAGS_TRPY_FW_RST 0x0100
7501 #define RVBD_FLAGS_TRPY_FW_RST_INNER 0x0200
7502 #define RVBD_FLAGS_TRPY_FW_RST_PROBE 0x0400
7504 static const true_false_string trpy_mode_str = {
7505 "Port Transparency",
7506 "Full Transparency"
7509 static int
7510 dissect_tcpopt_rvbd_trpy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
7512 proto_tree *field_tree;
7513 proto_item *pitem;
7514 proto_item *length_item;
7515 uint16_t sport, dport, flags;
7516 int offset = 0,
7517 optlen = tvb_reported_length(tvb);
7518 static int * const rvbd_trpy_flags[] = {
7519 &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
7520 &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
7521 &hf_tcp_option_rvbd_trpy_flag_fw_rst,
7522 &hf_tcp_option_rvbd_trpy_flag_chksum,
7523 &hf_tcp_option_rvbd_trpy_flag_oob,
7524 &hf_tcp_option_rvbd_trpy_flag_mode,
7525 NULL
7528 col_prepend_fstr(pinfo->cinfo, COL_INFO, "TRPY, ");
7530 pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_trpy, tvb, offset, -1, ENC_NA);
7531 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_trpy);
7533 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
7534 offset, 1, ENC_BIG_ENDIAN);
7535 length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
7536 offset + 1, 1, ENC_BIG_ENDIAN);
7538 if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_RVBD_TRPY_MIN))
7539 return tvb_captured_length(tvb);
7541 flags = tvb_get_ntohs(tvb, offset + TRPY_OPTIONS_OFFSET);
7542 proto_tree_add_bitmask_with_flags(field_tree, tvb, offset + TRPY_OPTIONS_OFFSET, hf_tcp_option_rvbd_trpy_flags,
7543 ett_tcp_opt_rvbd_trpy_flags, rvbd_trpy_flags, ENC_NA, BMT_NO_APPEND);
7545 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src,
7546 tvb, offset + TRPY_SRC_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
7548 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst,
7549 tvb, offset + TRPY_DST_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
7551 sport = tvb_get_ntohs(tvb, offset + TRPY_SRC_PORT_OFFSET);
7552 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src_port,
7553 tvb, offset + TRPY_SRC_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7555 dport = tvb_get_ntohs(tvb, offset + TRPY_DST_PORT_OFFSET);
7556 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst_port,
7557 tvb, offset + TRPY_DST_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7559 proto_item_append_text(pitem, " %s:%u -> %s:%u",
7560 tvb_ip_to_str(pinfo->pool, tvb, offset + TRPY_SRC_ADDR_OFFSET), sport,
7561 tvb_ip_to_str(pinfo->pool, tvb, offset + TRPY_DST_ADDR_OFFSET), dport);
7563 /* Client port only set on SYN: optlen == 18 */
7564 if ((flags & RVBD_FLAGS_TRPY_OOB) && (optlen > TCPOLEN_RVBD_TRPY_MIN))
7565 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_client_port,
7566 tvb, offset + TRPY_CLIENT_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
7568 /* Despite that we have the right TCP ports for other protocols,
7569 * the data is related to the Riverbed Optimization Protocol and
7570 * not understandable by normal protocol dissectors. If the sport
7571 * protocol is available then use that, otherwise just output it
7572 * as a hex-dump.
7574 if (sport_handle != NULL) {
7575 conversation_t *conversation;
7576 conversation = find_or_create_conversation(pinfo);
7577 if (conversation_get_dissector(conversation, pinfo->num) != sport_handle) {
7578 conversation_set_dissector(conversation, sport_handle);
7580 } else if (data_handle != NULL) {
7581 conversation_t *conversation;
7582 conversation = find_or_create_conversation(pinfo);
7583 if (conversation_get_dissector(conversation, pinfo->num) != data_handle) {
7584 conversation_set_dissector(conversation, data_handle);
7588 return tvb_captured_length(tvb);
7591 /* Started as a copy of dissect_ip_tcp_options(), but was changed to support
7592 options as a dissector table */
7593 static void
7594 tcp_dissect_options(tvbuff_t *tvb, int offset, unsigned length,
7595 packet_info *pinfo, proto_tree *opt_tree,
7596 proto_item *opt_item, void * data)
7598 unsigned char opt;
7599 unsigned optlen, nop_count = 0;
7600 proto_tree *field_tree;
7601 const char *name;
7602 dissector_handle_t option_dissector;
7603 tvbuff_t *next_tvb;
7604 struct tcpheader *tcph = (struct tcpheader *)data;
7605 bool mss_seen = false;
7606 bool eol_seen = false;
7607 bool sack_perm_seen = false;
7609 while (length > 0) {
7610 opt = tvb_get_uint8(tvb, offset);
7611 if (eol_seen && opt != TCPOPT_EOL) {
7612 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_non_zero_bytes_after_eol, tvb, offset, length,
7613 "Non-zero header padding");
7614 return;
7616 --length; /* account for type byte */
7617 if ((opt == TCPOPT_EOL) || (opt == TCPOPT_NOP)) {
7618 int local_proto;
7619 proto_item* field_item;
7621 /* We assume that the only options with no length are EOL and
7622 NOP options, so that we can treat unknown options as having
7623 a minimum length of 2, and at least be able to move on to
7624 the next option by using the length in the option. */
7625 if (opt == TCPOPT_EOL) {
7626 local_proto = proto_tcp_option_eol;
7627 eol_seen = true;
7628 } else if (opt == TCPOPT_NOP) {
7629 local_proto = proto_tcp_option_nop;
7631 if (opt_item && (nop_count == 0 || offset % 4)) {
7632 /* Count number of NOP in a row within a uint32 */
7633 nop_count++;
7635 if (nop_count == 4) {
7636 expert_add_info(pinfo, opt_item, &ei_tcp_nop);
7638 } else {
7639 nop_count = 0;
7641 } else {
7642 DISSECTOR_ASSERT_NOT_REACHED();
7645 field_item = proto_tree_add_item(opt_tree, local_proto, tvb, offset, 1, ENC_NA);
7646 field_tree = proto_item_add_subtree(field_item, ett_tcp_option_other);
7647 proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
7648 proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", proto_get_protocol_short_name(find_protocol_by_id(local_proto)));
7649 offset += 1;
7650 } else {
7651 option_dissector = dissector_get_uint_handle(tcp_option_table, opt);
7652 if (option_dissector == NULL) {
7653 name = wmem_strdup_printf(pinfo->pool, "Unknown (0x%02x)", opt);
7654 option_dissector = tcp_opt_unknown_handle;
7655 } else {
7656 name = dissector_handle_get_protocol_short_name(option_dissector);
7659 /* Option has a length. Is it in the packet? */
7660 if (length == 0) {
7661 /* Bogus - packet must at least include option code byte and
7662 length byte! */
7663 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, 1,
7664 "%s (length byte past end of options)", name);
7665 return;
7668 optlen = tvb_get_uint8(tvb, offset + 1); /* total including type, len */
7669 --length; /* account for length byte */
7671 if (optlen < 2) {
7672 /* Bogus - option length is too short to include option code and
7673 option length. */
7674 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, 2,
7675 "%s (with too-short option length = %u byte%s)",
7676 name, optlen, plurality(optlen, "", "s"));
7677 return;
7678 } else if (optlen - 2 > length) {
7679 /* Bogus - option goes past the end of the header. */
7680 proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, length,
7681 "%s (option length = %u byte%s says option goes past end of options)",
7682 name, optlen, plurality(optlen, "", "s"));
7683 return;
7686 if (opt == TCPOPT_MSS)
7688 mss_seen = true;
7689 } else if (opt == TCPOPT_SACK_PERM)
7691 sack_perm_seen = true;
7694 next_tvb = tvb_new_subset_length(tvb, offset, optlen);
7695 call_dissector_with_data(option_dissector, next_tvb, pinfo, opt_tree/* tree */, data);
7696 proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name);
7698 offset += optlen;
7699 length -= (optlen-2); //already accounted for type and len bytes
7703 if (tcph->th_flags & TH_SYN)
7705 if (mss_seen == false)
7707 expert_add_info(pinfo, opt_item, &ei_tcp_option_mss_absent);
7709 if (sack_perm_seen == false)
7711 expert_add_info(pinfo, opt_item, &ei_tcp_option_sack_perm_absent);
7716 /* Determine if there is a sub-dissector and call it; return true
7717 if there was a sub-dissector, false otherwise.
7719 This has been separated into a stand alone routine to other protocol
7720 dissectors can call to it, e.g., SOCKS. */
7722 static bool try_heuristic_first;
7725 /* this function can be called with tcpd==NULL as from the msproxy dissector */
7726 bool
7727 decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
7728 proto_tree *tree, int src_port, int dst_port,
7729 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
7731 tvbuff_t *next_tvb;
7732 int low_port, high_port;
7733 int save_desegment_offset;
7734 bool try_low_port, try_high_port, try_server_port;
7735 uint32_t save_desegment_len;
7736 heur_dtbl_entry_t *hdtbl_entry;
7737 exp_pdu_data_t *exp_pdu_data;
7739 /* Don't call subdissectors for keepalives. Even though they do contain
7740 * payload "data", it's just garbage. Display any data the keepalive
7741 * packet might contain though.
7743 if(tcpd && tcpd->ta) {
7744 if(tcpd->ta->flags&TCP_A_KEEP_ALIVE) {
7745 next_tvb = tvb_new_subset_remaining(tvb, offset);
7746 call_dissector(data_handle, next_tvb, pinfo, tree);
7747 return true;
7751 if (tcp_no_subdissector_on_error && !(tcp_desegment && tcp_reassemble_out_of_order) &&
7752 tcpd && tcpd->ta && tcpd->ta->flags & (TCP_A_RETRANSMISSION | TCP_A_FAST_RETRANSMISSION |
7753 TCP_A_SPURIOUS_RETRANSMISSION | TCP_A_OUT_OF_ORDER)) {
7754 /* Don't try to dissect a retransmission high chance that it will mess
7755 * subdissectors for protocols that require in-order delivery of the
7756 * PDUs. (i.e. DCE/RPCoverHTTP and encryption)
7757 * If OoO reassembly is enabled and if this segment was previously lost,
7758 * then this retransmission could have finished reassembly, so continue.
7759 * XXX should this option be removed? "tcp_reassemble_out_of_order"
7760 * should have addressed the above in-order requirement.
7762 return false;
7764 next_tvb = tvb_new_subset_remaining(tvb, offset);
7766 save_desegment_offset = pinfo->desegment_offset;
7767 save_desegment_len = pinfo->desegment_len;
7769 /* determine if this packet is part of a conversation and call dissector */
7770 /* for the conversation if available */
7772 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, CONVERSATION_TCP,
7773 src_port, dst_port, next_tvb, pinfo, tree, tcpinfo, 0)) {
7774 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7775 handle_export_pdu_conversation(pinfo, next_tvb, src_port, dst_port, tcpinfo);
7776 return true;
7779 /* If the user has manually configured one of the server, low, or high
7780 * ports to a dissector other than the default (via Decode As or the
7781 * preferences associated with Decode As), try those first, in that order.
7783 try_server_port = false;
7784 if (tcpd && tcpd->server_port != 0) {
7785 if (dissector_is_uint_changed(subdissector_table, tcpd->server_port)) {
7786 if (dissector_try_uint_with_data(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7787 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7788 handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo);
7789 return true;
7791 } else {
7792 /* The default; try it later */
7793 try_server_port = true;
7797 /* Prevent the client port number being used for selecting the dissector
7798 when we have seen the SYN or SYN/ACK (and therefor tcpd->server_port
7799 is defined)
7800 Use the preference Clientport dissectors to keep dissecting certain
7801 protocols based on the client port instead of the server port
7802 Port 20 for active ftp data transfers being the default. */
7803 if (tcpd && tcpd->server_port != 0) {
7804 if (dst_port == tcpd->server_port) {
7805 if (!(dissector_is_uint_changed(subdissector_table, src_port) ||
7806 value_is_in_range(tcp_clientport_dissectors_range, src_port) ) ) {
7807 src_port = 0;
7809 } else {
7810 if (!(dissector_is_uint_changed(subdissector_table, dst_port) ||
7811 value_is_in_range(tcp_clientport_dissectors_range, dst_port) ) ) {
7812 dst_port = 0;
7817 if (src_port > dst_port) {
7818 low_port = dst_port;
7819 high_port = src_port;
7820 } else {
7821 low_port = src_port;
7822 high_port = dst_port;
7825 try_low_port = false;
7826 if (low_port != 0) {
7827 if (dissector_is_uint_changed(subdissector_table, low_port)) {
7828 if (dissector_try_uint_with_data(subdissector_table, low_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7829 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7830 handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo);
7831 return true;
7833 } else {
7834 /* The default; try it later */
7835 try_low_port = true;
7839 try_high_port = false;
7840 if (high_port != 0) {
7841 if (dissector_is_uint_changed(subdissector_table, high_port)) {
7842 if (dissector_try_uint_with_data(subdissector_table, high_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7843 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7844 handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo);
7845 return true;
7847 } else {
7848 /* The default; try it later */
7849 try_high_port = true;
7853 if (try_heuristic_first) {
7854 /* do lookup with the heuristic subdissector table */
7855 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) {
7856 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7857 handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo);
7858 return true;
7862 /* Do lookups with the subdissector table.
7863 Try the server port captured on the SYN or SYN|ACK packet. After that
7864 try the port number with the lower value first, followed by the
7865 port number with the higher value. This means that, for packets
7866 where a dissector is registered for *both* port numbers:
7868 1) we pick the same dissector for traffic going in both directions;
7870 2) we prefer the port number that's more likely to be the right
7871 one (as that prefers well-known ports to reserved ports);
7873 although there is, of course, no guarantee that any such strategy
7874 will always pick the right port number.
7876 XXX - we ignore port numbers of 0, as some dissectors use a port
7877 number of 0 to disable the port. */
7879 if (try_server_port &&
7880 dissector_try_uint_with_data(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7881 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7882 handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo);
7883 return true;
7886 if (try_low_port &&
7887 dissector_try_uint_with_data(subdissector_table, low_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7888 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7889 handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo);
7890 return true;
7892 if (try_high_port &&
7893 dissector_try_uint_with_data(subdissector_table, high_port, next_tvb, pinfo, tree, true, tcpinfo)) {
7894 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7895 handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo);
7896 return true;
7899 if (!try_heuristic_first) {
7900 /* do lookup with the heuristic subdissector table */
7901 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) {
7902 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7903 handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo);
7904 return true;
7909 * heuristic / conversation / port registered dissectors rejected the packet;
7910 * make sure they didn't also request desegmentation (we could just override
7911 * the request, but rejecting a packet *and* requesting desegmentation is a sign
7912 * of the dissector's code needing clearer thought, so we fail so that the
7913 * problem is made more obvious).
7915 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
7916 save_desegment_len == pinfo->desegment_len);
7918 /* Oh, well, we don't know this; dissect it as data. */
7919 call_dissector(data_handle,next_tvb, pinfo, tree);
7921 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
7922 if (have_tap_listener(exported_pdu_tap)) {
7923 exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME);
7924 exp_pdu_data->tvb_captured_length = tvb_captured_length(next_tvb);
7925 exp_pdu_data->tvb_reported_length = tvb_reported_length(next_tvb);
7926 exp_pdu_data->pdu_tvb = next_tvb;
7928 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
7930 return false;
7933 static void
7934 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
7935 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
7936 uint32_t seq, uint32_t nxtseq, bool is_tcp_segment,
7937 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
7939 pinfo->want_pdu_tracking=0;
7941 TRY {
7942 if(is_tcp_segment) {
7943 /*qqq see if it is an unaligned PDU */
7944 if(tcpd && tcp_analyze_seq && (!tcp_desegment)) {
7945 if(seq || nxtseq) {
7946 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
7947 seq, nxtseq, tcpd->fwd->multisegment_pdus);
7951 /* if offset is -1 this means that this segment is known
7952 * to be fully inside a previously detected pdu
7953 * so we don't even need to try to dissect it either.
7955 if( (offset!=-1) &&
7956 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
7957 dst_port, tcpd, tcpinfo) ) {
7959 * We succeeded in handing off to a subdissector.
7961 * Is this a TCP segment or a reassembled chunk of
7962 * TCP payload?
7964 if(is_tcp_segment) {
7965 /* if !visited, check want_pdu_tracking and
7966 store it in table */
7967 if(tcpd && (!pinfo->fd->visited) &&
7968 tcp_analyze_seq && pinfo->want_pdu_tracking) {
7969 if(seq || nxtseq) {
7970 pdu_store_sequencenumber_of_next_pdu(
7971 pinfo,
7972 seq,
7973 nxtseq+pinfo->bytes_until_next_pdu,
7974 tcpd->fwd->multisegment_pdus);
7980 CATCH_ALL {
7981 /* We got an exception. At this point the dissection is
7982 * completely aborted and execution will be transferred back
7983 * to (probably) the frame dissector.
7984 * Here we have to place whatever we want the dissector
7985 * to do before aborting the tcp dissection.
7988 * Is this a TCP segment or a reassembled chunk of TCP
7989 * payload?
7991 if(is_tcp_segment) {
7993 * It's from a TCP segment.
7995 * if !visited, check want_pdu_tracking and store it
7996 * in table
7998 if(tcpd && (!pinfo->fd->visited) && tcp_analyze_seq && pinfo->want_pdu_tracking) {
7999 if(seq || nxtseq) {
8000 pdu_store_sequencenumber_of_next_pdu(pinfo,
8001 seq,
8002 nxtseq+pinfo->bytes_until_next_pdu,
8003 tcpd->fwd->multisegment_pdus);
8007 RETHROW;
8009 ENDTRY;
8012 void
8013 dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, uint32_t seq,
8014 uint32_t nxtseq, uint32_t sport, uint32_t dport,
8015 proto_tree *tree, proto_tree *tcp_tree,
8016 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
8018 int nbytes;
8019 bool save_fragmented;
8021 nbytes = tvb_reported_length_remaining(tvb, offset);
8022 proto_tree_add_bytes_format(tcp_tree, hf_tcp_payload, tvb, offset,
8023 -1, NULL, "TCP payload (%u byte%s)", nbytes,
8024 plurality(nbytes, "", "s"));
8026 /* Can we desegment this segment? */
8027 if (pinfo->can_desegment) {
8028 /* Yes. */
8029 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
8030 tcp_tree, tcpd, tcpinfo);
8031 } else {
8032 /* No - just call the subdissector.
8033 Mark this as fragmented, so if somebody throws an exception,
8034 we don't report it as a malformed frame. */
8035 save_fragmented = pinfo->fragmented;
8036 pinfo->fragmented = true;
8038 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
8039 seq, nxtseq, true, tcpd, tcpinfo);
8040 pinfo->fragmented = save_fragmented;
8044 static bool
8045 capture_tcp(const unsigned char *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header)
8047 uint16_t src_port, dst_port, low_port, high_port;
8049 if (!BYTES_ARE_IN_FRAME(offset, len, 4))
8050 return false;
8052 capture_dissector_increment_count(cpinfo, proto_tcp);
8054 src_port = pntoh16(&pd[offset]);
8055 dst_port = pntoh16(&pd[offset+2]);
8057 if (src_port > dst_port) {
8058 low_port = dst_port;
8059 high_port = src_port;
8060 } else {
8061 low_port = src_port;
8062 high_port = dst_port;
8065 if (low_port != 0 &&
8066 try_capture_dissector("tcp.port", low_port, pd, offset+20, len, cpinfo, pseudo_header))
8067 return true;
8069 if (high_port != 0 &&
8070 try_capture_dissector("tcp.port", high_port, pd, offset+20, len, cpinfo, pseudo_header))
8071 return true;
8073 /* We've at least identified one type of packet, so this shouldn't be "other" */
8074 return true;
8077 typedef struct _tcp_tap_cleanup_t {
8079 packet_info *pinfo;
8080 struct tcpheader *tcph;
8082 } tcp_tap_cleanup_t;
8084 static void tcp_tap_cleanup(void *data)
8086 tcp_tap_cleanup_t *cleanup = (tcp_tap_cleanup_t *)data;
8088 tap_queue_packet(tcp_tap, cleanup->pinfo, cleanup->tcph);
8091 static int
8092 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
8094 uint8_t th_off_x2; /* combines th_off and th_x2 */
8095 uint16_t th_sum;
8096 uint32_t th_urp;
8097 proto_tree *tcp_tree = NULL, *field_tree = NULL;
8098 proto_item *ti = NULL, *tf, *hidden_item;
8099 proto_item *options_item, *hide_seqack_abs_item;
8100 proto_tree *options_tree;
8101 int offset = 0;
8102 char *flags_str, *flags_str_first_letter;
8103 unsigned optlen;
8104 uint32_t nxtseq = 0;
8105 unsigned reported_len;
8106 vec_t cksum_vec[4];
8107 uint32_t phdr[2];
8108 uint16_t computed_cksum;
8109 uint16_t real_window;
8110 unsigned captured_length_remaining;
8111 bool desegment_ok;
8112 struct tcpinfo tcpinfo;
8113 struct tcpheader *tcph;
8114 proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL, *scaled_pi;
8115 conversation_t *conv=NULL;
8116 struct tcp_analysis *tcpd=NULL;
8117 struct tcp_per_packet_data_t *tcppd=NULL;
8118 proto_item *item;
8119 proto_tree *checksum_tree;
8120 bool icmp_ip = false;
8121 uint8_t conversation_completeness = 0;
8122 bool conversation_is_new = false;
8123 uint8_t ace;
8125 tcph = wmem_new0(pinfo->pool, struct tcpheader);
8126 tcph->th_sport = tvb_get_ntohs(tvb, offset);
8127 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
8128 copy_address_shallow(&tcph->ip_src, &pinfo->src);
8129 copy_address_shallow(&tcph->ip_dst, &pinfo->dst);
8131 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
8132 col_clear(pinfo->cinfo, COL_INFO);
8133 col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, tcph->th_sport, tcph->th_dport);
8135 if (tree) {
8136 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, ENC_NA);
8137 if (tcp_summary_in_tree) {
8138 proto_item_append_text(ti, ", Src Port: %s, Dst Port: %s",
8139 port_with_resolution_to_str(pinfo->pool, PT_TCP, tcph->th_sport),
8140 port_with_resolution_to_str(pinfo->pool, PT_TCP, tcph->th_dport));
8142 tcp_tree = proto_item_add_subtree(ti, ett_tcp);
8143 p_add_proto_data(pinfo->pool, pinfo, proto_tcp, pinfo->curr_layer_num, tcp_tree);
8145 proto_tree_add_item(tcp_tree, hf_tcp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN);
8146 proto_tree_add_item(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
8147 hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
8148 proto_item_set_hidden(hidden_item);
8149 hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
8150 proto_item_set_hidden(hidden_item);
8152 /* If we're dissecting the headers of a TCP packet in an ICMP packet
8153 * then go ahead and put the sequence numbers in the tree now (because
8154 * they won't be put in later because the ICMP packet only contains up
8155 * to the sequence number).
8156 * We should only need to do this for IPv4 since IPv6 will hopefully
8157 * carry enough TCP payload for this dissector to put the sequence
8158 * numbers in via the regular code path.
8161 wmem_list_frame_t *frame;
8162 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
8163 if (proto_ip == (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame))) {
8164 frame = wmem_list_frame_prev(frame);
8165 if (proto_icmp == (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame))) {
8166 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
8167 icmp_ip = true;
8173 /* Set the source and destination port numbers as soon as we get them,
8174 so that they're available to the "Follow TCP Stream" code even if
8175 we throw an exception dissecting the rest of the TCP header. */
8176 pinfo->ptype = PT_TCP;
8177 pinfo->srcport = tcph->th_sport;
8178 pinfo->destport = tcph->th_dport;
8180 p_add_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num, GUINT_TO_POINTER(tcph->th_sport));
8181 p_add_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num, GUINT_TO_POINTER(tcph->th_dport));
8183 tcph->th_rawseq = tvb_get_ntohl(tvb, offset + 4);
8184 tcph->th_seq = tcph->th_rawseq;
8185 tcph->th_rawack = tvb_get_ntohl(tvb, offset + 8);
8186 tcph->th_ack = tcph->th_rawack;
8187 th_off_x2 = tvb_get_uint8(tvb, offset + 12);
8188 tcpinfo.flags = tcph->th_flags = tvb_get_ntohs(tvb, offset + 12) & TH_MASK;
8189 tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
8191 /* find(or create if needed) the conversation for this tcp session
8192 * This is a slight deviation from find_or_create_conversation so it's
8193 * done manually. This is done to avoid conversation overlapping when
8194 * reusing ports (see issue 15097), as find_or_create_conversation automatically
8195 * extends the conversation found. This extension is done later.
8198 conv = find_conversation_strat(pinfo, CONVERSATION_TCP, 0);
8199 if(!conv) {
8200 conv=conversation_new_strat(pinfo, CONVERSATION_TCP, 0);
8201 conversation_is_new = true;
8204 tcpd=get_tcp_conversation_data(conv,pinfo);
8206 if (!PINFO_FD_VISITED(pinfo)) {
8207 /* If this is a SYN packet, then check if its seq-nr is different
8208 * from the base_seq of the retrieved conversation. If this is the
8209 * case, create a new conversation with the same addresses and ports
8210 * and set the TA_PORTS_REUSED flag. (XXX: There is a small chance
8211 * that this is an old duplicate SYN received after the connection
8212 * is ESTABLISHED on both sides, the other side will respond with
8213 * an appropriate ACK, and this SYN ought to be ignored rather than
8214 * create a new conversation.)
8216 * If the seq-nr is the same as the base_seq, it might be a simple
8217 * retransmission, reattempting a handshake that was reset (due
8218 * to a half-open connection) with the same sequence number, or
8219 * (unlikely) a new connection that happens to use the same sequence
8220 * number as the previous one (#18333).
8222 * If we have received a RST or FIN on the retrieved conversation,
8223 * we can detect that unlikely case, and create a new conversation
8224 * in order to clear out the follow info, sequence analysis,
8225 * desegmentation, etc.
8226 * If not, it's probably a retransmission, and will be marked
8227 * as one later, but restore some flow values to reduce the
8228 * sequence analysis warnings if our capture file is missing a RST
8229 * or FIN segment that was present on the network.
8231 * XXX - Is this affected by MPTCP which can use multiple SYNs?
8233 if (tcpd != NULL && (tcph->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) {
8234 if (tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET) {
8235 if(tcph->th_seq!=tcpd->fwd->base_seq || (tcpd->conversation_completeness & TCP_COMPLETENESS_RST) || (tcpd->conversation_completeness & TCP_COMPLETENESS_FIN)) {
8236 conv=conversation_new_strat(pinfo, CONVERSATION_TCP, 0);
8237 tcpd=get_tcp_conversation_data(conv,pinfo);
8239 if(!tcpd->ta)
8240 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, true, tcpd);
8241 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
8243 /* As above, a new conversation starting with a SYN implies conversation completeness value 1 */
8244 conversation_is_new = true;
8245 } else {
8247 * Sometimes we need to restore the nextseq value.
8248 * As stated in RFC 793 3.4 a RST packet might be
8249 * sent with SEQ being equal to the ACK received,
8250 * thus breaking our flow monitoring. (issue 17616)
8252 if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info) {
8253 tcpd->fwd->tcp_analyze_seq_info->nextseq = tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked;
8256 if(!tcpd->ta)
8257 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, true, tcpd);
8259 } else {
8261 * TCP_S_BASE_SEQ_SET being not set, we are dealing with a new conversation,
8262 * either created ad hoc above (general case), or by a higher protocol such as FTP.
8263 * Track this information, as the Completeness value will be initialized later.
8264 * See issue 19092.
8266 conversation_is_new = true;
8268 tcpd->had_acc_ecn_setup_syn = (tcph->th_flags & (TH_AE|TH_CWR|TH_ECE)) == (TH_AE|TH_CWR|TH_ECE);
8271 /* Handle cases of a SYN/ACK packet where there's evidence of a new
8272 * conversation but the capture is missing the SYN packet of the
8273 * new conversation.
8275 * If this is a SYN/ACK packet, then check if its seq-nr is different
8276 * from the base_seq of the retrieved conversation. If this is the
8277 * case, create a new conversation as above with a SYN packet, and set
8278 * the TA_PORTS_REUSED flag and override the base seq.
8279 * If the seq-nr is the same as the base_seq, then do nothing so it
8280 * will be marked as a retransmission later, unless we have received
8281 * a RST or FIN on the conversation (in which case this is the case
8282 * of a RST followed by the same initial sequence number being picked.)
8284 * If this is an unacceptable SYN-ACK and the other side believes that
8285 * the conversation is ESTABLISHED, it will be replied to with an
8286 * empty ACK with the current sequence number (according to the other
8287 * side.) See RFC 9293 3.5.2. This *probably* leads to a situation where
8288 * the side sending this SYN-ACK then issues a RST, because the two
8289 * sides have different ideas about the connection state. It's not clear
8290 * how to handle the annoying edge case where A sends a SYN, B responds
8291 * with a SYN-ACK that A intends to accept, but before A can finish
8292 * the handshake B responds with another SYN-ACK _with a different seq-nr_
8293 * instead of retransmitting, then A responds accepting the first SYN-ACK,
8294 * and then B goes on happily using the sequence number from the first
8295 * SYN-ACK, forgetting all about the second one it sent instead of sending
8296 * a RST. In such a case we'll have changed the seq-nr to the new one
8297 * and/or set up a new conversation instead of just ignoring that SYN-ACK.
8299 * XXX - Is this affected by MPTCP which can use multiple SYNs?
8301 if (tcpd != NULL && (tcph->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
8302 if ((tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET) &&
8303 (tcph->th_seq != tcpd->fwd->base_seq ||
8304 (tcpd->conversation_completeness & TCP_COMPLETENESS_RST) ||
8305 (tcpd->conversation_completeness & TCP_COMPLETENESS_FIN))) {
8306 /* the retrieved conversation might have a different base_seq (issue 16944) */
8308 conv=conversation_new_strat(pinfo, CONVERSATION_TCP, 0);
8309 tcpd=get_tcp_conversation_data(conv,pinfo);
8311 if(!tcpd->ta)
8312 tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, true, tcpd);
8313 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
8315 /* As above, a new conversation */
8316 conversation_is_new = true;
8318 tcpd->had_acc_ecn_setup_syn_ack = ((tcph->th_flags & (TH_AE|TH_CWR)) == TH_CWR) ||
8319 ((tcph->th_flags & (TH_AE|TH_ECE)) == TH_AE);
8322 /* Do we need to calculate timestamps relative to the tcp-stream? */
8323 if (tcp_calculate_ts) {
8324 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
8326 /* Calculate the timestamps relative to this conversation */
8327 tcp_calculate_timestamps(pinfo, tcpd, tcppd);
8331 if (tcpd) {
8332 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, tcpd->stream);
8333 proto_item_set_generated(item);
8334 tcpinfo.stream = tcpd->stream;
8336 if (tcppd) {
8337 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream_pnum, tvb, offset, 0, tcppd->pnum);
8338 proto_item_set_generated(item);
8341 /* Display the completeness of this TCP conversation */
8342 static int* const completeness_fields[] = {
8343 &hf_tcp_completeness_rst,
8344 &hf_tcp_completeness_fin,
8345 &hf_tcp_completeness_data,
8346 &hf_tcp_completeness_ack,
8347 &hf_tcp_completeness_syn_ack,
8348 &hf_tcp_completeness_syn,
8349 NULL};
8351 item = proto_tree_add_bitmask_value_with_flags(tcp_tree, NULL, 0,
8352 hf_tcp_completeness, ett_tcp_completeness, completeness_fields,
8353 tcpd->conversation_completeness, BMT_NO_APPEND);
8354 proto_item_set_generated(item);
8355 field_tree = proto_item_add_subtree(item, ett_tcp_completeness);
8357 flags_str_first_letter = tcpd->conversation_completeness_str;
8358 item = proto_tree_add_string(field_tree, hf_tcp_completeness_str, tvb, 0, 0, flags_str_first_letter);
8359 proto_item_set_generated(item);
8361 /* Copy the stream index into the header as well to make it available
8362 * to tap listeners.
8364 tcph->th_stream = tcpd->stream;
8366 /* Copy the stream index into pinfo as well to make it available
8367 * to callback functions (essentially conversation following events in GUI)
8369 pinfo->stream_id = tcpd->stream;
8371 /* initialize the SACK blocks seen to 0 */
8372 if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info) {
8373 tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = 0;
8377 /* is there any manual analysis waiting ? */
8378 if(pinfo->fd->tcp_snd_manual_analysis > 0) {
8379 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
8380 tcppd->tcp_snd_manual_analysis = pinfo->fd->tcp_snd_manual_analysis;
8383 /* We have have the absolute sequence numbers (we would have thrown an
8384 * exception if not) and tcpd, so set relative sequence numbers now. */
8386 /* XXX - Why not in an error packet? */
8387 if (tcpd != NULL && !pinfo->flags.in_error_pkt) {
8388 /* initialize base_seq numbers if needed */
8389 if (!(pinfo->fd->visited)) {
8390 /* if this is the first segment for this list we need to store the
8391 * base_seq
8392 * We use TCP_S_SAW_SYN/SYNACK to distinguish between client and server
8394 * Start relative seq and ack numbers at 1 if this
8395 * is not a SYN packet. This makes the relative
8396 * seq/ack numbers to be displayed correctly in the
8397 * event that the SYN or SYN/ACK packet is not seen
8398 * (this solves bug 1542)
8400 if( !(tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET)) {
8401 if(tcph->th_flags & TH_SYN) {
8402 tcpd->fwd->base_seq = tcph->th_seq;
8403 tcpd->fwd->static_flags |= (tcph->th_flags & TH_ACK) ? TCP_S_SAW_SYNACK : TCP_S_SAW_SYN;
8405 else {
8406 tcpd->fwd->base_seq = tcph->th_seq-1;
8408 tcpd->fwd->static_flags |= TCP_S_BASE_SEQ_SET;
8411 /* Only store reverse sequence if this isn't the SYN
8412 * There's no guarantee that the ACK field of a SYN
8413 * contains zeros; get the ISN from the first segment
8414 * with the ACK bit set instead (usually the SYN/ACK).
8416 * If the SYN and SYN/ACK were received out-of-order,
8417 * the ISN is ack-1. If we missed the SYN/ACK, but got
8418 * the last ACK of the 3WHS, the ISN is ack-1. For all
8419 * other packets the ISN is unknown, so ack-1 is
8420 * as good a guess as ack.
8422 if( !(tcpd->rev->static_flags & TCP_S_BASE_SEQ_SET) && (tcph->th_flags & TH_ACK) ) {
8423 tcpd->rev->base_seq = tcph->th_ack-1;
8424 tcpd->rev->static_flags |= TCP_S_BASE_SEQ_SET;
8427 if (tcp_analyze_seq && tcp_relative_seq) {
8428 tcph->th_seq -= tcpd->fwd->base_seq;
8429 if (tcph->th_flags & TH_ACK) {
8430 tcph->th_ack -= tcpd->rev->base_seq;
8436 * If we've been handed an IP fragment, we don't know how big the TCP
8437 * segment is, so don't do anything that requires that we know that.
8439 * The same applies if we're part of an error packet. (XXX - if the
8440 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
8441 * header says it is" length in the tvbuff, we could use that; such
8442 * a length might also be useful for handling packets where the IP
8443 * length is bigger than the actual data available in the frame; the
8444 * dissectors should trust that length, and then throw a
8445 * ReportedBoundsError exception when they go past the end of the frame.)
8447 * We also can't determine the segment length if the reported length
8448 * of the TCP packet is less than the TCP header length.
8450 reported_len = tvb_reported_length(tvb);
8452 if (!pinfo->fragmented && !pinfo->flags.in_error_pkt) {
8453 if (reported_len < tcph->th_hlen) {
8454 proto_tree_add_expert_format(tcp_tree, pinfo, &ei_tcp_short_segment, tvb, offset, 0,
8455 "Short segment. Segment/fragment does not contain a full TCP header"
8456 " (might be NMAP or someone else deliberately sending unusual packets)");
8457 tcph->th_have_seglen = false;
8458 } else {
8459 proto_item *pi;
8461 /* Compute the length of data in this segment. */
8462 tcph->th_seglen = reported_len - tcph->th_hlen;
8463 tcph->th_have_seglen = true;
8465 pi = proto_tree_add_uint(ti, hf_tcp_len, tvb, 0, 0, tcph->th_seglen);
8466 proto_item_set_generated(pi);
8468 /* handle TCP seq# analysis parse all new segments we see */
8469 /* We need the window size to perform sequence analysis.
8470 * (Zero is a possible value treated specially. */
8471 if(tcp_analyze_seq && tvb_bytes_exist(tvb, offset + 14, 2)) {
8473 /* Get it on every pass so that dissection is the same. */
8474 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
8476 if(!(pinfo->fd->visited)) {
8477 tcp_analyze_sequence_number(pinfo, tcph->th_rawseq, tcph->th_rawack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd, tcppd);
8481 /* Compute the sequence number of next octet after this segment. */
8482 nxtseq = tcph->th_seq + tcph->th_seglen;
8484 } else
8485 tcph->th_have_seglen = false;
8488 * Decode the ECN related flags as ACE if it is not a SYN segment,
8489 * and an AccECN-setup SYN and SYN ACK have been observed, or an
8490 * AccECN option was observed (this covers the case where Wireshark
8491 * did not observe the initial handshake).
8493 tcph->th_use_ace = (tcph->th_flags & TH_SYN) == 0 &&
8494 tcpd != NULL &&
8495 ((tcpd->had_acc_ecn_setup_syn && tcpd->had_acc_ecn_setup_syn_ack) ||
8496 tcpd->had_acc_ecn_option);
8497 flags_str = tcp_flags_to_str(pinfo->pool, tcph);
8498 flags_str_first_letter = tcp_flags_to_str_first_letter(pinfo->pool, tcph);
8500 col_append_lstr(pinfo->cinfo, COL_INFO,
8501 " [", flags_str, "]",
8502 COL_ADD_LSTR_TERMINATOR);
8503 tcp_info_append_uint(pinfo, "Seq", tcph->th_seq);
8504 if (tcph->th_flags&TH_ACK)
8505 tcp_info_append_uint(pinfo, "Ack", tcph->th_ack);
8507 if (tcp_summary_in_tree) {
8508 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
8511 if (!icmp_ip) {
8512 if(tcp_relative_seq && tcp_analyze_seq) {
8513 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);
8514 item = proto_tree_add_uint(tcp_tree, hf_tcp_seq_abs, tvb, offset + 4, 4, tcph->th_rawseq);
8515 if (read_seq_as_syn_cookie) {
8516 proto_item* syncookie_ti = NULL;
8517 proto_item_append_text(item, " (syn cookie)");
8518 syncookie_ti = proto_item_add_subtree(item, ett_tcp_syncookie);
8519 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_time, tvb, (offset + 4) * 8, 5, ENC_NA);
8520 proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_mss, tvb, (offset + 4) * 8 + 5, 3, ENC_NA);
8521 proto_tree_add_item(syncookie_ti, hf_tcp_syncookie_hash, tvb, offset + 4 + 1, 3, ENC_NA);
8524 } else {
8525 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
8526 hide_seqack_abs_item = proto_tree_add_uint(tcp_tree, hf_tcp_seq_abs, tvb, offset + 4, 4, tcph->th_rawseq);
8527 proto_item_set_hidden(hide_seqack_abs_item);
8531 if (tcph->th_hlen < TCPH_MIN_LEN) {
8532 /* Give up at this point; we put the source and destination port in
8533 the tree, before fetching the header length, so that they'll
8534 show up if this is in the failing packet in an ICMP error packet,
8535 but it's now time to give up if the header length is bogus. */
8536 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
8537 tcph->th_hlen, TCPH_MIN_LEN);
8539 tf = proto_tree_add_uint_bits_format_value(tcp_tree, hf_tcp_hdr_len, tvb, (offset + 12) << 3, 4, tcph->th_hlen,
8540 ENC_BIG_ENDIAN, "%u bytes (%u)", tcph->th_hlen, tcph->th_hlen >> 2);
8541 expert_add_info_format(pinfo, tf, &ei_tcp_bogus_header_length,
8542 "Bogus TCP header length (%u, must be at least %u)", tcph->th_hlen, TCPH_MIN_LEN);
8543 return offset+12;
8546 /* Now we certainly have enough information to be willing to send
8547 * the header information to the tap. The options can add information
8548 * about the SACKs, but the other taps don't really *require* that.
8549 * Add a CLEANUP function so that the tap_queue_packet gets called
8550 * if any exception is thrown.
8552 * XXX - We haven't necessarily retrieved the window size yet. We'll
8553 * try to do so before sending it to the tap, but if the header is
8554 * truncated to 14 octets, the taps will receive a window size of 0.
8555 * Can they handle it with minimal problems?
8558 tcp_tap_cleanup_t *cleanup = wmem_new(pinfo->pool, tcp_tap_cleanup_t);
8559 cleanup->pinfo = pinfo;
8560 cleanup->tcph = tcph;
8561 CLEANUP_PUSH(tcp_tap_cleanup, cleanup);
8563 /* initialize or move forward the conversation completeness */
8564 if(tcpd) {
8565 if(conversation_is_new) { /* pure SYN must be sought in new conversations only */
8566 if((tcph->th_flags&(TH_SYN|TH_ACK))==TH_SYN) {
8567 conversation_completeness |= TCP_COMPLETENESS_SYNSENT;
8568 if(tcph->th_seglen > 0) { /* TCP Fast Open */
8569 conversation_completeness |= TCP_COMPLETENESS_DATA;
8573 else {
8574 /* Explicitly and immediately move forward the conversation last_frame,
8575 * although it would one way or another be changed later
8576 * in the conversation helper functions.
8578 if (!(pinfo->fd->visited)) {
8579 if (pinfo->num > conv->last_frame) {
8580 conv->last_frame = pinfo->num;
8584 conversation_completeness = tcpd->conversation_completeness ;
8587 /* SYN-ACK */
8588 if((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
8589 conversation_completeness |= TCP_COMPLETENESS_SYNACK;
8592 /* ACKs */
8593 if((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_ACK)) {
8594 if(tcph->th_seglen>0) { /* transporting some data */
8595 conversation_completeness |= TCP_COMPLETENESS_DATA;
8597 else { /* pure ACK */
8598 conversation_completeness |= TCP_COMPLETENESS_ACK;
8602 /* FIN-ACK */
8603 if((tcph->th_flags&(TH_FIN|TH_ACK))==(TH_FIN|TH_ACK)) {
8604 conversation_completeness |= TCP_COMPLETENESS_FIN;
8607 /* RST */
8608 /* XXX: A RST segment should be validated (RFC 9293 3.5.3),
8609 * and if not valid should not change the conversation state.
8611 if(tcph->th_flags&(TH_RST)) {
8612 conversation_completeness |= TCP_COMPLETENESS_RST;
8615 /* Store the completeness at the conversation level,
8616 * both as numerical and as Flag First Letters string, to avoid
8617 * computing many times the same thing.
8619 if (tcpd->conversation_completeness) {
8620 if (tcpd->conversation_completeness != conversation_completeness) {
8621 tcpd->conversation_completeness = conversation_completeness;
8622 tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ;
8625 else {
8626 tcpd->conversation_completeness = conversation_completeness;
8627 tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ;
8631 if (tcp_summary_in_tree) {
8632 if(tcph->th_flags&TH_ACK) {
8633 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
8635 if (tcph->th_have_seglen)
8636 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
8638 proto_item_set_len(ti, tcph->th_hlen);
8639 if (tcph->th_have_seglen) {
8640 if(tcp_relative_seq && tcp_analyze_seq) {
8641 if (tcph->th_flags&(TH_SYN|TH_FIN)) {
8642 tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq + 1, "%u (relative sequence number)", nxtseq + 1);
8643 } else {
8644 tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "%u (relative sequence number)", nxtseq);
8646 } else {
8647 if (tcph->th_flags&(TH_SYN|TH_FIN)) {
8648 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq + 1);
8649 } else {
8650 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
8653 proto_item_set_generated(tf);
8656 tf = proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
8657 hide_seqack_abs_item = proto_tree_add_uint(tcp_tree, hf_tcp_ack_abs, tvb, offset + 8, 4, tcph->th_rawack);
8658 if (tcph->th_flags & TH_ACK) {
8659 if (tcp_relative_seq && tcp_analyze_seq) {
8660 proto_item_append_text(tf, " (relative ack number)");
8661 } else {
8662 proto_item_set_hidden(hide_seqack_abs_item);
8664 if ((tcph->th_flags & TH_SYN) && tcp_analyze_seq) {
8665 if ((tcp_relative_seq && tcph->th_ack > 1) ||
8666 (!tcp_relative_seq && tcpd && (tcph->th_ack - tcpd->rev->base_seq) > 1)) {
8667 expert_add_info(pinfo, tf, &ei_tcp_analysis_tfo_ack);
8668 } else if (tcpd && tcpd->tfo_syn_data) {
8669 expert_add_info(pinfo, tf, &ei_tcp_analysis_tfo_ignored);
8672 } else {
8673 /* Note if the ACK field is non-zero */
8674 if (tvb_get_ntohl(tvb, offset+8) != 0) {
8675 expert_add_info(pinfo, tf, &ei_tcp_ack_nonzero);
8679 if (tree) {
8680 // This should be consistent with ip.hdr_len.
8681 proto_tree_add_uint_bits_format_value(tcp_tree, hf_tcp_hdr_len, tvb, (offset + 12) << 3, 4, tcph->th_hlen,
8682 ENC_BIG_ENDIAN, "%u bytes (%u)", tcph->th_hlen, tcph->th_hlen>>2);
8683 tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 12, 2,
8684 tcph->th_flags, "Flags: 0x%03x (%s)", tcph->th_flags, flags_str);
8685 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
8686 proto_tree_add_boolean(field_tree, hf_tcp_flags_res, tvb, offset + 12, 1, tcph->th_flags);
8687 if (tcph->th_use_ace) {
8688 ace = tcp_get_ace(tcph);
8689 proto_tree_add_uint_format(field_tree, hf_tcp_flags_ace, tvb, 12, 2, ace,
8690 "...%c %c%c.. .... = ACE: %u",
8691 ace & 0x04 ? '1' : '0',
8692 ace & 0x02 ? '1' : '0',
8693 ace & 0x01 ? '1' : '0',
8694 ace);
8695 } else {
8696 proto_tree_add_boolean(field_tree, hf_tcp_flags_ae, tvb, offset + 12, 1, tcph->th_flags);
8697 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
8698 proto_tree_add_boolean(field_tree, hf_tcp_flags_ece, tvb, offset + 13, 1, tcph->th_flags);
8700 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
8701 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
8702 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
8703 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
8704 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
8705 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
8707 tf = proto_tree_add_string(field_tree, hf_tcp_flags_str, tvb, offset + 12, 2, flags_str_first_letter);
8708 proto_item_set_generated(tf);
8711 if(tcph->th_flags & TH_SYN) {
8712 if(tcph->th_flags & TH_ACK) {
8713 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_synack,
8714 "Connection establish acknowledge (SYN+ACK): server port %u", tcph->th_sport);
8715 /* Save the server port to help determine dissector used */
8716 tcpd->server_port = tcph->th_sport;
8718 else {
8719 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_syn,
8720 "Connection establish request (SYN): server port %u", tcph->th_dport);
8721 /* Save the server port to help determine dissector used */
8722 tcpd->server_port = tcph->th_dport;
8723 tcpd->ts_mru_syn = pinfo->abs_ts;
8725 /* Remember where the next segment will start. */
8726 if (tcp_desegment && tcp_reassemble_out_of_order && tcpd && !PINFO_FD_VISITED(pinfo)) {
8727 if (tcpd->fwd->maxnextseq == 0) {
8728 tcpd->fwd->maxnextseq = tcph->th_seq + 1;
8731 /* Initialize the is_first_ack */
8732 tcpd->fwd->is_first_ack = true;
8734 if(tcph->th_flags & TH_FIN) {
8735 /* XXX - find a way to know the server port and output only that one */
8736 expert_add_info(pinfo, tf_fin, &ei_tcp_connection_fin);
8738 /* Track closing initiator.
8739 If it was not already closed by the reverse flow, it means we are the first */
8740 if(!tcpd->rev->closing_initiator) {
8741 tcpd->fwd->closing_initiator = true;
8742 expert_add_info(pinfo, tf, &ei_tcp_connection_fin_active);
8743 } else {
8744 expert_add_info(pinfo, tf, &ei_tcp_connection_fin_passive);
8747 if(tcph->th_flags & TH_RST){
8748 /* XXX - find a way to know the server port and output only that one */
8749 expert_add_info(pinfo, tf_rst, &ei_tcp_connection_rst);
8752 if(tcp_analyze_seq
8753 && (tcph->th_flags & (TH_SYN|TH_ACK)) == TH_ACK
8754 && !nstime_is_zero(&tcpd->ts_mru_syn)
8755 && nstime_is_zero(&tcpd->ts_first_rtt)) {
8756 /* If all of the following:
8757 * - we care (the pref is set)
8758 * - this is a pure ACK
8759 * - we have a timestamp for the most-recently-transmitted SYN
8760 * - we haven't seen a pure ACK yet (no ts_first_rtt stored)
8761 * then assume it's the last part of the handshake and store the initial
8762 * RTT time
8764 nstime_delta(&(tcpd->ts_first_rtt), &(pinfo->abs_ts), &(tcpd->ts_mru_syn));
8768 * Remember if we have already seen at least one ACK,
8769 * then we can neutralize the Window Scale side-effect at the beginning (issue 14690)
8771 if(tcp_analyze_seq
8772 && (tcph->th_flags & (TH_SYN|TH_ACK)) == TH_ACK) {
8773 if(tcpd->fwd->is_first_ack) {
8774 tcpd->fwd->is_first_ack = false;
8778 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
8779 real_window = tcph->th_win;
8780 /* re-calculate window size based on scaling factor */
8781 if (!(tcph->th_flags&TH_SYN)) { /* SYNs are never scaled */
8782 if (tcpd && (tcpd->fwd->win_scale>=0)) {
8783 (tcph->th_win)<<=tcpd->fwd->win_scale;
8785 else if (tcpd && (tcpd->fwd->win_scale == -1)) {
8786 /* i.e. Unknown, but wasn't signalled with no scaling, so use preference setting instead! */
8787 if (tcp_default_window_scaling>=0) {
8788 (tcph->th_win)<<=tcp_default_window_scaling;
8793 tcp_info_append_uint(pinfo, "Win", tcph->th_win);
8795 if (tree) {
8796 /* As discussed in bug 5541, it is better to use two separate
8797 * fields for the real and calculated window size.
8799 proto_tree_add_uint(tcp_tree, hf_tcp_window_size_value, tvb, offset + 14, 2, real_window);
8800 if(tcph->th_flags & TH_RST){
8801 /* Check if the window value of this reset packet is in the NetScaler error code range */
8802 const char *tcp_ns_reset_window_error_descr = try_val_to_str(real_window, netscaler_reset_window_error_code_vals);
8803 if (tcp_ns_reset_window_error_descr != NULL) { /* If its in the Netscaler range, add tree */
8804 item = proto_tree_add_string(tcp_tree, hf_tcp_ns_reset_window_error_code, tvb,
8805 offset + 14, 2, tcp_ns_reset_window_error_descr);
8806 proto_item_set_generated(item);
8809 scaled_pi = proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win);
8810 proto_item_set_generated(scaled_pi);
8812 if( !(tcph->th_flags&TH_SYN) && tcpd ) {
8813 switch (tcpd->fwd->win_scale) {
8815 case -1:
8816 /* Unknown */
8818 int16_t win_scale = tcpd->fwd->win_scale;
8819 bool override_with_pref = false;
8821 /* Use preference setting (if set) */
8822 if (tcp_default_window_scaling != WindowScaling_NotKnown) {
8823 win_scale = (1 << tcp_default_window_scaling);
8824 override_with_pref = true;
8827 scaled_pi = proto_tree_add_int_format_value(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2,
8828 win_scale, "%d (%s)",
8829 win_scale,
8830 (override_with_pref) ? "missing - taken from preference" : "unknown");
8831 proto_item_set_generated(scaled_pi);
8833 break;
8835 case -2:
8836 /* No window scaling used */
8837 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);
8838 proto_item_set_generated(scaled_pi);
8839 break;
8841 default:
8842 /* Scaling from signalled value */
8843 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);
8844 proto_item_set_generated(scaled_pi);
8849 /* Supply the sequence number of the first byte and of the first byte
8850 after the segment. */
8851 tcpinfo.seq = tcph->th_seq;
8852 tcpinfo.nxtseq = nxtseq;
8853 tcpinfo.lastackseq = tcph->th_ack;
8855 /* Assume we'll pass un-reassembled data to subdissectors. */
8856 tcpinfo.is_reassembled = false;
8859 * Assume, initially, that we can't desegment.
8861 pinfo->can_desegment = 0;
8862 th_sum = tvb_get_ntohs(tvb, offset + 16);
8863 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
8864 /* The packet isn't part of an un-reassembled fragmented datagram
8865 and isn't truncated. This means we have all the data, and thus
8866 can checksum it and, unless it's being returned in an error
8867 packet, are willing to allow subdissectors to request reassembly
8868 on it. */
8870 if (tcp_check_checksum) {
8871 /* We haven't turned checksum checking off; checksum it. */
8873 /* Set up the fields of the pseudo-header. */
8874 SET_CKSUM_VEC_PTR(cksum_vec[0], (const uint8_t *)pinfo->src.data, pinfo->src.len);
8875 SET_CKSUM_VEC_PTR(cksum_vec[1], (const uint8_t *)pinfo->dst.data, pinfo->dst.len);
8876 switch (pinfo->src.type) {
8878 case AT_IPv4:
8879 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
8880 SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *)phdr, 4);
8881 break;
8883 case AT_IPv6:
8884 phdr[0] = g_htonl(reported_len);
8885 phdr[1] = g_htonl(IP_PROTO_TCP);
8886 SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *)phdr, 8);
8887 break;
8889 default:
8890 /* TCP runs only atop IPv4 and IPv6.... */
8891 DISSECTOR_ASSERT_NOT_REACHED();
8892 break;
8894 /* See discussion in packet-udp.c of partial checksums used in
8895 * checksum offloading in Linux and Windows (and possibly others.)
8897 uint16_t partial_cksum;
8898 SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, offset, reported_len);
8899 computed_cksum = in_cksum_ret_partial(cksum_vec, 4, &partial_cksum);
8900 if (computed_cksum == 0 && th_sum == 0xffff) {
8901 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
8902 offset + 16, 2, th_sum,
8903 "0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);
8905 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
8906 item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_calculated, tvb,
8907 offset + 16, 2, 0x0000);
8908 proto_item_set_generated(item);
8909 /* XXX - What should this special status be? */
8910 item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_status, tvb,
8911 offset + 16, 0, PROTO_CHECKSUM_E_BAD);
8912 proto_item_set_generated(item);
8913 expert_add_info(pinfo, item, &ei_tcp_checksum_ffff);
8915 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");
8917 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
8918 desegment_ok = true;
8919 } else {
8920 proto_item* calc_item;
8921 uint16_t shouldbe_cksum = in_cksum_shouldbe(th_sum, computed_cksum);
8922 if (computed_cksum != 0 && th_sum == g_htons(partial_cksum)) {
8923 /* Don't use PROTO_CHECKSUM_IN_CKSUM because we expect the value
8924 * to match what we pass in. */
8925 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),
8926 ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
8927 proto_item_append_text(item, " (matches partial checksum, not 0x%04x, likely caused by \"TCP checksum offload\")", shouldbe_cksum);
8928 expert_add_info(pinfo, item, &ei_tcp_checksum_partial);
8929 computed_cksum = 0;
8930 /* XXX Add a new status, e.g. PROTO_CHECKSUM_E_PARTIAL? */
8931 } else {
8932 item = proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, computed_cksum,
8933 ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
8935 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
8936 calc_item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_calculated, tvb,
8937 offset + 16, 2, shouldbe_cksum);
8938 proto_item_set_generated(calc_item);
8940 /* Checksum is valid, so we're willing to desegment it. */
8941 if (computed_cksum == 0) {
8942 desegment_ok = true;
8943 } else {
8944 proto_item_append_text(item, "(maybe caused by \"TCP checksum offload\"?)");
8946 /* Checksum is invalid, so we're not willing to desegment it. */
8947 desegment_ok = false;
8948 pinfo->noreassembly_reason = " [incorrect TCP checksum]";
8949 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");
8952 } else {
8953 proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, 0,
8954 ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
8956 /* We didn't check the checksum, and don't care if it's valid,
8957 so we're willing to desegment it. */
8958 desegment_ok = true;
8960 } else {
8961 /* We don't have all the packet data, so we can't checksum it... */
8962 proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, 0,
8963 ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
8965 /* ...and aren't willing to desegment it. */
8966 desegment_ok = false;
8969 if (desegment_ok) {
8970 /* We're willing to desegment this. Is desegmentation enabled? */
8971 if (tcp_desegment) {
8972 /* Yes - is this segment being returned in an error packet? */
8973 if (!pinfo->flags.in_error_pkt) {
8974 /* No - indicate that we will desegment.
8975 We do NOT want to desegment segments returned in error
8976 packets, as they're not part of a TCP connection. */
8977 pinfo->can_desegment = 2;
8982 item = proto_tree_add_item_ret_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, ENC_BIG_ENDIAN, &th_urp);
8984 if (IS_TH_URG(tcph->th_flags)) {
8985 /* Export the urgent pointer, for the benefit of protocols such as
8986 rlogin. */
8987 tcpinfo.urgent_pointer = (uint16_t)th_urp;
8988 tcp_info_append_uint(pinfo, "Urg", th_urp);
8989 } else {
8990 if (th_urp) {
8991 /* Note if the urgent pointer field is non-zero */
8992 expert_add_info(pinfo, item, &ei_tcp_urgent_pointer_non_zero);
8996 if (tcph->th_have_seglen)
8997 tcp_info_append_uint(pinfo, "Len", tcph->th_seglen);
8999 /* If there's more than just the fixed-length header (20 bytes), create
9000 a protocol tree item for the options. (We already know there's
9001 not less than the fixed-length header - we checked that above.)
9003 We ensure that we don't throw an exception here, so that we can
9004 do some analysis before we dissect the options and possibly
9005 throw an exception. (Trying to avoid throwing an exception when
9006 dissecting options is not something we should do.) */
9007 optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
9008 options_item = NULL;
9009 options_tree = NULL;
9010 if (optlen != 0) {
9011 unsigned bc = (unsigned)tvb_captured_length_remaining(tvb, offset + 20);
9013 if (tcp_tree != NULL) {
9014 options_item = proto_tree_add_item(tcp_tree, hf_tcp_options, tvb, offset + 20,
9015 bc < optlen ? bc : optlen, ENC_NA);
9016 proto_item_set_text(options_item, "Options: (%u bytes)", optlen);
9017 options_tree = proto_item_add_subtree(options_item, ett_tcp_options);
9021 tcph->num_sack_ranges = 0;
9023 /* handle conversation timestamps */
9024 if(tcp_calculate_ts) {
9025 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
9028 /* Now dissect the options. */
9029 if (optlen) {
9030 rvbd_option_data* option_data;
9032 tcp_dissect_options(tvb, offset + 20, optlen,
9033 pinfo, options_tree,
9034 options_item, tcph);
9036 /* Do some post evaluation of some Riverbed probe options in the list */
9037 option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num);
9038 if (option_data != NULL)
9040 if (option_data->valid)
9042 /* Distinguish S+ from S+* */
9043 col_prepend_fstr(pinfo->cinfo, COL_INFO, "S%s, ",
9044 option_data->type == PROBE_TRACE ? "#" :
9045 (option_data->probe_flags & RVBD_FLAGS_PROBE_NCFE) ? "+*" : "+");
9051 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
9052 if(tcp_analyze_seq) {
9053 uint32_t use_seq = tcph->th_seq;
9054 uint32_t use_ack = tcph->th_ack;
9055 /* May need to recover absolute values here... */
9056 if (tcp_relative_seq) {
9057 use_seq += tcpd->fwd->base_seq;
9058 if (tcph->th_flags & TH_ACK) {
9059 use_ack += tcpd->rev->base_seq;
9062 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd, use_seq, use_ack);
9065 if(!pinfo->fd->visited) {
9066 if((tcph->th_flags & TH_SYN)==TH_SYN) {
9067 /* Check the validity of the window scale value
9069 verify_tcp_window_scaling((tcph->th_flags&TH_ACK)==TH_ACK,tcpd);
9072 if((tcph->th_flags & (TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
9073 /* If the SYN or the SYN+ACK offered SCPS capabilities,
9074 * validate the flow's bidirectional scps capabilities.
9075 * The or protects against broken implementations offering
9076 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
9078 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {
9079 verify_scps(pinfo, tf_syn, tcpd);
9085 if (tcph->th_mptcp) {
9087 if (tcp_analyze_mptcp) {
9088 mptcp_add_analysis_subtree(pinfo, tvb, tcp_tree, tcpd, tcpd->mptcp_analysis, tcph );
9092 /* Skip over header + options */
9093 offset += tcph->th_hlen;
9095 /* Check the packet length to see if there's more data
9096 (it could be an ACK-only packet) */
9097 captured_length_remaining = tvb_captured_length_remaining(tvb, offset);
9099 if (tcph->th_have_seglen) {
9100 if(have_tap_listener(tcp_follow_tap)) {
9101 tcp_follow_tap_data_t* follow_data = wmem_new0(pinfo->pool, tcp_follow_tap_data_t);
9103 follow_data->tvb = tvb_new_subset_remaining(tvb, offset);
9104 follow_data->tcph = tcph;
9105 follow_data->tcpd = tcpd;
9107 tap_queue_packet(tcp_follow_tap, pinfo, follow_data);
9111 /* Nothing more to add to tcph, go ahead and send to the taps. */
9112 CLEANUP_CALL_AND_POP;
9114 /* if it is an MPTCP packet */
9115 if(tcpd->mptcp_analysis) {
9116 tap_queue_packet(mptcp_tap, pinfo, tcpd);
9119 /* If we're reassembling something whose length isn't known
9120 * beforehand, and that runs all the way to the end of
9121 * the data stream, a FIN indicates the end of the data
9122 * stream and thus the completion of reassembly, so we
9123 * need to explicitly check for that here.
9125 if(tcph->th_have_seglen && tcpd && (tcph->th_flags & TH_FIN)
9126 && pinfo->can_desegment
9127 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ) {
9128 struct tcp_multisegment_pdu *msp;
9130 /* Is this the FIN that ended the data stream or is it a
9131 * retransmission of that FIN?
9133 if (tcpd->fwd->fin == 0 || tcpd->fwd->fin == pinfo->num) {
9134 /* Either we haven't seen a FIN for this flow or we
9135 * have and it's this frame. Note that this is the FIN
9136 * for this flow, terminate reassembly and dissect the
9137 * results. */
9138 tcpd->fwd->fin = pinfo->num;
9139 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq);
9140 if(msp) {
9141 fragment_head *ipfd_head;
9143 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,
9144 pinfo, msp->first_frame, msp,
9145 tcph->th_seq - msp->seq,
9146 tcph->th_seglen,
9147 false );
9148 if(ipfd_head && ipfd_head->reassembled_in == pinfo->num && ipfd_head->reas_in_layer_num == pinfo->curr_layer_num) {
9149 tvbuff_t *next_tvb;
9151 /* create a new TVB structure for desegmented data
9152 * datalen-1 to strip the dummy FIN byte off
9154 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
9156 /* add desegmented data to the data source list */
9157 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
9159 /* Show details of the reassembly */
9160 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
9162 /* call the payload dissector
9163 * but make sure we don't offer desegmentation any more
9165 pinfo->can_desegment = 0;
9167 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq,
9168 nxtseq, false, tcpd, &tcpinfo);
9170 return tvb_captured_length(tvb);
9173 } else {
9174 /* Yes. This is a retransmission of the final FIN (or it's
9175 * the final FIN transmitted via a different path).
9176 * XXX - we need to flag retransmissions a bit better.
9178 proto_tree_add_uint(tcp_tree, hf_tcp_fin_retransmission, tvb, 0, 0, tcpd->fwd->fin);
9182 if (tcp_display_process_info && tcpd && ((tcpd->fwd && tcpd->fwd->process_info && tcpd->fwd->process_info->command) ||
9183 (tcpd->rev && tcpd->rev->process_info && tcpd->rev->process_info->command))) {
9184 field_tree = proto_tree_add_subtree(tcp_tree, tvb, offset, 0, ett_tcp_process_info, &ti, "Process Information");
9185 proto_item_set_generated(ti);
9186 if (tcpd->fwd && tcpd->fwd->process_info && tcpd->fwd->process_info->command) {
9187 proto_tree_add_uint(field_tree, hf_tcp_proc_dst_uid, tvb, 0, 0, tcpd->fwd->process_info->process_uid);
9188 proto_tree_add_uint(field_tree, hf_tcp_proc_dst_pid, tvb, 0, 0, tcpd->fwd->process_info->process_pid);
9189 proto_tree_add_string(field_tree, hf_tcp_proc_dst_uname, tvb, 0, 0, tcpd->fwd->process_info->username);
9190 proto_tree_add_string(field_tree, hf_tcp_proc_dst_cmd, tvb, 0, 0, tcpd->fwd->process_info->command);
9192 if (tcpd->rev && tcpd->rev->process_info && tcpd->rev->process_info->command) {
9193 proto_tree_add_uint(field_tree, hf_tcp_proc_src_uid, tvb, 0, 0, tcpd->rev->process_info->process_uid);
9194 proto_tree_add_uint(field_tree, hf_tcp_proc_src_pid, tvb, 0, 0, tcpd->rev->process_info->process_pid);
9195 proto_tree_add_string(field_tree, hf_tcp_proc_src_uname, tvb, 0, 0, tcpd->rev->process_info->username);
9196 proto_tree_add_string(field_tree, hf_tcp_proc_src_cmd, tvb, 0, 0, tcpd->rev->process_info->command);
9201 * XXX - what, if any, of this should we do if this is included in an
9202 * error packet? It might be nice to see the details of the packet
9203 * that caused the ICMP error, but it might not be nice to have the
9204 * dissector update state based on it.
9205 * Also, we probably don't want to run TCP taps on those packets.
9207 if (captured_length_remaining != 0) {
9208 if (tcph->th_flags & TH_RST) {
9210 * RFC1122 says:
9212 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
9214 * A TCP SHOULD allow a received RST segment to include data.
9216 * DISCUSSION
9217 * It has been suggested that a RST segment could contain
9218 * ASCII text that encoded and explained the cause of the
9219 * RST. No standard has yet been established for such
9220 * data.
9222 * so for segments with RST we just display the data as text.
9224 proto_tree_add_item(tcp_tree, hf_tcp_reset_cause, tvb, offset, captured_length_remaining, ENC_NA|ENC_ASCII);
9225 } else {
9226 /* When we have a frame with TCP SYN bit set and segmented TCP payload we need
9227 * to increment seq and nxtseq to detect the overlapping byte(s). This is to fix Bug 9882.
9229 if(tcph->th_flags & TH_SYN) {
9230 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq + 1, nxtseq + 1,
9231 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo);
9232 } else {
9233 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
9234 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo);
9238 return tvb_captured_length(tvb);
9241 static void
9242 tcp_init(void)
9244 tcp_stream_count = 0;
9246 /* MPTCP init */
9247 mptcp_stream_count = 0;
9248 mptcp_tokens = wmem_tree_new(wmem_file_scope());
9251 void
9252 proto_register_tcp(void)
9254 static hf_register_info hf[] = {
9256 { &hf_tcp_srcport,
9257 { "Source Port", "tcp.srcport", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
9258 NULL, HFILL }},
9260 { &hf_tcp_dstport,
9261 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
9262 NULL, HFILL }},
9264 { &hf_tcp_port,
9265 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
9266 NULL, HFILL }},
9268 { &hf_tcp_stream,
9269 { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
9270 NULL, HFILL }},
9272 { &hf_tcp_stream_pnum,
9273 { "Stream Packet Number", "tcp.stream.pnum", FT_UINT32, BASE_DEC,
9274 NULL, 0x0,
9275 "Relative packet number in this TCP stream", HFILL }},
9277 { &hf_tcp_completeness,
9278 { "Conversation completeness", "tcp.completeness", FT_UINT8,
9279 BASE_CUSTOM, CF_FUNC(conversation_completeness_fill), 0x0,
9280 "The completeness of the conversation capture", HFILL }},
9282 { &hf_tcp_completeness_syn,
9283 { "SYN", "tcp.completeness.syn", FT_BOOLEAN, 8,
9284 TFS(&tfs_present_absent), TCP_COMPLETENESS_SYNSENT,
9285 "Conversation has a SYN packet", HFILL}},
9287 { &hf_tcp_completeness_syn_ack,
9288 { "SYN-ACK", "tcp.completeness.syn-ack", FT_BOOLEAN, 8,
9289 TFS(&tfs_present_absent), TCP_COMPLETENESS_SYNACK,
9290 "Conversation has a SYN-ACK packet", HFILL}},
9292 { &hf_tcp_completeness_ack,
9293 { "ACK", "tcp.completeness.ack", FT_BOOLEAN, 8,
9294 TFS(&tfs_present_absent), TCP_COMPLETENESS_ACK,
9295 "Conversation has an ACK packet", HFILL}},
9297 { &hf_tcp_completeness_data,
9298 { "Data", "tcp.completeness.data", FT_BOOLEAN, 8,
9299 TFS(&tfs_present_absent), TCP_COMPLETENESS_DATA,
9300 "Conversation has payload DATA", HFILL}},
9302 { &hf_tcp_completeness_fin,
9303 { "FIN", "tcp.completeness.fin", FT_BOOLEAN, 8,
9304 TFS(&tfs_present_absent), TCP_COMPLETENESS_FIN,
9305 "Conversation has a FIN packet", HFILL}},
9307 { &hf_tcp_completeness_rst,
9308 { "RST", "tcp.completeness.rst", FT_BOOLEAN, 8,
9309 TFS(&tfs_present_absent), TCP_COMPLETENESS_RST,
9310 "Conversation has a RST packet", HFILL}},
9312 { &hf_tcp_completeness_str,
9313 { "Completeness Flags", "tcp.completeness.str", FT_STRING, BASE_NONE, NULL, 0x0,
9314 NULL, HFILL }},
9316 { &hf_tcp_seq,
9317 { "Sequence Number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
9318 NULL, HFILL }},
9320 { &hf_tcp_seq_abs,
9321 { "Sequence Number (raw)", "tcp.seq_raw", FT_UINT32, BASE_DEC, NULL, 0x0,
9322 "This shows the raw value of the sequence number", HFILL }},
9324 { &hf_tcp_nxtseq,
9325 { "Next Sequence Number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
9326 NULL, HFILL }},
9328 { &hf_tcp_ack,
9329 { "Acknowledgment Number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
9330 NULL, HFILL }},
9332 { &hf_tcp_ack_abs,
9333 { "Acknowledgment number (raw)", "tcp.ack_raw", FT_UINT32, BASE_DEC, NULL, 0x0,
9334 "This shows the raw value of the acknowledgment number", HFILL } },
9336 // "Data Offset" in https://tools.ietf.org/html/rfc793#section-3.1 and
9337 // "Data offset" in https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure
9338 { &hf_tcp_hdr_len,
9339 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
9340 "Data offset in 32-bit words", HFILL }},
9342 { &hf_tcp_flags,
9343 { "Flags", "tcp.flags", FT_UINT16, BASE_HEX, NULL, TH_MASK,
9344 NULL, HFILL }},
9346 { &hf_tcp_flags_res,
9347 { "Reserved", "tcp.flags.res", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RES,
9348 "Three reserved bits (must be zero)", HFILL }},
9350 { &hf_tcp_flags_ae,
9351 { "Accurate ECN", "tcp.flags.ae", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_AE,
9352 NULL, HFILL }},
9354 { &hf_tcp_flags_cwr,
9355 { "Congestion Window Reduced", "tcp.flags.cwr", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_CWR,
9356 NULL, HFILL }},
9358 { &hf_tcp_flags_ece,
9359 { "ECN-Echo", "tcp.flags.ece", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ECE,
9360 NULL, HFILL }},
9362 { &hf_tcp_flags_ace,
9363 { "ACE", "tcp.flags.ace", FT_UINT8, BASE_DEC, NULL, 0x0,
9364 NULL, HFILL }},
9366 { &hf_tcp_flags_urg,
9367 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_URG,
9368 NULL, HFILL }},
9370 { &hf_tcp_flags_ack,
9371 { "Acknowledgment", "tcp.flags.ack", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ACK,
9372 NULL, HFILL }},
9374 { &hf_tcp_flags_push,
9375 { "Push", "tcp.flags.push", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_PUSH,
9376 NULL, HFILL }},
9378 { &hf_tcp_flags_reset,
9379 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RST,
9380 NULL, HFILL }},
9382 { &hf_tcp_flags_syn,
9383 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_SYN,
9384 NULL, HFILL }},
9386 { &hf_tcp_flags_fin,
9387 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_FIN,
9388 NULL, HFILL }},
9390 { &hf_tcp_flags_str,
9391 { "TCP Flags", "tcp.flags.str", FT_STRING, BASE_NONE, NULL, 0x0,
9392 NULL, HFILL }},
9394 { &hf_tcp_window_size_value,
9395 { "Window", "tcp.window_size_value", FT_UINT16, BASE_DEC, NULL, 0x0,
9396 "The window size value from the TCP header", HFILL }},
9398 /* 32 bits so we can present some values adjusted to window scaling */
9399 { &hf_tcp_window_size,
9400 { "Calculated window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
9401 "The scaled window size (if scaling has been used)", HFILL }},
9403 { &hf_tcp_window_size_scalefactor,
9404 { "Window size scaling factor", "tcp.window_size_scalefactor", FT_INT32, BASE_DEC, NULL, 0x0,
9405 "The window size scaling factor (-1 when unknown, -2 when no scaling is used)", HFILL }},
9407 { &hf_tcp_checksum,
9408 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
9409 "Details at: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
9411 { &hf_tcp_checksum_status,
9412 { "Checksum Status", "tcp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
9413 NULL, HFILL }},
9415 { &hf_tcp_checksum_calculated,
9416 { "Calculated Checksum", "tcp.checksum_calculated", FT_UINT16, BASE_HEX, NULL, 0x0,
9417 "The expected TCP checksum field as calculated from the TCP segment", HFILL }},
9419 { &hf_tcp_analysis,
9420 { "SEQ/ACK analysis", "tcp.analysis", FT_NONE, BASE_NONE, NULL, 0x0,
9421 "This frame has some of the TCP analysis shown", HFILL }},
9423 { &hf_tcp_analysis_flags,
9424 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
9425 "This frame has some of the TCP analysis flags set", HFILL }},
9427 { &hf_tcp_analysis_duplicate_ack,
9428 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
9429 "This is a duplicate ACK", HFILL }},
9431 { &hf_tcp_analysis_duplicate_ack_num,
9432 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
9433 "This is duplicate ACK number #", HFILL }},
9435 { &hf_tcp_analysis_duplicate_ack_frame,
9436 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_DUP_ACK), 0x0,
9437 "This is a duplicate to the ACK in frame #", HFILL }},
9439 { &hf_tcp_continuation_to,
9440 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9441 "This is a continuation to the PDU in frame #", HFILL }},
9443 { &hf_tcp_len,
9444 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
9445 NULL, HFILL}},
9447 { &hf_tcp_analysis_acks_frame,
9448 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0,
9449 "Which previous segment is this an ACK for", HFILL}},
9451 { &hf_tcp_analysis_bytes_in_flight,
9452 { "Bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL, 0x0,
9453 "How many bytes are now in flight for this connection", HFILL}},
9455 { &hf_tcp_analysis_push_bytes_sent,
9456 { "Bytes sent since last PSH flag", "tcp.analysis.push_bytes_sent", FT_UINT32, BASE_DEC, NULL, 0x0,
9457 "How many bytes have been sent since the last PSH flag", HFILL}},
9459 { &hf_tcp_analysis_ack_rtt,
9460 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
9461 "How long time it took to ACK the segment (RTT)", HFILL}},
9463 { &hf_tcp_analysis_first_rtt,
9464 { "iRTT", "tcp.analysis.initial_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
9465 "How long it took for the SYN to ACK handshake (iRTT)", HFILL}},
9467 { &hf_tcp_analysis_rto,
9468 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
9469 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL}},
9471 { &hf_tcp_analysis_rto_frame,
9472 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9473 "This is the frame we measure the RTO from", HFILL }},
9475 { &hf_tcp_urgent_pointer,
9476 { "Urgent Pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
9477 NULL, HFILL }},
9479 { &hf_tcp_segment_overlap,
9480 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9481 "Segment overlaps with other segments", HFILL }},
9483 { &hf_tcp_segment_overlap_conflict,
9484 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9485 "Overlapping segments contained conflicting data", HFILL }},
9487 { &hf_tcp_segment_multiple_tails,
9488 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9489 "Several tails were found when reassembling the pdu", HFILL }},
9491 { &hf_tcp_segment_too_long_fragment,
9492 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9493 "Segment contained data past end of the pdu", HFILL }},
9495 { &hf_tcp_segment_error,
9496 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9497 "Reassembling error due to illegal segments", HFILL }},
9499 { &hf_tcp_segment_count,
9500 { "Segment count", "tcp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
9501 NULL, HFILL }},
9503 { &hf_tcp_segment,
9504 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9505 NULL, HFILL }},
9507 { &hf_tcp_segments,
9508 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
9509 NULL, HFILL }},
9511 { &hf_tcp_reassembled_in,
9512 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
9513 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
9515 { &hf_tcp_reassembled_length,
9516 { "Reassembled TCP length", "tcp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
9517 "The total length of the reassembled payload", HFILL }},
9519 { &hf_tcp_reassembled_data,
9520 { "Reassembled TCP Data", "tcp.reassembled.data", FT_BYTES, BASE_NONE, NULL, 0x0,
9521 "The reassembled payload", HFILL }},
9523 { &hf_tcp_option_kind,
9524 { "Kind", "tcp.option_kind", FT_UINT8,
9525 BASE_DEC|BASE_EXT_STRING, &tcp_option_kind_vs_ext, 0x0, "This TCP option's kind", HFILL }},
9527 { &hf_tcp_option_len,
9528 { "Length", "tcp.option_len", FT_UINT8,
9529 BASE_DEC, NULL, 0x0, "Length of this TCP option in bytes (including kind and length fields)", HFILL }},
9531 { &hf_tcp_options,
9532 { "TCP Options", "tcp.options", FT_BYTES,
9533 BASE_NONE, NULL, 0x0, NULL, HFILL }},
9535 { &hf_tcp_option_mss_val,
9536 { "MSS Value", "tcp.options.mss_val", FT_UINT16,
9537 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9539 { &hf_tcp_option_wscale_shift,
9540 { "Shift count", "tcp.options.wscale.shift", FT_UINT8,
9541 BASE_DEC, NULL, 0x0, "Logarithmically encoded power of 2 scale factor", HFILL}},
9543 { &hf_tcp_option_wscale_multiplier,
9544 { "Multiplier", "tcp.options.wscale.multiplier", FT_UINT16,
9545 BASE_DEC, NULL, 0x0, "Multiply segment window size by this for scaled window size", HFILL}},
9547 { &hf_tcp_option_exp_data,
9548 { "Data", "tcp.options.experimental.data", FT_BYTES,
9549 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9551 { &hf_tcp_option_exp_exid,
9552 { "Experiment Identifier", "tcp.options.experimental.exid", FT_UINT16,
9553 BASE_HEX, &tcp_exid_vs, 0x0, NULL, HFILL}},
9555 { &hf_tcp_option_unknown_payload,
9556 { "Payload", "tcp.options.unknown.payload", FT_BYTES,
9557 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9559 { &hf_tcp_option_sack_sle,
9560 {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32,
9561 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9563 { &hf_tcp_option_sack_sre,
9564 {"TCP SACK Right Edge", "tcp.options.sack_re", FT_UINT32,
9565 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9567 { &hf_tcp_option_sack_range_count,
9568 { "TCP SACK Count", "tcp.options.sack.count", FT_UINT8,
9569 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9571 { &hf_tcp_option_sack_dsack_le,
9572 {"TCP D-SACK Left Edge", "tcp.options.sack.dsack_le", FT_UINT32,
9573 BASE_DEC, NULL, 0x0, "Duplicate SACK Left Edge", HFILL}},
9575 { &hf_tcp_option_sack_dsack_re,
9576 {"TCP D-SACK Right Edge", "tcp.options.sack.dsack_re", FT_UINT32,
9577 BASE_DEC, NULL, 0x0, "Duplicate SACK Right Edge", HFILL}},
9579 { &hf_tcp_option_echo,
9580 { "TCP Echo Option", "tcp.options.echo_value", FT_UINT32,
9581 BASE_DEC, NULL, 0x0, "TCP Sack Echo", HFILL}},
9583 { &hf_tcp_option_timestamp_tsval,
9584 { "Timestamp value", "tcp.options.timestamp.tsval", FT_UINT32,
9585 BASE_DEC, NULL, 0x0, "Value of sending machine's timestamp clock", HFILL}},
9587 { &hf_tcp_option_timestamp_tsecr,
9588 { "Timestamp echo reply", "tcp.options.timestamp.tsecr", FT_UINT32,
9589 BASE_DEC, NULL, 0x0, "Echoed timestamp from remote machine", HFILL}},
9591 { &hf_tcp_option_mptcp_subtype,
9592 { "Multipath TCP subtype", "tcp.options.mptcp.subtype", FT_UINT8,
9593 BASE_DEC, VALS(mptcp_subtype_vs), 0xF0, NULL, HFILL}},
9595 { &hf_tcp_option_mptcp_version,
9596 { "Multipath TCP version", "tcp.options.mptcp.version", FT_UINT8,
9597 BASE_DEC, NULL, 0x0F, NULL, HFILL}},
9599 { &hf_tcp_option_mptcp_reserved,
9600 { "Reserved", "tcp.options.mptcp.reserved", FT_UINT16,
9601 BASE_HEX, NULL, 0x0FFF, NULL, HFILL}},
9603 { &hf_tcp_option_mptcp_flags,
9604 { "Multipath TCP flags", "tcp.options.mptcp.flags", FT_UINT8,
9605 BASE_HEX, NULL, 0x0, NULL, HFILL}},
9607 { &hf_tcp_option_mptcp_backup_flag,
9608 { "Backup flag", "tcp.options.mptcp.backup.flag", FT_UINT8,
9609 BASE_DEC, NULL, 0x01, NULL, HFILL}},
9611 { &hf_tcp_option_mptcp_checksum_flag,
9612 { "Checksum required", "tcp.options.mptcp.checksumreq.flags", FT_UINT8,
9613 BASE_DEC, NULL, MPTCP_CHECKSUM_MASK, NULL, HFILL}},
9615 { &hf_tcp_option_mptcp_B_flag,
9616 { "Extensibility", "tcp.options.mptcp.extensibility.flag", FT_UINT8,
9617 BASE_DEC, NULL, 0x40, NULL, HFILL}},
9619 { &hf_tcp_option_mptcp_C_flag,
9620 { "Do not attempt to establish new subflows to this address and port", "tcp.options.mptcp.nomoresubflows.flag", FT_UINT8,
9621 BASE_DEC, NULL, 0x20, NULL, HFILL}},
9623 { &hf_tcp_option_mptcp_H_v0_flag,
9624 { "Use HMAC-SHA1", "tcp.options.mptcp.sha1.flag", FT_UINT8,
9625 BASE_DEC, NULL, 0x01, NULL, HFILL}},
9627 { &hf_tcp_option_mptcp_H_v1_flag,
9628 { "Use HMAC-SHA256", "tcp.options.mptcp.sha256.flag", FT_UINT8,
9629 BASE_DEC, NULL, 0x01, NULL, HFILL}},
9631 { &hf_tcp_option_mptcp_F_flag,
9632 { "DATA_FIN", "tcp.options.mptcp.datafin.flag", FT_UINT8,
9633 BASE_DEC, NULL, MPTCP_DSS_FLAG_DATA_FIN_PRESENT, NULL, HFILL}},
9635 { &hf_tcp_option_mptcp_m_flag,
9636 { "Data Sequence Number is 8 octets", "tcp.options.mptcp.dseqn8.flag", FT_UINT8,
9637 BASE_DEC, NULL, MPTCP_DSS_FLAG_DSN_8BYTES, NULL, HFILL}},
9639 { &hf_tcp_option_mptcp_M_flag,
9640 { "Data Sequence Number, Subflow Sequence Number, Data-level Length, Checksum present", "tcp.options.mptcp.dseqnpresent.flag", FT_UINT8,
9641 BASE_DEC, NULL, MPTCP_DSS_FLAG_MAPPING_PRESENT, NULL, HFILL}},
9643 { &hf_tcp_option_mptcp_a_flag,
9644 { "Data ACK is 8 octets", "tcp.options.mptcp.dataack8.flag", FT_UINT8,
9645 BASE_DEC, NULL, MPTCP_DSS_FLAG_DATA_ACK_8BYTES, NULL, HFILL}},
9647 { &hf_tcp_option_mptcp_A_flag,
9648 { "Data ACK is present", "tcp.options.mptcp.dataackpresent.flag", FT_UINT8,
9649 BASE_DEC, NULL, MPTCP_DSS_FLAG_DATA_ACK_PRESENT, NULL, HFILL}},
9651 { &hf_tcp_option_mptcp_reserved_v0_flag,
9652 { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8,
9653 BASE_HEX, NULL, 0x3E, NULL, HFILL}},
9655 { &hf_tcp_option_mptcp_reserved_v1_flag,
9656 { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8,
9657 BASE_HEX, NULL, 0x1E, NULL, HFILL}},
9659 { &hf_tcp_option_mptcp_U_flag,
9660 { "Flag U", "tcp.options.mptcp.flag_U.flag", FT_BOOLEAN,
9661 4, TFS(&tfs_set_notset), MPTCP_TCPRST_FLAG_U_PRESENT, NULL, HFILL}},
9663 { &hf_tcp_option_mptcp_V_flag,
9664 { "Flag V", "tcp.options.mptcp.flag_V.flag", FT_BOOLEAN,
9665 4, TFS(&tfs_set_notset), MPTCP_TCPRST_FLAG_V_PRESENT, NULL, HFILL}},
9667 { &hf_tcp_option_mptcp_W_flag,
9668 { "Flag W", "tcp.options.mptcp.flag_W.flag", FT_BOOLEAN,
9669 4, TFS(&tfs_set_notset), MPTCP_TCPRST_FLAG_W_PRESENT, NULL, HFILL}},
9671 { &hf_tcp_option_mptcp_T_flag,
9672 { "Transient", "tcp.options.mptcp.flag_T.flag", FT_BOOLEAN,
9673 4, TFS(&tfs_set_notset), MPTCP_TCPRST_FLAG_T_PRESENT, NULL, HFILL}},
9675 { &hf_tcp_option_mptcp_tcprst_reason,
9676 { "TCPRST Reason", "tcp.options.mptcp.rst_reason", FT_UINT8,
9677 BASE_HEX, VALS(mp_tcprst_reasons), 0x0, "Multipath TCPRST Reason Code", HFILL}},
9679 { &hf_tcp_option_mptcp_address_id,
9680 { "Address ID", "tcp.options.mptcp.addrid", FT_UINT8,
9681 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9683 { &hf_tcp_option_mptcp_sender_key,
9684 { "Sender's Key", "tcp.options.mptcp.sendkey", FT_UINT64,
9685 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9687 { &hf_tcp_option_mptcp_recv_key,
9688 { "Receiver's Key", "tcp.options.mptcp.recvkey", FT_UINT64,
9689 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9691 { &hf_tcp_option_mptcp_recv_token,
9692 { "Receiver's Token", "tcp.options.mptcp.recvtok", FT_UINT32,
9693 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9695 { &hf_tcp_option_mptcp_sender_rand,
9696 { "Sender's Random Number", "tcp.options.mptcp.sendrand", FT_UINT32,
9697 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9699 { &hf_tcp_option_mptcp_sender_trunc_hmac,
9700 { "Sender's Truncated HMAC", "tcp.options.mptcp.sendtrunchmac", FT_UINT64,
9701 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9703 { &hf_tcp_option_mptcp_sender_hmac,
9704 { "Sender's HMAC", "tcp.options.mptcp.sendhmac", FT_BYTES,
9705 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9707 { &hf_tcp_option_mptcp_addaddr_trunc_hmac,
9708 { "Truncated HMAC", "tcp.options.mptcp.addaddrtrunchmac", FT_UINT64,
9709 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9711 { &hf_tcp_option_mptcp_data_ack_raw,
9712 { "Original MPTCP Data ACK", "tcp.options.mptcp.rawdataack", FT_UINT64,
9713 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9715 { &hf_tcp_option_mptcp_data_seq_no_raw,
9716 { "Data Sequence Number", "tcp.options.mptcp.rawdataseqno", FT_UINT64,
9717 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9719 { &hf_tcp_option_mptcp_subflow_seq_no,
9720 { "Subflow Sequence Number", "tcp.options.mptcp.subflowseqno", FT_UINT32,
9721 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9723 { &hf_tcp_option_mptcp_data_lvl_len,
9724 { "Data-level Length", "tcp.options.mptcp.datalvllen", FT_UINT16,
9725 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9727 { &hf_tcp_option_mptcp_checksum,
9728 { "Checksum", "tcp.options.mptcp.checksum", FT_UINT16,
9729 BASE_HEX, NULL, 0x0, NULL, HFILL}},
9731 { &hf_tcp_option_mptcp_ipver,
9732 { "IP version", "tcp.options.mptcp.ipver", FT_UINT8,
9733 BASE_DEC, NULL, 0x0F, NULL, HFILL}},
9735 { &hf_tcp_option_mptcp_echo,
9736 { "Echo", "tcp.options.mptcp.echo", FT_UINT8,
9737 BASE_DEC, NULL, 0x01, NULL, HFILL}},
9739 { &hf_tcp_option_mptcp_ipv4,
9740 { "Advertised IPv4 Address", "tcp.options.mptcp.ipv4", FT_IPv4,
9741 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9743 { &hf_tcp_option_mptcp_ipv6,
9744 { "Advertised IPv6 Address", "tcp.options.mptcp.ipv6", FT_IPv6,
9745 BASE_NONE, NULL, 0x0, NULL, HFILL}},
9747 { &hf_tcp_option_mptcp_port,
9748 { "Advertised port", "tcp.options.mptcp.port", FT_UINT16,
9749 BASE_DEC, NULL, 0x0, NULL, HFILL}},
9751 { &hf_tcp_option_cc,
9752 { "TCP CC Option", "tcp.options.cc_value", FT_UINT32, BASE_DEC,
9753 NULL, 0x0, NULL, HFILL}},
9755 { &hf_tcp_option_md5_digest,
9756 { "MD5 digest", "tcp.options.md5.digest", FT_BYTES, BASE_NONE,
9757 NULL, 0x0, NULL, HFILL}},
9759 { &hf_tcp_option_ao_keyid,
9760 { "AO KeyID", "tcp.options.ao.keyid", FT_UINT8, BASE_DEC,
9761 NULL, 0x0, NULL, HFILL}},
9763 { &hf_tcp_option_ao_rnextkeyid,
9764 { "AO RNextKeyID", "tcp.options.ao.rnextkeyid", FT_UINT8, BASE_DEC,
9765 NULL, 0x0, NULL, HFILL}},
9767 { &hf_tcp_option_ao_mac,
9768 { "AO MAC", "tcp.options.ao.mac", FT_BYTES, BASE_NONE,
9769 NULL, 0x0, NULL, HFILL}},
9771 { &hf_tcp_option_qs_rate,
9772 { "QS Rate", "tcp.options.qs.rate", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
9773 &qs_rate_vals_ext, 0x0F, NULL, HFILL}},
9775 { &hf_tcp_option_qs_ttl_diff,
9776 { "QS Rate", "tcp.options.qs.ttl_diff", FT_UINT8, BASE_DEC,
9777 NULL, 0x0, NULL, HFILL}},
9779 { &hf_tcp_option_tarr_rate,
9780 { "TARR Rate", "tcp.options.tarr.rate", FT_UINT8, BASE_DEC,
9781 NULL, TCPOPT_TARR_RATE_MASK, NULL, HFILL}},
9783 { &hf_tcp_option_tarr_reserved,
9784 { "TARR Reserved", "tcp.options.tar.reserved", FT_UINT8, BASE_DEC,
9785 NULL, TCPOPT_TARR_RESERVED_MASK, NULL, HFILL}},
9787 { &hf_tcp_option_acc_ecn_ee0b,
9788 { "Accurate ECN Echo ECT(0) Byte Counter", "tcp.options.acc_ecn.ee0b",
9789 FT_UINT24, BASE_DEC, NULL, 0x0,
9790 NULL, HFILL}},
9792 { &hf_tcp_option_acc_ecn_eceb,
9793 { "Accurate ECN Echo CE Byte Counter", "tcp.options.acc_ecn.eceb",
9794 FT_UINT24, BASE_DEC, NULL, 0x0,
9795 NULL, HFILL}},
9797 { &hf_tcp_option_acc_ecn_ee1b,
9798 { "Accurate ECN Echo ECT(1) Byte Counter", "tcp.options.acc_ecn.ee1b",
9799 FT_UINT24, BASE_DEC, NULL, 0x0,
9800 NULL, HFILL}},
9802 { &hf_tcp_option_scps_vector,
9803 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
9804 FT_UINT8, BASE_HEX, NULL, 0x0,
9805 NULL, HFILL}},
9807 { &hf_tcp_option_scps_binding,
9808 { "Binding Space (Community) ID",
9809 "tcp.options.scps.binding.id",
9810 FT_UINT8, BASE_DEC, NULL, 0x0,
9811 "TCP SCPS Extended Binding Space (Community) ID", HFILL}},
9813 { &hf_tcp_option_scps_binding_len,
9814 { "Extended Capability Length",
9815 "tcp.options.scps.binding.len",
9816 FT_UINT8, BASE_DEC, NULL, 0x0,
9817 "TCP SCPS Extended Capability Length in bytes", HFILL}},
9819 { &hf_tcp_option_snack_offset,
9820 { "TCP SNACK Offset", "tcp.options.snack.offset",
9821 FT_UINT16, BASE_DEC, NULL, 0x0,
9822 NULL, HFILL}},
9824 { &hf_tcp_option_snack_size,
9825 { "TCP SNACK Size", "tcp.options.snack.size",
9826 FT_UINT16, BASE_DEC, NULL, 0x0,
9827 NULL, HFILL}},
9829 { &hf_tcp_option_snack_le,
9830 { "TCP SNACK Left Edge", "tcp.options.snack.le",
9831 FT_UINT16, BASE_DEC, NULL, 0x0,
9832 NULL, HFILL}},
9834 { &hf_tcp_option_snack_re,
9835 { "TCP SNACK Right Edge", "tcp.options.snack.re",
9836 FT_UINT16, BASE_DEC, NULL, 0x0,
9837 NULL, HFILL}},
9839 { &hf_tcp_scpsoption_flags_bets,
9840 { "Partial Reliability Capable (BETS)",
9841 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,
9842 TFS(&tfs_set_notset), 0x80, NULL, HFILL }},
9844 { &hf_tcp_scpsoption_flags_snack1,
9845 { "Short Form SNACK Capable (SNACK1)",
9846 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,
9847 TFS(&tfs_set_notset), 0x40, NULL, HFILL }},
9849 { &hf_tcp_scpsoption_flags_snack2,
9850 { "Long Form SNACK Capable (SNACK2)",
9851 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,
9852 TFS(&tfs_set_notset), 0x20, NULL, HFILL }},
9854 { &hf_tcp_scpsoption_flags_compress,
9855 { "Lossless Header Compression (COMP)",
9856 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,
9857 TFS(&tfs_set_notset), 0x10, NULL, HFILL }},
9859 { &hf_tcp_scpsoption_flags_nlts,
9860 { "Network Layer Timestamp (NLTS)",
9861 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,
9862 TFS(&tfs_set_notset), 0x8, NULL, HFILL }},
9864 { &hf_tcp_scpsoption_flags_reserved,
9865 { "Reserved",
9866 "tcp.options.scpsflags.reserved", FT_UINT8, BASE_DEC,
9867 NULL, 0x7, NULL, HFILL }},
9869 { &hf_tcp_scpsoption_connection_id,
9870 { "Connection ID",
9871 "tcp.options.scps.binding",
9872 FT_UINT8, BASE_DEC, NULL, 0x0,
9873 "TCP SCPS Connection ID", HFILL}},
9875 { &hf_tcp_option_user_to_granularity,
9876 { "Granularity", "tcp.options.user_to_granularity", FT_BOOLEAN,
9877 16, TFS(&tcp_option_user_to_granularity), 0x8000, "TCP User Timeout Granularity", HFILL}},
9879 { &hf_tcp_option_user_to_val,
9880 { "User Timeout", "tcp.options.user_to_val", FT_UINT16,
9881 BASE_DEC, NULL, 0x7FFF, "TCP User Timeout Value", HFILL}},
9883 { &hf_tcp_option_rvbd_probe_type1,
9884 { "Type", "tcp.options.rvbd.probe.type1",
9885 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
9887 { &hf_tcp_option_rvbd_probe_type2,
9888 { "Type", "tcp.options.rvbd.probe.type2",
9889 FT_UINT8, BASE_DEC, NULL, 0xFE, NULL, HFILL }},
9891 { &hf_tcp_option_rvbd_probe_version1,
9892 { "Version", "tcp.options.rvbd.probe.version",
9893 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
9895 { &hf_tcp_option_rvbd_probe_version2,
9896 { "Version", "tcp.options.rvbd.probe.version_raw",
9897 FT_UINT8, BASE_DEC, NULL, 0x01, "Version 2 Raw Value", HFILL }},
9899 { &hf_tcp_option_rvbd_probe_prober,
9900 { "CSH IP", "tcp.options.rvbd.probe.prober",
9901 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
9903 { &hf_tcp_option_rvbd_probe_proxy,
9904 { "SSH IP", "tcp.options.rvbd.probe.proxy.ip",
9905 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
9907 { &hf_tcp_option_rvbd_probe_proxy_port,
9908 { "SSH Port", "tcp.options.rvbd.probe.proxy.port",
9909 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
9911 { &hf_tcp_option_rvbd_probe_appli_ver,
9912 { "Application Version", "tcp.options.rvbd.probe.appli_ver",
9913 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
9915 { &hf_tcp_option_rvbd_probe_client,
9916 { "Client IP", "tcp.options.rvbd.probe.client.ip",
9917 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
9919 { &hf_tcp_option_rvbd_probe_storeid,
9920 { "CFE Store ID", "tcp.options.rvbd.probe.storeid",
9921 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
9923 { &hf_tcp_option_rvbd_probe_flags,
9924 { "Probe Flags", "tcp.options.rvbd.probe.flags",
9925 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
9927 { &hf_tcp_option_rvbd_probe_flag_not_cfe,
9928 { "Not CFE", "tcp.options.rvbd.probe.flags.notcfe",
9929 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_NCFE,
9930 NULL, HFILL }},
9932 { &hf_tcp_option_rvbd_probe_flag_last_notify,
9933 { "Last Notify", "tcp.options.rvbd.probe.flags.last",
9934 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_LAST,
9935 NULL, HFILL }},
9937 { &hf_tcp_option_rvbd_probe_flag_probe_cache,
9938 { "Disable Probe Cache on CSH", "tcp.options.rvbd.probe.flags.probe",
9939 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE,
9940 NULL, HFILL }},
9942 { &hf_tcp_option_rvbd_probe_flag_sslcert,
9943 { "SSL Enabled", "tcp.options.rvbd.probe.flags.ssl",
9944 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SSLCERT,
9945 NULL, HFILL }},
9947 { &hf_tcp_option_rvbd_probe_flag_server_connected,
9948 { "SSH outer to server established", "tcp.options.rvbd.probe.flags.server",
9949 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SERVER,
9950 NULL, HFILL }},
9952 { &hf_tcp_option_rvbd_trpy_flags,
9953 { "Transparency Options", "tcp.options.rvbd.trpy.flags",
9954 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
9956 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
9957 { "Enable FW traversal feature", "tcp.options.rvbd.trpy.flags.fw_rst_probe",
9958 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
9959 RVBD_FLAGS_TRPY_FW_RST_PROBE,
9960 "Reset state created by probe on the nexthop firewall",
9961 HFILL }},
9963 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
9964 { "Enable Inner FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst_inner",
9965 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
9966 RVBD_FLAGS_TRPY_FW_RST_INNER,
9967 "Reset state created by transparent inner on all firewalls"
9968 " before passing connection through",
9969 HFILL }},
9971 { &hf_tcp_option_rvbd_trpy_flag_fw_rst,
9972 { "Enable Transparency FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst",
9973 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
9974 RVBD_FLAGS_TRPY_FW_RST,
9975 "Reset state created by probe on all firewalls before "
9976 "establishing transparent inner connection", HFILL }},
9978 { &hf_tcp_option_rvbd_trpy_flag_chksum,
9979 { "Reserved", "tcp.options.rvbd.trpy.flags.chksum",
9980 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
9981 RVBD_FLAGS_TRPY_CHKSUM, NULL, HFILL }},
9983 { &hf_tcp_option_rvbd_trpy_flag_oob,
9984 { "Out of band connection", "tcp.options.rvbd.trpy.flags.oob",
9985 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
9986 RVBD_FLAGS_TRPY_OOB, NULL, HFILL }},
9988 { &hf_tcp_option_rvbd_trpy_flag_mode,
9989 { "Transparency Mode", "tcp.options.rvbd.trpy.flags.mode",
9990 FT_BOOLEAN, 16, TFS(&trpy_mode_str),
9991 RVBD_FLAGS_TRPY_MODE, NULL, HFILL }},
9993 { &hf_tcp_option_rvbd_trpy_src,
9994 { "Src SH IP Addr", "tcp.options.rvbd.trpy.src.ip",
9995 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
9997 { &hf_tcp_option_rvbd_trpy_dst,
9998 { "Dst SH IP Addr", "tcp.options.rvbd.trpy.dst.ip",
9999 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
10001 { &hf_tcp_option_rvbd_trpy_src_port,
10002 { "Src SH Inner Port", "tcp.options.rvbd.trpy.src.port",
10003 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
10005 { &hf_tcp_option_rvbd_trpy_dst_port,
10006 { "Dst SH Inner Port", "tcp.options.rvbd.trpy.dst.port",
10007 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
10009 { &hf_tcp_option_rvbd_trpy_client_port,
10010 { "Out of band connection Client Port", "tcp.options.rvbd.trpy.client.port",
10011 FT_UINT16, BASE_DEC, NULL , 0x0, NULL, HFILL }},
10013 { &hf_tcp_option_fast_open_cookie_request,
10014 { "Fast Open Cookie Request", "tcp.options.tfo.request", FT_NONE,
10015 BASE_NONE, NULL, 0x0, NULL, HFILL }},
10017 { &hf_tcp_option_fast_open_cookie,
10018 { "Fast Open Cookie", "tcp.options.tfo.cookie", FT_BYTES,
10019 BASE_NONE, NULL, 0x0, NULL, HFILL}},
10021 { &hf_tcp_pdu_time,
10022 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
10023 "How long time has passed until the last frame of this PDU", HFILL}},
10025 { &hf_tcp_pdu_size,
10026 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL, 0x0,
10027 "The size of this PDU", HFILL}},
10029 { &hf_tcp_pdu_last_frame,
10030 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
10031 "This is the last frame of the PDU starting in this segment", HFILL }},
10033 { &hf_tcp_ts_relative,
10034 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
10035 "Time relative to first frame in this TCP stream", HFILL}},
10037 { &hf_tcp_ts_delta,
10038 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
10039 "Time delta from previous frame in this TCP stream", HFILL}},
10041 { &hf_tcp_proc_src_uid,
10042 { "Source process user ID", "tcp.proc.srcuid", FT_UINT32, BASE_DEC, NULL, 0x0,
10043 NULL, HFILL}},
10045 { &hf_tcp_proc_src_pid,
10046 { "Source process ID", "tcp.proc.srcpid", FT_UINT32, BASE_DEC, NULL, 0x0,
10047 NULL, HFILL}},
10049 { &hf_tcp_proc_src_uname,
10050 { "Source process user name", "tcp.proc.srcuname", FT_STRING, BASE_NONE, NULL, 0x0,
10051 NULL, HFILL}},
10053 { &hf_tcp_proc_src_cmd,
10054 { "Source process name", "tcp.proc.srccmd", FT_STRING, BASE_NONE, NULL, 0x0,
10055 "Source process command name", HFILL}},
10057 { &hf_tcp_proc_dst_uid,
10058 { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32, BASE_DEC, NULL, 0x0,
10059 NULL, HFILL}},
10061 { &hf_tcp_proc_dst_pid,
10062 { "Destination process ID", "tcp.proc.dstpid", FT_UINT32, BASE_DEC, NULL, 0x0,
10063 NULL, HFILL}},
10065 { &hf_tcp_proc_dst_uname,
10066 { "Destination process user name", "tcp.proc.dstuname", FT_STRING, BASE_NONE, NULL, 0x0,
10067 NULL, HFILL}},
10069 { &hf_tcp_proc_dst_cmd,
10070 { "Destination process name", "tcp.proc.dstcmd", FT_STRING, BASE_NONE, NULL, 0x0,
10071 "Destination process command name", HFILL}},
10073 { &hf_tcp_segment_data,
10074 { "TCP segment data", "tcp.segment_data", FT_BYTES, BASE_NONE, NULL, 0x0,
10075 "A data segment used in reassembly of an upper-layer protocol (ULP)", HFILL}},
10077 { &hf_tcp_payload,
10078 { "TCP payload", "tcp.payload", FT_BYTES, BASE_NONE, NULL, 0x0,
10079 "The TCP payload of this packet", HFILL}},
10081 { &hf_tcp_option_scps_binding_data,
10082 { "Binding Space Data", "tcp.options.scps.binding.data", FT_BYTES, BASE_NONE, NULL, 0x0,
10083 NULL, HFILL }},
10085 { &hf_tcp_option_rvbd_probe_reserved,
10086 { "Reserved", "tcp.options.rvbd.probe.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
10087 NULL, HFILL }},
10089 { &hf_tcp_fin_retransmission,
10090 { "Retransmission of FIN from frame", "tcp.fin_retransmission", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
10091 NULL, HFILL }},
10093 { &hf_tcp_reset_cause,
10094 { "Reset cause", "tcp.reset_cause", FT_STRING, BASE_NONE, NULL, 0x0,
10095 NULL, HFILL }},
10097 { &hf_tcp_syncookie_time,
10098 { "SYN Cookie Time", "tcp.syncookie.time", FT_UINT8, BASE_DEC, NULL, 0x0,
10099 NULL, HFILL }},
10101 { &hf_tcp_syncookie_mss,
10102 { "SYN Cookie Maximum Segment Size", "tcp.syncookie.mss", FT_UINT8, BASE_DEC, NULL, 0x0,
10103 NULL, HFILL }},
10105 { &hf_tcp_syncookie_hash,
10106 { "SYN Cookie hash", "tcp.syncookie.hash", FT_UINT24, BASE_HEX, NULL, 0x0,
10107 NULL, HFILL }},
10109 { &hf_tcp_syncookie_option_timestamp,
10110 { "SYN Cookie Timestamp", "tcp.options.timestamp.tsval.syncookie.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
10111 NULL, HFILL }},
10113 { &hf_tcp_syncookie_option_ecn,
10114 { "SYN Cookie ECN", "tcp.options.timestamp.tsval.syncookie.ecn", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
10115 NULL, HFILL }},
10117 { &hf_tcp_syncookie_option_sack,
10118 { "SYN Cookie SACK", "tcp.options.timestamp.tsval.syncookie.sack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
10119 NULL, HFILL }},
10121 { &hf_tcp_syncookie_option_wscale,
10122 { "SYN Cookie WScale", "tcp.options.timestamp.tsval.syncookie.wscale", FT_UINT8, BASE_DEC, NULL, 0x0,
10123 NULL, HFILL }},
10125 { &hf_tcp_ns_reset_window_error_code,
10126 { "NetScaler TCP Reset Window Error Code", "tcp.nstrace.rst.window_error_code", FT_STRING, BASE_NONE, NULL, 0x0,
10127 NULL, HFILL }},
10130 static int *ett[] = {
10131 &ett_tcp,
10132 &ett_tcp_completeness,
10133 &ett_tcp_flags,
10134 &ett_tcp_options,
10135 &ett_tcp_option_timestamp,
10136 &ett_tcp_option_mptcp,
10137 &ett_tcp_option_wscale,
10138 &ett_tcp_option_sack,
10139 &ett_tcp_option_snack,
10140 &ett_tcp_option_scps,
10141 &ett_tcp_scpsoption_flags,
10142 &ett_tcp_option_scps_extended,
10143 &ett_tcp_option_user_to,
10144 &ett_tcp_option_exp,
10145 &ett_tcp_option_acc_ecn,
10146 &ett_tcp_option_sack_perm,
10147 &ett_tcp_option_mss,
10148 &ett_tcp_opt_rvbd_probe,
10149 &ett_tcp_opt_rvbd_probe_flags,
10150 &ett_tcp_opt_rvbd_trpy,
10151 &ett_tcp_opt_rvbd_trpy_flags,
10152 &ett_tcp_opt_echo,
10153 &ett_tcp_opt_cc,
10154 &ett_tcp_opt_md5,
10155 &ett_tcp_opt_ao,
10156 &ett_tcp_opt_qs,
10157 &ett_tcp_analysis_faults,
10158 &ett_tcp_analysis,
10159 &ett_tcp_timestamps,
10160 &ett_tcp_segments,
10161 &ett_tcp_segment,
10162 &ett_tcp_checksum,
10163 &ett_tcp_process_info,
10164 &ett_tcp_unknown_opt,
10165 &ett_tcp_opt_recbound,
10166 &ett_tcp_opt_scpscor,
10167 &ett_tcp_option_other,
10168 &ett_tcp_syncookie,
10169 &ett_tcp_syncookie_option
10172 static int *mptcp_ett[] = {
10173 &ett_mptcp_analysis,
10174 &ett_mptcp_analysis_subflows
10177 static const enum_val_t window_scaling_vals[] = {
10178 {"not-known", "Not known", WindowScaling_NotKnown},
10179 {"0", "0 (no scaling)", WindowScaling_0},
10180 {"1", "1 (multiply by 2)", WindowScaling_1},
10181 {"2", "2 (multiply by 4)", WindowScaling_2},
10182 {"3", "3 (multiply by 8)", WindowScaling_3},
10183 {"4", "4 (multiply by 16)", WindowScaling_4},
10184 {"5", "5 (multiply by 32)", WindowScaling_5},
10185 {"6", "6 (multiply by 64)", WindowScaling_6},
10186 {"7", "7 (multiply by 128)", WindowScaling_7},
10187 {"8", "8 (multiply by 256)", WindowScaling_8},
10188 {"9", "9 (multiply by 512)", WindowScaling_9},
10189 {"10", "10 (multiply by 1024)", WindowScaling_10},
10190 {"11", "11 (multiply by 2048)", WindowScaling_11},
10191 {"12", "12 (multiply by 4096)", WindowScaling_12},
10192 {"13", "13 (multiply by 8192)", WindowScaling_13},
10193 {"14", "14 (multiply by 16384)", WindowScaling_14},
10194 {NULL, NULL, -1}
10197 static const enum_val_t override_analysis_vals[] = {
10198 {"0", "0 (none)", OverrideAnalysis_0},
10199 {"1", "1 (Out-of-Order)", OverrideAnalysis_1},
10200 {"2", "2 (Retransmission)", OverrideAnalysis_2},
10201 {"3", "3 (Fast Retransmission)", OverrideAnalysis_3},
10202 {"4", "4 (Spurious Retransmission)",OverrideAnalysis_4},
10203 {NULL, NULL, -1}
10206 static ei_register_info ei[] = {
10207 { &ei_tcp_opt_len_invalid, { "tcp.option.len.invalid", PI_SEQUENCE, PI_NOTE, "Invalid length for option", EXPFILL }},
10208 { &ei_tcp_analysis_retransmission, { "tcp.analysis.retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) retransmission", EXPFILL }},
10209 { &ei_tcp_analysis_fast_retransmission, { "tcp.analysis.fast_retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) fast retransmission", EXPFILL }},
10210 { &ei_tcp_analysis_spurious_retransmission, { "tcp.analysis.spurious_retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) spurious retransmission", EXPFILL }},
10211 { &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 }},
10212 { &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 }},
10213 { &ei_tcp_analysis_lost_packet, { "tcp.analysis.lost_segment", PI_SEQUENCE, PI_WARN, "Previous segment(s) not captured (common at capture start)", EXPFILL }},
10214 { &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 }},
10215 { &ei_tcp_analysis_window_update, { "tcp.analysis.window_update", PI_SEQUENCE, PI_CHAT, "TCP window update", EXPFILL }},
10216 { &ei_tcp_analysis_window_full, { "tcp.analysis.window_full", PI_SEQUENCE, PI_WARN, "TCP window specified by the receiver is now completely full", EXPFILL }},
10217 { &ei_tcp_analysis_keep_alive, { "tcp.analysis.keep_alive", PI_SEQUENCE, PI_NOTE, "TCP keep-alive segment", EXPFILL }},
10218 { &ei_tcp_analysis_keep_alive_ack, { "tcp.analysis.keep_alive_ack", PI_SEQUENCE, PI_NOTE, "ACK to a TCP keep-alive segment", EXPFILL }},
10219 { &ei_tcp_analysis_duplicate_ack, { "tcp.analysis.duplicate_ack", PI_SEQUENCE, PI_NOTE, "Duplicate ACK", EXPFILL }},
10220 { &ei_tcp_analysis_zero_window_probe, { "tcp.analysis.zero_window_probe", PI_SEQUENCE, PI_NOTE, "TCP Zero Window Probe", EXPFILL }},
10221 { &ei_tcp_analysis_zero_window, { "tcp.analysis.zero_window", PI_SEQUENCE, PI_WARN, "TCP Zero Window segment", EXPFILL }},
10222 { &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 }},
10223 { &ei_tcp_analysis_tfo_syn, { "tcp.analysis.tfo_syn", PI_SEQUENCE, PI_NOTE, "TCP SYN with TFO Cookie", EXPFILL }},
10224 { &ei_tcp_analysis_tfo_ack, { "tcp.analysis.tfo_ack", PI_SEQUENCE, PI_NOTE, "TCP SYN-ACK accepting TFO data", EXPFILL }},
10225 { &ei_tcp_analysis_tfo_ignored, { "tcp.analysis.tfo_ignored", PI_SEQUENCE, PI_NOTE, "TCP SYN-ACK ignoring TFO data", EXPFILL }},
10226 { &ei_tcp_analysis_partial_ack, { "tcp.analysis.partial_ack", PI_SEQUENCE, PI_NOTE, "Partial Acknowledgement of a segment", EXPFILL }},
10227 { &ei_tcp_connection_fin_active, { "tcp.connection.fin_active", PI_SEQUENCE, PI_NOTE, "This frame initiates the connection closing", EXPFILL }},
10228 { &ei_tcp_connection_fin_passive, { "tcp.connection.fin_passive", PI_SEQUENCE, PI_NOTE, "This frame undergoes the connection closing", EXPFILL }},
10229 { &ei_tcp_scps_capable, { "tcp.analysis.scps_capable", PI_SEQUENCE, PI_NOTE, "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated", EXPFILL }},
10230 { &ei_tcp_option_sack_dsack, { "tcp.options.sack.dsack", PI_SEQUENCE, PI_WARN, "D-SACK Sequence", EXPFILL }},
10231 { &ei_tcp_option_snack_sequence, { "tcp.options.snack.sequence", PI_SEQUENCE, PI_NOTE, "SNACK Sequence", EXPFILL }},
10232 { &ei_tcp_option_wscale_shift_invalid, { "tcp.options.wscale.shift.invalid", PI_PROTOCOL, PI_WARN, "Window scale shift exceeds 14", EXPFILL }},
10233 { &ei_tcp_option_mss_absent, { "tcp.options.mss.absent", PI_PROTOCOL, PI_NOTE, "The SYN packet does not contain a MSS option", EXPFILL }},
10234 { &ei_tcp_option_mss_present, { "tcp.options.mss.present", PI_PROTOCOL, PI_WARN, "The non-SYN packet does contain a MSS option", EXPFILL }},
10235 { &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 }},
10236 { &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 }},
10237 { &ei_tcp_short_segment, { "tcp.short_segment", PI_MALFORMED, PI_WARN, "Short segment", EXPFILL }},
10238 { &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 }},
10239 { &ei_tcp_connection_synack, { "tcp.connection.synack", PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK)", EXPFILL }},
10240 { &ei_tcp_connection_syn, { "tcp.connection.syn", PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN)", EXPFILL }},
10241 { &ei_tcp_connection_fin, { "tcp.connection.fin", PI_SEQUENCE, PI_CHAT, "Connection finish (FIN)", EXPFILL }},
10242 /* According to RFCs, RST is an indication of an error. Some applications use it
10243 * to terminate a connection as well, which is a misbehavior (see e.g. rfc3360)
10245 { &ei_tcp_connection_rst, { "tcp.connection.rst", PI_SEQUENCE, PI_WARN, "Connection reset (RST)", EXPFILL }},
10246 { &ei_tcp_checksum_ffff, { "tcp.checksum.ffff", PI_CHECKSUM, PI_WARN, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)", EXPFILL }},
10247 { &ei_tcp_checksum_partial, { "tcp.checksum.partial", PI_CHECKSUM, PI_NOTE, "Partial (pseudo header) checksum (likely caused by \"TCP checksum offload\")", EXPFILL }},
10248 { &ei_tcp_checksum_bad, { "tcp.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
10249 { &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 }},
10250 { &ei_tcp_suboption_malformed, { "tcp.suboption_malformed", PI_MALFORMED, PI_ERROR, "suboption would go past end of option", EXPFILL }},
10251 { &ei_tcp_nop, { "tcp.nop", PI_PROTOCOL, PI_WARN, "4 NOP in a row - a router may have removed some options", EXPFILL }},
10252 { &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 }},
10253 { &ei_tcp_bogus_header_length, { "tcp.bogus_header_length", PI_PROTOCOL, PI_ERROR, "Bogus TCP Header length", EXPFILL }},
10256 static ei_register_info mptcp_ei[] = {
10257 #if 0
10258 { &ei_mptcp_analysis_unexpected_idsn, { "mptcp.connection.unexpected_idsn", PI_PROTOCOL, PI_NOTE, "Unexpected initial sequence number", EXPFILL }},
10259 #endif
10260 { &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 }},
10261 { &ei_mptcp_analysis_missing_algorithm, { "mptcp.connection.missing_algorithm", PI_PROTOCOL, PI_WARN, "No crypto algorithm specified", EXPFILL }},
10262 { &ei_mptcp_analysis_unsupported_algorithm, { "mptcp.connection.unsupported_algorithm", PI_PROTOCOL, PI_WARN, "Unsupported algorithm", EXPFILL }},
10263 { &ei_mptcp_infinite_mapping, { "mptcp.dss.infinite_mapping", PI_PROTOCOL, PI_WARN, "Fallback to infinite mapping", EXPFILL }},
10264 { &ei_mptcp_mapping_missing, { "mptcp.dss.missing_mapping", PI_PROTOCOL, PI_WARN, "No mapping available", EXPFILL }},
10265 #if 0
10266 { &ei_mptcp_stream_incomplete, { "mptcp.incomplete", PI_PROTOCOL, PI_WARN, "Everything was not captured", EXPFILL }},
10267 { &ei_mptcp_analysis_dsn_out_of_order, { "mptcp.analysis.dsn.out_of_order", PI_PROTOCOL, PI_WARN, "Out of order dsn", EXPFILL }},
10268 #endif
10271 static hf_register_info mptcp_hf[] = {
10272 { &hf_mptcp_ack,
10273 { "Multipath TCP Data ACK", "mptcp.ack", FT_UINT64,
10274 BASE_DEC, NULL, 0x0, NULL, HFILL}},
10276 { &hf_mptcp_dsn,
10277 { "Data Sequence Number", "mptcp.dsn", FT_UINT64, BASE_DEC, NULL, 0x0,
10278 "Data Sequence Number mapped to this TCP sequence number", HFILL}},
10280 { &hf_mptcp_rawdsn64,
10281 { "Raw Data Sequence Number", "mptcp.rawdsn64", FT_UINT64, BASE_DEC, NULL, 0x0,
10282 "Data Sequence Number mapped to this TCP sequence number", HFILL}},
10284 { &hf_mptcp_dss_dsn,
10285 { "DSS Data Sequence Number", "mptcp.dss.dsn", FT_UINT64,
10286 BASE_DEC, NULL, 0x0, NULL, HFILL}},
10288 { &hf_mptcp_expected_idsn,
10289 { "Subflow expected IDSN", "mptcp.expected_idsn", FT_UINT64,
10290 BASE_DEC|BASE_UNIT_STRING, UNS(&units_64bit_version), 0x0, NULL, HFILL}},
10292 { &hf_mptcp_analysis,
10293 { "MPTCP analysis", "mptcp.analysis", FT_NONE, BASE_NONE, NULL, 0x0,
10294 "This frame has some of the MPTCP analysis shown", HFILL }},
10296 { &hf_mptcp_related_mapping,
10297 { "Related mapping", "mptcp.related_mapping", FT_FRAMENUM , BASE_NONE, NULL, 0x0,
10298 "Packet in which current packet DSS mapping was sent", HFILL }},
10300 { &hf_mptcp_reinjection_of,
10301 { "Reinjection of", "mptcp.reinjection_of", FT_FRAMENUM , BASE_NONE, NULL, 0x0,
10302 "This is a retransmission of data sent on another subflow", HFILL }},
10304 { &hf_mptcp_reinjected_in,
10305 { "Data reinjected in", "mptcp.reinjected_in", FT_FRAMENUM , BASE_NONE, NULL, 0x0,
10306 "This was retransmitted on another subflow", HFILL }},
10308 { &hf_mptcp_analysis_subflows,
10309 { "TCP subflow stream id(s)", "mptcp.analysis.subflows", FT_STRING, BASE_NONE, NULL, 0x0,
10310 "List all TCP connections mapped to this MPTCP connection", HFILL }},
10312 { &hf_mptcp_stream,
10313 { "Stream index", "mptcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
10314 NULL, HFILL }},
10316 { &hf_mptcp_number_of_removed_addresses,
10317 { "Number of removed addresses", "mptcp.rm_addr.count", FT_UINT8,
10318 BASE_DEC, NULL, 0x0, NULL, HFILL}},
10320 { &hf_mptcp_expected_token,
10321 { "Subflow token generated from key", "mptcp.expected_token", FT_UINT32,
10322 BASE_DEC, NULL, 0x0, NULL, HFILL}},
10324 { &hf_mptcp_analysis_master,
10325 { "Master flow", "mptcp.master", FT_BOOLEAN, BASE_NONE,
10326 NULL, 0x0, NULL, HFILL}}
10330 static build_valid_func tcp_da_src_values[1] = {tcp_src_value};
10331 static build_valid_func tcp_da_dst_values[1] = {tcp_dst_value};
10332 static build_valid_func tcp_da_both_values[2] = {tcp_src_value, tcp_dst_value};
10333 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}};
10334 static decode_as_t tcp_da = {"tcp", "tcp.port", 3, 2, tcp_da_values, "TCP", "port(s) as",
10335 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
10337 module_t *tcp_module;
10338 module_t *mptcp_module;
10339 expert_module_t* expert_tcp;
10340 expert_module_t* expert_mptcp;
10342 proto_tcp = proto_register_protocol("Transmission Control Protocol", "TCP", "tcp");
10343 tcp_handle = register_dissector("tcp", dissect_tcp, proto_tcp);
10344 tcp_cap_handle = register_capture_dissector("tcp", capture_tcp, proto_tcp);
10345 proto_register_field_array(proto_tcp, hf, array_length(hf));
10346 proto_register_subtree_array(ett, array_length(ett));
10347 expert_tcp = expert_register_protocol(proto_tcp);
10348 expert_register_field_array(expert_tcp, ei, array_length(ei));
10350 /* subdissector code */
10351 subdissector_table = register_dissector_table("tcp.port",
10352 "TCP port", proto_tcp, FT_UINT16, BASE_DEC);
10353 heur_subdissector_list = register_heur_dissector_list_with_description("tcp", "TCP heuristic", proto_tcp);
10354 tcp_option_table = register_dissector_table("tcp.option",
10355 "TCP Options", proto_tcp, FT_UINT8, BASE_DEC);
10357 /* Register TCP options as their own protocols so we can get the name of the option */
10358 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);
10359 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);
10360 proto_tcp_option_timestamp = proto_register_protocol_in_name_only("TCP Option - Timestamps", "Timestamps", "tcp.options.timestamp", proto_tcp, FT_BYTES);
10361 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);
10362 proto_tcp_option_wscale = proto_register_protocol_in_name_only("TCP Option - Window scale", "Window scale", "tcp.options.wscale", proto_tcp, FT_BYTES);
10363 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);
10364 proto_tcp_option_sack = proto_register_protocol_in_name_only("TCP Option - SACK", "SACK", "tcp.options.sack", proto_tcp, FT_BYTES);
10365 proto_tcp_option_echo = proto_register_protocol_in_name_only("TCP Option - Echo", "Echo", "tcp.options.echo", proto_tcp, FT_BYTES);
10366 proto_tcp_option_echoreply = proto_register_protocol_in_name_only("TCP Option - Echo reply", "Echo reply", "tcp.options.echoreply", proto_tcp, FT_BYTES);
10367 proto_tcp_option_cc = proto_register_protocol_in_name_only("TCP Option - CC", "CC", "tcp.options.cc", proto_tcp, FT_BYTES);
10368 proto_tcp_option_cc_new = proto_register_protocol_in_name_only("TCP Option - CC.NEW", "CC.NEW", "tcp.options.ccnew", proto_tcp, FT_BYTES);
10369 proto_tcp_option_cc_echo = proto_register_protocol_in_name_only("TCP Option - CC.ECHO", "CC.ECHO", "tcp.options.ccecho", proto_tcp, FT_BYTES);
10370 proto_tcp_option_ao = proto_register_protocol_in_name_only("TCP Option - TCP AO", "TCP AO", "tcp.options.ao", proto_tcp, FT_BYTES);
10371 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);
10372 proto_tcp_option_scps = proto_register_protocol_in_name_only("TCP Option - SCPS capabilities", "SCPS capabilities", "tcp.options.scps", proto_tcp, FT_BYTES);
10373 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);
10374 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);
10375 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);
10376 proto_tcp_option_qs = proto_register_protocol_in_name_only("TCP Option - Quick-Start", "Quick-Start", "tcp.options.qs", proto_tcp, FT_BYTES);
10377 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);
10378 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);
10379 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);
10380 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);
10381 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);
10382 proto_tcp_option_exp = proto_register_protocol_in_name_only("TCP Option - Experimental", "Experimental", "tcp.options.experimental", proto_tcp, FT_BYTES);
10383 proto_tcp_option_unknown = proto_register_protocol_in_name_only("TCP Option - Unknown", "Unknown", "tcp.options.unknown", proto_tcp, FT_BYTES);
10385 register_capture_dissector_table("tcp.port", "TCP");
10387 /* Register configuration preferences */
10388 tcp_module = prefs_register_protocol(proto_tcp, NULL);
10389 prefs_register_bool_preference(tcp_module, "summary_in_tree",
10390 "Show TCP summary in protocol tree",
10391 "Whether the TCP summary line should be shown in the protocol tree",
10392 &tcp_summary_in_tree);
10393 prefs_register_bool_preference(tcp_module, "check_checksum",
10394 "Validate the TCP checksum if possible",
10395 "Whether to validate the TCP checksum or not. "
10396 "(Invalid checksums will cause reassembly, if enabled, to fail.)",
10397 &tcp_check_checksum);
10398 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
10399 "Allow subdissector to reassemble TCP streams",
10400 "Whether subdissector can request TCP streams to be reassembled",
10401 &tcp_desegment);
10402 prefs_register_bool_preference(tcp_module, "reassemble_out_of_order",
10403 "Reassemble out-of-order segments",
10404 "Whether out-of-order segments should be buffered and reordered before passing it to a subdissector. "
10405 "To use this option you must also enable \"Allow subdissector to reassemble TCP streams\".",
10406 &tcp_reassemble_out_of_order);
10407 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
10408 "Analyze TCP sequence numbers",
10409 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
10410 &tcp_analyze_seq);
10411 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
10412 "Relative sequence numbers (Requires \"Analyze TCP sequence numbers\")",
10413 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
10414 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
10415 &tcp_relative_seq);
10417 prefs_register_custom_preference_TCP_Analysis(tcp_module, "default_override_analysis",
10418 "Force interpretation to selected packet(s)",
10419 "Override the default analysis with this value for the selected packet",
10420 &tcp_default_override_analysis, override_analysis_vals, false);
10422 prefs_register_enum_preference(tcp_module, "default_window_scaling",
10423 "Scaling factor to use when not available from capture",
10424 "Make the TCP dissector use this scaling factor for streams where the signalled scaling factor "
10425 "is not visible in the capture",
10426 &tcp_default_window_scaling, window_scaling_vals, false);
10428 /* Presumably a retired, unconditional version of what has been added back with the preference above... */
10429 prefs_register_obsolete_preference(tcp_module, "window_scaling");
10431 prefs_register_bool_preference(tcp_module, "track_bytes_in_flight",
10432 "Track number of bytes in flight",
10433 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "
10434 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
10435 "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",
10436 &tcp_track_bytes_in_flight);
10437 prefs_register_bool_preference(tcp_module, "bif_seq_based",
10438 "Evaluate bytes in flight based on sequence numbers",
10439 "Evaluate BiF on actual sequence numbers or use the historical method based on payloads (default). "
10440 "This option has no effect if not used with \"Track number of bytes in flight\". ",
10441 &tcp_bif_seq_based);
10442 prefs_register_bool_preference(tcp_module, "calculate_timestamps",
10443 "Calculate stream packet number and timestamps",
10444 "Calculate relative packet number and timestamps relative to the first frame and the previous frame in the tcp conversation",
10445 &tcp_calculate_ts);
10446 prefs_register_bool_preference(tcp_module, "try_heuristic_first",
10447 "Try heuristic sub-dissectors first",
10448 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
10449 &try_heuristic_first);
10450 prefs_register_bool_preference(tcp_module, "ignore_tcp_timestamps",
10451 "Ignore TCP Timestamps in summary",
10452 "Do not place the TCP Timestamps in the summary line",
10453 &tcp_ignore_timestamps);
10454 prefs_register_bool_preference(tcp_module, "fastrt_supersedes_ooo",
10455 "Fast Retransmission supersedes Out-of-Order interpretation",
10456 "When interpreting ambiguous packets, give precedence to Fast Retransmission or OOO ",
10457 &tcp_fastrt_precedence);
10459 prefs_register_bool_preference(tcp_module, "no_subdissector_on_error",
10460 "Do not call subdissectors for error packets",
10461 "Do not call any subdissectors for Retransmitted or OutOfOrder segments",
10462 &tcp_no_subdissector_on_error);
10464 prefs_register_bool_preference(tcp_module, "dissect_experimental_options_rfc6994",
10465 "TCP Experimental Options using the format of RFC 6994",
10466 "Assume TCP Experimental Options (253, 254) have an Experiment Identifier and use it for dissection",
10467 &tcp_exp_options_rfc6994);
10469 prefs_register_bool_preference(tcp_module, "display_process_info_from_ipfix",
10470 "Display process information via IPFIX",
10471 "Collect and store process information retrieved from IPFIX dissector",
10472 &tcp_display_process_info);
10474 prefs_register_bool_preference(tcp_module, "read_seq_as_syn_cookie",
10475 "Read the seq no. as syn cookie",
10476 "Read the sequence number as it was a syn cookie",
10477 &read_seq_as_syn_cookie);
10479 register_init_routine(tcp_init);
10480 reassembly_table_register(&tcp_reassembly_table,
10481 &tcp_reassembly_table_functions);
10483 register_decode_as(&tcp_da);
10485 register_conversation_table(proto_tcp, false, tcpip_conversation_packet, tcpip_endpoint_packet);
10486 register_conversation_filter("tcp", "TCP", tcp_filter_valid, tcp_build_filter_by_id, NULL);
10488 register_seq_analysis("tcp", "TCP Flows", proto_tcp, NULL, TL_REQUIRES_NOTHING, tcp_seq_analysis_packet);
10490 /* considers MPTCP as a distinct protocol (even if it's a TCP option) */
10491 proto_mptcp = proto_register_protocol("Multipath Transmission Control Protocol", "MPTCP", "mptcp");
10493 proto_register_field_array(proto_mptcp, mptcp_hf, array_length(mptcp_hf));
10494 proto_register_subtree_array(mptcp_ett, array_length(mptcp_ett));
10496 /* Register configuration preferences */
10497 mptcp_module = prefs_register_protocol(proto_mptcp, NULL);
10498 expert_mptcp = expert_register_protocol(proto_tcp);
10499 expert_register_field_array(expert_mptcp, mptcp_ei, array_length(mptcp_ei));
10501 prefs_register_bool_preference(mptcp_module, "analyze_mptcp",
10502 "Map TCP subflows to their respective MPTCP connections",
10503 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
10504 &tcp_analyze_mptcp);
10506 prefs_register_bool_preference(mptcp_module, "relative_sequence_numbers",
10507 "Display relative MPTCP sequence numbers.",
10508 "In case you don't capture the key, it will use the first DSN seen",
10509 &mptcp_relative_seq);
10511 prefs_register_bool_preference(mptcp_module, "analyze_mappings",
10512 "Deeper analysis of Data Sequence Signal (DSS)",
10513 "Scales logarithmically with the number of packets"
10514 "You need to capture the handshake for this to work."
10515 "\"Map TCP subflows to their respective MPTCP connections\"",
10516 &mptcp_analyze_mappings);
10518 prefs_register_bool_preference(mptcp_module, "intersubflows_retransmission",
10519 "Check for data duplication across subflows",
10520 "(Greedy algorithm: Scales linearly with number of subflows and"
10521 " logarithmic scaling with number of packets)"
10522 "You need to enable DSS mapping analysis for this option to work",
10523 &mptcp_intersubflows_retransmission);
10525 range_convert_str(wmem_epan_scope(), &tcp_clientport_dissectors_range, TCP_DEFAULT_CLIENTPORT_DISSECTORS, 65535);
10526 prefs_register_range_preference(tcp_module, "clientport_dissectors", "Client port dissectors",
10527 "Ports for which the dissector will to be chosen based on the client port instead of the server port",
10528 &tcp_clientport_dissectors_range, 65535);
10530 register_conversation_table(proto_mptcp, false, mptcpip_conversation_packet, tcpip_endpoint_packet);
10531 register_follow_stream(proto_tcp, "tcp_follow", tcp_follow_conv_filter, tcp_follow_index_filter, tcp_follow_address_filter,
10532 tcp_port_to_display, follow_tcp_tap_listener, get_tcp_stream_count, NULL);
10534 tcp_tap = register_tap("tcp");
10535 tcp_follow_tap = register_tap("tcp_follow");
10536 mptcp_tap = register_tap("mptcp");
10539 void
10540 proto_reg_handoff_tcp(void)
10542 dissector_add_uint("ip.proto", IP_PROTO_TCP, tcp_handle);
10543 dissector_add_for_decode_as_with_preference("udp.port", tcp_handle);
10544 data_handle = find_dissector("data");
10545 sport_handle = find_dissector("sport");
10547 capture_dissector_add_uint("ip.proto", IP_PROTO_TCP, tcp_cap_handle);
10549 /* Create dissection function handles for all TCP options */
10550 dissector_add_uint("tcp.option", TCPOPT_TIMESTAMP, create_dissector_handle( dissect_tcpopt_timestamp, proto_tcp_option_timestamp ));
10551 dissector_add_uint("tcp.option", TCPOPT_MSS, create_dissector_handle( dissect_tcpopt_mss, proto_tcp_option_mss ));
10552 dissector_add_uint("tcp.option", TCPOPT_WINDOW, create_dissector_handle( dissect_tcpopt_wscale, proto_tcp_option_wscale ));
10553 dissector_add_uint("tcp.option", TCPOPT_SACK_PERM, create_dissector_handle( dissect_tcpopt_sack_perm, proto_tcp_option_sack_perm ));
10554 dissector_add_uint("tcp.option", TCPOPT_SACK, create_dissector_handle( dissect_tcpopt_sack, proto_tcp_option_sack ));
10555 dissector_add_uint("tcp.option", TCPOPT_ECHO, create_dissector_handle( dissect_tcpopt_echo, proto_tcp_option_echo ));
10556 dissector_add_uint("tcp.option", TCPOPT_ECHOREPLY, create_dissector_handle( dissect_tcpopt_echo, proto_tcp_option_echoreply ));
10557 dissector_add_uint("tcp.option", TCPOPT_CC, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc ));
10558 dissector_add_uint("tcp.option", TCPOPT_CCNEW, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc_new ));
10559 dissector_add_uint("tcp.option", TCPOPT_CCECHO, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc_echo ));
10560 dissector_add_uint("tcp.option", TCPOPT_MD5, create_dissector_handle( dissect_tcpopt_md5, proto_tcp_option_md5 ));
10561 dissector_add_uint("tcp.option", TCPOPT_AO, create_dissector_handle( dissect_tcpopt_ao, proto_tcp_option_ao ));
10562 dissector_add_uint("tcp.option", TCPOPT_SCPS, create_dissector_handle( dissect_tcpopt_scps, proto_tcp_option_scps ));
10563 dissector_add_uint("tcp.option", TCPOPT_SNACK, create_dissector_handle( dissect_tcpopt_snack, proto_tcp_option_snack ));
10564 dissector_add_uint("tcp.option", TCPOPT_RECBOUND, create_dissector_handle( dissect_tcpopt_recbound, proto_tcp_option_scpsrec ));
10565 dissector_add_uint("tcp.option", TCPOPT_CORREXP, create_dissector_handle( dissect_tcpopt_correxp, proto_tcp_option_scpscor ));
10566 dissector_add_uint("tcp.option", TCPOPT_QS, create_dissector_handle( dissect_tcpopt_qs, proto_tcp_option_qs ));
10567 dissector_add_uint("tcp.option", TCPOPT_USER_TO, create_dissector_handle( dissect_tcpopt_user_to, proto_tcp_option_user_to ));
10568 dissector_add_uint("tcp.option", TCPOPT_TFO, create_dissector_handle( dissect_tcpopt_tfo, proto_tcp_option_tfo ));
10569 dissector_add_uint("tcp.option", TCPOPT_RVBD_PROBE, create_dissector_handle( dissect_tcpopt_rvbd_probe, proto_tcp_option_rvbd_probe ));
10570 dissector_add_uint("tcp.option", TCPOPT_RVBD_TRPY, create_dissector_handle( dissect_tcpopt_rvbd_trpy, proto_tcp_option_rvbd_trpy ));
10571 dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_0, create_dissector_handle( dissect_tcpopt_acc_ecn, proto_tcp_option_acc_ecn ));
10572 dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_1, create_dissector_handle( dissect_tcpopt_acc_ecn, proto_tcp_option_acc_ecn ));
10573 dissector_add_uint("tcp.option", TCPOPT_EXP_FD, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp ));
10574 dissector_add_uint("tcp.option", TCPOPT_EXP_FE, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp ));
10575 dissector_add_uint("tcp.option", TCPOPT_MPTCP, create_dissector_handle( dissect_tcpopt_mptcp, proto_mptcp ));
10576 /* Common handle for all the unknown/unsupported TCP options */
10577 tcp_opt_unknown_handle = create_dissector_handle( dissect_tcpopt_unknown, proto_tcp_option_unknown );
10579 exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4);
10581 proto_ip = proto_get_id_by_filter_name("ip");
10582 proto_icmp = proto_get_id_by_filter_name("icmp");
10586 * Editor modelines
10588 * Local Variables:
10589 * c-basic-offset: 4
10590 * tab-width: 8
10591 * indent-tabs-mode: nil
10592 * End:
10594 * ex: set shiftwidth=4 tabstop=8 expandtab:
10595 * :indentSize=4:tabSize=8:noTabs=true: