clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-tcp.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-17/lib/clang/17 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-error=stringop-overflow= -Wno-error=deprecated-declarations -Wno-format-truncation -Wno-pointer-sign -std=gnu11 -fdebug-compilation-dir=/builds/wireshark/wireshark/build -ferror-limit 19 -fvisibility=hidden -fwrapv -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-04-20-100240-3130-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-tcp.c
1 | /* packet-tcp.c |
2 | * Routines for TCP packet disassembly |
3 | * |
4 | * Wireshark - Network traffic analyzer |
5 | * By Gerald Combs <[emailprotected]> |
6 | * Copyright 1998 Gerald Combs |
7 | * |
8 | * SPDX-License-Identifier: GPL-2.0-or-later |
9 | */ |
10 | |
11 | #include "config.h" |
12 | |
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 | |
32 | #include <wsutil/utf8_entities.h> |
33 | #include <wsutil/str_util.h> |
34 | #include <wsutil/wsgcrypt.h> |
35 | #include <wsutil/pint.h> |
36 | #include <wsutil/ws_assert.h> |
37 | |
38 | #include "packet-tcp.h" |
39 | #include "packet-ip.h" |
40 | #include "packet-icmp.h" |
41 | |
42 | void proto_register_tcp(void); |
43 | void proto_reg_handoff_tcp(void); |
44 | static void conversation_completeness_fill(gchar*, guint32); |
45 | |
46 | static int tcp_tap; |
47 | static int tcp_follow_tap; |
48 | static int mptcp_tap; |
49 | static int exported_pdu_tap; |
50 | |
51 | /* Place TCP summary in proto tree */ |
52 | static bool_Bool tcp_summary_in_tree = true1; |
53 | |
54 | static inline guint64 KEEP_32MSB_OF_GUINT64(guint64 nb) { |
55 | return (nb >> 32) << 32; |
56 | } |
57 | |
58 | #define MPTCP_DSS_FLAG_DATA_ACK_PRESENT0x01 0x01 |
59 | #define MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02 0x02 |
60 | #define MPTCP_DSS_FLAG_MAPPING_PRESENT0x04 0x04 |
61 | #define MPTCP_DSS_FLAG_DSN_8BYTES0x08 0x08 |
62 | #define MPTCP_DSS_FLAG_DATA_FIN_PRESENT0x10 0x10 |
63 | |
64 | /* |
65 | * Flag to control whether to check the TCP checksum. |
66 | * |
67 | * In at least some Solaris network traces, there are packets with bad |
68 | * TCP checksums, but the traffic appears to indicate that the packets |
69 | * *were* received; the packets were probably sent by the host on which |
70 | * the capture was being done, on a network interface to which |
71 | * checksumming was offloaded, so that DLPI supplied an un-checksummed |
72 | * packet to the capture program but a checksummed packet got put onto |
73 | * the wire. |
74 | */ |
75 | static bool_Bool tcp_check_checksum; |
76 | |
77 | /* |
78 | * Window scaling values to be used when not known (set as a preference) */ |
79 | enum scaling_window_value { |
80 | WindowScaling_NotKnown=-1, |
81 | WindowScaling_0=0, |
82 | WindowScaling_1, |
83 | WindowScaling_2, |
84 | WindowScaling_3, |
85 | WindowScaling_4, |
86 | WindowScaling_5, |
87 | WindowScaling_6, |
88 | WindowScaling_7, |
89 | WindowScaling_8, |
90 | WindowScaling_9, |
91 | WindowScaling_10, |
92 | WindowScaling_11, |
93 | WindowScaling_12, |
94 | WindowScaling_13, |
95 | WindowScaling_14 |
96 | }; |
97 | |
98 | /* |
99 | * Analysis overriding values to be used when not satisfied by the automatic |
100 | * result. (Accessed through preferences but not stored as a preference) |
101 | */ |
102 | enum override_analysis_value { |
103 | OverrideAnalysis_0=0, |
104 | OverrideAnalysis_1, |
105 | OverrideAnalysis_2, |
106 | OverrideAnalysis_3, |
107 | OverrideAnalysis_4 |
108 | }; |
109 | |
110 | /* |
111 | * Using enum instead of boolean make API easier |
112 | */ |
113 | enum mptcp_dsn_conversion { |
114 | DSN_CONV_64_TO_32, |
115 | DSN_CONV_32_TO_64, |
116 | DSN_CONV_NONE |
117 | } ; |
118 | |
119 | #define MPTCP_TCPRST_FLAG_T_PRESENT0x1 0x1 |
120 | #define MPTCP_TCPRST_FLAG_W_PRESENT0x2 0x2 |
121 | #define MPTCP_TCPRST_FLAG_V_PRESENT0x4 0x4 |
122 | #define MPTCP_TCPRST_FLAG_U_PRESENT0x8 0x8 |
123 | |
124 | static const value_string mp_tcprst_reasons[] = { |
125 | { 0x0, "Unspecified error" }, |
126 | { 0x1, "MPTCP-specific error" }, |
127 | { 0x2, "Lack of resources" }, |
128 | { 0x3, "Administratively prohibited" }, |
129 | { 0x4, "Too much outstanding data" }, |
130 | { 0x5, "Unacceptable performance" }, |
131 | { 0x6, "Middlebox interference" }, |
132 | { 0, NULL((void*)0) }, |
133 | }; |
134 | |
135 | static gint tcp_default_window_scaling = (gint)WindowScaling_NotKnown; |
136 | |
137 | static gint tcp_default_override_analysis = (gint)OverrideAnalysis_0; |
138 | |
139 | static int proto_tcp; |
140 | static int proto_ip; |
141 | static int proto_icmp; |
142 | |
143 | static int proto_tcp_option_nop; |
144 | static int proto_tcp_option_eol; |
145 | static int proto_tcp_option_timestamp; |
146 | static int proto_tcp_option_mss; |
147 | static int proto_tcp_option_wscale; |
148 | static int proto_tcp_option_sack_perm; |
149 | static int proto_tcp_option_sack; |
150 | static int proto_tcp_option_echo; |
151 | static int proto_tcp_option_echoreply; |
152 | static int proto_tcp_option_cc; |
153 | static int proto_tcp_option_cc_new; |
154 | static int proto_tcp_option_cc_echo; |
155 | static int proto_tcp_option_md5; |
156 | static int proto_tcp_option_ao; |
157 | static int proto_tcp_option_scps; |
158 | static int proto_tcp_option_snack; |
159 | static int proto_tcp_option_scpsrec; |
160 | static int proto_tcp_option_scpscor; |
161 | static int proto_tcp_option_qs; |
162 | static int proto_tcp_option_user_to; |
163 | static int proto_tcp_option_tfo; |
164 | static int proto_tcp_option_acc_ecn; |
165 | static int proto_tcp_option_rvbd_probe; |
166 | static int proto_tcp_option_rvbd_trpy; |
167 | static int proto_tcp_option_exp; |
168 | static int proto_tcp_option_unknown; |
169 | static int proto_mptcp; |
170 | |
171 | static int hf_tcp_srcport; |
172 | static int hf_tcp_dstport; |
173 | static int hf_tcp_port; |
174 | static int hf_tcp_stream; |
175 | static int hf_tcp_stream_pnum; |
176 | static int hf_tcp_completeness; |
177 | static int hf_tcp_completeness_syn; |
178 | static int hf_tcp_completeness_syn_ack; |
179 | static int hf_tcp_completeness_ack; |
180 | static int hf_tcp_completeness_data; |
181 | static int hf_tcp_completeness_fin; |
182 | static int hf_tcp_completeness_rst; |
183 | static int hf_tcp_completeness_str; |
184 | static int hf_tcp_seq; |
185 | static int hf_tcp_seq_abs; |
186 | static int hf_tcp_nxtseq; |
187 | static int hf_tcp_ack; |
188 | static int hf_tcp_ack_abs; |
189 | static int hf_tcp_hdr_len; |
190 | static int hf_tcp_flags; |
191 | static int hf_tcp_flags_res; |
192 | static int hf_tcp_flags_ae; |
193 | static int hf_tcp_flags_cwr; |
194 | static int hf_tcp_flags_ece; |
195 | static int hf_tcp_flags_ace; |
196 | static int hf_tcp_flags_urg; |
197 | static int hf_tcp_flags_ack; |
198 | static int hf_tcp_flags_push; |
199 | static int hf_tcp_flags_reset; |
200 | static int hf_tcp_flags_syn; |
201 | static int hf_tcp_flags_fin; |
202 | static int hf_tcp_flags_str; |
203 | static int hf_tcp_window_size_value; |
204 | static int hf_tcp_window_size; |
205 | static int hf_tcp_window_size_scalefactor; |
206 | static int hf_tcp_checksum; |
207 | static int hf_tcp_checksum_status; |
208 | static int hf_tcp_checksum_calculated; |
209 | static int hf_tcp_len; |
210 | static int hf_tcp_urgent_pointer; |
211 | static int hf_tcp_analysis; |
212 | static int hf_tcp_analysis_flags; |
213 | static int hf_tcp_analysis_bytes_in_flight; |
214 | static int hf_tcp_analysis_push_bytes_sent; |
215 | static int hf_tcp_analysis_acks_frame; |
216 | static int hf_tcp_analysis_ack_rtt; |
217 | static int hf_tcp_analysis_first_rtt; |
218 | static int hf_tcp_analysis_rto; |
219 | static int hf_tcp_analysis_rto_frame; |
220 | static int hf_tcp_analysis_duplicate_ack; |
221 | static int hf_tcp_analysis_duplicate_ack_num; |
222 | static int hf_tcp_analysis_duplicate_ack_frame; |
223 | static int hf_tcp_continuation_to; |
224 | static int hf_tcp_pdu_time; |
225 | static int hf_tcp_pdu_size; |
226 | static int hf_tcp_pdu_last_frame; |
227 | static int hf_tcp_reassembled_in; |
228 | static int hf_tcp_reassembled_length; |
229 | static int hf_tcp_reassembled_data; |
230 | static int hf_tcp_segments; |
231 | static int hf_tcp_segment; |
232 | static int hf_tcp_segment_overlap; |
233 | static int hf_tcp_segment_overlap_conflict; |
234 | static int hf_tcp_segment_multiple_tails; |
235 | static int hf_tcp_segment_too_long_fragment; |
236 | static int hf_tcp_segment_error; |
237 | static int hf_tcp_segment_count; |
238 | static int hf_tcp_options; |
239 | static int hf_tcp_option_kind; |
240 | static int hf_tcp_option_len; |
241 | static int hf_tcp_option_mss_val; |
242 | static int hf_tcp_option_wscale_shift; |
243 | static int hf_tcp_option_wscale_multiplier; |
244 | static int hf_tcp_option_sack_sle; |
245 | static int hf_tcp_option_sack_sre; |
246 | static int hf_tcp_option_sack_range_count; |
247 | static int hf_tcp_option_sack_dsack_le; |
248 | static int hf_tcp_option_sack_dsack_re; |
249 | static int hf_tcp_option_echo; |
250 | static int hf_tcp_option_timestamp_tsval; |
251 | static int hf_tcp_option_timestamp_tsecr; |
252 | static int hf_tcp_option_cc; |
253 | static int hf_tcp_option_md5_digest; |
254 | static int hf_tcp_option_ao_keyid; |
255 | static int hf_tcp_option_ao_rnextkeyid; |
256 | static int hf_tcp_option_ao_mac; |
257 | static int hf_tcp_option_qs_rate; |
258 | static int hf_tcp_option_qs_ttl_diff; |
259 | static int hf_tcp_option_tarr_rate; |
260 | static int hf_tcp_option_tarr_reserved; |
261 | static int hf_tcp_option_acc_ecn_ee0b; |
262 | static int hf_tcp_option_acc_ecn_eceb; |
263 | static int hf_tcp_option_acc_ecn_ee1b; |
264 | static int hf_tcp_option_exp_data; |
265 | static int hf_tcp_option_exp_exid; |
266 | static int hf_tcp_option_unknown_payload; |
267 | |
268 | static int hf_tcp_option_rvbd_probe_version1; |
269 | static int hf_tcp_option_rvbd_probe_version2; |
270 | static int hf_tcp_option_rvbd_probe_type1; |
271 | static int hf_tcp_option_rvbd_probe_type2; |
272 | static int hf_tcp_option_rvbd_probe_prober; |
273 | static int hf_tcp_option_rvbd_probe_proxy; |
274 | static int hf_tcp_option_rvbd_probe_client; |
275 | static int hf_tcp_option_rvbd_probe_proxy_port; |
276 | static int hf_tcp_option_rvbd_probe_appli_ver; |
277 | static int hf_tcp_option_rvbd_probe_storeid; |
278 | static int hf_tcp_option_rvbd_probe_flags; |
279 | static int hf_tcp_option_rvbd_probe_flag_last_notify; |
280 | static int hf_tcp_option_rvbd_probe_flag_server_connected; |
281 | static int hf_tcp_option_rvbd_probe_flag_not_cfe; |
282 | static int hf_tcp_option_rvbd_probe_flag_sslcert; |
283 | static int hf_tcp_option_rvbd_probe_flag_probe_cache; |
284 | |
285 | static int hf_tcp_option_rvbd_trpy_flags; |
286 | static int hf_tcp_option_rvbd_trpy_flag_mode; |
287 | static int hf_tcp_option_rvbd_trpy_flag_oob; |
288 | static int hf_tcp_option_rvbd_trpy_flag_chksum; |
289 | static int hf_tcp_option_rvbd_trpy_flag_fw_rst; |
290 | static int hf_tcp_option_rvbd_trpy_flag_fw_rst_inner; |
291 | static int hf_tcp_option_rvbd_trpy_flag_fw_rst_probe; |
292 | static int hf_tcp_option_rvbd_trpy_src; |
293 | static int hf_tcp_option_rvbd_trpy_dst; |
294 | static int hf_tcp_option_rvbd_trpy_src_port; |
295 | static int hf_tcp_option_rvbd_trpy_dst_port; |
296 | static int hf_tcp_option_rvbd_trpy_client_port; |
297 | |
298 | static int hf_tcp_option_mptcp_flags; |
299 | static int hf_tcp_option_mptcp_backup_flag; |
300 | static int hf_tcp_option_mptcp_checksum_flag; |
301 | static int hf_tcp_option_mptcp_B_flag; |
302 | static int hf_tcp_option_mptcp_C_flag; |
303 | static int hf_tcp_option_mptcp_H_v0_flag; |
304 | static int hf_tcp_option_mptcp_H_v1_flag; |
305 | static int hf_tcp_option_mptcp_F_flag; |
306 | static int hf_tcp_option_mptcp_m_flag; |
307 | static int hf_tcp_option_mptcp_M_flag; |
308 | static int hf_tcp_option_mptcp_a_flag; |
309 | static int hf_tcp_option_mptcp_A_flag; |
310 | static int hf_tcp_option_mptcp_U_flag; |
311 | static int hf_tcp_option_mptcp_V_flag; |
312 | static int hf_tcp_option_mptcp_W_flag; |
313 | static int hf_tcp_option_mptcp_T_flag; |
314 | static int hf_tcp_option_mptcp_tcprst_reason; |
315 | static int hf_tcp_option_mptcp_reserved_v0_flag; |
316 | static int hf_tcp_option_mptcp_reserved_v1_flag; |
317 | static int hf_tcp_option_mptcp_subtype; |
318 | static int hf_tcp_option_mptcp_version; |
319 | static int hf_tcp_option_mptcp_reserved; |
320 | static int hf_tcp_option_mptcp_address_id; |
321 | static int hf_tcp_option_mptcp_recv_token; |
322 | static int hf_tcp_option_mptcp_sender_key; |
323 | static int hf_tcp_option_mptcp_recv_key; |
324 | static int hf_tcp_option_mptcp_sender_rand; |
325 | static int hf_tcp_option_mptcp_sender_trunc_hmac; |
326 | static int hf_tcp_option_mptcp_sender_hmac; |
327 | static int hf_tcp_option_mptcp_addaddr_trunc_hmac; |
328 | static int hf_tcp_option_mptcp_data_ack_raw; |
329 | static int hf_tcp_option_mptcp_data_seq_no_raw; |
330 | static int hf_tcp_option_mptcp_subflow_seq_no; |
331 | static int hf_tcp_option_mptcp_data_lvl_len; |
332 | static int hf_tcp_option_mptcp_checksum; |
333 | static int hf_tcp_option_mptcp_ipver; |
334 | static int hf_tcp_option_mptcp_echo; |
335 | static int hf_tcp_option_mptcp_ipv4; |
336 | static int hf_tcp_option_mptcp_ipv6; |
337 | static int hf_tcp_option_mptcp_port; |
338 | static int hf_mptcp_expected_idsn; |
339 | |
340 | static int hf_mptcp_dsn; |
341 | static int hf_mptcp_rawdsn64; |
342 | static int hf_mptcp_dss_dsn; |
343 | static int hf_mptcp_ack; |
344 | static int hf_mptcp_stream; |
345 | static int hf_mptcp_expected_token; |
346 | static int hf_mptcp_analysis; |
347 | static int hf_mptcp_analysis_master; |
348 | static int hf_mptcp_analysis_subflows; |
349 | static int hf_mptcp_number_of_removed_addresses; |
350 | static int hf_mptcp_related_mapping; |
351 | static int hf_mptcp_reinjection_of; |
352 | static int hf_mptcp_reinjected_in; |
353 | |
354 | |
355 | static int hf_tcp_option_fast_open_cookie_request; |
356 | static int hf_tcp_option_fast_open_cookie; |
357 | |
358 | static int hf_tcp_ts_relative; |
359 | static int hf_tcp_ts_delta; |
360 | static int hf_tcp_option_scps_vector; |
361 | static int hf_tcp_option_scps_binding; |
362 | static int hf_tcp_option_scps_binding_len; |
363 | static int hf_tcp_scpsoption_flags_bets; |
364 | static int hf_tcp_scpsoption_flags_snack1; |
365 | static int hf_tcp_scpsoption_flags_snack2; |
366 | static int hf_tcp_scpsoption_flags_compress; |
367 | static int hf_tcp_scpsoption_flags_nlts; |
368 | static int hf_tcp_scpsoption_flags_reserved; |
369 | static int hf_tcp_scpsoption_connection_id; |
370 | static int hf_tcp_option_snack_offset; |
371 | static int hf_tcp_option_snack_size; |
372 | static int hf_tcp_option_snack_le; |
373 | static int hf_tcp_option_snack_re; |
374 | static int hf_tcp_option_user_to_granularity; |
375 | static int hf_tcp_option_user_to_val; |
376 | static int hf_tcp_proc_src_uid; |
377 | static int hf_tcp_proc_src_pid; |
378 | static int hf_tcp_proc_src_uname; |
379 | static int hf_tcp_proc_src_cmd; |
380 | static int hf_tcp_proc_dst_uid; |
381 | static int hf_tcp_proc_dst_pid; |
382 | static int hf_tcp_proc_dst_uname; |
383 | static int hf_tcp_proc_dst_cmd; |
384 | static int hf_tcp_segment_data; |
385 | static int hf_tcp_payload; |
386 | static int hf_tcp_reset_cause; |
387 | static int hf_tcp_fin_retransmission; |
388 | static int hf_tcp_option_rvbd_probe_reserved; |
389 | static int hf_tcp_option_scps_binding_data; |
390 | static int hf_tcp_syncookie_time; |
391 | static int hf_tcp_syncookie_mss; |
392 | static int hf_tcp_syncookie_hash; |
393 | static int hf_tcp_syncookie_option_timestamp; |
394 | static int hf_tcp_syncookie_option_ecn; |
395 | static int hf_tcp_syncookie_option_sack; |
396 | static int hf_tcp_syncookie_option_wscale; |
397 | |
398 | static gint ett_tcp; |
399 | static gint ett_tcp_completeness; |
400 | static gint ett_tcp_flags; |
401 | static gint ett_tcp_options; |
402 | static gint ett_tcp_option_timestamp; |
403 | static gint ett_tcp_option_mss; |
404 | static gint ett_tcp_option_wscale; |
405 | static gint ett_tcp_option_sack; |
406 | static gint ett_tcp_option_snack; |
407 | static gint ett_tcp_option_scps; |
408 | static gint ett_tcp_scpsoption_flags; |
409 | static gint ett_tcp_option_scps_extended; |
410 | static gint ett_tcp_option_user_to; |
411 | static gint ett_tcp_option_exp; |
412 | static gint ett_tcp_option_acc_ecn; |
413 | static gint ett_tcp_option_sack_perm; |
414 | static gint ett_tcp_analysis; |
415 | static gint ett_tcp_analysis_faults; |
416 | static gint ett_tcp_timestamps; |
417 | static gint ett_tcp_segments; |
418 | static gint ett_tcp_segment; |
419 | static gint ett_tcp_checksum; |
420 | static gint ett_tcp_process_info; |
421 | static gint ett_tcp_option_mptcp; |
422 | static gint ett_tcp_opt_rvbd_probe; |
423 | static gint ett_tcp_opt_rvbd_probe_flags; |
424 | static gint ett_tcp_opt_rvbd_trpy; |
425 | static gint ett_tcp_opt_rvbd_trpy_flags; |
426 | static gint ett_tcp_opt_echo; |
427 | static gint ett_tcp_opt_cc; |
428 | static gint ett_tcp_opt_md5; |
429 | static gint ett_tcp_opt_ao; |
430 | static gint ett_tcp_opt_qs; |
431 | static gint ett_tcp_opt_recbound; |
432 | static gint ett_tcp_opt_scpscor; |
433 | static gint ett_tcp_unknown_opt; |
434 | static gint ett_tcp_option_other; |
435 | static gint ett_tcp_syncookie; |
436 | static gint ett_tcp_syncookie_option; |
437 | static gint ett_mptcp_analysis; |
438 | static gint ett_mptcp_analysis_subflows; |
439 | |
440 | static expert_field ei_tcp_opt_len_invalid; |
441 | static expert_field ei_tcp_analysis_retransmission; |
442 | static expert_field ei_tcp_analysis_fast_retransmission; |
443 | static expert_field ei_tcp_analysis_spurious_retransmission; |
444 | static expert_field ei_tcp_analysis_out_of_order; |
445 | static expert_field ei_tcp_analysis_reused_ports; |
446 | static expert_field ei_tcp_analysis_lost_packet; |
447 | static expert_field ei_tcp_analysis_ack_lost_packet; |
448 | static expert_field ei_tcp_analysis_window_update; |
449 | static expert_field ei_tcp_analysis_window_full; |
450 | static expert_field ei_tcp_analysis_keep_alive; |
451 | static expert_field ei_tcp_analysis_keep_alive_ack; |
452 | static expert_field ei_tcp_analysis_duplicate_ack; |
453 | static expert_field ei_tcp_analysis_zero_window_probe; |
454 | static expert_field ei_tcp_analysis_zero_window; |
455 | static expert_field ei_tcp_analysis_zero_window_probe_ack; |
456 | static expert_field ei_tcp_analysis_tfo_syn; |
457 | static expert_field ei_tcp_analysis_tfo_ack; |
458 | static expert_field ei_tcp_analysis_tfo_ignored; |
459 | static expert_field ei_tcp_analysis_partial_ack; |
460 | static expert_field ei_tcp_scps_capable; |
461 | static expert_field ei_tcp_option_sack_dsack; |
462 | static expert_field ei_tcp_option_snack_sequence; |
463 | static expert_field ei_tcp_option_wscale_shift_invalid; |
464 | static expert_field ei_tcp_option_mss_absent; |
465 | static expert_field ei_tcp_option_mss_present; |
466 | static expert_field ei_tcp_option_sack_perm_absent; |
467 | static expert_field ei_tcp_option_sack_perm_present; |
468 | static expert_field ei_tcp_short_segment; |
469 | static expert_field ei_tcp_ack_nonzero; |
470 | static expert_field ei_tcp_connection_synack; |
471 | static expert_field ei_tcp_connection_syn; |
472 | static expert_field ei_tcp_connection_fin; |
473 | static expert_field ei_tcp_connection_rst; |
474 | static expert_field ei_tcp_connection_fin_active; |
475 | static expert_field ei_tcp_connection_fin_passive; |
476 | static expert_field ei_tcp_checksum_ffff; |
477 | static expert_field ei_tcp_checksum_partial; |
478 | static expert_field ei_tcp_checksum_bad; |
479 | static expert_field ei_tcp_urgent_pointer_non_zero; |
480 | static expert_field ei_tcp_suboption_malformed; |
481 | static expert_field ei_tcp_nop; |
482 | static expert_field ei_tcp_non_zero_bytes_after_eol; |
483 | static expert_field ei_tcp_bogus_header_length; |
484 | |
485 | /* static expert_field ei_mptcp_analysis_unexpected_idsn; */ |
486 | static expert_field ei_mptcp_analysis_echoed_key_mismatch; |
487 | static expert_field ei_mptcp_analysis_missing_algorithm; |
488 | static expert_field ei_mptcp_analysis_unsupported_algorithm; |
489 | static expert_field ei_mptcp_infinite_mapping; |
490 | static expert_field ei_mptcp_mapping_missing; |
491 | /* static expert_field ei_mptcp_stream_incomplete; */ |
492 | /* static expert_field ei_mptcp_analysis_dsn_out_of_order; */ |
493 | |
494 | /* Some protocols such as encrypted DCE/RPCoverHTTP have dependencies |
495 | * from one PDU to the next PDU and require that they are called in sequence. |
496 | * These protocols would not be able to handle PDUs coming out of order |
497 | * or for example when a PDU is seen twice, like for retransmissions. |
498 | * This preference can be set for such protocols to make sure that we don't |
499 | * invoke the subdissectors for retransmitted or out-of-order segments. |
500 | */ |
501 | static bool_Bool tcp_no_subdissector_on_error = true1; |
502 | |
503 | /* Enable buffering of out-of-order TCP segments before passing it to a |
504 | * subdissector (depends on "tcp_desegment"). */ |
505 | static bool_Bool tcp_reassemble_out_of_order; |
506 | |
507 | /* |
508 | * FF: https://www.rfc-editor.org/rfc/rfc6994.html |
509 | * With this flag set we assume the option structure for experimental |
510 | * codepoints (253, 254) has an Experiment Identifier (ExID), which is |
511 | * the first 16-bit field after the Kind and Length. |
512 | * The ExID is used to differentiate different experiments and thus will |
513 | * be used in data dissection. |
514 | */ |
515 | static bool_Bool tcp_exp_options_rfc6994 = true1; |
516 | |
517 | /* |
518 | * This flag indicates which of Fast Retransmission or Out-of-Order |
519 | * interpretation should supersede when analyzing an ambiguous packet as |
520 | * things are not always clear. The user is authorized to change this |
521 | * behavior. |
522 | * When set, we keep the historical interpretation (Fast RT > OOO) |
523 | */ |
524 | static bool_Bool tcp_fastrt_precedence = true1; |
525 | |
526 | /* Process info, currently discovered via IPFIX */ |
527 | static bool_Bool tcp_display_process_info; |
528 | |
529 | /* Read the sequence number as syn cookie */ |
530 | static bool_Bool read_seq_as_syn_cookie; |
531 | |
532 | /* |
533 | * TCP option |
534 | */ |
535 | #define TCPOPT_NOP1 1 /* Padding */ |
536 | #define TCPOPT_EOL0 0 /* End of options */ |
537 | #define TCPOPT_MSS2 2 /* Segment size negotiating */ |
538 | #define TCPOPT_WINDOW3 3 /* Window scaling */ |
539 | #define TCPOPT_SACK_PERM4 4 /* SACK Permitted */ |
540 | #define TCPOPT_SACK5 5 /* SACK Block */ |
541 | #define TCPOPT_ECHO6 6 |
542 | #define TCPOPT_ECHOREPLY7 7 |
543 | #define TCPOPT_TIMESTAMP8 8 /* Better RTT estimations/PAWS */ |
544 | #define TCPOPT_CC11 11 |
545 | #define TCPOPT_CCNEW12 12 |
546 | #define TCPOPT_CCECHO13 13 |
547 | #define TCPOPT_MD519 19 /* RFC2385 */ |
548 | #define TCPOPT_SCPS20 20 /* SCPS Capabilities */ |
549 | #define TCPOPT_SNACK21 21 /* SCPS SNACK */ |
550 | #define TCPOPT_RECBOUND22 22 /* SCPS Record Boundary */ |
551 | #define TCPOPT_CORREXP23 23 /* SCPS Corruption Experienced */ |
552 | #define TCPOPT_QS27 27 /* RFC4782 Quick-Start Response */ |
553 | #define TCPOPT_USER_TO28 28 /* RFC5482 User Timeout Option */ |
554 | #define TCPOPT_AO29 29 /* RFC5925 The TCP Authentication Option */ |
555 | #define TCPOPT_MPTCP30 30 /* RFC6824 Multipath TCP */ |
556 | #define TCPOPT_TFO34 34 /* RFC7413 TCP Fast Open Cookie */ |
557 | #define TCPOPT_ACC_ECN_00xac 0xac /* draft-ietf-tcpm-accurate-ecn */ |
558 | #define TCPOPT_ACC_ECN_10xae 0xae /* draft-ietf-tcpm-accurate-ecn */ |
559 | #define TCPOPT_EXP_FD0xfd 0xfd /* Experimental, reserved */ |
560 | #define TCPOPT_EXP_FE0xfe 0xfe /* Experimental, reserved */ |
561 | /* Non IANA registered option numbers */ |
562 | #define TCPOPT_RVBD_PROBE76 76 /* Riverbed probe option */ |
563 | #define TCPOPT_RVBD_TRPY78 78 /* Riverbed transparency option */ |
564 | |
565 | /* |
566 | * TCP option lengths |
567 | */ |
568 | #define TCPOLEN_MSS4 4 |
569 | #define TCPOLEN_WINDOW3 3 |
570 | #define TCPOLEN_SACK_PERM2 2 |
571 | #define TCPOLEN_SACK_MIN2 2 |
572 | #define TCPOLEN_ECHO6 6 |
573 | #define TCPOLEN_ECHOREPLY6 6 |
574 | #define TCPOLEN_TIMESTAMP10 10 |
575 | #define TCPOLEN_CC6 6 |
576 | #define TCPOLEN_CCNEW6 6 |
577 | #define TCPOLEN_CCECHO6 6 |
578 | #define TCPOLEN_MD518 18 |
579 | #define TCPOLEN_SCPS4 4 |
580 | #define TCPOLEN_SNACK6 6 |
581 | #define TCPOLEN_RECBOUND2 2 |
582 | #define TCPOLEN_CORREXP2 2 |
583 | #define TCPOLEN_QS8 8 |
584 | #define TCPOLEN_USER_TO4 4 |
585 | #define TCPOLEN_MPTCP_MIN3 3 |
586 | #define TCPOLEN_TFO_MIN2 2 |
587 | #define TCPOLEN_RVBD_PROBE_MIN3 3 |
588 | #define TCPOLEN_RVBD_TRPY_MIN16 16 |
589 | #define TCPOLEN_EXP_MIN4 4 |
590 | |
591 | /* |
592 | * TCP Experimental Option Experiment Identifiers (TCP ExIDs) |
593 | * See: https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-exids |
594 | * Wireshark only supports 16-bit ExIDs |
595 | */ |
596 | |
597 | #define TCPEXID_TARR0x00ac 0x00ac |
598 | #define TCPEXID_HOST_ID0x0348 0x0348 |
599 | #define TCPEXID_ASC0x0a0d 0x0a0d |
600 | #define TCPEXID_CAPABILITY0x0ca0 0x0ca0 |
601 | #define TCPEXID_EDO0x0ed0 0x0ed0 |
602 | #define TCPEXID_ENO0x454e 0x454e |
603 | #define TCPEXID_SNO0x5323 0x5323 |
604 | #define TCPEXID_TS_INTERVAL0x75ec 0x75ec /* 32-bit ExID: 0x75ecffee */ |
605 | #define TCPEXID_ACC_ECN_00xacc0 0xacc0 |
606 | #define TCPEXID_ACC_ECN_10xacc1 0xacc1 |
607 | #define TCPEXID_ACC_ECN0xacce 0xacce |
608 | #define TCPEXID_SMC_R0xe2d4 0xe2d4 /* 32-bit ExID: 0xe2d4c3d9 */ |
609 | #define TCPEXID_FO0xf989 0xf989 |
610 | #define TCPEXID_LOW_LATENCY0xf990 0xf990 |
611 | |
612 | /* |
613 | * Multipath TCP subtypes |
614 | */ |
615 | #define TCPOPT_MPTCP_MP_CAPABLE0x0 0x0 /* Multipath TCP Multipath Capable */ |
616 | #define TCPOPT_MPTCP_MP_JOIN0x1 0x1 /* Multipath TCP Join Connection */ |
617 | #define TCPOPT_MPTCP_DSS0x2 0x2 /* Multipath TCP Data Sequence Signal */ |
618 | #define TCPOPT_MPTCP_ADD_ADDR0x3 0x3 /* Multipath TCP Add Address */ |
619 | #define TCPOPT_MPTCP_REMOVE_ADDR0x4 0x4 /* Multipath TCP Remove Address */ |
620 | #define TCPOPT_MPTCP_MP_PRIO0x5 0x5 /* Multipath TCP Change Subflow Priority */ |
621 | #define TCPOPT_MPTCP_MP_FAIL0x6 0x6 /* Multipath TCP Fallback */ |
622 | #define TCPOPT_MPTCP_MP_FASTCLOSE0x7 0x7 /* Multipath TCP Fast Close */ |
623 | #define TCPOPT_MPTCP_MP_TCPRST0x8 0x8 /* Multipath TCP Reset */ |
624 | |
625 | /* |
626 | * Conversation Completeness values |
627 | */ |
628 | #define TCP_COMPLETENESS_SYNSENT0x01 0x01 /* TCP SYN SENT */ |
629 | #define TCP_COMPLETENESS_SYNACK0x02 0x02 /* TCP SYN ACK */ |
630 | #define TCP_COMPLETENESS_ACK0x04 0x04 /* TCP ACK */ |
631 | #define TCP_COMPLETENESS_DATA0x08 0x08 /* TCP data */ |
632 | #define TCP_COMPLETENESS_FIN0x10 0x10 /* TCP FIN */ |
633 | #define TCP_COMPLETENESS_RST0x20 0x20 /* TCP RST */ |
634 | |
635 | static const true_false_string tcp_option_user_to_granularity = { |
636 | "Minutes", "Seconds" |
637 | }; |
638 | |
639 | static const value_string tcp_option_kind_vs[] = { |
640 | { TCPOPT_EOL0, "End of Option List" }, |
641 | { TCPOPT_NOP1, "No-Operation" }, |
642 | { TCPOPT_MSS2, "Maximum Segment Size" }, |
643 | { TCPOPT_WINDOW3, "Window Scale" }, |
644 | { TCPOPT_SACK_PERM4, "SACK Permitted" }, |
645 | { TCPOPT_SACK5, "SACK" }, |
646 | { TCPOPT_ECHO6, "Echo" }, |
647 | { TCPOPT_ECHOREPLY7, "Echo Reply" }, |
648 | { TCPOPT_TIMESTAMP8, "Time Stamp Option" }, |
649 | { 9, "Partial Order Connection Permitted" }, |
650 | { 10, "Partial Order Service Profile" }, |
651 | { TCPOPT_CC11, "CC" }, |
652 | { TCPOPT_CCNEW12, "CC.NEW" }, |
653 | { TCPOPT_CCECHO13, "CC.ECHO" }, |
654 | { 14, "TCP Alternate Checksum Request" }, |
655 | { 15, "TCP Alternate Checksum Data" }, |
656 | { 16, "Skeeter" }, |
657 | { 17, "Bubba" }, |
658 | { 18, "Trailer Checksum Option" }, |
659 | { TCPOPT_MD519, "MD5 Signature Option" }, |
660 | { TCPOPT_SCPS20, "SCPS Capabilities" }, |
661 | { TCPOPT_SNACK21, "Selective Negative Acknowledgements" }, |
662 | { TCPOPT_RECBOUND22, "Record Boundaries" }, |
663 | { TCPOPT_CORREXP23, "Corruption experienced" }, |
664 | { 24, "SNAP" }, |
665 | { 25, "Unassigned" }, |
666 | { 26, "TCP Compression Filter" }, |
667 | { TCPOPT_QS27, "Quick-Start Response" }, |
668 | { TCPOPT_USER_TO28, "User Timeout Option" }, |
669 | { TCPOPT_AO29, "The TCP Authentication Option" }, |
670 | { TCPOPT_MPTCP30, "Multipath TCP" }, |
671 | { TCPOPT_TFO34, "TCP Fast Open Cookie" }, |
672 | { TCPOPT_RVBD_PROBE76, "Riverbed Probe" }, |
673 | { TCPOPT_RVBD_TRPY78, "Riverbed Transparency" }, |
674 | { TCPOPT_ACC_ECN_00xac, "Accurate ECN Order 0" }, |
675 | { TCPOPT_ACC_ECN_10xae, "Accurate ECN Order 1" }, |
676 | { TCPOPT_EXP_FD0xfd, "RFC3692-style Experiment 1" }, |
677 | { TCPOPT_EXP_FE0xfe, "RFC3692-style Experiment 2" }, |
678 | { 0, NULL((void*)0) } |
679 | }; |
680 | static value_string_ext tcp_option_kind_vs_ext = VALUE_STRING_EXT_INIT(tcp_option_kind_vs){ _try_val_to_str_ext_init, 0, (sizeof (tcp_option_kind_vs) / sizeof ((tcp_option_kind_vs)[0]))-1, tcp_option_kind_vs, "tcp_option_kind_vs" }; |
681 | |
682 | static const value_string tcp_exid_vs[] = { |
683 | { TCPEXID_TARR0x00ac, "TCP ACK Rate Request" }, |
684 | { TCPEXID_HOST_ID0x0348, "Host ID" }, |
685 | { TCPEXID_ASC0x0a0d, "Autonomous System Compensation" }, |
686 | { TCPEXID_CAPABILITY0x0ca0, "Capability Option" }, |
687 | { TCPEXID_EDO0x0ed0, "Extended Data Offset" }, |
688 | { TCPEXID_ENO0x454e, "Encryption Negotiation" }, |
689 | { TCPEXID_SNO0x5323, "Service Number" }, |
690 | { TCPEXID_TS_INTERVAL0x75ec, "Timestamp Interval" }, |
691 | { TCPEXID_ACC_ECN_00xacc0, "Accurate ECN - Order 0" }, |
692 | { TCPEXID_ACC_ECN_10xacc1, "Accurate ECN - Order 1" }, |
693 | { TCPEXID_ACC_ECN0xacce, "Accurate ECN" }, |
694 | { TCPEXID_SMC_R0xe2d4, "Shared Memory communications over RMDA protocol" }, |
695 | { TCPEXID_FO0xf989, "Fast Open" }, |
696 | { TCPEXID_LOW_LATENCY0xf990, "Low Latency" }, |
697 | { 0, NULL((void*)0) } |
698 | }; |
699 | |
700 | /* not all of the hf_fields below make sense for TCP but we have to provide |
701 | them anyways to comply with the API (which was aimed for IP fragment |
702 | reassembly) */ |
703 | static const fragment_items tcp_segment_items = { |
704 | &ett_tcp_segment, |
705 | &ett_tcp_segments, |
706 | &hf_tcp_segments, |
707 | &hf_tcp_segment, |
708 | &hf_tcp_segment_overlap, |
709 | &hf_tcp_segment_overlap_conflict, |
710 | &hf_tcp_segment_multiple_tails, |
711 | &hf_tcp_segment_too_long_fragment, |
712 | &hf_tcp_segment_error, |
713 | &hf_tcp_segment_count, |
714 | &hf_tcp_reassembled_in, |
715 | &hf_tcp_reassembled_length, |
716 | &hf_tcp_reassembled_data, |
717 | "Segments" |
718 | }; |
719 | |
720 | |
721 | static const value_string mptcp_subtype_vs[] = { |
722 | { TCPOPT_MPTCP_MP_CAPABLE0x0, "Multipath Capable" }, |
723 | { TCPOPT_MPTCP_MP_JOIN0x1, "Join Connection" }, |
724 | { TCPOPT_MPTCP_DSS0x2, "Data Sequence Signal" }, |
725 | { TCPOPT_MPTCP_ADD_ADDR0x3, "Add Address"}, |
726 | { TCPOPT_MPTCP_REMOVE_ADDR0x4, "Remove Address" }, |
727 | { TCPOPT_MPTCP_MP_PRIO0x5, "Change Subflow Priority" }, |
728 | { TCPOPT_MPTCP_MP_FAIL0x6, "TCP Fallback" }, |
729 | { TCPOPT_MPTCP_MP_FASTCLOSE0x7, "Fast Close" }, |
730 | { TCPOPT_MPTCP_MP_TCPRST0x8, "TCP Reset" }, |
731 | { 0, NULL((void*)0) } |
732 | }; |
733 | |
734 | static dissector_table_t subdissector_table; |
735 | static dissector_table_t tcp_option_table; |
736 | static heur_dissector_list_t heur_subdissector_list; |
737 | static dissector_handle_t data_handle; |
738 | static dissector_handle_t tcp_handle; |
739 | static dissector_handle_t sport_handle; |
740 | static dissector_handle_t tcp_opt_unknown_handle; |
741 | static capture_dissector_handle_t tcp_cap_handle; |
742 | |
743 | static guint32 tcp_stream_count; |
744 | static guint32 mptcp_stream_count; |
745 | |
746 | |
747 | |
748 | /* |
749 | * Maps an MPTCP token to a mptcp_analysis structure |
750 | * Collisions are not handled |
751 | */ |
752 | static wmem_tree_t *mptcp_tokens; |
753 | |
754 | static int * const tcp_option_mptcp_capable_v0_flags[] = { |
755 | &hf_tcp_option_mptcp_checksum_flag, |
756 | &hf_tcp_option_mptcp_B_flag, |
757 | &hf_tcp_option_mptcp_H_v0_flag, |
758 | &hf_tcp_option_mptcp_reserved_v0_flag, |
759 | NULL((void*)0) |
760 | }; |
761 | |
762 | static int * const tcp_option_mptcp_capable_v1_flags[] = { |
763 | &hf_tcp_option_mptcp_checksum_flag, |
764 | &hf_tcp_option_mptcp_B_flag, |
765 | &hf_tcp_option_mptcp_C_flag, |
766 | &hf_tcp_option_mptcp_H_v1_flag, |
767 | &hf_tcp_option_mptcp_reserved_v1_flag, |
768 | NULL((void*)0) |
769 | }; |
770 | |
771 | static int * const tcp_option_mptcp_join_flags[] = { |
772 | &hf_tcp_option_mptcp_backup_flag, |
773 | NULL((void*)0) |
774 | }; |
775 | |
776 | static int * const tcp_option_mptcp_dss_flags[] = { |
777 | &hf_tcp_option_mptcp_F_flag, |
778 | &hf_tcp_option_mptcp_m_flag, |
779 | &hf_tcp_option_mptcp_M_flag, |
780 | &hf_tcp_option_mptcp_a_flag, |
781 | &hf_tcp_option_mptcp_A_flag, |
782 | NULL((void*)0) |
783 | }; |
784 | |
785 | static int * const tcp_option_mptcp_tcprst_flags[] = { |
786 | &hf_tcp_option_mptcp_U_flag, |
787 | &hf_tcp_option_mptcp_V_flag, |
788 | &hf_tcp_option_mptcp_W_flag, |
789 | &hf_tcp_option_mptcp_T_flag, |
790 | NULL((void*)0) |
791 | }; |
792 | |
793 | static const unit_name_string units_64bit_version = { " (64bits version)", NULL((void*)0) }; |
794 | |
795 | static guint8 |
796 | tcp_get_ace(const struct tcpheader *tcph) |
797 | { |
798 | guint8 ace; |
799 | |
800 | ace = 0; |
801 | if (tcph->th_flags & TH_AE0x0100) { |
802 | ace += 4; |
803 | } |
804 | if (tcph->th_flags & TH_CWR0x0080) { |
805 | ace += 2; |
806 | } |
807 | if (tcph->th_flags & TH_ECE0x0040) { |
808 | ace += 1; |
809 | } |
810 | return ace; |
811 | } |
812 | |
813 | static char * |
814 | tcp_flags_to_str(wmem_allocator_t *scope, const struct tcpheader *tcph) |
815 | { |
816 | static const char flags[][4] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECE", "CWR", "AE" }; |
817 | static const char digit[][2] = { "0", "1", "2", "3", "4", "5", "6", "7" }; |
818 | const int maxlength = 64; /* upper bounds, max 53B: 8 * 3 + 2 + strlen("Reserved") + 9 * 2 + 1 */ |
819 | |
820 | char *pbuf; |
821 | char *buf; |
822 | guint8 ace; |
823 | int i; |
824 | |
825 | buf = pbuf = (char *) wmem_alloc(scope, maxlength); |
826 | *pbuf = '\0'; |
827 | |
828 | for (i = 0; i < (tcph->th_use_ace ? 6 : 9); i++) { |
829 | if (tcph->th_flags & (1 << i)) { |
830 | if (buf[0]) |
831 | pbuf = g_stpcpy(pbuf, ", "); |
832 | pbuf = g_stpcpy(pbuf, flags[i]); |
833 | } |
834 | } |
835 | if (tcph->th_use_ace) { |
836 | ace = tcp_get_ace(tcph); |
837 | pbuf = g_stpcpy(pbuf, ", ACE="); |
838 | pbuf = g_stpcpy(pbuf, digit[ace]); |
839 | } |
840 | |
841 | if (tcph->th_flags & TH_RES0x0E00) { |
842 | if (buf[0]) |
843 | pbuf = g_stpcpy(pbuf, ", "); |
844 | g_stpcpy(pbuf, "Reserved"); |
845 | } |
846 | |
847 | if (buf[0] == '\0') |
848 | g_stpcpy(pbuf, "<None>"); |
849 | |
850 | return buf; |
851 | } |
852 | |
853 | static char * |
854 | tcp_flags_to_str_first_letter(wmem_allocator_t *scope, const struct tcpheader *tcph) |
855 | { |
856 | wmem_strbuf_t *buf = wmem_strbuf_new(scope, ""); |
857 | unsigned i; |
858 | const unsigned flags_count = 12; |
859 | const char first_letters[] = "RRRACEUAPRSF"; |
860 | const char digits[] = "01234567"; |
861 | |
862 | /* upper three bytes are marked as reserved ('R'). */ |
863 | for (i = 0; i < flags_count; i++) { |
864 | if (tcph->th_use_ace && 3 <= i && i <= 5) { |
865 | if (i == 4) { |
866 | wmem_strbuf_append_c(buf, digits[tcp_get_ace(tcph)]); |
867 | } else { |
868 | wmem_strbuf_append_c(buf, '-'); |
869 | } |
870 | } else { |
871 | if (((tcph->th_flags >> (flags_count - 1 - i)) & 1)) { |
872 | wmem_strbuf_append_c(buf, first_letters[i]); |
873 | } else { |
874 | wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7"); |
875 | } |
876 | } |
877 | } |
878 | |
879 | return wmem_strbuf_finalize(buf); |
880 | } |
881 | |
882 | /* |
883 | * Print the first letter of each flag set, or the dot character otherwise |
884 | */ |
885 | static char * |
886 | completeness_flags_to_str_first_letter(wmem_allocator_t *scope, guint8 flags) |
887 | { |
888 | wmem_strbuf_t *buf = wmem_strbuf_new(scope, ""); |
889 | |
890 | if( flags & TCP_COMPLETENESS_RST0x20 ) |
891 | wmem_strbuf_append(buf, "R"); |
892 | else |
893 | wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7"); |
894 | |
895 | if( flags & TCP_COMPLETENESS_FIN0x10 ) |
896 | wmem_strbuf_append(buf, "F"); |
897 | else |
898 | wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7"); |
899 | |
900 | if( flags & TCP_COMPLETENESS_DATA0x08 ) |
901 | wmem_strbuf_append(buf, "D"); |
902 | else |
903 | wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7"); |
904 | |
905 | if( flags & TCP_COMPLETENESS_ACK0x04 ) |
906 | wmem_strbuf_append(buf, "A"); |
907 | else |
908 | wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7"); |
909 | |
910 | if( flags & TCP_COMPLETENESS_SYNACK0x02 ) |
911 | wmem_strbuf_append(buf, "S"); |
912 | else |
913 | wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7"); |
914 | |
915 | if( flags & TCP_COMPLETENESS_SYNSENT0x01 ) |
916 | wmem_strbuf_append(buf, "S"); |
917 | else |
918 | wmem_strbuf_append(buf, UTF8_MIDDLE_DOT"\xc2\xb7"); |
919 | |
920 | return wmem_strbuf_finalize(buf); |
921 | } |
922 | |
923 | static void |
924 | tcp_src_prompt(packet_info *pinfo, gchar *result) |
925 | { |
926 | guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport , pinfo->curr_layer_num))); |
927 | |
928 | snprintf(result, MAX_DECODE_AS_PROMPT_LEN200, "source (%u%s)", port, UTF8_RIGHTWARDS_ARROW"\xe2\x86\x92"); |
929 | } |
930 | |
931 | static gpointer |
932 | tcp_src_value(packet_info *pinfo) |
933 | { |
934 | return p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num); |
935 | } |
936 | |
937 | static void |
938 | tcp_dst_prompt(packet_info *pinfo, gchar *result) |
939 | { |
940 | guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport , pinfo->curr_layer_num))); |
941 | |
942 | snprintf(result, MAX_DECODE_AS_PROMPT_LEN200, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW"\xe2\x86\x92", port); |
943 | } |
944 | |
945 | static gpointer |
946 | tcp_dst_value(packet_info *pinfo) |
947 | { |
948 | return p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num); |
949 | } |
950 | |
951 | static void |
952 | tcp_both_prompt(packet_info *pinfo, gchar *result) |
953 | { |
954 | guint32 srcport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, hf_tcp_srcport , pinfo->curr_layer_num))), |
955 | destport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, hf_tcp_dstport , pinfo->curr_layer_num))); |
956 | snprintf(result, MAX_DECODE_AS_PROMPT_LEN200, "both (%u%s%u)", srcport, UTF8_LEFT_RIGHT_ARROW"\xe2\x86\x94", destport); |
957 | } |
958 | |
959 | static const char* tcp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter) |
960 | { |
961 | |
962 | if (filter == CONV_FT_SRC_PORT) |
963 | return "tcp.srcport"; |
964 | |
965 | if (filter == CONV_FT_DST_PORT) |
966 | return "tcp.dstport"; |
967 | |
968 | if (filter == CONV_FT_ANY_PORT) |
969 | return "tcp.port"; |
970 | |
971 | if(!conv) { |
972 | return CONV_FILTER_INVALID"INVALID"; |
973 | } |
974 | |
975 | if (filter == CONV_FT_SRC_ADDRESS) { |
976 | if (conv->src_address.type == AT_IPv4) |
977 | return "ip.src"; |
978 | if (conv->src_address.type == AT_IPv6) |
979 | return "ipv6.src"; |
980 | } |
981 | |
982 | if (filter == CONV_FT_DST_ADDRESS) { |
983 | if (conv->dst_address.type == AT_IPv4) |
984 | return "ip.dst"; |
985 | if (conv->dst_address.type == AT_IPv6) |
986 | return "ipv6.dst"; |
987 | } |
988 | |
989 | if (filter == CONV_FT_ANY_ADDRESS) { |
990 | if (conv->src_address.type == AT_IPv4) |
991 | return "ip.addr"; |
992 | if (conv->src_address.type == AT_IPv6) |
993 | return "ipv6.addr"; |
994 | } |
995 | |
996 | return CONV_FILTER_INVALID"INVALID"; |
997 | } |
998 | |
999 | static ct_dissector_info_t tcp_ct_dissector_info = {&tcp_conv_get_filter_type}; |
1000 | |
1001 | /* |
1002 | * callback function for conversation stats |
1003 | */ |
1004 | static int tcp_conv_cb_update(conversation_t *conv) |
1005 | { |
1006 | struct tcp_analysis *tcpd; |
1007 | tcpd=get_tcp_conversation_data_idempotent(conv); |
1008 | if(tcpd) |
1009 | return tcpd->flow1.flow_count + tcpd->flow2.flow_count; |
1010 | else |
1011 | return 0; |
1012 | } |
1013 | |
1014 | static tap_packet_status |
1015 | tcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *vip, tap_flags_t flags) |
1016 | { |
1017 | conv_hash_t *hash = (conv_hash_t*) pct; |
1018 | hash->flags = flags; |
1019 | |
1020 | const struct tcpheader *tcphdr=(const struct tcpheader *)vip; |
1021 | |
1022 | 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, |
1023 | &pinfo->rel_ts, &pinfo->abs_ts, &tcp_ct_dissector_info, CONVERSATION_TCP, (guint32)pinfo->num, tcp_conv_cb_update); |
1024 | |
1025 | |
1026 | return TAP_PACKET_REDRAW; |
1027 | } |
1028 | |
1029 | static tap_packet_status |
1030 | mptcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *vip, tap_flags_t flags) |
1031 | { |
1032 | conv_hash_t *hash = (conv_hash_t*) pct; |
1033 | hash->flags = flags; |
1034 | |
1035 | const struct tcp_analysis *tcpd=(const struct tcp_analysis *)vip; |
1036 | const mptcp_meta_flow_t *meta=(const mptcp_meta_flow_t *)tcpd->fwd->mptcp_subflow->meta; |
1037 | |
1038 | add_conversation_table_data_with_conv_id(hash, &meta->ip_src, &meta->ip_dst, |
1039 | meta->sport, meta->dport, (conv_id_t) tcpd->mptcp_analysis->stream, 1, pinfo->fd->pkt_len, |
1040 | &pinfo->rel_ts, &pinfo->abs_ts, &tcp_ct_dissector_info, CONVERSATION_TCP); |
1041 | |
1042 | return TAP_PACKET_REDRAW; |
1043 | } |
1044 | |
1045 | static const char* tcp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter) |
1046 | { |
1047 | if (filter == CONV_FT_SRC_PORT) |
1048 | return "tcp.srcport"; |
1049 | |
1050 | if (filter == CONV_FT_DST_PORT) |
1051 | return "tcp.dstport"; |
1052 | |
1053 | if (filter == CONV_FT_ANY_PORT) |
1054 | return "tcp.port"; |
1055 | |
1056 | if(!endpoint) { |
1057 | return CONV_FILTER_INVALID"INVALID"; |
1058 | } |
1059 | |
1060 | if (filter == CONV_FT_SRC_ADDRESS) { |
1061 | if (endpoint->myaddress.type == AT_IPv4) |
1062 | return "ip.src"; |
1063 | if (endpoint->myaddress.type == AT_IPv6) |
1064 | return "ipv6.src"; |
1065 | } |
1066 | |
1067 | if (filter == CONV_FT_DST_ADDRESS) { |
1068 | if (endpoint->myaddress.type == AT_IPv4) |
1069 | return "ip.dst"; |
1070 | if (endpoint->myaddress.type == AT_IPv6) |
1071 | return "ipv6.dst"; |
1072 | } |
1073 | |
1074 | if (filter == CONV_FT_ANY_ADDRESS) { |
1075 | if (endpoint->myaddress.type == AT_IPv4) |
1076 | return "ip.addr"; |
1077 | if (endpoint->myaddress.type == AT_IPv6) |
1078 | return "ipv6.addr"; |
1079 | } |
1080 | |
1081 | return CONV_FILTER_INVALID"INVALID"; |
1082 | } |
1083 | |
1084 | static et_dissector_info_t tcp_endpoint_dissector_info = {&tcp_endpoint_get_filter_type}; |
1085 | |
1086 | static tap_packet_status |
1087 | tcpip_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *vip, tap_flags_t flags) |
1088 | { |
1089 | conv_hash_t *hash = (conv_hash_t*) pit; |
1090 | hash->flags = flags; |
1091 | |
1092 | const struct tcpheader *tcphdr=(const struct tcpheader *)vip; |
1093 | |
1094 | /* Take two "add" passes per packet, adding for each direction, ensures that all |
1095 | packets are counted properly (even if address is sending to itself) |
1096 | XXX - this could probably be done more efficiently inside endpoint_table */ |
1097 | add_endpoint_table_data(hash, &tcphdr->ip_src, tcphdr->th_sport, TRUE(!(0)), 1, pinfo->fd->pkt_len, &tcp_endpoint_dissector_info, ENDPOINT_TCPCONVERSATION_TCP); |
1098 | add_endpoint_table_data(hash, &tcphdr->ip_dst, tcphdr->th_dport, FALSE(0), 1, pinfo->fd->pkt_len, &tcp_endpoint_dissector_info, ENDPOINT_TCPCONVERSATION_TCP); |
1099 | |
1100 | return TAP_PACKET_REDRAW; |
1101 | } |
1102 | |
1103 | static gboolean |
1104 | tcp_filter_valid(packet_info *pinfo, void *user_data _U___attribute__((unused))) |
1105 | { |
1106 | return proto_is_frame_protocol(pinfo->layers, "tcp"); |
1107 | } |
1108 | |
1109 | static gchar* |
1110 | tcp_build_filter_by_id(packet_info *pinfo, void *user_data _U___attribute__((unused))) |
1111 | { |
1112 | return ws_strdup_printf("tcp.stream eq %d", pinfo->stream_id)wmem_strdup_printf(((void*)0), "tcp.stream eq %d", pinfo-> stream_id); |
1113 | } |
1114 | |
1115 | |
1116 | /****************************************************************************/ |
1117 | /* whenever a TCP packet is seen by the tap listener */ |
1118 | /* Add a new tcp frame into the graph */ |
1119 | static tap_packet_status |
1120 | tcp_seq_analysis_packet( void *ptr, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *tcp_info, tap_flags_t tapflags _U___attribute__((unused))) |
1121 | { |
1122 | seq_analysis_info_t *sainfo = (seq_analysis_info_t *) ptr; |
1123 | const struct tcpheader *tcph = (const struct tcpheader *)tcp_info; |
1124 | char* flags; |
1125 | seq_analysis_item_t *sai = sequence_analysis_create_sai_with_addresses(pinfo, sainfo); |
1126 | |
1127 | if (!sai) |
1128 | return TAP_PACKET_DONT_REDRAW; |
1129 | |
1130 | sai->frame_number = pinfo->num; |
1131 | |
1132 | sai->port_src=pinfo->srcport; |
1133 | sai->port_dst=pinfo->destport; |
1134 | |
1135 | flags = tcp_flags_to_str(NULL((void*)0), tcph); |
1136 | |
1137 | if ((tcph->th_have_seglen)&&(tcph->th_seglen!=0)){ |
1138 | sai->frame_label = ws_strdup_printf("%s - Len: %u",flags, tcph->th_seglen)wmem_strdup_printf(((void*)0), "%s - Len: %u",flags, tcph-> th_seglen); |
1139 | } |
1140 | else{ |
1141 | sai->frame_label = g_strdup(flags); |
1142 | } |
1143 | |
1144 | wmem_free(NULL((void*)0), flags); |
1145 | |
1146 | if (tcph->th_flags & TH_ACK0x0010) |
1147 | sai->comment = ws_strdup_printf("Seq = %u Ack = %u",tcph->th_seq, tcph->th_ack)wmem_strdup_printf(((void*)0), "Seq = %u Ack = %u",tcph->th_seq , tcph->th_ack); |
1148 | else |
1149 | sai->comment = ws_strdup_printf("Seq = %u",tcph->th_seq)wmem_strdup_printf(((void*)0), "Seq = %u",tcph->th_seq); |
1150 | |
1151 | sai->line_style = 1; |
1152 | sai->conv_num = (guint16) tcph->th_stream; |
1153 | sai->display = TRUE(!(0)); |
1154 | |
1155 | g_queue_push_tail(sainfo->items, sai); |
1156 | |
1157 | return TAP_PACKET_REDRAW; |
1158 | } |
1159 | |
1160 | |
1161 | gchar *tcp_follow_conv_filter(epan_dissect_t *edt _U___attribute__((unused)), packet_info *pinfo, guint *stream, guint *sub_stream _U___attribute__((unused))) |
1162 | { |
1163 | conversation_t *conv; |
1164 | struct tcp_analysis *tcpd; |
1165 | |
1166 | /* XXX: Since TCP doesn't use the endpoint API, we can only look |
1167 | * up using the current pinfo addresses and ports. We don't want |
1168 | * to create a new conversation or new TCP stream. |
1169 | * Eventually the endpoint API should support storing multiple |
1170 | * endpoints and TCP should be changed to use the endpoint API. |
1171 | */ |
1172 | conv = find_conversation_strat(pinfo); |
1173 | if (((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) || |
1174 | (pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6)) |
1175 | && (pinfo->ptype == PT_TCP) && |
1176 | conv != NULL((void*)0)) |
1177 | { |
1178 | /* TCP over IPv4/6 */ |
1179 | tcpd=get_tcp_conversation_data(conv, pinfo); |
1180 | if (tcpd == NULL((void*)0)) |
1181 | return NULL((void*)0); |
1182 | |
1183 | *stream = tcpd->stream; |
1184 | return ws_strdup_printf("tcp.stream eq %u", tcpd->stream)wmem_strdup_printf(((void*)0), "tcp.stream eq %u", tcpd->stream ); |
1185 | } |
1186 | |
1187 | return NULL((void*)0); |
1188 | } |
1189 | |
1190 | gchar *tcp_follow_index_filter(guint stream, guint sub_stream _U___attribute__((unused))) |
1191 | { |
1192 | return ws_strdup_printf("tcp.stream eq %u", stream)wmem_strdup_printf(((void*)0), "tcp.stream eq %u", stream); |
1193 | } |
1194 | |
1195 | gchar *tcp_follow_address_filter(address *src_addr, address *dst_addr, int src_port, int dst_port) |
1196 | { |
1197 | const gchar *ip_version = src_addr->type == AT_IPv6 ? "v6" : ""; |
1198 | gchar src_addr_str[WS_INET6_ADDRSTRLEN46]; |
1199 | gchar dst_addr_str[WS_INET6_ADDRSTRLEN46]; |
1200 | |
1201 | address_to_str_buf(src_addr, src_addr_str, sizeof(src_addr_str)); |
1202 | address_to_str_buf(dst_addr, dst_addr_str, sizeof(dst_addr_str)); |
1203 | |
1204 | return ws_strdup_printf("((ip%s.src eq %s and tcp.srcport eq %d) and "wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port) |
1205 | "(ip%s.dst eq %s and tcp.dstport eq %d))"wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port) |
1206 | " or "wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port) |
1207 | "((ip%s.src eq %s and tcp.srcport eq %d) and "wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port) |
1208 | "(ip%s.dst eq %s and tcp.dstport eq %d))",wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port) |
1209 | ip_version, src_addr_str, src_port,wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port) |
1210 | ip_version, dst_addr_str, dst_port,wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port) |
1211 | ip_version, dst_addr_str, dst_port,wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port) |
1212 | ip_version, src_addr_str, src_port)wmem_strdup_printf(((void*)0), "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))" " or " "((ip%s.src eq %s and tcp.srcport eq %d) and " "(ip%s.dst eq %s and tcp.dstport eq %d))", ip_version, src_addr_str , src_port, ip_version, dst_addr_str, dst_port, ip_version, dst_addr_str , dst_port, ip_version, src_addr_str, src_port); |
1213 | |
1214 | } |
1215 | |
1216 | typedef struct tcp_follow_tap_data |
1217 | { |
1218 | tvbuff_t *tvb; |
1219 | struct tcpheader* tcph; |
1220 | struct tcp_analysis *tcpd; |
1221 | |
1222 | } tcp_follow_tap_data_t; |
1223 | |
1224 | /* |
1225 | * Tries to apply segments from fragments list to the reconstructed payload. |
1226 | * Fragments that can be appended to the end of the payload will be applied (and |
1227 | * removed from the list). Fragments that should have been received (according |
1228 | * to the ack number) will also be appended to the payload (preceded by some |
1229 | * dummy data to mark packet loss if any). |
1230 | * |
1231 | * Returns TRUE if one fragment has been applied or FALSE if no more fragments |
1232 | * can be added to the payload (there might still be unacked fragments with |
1233 | * missing segments before them). |
1234 | */ |
1235 | static gboolean |
1236 | check_follow_fragments(follow_info_t *follow_info, gboolean is_server, guint32 acknowledged, guint32 packet_num, gboolean use_ack) |
1237 | { |
1238 | GList *fragment_entry; |
1239 | follow_record_t *fragment, *follow_record; |
1240 | guint32 lowest_seq = 0; |
1241 | gchar *dummy_str; |
1242 | |
1243 | fragment_entry = g_list_first(follow_info->fragments[is_server]); |
1244 | if (fragment_entry == NULL((void*)0)) |
1245 | return FALSE(0); |
1246 | |
1247 | fragment = (follow_record_t*)fragment_entry->data; |
1248 | lowest_seq = fragment->seq; |
1249 | |
1250 | for (; fragment_entry != NULL((void*)0); fragment_entry = g_list_next(fragment_entry)((fragment_entry) ? (((GList *)(fragment_entry))->next) : ( (void*)0))) |
1251 | { |
1252 | fragment = (follow_record_t*)fragment_entry->data; |
1253 | |
1254 | if( GT_SEQ(lowest_seq, fragment->seq)((gint32)((fragment->seq) - (lowest_seq)) < 0) ) { |
1255 | lowest_seq = fragment->seq; |
1256 | } |
1257 | |
1258 | if( LT_SEQ(fragment->seq, follow_info->seq[is_server])((gint32)((fragment->seq) - (follow_info->seq[is_server ])) < 0) ) { |
1259 | guint32 newseq; |
1260 | /* this sequence number seems dated, but |
1261 | check the end to make sure it has no more |
1262 | info than we have already seen */ |
1263 | newseq = fragment->seq + fragment->data->len; |
1264 | if( GT_SEQ(newseq, follow_info->seq[is_server])((gint32)((follow_info->seq[is_server]) - (newseq)) < 0 ) ) { |
1265 | guint32 new_pos; |
1266 | |
1267 | /* this one has more than we have seen. let's get the |
1268 | payload that we have not seen. This happens when |
1269 | part of this frame has been retransmitted */ |
1270 | |
1271 | new_pos = follow_info->seq[is_server] - fragment->seq; |
1272 | |
1273 | if ( fragment->data->len > new_pos ) { |
1274 | guint32 new_frag_size = fragment->data->len - new_pos; |
1275 | |
1276 | follow_record = g_new0(follow_record_t,1)((follow_record_t *) g_malloc0_n ((1), sizeof (follow_record_t ))); |
1277 | |
1278 | follow_record->is_server = is_server; |
1279 | follow_record->packet_num = fragment->packet_num; |
1280 | follow_record->abs_ts = fragment->abs_ts; |
1281 | follow_record->seq = follow_info->seq[is_server] + new_frag_size; |
1282 | |
1283 | follow_record->data = g_byte_array_append(g_byte_array_new(), |
1284 | fragment->data->data + new_pos, |
1285 | new_frag_size); |
1286 | |
1287 | follow_info->payload = g_list_prepend(follow_info->payload, follow_record); |
1288 | } |
1289 | |
1290 | follow_info->seq[is_server] += (fragment->data->len - new_pos); |
1291 | } |
1292 | |
1293 | /* Remove the fragment from the list as the "new" part of it |
1294 | * has been processed or its data has been seen already in |
1295 | * another packet. */ |
1296 | g_byte_array_free(fragment->data, TRUE(!(0))); |
1297 | g_free(fragment); |
1298 | follow_info->fragments[is_server] = g_list_delete_link(follow_info->fragments[is_server], fragment_entry); |
1299 | return TRUE(!(0)); |
1300 | } |
1301 | |
1302 | if( EQ_SEQ(fragment->seq, follow_info->seq[is_server])(fragment->seq) == (follow_info->seq[is_server]) ) { |
1303 | /* this fragment fits the stream */ |
1304 | if( fragment->data->len > 0 ) { |
1305 | follow_info->payload = g_list_prepend(follow_info->payload, fragment); |
1306 | } |
1307 | |
1308 | follow_info->seq[is_server] += fragment->data->len; |
1309 | follow_info->fragments[is_server] = g_list_delete_link(follow_info->fragments[is_server], fragment_entry); |
1310 | return TRUE(!(0)); |
1311 | } |
1312 | } |
1313 | |
1314 | if( use_ack && GT_SEQ(acknowledged, lowest_seq)((gint32)((lowest_seq) - (acknowledged)) < 0) ) { |
1315 | /* There are frames missing in the capture file that were seen |
1316 | * by the receiving host. Add dummy stream chunk with the data |
1317 | * "[xxx bytes missing in capture file]". |
1318 | */ |
1319 | dummy_str = ws_strdup_printf("[%d bytes missing in capture file]",wmem_strdup_printf(((void*)0), "[%d bytes missing in capture file]" , (int)(lowest_seq - follow_info->seq[is_server])) |
1320 | (int)(lowest_seq - follow_info->seq[is_server]) )wmem_strdup_printf(((void*)0), "[%d bytes missing in capture file]" , (int)(lowest_seq - follow_info->seq[is_server])); |
1321 | // XXX the dummy replacement could be larger than the actual missing bytes. |
1322 | |
1323 | follow_record = g_new0(follow_record_t,1)((follow_record_t *) g_malloc0_n ((1), sizeof (follow_record_t ))); |
1324 | |
1325 | follow_record->data = g_byte_array_append(g_byte_array_new(), |
1326 | (guchar*)dummy_str, |
1327 | (guint)strlen(dummy_str)+1); |
1328 | g_free(dummy_str); |
1329 | follow_record->is_server = is_server; |
1330 | follow_record->packet_num = packet_num; |
1331 | follow_record->seq = lowest_seq; |
1332 | |
1333 | follow_info->seq[is_server] = lowest_seq; |
1334 | follow_info->payload = g_list_prepend(follow_info->payload, follow_record); |
1335 | return TRUE(!(0)); |
1336 | } |
1337 | |
1338 | return FALSE(0); |
1339 | } |
1340 | |
1341 | static tap_packet_status |
1342 | follow_tcp_tap_listener(void *tapdata, packet_info *pinfo, |
1343 | epan_dissect_t *edt _U___attribute__((unused)), const void *data, tap_flags_t flags _U___attribute__((unused))) |
1344 | { |
1345 | follow_record_t *follow_record; |
1346 | follow_info_t *follow_info = (follow_info_t *)tapdata; |
1347 | const tcp_follow_tap_data_t *follow_data = (const tcp_follow_tap_data_t *)data; |
1348 | gboolean is_server; |
1349 | guint32 sequence = follow_data->tcph->th_seq; |
1350 | guint32 length = follow_data->tcph->th_have_seglen |
1351 | ? follow_data->tcph->th_seglen |
1352 | : 0; |
1353 | guint32 data_offset = 0; |
1354 | guint32 data_length = tvb_captured_length(follow_data->tvb); |
1355 | |
1356 | if (follow_data->tcph->th_flags & TH_SYN0x0002) { |
1357 | sequence++; |
1358 | } |
1359 | |
1360 | if (follow_info->client_port == 0) { |
1361 | follow_info->client_port = pinfo->srcport; |
1362 | copy_address(&follow_info->client_ip, &pinfo->src); |
1363 | follow_info->server_port = pinfo->destport; |
1364 | copy_address(&follow_info->server_ip, &pinfo->dst); |
1365 | } |
1366 | |
1367 | is_server = !(addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport); |
1368 | |
1369 | /* Check whether this frame ACKs fragments in flow from the other direction. |
1370 | * This happens when frames are not in the capture file, but were actually |
1371 | * seen by the receiving host (Fixes bug 592). |
1372 | */ |
1373 | if (follow_info->fragments[!is_server] != NULL((void*)0)) { |
1374 | while (check_follow_fragments(follow_info, !is_server, follow_data->tcph->th_ack, pinfo->fd->num, TRUE(!(0)))); |
1375 | } |
1376 | |
1377 | /* |
1378 | * If this is the first segment of this stream, initialize the next expected |
1379 | * sequence number. If there is any data, it will be added below. |
1380 | */ |
1381 | if (follow_info->bytes_written[is_server] == 0 && follow_info->seq[is_server] == 0) { |
1382 | follow_info->seq[is_server] = sequence; |
1383 | } |
1384 | |
1385 | /* We have already seen this src (and received some segments), let's figure |
1386 | * out whether this segment extends the stream or overlaps a previous gap. */ |
1387 | if (LT_SEQ(sequence, follow_info->seq[is_server])((gint32)((sequence) - (follow_info->seq[is_server])) < 0)) { |
1388 | /* This sequence number seems dated, but check the end in case it was a |
1389 | * retransmission with more data. */ |
1390 | guint32 nextseq = sequence + length; |
1391 | if (GT_SEQ(nextseq, follow_info->seq[is_server])((gint32)((follow_info->seq[is_server]) - (nextseq)) < 0 )) { |
1392 | /* The begin of the segment was already seen, try to add the |
1393 | * remaining data that we have not seen to the payload. */ |
1394 | data_offset = follow_info->seq[is_server] - sequence; |
1395 | if (data_length <= data_offset) { |
1396 | data_length = 0; |
1397 | } else { |
1398 | data_length -= data_offset; |
1399 | } |
1400 | |
1401 | sequence = follow_info->seq[is_server]; |
1402 | length = nextseq - follow_info->seq[is_server]; |
1403 | } |
1404 | } |
1405 | /* |
1406 | * Ignore segments that have no new data (either because it was empty, or |
1407 | * because it was fully overlapping with previously received data). |
1408 | */ |
1409 | if (data_length == 0 || LT_SEQ(sequence, follow_info->seq[is_server])((gint32)((sequence) - (follow_info->seq[is_server])) < 0)) { |
1410 | return TAP_PACKET_DONT_REDRAW; |
1411 | } |
1412 | |
1413 | follow_record = g_new0(follow_record_t, 1)((follow_record_t *) g_malloc0_n ((1), sizeof (follow_record_t ))); |
1414 | follow_record->is_server = is_server; |
1415 | follow_record->packet_num = pinfo->fd->num; |
1416 | follow_record->abs_ts = pinfo->fd->abs_ts; |
1417 | follow_record->seq = sequence; /* start of fragment, used by check_follow_fragments. */ |
1418 | follow_record->data = g_byte_array_append(g_byte_array_new(), |
1419 | tvb_get_ptr(follow_data->tvb, data_offset, data_length), |
1420 | data_length); |
1421 | |
1422 | if (EQ_SEQ(sequence, follow_info->seq[is_server])(sequence) == (follow_info->seq[is_server])) { |
1423 | /* The segment overlaps or extends the previous end of stream. */ |
1424 | follow_info->seq[is_server] += length; |
1425 | follow_info->bytes_written[is_server] += follow_record->data->len; |
1426 | follow_info->payload = g_list_prepend(follow_info->payload, follow_record); |
1427 | |
1428 | /* done with the packet, see if it caused a fragment to fit */ |
1429 | while(check_follow_fragments(follow_info, is_server, 0, pinfo->fd->num, FALSE(0))); |
1430 | } else { |
1431 | /* Out of order packet (more preceding segments are expected). */ |
1432 | follow_info->fragments[is_server] = g_list_append(follow_info->fragments[is_server], follow_record); |
1433 | } |
1434 | return TAP_PACKET_DONT_REDRAW; |
1435 | } |
1436 | |
1437 | #define EXP_PDU_TCP_INFO_DATA_LEN19 19 |
1438 | #define EXP_PDU_TCP_INFO_VERSION1 1 |
1439 | |
1440 | static int exp_pdu_tcp_dissector_data_size(packet_info *pinfo _U___attribute__((unused)), void* data _U___attribute__((unused))) |
1441 | { |
1442 | return EXP_PDU_TCP_INFO_DATA_LEN19+4; |
1443 | } |
1444 | |
1445 | static int exp_pdu_tcp_dissector_data_populate_data(packet_info *pinfo _U___attribute__((unused)), void* data, guint8 *tlv_buffer, guint32 buffer_size _U___attribute__((unused))) |
1446 | { |
1447 | struct tcpinfo* dissector_data = (struct tcpinfo*)data; |
1448 | |
1449 | phton16(&tlv_buffer[0], EXP_PDU_TAG_TCP_INFO_DATA34); |
1450 | phton16(&tlv_buffer[2], EXP_PDU_TCP_INFO_DATA_LEN19); /* tag length */ |
1451 | phton16(&tlv_buffer[4], EXP_PDU_TCP_INFO_VERSION1); |
1452 | phton32(&tlv_buffer[6], dissector_data->seq); |
1453 | phton32(&tlv_buffer[10], dissector_data->nxtseq); |
1454 | phton32(&tlv_buffer[14], dissector_data->lastackseq); |
1455 | tlv_buffer[18] = dissector_data->is_reassembled; |
1456 | phton16(&tlv_buffer[19], dissector_data->flags); |
1457 | phton16(&tlv_buffer[21], dissector_data->urgent_pointer); |
1458 | |
1459 | return exp_pdu_tcp_dissector_data_size(pinfo, data); |
1460 | } |
1461 | |
1462 | static tvbuff_t* |
1463 | handle_export_pdu_check_desegmentation(packet_info *pinfo, tvbuff_t *tvb) |
1464 | { |
1465 | /* Check to see if the tvb we're planning on exporting PDUs from was |
1466 | * dissected fully, or whether it requested further desegmentation. |
1467 | * This should only matter on the first pass (so in one-pass tshark.) |
1468 | */ |
1469 | if (pinfo->can_desegment > 0 && pinfo->desegment_len != 0) { |
1470 | /* Desegmentation was requested. How much did we desegment here? |
1471 | * The rest, presumably, will be handled in another frame. |
1472 | */ |
1473 | if (pinfo->desegment_offset == 0) { |
1474 | /* We couldn't, in fact, dissect any of it. */ |
1475 | return NULL((void*)0); |
1476 | } |
1477 | tvb = tvb_new_subset_length(tvb, 0, pinfo->desegment_offset); |
1478 | } |
1479 | return tvb; |
1480 | } |
1481 | |
1482 | static void |
1483 | handle_export_pdu_dissection_table(packet_info *pinfo, tvbuff_t *tvb, guint32 port, struct tcpinfo *tcpinfo) |
1484 | { |
1485 | if (have_tap_listener(exported_pdu_tap)) { |
1486 | tvb = handle_export_pdu_check_desegmentation(pinfo, tvb); |
1487 | if (tvb == NULL((void*)0)) { |
1488 | return; |
1489 | } |
1490 | 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((void*)0)}; |
1491 | exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL((void*)0)}; |
1492 | const exp_pdu_data_item_t *tcp_exp_pdu_items[] = { |
1493 | &exp_pdu_data_src_ip, |
1494 | &exp_pdu_data_dst_ip, |
1495 | &exp_pdu_data_port_type, |
1496 | &exp_pdu_data_src_port, |
1497 | &exp_pdu_data_dst_port, |
1498 | &exp_pdu_data_orig_frame_num, |
1499 | &exp_pdu_data_table_value, |
1500 | &exp_pdu_data_dissector_data, |
1501 | NULL((void*)0) |
1502 | }; |
1503 | |
1504 | exp_pdu_data_t *exp_pdu_data; |
1505 | |
1506 | exp_pdu_data_table_value.data = GUINT_TO_POINTER(port)((gpointer) (gulong) (port)); |
1507 | exp_pdu_data_dissector_data.data = tcpinfo; |
1508 | |
1509 | exp_pdu_data = export_pdu_create_tags(pinfo, "tcp.port", EXP_PDU_TAG_DISSECTOR_TABLE_NAME14, tcp_exp_pdu_items); |
1510 | exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); |
1511 | exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); |
1512 | exp_pdu_data->pdu_tvb = tvb; |
1513 | |
1514 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
1515 | } |
1516 | } |
1517 | |
1518 | static void |
1519 | handle_export_pdu_heuristic(packet_info *pinfo, tvbuff_t *tvb, heur_dtbl_entry_t *hdtbl_entry, struct tcpinfo *tcpinfo) |
1520 | { |
1521 | exp_pdu_data_t *exp_pdu_data = NULL((void*)0); |
1522 | |
1523 | if (have_tap_listener(exported_pdu_tap)) { |
1524 | tvb = handle_export_pdu_check_desegmentation(pinfo, tvb); |
1525 | if (tvb == NULL((void*)0)) { |
1526 | return; |
1527 | } |
1528 | if ((!hdtbl_entry->enabled) || |
1529 | (hdtbl_entry->protocol != NULL((void*)0) && !proto_is_protocol_enabled(hdtbl_entry->protocol))) { |
1530 | exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME12); |
1531 | } else if (hdtbl_entry->protocol != NULL((void*)0)) { |
1532 | exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL((void*)0)}; |
1533 | const exp_pdu_data_item_t *tcp_exp_pdu_items[] = { |
1534 | &exp_pdu_data_src_ip, |
1535 | &exp_pdu_data_dst_ip, |
1536 | &exp_pdu_data_port_type, |
1537 | &exp_pdu_data_src_port, |
1538 | &exp_pdu_data_dst_port, |
1539 | &exp_pdu_data_orig_frame_num, |
1540 | &exp_pdu_data_dissector_data, |
1541 | NULL((void*)0) |
1542 | }; |
1543 | |
1544 | exp_pdu_data_dissector_data.data = tcpinfo; |
1545 | |
1546 | exp_pdu_data = export_pdu_create_tags(pinfo, hdtbl_entry->short_name, EXP_PDU_TAG_HEUR_DISSECTOR_NAME13, tcp_exp_pdu_items); |
1547 | } |
1548 | |
1549 | if (exp_pdu_data != NULL((void*)0)) { |
1550 | exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); |
1551 | exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); |
1552 | exp_pdu_data->pdu_tvb = tvb; |
1553 | |
1554 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
1555 | } |
1556 | } |
1557 | } |
1558 | |
1559 | static void |
1560 | handle_export_pdu_conversation(packet_info *pinfo, tvbuff_t *tvb, int src_port, int dst_port, struct tcpinfo *tcpinfo) |
1561 | { |
1562 | if (have_tap_listener(exported_pdu_tap)) { |
1563 | tvb = handle_export_pdu_check_desegmentation(pinfo, tvb); |
1564 | if (tvb == NULL((void*)0)) { |
1565 | return; |
1566 | } |
1567 | conversation_t *conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, src_port, dst_port, 0); |
1568 | if (conversation != NULL((void*)0)) |
1569 | { |
1570 | dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num); |
1571 | if (handle != NULL((void*)0)) |
1572 | { |
1573 | exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL((void*)0)}; |
1574 | const exp_pdu_data_item_t *tcp_exp_pdu_items[] = { |
1575 | &exp_pdu_data_src_ip, |
1576 | &exp_pdu_data_dst_ip, |
1577 | &exp_pdu_data_port_type, |
1578 | &exp_pdu_data_src_port, |
1579 | &exp_pdu_data_dst_port, |
1580 | &exp_pdu_data_orig_frame_num, |
1581 | &exp_pdu_data_dissector_data, |
1582 | NULL((void*)0) |
1583 | }; |
1584 | |
1585 | exp_pdu_data_t *exp_pdu_data; |
1586 | |
1587 | exp_pdu_data_dissector_data.data = tcpinfo; |
1588 | |
1589 | exp_pdu_data = export_pdu_create_tags(pinfo, dissector_handle_get_dissector_name(handle), EXP_PDU_TAG_DISSECTOR_NAME12, tcp_exp_pdu_items); |
1590 | exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); |
1591 | exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); |
1592 | exp_pdu_data->pdu_tvb = tvb; |
1593 | |
1594 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
1595 | } |
1596 | } |
1597 | } |
1598 | } |
1599 | |
1600 | /* |
1601 | * display the TCP Conversation Completeness |
1602 | * we of course pay much attention on complete conversations but also incomplete ones which |
1603 | * have a regular start, as in practice we are often looking for such thing |
1604 | */ |
1605 | static void conversation_completeness_fill(gchar *buf, guint32 value) |
1606 | { |
1607 | switch(value) { |
1608 | case TCP_COMPLETENESS_SYNSENT0x01: |
1609 | snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete, SYN_SENT (%u)", value); |
1610 | break; |
1611 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1612 | TCP_COMPLETENESS_SYNACK0x02): |
1613 | snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete, CLIENT_ESTABLISHED (%u)", value); |
1614 | break; |
1615 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1616 | TCP_COMPLETENESS_SYNACK0x02| |
1617 | TCP_COMPLETENESS_ACK0x04): |
1618 | snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete, ESTABLISHED (%u)", value); |
1619 | break; |
1620 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1621 | TCP_COMPLETENESS_SYNACK0x02| |
1622 | TCP_COMPLETENESS_ACK0x04| |
1623 | TCP_COMPLETENESS_DATA0x08): |
1624 | snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete, DATA (%u)", value); |
1625 | break; |
1626 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1627 | TCP_COMPLETENESS_SYNACK0x02| |
1628 | TCP_COMPLETENESS_ACK0x04| |
1629 | TCP_COMPLETENESS_DATA0x08| |
1630 | TCP_COMPLETENESS_FIN0x10): |
1631 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1632 | TCP_COMPLETENESS_SYNACK0x02| |
1633 | TCP_COMPLETENESS_ACK0x04| |
1634 | TCP_COMPLETENESS_DATA0x08| |
1635 | TCP_COMPLETENESS_RST0x20): |
1636 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1637 | TCP_COMPLETENESS_SYNACK0x02| |
1638 | TCP_COMPLETENESS_ACK0x04| |
1639 | TCP_COMPLETENESS_DATA0x08| |
1640 | TCP_COMPLETENESS_FIN0x10| |
1641 | TCP_COMPLETENESS_RST0x20): |
1642 | snprintf(buf, ITEM_LABEL_LENGTH240, "Complete, WITH_DATA (%u)", value); |
1643 | break; |
1644 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1645 | TCP_COMPLETENESS_SYNACK0x02| |
1646 | TCP_COMPLETENESS_ACK0x04| |
1647 | TCP_COMPLETENESS_FIN0x10): |
1648 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1649 | TCP_COMPLETENESS_SYNACK0x02| |
1650 | TCP_COMPLETENESS_ACK0x04| |
1651 | TCP_COMPLETENESS_RST0x20): |
1652 | case (TCP_COMPLETENESS_SYNSENT0x01| |
1653 | TCP_COMPLETENESS_SYNACK0x02| |
1654 | TCP_COMPLETENESS_ACK0x04| |
1655 | TCP_COMPLETENESS_FIN0x10| |
1656 | TCP_COMPLETENESS_RST0x20): |
1657 | snprintf(buf, ITEM_LABEL_LENGTH240, "Complete, NO_DATA (%u)", value); |
1658 | break; |
1659 | default: |
1660 | snprintf(buf, ITEM_LABEL_LENGTH240, "Incomplete (%u)", value); |
1661 | break; |
1662 | } |
1663 | } |
1664 | |
1665 | /* TCP structs and definitions */ |
1666 | |
1667 | /* ************************************************************************** |
1668 | * RTT, relative sequence numbers, window scaling & etc. |
1669 | * **************************************************************************/ |
1670 | static bool_Bool tcp_analyze_seq = true1; |
1671 | static bool_Bool tcp_relative_seq = true1; |
1672 | static bool_Bool tcp_track_bytes_in_flight = true1; |
1673 | static bool_Bool tcp_bif_seq_based; |
1674 | static bool_Bool tcp_calculate_ts = true1; |
1675 | |
1676 | static bool_Bool tcp_analyze_mptcp = true1; |
1677 | static bool_Bool mptcp_relative_seq = true1; |
1678 | static bool_Bool mptcp_analyze_mappings; |
1679 | static bool_Bool mptcp_intersubflows_retransmission; |
1680 | |
1681 | |
1682 | #define TCP_A_RETRANSMISSION0x0001 0x0001 |
1683 | #define TCP_A_LOST_PACKET0x0002 0x0002 |
1684 | #define TCP_A_ACK_LOST_PACKET0x0004 0x0004 |
1685 | #define TCP_A_KEEP_ALIVE0x0008 0x0008 |
1686 | #define TCP_A_DUPLICATE_ACK0x0010 0x0010 |
1687 | #define TCP_A_ZERO_WINDOW0x0020 0x0020 |
1688 | #define TCP_A_ZERO_WINDOW_PROBE0x0040 0x0040 |
1689 | #define TCP_A_ZERO_WINDOW_PROBE_ACK0x0080 0x0080 |
1690 | #define TCP_A_KEEP_ALIVE_ACK0x0100 0x0100 |
1691 | #define TCP_A_OUT_OF_ORDER0x0200 0x0200 |
1692 | #define TCP_A_FAST_RETRANSMISSION0x0400 0x0400 |
1693 | #define TCP_A_WINDOW_UPDATE0x0800 0x0800 |
1694 | #define TCP_A_WINDOW_FULL0x1000 0x1000 |
1695 | #define TCP_A_REUSED_PORTS0x2000 0x2000 |
1696 | #define TCP_A_SPURIOUS_RETRANSMISSION0x4000 0x4000 |
1697 | |
1698 | /* This flag for desegment_tcp to exclude segments with previously |
1699 | * seen sequence numbers. |
1700 | * It is from the perspective of Wireshark's reassembler, whereas |
1701 | * the other flags above are from the perspective of the sender. |
1702 | * (E.g., TCP_A_RETRANSMISSION or TCP_A_SPURIOUS_RETRANSMISSION |
1703 | * can be set even when first appearance in the capture file.) |
1704 | */ |
1705 | #define TCP_A_OLD_DATA0x8000 0x8000 |
1706 | |
1707 | /* Static TCP flags. Set in tcp_flow_t:static_flags */ |
1708 | #define TCP_S_BASE_SEQ_SET0x01 0x01 |
1709 | #define TCP_S_SAW_SYN0x03 0x03 |
1710 | #define TCP_S_SAW_SYNACK0x05 0x05 |
1711 | |
1712 | |
1713 | /* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */ |
1714 | #define MPTCP_META_HAS_BASE_DSN_MSB0x01 0x01 |
1715 | #define MPTCP_META_HAS_KEY0x03 0x03 |
1716 | #define MPTCP_META_HAS_TOKEN0x04 0x04 |
1717 | #define MPTCP_META_HAS_ADDRESSES0x08 0x08 |
1718 | |
1719 | /* Describe the fields sniffed and set in mptcp_meta_flow_t:static_flags */ |
1720 | #define MPTCP_SUBFLOW_HAS_NONCE0x01 0x01 |
1721 | #define MPTCP_SUBFLOW_HAS_ADDRESS_ID0x02 0x02 |
1722 | |
1723 | /* MPTCP meta analysis related */ |
1724 | #define MPTCP_META_CHECKSUM_REQUIRED0x0002 0x0002 |
1725 | |
1726 | /* if we have no key for this connection, some conversion become impossible, |
1727 | * thus return false |
1728 | */ |
1729 | static |
1730 | gboolean |
1731 | mptcp_convert_dsn(guint64 dsn, mptcp_meta_flow_t *meta, enum mptcp_dsn_conversion conv, gboolean relative, guint64 *result ) { |
1732 | |
1733 | *result = dsn; |
1734 | |
1735 | /* if relative is set then we need the 64 bits version anyway |
1736 | * we assume no wrapping was done on the 32 lsb so this may be wrong for elephant flows |
1737 | */ |
1738 | if(conv == DSN_CONV_32_TO_64 || relative) { |
1739 | |
1740 | if(!(meta->static_flags & MPTCP_META_HAS_BASE_DSN_MSB0x01)) { |
1741 | /* can't do those without the expected_idsn based on the key */ |
1742 | return FALSE(0); |
1743 | } |
1744 | } |
1745 | |
1746 | if(conv == DSN_CONV_32_TO_64) { |
1747 | *result = KEEP_32MSB_OF_GUINT64(meta->base_dsn) | dsn; |
1748 | } |
1749 | |
1750 | if(relative) { |
1751 | *result -= meta->base_dsn; |
1752 | } |
1753 | |
1754 | if(conv == DSN_CONV_64_TO_32) { |
1755 | *result = (guint32) *result; |
1756 | } |
1757 | |
1758 | return TRUE(!(0)); |
1759 | } |
1760 | |
1761 | |
1762 | static void |
1763 | process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo, |
1764 | proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port, |
1765 | guint32 seq, guint32 nxtseq, gboolean is_tcp_segment, |
1766 | struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo); |
1767 | |
1768 | |
1769 | static struct tcp_analysis * |
1770 | init_tcp_conversation_data(packet_info *pinfo, int direction) |
1771 | { |
1772 | struct tcp_analysis *tcpd; |
1773 | |
1774 | /* Initialize the tcp protocol data structure to add to the tcp conversation */ |
1775 | tcpd=wmem_new0(wmem_file_scope(), struct tcp_analysis)((struct tcp_analysis*)wmem_alloc0((wmem_file_scope()), sizeof (struct tcp_analysis))); |
1776 | tcpd->flow1.win_scale = (direction >= 0) ? pinfo->src_win_scale : pinfo->dst_win_scale; |
1777 | tcpd->flow1.window = G_MAXUINT32((guint32) 0xffffffff); |
1778 | tcpd->flow1.multisegment_pdus=wmem_tree_new(wmem_file_scope()); |
1779 | |
1780 | tcpd->flow2.window = G_MAXUINT32((guint32) 0xffffffff); |
1781 | tcpd->flow2.win_scale = (direction >= 0) ? pinfo->dst_win_scale : pinfo->src_win_scale; |
1782 | tcpd->flow2.multisegment_pdus=wmem_tree_new(wmem_file_scope()); |
1783 | |
1784 | if (tcp_reassemble_out_of_order) { |
1785 | tcpd->flow1.ooo_segments=wmem_list_new(wmem_file_scope()); |
1786 | tcpd->flow2.ooo_segments=wmem_list_new(wmem_file_scope()); |
1787 | } |
1788 | |
1789 | /* Only allocate the data if its actually going to be analyzed */ |
1790 | if (tcp_analyze_seq) |
1791 | { |
1792 | tcpd->flow1.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t)((struct tcp_analyze_seq_flow_info_t*)wmem_alloc0((wmem_file_scope ()), sizeof(struct tcp_analyze_seq_flow_info_t))); |
1793 | tcpd->flow2.tcp_analyze_seq_info = wmem_new0(wmem_file_scope(), struct tcp_analyze_seq_flow_info_t)((struct tcp_analyze_seq_flow_info_t*)wmem_alloc0((wmem_file_scope ()), sizeof(struct tcp_analyze_seq_flow_info_t))); |
1794 | } |
1795 | /* Only allocate the data if its actually going to be displayed */ |
1796 | if (tcp_display_process_info) |
1797 | { |
1798 | tcpd->flow1.process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t)((struct tcp_process_info_t*)wmem_alloc0((wmem_file_scope()), sizeof(struct tcp_process_info_t))); |
1799 | tcpd->flow2.process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t)((struct tcp_process_info_t*)wmem_alloc0((wmem_file_scope()), sizeof(struct tcp_process_info_t))); |
1800 | } |
1801 | |
1802 | tcpd->acked_table=wmem_tree_new(wmem_file_scope()); |
1803 | tcpd->ts_first.secs=pinfo->abs_ts.secs; |
1804 | tcpd->ts_first.nsecs=pinfo->abs_ts.nsecs; |
1805 | nstime_set_zero(&tcpd->ts_mru_syn); |
1806 | nstime_set_zero(&tcpd->ts_first_rtt); |
1807 | tcpd->ts_prev.secs=pinfo->abs_ts.secs; |
1808 | tcpd->ts_prev.nsecs=pinfo->abs_ts.nsecs; |
1809 | tcpd->flow1.valid_bif = 1; |
1810 | tcpd->flow2.valid_bif = 1; |
1811 | tcpd->flow1.push_bytes_sent = 0; |
1812 | tcpd->flow2.push_bytes_sent = 0; |
1813 | tcpd->flow1.push_set_last = FALSE(0); |
1814 | tcpd->flow2.push_set_last = FALSE(0); |
1815 | tcpd->flow1.closing_initiator = FALSE(0); |
1816 | tcpd->flow2.closing_initiator = FALSE(0); |
1817 | tcpd->stream = tcp_stream_count++; |
1818 | tcpd->server_port = 0; |
1819 | tcpd->flow_direction = 0; |
1820 | tcpd->flow1.flow_count = 0; |
1821 | tcpd->flow2.flow_count = 0; |
1822 | |
1823 | return tcpd; |
1824 | } |
1825 | |
1826 | /* setup meta as well */ |
1827 | static void |
1828 | mptcp_init_subflow(tcp_flow_t *flow) |
1829 | { |
1830 | struct mptcp_subflow *sf = wmem_new0(wmem_file_scope(), struct mptcp_subflow)((struct mptcp_subflow*)wmem_alloc0((wmem_file_scope()), sizeof (struct mptcp_subflow))); |
1831 | |
1832 | DISSECTOR_ASSERT(flow->mptcp_subflow == 0)((void) ((flow->mptcp_subflow == 0) ? (void)0 : (proto_report_dissector_bug ("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c" , 1832, "flow->mptcp_subflow == 0")))); |
1833 | flow->mptcp_subflow = sf; |
1834 | sf->ssn2dsn_mappings = wmem_itree_new(wmem_file_scope()); |
1835 | sf->dsn2packet_map = wmem_itree_new(wmem_file_scope()); |
1836 | } |
1837 | |
1838 | |
1839 | /* add a new subflow to an mptcp connection */ |
1840 | static void |
1841 | mptcp_attach_subflow(struct mptcp_analysis* mptcpd, struct tcp_analysis* tcpd) { |
1842 | |
1843 | if(!wmem_list_find(mptcpd->subflows, tcpd)) { |
1844 | wmem_list_prepend(mptcpd->subflows, tcpd); |
1845 | } |
1846 | |
1847 | /* in case we merge 2 mptcp connections */ |
1848 | tcpd->mptcp_analysis = mptcpd; |
1849 | } |
1850 | |
1851 | struct tcp_analysis * |
1852 | get_tcp_conversation_data_idempotent(conversation_t *conv) |
1853 | { |
1854 | struct tcp_analysis *tcpd; |
1855 | |
1856 | /* Get the data for this conversation */ |
1857 | tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp); |
1858 | |
1859 | return tcpd; |
1860 | } |
1861 | |
1862 | struct tcp_analysis * |
1863 | get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo) |
1864 | { |
1865 | int direction; |
1866 | struct tcp_analysis *tcpd; |
1867 | gboolean clear_ta = TRUE(!(0)); |
1868 | |
1869 | /* Did the caller supply the conversation pointer? */ |
1870 | if( conv==NULL((void*)0) ) { |
1871 | /* If the caller didn't supply a conversation, don't |
1872 | * clear the analysis, it may be needed */ |
1873 | clear_ta = FALSE(0); |
1874 | conv = find_or_create_conversation(pinfo); |
1875 | } |
1876 | |
1877 | /* Get the data for this conversation */ |
1878 | tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp); |
1879 | |
1880 | direction = cmp_address(&pinfo->src, &pinfo->dst); |
1881 | /* if the addresses are equal, match the ports instead */ |
1882 | if (direction == 0) { |
1883 | direction = (pinfo->srcport > pinfo->destport) ? 1 : -1; |
1884 | } |
1885 | /* If the conversation was just created or it matched a |
1886 | * conversation with template options, tcpd will not |
1887 | * have been initialized. So, initialize |
1888 | * a new tcpd structure for the conversation. |
1889 | */ |
1890 | if (!tcpd) { |
1891 | tcpd = init_tcp_conversation_data(pinfo, direction); |
1892 | conversation_add_proto_data(conv, proto_tcp, tcpd); |
1893 | } |
1894 | |
1895 | if (!tcpd) { |
1896 | return NULL((void*)0); |
1897 | } |
1898 | |
1899 | /* check direction and get ua lists */ |
1900 | if(direction>=0) { |
1901 | tcpd->fwd=&(tcpd->flow1); |
1902 | tcpd->rev=&(tcpd->flow2); |
1903 | } else { |
1904 | tcpd->fwd=&(tcpd->flow2); |
1905 | tcpd->rev=&(tcpd->flow1); |
1906 | } |
1907 | |
1908 | if (clear_ta) { |
1909 | tcpd->ta=NULL((void*)0); |
1910 | } |
1911 | return tcpd; |
1912 | } |
1913 | |
1914 | /* Attach process info to a flow */ |
1915 | /* XXX - We depend on the TCP dissector finding the conversation first */ |
1916 | void |
1917 | add_tcp_process_info(guint32 frame_num, address *local_addr, address *remote_addr, guint16 local_port, guint16 remote_port, guint32 uid, guint32 pid, gchar *username, gchar *command) { |
1918 | conversation_t *conv; |
1919 | struct tcp_analysis *tcpd; |
1920 | tcp_flow_t *flow = NULL((void*)0); |
1921 | |
1922 | if (!tcp_display_process_info) |
1923 | return; |
1924 | |
1925 | conv = find_conversation(frame_num, local_addr, remote_addr, CONVERSATION_TCP, local_port, remote_port, 0); |
1926 | if (!conv) { |
1927 | return; |
1928 | } |
1929 | |
1930 | tcpd = (struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp); |
1931 | if (!tcpd) { |
1932 | return; |
1933 | } |
1934 | |
1935 | if (cmp_address(local_addr, conversation_key_addr1(conv->key_ptr)) == 0 && local_port == conversation_key_port1(conv->key_ptr)) { |
1936 | flow = &tcpd->flow1; |
1937 | } else if (cmp_address(remote_addr, conversation_key_addr1(conv->key_ptr)) == 0 && remote_port == conversation_key_port1(conv->key_ptr)) { |
1938 | flow = &tcpd->flow2; |
1939 | } |
1940 | if (!flow || (flow->process_info && flow->process_info->command)) { |
1941 | return; |
1942 | } |
1943 | |
1944 | if (flow->process_info == NULL((void*)0)) |
1945 | flow->process_info = wmem_new0(wmem_file_scope(), struct tcp_process_info_t)((struct tcp_process_info_t*)wmem_alloc0((wmem_file_scope()), sizeof(struct tcp_process_info_t))); |
1946 | |
1947 | flow->process_info->process_uid = uid; |
1948 | flow->process_info->process_pid = pid; |
1949 | flow->process_info->username = wmem_strdup(wmem_file_scope(), username); |
1950 | flow->process_info->command = wmem_strdup(wmem_file_scope(), command); |
1951 | } |
1952 | |
1953 | /* Return the current stream count */ |
1954 | guint32 get_tcp_stream_count(void) |
1955 | { |
1956 | return tcp_stream_count; |
1957 | } |
1958 | |
1959 | /* Return the mptcp current stream count */ |
1960 | guint32 get_mptcp_stream_count(void) |
1961 | { |
1962 | return mptcp_stream_count; |
1963 | } |
1964 | |
1965 | /* Calculate the timestamps relative to this conversation */ |
1966 | static void |
1967 | tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd, |
1968 | struct tcp_per_packet_data_t *tcppd) |
1969 | { |
1970 | if( !tcppd ) { |
1971 | tcppd = wmem_new(wmem_file_scope(), struct tcp_per_packet_data_t)((struct tcp_per_packet_data_t*)wmem_alloc((wmem_file_scope() ), sizeof(struct tcp_per_packet_data_t))); |
1972 | p_add_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num, tcppd); |
1973 | } |
1974 | |
1975 | if (!tcpd) |
1976 | return; |
1977 | |
1978 | /* pre-increment so packet numbers start at 1 */ |
1979 | tcppd->pnum = ++tcpd->pnum; |
1980 | |
1981 | nstime_delta(&tcppd->ts_del, &pinfo->abs_ts, &tcpd->ts_prev); |
1982 | |
1983 | tcpd->ts_prev.secs=pinfo->abs_ts.secs; |
1984 | tcpd->ts_prev.nsecs=pinfo->abs_ts.nsecs; |
1985 | } |
1986 | |
1987 | /* Add a subtree with the timestamps relative to this conversation */ |
1988 | static void |
1989 | tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd) |
1990 | { |
1991 | proto_item *item; |
1992 | proto_tree *tree; |
1993 | nstime_t ts; |
1994 | |
1995 | if (!tcpd) |
1996 | return; |
1997 | |
1998 | tree=proto_tree_add_subtree(parent_tree, tvb, 0, 0, ett_tcp_timestamps, &item, "Timestamps"); |
1999 | proto_item_set_generated(item); |
2000 | |
2001 | nstime_delta(&ts, &pinfo->abs_ts, &tcpd->ts_first); |
2002 | item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts); |
2003 | proto_item_set_generated(item); |
2004 | |
2005 | if( !tcppd ) |
2006 | tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num); |
2007 | |
2008 | if( tcppd ) { |
2009 | item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0, |
2010 | &tcppd->ts_del); |
2011 | proto_item_set_generated(item); |
2012 | } |
2013 | } |
2014 | |
2015 | static void |
2016 | print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp) |
2017 | { |
2018 | proto_item *item; |
2019 | |
2020 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame); |
2021 | item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to, |
2022 | tvb, 0, 0, msp->first_frame); |
2023 | proto_item_set_generated(item); |
2024 | } |
2025 | |
2026 | /* if we know that a PDU starts inside this segment, return the adjusted |
2027 | offset to where that PDU starts or just return offset back |
2028 | and let TCP try to find out what it can about this segment |
2029 | */ |
2030 | static int |
2031 | scan_for_next_pdu(tvbuff_t *tvb, proto_tree *tcp_tree, packet_info *pinfo, int offset, guint32 seq, guint32 nxtseq, wmem_tree_t *multisegment_pdus) |
2032 | { |
2033 | struct tcp_multisegment_pdu *msp=NULL((void*)0); |
2034 | |
2035 | if(!pinfo->fd->visited) { |
2036 | msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1); |
2037 | if(msp) { |
2038 | /* If this is a continuation of a PDU started in a |
2039 | * previous segment we need to update the last_frame |
2040 | * variables. |
2041 | */ |
2042 | if(seq>msp->seq && seq<msp->nxtpdu) { |
2043 | msp->last_frame=pinfo->num; |
2044 | msp->last_frame_time=pinfo->abs_ts; |
2045 | print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp); |
2046 | } |
2047 | |
2048 | /* If this segment is completely within a previous PDU |
2049 | * then we just skip this packet |
2050 | */ |
2051 | if(seq>msp->seq && nxtseq<=msp->nxtpdu) { |
2052 | return -1; |
2053 | } |
2054 | if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) { |
2055 | offset+=msp->nxtpdu-seq; |
2056 | return offset; |
2057 | } |
2058 | |
2059 | } |
2060 | } else { |
2061 | /* First we try to find the start and transfer time for a PDU. |
2062 | * We only print this for the very first segment of a PDU |
2063 | * and only for PDUs spanning multiple segments. |
2064 | * Se we look for if there was any multisegment PDU started |
2065 | * just BEFORE the end of this segment. I.e. either inside this |
2066 | * segment or in a previous segment. |
2067 | * Since this might also match PDUs that are completely within |
2068 | * this segment we also verify that the found PDU does span |
2069 | * beyond the end of this segment. |
2070 | */ |
2071 | msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, nxtseq-1); |
2072 | if(msp) { |
2073 | if(pinfo->num==msp->first_frame) { |
2074 | proto_item *item; |
2075 | nstime_t ns; |
2076 | |
2077 | item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame); |
2078 | proto_item_set_generated(item); |
2079 | |
2080 | nstime_delta(&ns, &msp->last_frame_time, &pinfo->abs_ts); |
2081 | item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time, |
2082 | tvb, 0, 0, &ns); |
2083 | proto_item_set_generated(item); |
2084 | } |
2085 | } |
2086 | |
2087 | /* Second we check if this segment is part of a PDU started |
2088 | * prior to the segment (seq-1) |
2089 | */ |
2090 | msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1); |
2091 | if(msp) { |
2092 | /* If this segment is completely within a previous PDU |
2093 | * then we just skip this packet |
2094 | */ |
2095 | if(seq>msp->seq && nxtseq<=msp->nxtpdu) { |
2096 | print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp); |
2097 | return -1; |
2098 | } |
2099 | |
2100 | if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) { |
2101 | offset+=msp->nxtpdu-seq; |
2102 | return offset; |
2103 | } |
2104 | } |
2105 | |
2106 | } |
2107 | return offset; |
2108 | } |
2109 | |
2110 | /* if we saw a PDU that extended beyond the end of the segment, |
2111 | use this function to remember where the next pdu starts |
2112 | */ |
2113 | struct tcp_multisegment_pdu * |
2114 | pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, wmem_tree_t *multisegment_pdus) |
2115 | { |
2116 | struct tcp_multisegment_pdu *msp; |
2117 | |
2118 | msp=wmem_new(wmem_file_scope(), struct tcp_multisegment_pdu)((struct tcp_multisegment_pdu*)wmem_alloc((wmem_file_scope()) , sizeof(struct tcp_multisegment_pdu))); |
2119 | msp->nxtpdu=nxtpdu; |
2120 | msp->seq=seq; |
2121 | msp->first_frame=pinfo->num; |
2122 | msp->first_frame_with_seq=pinfo->num; |
2123 | msp->last_frame=pinfo->num; |
2124 | msp->last_frame_time=pinfo->abs_ts; |
2125 | msp->flags=0; |
2126 | wmem_tree_insert32(multisegment_pdus, seq, (void *)msp); |
2127 | /*ws_warning("pdu_store_sequencenumber_of_next_pdu: seq %u", seq);*/ |
2128 | return msp; |
2129 | } |
2130 | |
2131 | /* This is called for SYN and SYN+ACK packets and the purpose is to verify |
2132 | * that we have seen window scaling in both directions. |
2133 | * If we can't find window scaling being set in both directions |
2134 | * that means it was present in the SYN but not in the SYN+ACK |
2135 | * (or the SYN was missing) and then we disable the window scaling |
2136 | * for this tcp session. |
2137 | */ |
2138 | static void |
2139 | verify_tcp_window_scaling(gboolean is_synack, struct tcp_analysis *tcpd) |
2140 | { |
2141 | if( tcpd->fwd->win_scale==-1 ) { |
2142 | /* We know window scaling will not be used as: |
2143 | * a) this is the SYN and it does not have the WS option |
2144 | * (we set the reverse win_scale also in case we miss |
2145 | * the SYN/ACK) |
2146 | * b) this is the SYN/ACK and either the SYN packet has not |
2147 | * been seen or it did have the WS option. As the SYN/ACK |
2148 | * does not have the WS option, window scaling will not be used. |
2149 | * |
2150 | * Setting win_scale to -2 to indicate that we can |
2151 | * trust the window_size value in the TCP header. |
2152 | */ |
2153 | tcpd->fwd->win_scale = -2; |
2154 | tcpd->rev->win_scale = -2; |
2155 | |
2156 | } else if( is_synack && tcpd->rev->win_scale==-2 ) { |
2157 | /* The SYN/ACK has the WS option, while the SYN did not, |
2158 | * this should not happen, but the endpoints will not |
2159 | * have used window scaling, so we will neither |
2160 | */ |
2161 | tcpd->fwd->win_scale = -2; |
2162 | } |
2163 | } |
2164 | |
2165 | /* given a tcpd, returns the mptcp_subflow that sides with meta */ |
2166 | static struct mptcp_subflow * |
2167 | mptcp_select_subflow_from_meta(const struct tcp_analysis *tcpd, const mptcp_meta_flow_t *meta) |
2168 | { |
2169 | /* select the tcp_flow with appropriate direction */ |
2170 | if( tcpd->flow1.mptcp_subflow->meta == meta) { |
2171 | return tcpd->flow1.mptcp_subflow; |
2172 | } |
2173 | else { |
2174 | return tcpd->flow2.mptcp_subflow; |
2175 | } |
2176 | } |
2177 | |
2178 | /* if we saw a window scaling option, store it for future reference |
2179 | */ |
2180 | static void |
2181 | pdu_store_window_scale_option(guint8 ws, struct tcp_analysis *tcpd) |
2182 | { |
2183 | if (tcpd) |
2184 | tcpd->fwd->win_scale=ws; |
2185 | } |
2186 | |
2187 | /* when this function returns, it will (if createflag) populate the ta pointer. |
2188 | */ |
2189 | static void |
2190 | tcp_analyze_get_acked_struct(guint32 frame, guint32 seq, guint32 ack, gboolean createflag, struct tcp_analysis *tcpd) |
2191 | { |
2192 | |
2193 | wmem_tree_key_t key[4]; |
2194 | |
2195 | key[0].length = 1; |
2196 | key[0].key = &frame; |
2197 | |
2198 | key[1].length = 1; |
2199 | key[1].key = &seq; |
2200 | |
2201 | key[2].length = 1; |
2202 | key[2].key = &ack; |
2203 | |
2204 | key[3].length = 0; |
2205 | key[3].key = NULL((void*)0); |
2206 | |
2207 | if (!tcpd) { |
2208 | return; |
2209 | } |
2210 | |
2211 | tcpd->ta = (struct tcp_acked *)wmem_tree_lookup32_array(tcpd->acked_table, key); |
2212 | if((!tcpd->ta) && createflag) { |
2213 | tcpd->ta = wmem_new0(wmem_file_scope(), struct tcp_acked)((struct tcp_acked*)wmem_alloc0((wmem_file_scope()), sizeof(struct tcp_acked))); |
2214 | wmem_tree_insert32_array(tcpd->acked_table, key, (void *)tcpd->ta); |
2215 | } |
2216 | } |
2217 | |
2218 | |
2219 | |
2220 | /* fwd contains a list of all segments processed but not yet ACKed in the |
2221 | * same direction as the current segment. |
2222 | * rev contains a list of all segments received but not yet ACKed in the |
2223 | * opposite direction to the current segment. |
2224 | * |
2225 | * New segments are always added to the head of the fwd/rev lists. |
2226 | * |
2227 | * Changes below should be synced with ChAdvTCPAnalysis in the User's |
2228 | * Guide: docbook/wsug_src/WSUG_chapter_advanced.adoc |
2229 | */ |
2230 | static void |
2231 | tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint16 flags, guint32 window, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd) |
2232 | { |
2233 | tcp_unacked_t *ual=NULL((void*)0); |
2234 | tcp_unacked_t *prevual=NULL((void*)0); |
2235 | guint32 nextseq; |
2236 | |
2237 | #if 0 |
2238 | printf("\nanalyze_sequence numbers frame:%u\n",pinfo->num); |
2239 | 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); |
2240 | for(ual=tcpd->fwd->tcp_analyze_seq_info->segments; ual; ual=ual->next) |
2241 | printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq); |
2242 | 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); |
2243 | for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next) |
2244 | printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq); |
2245 | #endif |
2246 | |
2247 | if (!tcpd) { |
2248 | return; |
2249 | } |
2250 | |
2251 | if( flags & TH_ACK0x0010 ) { |
2252 | tcpd->rev->valid_bif = 1; |
2253 | } |
2254 | |
2255 | /* ZERO WINDOW PROBE |
2256 | * it is a zero window probe if |
2257 | * the sequence number is the next expected one |
2258 | * the window in the other direction is 0 |
2259 | * the segment is exactly 1 byte |
2260 | */ |
2261 | if( seglen==1 |
2262 | && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq |
2263 | && tcpd->rev->window==0 ) { |
2264 | if(!tcpd->ta) { |
2265 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2266 | } |
2267 | tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE0x0040; |
2268 | goto finished_fwd; |
2269 | } |
2270 | |
2271 | |
2272 | /* ZERO WINDOW |
2273 | * a zero window packet has window == 0 but none of the SYN/FIN/RST set |
2274 | */ |
2275 | if( window==0 |
2276 | && (flags&(TH_RST0x0004|TH_FIN0x0001|TH_SYN0x0002))==0 ) { |
2277 | if(!tcpd->ta) { |
2278 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2279 | } |
2280 | tcpd->ta->flags|=TCP_A_ZERO_WINDOW0x0020; |
2281 | } |
2282 | |
2283 | |
2284 | /* LOST PACKET |
2285 | * If this segment is beyond the last seen nextseq we must |
2286 | * have missed some previous segment |
2287 | * |
2288 | * We only check for this if we have actually seen segments prior to this |
2289 | * one. |
2290 | * RST packets are not checked for this. |
2291 | */ |
2292 | if( tcpd->fwd->tcp_analyze_seq_info->nextseq |
2293 | && GT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq)((gint32)((tcpd->fwd->tcp_analyze_seq_info->nextseq) - (seq)) < 0) |
2294 | && (flags&(TH_RST0x0004))==0 ) { |
2295 | if(!tcpd->ta) { |
2296 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2297 | } |
2298 | tcpd->ta->flags|=TCP_A_LOST_PACKET0x0002; |
2299 | |
2300 | /* Disable BiF until an ACK is seen in the other direction */ |
2301 | tcpd->fwd->valid_bif = 0; |
2302 | } |
2303 | |
2304 | |
2305 | /* KEEP ALIVE |
2306 | * a keepalive contains 0 or 1 bytes of data and starts one byte prior |
2307 | * to what should be the next sequence number. |
2308 | * SYN/FIN/RST segments are never keepalives |
2309 | */ |
2310 | if( (seglen==0||seglen==1) |
2311 | && seq==(tcpd->fwd->tcp_analyze_seq_info->nextseq-1) |
2312 | && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) { |
2313 | if(!tcpd->ta) { |
2314 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2315 | } |
2316 | tcpd->ta->flags|=TCP_A_KEEP_ALIVE0x0008; |
2317 | } |
2318 | |
2319 | /* WINDOW UPDATE |
2320 | * A window update is a 0 byte segment with the same SEQ/ACK numbers as |
2321 | * the previous seen segment and with a new window value |
2322 | */ |
2323 | if( seglen==0 |
2324 | && window |
2325 | && window!=tcpd->fwd->window |
2326 | && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq |
2327 | && ack==tcpd->fwd->tcp_analyze_seq_info->lastack |
2328 | && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) { |
2329 | if(!tcpd->ta) { |
2330 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2331 | } |
2332 | tcpd->ta->flags|=TCP_A_WINDOW_UPDATE0x0800; |
2333 | } |
2334 | |
2335 | |
2336 | /* WINDOW FULL |
2337 | * If we know the window scaling |
2338 | * and if this segment contains data and goes all the way to the |
2339 | * edge of the advertised window |
2340 | * then we mark it as WINDOW FULL |
2341 | * SYN/RST/FIN packets are never WINDOW FULL |
2342 | */ |
2343 | if( seglen>0 |
2344 | && tcpd->rev->win_scale!=-1 |
2345 | && (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)))) |
2346 | && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) { |
2347 | if(!tcpd->ta) { |
2348 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2349 | } |
2350 | tcpd->ta->flags|=TCP_A_WINDOW_FULL0x1000; |
2351 | } |
2352 | |
2353 | |
2354 | /* KEEP ALIVE ACK |
2355 | * It is a keepalive ack if it repeats the previous ACK and if |
2356 | * the last segment in the reverse direction was a keepalive |
2357 | */ |
2358 | if( seglen==0 |
2359 | && window |
2360 | && window==tcpd->fwd->window |
2361 | && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq |
2362 | && ack==tcpd->fwd->tcp_analyze_seq_info->lastack |
2363 | && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE0x0008) |
2364 | && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) { |
2365 | if(!tcpd->ta) { |
2366 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2367 | } |
2368 | tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK0x0100; |
2369 | goto finished_fwd; |
2370 | } |
2371 | |
2372 | |
2373 | /* ZERO WINDOW PROBE ACK |
2374 | * It is a zerowindowprobe ack if it repeats the previous ACK and if |
2375 | * the last segment in the reverse direction was a zerowindowprobe |
2376 | * It also repeats the previous zero window indication |
2377 | */ |
2378 | if( seglen==0 |
2379 | && window==0 |
2380 | && window==tcpd->fwd->window |
2381 | && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq |
2382 | && (ack==tcpd->fwd->tcp_analyze_seq_info->lastack || EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)(ack) == (tcpd->fwd->tcp_analyze_seq_info->lastack+1 )) |
2383 | && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE0x0040) |
2384 | && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) { |
2385 | if(!tcpd->ta) { |
2386 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2387 | } |
2388 | tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK0x0080; |
2389 | |
2390 | /* Some receivers consume that extra byte brought in the PROBE, |
2391 | * but it was too early to know that during the WINDOW PROBE analysis. |
2392 | * Do it now by moving the rev nextseq & maxseqtobeacked. |
2393 | * See issue 10745. |
2394 | */ |
2395 | if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)(ack) == (tcpd->fwd->tcp_analyze_seq_info->lastack+1 )) { |
2396 | tcpd->rev->tcp_analyze_seq_info->nextseq=ack; |
2397 | tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack; |
2398 | } |
2399 | goto finished_fwd; |
2400 | } |
2401 | |
2402 | |
2403 | /* DUPLICATE ACK |
2404 | * It is a duplicate ack if window/seq/ack is the same as the previous |
2405 | * segment and if the segment length is 0 |
2406 | */ |
2407 | if( seglen==0 |
2408 | && window |
2409 | && window==tcpd->fwd->window |
2410 | && seq==tcpd->fwd->tcp_analyze_seq_info->nextseq |
2411 | && ack==tcpd->fwd->tcp_analyze_seq_info->lastack |
2412 | && (flags&(TH_SYN0x0002|TH_FIN0x0001|TH_RST0x0004))==0 ) { |
2413 | |
2414 | /* MPTCP tolerates duplicate acks in some circ*mstances, see RFC 8684 4. */ |
2415 | if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) { |
2416 | /* just ignore this DUPLICATE ACK */ |
2417 | } else { |
2418 | tcpd->fwd->tcp_analyze_seq_info->dupacknum++; |
2419 | |
2420 | if(!tcpd->ta) { |
2421 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2422 | } |
2423 | tcpd->ta->flags|=TCP_A_DUPLICATE_ACK0x0010; |
2424 | tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum; |
2425 | tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack; |
2426 | } |
2427 | } |
2428 | |
2429 | |
2430 | |
2431 | finished_fwd: |
2432 | /* If the ack number changed we must reset the dupack counters */ |
2433 | if( ack != tcpd->fwd->tcp_analyze_seq_info->lastack ) { |
2434 | tcpd->fwd->tcp_analyze_seq_info->lastnondupack=pinfo->num; |
2435 | tcpd->fwd->tcp_analyze_seq_info->dupacknum=0; |
2436 | } |
2437 | |
2438 | |
2439 | /* ACKED LOST PACKET |
2440 | * If this segment acks beyond the 'max seq to be acked' in the other direction |
2441 | * then that means we have missed packets going in the |
2442 | * other direction. |
2443 | * It might also indicate we are resuming from a Zero Window, |
2444 | * where a Probe is just followed by an ACK opening again the window. |
2445 | * See issue 8404. |
2446 | * |
2447 | * We only check this if we have actually seen some seq numbers |
2448 | * in the other direction. |
2449 | */ |
2450 | if( tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked |
2451 | && GT_SEQ(ack, tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked )((gint32)((tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked ) - (ack)) < 0) |
2452 | && (flags&(TH_ACK0x0010))!=0 ) { |
2453 | if(!tcpd->ta) { |
2454 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2455 | } |
2456 | |
2457 | /* resuming from a Zero Window Probe which re-opens the window, |
2458 | * mark it as a Window Update |
2459 | */ |
2460 | if(EQ_SEQ(ack,tcpd->fwd->tcp_analyze_seq_info->lastack+1)(ack) == (tcpd->fwd->tcp_analyze_seq_info->lastack+1 ) |
2461 | && (seq==tcpd->fwd->tcp_analyze_seq_info->nextseq) |
2462 | && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE0x0040) ) { |
2463 | tcpd->rev->tcp_analyze_seq_info->nextseq=ack; |
2464 | tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack; |
2465 | tcpd->ta->flags|=TCP_A_WINDOW_UPDATE0x0800; |
2466 | } |
2467 | /* real ACKED LOST PACKET */ |
2468 | else { |
2469 | /* We ensure there is no matching packet waiting in the unacked list, |
2470 | * and take this opportunity to push the tail further than this single packet |
2471 | */ |
2472 | |
2473 | guint32 tail_le = 0, tail_re = 0; |
2474 | for(ual=tcpd->rev->tcp_analyze_seq_info->segments; ual; ual=ual->next) { |
2475 | |
2476 | if(tail_le == tail_re) { /* init edge values */ |
2477 | tail_le = ual->seq; |
2478 | tail_re = ual->nextseq; |
2479 | } |
2480 | |
2481 | /* Only look at what happens above the current ACK value, |
2482 | * as what happened before is definetely ACKed here and can be |
2483 | * safely ignored. */ |
2484 | if(GE_SEQ(ual->seq,ack)((gint32)((ack) - (ual->seq)) <= 0)) { |
2485 | |
2486 | /* if the left edge is contiguous, move the tail leftward */ |
2487 | if(EQ_SEQ(ual->nextseq,tail_le)(ual->nextseq) == (tail_le)) { |
2488 | tail_le = ual->seq; |
2489 | } |
2490 | |
2491 | /* otherwise, we have isolated segments above what is being ACKed here, |
2492 | * and we reinit the tails with the current values */ |
2493 | else { |
2494 | tail_le = ual->seq; |
2495 | tail_re = ual->nextseq; // move the end tail |
2496 | } |
2497 | } |
2498 | } |
2499 | |
2500 | /* a tail was found and we can push the maxseqtobeacked further */ |
2501 | if(EQ_SEQ(ack,tail_le)(ack) == (tail_le) && GT_SEQ(tail_re, ack)((gint32)((ack) - (tail_re)) < 0)) { |
2502 | tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=tail_re; |
2503 | } |
2504 | |
2505 | /* otherwise, just take into account the value being ACKed now */ |
2506 | else { |
2507 | tcpd->rev->tcp_analyze_seq_info->maxseqtobeacked=ack; |
2508 | } |
2509 | |
2510 | tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET0x0004; |
2511 | } |
2512 | } |
2513 | |
2514 | |
2515 | /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER |
2516 | * If the segment contains data (or is a SYN or a FIN) and |
2517 | * if it does not advance the sequence number, it must be one |
2518 | * of these three. |
2519 | * Only test for this if we know what the seq number should be |
2520 | * (tcpd->fwd->nextseq) |
2521 | * |
2522 | * Note that a simple KeepAlive is not a retransmission |
2523 | */ |
2524 | if (seglen>0 || flags&(TH_SYN0x0002|TH_FIN0x0001)) { |
2525 | gboolean seq_not_advanced = tcpd->fwd->tcp_analyze_seq_info->nextseq |
2526 | && (LT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq)((gint32)((seq) - (tcpd->fwd->tcp_analyze_seq_info-> nextseq)) < 0)); |
2527 | |
2528 | guint64 t; |
2529 | guint64 ooo_thres; |
2530 | |
2531 | if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE0x0008) ) { |
2532 | goto finished_checking_retransmission_type; |
2533 | } |
2534 | |
2535 | /* This segment is *not* considered a retransmission/out-of-order if |
2536 | * the segment length is larger than one (it really adds new data) |
2537 | * the sequence number is one less than the previous nextseq and |
2538 | * (the previous segment is possibly a zero window probe) |
2539 | * |
2540 | * We should still try to flag Spurious Retransmissions though. |
2541 | */ |
2542 | if (seglen > 1 && tcpd->fwd->tcp_analyze_seq_info->nextseq - 1 == seq) { |
2543 | seq_not_advanced = FALSE(0); |
2544 | } |
2545 | |
2546 | /* Check for spurious retransmission. If the current seq + segment length |
2547 | * is less than or equal to the current lastack, the packet contains |
2548 | * duplicate data and may be considered spurious. |
2549 | */ |
2550 | if ( seglen > 0 |
2551 | && tcpd->rev->tcp_analyze_seq_info->lastack |
2552 | && LE_SEQ(seq + seglen, tcpd->rev->tcp_analyze_seq_info->lastack)((gint32)((seq + seglen) - (tcpd->rev->tcp_analyze_seq_info ->lastack)) <= 0) ) { |
2553 | if(!tcpd->ta){ |
2554 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2555 | } |
2556 | tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION0x4000; |
2557 | goto finished_checking_retransmission_type; |
2558 | } |
2559 | |
2560 | nextseq = seq+seglen; |
2561 | |
2562 | gboolean precedence_count = tcp_fastrt_precedence; |
2563 | do { |
2564 | switch(precedence_count) { |
2565 | case TRUE(!(0)): |
2566 | /* If there were >=2 duplicate ACKs in the reverse direction |
2567 | * (there might be duplicate acks missing from the trace) |
2568 | * and if this sequence number matches those ACKs |
2569 | * and if the packet occurs within 20ms of the last |
2570 | * duplicate ack |
2571 | * then this is a fast retransmission |
2572 | */ |
2573 | t=(pinfo->abs_ts.secs-tcpd->rev->tcp_analyze_seq_info->lastacktime.secs)*1000000000; |
2574 | t=t+(pinfo->abs_ts.nsecs)-tcpd->rev->tcp_analyze_seq_info->lastacktime.nsecs; |
2575 | if( seq_not_advanced |
2576 | && tcpd->rev->tcp_analyze_seq_info->dupacknum>=2 |
2577 | && tcpd->rev->tcp_analyze_seq_info->lastack==seq |
2578 | && t<20000000 ) { |
2579 | if(!tcpd->ta) { |
2580 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2581 | } |
2582 | tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION0x0400; |
2583 | goto finished_checking_retransmission_type; |
2584 | } |
2585 | |
2586 | /* Look for this segment in reported SACK ranges, |
2587 | * if not present this might very well be a FAST Retrans, |
2588 | * when the conditions above (timing, number of retrans) are still true */ |
2589 | if( seq_not_advanced |
2590 | && t<20000000 |
2591 | && tcpd->rev->tcp_analyze_seq_info->dupacknum>=2 |
2592 | && tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) { |
2593 | |
2594 | gboolean is_sacked = FALSE(0); |
2595 | int i=0; |
2596 | while( !is_sacked && i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges ) { |
2597 | is_sacked = ((seq >= tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i++]) |
2598 | && (nextseq <= tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i])); |
2599 | } |
2600 | |
2601 | /* fine, it's probably a Fast Retrans triggered by the SACK sender algo */ |
2602 | if(!is_sacked) { |
2603 | if(!tcpd->ta) |
2604 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2605 | tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION0x0400; |
2606 | goto finished_checking_retransmission_type; |
2607 | } |
2608 | } |
2609 | |
2610 | precedence_count=!precedence_count; |
2611 | break; |
2612 | |
2613 | case FALSE(0): |
2614 | /* If the segment came relatively close since the segment with the highest |
2615 | * seen sequence number and it doesn't look like a retransmission |
2616 | * then it is an OUT-OF-ORDER segment. |
2617 | */ |
2618 | t=(pinfo->abs_ts.secs-tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs)*1000000000; |
2619 | t=t+(pinfo->abs_ts.nsecs)-tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs; |
2620 | if (tcpd->ts_first_rtt.nsecs == 0 && tcpd->ts_first_rtt.secs == 0) { |
2621 | ooo_thres = 3000000; |
2622 | } else { |
2623 | ooo_thres = tcpd->ts_first_rtt.nsecs + tcpd->ts_first_rtt.secs*1000000000; |
2624 | } |
2625 | |
2626 | /* If the segment is already seen and waiting to be acknowledged, ignore the |
2627 | * Fast-Retrans/OOO debate and go ahead, as it only can be an ordinary Retrans. |
2628 | * Fast-Retrans/Retrans are never ambiguous in the context of packets seen but |
2629 | * this code could be moved above. |
2630 | * See Issues 13284, 13843 |
2631 | * XXX: if compared packets have different sizes, it's not handled yet |
2632 | */ |
2633 | gboolean pk_already_seen = FALSE(0); |
2634 | ual = tcpd->fwd->tcp_analyze_seq_info->segments; |
2635 | while(ual) { |
2636 | if(GE_SEQ(seq,ual->seq)((gint32)((ual->seq) - (seq)) <= 0) && LE_SEQ(seq+seglen,ual->nextseq)((gint32)((seq+seglen) - (ual->nextseq)) <= 0)) { |
2637 | pk_already_seen = TRUE(!(0)); |
2638 | break; |
2639 | } |
2640 | ual=ual->next; |
2641 | } |
2642 | |
2643 | if(seq_not_advanced && t < ooo_thres && !pk_already_seen) { |
2644 | /* ordinary OOO with SEQ numbers and lengths clearly stating the situation */ |
2645 | if( tcpd->fwd->tcp_analyze_seq_info->nextseq != (seq + seglen + (flags&(TH_SYN0x0002|TH_FIN0x0001) ? 1 : 0))) { |
2646 | if(!tcpd->ta) { |
2647 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2648 | } |
2649 | |
2650 | tcpd->ta->flags|=TCP_A_OUT_OF_ORDER0x0200; |
2651 | goto finished_checking_retransmission_type; |
2652 | } |
2653 | else { |
2654 | /* facing an OOO closing a series of disordered packets, |
2655 | all preceded by a pure ACK. See issue 17214 */ |
2656 | if(tcpd->fwd->tcp_analyze_seq_info->lastacklen == 0) { |
2657 | if(!tcpd->ta) { |
2658 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2659 | } |
2660 | |
2661 | tcpd->ta->flags|=TCP_A_OUT_OF_ORDER0x0200; |
2662 | goto finished_checking_retransmission_type; |
2663 | } |
2664 | } |
2665 | } |
2666 | precedence_count=!precedence_count; |
2667 | break; |
2668 | } |
2669 | } while (precedence_count!=tcp_fastrt_precedence) ; |
2670 | |
2671 | if (seq_not_advanced) { |
2672 | /* Then it has to be a generic retransmission */ |
2673 | if(!tcpd->ta) { |
2674 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2675 | } |
2676 | tcpd->ta->flags|=TCP_A_RETRANSMISSION0x0001; |
2677 | |
2678 | /* |
2679 | * worst case scenario: if we don't have better than a recent packet, |
2680 | * use it as the reference for RTO |
2681 | */ |
2682 | nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &tcpd->fwd->tcp_analyze_seq_info->nextseqtime); |
2683 | tcpd->ta->rto_frame=tcpd->fwd->tcp_analyze_seq_info->nextseqframe; |
2684 | |
2685 | /* |
2686 | * better case scenario: if we have a list of the previous unacked packets, |
2687 | * go back to the eldest one, which in theory is likely to be the one retransmitted here. |
2688 | * It's not always the perfect match, particularly when original captured packet used LSO |
2689 | * We may parse this list and try to find an obvious matching packet present in the |
2690 | * capture. If such packet is actually missing, we'll reach the list first entry. |
2691 | * See : issue #12259 |
2692 | * See : issue #17714 |
2693 | */ |
2694 | ual = tcpd->fwd->tcp_analyze_seq_info->segments; |
2695 | while(ual) { |
2696 | if(GE_SEQ(ual->seq, seq)((gint32)((seq) - (ual->seq)) <= 0)) { |
2697 | nstime_delta(&tcpd->ta->rto_ts, &pinfo->abs_ts, &ual->ts ); |
2698 | tcpd->ta->rto_frame=ual->frame; |
2699 | } |
2700 | ual=ual->next; |
2701 | } |
2702 | } |
2703 | } |
2704 | |
2705 | finished_checking_retransmission_type: |
2706 | |
2707 | /* Override the TCP sequence analysis with the value given |
2708 | * manually by the user. This only applies to flagged packets. |
2709 | */ |
2710 | if(tcppd && tcpd->ta && |
2711 | (tcppd->tcp_snd_manual_analysis>0) && |
2712 | (tcpd->ta->flags & TCP_A_RETRANSMISSION0x0001 || |
2713 | tcpd->ta->flags & TCP_A_OUT_OF_ORDER0x0200 || |
2714 | tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION0x0400 || |
2715 | tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION0x4000)) { |
2716 | |
2717 | /* clean flags set during the automatic analysis */ |
2718 | tcpd->ta->flags &= ~(TCP_A_RETRANSMISSION0x0001| |
2719 | TCP_A_OUT_OF_ORDER0x0200| |
2720 | TCP_A_FAST_RETRANSMISSION0x0400| |
2721 | TCP_A_SPURIOUS_RETRANSMISSION0x4000); |
2722 | |
2723 | /* set the corresponding flag chosen by the user */ |
2724 | switch(tcppd->tcp_snd_manual_analysis) { |
2725 | case 0: |
2726 | /* the user asked for an empty overriding, which |
2727 | * means removing any previous value, thus restoring |
2728 | * the automatic analysis. |
2729 | */ |
2730 | break; |
2731 | |
2732 | case 1: |
2733 | tcpd->ta->flags|=TCP_A_OUT_OF_ORDER0x0200; |
2734 | break; |
2735 | |
2736 | case 2: |
2737 | tcpd->ta->flags|=TCP_A_RETRANSMISSION0x0001; |
2738 | break; |
2739 | |
2740 | case 3: |
2741 | tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION0x0400; |
2742 | break; |
2743 | |
2744 | case 4: |
2745 | tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION0x4000; |
2746 | break; |
2747 | |
2748 | default: |
2749 | /* there is no expected default case */ |
2750 | break; |
2751 | } |
2752 | } |
2753 | |
2754 | nextseq = seq+seglen; |
2755 | if ((seglen || flags&(TH_SYN0x0002|TH_FIN0x0001)) && tcpd->fwd->tcp_analyze_seq_info->segment_count < TCP_MAX_UNACKED_SEGMENTS10000) { |
2756 | /* Add this new sequence number to the fwd list. But only if there |
2757 | * aren't "too many" unacked segments (e.g., we're not seeing the ACKs). |
2758 | */ |
2759 | ual = wmem_new(wmem_file_scope(), tcp_unacked_t)((tcp_unacked_t*)wmem_alloc((wmem_file_scope()), sizeof(tcp_unacked_t ))); |
2760 | ual->next=tcpd->fwd->tcp_analyze_seq_info->segments; |
2761 | tcpd->fwd->tcp_analyze_seq_info->segments=ual; |
2762 | tcpd->fwd->tcp_analyze_seq_info->segment_count++; |
2763 | ual->frame=pinfo->num; |
2764 | ual->seq=seq; |
2765 | ual->ts=pinfo->abs_ts; |
2766 | |
2767 | /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */ |
2768 | if( (flags&(TH_SYN0x0002|TH_FIN0x0001)) ) { |
2769 | nextseq+=1; |
2770 | } |
2771 | ual->nextseq=nextseq; |
2772 | } |
2773 | |
2774 | /* Every time we are moving the highest number seen, |
2775 | * we are also tracking the segment length then we will know for sure, |
2776 | * later, if this was a pure ACK or an ordinary data packet. */ |
2777 | if(!tcpd->fwd->tcp_analyze_seq_info->nextseq |
2778 | || GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq + (flags&(TH_SYN|TH_FIN) ? 1 : 0))((gint32)((tcpd->fwd->tcp_analyze_seq_info->nextseq + (flags&(0x0002|0x0001) ? 1 : 0)) - (nextseq)) < 0)) { |
2779 | tcpd->fwd->tcp_analyze_seq_info->lastacklen=seglen; |
2780 | } |
2781 | |
2782 | /* Store the highest number seen so far for nextseq so we can detect |
2783 | * when we receive segments that arrive with a "hole" |
2784 | * If we don't have anything since before, just store what we got. |
2785 | * ZeroWindowProbes are special and don't really advance the nextseq |
2786 | */ |
2787 | if(GT_SEQ(nextseq, tcpd->fwd->tcp_analyze_seq_info->nextseq)((gint32)((tcpd->fwd->tcp_analyze_seq_info->nextseq) - (nextseq)) < 0) || !tcpd->fwd->tcp_analyze_seq_info->nextseq) { |
2788 | if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE0x0040) ) { |
2789 | tcpd->fwd->tcp_analyze_seq_info->nextseq=nextseq; |
2790 | tcpd->fwd->tcp_analyze_seq_info->nextseqframe=pinfo->num; |
2791 | tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs=pinfo->abs_ts.secs; |
2792 | tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs=pinfo->abs_ts.nsecs; |
2793 | |
2794 | /* Count the flows turns by checking all packets carrying real data |
2795 | * Packets not ordered are ignored. |
2796 | */ |
2797 | if((!tcpd->ta ) || |
2798 | !(tcpd->ta->flags & TCP_A_RETRANSMISSION0x0001 || |
2799 | tcpd->ta->flags & TCP_A_OUT_OF_ORDER0x0200 || |
2800 | tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION0x0400 || |
2801 | tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION0x4000)) { |
2802 | |
2803 | if( seglen>0) { |
2804 | /* check direction */ |
2805 | gint8 direction; |
2806 | direction=cmp_address(&pinfo->src, &pinfo->dst); |
2807 | |
2808 | /* if the addresses are equal, match the ports instead */ |
2809 | if(direction==0) { |
2810 | direction= (pinfo->srcport > pinfo->destport) ? 1 : -1; |
2811 | } |
2812 | |
2813 | /* invert the direction and increment the counter */ |
2814 | if(direction != tcpd->flow_direction) { |
2815 | tcpd->flow_direction = direction; |
2816 | tcpd->fwd->flow_count++; |
2817 | } |
2818 | /* if the direction was not reversed, maybe are we |
2819 | * facing the first flow ? Yes, if the counter still equals 0. |
2820 | */ |
2821 | else { |
2822 | if(tcpd->fwd->flow_count==0) { |
2823 | tcpd->fwd->flow_count++; |
2824 | } |
2825 | } |
2826 | } |
2827 | } |
2828 | } |
2829 | } |
2830 | |
2831 | /* Store the highest continuous seq number seen so far for 'max seq to be acked', |
2832 | * so we can detect TCP_A_ACK_LOST_PACKET condition. |
2833 | * If this ever happens, this boundary value can "jump" further in order to |
2834 | * avoid duplicating multiple messages for the very same lost packet. See later |
2835 | * how ACKED LOST PACKET are handled. |
2836 | * Zero Window Probes are logically left out at this moment, but if their data |
2837 | * really were to be ack'ed, then it will be done later when analyzing their |
2838 | * Probe ACK (be it a real Probe ACK, or an ordinary ACK moving the RCV Window). |
2839 | */ |
2840 | if(EQ_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked)(seq) == (tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked ) || !tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked) { |
2841 | if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE0x0040) ) { |
2842 | tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked=tcpd->fwd->tcp_analyze_seq_info->nextseq; |
2843 | } |
2844 | } |
2845 | |
2846 | |
2847 | /* remember what the ack/window is so we can track window updates and retransmissions */ |
2848 | tcpd->fwd->window=window; |
2849 | tcpd->fwd->tcp_analyze_seq_info->lastack=ack; |
2850 | tcpd->fwd->tcp_analyze_seq_info->lastacktime.secs=pinfo->abs_ts.secs; |
2851 | tcpd->fwd->tcp_analyze_seq_info->lastacktime.nsecs=pinfo->abs_ts.nsecs; |
2852 | |
2853 | /* remember the MPTCP operations if any */ |
2854 | if( tcpd->mptcp_analysis ) { |
2855 | tcpd->fwd->mp_operations=tcpd->mptcp_analysis->mp_operations; |
2856 | } |
2857 | |
2858 | /* if there were any flags set for this segment we need to remember them |
2859 | * we only remember the flags for the very last segment though. |
2860 | */ |
2861 | if(tcpd->ta) { |
2862 | tcpd->fwd->lastsegmentflags=tcpd->ta->flags; |
2863 | } else { |
2864 | tcpd->fwd->lastsegmentflags=0; |
2865 | } |
2866 | |
2867 | |
2868 | /* remove all segments this ACKs and we don't need to keep around any more |
2869 | */ |
2870 | prevual = NULL((void*)0); |
2871 | ual = tcpd->rev->tcp_analyze_seq_info->segments; |
2872 | while(ual) { |
2873 | tcp_unacked_t *tmpual; |
2874 | |
2875 | /* If this ack matches the segment, process accordingly */ |
2876 | if(ack==ual->nextseq) { |
2877 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2878 | tcpd->ta->frame_acked=ual->frame; |
2879 | nstime_delta(&tcpd->ta->ts, &pinfo->abs_ts, &ual->ts); |
2880 | /* mark it as a full segment ACK */ |
2881 | tcpd->ta->partial_ack=0; |
2882 | } |
2883 | /* If this acknowledges part of the segment, adjust the segment info for the acked part. |
2884 | * This typically happens in the context of GSO/GRO or Retransmissions with |
2885 | * segment repackaging (elsewhere called repacketization). For the user, looking at the |
2886 | * previous packets for any Retransmission or at the SYN MSS Option presence would |
2887 | * answer what case is precisely encountered. |
2888 | */ |
2889 | else if (GT_SEQ(ack, ual->seq)((gint32)((ual->seq) - (ack)) < 0) && LE_SEQ(ack, ual->nextseq)((gint32)((ack) - (ual->nextseq)) <= 0)) { |
2890 | ual->seq = ack; |
2891 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2892 | tcpd->ta->frame_acked=ual->frame; |
2893 | nstime_delta(&tcpd->ta->ts, &pinfo->abs_ts, &ual->ts); |
2894 | |
2895 | /* mark it as a partial segment ACK |
2896 | * |
2897 | * XXX - This mark is used later to create an Expert Note, |
2898 | * but other ways of tracking these packets are possible: |
2899 | * for example a similar indication to ta->frame_acked |
2900 | * would help differentiating the SEQ/ACK analysis messages. |
2901 | * Also, a TCP Analysis Flag could be added, but doesn't seem |
2902 | * essential yet, as matching packets can be selected with |
2903 | * 'tcp.analysis.partial_ack'. |
2904 | */ |
2905 | tcpd->ta->partial_ack=1; |
2906 | continue; |
2907 | } |
2908 | /* If this acknowledges a segment prior to this one, leave this segment alone and move on */ |
2909 | else if (GT_SEQ(ual->nextseq,ack)((gint32)((ack) - (ual->nextseq)) < 0)) { |
2910 | prevual = ual; |
2911 | ual = ual->next; |
2912 | continue; |
2913 | } |
2914 | |
2915 | /* This segment is old, or an exact match. Delete the segment from the list */ |
2916 | tmpual=ual->next; |
2917 | |
2918 | if (tcpd->rev->scps_capable) { |
2919 | /* Track largest segment successfully sent for SNACK analysis*/ |
2920 | if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) { |
2921 | tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq); |
2922 | } |
2923 | } |
2924 | |
2925 | if (!prevual) { |
2926 | tcpd->rev->tcp_analyze_seq_info->segments = tmpual; |
2927 | } |
2928 | else{ |
2929 | prevual->next = tmpual; |
2930 | } |
2931 | wmem_free(wmem_file_scope(), ual); |
2932 | ual = tmpual; |
2933 | tcpd->rev->tcp_analyze_seq_info->segment_count--; |
2934 | } |
2935 | |
2936 | /* how many bytes of data are there in flight after this frame |
2937 | * was sent |
2938 | * The historical evaluation is done from the payload seen in the |
2939 | * segments captured. Another method deduced from the SEQ numbers |
2940 | * is introduced with issue 7703, but not used by default now. The |
2941 | * method is chosen by the user preference tcp_bif_seq_based. |
2942 | */ |
2943 | if(tcp_track_bytes_in_flight) { |
2944 | guint32 in_flight, delivered = 0; |
2945 | /* |
2946 | * "don't repeat yourself" boolean, for the shared part |
2947 | * between both methods |
2948 | */ |
2949 | gboolean dry_bif_handling = FALSE(0); |
2950 | |
2951 | /* |
2952 | * historical calculation method based on payloads, which is |
2953 | * by now still the default. |
2954 | */ |
2955 | if(!tcp_bif_seq_based) { |
2956 | ual=tcpd->fwd->tcp_analyze_seq_info->segments; |
2957 | |
2958 | if (seglen!=0 && ual && tcpd->fwd->valid_bif) { |
2959 | guint32 first_seq, last_seq; |
2960 | |
2961 | dry_bif_handling = TRUE(!(0)); |
2962 | |
2963 | first_seq = ual->seq - tcpd->fwd->base_seq; |
2964 | last_seq = ual->nextseq - tcpd->fwd->base_seq; |
2965 | while (ual) { |
2966 | if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) { |
2967 | last_seq = ual->nextseq-tcpd->fwd->base_seq; |
2968 | } |
2969 | if ((ual->seq-tcpd->fwd->base_seq)<first_seq) { |
2970 | first_seq = ual->seq-tcpd->fwd->base_seq; |
2971 | } |
2972 | ual = ual->next; |
2973 | } |
2974 | in_flight = last_seq-first_seq; |
2975 | } |
2976 | } else { /* calculation based on SEQ numbers (see issue 7703) */ |
2977 | if (seglen!=0 && tcpd->fwd->tcp_analyze_seq_info && tcpd->fwd->valid_bif) { |
2978 | |
2979 | dry_bif_handling = TRUE(!(0)); |
2980 | |
2981 | in_flight = tcpd->fwd->tcp_analyze_seq_info->nextseq |
2982 | - tcpd->rev->tcp_analyze_seq_info->lastack; |
2983 | } |
2984 | } |
2985 | if(dry_bif_handling) { |
2986 | /* subtract any SACK block */ |
2987 | if(tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) { |
2988 | int i; |
2989 | for(i = 0; i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges; i++) { |
2990 | delivered += (tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i+1] - |
2991 | tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i+1]); |
2992 | } |
2993 | in_flight -= delivered; |
2994 | } |
2995 | |
2996 | if (in_flight>0 && in_flight<2000000000) { |
2997 | if(!tcpd->ta) { |
2998 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE(!(0)), tcpd); |
2999 | } |
3000 | tcpd->ta->bytes_in_flight = in_flight; |
3001 | /* Decrement in_flight bytes by one when we have a SYN or FIN bit |
3002 | * flag set as it is only virtual. |
3003 | */ |
3004 | if (flags&(TH_SYN0x0002|TH_FIN0x0001)) { |
3005 | tcpd->ta->bytes_in_flight -= 1; |
3006 | } |
3007 | } |
3008 | |
3009 | if((flags & TH_PUSH0x0008) && !tcpd->fwd->push_set_last) { |
3010 | tcpd->fwd->push_bytes_sent += seglen; |
3011 | tcpd->fwd->push_set_last = TRUE(!(0)); |
3012 | } else if ((flags & TH_PUSH0x0008) && tcpd->fwd->push_set_last) { |
3013 | tcpd->fwd->push_bytes_sent = seglen; |
3014 | tcpd->fwd->push_set_last = TRUE(!(0)); |
3015 | } else if (tcpd->fwd->push_set_last) { |
3016 | tcpd->fwd->push_bytes_sent = seglen; |
3017 | tcpd->fwd->push_set_last = FALSE(0); |
3018 | } else { |
3019 | tcpd->fwd->push_bytes_sent += seglen; |
3020 | } |
3021 | if(!tcpd->ta) { |
3022 | tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE(!(0)), tcpd); |
3023 | } |
3024 | tcpd->ta->push_bytes_sent = tcpd->fwd->push_bytes_sent; |
3025 | } |
3026 | } |
3027 | |
3028 | } |
3029 | |
3030 | /* |
3031 | * Prints results of the sequence number analysis concerning tcp segments |
3032 | * retransmitted or out-of-order |
3033 | */ |
3034 | static void |
3035 | tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo, |
3036 | tvbuff_t * tvb, |
3037 | proto_tree * flags_tree, proto_item * flags_item, |
3038 | struct tcp_acked *ta |
3039 | ) |
3040 | { |
3041 | /* TCP Retransmission */ |
3042 | if (ta->flags & TCP_A_RETRANSMISSION0x0001) { |
3043 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission); |
3044 | |
3045 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] "); |
3046 | |
3047 | if (ta->rto_ts.secs || ta->rto_ts.nsecs) { |
3048 | flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto, |
3049 | tvb, 0, 0, &ta->rto_ts); |
3050 | proto_item_set_generated(flags_item); |
3051 | flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame, |
3052 | tvb, 0, 0, ta->rto_frame); |
3053 | proto_item_set_generated(flags_item); |
3054 | } |
3055 | } |
3056 | /* TCP Fast Retransmission */ |
3057 | if (ta->flags & TCP_A_FAST_RETRANSMISSION0x0400) { |
3058 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_fast_retransmission); |
3059 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission); |
3060 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, |
3061 | "[TCP Fast Retransmission] "); |
3062 | } |
3063 | /* TCP Spurious Retransmission */ |
3064 | if (ta->flags & TCP_A_SPURIOUS_RETRANSMISSION0x4000) { |
3065 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_spurious_retransmission); |
3066 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission); |
3067 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, |
3068 | "[TCP Spurious Retransmission] "); |
3069 | } |
3070 | |
3071 | /* TCP Out-Of-Order */ |
3072 | if (ta->flags & TCP_A_OUT_OF_ORDER0x0200) { |
3073 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_out_of_order); |
3074 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] "); |
3075 | } |
3076 | } |
3077 | |
3078 | /* Prints results of the sequence number analysis concerning reused ports */ |
3079 | static void |
3080 | tcp_sequence_number_analysis_print_reused(packet_info * pinfo, |
3081 | proto_item * flags_item, |
3082 | struct tcp_acked *ta |
3083 | ) |
3084 | { |
3085 | /* TCP Ports Reused */ |
3086 | if (ta->flags & TCP_A_REUSED_PORTS0x2000) { |
3087 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_reused_ports); |
3088 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, |
3089 | "[TCP Port numbers reused] "); |
3090 | } |
3091 | } |
3092 | |
3093 | /* Prints results of the sequence number analysis concerning lost tcp segments */ |
3094 | static void |
3095 | tcp_sequence_number_analysis_print_lost(packet_info * pinfo, |
3096 | proto_item * flags_item, |
3097 | struct tcp_acked *ta |
3098 | ) |
3099 | { |
3100 | /* TCP Lost Segment */ |
3101 | if (ta->flags & TCP_A_LOST_PACKET0x0002) { |
3102 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_lost_packet); |
3103 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, |
3104 | "[TCP Previous segment not captured] "); |
3105 | } |
3106 | /* TCP Ack lost segment */ |
3107 | if (ta->flags & TCP_A_ACK_LOST_PACKET0x0004) { |
3108 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_ack_lost_packet); |
3109 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, |
3110 | "[TCP ACKed unseen segment] "); |
3111 | } |
3112 | } |
3113 | |
3114 | /* Prints results of the sequence number analysis concerning tcp window */ |
3115 | static void |
3116 | tcp_sequence_number_analysis_print_window(packet_info * pinfo, |
3117 | proto_item * flags_item, |
3118 | struct tcp_acked *ta |
3119 | ) |
3120 | { |
3121 | /* TCP Window Update */ |
3122 | if (ta->flags & TCP_A_WINDOW_UPDATE0x0800) { |
3123 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_update); |
3124 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] "); |
3125 | } |
3126 | /* TCP Full Window */ |
3127 | if (ta->flags & TCP_A_WINDOW_FULL0x1000) { |
3128 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_full); |
3129 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] "); |
3130 | } |
3131 | } |
3132 | |
3133 | /* Prints results of the sequence number analysis concerning tcp keepalive */ |
3134 | static void |
3135 | tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo, |
3136 | proto_item * flags_item, |
3137 | struct tcp_acked *ta |
3138 | ) |
3139 | { |
3140 | /*TCP Keep Alive */ |
3141 | if (ta->flags & TCP_A_KEEP_ALIVE0x0008) { |
3142 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive); |
3143 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] "); |
3144 | } |
3145 | /* TCP Ack Keep Alive */ |
3146 | if (ta->flags & TCP_A_KEEP_ALIVE_ACK0x0100) { |
3147 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive_ack); |
3148 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] "); |
3149 | } |
3150 | } |
3151 | |
3152 | /* Prints results of the sequence number analysis concerning tcp duplicate ack */ |
3153 | static void |
3154 | tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo, |
3155 | tvbuff_t * tvb, |
3156 | proto_tree * flags_tree, |
3157 | struct tcp_acked *ta, |
3158 | proto_tree * tree |
3159 | ) |
3160 | { |
3161 | proto_item * flags_item; |
3162 | |
3163 | /* TCP Duplicate ACK */ |
3164 | if (ta->dupack_num) { |
3165 | if (ta->flags & TCP_A_DUPLICATE_ACK0x0010 ) { |
3166 | flags_item=proto_tree_add_none_format(flags_tree, |
3167 | hf_tcp_analysis_duplicate_ack, |
3168 | tvb, 0, 0, |
3169 | "This is a TCP duplicate ack" |
3170 | ); |
3171 | proto_item_set_generated(flags_item); |
3172 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, |
3173 | "[TCP Dup ACK %u#%u] ", |
3174 | ta->dupack_frame, |
3175 | ta->dupack_num |
3176 | ); |
3177 | |
3178 | } |
3179 | flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num, |
3180 | tvb, 0, 0, ta->dupack_num); |
3181 | proto_item_set_generated(flags_item); |
3182 | flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame, |
3183 | tvb, 0, 0, ta->dupack_frame); |
3184 | proto_item_set_generated(flags_item); |
3185 | expert_add_info_format(pinfo, flags_item, &ei_tcp_analysis_duplicate_ack, "Duplicate ACK (#%u)", ta->dupack_num); |
3186 | } |
3187 | } |
3188 | |
3189 | /* Prints results of the sequence number analysis concerning tcp zero window */ |
3190 | static void |
3191 | tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo, |
3192 | proto_item * flags_item, |
3193 | struct tcp_acked *ta |
3194 | ) |
3195 | { |
3196 | /* TCP Zero Window Probe */ |
3197 | if (ta->flags & TCP_A_ZERO_WINDOW_PROBE0x0040) { |
3198 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe); |
3199 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] "); |
3200 | } |
3201 | /* TCP Zero Window */ |
3202 | if (ta->flags&TCP_A_ZERO_WINDOW0x0020) { |
3203 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window); |
3204 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] "); |
3205 | } |
3206 | /* TCP Zero Window Probe Ack */ |
3207 | if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK0x0080) { |
3208 | expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe_ack); |
3209 | col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, |
3210 | "[TCP ZeroWindowProbeAck] "); |
3211 | } |
3212 | } |
3213 | |
3214 | |
3215 | /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */ |
3216 | static void |
3217 | tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U___attribute__((unused)), |
3218 | tvbuff_t * tvb, |
3219 | proto_tree * flags_tree, |
3220 | struct tcp_acked *ta |
3221 | ) |
3222 | { |
3223 | proto_item * flags_item; |
3224 | |
3225 | if (tcp_track_bytes_in_flight) { |
3226 | flags_item=proto_tree_add_uint(flags_tree, |
3227 | hf_tcp_analysis_bytes_in_flight, |
3228 | tvb, 0, 0, ta->bytes_in_flight); |
3229 | |
3230 | proto_item_set_generated(flags_item); |
3231 | } |
3232 | } |
3233 | |
3234 | /* Generate the initial data sequence number and MPTCP connection token from the key. */ |
3235 | static void |
3236 | mptcp_cryptodata_sha1(const guint64 key, guint32 *token, guint64 *idsn) |
3237 | { |
3238 | guint8 digest_buf[HASH_SHA1_LENGTH20]; |
3239 | guint64 pseudokey = GUINT64_TO_BE(key)((((guint64) ( (((guint64) (key) & (guint64) (0x00000000000000ffUL )) << 56) | (((guint64) (key) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (key) & (guint64) (0x0000000000ff0000UL )) << 24) | (((guint64) (key) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (key) & (guint64) (0x000000ff00000000UL )) >> 8) | (((guint64) (key) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (key) & (guint64) (0x00ff000000000000UL )) >> 40) | (((guint64) (key) & (guint64) (0xff00000000000000UL )) >> 56))))); |
3240 | guint32 _token; |
3241 | guint64 _isdn; |
3242 | |
3243 | gcry_md_hash_buffer(GCRY_MD_SHA1, digest_buf, (const guint8 *)&pseudokey, 8); |
3244 | |
3245 | /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */ |
3246 | memcpy(&_token, digest_buf, sizeof(_token)); |
3247 | *token = GUINT32_FROM_BE(_token)(((((guint32) ( (((guint32) (_token) & (guint32) 0x000000ffU ) << 24) | (((guint32) (_token) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (_token) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (_token) & (guint32) 0xff000000U ) >> 24)))))); |
3248 | memcpy(&_isdn, digest_buf + HASH_SHA1_LENGTH20 - sizeof(_isdn), sizeof(_isdn)); |
3249 | *idsn = GUINT64_FROM_BE(_isdn)(((((guint64) ( (((guint64) (_isdn) & (guint64) (0x00000000000000ffUL )) << 56) | (((guint64) (_isdn) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (_isdn) & (guint64) (0x0000000000ff0000UL )) << 24) | (((guint64) (_isdn) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (_isdn) & (guint64) (0x000000ff00000000UL )) >> 8) | (((guint64) (_isdn) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (_isdn) & (guint64) (0x00ff000000000000UL )) >> 40) | (((guint64) (_isdn) & (guint64) (0xff00000000000000UL )) >> 56)))))); |
3250 | } |
3251 | |
3252 | /* Generate the initial data sequence number and MPTCP connection token from the key. */ |
3253 | static void |
3254 | mptcp_cryptodata_sha256(const guint64 key, guint32 *token, guint64 *idsn) |
3255 | { |
3256 | guint8 digest_buf[HASH_SHA2_256_LENGTH32]; |
3257 | guint64 pseudokey = GUINT64_TO_BE(key)((((guint64) ( (((guint64) (key) & (guint64) (0x00000000000000ffUL )) << 56) | (((guint64) (key) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (key) & (guint64) (0x0000000000ff0000UL )) << 24) | (((guint64) (key) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (key) & (guint64) (0x000000ff00000000UL )) >> 8) | (((guint64) (key) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (key) & (guint64) (0x00ff000000000000UL )) >> 40) | (((guint64) (key) & (guint64) (0xff00000000000000UL )) >> 56))))); |
3258 | guint32 _token; |
3259 | guint64 _isdn; |
3260 | |
3261 | gcry_md_hash_buffer(GCRY_MD_SHA256, digest_buf, (const guint8 *)&pseudokey, 8); |
3262 | |
3263 | /* memcpy to prevent -Wstrict-aliasing errors with GCC 4 */ |
3264 | memcpy(&_token, digest_buf, sizeof(_token)); |
3265 | *token = GUINT32_FROM_BE(_token)(((((guint32) ( (((guint32) (_token) & (guint32) 0x000000ffU ) << 24) | (((guint32) (_token) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (_token) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (_token) & (guint32) 0xff000000U ) >> 24)))))); |
3266 | memcpy(&_isdn, digest_buf + HASH_SHA2_256_LENGTH32 - sizeof(_isdn), sizeof(_isdn)); |
3267 | *idsn = GUINT64_FROM_BE(_isdn)(((((guint64) ( (((guint64) (_isdn) & (guint64) (0x00000000000000ffUL )) << 56) | (((guint64) (_isdn) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (_isdn) & (guint64) (0x0000000000ff0000UL )) << 24) | (((guint64) (_isdn) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (_isdn) & (guint64) (0x000000ff00000000UL )) >> 8) | (((guint64) (_isdn) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (_isdn) & (guint64) (0x00ff000000000000UL )) >> 40) | (((guint64) (_isdn) & (guint64) (0xff00000000000000UL )) >> 56)))))); |
3268 | } |
3269 | |
3270 | |
3271 | /* Print formatted list of tcp stream ids that are part of the connection */ |
3272 | static void |
3273 | mptcp_analysis_add_subflows(packet_info *pinfo, tvbuff_t *tvb, |
3274 | proto_tree *parent_tree, struct mptcp_analysis* mptcpd) |
3275 | { |
3276 | wmem_list_frame_t *it; |
3277 | proto_item *item; |
3278 | |
3279 | wmem_strbuf_t *val = wmem_strbuf_new(pinfo->pool, ""); |
3280 | |
3281 | /* for the analysis, we set each subflow tcp stream id */ |
3282 | for(it = wmem_list_head(mptcpd->subflows); it != NULL((void*)0); it = wmem_list_frame_next(it)) { |
3283 | struct tcp_analysis *sf = (struct tcp_analysis *)wmem_list_frame_data(it); |
3284 | wmem_strbuf_append_printf(val, "%u ", sf->stream); |
3285 | } |
3286 | |
3287 | item = proto_tree_add_string(parent_tree, hf_mptcp_analysis_subflows, tvb, 0, 0, wmem_strbuf_get_str(val)); |
3288 | proto_item_set_generated(item); |
3289 | } |
3290 | |
3291 | /* Compute raw dsn if relative tcp seq covered by DSS mapping */ |
3292 | static gboolean |
3293 | mptcp_map_relssn_to_rawdsn(mptcp_dss_mapping_t *mapping, guint32 relssn, guint64 *dsn) |
3294 | { |
3295 | if( (relssn < mapping->ssn_low) || (relssn > mapping->ssn_high)) { |
3296 | return FALSE(0); |
3297 | } |
3298 | |
3299 | *dsn = mapping->rawdsn + (relssn - mapping->ssn_low); |
3300 | return TRUE(!(0)); |
3301 | } |
3302 | |
3303 | |
3304 | /* Add duplicated data */ |
3305 | static mptcp_dsn2packet_mapping_t * |
3306 | mptcp_add_duplicated_dsn(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, struct mptcp_subflow *subflow, |
3307 | guint64 rawdsn64low, guint64 rawdsn64high |
3308 | ) |
3309 | { |
3310 | wmem_list_t *results = NULL((void*)0); |
3311 | wmem_list_frame_t *packet_it = NULL((void*)0); |
3312 | mptcp_dsn2packet_mapping_t *packet = NULL((void*)0); |
3313 | proto_item *item = NULL((void*)0); |
3314 | |
3315 | results = wmem_itree_find_intervals(subflow->dsn2packet_map, |
3316 | pinfo->pool, |
3317 | rawdsn64low, |
3318 | rawdsn64high |
3319 | ); |
3320 | |
3321 | for(packet_it = wmem_list_head(results); |
3322 | packet_it != NULL((void*)0); |
3323 | packet_it = wmem_list_frame_next(packet_it)) |
3324 | { |
3325 | |
3326 | packet = (mptcp_dsn2packet_mapping_t *) wmem_list_frame_data(packet_it); |
3327 | DISSECTOR_ASSERT(packet)((void) ((packet) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3327, "packet")))); |
3328 | |
3329 | if(pinfo->num > packet->frame) { |
3330 | item = proto_tree_add_uint(tree, hf_mptcp_reinjection_of, tvb, 0, 0, packet->frame); |
3331 | } |
3332 | else { |
3333 | item = proto_tree_add_uint(tree, hf_mptcp_reinjected_in, tvb, 0, 0, packet->frame); |
3334 | } |
3335 | proto_item_set_generated(item); |
3336 | } |
3337 | |
3338 | return packet; |
3339 | } |
3340 | |
3341 | |
3342 | /* Lookup mappings that describe the packet and then converts the tcp seq number |
3343 | * into the MPTCP Data Sequence Number (DSN) |
3344 | */ |
3345 | static void |
3346 | mptcp_analysis_dsn_lookup(packet_info *pinfo , tvbuff_t *tvb, |
3347 | proto_tree *parent_tree, struct tcp_analysis* tcpd, struct tcpheader * tcph, mptcp_per_packet_data_t *mptcppd) |
3348 | { |
3349 | struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis; |
3350 | proto_item *item = NULL((void*)0); |
3351 | mptcp_dss_mapping_t *mapping = NULL((void*)0); |
3352 | guint32 relseq; |
3353 | guint64 rawdsn = 0; |
3354 | enum mptcp_dsn_conversion convert; |
3355 | |
3356 | if(!mptcp_analyze_mappings) |
3357 | { |
3358 | /* abort analysis */ |
3359 | return; |
3360 | } |
3361 | |
3362 | /* for this to work, we need to know the original seq number from the SYN, not from a subsequent packet |
3363 | * hence, we abort if we didn't capture the SYN |
3364 | */ |
3365 | if(!(tcpd->fwd->static_flags & ~TCP_S_BASE_SEQ_SET0x01 & (TCP_S_SAW_SYN0x03 | TCP_S_SAW_SYNACK0x05))) { |
3366 | return; |
3367 | } |
3368 | |
3369 | /* if seq not relative yet, we compute it */ |
3370 | relseq = (tcp_relative_seq) ? tcph->th_seq : tcph->th_seq - tcpd->fwd->base_seq; |
3371 | |
3372 | DISSECTOR_ASSERT(mptcpd)((void) ((mptcpd) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3372, "mptcpd")))); |
3373 | DISSECTOR_ASSERT(mptcppd)((void) ((mptcppd) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3373, "mptcppd")))); |
3374 | |
3375 | /* in case of a SYN, there is no mapping covering the DSN */ |
3376 | if(tcph->th_flags & TH_SYN0x0002) { |
3377 | |
3378 | rawdsn = tcpd->fwd->mptcp_subflow->meta->base_dsn; |
3379 | convert = DSN_CONV_NONE; |
3380 | } |
3381 | /* if it's a non-syn packet without data (just used to convey TCP options) |
3382 | * then there would be no mappings */ |
3383 | else if(relseq == 1 && tcph->th_seglen == 0) { |
3384 | rawdsn = tcpd->fwd->mptcp_subflow->meta->base_dsn + 1; |
3385 | convert = DSN_CONV_NONE; |
3386 | } |
3387 | else { |
3388 | |
3389 | wmem_list_frame_t *dss_it = NULL((void*)0); |
3390 | wmem_list_t *results = NULL((void*)0); |
3391 | guint32 ssn_low = relseq; |
3392 | guint32 seglen = tcph->th_seglen; |
3393 | |
3394 | results = wmem_itree_find_intervals(tcpd->fwd->mptcp_subflow->ssn2dsn_mappings, |
3395 | pinfo->pool, |
3396 | ssn_low, |
3397 | (seglen) ? ssn_low + seglen - 1 : ssn_low |
3398 | ); |
3399 | dss_it = wmem_list_head(results); /* assume it's always ok */ |
3400 | if(dss_it) { |
3401 | mapping = (mptcp_dss_mapping_t *) wmem_list_frame_data(dss_it); |
3402 | } |
3403 | if(dss_it == NULL((void*)0) || mapping == NULL((void*)0)) { |
3404 | expert_add_info(pinfo, parent_tree, &ei_mptcp_mapping_missing); |
3405 | return; |
3406 | } |
3407 | else { |
3408 | mptcppd->mapping = mapping; |
3409 | } |
3410 | |
3411 | DISSECTOR_ASSERT(mapping)((void) ((mapping) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3411, "mapping")))); |
3412 | if(seglen) { |
3413 | /* Finds mappings that cover the sent data and adds them to the dissection tree */ |
3414 | for(dss_it = wmem_list_head(results); |
3415 | dss_it != NULL((void*)0); |
3416 | dss_it = wmem_list_frame_next(dss_it)) |
3417 | { |
3418 | mapping = (mptcp_dss_mapping_t *) wmem_list_frame_data(dss_it); |
3419 | DISSECTOR_ASSERT(mapping)((void) ((mapping) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3419, "mapping")))); |
3420 | |
3421 | item = proto_tree_add_uint(parent_tree, hf_mptcp_related_mapping, tvb, 0, 0, mapping->frame); |
3422 | proto_item_set_generated(item); |
3423 | } |
3424 | } |
3425 | |
3426 | convert = (mapping->extended_dsn) ? DSN_CONV_NONE : DSN_CONV_32_TO_64; |
3427 | DISSECTOR_ASSERT(mptcp_map_relssn_to_rawdsn(mapping, relseq, &rawdsn))((void) ((mptcp_map_relssn_to_rawdsn(mapping, relseq, &rawdsn )) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3427, "mptcp_map_relssn_to_rawdsn(mapping, relseq, &rawdsn)" )))); |
3428 | } |
3429 | |
3430 | /* Make sure we have the 64bit raw DSN */ |
3431 | if(mptcp_convert_dsn(rawdsn, tcpd->fwd->mptcp_subflow->meta, |
3432 | convert, FALSE(0), &tcph->th_mptcp->mh_rawdsn64)) { |
3433 | |
3434 | /* always display the rawdsn64 (helpful for debug) */ |
3435 | item = proto_tree_add_uint64(parent_tree, hf_mptcp_rawdsn64, tvb, 0, 0, tcph->th_mptcp->mh_rawdsn64); |
3436 | |
3437 | /* converts to relative if required */ |
3438 | if (mptcp_relative_seq |
3439 | && mptcp_convert_dsn(tcph->th_mptcp->mh_rawdsn64, tcpd->fwd->mptcp_subflow->meta, DSN_CONV_NONE, TRUE(!(0)), &tcph->th_mptcp->mh_dsn)) { |
3440 | item = proto_tree_add_uint64(parent_tree, hf_mptcp_dsn, tvb, 0, 0, tcph->th_mptcp->mh_dsn); |
3441 | proto_item_append_text(item, " (Relative)"); |
3442 | } |
3443 | |
3444 | /* register dsn->packet mapping */ |
3445 | if(mptcp_intersubflows_retransmission |
3446 | && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) |
3447 | && tcph->th_seglen > 0 |
3448 | ) { |
3449 | mptcp_dsn2packet_mapping_t *packet = 0; |
3450 | packet = wmem_new0(wmem_file_scope(), mptcp_dsn2packet_mapping_t)((mptcp_dsn2packet_mapping_t*)wmem_alloc0((wmem_file_scope()) , sizeof(mptcp_dsn2packet_mapping_t))); |
3451 | packet->frame = pinfo->fd->num; |
3452 | packet->subflow = tcpd; |
3453 | |
3454 | wmem_itree_insert(tcpd->fwd->mptcp_subflow->dsn2packet_map, |
3455 | tcph->th_mptcp->mh_rawdsn64, |
3456 | tcph->th_mptcp->mh_rawdsn64 + (tcph->th_seglen - 1 ), |
3457 | packet |
3458 | ); |
3459 | } |
3460 | proto_item_set_generated(item); |
3461 | |
3462 | /* We can do this only if rawdsn64 is valid ! |
3463 | if enabled, look for overlapping mappings on other subflows */ |
3464 | if(mptcp_intersubflows_retransmission |
3465 | && tcph->th_have_seglen |
3466 | && tcph->th_seglen) { |
3467 | |
3468 | wmem_list_frame_t *subflow_it = NULL((void*)0); |
3469 | |
3470 | /* results should be some kind of list in case 2 DSS are needed to cover this packet */ |
3471 | for(subflow_it = wmem_list_head(mptcpd->subflows); subflow_it != NULL((void*)0); subflow_it = wmem_list_frame_next(subflow_it)) { |
3472 | struct tcp_analysis *sf_tcpd = (struct tcp_analysis *)wmem_list_frame_data(subflow_it); |
3473 | struct mptcp_subflow *sf = mptcp_select_subflow_from_meta(sf_tcpd, tcpd->fwd->mptcp_subflow->meta); |
3474 | |
3475 | /* for current subflow */ |
3476 | if (sf == tcpd->fwd->mptcp_subflow) { |
3477 | /* skip, this is the current subflow */ |
3478 | } |
3479 | /* in case there were retransmissions on other subflows */ |
3480 | else { |
3481 | mptcp_add_duplicated_dsn(pinfo, parent_tree, tvb, sf, |
3482 | tcph->th_mptcp->mh_rawdsn64, |
3483 | tcph->th_mptcp->mh_rawdsn64 + tcph->th_seglen-1); |
3484 | } |
3485 | } |
3486 | } |
3487 | } |
3488 | else { |
3489 | /* could not get the rawdsn64, ignore and continue */ |
3490 | } |
3491 | |
3492 | } |
3493 | |
3494 | |
3495 | /* Print subflow list */ |
3496 | static void |
3497 | mptcp_add_analysis_subtree(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, |
3498 | struct tcp_analysis *tcpd, struct mptcp_analysis *mptcpd, struct tcpheader * tcph) |
3499 | { |
3500 | |
3501 | proto_item *item = NULL((void*)0); |
3502 | proto_tree *tree = NULL((void*)0); |
3503 | mptcp_per_packet_data_t *mptcppd = NULL((void*)0); |
3504 | |
3505 | if(mptcpd == NULL((void*)0)) { |
3506 | return; |
3507 | } |
3508 | |
3509 | item=proto_tree_add_item(parent_tree, hf_mptcp_analysis, tvb, 0, 0, ENC_NA0x00000000); |
3510 | proto_item_set_generated(item); |
3511 | tree=proto_item_add_subtree(item, ett_mptcp_analysis); |
3512 | proto_item_set_generated(tree); |
3513 | |
3514 | /* set field with mptcp stream */ |
3515 | if(mptcpd->master) { |
3516 | |
3517 | item = proto_tree_add_boolean_format_value(tree, hf_mptcp_analysis_master, tvb, 0, |
3518 | 0, (mptcpd->master->stream == tcpd->stream) ? TRUE(!(0)) : FALSE(0) |
3519 | , "Master is tcp stream %u", mptcpd->master->stream |
3520 | ); |
3521 | |
3522 | } |
3523 | else { |
3524 | item = proto_tree_add_boolean(tree, hf_mptcp_analysis_master, tvb, 0, |
3525 | 0, FALSE(0)); |
3526 | } |
3527 | |
3528 | proto_item_set_generated(item); |
3529 | |
3530 | #if 0 // nbOptionsChanged is currently unused. |
3531 | /* store the TCP Options related to MPTCP then we will avoid false DUP ACKs later */ |
3532 | guint8 nbOptionsChanged = 0; |
3533 | if((tcpd->mptcp_analysis->mp_operations&(0x01))!=tcph->th_mptcp->mh_mpc) { |
3534 | tcpd->mptcp_analysis->mp_operations |= 0x01; |
3535 | nbOptionsChanged++; |
3536 | } |
3537 | if((tcpd->mptcp_analysis->mp_operations&(0x02))!=tcph->th_mptcp->mh_join) { |
3538 | tcpd->mptcp_analysis->mp_operations |= 0x02; |
3539 | nbOptionsChanged++; |
3540 | } |
3541 | if((tcpd->mptcp_analysis->mp_operations&(0x04))!=tcph->th_mptcp->mh_dss) { |
3542 | tcpd->mptcp_analysis->mp_operations |= 0x04; |
3543 | nbOptionsChanged++; |
3544 | } |
3545 | if((tcpd->mptcp_analysis->mp_operations&(0x08))!=tcph->th_mptcp->mh_add) { |
3546 | tcpd->mptcp_analysis->mp_operations |= 0x08; |
3547 | nbOptionsChanged++; |
3548 | } |
3549 | if((tcpd->mptcp_analysis->mp_operations&(0x10))!=tcph->th_mptcp->mh_remove) { |
3550 | tcpd->mptcp_analysis->mp_operations |= 0x10; |
3551 | nbOptionsChanged++; |
3552 | } |
3553 | if((tcpd->mptcp_analysis->mp_operations&(0x20))!=tcph->th_mptcp->mh_prio) { |
3554 | tcpd->mptcp_analysis->mp_operations |= 0x20; |
3555 | nbOptionsChanged++; |
3556 | } |
3557 | if((tcpd->mptcp_analysis->mp_operations&(0x40))!=tcph->th_mptcp->mh_fail) { |
3558 | tcpd->mptcp_analysis->mp_operations |= 0x40; |
3559 | nbOptionsChanged++; |
3560 | } |
3561 | if((tcpd->mptcp_analysis->mp_operations&(0x80))!=tcph->th_mptcp->mh_fastclose) { |
3562 | tcpd->mptcp_analysis->mp_operations |= 0x80; |
3563 | nbOptionsChanged++; |
3564 | } |
3565 | /* we could track MPTCP option changes here, with nbOptionsChanged */ |
3566 | #endif |
3567 | |
3568 | item = proto_tree_add_uint(tree, hf_mptcp_stream, tvb, 0, 0, mptcpd->stream); |
3569 | proto_item_set_generated(item); |
3570 | |
3571 | /* retrieve saved analysis of packets, else create it */ |
3572 | mptcppd = (mptcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mptcp, pinfo->curr_layer_num); |
3573 | if(!mptcppd) { |
3574 | mptcppd = (mptcp_per_packet_data_t *)wmem_new0(wmem_file_scope(), mptcp_per_packet_data_t)((mptcp_per_packet_data_t*)wmem_alloc0((wmem_file_scope()), sizeof (mptcp_per_packet_data_t))); |
3575 | p_add_proto_data(wmem_file_scope(), pinfo, proto_mptcp, pinfo->curr_layer_num, mptcppd); |
3576 | } |
3577 | |
3578 | /* Print formatted list of tcp stream ids that are part of the connection */ |
3579 | mptcp_analysis_add_subflows(pinfo, tvb, tree, mptcpd); |
3580 | |
3581 | /* Converts TCP seq number into its MPTCP DSN */ |
3582 | mptcp_analysis_dsn_lookup(pinfo, tvb, tree, tcpd, tcph, mptcppd); |
3583 | |
3584 | } |
3585 | |
3586 | |
3587 | static void |
3588 | tcp_sequence_number_analysis_print_push_bytes_sent(packet_info * pinfo _U___attribute__((unused)), |
3589 | tvbuff_t * tvb, |
3590 | proto_tree * flags_tree, |
3591 | struct tcp_acked *ta |
3592 | ) |
3593 | { |
3594 | proto_item * flags_item; |
3595 | |
3596 | if (tcp_track_bytes_in_flight) { |
3597 | flags_item=proto_tree_add_uint(flags_tree, |
3598 | hf_tcp_analysis_push_bytes_sent, |
3599 | tvb, 0, 0, ta->push_bytes_sent); |
3600 | |
3601 | proto_item_set_generated(flags_item); |
3602 | } |
3603 | } |
3604 | |
3605 | static void |
3606 | tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, |
3607 | struct tcp_analysis *tcpd, guint32 seq, guint32 ack) |
3608 | { |
3609 | struct tcp_acked *ta = NULL((void*)0); |
3610 | proto_item *item; |
3611 | proto_tree *tree; |
3612 | proto_tree *flags_tree=NULL((void*)0); |
3613 | |
3614 | if (!tcpd) { |
3615 | return; |
3616 | } |
3617 | if(!tcpd->ta) { |
3618 | tcp_analyze_get_acked_struct(pinfo->num, seq, ack, FALSE(0), tcpd); |
3619 | } |
3620 | ta=tcpd->ta; |
3621 | if(!ta) { |
3622 | return; |
3623 | } |
3624 | |
3625 | item=proto_tree_add_item(parent_tree, hf_tcp_analysis, tvb, 0, 0, ENC_NA0x00000000); |
3626 | proto_item_set_generated(item); |
3627 | tree=proto_item_add_subtree(item, ett_tcp_analysis); |
3628 | |
3629 | /* encapsulate all proto_tree_add_xxx in ifs so we only print what |
3630 | data we actually have */ |
3631 | if(ta->frame_acked) { |
3632 | item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame, |
3633 | tvb, 0, 0, ta->frame_acked); |
3634 | proto_item_set_generated(item); |
3635 | |
3636 | if(ta->partial_ack) { |
3637 | expert_add_info(pinfo, item, &ei_tcp_analysis_partial_ack); |
3638 | } |
3639 | |
3640 | /* only display RTT if we actually have something we are acking */ |
3641 | if( ta->ts.secs || ta->ts.nsecs ) { |
3642 | item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt, |
3643 | tvb, 0, 0, &ta->ts); |
3644 | proto_item_set_generated(item); |
3645 | } |
3646 | } |
3647 | if (!nstime_is_zero(&tcpd->ts_first_rtt)) { |
3648 | item = proto_tree_add_time(tree, hf_tcp_analysis_first_rtt, |
3649 | tvb, 0, 0, &(tcpd->ts_first_rtt)); |
3650 | proto_item_set_generated(item); |
3651 | } |
3652 | |
3653 | if(ta->bytes_in_flight) { |
3654 | /* print results for amount of data in flight */ |
3655 | tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta); |
3656 | tcp_sequence_number_analysis_print_push_bytes_sent(pinfo, tvb, tree, ta); |
3657 | } |
3658 | |
3659 | if(ta->flags) { |
3660 | item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, 0, ENC_NA0x00000000); |
3661 | proto_item_set_generated(item); |
3662 | flags_tree=proto_item_add_subtree(item, ett_tcp_analysis); |
3663 | |
3664 | /* print results for reused tcp ports */ |
3665 | tcp_sequence_number_analysis_print_reused(pinfo, item, ta); |
3666 | |
3667 | /* print results for retransmission and out-of-order segments */ |
3668 | tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, item, ta); |
3669 | |
3670 | /* print results for lost tcp segments */ |
3671 | tcp_sequence_number_analysis_print_lost(pinfo, item, ta); |
3672 | |
3673 | /* print results for tcp window information */ |
3674 | tcp_sequence_number_analysis_print_window(pinfo, item, ta); |
3675 | |
3676 | /* print results for tcp keep alive information */ |
3677 | tcp_sequence_number_analysis_print_keepalive(pinfo, item, ta); |
3678 | |
3679 | /* print results for tcp duplicate acks */ |
3680 | tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree); |
3681 | |
3682 | /* print results for tcp zero window */ |
3683 | tcp_sequence_number_analysis_print_zero_window(pinfo, item, ta); |
3684 | |
3685 | } |
3686 | |
3687 | } |
3688 | |
3689 | static void |
3690 | print_tcp_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *tcp_tree, packet_info *pinfo, tvbuff_t *next_tvb) |
3691 | { |
3692 | proto_item *tcp_tree_item, *frag_tree_item; |
3693 | |
3694 | /* |
3695 | * The subdissector thought it was completely |
3696 | * desegmented (although the stuff at the |
3697 | * end may, in turn, require desegmentation), |
3698 | * so we show a tree with all segments. |
3699 | */ |
3700 | show_fragment_tree(ipfd_head, &tcp_segment_items, |
3701 | tree, pinfo, next_tvb, &frag_tree_item); |
3702 | /* |
3703 | * The toplevel fragment subtree is now |
3704 | * behind all desegmented data; move it |
3705 | * right behind the TCP tree. |
3706 | */ |
3707 | tcp_tree_item = proto_tree_get_parent(tcp_tree); |
3708 | if(frag_tree_item && tcp_tree_item) { |
3709 | proto_tree_move_item(tree, tcp_tree_item, frag_tree_item); |
3710 | } |
3711 | } |
3712 | |
3713 | /* ************************************************************************** |
3714 | * End of tcp sequence number analysis |
3715 | * **************************************************************************/ |
3716 | |
3717 | |
3718 | /* Minimum TCP header length. */ |
3719 | #define TCPH_MIN_LEN20 20 |
3720 | |
3721 | /* Desegmentation of TCP streams */ |
3722 | |
3723 | /* The primary ID is the first frame of a multisegment PDU, which is |
3724 | * most likely unique in the capture (unlike sequence numbers which |
3725 | * can be re-used, especially when relative sequence numbers are enabled). |
3726 | * However, frames can have multiple PDUs with certain encapsulations like |
3727 | * GSE or MPE over DVB BaseBand Frames. |
3728 | */ |
3729 | |
3730 | typedef struct _tcp_endpoint { |
3731 | |
3732 | address src_addr; |
3733 | address dst_addr; |
3734 | port_type ptype; |
3735 | guint32 src_port; |
3736 | guint32 dst_port; |
3737 | } tcp_endpoint_t; |
3738 | |
3739 | static void |
3740 | save_endpoint(packet_info *pinfo, tcp_endpoint_t *a) |
3741 | { |
3742 | copy_address_shallow(&a->src_addr, &pinfo->src); |
3743 | copy_address_shallow(&a->dst_addr, &pinfo->dst); |
3744 | a->ptype = pinfo->ptype; |
3745 | a->src_port = pinfo->srcport; |
3746 | a->dst_port = pinfo->destport; |
3747 | } |
3748 | |
3749 | static void |
3750 | restore_endpoint(packet_info *pinfo, tcp_endpoint_t *a) |
3751 | { |
3752 | copy_address_shallow(&pinfo->src, &a->src_addr); |
3753 | copy_address_shallow(&pinfo->dst, &a->dst_addr); |
3754 | pinfo->ptype = a->ptype; |
3755 | pinfo->srcport = a->src_port; |
3756 | pinfo->destport = a->dst_port; |
3757 | } |
3758 | |
3759 | typedef struct _tcp_segment_key { |
3760 | address src_addr; |
3761 | address dst_addr; |
3762 | guint32 src_port; |
3763 | guint32 dst_port; |
3764 | guint32 id; /* msp->first_frame */ |
3765 | guint32 seq; /* msp->seq */ |
3766 | } tcp_segment_key; |
3767 | |
3768 | static guint |
3769 | tcp_segment_hash(gconstpointer k) |
3770 | { |
3771 | const tcp_segment_key* key = (const tcp_segment_key*) k; |
3772 | guint hash_val; |
3773 | |
3774 | hash_val = key->id; |
3775 | |
3776 | /* In most captures there is only one fragment per id / first_frame, |
3777 | so we only use it in the hash as an optimization. |
3778 | |
3779 | int i; |
3780 | for (i = 0; i < key->src.len; i++) |
3781 | hash_val += key->src_addr.data[i]; |
3782 | for (i = 0; i < key->dst.len; i++) |
3783 | hash_val += key->dst_addr.data[i]; |
3784 | hash_val += key->src_port; |
3785 | hash_val += key->dst_port; |
3786 | hash_val += key->seq; |
3787 | */ |
3788 | |
3789 | return hash_val; |
3790 | } |
3791 | |
3792 | static gint |
3793 | tcp_segment_equal(gconstpointer k1, gconstpointer k2) |
3794 | { |
3795 | const tcp_segment_key* key1 = (const tcp_segment_key*) k1; |
3796 | const tcp_segment_key* key2 = (const tcp_segment_key*) k2; |
3797 | |
3798 | /* |
3799 | * key.id is the first item to compare since it's the item most |
3800 | * likely to differ between sessions, thus short-circuiting |
3801 | * the comparison of addresses and ports. |
3802 | */ |
3803 | return (key1->id == key2->id) && |
3804 | (addresses_equal(&key1->src_addr, &key2->src_addr)) && |
3805 | (addresses_equal(&key1->dst_addr, &key2->dst_addr)) && |
3806 | (key1->src_port == key2->src_port) && |
3807 | (key1->dst_port == key2->dst_port) && |
3808 | (key1->seq == key2->seq); |
3809 | } |
3810 | |
3811 | /* |
3812 | * Create a fragment key for temporary use; it can point to non- |
3813 | * persistent data, and so must only be used to look up and |
3814 | * delete entries, not to add them. |
3815 | */ |
3816 | static gpointer |
3817 | tcp_segment_temporary_key(const packet_info *pinfo, const guint32 id, |
3818 | const void *data) |
3819 | { |
3820 | struct tcp_multisegment_pdu *msp = (struct tcp_multisegment_pdu*)data; |
3821 | DISSECTOR_ASSERT(msp)((void) ((msp) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3821, "msp")))); |
3822 | tcp_segment_key *key = g_slice_new(tcp_segment_key)((tcp_segment_key*) g_slice_alloc (sizeof (tcp_segment_key))); |
3823 | |
3824 | /* |
3825 | * Do a shallow copy of the addresses. |
3826 | */ |
3827 | copy_address_shallow(&key->src_addr, &pinfo->src); |
3828 | copy_address_shallow(&key->dst_addr, &pinfo->dst); |
3829 | key->src_port = pinfo->srcport; |
3830 | key->dst_port = pinfo->destport; |
3831 | key->id = id; |
3832 | key->seq = msp->seq; |
3833 | |
3834 | return (gpointer)key; |
3835 | } |
3836 | |
3837 | /* |
3838 | * Create a fragment key for permanent use; it must point to persistent |
3839 | * data, so that it can be used to add entries. |
3840 | */ |
3841 | static gpointer |
3842 | tcp_segment_persistent_key(const packet_info *pinfo, |
3843 | const guint32 id, const void *data) |
3844 | { |
3845 | struct tcp_multisegment_pdu *msp = (struct tcp_multisegment_pdu*)data; |
3846 | DISSECTOR_ASSERT(msp)((void) ((msp) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3846, "msp")))); |
3847 | tcp_segment_key *key = g_slice_new(tcp_segment_key)((tcp_segment_key*) g_slice_alloc (sizeof (tcp_segment_key))); |
3848 | |
3849 | /* |
3850 | * Do a deep copy of the addresses. |
3851 | */ |
3852 | copy_address(&key->src_addr, &pinfo->src); |
3853 | copy_address(&key->dst_addr, &pinfo->dst); |
3854 | key->src_port = pinfo->srcport; |
3855 | key->dst_port = pinfo->destport; |
3856 | key->id = id; |
3857 | key->seq = msp->seq; |
3858 | |
3859 | return (gpointer)key; |
3860 | } |
3861 | |
3862 | static void |
3863 | tcp_segment_free_temporary_key(gpointer ptr) |
3864 | { |
3865 | tcp_segment_key *key = (tcp_segment_key *)ptr; |
3866 | g_slice_free(tcp_segment_key, key)do { if (1) g_slice_free1 (sizeof (tcp_segment_key), (key)); else (void) ((tcp_segment_key*) 0 == (key)); } while (0); |
3867 | } |
3868 | |
3869 | static void |
3870 | tcp_segment_free_persistent_key(gpointer ptr) |
3871 | { |
3872 | tcp_segment_key *key = (tcp_segment_key *)ptr; |
3873 | |
3874 | if(key){ |
3875 | /* |
3876 | * Free up the copies of the addresses from the old key. |
3877 | */ |
3878 | free_address(&key->src_addr); |
3879 | free_address(&key->dst_addr); |
3880 | |
3881 | g_slice_free(tcp_segment_key, key)do { if (1) g_slice_free1 (sizeof (tcp_segment_key), (key)); else (void) ((tcp_segment_key*) 0 == (key)); } while (0); |
3882 | } |
3883 | } |
3884 | |
3885 | const reassembly_table_functions |
3886 | tcp_reassembly_table_functions = { |
3887 | tcp_segment_hash, |
3888 | tcp_segment_equal, |
3889 | tcp_segment_temporary_key, |
3890 | tcp_segment_persistent_key, |
3891 | tcp_segment_free_temporary_key, |
3892 | tcp_segment_free_persistent_key |
3893 | }; |
3894 | |
3895 | static reassembly_table tcp_reassembly_table; |
3896 | |
3897 | /* functions to trace tcp segments */ |
3898 | /* Enable desegmenting of TCP streams */ |
3899 | static bool_Bool tcp_desegment = true1; |
3900 | |
3901 | /* Returns the maximum contiguous sequence number of the reassembly associated |
3902 | * with the msp *if* a new fragment were added ending in the given maxnextseq. |
3903 | * The new fragment is from the current frame and may not have been added yet. |
3904 | */ |
3905 | static guint32 |
3906 | find_maxnextseq(packet_info *pinfo, struct tcp_multisegment_pdu *msp, guint32 maxnextseq) |
3907 | { |
3908 | fragment_head *fd_head; |
3909 | |
3910 | DISSECTOR_ASSERT(msp)((void) ((msp) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3910, "msp")))); |
3911 | |
3912 | fd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp); |
3913 | /* msp implies existence of fragments, this should never be NULL. */ |
3914 | DISSECTOR_ASSERT(fd_head)((void) ((fd_head) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3914, "fd_head")))); |
3915 | |
3916 | /* Find length of contiguous fragments. |
3917 | * Start with the first gap, but the new fragment is allowed to |
3918 | * fill that gap. */ |
3919 | guint32 max_len = maxnextseq - msp->seq; |
3920 | fragment_item* frag = (fd_head->first_gap) ? fd_head->first_gap : fd_head->next; |
3921 | for (; frag && frag->offset <= max_len; frag = frag->next) { |
3922 | max_len = MAX(max_len, frag->offset + frag->len)(((max_len) > (frag->offset + frag->len)) ? (max_len ) : (frag->offset + frag->len)); |
3923 | } |
3924 | |
3925 | return max_len + msp->seq; |
3926 | } |
3927 | |
3928 | static struct tcp_multisegment_pdu* |
3929 | split_msp(packet_info *pinfo, struct tcp_multisegment_pdu *msp, struct tcp_analysis *tcpd) |
3930 | { |
3931 | fragment_head *fd_head; |
3932 | guint32 first_frame = 0; |
3933 | guint32 last_frame = 0; |
3934 | const guint32 split_offset = pinfo->desegment_offset; |
3935 | |
3936 | fd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp); |
3937 | /* This is for splitting defragmented MSPs, so fd_head should exist |
3938 | * and be defragmented. This also ensures that fd_i->tvb_data exists. |
3939 | */ |
3940 | DISSECTOR_ASSERT(fd_head && fd_head->flags & FD_DEFRAGMENTED)((void) ((fd_head && fd_head->flags & 0x0001) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3940, "fd_head && fd_head->flags & 0x0001" )))); |
3941 | |
3942 | fragment_item *fd_i, *first_frag = NULL((void*)0); |
3943 | |
3944 | /* The fragment list is sorted in offset order, but not nec. frame order |
3945 | * or end offset order due to out of order reassembly and possible overlap. |
3946 | * fd_i->offset < split_offset - some bytes are before the split |
3947 | * fd_i->offset + fd_i->len >= split_offset - some bytes are after split |
3948 | * Look through all the fragments that have some data before the split point. |
3949 | */ |
3950 | for (fd_i = fd_head->next; fd_i && (fd_i->offset < split_offset); fd_i = fd_i->next) { |
3951 | if (last_frame < fd_i->frame) { |
3952 | last_frame = fd_i->frame; |
3953 | } |
3954 | if (fd_i->offset + fd_i->len >= split_offset) { |
3955 | if (first_frag == NULL((void*)0)) { |
3956 | first_frag = fd_i; |
3957 | first_frame = fd_i->frame; |
3958 | } else if (fd_i->frame < first_frame) { |
3959 | first_frame = fd_i->frame; |
3960 | } |
3961 | } |
3962 | }; |
3963 | |
3964 | /* Now look through all the remaining fragments that only have bytes after |
3965 | * the split. |
3966 | */ |
3967 | for (; fd_i; fd_i = fd_i->next) { |
3968 | guint32 frag_end = fd_i->offset + fd_i->len; |
3969 | if (split_offset <= frag_end && fd_i->frame < first_frame) { |
3970 | first_frame = fd_i->frame; |
3971 | } |
3972 | } |
3973 | |
3974 | /* We only call this when the frame the fragments were reassembled in |
3975 | * (which is the current frame) includes some data before the split |
3976 | * point, so that it won't change and we can be consistent dissecting |
3977 | * between passes. We also should have at least some data after the |
3978 | * split point (because the subdissector claimed there was undissected |
3979 | * data.) |
3980 | */ |
3981 | DISSECTOR_ASSERT(fd_head->reassembled_in == last_frame)((void) ((fd_head->reassembled_in == last_frame) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 3981, "fd_head->reassembled_in == last_frame" )))); |
3982 | DISSECTOR_ASSERT(first_frag != NULL)((void) ((first_frag != ((void*)0)) ? (void)0 : (proto_report_dissector_bug ("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c" , 3982, "first_frag != ((void*)0)")))); |
3983 | |
3984 | guint32 new_seq = msp->seq + pinfo->desegment_offset; |
3985 | struct tcp_multisegment_pdu *newmsp; |
3986 | newmsp = pdu_store_sequencenumber_of_next_pdu(pinfo, new_seq, |
3987 | new_seq+1, tcpd->fwd->multisegment_pdus); |
3988 | newmsp->first_frame = first_frame; |
3989 | newmsp->nxtpdu = msp->nxtpdu; |
3990 | |
3991 | /* XXX: Could do the adding the new fragments in fragment_truncate */ |
3992 | for (fd_i = first_frag; fd_i; fd_i = fd_i->next) { |
3993 | guint32 frag_offset = fd_i->offset; |
3994 | guint32 frag_len = fd_i->len; |
3995 | /* Check for some unusual out of order overlapping segment situations. */ |
3996 | if (split_offset < frag_offset + frag_len) { |
3997 | if (fd_i->offset < split_offset) { |
3998 | frag_offset = split_offset; |
3999 | frag_len -= (split_offset - fd_i->offset); |
4000 | } |
4001 | fragment_add_out_of_order(&tcp_reassembly_table, fd_head->tvb_data, |
4002 | frag_offset, pinfo, first_frame, newmsp, |
4003 | frag_offset - split_offset, frag_len, TRUE(!(0)), fd_i->frame); |
4004 | } |
4005 | } |
4006 | |
4007 | fragment_truncate(&tcp_reassembly_table, pinfo, msp->first_frame, msp, split_offset); |
4008 | msp->nxtpdu = msp->seq + split_offset; |
4009 | |
4010 | /* The newmsp nxtpdu will be adjusted after leaving this function. */ |
4011 | return newmsp; |
4012 | } |
4013 | |
4014 | typedef struct _ooo_segment_item { |
4015 | guint32 frame; |
4016 | guint32 seq; |
4017 | guint32 len; |
4018 | guint8 *data; |
4019 | } ooo_segment_item; |
4020 | |
4021 | static gint |
4022 | compare_ooo_segment_item(gconstpointer a, gconstpointer b) |
4023 | { |
4024 | const ooo_segment_item *fd_a = a; |
4025 | const ooo_segment_item *fd_b = b; |
4026 | |
4027 | /* We only insert segments into this list that satisfy |
4028 | * LT_SEQ(tcpd->fwd->maxnextseq, seq), for the current value |
4029 | * of maxnextseq (removing segments when maxnextseq is advanced) |
4030 | * so these rollover-aware comparisons are transitive over the |
4031 | * domain (never greater than 2^31). |
4032 | */ |
4033 | if (LT_SEQ(fd_a->seq, fd_b->seq)((gint32)((fd_a->seq) - (fd_b->seq)) < 0)) |
4034 | return -1; |
4035 | |
4036 | if (GT_SEQ(fd_a->seq, fd_b->seq)((gint32)((fd_b->seq) - (fd_a->seq)) < 0)) |
4037 | return 1; |
4038 | |
4039 | if (fd_a->frame < fd_b->frame) |
4040 | return -1; |
4041 | |
4042 | if (fd_a->frame > fd_b->frame) |
4043 | return 1; |
4044 | |
4045 | return 0; |
4046 | } |
4047 | |
4048 | /* Search through our list of out of order segments and add the ones that are |
4049 | * now contiguous onto a MSP until we use them all or reach another gap. |
4050 | * |
4051 | * If the MSP parameter is a incomplete, returns it with any OOO segments added. |
4052 | * If the MSP parameter is NULL or complete, returns a newly created MSP with |
4053 | * OOO segments added, or NULL if there were no segments to add. |
4054 | */ |
4055 | static struct tcp_multisegment_pdu * |
4056 | msp_add_out_of_order(packet_info *pinfo, struct tcp_multisegment_pdu *msp, struct tcp_analysis *tcpd, guint32 seq) |
4057 | { |
4058 | |
4059 | /* Whether a previous MSP exists with missing segments. */ |
4060 | gboolean has_unfinished_msp = msp && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002); |
4061 | bool_Bool updated_maxnextseq = FALSE(0); |
4062 | |
4063 | if (msp) { |
4064 | guint32 maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq); |
4065 | if (LE_SEQ(tcpd->fwd->maxnextseq, maxnextseq)((gint32)((tcpd->fwd->maxnextseq) - (maxnextseq)) <= 0)) { |
4066 | tcpd->fwd->maxnextseq = maxnextseq; |
4067 | } |
4068 | updated_maxnextseq = TRUE(!(0)); |
4069 | } |
4070 | wmem_list_frame_t *curr_entry; |
4071 | curr_entry = wmem_list_head(tcpd->fwd->ooo_segments); |
4072 | ooo_segment_item *fd; |
4073 | tvbuff_t *tvb_data; |
4074 | while (curr_entry) { |
4075 | fd = (ooo_segment_item *)wmem_list_frame_data(curr_entry); |
4076 | if (LT_SEQ(tcpd->fwd->maxnextseq, fd->seq)((gint32)((tcpd->fwd->maxnextseq) - (fd->seq)) < 0 )) { |
4077 | /* There might be segments already added to the msp that now extend |
4078 | * the maximum contiguous sequence number. Check for them. */ |
4079 | if (msp && !updated_maxnextseq) { |
4080 | tcpd->fwd->maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq); |
4081 | updated_maxnextseq = TRUE(!(0)); |
4082 | } |
4083 | if (LT_SEQ(tcpd->fwd->maxnextseq, fd->seq)((gint32)((tcpd->fwd->maxnextseq) - (fd->seq)) < 0 )) { |
4084 | break; |
4085 | } |
4086 | } |
4087 | /* We have filled in the gap, so this out of order |
4088 | * segment is now contiguous and can be processed along |
4089 | * with the segment we just received. |
4090 | */ |
4091 | tcpd->fwd->maxnextseq = fd->seq + fd->len; |
4092 | tvb_data = tvb_new_real_data(fd->data, fd->len, fd->len); |
4093 | if (has_unfinished_msp) { |
4094 | |
4095 | /* Increase the expected MSP size if necessary. Yes, the |
4096 | * subdissector may have told us that a PDU ended here, but we |
4097 | * might have enough newly contiguous data to dissect another |
4098 | * PDU past that, and we should send that to the subdissector |
4099 | * too. */ |
4100 | if (LT_SEQ(msp->nxtpdu, fd->seq + fd->len)((gint32)((msp->nxtpdu) - (fd->seq + fd->len)) < 0 )) { |
4101 | msp->nxtpdu = fd->seq + fd->len; |
4102 | } |
4103 | /* Add this OOO segment to the unfinished MSP */ |
4104 | fragment_add_out_of_order(&tcp_reassembly_table, |
4105 | tvb_data, 0, |
4106 | pinfo, msp->first_frame, msp, |
4107 | fd->seq - msp->seq, fd->len, |
4108 | msp->nxtpdu, fd->frame); |
4109 | } else { |
4110 | /* No MSP in progress, so create one starting |
4111 | * at the sequence number of segment received |
4112 | * in this frame. Note that we will be adding |
4113 | * the first segment below, and this is the frame |
4114 | * of the first segment, so first_frame_with_seq |
4115 | * is already correct (and unnecessary) and |
4116 | * we don't need MSP_FLAGS_MISSING_FIRST_SEGMENT. */ |
4117 | msp = pdu_store_sequencenumber_of_next_pdu(pinfo, |
4118 | seq, fd->seq + fd->len, |
4119 | tcpd->fwd->multisegment_pdus); |
4120 | fragment_add_out_of_order(&tcp_reassembly_table, |
4121 | tvb_data, 0, pinfo, msp->first_frame, |
4122 | msp, fd->seq - msp->seq, fd->len, |
4123 | msp->nxtpdu, fd->frame); |
4124 | has_unfinished_msp = TRUE(!(0)); |
4125 | } |
4126 | updated_maxnextseq = FALSE(0); |
4127 | tvb_free(tvb_data); |
4128 | wmem_list_remove_frame(tcpd->fwd->ooo_segments, curr_entry); |
4129 | curr_entry = wmem_list_head(tcpd->fwd->ooo_segments); |
4130 | |
4131 | } |
4132 | /* There might be segments already added to the msp that now extend |
4133 | * the maximum contiguous sequence number. Check for them. */ |
4134 | if (msp && !updated_maxnextseq) { |
4135 | tcpd->fwd->maxnextseq = find_maxnextseq(pinfo, msp, tcpd->fwd->maxnextseq); |
4136 | } |
4137 | return msp; |
4138 | } |
4139 | |
4140 | static void |
4141 | desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset, |
4142 | guint32 seq, guint32 nxtseq, |
4143 | guint32 sport, guint32 dport, |
4144 | proto_tree *tree, proto_tree *tcp_tree, |
4145 | struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo) |
4146 | { |
4147 | fragment_head *ipfd_head; |
4148 | int last_fragment_len; |
4149 | gboolean must_desegment; |
4150 | gboolean called_dissector; |
4151 | gboolean has_gap; |
4152 | int another_pdu_follows; |
4153 | int deseg_offset; |
4154 | guint32 deseg_seq; |
4155 | gint nbytes; |
4156 | proto_item *item; |
4157 | struct tcp_multisegment_pdu *msp; |
4158 | gboolean cleared_writable = col_get_writable(pinfo->cinfo, COL_PROTOCOL); |
4159 | gboolean first_pdu = TRUE(!(0)); |
4160 | const gboolean reassemble_ooo = tcp_analyze_seq && tcp_desegment && tcp_reassemble_out_of_order && tcpd && tcpd->fwd->ooo_segments; |
4161 | |
4162 | tcp_endpoint_t orig_endpoint, new_endpoint; |
4163 | |
4164 | save_endpoint(pinfo, &orig_endpoint); |
4165 | save_endpoint(pinfo, &new_endpoint); |
4166 | |
4167 | again: |
4168 | ipfd_head = NULL((void*)0); |
4169 | last_fragment_len = 0; |
4170 | must_desegment = FALSE(0); |
4171 | called_dissector = FALSE(0); |
4172 | has_gap = FALSE(0); |
4173 | another_pdu_follows = 0; |
4174 | msp = NULL((void*)0); |
4175 | |
4176 | /* |
4177 | * Initialize these to assume no desegmentation. |
4178 | * If that's not the case, these will be set appropriately |
4179 | * by the subdissector. |
4180 | */ |
4181 | pinfo->desegment_offset = 0; |
4182 | pinfo->desegment_len = 0; |
4183 | |
4184 | /* |
4185 | * Initialize this to assume that this segment will just be |
4186 | * added to the middle of a desegmented chunk of data, so |
4187 | * that we should show it all as data. |
4188 | * If that's not the case, it will be set appropriately. |
4189 | */ |
4190 | deseg_offset = offset; |
4191 | |
4192 | /* |
4193 | * TODO: Some notes on current limitations with TCP desegmentation: |
4194 | * |
4195 | * This function can be called with either relative or absolute sequence |
4196 | * numbers; the ??_SEQ macros are called for comparisons to deal with |
4197 | * with sequence number rollover. (With relative sequence numbers, if |
4198 | * early TCP segments are received out of order before the SYN it can be |
4199 | * possible for rollover to occur at the very beginning of a connection.) |
4200 | * |
4201 | * However, multi-segment PDU lookup does not work for MSPs that span |
4202 | * TCP sequence number rollover, and desegmentation fails. |
4203 | * |
4204 | * When there is a single TCP connection that is longer than 4 GiB and |
4205 | * thus sequence numbers are reused, multi-segment PDU lookup and |
4206 | * retransmission identification does not work. (Bug 10503). |
4207 | * |
4208 | * Distinguishing between sequence number reuse on a very long connection |
4209 | * and sequence number reuse due to retransmission is difficult. Right |
4210 | * now very long connections are just not handled as the rarer case. |
4211 | * Perhaps retransmission identification could be entirely left up to TCP |
4212 | * analysis (if enabled, not done at all if disabled), instead of TCP |
4213 | * analysis results only used to supplement work here? |
4214 | * |
4215 | * TCP sequence analysis can set TCP_A_RETRANSMISSION in cases where |
4216 | * we still need to process the segment anyway because something other |
4217 | * than the sequence number is different from the prior segment. That |
4218 | * includes "retransmitted but with additional data" (Bug 13523) and |
4219 | * "retransmitted due to bad checksum" (especially if checksum verification |
4220 | * is enabled.) |
4221 | * |
4222 | * "Reassemble out-of-order segments" uses its own method of detecting |
4223 | * retranmission, but uses more memory and CPU, and when used, a TCP stream |
4224 | * that has missing segments that are never retransmitted stop processing |
4225 | * after the missing segment. |
4226 | * |
4227 | * If multiple TCP/IP packets are encapsulated in the same frame (such |
4228 | * as with GSE, which has very long Baseband Frames) this causes issues: |
4229 | * |
4230 | * If a subdissector reports that it can handle a payload, but needs |
4231 | * more data (pinfo->desegment_len > 0) and did not actually dissect |
4232 | * any of it (pinfo->desegment_offset == 0), on the first pass it |
4233 | * still adds layers to the frame. On subsequent passes, the MSP created |
4234 | * (or extended) in the first pass means that the subdissector won't be |
4235 | * called at all. If there are other protocols contained in the frame |
4236 | * that are dissected on the second pass they will have different |
4237 | * layer numbers than in the first pass, which can disturb proto_data |
4238 | * lookup, reassembly, etc. (Bug 16109 describes this for TLS.) |
4239 | */ |
4240 | |
4241 | if (tcpd) { |
4242 | |
4243 | if (reassemble_ooo) { |
4244 | /* If we are reassembling out of order, we can do this retransmission |
4245 | * check. Anything before the latest consecutive sequence number we've |
4246 | * already processed is a retransmission (from the perspective of has |
4247 | * been passed to subdissectors; the judgment of TCP Sequence Analysis |
4248 | * may be different, because it considers RTO and ACKs and so forth). |
4249 | * |
4250 | * XXX: If these segments are part of incomplete MSPs, we pass them |
4251 | * to the reassembly code which tests for overlap conflicts. |
4252 | * For those which are part of completed reassemblies or not part |
4253 | * of MSPs, we just don't process them. The former would throw a |
4254 | * ReassemblyError, which is likely acceptable in the case of |
4255 | * retransmission of the same segment but not if retransmitted with |
4256 | * additional data, where we'd need to catch the exception to |
4257 | * process the extra data. For ones that were not added to MSPs at |
4258 | * all, we can't do much. (Bug #13061) |
4259 | * |
4260 | * Retransmissions of out of order segments after our latest |
4261 | * consecutive sequence number will all be stored and then eventually |
4262 | * put on multisegment PDUs and go to the reassembler, which should |
4263 | * be able to handle retransmission, as those are still incomplete. |
4264 | */ |
4265 | |
4266 | msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq); |
4267 | |
4268 | gboolean has_unfinished_msp = FALSE(0); |
4269 | if (msp && LE_SEQ(msp->seq, seq)((gint32)((msp->seq) - (seq)) <= 0) && GT_SEQ(msp->nxtpdu, seq)((gint32)((seq) - (msp->nxtpdu)) < 0) && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002)) { |
4270 | has_unfinished_msp = TRUE(!(0)); |
4271 | } |
4272 | |
4273 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && first_pdu) { |
4274 | if (tcpd->fwd->maxnextseq && LT_SEQ(seq, tcpd->fwd->maxnextseq)((gint32)((seq) - (tcpd->fwd->maxnextseq)) < 0) && !has_unfinished_msp) { |
4275 | if(!tcpd->ta) { |
4276 | tcp_analyze_get_acked_struct(pinfo->num, seq, tcpinfo->lastackseq, TRUE(!(0)), tcpd); |
4277 | } |
4278 | tcpd->ta->flags |= TCP_A_OLD_DATA0x8000; |
4279 | if (GT_SEQ(nxtseq, tcpd->fwd->maxnextseq)((gint32)((tcpd->fwd->maxnextseq) - (nxtseq)) < 0)) { |
4280 | tcpd->ta->new_data_seq = tcpd->fwd->maxnextseq; |
4281 | } else { |
4282 | tcpd->ta->new_data_seq = nxtseq; |
4283 | } |
4284 | } |
4285 | } |
4286 | |
4287 | if(tcpd->ta && first_pdu) { |
4288 | if((tcpd->ta->flags&TCP_A_OLD_DATA0x8000) == TCP_A_OLD_DATA0x8000) { |
4289 | nbytes = tcpd->ta->new_data_seq - seq; |
4290 | |
4291 | proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, |
4292 | offset, nbytes, NULL((void*)0), |
4293 | "Retransmitted TCP segment data (%u byte%s)", |
4294 | nbytes, plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s"))); |
4295 | |
4296 | offset += nbytes; |
4297 | seq = tcpd->ta->new_data_seq; |
4298 | first_pdu = FALSE(0); |
4299 | if (tvb_captured_length_remaining(tvb, offset) > 0) |
4300 | goto again; |
4301 | goto clean_exit; |
4302 | } |
4303 | } |
4304 | } else { |
4305 | |
4306 | /* Have we seen this PDU before (and is it the start of a multi- |
4307 | * segment PDU)? |
4308 | * |
4309 | * If the sequence number was seen before, it is part of a |
4310 | * retransmission if the whole segment fits within the MSP. |
4311 | * (But if this is this frame was already visited and the first frame of |
4312 | * the MSP matches the current frame, then it is not a retransmission, |
4313 | * but the start of a new MSP.) |
4314 | * |
4315 | * If only part of the segment fits in the MSP, then either: |
4316 | * - The previous segment included with the MSP was a Zero Window Probe |
4317 | * with one byte of data and the subdissector just asked for one more |
4318 | * byte. Do not mark it as retransmission (Bug 15427). |
4319 | * - Data was actually being retransmitted, but with additional data |
4320 | * (Bug 13523). Do not mark it as retransmission to handle the extra |
4321 | * bytes. (NOTE Due to the TCP_A_RETRANSMISSION check below, such |
4322 | * extra data will still be ignored.) |
4323 | * - The MSP contains multiple segments, but the subdissector finished |
4324 | * reassembly using a subset of the final segment (thus "msp->nxtpdu" |
4325 | * is smaller than the nxtseq of the previous segment). If that final |
4326 | * segment was retransmitted, then "nxtseq > msp->nxtpdu". |
4327 | * Unfortunately that will *not* be marked as retransmission here. |
4328 | * The next TCP_A_RETRANSMISSION hopefully takes care of it though. |
4329 | * |
4330 | * Only shortcircuit here when the first segment of the MSP is known, |
4331 | * and when this first segment is not one to complete the MSP. |
4332 | */ |
4333 | if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, seq)) && |
4334 | nxtseq <= msp->nxtpdu && |
4335 | !(msp->flags & MSP_FLAGS_MISSING_FIRST_SEGMENT0x00000004) && msp->last_frame != pinfo->num) { |
4336 | const char* str; |
4337 | gboolean is_retransmission = FALSE(0); |
4338 | |
4339 | /* Yes. This could be because we've dissected this frame before |
4340 | * or because this is a retransmission of a previously-seen |
4341 | * segment. Either way, we don't need to hand it off to the |
4342 | * subdissector and we certainly don't want to re-add it to the |
4343 | * multisegment_pdus list: if we did, subsequent lookups would |
4344 | * find this retransmission instead of the original transmission |
4345 | * (breaking desegmentation if we'd already linked other segments |
4346 | * to the original transmission's entry). |
4347 | * |
4348 | * Cases to handle here: |
4349 | * - In-order stream, pinfo->num matches begin of MSP. |
4350 | * - In-order stream, but pinfo->num does not match the begin of the |
4351 | * MSP. Must be a retransmission. |
4352 | * - OoO stream where this segment fills the gap in the begin of the |
4353 | * MSP. msp->first_frame is the start where the gap was detected |
4354 | * (and does NOT match pinfo->num). |
4355 | */ |
4356 | |
4357 | if (msp->first_frame == pinfo->num || msp->first_frame_with_seq == pinfo->num) { |
4358 | str = ""; |
4359 | } else { |
4360 | str = "Retransmitted "; |
4361 | is_retransmission = TRUE(!(0)); |
4362 | /* TCP analysis already flags this (in COL_INFO) as a retransmission--if it's enabled */ |
4363 | } |
4364 | |
4365 | /* Fix for bug 3264: look up ipfd for this (first) segment, |
4366 | so can add tcp.reassembled_in generated field on this code path. */ |
4367 | if (!is_retransmission) { |
4368 | ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp); |
4369 | if (ipfd_head) { |
4370 | if (ipfd_head->reassembled_in != 0) { |
4371 | item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0, |
4372 | 0, ipfd_head->reassembled_in); |
4373 | proto_item_set_generated(item); |
4374 | |
4375 | if (first_pdu) { |
4376 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[TCP PDU reassembled in %u]", |
4377 | ipfd_head->reassembled_in); |
4378 | } |
4379 | } |
4380 | } |
4381 | } |
4382 | |
4383 | nbytes = tvb_reported_length_remaining(tvb, offset); |
4384 | |
4385 | proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset, |
4386 | nbytes, NULL((void*)0), "%sTCP segment data (%u byte%s)", str, nbytes, |
4387 | plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s"))); |
4388 | goto clean_exit; |
4389 | } |
4390 | |
4391 | /* Else, find the most previous PDU starting before this sequence number */ |
4392 | if (!msp) { |
4393 | msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1); |
4394 | } |
4395 | |
4396 | gboolean has_unfinished_msp = FALSE(0); |
4397 | if (msp && LE_SEQ(msp->seq, seq)((gint32)((msp->seq) - (seq)) <= 0) && GT_SEQ(msp->nxtpdu, seq)((gint32)((seq) - (msp->nxtpdu)) < 0) && !(msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002)) { |
4398 | has_unfinished_msp = TRUE(!(0)); |
4399 | } |
4400 | |
4401 | /* The above code only finds retransmission if the PDU boundaries and the seq coincide |
4402 | * If we have sequence analysis active use the TCP_A_RETRANSMISSION flag. |
4403 | * XXXX Could the above code be improved? |
4404 | */ |
4405 | if(tcpd->ta) { |
4406 | /* If we have an unfinished MSP that this segment belongs to |
4407 | * or if the sequence number is newer than anything we've seen, |
4408 | * then this is Out of Order from the reassembly perspective |
4409 | * and we want to process it anyway. |
4410 | */ |
4411 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && tcpd->fwd->maxnextseq && LE_SEQ(seq, tcpd->fwd->maxnextseq)((gint32)((seq) - (tcpd->fwd->maxnextseq)) <= 0) && !has_unfinished_msp) { |
4412 | /* Otherwise, if TCP Analysis calls the segment a |
4413 | * Spurious Retransmission or Retransmission, ignore it |
4414 | * here and on future passes. |
4415 | * See issue 10289 |
4416 | * XXX: There are still some cases where TCP Analysis |
4417 | * marks segments as Retransmissions when they are |
4418 | * Out of Order from this perspective (#10725, #13843) |
4419 | */ |
4420 | if((tcpd->ta->flags&TCP_A_SPURIOUS_RETRANSMISSION0x4000) == TCP_A_SPURIOUS_RETRANSMISSION0x4000 || |
4421 | ((tcpd->ta->flags&TCP_A_RETRANSMISSION0x0001) == TCP_A_RETRANSMISSION0x0001)) { |
4422 | tcpd->ta->flags |= TCP_A_OLD_DATA0x8000; |
4423 | } |
4424 | } |
4425 | if((tcpd->ta->flags&TCP_A_OLD_DATA0x8000) == TCP_A_OLD_DATA0x8000) { |
4426 | const char* str = "Retransmitted "; |
4427 | nbytes = tvb_reported_length_remaining(tvb, offset); |
4428 | proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset, |
4429 | nbytes, NULL((void*)0), "%sTCP segment data (%u byte%s)", str, nbytes, |
4430 | plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s"))); |
4431 | goto clean_exit; |
4432 | } |
4433 | } |
4434 | } |
4435 | } |
4436 | |
4437 | if (reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001)) { |
4438 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4439 | /* If there is a gap between this segment and any previous ones |
4440 | * (that is, seqno is larger than the maximum expected seqno), then |
4441 | * it is possibly an out-of-order segment. The very first segment |
4442 | * is expected to be in-order though (otherwise captures starting |
4443 | * in midst of a connection would never be reassembled). |
4444 | * (maxnextseq is 0 if we have not seen a SYN packet, even with |
4445 | * absolute sequence numbers.) |
4446 | * |
4447 | * Do not bother checking for OoO segments for streams that are |
4448 | * reassembled at FIN, the order of segments before FIN does not |
4449 | * matter as reordering and reassembly occurs at FIN. |
4450 | */ |
4451 | |
4452 | if (tcpd->fwd->maxnextseq) { |
4453 | /* Segments may be missing due to packet loss (assume later |
4454 | * retransmission) or out-of-order (assume it appears later). |
4455 | * |
4456 | * XXX: It would be nice to handle captures that have both |
4457 | * out-of-order packets and some lost packets that are |
4458 | * never retransmitted. But using the reverse flow ACK |
4459 | * (like follow_tcp_tap_listener) or using a known end of |
4460 | * a MSP (that we haven't fully received yet) to process a |
4461 | * segment that starts right afterwards would both break the |
4462 | * promise of in-order delivery, if a missing packet did arrive |
4463 | * later, which is a problem for any state-based dissector |
4464 | * (including TLS.) |
4465 | */ |
4466 | |
4467 | /* Whether the new segment has a gap from our latest contiguous |
4468 | * sequence number. */ |
4469 | has_gap = LT_SEQ(tcpd->fwd->maxnextseq, seq)((gint32)((tcpd->fwd->maxnextseq) - (seq)) < 0); |
4470 | } |
4471 | |
4472 | if (!has_gap) { |
4473 | /* Update the maximum expected seqno if no SYN packet was seen |
4474 | * before, or if the new segment succeeds previous segments. */ |
4475 | tcpd->fwd->maxnextseq = nxtseq; |
4476 | |
4477 | /* If there is no gap, look for any OOO packets that are now |
4478 | * contiguous. */ |
4479 | msp = msp_add_out_of_order(pinfo, msp, tcpd, seq); |
4480 | } |
4481 | } else { |
4482 | /* If we have visited this frame before, look for the frame in the |
4483 | * list of unused out of order segments. Since we know the gap will |
4484 | * never be filled, we could pass it to the subdissector, but |
4485 | * we want to be consistent between passes. |
4486 | */ |
4487 | ooo_segment_item *fd; |
4488 | fd = wmem_new0(pinfo->pool, ooo_segment_item)((ooo_segment_item*)wmem_alloc0((pinfo->pool), sizeof(ooo_segment_item ))); |
4489 | fd->frame = pinfo->num; |
4490 | fd->seq = seq; |
4491 | fd->len = nxtseq - seq; |
4492 | if (wmem_list_find_custom(tcpd->fwd->ooo_segments, fd, compare_ooo_segment_item)) { |
4493 | has_gap = TRUE(!(0)); |
4494 | } |
4495 | } |
4496 | } |
4497 | |
4498 | /* If we are not processing out of order, update the max nextseq value if |
4499 | * is later than our current value (or our first value.) |
4500 | */ |
4501 | if (!reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001)) { |
4502 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4503 | if (LT_SEQ(tcpd->fwd->maxnextseq, nxtseq)((gint32)((tcpd->fwd->maxnextseq) - (nxtseq)) < 0) || tcpd->fwd->maxnextseq == 0) { |
4504 | tcpd->fwd->maxnextseq = nxtseq; |
4505 | } |
4506 | } |
4507 | } |
4508 | |
4509 | if (msp && LE_SEQ(msp->seq, seq)((gint32)((msp->seq) - (seq)) <= 0) && GT_SEQ(msp->nxtpdu, seq)((gint32)((seq) - (msp->nxtpdu)) < 0)) { |
4510 | int len; |
4511 | |
4512 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4513 | msp->last_frame=pinfo->num; |
4514 | msp->last_frame_time=pinfo->abs_ts; |
4515 | } |
4516 | |
4517 | /* OK, this PDU was found, which means the segment continues |
4518 | * a higher-level PDU and that we must desegment it. |
4519 | */ |
4520 | if (msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001) { |
4521 | /* The dissector asked for the entire segment */ |
4522 | len = tvb_captured_length_remaining(tvb, offset); |
4523 | } else { |
4524 | /* Wraparound is possible, so subtraction does not |
4525 | * distribute across MIN(x, y) |
4526 | */ |
4527 | len = MIN(nxtseq - seq, msp->nxtpdu - seq)(((nxtseq - seq) < (msp->nxtpdu - seq)) ? (nxtseq - seq ) : (msp->nxtpdu - seq)); |
4528 | } |
4529 | last_fragment_len = len; |
4530 | |
4531 | |
4532 | if (reassemble_ooo && tcpd && !(tcpd->fwd->flags & TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001)) { |
4533 | /* |
4534 | * If the previous segment requested more data (setting |
4535 | * FD_PARTIAL_REASSEMBLY as the next segment length is unknown), but |
4536 | * subsequently an OoO segment was received (for an earlier hole), |
4537 | * then "fragment_add" would truncate the reassembled PDU to the end |
4538 | * of this OoO segment. To prevent that, explicitly specify the MSP |
4539 | * length before calling "fragment_add". |
4540 | * |
4541 | * When a subdissector requests reassembly at the end of the |
4542 | * connection (DESEGMENT_UNTIL_FIN), then it is not |
4543 | * possible for an earlier segment to complete reassembly |
4544 | * (more_frags for fragment_add is always TRUE). Thus we do not |
4545 | * have to worry about increasing the fragment length here. |
4546 | */ |
4547 | fragment_reset_tot_len(&tcp_reassembly_table, pinfo, |
4548 | msp->first_frame, msp, |
4549 | MAX(seq + len, msp->nxtpdu)(((seq + len) > (msp->nxtpdu)) ? (seq + len) : (msp-> nxtpdu)) - msp->seq); |
4550 | } |
4551 | |
4552 | ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset, |
4553 | pinfo, msp->first_frame, msp, |
4554 | seq - msp->seq, len, |
4555 | (LT_SEQ (nxtseq,msp->nxtpdu)((gint32)((nxtseq) - (msp->nxtpdu)) < 0)) ); |
4556 | |
4557 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && ipfd_head |
4558 | && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001) { |
4559 | msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001); |
4560 | |
4561 | /* If we consumed the entire segment there is no |
4562 | * other pdu starting anywhere inside this segment. |
4563 | * So update nxtpdu to point at least to the start |
4564 | * of the next segment. |
4565 | * (If the subdissector asks for even more data we |
4566 | * will advance nxtpdu even further later down in |
4567 | * the code.) |
4568 | */ |
4569 | if (LT_SEQ(msp->nxtpdu, nxtseq)((gint32)((msp->nxtpdu) - (nxtseq)) < 0)) { |
4570 | msp->nxtpdu = nxtseq; |
4571 | } |
4572 | } |
4573 | |
4574 | if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4575 | /* Remember when all segments are ready to avoid subsequent |
4576 | * out-of-order packets from extending this MSP. If a subsdissector |
4577 | * needs more segments, the flag will be cleared below. */ |
4578 | if (ipfd_head) { |
4579 | msp->flags |= MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002; |
4580 | } |
4581 | } |
4582 | |
4583 | if( (msp->nxtpdu < nxtseq) |
4584 | && (msp->nxtpdu >= seq) |
4585 | && (len > 0)) { |
4586 | another_pdu_follows=msp->nxtpdu - seq; |
4587 | } |
4588 | } else if (has_gap) { |
4589 | /* This is an OOO segment with a gap and past the known end of |
4590 | * the current MSP, if any. We don't know for certain which MSP |
4591 | * it belongs to, and the reassembly functions don't let us remove |
4592 | * fragment items added by mistake. Keep it around in a separate |
4593 | * structure, and add it later. |
4594 | * |
4595 | * On the second and later passes, we know that this gap will |
4596 | * never be filled in, so we could hand the segment to the |
4597 | * subdissector anyway. However, we want dissection to be |
4598 | * consistent between passes. |
4599 | */ |
4600 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4601 | ooo_segment_item *fd; |
4602 | fd = wmem_new0(wmem_file_scope(), ooo_segment_item)((ooo_segment_item*)wmem_alloc0((wmem_file_scope()), sizeof(ooo_segment_item ))); |
4603 | fd->frame = pinfo->num; |
4604 | fd->seq = seq; |
4605 | fd->len = nxtseq - seq; |
4606 | /* We only enter here if dissect_tcp set can_desegment, |
4607 | * which means that these bytes exist. */ |
4608 | fd->data = tvb_memdup(wmem_file_scope(), tvb, offset, fd->len); |
4609 | wmem_list_insert_sorted(tcpd->fwd->ooo_segments, fd, compare_ooo_segment_item); |
4610 | } |
4611 | ipfd_head = NULL((void*)0); |
4612 | } else { |
4613 | /* This segment was not found in our table, so it doesn't |
4614 | * contain a continuation of a higher-level PDU. |
4615 | * Call the normal subdissector. |
4616 | */ |
4617 | |
4618 | /* |
4619 | * Supply the sequence number of this segment. We set this here |
4620 | * because this segment could be after another in the same packet, |
4621 | * in which case seq was incremented at the end of the loop. |
4622 | */ |
4623 | tcpinfo->seq = seq; |
4624 | |
4625 | process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, |
4626 | sport, dport, 0, 0, FALSE(0), tcpd, tcpinfo); |
4627 | |
4628 | /* Unless it failed to dissect any data at all, the subdissector |
4629 | * might have changed the addresses and/or ports. Save them, and |
4630 | * set them back to the original values temporarily so that the |
4631 | * fragment functions work correctly (including in any later PDU.) |
4632 | * |
4633 | * (If we didn't dissect any data, the subdissector *shouldn't* |
4634 | * have changed the addresses or ports, so don't save them, but |
4635 | * restore them just in case.) |
4636 | */ |
4637 | if (!(pinfo->desegment_len && pinfo->desegment_offset == 0)) { |
4638 | save_endpoint(pinfo, &new_endpoint); |
4639 | } |
4640 | restore_endpoint(pinfo, &orig_endpoint); |
4641 | called_dissector = TRUE(!(0)); |
4642 | |
4643 | /* Did the subdissector ask us to desegment some more data |
4644 | * before it could handle the packet? |
4645 | * If so we'll have to handle that later. |
4646 | */ |
4647 | if(pinfo->desegment_len) { |
4648 | must_desegment = TRUE(!(0)); |
4649 | |
4650 | /* |
4651 | * Set "deseg_offset" to the offset in "tvb" |
4652 | * of the first byte of data that the |
4653 | * subdissector didn't process. |
4654 | */ |
4655 | deseg_offset = offset + pinfo->desegment_offset; |
4656 | } |
4657 | |
4658 | /* Either no desegmentation is necessary, or this is |
4659 | * segment contains the beginning but not the end of |
4660 | * a higher-level PDU and thus isn't completely |
4661 | * desegmented. |
4662 | */ |
4663 | ipfd_head = NULL((void*)0); |
4664 | } |
4665 | |
4666 | |
4667 | /* is it completely desegmented? */ |
4668 | if (ipfd_head) { |
4669 | /* |
4670 | * Yes, we think it is. |
4671 | * We only call subdissector for the last segment. |
4672 | * Note that the last segment may include more than what |
4673 | * we needed. |
4674 | */ |
4675 | if (ipfd_head->reassembled_in == pinfo->num && ipfd_head->reas_in_layer_num == pinfo->curr_layer_num) { |
4676 | /* |
4677 | * OK, this is the last segment. |
4678 | * Let's call the subdissector with the desegmented |
4679 | * data. |
4680 | */ |
4681 | tvbuff_t *next_tvb; |
4682 | |
4683 | /* create a new TVB structure for desegmented data */ |
4684 | next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data); |
4685 | |
4686 | /* add desegmented data to the data source list */ |
4687 | add_new_data_source(pinfo, next_tvb, "Reassembled TCP"); |
4688 | |
4689 | /* |
4690 | * Supply the sequence number of the first of the |
4691 | * reassembled bytes. |
4692 | */ |
4693 | tcpinfo->seq = msp->seq; |
4694 | |
4695 | /* indicate that this is reassembled data */ |
4696 | tcpinfo->is_reassembled = TRUE(!(0)); |
4697 | |
4698 | /* call subdissector */ |
4699 | process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, sport, |
4700 | dport, 0, 0, FALSE(0), tcpd, tcpinfo); |
4701 | |
4702 | /* Unless it failed to dissect any data at all, the subdissector |
4703 | * might have changed the addresses and/or ports. Save them, and |
4704 | * set them back to the original values temporarily so that the |
4705 | * fragment functions work correctly (including in any later PDU.) |
4706 | * |
4707 | * (If we didn't dissect any data, the subdissector *shouldn't* |
4708 | * have changed the addresses or ports, so don't save them, but |
4709 | * restore them just in case.) |
4710 | */ |
4711 | if (!(pinfo->desegment_len && pinfo->desegment_offset == 0)) { |
4712 | save_endpoint(pinfo, &new_endpoint); |
4713 | } |
4714 | restore_endpoint(pinfo, &orig_endpoint); |
4715 | called_dissector = TRUE(!(0)); |
4716 | |
4717 | /* |
4718 | * OK, did the subdissector think it was completely |
4719 | * desegmented, or does it think we need even more |
4720 | * data? |
4721 | */ |
4722 | if (pinfo->desegment_len) { |
4723 | /* |
4724 | * "desegment_len" isn't 0, so it needs more data |
4725 | * to fully dissect the current MSP. msp->nxtpdu was |
4726 | * not accurate and needs to be updated. |
4727 | * |
4728 | * This can happen if a dissector asked for one |
4729 | * more segment (but didn't know exactly how much data) |
4730 | * or if segments were added out of order. |
4731 | * |
4732 | * This is opposed to the current MSP being completely |
4733 | * desegmented, but the stuff at the end of the |
4734 | * current frame past last_fragment_len starting a new |
4735 | * higher-level PDU that may also need desegmentation. |
4736 | * That case is handled on the next loop. |
4737 | * |
4738 | * We want to keep the same dissection and protocol layer |
4739 | * numbers on subsequent passes. |
4740 | * |
4741 | * If "desegment_offset" is 0, then nothing in the reassembled |
4742 | * TCP segments was dissected, so remove the data source. |
4743 | */ |
4744 | if (pinfo->desegment_offset == 0) { |
4745 | if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4746 | msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002; |
4747 | } |
4748 | remove_last_data_source(pinfo); |
4749 | fragment_set_partial_reassembly(&tcp_reassembly_table, |
4750 | pinfo, msp->first_frame, |
4751 | msp); |
4752 | } else { |
4753 | /* If "desegment_offset" is not 0, then a PDU in the |
4754 | * reassembled segments was dissected, but some stuff |
4755 | * that was added previously is part of a later PDU. |
4756 | */ |
4757 | if (LE_SEQ(msp->seq + pinfo->desegment_offset, seq)((gint32)((msp->seq + pinfo->desegment_offset) - (seq)) <= 0)) { |
4758 | /* If we don't use anything from the current frame's |
4759 | * segment, then we can't split the msp. The frames of |
4760 | * the earlier PDU weren't reassembled until now, so |
4761 | * they need to point to a reassembled_in frame here |
4762 | * or later. |
4763 | * |
4764 | * Since this segment is the first of newly contiguous |
4765 | * segments, this means the subdissector is asking for |
4766 | * fewer bytes than it did before. |
4767 | * XXX: Report this as a dissector bug? |
4768 | */ |
4769 | if (reassemble_ooo && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4770 | msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS0x00000002; |
4771 | } |
4772 | fragment_set_partial_reassembly(&tcp_reassembly_table, |
4773 | pinfo, msp->first_frame, |
4774 | msp); |
4775 | } else { |
4776 | /* If we did use bytes from the current segment, then |
4777 | * we want to split the MSP; the earlier part is |
4778 | * dissected in this frame on the first pass, so for |
4779 | * consistency we want to do so on future passes, but |
4780 | * the latter part we cannot dissect until later. |
4781 | * We only need to do this on the first pass; split_msp |
4782 | * truncates the msp so we don't get here a second |
4783 | * time. |
4784 | */ |
4785 | /* nxtpdu adjustment for the new msp is the same. */ |
4786 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4787 | /* We don't need to clear MSP_FLAGS_GOT_ALL_SEGMENTS |
4788 | * since we are spliting the MSP. |
4789 | */ |
4790 | msp = split_msp(pinfo, msp, tcpd); |
4791 | } |
4792 | print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb); |
4793 | } |
4794 | } |
4795 | |
4796 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4797 | /* Update msp->nxtpdu to point to the new next |
4798 | * pdu boundary. |
4799 | * We only do this on the first pass, though we shouldn't |
4800 | * get here on a second pass (since we truncated the msp.) |
4801 | */ |
4802 | if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT0x0fffffff) { |
4803 | /* We want reassembly of at least one |
4804 | * more segment so set the nxtpdu |
4805 | * boundary to one byte into the next |
4806 | * segment. |
4807 | * This means that the next segment |
4808 | * will complete reassembly even if it |
4809 | * is only one single byte in length. |
4810 | * If this is an OoO segment, then increment |
4811 | * the MSP end. |
4812 | */ |
4813 | msp->nxtpdu = MAX(seq + tvb_reported_length_remaining(tvb, offset), msp->nxtpdu)(((seq + tvb_reported_length_remaining(tvb, offset)) > (msp ->nxtpdu)) ? (seq + tvb_reported_length_remaining(tvb, offset )) : (msp->nxtpdu)) + 1; |
4814 | msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001; |
4815 | } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) { |
4816 | tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001; |
4817 | /* This is not the first segment, and we thought the |
4818 | * reassembly would be done now, but now know we must |
4819 | * desgment until FIN. (E.g., HTTP Response with headers |
4820 | * split across segments, and no Content-Length or |
4821 | * Transfer-Encoding (RFC 7230, Section 3.3.3, case 7.) |
4822 | * For the same reasons as below when we encounter |
4823 | * DESEGMENT_UNTIL_FIN on the first segment, give |
4824 | * msp->nxtpdu a big (but not too big) offset so |
4825 | * reassembly will pick up the segments later. |
4826 | */ |
4827 | msp->nxtpdu = msp->seq + 0x40000000; |
4828 | } else { |
4829 | if (seq + last_fragment_len >= msp->nxtpdu) { |
4830 | /* This is the segment (overlapping) the end of |
4831 | * the MSP. |
4832 | */ |
4833 | msp->nxtpdu = seq + last_fragment_len + pinfo->desegment_len; |
4834 | } else { |
4835 | /* This is a segment before the end of the MSP, so |
4836 | * it must be an out-of-order segment that completed |
4837 | * the MSP. The requested additional data is |
4838 | * relative to that end. |
4839 | */ |
4840 | msp->nxtpdu += pinfo->desegment_len; |
4841 | } |
4842 | } |
4843 | } |
4844 | |
4845 | /* Since we need at least some more data |
4846 | * there can be no pdu following in the |
4847 | * tail of this segment. |
4848 | */ |
4849 | another_pdu_follows = 0; |
4850 | offset += last_fragment_len; |
4851 | seq += last_fragment_len; |
4852 | if (tvb_captured_length_remaining(tvb, offset) > 0) |
4853 | goto again; |
4854 | } else { |
4855 | /* |
4856 | * Show the stuff in this TCP segment as |
4857 | * just raw TCP segment data. |
4858 | */ |
4859 | nbytes = another_pdu_follows > 0 |
4860 | ? another_pdu_follows |
4861 | : tvb_reported_length_remaining(tvb, offset); |
4862 | proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset, |
4863 | nbytes, NULL((void*)0), "TCP segment data (%u byte%s)", nbytes, |
4864 | plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s"))); |
4865 | |
4866 | print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb); |
4867 | } |
4868 | } |
4869 | } |
4870 | |
4871 | if (must_desegment) { |
4872 | /* |
4873 | * The sequence number at which the stuff to be desegmented |
4874 | * starts is the sequence number of the byte at an offset |
4875 | * of "deseg_offset" into "tvb". |
4876 | * |
4877 | * The sequence number of the byte at an offset of "offset" |
4878 | * is "seq", i.e. the starting sequence number of this |
4879 | * segment, so the sequence number of the byte at |
4880 | * "deseg_offset" is "seq + (deseg_offset - offset)". |
4881 | */ |
4882 | deseg_seq = seq + (deseg_offset - offset); |
4883 | |
4884 | /* We have to create some structures in our table but |
4885 | * this is something we only do the first time we see this |
4886 | * packet. */ |
4887 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
4888 | /* If the dissector requested "reassemble until FIN" |
4889 | * just set this flag for the flow and let reassembly |
4890 | * proceed at normal. We will check/pick up these |
4891 | * reassembled PDUs later down in dissect_tcp() when checking |
4892 | * for the FIN flag. |
4893 | */ |
4894 | if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) { |
4895 | tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001; |
4896 | } |
4897 | if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)) { |
4898 | if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT0x0fffffff) { |
4899 | /* The subdissector asked to reassemble using the |
4900 | * entire next segment. |
4901 | * Just ask reassembly for one more byte |
4902 | * but set this msp flag so we can pick it up |
4903 | * above. |
4904 | */ |
4905 | msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq, |
4906 | nxtseq+1, tcpd->fwd->multisegment_pdus); |
4907 | msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001; |
4908 | } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) { |
4909 | /* |
4910 | * The subdissector asked to reassemble at the end of the |
4911 | * connection. That will be done in dissect_tcp, but here we |
4912 | * have to ask reassembly to collect all future segments. |
4913 | * Note that TCP_FLOW_REASSEMBLE_UNTIL_FIN was set before, |
4914 | * this ensures that OoO detection is skipped. |
4915 | * The exact nxtpdu offset does not matter, but it should be |
4916 | * smaller than half of the maximum 32-bit unsigned integer |
4917 | * to allow detection of sequence number wraparound, and |
4918 | * larger than the largest possible stream size. Hopefully |
4919 | * 1GiB (0x40000000 bytes) should be enough. |
4920 | */ |
4921 | msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq, |
4922 | nxtseq+0x40000000, tcpd->fwd->multisegment_pdus); |
4923 | } else { |
4924 | msp = pdu_store_sequencenumber_of_next_pdu(pinfo, |
4925 | deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus); |
4926 | } |
4927 | |
4928 | /* add this segment as the first one for this new pdu */ |
4929 | fragment_add(&tcp_reassembly_table, tvb, deseg_offset, |
4930 | pinfo, msp->first_frame, msp, |
4931 | 0, nxtseq - deseg_seq, |
4932 | LT_SEQ(nxtseq, msp->nxtpdu)((gint32)((nxtseq) - (msp->nxtpdu)) < 0)); |
4933 | } |
4934 | } else { |
4935 | /* If this is not the first time we have seen the packet, then |
4936 | * the MSP should already be created. Retrieve it to see if we |
4937 | * know what later frame the PDU is reassembled in. |
4938 | */ |
4939 | if (tcpd && (msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, deseg_seq))) { |
4940 | ipfd_head = fragment_get(&tcp_reassembly_table, pinfo, msp->first_frame, msp); |
4941 | } |
4942 | } |
4943 | } |
4944 | |
4945 | if (!called_dissector || pinfo->desegment_len != 0) { |
4946 | if (ipfd_head != NULL((void*)0) && ipfd_head->reassembled_in != 0 && |
4947 | ipfd_head->reassembled_in != pinfo->num && |
4948 | !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY0x0040)) { |
4949 | /* |
4950 | * We know what other frame this PDU is reassembled in; |
4951 | * let the user know. |
4952 | */ |
4953 | item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0, |
4954 | 0, ipfd_head->reassembled_in); |
4955 | proto_item_set_generated(item); |
4956 | } |
4957 | |
4958 | /* |
4959 | * Either we didn't call the subdissector at all (i.e., |
4960 | * this is a segment that contains the middle of a |
4961 | * higher-level PDU, but contains neither the beginning |
4962 | * nor the end), or the subdissector couldn't dissect it |
4963 | * all, as some data was missing (i.e., it set |
4964 | * "pinfo->desegment_len" to the amount of additional |
4965 | * data it needs). |
4966 | */ |
4967 | if (pinfo->desegment_offset == 0) { |
4968 | /* |
4969 | * It couldn't, in fact, dissect any of it (the |
4970 | * first byte it couldn't dissect is at an offset |
4971 | * of "pinfo->desegment_offset" from the beginning |
4972 | * of the payload, and that's 0). |
4973 | * Just mark this as TCP. |
4974 | */ |
4975 | if (first_pdu && ipfd_head != NULL((void*)0) && ipfd_head->reassembled_in != 0) { |
4976 | col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[TCP PDU reassembled in %u]", |
4977 | ipfd_head->reassembled_in); |
4978 | } |
4979 | } |
4980 | |
4981 | /* |
4982 | * Show what's left in the packet as just raw TCP segment |
4983 | * data. (It's possible that another PDU follows in the case |
4984 | * of an out of order frame that is part of two MSPs.) |
4985 | * XXX - remember what protocol the last subdissector |
4986 | * was, and report it as a continuation of that, instead? |
4987 | */ |
4988 | nbytes = another_pdu_follows ? another_pdu_follows : tvb_reported_length_remaining(tvb, deseg_offset); |
4989 | |
4990 | proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, deseg_offset, |
4991 | nbytes, NULL((void*)0), "TCP segment data (%u byte%s)", nbytes, |
4992 | plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s"))); |
4993 | } |
4994 | pinfo->can_desegment = 0; |
4995 | pinfo->desegment_offset = 0; |
4996 | pinfo->desegment_len = 0; |
4997 | |
4998 | if(another_pdu_follows) { |
4999 | /* there was another pdu following this one. */ |
5000 | pinfo->can_desegment = 2; |
5001 | /* we also have to prevent the dissector from changing the |
5002 | * PROTOCOL and INFO columns since what follows may be an |
5003 | * incomplete PDU and we don't want it be changed back from |
5004 | * <Protocol> to <TCP> |
5005 | */ |
5006 | col_set_fence(pinfo->cinfo, COL_INFO); |
5007 | cleared_writable |= col_get_writable(pinfo->cinfo, COL_PROTOCOL); |
5008 | col_set_writable(pinfo->cinfo, COL_PROTOCOL, FALSE(0)); |
5009 | first_pdu = FALSE(0); |
5010 | offset += another_pdu_follows; |
5011 | seq += another_pdu_follows; |
5012 | goto again; |
5013 | } else { |
5014 | /* remove any blocking set above otherwise the |
5015 | * proto,colinfo tap will break |
5016 | */ |
5017 | if(cleared_writable) { |
5018 | col_set_writable(pinfo->cinfo, COL_PROTOCOL, TRUE(!(0))); |
5019 | } |
5020 | } |
5021 | |
5022 | clean_exit: |
5023 | /* Restore the addresses and ports to whatever they were after |
5024 | * the last segment that successfully dissected some data, if any. |
5025 | */ |
5026 | restore_endpoint(pinfo, &new_endpoint); |
5027 | } |
5028 | |
5029 | void |
5030 | tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
5031 | gboolean proto_desegment, guint fixed_len, |
5032 | guint (*get_pdu_len)(packet_info *, tvbuff_t *, int, void*), |
5033 | dissector_t dissect_pdu, void* dissector_data) |
5034 | { |
5035 | volatile int offset = 0; |
5036 | int offset_before; |
5037 | guint captured_length_remaining; |
5038 | volatile guint plen; |
5039 | guint length; |
5040 | tvbuff_t *next_tvb; |
5041 | proto_item *item=NULL((void*)0); |
5042 | const char *saved_proto; |
5043 | guint8 curr_layer_num; |
5044 | wmem_list_frame_t *frame; |
5045 | |
5046 | tcp_endpoint_t orig_endpoint; |
5047 | |
5048 | save_endpoint(pinfo, &orig_endpoint); |
5049 | |
5050 | while (tvb_reported_length_remaining(tvb, offset) > 0) { |
5051 | /* |
5052 | * We use "tvb_ensure_captured_length_remaining()" to make |
5053 | * sure there actually *is* data remaining. The protocol |
5054 | * we're handling could conceivably consists of a sequence of |
5055 | * fixed-length PDUs, and therefore the "get_pdu_len" routine |
5056 | * might not actually fetch anything from the tvbuff, and thus |
5057 | * might not cause an exception to be thrown if we've run past |
5058 | * the end of the tvbuff. |
5059 | * |
5060 | * This means we're guaranteed that "captured_length_remaining" is positive. |
5061 | */ |
5062 | captured_length_remaining = tvb_ensure_captured_length_remaining(tvb, offset); |
5063 | |
5064 | /* |
5065 | * Can we do reassembly? |
5066 | */ |
5067 | if (proto_desegment && pinfo->can_desegment) { |
5068 | /* |
5069 | * Yes - is the fixed-length part of the PDU split across segment |
5070 | * boundaries? |
5071 | */ |
5072 | if (captured_length_remaining < fixed_len) { |
5073 | /* |
5074 | * Yes. Tell the TCP dissector where the data for this message |
5075 | * starts in the data it handed us and that we need "some more |
5076 | * data." Don't tell it exactly how many bytes we need because |
5077 | * if/when we ask for even more (after the header) that will |
5078 | * break reassembly. |
5079 | */ |
5080 | pinfo->desegment_offset = offset; |
5081 | pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff; |
5082 | return; |
5083 | } |
5084 | } |
5085 | |
5086 | /* |
5087 | * Get the length of the PDU. |
5088 | */ |
5089 | plen = (*get_pdu_len)(pinfo, tvb, offset, dissector_data); |
5090 | if (plen == 0) { |
5091 | /* |
5092 | * Support protocols which have a variable length which cannot |
5093 | * always be determined within the given fixed_len. |
5094 | */ |
5095 | /* |
5096 | * If another segment was requested but we can't do reassembly, |
5097 | * abort and warn about the unreassembled packet. |
5098 | */ |
5099 | THROW_ON(!(proto_desegment && pinfo->can_desegment), FragmentBoundsError)do { if ((!(proto_desegment && pinfo->can_desegment ))) except_throw(1, (4), ((void*)0)); } while (0); |
5100 | /* |
5101 | * Tell the TCP dissector where the data for this message |
5102 | * starts in the data it handed us, and that we need one |
5103 | * more segment, and return. |
5104 | */ |
5105 | pinfo->desegment_offset = offset; |
5106 | pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff; |
5107 | return; |
5108 | } |
5109 | if (plen < fixed_len) { |
5110 | /* |
5111 | * Either: |
5112 | * |
5113 | * 1) the length value extracted from the fixed-length portion |
5114 | * doesn't include the fixed-length portion's length, and |
5115 | * was so large that, when the fixed-length portion's |
5116 | * length was added to it, the total length overflowed; |
5117 | * |
5118 | * 2) the length value extracted from the fixed-length portion |
5119 | * includes the fixed-length portion's length, and the value |
5120 | * was less than the fixed-length portion's length, i.e. it |
5121 | * was bogus. |
5122 | * |
5123 | * Report this as a bounds error. |
5124 | */ |
5125 | show_reported_bounds_error(tvb, pinfo, tree); |
5126 | return; |
5127 | } |
5128 | |
5129 | /* give a hint to TCP where the next PDU starts |
5130 | * so that it can attempt to find it in case it starts |
5131 | * somewhere in the middle of a segment. |
5132 | */ |
5133 | if(!pinfo->fd->visited && tcp_analyze_seq) { |
5134 | guint remaining_bytes; |
5135 | remaining_bytes = tvb_reported_length_remaining(tvb, offset); |
5136 | if(plen>remaining_bytes) { |
5137 | pinfo->want_pdu_tracking=2; |
5138 | pinfo->bytes_until_next_pdu=plen-remaining_bytes; |
5139 | } |
5140 | } |
5141 | |
5142 | /* |
5143 | * Can we do reassembly? |
5144 | */ |
5145 | if (proto_desegment && pinfo->can_desegment) { |
5146 | /* |
5147 | * Yes - is the PDU split across segment boundaries? |
5148 | */ |
5149 | if (captured_length_remaining < plen) { |
5150 | /* |
5151 | * Yes. Tell the TCP dissector where the data for this message |
5152 | * starts in the data it handed us, and how many more bytes we |
5153 | * need, and return. |
5154 | */ |
5155 | pinfo->desegment_offset = offset; |
5156 | pinfo->desegment_len = plen - captured_length_remaining; |
5157 | return; |
5158 | } |
5159 | } |
5160 | |
5161 | curr_layer_num = pinfo->curr_layer_num-1; |
5162 | frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers)); |
5163 | while (frame && (proto_tcp != (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))((guint) (gulong) (wmem_list_frame_data(frame))))) { |
5164 | frame = wmem_list_frame_prev(frame); |
5165 | curr_layer_num--; |
5166 | } |
5167 | #if 0 |
5168 | if (captured_length_remaining >= plen || there are more packets) |
5169 | { |
5170 | #endif |
5171 | /* |
5172 | * Display the PDU length as a field |
5173 | */ |
5174 | item=proto_tree_add_uint((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_tcp, curr_layer_num), |
5175 | hf_tcp_pdu_size, |
5176 | tvb, offset, plen, plen); |
5177 | proto_item_set_generated(item); |
5178 | #if 0 |
5179 | } else { |
5180 | item = proto_tree_add_expert_format((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_tcp, curr_layer_num), |
5181 | tvb, offset, -1, |
5182 | "PDU Size: %u cut short at %u",plen,captured_length_remaining); |
5183 | proto_item_set_generated(item); |
5184 | } |
5185 | #endif |
5186 | |
5187 | /* |
5188 | * Construct a tvbuff containing the amount of the payload we have |
5189 | * available. Make its reported length the amount of data in the PDU. |
5190 | */ |
5191 | length = captured_length_remaining; |
5192 | if (length > plen) |
5193 | length = plen; |
5194 | next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, plen); |
5195 | if (!(proto_desegment && pinfo->can_desegment)) { |
5196 | if (plen > length) { |
5197 | /* If we can't do reassembly but the PDU is split across |
5198 | * segment boundaries, mark the tvbuff as a fragment so |
5199 | * we throw FragmentBoundsError instead of malformed |
5200 | * errors. |
5201 | */ |
5202 | tvb_set_fragment(next_tvb); |
5203 | } |
5204 | } |
5205 | |
5206 | |
5207 | /* |
5208 | * Dissect the PDU. |
5209 | * |
5210 | * If it gets an error that means there's no point in |
5211 | * dissecting any more PDUs, rethrow the exception in |
5212 | * question. |
5213 | * |
5214 | * If it gets any other error, report it and continue, as that |
5215 | * means that PDU got an error, but that doesn't mean we should |
5216 | * stop dissecting PDUs within this frame or chunk of reassembled |
5217 | * data. |
5218 | */ |
5219 | saved_proto = pinfo->current_proto; |
5220 | restore_endpoint(pinfo, &orig_endpoint); |
5221 | TRY{ except_t *volatile exc; volatile int except_state = 0; static const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch except_ch; except_setup_try(& except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch .except_jmp)) *(&exc) = &except_ch.except_obj; else * (&exc) = 0; if(except_state & 1) except_state |= 2; except_state &= ~1; if (except_state == 0 && exc == 0) { |
5222 | (*dissect_pdu)(next_tvb, pinfo, tree, dissector_data); |
5223 | } |
5224 | CATCH_NONFATAL_ERRORSif (except_state == 0 && exc != 0 && (exc-> except_id.except_code == (3) || exc->except_id.except_code == (2) || exc->except_id.except_code == (7) || exc->except_id .except_code == (9)) && (except_state|=1)) { |
5225 | show_exception(tvb, pinfo, tree, EXCEPT_CODE((exc)->except_id.except_code), GET_MESSAGE((exc)->except_message)); |
5226 | |
5227 | /* |
5228 | * Restore the saved protocol as well; we do this after |
5229 | * show_exception(), so that the "Malformed packet" indication |
5230 | * shows the protocol for which dissection failed. |
5231 | */ |
5232 | pinfo->current_proto = saved_proto; |
5233 | } |
5234 | ENDTRYif(!(except_state&1) && exc != 0) except_rethrow( exc); except_free(except_ch.except_obj.except_dyndata); except_pop (); };}; |
5235 | |
5236 | /* |
5237 | * Step to the next PDU. |
5238 | * Make sure we don't overflow. |
5239 | */ |
5240 | offset_before = offset; |
5241 | offset += plen; |
5242 | if (offset <= offset_before) |
5243 | break; |
5244 | } |
5245 | } |
5246 | |
5247 | static void |
5248 | tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val) |
5249 | { |
5250 | /* fstr(" %s=%u", abbrev, val) */ |
5251 | col_append_str_uint(pinfo->cinfo, COL_INFO, abbrev, val, " "); |
5252 | } |
5253 | |
5254 | static void |
5255 | tcp_info_append_hex_uint(packet_info *pinfo, const char *abbrev, guint32 val) |
5256 | { |
5257 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%X", abbrev, val); |
5258 | } |
5259 | |
5260 | static gboolean |
5261 | tcp_option_len_check(proto_item* length_item, packet_info *pinfo, guint len, guint optlen) |
5262 | { |
5263 | if (len != optlen) { |
5264 | /* Bogus - option length isn't what it's supposed to be for this option. */ |
5265 | expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, |
5266 | "option length should be %u", optlen); |
5267 | return FALSE(0); |
5268 | } |
5269 | |
5270 | return TRUE(!(0)); |
5271 | } |
5272 | |
5273 | static int |
5274 | dissect_tcpopt_unknown(tvbuff_t *tvb, packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, void* data _U___attribute__((unused))) |
5275 | { |
5276 | proto_item *item; |
5277 | proto_tree *exp_tree; |
5278 | int offset = 0, optlen = tvb_reported_length(tvb); |
5279 | |
5280 | item = proto_tree_add_item(tree, proto_tcp_option_unknown, tvb, offset, -1, ENC_NA0x00000000); |
5281 | exp_tree = proto_item_add_subtree(item, ett_tcp_unknown_opt); |
5282 | |
5283 | proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5284 | proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
5285 | if (optlen > 2) |
5286 | proto_tree_add_item(exp_tree, hf_tcp_option_unknown_payload, tvb, offset + 2, optlen - 2, ENC_NA0x00000000); |
5287 | |
5288 | return tvb_captured_length(tvb); |
5289 | } |
5290 | |
5291 | static int |
5292 | dissect_tcpopt_default_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, int ett) |
5293 | { |
5294 | proto_item *item; |
5295 | proto_tree *exp_tree; |
5296 | proto_item *length_item; |
5297 | int offset = 0; |
5298 | |
5299 | item = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA0x00000000); |
5300 | exp_tree = proto_item_add_subtree(item, ett); |
5301 | |
5302 | proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5303 | length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
5304 | |
5305 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), 2)) |
5306 | return tvb_captured_length(tvb); |
5307 | |
5308 | return tvb_captured_length(tvb); |
5309 | } |
5310 | |
5311 | static int |
5312 | dissect_tcpopt_recbound(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
5313 | { |
5314 | return dissect_tcpopt_default_option(tvb, pinfo, tree, proto_tcp_option_scpsrec, ett_tcp_opt_recbound); |
5315 | } |
5316 | |
5317 | static int |
5318 | dissect_tcpopt_correxp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
5319 | { |
5320 | return dissect_tcpopt_default_option(tvb, pinfo, tree, proto_tcp_option_scpscor, ett_tcp_opt_scpscor); |
5321 | } |
5322 | |
5323 | static void |
5324 | dissect_tcpopt_tfo_payload(tvbuff_t *tvb, int offset, guint optlen, |
5325 | packet_info *pinfo, proto_tree *exp_tree, void *data) |
5326 | { |
5327 | proto_item *ti; |
5328 | struct tcpheader *tcph = (struct tcpheader*)data; |
5329 | struct tcp_analysis *tcpd; |
5330 | |
5331 | if (optlen == 2) { |
5332 | /* Fast Open Cookie Request */ |
5333 | proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie_request, |
5334 | tvb, offset, 2, ENC_NA0x00000000); |
5335 | col_append_str(pinfo->cinfo, COL_INFO, " TFO=R"); |
5336 | } else if (optlen > 2) { |
5337 | /* Fast Open Cookie */ |
5338 | ti = proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie, |
5339 | tvb, offset + 2, optlen - 2, ENC_NA0x00000000); |
5340 | col_append_str(pinfo->cinfo, COL_INFO, " TFO=C"); |
5341 | if ((tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == TH_SYN0x0002) { |
5342 | expert_add_info(pinfo, ti, &ei_tcp_analysis_tfo_syn); |
5343 | |
5344 | /* Is this a SYN with data and the cookie? */ |
5345 | if (tcph->th_have_seglen && tcph->th_seglen) { |
5346 | tcpd = get_tcp_conversation_data(NULL((void*)0), pinfo); |
5347 | if (tcpd) { |
5348 | tcpd->tfo_syn_data = 1; |
5349 | } |
5350 | } |
5351 | } |
5352 | } |
5353 | } |
5354 | |
5355 | static int |
5356 | dissect_tcpopt_tfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
5357 | { |
5358 | proto_item *item; |
5359 | proto_tree *exp_tree; |
5360 | int offset = 0; |
5361 | |
5362 | item = proto_tree_add_item(tree, proto_tcp_option_tfo, tvb, offset, -1, ENC_NA0x00000000); |
5363 | exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp); |
5364 | proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5365 | proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
5366 | |
5367 | dissect_tcpopt_tfo_payload(tvb, offset, tvb_reported_length(tvb), pinfo, exp_tree, data); |
5368 | return tvb_captured_length(tvb); |
5369 | } |
5370 | |
5371 | /* |
5372 | * TCP ACK Rate Request option is based on |
5373 | * https://datatracker.ietf.org/doc/html/draft-gomez-tcpm-ack-rate-request-06 |
5374 | */ |
5375 | |
5376 | #define TCPOPT_TARR_RATE_MASK0xfe 0xfe |
5377 | #define TCPOPT_TARR_RESERVED_MASK0x01 0x01 |
5378 | #define TCPOPT_TARR_RATE_SHIFT1 1 |
5379 | |
5380 | static void |
5381 | dissect_tcpopt_tarr_data(tvbuff_t *tvb, int data_offset, guint data_len, |
5382 | packet_info *pinfo, proto_tree *tree, proto_item *item, void *data _U___attribute__((unused))) |
5383 | { |
5384 | guint8 rate; |
5385 | |
5386 | switch (data_len) { |
5387 | case 0: |
5388 | col_append_str(pinfo->cinfo, COL_INFO, " TARR"); |
5389 | break; |
5390 | case 1: |
5391 | rate = (tvb_get_guint8(tvb, data_offset) & TCPOPT_TARR_RATE_MASK0xfe) >> TCPOPT_TARR_RATE_SHIFT1; |
5392 | proto_tree_add_item(tree, hf_tcp_option_tarr_rate, tvb, data_offset, 1, ENC_BIG_ENDIAN0x00000000); |
5393 | proto_tree_add_item(tree, hf_tcp_option_tarr_reserved, tvb, data_offset, 1, ENC_BIG_ENDIAN0x00000000); |
5394 | tcp_info_append_uint(pinfo, "TARR", rate); |
5395 | proto_item_append_text(item, " %u", rate); |
5396 | break; |
5397 | } |
5398 | } |
5399 | |
5400 | static void |
5401 | dissect_tcpopt_acc_ecn_data(tvbuff_t *tvb, int data_offset, guint data_len, |
5402 | gboolean is_order_0, packet_info *pinfo, proto_tree *tree, proto_item *item, void *data _U___attribute__((unused))) |
5403 | { |
5404 | struct tcp_analysis *tcpd; |
5405 | guint32 ee0b, eceb, ee1b; |
5406 | |
5407 | switch (data_len) { |
5408 | case 0: |
5409 | col_append_str(pinfo->cinfo, COL_INFO, " AccECN"); |
5410 | break; |
5411 | case 3: |
5412 | if (is_order_0) { |
5413 | ee0b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000); |
5414 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000); |
5415 | proto_item_append_text(item, " (Order 0): EE0B %u", ee0b); |
5416 | tcp_info_append_uint(pinfo, "EE0B", ee0b); |
5417 | } else { |
5418 | ee1b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000); |
5419 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000); |
5420 | proto_item_append_text(item, " (Order 1): EE1B %u", ee1b); |
5421 | tcp_info_append_uint(pinfo, "EE1B", ee1b); |
5422 | } |
5423 | break; |
5424 | case 6: |
5425 | if (is_order_0) { |
5426 | ee0b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000); |
5427 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000); |
5428 | tcp_info_append_uint(pinfo, "EE0B", ee0b); |
5429 | } else { |
5430 | ee1b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000); |
5431 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000); |
5432 | tcp_info_append_uint(pinfo, "EE1B", ee1b); |
5433 | } |
5434 | eceb = tvb_get_guint24(tvb, data_offset + 3, ENC_BIG_ENDIAN0x00000000); |
5435 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_eceb, tvb, data_offset + 3, 3, ENC_BIG_ENDIAN0x00000000); |
5436 | tcp_info_append_uint(pinfo, "ECEB", eceb); |
5437 | if (is_order_0) { |
5438 | proto_item_append_text(item, " (Order 0): EE0B %u, ECEB %u", ee0b, eceb); |
5439 | } else { |
5440 | proto_item_append_text(item, " (Order 1): EE1B %u, ECEB %u", ee1b, eceb); |
5441 | } |
5442 | break; |
5443 | case 9: |
5444 | if (is_order_0) { |
5445 | ee0b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000); |
5446 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000); |
5447 | tcp_info_append_uint(pinfo, "EE0B", ee0b); |
5448 | } else { |
5449 | ee1b = tvb_get_guint24(tvb, data_offset, ENC_BIG_ENDIAN0x00000000); |
5450 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset, 3, ENC_BIG_ENDIAN0x00000000); |
5451 | tcp_info_append_uint(pinfo, "EE1B", ee1b); |
5452 | } |
5453 | eceb = tvb_get_guint24(tvb, data_offset + 3, ENC_BIG_ENDIAN0x00000000); |
5454 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_eceb, tvb, data_offset + 3, 3, ENC_BIG_ENDIAN0x00000000); |
5455 | tcp_info_append_uint(pinfo, "ECEB", eceb); |
5456 | if (is_order_0) { |
5457 | ee1b = tvb_get_guint24(tvb, data_offset + 6, ENC_BIG_ENDIAN0x00000000); |
5458 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee1b, tvb, data_offset + 6, 3, ENC_BIG_ENDIAN0x00000000); |
5459 | tcp_info_append_uint(pinfo, "EE1B", ee1b); |
5460 | proto_item_append_text(item, " (Order 0): EE0B %u, ECEB %u, EE1B %u", ee0b, eceb, ee1b); |
5461 | } else { |
5462 | ee0b = tvb_get_guint24(tvb, data_offset + 6, ENC_BIG_ENDIAN0x00000000); |
5463 | proto_tree_add_item(tree, hf_tcp_option_acc_ecn_ee0b, tvb, data_offset + 6, 3, ENC_BIG_ENDIAN0x00000000); |
5464 | tcp_info_append_uint(pinfo, "EE0B", ee0b); |
5465 | proto_item_append_text(item, " (Order 1): EE1B %u, ECEB %u, EE0B %u", ee1b, eceb, ee0b); |
5466 | } |
5467 | break; |
5468 | } |
5469 | tcpd = get_tcp_conversation_data(NULL((void*)0), pinfo); |
5470 | if (tcpd != NULL((void*)0)) { |
5471 | tcpd->had_acc_ecn_option = TRUE(!(0)); |
5472 | } |
5473 | } |
5474 | |
5475 | static int |
5476 | dissect_tcpopt_acc_ecn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused))) |
5477 | { |
5478 | proto_item *length_item, *item; |
5479 | proto_tree *acc_ecn_tree; |
5480 | int offset; |
5481 | guint8 kind, length; |
5482 | |
5483 | offset = 0; |
5484 | item = proto_tree_add_item(tree, proto_tcp_option_acc_ecn, tvb, offset, -1, ENC_NA0x00000000); |
5485 | acc_ecn_tree = proto_item_add_subtree(item, ett_tcp_option_acc_ecn); |
5486 | kind = tvb_get_guint8(tvb, offset); |
5487 | proto_tree_add_item(acc_ecn_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5488 | offset += 1; |
5489 | length = tvb_get_guint8(tvb, offset); |
5490 | length_item = proto_tree_add_item(acc_ecn_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5491 | offset += 1; |
5492 | if (length != 2 && length != 5 && length != 8 && length != 11) { |
5493 | expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, |
5494 | "option length should be 2, 5, 8, or 11 instead of %u", length); |
5495 | } else { |
5496 | dissect_tcpopt_acc_ecn_data(tvb, offset, length - 2, kind == TCPOPT_ACC_ECN_00xac, pinfo, acc_ecn_tree, item, data); |
5497 | } |
5498 | return tvb_captured_length(tvb); |
5499 | } |
5500 | |
5501 | static int |
5502 | dissect_tcpopt_exp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
5503 | { |
5504 | proto_item *item, *length_item; |
5505 | proto_tree *exp_tree; |
5506 | guint16 exid; |
5507 | guint8 kind; |
5508 | gint offset = 0, optlen = tvb_reported_length(tvb); |
5509 | |
5510 | item = proto_tree_add_item(tree, proto_tcp_option_exp, tvb, offset, -1, ENC_NA0x00000000); |
5511 | exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp); |
5512 | proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5513 | kind = tvb_get_guint8(tvb, offset); |
5514 | length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
5515 | if (tcp_exp_options_rfc6994) { |
5516 | if (optlen >= TCPOLEN_EXP_MIN4) { |
5517 | exid = tvb_get_ntohs(tvb, offset + 2); |
5518 | proto_tree_add_item(exp_tree, hf_tcp_option_exp_exid, tvb, |
5519 | offset + 2, 2, ENC_BIG_ENDIAN0x00000000); |
5520 | proto_item_append_text(item, ": %s", val_to_str_const(exid, tcp_exid_vs, "Unknown")); |
5521 | switch (exid) { |
5522 | case TCPEXID_TARR0x00ac: |
5523 | if (optlen != 4 && optlen != 5) { |
5524 | expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, |
5525 | "option length should be 4 or 5 instead of %d", |
5526 | optlen); |
5527 | } else { |
5528 | dissect_tcpopt_tarr_data(tvb, offset + 4, optlen - 4, |
5529 | pinfo, exp_tree, item, data); |
5530 | } |
5531 | break; |
5532 | case 0xACC0: /* draft-ietf-tcpm-accurate-ecn-20 */ |
5533 | case 0xACC1: |
5534 | if (optlen != 4 && optlen != 7 && optlen != 10 && optlen != 13) { |
5535 | expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, |
5536 | "option length should be 4, 7, 10, or 13 instead of %d", |
5537 | optlen); |
5538 | } else { |
5539 | proto_item_append_text(item, ": Accurate ECN"); |
5540 | dissect_tcpopt_acc_ecn_data(tvb, offset + 4, optlen - 4, |
5541 | exid == 0xACC0, pinfo, exp_tree, |
5542 | item, data); |
5543 | } |
5544 | break; |
5545 | case TCPEXID_FO0xf989: |
5546 | dissect_tcpopt_tfo_payload(tvb, offset + 2, optlen - 2, pinfo, exp_tree, data); |
5547 | break; |
5548 | default: |
5549 | if (optlen > TCPOLEN_EXP_MIN4) { |
5550 | proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb, |
5551 | offset + TCPOLEN_EXP_MIN4, |
5552 | optlen - TCPOLEN_EXP_MIN4, ENC_NA0x00000000); |
5553 | } |
5554 | tcp_info_append_hex_uint(pinfo, "ExID", exid); |
5555 | break; |
5556 | } |
5557 | } else { |
5558 | expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, |
5559 | "option length %u smaller than 4", optlen); |
5560 | } |
5561 | } else { |
5562 | proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb, |
5563 | offset + 2, optlen - 2, ENC_NA0x00000000); |
5564 | tcp_info_append_uint(pinfo, "Exp", (kind == TCPOPT_EXP_FD0xfd) ? 1 : 2); |
5565 | } |
5566 | return tvb_captured_length(tvb); |
5567 | } |
5568 | |
5569 | static int |
5570 | dissect_tcpopt_sack_perm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
5571 | { |
5572 | proto_item *item; |
5573 | proto_tree *exp_tree; |
5574 | proto_item *length_item; |
5575 | int offset = 0; |
5576 | struct tcpheader *tcph = (struct tcpheader *)data; |
5577 | |
5578 | item = proto_tree_add_item(tree, proto_tcp_option_sack_perm, tvb, offset, -1, ENC_NA0x00000000); |
5579 | exp_tree = proto_item_add_subtree(item, ett_tcp_option_sack_perm); |
5580 | |
5581 | if (!(tcph->th_flags & TH_SYN0x0002)) |
5582 | { |
5583 | expert_add_info(pinfo, item, &ei_tcp_option_sack_perm_present); |
5584 | } |
5585 | |
5586 | proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5587 | length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
5588 | |
5589 | col_append_str(pinfo->cinfo, COL_INFO, " SACK_PERM"); |
5590 | |
5591 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SACK_PERM2)) |
5592 | return tvb_captured_length(tvb); |
5593 | |
5594 | return tvb_captured_length(tvb); |
5595 | } |
5596 | |
5597 | static int |
5598 | dissect_tcpopt_mss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
5599 | { |
5600 | proto_item *item; |
5601 | proto_tree *exp_tree; |
5602 | proto_item *length_item; |
5603 | int offset = 0; |
5604 | struct tcpheader *tcph = (struct tcpheader *)data; |
5605 | guint32 mss; |
5606 | |
5607 | item = proto_tree_add_item(tree, proto_tcp_option_mss, tvb, offset, -1, ENC_NA0x00000000); |
5608 | exp_tree = proto_item_add_subtree(item, ett_tcp_option_mss); |
5609 | |
5610 | if (!(tcph->th_flags & TH_SYN0x0002)) |
5611 | { |
5612 | expert_add_info(pinfo, item, &ei_tcp_option_mss_present); |
5613 | } |
5614 | |
5615 | proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5616 | length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
5617 | |
5618 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_MSS4)) |
5619 | return tvb_captured_length(tvb); |
5620 | |
5621 | proto_tree_add_item_ret_uint(exp_tree, hf_tcp_option_mss_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000, &mss); |
5622 | proto_item_append_text(item, ": %u bytes", mss); |
5623 | tcp_info_append_uint(pinfo, "MSS", mss); |
5624 | |
5625 | return tvb_captured_length(tvb); |
5626 | } |
5627 | |
5628 | /* The window scale extension is defined in RFC 1323 */ |
5629 | static int |
5630 | dissect_tcpopt_wscale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
5631 | { |
5632 | guint8 val; |
5633 | guint32 shift; |
5634 | proto_item *wscale_pi, *shift_pi, *gen_pi; |
5635 | proto_tree *wscale_tree; |
5636 | proto_item *length_item; |
5637 | int offset = 0; |
5638 | struct tcp_analysis *tcpd; |
5639 | |
5640 | conversation_t *stratconv = find_conversation_strat(pinfo); |
5641 | tcpd=get_tcp_conversation_data(stratconv,pinfo); |
5642 | |
5643 | wscale_pi = proto_tree_add_item(tree, proto_tcp_option_wscale, tvb, offset, -1, ENC_NA0x00000000); |
5644 | wscale_tree = proto_item_add_subtree(wscale_pi, ett_tcp_option_wscale); |
5645 | |
5646 | proto_tree_add_item(wscale_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5647 | offset += 1; |
5648 | |
5649 | length_item = proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5650 | offset += 1; |
5651 | |
5652 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_WINDOW3)) |
5653 | return tvb_captured_length(tvb); |
5654 | |
5655 | shift_pi = proto_tree_add_item_ret_uint(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &shift); |
5656 | if (shift > 14) { |
5657 | /* RFC 1323: "If a Window Scale option is received with a shift.cnt |
5658 | * value exceeding 14, the TCP should log the error but use 14 instead |
5659 | * of the specified value." */ |
5660 | shift = 14; |
5661 | expert_add_info(pinfo, shift_pi, &ei_tcp_option_wscale_shift_invalid); |
5662 | } |
5663 | |
5664 | gen_pi = proto_tree_add_uint(wscale_tree, hf_tcp_option_wscale_multiplier, tvb, |
5665 | offset, 1, 1 << shift); |
5666 | proto_item_set_generated(gen_pi); |
5667 | val = tvb_get_guint8(tvb, offset); |
5668 | |
5669 | proto_item_append_text(wscale_pi, ": %u (multiply by %u)", val, 1 << shift); |
5670 | |
5671 | tcp_info_append_uint(pinfo, "WS", 1 << shift); |
5672 | |
5673 | if(!pinfo->fd->visited) { |
5674 | pdu_store_window_scale_option(shift, tcpd); |
5675 | } |
5676 | |
5677 | return tvb_captured_length(tvb); |
5678 | } |
5679 | |
5680 | static int |
5681 | dissect_tcpopt_sack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
5682 | { |
5683 | proto_tree *field_tree = NULL((void*)0); |
5684 | proto_item *tf, *ti; |
5685 | guint32 leftedge, rightedge; |
5686 | struct tcp_analysis *tcpd=NULL((void*)0); |
5687 | struct tcpheader *tcph = (struct tcpheader *)data; |
| |
5688 | guint32 base_ack=0; |
5689 | guint num_sack_ranges = 0; |
5690 | int offset = 0; |
5691 | int sackoffset; |
5692 | int optlen = tvb_reported_length(tvb); |
5693 | |
5694 | /* |
5695 | * SEQ analysis is the condition for both relative analysis obviously, |
5696 | * and SACK handling for the in-flight update |
5697 | */ |
5698 | if(tcp_analyze_seq) { |
| 2 | | Assuming 'tcp_analyze_seq' is false | |
|
5699 | /* find(or create if needed) the conversation for this tcp session */ |
5700 | tcpd=get_tcp_conversation_data(NULL((void*)0),pinfo); |
5701 | |
5702 | if (tcpd) { |
5703 | if (tcp_relative_seq) { |
5704 | base_ack=tcpd->rev->base_seq; |
5705 | } |
5706 | |
5707 | /* |
5708 | * initialize the number of SACK blocks to 0, it will be |
5709 | * updated some lines later |
5710 | */ |
5711 | if (tcp_track_bytes_in_flight && tcpd->fwd->tcp_analyze_seq_info) { |
5712 | tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = 0; |
5713 | } |
5714 | } |
5715 | } |
5716 | |
5717 | /* Late discovery of a 'false' Window Update in presence of SACK option, |
5718 | * which means we are dealing with a Dup ACK rather than a Window Update. |
5719 | * Classify accordingly by removing the UPDATE and adding the DUP flags. |
5720 | * Mostly a copy/paste from tcp_analyze_sequence_number(), ensure consistency |
5721 | * whenever the latter changes. |
5722 | * see Issue #14937 |
5723 | */ |
5724 | if( tcp_analyze_seq2.1 | 'tcp_analyze_seq' is false | && tcpd && tcpd->ta && tcpd->ta->flags&TCP_A_WINDOW_UPDATE0x0800 ) { |
5725 | |
5726 | /* MPTCP tolerates duplicate acks in some circ*mstances, see RFC 8684 4. */ |
5727 | if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) { |
5728 | /* just ignore this DUPLICATE ACK */ |
5729 | } else { |
5730 | tcpd->fwd->tcp_analyze_seq_info->dupacknum++; |
5731 | |
5732 | /* no initialization required of the tcpd->ta as this code would |
5733 | * be unreachable otherwise |
5734 | */ |
5735 | tcpd->ta->flags &= ~TCP_A_WINDOW_UPDATE0x0800; |
5736 | tcpd->ta->flags |= TCP_A_DUPLICATE_ACK0x0010; |
5737 | tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum; |
5738 | tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack; |
5739 | } |
5740 | } |
5741 | |
5742 | ti = proto_tree_add_item(tree, proto_tcp_option_sack, tvb, offset, -1, ENC_NA0x00000000); |
5743 | field_tree = proto_item_add_subtree(ti, ett_tcp_option_sack); |
5744 | |
5745 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
5746 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
5747 | proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
5748 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
5749 | |
5750 | offset += 2; /* skip past type and length */ |
5751 | optlen -= 2; /* subtract size of type and length */ |
5752 | |
5753 | sackoffset = offset; |
5754 | while (optlen > 0) { |
| 3 | | Assuming 'optlen' is > 0 | |
|
| 4 | | Loop condition is true. Entering loop body | |
|
| 13 | | Assuming 'optlen' is <= 0 | |
|
| 14 | | Loop condition is false. Execution continues on line 5800 | |
|
5755 | if (optlen < 4) { |
| 5 | | Assuming 'optlen' is >= 4 | |
|
| |
5756 | proto_tree_add_expert(field_tree, pinfo, &ei_tcp_suboption_malformed, tvb, offset, optlen); |
5757 | break; |
5758 | } |
5759 | leftedge = tvb_get_ntohl(tvb, offset)-base_ack; |
5760 | proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb, |
5761 | offset, 4, leftedge, |
5762 | "left edge = %u%s", leftedge, |
5763 | (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : ""); |
| 7 | | Assuming 'tcp_analyze_seq' is false | |
|
5764 | optlen -= 4; |
5765 | if (optlen < 4) { |
| 8 | | Assuming 'optlen' is >= 4 | |
|
| |
5766 | proto_tree_add_expert(field_tree, pinfo, &ei_tcp_suboption_malformed, tvb, offset, optlen); |
5767 | break; |
5768 | } |
5769 | /* XXX - check whether it goes past end of packet */ |
5770 | rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack; |
5771 | optlen -= 4; |
5772 | proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb, |
5773 | offset+4, 4, rightedge, |
5774 | "right edge = %u%s", rightedge, |
5775 | (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : ""); |
| 10 | | Assuming 'tcp_analyze_seq' is false | |
|
5776 | tcp_info_append_uint(pinfo, "SLE", leftedge); |
5777 | tcp_info_append_uint(pinfo, "SRE", rightedge); |
5778 | num_sack_ranges++; |
5779 | |
5780 | /* Store blocks for BiF analysis */ |
5781 | if (tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info && tcp_track_bytes_in_flight && num_sack_ranges < MAX_TCP_SACK_RANGES4) { |
| 11 | | Assuming 'tcp_analyze_seq' is false | |
|
5782 | tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = num_sack_ranges; |
5783 | tcpd->fwd->tcp_analyze_seq_info->sack_left_edge[num_sack_ranges] = leftedge; |
5784 | tcpd->fwd->tcp_analyze_seq_info->sack_right_edge[num_sack_ranges] = rightedge; |
5785 | } |
5786 | |
5787 | /* Update tap info */ |
5788 | if (tcph != NULL((void*)0) && (tcph->num_sack_ranges < MAX_TCP_SACK_RANGES4)) { |
| 12 | | Assuming 'tcph' is equal to NULL | |
|
5789 | tcph->sack_left_edge[tcph->num_sack_ranges] = leftedge; |
5790 | tcph->sack_right_edge[tcph->num_sack_ranges] = rightedge; |
5791 | tcph->num_sack_ranges++; |
5792 | } |
5793 | |
5794 | proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge); |
5795 | offset += 8; |
5796 | } |
5797 | |
5798 | |
5799 | /* Show number of SACK ranges in this option as a generated field */ |
5800 | tf = proto_tree_add_uint(field_tree, hf_tcp_option_sack_range_count, |
5801 | tvb, 0, 0, num_sack_ranges); |
5802 | proto_item_set_generated(tf); |
5803 | |
5804 | /* RFC 2883 "An Extension to the Selective Acknowledgement (SACK) Option for TCP" aka "D-SACK" |
5805 | * Section 4 |
5806 | * Conditions: Either the first sack-block is inside the already acknowledged range or |
5807 | * the first sack block is inside the second sack block. |
5808 | * |
5809 | * Maybe add later: |
5810 | * (1) A D-SACK block is only used to report a duplicate contiguous sequence of data received by |
5811 | * the receiver in the most recent packet. |
5812 | */ |
5813 | if (LE_SEQ(tcph->sack_right_edge[0], tcph->th_ack)((gint32)((tcph->sack_right_edge[0]) - (tcph->th_ack)) <= 0) || |
| 15 | | Array access (via field 'sack_right_edge') results in a null pointer dereference |
|
5814 | (tcph->num_sack_ranges > 1 && |
5815 | LT_SEQ(tcph->sack_left_edge[1], tcph->sack_right_edge[0])((gint32)((tcph->sack_left_edge[1]) - (tcph->sack_right_edge [0])) < 0) && |
5816 | GE_SEQ(tcph->sack_right_edge[1], tcph->sack_right_edge[0])((gint32)((tcph->sack_right_edge[0]) - (tcph->sack_right_edge [1])) <= 0)) |
5817 | ) { |
5818 | leftedge = tvb_get_ntohl(tvb, sackoffset)-base_ack; |
5819 | tf = proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_dsack_le, tvb, sackoffset, 4, leftedge, |
5820 | "D-SACK Left Edge = %u%s", leftedge, (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : ""); |
5821 | proto_item_set_generated(tf); |
5822 | rightedge = tvb_get_ntohl(tvb, sackoffset+4)-base_ack; |
5823 | tf = proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_dsack_re, tvb, sackoffset+4, 4, rightedge, |
5824 | "D-SACK Right Edge = %u%s", rightedge, (tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : ""); |
5825 | proto_item_set_generated(tf); |
5826 | proto_tree_add_expert(field_tree, pinfo, &ei_tcp_option_sack_dsack, tvb, sackoffset, 8); |
5827 | } |
5828 | |
5829 | return tvb_captured_length(tvb); |
5830 | } |
5831 | |
5832 | static int |
5833 | dissect_tcpopt_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
5834 | { |
5835 | proto_tree *field_tree; |
5836 | proto_item *item; |
5837 | proto_item *length_item; |
5838 | guint32 echo; |
5839 | int offset = 0; |
5840 | |
5841 | item = proto_tree_add_item(tree, proto_tcp_option_echo, tvb, offset, -1, ENC_NA0x00000000); |
5842 | field_tree = proto_item_add_subtree(item, ett_tcp_opt_echo); |
5843 | |
5844 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
5845 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
5846 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
5847 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
5848 | |
5849 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_ECHO6)) |
5850 | return tvb_captured_length(tvb); |
5851 | |
5852 | proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_echo, tvb, |
5853 | offset + 2, 4, ENC_BIG_ENDIAN0x00000000, &echo); |
5854 | |
5855 | proto_item_append_text(item, ": %u", echo); |
5856 | tcp_info_append_uint(pinfo, "ECHO", echo); |
5857 | |
5858 | return tvb_captured_length(tvb); |
5859 | } |
5860 | |
5861 | /* If set, do not put the TCP timestamp information on the summary line */ |
5862 | static bool_Bool tcp_ignore_timestamps; |
5863 | |
5864 | static int |
5865 | dissect_tcpopt_timestamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
5866 | { |
5867 | proto_item *ti, *tsval_ti; |
5868 | proto_tree *ts_tree; |
5869 | proto_item *length_item; |
5870 | int offset = 0; |
5871 | guint32 ts_val, ts_ecr; |
5872 | int len = tvb_reported_length(tvb); |
5873 | |
5874 | ti = proto_tree_add_item(tree, proto_tcp_option_timestamp, tvb, offset, -1, ENC_NA0x00000000); |
5875 | ts_tree = proto_item_add_subtree(ti, ett_tcp_option_timestamp); |
5876 | |
5877 | proto_tree_add_item(ts_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5878 | offset += 1; |
5879 | |
5880 | length_item = proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
5881 | offset += 1; |
5882 | |
5883 | if (!tcp_option_len_check(length_item, pinfo, len, TCPOLEN_TIMESTAMP10)) |
5884 | return tvb_captured_length(tvb); |
5885 | |
5886 | tsval_ti = proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset, |
5887 | 4, ENC_BIG_ENDIAN0x00000000, &ts_val); |
5888 | |
5889 | proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset + 4, |
5890 | 4, ENC_BIG_ENDIAN0x00000000, &ts_ecr); |
5891 | |
5892 | proto_item_append_text(ti, ": TSval %u, TSecr %u", ts_val, ts_ecr); |
5893 | if (tcp_ignore_timestamps == FALSE(0)) { |
5894 | tcp_info_append_uint(pinfo, "TSval", ts_val); |
5895 | tcp_info_append_uint(pinfo, "TSecr", ts_ecr); |
5896 | } |
5897 | |
5898 | if (read_seq_as_syn_cookie) { |
5899 | proto_item_append_text(ti, " (syn cookie)"); |
5900 | proto_item* syncookie_ti = proto_item_add_subtree(tsval_ti, ett_tcp_syncookie_option); |
5901 | guint32 timestamp = tvb_get_bits32(tvb, offset * 8, 26, ENC_NA0x00000000) << 6; |
5902 | proto_tree_add_uint_bits_format_value(syncookie_ti, hf_tcp_syncookie_option_timestamp, tvb, offset * 8, |
5903 | 26, timestamp, ENC_TIME_SECS0x00000012, "%s", abs_time_secs_to_str(pinfo->pool, timestamp, ABSOLUTE_TIME_LOCAL, TRUE)abs_time_secs_to_str_ex(pinfo->pool, timestamp, ABSOLUTE_TIME_LOCAL , ((!(0))) ? (1U << 0) : 0)); |
5904 | proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_ecn, tvb, offset * 8 + 26, 1, ENC_NA0x00000000); |
5905 | proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_sack, tvb, offset * 8 + 27, 1, ENC_NA0x00000000); |
5906 | proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_option_wscale, tvb, offset * 8 + 28, 4, ENC_NA0x00000000); |
5907 | } |
5908 | |
5909 | return tvb_captured_length(tvb); |
5910 | } |
5911 | |
5912 | static struct mptcp_analysis* |
5913 | mptcp_alloc_analysis(struct tcp_analysis* tcpd) { |
5914 | |
5915 | struct mptcp_analysis* mptcpd; |
5916 | |
5917 | DISSECTOR_ASSERT(tcpd->mptcp_analysis == 0)((void) ((tcpd->mptcp_analysis == 0) ? (void)0 : (proto_report_dissector_bug ("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c" , 5917, "tcpd->mptcp_analysis == 0")))); |
5918 | |
5919 | mptcpd = (struct mptcp_analysis*)wmem_new0(wmem_file_scope(), struct mptcp_analysis)((struct mptcp_analysis*)wmem_alloc0((wmem_file_scope()), sizeof (struct mptcp_analysis))); |
5920 | mptcpd->subflows = wmem_list_new(wmem_file_scope()); |
5921 | |
5922 | mptcpd->stream = mptcp_stream_count++; |
5923 | tcpd->mptcp_analysis = mptcpd; |
5924 | |
5925 | memset(&mptcpd->meta_flow, 0, 2*sizeof(mptcp_meta_flow_t)); |
5926 | |
5927 | /* arbitrary assignment. Callers may override this */ |
5928 | tcpd->fwd->mptcp_subflow->meta = &mptcpd->meta_flow[0]; |
5929 | tcpd->rev->mptcp_subflow->meta = &mptcpd->meta_flow[1]; |
5930 | |
5931 | return mptcpd; |
5932 | } |
5933 | |
5934 | |
5935 | /* will create necessary structure if fails to find a match on the token */ |
5936 | static struct mptcp_analysis* |
5937 | mptcp_get_meta_from_token(struct tcp_analysis* tcpd, tcp_flow_t *tcp_flow, guint32 token) { |
5938 | |
5939 | struct mptcp_analysis* result = NULL((void*)0); |
5940 | struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis; |
5941 | guint8 assignedMetaId = 0; /* array id < 2 */ |
5942 | |
5943 | DISSECTOR_ASSERT(tcp_flow == tcpd->fwd || tcp_flow == tcpd->rev)((void) ((tcp_flow == tcpd->fwd || tcp_flow == tcpd->rev ) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 5943, "tcp_flow == tcpd->fwd || tcp_flow == tcpd->rev" )))); |
5944 | |
5945 | |
5946 | |
5947 | /* if token already set for this meta */ |
5948 | if( tcp_flow->mptcp_subflow->meta && (tcp_flow->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_TOKEN0x04)) { |
5949 | return mptcpd; |
5950 | } |
5951 | |
5952 | /* else look for a registered meta with this token */ |
5953 | result = (struct mptcp_analysis*)wmem_tree_lookup32(mptcp_tokens, token); |
5954 | |
5955 | /* if token already registered than just share it across TCP connections */ |
5956 | if(result) { |
5957 | mptcpd = result; |
5958 | mptcp_attach_subflow(mptcpd, tcpd); |
5959 | } |
5960 | else { |
5961 | /* we create it if this connection */ |
5962 | if(!mptcpd) { |
5963 | /* don't care which meta to choose assign each meta to a direction */ |
5964 | mptcpd = mptcp_alloc_analysis(tcpd); |
5965 | mptcp_attach_subflow(mptcpd, tcpd); |
5966 | } |
5967 | else { |
5968 | |
5969 | /* already exists, thus some meta may already have been configured */ |
5970 | if(mptcpd->meta_flow[0].static_flags & MPTCP_META_HAS_TOKEN0x04) { |
5971 | assignedMetaId = 1; |
5972 | } |
5973 | else if(mptcpd->meta_flow[1].static_flags & MPTCP_META_HAS_TOKEN0x04) { |
5974 | assignedMetaId = 0; |
5975 | } |
5976 | else { |
5977 | DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\"" , "epan/dissectors/packet-tcp.c", 5977)); |
5978 | } |
5979 | tcp_flow->mptcp_subflow->meta = &mptcpd->meta_flow[assignedMetaId]; |
5980 | } |
5981 | DISSECTOR_ASSERT(tcp_flow->mptcp_subflow->meta)((void) ((tcp_flow->mptcp_subflow->meta) ? (void)0 : (proto_report_dissector_bug ("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c" , 5981, "tcp_flow->mptcp_subflow->meta")))); |
5982 | |
5983 | tcp_flow->mptcp_subflow->meta->token = token; |
5984 | tcp_flow->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_TOKEN0x04; |
5985 | |
5986 | wmem_tree_insert32(mptcp_tokens, token, mptcpd); |
5987 | } |
5988 | |
5989 | DISSECTOR_ASSERT(mptcpd)((void) ((mptcpd) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 5989, "mptcpd")))); |
5990 | |
5991 | |
5992 | /* compute the meta id assigned to tcp_flow */ |
5993 | assignedMetaId = (tcp_flow->mptcp_subflow->meta == &mptcpd->meta_flow[0]) ? 0 : 1; |
5994 | |
5995 | /* computes the metaId tcpd->fwd should be assigned to */ |
5996 | assignedMetaId = (tcp_flow == tcpd->fwd) ? assignedMetaId : (assignedMetaId +1) %2; |
5997 | |
5998 | tcpd->fwd->mptcp_subflow->meta = &mptcpd->meta_flow[ (assignedMetaId) ]; |
5999 | tcpd->rev->mptcp_subflow->meta = &mptcpd->meta_flow[ (assignedMetaId +1) %2]; |
6000 | |
6001 | return mptcpd; |
6002 | } |
6003 | |
6004 | /* setup from_key */ |
6005 | static |
6006 | struct mptcp_analysis* |
6007 | get_or_create_mptcpd_from_key(struct tcp_analysis* tcpd, tcp_flow_t *fwd, guint8 version, guint64 key, guint8 hmac_algo _U___attribute__((unused))) { |
6008 | |
6009 | guint32 token = 0; |
6010 | guint64 expected_idsn= 0; |
6011 | struct mptcp_analysis* mptcpd = tcpd->mptcp_analysis; |
6012 | |
6013 | if(fwd->mptcp_subflow->meta && (fwd->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_KEY0x03)) { |
6014 | return mptcpd; |
6015 | } |
6016 | |
6017 | /* MPTCP v0 only standardizes SHA1, and v1 SHA256. */ |
6018 | if (version == 0) |
6019 | mptcp_cryptodata_sha1(key, &token, &expected_idsn); |
6020 | else if (version == 1) |
6021 | mptcp_cryptodata_sha256(key, &token, &expected_idsn); |
6022 | |
6023 | mptcpd = mptcp_get_meta_from_token(tcpd, fwd, token); |
6024 | |
6025 | DISSECTOR_ASSERT(fwd->mptcp_subflow->meta)((void) ((fwd->mptcp_subflow->meta) ? (void)0 : (proto_report_dissector_bug ("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-tcp.c" , 6025, "fwd->mptcp_subflow->meta")))); |
6026 | |
6027 | fwd->mptcp_subflow->meta->version = version; |
6028 | fwd->mptcp_subflow->meta->key = key; |
6029 | fwd->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_KEY0x03; |
6030 | fwd->mptcp_subflow->meta->base_dsn = expected_idsn; |
6031 | return mptcpd; |
6032 | } |
6033 | |
6034 | /* record this mapping */ |
6035 | static |
6036 | void analyze_mapping(struct tcp_analysis *tcpd, packet_info *pinfo, guint16 len, guint64 dsn, gboolean extended, guint32 ssn) { |
6037 | |
6038 | /* store mapping only if analysis is enabled and mapping is not unlimited */ |
6039 | if (!mptcp_analyze_mappings || !len) { |
6040 | return; |
6041 | } |
6042 | |
6043 | if (PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
6044 | return; |
6045 | } |
6046 | |
6047 | /* register SSN range described by the mapping into a subflow interval_tree */ |
6048 | mptcp_dss_mapping_t *mapping = NULL((void*)0); |
6049 | mapping = wmem_new0(wmem_file_scope(), mptcp_dss_mapping_t)((mptcp_dss_mapping_t*)wmem_alloc0((wmem_file_scope()), sizeof (mptcp_dss_mapping_t))); |
6050 | |
6051 | mapping->rawdsn = dsn; |
6052 | mapping->extended_dsn = extended; |
6053 | mapping->frame = pinfo->fd->num; |
6054 | mapping->ssn_low = ssn; |
6055 | mapping->ssn_high = ssn + len - 1; |
6056 | |
6057 | wmem_itree_insert(tcpd->fwd->mptcp_subflow->ssn2dsn_mappings, |
6058 | mapping->ssn_low, |
6059 | mapping->ssn_high, |
6060 | mapping |
6061 | ); |
6062 | } |
6063 | |
6064 | /* |
6065 | * The TCP Extensions for Multipath Operation with Multiple Addresses |
6066 | * are defined in RFC 6824 |
6067 | * |
6068 | * https://tools.ietf.org/html/rfc6824 |
6069 | * |
6070 | * Author: Andrei Maruseac <[emailprotected]> |
6071 | * Matthieu Coudron <[emailprotected]> |
6072 | * |
6073 | * This function just generates the mptcpheader, i.e. the generation of |
6074 | * datastructures is delayed/delegated to mptcp_analyze |
6075 | */ |
6076 | static int |
6077 | dissect_tcpopt_mptcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
6078 | { |
6079 | proto_item *item,*main_item; |
6080 | proto_tree *mptcp_tree; |
6081 | |
6082 | guint32 version; |
6083 | guint8 subtype; |
6084 | guint8 ipver; |
6085 | int offset = 0; |
6086 | int optlen = tvb_reported_length(tvb); |
6087 | int start_offset = offset; |
6088 | struct tcp_analysis *tcpd = NULL((void*)0); |
6089 | struct mptcp_analysis* mptcpd = NULL((void*)0); |
6090 | struct tcpheader *tcph = (struct tcpheader *)data; |
6091 | |
6092 | /* There may be several MPTCP options per packet, don't duplicate the structure */ |
6093 | struct mptcpheader* mph = tcph->th_mptcp; |
6094 | |
6095 | if(!mph) { |
6096 | mph = wmem_new0(pinfo->pool, struct mptcpheader)((struct mptcpheader*)wmem_alloc0((pinfo->pool), sizeof(struct mptcpheader))); |
6097 | tcph->th_mptcp = mph; |
6098 | } |
6099 | |
6100 | tcpd=get_tcp_conversation_data(NULL((void*)0),pinfo); |
6101 | mptcpd=tcpd->mptcp_analysis; |
6102 | |
6103 | /* seeing an MPTCP packet on the subflow automatically qualifies it as an mptcp subflow */ |
6104 | if(!tcpd->fwd->mptcp_subflow) { |
6105 | mptcp_init_subflow(tcpd->fwd); |
6106 | } |
6107 | if(!tcpd->rev->mptcp_subflow) { |
6108 | mptcp_init_subflow(tcpd->rev); |
6109 | } |
6110 | |
6111 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPTCP"); |
6112 | main_item = proto_tree_add_item(tree, proto_mptcp, tvb, offset, -1, ENC_NA0x00000000); |
6113 | mptcp_tree = proto_item_add_subtree(main_item, ett_tcp_option_mptcp); |
6114 | |
6115 | proto_tree_add_item(mptcp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
6116 | offset += 1; |
6117 | |
6118 | proto_tree_add_item(mptcp_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
6119 | offset += 1; |
6120 | |
6121 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_subtype, tvb, |
6122 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
6123 | |
6124 | subtype = tvb_get_guint8(tvb, offset) >> 4; |
6125 | proto_item_append_text(main_item, ": %s", val_to_str(subtype, mptcp_subtype_vs, "Unknown (%d)")); |
6126 | |
6127 | /** preemptively allocate mptcpd when subtype won't allow to find a meta */ |
6128 | if(!mptcpd && (subtype > TCPOPT_MPTCP_MP_JOIN0x1)) { |
6129 | mptcpd = mptcp_alloc_analysis(tcpd); |
6130 | } |
6131 | |
6132 | switch (subtype) { |
6133 | case TCPOPT_MPTCP_MP_CAPABLE0x0: |
6134 | mph->mh_mpc = TRUE(!(0)); |
6135 | |
6136 | proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_version, tvb, |
6137 | offset, 1, ENC_BIG_ENDIAN0x00000000, &version); |
6138 | offset += 1; |
6139 | |
6140 | item = proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags, |
6141 | ett_tcp_option_mptcp, |
6142 | version == 1 ? tcp_option_mptcp_capable_v1_flags : tcp_option_mptcp_capable_v0_flags, |
6143 | ENC_BIG_ENDIAN0x00000000); |
6144 | mph->mh_capable_flags = tvb_get_guint8(tvb, offset); |
6145 | if ((mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK0x3F) == 0) { |
6146 | expert_add_info(pinfo, item, &ei_mptcp_analysis_missing_algorithm); |
6147 | } |
6148 | if ((mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK0x3F) != MPTCP_HMAC_SHA) { |
6149 | expert_add_info(pinfo, item, &ei_mptcp_analysis_unsupported_algorithm); |
6150 | } |
6151 | offset += 1; |
6152 | |
6153 | /* optlen == 12 => SYN or SYN/ACK; optlen == 20 => ACK; |
6154 | * optlen == 22 => ACK + data (v1 only); |
6155 | * optlen == 24 => ACK + data + csum (v1 only) |
6156 | */ |
6157 | if (optlen == 12 || optlen == 20 || optlen == 22 || optlen == 24) { |
6158 | |
6159 | mph->mh_key = tvb_get_ntoh64(tvb,offset); |
6160 | proto_tree_add_uint64(mptcp_tree, hf_tcp_option_mptcp_sender_key, tvb, offset, 8, mph->mh_key); |
6161 | offset += 8; |
6162 | |
6163 | mptcpd = get_or_create_mptcpd_from_key(tcpd, tcpd->fwd, version, mph->mh_key, mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK0x3F); |
6164 | mptcpd->master = tcpd; |
6165 | |
6166 | item = proto_tree_add_uint(mptcp_tree, |
6167 | hf_mptcp_expected_token, tvb, offset, 0, tcpd->fwd->mptcp_subflow->meta->token); |
6168 | proto_item_set_generated(item); |
6169 | |
6170 | item = proto_tree_add_uint64(mptcp_tree, |
6171 | hf_mptcp_expected_idsn, tvb, offset, 0, tcpd->fwd->mptcp_subflow->meta->base_dsn); |
6172 | proto_item_set_generated(item); |
6173 | |
6174 | /* last ACK of 3WHS, repeats both keys */ |
6175 | if (optlen >= 20) { |
6176 | guint64 recv_key = tvb_get_ntoh64(tvb,offset); |
6177 | proto_tree_add_uint64(mptcp_tree, hf_tcp_option_mptcp_recv_key, tvb, offset, 8, recv_key); |
6178 | offset += 8; |
6179 | |
6180 | if(tcpd->rev->mptcp_subflow->meta |
6181 | && (tcpd->rev->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_KEY0x03)) { |
6182 | |
6183 | /* compare the echoed key with the server key */ |
6184 | if(tcpd->rev->mptcp_subflow->meta->key != recv_key) { |
6185 | expert_add_info(pinfo, item, &ei_mptcp_analysis_echoed_key_mismatch); |
6186 | } |
6187 | } |
6188 | else { |
6189 | mptcpd = get_or_create_mptcpd_from_key(tcpd, tcpd->rev, version, recv_key, mph->mh_capable_flags & MPTCP_CAPABLE_CRYPTO_MASK0x3F); |
6190 | } |
6191 | } |
6192 | |
6193 | /* MPTCP v1 ACK + data, contains data_len and optional checksum */ |
6194 | if (optlen >= 22) { |
6195 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_lvl_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); |
6196 | mph->mh_dss_length = tvb_get_ntohs(tvb,offset); |
6197 | offset += 2; |
6198 | |
6199 | if (mph->mh_dss_length == 0) { |
6200 | expert_add_info(pinfo, mptcp_tree, &ei_mptcp_infinite_mapping); |
6201 | } |
6202 | |
6203 | /* when data len is present, this MP_CAPABLE also carries an implicit mapping ... */ |
6204 | analyze_mapping(tcpd, pinfo, mph->mh_dss_length, tcpd->fwd->mptcp_subflow->meta->base_dsn + 1, TRUE(!(0)), tcph->th_seq); |
6205 | |
6206 | /* ... with optional checksum */ |
6207 | if (optlen == 24) |
6208 | { |
6209 | proto_tree_add_checksum(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_checksum, -1, NULL((void*)0), pinfo, 0, ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00); |
6210 | } |
6211 | } |
6212 | } |
6213 | break; |
6214 | |
6215 | case TCPOPT_MPTCP_MP_JOIN0x1: |
6216 | mph->mh_join = TRUE(!(0)); |
6217 | if(optlen != 12 && !mptcpd) { |
6218 | mptcpd = mptcp_alloc_analysis(tcpd); |
6219 | } |
6220 | switch (optlen) { |
6221 | /* Syn */ |
6222 | case 12: |
6223 | { |
6224 | proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags, |
6225 | ett_tcp_option_mptcp, tcp_option_mptcp_join_flags, |
6226 | ENC_BIG_ENDIAN0x00000000); |
6227 | offset += 1; |
6228 | tcpd->fwd->mptcp_subflow->address_id = tvb_get_guint8(tvb, offset); |
6229 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset, |
6230 | 1, ENC_BIG_ENDIAN0x00000000); |
6231 | offset += 1; |
6232 | |
6233 | proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_recv_token, tvb, offset, |
6234 | 4, ENC_BIG_ENDIAN0x00000000, &mph->mh_token); |
6235 | offset += 4; |
6236 | |
6237 | mptcpd = mptcp_get_meta_from_token(tcpd, tcpd->rev, mph->mh_token); |
6238 | if (tcpd->fwd->mptcp_subflow->meta->version == 1) { |
6239 | mptcp_meta_flow_t *tmp = tcpd->fwd->mptcp_subflow->meta; |
6240 | |
6241 | /* if the negotiated version is v1 the first key was exchanged on SYN/ACK packet: we must swap the meta */ |
6242 | tcpd->fwd->mptcp_subflow->meta = tcpd->rev->mptcp_subflow->meta; |
6243 | tcpd->rev->mptcp_subflow->meta = tmp; |
6244 | } |
6245 | |
6246 | proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_sender_rand, tvb, offset, |
6247 | 4, ENC_BIG_ENDIAN0x00000000, &tcpd->fwd->mptcp_subflow->nonce); |
6248 | |
6249 | } |
6250 | break; |
6251 | |
6252 | |
6253 | case 16: /* Syn/Ack */ |
6254 | proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags, |
6255 | ett_tcp_option_mptcp, tcp_option_mptcp_join_flags, |
6256 | ENC_BIG_ENDIAN0x00000000); |
6257 | offset += 1; |
6258 | |
6259 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset, |
6260 | 1, ENC_BIG_ENDIAN0x00000000); |
6261 | offset += 1; |
6262 | |
6263 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_trunc_hmac, tvb, offset, |
6264 | 8, ENC_BIG_ENDIAN0x00000000); |
6265 | offset += 8; |
6266 | |
6267 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_rand, tvb, offset, |
6268 | 4, ENC_BIG_ENDIAN0x00000000); |
6269 | break; |
6270 | |
6271 | case 24: /* Ack */ |
6272 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_reserved, tvb, offset, |
6273 | 2, ENC_BIG_ENDIAN0x00000000); |
6274 | offset += 2; |
6275 | |
6276 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_sender_hmac, tvb, offset, |
6277 | 20, ENC_NA0x00000000); |
6278 | break; |
6279 | |
6280 | default: |
6281 | break; |
6282 | } |
6283 | break; |
6284 | |
6285 | /* display only *raw* values since it is harder to guess a correct value than for TCP. |
6286 | One needs to enable mptcp_analysis to get more interesting data |
6287 | */ |
6288 | case TCPOPT_MPTCP_DSS0x2: |
6289 | mph->mh_dss = TRUE(!(0)); |
6290 | |
6291 | offset += 1; |
6292 | mph->mh_dss_flags = tvb_get_guint8(tvb, offset) & 0x1F; |
6293 | |
6294 | proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags, |
6295 | ett_tcp_option_mptcp, tcp_option_mptcp_dss_flags, |
6296 | ENC_BIG_ENDIAN0x00000000); |
6297 | offset += 1; |
6298 | |
6299 | /* displays "raw" DataAck , ie does not convert it to its 64 bits form |
6300 | to do so you need to enable |
6301 | */ |
6302 | if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_PRESENT0x01) { |
6303 | |
6304 | guint64 dack64; |
6305 | |
6306 | /* 64bits ack */ |
6307 | if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02) { |
6308 | |
6309 | mph->mh_dss_rawack = tvb_get_ntoh64(tvb,offset); |
6310 | proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_ack_raw, tvb, offset, 8, mph->mh_dss_rawack, "%" PRIu64"l" "u" " (64bits)", mph->mh_dss_rawack); |
6311 | offset += 8; |
6312 | } |
6313 | /* 32bits ack */ |
6314 | else { |
6315 | mph->mh_dss_rawack = tvb_get_ntohl(tvb,offset); |
6316 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_ack_raw, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000); |
6317 | offset += 4; |
6318 | } |
6319 | |
6320 | if(mptcp_convert_dsn(mph->mh_dss_rawack, tcpd->rev->mptcp_subflow->meta, |
6321 | (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02) ? DSN_CONV_NONE : DSN_CONV_32_TO_64, mptcp_relative_seq, &dack64)) { |
6322 | item = proto_tree_add_uint64(mptcp_tree, hf_mptcp_ack, tvb, 0, 0, dack64); |
6323 | if (mptcp_relative_seq) { |
6324 | proto_item_append_text(item, " (Relative)"); |
6325 | } |
6326 | |
6327 | proto_item_set_generated(item); |
6328 | } |
6329 | else { |
6330 | /* ignore and continue */ |
6331 | } |
6332 | |
6333 | } |
6334 | |
6335 | /* Mapping present */ |
6336 | if (mph->mh_dss_flags & MPTCP_DSS_FLAG_MAPPING_PRESENT0x04) { |
6337 | |
6338 | guint64 dsn; |
6339 | |
6340 | if (mph->mh_dss_flags & MPTCP_DSS_FLAG_DSN_8BYTES0x08) { |
6341 | |
6342 | dsn = tvb_get_ntoh64(tvb,offset); |
6343 | proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 8, dsn, "%" PRIu64"l" "u" " (64bits version)", dsn); |
6344 | |
6345 | /* if we have the opportunity to complete the 32 Most Significant Bits of the |
6346 | * |
6347 | */ |
6348 | if(!(tcpd->fwd->mptcp_subflow->meta->static_flags & MPTCP_META_HAS_BASE_DSN_MSB0x01)) { |
6349 | tcpd->fwd->mptcp_subflow->meta->static_flags |= MPTCP_META_HAS_BASE_DSN_MSB0x01; |
6350 | tcpd->fwd->mptcp_subflow->meta->base_dsn |= (dsn & (guint32) 0); |
6351 | } |
6352 | offset += 8; |
6353 | } else { |
6354 | dsn = tvb_get_ntohl(tvb,offset); |
6355 | proto_tree_add_uint64_format_value(mptcp_tree, hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 4, dsn, "%" PRIu64"l" "u" " (32bits version)", dsn); |
6356 | offset += 4; |
6357 | } |
6358 | mph->mh_dss_rawdsn = dsn; |
6359 | |
6360 | proto_tree_add_item_ret_uint(mptcp_tree, hf_tcp_option_mptcp_subflow_seq_no, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &mph->mh_dss_ssn); |
6361 | offset += 4; |
6362 | |
6363 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_data_lvl_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); |
6364 | mph->mh_dss_length = tvb_get_ntohs(tvb,offset); |
6365 | offset += 2; |
6366 | |
6367 | if(mph->mh_dss_length == 0) { |
6368 | expert_add_info(pinfo, mptcp_tree, &ei_mptcp_infinite_mapping); |
6369 | } |
6370 | |
6371 | /* print head & tail dsn */ |
6372 | if(mptcp_convert_dsn(mph->mh_dss_rawdsn, tcpd->fwd->mptcp_subflow->meta, |
6373 | (mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02) ? DSN_CONV_NONE : DSN_CONV_32_TO_64, mptcp_relative_seq, &dsn)) { |
6374 | item = proto_tree_add_uint64(mptcp_tree, hf_mptcp_dss_dsn, tvb, 0, 0, dsn); |
6375 | if (mptcp_relative_seq) { |
6376 | proto_item_append_text(item, " (Relative)"); |
6377 | } |
6378 | |
6379 | proto_item_set_generated(item); |
6380 | } |
6381 | else { |
6382 | /* ignore and continue */ |
6383 | } |
6384 | |
6385 | analyze_mapping(tcpd, pinfo, mph->mh_dss_length, mph->mh_dss_rawdsn, mph->mh_dss_flags & MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02, mph->mh_dss_ssn); |
6386 | |
6387 | if ((int)optlen >= offset-start_offset+4) |
6388 | { |
6389 | proto_tree_add_checksum(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_checksum, -1, NULL((void*)0), pinfo, 0, ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00); |
6390 | } |
6391 | } |
6392 | break; |
6393 | |
6394 | case TCPOPT_MPTCP_ADD_ADDR0x3: |
6395 | mph->mh_add = TRUE(!(0)); |
6396 | ipver = tvb_get_guint8(tvb, offset) & 0x0F; |
6397 | if (ipver == 4 || ipver == 6) |
6398 | proto_tree_add_item(mptcp_tree, |
6399 | hf_tcp_option_mptcp_ipver, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
6400 | else |
6401 | proto_tree_add_item(mptcp_tree, |
6402 | hf_tcp_option_mptcp_echo, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
6403 | offset += 1; |
6404 | |
6405 | proto_tree_add_item(mptcp_tree, |
6406 | hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
6407 | offset += 1; |
6408 | |
6409 | if (optlen == 8 || optlen == 10 || optlen == 16 || optlen == 18) { |
6410 | proto_tree_add_item(mptcp_tree, |
6411 | hf_tcp_option_mptcp_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000); |
6412 | offset += 4; |
6413 | } |
6414 | |
6415 | if (optlen == 20 || optlen == 22 || optlen == 28 || optlen == 30) { |
6416 | proto_tree_add_item(mptcp_tree, |
6417 | hf_tcp_option_mptcp_ipv6, tvb, offset, 16, ENC_NA0x00000000); |
6418 | offset += 16; |
6419 | } |
6420 | |
6421 | if (optlen == 10 || optlen == 18 || optlen == 22 || optlen == 30) { |
6422 | proto_tree_add_item(mptcp_tree, |
6423 | hf_tcp_option_mptcp_port, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); |
6424 | offset += 2; |
6425 | } |
6426 | |
6427 | if (optlen == 16 || optlen == 18 || optlen == 28 || optlen == 30) { |
6428 | proto_tree_add_item(mptcp_tree, |
6429 | hf_tcp_option_mptcp_addaddr_trunc_hmac, tvb, offset, 8, ENC_BIG_ENDIAN0x00000000); |
6430 | } |
6431 | break; |
6432 | |
6433 | case TCPOPT_MPTCP_REMOVE_ADDR0x4: |
6434 | mph->mh_remove = TRUE(!(0)); |
6435 | item = proto_tree_add_uint(mptcp_tree, hf_mptcp_number_of_removed_addresses, tvb, start_offset+2, |
6436 | 1, optlen - 3); |
6437 | proto_item_set_generated(item); |
6438 | offset += 1; |
6439 | while(offset < start_offset + (int)optlen) { |
6440 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_address_id, tvb, offset, |
6441 | 1, ENC_BIG_ENDIAN0x00000000); |
6442 | offset += 1; |
6443 | } |
6444 | break; |
6445 | |
6446 | case TCPOPT_MPTCP_MP_PRIO0x5: |
6447 | mph->mh_prio = TRUE(!(0)); |
6448 | proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags, |
6449 | ett_tcp_option_mptcp, tcp_option_mptcp_join_flags, |
6450 | ENC_BIG_ENDIAN0x00000000); |
6451 | offset += 1; |
6452 | |
6453 | if (optlen == 4) { |
6454 | proto_tree_add_item(mptcp_tree, |
6455 | hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
6456 | } |
6457 | break; |
6458 | |
6459 | case TCPOPT_MPTCP_MP_FAIL0x6: |
6460 | mph->mh_fail = TRUE(!(0)); |
6461 | proto_tree_add_item(mptcp_tree, |
6462 | hf_tcp_option_mptcp_reserved, tvb, offset,2, ENC_BIG_ENDIAN0x00000000); |
6463 | offset += 2; |
6464 | |
6465 | proto_tree_add_item(mptcp_tree, |
6466 | hf_tcp_option_mptcp_data_seq_no_raw, tvb, offset, 8, ENC_BIG_ENDIAN0x00000000); |
6467 | break; |
6468 | |
6469 | case TCPOPT_MPTCP_MP_FASTCLOSE0x7: |
6470 | mph->mh_fastclose = TRUE(!(0)); |
6471 | proto_tree_add_item(mptcp_tree, |
6472 | hf_tcp_option_mptcp_reserved, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); |
6473 | offset += 2; |
6474 | |
6475 | proto_tree_add_item(mptcp_tree, |
6476 | hf_tcp_option_mptcp_recv_key, tvb, offset, 8, ENC_BIG_ENDIAN0x00000000); |
6477 | mph->mh_key = tvb_get_ntoh64(tvb,offset); |
6478 | break; |
6479 | |
6480 | case TCPOPT_MPTCP_MP_TCPRST0x8: |
6481 | mph->mh_tcprst = TRUE(!(0)); |
6482 | proto_tree_add_bitmask(mptcp_tree, tvb, offset, hf_tcp_option_mptcp_flags, |
6483 | ett_tcp_option_mptcp, tcp_option_mptcp_tcprst_flags, |
6484 | ENC_BIG_ENDIAN0x00000000); |
6485 | offset += 1; |
6486 | proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_tcprst_reason, tvb, offset, 1, |
6487 | ENC_BIG_ENDIAN0x00000000); |
6488 | break; |
6489 | |
6490 | default: |
6491 | break; |
6492 | } |
6493 | |
6494 | if ((mptcpd != NULL((void*)0)) && (tcpd->mptcp_analysis != NULL((void*)0))) { |
6495 | |
6496 | /* if mptcpd just got allocated, remember the initial addresses |
6497 | * which will serve as identifiers for the conversation filter |
6498 | */ |
6499 | if(tcpd->fwd->mptcp_subflow->meta->ip_src.len == 0) { |
6500 | |
6501 | copy_address_wmem(wmem_file_scope(), &tcpd->fwd->mptcp_subflow->meta->ip_src, &tcph->ip_src); |
6502 | copy_address_wmem(wmem_file_scope(), &tcpd->fwd->mptcp_subflow->meta->ip_dst, &tcph->ip_dst); |
6503 | |
6504 | copy_address_shallow(&tcpd->rev->mptcp_subflow->meta->ip_src, &tcpd->fwd->mptcp_subflow->meta->ip_dst); |
6505 | copy_address_shallow(&tcpd->rev->mptcp_subflow->meta->ip_dst, &tcpd->fwd->mptcp_subflow->meta->ip_src); |
6506 | |
6507 | tcpd->fwd->mptcp_subflow->meta->sport = tcph->th_sport; |
6508 | tcpd->fwd->mptcp_subflow->meta->dport = tcph->th_dport; |
6509 | } |
6510 | |
6511 | mph->mh_stream = tcpd->mptcp_analysis->stream; |
6512 | } |
6513 | |
6514 | return tvb_captured_length(tvb); |
6515 | } |
6516 | |
6517 | static int |
6518 | dissect_tcpopt_cc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
6519 | { |
6520 | proto_tree *field_tree; |
6521 | proto_item *item; |
6522 | proto_item *length_item; |
6523 | int offset = 0; |
6524 | guint32 cc; |
6525 | |
6526 | item = proto_tree_add_item(tree, proto_tcp_option_cc, tvb, offset, -1, ENC_NA0x00000000); |
6527 | field_tree = proto_item_add_subtree(item, ett_tcp_opt_cc); |
6528 | |
6529 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
6530 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
6531 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
6532 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
6533 | |
6534 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_CC6)) |
6535 | return tvb_captured_length(tvb); |
6536 | |
6537 | proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_cc, tvb, |
6538 | offset + 2, 4, ENC_BIG_ENDIAN0x00000000, &cc); |
6539 | |
6540 | tcp_info_append_uint(pinfo, "CC", cc); |
6541 | return tvb_captured_length(tvb); |
6542 | } |
6543 | |
6544 | static int |
6545 | dissect_tcpopt_md5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
6546 | { |
6547 | proto_tree *field_tree; |
6548 | proto_item *item; |
6549 | proto_item *length_item; |
6550 | int offset = 0, optlen = tvb_reported_length(tvb); |
6551 | |
6552 | item = proto_tree_add_item(tree, proto_tcp_option_md5, tvb, offset, -1, ENC_NA0x00000000); |
6553 | field_tree = proto_item_add_subtree(item, ett_tcp_opt_md5); |
6554 | |
6555 | col_append_lstr(pinfo->cinfo, COL_INFO, " MD5", COL_ADD_LSTR_TERMINATOR(const char *) -1); |
6556 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
6557 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
6558 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
6559 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
6560 | |
6561 | if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_MD518)) |
6562 | return tvb_captured_length(tvb); |
6563 | |
6564 | proto_tree_add_item(field_tree, hf_tcp_option_md5_digest, tvb, |
6565 | offset + 2, optlen - 2, ENC_NA0x00000000); |
6566 | |
6567 | return tvb_captured_length(tvb); |
6568 | } |
6569 | |
6570 | static int |
6571 | dissect_tcpopt_ao(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
6572 | { |
6573 | proto_tree *field_tree; |
6574 | proto_item *item; |
6575 | proto_item *length_item; |
6576 | int offset = 0, optlen = tvb_reported_length(tvb); |
6577 | |
6578 | item = proto_tree_add_item(tree, proto_tcp_option_ao, tvb, offset, -1, ENC_NA0x00000000); |
6579 | field_tree = proto_item_add_subtree(item, ett_tcp_opt_ao); |
6580 | |
6581 | col_append_lstr(pinfo->cinfo, COL_INFO, "TCP AO", COL_ADD_LSTR_TERMINATOR(const char *) -1); |
6582 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
6583 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
6584 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
6585 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
6586 | |
6587 | if (optlen < 4) { |
6588 | expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, |
6589 | "option length should be >= than 4"); |
6590 | return tvb_captured_length(tvb); |
6591 | } |
6592 | |
6593 | proto_tree_add_item(field_tree, hf_tcp_option_ao_keyid, tvb, |
6594 | offset + 2, 1, ENC_NA0x00000000); |
6595 | |
6596 | proto_tree_add_item(field_tree, hf_tcp_option_ao_rnextkeyid, tvb, |
6597 | offset + 3, 1, ENC_NA0x00000000); |
6598 | |
6599 | if (optlen > 4) |
6600 | proto_tree_add_item(field_tree, hf_tcp_option_ao_mac, tvb, |
6601 | offset + 4, optlen - 4, ENC_NA0x00000000); |
6602 | |
6603 | return tvb_captured_length(tvb); |
6604 | } |
6605 | |
6606 | static int |
6607 | dissect_tcpopt_qs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
6608 | { |
6609 | proto_tree *field_tree; |
6610 | proto_item *item; |
6611 | proto_item *length_item; |
6612 | guint8 rate; |
6613 | int offset = 0; |
6614 | |
6615 | item = proto_tree_add_item(tree, proto_tcp_option_qs, tvb, offset, -1, ENC_NA0x00000000); |
6616 | field_tree = proto_item_add_subtree(item, ett_tcp_opt_qs); |
6617 | |
6618 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
6619 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
6620 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
6621 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
6622 | |
6623 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_QS8)) |
6624 | return tvb_captured_length(tvb); |
6625 | |
6626 | rate = tvb_get_guint8(tvb, offset + 2) & 0x0f; |
6627 | col_append_lstr(pinfo->cinfo, COL_INFO, |
6628 | " QSresp=", val_to_str_ext_const(rate, &qs_rate_vals_ext, "Unknown"), |
6629 | COL_ADD_LSTR_TERMINATOR(const char *) -1); |
6630 | proto_tree_add_item(field_tree, hf_tcp_option_qs_rate, tvb, |
6631 | offset + 2, 1, ENC_BIG_ENDIAN0x00000000); |
6632 | proto_tree_add_item(field_tree, hf_tcp_option_qs_ttl_diff, tvb, |
6633 | offset + 3, 1, ENC_BIG_ENDIAN0x00000000); |
6634 | |
6635 | return tvb_captured_length(tvb); |
6636 | } |
6637 | |
6638 | static int |
6639 | dissect_tcpopt_scps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
6640 | { |
6641 | struct tcp_analysis *tcpd; |
6642 | proto_tree *field_tree = NULL((void*)0); |
6643 | tcp_flow_t *flow; |
6644 | int direction; |
6645 | proto_item *tf = NULL((void*)0), *item; |
6646 | proto_tree *flags_tree = NULL((void*)0); |
6647 | guint8 capvector; |
6648 | guint8 connid; |
6649 | int offset = 0, optlen = tvb_reported_length(tvb); |
6650 | |
6651 | tcpd = get_tcp_conversation_data(NULL((void*)0),pinfo); |
6652 | |
6653 | /* check direction and get ua lists */ |
6654 | direction=cmp_address(&pinfo->src, &pinfo->dst); |
6655 | |
6656 | /* if the addresses are equal, match the ports instead */ |
6657 | if(direction==0) { |
6658 | direction= (pinfo->srcport > pinfo->destport) ? 1 : -1; |
6659 | } |
6660 | |
6661 | if(direction>=0) |
6662 | flow =&(tcpd->flow1); |
6663 | else |
6664 | flow =&(tcpd->flow2); |
6665 | |
6666 | item = proto_tree_add_item(tree, proto_tcp_option_scps, |
6667 | tvb, offset, -1, ENC_NA0x00000000); |
6668 | field_tree = proto_item_add_subtree(item, ett_tcp_option_scps); |
6669 | |
6670 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
6671 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
6672 | proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
6673 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
6674 | |
6675 | /* If the option length == 4, this is a real SCPS capability option |
6676 | * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol |
6677 | * (SCPS-TP)" Section 3.2.3 for definition. |
6678 | */ |
6679 | if (optlen == 4) { |
6680 | tf = proto_tree_add_item(field_tree, hf_tcp_option_scps_vector, tvb, |
6681 | offset + 2, 1, ENC_BIG_ENDIAN0x00000000); |
6682 | flags_tree = proto_item_add_subtree(tf, ett_tcp_scpsoption_flags); |
6683 | proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_bets, tvb, |
6684 | offset + 2, 1, ENC_BIG_ENDIAN0x00000000); |
6685 | proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack1, tvb, |
6686 | offset + 2, 1, ENC_BIG_ENDIAN0x00000000); |
6687 | proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack2, tvb, |
6688 | offset + 2, 1, ENC_BIG_ENDIAN0x00000000); |
6689 | proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_compress, tvb, |
6690 | offset + 2, 1, ENC_BIG_ENDIAN0x00000000); |
6691 | proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_nlts, tvb, |
6692 | offset + 2, 1, ENC_BIG_ENDIAN0x00000000); |
6693 | proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_reserved, tvb, |
6694 | offset + 2, 1, ENC_BIG_ENDIAN0x00000000); |
6695 | capvector = tvb_get_guint8(tvb, offset + 2); |
6696 | |
6697 | if (capvector) { |
6698 | struct capvec |
6699 | { |
6700 | guint8 mask; |
6701 | const gchar *str; |
6702 | } capvecs[] = { |
6703 | {0x80, "BETS"}, |
6704 | {0x40, "SNACK1"}, |
6705 | {0x20, "SNACK2"}, |
6706 | {0x10, "COMP"}, |
6707 | {0x08, "NLTS"}, |
6708 | {0x07, "RESERVED"} |
6709 | }; |
6710 | gboolean anyflag = FALSE(0); |
6711 | guint i; |
6712 | |
6713 | col_append_str(pinfo->cinfo, COL_INFO, " SCPS["); |
6714 | for (i = 0; i < sizeof(capvecs)/sizeof(struct capvec); i++) { |
6715 | if (capvector & capvecs[i].mask) { |
6716 | proto_item_append_text(tf, "%s%s", anyflag ? ", " : " (", |
6717 | capvecs[i].str); |
6718 | col_append_lstr(pinfo->cinfo, COL_INFO, |
6719 | anyflag ? ", " : "", |
6720 | capvecs[i].str, |
6721 | COL_ADD_LSTR_TERMINATOR(const char *) -1); |
6722 | anyflag = TRUE(!(0)); |
6723 | } |
6724 | } |
6725 | col_append_str(pinfo->cinfo, COL_INFO, "]"); |
6726 | proto_item_append_text(tf, ")"); |
6727 | } |
6728 | |
6729 | proto_tree_add_item(field_tree, hf_tcp_scpsoption_connection_id, tvb, |
6730 | offset + 3, 1, ENC_BIG_ENDIAN0x00000000); |
6731 | connid = tvb_get_guint8(tvb, offset + 3); |
6732 | flow->scps_capable = 1; |
6733 | |
6734 | if (connid) |
6735 | tcp_info_append_uint(pinfo, "Connection ID", connid); |
6736 | } else { |
6737 | /* The option length != 4, so this is an infamous "extended capabilities |
6738 | * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS |
6739 | * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition. |
6740 | * |
6741 | * As the format of this option is only partially defined (it is |
6742 | * a community (or more likely vendor) defined format beyond that, so |
6743 | * at least for now, we only parse the standardized portion of the option. |
6744 | */ |
6745 | guint8 local_offset = 2; |
6746 | guint8 binding_space; |
6747 | guint8 extended_cap_length; |
6748 | |
6749 | if (flow->scps_capable != 1) { |
6750 | /* There was no SCPS capabilities option preceding this */ |
6751 | proto_item_set_text(item, |
6752 | "Illegal SCPS Extended Capabilities (%u bytes)", |
6753 | optlen); |
6754 | } else { |
6755 | proto_item_set_text(item, |
6756 | "SCPS Extended Capabilities (%u bytes)", |
6757 | optlen); |
6758 | |
6759 | /* There may be multiple binding spaces included in a single option, |
6760 | * so we will semi-parse each of the stacked binding spaces - skipping |
6761 | * over the octets following the binding space identifier and length. |
6762 | */ |
6763 | while (optlen > local_offset) { |
6764 | |
6765 | /* 1st octet is Extended Capability Binding Space */ |
6766 | binding_space = tvb_get_guint8(tvb, (offset + local_offset)); |
6767 | |
6768 | /* 2nd octet (upper 4-bits) has binding space length in 16-bit words. |
6769 | * As defined by the specification, this length is exclusive of the |
6770 | * octets containing the extended capability type and length |
6771 | */ |
6772 | extended_cap_length = |
6773 | (tvb_get_guint8(tvb, (offset + local_offset + 1)) >> 4); |
6774 | |
6775 | /* Convert the extended capabilities length into bytes for display */ |
6776 | extended_cap_length = (extended_cap_length << 1); |
6777 | |
6778 | proto_tree_add_item(field_tree, hf_tcp_option_scps_binding, tvb, offset + local_offset, 1, ENC_BIG_ENDIAN0x00000000); |
6779 | proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding_len, tvb, offset + local_offset + 1, 1, extended_cap_length); |
6780 | |
6781 | /* Step past the binding space and length octets */ |
6782 | local_offset += 2; |
6783 | |
6784 | proto_tree_add_item(field_tree, hf_tcp_option_scps_binding_data, tvb, offset + local_offset, extended_cap_length, ENC_NA0x00000000); |
6785 | |
6786 | tcp_info_append_uint(pinfo, "EXCAP", binding_space); |
6787 | |
6788 | /* Step past the Extended capability data |
6789 | * Treat the extended capability data area as opaque; |
6790 | * If one desires to parse the extended capability data |
6791 | * (say, in a vendor aware build of wireshark), it would |
6792 | * be triggered here. |
6793 | */ |
6794 | local_offset += extended_cap_length; |
6795 | } |
6796 | } |
6797 | } |
6798 | |
6799 | return tvb_captured_length(tvb); |
6800 | } |
6801 | |
6802 | static int |
6803 | dissect_tcpopt_user_to(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
6804 | { |
6805 | proto_item *tf; |
6806 | proto_tree *field_tree; |
6807 | proto_item *length_item; |
6808 | guint16 to; |
6809 | int offset = 0; |
6810 | |
6811 | tf = proto_tree_add_item(tree, proto_tcp_option_user_to, tvb, offset, -1, ENC_NA0x00000000); |
6812 | field_tree = proto_item_add_subtree(tf, ett_tcp_option_user_to); |
6813 | |
6814 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
6815 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
6816 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
6817 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
6818 | |
6819 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_USER_TO4)) |
6820 | return tvb_captured_length(tvb); |
6821 | |
6822 | proto_tree_add_item(field_tree, hf_tcp_option_user_to_granularity, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000); |
6823 | to = tvb_get_ntohs(tvb, offset + 2) & 0x7FFF; |
6824 | proto_tree_add_item(field_tree, hf_tcp_option_user_to_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000); |
6825 | |
6826 | tcp_info_append_uint(pinfo, "USER_TO", to); |
6827 | return tvb_captured_length(tvb); |
6828 | } |
6829 | |
6830 | /* This is called for SYN+ACK packets and the purpose is to verify that |
6831 | * the SCPS capabilities option has been successfully negotiated for the flow. |
6832 | * If the SCPS capabilities option was offered by only one party, the |
6833 | * proactively set scps_capable attribute of the flow (set upon seeing |
6834 | * the first instance of the SCPS option) is revoked. |
6835 | */ |
6836 | static void |
6837 | verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd) |
6838 | { |
6839 | tf_syn = 0x0; |
6840 | |
6841 | if(tcpd) { |
6842 | if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) { |
6843 | tcpd->flow1.scps_capable = 0; |
6844 | tcpd->flow2.scps_capable = 0; |
6845 | } else { |
6846 | expert_add_info(pinfo, tf_syn, &ei_tcp_scps_capable); |
6847 | } |
6848 | } |
6849 | } |
6850 | |
6851 | /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS |
6852 | * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option |
6853 | */ |
6854 | static int |
6855 | dissect_tcpopt_snack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
6856 | { |
6857 | struct tcp_analysis *tcpd=NULL((void*)0); |
6858 | guint32 relative_hole_offset; |
6859 | guint32 relative_hole_size; |
6860 | guint16 base_mss = 0; |
6861 | guint32 ack; |
6862 | guint32 hole_start; |
6863 | guint32 hole_end; |
6864 | int offset = 0; |
6865 | proto_item *hidden_item, *tf; |
6866 | proto_tree *field_tree; |
6867 | proto_item *length_item; |
6868 | |
6869 | tf = proto_tree_add_item(tree, proto_tcp_option_snack, tvb, offset, -1, ENC_NA0x00000000); |
6870 | field_tree = proto_item_add_subtree(tf, ett_tcp_option_snack); |
6871 | |
6872 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
6873 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
6874 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
6875 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
6876 | |
6877 | if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SNACK6)) |
6878 | return tvb_captured_length(tvb); |
6879 | |
6880 | tcpd = get_tcp_conversation_data(NULL((void*)0),pinfo); |
6881 | |
6882 | /* The SNACK option reports missing data with a granularity of segments. */ |
6883 | proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_snack_offset, |
6884 | tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000, &relative_hole_offset); |
6885 | |
6886 | proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_snack_size, |
6887 | tvb, offset + 4, 2, ENC_BIG_ENDIAN0x00000000, &relative_hole_size); |
6888 | |
6889 | ack = tvb_get_ntohl(tvb, 8); |
6890 | |
6891 | if (tcp_analyze_seq && tcp_relative_seq) { |
6892 | ack -= tcpd->rev->base_seq; |
6893 | } |
6894 | |
6895 | /* To aid analysis, we can use a simple but generally effective heuristic |
6896 | * to report the most likely boundaries of the missing data. If the |
6897 | * flow is scps_capable, we track the maximum sized segment that was |
6898 | * acknowledged by the receiver and use that as the reporting granularity. |
6899 | * This may be different from the negotiated MTU due to PMTUD or flows |
6900 | * that do not send max-sized segments. |
6901 | */ |
6902 | base_mss = tcpd->fwd->maxsizeacked; |
6903 | |
6904 | if (base_mss) { |
6905 | /* Scale the reported offset and hole size by the largest segment acked */ |
6906 | hole_start = ack + (base_mss * relative_hole_offset); |
6907 | hole_end = hole_start + (base_mss * relative_hole_size); |
6908 | |
6909 | hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_snack_le, |
6910 | tvb, offset + 2, 2, hole_start); |
6911 | proto_item_set_hidden(hidden_item); |
6912 | |
6913 | hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_snack_re, |
6914 | tvb, offset + 4, 2, hole_end); |
6915 | proto_item_set_hidden(hidden_item); |
6916 | |
6917 | proto_tree_add_expert_format(field_tree, pinfo, &ei_tcp_option_snack_sequence, tvb, offset+2, 4, |
6918 | "SNACK Sequence %u - %u%s", hole_start, hole_end, ((tcp_analyze_seq && tcp_relative_seq) ? " (relative)" : "")); |
6919 | |
6920 | tcp_info_append_uint(pinfo, "SNLE", hole_start); |
6921 | tcp_info_append_uint(pinfo, "SNRE", hole_end); |
6922 | } |
6923 | |
6924 | return tvb_captured_length(tvb); |
6925 | } |
6926 | |
6927 | enum |
6928 | { |
6929 | PROBE_VERSION_UNSPEC = 0, |
6930 | PROBE_VERSION_1 = 1, |
6931 | PROBE_VERSION_2 = 2, |
6932 | PROBE_VERSION_MAX |
6933 | }; |
6934 | |
6935 | /* Probe type definition. */ |
6936 | enum |
6937 | { |
6938 | PROBE_QUERY = 0, |
6939 | PROBE_RESPONSE = 1, |
6940 | PROBE_INTERNAL = 2, |
6941 | PROBE_TRACE = 3, |
6942 | PROBE_QUERY_SH = 4, |
6943 | PROBE_RESPONSE_SH = 5, |
6944 | PROBE_QUERY_INFO = 6, |
6945 | PROBE_RESPONSE_INFO = 7, |
6946 | PROBE_QUERY_INFO_SH = 8, |
6947 | PROBE_QUERY_INFO_SID = 9, |
6948 | PROBE_RST = 10, |
6949 | PROBE_TYPE_MAX |
6950 | }; |
6951 | |
6952 | static const value_string rvbd_probe_type_vs[] = { |
6953 | { PROBE_QUERY, "Probe Query" }, |
6954 | { PROBE_RESPONSE, "Probe Response" }, |
6955 | { PROBE_INTERNAL, "Probe Internal" }, |
6956 | { PROBE_TRACE, "Probe Trace" }, |
6957 | { PROBE_QUERY_SH, "Probe Query SH" }, |
6958 | { PROBE_RESPONSE_SH, "Probe Response SH" }, |
6959 | { PROBE_QUERY_INFO, "Probe Query Info" }, |
6960 | { PROBE_RESPONSE_INFO, "Probe Response Info" }, |
6961 | { PROBE_QUERY_INFO_SH, "Probe Query Info SH" }, |
6962 | { PROBE_QUERY_INFO_SID, "Probe Query Info Store ID" }, |
6963 | { PROBE_RST, "Probe Reset" }, |
6964 | { 0, NULL((void*)0) } |
6965 | }; |
6966 | |
6967 | #define PROBE_OPTLEN_OFFSET1 1 |
6968 | |
6969 | #define PROBE_VERSION_TYPE_OFFSET2 2 |
6970 | #define PROBE_V1_RESERVED_OFFSET3 3 |
6971 | #define PROBE_V1_PROBER_OFFSET4 4 |
6972 | #define PROBE_V1_APPLI_VERSION_OFFSET8 8 |
6973 | #define PROBE_V1_PROXY_ADDR_OFFSET8 8 |
6974 | #define PROBE_V1_PROXY_PORT_OFFSET12 12 |
6975 | #define PROBE_V1_SH_CLIENT_ADDR_OFFSET8 8 |
6976 | #define PROBE_V1_SH_PROXY_ADDR_OFFSET12 12 |
6977 | #define PROBE_V1_SH_PROXY_PORT_OFFSET16 16 |
6978 | |
6979 | #define PROBE_V2_INFO_OFFSET3 3 |
6980 | |
6981 | #define PROBE_V2_INFO_CLIENT_ADDR_OFFSET4 4 |
6982 | #define PROBE_V2_INFO_STOREID_OFFSET4 4 |
6983 | |
6984 | #define PROBE_VERSION_MASK0x01 0x01 |
6985 | |
6986 | /* Probe Query Extra Info flags */ |
6987 | #define RVBD_FLAGS_PROBE_LAST0x01 0x01 |
6988 | #define RVBD_FLAGS_PROBE_NCFE0x04 0x04 |
6989 | |
6990 | /* Probe Response Extra Info flags */ |
6991 | #define RVBD_FLAGS_PROBE_SERVER0x01 0x01 |
6992 | #define RVBD_FLAGS_PROBE_SSLCERT0x02 0x02 |
6993 | #define RVBD_FLAGS_PROBE0x10 0x10 |
6994 | |
6995 | typedef struct rvbd_option_data |
6996 | { |
6997 | gboolean valid; |
6998 | guint8 type; |
6999 | guint8 probe_flags; |
7000 | |
7001 | } rvbd_option_data; |
7002 | |
7003 | static void |
7004 | rvbd_probe_decode_version_type(const guint8 vt, guint8 *ver, guint8 *type) |
7005 | { |
7006 | if (vt & PROBE_VERSION_MASK0x01) { |
7007 | *ver = PROBE_VERSION_1; |
7008 | *type = vt >> 4; |
7009 | } else { |
7010 | *ver = PROBE_VERSION_2; |
7011 | *type = vt >> 1; |
7012 | } |
7013 | } |
7014 | |
7015 | static void |
7016 | rvbd_probe_resp_add_info(proto_item *pitem, packet_info *pinfo, tvbuff_t *tvb, int ip_offset, guint16 port) |
7017 | { |
7018 | proto_item_append_text(pitem, ", Server Steelhead: %s:%u", tvb_ip_to_str(pinfo->pool, tvb, ip_offset)tvb_address_to_str(pinfo->pool, tvb, AT_IPv4, ip_offset), port); |
7019 | |
7020 | col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA+, "); |
7021 | } |
7022 | |
7023 | static int |
7024 | dissect_tcpopt_rvbd_probe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
7025 | { |
7026 | guint8 ver, type; |
7027 | proto_tree *field_tree; |
7028 | proto_item *pitem; |
7029 | proto_item *length_item; |
7030 | int offset = 0, |
7031 | optlen = tvb_reported_length(tvb); |
7032 | struct tcpheader *tcph = (struct tcpheader*)data; |
7033 | |
7034 | pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_probe, tvb, offset, -1, ENC_NA0x00000000); |
7035 | field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe); |
7036 | |
7037 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
7038 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
7039 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
7040 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
7041 | |
7042 | if (optlen < TCPOLEN_RVBD_PROBE_MIN3) { |
7043 | /* Bogus - option length is less than what it's supposed to be for |
7044 | this option. */ |
7045 | expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, |
7046 | "option length should be >= %u)", |
7047 | TCPOLEN_RVBD_PROBE_MIN3); |
7048 | return tvb_captured_length(tvb); |
7049 | } |
7050 | |
7051 | rvbd_probe_decode_version_type( |
7052 | tvb_get_guint8(tvb, offset + PROBE_VERSION_TYPE_OFFSET2), |
7053 | &ver, &type); |
7054 | |
7055 | proto_item_append_text(pitem, ": %s", val_to_str_const(type, rvbd_probe_type_vs, "Probe Unknown")); |
7056 | |
7057 | if (type >= PROBE_TYPE_MAX) |
7058 | return tvb_captured_length(tvb); |
7059 | |
7060 | if (ver == PROBE_VERSION_1) { |
7061 | guint16 port; |
7062 | |
7063 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type1, tvb, |
7064 | offset + PROBE_VERSION_TYPE_OFFSET2, 1, ENC_BIG_ENDIAN0x00000000); |
7065 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_version1, tvb, |
7066 | offset + PROBE_VERSION_TYPE_OFFSET2, 1, ENC_BIG_ENDIAN0x00000000); |
7067 | |
7068 | if (type == PROBE_INTERNAL) |
7069 | return offset + PROBE_VERSION_TYPE_OFFSET2; |
7070 | |
7071 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_reserved, tvb, offset + PROBE_V1_RESERVED_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000); |
7072 | |
7073 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_prober, tvb, |
7074 | offset + PROBE_V1_PROBER_OFFSET4, 4, ENC_BIG_ENDIAN0x00000000); |
7075 | |
7076 | switch (type) { |
7077 | |
7078 | case PROBE_QUERY: |
7079 | case PROBE_QUERY_SH: |
7080 | case PROBE_TRACE: |
7081 | { |
7082 | rvbd_option_data* option_data; |
7083 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_appli_ver, tvb, |
7084 | offset + PROBE_V1_APPLI_VERSION_OFFSET8, 2, |
7085 | ENC_BIG_ENDIAN0x00000000); |
7086 | |
7087 | proto_item_append_text(pitem, ", CSH IP: %s", tvb_ip_to_str(pinfo->pool, tvb, offset + PROBE_V1_PROBER_OFFSET)tvb_address_to_str(pinfo->pool, tvb, AT_IPv4, offset + 4)); |
7088 | |
7089 | option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num); |
7090 | if (option_data == NULL((void*)0)) |
7091 | { |
7092 | option_data = wmem_new0(pinfo->pool, rvbd_option_data)((rvbd_option_data*)wmem_alloc0((pinfo->pool), sizeof(rvbd_option_data ))); |
7093 | p_add_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num, option_data); |
7094 | } |
7095 | |
7096 | option_data->valid = TRUE(!(0)); |
7097 | option_data->type = type; |
7098 | |
7099 | } |
7100 | break; |
7101 | |
7102 | case PROBE_RESPONSE: |
7103 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb, |
7104 | offset + PROBE_V1_PROXY_ADDR_OFFSET8, 4, ENC_BIG_ENDIAN0x00000000); |
7105 | |
7106 | port = tvb_get_ntohs(tvb, offset + PROBE_V1_PROXY_PORT_OFFSET12); |
7107 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb, |
7108 | offset + PROBE_V1_PROXY_PORT_OFFSET12, 2, ENC_BIG_ENDIAN0x00000000); |
7109 | |
7110 | rvbd_probe_resp_add_info(pitem, pinfo, tvb, offset + PROBE_V1_PROXY_ADDR_OFFSET8, port); |
7111 | break; |
7112 | |
7113 | case PROBE_RESPONSE_SH: |
7114 | proto_tree_add_item(field_tree, |
7115 | hf_tcp_option_rvbd_probe_client, tvb, |
7116 | offset + PROBE_V1_SH_CLIENT_ADDR_OFFSET8, 4, |
7117 | ENC_BIG_ENDIAN0x00000000); |
7118 | |
7119 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb, |
7120 | offset + PROBE_V1_SH_PROXY_ADDR_OFFSET12, 4, ENC_BIG_ENDIAN0x00000000); |
7121 | |
7122 | port = tvb_get_ntohs(tvb, offset + PROBE_V1_SH_PROXY_PORT_OFFSET16); |
7123 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb, |
7124 | offset + PROBE_V1_SH_PROXY_PORT_OFFSET16, 2, ENC_BIG_ENDIAN0x00000000); |
7125 | |
7126 | rvbd_probe_resp_add_info(pitem, pinfo, tvb, offset + PROBE_V1_SH_PROXY_ADDR_OFFSET12, port); |
7127 | break; |
7128 | } |
7129 | } |
7130 | else if (ver == PROBE_VERSION_2) { |
7131 | proto_item *ver_pi; |
7132 | proto_item *flag_pi; |
7133 | proto_tree *flag_tree; |
7134 | guint8 flags; |
7135 | |
7136 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type2, tvb, |
7137 | offset + PROBE_VERSION_TYPE_OFFSET2, 1, ENC_BIG_ENDIAN0x00000000); |
7138 | |
7139 | proto_tree_add_uint_format_value( |
7140 | field_tree, hf_tcp_option_rvbd_probe_version2, tvb, |
7141 | offset + PROBE_VERSION_TYPE_OFFSET2, 1, ver, "%u", ver); |
7142 | /* Use version1 for filtering purposes because version2 packet |
7143 | value is 0, but filtering is usually done for value 2 */ |
7144 | ver_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_version1, tvb, |
7145 | offset + PROBE_VERSION_TYPE_OFFSET2, 1, ver); |
7146 | proto_item_set_hidden(ver_pi); |
7147 | |
7148 | switch (type) { |
7149 | |
7150 | case PROBE_QUERY_INFO: |
7151 | case PROBE_QUERY_INFO_SH: |
7152 | case PROBE_QUERY_INFO_SID: |
7153 | flags = tvb_get_guint8(tvb, offset + PROBE_V2_INFO_OFFSET3); |
7154 | flag_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_flags, |
7155 | tvb, offset + PROBE_V2_INFO_OFFSET3, |
7156 | 1, flags); |
7157 | |
7158 | flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags); |
7159 | proto_tree_add_item(flag_tree, |
7160 | hf_tcp_option_rvbd_probe_flag_not_cfe, |
7161 | tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000); |
7162 | proto_tree_add_item(flag_tree, |
7163 | hf_tcp_option_rvbd_probe_flag_last_notify, |
7164 | tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000); |
7165 | |
7166 | switch (type) |
7167 | { |
7168 | case PROBE_QUERY_INFO: |
7169 | { |
7170 | rvbd_option_data* option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num); |
7171 | if (option_data == NULL((void*)0)) |
7172 | { |
7173 | option_data = wmem_new0(pinfo->pool, rvbd_option_data)((rvbd_option_data*)wmem_alloc0((pinfo->pool), sizeof(rvbd_option_data ))); |
7174 | p_add_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num, option_data); |
7175 | } |
7176 | |
7177 | option_data->probe_flags = flags; |
7178 | } |
7179 | break; |
7180 | case PROBE_QUERY_INFO_SH: |
7181 | proto_tree_add_item(flag_tree, |
7182 | hf_tcp_option_rvbd_probe_client, tvb, |
7183 | offset + PROBE_V2_INFO_CLIENT_ADDR_OFFSET4, |
7184 | 4, ENC_BIG_ENDIAN0x00000000); |
7185 | break; |
7186 | case PROBE_QUERY_INFO_SID: |
7187 | proto_tree_add_item(flag_tree, |
7188 | hf_tcp_option_rvbd_probe_storeid, tvb, |
7189 | offset + PROBE_V2_INFO_STOREID_OFFSET4, |
7190 | 4, ENC_BIG_ENDIAN0x00000000); |
7191 | break; |
7192 | } |
7193 | |
7194 | if (type != PROBE_QUERY_INFO_SID && |
7195 | tcph != NULL((void*)0) && |
7196 | (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == (TH_SYN0x0002|TH_ACK0x0010) && |
7197 | (flags & RVBD_FLAGS_PROBE_LAST0x01)) { |
7198 | col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA++, "); |
7199 | } |
7200 | |
7201 | break; |
7202 | |
7203 | case PROBE_RESPONSE_INFO: |
7204 | flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags, |
7205 | tvb, offset + PROBE_V2_INFO_OFFSET3, |
7206 | 1, ENC_BIG_ENDIAN0x00000000); |
7207 | |
7208 | flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags); |
7209 | proto_tree_add_item(flag_tree, |
7210 | hf_tcp_option_rvbd_probe_flag_probe_cache, |
7211 | tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000); |
7212 | proto_tree_add_item(flag_tree, |
7213 | hf_tcp_option_rvbd_probe_flag_sslcert, |
7214 | tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000); |
7215 | proto_tree_add_item(flag_tree, |
7216 | hf_tcp_option_rvbd_probe_flag_server_connected, |
7217 | tvb, offset + PROBE_V2_INFO_OFFSET3, 1, ENC_BIG_ENDIAN0x00000000); |
7218 | break; |
7219 | |
7220 | case PROBE_RST: |
7221 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags, |
7222 | tvb, offset + PROBE_V2_INFO_OFFSET3, |
7223 | 1, ENC_BIG_ENDIAN0x00000000); |
7224 | break; |
7225 | } |
7226 | } |
7227 | |
7228 | return tvb_captured_length(tvb); |
7229 | } |
7230 | |
7231 | enum { |
7232 | TRPY_OPTNUM_OFFSET = 0, |
7233 | TRPY_OPTLEN_OFFSET = 1, |
7234 | |
7235 | TRPY_OPTIONS_OFFSET = 2, |
7236 | TRPY_SRC_ADDR_OFFSET = 4, |
7237 | TRPY_DST_ADDR_OFFSET = 8, |
7238 | TRPY_SRC_PORT_OFFSET = 12, |
7239 | TRPY_DST_PORT_OFFSET = 14, |
7240 | TRPY_CLIENT_PORT_OFFSET = 16 |
7241 | }; |
7242 | |
7243 | /* Trpy Flags */ |
7244 | #define RVBD_FLAGS_TRPY_MODE0x0001 0x0001 |
7245 | #define RVBD_FLAGS_TRPY_OOB0x0002 0x0002 |
7246 | #define RVBD_FLAGS_TRPY_CHKSUM0x0004 0x0004 |
7247 | #define RVBD_FLAGS_TRPY_FW_RST0x0100 0x0100 |
7248 | #define RVBD_FLAGS_TRPY_FW_RST_INNER0x0200 0x0200 |
7249 | #define RVBD_FLAGS_TRPY_FW_RST_PROBE0x0400 0x0400 |
7250 | |
7251 | static const true_false_string trpy_mode_str = { |
7252 | "Port Transparency", |
7253 | "Full Transparency" |
7254 | }; |
7255 | |
7256 | static int |
7257 | dissect_tcpopt_rvbd_trpy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
7258 | { |
7259 | proto_tree *field_tree; |
7260 | proto_item *pitem; |
7261 | proto_item *length_item; |
7262 | guint16 sport, dport, flags; |
7263 | int offset = 0, |
7264 | optlen = tvb_reported_length(tvb); |
7265 | static int * const rvbd_trpy_flags[] = { |
7266 | &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe, |
7267 | &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner, |
7268 | &hf_tcp_option_rvbd_trpy_flag_fw_rst, |
7269 | &hf_tcp_option_rvbd_trpy_flag_chksum, |
7270 | &hf_tcp_option_rvbd_trpy_flag_oob, |
7271 | &hf_tcp_option_rvbd_trpy_flag_mode, |
7272 | NULL((void*)0) |
7273 | }; |
7274 | |
7275 | col_prepend_fstr(pinfo->cinfo, COL_INFO, "TRPY, "); |
7276 | |
7277 | pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_trpy, tvb, offset, -1, ENC_NA0x00000000); |
7278 | field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_trpy); |
7279 | |
7280 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, |
7281 | offset, 1, ENC_BIG_ENDIAN0x00000000); |
7282 | length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, |
7283 | offset + 1, 1, ENC_BIG_ENDIAN0x00000000); |
7284 | |
7285 | if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_RVBD_TRPY_MIN16)) |
7286 | return tvb_captured_length(tvb); |
7287 | |
7288 | flags = tvb_get_ntohs(tvb, offset + TRPY_OPTIONS_OFFSET); |
7289 | proto_tree_add_bitmask_with_flags(field_tree, tvb, offset + TRPY_OPTIONS_OFFSET, hf_tcp_option_rvbd_trpy_flags, |
7290 | ett_tcp_opt_rvbd_trpy_flags, rvbd_trpy_flags, ENC_NA0x00000000, BMT_NO_APPEND0x01); |
7291 | |
7292 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src, |
7293 | tvb, offset + TRPY_SRC_ADDR_OFFSET, 4, ENC_BIG_ENDIAN0x00000000); |
7294 | |
7295 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst, |
7296 | tvb, offset + TRPY_DST_ADDR_OFFSET, 4, ENC_BIG_ENDIAN0x00000000); |
7297 | |
7298 | sport = tvb_get_ntohs(tvb, offset + TRPY_SRC_PORT_OFFSET); |
7299 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src_port, |
7300 | tvb, offset + TRPY_SRC_PORT_OFFSET, 2, ENC_BIG_ENDIAN0x00000000); |
7301 | |
7302 | dport = tvb_get_ntohs(tvb, offset + TRPY_DST_PORT_OFFSET); |
7303 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst_port, |
7304 | tvb, offset + TRPY_DST_PORT_OFFSET, 2, ENC_BIG_ENDIAN0x00000000); |
7305 | |
7306 | proto_item_append_text(pitem, " %s:%u -> %s:%u", |
7307 | tvb_ip_to_str(pinfo->pool, tvb, offset + TRPY_SRC_ADDR_OFFSET)tvb_address_to_str(pinfo->pool, tvb, AT_IPv4, offset + TRPY_SRC_ADDR_OFFSET ), sport, |
7308 | tvb_ip_to_str(pinfo->pool, tvb, offset + TRPY_DST_ADDR_OFFSET)tvb_address_to_str(pinfo->pool, tvb, AT_IPv4, offset + TRPY_DST_ADDR_OFFSET ), dport); |
7309 | |
7310 | /* Client port only set on SYN: optlen == 18 */ |
7311 | if ((flags & RVBD_FLAGS_TRPY_OOB0x0002) && (optlen > TCPOLEN_RVBD_TRPY_MIN16)) |
7312 | proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_client_port, |
7313 | tvb, offset + TRPY_CLIENT_PORT_OFFSET, 2, ENC_BIG_ENDIAN0x00000000); |
7314 | |
7315 | /* Despite that we have the right TCP ports for other protocols, |
7316 | * the data is related to the Riverbed Optimization Protocol and |
7317 | * not understandable by normal protocol dissectors. If the sport |
7318 | * protocol is available then use that, otherwise just output it |
7319 | * as a hex-dump. |
7320 | */ |
7321 | if (sport_handle != NULL((void*)0)) { |
7322 | conversation_t *conversation; |
7323 | conversation = find_or_create_conversation(pinfo); |
7324 | if (conversation_get_dissector(conversation, pinfo->num) != sport_handle) { |
7325 | conversation_set_dissector(conversation, sport_handle); |
7326 | } |
7327 | } else if (data_handle != NULL((void*)0)) { |
7328 | conversation_t *conversation; |
7329 | conversation = find_or_create_conversation(pinfo); |
7330 | if (conversation_get_dissector(conversation, pinfo->num) != data_handle) { |
7331 | conversation_set_dissector(conversation, data_handle); |
7332 | } |
7333 | } |
7334 | |
7335 | return tvb_captured_length(tvb); |
7336 | } |
7337 | |
7338 | /* Started as a copy of dissect_ip_tcp_options(), but was changed to support |
7339 | options as a dissector table */ |
7340 | static void |
7341 | tcp_dissect_options(tvbuff_t *tvb, int offset, guint length, |
7342 | packet_info *pinfo, proto_tree *opt_tree, |
7343 | proto_item *opt_item, void * data) |
7344 | { |
7345 | guchar opt; |
7346 | guint optlen, nop_count = 0; |
7347 | proto_tree *field_tree; |
7348 | const char *name; |
7349 | dissector_handle_t option_dissector; |
7350 | tvbuff_t *next_tvb; |
7351 | struct tcpheader *tcph = (struct tcpheader *)data; |
7352 | gboolean mss_seen = FALSE(0); |
7353 | gboolean eol_seen = FALSE(0); |
7354 | gboolean sack_perm_seen = FALSE(0); |
7355 | |
7356 | while (length > 0) { |
7357 | opt = tvb_get_guint8(tvb, offset); |
7358 | if (eol_seen && opt != TCPOPT_EOL0) { |
7359 | proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_non_zero_bytes_after_eol, tvb, offset, length, |
7360 | "Non-zero header padding"); |
7361 | return; |
7362 | } |
7363 | --length; /* account for type byte */ |
7364 | if ((opt == TCPOPT_EOL0) || (opt == TCPOPT_NOP1)) { |
7365 | int local_proto; |
7366 | proto_item* field_item; |
7367 | |
7368 | /* We assume that the only options with no length are EOL and |
7369 | NOP options, so that we can treat unknown options as having |
7370 | a minimum length of 2, and at least be able to move on to |
7371 | the next option by using the length in the option. */ |
7372 | if (opt == TCPOPT_EOL0) { |
7373 | local_proto = proto_tcp_option_eol; |
7374 | eol_seen = true1; |
7375 | } else if (opt == TCPOPT_NOP1) { |
7376 | local_proto = proto_tcp_option_nop; |
7377 | |
7378 | if (opt_item && (nop_count == 0 || offset % 4)) { |
7379 | /* Count number of NOP in a row within a uint32 */ |
7380 | nop_count++; |
7381 | |
7382 | if (nop_count == 4) { |
7383 | expert_add_info(pinfo, opt_item, &ei_tcp_nop); |
7384 | } |
7385 | } else { |
7386 | nop_count = 0; |
7387 | } |
7388 | } else { |
7389 | DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\"" , "epan/dissectors/packet-tcp.c", 7389)); |
7390 | } |
7391 | |
7392 | field_item = proto_tree_add_item(opt_tree, local_proto, tvb, offset, 1, ENC_NA0x00000000); |
7393 | field_tree = proto_item_add_subtree(field_item, ett_tcp_option_other); |
7394 | proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); |
7395 | proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", proto_get_protocol_short_name(find_protocol_by_id(local_proto))); |
7396 | offset += 1; |
7397 | } else { |
7398 | option_dissector = dissector_get_uint_handle(tcp_option_table, opt); |
7399 | if (option_dissector == NULL((void*)0)) { |
7400 | name = wmem_strdup_printf(pinfo->pool, "Unknown (0x%02x)", opt); |
7401 | option_dissector = tcp_opt_unknown_handle; |
7402 | } else { |
7403 | name = dissector_handle_get_protocol_short_name(option_dissector); |
7404 | } |
7405 | |
7406 | /* Option has a length. Is it in the packet? */ |
7407 | if (length == 0) { |
7408 | /* Bogus - packet must at least include option code byte and |
7409 | length byte! */ |
7410 | proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, 1, |
7411 | "%s (length byte past end of options)", name); |
7412 | return; |
7413 | } |
7414 | |
7415 | optlen = tvb_get_guint8(tvb, offset + 1); /* total including type, len */ |
7416 | --length; /* account for length byte */ |
7417 | |
7418 | if (optlen < 2) { |
7419 | /* Bogus - option length is too short to include option code and |
7420 | option length. */ |
7421 | proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, 2, |
7422 | "%s (with too-short option length = %u byte%s)", |
7423 | name, optlen, plurality(optlen, "", "s")((optlen) == 1 ? ("") : ("s"))); |
7424 | return; |
7425 | } else if (optlen - 2 > length) { |
7426 | /* Bogus - option goes past the end of the header. */ |
7427 | proto_tree_add_expert_format(opt_tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, length, |
7428 | "%s (option length = %u byte%s says option goes past end of options)", |
7429 | name, optlen, plurality(optlen, "", "s")((optlen) == 1 ? ("") : ("s"))); |
7430 | return; |
7431 | } |
7432 | |
7433 | if (opt == TCPOPT_MSS2) |
7434 | { |
7435 | mss_seen = TRUE(!(0)); |
7436 | } else if (opt == TCPOPT_SACK_PERM4) |
7437 | { |
7438 | sack_perm_seen = TRUE(!(0)); |
7439 | } |
7440 | |
7441 | next_tvb = tvb_new_subset_length(tvb, offset, optlen); |
7442 | call_dissector_with_data(option_dissector, next_tvb, pinfo, opt_tree/* tree */, data); |
7443 | proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name); |
7444 | |
7445 | offset += optlen; |
7446 | length -= (optlen-2); //already accounted for type and len bytes |
7447 | } |
7448 | } |
7449 | |
7450 | if (tcph->th_flags & TH_SYN0x0002) |
7451 | { |
7452 | if (mss_seen == FALSE(0)) |
7453 | { |
7454 | expert_add_info(pinfo, opt_item, &ei_tcp_option_mss_absent); |
7455 | } |
7456 | if (sack_perm_seen == FALSE(0)) |
7457 | { |
7458 | expert_add_info(pinfo, opt_item, &ei_tcp_option_sack_perm_absent); |
7459 | } |
7460 | } |
7461 | } |
7462 | |
7463 | /* Determine if there is a sub-dissector and call it; return TRUE |
7464 | if there was a sub-dissector, FALSE otherwise. |
7465 | |
7466 | This has been separated into a stand alone routine to other protocol |
7467 | dissectors can call to it, e.g., SOCKS. */ |
7468 | |
7469 | static bool_Bool try_heuristic_first; |
7470 | |
7471 | |
7472 | /* this function can be called with tcpd==NULL as from the msproxy dissector */ |
7473 | gboolean |
7474 | decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, |
7475 | proto_tree *tree, int src_port, int dst_port, |
7476 | struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo) |
7477 | { |
7478 | tvbuff_t *next_tvb; |
7479 | int low_port, high_port; |
7480 | int save_desegment_offset; |
7481 | gboolean try_low_port, try_high_port, try_server_port; |
7482 | guint32 save_desegment_len; |
7483 | heur_dtbl_entry_t *hdtbl_entry; |
7484 | exp_pdu_data_t *exp_pdu_data; |
7485 | |
7486 | /* Don't call subdissectors for keepalives. Even though they do contain |
7487 | * payload "data", it's just garbage. Display any data the keepalive |
7488 | * packet might contain though. |
7489 | */ |
7490 | if(tcpd && tcpd->ta) { |
7491 | if(tcpd->ta->flags&TCP_A_KEEP_ALIVE0x0008) { |
7492 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
7493 | call_dissector(data_handle, next_tvb, pinfo, tree); |
7494 | return TRUE(!(0)); |
7495 | } |
7496 | } |
7497 | |
7498 | if (tcp_no_subdissector_on_error && !(tcp_desegment && tcp_reassemble_out_of_order) && |
7499 | tcpd && tcpd->ta && tcpd->ta->flags & (TCP_A_RETRANSMISSION0x0001 | TCP_A_OUT_OF_ORDER0x0200)) { |
7500 | /* Don't try to dissect a retransmission high chance that it will mess |
7501 | * subdissectors for protocols that require in-order delivery of the |
7502 | * PDUs. (i.e. DCE/RPCoverHTTP and encryption) |
7503 | * If OoO reassembly is enabled and if this segment was previously lost, |
7504 | * then this retransmission could have finished reassembly, so continue. |
7505 | * XXX should this option be removed? "tcp_reassemble_out_of_order" |
7506 | * should have addressed the above in-order requirement. |
7507 | */ |
7508 | return FALSE(0); |
7509 | } |
7510 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
7511 | |
7512 | save_desegment_offset = pinfo->desegment_offset; |
7513 | save_desegment_len = pinfo->desegment_len; |
7514 | |
7515 | /* determine if this packet is part of a conversation and call dissector */ |
7516 | /* for the conversation if available */ |
7517 | |
7518 | if (try_conversation_dissector(&pinfo->src, &pinfo->dst, CONVERSATION_TCP, |
7519 | src_port, dst_port, next_tvb, pinfo, tree, tcpinfo, 0)) { |
7520 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7521 | handle_export_pdu_conversation(pinfo, next_tvb, src_port, dst_port, tcpinfo); |
7522 | return TRUE(!(0)); |
7523 | } |
7524 | |
7525 | /* If the user has manually configured one of the server, low, or high |
7526 | * ports to a dissector other than the default (via Decode As or the |
7527 | * preferences associated with Decode As), try those first, in that order. |
7528 | */ |
7529 | try_server_port = FALSE(0); |
7530 | if (tcpd && tcpd->server_port != 0) { |
7531 | if (dissector_is_uint_changed(subdissector_table, tcpd->server_port)) { |
7532 | if (dissector_try_uint_new(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) { |
7533 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7534 | handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo); |
7535 | return TRUE(!(0)); |
7536 | } |
7537 | } else { |
7538 | /* The default; try it later */ |
7539 | try_server_port = TRUE(!(0)); |
7540 | } |
7541 | } |
7542 | |
7543 | if (src_port > dst_port) { |
7544 | low_port = dst_port; |
7545 | high_port = src_port; |
7546 | } else { |
7547 | low_port = src_port; |
7548 | high_port = dst_port; |
7549 | } |
7550 | |
7551 | try_low_port = FALSE(0); |
7552 | if (low_port != 0) { |
7553 | if (dissector_is_uint_changed(subdissector_table, low_port)) { |
7554 | if (dissector_try_uint_new(subdissector_table, low_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) { |
7555 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7556 | handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo); |
7557 | return TRUE(!(0)); |
7558 | } |
7559 | } else { |
7560 | /* The default; try it later */ |
7561 | try_low_port = TRUE(!(0)); |
7562 | } |
7563 | } |
7564 | |
7565 | try_high_port = FALSE(0); |
7566 | if (high_port != 0) { |
7567 | if (dissector_is_uint_changed(subdissector_table, high_port)) { |
7568 | if (dissector_try_uint_new(subdissector_table, high_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) { |
7569 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7570 | handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo); |
7571 | return TRUE(!(0)); |
7572 | } |
7573 | } else { |
7574 | /* The default; try it later */ |
7575 | try_high_port = TRUE(!(0)); |
7576 | } |
7577 | } |
7578 | |
7579 | if (try_heuristic_first) { |
7580 | /* do lookup with the heuristic subdissector table */ |
7581 | if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) { |
7582 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7583 | handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo); |
7584 | return TRUE(!(0)); |
7585 | } |
7586 | } |
7587 | |
7588 | /* Do lookups with the subdissector table. |
7589 | Try the server port captured on the SYN or SYN|ACK packet. After that |
7590 | try the port number with the lower value first, followed by the |
7591 | port number with the higher value. This means that, for packets |
7592 | where a dissector is registered for *both* port numbers: |
7593 | |
7594 | 1) we pick the same dissector for traffic going in both directions; |
7595 | |
7596 | 2) we prefer the port number that's more likely to be the right |
7597 | one (as that prefers well-known ports to reserved ports); |
7598 | |
7599 | although there is, of course, no guarantee that any such strategy |
7600 | will always pick the right port number. |
7601 | |
7602 | XXX - we ignore port numbers of 0, as some dissectors use a port |
7603 | number of 0 to disable the port. */ |
7604 | |
7605 | if (try_server_port && |
7606 | dissector_try_uint_new(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) { |
7607 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7608 | handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo); |
7609 | return TRUE(!(0)); |
7610 | } |
7611 | |
7612 | if (try_low_port && |
7613 | dissector_try_uint_new(subdissector_table, low_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) { |
7614 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7615 | handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo); |
7616 | return TRUE(!(0)); |
7617 | } |
7618 | if (try_high_port && |
7619 | dissector_try_uint_new(subdissector_table, high_port, next_tvb, pinfo, tree, TRUE(!(0)), tcpinfo)) { |
7620 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7621 | handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo); |
7622 | return TRUE(!(0)); |
7623 | } |
7624 | |
7625 | if (!try_heuristic_first) { |
7626 | /* do lookup with the heuristic subdissector table */ |
7627 | if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) { |
7628 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7629 | handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo); |
7630 | return TRUE(!(0)); |
7631 | } |
7632 | } |
7633 | |
7634 | /* |
7635 | * heuristic / conversation / port registered dissectors rejected the packet; |
7636 | * make sure they didn't also request desegmentation (we could just override |
7637 | * the request, but rejecting a packet *and* requesting desegmentation is a sign |
7638 | * of the dissector's code needing clearer thought, so we fail so that the |
7639 | * problem is made more obvious). |
7640 | */ |
7641 | DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&((void) ((save_desegment_offset == pinfo->desegment_offset && save_desegment_len == pinfo->desegment_len) ? ( void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 7642, "save_desegment_offset == pinfo->desegment_offset && save_desegment_len == pinfo->desegment_len" )))) |
7642 | save_desegment_len == pinfo->desegment_len)((void) ((save_desegment_offset == pinfo->desegment_offset && save_desegment_len == pinfo->desegment_len) ? ( void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\"" , "epan/dissectors/packet-tcp.c", 7642, "save_desegment_offset == pinfo->desegment_offset && save_desegment_len == pinfo->desegment_len" )))); |
7643 | |
7644 | /* Oh, well, we don't know this; dissect it as data. */ |
7645 | call_dissector(data_handle,next_tvb, pinfo, tree); |
7646 | |
7647 | pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); |
7648 | if (have_tap_listener(exported_pdu_tap)) { |
7649 | exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME12); |
7650 | exp_pdu_data->tvb_captured_length = tvb_captured_length(next_tvb); |
7651 | exp_pdu_data->tvb_reported_length = tvb_reported_length(next_tvb); |
7652 | exp_pdu_data->pdu_tvb = next_tvb; |
7653 | |
7654 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
7655 | } |
7656 | return FALSE(0); |
7657 | } |
7658 | |
7659 | static void |
7660 | process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo, |
7661 | proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port, |
7662 | guint32 seq, guint32 nxtseq, gboolean is_tcp_segment, |
7663 | struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo) |
7664 | { |
7665 | pinfo->want_pdu_tracking=0; |
7666 | |
7667 | TRY{ except_t *volatile exc; volatile int except_state = 0; static const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch except_ch; except_setup_try(& except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch .except_jmp)) *(&exc) = &except_ch.except_obj; else * (&exc) = 0; if(except_state & 1) except_state |= 2; except_state &= ~1; if (except_state == 0 && exc == 0) { |
7668 | if(is_tcp_segment) { |
7669 | /*qqq see if it is an unaligned PDU */ |
7670 | if(tcpd && tcp_analyze_seq && (!tcp_desegment)) { |
7671 | if(seq || nxtseq) { |
7672 | offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset, |
7673 | seq, nxtseq, tcpd->fwd->multisegment_pdus); |
7674 | } |
7675 | } |
7676 | } |
7677 | /* if offset is -1 this means that this segment is known |
7678 | * to be fully inside a previously detected pdu |
7679 | * so we don't even need to try to dissect it either. |
7680 | */ |
7681 | if( (offset!=-1) && |
7682 | decode_tcp_ports(tvb, offset, pinfo, tree, src_port, |
7683 | dst_port, tcpd, tcpinfo) ) { |
7684 | /* |
7685 | * We succeeded in handing off to a subdissector. |
7686 | * |
7687 | * Is this a TCP segment or a reassembled chunk of |
7688 | * TCP payload? |
7689 | */ |
7690 | if(is_tcp_segment) { |
7691 | /* if !visited, check want_pdu_tracking and |
7692 | store it in table */ |
7693 | if(tcpd && (!pinfo->fd->visited) && |
7694 | tcp_analyze_seq && pinfo->want_pdu_tracking) { |
7695 | if(seq || nxtseq) { |
7696 | pdu_store_sequencenumber_of_next_pdu( |
7697 | pinfo, |
7698 | seq, |
7699 | nxtseq+pinfo->bytes_until_next_pdu, |
7700 | tcpd->fwd->multisegment_pdus); |
7701 | } |
7702 | } |
7703 | } |
7704 | } |
7705 | } |
7706 | CATCH_ALLif (except_state == 0 && exc != 0 && (except_state |=1)) { |
7707 | /* We got an exception. At this point the dissection is |
7708 | * completely aborted and execution will be transferred back |
7709 | * to (probably) the frame dissector. |
7710 | * Here we have to place whatever we want the dissector |
7711 | * to do before aborting the tcp dissection. |
7712 | */ |
7713 | /* |
7714 | * Is this a TCP segment or a reassembled chunk of TCP |
7715 | * payload? |
7716 | */ |
7717 | if(is_tcp_segment) { |
7718 | /* |
7719 | * It's from a TCP segment. |
7720 | * |
7721 | * if !visited, check want_pdu_tracking and store it |
7722 | * in table |
7723 | */ |
7724 | if(tcpd && (!pinfo->fd->visited) && tcp_analyze_seq && pinfo->want_pdu_tracking) { |
7725 | if(seq || nxtseq) { |
7726 | pdu_store_sequencenumber_of_next_pdu(pinfo, |
7727 | seq, |
7728 | nxtseq+pinfo->bytes_until_next_pdu, |
7729 | tcpd->fwd->multisegment_pdus); |
7730 | } |
7731 | } |
7732 | } |
7733 | RETHROW{ do { if ((1) && !(except_state == 1)) ws_log_fatal_full ("", LOG_LEVEL_ERROR, "epan/dissectors/packet-tcp.c", 7733, __func__ , "assertion failed: %s", "except_state == 1"); } while (0); longjmp (except_ch.except_jmp,1); }; |
7734 | } |
7735 | ENDTRYif(!(except_state&1) && exc != 0) except_rethrow( exc); except_free(except_ch.except_obj.except_dyndata); except_pop (); };}; |
7736 | } |
7737 | |
7738 | void |
7739 | dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq, |
7740 | guint32 nxtseq, guint32 sport, guint32 dport, |
7741 | proto_tree *tree, proto_tree *tcp_tree, |
7742 | struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo) |
7743 | { |
7744 | gint nbytes; |
7745 | gboolean save_fragmented; |
7746 | |
7747 | nbytes = tvb_reported_length_remaining(tvb, offset); |
7748 | proto_tree_add_bytes_format(tcp_tree, hf_tcp_payload, tvb, offset, |
7749 | -1, NULL((void*)0), "TCP payload (%u byte%s)", nbytes, |
7750 | plurality(nbytes, "", "s")((nbytes) == 1 ? ("") : ("s"))); |
7751 | |
7752 | /* Can we desegment this segment? */ |
7753 | if (pinfo->can_desegment) { |
7754 | /* Yes. */ |
7755 | desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree, |
7756 | tcp_tree, tcpd, tcpinfo); |
7757 | } else { |
7758 | /* No - just call the subdissector. |
7759 | Mark this as fragmented, so if somebody throws an exception, |
7760 | we don't report it as a malformed frame. */ |
7761 | save_fragmented = pinfo->fragmented; |
7762 | pinfo->fragmented = TRUE(!(0)); |
7763 | |
7764 | process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport, |
7765 | seq, nxtseq, TRUE(!(0)), tcpd, tcpinfo); |
7766 | pinfo->fragmented = save_fragmented; |
7767 | } |
7768 | } |
7769 | |
7770 | static gboolean |
7771 | capture_tcp(const guchar *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header) |
7772 | { |
7773 | guint16 src_port, dst_port, low_port, high_port; |
7774 | |
7775 | if (!BYTES_ARE_IN_FRAME(offset, len, 4)((guint)(offset) + (guint)(4) > (guint)(offset) && (guint)(offset) + (guint)(4) <= (guint)(len))) |
7776 | return FALSE(0); |
7777 | |
7778 | capture_dissector_increment_count(cpinfo, proto_tcp); |
7779 | |
7780 | src_port = pntoh16(&pd[offset]); |
7781 | dst_port = pntoh16(&pd[offset+2]); |
7782 | |
7783 | if (src_port > dst_port) { |
7784 | low_port = dst_port; |
7785 | high_port = src_port; |
7786 | } else { |
7787 | low_port = src_port; |
7788 | high_port = dst_port; |
7789 | } |
7790 | |
7791 | if (low_port != 0 && |
7792 | try_capture_dissector("tcp.port", low_port, pd, offset+20, len, cpinfo, pseudo_header)) |
7793 | return TRUE(!(0)); |
7794 | |
7795 | if (high_port != 0 && |
7796 | try_capture_dissector("tcp.port", high_port, pd, offset+20, len, cpinfo, pseudo_header)) |
7797 | return TRUE(!(0)); |
7798 | |
7799 | /* We've at least identified one type of packet, so this shouldn't be "other" */ |
7800 | return TRUE(!(0)); |
7801 | } |
7802 | |
7803 | typedef struct _tcp_tap_cleanup_t { |
7804 | |
7805 | packet_info *pinfo; |
7806 | struct tcpheader *tcph; |
7807 | |
7808 | } tcp_tap_cleanup_t; |
7809 | |
7810 | static void tcp_tap_cleanup(void *data) |
7811 | { |
7812 | tcp_tap_cleanup_t *cleanup = (tcp_tap_cleanup_t *)data; |
7813 | |
7814 | tap_queue_packet(tcp_tap, cleanup->pinfo, cleanup->tcph); |
7815 | } |
7816 | |
7817 | static int |
7818 | dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) |
7819 | { |
7820 | guint8 th_off_x2; /* combines th_off and th_x2 */ |
7821 | guint16 th_sum; |
7822 | guint32 th_urp; |
7823 | proto_tree *tcp_tree = NULL((void*)0), *field_tree = NULL((void*)0); |
7824 | proto_item *ti = NULL((void*)0), *tf, *hidden_item; |
7825 | proto_item *options_item, *hide_seqack_abs_item; |
7826 | proto_tree *options_tree; |
7827 | int offset = 0; |
7828 | char *flags_str, *flags_str_first_letter; |
7829 | guint optlen; |
7830 | guint32 nxtseq = 0; |
7831 | guint reported_len; |
7832 | vec_t cksum_vec[4]; |
7833 | guint32 phdr[2]; |
7834 | guint16 computed_cksum; |
7835 | guint16 real_window; |
7836 | guint captured_length_remaining; |
7837 | gboolean desegment_ok; |
7838 | struct tcpinfo tcpinfo; |
7839 | struct tcpheader *tcph; |
7840 | proto_item *tf_syn = NULL((void*)0), *tf_fin = NULL((void*)0), *tf_rst = NULL((void*)0), *scaled_pi; |
7841 | conversation_t *conv=NULL((void*)0); |
7842 | struct tcp_analysis *tcpd=NULL((void*)0); |
7843 | struct tcp_per_packet_data_t *tcppd=NULL((void*)0); |
7844 | proto_item *item; |
7845 | proto_tree *checksum_tree; |
7846 | gboolean icmp_ip = FALSE(0); |
7847 | guint8 conversation_completeness = 0; |
7848 | gboolean conversation_is_new = FALSE(0); |
7849 | guint8 ace; |
7850 | |
7851 | tcph = wmem_new0(pinfo->pool, struct tcpheader)((struct tcpheader*)wmem_alloc0((pinfo->pool), sizeof(struct tcpheader))); |
7852 | tcph->th_sport = tvb_get_ntohs(tvb, offset); |
7853 | tcph->th_dport = tvb_get_ntohs(tvb, offset + 2); |
7854 | copy_address_shallow(&tcph->ip_src, &pinfo->src); |
7855 | copy_address_shallow(&tcph->ip_dst, &pinfo->dst); |
7856 | |
7857 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP"); |
7858 | col_clear(pinfo->cinfo, COL_INFO); |
7859 | col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, tcph->th_sport, tcph->th_dport); |
7860 | |
7861 | if (tree) { |
7862 | ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, ENC_NA0x00000000); |
7863 | if (tcp_summary_in_tree) { |
7864 | proto_item_append_text(ti, ", Src Port: %s, Dst Port: %s", |
7865 | port_with_resolution_to_str(pinfo->pool, PT_TCP, tcph->th_sport), |
7866 | port_with_resolution_to_str(pinfo->pool, PT_TCP, tcph->th_dport)); |
7867 | } |
7868 | tcp_tree = proto_item_add_subtree(ti, ett_tcp); |
7869 | p_add_proto_data(pinfo->pool, pinfo, proto_tcp, pinfo->curr_layer_num, tcp_tree); |
7870 | |
7871 | proto_tree_add_item(tcp_tree, hf_tcp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); |
7872 | proto_tree_add_item(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000); |
7873 | hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); |
7874 | proto_item_set_hidden(hidden_item); |
7875 | hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000); |
7876 | proto_item_set_hidden(hidden_item); |
7877 | |
7878 | /* If we're dissecting the headers of a TCP packet in an ICMP packet |
7879 | * then go ahead and put the sequence numbers in the tree now (because |
7880 | * they won't be put in later because the ICMP packet only contains up |
7881 | * to the sequence number). |
7882 | * We should only need to do this for IPv4 since IPv6 will hopefully |
7883 | * carry enough TCP payload for this dissector to put the sequence |
7884 | * numbers in via the regular code path. |
7885 | */ |
7886 | { |
7887 | wmem_list_frame_t *frame; |
7888 | frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers)); |
7889 | if (proto_ip == (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))((guint) (gulong) (wmem_list_frame_data(frame)))) { |
7890 | frame = wmem_list_frame_prev(frame); |
7891 | if (proto_icmp == (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))((guint) (gulong) (wmem_list_frame_data(frame)))) { |
7892 | proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, ENC_BIG_ENDIAN0x00000000); |
7893 | icmp_ip = TRUE(!(0)); |
7894 | } |
7895 | } |
7896 | } |
7897 | } |
7898 | |
7899 | /* Set the source and destination port numbers as soon as we get them, |
7900 | so that they're available to the "Follow TCP Stream" code even if |
7901 | we throw an exception dissecting the rest of the TCP header. */ |
7902 | pinfo->ptype = PT_TCP; |
7903 | pinfo->srcport = tcph->th_sport; |
7904 | pinfo->destport = tcph->th_dport; |
7905 | |
7906 | p_add_proto_data(pinfo->pool, pinfo, hf_tcp_srcport, pinfo->curr_layer_num, GUINT_TO_POINTER(tcph->th_sport)((gpointer) (gulong) (tcph->th_sport))); |
7907 | p_add_proto_data(pinfo->pool, pinfo, hf_tcp_dstport, pinfo->curr_layer_num, GUINT_TO_POINTER(tcph->th_dport)((gpointer) (gulong) (tcph->th_dport))); |
7908 | |
7909 | tcph->th_rawseq = tvb_get_ntohl(tvb, offset + 4); |
7910 | tcph->th_seq = tcph->th_rawseq; |
7911 | tcph->th_rawack = tvb_get_ntohl(tvb, offset + 8); |
7912 | tcph->th_ack = tcph->th_rawack; |
7913 | th_off_x2 = tvb_get_guint8(tvb, offset + 12); |
7914 | tcpinfo.flags = tcph->th_flags = tvb_get_ntohs(tvb, offset + 12) & TH_MASK0x0FFF; |
7915 | tcph->th_win = tvb_get_ntohs(tvb, offset + 14); |
7916 | real_window = tcph->th_win; |
7917 | tcph->th_hlen = hi_nibble(th_off_x2)(((th_off_x2) & 0xf0) >> 4) * 4; /* TCP header length, in bytes */ |
7918 | |
7919 | /* find(or create if needed) the conversation for this tcp session |
7920 | * This is a slight deviation from find_or_create_conversation so it's |
7921 | * done manually. This is done to avoid conversation overlapping when |
7922 | * reusing ports (see issue 15097), as find_or_create_conversation automatically |
7923 | * extends the conversation found. This extension is done later. |
7924 | */ |
7925 | gboolean is_ordinary_conv = TRUE(!(0)); |
7926 | |
7927 | /* deinterlacing requested */ |
7928 | if(prefs.conversation_deinterlacing_key>0) { |
7929 | guint conv_type; |
7930 | guint32 dtlc_iface = 0; |
7931 | guint32 dtlc_vlan = 0; |
7932 | |
7933 | if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_INTERFACE0x02 && |
7934 | pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID0x00000004) { |
7935 | |
7936 | if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN0x08 && |
7937 | pinfo->vlan_id>0) { |
7938 | |
7939 | conv_type = CONVERSATION_ETH_IV; |
7940 | dtlc_vlan = pinfo->vlan_id; |
7941 | } |
7942 | else { |
7943 | conv_type = CONVERSATION_ETH_IN; |
7944 | } |
7945 | dtlc_iface = pinfo->rec->rec_header.packet_header.interface_id; |
7946 | } |
7947 | else { |
7948 | |
7949 | if(prefs.conversation_deinterlacing_key&CONV_DEINT_KEY_VLAN0x08 && |
7950 | pinfo->vlan_id>0) { |
7951 | |
7952 | conv_type = CONVERSATION_ETH_NV; |
7953 | dtlc_vlan = pinfo->vlan_id; |
7954 | } |
7955 | else { |
7956 | conv_type = CONVERSATION_ETH_NN; |
7957 | } |
7958 | } |
7959 | conversation_t *underlying_conv = find_conversation_deinterlacer(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, conv_type, dtlc_iface, dtlc_vlan , 0); |
7960 | if(underlying_conv) { |
7961 | is_ordinary_conv = FALSE(0); |
7962 | |
7963 | conv = find_conversation_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, pinfo->srcport, pinfo->destport, underlying_conv->conv_index, 0); |
7964 | if(!conv) { |
7965 | conv = conversation_new_deinterlaced(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, |
7966 | pinfo->srcport, pinfo->destport, underlying_conv->conv_index, 0); |
7967 | conversation_is_new = TRUE(!(0)); |
7968 | } |
7969 | } |
7970 | } |
7971 | |
7972 | /* |
7973 | * When it's not asked to deinterlace, or if deinterlacing failed (no related IP conversation), |
7974 | * just proceed the ordinary way. |
7975 | */ |
7976 | if(is_ordinary_conv) { |
7977 | |
7978 | conv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, pinfo->srcport, pinfo->destport, 0); |
7979 | if(!conv) { |
7980 | conv = conversation_new(pinfo->num, &pinfo->src, |
7981 | &pinfo->dst, CONVERSATION_TCP, |
7982 | pinfo->srcport, pinfo->destport, 0); |
7983 | /* we need to know when a conversation is new then we initialize the completeness correctly */ |
7984 | conversation_is_new = TRUE(!(0)); |
7985 | } |
7986 | } |
7987 | tcpd=get_tcp_conversation_data(conv,pinfo); |
7988 | |
7989 | /* If this is a SYN packet, then check if its seq-nr is different |
7990 | * from the base_seq of the retrieved conversation. If this is the |
7991 | * case, create a new conversation with the same addresses and ports |
7992 | * and set the TA_PORTS_REUSED flag. (XXX: There is a small chance |
7993 | * that this is an old duplicate SYN received after the connection |
7994 | * is ESTABLISHED on both sides, the other side will respond with |
7995 | * an appropriate ACK, and this SYN ought to be ignored rather than |
7996 | * create a new conversation.) |
7997 | * |
7998 | * If the seq-nr is the same as the base_seq, it might be a simple |
7999 | * retransmission, reattempting a handshake that was reset (due |
8000 | * to a half-open connection) with the same sequence number, or |
8001 | * (unlikely) a new connection that happens to use the same sequence |
8002 | * number as the previous one. |
8003 | * |
8004 | * If we have received a RST or FIN on the retrieved conversation, |
8005 | * create a new conversation in order to clear out the follow info, |
8006 | * sequence analysis, desegmentation, etc. |
8007 | * If not, it's probably a retransmission, and will be marked |
8008 | * as one later, but restore some flow values to reduce the |
8009 | * sequence analysis warnings if our capture file is missing a RST |
8010 | * or FIN segment that was present on the network. |
8011 | * |
8012 | * XXX - Is this affected by MPTCP which can use multiple SYNs? |
8013 | */ |
8014 | if (tcpd != NULL((void*)0) && (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == TH_SYN0x0002) { |
8015 | if (tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET0x01) { |
8016 | if(tcph->th_seq!=tcpd->fwd->base_seq || (tcpd->conversation_completeness & TCP_COMPLETENESS_RST0x20) || (tcpd->conversation_completeness & TCP_COMPLETENESS_FIN0x10)) { |
8017 | if (!(pinfo->fd->visited)) { |
8018 | |
8019 | conv=conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_TCP, pinfo->srcport, pinfo->destport, 0); |
8020 | tcpd=get_tcp_conversation_data(conv,pinfo); |
8021 | |
8022 | if(!tcpd->ta) |
8023 | tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, TRUE(!(0)), tcpd); |
8024 | tcpd->ta->flags|=TCP_A_REUSED_PORTS0x2000; |
8025 | |
8026 | /* As above, a new conversation starting with a SYN implies conversation completeness value 1 */ |
8027 | conversation_is_new = TRUE(!(0)); |
8028 | } |
8029 | } else { |
8030 | if (!(pinfo->fd->visited)) { |
8031 | /* |
8032 | * Sometimes we need to restore the nextseq value. |
8033 | * As stated in RFC 793 3.4 a RST packet might be |
8034 | * sent with SEQ being equal to the ACK received, |
8035 | * thus breaking our flow monitoring. (issue 17616) |
8036 | */ |
8037 | if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info) { |
8038 | tcpd->fwd->tcp_analyze_seq_info->nextseq = tcpd->fwd->tcp_analyze_seq_info->maxseqtobeacked; |
8039 | } |
8040 | |
8041 | if(!tcpd->ta) |
8042 | tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, TRUE(!(0)), tcpd); |
8043 | } |
8044 | } |
8045 | } |
8046 | else { |
8047 | /* |
8048 | * TCP_S_BASE_SEQ_SET being not set, we are dealing with a new conversation, |
8049 | * either created ad hoc above (general case), or by a higher protocol such as FTP. |
8050 | * Track this information, as the Completeness value will be initialized later. |
8051 | * See issue 19092. |
8052 | */ |
8053 | if (!(pinfo->fd->visited)) |
8054 | conversation_is_new = TRUE(!(0)); |
8055 | } |
8056 | tcpd->had_acc_ecn_setup_syn = (tcph->th_flags & (TH_AE0x0100|TH_CWR0x0080|TH_ECE0x0040)) == (TH_AE0x0100|TH_CWR0x0080|TH_ECE0x0040); |
8057 | } |
8058 | |
8059 | /* If this is a SYN/ACK packet, then check if its seq-nr is different |
8060 | * from the base_seq of the retrieved conversation. If this is the |
8061 | * case, set the TA_PORTS_REUSED flag and override the base seq. |
8062 | * (XXX: Should this create a new conversation, as above with a |
8063 | * SYN packet? We might have received the new connection's SYN/ACK before |
8064 | * the SYN packet, or the SYN might be missing from the capture file.) |
8065 | * If the seq-nr is the same as the base_seq, then do nothing so it |
8066 | * will be marked as a retransmission later. |
8067 | * XXX - Is this affected by MPTCP which can use multiple SYNs? |
8068 | */ |
8069 | if (tcpd != NULL((void*)0) && (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == (TH_SYN0x0002|TH_ACK0x0010)) { |
8070 | if ((tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET0x01) && |
8071 | (tcph->th_seq != tcpd->fwd->base_seq)) { |
8072 | |
8073 | /* the retrieved conversation might have a different base_seq (issue 16944) */ |
8074 | /* XXX: Shouldn't this create a new conversation? Changing the |
8075 | * base_seq will change how the previous packets in the conversation |
8076 | * are processed in the second pass. |
8077 | */ |
8078 | tcpd->fwd->base_seq = tcph->th_seq; |
8079 | |
8080 | if(!tcpd->ta) |
8081 | tcp_analyze_get_acked_struct(pinfo->num, tcph->th_seq, tcph->th_ack, TRUE(!(0)), tcpd); |
8082 | tcpd->ta->flags|=TCP_A_REUSED_PORTS0x2000; |
8083 | } |
8084 | tcpd->had_acc_ecn_setup_syn_ack = ((tcph->th_flags & (TH_AE0x0100|TH_CWR0x0080)) == TH_CWR0x0080) || |
8085 | ((tcph->th_flags & (TH_AE0x0100|TH_ECE0x0040)) == TH_AE0x0100); |
8086 | } |
8087 | |
8088 | /* Do we need to calculate timestamps relative to the tcp-stream? */ |
8089 | if (tcp_calculate_ts) { |
8090 | tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num); |
8091 | |
8092 | /* |
8093 | * Calculate the timestamps relative to this conversation (but only on |
8094 | * the first run when frames are accessed sequentially) |
8095 | */ |
8096 | if (!(pinfo->fd->visited)) |
8097 | tcp_calculate_timestamps(pinfo, tcpd, tcppd); |
8098 | } |
8099 | |
8100 | if (tcpd) { |
8101 | item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, tcpd->stream); |
8102 | proto_item_set_generated(item); |
8103 | |
8104 | if (tcppd) { |
8105 | item = proto_tree_add_uint(tcp_tree, hf_tcp_stream_pnum, tvb, offset, 0, tcppd->pnum); |
8106 | proto_item_set_generated(item); |
8107 | } |
8108 | |
8109 | /* Display the completeness of this TCP conversation */ |
8110 | static int* const completeness_fields[] = { |
8111 | &hf_tcp_completeness_rst, |
8112 | &hf_tcp_completeness_fin, |
8113 | &hf_tcp_completeness_data, |
8114 | &hf_tcp_completeness_ack, |
8115 | &hf_tcp_completeness_syn_ack, |
8116 | &hf_tcp_completeness_syn, |
8117 | NULL((void*)0)}; |
8118 | |
8119 | item = proto_tree_add_bitmask_value_with_flags(tcp_tree, NULL((void*)0), 0, |
8120 | hf_tcp_completeness, ett_tcp_completeness, completeness_fields, |
8121 | tcpd->conversation_completeness, BMT_NO_APPEND0x01); |
8122 | proto_item_set_generated(item); |
8123 | field_tree = proto_item_add_subtree(item, ett_tcp_completeness); |
8124 | |
8125 | flags_str_first_letter = tcpd->conversation_completeness_str; |
8126 | item = proto_tree_add_string(field_tree, hf_tcp_completeness_str, tvb, 0, 0, flags_str_first_letter); |
8127 | proto_item_set_generated(item); |
8128 | |
8129 | /* Copy the stream index into the header as well to make it available |
8130 | * to tap listeners. |
8131 | */ |
8132 | tcph->th_stream = tcpd->stream; |
8133 | |
8134 | /* Copy the stream index into pinfo as well to make it available |
8135 | * to callback functions (essentially conversation following events in GUI) |
8136 | */ |
8137 | pinfo->stream_id = tcpd->stream; |
8138 | |
8139 | /* initialize the SACK blocks seen to 0 */ |
8140 | if(tcp_analyze_seq && tcpd->fwd->tcp_analyze_seq_info) { |
8141 | tcpd->fwd->tcp_analyze_seq_info->num_sack_ranges = 0; |
8142 | } |
8143 | } |
8144 | |
8145 | /* is there any manual analysis waiting ? */ |
8146 | if(pinfo->fd->tcp_snd_manual_analysis > 0) { |
8147 | tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num); |
8148 | tcppd->tcp_snd_manual_analysis = pinfo->fd->tcp_snd_manual_analysis; |
8149 | } |
8150 | |
8151 | /* |
8152 | * If we've been handed an IP fragment, we don't know how big the TCP |
8153 | * segment is, so don't do anything that requires that we know that. |
8154 | * |
8155 | * The same applies if we're part of an error packet. (XXX - if the |
8156 | * ICMP and ICMPv6 dissectors could set a "this is how big the IP |
8157 | * header says it is" length in the tvbuff, we could use that; such |
8158 | * a length might also be useful for handling packets where the IP |
8159 | * length is bigger than the actual data available in the frame; the |
8160 | * dissectors should trust that length, and then throw a |
8161 | * ReportedBoundsError exception when they go past the end of the frame.) |
8162 | * |
8163 | * We also can't determine the segment length if the reported length |
8164 | * of the TCP packet is less than the TCP header length. |
8165 | */ |
8166 | reported_len = tvb_reported_length(tvb); |
8167 | |
8168 | if (!pinfo->fragmented && !pinfo->flags.in_error_pkt) { |
8169 | if (reported_len < tcph->th_hlen) { |
8170 | proto_tree_add_expert_format(tcp_tree, pinfo, &ei_tcp_short_segment, tvb, offset, 0, |
8171 | "Short segment. Segment/fragment does not contain a full TCP header" |
8172 | " (might be NMAP or someone else deliberately sending unusual packets)"); |
8173 | tcph->th_have_seglen = FALSE(0); |
8174 | } else { |
8175 | proto_item *pi; |
8176 | |
8177 | /* Compute the length of data in this segment. */ |
8178 | tcph->th_seglen = reported_len - tcph->th_hlen; |
8179 | tcph->th_have_seglen = TRUE(!(0)); |
8180 | |
8181 | pi = proto_tree_add_uint(ti, hf_tcp_len, tvb, 0, 0, tcph->th_seglen); |
8182 | proto_item_set_generated(pi); |
8183 | |
8184 | /* initialize base_seq numbers */ |
8185 | if(!(pinfo->fd->visited) && tcpd) { |
8186 | /* if this is the first segment for this list we need to store the |
8187 | * base_seq |
8188 | * We use TCP_S_SAW_SYN/SYNACK to distinguish between client and server |
8189 | * |
8190 | * Start relative seq and ack numbers at 1 if this |
8191 | * is not a SYN packet. This makes the relative |
8192 | * seq/ack numbers to be displayed correctly in the |
8193 | * event that the SYN or SYN/ACK packet is not seen |
8194 | * (this solves bug 1542) |
8195 | */ |
8196 | if( !(tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET0x01)) { |
8197 | if(tcph->th_flags & TH_SYN0x0002) { |
8198 | tcpd->fwd->base_seq = tcph->th_seq; |
8199 | tcpd->fwd->static_flags |= (tcph->th_flags & TH_ACK0x0010) ? TCP_S_SAW_SYNACK0x05 : TCP_S_SAW_SYN0x03; |
8200 | } |
8201 | else { |
8202 | tcpd->fwd->base_seq = tcph->th_seq-1; |
8203 | } |
8204 | tcpd->fwd->static_flags |= TCP_S_BASE_SEQ_SET0x01; |
8205 | } |
8206 | |
8207 | /* Only store reverse sequence if this isn't the SYN |
8208 | * There's no guarantee that the ACK field of a SYN |
8209 | * contains zeros; get the ISN from the first segment |
8210 | * with the ACK bit set instead (usually the SYN/ACK). |
8211 | * |
8212 | * If the SYN and SYN/ACK were received out-of-order, |
8213 | * the ISN is ack-1. If we missed the SYN/ACK, but got |
8214 | * the last ACK of the 3WHS, the ISN is ack-1. For all |
8215 | * other packets the ISN is unknown, so ack-1 is |
8216 | * as good a guess as ack. |
8217 | */ |
8218 | if( !(tcpd->rev->static_flags & TCP_S_BASE_SEQ_SET0x01) && (tcph->th_flags & TH_ACK0x0010) ) { |
8219 | tcpd->rev->base_seq = tcph->th_ack-1; |
8220 | tcpd->rev->static_flags |= TCP_S_BASE_SEQ_SET0x01; |
8221 | } |
8222 | } |
8223 | |
8224 | /* handle TCP seq# analysis parse all new segments we see */ |
8225 | if(tcp_analyze_seq) { |
8226 | if(!(pinfo->fd->visited)) { |
8227 | tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd, tcppd); |
8228 | } |
8229 | if(tcpd && tcp_relative_seq) { |
8230 | (tcph->th_seq) -= tcpd->fwd->base_seq; |
8231 | if (tcph->th_flags & TH_ACK0x0010) { |
8232 | (tcph->th_ack) -= tcpd->rev->base_seq; |
8233 | } |
8234 | } |
8235 | } |
8236 | |
8237 | /* re-calculate window size, based on scaling factor */ |
8238 | if (!(tcph->th_flags&TH_SYN0x0002)) { /* SYNs are never scaled */ |
8239 | if (tcpd && (tcpd->fwd->win_scale>=0)) { |
8240 | (tcph->th_win)<<=tcpd->fwd->win_scale; |
8241 | } |
8242 | else if (tcpd && (tcpd->fwd->win_scale == -1)) { |
8243 | /* i.e. Unknown, but wasn't signalled with no scaling, so use preference setting instead! */ |
8244 | if (tcp_default_window_scaling>=0) { |
8245 | (tcph->th_win)<<=tcp_default_window_scaling; |
8246 | } |
8247 | } |
8248 | } |
8249 | |
8250 | /* Compute the sequence number of next octet after this segment. */ |
8251 | nxtseq = tcph->th_seq + tcph->th_seglen; |
8252 | } |
8253 | } else |
8254 | tcph->th_have_seglen = FALSE(0); |
8255 | |
8256 | /* |
8257 | * Decode the ECN related flags as ACE if it is not a SYN segment, |
8258 | * and an AccECN-setup SYN and SYN ACK have been observed, or an |
8259 | * AccECN option was observed (this covers the case where Wireshark |
8260 | * did not observe the initial handshake). |
8261 | */ |
8262 | tcph->th_use_ace = (tcph->th_flags & TH_SYN0x0002) == 0 && |
8263 | tcpd != NULL((void*)0) && |
8264 | ((tcpd->had_acc_ecn_setup_syn && tcpd->had_acc_ecn_setup_syn_ack) || |
8265 | tcpd->had_acc_ecn_option); |
8266 | flags_str = tcp_flags_to_str(pinfo->pool, tcph); |
8267 | flags_str_first_letter = tcp_flags_to_str_first_letter(pinfo->pool, tcph); |
8268 | |
8269 | col_append_lstr(pinfo->cinfo, COL_INFO, |
8270 | " [", flags_str, "]", |
8271 | COL_ADD_LSTR_TERMINATOR(const char *) -1); |
8272 | tcp_info_append_uint(pinfo, "Seq", tcph->th_seq); |
8273 | if (tcph->th_flags&TH_ACK0x0010) |
8274 | tcp_info_append_uint(pinfo, "Ack", tcph->th_ack); |
8275 | |
8276 | tcp_info_append_uint(pinfo, "Win", tcph->th_win); |
8277 | |
8278 | if (tcp_summary_in_tree) { |
8279 | proto_item_append_text(ti, ", Seq: %u", tcph->th_seq); |
8280 | } |
8281 | |
8282 | if (!icmp_ip) { |
8283 | if(tcp_relative_seq && tcp_analyze_seq) { |
8284 | 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); |
8285 | item = proto_tree_add_uint(tcp_tree, hf_tcp_seq_abs, tvb, offset + 4, 4, tcph->th_rawseq); |
8286 | if (read_seq_as_syn_cookie) { |
8287 | proto_item* syncookie_ti = NULL((void*)0); |
8288 | proto_item_append_text(item, " (syn cookie)"); |
8289 | syncookie_ti = proto_item_add_subtree(item, ett_tcp_syncookie); |
8290 | proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_time, tvb, (offset + 4) * 8, 5, ENC_NA0x00000000); |
8291 | proto_tree_add_bits_item(syncookie_ti, hf_tcp_syncookie_mss, tvb, (offset + 4) * 8 + 5, 3, ENC_NA0x00000000); |
8292 | proto_tree_add_item(syncookie_ti, hf_tcp_syncookie_hash, tvb, offset + 4 + 1, 3, ENC_NA0x00000000); |
8293 | } |
8294 | |
8295 | } else { |
8296 | proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq); |
8297 | hide_seqack_abs_item = proto_tree_add_uint(tcp_tree, hf_tcp_seq_abs, tvb, offset + 4, 4, tcph->th_rawseq); |
8298 | proto_item_set_hidden(hide_seqack_abs_item); |
8299 | } |
8300 | } |
8301 | |
8302 | if (tcph->th_hlen < TCPH_MIN_LEN20) { |
8303 | /* Give up at this point; we put the source and destination port in |
8304 | the tree, before fetching the header length, so that they'll |
8305 | show up if this is in the failing packet in an ICMP error packet, |
8306 | but it's now time to give up if the header length is bogus. */ |
8307 | col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)", |
8308 | tcph->th_hlen, TCPH_MIN_LEN20); |
8309 | if (tree) { |
8310 | tf = proto_tree_add_uint_bits_format_value(tcp_tree, hf_tcp_hdr_len, tvb, (offset + 12) << 3, 4, tcph->th_hlen, |
8311 | ENC_BIG_ENDIAN0x00000000, "%u bytes (%u)", tcph->th_hlen, tcph->th_hlen >> 2); |
8312 | expert_add_info_format(pinfo, tf, &ei_tcp_bogus_header_length, |
8313 | "Bogus TCP header length (%u, must be at least %u)", tcph->th_hlen, TCPH_MIN_LEN20); |
8314 | } |
8315 | return offset+12; |
8316 | } |
8317 | |
8318 | /* Now we certainly have enough information to be willing to send |
8319 | * the header information to the tap. The options can add information |
8320 | * about the SACKs, but the other taps don't really *require* that. |
8321 | * Add a CLEANUP function so that the tap_queue_packet gets called |
8322 | * if any exception is thrown. |
8323 | * |
8324 | * XXX: Could we move this earlier, before the window size and urgent |
8325 | * pointer, for example? Probably, but if so, remember to |
8326 | * CLEANUP_CALL_AND_POP before any return statements, such as the |
8327 | * one above. |
8328 | */ |
8329 | |
8330 | tcp_tap_cleanup_t *cleanup = wmem_new(pinfo->pool, tcp_tap_cleanup_t)((tcp_tap_cleanup_t*)wmem_alloc((pinfo->pool), sizeof(tcp_tap_cleanup_t ))); |
8331 | cleanup->pinfo = pinfo; |
8332 | cleanup->tcph = tcph; |
8333 | CLEANUP_PUSH(tcp_tap_cleanup, cleanup){ struct except_stacknode except_sn; struct except_cleanup except_cl ; except_setup_clean(&except_sn, &except_cl, (tcp_tap_cleanup ), (cleanup)); |
8334 | |
8335 | /* initialize or move forward the conversation completeness */ |
8336 | if(tcpd) { |
8337 | if(conversation_is_new) { /* pure SYN must be sought in new conversations only */ |
8338 | if((tcph->th_flags&(TH_SYN0x0002|TH_ACK0x0010))==TH_SYN0x0002) { |
8339 | conversation_completeness |= TCP_COMPLETENESS_SYNSENT0x01; |
8340 | if(tcph->th_seglen > 0) { /* TCP Fast Open */ |
8341 | conversation_completeness |= TCP_COMPLETENESS_DATA0x08; |
8342 | } |
8343 | } |
8344 | } |
8345 | else { |
8346 | /* Explicitly and immediately move forward the conversation last_frame, |
8347 | * although it would one way or another be changed later |
8348 | * in the conversation helper functions. |
8349 | */ |
8350 | if (!(pinfo->fd->visited)) { |
8351 | if (pinfo->num > conv->last_frame) { |
8352 | conv->last_frame = pinfo->num; |
8353 | } |
8354 | } |
8355 | |
8356 | conversation_completeness = tcpd->conversation_completeness ; |
8357 | } |
8358 | |
8359 | /* SYN-ACK */ |
8360 | if((tcph->th_flags&(TH_SYN0x0002|TH_ACK0x0010))==(TH_SYN0x0002|TH_ACK0x0010)) { |
8361 | conversation_completeness |= TCP_COMPLETENESS_SYNACK0x02; |
8362 | } |
8363 | |
8364 | /* ACKs */ |
8365 | if((tcph->th_flags&(TH_SYN0x0002|TH_ACK0x0010))==(TH_ACK0x0010)) { |
8366 | if(tcph->th_seglen>0) { /* transporting some data */ |
8367 | conversation_completeness |= TCP_COMPLETENESS_DATA0x08; |
8368 | } |
8369 | else { /* pure ACK */ |
8370 | conversation_completeness |= TCP_COMPLETENESS_ACK0x04; |
8371 | } |
8372 | } |
8373 | |
8374 | /* FIN-ACK */ |
8375 | if((tcph->th_flags&(TH_FIN0x0001|TH_ACK0x0010))==(TH_FIN0x0001|TH_ACK0x0010)) { |
8376 | conversation_completeness |= TCP_COMPLETENESS_FIN0x10; |
8377 | } |
8378 | |
8379 | /* RST */ |
8380 | /* XXX: A RST segment should be validated (RFC 9293 3.5.3), |
8381 | * and if not valid should not change the conversation state. |
8382 | */ |
8383 | if(tcph->th_flags&(TH_RST0x0004)) { |
8384 | conversation_completeness |= TCP_COMPLETENESS_RST0x20; |
8385 | } |
8386 | |
8387 | /* Store the completeness at the conversation level, |
8388 | * both as numerical and as Flag First Letters string, to avoid |
8389 | * computing many times the same thing. |
8390 | */ |
8391 | if (tcpd->conversation_completeness) { |
8392 | if (tcpd->conversation_completeness != conversation_completeness) { |
8393 | tcpd->conversation_completeness = conversation_completeness; |
8394 | tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ; |
8395 | } |
8396 | } |
8397 | else { |
8398 | tcpd->conversation_completeness = conversation_completeness; |
8399 | tcpd->conversation_completeness_str = completeness_flags_to_str_first_letter(wmem_file_scope(), tcpd->conversation_completeness) ; |
8400 | } |
8401 | } |
8402 | |
8403 | if (tcp_summary_in_tree) { |
8404 | if(tcph->th_flags&TH_ACK0x0010) { |
8405 | proto_item_append_text(ti, ", Ack: %u", tcph->th_ack); |
8406 | } |
8407 | if (tcph->th_have_seglen) |
8408 | proto_item_append_text(ti, ", Len: %u", tcph->th_seglen); |
8409 | } |
8410 | proto_item_set_len(ti, tcph->th_hlen); |
8411 | if (tcph->th_have_seglen) { |
8412 | if(tcp_relative_seq && tcp_analyze_seq) { |
8413 | if (tcph->th_flags&(TH_SYN0x0002|TH_FIN0x0001)) { |
8414 | tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq + 1, "%u (relative sequence number)", nxtseq + 1); |
8415 | } else { |
8416 | tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "%u (relative sequence number)", nxtseq); |
8417 | } |
8418 | } else { |
8419 | if (tcph->th_flags&(TH_SYN0x0002|TH_FIN0x0001)) { |
8420 | tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq + 1); |
8421 | } else { |
8422 | tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq); |
8423 | } |
8424 | } |
8425 | proto_item_set_generated(tf); |
8426 | } |
8427 | |
8428 | tf = proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack); |
8429 | hide_seqack_abs_item = proto_tree_add_uint(tcp_tree, hf_tcp_ack_abs, tvb, offset + 8, 4, tcph->th_rawack); |
8430 | if (tcph->th_flags & TH_ACK0x0010) { |
8431 | if (tcp_relative_seq && tcp_analyze_seq) { |
8432 | proto_item_append_text(tf, " (relative ack number)"); |
8433 | } else { |
8434 | proto_item_set_hidden(hide_seqack_abs_item); |
8435 | } |
8436 | if ((tcph->th_flags & TH_SYN0x0002) && tcp_analyze_seq) { |
8437 | if ((tcp_relative_seq && tcph->th_ack > 1) || |
8438 | (!tcp_relative_seq && tcpd && (tcph->th_ack - tcpd->rev->base_seq) > 1)) { |
8439 | expert_add_info(pinfo, tf, &ei_tcp_analysis_tfo_ack); |
8440 | } else if (tcpd && tcpd->tfo_syn_data) { |
8441 | expert_add_info(pinfo, tf, &ei_tcp_analysis_tfo_ignored); |
8442 | } |
8443 | } |
8444 | } else { |
8445 | /* Note if the ACK field is non-zero */ |
8446 | if (tvb_get_ntohl(tvb, offset+8) != 0) { |
8447 | expert_add_info(pinfo, tf, &ei_tcp_ack_nonzero); |
8448 | } |
8449 | } |
8450 | |
8451 | if (tree) { |
8452 | // This should be consistent with ip.hdr_len. |
8453 | proto_tree_add_uint_bits_format_value(tcp_tree, hf_tcp_hdr_len, tvb, (offset + 12) << 3, 4, tcph->th_hlen, |
8454 | ENC_BIG_ENDIAN0x00000000, "%u bytes (%u)", tcph->th_hlen, tcph->th_hlen>>2); |
8455 | tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 12, 2, |
8456 | tcph->th_flags, "Flags: 0x%03x (%s)", tcph->th_flags, flags_str); |
8457 | field_tree = proto_item_add_subtree(tf, ett_tcp_flags); |
8458 | proto_tree_add_boolean(field_tree, hf_tcp_flags_res, tvb, offset + 12, 1, tcph->th_flags); |
8459 | if (tcph->th_use_ace) { |
8460 | ace = tcp_get_ace(tcph); |
8461 | proto_tree_add_uint_format(field_tree, hf_tcp_flags_ace, tvb, 12, 2, ace, |
8462 | "...%c %c%c.. .... = ACE: %u", |
8463 | ace & 0x04 ? '1' : '0', |
8464 | ace & 0x02 ? '1' : '0', |
8465 | ace & 0x01 ? '1' : '0', |
8466 | ace); |
8467 | } else { |
8468 | proto_tree_add_boolean(field_tree, hf_tcp_flags_ae, tvb, offset + 12, 1, tcph->th_flags); |
8469 | proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags); |
8470 | proto_tree_add_boolean(field_tree, hf_tcp_flags_ece, tvb, offset + 13, 1, tcph->th_flags); |
8471 | } |
8472 | proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags); |
8473 | proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags); |
8474 | proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags); |
8475 | tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags); |
8476 | tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags); |
8477 | tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags); |
8478 | |
8479 | tf = proto_tree_add_string(field_tree, hf_tcp_flags_str, tvb, offset + 12, 2, flags_str_first_letter); |
8480 | proto_item_set_generated(tf); |
8481 | /* As discussed in bug 5541, it is better to use two separate |
8482 | * fields for the real and calculated window size. |
8483 | */ |
8484 | proto_tree_add_uint(tcp_tree, hf_tcp_window_size_value, tvb, offset + 14, 2, real_window); |
8485 | scaled_pi = proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win); |
8486 | proto_item_set_generated(scaled_pi); |
8487 | |
8488 | if( !(tcph->th_flags&TH_SYN0x0002) && tcpd ) { |
8489 | switch (tcpd->fwd->win_scale) { |
8490 | |
8491 | case -1: |
8492 | /* Unknown */ |
8493 | { |
8494 | gint16 win_scale = tcpd->fwd->win_scale; |
8495 | gboolean override_with_pref = FALSE(0); |
8496 | |
8497 | /* Use preference setting (if set) */ |
8498 | if (tcp_default_window_scaling != WindowScaling_NotKnown) { |
8499 | win_scale = (1 << tcp_default_window_scaling); |
8500 | override_with_pref = TRUE(!(0)); |
8501 | } |
8502 | |
8503 | scaled_pi = proto_tree_add_int_format_value(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2, |
8504 | win_scale, "%d (%s)", |
8505 | win_scale, |
8506 | (override_with_pref) ? "missing - taken from preference" : "unknown"); |
8507 | proto_item_set_generated(scaled_pi); |
8508 | } |
8509 | break; |
8510 | |
8511 | case -2: |
8512 | /* No window scaling used */ |
8513 | 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); |
8514 | proto_item_set_generated(scaled_pi); |
8515 | break; |
8516 | |
8517 | default: |
8518 | /* Scaling from signalled value */ |
8519 | 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); |
8520 | proto_item_set_generated(scaled_pi); |
8521 | } |
8522 | } |
8523 | } |
8524 | |
8525 | if(tcph->th_flags & TH_SYN0x0002) { |
8526 | if(tcph->th_flags & TH_ACK0x0010) { |
8527 | expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_synack, |
8528 | "Connection establish acknowledge (SYN+ACK): server port %u", tcph->th_sport); |
8529 | /* Save the server port to help determine dissector used */ |
8530 | tcpd->server_port = tcph->th_sport; |
8531 | } |
8532 | else { |
8533 | expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_syn, |
8534 | "Connection establish request (SYN): server port %u", tcph->th_dport); |
8535 | /* Save the server port to help determine dissector used */ |
8536 | tcpd->server_port = tcph->th_dport; |
8537 | tcpd->ts_mru_syn = pinfo->abs_ts; |
8538 | } |
8539 | /* Remember where the next segment will start. */ |
8540 | if (tcp_desegment && tcp_reassemble_out_of_order && tcpd && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) { |
8541 | if (tcpd->fwd->maxnextseq == 0) { |
8542 | tcpd->fwd->maxnextseq = tcph->th_seq + 1; |
8543 | } |
8544 | } |
8545 | /* Initialize the is_first_ack */ |
8546 | tcpd->fwd->is_first_ack = TRUE(!(0)); |
8547 | } |
8548 | if(tcph->th_flags & TH_FIN0x0001) { |
8549 | /* XXX - find a way to know the server port and output only that one */ |
8550 | expert_add_info(pinfo, tf_fin, &ei_tcp_connection_fin); |
8551 | |
8552 | /* Track closing initiator. |
8553 | If it was not already closed by the reverse flow, it means we are the first */ |
8554 | if(!tcpd->rev->closing_initiator) { |
8555 | tcpd->fwd->closing_initiator = TRUE(!(0)); |
8556 | expert_add_info(pinfo, tf, &ei_tcp_connection_fin_active); |
8557 | } else { |
8558 | expert_add_info(pinfo, tf, &ei_tcp_connection_fin_passive); |
8559 | } |
8560 | } |
8561 | if(tcph->th_flags & TH_RST0x0004) |
8562 | /* XXX - find a way to know the server port and output only that one */ |
8563 | expert_add_info(pinfo, tf_rst, &ei_tcp_connection_rst); |
8564 | |
8565 | if(tcp_analyze_seq |
8566 | && (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == TH_ACK0x0010 |
8567 | && !nstime_is_zero(&tcpd->ts_mru_syn) |
8568 | && nstime_is_zero(&tcpd->ts_first_rtt)) { |
8569 | /* If all of the following: |
8570 | * - we care (the pref is set) |
8571 | * - this is a pure ACK |
8572 | * - we have a timestamp for the most-recently-transmitted SYN |
8573 | * - we haven't seen a pure ACK yet (no ts_first_rtt stored) |
8574 | * then assume it's the last part of the handshake and store the initial |
8575 | * RTT time |
8576 | */ |
8577 | nstime_delta(&(tcpd->ts_first_rtt), &(pinfo->abs_ts), &(tcpd->ts_mru_syn)); |
8578 | } |
8579 | |
8580 | /* |
8581 | * Remember if we have already seen at least one ACK, |
8582 | * then we can neutralize the Window Scale side-effect at the beginning (issue 14690) |
8583 | */ |
8584 | if(tcp_analyze_seq |
8585 | && (tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010)) == TH_ACK0x0010) { |
8586 | if(tcpd->fwd->is_first_ack) { |
8587 | tcpd->fwd->is_first_ack = FALSE(0); |
8588 | } |
8589 | } |
8590 | |
8591 | /* Supply the sequence number of the first byte and of the first byte |
8592 | after the segment. */ |
8593 | tcpinfo.seq = tcph->th_seq; |
8594 | tcpinfo.nxtseq = nxtseq; |
8595 | tcpinfo.lastackseq = tcph->th_ack; |
8596 | |
8597 | /* Assume we'll pass un-reassembled data to subdissectors. */ |
8598 | tcpinfo.is_reassembled = FALSE(0); |
8599 | |
8600 | /* |
8601 | * Assume, initially, that we can't desegment. |
8602 | */ |
8603 | pinfo->can_desegment = 0; |
8604 | th_sum = tvb_get_ntohs(tvb, offset + 16); |
8605 | if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) { |
8606 | /* The packet isn't part of an un-reassembled fragmented datagram |
8607 | and isn't truncated. This means we have all the data, and thus |
8608 | can checksum it and, unless it's being returned in an error |
8609 | packet, are willing to allow subdissectors to request reassembly |
8610 | on it. */ |
8611 | |
8612 | if (tcp_check_checksum) { |
8613 | /* We haven't turned checksum checking off; checksum it. */ |
8614 | |
8615 | /* Set up the fields of the pseudo-header. */ |
8616 | SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len)do { cksum_vec[0].ptr = ((const guint8 *)pinfo->src.data); cksum_vec[0].len = (pinfo->src.len); } while (0); |
8617 | SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data, pinfo->dst.len)do { cksum_vec[1].ptr = ((const guint8 *)pinfo->dst.data); cksum_vec[1].len = (pinfo->dst.len); } while (0); |
8618 | switch (pinfo->src.type) { |
8619 | |
8620 | case AT_IPv4: |
8621 | phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len)(((((guint32) ( (((guint32) ((6<<16) + reported_len) & (guint32) 0x000000ffU) << 24) | (((guint32) ((6<< 16) + reported_len) & (guint32) 0x0000ff00U) << 8) | (((guint32) ((6<<16) + reported_len) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) ((6<<16) + reported_len) & (guint32) 0xff000000U) >> 24)))))); |
8622 | SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 4)do { cksum_vec[2].ptr = ((const guint8 *)phdr); cksum_vec[2]. len = (4); } while (0); |
8623 | break; |
8624 | |
8625 | case AT_IPv6: |
8626 | phdr[0] = g_htonl(reported_len)(((((guint32) ( (((guint32) (reported_len) & (guint32) 0x000000ffU ) << 24) | (((guint32) (reported_len) & (guint32) 0x0000ff00U ) << 8) | (((guint32) (reported_len) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (reported_len) & (guint32) 0xff000000U ) >> 24)))))); |
8627 | phdr[1] = g_htonl(IP_PROTO_TCP)(((((guint32) ( (((guint32) (6) & (guint32) 0x000000ffU) << 24) | (((guint32) (6) & (guint32) 0x0000ff00U) << 8 ) | (((guint32) (6) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (6) & (guint32) 0xff000000U) >> 24)))) )); |
8628 | SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 8)do { cksum_vec[2].ptr = ((const guint8 *)phdr); cksum_vec[2]. len = (8); } while (0); |
8629 | break; |
8630 | |
8631 | default: |
8632 | /* TCP runs only atop IPv4 and IPv6.... */ |
8633 | DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\"" , "epan/dissectors/packet-tcp.c", 8633)); |
8634 | break; |
8635 | } |
8636 | /* See discussion in packet-udp.c of partial checksums used in |
8637 | * checksum offloading in Linux and Windows (and possibly others.) |
8638 | */ |
8639 | uint16_t partial_cksum; |
8640 | SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, offset, reported_len)do { cksum_vec[3].len = (reported_len); cksum_vec[3].ptr = tvb_get_ptr ((tvb), (offset), cksum_vec[3].len); } while (0); |
8641 | computed_cksum = in_cksum_ret_partial(cksum_vec, 4, &partial_cksum); |
8642 | if (computed_cksum == 0 && th_sum == 0xffff) { |
8643 | item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb, |
8644 | offset + 16, 2, th_sum, |
8645 | "0x%04x [should be 0x0000 (see RFC 1624)]", th_sum); |
8646 | |
8647 | checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum); |
8648 | item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_calculated, tvb, |
8649 | offset + 16, 2, 0x0000); |
8650 | proto_item_set_generated(item); |
8651 | /* XXX - What should this special status be? */ |
8652 | item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_status, tvb, |
8653 | offset + 16, 0, PROTO_CHECKSUM_E_BAD); |
8654 | proto_item_set_generated(item); |
8655 | expert_add_info(pinfo, item, &ei_tcp_checksum_ffff); |
8656 | |
8657 | col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]"); |
8658 | |
8659 | /* Checksum is treated as valid on most systems, so we're willing to desegment it. */ |
8660 | desegment_ok = TRUE(!(0)); |
8661 | } else { |
8662 | proto_item* calc_item; |
8663 | uint16_t shouldbe_cksum = in_cksum_shouldbe(th_sum, computed_cksum); |
8664 | if (computed_cksum != 0 && th_sum == g_htons(partial_cksum)(((((guint16) ( (guint16) ((guint16) (partial_cksum) >> 8) | (guint16) ((guint16) (partial_cksum) << 8))))))) { |
8665 | /* Don't use PROTO_CHECKSUM_IN_CKSUM because we expect the value |
8666 | * to match what we pass in. */ |
8667 | 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)(((((guint16) ( (guint16) ((guint16) (partial_cksum) >> 8) | (guint16) ((guint16) (partial_cksum) << 8)))))), |
8668 | ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_VERIFY0x01); |
8669 | proto_item_append_text(item, " (matches partial checksum, not 0x%04x, likely caused by \"TCP checksum offload\")", shouldbe_cksum); |
8670 | expert_add_info(pinfo, item, &ei_tcp_checksum_partial); |
8671 | computed_cksum = 0; |
8672 | /* XXX Add a new status, e.g. PROTO_CHECKSUM_E_PARTIAL? */ |
8673 | } else { |
8674 | item = proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, computed_cksum, |
8675 | ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_VERIFY0x01|PROTO_CHECKSUM_IN_CKSUM0x04); |
8676 | } |
8677 | checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum); |
8678 | calc_item = proto_tree_add_uint(checksum_tree, hf_tcp_checksum_calculated, tvb, |
8679 | offset + 16, 2, shouldbe_cksum); |
8680 | proto_item_set_generated(calc_item); |
8681 | |
8682 | /* Checksum is valid, so we're willing to desegment it. */ |
8683 | if (computed_cksum == 0) { |
8684 | desegment_ok = TRUE(!(0)); |
8685 | } else { |
8686 | proto_item_append_text(item, "(maybe caused by \"TCP checksum offload\"?)"); |
8687 | |
8688 | /* Checksum is invalid, so we're not willing to desegment it. */ |
8689 | desegment_ok = FALSE(0); |
8690 | pinfo->noreassembly_reason = " [incorrect TCP checksum]"; |
8691 | col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]"); |
8692 | } |
8693 | } |
8694 | } else { |
8695 | proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, 0, |
8696 | ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00); |
8697 | |
8698 | /* We didn't check the checksum, and don't care if it's valid, |
8699 | so we're willing to desegment it. */ |
8700 | desegment_ok = TRUE(!(0)); |
8701 | } |
8702 | } else { |
8703 | /* We don't have all the packet data, so we can't checksum it... */ |
8704 | proto_tree_add_checksum(tcp_tree, tvb, offset+16, hf_tcp_checksum, hf_tcp_checksum_status, &ei_tcp_checksum_bad, pinfo, 0, |
8705 | ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00); |
8706 | |
8707 | /* ...and aren't willing to desegment it. */ |
8708 | desegment_ok = FALSE(0); |
8709 | } |
8710 | |
8711 | if (desegment_ok) { |
8712 | /* We're willing to desegment this. Is desegmentation enabled? */ |
8713 | if (tcp_desegment) { |
8714 | /* Yes - is this segment being returned in an error packet? */ |
8715 | if (!pinfo->flags.in_error_pkt) { |
8716 | /* No - indicate that we will desegment. |
8717 | We do NOT want to desegment segments returned in error |
8718 | packets, as they're not part of a TCP connection. */ |
8719 | pinfo->can_desegment = 2; |
8720 | } |
8721 | } |
8722 | } |
8723 | |
8724 | item = proto_tree_add_item_ret_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, ENC_BIG_ENDIAN0x00000000, &th_urp); |
8725 | |
8726 | if (IS_TH_URG(tcph->th_flags)(tcph->th_flags & 0x0020)) { |
8727 | /* Export the urgent pointer, for the benefit of protocols such as |
8728 | rlogin. */ |
8729 | tcpinfo.urgent_pointer = (guint16)th_urp; |
8730 | tcp_info_append_uint(pinfo, "Urg", th_urp); |
8731 | } else { |
8732 | if (th_urp) { |
8733 | /* Note if the urgent pointer field is non-zero */ |
8734 | expert_add_info(pinfo, item, &ei_tcp_urgent_pointer_non_zero); |
8735 | } |
8736 | } |
8737 | |
8738 | if (tcph->th_have_seglen) |
8739 | tcp_info_append_uint(pinfo, "Len", tcph->th_seglen); |
8740 | |
8741 | /* If there's more than just the fixed-length header (20 bytes), create |
8742 | a protocol tree item for the options. (We already know there's |
8743 | not less than the fixed-length header - we checked that above.) |
8744 | |
8745 | We ensure that we don't throw an exception here, so that we can |
8746 | do some analysis before we dissect the options and possibly |
8747 | throw an exception. (Trying to avoid throwing an exception when |
8748 | dissecting options is not something we should do.) */ |
8749 | optlen = tcph->th_hlen - TCPH_MIN_LEN20; /* length of options, in bytes */ |
8750 | options_item = NULL((void*)0); |
8751 | options_tree = NULL((void*)0); |
8752 | if (optlen != 0) { |
8753 | guint bc = (guint)tvb_captured_length_remaining(tvb, offset + 20); |
8754 | |
8755 | if (tcp_tree != NULL((void*)0)) { |
8756 | options_item = proto_tree_add_item(tcp_tree, hf_tcp_options, tvb, offset + 20, |
8757 | bc < optlen ? bc : optlen, ENC_NA0x00000000); |
8758 | proto_item_set_text(options_item, "Options: (%u bytes)", optlen); |
8759 | options_tree = proto_item_add_subtree(options_item, ett_tcp_options); |
8760 | } |
8761 | } |
8762 | |
8763 | tcph->num_sack_ranges = 0; |
8764 | |
8765 | /* handle conversation timestamps */ |
8766 | if(tcp_calculate_ts) { |
8767 | tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd); |
8768 | } |
8769 | |
8770 | /* Now dissect the options. */ |
8771 | if (optlen) { |
8772 | rvbd_option_data* option_data; |
8773 | |
8774 | tcp_dissect_options(tvb, offset + 20, optlen, |
8775 | pinfo, options_tree, |
8776 | options_item, tcph); |
8777 | |
8778 | /* Do some post evaluation of some Riverbed probe options in the list */ |
8779 | option_data = (rvbd_option_data*)p_get_proto_data(pinfo->pool, pinfo, proto_tcp_option_rvbd_probe, pinfo->curr_layer_num); |
8780 | if (option_data != NULL((void*)0)) |
8781 | { |
8782 | if (option_data->valid) |
8783 | { |
8784 | /* Distinguish S+ from S+* */ |
8785 | col_prepend_fstr(pinfo->cinfo, COL_INFO, "S%s, ", |
8786 | option_data->type == PROBE_TRACE ? "#" : |
8787 | (option_data->probe_flags & RVBD_FLAGS_PROBE_NCFE0x04) ? "+*" : "+"); |
8788 | } |
8789 | } |
8790 | |
8791 | } |
8792 | |
8793 | /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/ |
8794 | if(tcp_analyze_seq) { |
8795 | guint32 use_seq = tcph->th_seq; |
8796 | guint32 use_ack = tcph->th_ack; |
8797 | /* May need to recover absolute values here... */ |
8798 | if (tcp_relative_seq) { |
8799 | use_seq += tcpd->fwd->base_seq; |
8800 | if (tcph->th_flags & TH_ACK0x0010) { |
8801 | use_ack += tcpd->rev->base_seq; |
8802 | } |
8803 | } |
8804 | tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd, use_seq, use_ack); |
8805 | } |
8806 | |
8807 | if(!pinfo->fd->visited) { |
8808 | if((tcph->th_flags & TH_SYN0x0002)==TH_SYN0x0002) { |
8809 | /* Check the validity of the window scale value |
8810 | */ |
8811 | verify_tcp_window_scaling((tcph->th_flags&TH_ACK0x0010)==TH_ACK0x0010,tcpd); |
8812 | } |
8813 | |
8814 | if((tcph->th_flags & (TH_SYN0x0002|TH_ACK0x0010))==(TH_SYN0x0002|TH_ACK0x0010)) { |
8815 | /* If the SYN or the SYN+ACK offered SCPS capabilities, |
8816 | * validate the flow's bidirectional scps capabilities. |
8817 | * The or protects against broken implementations offering |
8818 | * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN |
8819 | */ |
8820 | if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) { |
8821 | verify_scps(pinfo, tf_syn, tcpd); |
8822 | } |
8823 | |
8824 | } |
8825 | } |
8826 | |
8827 | if (tcph->th_mptcp) { |
8828 | |
8829 | if (tcp_analyze_mptcp) { |
8830 | mptcp_add_analysis_subtree(pinfo, tvb, tcp_tree, tcpd, tcpd->mptcp_analysis, tcph ); |
8831 | } |
8832 | } |
8833 | |
8834 | /* Skip over header + options */ |
8835 | offset += tcph->th_hlen; |
8836 | |
8837 | /* Check the packet length to see if there's more data |
8838 | (it could be an ACK-only packet) */ |
8839 | captured_length_remaining = tvb_captured_length_remaining(tvb, offset); |
8840 | |
8841 | if (tcph->th_have_seglen) { |
8842 | if(have_tap_listener(tcp_follow_tap)) { |
8843 | tcp_follow_tap_data_t* follow_data = wmem_new0(pinfo->pool, tcp_follow_tap_data_t)((tcp_follow_tap_data_t*)wmem_alloc0((pinfo->pool), sizeof (tcp_follow_tap_data_t))); |
8844 | |
8845 | follow_data->tvb = tvb_new_subset_remaining(tvb, offset); |
8846 | follow_data->tcph = tcph; |
8847 | follow_data->tcpd = tcpd; |
8848 | |
8849 | tap_queue_packet(tcp_follow_tap, pinfo, follow_data); |
8850 | } |
8851 | } |
8852 | |
8853 | /* Nothing more to add to tcph, go ahead and send to the taps. */ |
8854 | CLEANUP_CALL_AND_POPexcept_pop(); if (1) except_cl.except_func(except_cl.except_context ); }; |
8855 | |
8856 | /* if it is an MPTCP packet */ |
8857 | if(tcpd->mptcp_analysis) { |
8858 | tap_queue_packet(mptcp_tap, pinfo, tcpd); |
8859 | } |
8860 | |
8861 | /* If we're reassembling something whose length isn't known |
8862 | * beforehand, and that runs all the way to the end of |
8863 | * the data stream, a FIN indicates the end of the data |
8864 | * stream and thus the completion of reassembly, so we |
8865 | * need to explicitly check for that here. |
8866 | */ |
8867 | if(tcph->th_have_seglen && tcpd && (tcph->th_flags & TH_FIN0x0001) |
8868 | && pinfo->can_desegment |
8869 | && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001) ) { |
8870 | struct tcp_multisegment_pdu *msp; |
8871 | |
8872 | /* Is this the FIN that ended the data stream or is it a |
8873 | * retransmission of that FIN? |
8874 | */ |
8875 | if (tcpd->fwd->fin == 0 || tcpd->fwd->fin == pinfo->num) { |
8876 | /* Either we haven't seen a FIN for this flow or we |
8877 | * have and it's this frame. Note that this is the FIN |
8878 | * for this flow, terminate reassembly and dissect the |
8879 | * results. */ |
8880 | tcpd->fwd->fin = pinfo->num; |
8881 | msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq); |
8882 | if(msp) { |
8883 | fragment_head *ipfd_head; |
8884 | |
8885 | ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset, |
8886 | pinfo, msp->first_frame, msp, |
8887 | tcph->th_seq - msp->seq, |
8888 | tcph->th_seglen, |
8889 | FALSE(0) ); |
8890 | if(ipfd_head && ipfd_head->reassembled_in == pinfo->num && ipfd_head->reas_in_layer_num == pinfo->curr_layer_num) { |
8891 | tvbuff_t *next_tvb; |
8892 | |
8893 | /* create a new TVB structure for desegmented data |
8894 | * datalen-1 to strip the dummy FIN byte off |
8895 | */ |
8896 | next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data); |
8897 | |
8898 | /* add desegmented data to the data source list */ |
8899 | add_new_data_source(pinfo, next_tvb, "Reassembled TCP"); |
8900 | |
8901 | /* Show details of the reassembly */ |
8902 | print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb); |
8903 | |
8904 | /* call the payload dissector |
8905 | * but make sure we don't offer desegmentation any more |
8906 | */ |
8907 | pinfo->can_desegment = 0; |
8908 | |
8909 | process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq, |
8910 | nxtseq, FALSE(0), tcpd, &tcpinfo); |
8911 | |
8912 | return tvb_captured_length(tvb); |
8913 | } |
8914 | } |
8915 | } else { |
8916 | /* Yes. This is a retransmission of the final FIN (or it's |
8917 | * the final FIN transmitted via a different path). |
8918 | * XXX - we need to flag retransmissions a bit better. |
8919 | */ |
8920 | proto_tree_add_uint(tcp_tree, hf_tcp_fin_retransmission, tvb, 0, 0, tcpd->fwd->fin); |
8921 | } |
8922 | } |
8923 | |
8924 | if (tcp_display_process_info && tcpd && ((tcpd->fwd && tcpd->fwd->process_info && tcpd->fwd->process_info->command) || |
8925 | (tcpd->rev && tcpd->rev->process_info && tcpd->rev->process_info->command))) { |
8926 | field_tree = proto_tree_add_subtree(tcp_tree, tvb, offset, 0, ett_tcp_process_info, &ti, "Process Information"); |
8927 | proto_item_set_generated(ti); |
8928 | if (tcpd->fwd && tcpd->fwd->process_info && tcpd->fwd->process_info->command) { |
8929 | proto_tree_add_uint(field_tree, hf_tcp_proc_dst_uid, tvb, 0, 0, tcpd->fwd->process_info->process_uid); |
8930 | proto_tree_add_uint(field_tree, hf_tcp_proc_dst_pid, tvb, 0, 0, tcpd->fwd->process_info->process_pid); |
8931 | proto_tree_add_string(field_tree, hf_tcp_proc_dst_uname, tvb, 0, 0, tcpd->fwd->process_info->username); |
8932 | proto_tree_add_string(field_tree, hf_tcp_proc_dst_cmd, tvb, 0, 0, tcpd->fwd->process_info->command); |
8933 | } |
8934 | if (tcpd->rev && tcpd->rev->process_info && tcpd->rev->process_info->command) { |
8935 | proto_tree_add_uint(field_tree, hf_tcp_proc_src_uid, tvb, 0, 0, tcpd->rev->process_info->process_uid); |
8936 | proto_tree_add_uint(field_tree, hf_tcp_proc_src_pid, tvb, 0, 0, tcpd->rev->process_info->process_pid); |
8937 | proto_tree_add_string(field_tree, hf_tcp_proc_src_uname, tvb, 0, 0, tcpd->rev->process_info->username); |
8938 | proto_tree_add_string(field_tree, hf_tcp_proc_src_cmd, tvb, 0, 0, tcpd->rev->process_info->command); |
8939 | } |
8940 | } |
8941 | |
8942 | /* |
8943 | * XXX - what, if any, of this should we do if this is included in an |
8944 | * error packet? It might be nice to see the details of the packet |
8945 | * that caused the ICMP error, but it might not be nice to have the |
8946 | * dissector update state based on it. |
8947 | * Also, we probably don't want to run TCP taps on those packets. |
8948 | */ |
8949 | if (captured_length_remaining != 0) { |
8950 | if (tcph->th_flags & TH_RST0x0004) { |
8951 | /* |
8952 | * RFC1122 says: |
8953 | * |
8954 | * 4.2.2.12 RST Segment: RFC-793 Section 3.4 |
8955 | * |
8956 | * A TCP SHOULD allow a received RST segment to include data. |
8957 | * |
8958 | * DISCUSSION |
8959 | * It has been suggested that a RST segment could contain |
8960 | * ASCII text that encoded and explained the cause of the |
8961 | * RST. No standard has yet been established for such |
8962 | * data. |
8963 | * |
8964 | * so for segments with RST we just display the data as text. |
8965 | */ |
8966 | proto_tree_add_item(tcp_tree, hf_tcp_reset_cause, tvb, offset, captured_length_remaining, ENC_NA0x00000000|ENC_ASCII0x00000000); |
8967 | } else { |
8968 | /* When we have a frame with TCP SYN bit set and segmented TCP payload we need |
8969 | * to increment seq and nxtseq to detect the overlapping byte(s). This is to fix Bug 9882. |
8970 | */ |
8971 | if(tcph->th_flags & TH_SYN0x0002) { |
8972 | dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq + 1, nxtseq + 1, |
8973 | tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo); |
8974 | } else { |
8975 | dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq, |
8976 | tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo); |
8977 | } |
8978 | } |
8979 | } |
8980 | return tvb_captured_length(tvb); |
8981 | } |
8982 | |
8983 | static void |
8984 | tcp_init(void) |
8985 | { |
8986 | tcp_stream_count = 0; |
8987 | |
8988 | /* MPTCP init */ |
8989 | mptcp_stream_count = 0; |
8990 | mptcp_tokens = wmem_tree_new(wmem_file_scope()); |
8991 | } |
8992 | |
8993 | void |
8994 | proto_register_tcp(void) |
8995 | { |
8996 | static hf_register_info hf[] = { |
8997 | |
8998 | { &hf_tcp_srcport, |
8999 | { "Source Port", "tcp.srcport", FT_UINT16, BASE_PT_TCP, NULL((void*)0), 0x0, |
9000 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9001 | |
9002 | { &hf_tcp_dstport, |
9003 | { "Destination Port", "tcp.dstport", FT_UINT16, BASE_PT_TCP, NULL((void*)0), 0x0, |
9004 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9005 | |
9006 | { &hf_tcp_port, |
9007 | { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_PT_TCP, NULL((void*)0), 0x0, |
9008 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9009 | |
9010 | { &hf_tcp_stream, |
9011 | { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9012 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9013 | |
9014 | { &hf_tcp_stream_pnum, |
9015 | { "Stream Packet Number", "tcp.stream.pnum", FT_UINT32, BASE_DEC, |
9016 | NULL((void*)0), 0x0, |
9017 | "Relative packet number in this TCP stream", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9018 | |
9019 | { &hf_tcp_completeness, |
9020 | { "Conversation completeness", "tcp.completeness", FT_UINT8, |
9021 | BASE_CUSTOM, CF_FUNC(conversation_completeness_fill)((const void *) (gsize) (conversation_completeness_fill)), 0x0, |
9022 | "The completeness of the conversation capture", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9023 | |
9024 | { &hf_tcp_completeness_syn, |
9025 | { "SYN", "tcp.completeness.syn", FT_BOOLEAN, 8, |
9026 | TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent )))), TCP_COMPLETENESS_SYNSENT0x01, |
9027 | "Conversation has a SYN packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9028 | |
9029 | { &hf_tcp_completeness_syn_ack, |
9030 | { "SYN-ACK", "tcp.completeness.syn-ack", FT_BOOLEAN, 8, |
9031 | TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent )))), TCP_COMPLETENESS_SYNACK0x02, |
9032 | "Conversation has a SYN-ACK packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9033 | |
9034 | { &hf_tcp_completeness_ack, |
9035 | { "ACK", "tcp.completeness.ack", FT_BOOLEAN, 8, |
9036 | TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent )))), TCP_COMPLETENESS_ACK0x04, |
9037 | "Conversation has an ACK packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9038 | |
9039 | { &hf_tcp_completeness_data, |
9040 | { "Data", "tcp.completeness.data", FT_BOOLEAN, 8, |
9041 | TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent )))), TCP_COMPLETENESS_DATA0x08, |
9042 | "Conversation has payload DATA", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9043 | |
9044 | { &hf_tcp_completeness_fin, |
9045 | { "FIN", "tcp.completeness.fin", FT_BOOLEAN, 8, |
9046 | TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent )))), TCP_COMPLETENESS_FIN0x10, |
9047 | "Conversation has a FIN packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9048 | |
9049 | { &hf_tcp_completeness_rst, |
9050 | { "RST", "tcp.completeness.rst", FT_BOOLEAN, 8, |
9051 | TFS(&tfs_present_absent)((0 ? (const struct true_false_string*)0 : ((&tfs_present_absent )))), TCP_COMPLETENESS_RST0x20, |
9052 | "Conversation has a RST packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9053 | |
9054 | { &hf_tcp_completeness_str, |
9055 | { "Completeness Flags", "tcp.completeness.str", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, |
9056 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9057 | |
9058 | { &hf_tcp_seq, |
9059 | { "Sequence Number", "tcp.seq", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9060 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9061 | |
9062 | { &hf_tcp_seq_abs, |
9063 | { "Sequence Number (raw)", "tcp.seq_raw", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9064 | "This shows the raw value of the sequence number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9065 | |
9066 | { &hf_tcp_nxtseq, |
9067 | { "Next Sequence Number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9068 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9069 | |
9070 | { &hf_tcp_ack, |
9071 | { "Acknowledgment Number", "tcp.ack", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9072 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9073 | |
9074 | { &hf_tcp_ack_abs, |
9075 | { "Acknowledgment number (raw)", "tcp.ack_raw", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9076 | "This shows the raw value of the acknowledgment number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, |
9077 | |
9078 | // "Data Offset" in https://tools.ietf.org/html/rfc793#section-3.1 and |
9079 | // "Data offset" in https://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure |
9080 | { &hf_tcp_hdr_len, |
9081 | { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, |
9082 | "Data offset in 32-bit words", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9083 | |
9084 | { &hf_tcp_flags, |
9085 | { "Flags", "tcp.flags", FT_UINT16, BASE_HEX, NULL((void*)0), TH_MASK0x0FFF, |
9086 | "Flags (12 bits)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9087 | |
9088 | { &hf_tcp_flags_res, |
9089 | { "Reserved", "tcp.flags.res", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_RES0x0E00, |
9090 | "Three reserved bits (must be zero)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9091 | |
9092 | { &hf_tcp_flags_ae, |
9093 | { "Accurate ECN", "tcp.flags.ae", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_AE0x0100, |
9094 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9095 | |
9096 | { &hf_tcp_flags_cwr, |
9097 | { "Congestion Window Reduced", "tcp.flags.cwr", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_CWR0x0080, |
9098 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9099 | |
9100 | { &hf_tcp_flags_ece, |
9101 | { "ECN-Echo", "tcp.flags.ece", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_ECE0x0040, |
9102 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9103 | |
9104 | { &hf_tcp_flags_ace, |
9105 | { "ACE", "tcp.flags.ace", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, |
9106 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9107 | |
9108 | { &hf_tcp_flags_urg, |
9109 | { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_URG0x0020, |
9110 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9111 | |
9112 | { &hf_tcp_flags_ack, |
9113 | { "Acknowledgment", "tcp.flags.ack", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_ACK0x0010, |
9114 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9115 | |
9116 | { &hf_tcp_flags_push, |
9117 | { "Push", "tcp.flags.push", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_PUSH0x0008, |
9118 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9119 | |
9120 | { &hf_tcp_flags_reset, |
9121 | { "Reset", "tcp.flags.reset", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_RST0x0004, |
9122 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9123 | |
9124 | { &hf_tcp_flags_syn, |
9125 | { "Syn", "tcp.flags.syn", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_SYN0x0002, |
9126 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9127 | |
9128 | { &hf_tcp_flags_fin, |
9129 | { "Fin", "tcp.flags.fin", FT_BOOLEAN, 12, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), TH_FIN0x0001, |
9130 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9131 | |
9132 | { &hf_tcp_flags_str, |
9133 | { "TCP Flags", "tcp.flags.str", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, |
9134 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9135 | |
9136 | { &hf_tcp_window_size_value, |
9137 | { "Window", "tcp.window_size_value", FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
9138 | "The window size value from the TCP header", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9139 | |
9140 | /* 32 bits so we can present some values adjusted to window scaling */ |
9141 | { &hf_tcp_window_size, |
9142 | { "Calculated window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9143 | "The scaled window size (if scaling has been used)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9144 | |
9145 | { &hf_tcp_window_size_scalefactor, |
9146 | { "Window size scaling factor", "tcp.window_size_scalefactor", FT_INT32, BASE_DEC, NULL((void*)0), 0x0, |
9147 | "The window size scaling factor (-1 when unknown, -2 when no scaling is used)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9148 | |
9149 | { &hf_tcp_checksum, |
9150 | { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, |
9151 | "Details at: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9152 | |
9153 | { &hf_tcp_checksum_status, |
9154 | { "Checksum Status", "tcp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals)((0 ? (const struct _value_string*)0 : ((proto_checksum_vals) ))), 0x0, |
9155 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9156 | |
9157 | { &hf_tcp_checksum_calculated, |
9158 | { "Calculated Checksum", "tcp.checksum_calculated", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, |
9159 | "The expected TCP checksum field as calculated from the TCP segment", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9160 | |
9161 | { &hf_tcp_analysis, |
9162 | { "SEQ/ACK analysis", "tcp.analysis", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, |
9163 | "This frame has some of the TCP analysis shown", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9164 | |
9165 | { &hf_tcp_analysis_flags, |
9166 | { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, |
9167 | "This frame has some of the TCP analysis flags set", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9168 | |
9169 | { &hf_tcp_analysis_duplicate_ack, |
9170 | { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, |
9171 | "This is a duplicate ACK", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9172 | |
9173 | { &hf_tcp_analysis_duplicate_ack_num, |
9174 | { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9175 | "This is duplicate ACK number #", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9176 | |
9177 | { &hf_tcp_analysis_duplicate_ack_frame, |
9178 | { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_DUP_ACK)((gpointer) (glong) (FT_FRAMENUM_DUP_ACK)), 0x0, |
9179 | "This is a duplicate to the ACK in frame #", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9180 | |
9181 | { &hf_tcp_continuation_to, |
9182 | { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, |
9183 | "This is a continuation to the PDU in frame #", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9184 | |
9185 | { &hf_tcp_len, |
9186 | { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9187 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9188 | |
9189 | { &hf_tcp_analysis_acks_frame, |
9190 | { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK)((gpointer) (glong) (FT_FRAMENUM_ACK)), 0x0, |
9191 | "Which previous segment is this an ACK for", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9192 | |
9193 | { &hf_tcp_analysis_bytes_in_flight, |
9194 | { "Bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9195 | "How many bytes are now in flight for this connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9196 | |
9197 | { &hf_tcp_analysis_push_bytes_sent, |
9198 | { "Bytes sent since last PSH flag", "tcp.analysis.push_bytes_sent", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9199 | "How many bytes have been sent since the last PSH flag", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9200 | |
9201 | { &hf_tcp_analysis_ack_rtt, |
9202 | { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0, |
9203 | "How long time it took to ACK the segment (RTT)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9204 | |
9205 | { &hf_tcp_analysis_first_rtt, |
9206 | { "iRTT", "tcp.analysis.initial_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0, |
9207 | "How long it took for the SYN to ACK handshake (iRTT)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9208 | |
9209 | { &hf_tcp_analysis_rto, |
9210 | { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0, |
9211 | "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9212 | |
9213 | { &hf_tcp_analysis_rto_frame, |
9214 | { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, |
9215 | "This is the frame we measure the RTO from", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9216 | |
9217 | { &hf_tcp_urgent_pointer, |
9218 | { "Urgent Pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
9219 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9220 | |
9221 | { &hf_tcp_segment_overlap, |
9222 | { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, |
9223 | "Segment overlaps with other segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9224 | |
9225 | { &hf_tcp_segment_overlap_conflict, |
9226 | { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, |
9227 | "Overlapping segments contained conflicting data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9228 | |
9229 | { &hf_tcp_segment_multiple_tails, |
9230 | { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, |
9231 | "Several tails were found when reassembling the pdu", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9232 | |
9233 | { &hf_tcp_segment_too_long_fragment, |
9234 | { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, |
9235 | "Segment contained data past end of the pdu", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9236 | |
9237 | { &hf_tcp_segment_error, |
9238 | { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, |
9239 | "Reassembling error due to illegal segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9240 | |
9241 | { &hf_tcp_segment_count, |
9242 | { "Segment count", "tcp.segment.count", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9243 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9244 | |
9245 | { &hf_tcp_segment, |
9246 | { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, |
9247 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9248 | |
9249 | { &hf_tcp_segments, |
9250 | { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, |
9251 | "TCP Segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9252 | |
9253 | { &hf_tcp_reassembled_in, |
9254 | { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, |
9255 | "The PDU that doesn't end in this segment is reassembled in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9256 | |
9257 | { &hf_tcp_reassembled_length, |
9258 | { "Reassembled TCP length", "tcp.reassembled.length", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9259 | "The total length of the reassembled payload", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9260 | |
9261 | { &hf_tcp_reassembled_data, |
9262 | { "Reassembled TCP Data", "tcp.reassembled.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, |
9263 | "The reassembled payload", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9264 | |
9265 | { &hf_tcp_option_kind, |
9266 | { "Kind", "tcp.option_kind", FT_UINT8, |
9267 | BASE_DEC|BASE_EXT_STRING0x00000200, &tcp_option_kind_vs_ext, 0x0, "This TCP option's kind", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9268 | |
9269 | { &hf_tcp_option_len, |
9270 | { "Length", "tcp.option_len", FT_UINT8, |
9271 | BASE_DEC, NULL((void*)0), 0x0, "Length of this TCP option in bytes (including kind and length fields)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9272 | |
9273 | { &hf_tcp_options, |
9274 | { "TCP Options", "tcp.options", FT_BYTES, |
9275 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9276 | |
9277 | { &hf_tcp_option_mss_val, |
9278 | { "MSS Value", "tcp.options.mss_val", FT_UINT16, |
9279 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9280 | |
9281 | { &hf_tcp_option_wscale_shift, |
9282 | { "Shift count", "tcp.options.wscale.shift", FT_UINT8, |
9283 | BASE_DEC, NULL((void*)0), 0x0, "Logarithmically encoded power of 2 scale factor", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9284 | |
9285 | { &hf_tcp_option_wscale_multiplier, |
9286 | { "Multiplier", "tcp.options.wscale.multiplier", FT_UINT16, |
9287 | BASE_DEC, NULL((void*)0), 0x0, "Multiply segment window size by this for scaled window size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9288 | |
9289 | { &hf_tcp_option_exp_data, |
9290 | { "Data", "tcp.options.experimental.data", FT_BYTES, |
9291 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9292 | |
9293 | { &hf_tcp_option_exp_exid, |
9294 | { "Experiment Identifier", "tcp.options.experimental.exid", FT_UINT16, |
9295 | BASE_HEX, &tcp_exid_vs, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9296 | |
9297 | { &hf_tcp_option_unknown_payload, |
9298 | { "Payload", "tcp.options.unknown.payload", FT_BYTES, |
9299 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9300 | |
9301 | { &hf_tcp_option_sack_sle, |
9302 | {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32, |
9303 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9304 | |
9305 | { &hf_tcp_option_sack_sre, |
9306 | {"TCP SACK Right Edge", "tcp.options.sack_re", FT_UINT32, |
9307 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9308 | |
9309 | { &hf_tcp_option_sack_range_count, |
9310 | { "TCP SACK Count", "tcp.options.sack.count", FT_UINT8, |
9311 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9312 | |
9313 | { &hf_tcp_option_sack_dsack_le, |
9314 | {"TCP D-SACK Left Edge", "tcp.options.sack.dsack_le", FT_UINT32, |
9315 | BASE_DEC, NULL((void*)0), 0x0, "Duplicate SACK Left Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9316 | |
9317 | { &hf_tcp_option_sack_dsack_re, |
9318 | {"TCP D-SACK Right Edge", "tcp.options.sack.dsack_re", FT_UINT32, |
9319 | BASE_DEC, NULL((void*)0), 0x0, "Duplicate SACK Right Edge", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9320 | |
9321 | { &hf_tcp_option_echo, |
9322 | { "TCP Echo Option", "tcp.options.echo_value", FT_UINT32, |
9323 | BASE_DEC, NULL((void*)0), 0x0, "TCP Sack Echo", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9324 | |
9325 | { &hf_tcp_option_timestamp_tsval, |
9326 | { "Timestamp value", "tcp.options.timestamp.tsval", FT_UINT32, |
9327 | BASE_DEC, NULL((void*)0), 0x0, "Value of sending machine's timestamp clock", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9328 | |
9329 | { &hf_tcp_option_timestamp_tsecr, |
9330 | { "Timestamp echo reply", "tcp.options.timestamp.tsecr", FT_UINT32, |
9331 | BASE_DEC, NULL((void*)0), 0x0, "Echoed timestamp from remote machine", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9332 | |
9333 | { &hf_tcp_option_mptcp_subtype, |
9334 | { "Multipath TCP subtype", "tcp.options.mptcp.subtype", FT_UINT8, |
9335 | BASE_DEC, VALS(mptcp_subtype_vs)((0 ? (const struct _value_string*)0 : ((mptcp_subtype_vs)))), 0xF0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9336 | |
9337 | { &hf_tcp_option_mptcp_version, |
9338 | { "Multipath TCP version", "tcp.options.mptcp.version", FT_UINT8, |
9339 | BASE_DEC, NULL((void*)0), 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9340 | |
9341 | { &hf_tcp_option_mptcp_reserved, |
9342 | { "Reserved", "tcp.options.mptcp.reserved", FT_UINT16, |
9343 | BASE_HEX, NULL((void*)0), 0x0FFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9344 | |
9345 | { &hf_tcp_option_mptcp_flags, |
9346 | { "Multipath TCP flags", "tcp.options.mptcp.flags", FT_UINT8, |
9347 | BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9348 | |
9349 | { &hf_tcp_option_mptcp_backup_flag, |
9350 | { "Backup flag", "tcp.options.mptcp.backup.flag", FT_UINT8, |
9351 | BASE_DEC, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9352 | |
9353 | { &hf_tcp_option_mptcp_checksum_flag, |
9354 | { "Checksum required", "tcp.options.mptcp.checksumreq.flags", FT_UINT8, |
9355 | BASE_DEC, NULL((void*)0), MPTCP_CHECKSUM_MASK0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9356 | |
9357 | { &hf_tcp_option_mptcp_B_flag, |
9358 | { "Extensibility", "tcp.options.mptcp.extensibility.flag", FT_UINT8, |
9359 | BASE_DEC, NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9360 | |
9361 | { &hf_tcp_option_mptcp_C_flag, |
9362 | { "Do not attempt to establish new subflows to this address and port", "tcp.options.mptcp.nomoresubflows.flag", FT_UINT8, |
9363 | BASE_DEC, NULL((void*)0), 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9364 | |
9365 | { &hf_tcp_option_mptcp_H_v0_flag, |
9366 | { "Use HMAC-SHA1", "tcp.options.mptcp.sha1.flag", FT_UINT8, |
9367 | BASE_DEC, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9368 | |
9369 | { &hf_tcp_option_mptcp_H_v1_flag, |
9370 | { "Use HMAC-SHA256", "tcp.options.mptcp.sha256.flag", FT_UINT8, |
9371 | BASE_DEC, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9372 | |
9373 | { &hf_tcp_option_mptcp_F_flag, |
9374 | { "DATA_FIN", "tcp.options.mptcp.datafin.flag", FT_UINT8, |
9375 | BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_DATA_FIN_PRESENT0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9376 | |
9377 | { &hf_tcp_option_mptcp_m_flag, |
9378 | { "Data Sequence Number is 8 octets", "tcp.options.mptcp.dseqn8.flag", FT_UINT8, |
9379 | BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_DSN_8BYTES0x08, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9380 | |
9381 | { &hf_tcp_option_mptcp_M_flag, |
9382 | { "Data Sequence Number, Subflow Sequence Number, Data-level Length, Checksum present", "tcp.options.mptcp.dseqnpresent.flag", FT_UINT8, |
9383 | BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_MAPPING_PRESENT0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9384 | |
9385 | { &hf_tcp_option_mptcp_a_flag, |
9386 | { "Data ACK is 8 octets", "tcp.options.mptcp.dataack8.flag", FT_UINT8, |
9387 | BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_DATA_ACK_8BYTES0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9388 | |
9389 | { &hf_tcp_option_mptcp_A_flag, |
9390 | { "Data ACK is present", "tcp.options.mptcp.dataackpresent.flag", FT_UINT8, |
9391 | BASE_DEC, NULL((void*)0), MPTCP_DSS_FLAG_DATA_ACK_PRESENT0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9392 | |
9393 | { &hf_tcp_option_mptcp_reserved_v0_flag, |
9394 | { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8, |
9395 | BASE_HEX, NULL((void*)0), 0x3E, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9396 | |
9397 | { &hf_tcp_option_mptcp_reserved_v1_flag, |
9398 | { "Reserved", "tcp.options.mptcp.reserved.flag", FT_UINT8, |
9399 | BASE_HEX, NULL((void*)0), 0x1E, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9400 | |
9401 | { &hf_tcp_option_mptcp_U_flag, |
9402 | { "Flag U", "tcp.options.mptcp.flag_U.flag", FT_BOOLEAN, |
9403 | 4, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MPTCP_TCPRST_FLAG_U_PRESENT0x8, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9404 | |
9405 | { &hf_tcp_option_mptcp_V_flag, |
9406 | { "Flag V", "tcp.options.mptcp.flag_V.flag", FT_BOOLEAN, |
9407 | 4, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MPTCP_TCPRST_FLAG_V_PRESENT0x4, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9408 | |
9409 | { &hf_tcp_option_mptcp_W_flag, |
9410 | { "Flag W", "tcp.options.mptcp.flag_W.flag", FT_BOOLEAN, |
9411 | 4, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MPTCP_TCPRST_FLAG_W_PRESENT0x2, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9412 | |
9413 | { &hf_tcp_option_mptcp_T_flag, |
9414 | { "Transient", "tcp.options.mptcp.flag_T.flag", FT_BOOLEAN, |
9415 | 4, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MPTCP_TCPRST_FLAG_T_PRESENT0x1, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9416 | |
9417 | { &hf_tcp_option_mptcp_tcprst_reason, |
9418 | { "TCPRST Reason", "tcp.options.mptcp.rst_reason", FT_UINT8, |
9419 | BASE_HEX, VALS(mp_tcprst_reasons)((0 ? (const struct _value_string*)0 : ((mp_tcprst_reasons))) ), 0x0, "Multipath TCPRST Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9420 | |
9421 | { &hf_tcp_option_mptcp_address_id, |
9422 | { "Address ID", "tcp.options.mptcp.addrid", FT_UINT8, |
9423 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9424 | |
9425 | { &hf_tcp_option_mptcp_sender_key, |
9426 | { "Sender's Key", "tcp.options.mptcp.sendkey", FT_UINT64, |
9427 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9428 | |
9429 | { &hf_tcp_option_mptcp_recv_key, |
9430 | { "Receiver's Key", "tcp.options.mptcp.recvkey", FT_UINT64, |
9431 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9432 | |
9433 | { &hf_tcp_option_mptcp_recv_token, |
9434 | { "Receiver's Token", "tcp.options.mptcp.recvtok", FT_UINT32, |
9435 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9436 | |
9437 | { &hf_tcp_option_mptcp_sender_rand, |
9438 | { "Sender's Random Number", "tcp.options.mptcp.sendrand", FT_UINT32, |
9439 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9440 | |
9441 | { &hf_tcp_option_mptcp_sender_trunc_hmac, |
9442 | { "Sender's Truncated HMAC", "tcp.options.mptcp.sendtrunchmac", FT_UINT64, |
9443 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9444 | |
9445 | { &hf_tcp_option_mptcp_sender_hmac, |
9446 | { "Sender's HMAC", "tcp.options.mptcp.sendhmac", FT_BYTES, |
9447 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9448 | |
9449 | { &hf_tcp_option_mptcp_addaddr_trunc_hmac, |
9450 | { "Truncated HMAC", "tcp.options.mptcp.addaddrtrunchmac", FT_UINT64, |
9451 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9452 | |
9453 | { &hf_tcp_option_mptcp_data_ack_raw, |
9454 | { "Original MPTCP Data ACK", "tcp.options.mptcp.rawdataack", FT_UINT64, |
9455 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9456 | |
9457 | { &hf_tcp_option_mptcp_data_seq_no_raw, |
9458 | { "Data Sequence Number", "tcp.options.mptcp.rawdataseqno", FT_UINT64, |
9459 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9460 | |
9461 | { &hf_tcp_option_mptcp_subflow_seq_no, |
9462 | { "Subflow Sequence Number", "tcp.options.mptcp.subflowseqno", FT_UINT32, |
9463 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9464 | |
9465 | { &hf_tcp_option_mptcp_data_lvl_len, |
9466 | { "Data-level Length", "tcp.options.mptcp.datalvllen", FT_UINT16, |
9467 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9468 | |
9469 | { &hf_tcp_option_mptcp_checksum, |
9470 | { "Checksum", "tcp.options.mptcp.checksum", FT_UINT16, |
9471 | BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9472 | |
9473 | { &hf_tcp_option_mptcp_ipver, |
9474 | { "IP version", "tcp.options.mptcp.ipver", FT_UINT8, |
9475 | BASE_DEC, NULL((void*)0), 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9476 | |
9477 | { &hf_tcp_option_mptcp_echo, |
9478 | { "Echo", "tcp.options.mptcp.echo", FT_UINT8, |
9479 | BASE_DEC, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9480 | |
9481 | { &hf_tcp_option_mptcp_ipv4, |
9482 | { "Advertised IPv4 Address", "tcp.options.mptcp.ipv4", FT_IPv4, |
9483 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9484 | |
9485 | { &hf_tcp_option_mptcp_ipv6, |
9486 | { "Advertised IPv6 Address", "tcp.options.mptcp.ipv6", FT_IPv6, |
9487 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9488 | |
9489 | { &hf_tcp_option_mptcp_port, |
9490 | { "Advertised port", "tcp.options.mptcp.port", FT_UINT16, |
9491 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9492 | |
9493 | { &hf_tcp_option_cc, |
9494 | { "TCP CC Option", "tcp.options.cc_value", FT_UINT32, BASE_DEC, |
9495 | NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9496 | |
9497 | { &hf_tcp_option_md5_digest, |
9498 | { "MD5 digest", "tcp.options.md5.digest", FT_BYTES, BASE_NONE, |
9499 | NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9500 | |
9501 | { &hf_tcp_option_ao_keyid, |
9502 | { "AO KeyID", "tcp.options.ao.keyid", FT_UINT8, BASE_DEC, |
9503 | NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9504 | |
9505 | { &hf_tcp_option_ao_rnextkeyid, |
9506 | { "AO RNextKeyID", "tcp.options.ao.rnextkeyid", FT_UINT8, BASE_DEC, |
9507 | NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9508 | |
9509 | { &hf_tcp_option_ao_mac, |
9510 | { "AO MAC", "tcp.options.ao.mac", FT_BYTES, BASE_NONE, |
9511 | NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9512 | |
9513 | { &hf_tcp_option_qs_rate, |
9514 | { "QS Rate", "tcp.options.qs.rate", FT_UINT8, BASE_DEC|BASE_EXT_STRING0x00000200, |
9515 | &qs_rate_vals_ext, 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9516 | |
9517 | { &hf_tcp_option_qs_ttl_diff, |
9518 | { "QS Rate", "tcp.options.qs.ttl_diff", FT_UINT8, BASE_DEC, |
9519 | NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9520 | |
9521 | { &hf_tcp_option_tarr_rate, |
9522 | { "TARR Rate", "tcp.options.tarr.rate", FT_UINT8, BASE_DEC, |
9523 | NULL((void*)0), TCPOPT_TARR_RATE_MASK0xfe, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9524 | |
9525 | { &hf_tcp_option_tarr_reserved, |
9526 | { "TARR Reserved", "tcp.options.tar.reserved", FT_UINT8, BASE_DEC, |
9527 | NULL((void*)0), TCPOPT_TARR_RESERVED_MASK0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9528 | |
9529 | { &hf_tcp_option_acc_ecn_ee0b, |
9530 | { "Accurate ECN Echo ECT(0) Byte Counter", "tcp.options.acc_ecn.ee0b", |
9531 | FT_UINT24, BASE_DEC, NULL((void*)0), 0x0, |
9532 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9533 | |
9534 | { &hf_tcp_option_acc_ecn_eceb, |
9535 | { "Accurate ECN Echo CE Byte Counter", "tcp.options.acc_ecn.eceb", |
9536 | FT_UINT24, BASE_DEC, NULL((void*)0), 0x0, |
9537 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9538 | |
9539 | { &hf_tcp_option_acc_ecn_ee1b, |
9540 | { "Accurate ECN Echo ECT(1) Byte Counter", "tcp.options.acc_ecn.ee1b", |
9541 | FT_UINT24, BASE_DEC, NULL((void*)0), 0x0, |
9542 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9543 | |
9544 | { &hf_tcp_option_scps_vector, |
9545 | { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector", |
9546 | FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, |
9547 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9548 | |
9549 | { &hf_tcp_option_scps_binding, |
9550 | { "Binding Space (Community) ID", |
9551 | "tcp.options.scps.binding.id", |
9552 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, |
9553 | "TCP SCPS Extended Binding Space (Community) ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9554 | |
9555 | { &hf_tcp_option_scps_binding_len, |
9556 | { "Extended Capability Length", |
9557 | "tcp.options.scps.binding.len", |
9558 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, |
9559 | "TCP SCPS Extended Capability Length in bytes", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9560 | |
9561 | { &hf_tcp_option_snack_offset, |
9562 | { "TCP SNACK Offset", "tcp.options.snack.offset", |
9563 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
9564 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9565 | |
9566 | { &hf_tcp_option_snack_size, |
9567 | { "TCP SNACK Size", "tcp.options.snack.size", |
9568 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
9569 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9570 | |
9571 | { &hf_tcp_option_snack_le, |
9572 | { "TCP SNACK Left Edge", "tcp.options.snack.le", |
9573 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
9574 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9575 | |
9576 | { &hf_tcp_option_snack_re, |
9577 | { "TCP SNACK Right Edge", "tcp.options.snack.re", |
9578 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, |
9579 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9580 | |
9581 | { &hf_tcp_scpsoption_flags_bets, |
9582 | { "Partial Reliability Capable (BETS)", |
9583 | "tcp.options.scpsflags.bets", FT_BOOLEAN, 8, |
9584 | TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9585 | |
9586 | { &hf_tcp_scpsoption_flags_snack1, |
9587 | { "Short Form SNACK Capable (SNACK1)", |
9588 | "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8, |
9589 | TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9590 | |
9591 | { &hf_tcp_scpsoption_flags_snack2, |
9592 | { "Long Form SNACK Capable (SNACK2)", |
9593 | "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8, |
9594 | TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9595 | |
9596 | { &hf_tcp_scpsoption_flags_compress, |
9597 | { "Lossless Header Compression (COMP)", |
9598 | "tcp.options.scpsflags.compress", FT_BOOLEAN, 8, |
9599 | TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), 0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9600 | |
9601 | { &hf_tcp_scpsoption_flags_nlts, |
9602 | { "Network Layer Timestamp (NLTS)", |
9603 | "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8, |
9604 | TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), 0x8, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9605 | |
9606 | { &hf_tcp_scpsoption_flags_reserved, |
9607 | { "Reserved", |
9608 | "tcp.options.scpsflags.reserved", FT_UINT8, BASE_DEC, |
9609 | NULL((void*)0), 0x7, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9610 | |
9611 | { &hf_tcp_scpsoption_connection_id, |
9612 | { "Connection ID", |
9613 | "tcp.options.scps.binding", |
9614 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, |
9615 | "TCP SCPS Connection ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9616 | |
9617 | { &hf_tcp_option_user_to_granularity, |
9618 | { "Granularity", "tcp.options.user_to_granularity", FT_BOOLEAN, |
9619 | 16, TFS(&tcp_option_user_to_granularity)((0 ? (const struct true_false_string*)0 : ((&tcp_option_user_to_granularity )))), 0x8000, "TCP User Timeout Granularity", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9620 | |
9621 | { &hf_tcp_option_user_to_val, |
9622 | { "User Timeout", "tcp.options.user_to_val", FT_UINT16, |
9623 | BASE_DEC, NULL((void*)0), 0x7FFF, "TCP User Timeout Value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9624 | |
9625 | { &hf_tcp_option_rvbd_probe_type1, |
9626 | { "Type", "tcp.options.rvbd.probe.type1", |
9627 | FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9628 | |
9629 | { &hf_tcp_option_rvbd_probe_type2, |
9630 | { "Type", "tcp.options.rvbd.probe.type2", |
9631 | FT_UINT8, BASE_DEC, NULL((void*)0), 0xFE, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9632 | |
9633 | { &hf_tcp_option_rvbd_probe_version1, |
9634 | { "Version", "tcp.options.rvbd.probe.version", |
9635 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x0F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9636 | |
9637 | { &hf_tcp_option_rvbd_probe_version2, |
9638 | { "Version", "tcp.options.rvbd.probe.version_raw", |
9639 | FT_UINT8, BASE_DEC, NULL((void*)0), 0x01, "Version 2 Raw Value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9640 | |
9641 | { &hf_tcp_option_rvbd_probe_prober, |
9642 | { "CSH IP", "tcp.options.rvbd.probe.prober", |
9643 | FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9644 | |
9645 | { &hf_tcp_option_rvbd_probe_proxy, |
9646 | { "SSH IP", "tcp.options.rvbd.probe.proxy.ip", |
9647 | FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9648 | |
9649 | { &hf_tcp_option_rvbd_probe_proxy_port, |
9650 | { "SSH Port", "tcp.options.rvbd.probe.proxy.port", |
9651 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9652 | |
9653 | { &hf_tcp_option_rvbd_probe_appli_ver, |
9654 | { "Application Version", "tcp.options.rvbd.probe.appli_ver", |
9655 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9656 | |
9657 | { &hf_tcp_option_rvbd_probe_client, |
9658 | { "Client IP", "tcp.options.rvbd.probe.client.ip", |
9659 | FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9660 | |
9661 | { &hf_tcp_option_rvbd_probe_storeid, |
9662 | { "CFE Store ID", "tcp.options.rvbd.probe.storeid", |
9663 | FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9664 | |
9665 | { &hf_tcp_option_rvbd_probe_flags, |
9666 | { "Probe Flags", "tcp.options.rvbd.probe.flags", |
9667 | FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9668 | |
9669 | { &hf_tcp_option_rvbd_probe_flag_not_cfe, |
9670 | { "Not CFE", "tcp.options.rvbd.probe.flags.notcfe", |
9671 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), RVBD_FLAGS_PROBE_NCFE0x04, |
9672 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9673 | |
9674 | { &hf_tcp_option_rvbd_probe_flag_last_notify, |
9675 | { "Last Notify", "tcp.options.rvbd.probe.flags.last", |
9676 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), RVBD_FLAGS_PROBE_LAST0x01, |
9677 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9678 | |
9679 | { &hf_tcp_option_rvbd_probe_flag_probe_cache, |
9680 | { "Disable Probe Cache on CSH", "tcp.options.rvbd.probe.flags.probe", |
9681 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), RVBD_FLAGS_PROBE0x10, |
9682 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9683 | |
9684 | { &hf_tcp_option_rvbd_probe_flag_sslcert, |
9685 | { "SSL Enabled", "tcp.options.rvbd.probe.flags.ssl", |
9686 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), RVBD_FLAGS_PROBE_SSLCERT0x02, |
9687 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9688 | |
9689 | { &hf_tcp_option_rvbd_probe_flag_server_connected, |
9690 | { "SSH outer to server established", "tcp.options.rvbd.probe.flags.server", |
9691 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), RVBD_FLAGS_PROBE_SERVER0x01, |
9692 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9693 | |
9694 | { &hf_tcp_option_rvbd_trpy_flags, |
9695 | { "Transparency Options", "tcp.options.rvbd.trpy.flags", |
9696 | FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9697 | |
9698 | { &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe, |
9699 | { "Enable FW traversal feature", "tcp.options.rvbd.trpy.flags.fw_rst_probe", |
9700 | FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), |
9701 | RVBD_FLAGS_TRPY_FW_RST_PROBE0x0400, |
9702 | "Reset state created by probe on the nexthop firewall", |
9703 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9704 | |
9705 | { &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner, |
9706 | { "Enable Inner FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst_inner", |
9707 | FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), |
9708 | RVBD_FLAGS_TRPY_FW_RST_INNER0x0200, |
9709 | "Reset state created by transparent inner on all firewalls" |
9710 | " before passing connection through", |
9711 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9712 | |
9713 | { &hf_tcp_option_rvbd_trpy_flag_fw_rst, |
9714 | { "Enable Transparency FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst", |
9715 | FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), |
9716 | RVBD_FLAGS_TRPY_FW_RST0x0100, |
9717 | "Reset state created by probe on all firewalls before " |
9718 | "establishing transparent inner connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9719 | |
9720 | { &hf_tcp_option_rvbd_trpy_flag_chksum, |
9721 | { "Reserved", "tcp.options.rvbd.trpy.flags.chksum", |
9722 | FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), |
9723 | RVBD_FLAGS_TRPY_CHKSUM0x0004, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9724 | |
9725 | { &hf_tcp_option_rvbd_trpy_flag_oob, |
9726 | { "Out of band connection", "tcp.options.rvbd.trpy.flags.oob", |
9727 | FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), |
9728 | RVBD_FLAGS_TRPY_OOB0x0002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9729 | |
9730 | { &hf_tcp_option_rvbd_trpy_flag_mode, |
9731 | { "Transparency Mode", "tcp.options.rvbd.trpy.flags.mode", |
9732 | FT_BOOLEAN, 16, TFS(&trpy_mode_str)((0 ? (const struct true_false_string*)0 : ((&trpy_mode_str )))), |
9733 | RVBD_FLAGS_TRPY_MODE0x0001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9734 | |
9735 | { &hf_tcp_option_rvbd_trpy_src, |
9736 | { "Src SH IP Addr", "tcp.options.rvbd.trpy.src.ip", |
9737 | FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9738 | |
9739 | { &hf_tcp_option_rvbd_trpy_dst, |
9740 | { "Dst SH IP Addr", "tcp.options.rvbd.trpy.dst.ip", |
9741 | FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9742 | |
9743 | { &hf_tcp_option_rvbd_trpy_src_port, |
9744 | { "Src SH Inner Port", "tcp.options.rvbd.trpy.src.port", |
9745 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9746 | |
9747 | { &hf_tcp_option_rvbd_trpy_dst_port, |
9748 | { "Dst SH Inner Port", "tcp.options.rvbd.trpy.dst.port", |
9749 | FT_UINT16, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9750 | |
9751 | { &hf_tcp_option_rvbd_trpy_client_port, |
9752 | { "Out of band connection Client Port", "tcp.options.rvbd.trpy.client.port", |
9753 | FT_UINT16, BASE_DEC, NULL((void*)0) , 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9754 | |
9755 | { &hf_tcp_option_fast_open_cookie_request, |
9756 | { "Fast Open Cookie Request", "tcp.options.tfo.request", FT_NONE, |
9757 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9758 | |
9759 | { &hf_tcp_option_fast_open_cookie, |
9760 | { "Fast Open Cookie", "tcp.options.tfo.cookie", FT_BYTES, |
9761 | BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9762 | |
9763 | { &hf_tcp_pdu_time, |
9764 | { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0, |
9765 | "How long time has passed until the last frame of this PDU", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9766 | |
9767 | { &hf_tcp_pdu_size, |
9768 | { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9769 | "The size of this PDU", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9770 | |
9771 | { &hf_tcp_pdu_last_frame, |
9772 | { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, |
9773 | "This is the last frame of the PDU starting in this segment", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9774 | |
9775 | { &hf_tcp_ts_relative, |
9776 | { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0, |
9777 | "Time relative to first frame in this TCP stream", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9778 | |
9779 | { &hf_tcp_ts_delta, |
9780 | { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0, |
9781 | "Time delta from previous frame in this TCP stream", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9782 | |
9783 | { &hf_tcp_proc_src_uid, |
9784 | { "Source process user ID", "tcp.proc.srcuid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9785 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9786 | |
9787 | { &hf_tcp_proc_src_pid, |
9788 | { "Source process ID", "tcp.proc.srcpid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9789 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9790 | |
9791 | { &hf_tcp_proc_src_uname, |
9792 | { "Source process user name", "tcp.proc.srcuname", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, |
9793 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9794 | |
9795 | { &hf_tcp_proc_src_cmd, |
9796 | { "Source process name", "tcp.proc.srccmd", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, |
9797 | "Source process command name", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9798 | |
9799 | { &hf_tcp_proc_dst_uid, |
9800 | { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9801 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9802 | |
9803 | { &hf_tcp_proc_dst_pid, |
9804 | { "Destination process ID", "tcp.proc.dstpid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9805 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9806 | |
9807 | { &hf_tcp_proc_dst_uname, |
9808 | { "Destination process user name", "tcp.proc.dstuname", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, |
9809 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9810 | |
9811 | { &hf_tcp_proc_dst_cmd, |
9812 | { "Destination process name", "tcp.proc.dstcmd", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, |
9813 | "Destination process command name", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9814 | |
9815 | { &hf_tcp_segment_data, |
9816 | { "TCP segment data", "tcp.segment_data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, |
9817 | "A data segment used in reassembly of an upper-layer protocol (ULP)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9818 | |
9819 | { &hf_tcp_payload, |
9820 | { "TCP payload", "tcp.payload", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, |
9821 | "The TCP payload of this packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
9822 | |
9823 | { &hf_tcp_option_scps_binding_data, |
9824 | { "Binding Space Data", "tcp.options.scps.binding.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, |
9825 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9826 | |
9827 | { &hf_tcp_option_rvbd_probe_reserved, |
9828 | { "Reserved", "tcp.options.rvbd.probe.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, |
9829 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9830 | |
9831 | { &hf_tcp_fin_retransmission, |
9832 | { "Retransmission of FIN from frame", "tcp.fin_retransmission", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0, |
9833 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9834 | |
9835 | { &hf_tcp_reset_cause, |
9836 | { "Reset cause", "tcp.reset_cause", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, |
9837 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9838 | |
9839 | { &hf_tcp_syncookie_time, |
9840 | { "SYN Cookie Time", "tcp.syncookie.time", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, |
9841 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9842 | |
9843 | { &hf_tcp_syncookie_mss, |
9844 | { "SYN Cookie Maximum Segment Size", "tcp.syncookie.mss", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, |
9845 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9846 | |
9847 | { &hf_tcp_syncookie_hash, |
9848 | { "SYN Cookie hash", "tcp.syncookie.hash", FT_UINT24, BASE_HEX, NULL((void*)0), 0x0, |
9849 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9850 | |
9851 | { &hf_tcp_syncookie_option_timestamp, |
9852 | { "SYN Cookie Timestamp", "tcp.options.timestamp.tsval.syncookie.timestamp", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
9853 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9854 | |
9855 | { &hf_tcp_syncookie_option_ecn, |
9856 | { "SYN Cookie ECN", "tcp.options.timestamp.tsval.syncookie.ecn", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, |
9857 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9858 | |
9859 | { &hf_tcp_syncookie_option_sack, |
9860 | { "SYN Cookie SACK", "tcp.options.timestamp.tsval.syncookie.sack", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0, |
9861 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9862 | |
9863 | { &hf_tcp_syncookie_option_wscale, |
9864 | { "SYN Cookie WScale", "tcp.options.timestamp.tsval.syncookie.wscale", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, |
9865 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
9866 | }; |
9867 | |
9868 | static gint *ett[] = { |
9869 | &ett_tcp, |
9870 | &ett_tcp_completeness, |
9871 | &ett_tcp_flags, |
9872 | &ett_tcp_options, |
9873 | &ett_tcp_option_timestamp, |
9874 | &ett_tcp_option_mptcp, |
9875 | &ett_tcp_option_wscale, |
9876 | &ett_tcp_option_sack, |
9877 | &ett_tcp_option_snack, |
9878 | &ett_tcp_option_scps, |
9879 | &ett_tcp_scpsoption_flags, |
9880 | &ett_tcp_option_scps_extended, |
9881 | &ett_tcp_option_user_to, |
9882 | &ett_tcp_option_exp, |
9883 | &ett_tcp_option_acc_ecn, |
9884 | &ett_tcp_option_sack_perm, |
9885 | &ett_tcp_option_mss, |
9886 | &ett_tcp_opt_rvbd_probe, |
9887 | &ett_tcp_opt_rvbd_probe_flags, |
9888 | &ett_tcp_opt_rvbd_trpy, |
9889 | &ett_tcp_opt_rvbd_trpy_flags, |
9890 | &ett_tcp_opt_echo, |
9891 | &ett_tcp_opt_cc, |
9892 | &ett_tcp_opt_md5, |
9893 | &ett_tcp_opt_ao, |
9894 | &ett_tcp_opt_qs, |
9895 | &ett_tcp_analysis_faults, |
9896 | &ett_tcp_analysis, |
9897 | &ett_tcp_timestamps, |
9898 | &ett_tcp_segments, |
9899 | &ett_tcp_segment, |
9900 | &ett_tcp_checksum, |
9901 | &ett_tcp_process_info, |
9902 | &ett_tcp_unknown_opt, |
9903 | &ett_tcp_opt_recbound, |
9904 | &ett_tcp_opt_scpscor, |
9905 | &ett_tcp_option_other, |
9906 | &ett_tcp_syncookie, |
9907 | &ett_tcp_syncookie_option |
9908 | }; |
9909 | |
9910 | static gint *mptcp_ett[] = { |
9911 | &ett_mptcp_analysis, |
9912 | &ett_mptcp_analysis_subflows |
9913 | }; |
9914 | |
9915 | static const enum_val_t window_scaling_vals[] = { |
9916 | {"not-known", "Not known", WindowScaling_NotKnown}, |
9917 | {"0", "0 (no scaling)", WindowScaling_0}, |
9918 | {"1", "1 (multiply by 2)", WindowScaling_1}, |
9919 | {"2", "2 (multiply by 4)", WindowScaling_2}, |
9920 | {"3", "3 (multiply by 8)", WindowScaling_3}, |
9921 | {"4", "4 (multiply by 16)", WindowScaling_4}, |
9922 | {"5", "5 (multiply by 32)", WindowScaling_5}, |
9923 | {"6", "6 (multiply by 64)", WindowScaling_6}, |
9924 | {"7", "7 (multiply by 128)", WindowScaling_7}, |
9925 | {"8", "8 (multiply by 256)", WindowScaling_8}, |
9926 | {"9", "9 (multiply by 512)", WindowScaling_9}, |
9927 | {"10", "10 (multiply by 1024)", WindowScaling_10}, |
9928 | {"11", "11 (multiply by 2048)", WindowScaling_11}, |
9929 | {"12", "12 (multiply by 4096)", WindowScaling_12}, |
9930 | {"13", "13 (multiply by 8192)", WindowScaling_13}, |
9931 | {"14", "14 (multiply by 16384)", WindowScaling_14}, |
9932 | {NULL((void*)0), NULL((void*)0), -1} |
9933 | }; |
9934 | |
9935 | static const enum_val_t override_analysis_vals[] = { |
9936 | {"0", "0 (none)", OverrideAnalysis_0}, |
9937 | {"1", "1 (Out-of-Order)", OverrideAnalysis_1}, |
9938 | {"2", "2 (Retransmission)", OverrideAnalysis_2}, |
9939 | {"3", "3 (Fast Retransmission)", OverrideAnalysis_3}, |
9940 | {"4", "4 (Spurious Retransmission)",OverrideAnalysis_4}, |
9941 | {NULL((void*)0), NULL((void*)0), -1} |
9942 | }; |
9943 | |
9944 | static ei_register_info ei[] = { |
9945 | { &ei_tcp_opt_len_invalid, { "tcp.option.len.invalid", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "Invalid length for option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9946 | { &ei_tcp_analysis_retransmission, { "tcp.analysis.retransmission", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame is a (suspected) retransmission", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9947 | { &ei_tcp_analysis_fast_retransmission, { "tcp.analysis.fast_retransmission", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame is a (suspected) fast retransmission", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9948 | { &ei_tcp_analysis_spurious_retransmission, { "tcp.analysis.spurious_retransmission", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame is a (suspected) spurious retransmission", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9949 | { &ei_tcp_analysis_out_of_order, { "tcp.analysis.out_of_order", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "This frame is a (suspected) out-of-order segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9950 | { &ei_tcp_analysis_reused_ports, { "tcp.analysis.reused_ports", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "A new tcp session is started with the same ports as an earlier session in this trace", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9951 | { &ei_tcp_analysis_lost_packet, { "tcp.analysis.lost_segment", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "Previous segment(s) not captured (common at capture start)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9952 | { &ei_tcp_analysis_ack_lost_packet, { "tcp.analysis.ack_lost_segment", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "ACKed segment that wasn't captured (common at capture start)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9953 | { &ei_tcp_analysis_window_update, { "tcp.analysis.window_update", PI_SEQUENCE0x02000000, PI_CHAT0x00200000, "TCP window update", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9954 | { &ei_tcp_analysis_window_full, { "tcp.analysis.window_full", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "TCP window specified by the receiver is now completely full", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9955 | { &ei_tcp_analysis_keep_alive, { "tcp.analysis.keep_alive", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP keep-alive segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9956 | { &ei_tcp_analysis_keep_alive_ack, { "tcp.analysis.keep_alive_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "ACK to a TCP keep-alive segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9957 | { &ei_tcp_analysis_duplicate_ack, { "tcp.analysis.duplicate_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "Duplicate ACK", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9958 | { &ei_tcp_analysis_zero_window_probe, { "tcp.analysis.zero_window_probe", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP Zero Window Probe", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9959 | { &ei_tcp_analysis_zero_window, { "tcp.analysis.zero_window", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "TCP Zero Window segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9960 | { &ei_tcp_analysis_zero_window_probe_ack, { "tcp.analysis.zero_window_probe_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "ACK to a TCP Zero Window Probe", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9961 | { &ei_tcp_analysis_tfo_syn, { "tcp.analysis.tfo_syn", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP SYN with TFO Cookie", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9962 | { &ei_tcp_analysis_tfo_ack, { "tcp.analysis.tfo_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP SYN-ACK accepting TFO data", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9963 | { &ei_tcp_analysis_tfo_ignored, { "tcp.analysis.tfo_ignored", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "TCP SYN-ACK ignoring TFO data", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9964 | { &ei_tcp_analysis_partial_ack, { "tcp.analysis.partial_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "Partial Acknowledgement of a segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9965 | { &ei_tcp_connection_fin_active, { "tcp.connection.fin_active", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame initiates the connection closing", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9966 | { &ei_tcp_connection_fin_passive, { "tcp.connection.fin_passive", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "This frame undergoes the connection closing", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9967 | { &ei_tcp_scps_capable, { "tcp.analysis.zero_window_probe_ack", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9968 | { &ei_tcp_option_sack_dsack, { "tcp.options.sack.dsack", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "D-SACK Sequence", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9969 | { &ei_tcp_option_snack_sequence, { "tcp.options.snack.sequence", PI_SEQUENCE0x02000000, PI_NOTE0x00400000, "SNACK Sequence", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9970 | { &ei_tcp_option_wscale_shift_invalid, { "tcp.options.wscale.shift.invalid", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Window scale shift exceeds 14", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9971 | { &ei_tcp_option_mss_absent, { "tcp.options.mss.absent", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "The SYN packet does not contain a MSS option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9972 | { &ei_tcp_option_mss_present, { "tcp.options.mss.present", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "The non-SYN packet does contain a MSS option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9973 | { &ei_tcp_option_sack_perm_absent, { "tcp.options.sack_perm.absent", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "The SYN packet does not contain a SACK PERM option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9974 | { &ei_tcp_option_sack_perm_present, { "tcp.options.sack_perm.present", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "The non-SYN packet does contain a SACK PERM option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9975 | { &ei_tcp_short_segment, { "tcp.short_segment", PI_MALFORMED0x07000000, PI_WARN0x00600000, "Short segment", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9976 | { &ei_tcp_ack_nonzero, { "tcp.ack.nonzero", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "The acknowledgment number field is nonzero while the ACK flag is not set", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9977 | { &ei_tcp_connection_synack, { "tcp.connection.synack", PI_SEQUENCE0x02000000, PI_CHAT0x00200000, "Connection establish acknowledge (SYN+ACK)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9978 | { &ei_tcp_connection_syn, { "tcp.connection.syn", PI_SEQUENCE0x02000000, PI_CHAT0x00200000, "Connection establish request (SYN)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9979 | { &ei_tcp_connection_fin, { "tcp.connection.fin", PI_SEQUENCE0x02000000, PI_CHAT0x00200000, "Connection finish (FIN)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9980 | /* According to RFCs, RST is an indication of an error. Some applications use it |
9981 | * to terminate a connection as well, which is a misbehavior (see e.g. rfc3360) |
9982 | */ |
9983 | { &ei_tcp_connection_rst, { "tcp.connection.rst", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "Connection reset (RST)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9984 | { &ei_tcp_checksum_ffff, { "tcp.checksum.ffff", PI_CHECKSUM0x01000000, PI_WARN0x00600000, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9985 | { &ei_tcp_checksum_partial, { "tcp.checksum.partial", PI_CHECKSUM0x01000000, PI_NOTE0x00400000, "Partial (pseudo header) checksum (likely caused by \"TCP checksum offload\")", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9986 | { &ei_tcp_checksum_bad, { "tcp.checksum_bad.expert", PI_CHECKSUM0x01000000, PI_ERROR0x00800000, "Bad checksum", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9987 | { &ei_tcp_urgent_pointer_non_zero, { "tcp.urgent_pointer.non_zero", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "The urgent pointer field is nonzero while the URG flag is not set", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9988 | { &ei_tcp_suboption_malformed, { "tcp.suboption_malformed", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "suboption would go past end of option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9989 | { &ei_tcp_nop, { "tcp.nop", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "4 NOP in a row - a router may have removed some options", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9990 | { &ei_tcp_non_zero_bytes_after_eol, { "tcp.non_zero_bytes_after_eol", PI_PROTOCOL0x09000000, PI_ERROR0x00800000, "Non zero bytes in option space after EOL option", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9991 | { &ei_tcp_bogus_header_length, { "tcp.bogus_header_length", PI_PROTOCOL0x09000000, PI_ERROR0x00800000, "Bogus TCP Header length", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9992 | }; |
9993 | |
9994 | static ei_register_info mptcp_ei[] = { |
9995 | #if 0 |
9996 | { &ei_mptcp_analysis_unexpected_idsn, { "mptcp.connection.unexpected_idsn", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "Unexpected initial sequence number", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9997 | #endif |
9998 | { &ei_mptcp_analysis_echoed_key_mismatch, { "mptcp.connection.echoed_key_mismatch", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "The echoed key in the ACK of the MPTCP handshake does not match the key of the SYN/ACK", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
9999 | { &ei_mptcp_analysis_missing_algorithm, { "mptcp.connection.missing_algorithm", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "No crypto algorithm specified", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
10000 | { &ei_mptcp_analysis_unsupported_algorithm, { "mptcp.connection.unsupported_algorithm", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Unsupported algorithm", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
10001 | { &ei_mptcp_infinite_mapping, { "mptcp.dss.infinite_mapping", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Fallback to infinite mapping", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
10002 | { &ei_mptcp_mapping_missing, { "mptcp.dss.missing_mapping", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "No mapping available", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
10003 | #if 0 |
10004 | { &ei_mptcp_stream_incomplete, { "mptcp.incomplete", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Everything was not captured", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
10005 | { &ei_mptcp_analysis_dsn_out_of_order, { "mptcp.analysis.dsn.out_of_order", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Out of order dsn", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, |
10006 | #endif |
10007 | }; |
10008 | |
10009 | static hf_register_info mptcp_hf[] = { |
10010 | { &hf_mptcp_ack, |
10011 | { "Multipath TCP Data ACK", "mptcp.ack", FT_UINT64, |
10012 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
10013 | |
10014 | { &hf_mptcp_dsn, |
10015 | { "Data Sequence Number", "mptcp.dsn", FT_UINT64, BASE_DEC, NULL((void*)0), 0x0, |
10016 | "Data Sequence Number mapped to this TCP sequence number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
10017 | |
10018 | { &hf_mptcp_rawdsn64, |
10019 | { "Raw Data Sequence Number", "mptcp.rawdsn64", FT_UINT64, BASE_DEC, NULL((void*)0), 0x0, |
10020 | "Data Sequence Number mapped to this TCP sequence number", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
10021 | |
10022 | { &hf_mptcp_dss_dsn, |
10023 | { "DSS Data Sequence Number", "mptcp.dss.dsn", FT_UINT64, |
10024 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
10025 | |
10026 | { &hf_mptcp_expected_idsn, |
10027 | { "Subflow expected IDSN", "mptcp.expected_idsn", FT_UINT64, |
10028 | BASE_DEC|BASE_UNIT_STRING0x00001000, &units_64bit_version, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
10029 | |
10030 | { &hf_mptcp_analysis, |
10031 | { "MPTCP analysis", "mptcp.analysis", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, |
10032 | "This frame has some of the MPTCP analysis shown", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
10033 | |
10034 | { &hf_mptcp_related_mapping, |
10035 | { "Related mapping", "mptcp.related_mapping", FT_FRAMENUM , BASE_NONE, NULL((void*)0), 0x0, |
10036 | "Packet in which current packet DSS mapping was sent", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
10037 | |
10038 | { &hf_mptcp_reinjection_of, |
10039 | { "Reinjection of", "mptcp.reinjection_of", FT_FRAMENUM , BASE_NONE, NULL((void*)0), 0x0, |
10040 | "This is a retransmission of data sent on another subflow", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
10041 | |
10042 | { &hf_mptcp_reinjected_in, |
10043 | { "Data reinjected in", "mptcp.reinjected_in", FT_FRAMENUM , BASE_NONE, NULL((void*)0), 0x0, |
10044 | "This was retransmitted on another subflow", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
10045 | |
10046 | { &hf_mptcp_analysis_subflows, |
10047 | { "TCP subflow stream id(s)", "mptcp.analysis.subflows", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, |
10048 | "List all TCP connections mapped to this MPTCP connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
10049 | |
10050 | { &hf_mptcp_stream, |
10051 | { "Stream index", "mptcp.stream", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, |
10052 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, |
10053 | |
10054 | { &hf_mptcp_number_of_removed_addresses, |
10055 | { "Number of removed addresses", "mptcp.rm_addr.count", FT_UINT8, |
10056 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
10057 | |
10058 | { &hf_mptcp_expected_token, |
10059 | { "Subflow token generated from key", "mptcp.expected_token", FT_UINT32, |
10060 | BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, |
10061 | |
10062 | { &hf_mptcp_analysis_master, |
10063 | { "Master flow", "mptcp.master", FT_BOOLEAN, BASE_NONE, |
10064 | NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}} |
10065 | |
10066 | }; |
10067 | |
10068 | static build_valid_func tcp_da_src_values[1] = {tcp_src_value}; |
10069 | static build_valid_func tcp_da_dst_values[1] = {tcp_dst_value}; |
10070 | static build_valid_func tcp_da_both_values[2] = {tcp_src_value, tcp_dst_value}; |
10071 | 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}}; |
10072 | static decode_as_t tcp_da = {"tcp", "tcp.port", 3, 2, tcp_da_values, "TCP", "port(s) as", |
10073 | decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL((void*)0)}; |
10074 | |
10075 | module_t *tcp_module; |
10076 | module_t *mptcp_module; |
10077 | expert_module_t* expert_tcp; |
10078 | expert_module_t* expert_mptcp; |
10079 | |
10080 | proto_tcp = proto_register_protocol("Transmission Control Protocol", "TCP", "tcp"); |
10081 | tcp_handle = register_dissector("tcp", dissect_tcp, proto_tcp); |
10082 | tcp_cap_handle = register_capture_dissector("tcp", capture_tcp, proto_tcp); |
10083 | proto_register_field_array(proto_tcp, hf, array_length(hf)(sizeof hf / sizeof hf[0])); |
10084 | proto_register_subtree_array(ett, array_length(ett)(sizeof ett / sizeof ett[0])); |
10085 | expert_tcp = expert_register_protocol(proto_tcp); |
10086 | expert_register_field_array(expert_tcp, ei, array_length(ei)(sizeof ei / sizeof ei[0])); |
10087 | |
10088 | /* subdissector code */ |
10089 | subdissector_table = register_dissector_table("tcp.port", |
10090 | "TCP port", proto_tcp, FT_UINT16, BASE_DEC); |
10091 | heur_subdissector_list = register_heur_dissector_list_with_description("tcp", "TCP heuristic", proto_tcp); |
10092 | tcp_option_table = register_dissector_table("tcp.option", |
10093 | "TCP Options", proto_tcp, FT_UINT8, BASE_DEC); |
10094 | |
10095 | /* Register TCP options as their own protocols so we can get the name of the option */ |
10096 | 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); |
10097 | 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); |
10098 | proto_tcp_option_timestamp = proto_register_protocol_in_name_only("TCP Option - Timestamps", "Timestamps", "tcp.options.timestamp", proto_tcp, FT_BYTES); |
10099 | 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); |
10100 | proto_tcp_option_wscale = proto_register_protocol_in_name_only("TCP Option - Window scale", "Window scale", "tcp.options.wscale", proto_tcp, FT_BYTES); |
10101 | 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); |
10102 | proto_tcp_option_sack = proto_register_protocol_in_name_only("TCP Option - SACK", "SACK", "tcp.options.sack", proto_tcp, FT_BYTES); |
10103 | proto_tcp_option_echo = proto_register_protocol_in_name_only("TCP Option - Echo", "Echo", "tcp.options.echo", proto_tcp, FT_BYTES); |
10104 | proto_tcp_option_echoreply = proto_register_protocol_in_name_only("TCP Option - Echo reply", "Echo reply", "tcp.options.echoreply", proto_tcp, FT_BYTES); |
10105 | proto_tcp_option_cc = proto_register_protocol_in_name_only("TCP Option - CC", "CC", "tcp.options.cc", proto_tcp, FT_BYTES); |
10106 | proto_tcp_option_cc_new = proto_register_protocol_in_name_only("TCP Option - CC.NEW", "CC.NEW", "tcp.options.ccnew", proto_tcp, FT_BYTES); |
10107 | proto_tcp_option_cc_echo = proto_register_protocol_in_name_only("TCP Option - CC.ECHO", "CC.ECHO", "tcp.options.ccecho", proto_tcp, FT_BYTES); |
10108 | proto_tcp_option_ao = proto_register_protocol_in_name_only("TCP Option - TCP AO", "TCP AO", "tcp.options.ao", proto_tcp, FT_BYTES); |
10109 | 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); |
10110 | proto_tcp_option_scps = proto_register_protocol_in_name_only("TCP Option - SCPS capabilities", "SCPS capabilities", "tcp.options.scps", proto_tcp, FT_BYTES); |
10111 | 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); |
10112 | 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); |
10113 | 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); |
10114 | proto_tcp_option_qs = proto_register_protocol_in_name_only("TCP Option - Quick-Start", "Quick-Start", "tcp.options.qs", proto_tcp, FT_BYTES); |
10115 | 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); |
10116 | 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); |
10117 | 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); |
10118 | 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); |
10119 | 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); |
10120 | proto_tcp_option_exp = proto_register_protocol_in_name_only("TCP Option - Experimental", "Experimental", "tcp.options.experimental", proto_tcp, FT_BYTES); |
10121 | proto_tcp_option_unknown = proto_register_protocol_in_name_only("TCP Option - Unknown", "Unknown", "tcp.options.unknown", proto_tcp, FT_BYTES); |
10122 | |
10123 | register_capture_dissector_table("tcp.port", "TCP"); |
10124 | |
10125 | /* Register configuration preferences */ |
10126 | tcp_module = prefs_register_protocol(proto_tcp, NULL((void*)0)); |
10127 | prefs_register_bool_preference(tcp_module, "summary_in_tree", |
10128 | "Show TCP summary in protocol tree", |
10129 | "Whether the TCP summary line should be shown in the protocol tree", |
10130 | &tcp_summary_in_tree); |
10131 | prefs_register_bool_preference(tcp_module, "check_checksum", |
10132 | "Validate the TCP checksum if possible", |
10133 | "Whether to validate the TCP checksum or not. " |
10134 | "(Invalid checksums will cause reassembly, if enabled, to fail.)", |
10135 | &tcp_check_checksum); |
10136 | prefs_register_bool_preference(tcp_module, "desegment_tcp_streams", |
10137 | "Allow subdissector to reassemble TCP streams", |
10138 | "Whether subdissector can request TCP streams to be reassembled", |
10139 | &tcp_desegment); |
10140 | prefs_register_bool_preference(tcp_module, "reassemble_out_of_order", |
10141 | "Reassemble out-of-order segments", |
10142 | "Whether out-of-order segments should be buffered and reordered before passing it to a subdissector. " |
10143 | "To use this option you must also enable \"Allow subdissector to reassemble TCP streams\".", |
10144 | &tcp_reassemble_out_of_order); |
10145 | prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers", |
10146 | "Analyze TCP sequence numbers", |
10147 | "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT", |
10148 | &tcp_analyze_seq); |
10149 | prefs_register_bool_preference(tcp_module, "relative_sequence_numbers", |
10150 | "Relative sequence numbers (Requires \"Analyze TCP sequence numbers\")", |
10151 | "Make the TCP dissector use relative sequence numbers instead of absolute ones. " |
10152 | "To use this option you must also enable \"Analyze TCP sequence numbers\". ", |
10153 | &tcp_relative_seq); |
10154 | |
10155 | prefs_register_custom_preference_TCP_Analysis(tcp_module, "default_override_analysis", |
10156 | "Force interpretation to selected packet(s)", |
10157 | "Override the default analysis with this value for the selected packet", |
10158 | &tcp_default_override_analysis, override_analysis_vals, FALSE(0)); |
10159 | |
10160 | prefs_register_enum_preference(tcp_module, "default_window_scaling", |
10161 | "Scaling factor to use when not available from capture", |
10162 | "Make the TCP dissector use this scaling factor for streams where the signalled scaling factor " |
10163 | "is not visible in the capture", |
10164 | &tcp_default_window_scaling, window_scaling_vals, FALSE(0)); |
10165 | |
10166 | /* Presumably a retired, unconditional version of what has been added back with the preference above... */ |
10167 | prefs_register_obsolete_preference(tcp_module, "window_scaling"); |
10168 | |
10169 | prefs_register_bool_preference(tcp_module, "track_bytes_in_flight", |
10170 | "Track number of bytes in flight", |
10171 | "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. " |
10172 | "To use this option you must also enable \"Analyze TCP sequence numbers\". " |
10173 | "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", |
10174 | &tcp_track_bytes_in_flight); |
10175 | prefs_register_bool_preference(tcp_module, "bif_seq_based", |
10176 | "Evaluate bytes in flight based on sequence numbers", |
10177 | "Evaluate BiF on actual sequence numbers or use the historical method based on payloads (default). " |
10178 | "This option has no effect if not used with \"Track number of bytes in flight\". ", |
10179 | &tcp_bif_seq_based); |
10180 | prefs_register_bool_preference(tcp_module, "calculate_timestamps", |
10181 | "Calculate stream packet number and timestamps", |
10182 | "Calculate relative packet number and timestamps relative to the first frame and the previous frame in the tcp conversation", |
10183 | &tcp_calculate_ts); |
10184 | prefs_register_bool_preference(tcp_module, "try_heuristic_first", |
10185 | "Try heuristic sub-dissectors first", |
10186 | "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port", |
10187 | &try_heuristic_first); |
10188 | prefs_register_bool_preference(tcp_module, "ignore_tcp_timestamps", |
10189 | "Ignore TCP Timestamps in summary", |
10190 | "Do not place the TCP Timestamps in the summary line", |
10191 | &tcp_ignore_timestamps); |
10192 | prefs_register_bool_preference(tcp_module, "fastrt_supersedes_ooo", |
10193 | "Fast Retransmission supersedes Out-of-Order interpretation", |
10194 | "When interpreting ambiguous packets, give precedence to Fast Retransmission or OOO ", |
10195 | &tcp_fastrt_precedence); |
10196 | |
10197 | prefs_register_bool_preference(tcp_module, "no_subdissector_on_error", |
10198 | "Do not call subdissectors for error packets", |
10199 | "Do not call any subdissectors for Retransmitted or OutOfOrder segments", |
10200 | &tcp_no_subdissector_on_error); |
10201 | |
10202 | prefs_register_bool_preference(tcp_module, "dissect_experimental_options_rfc6994", |
10203 | "TCP Experimental Options using the format of RFC 6994", |
10204 | "Assume TCP Experimental Options (253, 254) have an Experiment Identifier and use it for dissection", |
10205 | &tcp_exp_options_rfc6994); |
10206 | |
10207 | prefs_register_bool_preference(tcp_module, "display_process_info_from_ipfix", |
10208 | "Display process information via IPFIX", |
10209 | "Collect and store process information retrieved from IPFIX dissector", |
10210 | &tcp_display_process_info); |
10211 | |
10212 | prefs_register_bool_preference(tcp_module, "read_seq_as_syn_cookie", |
10213 | "Read the seq no. as syn cookie", |
10214 | "Read the sequence number as it was a syn cookie", |
10215 | &read_seq_as_syn_cookie); |
10216 | |
10217 | register_init_routine(tcp_init); |
10218 | reassembly_table_register(&tcp_reassembly_table, |
10219 | &tcp_reassembly_table_functions); |
10220 | |
10221 | register_decode_as(&tcp_da); |
10222 | |
10223 | register_conversation_table(proto_tcp, FALSE(0), tcpip_conversation_packet, tcpip_endpoint_packet); |
10224 | register_conversation_filter("tcp", "TCP", tcp_filter_valid, tcp_build_filter_by_id, NULL((void*)0)); |
10225 | |
10226 | register_seq_analysis("tcp", "TCP Flows", proto_tcp, NULL((void*)0), TL_REQUIRES_NOTHING0x00000000, tcp_seq_analysis_packet); |
10227 | |
10228 | /* considers MPTCP as a distinct protocol (even if it's a TCP option) */ |
10229 | proto_mptcp = proto_register_protocol("Multipath Transmission Control Protocol", "MPTCP", "mptcp"); |
10230 | |
10231 | proto_register_field_array(proto_mptcp, mptcp_hf, array_length(mptcp_hf)(sizeof mptcp_hf / sizeof mptcp_hf[0])); |
10232 | proto_register_subtree_array(mptcp_ett, array_length(mptcp_ett)(sizeof mptcp_ett / sizeof mptcp_ett[0])); |
10233 | |
10234 | /* Register configuration preferences */ |
10235 | mptcp_module = prefs_register_protocol(proto_mptcp, NULL((void*)0)); |
10236 | expert_mptcp = expert_register_protocol(proto_tcp); |
10237 | expert_register_field_array(expert_mptcp, mptcp_ei, array_length(mptcp_ei)(sizeof mptcp_ei / sizeof mptcp_ei[0])); |
10238 | |
10239 | prefs_register_bool_preference(mptcp_module, "analyze_mptcp", |
10240 | "Map TCP subflows to their respective MPTCP connections", |
10241 | "To use this option you must also enable \"Analyze TCP sequence numbers\". ", |
10242 | &tcp_analyze_mptcp); |
10243 | |
10244 | prefs_register_bool_preference(mptcp_module, "relative_sequence_numbers", |
10245 | "Display relative MPTCP sequence numbers.", |
10246 | "In case you don't capture the key, it will use the first DSN seen", |
10247 | &mptcp_relative_seq); |
10248 | |
10249 | prefs_register_bool_preference(mptcp_module, "analyze_mappings", |
10250 | "Deeper analysis of Data Sequence Signal (DSS)", |
10251 | "Scales logarithmically with the number of packets" |
10252 | "You need to capture the handshake for this to work." |
10253 | "\"Map TCP subflows to their respective MPTCP connections\"", |
10254 | &mptcp_analyze_mappings); |
10255 | |
10256 | prefs_register_bool_preference(mptcp_module, "intersubflows_retransmission", |
10257 | "Check for data duplication across subflows", |
10258 | "(Greedy algorithm: Scales linearly with number of subflows and" |
10259 | " logarithmic scaling with number of packets)" |
10260 | "You need to enable DSS mapping analysis for this option to work", |
10261 | &mptcp_intersubflows_retransmission); |
10262 | |
10263 | register_conversation_table(proto_mptcp, FALSE(0), mptcpip_conversation_packet, tcpip_endpoint_packet); |
10264 | register_follow_stream(proto_tcp, "tcp_follow", tcp_follow_conv_filter, tcp_follow_index_filter, tcp_follow_address_filter, |
10265 | tcp_port_to_display, follow_tcp_tap_listener, get_tcp_stream_count, NULL((void*)0)); |
10266 | } |
10267 | |
10268 | void |
10269 | proto_reg_handoff_tcp(void) |
10270 | { |
10271 | dissector_add_uint("ip.proto", IP_PROTO_TCP6, tcp_handle); |
10272 | dissector_add_for_decode_as_with_preference("udp.port", tcp_handle); |
10273 | data_handle = find_dissector("data"); |
10274 | sport_handle = find_dissector("sport"); |
10275 | tcp_tap = register_tap("tcp"); |
10276 | tcp_follow_tap = register_tap("tcp_follow"); |
10277 | |
10278 | capture_dissector_add_uint("ip.proto", IP_PROTO_TCP6, tcp_cap_handle); |
10279 | |
10280 | /* Create dissection function handles for all TCP options */ |
10281 | dissector_add_uint("tcp.option", TCPOPT_TIMESTAMP8, create_dissector_handle( dissect_tcpopt_timestamp, proto_tcp_option_timestamp )); |
10282 | dissector_add_uint("tcp.option", TCPOPT_MSS2, create_dissector_handle( dissect_tcpopt_mss, proto_tcp_option_mss )); |
10283 | dissector_add_uint("tcp.option", TCPOPT_WINDOW3, create_dissector_handle( dissect_tcpopt_wscale, proto_tcp_option_wscale )); |
10284 | dissector_add_uint("tcp.option", TCPOPT_SACK_PERM4, create_dissector_handle( dissect_tcpopt_sack_perm, proto_tcp_option_sack_perm )); |
10285 | dissector_add_uint("tcp.option", TCPOPT_SACK5, create_dissector_handle( dissect_tcpopt_sack, proto_tcp_option_sack )); |
10286 | dissector_add_uint("tcp.option", TCPOPT_ECHO6, create_dissector_handle( dissect_tcpopt_echo, proto_tcp_option_echo )); |
10287 | dissector_add_uint("tcp.option", TCPOPT_ECHOREPLY7, create_dissector_handle( dissect_tcpopt_echo, proto_tcp_option_echoreply )); |
10288 | dissector_add_uint("tcp.option", TCPOPT_CC11, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc )); |
10289 | dissector_add_uint("tcp.option", TCPOPT_CCNEW12, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc_new )); |
10290 | dissector_add_uint("tcp.option", TCPOPT_CCECHO13, create_dissector_handle( dissect_tcpopt_cc, proto_tcp_option_cc_echo )); |
10291 | dissector_add_uint("tcp.option", TCPOPT_MD519, create_dissector_handle( dissect_tcpopt_md5, proto_tcp_option_md5 )); |
10292 | dissector_add_uint("tcp.option", TCPOPT_AO29, create_dissector_handle( dissect_tcpopt_ao, proto_tcp_option_ao )); |
10293 | dissector_add_uint("tcp.option", TCPOPT_SCPS20, create_dissector_handle( dissect_tcpopt_scps, proto_tcp_option_scps )); |
10294 | dissector_add_uint("tcp.option", TCPOPT_SNACK21, create_dissector_handle( dissect_tcpopt_snack, proto_tcp_option_snack )); |
10295 | dissector_add_uint("tcp.option", TCPOPT_RECBOUND22, create_dissector_handle( dissect_tcpopt_recbound, proto_tcp_option_scpsrec )); |
10296 | dissector_add_uint("tcp.option", TCPOPT_CORREXP23, create_dissector_handle( dissect_tcpopt_correxp, proto_tcp_option_scpscor )); |
10297 | dissector_add_uint("tcp.option", TCPOPT_QS27, create_dissector_handle( dissect_tcpopt_qs, proto_tcp_option_qs )); |
10298 | dissector_add_uint("tcp.option", TCPOPT_USER_TO28, create_dissector_handle( dissect_tcpopt_user_to, proto_tcp_option_user_to )); |
10299 | dissector_add_uint("tcp.option", TCPOPT_TFO34, create_dissector_handle( dissect_tcpopt_tfo, proto_tcp_option_tfo )); |
10300 | dissector_add_uint("tcp.option", TCPOPT_RVBD_PROBE76, create_dissector_handle( dissect_tcpopt_rvbd_probe, proto_tcp_option_rvbd_probe )); |
10301 | dissector_add_uint("tcp.option", TCPOPT_RVBD_TRPY78, create_dissector_handle( dissect_tcpopt_rvbd_trpy, proto_tcp_option_rvbd_trpy )); |
10302 | dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_00xac, create_dissector_handle( dissect_tcpopt_acc_ecn, proto_tcp_option_acc_ecn )); |
10303 | dissector_add_uint("tcp.option", TCPOPT_ACC_ECN_10xae, create_dissector_handle( dissect_tcpopt_acc_ecn, proto_tcp_option_acc_ecn )); |
10304 | dissector_add_uint("tcp.option", TCPOPT_EXP_FD0xfd, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp )); |
10305 | dissector_add_uint("tcp.option", TCPOPT_EXP_FE0xfe, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp )); |
10306 | dissector_add_uint("tcp.option", TCPOPT_MPTCP30, create_dissector_handle( dissect_tcpopt_mptcp, proto_mptcp )); |
10307 | /* Common handle for all the unknown/unsupported TCP options */ |
10308 | tcp_opt_unknown_handle = create_dissector_handle( dissect_tcpopt_unknown, proto_tcp_option_unknown ); |
10309 | |
10310 | mptcp_tap = register_tap("mptcp"); |
10311 | exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4"OSI layer 4"); |
10312 | |
10313 | proto_ip = proto_get_id_by_filter_name("ip"); |
10314 | proto_icmp = proto_get_id_by_filter_name("icmp"); |
10315 | } |
10316 | |
10317 | /* |
10318 | * Editor modelines |
10319 | * |
10320 | * Local Variables: |
10321 | * c-basic-offset: 4 |
10322 | * tab-width: 8 |
10323 | * indent-tabs-mode: nil |
10324 | * End: |
10325 | * |
10326 | * ex: set shiftwidth=4 tabstop=8 expandtab: |
10327 | * :indentSize=4:tabSize=8:noTabs=true: |
10328 | */ |