2 * Routines for TCP packet disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 #include <epan/in_cksum.h>
32 #include <epan/packet.h>
33 #include <epan/exceptions.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/ipproto.h>
36 #include <epan/expert.h>
37 #include <epan/ip_opts.h>
38 #include <epan/follow.h>
39 #include <epan/prefs.h>
40 #include <epan/wmem/wmem.h>
41 #include <epan/show_exception.h>
42 #include <epan/conversation.h>
43 #include <epan/reassemble.h>
45 #include <epan/decode_as.h>
47 #include "packet-tcp.h"
48 #include "packet-ip.h"
49 #include "packet-icmp.h"
51 static int tcp_tap = -1;
53 /* Place TCP summary in proto tree */
54 static gboolean tcp_summary_in_tree = TRUE;
57 * Flag to control whether to check the TCP checksum.
59 * In at least some Solaris network traces, there are packets with bad
60 * TCP checksums, but the traffic appears to indicate that the packets
61 * *were* received; the packets were probably sent by the host on which
62 * the capture was being done, on a network interface to which
63 * checksumming was offloaded, so that DLPI supplied an un-checksummed
64 * packet to the capture program but a checksummed packet got put onto
67 static gboolean tcp_check_checksum = FALSE;
70 * Window scaling values to be used when not known (set as a preference) */
71 enum scaling_window_value {
72 WindowScaling_NotKnown=-1,
89 static gint tcp_default_window_scaling = (gint)WindowScaling_NotKnown;
92 extern FILE* data_out_file;
94 static int proto_tcp = -1;
95 static int hf_tcp_srcport = -1;
96 static int hf_tcp_dstport = -1;
97 static int hf_tcp_port = -1;
98 static int hf_tcp_stream = -1;
99 static int hf_tcp_seq = -1;
100 static int hf_tcp_nxtseq = -1;
101 static int hf_tcp_ack = -1;
102 static int hf_tcp_hdr_len = -1;
103 static int hf_tcp_flags = -1;
104 static int hf_tcp_flags_res = -1;
105 static int hf_tcp_flags_ns = -1;
106 static int hf_tcp_flags_cwr = -1;
107 static int hf_tcp_flags_ecn = -1;
108 static int hf_tcp_flags_urg = -1;
109 static int hf_tcp_flags_ack = -1;
110 static int hf_tcp_flags_push = -1;
111 static int hf_tcp_flags_reset = -1;
112 static int hf_tcp_flags_syn = -1;
113 static int hf_tcp_flags_fin = -1;
114 static int hf_tcp_window_size_value = -1;
115 static int hf_tcp_window_size = -1;
116 static int hf_tcp_window_size_scalefactor = -1;
117 static int hf_tcp_checksum = -1;
118 static int hf_tcp_checksum_bad = -1;
119 static int hf_tcp_checksum_good = -1;
120 static int hf_tcp_len = -1;
121 static int hf_tcp_urgent_pointer = -1;
122 static int hf_tcp_analysis = -1;
123 static int hf_tcp_analysis_flags = -1;
124 static int hf_tcp_analysis_bytes_in_flight = -1;
125 static int hf_tcp_analysis_acks_frame = -1;
126 static int hf_tcp_analysis_ack_rtt = -1;
127 static int hf_tcp_analysis_rto = -1;
128 static int hf_tcp_analysis_rto_frame = -1;
129 static int hf_tcp_analysis_duplicate_ack = -1;
130 static int hf_tcp_analysis_duplicate_ack_num = -1;
131 static int hf_tcp_analysis_duplicate_ack_frame = -1;
132 static int hf_tcp_continuation_to = -1;
133 static int hf_tcp_pdu_time = -1;
134 static int hf_tcp_pdu_size = -1;
135 static int hf_tcp_pdu_last_frame = -1;
136 static int hf_tcp_reassembled_in = -1;
137 static int hf_tcp_reassembled_length = -1;
138 static int hf_tcp_reassembled_data = -1;
139 static int hf_tcp_segments = -1;
140 static int hf_tcp_segment = -1;
141 static int hf_tcp_segment_overlap = -1;
142 static int hf_tcp_segment_overlap_conflict = -1;
143 static int hf_tcp_segment_multiple_tails = -1;
144 static int hf_tcp_segment_too_long_fragment = -1;
145 static int hf_tcp_segment_error = -1;
146 static int hf_tcp_segment_count = -1;
147 static int hf_tcp_options = -1;
148 static int hf_tcp_option_kind = -1;
149 static int hf_tcp_option_len = -1;
150 static int hf_tcp_option_mss = -1;
151 static int hf_tcp_option_mss_val = -1;
152 static int hf_tcp_option_wscale_shift = -1;
153 static int hf_tcp_option_wscale_multiplier = -1;
154 static int hf_tcp_option_sack_perm = -1;
155 static int hf_tcp_option_sack = -1;
156 static int hf_tcp_option_sack_sle = -1;
157 static int hf_tcp_option_sack_sre = -1;
158 static int hf_tcp_option_sack_range_count = -1;
159 static int hf_tcp_option_echo = -1;
160 static int hf_tcp_option_timestamp_tsval = -1;
161 static int hf_tcp_option_timestamp_tsecr = -1;
162 static int hf_tcp_option_cc = -1;
163 static int hf_tcp_option_qs = -1;
164 static int hf_tcp_option_exp = -1;
165 static int hf_tcp_option_exp_data = -1;
166 static int hf_tcp_option_exp_magic_number = -1;
168 static int hf_tcp_option_rvbd_probe = -1;
169 static int hf_tcp_option_rvbd_probe_version1 = -1;
170 static int hf_tcp_option_rvbd_probe_version2 = -1;
171 static int hf_tcp_option_rvbd_probe_type1 = -1;
172 static int hf_tcp_option_rvbd_probe_type2 = -1;
173 static int hf_tcp_option_rvbd_probe_optlen = -1;
174 static int hf_tcp_option_rvbd_probe_prober = -1;
175 static int hf_tcp_option_rvbd_probe_proxy = -1;
176 static int hf_tcp_option_rvbd_probe_client = -1;
177 static int hf_tcp_option_rvbd_probe_proxy_port = -1;
178 static int hf_tcp_option_rvbd_probe_appli_ver = -1;
179 static int hf_tcp_option_rvbd_probe_storeid = -1;
180 static int hf_tcp_option_rvbd_probe_flags = -1;
181 static int hf_tcp_option_rvbd_probe_flag_last_notify = -1;
182 static int hf_tcp_option_rvbd_probe_flag_server_connected = -1;
183 static int hf_tcp_option_rvbd_probe_flag_not_cfe = -1;
184 static int hf_tcp_option_rvbd_probe_flag_sslcert = -1;
185 static int hf_tcp_option_rvbd_probe_flag_probe_cache = -1;
187 static int hf_tcp_option_rvbd_trpy = -1;
188 static int hf_tcp_option_rvbd_trpy_flags = -1;
189 static int hf_tcp_option_rvbd_trpy_flag_mode = -1;
190 static int hf_tcp_option_rvbd_trpy_flag_oob = -1;
191 static int hf_tcp_option_rvbd_trpy_flag_chksum = -1;
192 static int hf_tcp_option_rvbd_trpy_flag_fw_rst = -1;
193 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_inner = -1;
194 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_probe = -1;
195 static int hf_tcp_option_rvbd_trpy_src = -1;
196 static int hf_tcp_option_rvbd_trpy_dst = -1;
197 static int hf_tcp_option_rvbd_trpy_src_port = -1;
198 static int hf_tcp_option_rvbd_trpy_dst_port = -1;
199 static int hf_tcp_option_rvbd_trpy_client_port = -1;
201 static int hf_tcp_option_mptcp_flags = -1;
202 static int hf_tcp_option_mptcp_B_flag = -1;
203 static int hf_tcp_option_mptcp_C_flag = -1;
204 static int hf_tcp_option_mptcp_S_flag = -1;
205 static int hf_tcp_option_mptcp_F_flag = -1;
206 static int hf_tcp_option_mptcp_m_flag = -1;
207 static int hf_tcp_option_mptcp_M_flag = -1;
208 static int hf_tcp_option_mptcp_a_flag = -1;
209 static int hf_tcp_option_mptcp_A_flag = -1;
210 static int hf_tcp_option_mptcp_subtype = -1;
211 static int hf_tcp_option_mptcp_version = -1;
212 static int hf_tcp_option_mptcp_address_id = -1;
213 static int hf_tcp_option_mptcp_recv_token = -1;
214 static int hf_tcp_option_mptcp_sender_key = -1;
215 static int hf_tcp_option_mptcp_recv_key = -1;
216 static int hf_tcp_option_mptcp_sender_rand = -1;
217 static int hf_tcp_option_mptcp_sender_trunc_mac = -1;
218 static int hf_tcp_option_mptcp_sender_mac = -1;
219 static int hf_tcp_option_mptcp_data_ack = -1;
220 static int hf_tcp_option_mptcp_data_seq_no = -1;
221 static int hf_tcp_option_mptcp_subflow_seq_no = -1;
222 static int hf_tcp_option_mptcp_data_lvl_len = -1;
223 static int hf_tcp_option_mptcp_checksum = -1;
224 static int hf_tcp_option_mptcp_ipver = -1;
225 static int hf_tcp_option_mptcp_ipv4 = -1;
226 static int hf_tcp_option_mptcp_ipv6 = -1;
227 static int hf_tcp_option_mptcp_port = -1;
228 static int hf_tcp_option_fast_open = -1;
229 static int hf_tcp_option_fast_open_cookie_request = -1;
230 static int hf_tcp_option_fast_open_cookie = -1;
232 static int hf_tcp_ts_relative = -1;
233 static int hf_tcp_ts_delta = -1;
234 static int hf_tcp_option_type = -1;
235 static int hf_tcp_option_type_copy = -1;
236 static int hf_tcp_option_type_class = -1;
237 static int hf_tcp_option_type_number = -1;
238 static int hf_tcp_option_scps = -1;
239 static int hf_tcp_option_scps_vector = -1;
240 static int hf_tcp_option_scps_binding = -1;
241 static int hf_tcp_option_scps_binding_len = -1;
242 static int hf_tcp_scpsoption_flags_bets = -1;
243 static int hf_tcp_scpsoption_flags_snack1 = -1;
244 static int hf_tcp_scpsoption_flags_snack2 = -1;
245 static int hf_tcp_scpsoption_flags_compress = -1;
246 static int hf_tcp_scpsoption_flags_nlts = -1;
247 static int hf_tcp_scpsoption_flags_reserved = -1;
248 static int hf_tcp_scpsoption_connection_id = -1;
249 static int hf_tcp_option_snack = -1;
250 static int hf_tcp_option_snack_offset = -1;
251 static int hf_tcp_option_snack_size = -1;
252 static int hf_tcp_option_snack_le = -1;
253 static int hf_tcp_option_snack_re = -1;
254 static int hf_tcp_option_user_to = -1;
255 static int hf_tcp_option_user_to_granularity = -1;
256 static int hf_tcp_option_user_to_val = -1;
257 static int hf_tcp_proc_src_uid = -1;
258 static int hf_tcp_proc_src_pid = -1;
259 static int hf_tcp_proc_src_uname = -1;
260 static int hf_tcp_proc_src_cmd = -1;
261 static int hf_tcp_proc_dst_uid = -1;
262 static int hf_tcp_proc_dst_pid = -1;
263 static int hf_tcp_proc_dst_uname = -1;
264 static int hf_tcp_proc_dst_cmd = -1;
265 static int hf_tcp_segment_data = -1;
267 static gint ett_tcp = -1;
268 static gint ett_tcp_flags = -1;
269 static gint ett_tcp_option_type = -1;
270 static gint ett_tcp_options = -1;
271 static gint ett_tcp_option_timestamp = -1;
272 static gint ett_tcp_option_mss = -1;
273 static gint ett_tcp_option_wscale = -1;
274 static gint ett_tcp_option_sack = -1;
275 static gint ett_tcp_option_scps = -1;
276 static gint ett_tcp_option_scps_extended = -1;
277 static gint ett_tcp_option_user_to = -1;
278 static gint ett_tcp_option_exp = -1;
279 static gint ett_tcp_option_sack_perm = -1;
280 static gint ett_tcp_analysis = -1;
281 static gint ett_tcp_analysis_faults = -1;
282 static gint ett_tcp_timestamps = -1;
283 static gint ett_tcp_segments = -1;
284 static gint ett_tcp_segment = -1;
285 static gint ett_tcp_checksum = -1;
286 static gint ett_tcp_process_info = -1;
287 static gint ett_tcp_option_mptcp = -1;
289 static gint ett_tcp_opt_rvbd_probe = -1;
290 static gint ett_tcp_opt_rvbd_probe_flags = -1;
291 static gint ett_tcp_opt_rvbd_trpy = -1;
292 static gint ett_tcp_opt_rvbd_trpy_flags = -1;
294 static expert_field ei_tcp_opt_len_invalid = EI_INIT;
295 static expert_field ei_tcp_analysis_retransmission = EI_INIT;
296 static expert_field ei_tcp_analysis_fast_retransmission = EI_INIT;
297 static expert_field ei_tcp_analysis_spurious_retransmission = EI_INIT;
298 static expert_field ei_tcp_analysis_out_of_order = EI_INIT;
299 static expert_field ei_tcp_analysis_reused_ports = EI_INIT;
300 static expert_field ei_tcp_analysis_lost_packet = EI_INIT;
301 static expert_field ei_tcp_analysis_ack_lost_packet = EI_INIT;
302 static expert_field ei_tcp_analysis_window_update = EI_INIT;
303 static expert_field ei_tcp_analysis_window_full = EI_INIT;
304 static expert_field ei_tcp_analysis_keep_alive = EI_INIT;
305 static expert_field ei_tcp_analysis_keep_alive_ack = EI_INIT;
306 static expert_field ei_tcp_analysis_duplicate_ack = EI_INIT;
307 static expert_field ei_tcp_analysis_zero_window_probe = EI_INIT;
308 static expert_field ei_tcp_analysis_zero_window = EI_INIT;
309 static expert_field ei_tcp_analysis_zero_window_probe_ack = EI_INIT;
310 static expert_field ei_tcp_scps_capable = EI_INIT;
311 static expert_field ei_tcp_option_snack_sequence = EI_INIT;
312 static expert_field ei_tcp_short_segment = EI_INIT;
313 static expert_field ei_tcp_ack_nonzero = EI_INIT;
314 static expert_field ei_tcp_connection_sack = EI_INIT;
315 static expert_field ei_tcp_connection_syn = EI_INIT;
316 static expert_field ei_tcp_connection_fin = EI_INIT;
317 static expert_field ei_tcp_connection_rst = EI_INIT;
318 static expert_field ei_tcp_checksum_ffff = EI_INIT;
319 static expert_field ei_tcp_checksum_bad = EI_INIT;
320 static expert_field ei_tcp_urgent_pointer_non_zero = EI_INIT;
322 /* Some protocols such as encrypted DCE/RPCoverHTTP have dependencies
323 * from one PDU to the next PDU and require that they are called in sequence.
324 * These protocols would not be able to handle PDUs coming out of order
325 * or for example when a PDU is seen twice, like for retransmissions.
326 * This preference can be set for such protocols to make sure that we don't
327 * invoke the subdissectors for retransmitted or out-of-order segments.
329 static gboolean tcp_no_subdissector_on_error = FALSE;
332 * FF: (draft-ietf-tcpm-experimental-options-03)
333 * With this flag set we assume the option structure for experimental
334 * codepoints (253, 254) has a magic number field (first field after the
335 * Kind and Length). The magic number is used to differentiate different
336 * experiments and thus will be used in data dissection.
338 static gboolean tcp_exp_options_with_magic = TRUE;
343 #define TCPOPT_NOP 1 /* Padding */
344 #define TCPOPT_EOL 0 /* End of options */
345 #define TCPOPT_MSS 2 /* Segment size negotiating */
346 #define TCPOPT_WINDOW 3 /* Window scaling */
347 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
348 #define TCPOPT_SACK 5 /* SACK Block */
349 #define TCPOPT_ECHO 6
350 #define TCPOPT_ECHOREPLY 7
351 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
353 #define TCPOPT_CCNEW 12
354 #define TCPOPT_CCECHO 13
355 #define TCPOPT_MD5 19 /* RFC2385 */
356 #define TCPOPT_MPTCP 0x1e /* Multipath TCP */
357 #define TCPOPT_SCPS 20 /* SCPS Capabilities */
358 #define TCPOPT_SNACK 21 /* SCPS SNACK */
359 #define TCPOPT_RECBOUND 22 /* SCPS Record Boundary */
360 #define TCPOPT_CORREXP 23 /* SCPS Corruption Experienced */
361 #define TCPOPT_QS 27 /* RFC4782 */
362 #define TCPOPT_USER_TO 28 /* RFC5482 */
363 #define TCPOPT_EXP_FD 0xfd /* Experimental, reserved */
364 #define TCPOPT_EXP_FE 0xfe /* Experimental, reserved */
365 /* Non IANA registered option numbers */
366 #define TCPOPT_RVBD_PROBE 76 /* Riverbed probe option */
367 #define TCPOPT_RVBD_TRPY 78 /* Riverbed transparency option */
372 #define TCPOLEN_MSS 4
373 #define TCPOLEN_WINDOW 3
374 #define TCPOLEN_SACK_PERM 2
375 #define TCPOLEN_SACK_MIN 2
376 #define TCPOLEN_ECHO 6
377 #define TCPOLEN_ECHOREPLY 6
378 #define TCPOLEN_TIMESTAMP 10
380 #define TCPOLEN_CCNEW 6
381 #define TCPOLEN_CCECHO 6
382 #define TCPOLEN_MD5 18
383 #define TCPOLEN_MPTCP_MIN 8
384 #define TCPOLEN_SCPS 4
385 #define TCPOLEN_SNACK 6
386 #define TCPOLEN_RECBOUND 2
387 #define TCPOLEN_CORREXP 2
389 #define TCPOLEN_USER_TO 4
390 #define TCPOLEN_RVBD_PROBE_MIN 3
391 #define TCPOLEN_RVBD_TRPY_MIN 16
392 #define TCPOLEN_EXP_MIN 2
395 * Multipath TCP subtypes
397 #define TCPOPT_MPTCP_MP_CAPABLE 0x0 /* Multipath TCP Multipath Capable */
398 #define TCPOPT_MPTCP_MP_JOIN 0x1 /* Multipath TCP Join Connection */
399 #define TCPOPT_MPTCP_DSS 0x2 /* Multipath TCP Data Sequence Signal */
400 #define TCPOPT_MPTCP_ADD_ADDR 0x3 /* Multipath TCP Add Address */
401 #define TCPOPT_MPTCP_REMOVE_ADDR 0x4 /* Multipath TCP Remove Address */
402 #define TCPOPT_MPTCP_MP_PRIO 0x5 /* Multipath TCP Change Subflow Priority */
403 #define TCPOPT_MPTCP_MP_FAIL 0x6 /* Multipath TCP Fallback */
405 static const true_false_string tcp_option_user_to_granularity = {
409 static const value_string tcp_option_kind_vs[] = {
410 { TCPOPT_EXP_FD, "Experimental 0xFD" },
411 { TCPOPT_EXP_FE, "Experimental 0xFE" },
412 { TCPOPT_WINDOW, "Window Scale" },
413 { TCPOPT_SACK_PERM, "SACK Permission" },
414 { TCPOPT_MSS, "MSS size" },
415 { TCPOPT_TIMESTAMP, "Timestamp" },
416 { TCPOPT_MPTCP, "Multipath TCP" },
420 /* not all of the hf_fields below make sense for TCP but we have to provide
421 them anyways to comply with the API (which was aimed for IP fragment
423 static const fragment_items tcp_segment_items = {
428 &hf_tcp_segment_overlap,
429 &hf_tcp_segment_overlap_conflict,
430 &hf_tcp_segment_multiple_tails,
431 &hf_tcp_segment_too_long_fragment,
432 &hf_tcp_segment_error,
433 &hf_tcp_segment_count,
434 &hf_tcp_reassembled_in,
435 &hf_tcp_reassembled_length,
436 &hf_tcp_reassembled_data,
440 static const value_string mptcp_subtype_vs[] = {
441 { TCPOPT_MPTCP_MP_CAPABLE, "Multipath Capable" },
442 { TCPOPT_MPTCP_MP_JOIN, "Join Connection" },
443 { TCPOPT_MPTCP_DSS, "Data Sequence Signal" },
444 { TCPOPT_MPTCP_ADD_ADDR, "Add Address"},
445 { TCPOPT_MPTCP_REMOVE_ADDR, "Remove Address" },
446 { TCPOPT_MPTCP_MP_PRIO, "Change Subflow Priority" },
447 { TCPOPT_MPTCP_MP_FAIL, "TCP Fallback" },
451 static dissector_table_t subdissector_table;
452 static heur_dissector_list_t heur_subdissector_list;
453 static dissector_handle_t data_handle;
454 static dissector_handle_t sport_handle;
455 static guint32 tcp_stream_count;
457 /* XXX - redefined here to not create UI dependencies */
458 #define UTF8_LEFTWARDS_ARROW "\xe2\x86\x90" /* 8592 / 0x2190 */
459 #define UTF8_RIGHTWARDS_ARROW "\xe2\x86\x92" /* 8594 / 0x2192 */
460 #define UTF8_LEFT_RIGHT_ARROW "\xe2\x86\x94" /* 8596 / 0x2194 */
462 static void tcp_src_prompt(packet_info *pinfo, gchar* result)
464 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Source (%u%s)", pinfo->srcport, UTF8_RIGHTWARDS_ARROW);
467 static gpointer tcp_src_value(packet_info *pinfo)
469 return GUINT_TO_POINTER(pinfo->srcport);
472 static void tcp_dst_prompt(packet_info *pinfo, gchar* result)
474 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Destination (%s%u)", UTF8_RIGHTWARDS_ARROW, pinfo->destport);
477 static gpointer tcp_dst_value(packet_info *pinfo)
479 return GUINT_TO_POINTER(pinfo->destport);
482 static void tcp_both_prompt(packet_info *pinfo, gchar* result)
484 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Both (%u%s%u)", pinfo->srcport,UTF8_LEFT_RIGHT_ARROW, pinfo->destport);
487 /* TCP structs and definitions */
489 /* **************************************************************************
490 * RTT, relative sequence numbers, window scaling & etc.
491 * **************************************************************************/
492 static gboolean tcp_analyze_seq = TRUE;
493 static gboolean tcp_relative_seq = TRUE;
494 static gboolean tcp_track_bytes_in_flight = TRUE;
495 static gboolean tcp_calculate_ts = FALSE;
497 #define TCP_A_RETRANSMISSION 0x0001
498 #define TCP_A_LOST_PACKET 0x0002
499 #define TCP_A_ACK_LOST_PACKET 0x0004
500 #define TCP_A_KEEP_ALIVE 0x0008
501 #define TCP_A_DUPLICATE_ACK 0x0010
502 #define TCP_A_ZERO_WINDOW 0x0020
503 #define TCP_A_ZERO_WINDOW_PROBE 0x0040
504 #define TCP_A_ZERO_WINDOW_PROBE_ACK 0x0080
505 #define TCP_A_KEEP_ALIVE_ACK 0x0100
506 #define TCP_A_OUT_OF_ORDER 0x0200
507 #define TCP_A_FAST_RETRANSMISSION 0x0400
508 #define TCP_A_WINDOW_UPDATE 0x0800
509 #define TCP_A_WINDOW_FULL 0x1000
510 #define TCP_A_REUSED_PORTS 0x2000
511 #define TCP_A_SPURIOUS_RETRANSMISSION 0x4000
514 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
515 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
516 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
517 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo);
520 struct tcp_analysis *
521 init_tcp_conversation_data(packet_info *pinfo)
523 struct tcp_analysis *tcpd;
525 /* Initialize the tcp protocol data structure to add to the tcp conversation */
526 tcpd=wmem_new0(wmem_file_scope(), struct tcp_analysis);
527 tcpd->flow1.win_scale=-1;
528 tcpd->flow1.window = G_MAXUINT32;
529 tcpd->flow1.multisegment_pdus=wmem_tree_new(wmem_file_scope());
531 tcpd->flow1.username = NULL;
532 tcpd->flow1.command = NULL;
534 tcpd->flow2.window = G_MAXUINT32;
535 tcpd->flow2.win_scale=-1;
536 tcpd->flow2.multisegment_pdus=wmem_tree_new(wmem_file_scope());
538 tcpd->flow2.username = NULL;
539 tcpd->flow2.command = NULL;
541 tcpd->acked_table=wmem_tree_new(wmem_file_scope());
542 tcpd->ts_first.secs=pinfo->fd->abs_ts.secs;
543 tcpd->ts_first.nsecs=pinfo->fd->abs_ts.nsecs;
544 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
545 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
546 tcpd->flow1.valid_bif = 1;
547 tcpd->flow2.valid_bif = 1;
548 tcpd->stream = tcp_stream_count++;
549 tcpd->server_port = 0;
554 struct tcp_analysis *
555 get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)
558 struct tcp_analysis *tcpd;
560 /* Did the caller supply the conversation pointer? */
562 conv = find_or_create_conversation(pinfo);
564 /* Get the data for this conversation */
565 tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
567 /* If the conversation was just created or it matched a
568 * conversation with template options, tcpd will not
569 * have been initialized. So, initialize
570 * a new tcpd structure for the conversation.
573 tcpd = init_tcp_conversation_data(pinfo);
574 conversation_add_proto_data(conv, proto_tcp, tcpd);
581 /* check direction and get ua lists */
582 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
583 /* if the addresses are equal, match the ports instead */
585 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
588 tcpd->fwd=&(tcpd->flow1);
589 tcpd->rev=&(tcpd->flow2);
591 tcpd->fwd=&(tcpd->flow2);
592 tcpd->rev=&(tcpd->flow1);
599 /* Attach process info to a flow */
600 /* XXX - We depend on the TCP dissector finding the conversation first */
602 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) {
603 conversation_t *conv;
604 struct tcp_analysis *tcpd;
605 tcp_flow_t *flow = NULL;
607 conv = find_conversation(frame_num, local_addr, remote_addr, PT_TCP, local_port, remote_port, 0);
612 tcpd = (struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
617 if (CMP_ADDRESS(local_addr, &conv->key_ptr->addr1) == 0 && local_port == conv->key_ptr->port1) {
619 } else if (CMP_ADDRESS(remote_addr, &conv->key_ptr->addr1) == 0 && remote_port == conv->key_ptr->port1) {
622 if (!flow || flow->command) {
626 flow->process_uid = uid;
627 flow->process_pid = pid;
628 flow->username = wmem_strdup(wmem_file_scope(), username);
629 flow->command = wmem_strdup(wmem_file_scope(), command);
632 /* Return the current stream count */
633 guint32 get_tcp_stream_count(void)
635 return tcp_stream_count;
638 /* Calculate the timestamps relative to this conversation */
640 tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
641 struct tcp_per_packet_data_t *tcppd)
644 tcppd = wmem_new(wmem_file_scope(), struct tcp_per_packet_data_t);
645 p_add_proto_data(wmem_file_scope(), pinfo, proto_tcp, 0, tcppd);
651 nstime_delta(&tcppd->ts_del, &pinfo->fd->abs_ts, &tcpd->ts_prev);
653 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
654 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
657 /* Add a subtree with the timestamps relative to this conversation */
659 tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
668 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "Timestamps");
669 PROTO_ITEM_SET_GENERATED(item);
670 tree=proto_item_add_subtree(item, ett_tcp_timestamps);
672 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
673 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);
674 PROTO_ITEM_SET_GENERATED(item);
677 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, 0);
680 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,
682 PROTO_ITEM_SET_GENERATED(item);
687 print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)
691 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);
692 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
693 tvb, 0, 0, msp->first_frame);
694 PROTO_ITEM_SET_GENERATED(item);
697 /* if we know that a PDU starts inside this segment, return the adjusted
698 offset to where that PDU starts or just return offset back
699 and let TCP try to find out what it can about this segment
702 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)
704 struct tcp_multisegment_pdu *msp=NULL;
706 if(!pinfo->fd->flags.visited) {
707 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);
709 /* If this is a continuation of a PDU started in a
710 * previous segment we need to update the last_frame
713 if(seq>msp->seq && seq<msp->nxtpdu) {
714 msp->last_frame=pinfo->fd->num;
715 msp->last_frame_time=pinfo->fd->abs_ts;
716 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
719 /* If this segment is completely within a previous PDU
720 * then we just skip this packet
722 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {
725 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {
726 offset+=msp->nxtpdu-seq;
732 /* First we try to find the start and transfer time for a PDU.
733 * We only print this for the very first segment of a PDU
734 * and only for PDUs spanning multiple segments.
735 * Se we look for if there was any multisegment PDU started
736 * just BEFORE the end of this segment. I.e. either inside this
737 * segment or in a previous segment.
738 * Since this might also match PDUs that are completely within
739 * this segment we also verify that the found PDU does span
740 * beyond the end of this segment.
742 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, nxtseq-1);
744 if(pinfo->fd->num==msp->first_frame) {
748 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);
749 PROTO_ITEM_SET_GENERATED(item);
751 nstime_delta(&ns, &msp->last_frame_time, &pinfo->fd->abs_ts);
752 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,
754 PROTO_ITEM_SET_GENERATED(item);
758 /* Second we check if this segment is part of a PDU started
759 * prior to the segment (seq-1)
761 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);
763 /* If this segment is completely within a previous PDU
764 * then we just skip this packet
766 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {
767 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
771 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {
772 offset+=msp->nxtpdu-seq;
781 /* if we saw a PDU that extended beyond the end of the segment,
782 use this function to remember where the next pdu starts
784 struct tcp_multisegment_pdu *
785 pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, wmem_tree_t *multisegment_pdus)
787 struct tcp_multisegment_pdu *msp;
789 msp=wmem_new(wmem_file_scope(), struct tcp_multisegment_pdu);
792 msp->first_frame=pinfo->fd->num;
793 msp->last_frame=pinfo->fd->num;
794 msp->last_frame_time=pinfo->fd->abs_ts;
796 wmem_tree_insert32(multisegment_pdus, seq, (void *)msp);
800 /* This is called for SYN and SYN+ACK packets and the purpose is to verify
801 * that we have seen window scaling in both directions.
802 * If we cant find window scaling being set in both directions
803 * that means it was present in the SYN but not in the SYN+ACK
804 * (or the SYN was missing) and then we disable the window scaling
805 * for this tcp session.
808 verify_tcp_window_scaling(gboolean is_synack, struct tcp_analysis *tcpd)
810 if( tcpd->fwd->win_scale==-1 ) {
811 /* We know window scaling will not be used as:
812 * a) this is the SYN and it does not have the WS option
813 * (we set the reverse win_scale also in case we miss
815 * b) this is the SYN/ACK and either the SYN packet has not
816 * been seen or it did have the WS option. As the SYN/ACK
817 * does not have the WS option, window scaling will not be used.
819 * Setting win_scale to -2 to indicate that we can
820 * trust the window_size value in the TCP header.
822 tcpd->fwd->win_scale = -2;
823 tcpd->rev->win_scale = -2;
825 } else if( is_synack && tcpd->rev->win_scale==-2 ) {
826 /* The SYN/ACK has the WS option, while the SYN did not,
827 * this should not happen, but the endpoints will not
828 * have used window scaling, so we will neither
830 tcpd->fwd->win_scale = -2;
834 /* if we saw a window scaling option, store it for future reference
837 pdu_store_window_scale_option(guint8 ws, struct tcp_analysis *tcpd)
840 tcpd->fwd->win_scale=ws;
843 /* when this function returns, it will (if createflag) populate the ta pointer.
846 tcp_analyze_get_acked_struct(guint32 frame, guint32 seq, guint32 ack, gboolean createflag, struct tcp_analysis *tcpd)
848 wmem_tree_key_t key[] = {{1, &frame}, {1, &seq}, {1, &ack}, {0, NULL}};
854 tcpd->ta = (struct tcp_acked *)wmem_tree_lookup32_array(tcpd->acked_table, key);
855 if((!tcpd->ta) && createflag) {
856 tcpd->ta = wmem_new0(wmem_file_scope(), struct tcp_acked);
857 wmem_tree_insert32_array(tcpd->acked_table, key, (void *)tcpd->ta);
862 /* fwd contains a list of all segments processed but not yet ACKed in the
863 * same direction as the current segment.
864 * rev contains a list of all segments received but not yet ACKed in the
865 * opposite direction to the current segment.
867 * New segments are always added to the head of the fwd/rev lists.
871 tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint16 flags, guint32 window, struct tcp_analysis *tcpd)
873 tcp_unacked_t *ual=NULL;
874 tcp_unacked_t *prevual=NULL;
879 printf("\nanalyze_sequence numbers frame:%u\n",pinfo->fd->num);
880 printf("FWD list lastflags:0x%04x base_seq:%u:\n",tcpd->fwd->lastsegmentflags,tcpd->fwd->base_seq);
881 for(ual=tcpd->fwd->segments; ual; ual=ual->next)
882 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);
883 printf("REV list lastflags:0x%04x base_seq:%u:\n",tcpd->rev->lastsegmentflags,tcpd->rev->base_seq);
884 for(ual=tcpd->rev->segments; ual; ual=ual->next)
885 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);
892 /* if this is the first segment for this list we need to store the
895 * Start relative seq and ack numbers at 1 if this
896 * is not a SYN packet. This makes the relative
897 * seq/ack numbers to be displayed correctly in the
898 * event that the SYN or SYN/ACK packet is not seen
899 * (this solves bug 1542)
901 if(tcpd->fwd->base_seq==0) {
902 tcpd->fwd->base_seq = (flags & TH_SYN) ? seq : seq-1;
905 /* Only store reverse sequence if this isn't the SYN
906 * There's no guarantee that the ACK field of a SYN
907 * contains zeros; get the ISN from the first segment
908 * with the ACK bit set instead (usually the SYN/ACK).
910 * If the SYN and SYN/ACK were received out-of-order,
911 * the ISN is ack-1. If we missed the SYN/ACK, but got
912 * the last ACK of the 3WHS, the ISN is ack-1. For all
913 * other packets the ISN is unknown, so ack-1 is
914 * as good a guess as ack.
916 if( (tcpd->rev->base_seq==0) && (flags & TH_ACK) ) {
917 tcpd->rev->base_seq = ack-1;
920 if( flags & TH_ACK ) {
921 tcpd->rev->valid_bif = 1;
925 * it is a zero window probe if
926 * the sequence number is the next expected one
927 * the window in the other direction is 0
928 * the segment is exactly 1 byte
932 && seq==tcpd->fwd->nextseq
933 && tcpd->rev->window==0 ) {
935 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
937 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
943 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
947 && (flags&(TH_RST|TH_FIN|TH_SYN))==0 ) {
949 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
951 tcpd->ta->flags|=TCP_A_ZERO_WINDOW;
956 * If this segment is beyond the last seen nextseq we must
957 * have missed some previous segment
959 * We only check for this if we have actually seen segments prior to this
961 * RST packets are not checked for this.
963 if( tcpd->fwd->nextseq
964 && GT_SEQ(seq, tcpd->fwd->nextseq)
965 && (flags&(TH_RST))==0 ) {
967 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
969 tcpd->ta->flags|=TCP_A_LOST_PACKET;
971 /* Disable BiF until an ACK is seen in the other direction */
972 tcpd->fwd->valid_bif = 0;
977 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
978 * to what should be the next sequence number.
979 * SYN/FIN/RST segments are never keepalives
982 if( (seglen==0||seglen==1)
983 && seq==(tcpd->fwd->nextseq-1)
984 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
986 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
988 tcpd->ta->flags|=TCP_A_KEEP_ALIVE;
992 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
993 * the previous seen segment and with a new window value
997 && window!=tcpd->fwd->window
998 && seq==tcpd->fwd->nextseq
999 && ack==tcpd->fwd->lastack
1000 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
1002 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1004 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
1009 * If we know the window scaling
1010 * and if this segment contains data and goes all the way to the
1011 * edge of the advertised window
1012 * then we mark it as WINDOW FULL
1013 * SYN/RST/FIN packets are never WINDOW FULL
1017 && tcpd->rev->win_scale!=-1
1018 && (seq+seglen)==(tcpd->rev->lastack+(tcpd->rev->window<<(tcpd->rev->win_scale==-2?0:tcpd->rev->win_scale)))
1019 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
1021 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1023 tcpd->ta->flags|=TCP_A_WINDOW_FULL;
1028 * It is a keepalive ack if it repeats the previous ACK and if
1029 * the last segment in the reverse direction was a keepalive
1034 && window==tcpd->fwd->window
1035 && seq==tcpd->fwd->nextseq
1036 && ack==tcpd->fwd->lastack
1037 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
1038 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
1040 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1042 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK;
1047 /* ZERO WINDOW PROBE ACK
1048 * It is a zerowindowprobe ack if it repeats the previous ACK and if
1049 * the last segment in the reverse direction was a zerowindowprobe
1050 * It also repeats the previous zero window indication
1055 && window==tcpd->fwd->window
1056 && seq==tcpd->fwd->nextseq
1057 && ack==tcpd->fwd->lastack
1058 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
1059 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
1061 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1063 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
1069 * It is a duplicate ack if window/seq/ack is the same as the previous
1070 * segment and if the segment length is 0
1074 && window==tcpd->fwd->window
1075 && seq==tcpd->fwd->nextseq
1076 && ack==tcpd->fwd->lastack
1077 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
1078 tcpd->fwd->dupacknum++;
1080 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1082 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
1083 tcpd->ta->dupack_num=tcpd->fwd->dupacknum;
1084 tcpd->ta->dupack_frame=tcpd->fwd->lastnondupack;
1090 /* If this was NOT a dupack we must reset the dupack counters */
1091 if( (!tcpd->ta) || !(tcpd->ta->flags&TCP_A_DUPLICATE_ACK) ) {
1092 tcpd->fwd->lastnondupack=pinfo->fd->num;
1093 tcpd->fwd->dupacknum=0;
1097 /* ACKED LOST PACKET
1098 * If this segment acks beyond the 'max seq to be acked' in the other direction
1099 * then that means we have missed packets going in the
1102 * We only check this if we have actually seen some seq numbers
1103 * in the other direction.
1105 if( tcpd->rev->maxseqtobeacked
1106 && GT_SEQ(ack, tcpd->rev->maxseqtobeacked )
1107 && (flags&(TH_ACK))!=0 ) {
1110 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1112 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
1113 /* update 'max seq to be acked' in the other direction so we don't get
1114 * this indication again.
1116 tcpd->rev->maxseqtobeacked=tcpd->rev->nextseq;
1120 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
1121 * If the segment contains data (or is a SYN or a FIN) and
1122 * if it does not advance the sequence number, it must be one
1124 * Only test for this if we know what the seq number should be
1125 * (tcpd->fwd->nextseq)
1127 * Note that a simple KeepAlive is not a retransmission
1129 if( (seglen>0 || flags&(TH_SYN|TH_FIN))
1130 && tcpd->fwd->nextseq
1131 && (LT_SEQ(seq, tcpd->fwd->nextseq)) ) {
1134 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ) {
1135 goto finished_checking_retransmission_type;
1138 /* If there were >=2 duplicate ACKs in the reverse direction
1139 * (there might be duplicate acks missing from the trace)
1140 * and if this sequence number matches those ACKs
1141 * and if the packet occurs within 20ms of the last
1143 * then this is a fast retransmission
1145 t=(pinfo->fd->abs_ts.secs-tcpd->rev->lastacktime.secs)*1000000000;
1146 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->rev->lastacktime.nsecs;
1147 if( tcpd->rev->dupacknum>=2
1148 && tcpd->rev->lastack==seq
1151 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1153 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
1154 goto finished_checking_retransmission_type;
1157 /* If the segment came <3ms since the segment with the highest
1158 * seen sequence number and it doesn't look like a retransmission
1159 * then it is an OUT-OF-ORDER segment.
1160 * (3ms is an arbitrary number)
1162 t=(pinfo->fd->abs_ts.secs-tcpd->fwd->nextseqtime.secs)*1000000000;
1163 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->fwd->nextseqtime.nsecs;
1165 && tcpd->fwd->nextseq != seq + seglen ) {
1167 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1169 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
1170 goto finished_checking_retransmission_type;
1173 /* Check for spurious retransmission. If the current seq + segment length
1174 * is less then the receivers lastask, the packet contains duplicated
1175 * data and may be considered spurious.
1177 if ( seq + seglen < tcpd->rev->lastack ) {
1179 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1181 tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION;
1182 goto finished_checking_retransmission_type;
1185 /* Then it has to be a generic retransmission */
1187 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1189 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
1190 nstime_delta(&tcpd->ta->rto_ts, &pinfo->fd->abs_ts, &tcpd->fwd->nextseqtime);
1191 tcpd->ta->rto_frame=tcpd->fwd->nextseqframe;
1194 finished_checking_retransmission_type:
1196 nextseq = seq+seglen;
1197 if (seglen || flags&(TH_SYN|TH_FIN)) {
1198 /* add this new sequence number to the fwd list */
1199 ual = wmem_new(wmem_file_scope(), tcp_unacked_t);
1200 ual->next=tcpd->fwd->segments;
1201 tcpd->fwd->segments=ual;
1202 ual->frame=pinfo->fd->num;
1204 ual->ts=pinfo->fd->abs_ts;
1206 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
1207 if( (flags&(TH_SYN|TH_FIN)) ) {
1210 ual->nextseq=nextseq;
1213 /* Store the highest number seen so far for nextseq so we can detect
1214 * when we receive segments that arrive with a "hole"
1215 * If we don't have anything since before, just store what we got.
1216 * ZeroWindowProbes are special and don't really advance the nextseq
1218 if(GT_SEQ(nextseq, tcpd->fwd->nextseq) || !tcpd->fwd->nextseq) {
1219 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
1220 tcpd->fwd->nextseq=nextseq;
1221 tcpd->fwd->nextseqframe=pinfo->fd->num;
1222 tcpd->fwd->nextseqtime.secs=pinfo->fd->abs_ts.secs;
1223 tcpd->fwd->nextseqtime.nsecs=pinfo->fd->abs_ts.nsecs;
1227 /* Store the highest continuous seq number seen so far for 'max seq to be acked',
1228 so we can detect TCP_A_ACK_LOST_PACKET condition
1230 if(EQ_SEQ(seq, tcpd->fwd->maxseqtobeacked) || !tcpd->fwd->maxseqtobeacked) {
1231 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
1232 tcpd->fwd->maxseqtobeacked=tcpd->fwd->nextseq;
1237 /* remember what the ack/window is so we can track window updates and retransmissions */
1238 tcpd->fwd->window=window;
1239 tcpd->fwd->lastack=ack;
1240 tcpd->fwd->lastacktime.secs=pinfo->fd->abs_ts.secs;
1241 tcpd->fwd->lastacktime.nsecs=pinfo->fd->abs_ts.nsecs;
1244 /* if there were any flags set for this segment we need to remember them
1245 * we only remember the flags for the very last segment though.
1248 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;
1250 tcpd->fwd->lastsegmentflags=0;
1254 /* remove all segments this ACKs and we don't need to keep around any more
1258 ual = tcpd->rev->segments;
1260 tcp_unacked_t *tmpual;
1262 /* If this ack matches the segment, process accordingly */
1263 if(ack==ual->nextseq) {
1264 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1265 tcpd->ta->frame_acked=ual->frame;
1266 nstime_delta(&tcpd->ta->ts, &pinfo->fd->abs_ts, &ual->ts);
1268 /* If this acknowledges part of the segment, adjust the segment info for the acked part */
1269 else if (GT_SEQ(ack, ual->seq) && LE_SEQ(ack, ual->nextseq)) {
1273 /* If this acknowledges a segment prior to this one, leave this segment alone and move on */
1274 else if (GT_SEQ(ual->nextseq,ack)) {
1280 /* This segment is old, or an exact match. Delete the segment from the list */
1284 if (tcpd->rev->scps_capable) {
1285 /* Track largest segment successfully sent for SNACK analysis*/
1286 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) {
1287 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);
1292 tcpd->rev->segments = tmpual;
1295 prevual->next = tmpual;
1297 wmem_free(wmem_file_scope(), ual);
1301 /* how many bytes of data are there in flight after this frame
1304 ual=tcpd->fwd->segments;
1305 if (tcp_track_bytes_in_flight && seglen!=0 && ual && tcpd->fwd->valid_bif) {
1306 guint32 first_seq, last_seq, in_flight;
1308 first_seq = ual->seq - tcpd->fwd->base_seq;
1309 last_seq = ual->nextseq - tcpd->fwd->base_seq;
1311 if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) {
1312 last_seq = ual->nextseq-tcpd->fwd->base_seq;
1314 if ((ual->seq-tcpd->fwd->base_seq)<first_seq) {
1315 first_seq = ual->seq-tcpd->fwd->base_seq;
1319 in_flight = last_seq-first_seq;
1321 if (in_flight>0 && in_flight<2000000000) {
1323 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1325 tcpd->ta->bytes_in_flight = in_flight;
1332 * Prints results of the sequence number analysis concerning tcp segments
1333 * retransmitted or out-of-order
1336 tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,
1338 proto_tree * flags_tree, proto_item * flags_item,
1339 struct tcp_acked *ta
1342 /* TCP Retransmission */
1343 if (ta->flags & TCP_A_RETRANSMISSION) {
1344 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
1346 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
1348 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {
1349 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
1350 tvb, 0, 0, &ta->rto_ts);
1351 PROTO_ITEM_SET_GENERATED(flags_item);
1352 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,
1353 tvb, 0, 0, ta->rto_frame);
1354 PROTO_ITEM_SET_GENERATED(flags_item);
1357 /* TCP Fast Retransmission */
1358 if (ta->flags & TCP_A_FAST_RETRANSMISSION) {
1359 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_fast_retransmission);
1360 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
1361 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1362 "[TCP Fast Retransmission] ");
1364 /* TCP Spurious Retransmission */
1365 if (ta->flags & TCP_A_SPURIOUS_RETRANSMISSION) {
1366 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_spurious_retransmission);
1367 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
1368 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1369 "[TCP Spurious Retransmission] ");
1372 /* TCP Out-Of-Order */
1373 if (ta->flags & TCP_A_OUT_OF_ORDER) {
1374 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_out_of_order);
1375 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
1379 /* Prints results of the sequence number analysis concerning reused ports */
1381 tcp_sequence_number_analysis_print_reused(packet_info * pinfo,
1382 proto_item * flags_item,
1383 struct tcp_acked *ta
1386 /* TCP Ports Reused */
1387 if (ta->flags & TCP_A_REUSED_PORTS) {
1388 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_reused_ports);
1389 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1390 "[TCP Port numbers reused] ");
1394 /* Prints results of the sequence number analysis concerning lost tcp segments */
1396 tcp_sequence_number_analysis_print_lost(packet_info * pinfo,
1397 proto_item * flags_item,
1398 struct tcp_acked *ta
1401 /* TCP Lost Segment */
1402 if (ta->flags & TCP_A_LOST_PACKET) {
1403 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_lost_packet);
1404 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1405 "[TCP Previous segment not captured] ");
1407 /* TCP Ack lost segment */
1408 if (ta->flags & TCP_A_ACK_LOST_PACKET) {
1409 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_ack_lost_packet);
1410 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1411 "[TCP ACKed unseen segment] ");
1415 /* Prints results of the sequence number analysis concerning tcp window */
1417 tcp_sequence_number_analysis_print_window(packet_info * pinfo,
1418 proto_item * flags_item,
1419 struct tcp_acked *ta
1422 /* TCP Window Update */
1423 if (ta->flags & TCP_A_WINDOW_UPDATE) {
1424 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_update);
1425 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
1427 /* TCP Full Window */
1428 if (ta->flags & TCP_A_WINDOW_FULL) {
1429 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_full);
1430 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
1434 /* Prints results of the sequence number analysis concerning tcp keepalive */
1436 tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,
1437 proto_item * flags_item,
1438 struct tcp_acked *ta
1442 if (ta->flags & TCP_A_KEEP_ALIVE) {
1443 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive);
1444 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
1446 /* TCP Ack Keep Alive */
1447 if (ta->flags & TCP_A_KEEP_ALIVE_ACK) {
1448 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive_ack);
1449 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
1453 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
1455 tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,
1457 proto_tree * flags_tree,
1458 struct tcp_acked *ta,
1462 proto_item * flags_item;
1464 /* TCP Duplicate ACK */
1465 if (ta->dupack_num) {
1466 if (ta->flags & TCP_A_DUPLICATE_ACK ) {
1467 flags_item=proto_tree_add_none_format(flags_tree,
1468 hf_tcp_analysis_duplicate_ack,
1470 "This is a TCP duplicate ack"
1472 PROTO_ITEM_SET_GENERATED(flags_item);
1473 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1474 "[TCP Dup ACK %u#%u] ",
1480 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
1481 tvb, 0, 0, ta->dupack_num);
1482 PROTO_ITEM_SET_GENERATED(flags_item);
1483 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
1484 tvb, 0, 0, ta->dupack_frame);
1485 PROTO_ITEM_SET_GENERATED(flags_item);
1486 expert_add_info_format(pinfo, flags_item, &ei_tcp_analysis_duplicate_ack, "Duplicate ACK (#%u)", ta->dupack_num);
1490 /* Prints results of the sequence number analysis concerning tcp zero window */
1492 tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,
1493 proto_item * flags_item,
1494 struct tcp_acked *ta
1497 /* TCP Zero Window Probe */
1498 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE) {
1499 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe);
1500 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
1502 /* TCP Zero Window */
1503 if (ta->flags&TCP_A_ZERO_WINDOW) {
1504 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window);
1505 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
1507 /* TCP Zero Window Probe Ack */
1508 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK) {
1509 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe_ack);
1510 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1511 "[TCP ZeroWindowProbeAck] ");
1516 /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */
1518 tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U_,
1520 proto_tree * flags_tree _U_,
1521 struct tcp_acked *ta
1524 proto_item * flags_item;
1526 if (tcp_track_bytes_in_flight) {
1527 flags_item=proto_tree_add_uint(flags_tree,
1528 hf_tcp_analysis_bytes_in_flight,
1529 tvb, 0, 0, ta->bytes_in_flight);
1531 PROTO_ITEM_SET_GENERATED(flags_item);
1536 tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree,
1537 struct tcp_analysis *tcpd, guint32 seq, guint32 ack)
1539 struct tcp_acked *ta = NULL;
1542 proto_tree *flags_tree=NULL;
1548 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, FALSE, tcpd);
1555 item=proto_tree_add_item(parent_tree, hf_tcp_analysis, tvb, 0, 0, ENC_NA);
1556 PROTO_ITEM_SET_GENERATED(item);
1557 tree=proto_item_add_subtree(item, ett_tcp_analysis);
1559 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
1560 data we actually have */
1561 if(ta->frame_acked) {
1562 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
1563 tvb, 0, 0, ta->frame_acked);
1564 PROTO_ITEM_SET_GENERATED(item);
1566 /* only display RTT if we actually have something we are acking */
1567 if( ta->ts.secs || ta->ts.nsecs ) {
1568 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
1569 tvb, 0, 0, &ta->ts);
1570 PROTO_ITEM_SET_GENERATED(item);
1574 if(ta->bytes_in_flight) {
1575 /* print results for amount of data in flight */
1576 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta);
1580 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, 0, ENC_NA);
1581 PROTO_ITEM_SET_GENERATED(item);
1582 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);
1584 /* print results for reused tcp ports */
1585 tcp_sequence_number_analysis_print_reused(pinfo, item, ta);
1587 /* print results for retransmission and out-of-order segments */
1588 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, item, ta);
1590 /* print results for lost tcp segments */
1591 tcp_sequence_number_analysis_print_lost(pinfo, item, ta);
1593 /* print results for tcp window information */
1594 tcp_sequence_number_analysis_print_window(pinfo, item, ta);
1596 /* print results for tcp keep alive information */
1597 tcp_sequence_number_analysis_print_keepalive(pinfo, item, ta);
1599 /* print results for tcp duplicate acks */
1600 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);
1602 /* print results for tcp zero window */
1603 tcp_sequence_number_analysis_print_zero_window(pinfo, item, ta);
1610 print_tcp_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *tcp_tree, packet_info *pinfo, tvbuff_t *next_tvb)
1612 proto_item *tcp_tree_item, *frag_tree_item;
1615 * The subdissector thought it was completely
1616 * desegmented (although the stuff at the
1617 * end may, in turn, require desegmentation),
1618 * so we show a tree with all segments.
1620 show_fragment_tree(ipfd_head, &tcp_segment_items,
1621 tree, pinfo, next_tvb, &frag_tree_item);
1623 * The toplevel fragment subtree is now
1624 * behind all desegmented data; move it
1625 * right behind the TCP tree.
1627 tcp_tree_item = proto_tree_get_parent(tcp_tree);
1628 if(frag_tree_item && tcp_tree_item) {
1629 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);
1633 /* **************************************************************************
1634 * End of tcp sequence number analysis
1635 * **************************************************************************/
1638 /* Minimum TCP header length. */
1639 #define TCPH_MIN_LEN 20
1641 /* Desegmentation of TCP streams */
1642 static reassembly_table tcp_reassembly_table;
1644 /* functions to trace tcp segments */
1645 /* Enable desegmenting of TCP streams */
1646 static gboolean tcp_desegment = TRUE;
1649 desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
1650 guint32 seq, guint32 nxtseq,
1651 guint32 sport, guint32 dport,
1652 proto_tree *tree, proto_tree *tcp_tree,
1653 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
1655 fragment_head *ipfd_head;
1656 int last_fragment_len;
1657 gboolean must_desegment;
1658 gboolean called_dissector;
1659 int another_pdu_follows;
1664 struct tcp_multisegment_pdu *msp;
1665 gboolean cleared_writable = col_get_writable(pinfo->cinfo);
1669 last_fragment_len = 0;
1670 must_desegment = FALSE;
1671 called_dissector = FALSE;
1672 another_pdu_follows = 0;
1676 * Initialize these to assume no desegmentation.
1677 * If that's not the case, these will be set appropriately
1678 * by the subdissector.
1680 pinfo->desegment_offset = 0;
1681 pinfo->desegment_len = 0;
1684 * Initialize this to assume that this segment will just be
1685 * added to the middle of a desegmented chunk of data, so
1686 * that we should show it all as data.
1687 * If that's not the case, it will be set appropriately.
1689 deseg_offset = offset;
1692 /* Have we seen this PDU before (and is it the start of a multi-
1695 if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, seq))) {
1698 /* Yes. This could be because we've dissected this frame before
1699 * or because this is a retransmission of a previously-seen
1700 * segment. Either way, we don't need to hand it off to the
1701 * subdissector and we certainly don't want to re-add it to the
1702 * multisegment_pdus list: if we did, subsequent lookups would
1703 * find this retransmission instead of the original transmission
1704 * (breaking desegmentation if we'd already linked other segments
1705 * to the original transmission's entry).
1708 if (msp->first_frame == PINFO_FD_NUM(pinfo)) {
1710 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
1712 str = "Retransmitted ";
1713 /* TCP analysis already flags this (in COL_INFO) as a retransmission--if it's enabled */
1716 nbytes = MAX(0, tvb_reported_length_remaining(tvb, offset));
1717 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
1718 nbytes, NULL, "%sTCP segment data (%u byte%s)", str, nbytes,
1719 plurality(nbytes, "", "s"));
1723 /* Else, find the most previous PDU starting before this sequence number */
1724 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);
1727 if (msp && msp->seq <= seq && msp->nxtpdu > seq) {
1730 if (!PINFO_FD_VISITED(pinfo)) {
1731 msp->last_frame=pinfo->fd->num;
1732 msp->last_frame_time=pinfo->fd->abs_ts;
1735 /* OK, this PDU was found, which means the segment continues
1736 * a higher-level PDU and that we must desegment it.
1738 if (msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
1739 /* The dissector asked for the entire segment */
1740 len = MAX(0, tvb_length_remaining(tvb, offset));
1742 len = MIN(nxtseq, msp->nxtpdu) - seq;
1744 last_fragment_len = len;
1746 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,
1747 pinfo, msp->first_frame, NULL,
1748 seq - msp->seq, len,
1749 (LT_SEQ (nxtseq,msp->nxtpdu)) );
1751 if (!PINFO_FD_VISITED(pinfo)
1752 && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
1753 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
1755 /* If we consumed the entire segment there is no
1756 * other pdu starting anywhere inside this segment.
1757 * So update nxtpdu to point at least to the start
1758 * of the next segment.
1759 * (If the subdissector asks for even more data we
1760 * will advance nxtpdu even further later down in
1763 msp->nxtpdu = nxtseq;
1766 if( (msp->nxtpdu < nxtseq)
1767 && (msp->nxtpdu >= seq)
1769 another_pdu_follows=msp->nxtpdu - seq;
1772 /* This segment was not found in our table, so it doesn't
1773 * contain a continuation of a higher-level PDU.
1774 * Call the normal subdissector.
1778 * Supply the sequence number of this segment. We set this here
1779 * because this segment could be after another in the same packet,
1780 * in which case seq was incremented at the end of the loop.
1784 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
1785 sport, dport, 0, 0, FALSE, tcpd, tcpinfo);
1786 called_dissector = TRUE;
1788 /* Did the subdissector ask us to desegment some more data
1789 * before it could handle the packet?
1790 * If so we have to create some structures in our table but
1791 * this is something we only do the first time we see this
1794 if(pinfo->desegment_len) {
1795 if (!PINFO_FD_VISITED(pinfo))
1796 must_desegment = TRUE;
1799 * Set "deseg_offset" to the offset in "tvb"
1800 * of the first byte of data that the
1801 * subdissector didn't process.
1803 deseg_offset = offset + pinfo->desegment_offset;
1806 /* Either no desegmentation is necessary, or this is
1807 * segment contains the beginning but not the end of
1808 * a higher-level PDU and thus isn't completely
1815 /* is it completely desegmented? */
1818 * Yes, we think it is.
1819 * We only call subdissector for the last segment.
1820 * Note that the last segment may include more than what
1823 if(ipfd_head->reassembled_in == pinfo->fd->num) {
1825 * OK, this is the last segment.
1826 * Let's call the subdissector with the desegmented
1832 /* create a new TVB structure for desegmented data */
1833 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
1835 /* add desegmented data to the data source list */
1836 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
1839 * Supply the sequence number of the first of the
1840 * reassembled bytes.
1842 tcpinfo->seq = msp->seq;
1844 /* indicate that this is reassembled data */
1845 tcpinfo->is_reassembled = TRUE;
1847 /* call subdissector */
1848 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, sport,
1849 dport, 0, 0, FALSE, tcpd, tcpinfo);
1850 called_dissector = TRUE;
1853 * OK, did the subdissector think it was completely
1854 * desegmented, or does it think we need even more
1857 old_len = (int)(tvb_reported_length(next_tvb) - last_fragment_len);
1858 if (pinfo->desegment_len &&
1859 pinfo->desegment_offset<=old_len) {
1861 * "desegment_len" isn't 0, so it needs more
1862 * data for something - and "desegment_offset"
1863 * is before "old_len", so it needs more data
1864 * to dissect the stuff we thought was
1865 * completely desegmented (as opposed to the
1866 * stuff at the beginning being completely
1867 * desegmented, but the stuff at the end
1868 * being a new higher-level PDU that also
1869 * needs desegmentation).
1871 fragment_set_partial_reassembly(&tcp_reassembly_table,
1872 pinfo, msp->first_frame, NULL);
1874 /* Update msp->nxtpdu to point to the new next
1877 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1878 /* We want reassembly of at least one
1879 * more segment so set the nxtpdu
1880 * boundary to one byte into the next
1882 * This means that the next segment
1883 * will complete reassembly even if it
1884 * is only one single byte in length.
1886 msp->nxtpdu = seq + MAX(0, tvb_reported_length_remaining(tvb, offset)) + 1;
1887 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1888 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
1889 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1891 msp->nxtpdu=seq + last_fragment_len + pinfo->desegment_len;
1894 /* Since we need at least some more data
1895 * there can be no pdu following in the
1896 * tail of this segment.
1898 another_pdu_follows = 0;
1899 offset += last_fragment_len;
1900 seq += last_fragment_len;
1901 if (tvb_length_remaining(tvb, offset) > 0)
1905 * Show the stuff in this TCP segment as
1906 * just raw TCP segment data.
1908 nbytes = another_pdu_follows > 0
1909 ? another_pdu_follows
1910 : MAX(0, tvb_reported_length_remaining(tvb, offset));
1911 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
1912 nbytes, NULL, "TCP segment data (%u byte%s)", nbytes,
1913 plurality(nbytes, "", "s"));
1915 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
1917 /* Did the subdissector ask us to desegment
1918 * some more data? This means that the data
1919 * at the beginning of this segment completed
1920 * a higher-level PDU, but the data at the
1921 * end of this segment started a higher-level
1922 * PDU but didn't complete it.
1924 * If so, we have to create some structures
1925 * in our table, but this is something we
1926 * only do the first time we see this packet.
1928 if(pinfo->desegment_len) {
1929 if (!PINFO_FD_VISITED(pinfo))
1930 must_desegment = TRUE;
1932 /* The stuff we couldn't dissect
1933 * must have come from this segment,
1934 * so it's all in "tvb".
1936 * "pinfo->desegment_offset" is
1937 * relative to the beginning of
1938 * "next_tvb"; we want an offset
1939 * relative to the beginning of "tvb".
1941 * First, compute the offset relative
1942 * to the *end* of "next_tvb" - i.e.,
1943 * the number of bytes before the end
1944 * of "next_tvb" at which the
1945 * subdissector stopped. That's the
1946 * length of "next_tvb" minus the
1947 * offset, relative to the beginning
1948 * of "next_tvb, at which the
1949 * subdissector stopped.
1951 deseg_offset = ipfd_head->datalen - pinfo->desegment_offset;
1953 /* "tvb" and "next_tvb" end at the
1954 * same byte of data, so the offset
1955 * relative to the end of "next_tvb"
1956 * of the byte at which we stopped
1957 * is also the offset relative to
1958 * the end of "tvb" of the byte at
1961 * Convert that back into an offset
1962 * relative to the beginning of
1963 * "tvb", by taking the length of
1964 * "tvb" and subtracting the offset
1965 * relative to the end.
1967 deseg_offset = tvb_reported_length(tvb) - deseg_offset;
1973 if (must_desegment) {
1974 /* If the dissector requested "reassemble until FIN"
1975 * just set this flag for the flow and let reassembly
1976 * proceed at normal. We will check/pick up these
1977 * reassembled PDUs later down in dissect_tcp() when checking
1980 if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
1981 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1984 * The sequence number at which the stuff to be desegmented
1985 * starts is the sequence number of the byte at an offset
1986 * of "deseg_offset" into "tvb".
1988 * The sequence number of the byte at an offset of "offset"
1989 * is "seq", i.e. the starting sequence number of this
1990 * segment, so the sequence number of the byte at
1991 * "deseg_offset" is "seq + (deseg_offset - offset)".
1993 deseg_seq = seq + (deseg_offset - offset);
1995 if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)
1996 && (!PINFO_FD_VISITED(pinfo))) {
1997 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1998 /* The subdissector asked to reassemble using the
1999 * entire next segment.
2000 * Just ask reassembly for one more byte
2001 * but set this msp flag so we can pick it up
2004 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
2005 nxtseq+1, tcpd->fwd->multisegment_pdus);
2006 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
2008 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
2009 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
2012 /* add this segment as the first one for this new pdu */
2013 fragment_add(&tcp_reassembly_table, tvb, deseg_offset,
2014 pinfo, msp->first_frame, NULL,
2015 0, nxtseq - deseg_seq,
2016 LT_SEQ(nxtseq, msp->nxtpdu));
2020 if (!called_dissector || pinfo->desegment_len != 0) {
2021 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
2022 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
2024 * We know what frame this PDU is reassembled in;
2025 * let the user know.
2027 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,
2028 0, ipfd_head->reassembled_in);
2029 PROTO_ITEM_SET_GENERATED(item);
2033 * Either we didn't call the subdissector at all (i.e.,
2034 * this is a segment that contains the middle of a
2035 * higher-level PDU, but contains neither the beginning
2036 * nor the end), or the subdissector couldn't dissect it
2037 * all, as some data was missing (i.e., it set
2038 * "pinfo->desegment_len" to the amount of additional
2041 if (pinfo->desegment_offset == 0) {
2043 * It couldn't, in fact, dissect any of it (the
2044 * first byte it couldn't dissect is at an offset
2045 * of "pinfo->desegment_offset" from the beginning
2046 * of the payload, and that's 0).
2047 * Just mark this as TCP.
2049 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
2050 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
2054 * Show what's left in the packet as just raw TCP segment
2056 * XXX - remember what protocol the last subdissector
2057 * was, and report it as a continuation of that, instead?
2059 nbytes = MAX(0, tvb_reported_length_remaining(tvb, deseg_offset));
2060 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, deseg_offset,
2061 -1, NULL, "TCP segment data (%u byte%s)", nbytes,
2062 plurality(nbytes, "", "s"));
2064 pinfo->can_desegment = 0;
2065 pinfo->desegment_offset = 0;
2066 pinfo->desegment_len = 0;
2068 if(another_pdu_follows) {
2069 /* there was another pdu following this one. */
2070 pinfo->can_desegment = 2;
2071 /* we also have to prevent the dissector from changing the
2072 * PROTOCOL and INFO columns since what follows may be an
2073 * incomplete PDU and we don't want it be changed back from
2074 * <Protocol> to <TCP>
2075 * XXX There is no good way to block the PROTOCOL column
2076 * from being changed yet so we set the entire row unwritable.
2077 * The flag cleared_writable stores the initial state.
2079 col_set_fence(pinfo->cinfo, COL_INFO);
2080 cleared_writable |= col_get_writable(pinfo->cinfo);
2081 col_set_writable(pinfo->cinfo, FALSE);
2082 offset += another_pdu_follows;
2083 seq += another_pdu_follows;
2086 /* remove any blocking set above otherwise the
2087 * proto,colinfo tap will break
2089 if(cleared_writable) {
2090 col_set_writable(pinfo->cinfo, TRUE);
2096 * Loop for dissecting PDUs within a TCP stream; assumes that a PDU
2097 * consists of a fixed-length chunk of data that contains enough information
2098 * to determine the length of the PDU, followed by rest of the PDU.
2100 * The first three arguments are the arguments passed to the dissector
2101 * that calls this routine.
2103 * "proto_desegment" is the dissector's flag controlling whether it should
2104 * desegment PDUs that cross TCP segment boundaries.
2106 * "fixed_len" is the length of the fixed-length part of the PDU.
2108 * "get_pdu_len()" is a routine called to get the length of the PDU from
2109 * the fixed-length part of the PDU; it's passed "pinfo", "tvb" and "offset".
2111 * "dissect_pdu()" is the routine to dissect a PDU.
2114 tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2115 gboolean proto_desegment, guint fixed_len,
2116 guint (*get_pdu_len)(packet_info *, tvbuff_t *, int),
2117 new_dissector_t dissect_pdu, void* dissector_data)
2119 volatile int offset = 0;
2121 guint length_remaining;
2125 proto_item *item=NULL;
2128 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2130 * We use "tvb_ensure_length_remaining()" to make sure there actually
2131 * *is* data remaining. The protocol we're handling could conceivably
2132 * consists of a sequence of fixed-length PDUs, and therefore the
2133 * "get_pdu_len" routine might not actually fetch anything from
2134 * the tvbuff, and thus might not cause an exception to be thrown if
2135 * we've run past the end of the tvbuff.
2137 * This means we're guaranteed that "length_remaining" is positive.
2139 length_remaining = tvb_ensure_length_remaining(tvb, offset);
2142 * Can we do reassembly?
2144 if (proto_desegment && pinfo->can_desegment) {
2146 * Yes - is the fixed-length part of the PDU split across segment
2149 if (length_remaining < fixed_len) {
2151 * Yes. Tell the TCP dissector where the data for this message
2152 * starts in the data it handed us and that we need "some more
2153 * data." Don't tell it exactly how many bytes we need because
2154 * if/when we ask for even more (after the header) that will
2157 pinfo->desegment_offset = offset;
2158 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
2164 * Get the length of the PDU.
2166 plen = (*get_pdu_len)(pinfo, tvb, offset);
2167 if (plen < fixed_len) {
2171 * 1) the length value extracted from the fixed-length portion
2172 * doesn't include the fixed-length portion's length, and
2173 * was so large that, when the fixed-length portion's
2174 * length was added to it, the total length overflowed;
2176 * 2) the length value extracted from the fixed-length portion
2177 * includes the fixed-length portion's length, and the value
2178 * was less than the fixed-length portion's length, i.e. it
2181 * Report this as a bounds error.
2183 show_reported_bounds_error(tvb, pinfo, tree);
2187 /* give a hint to TCP where the next PDU starts
2188 * so that it can attempt to find it in case it starts
2189 * somewhere in the middle of a segment.
2191 if(!pinfo->fd->flags.visited && tcp_analyze_seq) {
2192 guint remaining_bytes;
2193 remaining_bytes = MAX(0, tvb_reported_length_remaining(tvb, offset));
2194 if(plen>remaining_bytes) {
2195 pinfo->want_pdu_tracking=2;
2196 pinfo->bytes_until_next_pdu=plen-remaining_bytes;
2201 * Can we do reassembly?
2203 if (proto_desegment && pinfo->can_desegment) {
2205 * Yes - is the PDU split across segment boundaries?
2207 if (length_remaining < plen) {
2209 * Yes. Tell the TCP dissector where the data for this message
2210 * starts in the data it handed us, and how many more bytes we
2213 pinfo->desegment_offset = offset;
2214 pinfo->desegment_len = plen - length_remaining;
2220 * Do not display the the PDU length if it crosses the boundary of the
2221 * packet and no more packets are available.
2223 * XXX - we don't necessarily know whether more packets are
2224 * available; we might be doing a one-pass read through the
2225 * capture in TShark, or we might be doing a live capture in
2229 if (length_remaining >= plen || there are more packets)
2233 * Display the PDU length as a field
2235 item=proto_tree_add_uint(tree ? tree->last_child : NULL,
2237 tvb, offset, plen, plen);
2238 PROTO_ITEM_SET_GENERATED(item);
2241 item = proto_tree_add_text(tree ? tree->last_child : NULL, tvb, offset, -1,
2242 "PDU Size: %u cut short at %u",plen,length_remaining);
2243 PROTO_ITEM_SET_GENERATED(item);
2248 * Construct a tvbuff containing the amount of the payload we have
2249 * available. Make its reported length the amount of data in the PDU.
2251 length = length_remaining;
2254 next_tvb = tvb_new_subset(tvb, offset, length, plen);
2259 * If it gets an error that means there's no point in
2260 * dissecting any more PDUs, rethrow the exception in
2263 * If it gets any other error, report it and continue, as that
2264 * means that PDU got an error, but that doesn't mean we should
2265 * stop dissecting PDUs within this frame or chunk of reassembled
2268 pd_save = pinfo->private_data;
2270 (*dissect_pdu)(next_tvb, pinfo, tree, dissector_data);
2272 CATCH_NONFATAL_ERRORS {
2273 /* Restore the private_data structure in case one of the
2274 * called dissectors modified it (and, due to the exception,
2275 * was unable to restore it).
2277 pinfo->private_data = pd_save;
2278 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2283 * Step to the next PDU.
2284 * Make sure we don't overflow.
2286 offset_before = offset;
2288 if (offset <= offset_before)
2294 tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val)
2296 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%u", abbrev, val);
2300 dissect_tcpopt_exp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2301 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2304 proto_tree *exp_tree;
2305 proto_item *hidden_item;
2308 item = proto_tree_add_item(opt_tree, hf_tcp_option_exp, tvb,
2309 offset, optlen, ENC_NA);
2310 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);
2311 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
2312 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2313 if (tcp_exp_options_with_magic && ((optlen - 2) > 0)) {
2314 magic = tvb_get_ntohs(tvb, offset + 2);
2315 proto_tree_add_item(exp_tree, hf_tcp_option_exp_magic_number, tvb,
2316 offset + 2, 2, ENC_BIG_ENDIAN);
2319 /* FF: draft-ietf-tcpm-fastopen-02, TCP Fast Open */
2320 hidden_item = proto_tree_add_item(exp_tree, hf_tcp_option_fast_open,
2321 tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2322 PROTO_ITEM_SET_HIDDEN(hidden_item);
2323 if ((optlen - 2) == 2) {
2324 /* Fast Open Cookie Request */
2325 proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie_request,
2326 tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2327 col_append_str(pinfo->cinfo, COL_INFO, " TFO=R");
2328 } else if ((optlen - 2) > 2) {
2329 /* Fast Open Cookie */
2330 proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie,
2331 tvb, offset + 4, optlen - 4, ENC_NA);
2332 col_append_str(pinfo->cinfo, COL_INFO, " TFO=C");
2336 /* Unknown magic number */
2340 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,
2341 offset + 2, optlen - 2, ENC_NA);
2342 tcp_info_append_uint(pinfo, "Expxx", TRUE);
2347 dissect_tcpopt_sack_perm(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2348 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2351 proto_tree *exp_tree;
2353 item = proto_tree_add_boolean(opt_tree, hf_tcp_option_sack_perm, tvb, offset,
2355 exp_tree = proto_item_add_subtree(item, ett_tcp_option_sack_perm);
2356 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
2357 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2358 tcp_info_append_uint(pinfo, "SACK_PERM", TRUE);
2362 dissect_tcpopt_mss(const ip_tcp_opt *optp, tvbuff_t *tvb,
2363 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2366 proto_tree *exp_tree;
2369 mss = tvb_get_ntohs(tvb, offset + 2);
2370 item = proto_tree_add_none_format(opt_tree, hf_tcp_option_mss, tvb, offset,
2371 optlen, "%s: %u bytes", optp->name, mss);
2372 exp_tree = proto_item_add_subtree(item, ett_tcp_option_mss);
2373 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
2374 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2375 proto_tree_add_item(exp_tree, hf_tcp_option_mss_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2376 tcp_info_append_uint(pinfo, "MSS", mss);
2379 /* The window scale extension is defined in RFC 1323 */
2381 dissect_tcpopt_wscale(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2382 int offset, guint optlen _U_, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2385 proto_item *wscale_pi, *gen_pi;
2386 proto_tree *wscale_tree;
2387 struct tcp_analysis *tcpd=NULL;
2389 tcpd=get_tcp_conversation_data(NULL,pinfo);
2391 wscale_pi = proto_tree_add_text(opt_tree, tvb, offset, 3, "Window scale: ");
2392 wscale_tree = proto_item_add_subtree(wscale_pi, ett_tcp_option_wscale);
2394 proto_tree_add_item(wscale_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_NA);
2397 proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_NA);
2400 proto_tree_add_item(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1,
2402 shift = tvb_get_guint8(tvb, offset);
2404 gen_pi = proto_tree_add_uint(wscale_tree, hf_tcp_option_wscale_multiplier, tvb,
2405 offset, 1, 1 << shift);
2406 PROTO_ITEM_SET_GENERATED(gen_pi);
2407 val = tvb_get_guint8(tvb, offset);
2409 proto_item_append_text(wscale_pi, "%u (multiply by %u)", val, 1 << shift);
2411 tcp_info_append_uint(pinfo, "WS", 1 << shift);
2413 if(!pinfo->fd->flags.visited) {
2414 pdu_store_window_scale_option(shift, tcpd);
2419 dissect_tcpopt_sack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2420 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data)
2422 proto_tree *field_tree = NULL;
2423 proto_item *tf=NULL;
2424 proto_item *hidden_item;
2425 guint32 leftedge, rightedge;
2426 struct tcp_analysis *tcpd=NULL;
2427 struct tcpheader *tcph = (struct tcpheader *)data;
2429 guint num_sack_ranges = 0;
2431 if(tcp_analyze_seq && tcp_relative_seq) {
2432 /* find(or create if needed) the conversation for this tcp session */
2433 tcpd=get_tcp_conversation_data(NULL,pinfo);
2436 base_ack=tcpd->rev->base_seq;
2440 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2441 offset, 1, ENC_BIG_ENDIAN);
2442 PROTO_ITEM_SET_HIDDEN(hidden_item);
2443 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2444 offset + 1, 1, ENC_BIG_ENDIAN);
2445 PROTO_ITEM_SET_HIDDEN(hidden_item);
2447 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
2448 offset += 2; /* skip past type and length */
2449 optlen -= 2; /* subtract size of type and length */
2450 while (optlen > 0) {
2451 if (field_tree == NULL) {
2452 /* Haven't yet made a subtree out of this option. Do so. */
2453 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2454 hidden_item = proto_tree_add_boolean(field_tree, hf_tcp_option_sack, tvb,
2455 offset, optlen, TRUE);
2456 PROTO_ITEM_SET_HIDDEN(hidden_item);
2459 proto_tree_add_text(field_tree, tvb, offset, optlen,
2460 "(suboption would go past end of option)");
2463 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;
2464 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
2465 offset, 4, leftedge,
2466 "left edge = %u%s", leftedge,
2467 tcp_relative_seq ? " (relative)" : "");
2471 proto_tree_add_text(field_tree, tvb, offset, optlen,
2472 "(suboption would go past end of option)");
2475 /* XXX - check whether it goes past end of packet */
2476 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;
2478 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
2479 offset+4, 4, rightedge,
2480 "right edge = %u%s", rightedge,
2481 tcp_relative_seq ? " (relative)" : "");
2482 tcp_info_append_uint(pinfo, "SLE", leftedge);
2483 tcp_info_append_uint(pinfo, "SRE", rightedge);
2486 /* Update tap info */
2487 if (tcph != NULL && (tcph->num_sack_ranges < MAX_TCP_SACK_RANGES)) {
2488 tcph->sack_left_edge[tcph->num_sack_ranges] = leftedge;
2489 tcph->sack_right_edge[tcph->num_sack_ranges] = rightedge;
2490 tcph->num_sack_ranges++;
2493 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);
2497 /* Show number of SACK ranges in this option as a generated field */
2498 tf = proto_tree_add_uint(field_tree, hf_tcp_option_sack_range_count,
2499 tvb, 0, 0, num_sack_ranges);
2500 PROTO_ITEM_SET_GENERATED(tf);
2504 dissect_tcpopt_echo(const ip_tcp_opt *optp, tvbuff_t *tvb,
2505 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2507 proto_item *hidden_item;
2510 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2511 offset, 1, ENC_BIG_ENDIAN);
2512 PROTO_ITEM_SET_HIDDEN(hidden_item);
2513 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2514 offset + 1, 1, ENC_BIG_ENDIAN);
2515 PROTO_ITEM_SET_HIDDEN(hidden_item);
2517 echo = tvb_get_ntohl(tvb, offset + 2);
2518 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_echo, tvb, offset,
2520 PROTO_ITEM_SET_HIDDEN(hidden_item);
2521 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2522 "%s: %u", optp->name, echo);
2523 tcp_info_append_uint(pinfo, "ECHO", echo);
2526 /* If set, do not put the TCP timestamp information on the summary line */
2527 static gboolean tcp_ignore_timestamps = FALSE;
2530 dissect_tcpopt_timestamp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2531 int offset, guint optlen _U_, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2534 proto_tree *ts_tree;
2535 guint32 ts_val, ts_ecr;
2537 ti = proto_tree_add_text(opt_tree, tvb, offset, 10, "Timestamps: ");
2538 ts_tree = proto_item_add_subtree(ti, ett_tcp_option_timestamp);
2540 proto_tree_add_item(ts_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_NA);
2543 proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_NA);
2546 proto_tree_add_item(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset,
2548 ts_val = tvb_get_ntohl(tvb, offset);
2551 proto_tree_add_item(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset,
2553 ts_ecr = tvb_get_ntohl(tvb, offset);
2556 proto_item_append_text(ti, "TSval %u, TSecr %u", ts_val, ts_ecr);
2557 if (tcp_ignore_timestamps == FALSE) {
2558 tcp_info_append_uint(pinfo, "TSval", ts_val);
2559 tcp_info_append_uint(pinfo, "TSecr", ts_ecr);
2564 * The TCP Extensions for Multipath Operation with Multiple Addresses
2565 * are defined in draft-ietf-mptcp-multiaddressed-04
2567 * <http://tools.ietf.org/html/draft-ief-mptcp-multiaddressed-04>
2569 * Author: Andrei Maruseac <andrei.maruseac@intel.com>
2572 dissect_tcpopt_mptcp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2573 int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree, void *data _U_)
2576 proto_tree *mptcp_tree;
2578 proto_tree *mptcp_flags_tree;
2584 ti = proto_tree_add_text(opt_tree, tvb, offset, optlen, "Multipath TCP");
2585 mptcp_tree = proto_item_add_subtree(ti, ett_tcp_option_mptcp);
2587 proto_tree_add_item(mptcp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
2590 proto_tree_add_item(mptcp_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
2593 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_subtype, tvb,
2594 offset, 1, ENC_BIG_ENDIAN);
2596 subtype = tvb_get_guint8(tvb, offset) >> 4;
2597 proto_item_append_text(ti, ": %s", val_to_str(subtype, mptcp_subtype_vs, "Unknown (%d)"));
2599 case TCPOPT_MPTCP_MP_CAPABLE:
2600 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_version, tvb,
2601 offset, 1, ENC_BIG_ENDIAN);
2604 flags = tvb_get_guint8(tvb, offset);
2605 ti = proto_tree_add_uint(mptcp_tree, hf_tcp_option_mptcp_flags, tvb,
2607 mptcp_flags_tree = proto_item_add_subtree(ti, ett_tcp_option_mptcp);
2609 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_C_flag,
2610 tvb, offset, 1, ENC_BIG_ENDIAN);
2611 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_S_flag,
2612 tvb, offset, 1, ENC_BIG_ENDIAN);
2615 if (optlen == 12 || optlen == 20) {
2616 proto_tree_add_item(mptcp_tree,
2617 hf_tcp_option_mptcp_sender_key, tvb, offset, 8, ENC_BIG_ENDIAN);
2622 proto_tree_add_item(mptcp_tree,
2623 hf_tcp_option_mptcp_recv_key, tvb, offset, 8, ENC_BIG_ENDIAN);
2627 case TCPOPT_MPTCP_MP_JOIN:
2630 flags = tvb_get_guint8(tvb, offset) & 0x01;
2631 ti = proto_tree_add_uint(mptcp_tree,
2632 hf_tcp_option_mptcp_flags, tvb,
2634 mptcp_flags_tree = proto_item_add_subtree(ti,
2635 ett_tcp_option_mptcp);
2637 proto_tree_add_item(mptcp_flags_tree,
2638 hf_tcp_option_mptcp_B_flag, tvb, offset,
2642 proto_tree_add_item(mptcp_tree,
2643 hf_tcp_option_mptcp_address_id, tvb, offset,
2647 proto_tree_add_item(mptcp_tree,
2648 hf_tcp_option_mptcp_recv_token, tvb, offset,
2652 proto_tree_add_item(mptcp_tree,
2653 hf_tcp_option_mptcp_sender_rand, tvb, offset,
2658 flags = tvb_get_guint8(tvb, offset) & 0x01;
2659 ti = proto_tree_add_uint(mptcp_tree,
2660 hf_tcp_option_mptcp_flags, tvb,
2662 mptcp_flags_tree = proto_item_add_subtree(ti,
2663 ett_tcp_option_mptcp);
2665 proto_tree_add_item(mptcp_flags_tree,
2666 hf_tcp_option_mptcp_B_flag, tvb, offset,
2670 proto_tree_add_item(mptcp_tree,
2671 hf_tcp_option_mptcp_address_id, tvb, offset,
2675 proto_tree_add_item(mptcp_tree,
2676 hf_tcp_option_mptcp_sender_trunc_mac, tvb, offset,
2680 proto_tree_add_item(mptcp_tree,
2681 hf_tcp_option_mptcp_sender_rand, tvb, offset,
2687 for (indx = 0; indx < 5; indx++) {
2688 proto_tree_add_item(mptcp_tree,
2689 hf_tcp_option_mptcp_sender_mac, tvb, offset,
2700 case TCPOPT_MPTCP_DSS:
2702 flags = tvb_get_guint8(tvb, offset) & 0x1F;
2703 ti = proto_tree_add_uint(mptcp_tree, hf_tcp_option_mptcp_flags, tvb,
2705 mptcp_flags_tree = proto_item_add_subtree(ti, ett_tcp_option_mptcp);
2707 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_F_flag,
2708 tvb, offset, 1, ENC_BIG_ENDIAN);
2709 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_m_flag,
2710 tvb, offset, 1, ENC_BIG_ENDIAN);
2711 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_M_flag,
2712 tvb, offset, 1, ENC_BIG_ENDIAN);
2713 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_a_flag,
2714 tvb, offset, 1, ENC_BIG_ENDIAN);
2715 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_A_flag,
2716 tvb, offset, 1, ENC_BIG_ENDIAN);
2721 proto_tree_add_item(mptcp_tree,
2722 hf_tcp_option_mptcp_data_ack, tvb, offset,
2726 proto_tree_add_item(mptcp_tree,
2727 hf_tcp_option_mptcp_data_ack, tvb, offset,
2735 proto_tree_add_item(mptcp_tree,
2736 hf_tcp_option_mptcp_data_seq_no, tvb, offset,
2740 proto_tree_add_item(mptcp_tree,
2741 hf_tcp_option_mptcp_data_seq_no, tvb, offset,
2746 proto_tree_add_item(mptcp_tree,
2747 hf_tcp_option_mptcp_subflow_seq_no, tvb, offset,
2751 proto_tree_add_item(mptcp_tree,
2752 hf_tcp_option_mptcp_data_lvl_len, tvb, offset,
2756 proto_tree_add_item(mptcp_tree,
2757 hf_tcp_option_mptcp_checksum, tvb, offset,
2762 case TCPOPT_MPTCP_ADD_ADDR:
2763 proto_tree_add_item(mptcp_tree,
2764 hf_tcp_option_mptcp_ipver, tvb, offset, 1, ENC_BIG_ENDIAN);
2765 ipver = tvb_get_guint8(tvb, offset) & 0x0F;
2768 proto_tree_add_item(mptcp_tree,
2769 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2774 proto_tree_add_item(mptcp_tree,
2775 hf_tcp_option_mptcp_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
2780 proto_tree_add_item(mptcp_tree,
2781 hf_tcp_option_mptcp_ipv6, tvb, offset, 16, ENC_NA);
2789 if (optlen % 4 == 2) {
2790 proto_tree_add_item(mptcp_tree,
2791 hf_tcp_option_mptcp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2795 case TCPOPT_MPTCP_REMOVE_ADDR:
2797 proto_tree_add_item(mptcp_tree,
2798 hf_tcp_option_mptcp_address_id, tvb, offset,
2802 case TCPOPT_MPTCP_MP_PRIO:
2803 flags = tvb_get_guint8(tvb, offset) & 0x01;
2804 ti = proto_tree_add_uint(mptcp_tree, hf_tcp_option_mptcp_flags, tvb,
2806 mptcp_flags_tree = proto_item_add_subtree(ti, ett_tcp_option_mptcp);
2808 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_B_flag,
2809 tvb, offset, 1, ENC_BIG_ENDIAN);
2813 proto_tree_add_item(mptcp_tree,
2814 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2818 case TCPOPT_MPTCP_MP_FAIL:
2821 proto_tree_add_item(mptcp_tree,
2822 hf_tcp_option_mptcp_data_seq_no, tvb, offset, 8, ENC_BIG_ENDIAN);
2831 dissect_tcpopt_cc(const ip_tcp_opt *optp, tvbuff_t *tvb,
2832 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2834 proto_item *hidden_item;
2837 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2838 offset, 1, ENC_BIG_ENDIAN);
2839 PROTO_ITEM_SET_HIDDEN(hidden_item);
2840 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2841 offset + 1, 1, ENC_BIG_ENDIAN);
2842 PROTO_ITEM_SET_HIDDEN(hidden_item);
2844 cc = tvb_get_ntohl(tvb, offset + 2);
2845 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_cc, tvb, offset,
2847 PROTO_ITEM_SET_HIDDEN(hidden_item);
2848 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2849 "%s: %u", optp->name, cc);
2850 tcp_info_append_uint(pinfo, "CC", cc);
2854 dissect_tcpopt_qs(const ip_tcp_opt *optp, tvbuff_t *tvb,
2855 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2858 proto_item *hidden_item;
2860 guint8 rate = tvb_get_guint8(tvb, offset + 2) & 0x0f;
2862 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2863 offset, 1, ENC_BIG_ENDIAN);
2864 PROTO_ITEM_SET_HIDDEN(hidden_item);
2865 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2866 offset + 1, 1, ENC_BIG_ENDIAN);
2867 PROTO_ITEM_SET_HIDDEN(hidden_item);
2869 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_qs, tvb, offset,
2871 PROTO_ITEM_SET_HIDDEN(hidden_item);
2872 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2873 "%s: Rate response, %s, TTL diff %u ", optp->name,
2874 val_to_str_ext_const(rate, &qs_rate_vals_ext, "Unknown"),
2875 tvb_get_guint8(tvb, offset + 3));
2876 col_append_fstr(pinfo->cinfo, COL_INFO, " QSresp=%s", val_to_str_ext_const(rate, &qs_rate_vals_ext, "Unknown"));
2881 dissect_tcpopt_scps(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2882 int offset, guint optlen, packet_info *pinfo,
2883 proto_tree *opt_tree, void *data _U_)
2885 struct tcp_analysis *tcpd;
2886 proto_tree *field_tree = NULL;
2889 proto_item *tf = NULL, *hidden_item;
2893 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2894 offset, 1, ENC_BIG_ENDIAN);
2895 PROTO_ITEM_SET_HIDDEN(hidden_item);
2896 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2897 offset + 1, 1, ENC_BIG_ENDIAN);
2898 PROTO_ITEM_SET_HIDDEN(hidden_item);
2900 tcpd = get_tcp_conversation_data(NULL,pinfo);
2902 /* check direction and get ua lists */
2903 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
2905 /* if the addresses are equal, match the ports instead */
2907 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
2911 flow =&(tcpd->flow1);
2913 flow =&(tcpd->flow2);
2915 /* If the option length == 4, this is a real SCPS capability option
2916 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
2917 * (SCPS-TP)" Section 3.2.3 for definition.
2920 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_scps,
2921 tvb, offset, optlen, TRUE);
2922 PROTO_ITEM_SET_HIDDEN(hidden_item);
2924 capvector = tvb_get_guint8(tvb, offset + 2);
2925 connid = tvb_get_guint8(tvb, offset + 3);
2927 tf = proto_tree_add_item(opt_tree, hf_tcp_option_scps_vector, tvb,
2928 offset + 2, 1, ENC_BIG_ENDIAN);
2929 field_tree = proto_item_add_subtree(tf, ett_tcp_option_scps);
2930 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_bets, tvb,
2931 offset + 2, 1, ENC_BIG_ENDIAN);
2932 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_snack1, tvb,
2933 offset + 2, 1, ENC_BIG_ENDIAN);
2934 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_snack2, tvb,
2935 offset + 2, 1, ENC_BIG_ENDIAN);
2936 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_compress, tvb,
2937 offset + 2, 1, ENC_BIG_ENDIAN);
2938 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_nlts, tvb,
2939 offset + 2, 1, ENC_BIG_ENDIAN);
2940 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_reserved, tvb,
2941 offset + 2, 1, ENC_BIG_ENDIAN);
2956 gboolean anyflag = FALSE;
2959 col_append_str(pinfo->cinfo, COL_INFO, " SCPS[");
2960 for (i = 0; i < sizeof(capvecs)/sizeof(struct capvec); i++) {
2961 if (capvector & capvecs[i].mask) {
2962 proto_item_append_text(tf, "%s%s", anyflag ? ", " : " (",
2964 col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s",
2965 anyflag ? ", " : "", capvecs[i].str);
2969 col_append_str(pinfo->cinfo, COL_INFO, "]");
2970 proto_item_append_text(tf, ")");
2973 proto_tree_add_item(field_tree, hf_tcp_scpsoption_connection_id, tvb,
2974 offset + 3, 1, ENC_BIG_ENDIAN);
2975 flow->scps_capable = 1;
2978 tcp_info_append_uint(pinfo, "Connection ID", connid);
2980 /* The option length != 4, so this is an infamous "extended capabilities
2981 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2982 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
2984 * As the format of this option is only partially defined (it is
2985 * a community (or more likely vendor) defined format beyond that, so
2986 * at least for now, we only parse the standardized portion of the option.
2988 guint8 local_offset = 2;
2989 guint8 binding_space;
2990 guint8 extended_cap_length;
2992 if (flow->scps_capable != 1) {
2993 /* There was no SCPS capabilities option preceding this */
2994 proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2995 tvb, offset, optlen, 0,
2996 "Illegal SCPS Extended Capabilities (%d bytes)",
2999 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
3000 tvb, offset, optlen, 0,
3001 "SCPS Extended Capabilities (%d bytes)",
3003 field_tree=proto_item_add_subtree(tf, ett_tcp_option_scps_extended);
3005 /* There may be multiple binding spaces included in a single option,
3006 * so we will semi-parse each of the stacked binding spaces - skipping
3007 * over the octets following the binding space identifier and length.
3009 while (optlen > local_offset) {
3011 /* 1st octet is Extended Capability Binding Space */
3012 binding_space = tvb_get_guint8(tvb, (offset + local_offset));
3014 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
3015 * As defined by the specification, this length is exclusive of the
3016 * octets containing the extended capability type and length
3018 extended_cap_length =
3019 (tvb_get_guint8(tvb, (offset + local_offset + 1)) >> 4);
3021 /* Convert the extended capabilities length into bytes for display */
3022 extended_cap_length = (extended_cap_length << 1);
3024 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding, tvb, offset + local_offset, 1, ENC_BIG_ENDIAN);
3025 proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding_len, tvb, offset + local_offset + 1, 1, extended_cap_length);
3027 /* Step past the binding space and length octets */
3030 proto_tree_add_text(field_tree, tvb, offset + local_offset,
3031 extended_cap_length,
3032 "Binding Space Data (%u bytes)",
3033 extended_cap_length);
3035 tcp_info_append_uint(pinfo, "EXCAP", binding_space);
3037 /* Step past the Extended capability data
3038 * Treat the extended capability data area as opaque;
3039 * If one desires to parse the extended capability data
3040 * (say, in a vendor aware build of wireshark), it would
3041 * be triggered here.
3043 local_offset += extended_cap_length;
3050 dissect_tcpopt_user_to(const ip_tcp_opt *optp, tvbuff_t *tvb,
3051 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
3053 proto_item *hidden_item, *tf;
3054 proto_tree *field_tree;
3058 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
3059 offset, 1, ENC_BIG_ENDIAN);
3060 PROTO_ITEM_SET_HIDDEN(hidden_item);
3061 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
3062 offset + 1, 1, ENC_BIG_ENDIAN);
3063 PROTO_ITEM_SET_HIDDEN(hidden_item);
3065 g = tvb_get_ntohs(tvb, offset + 2) & 0x8000;
3066 to = tvb_get_ntohs(tvb, offset + 2) & 0x7FFF;
3067 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_user_to, tvb, offset,
3069 PROTO_ITEM_SET_HIDDEN(hidden_item);
3071 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_user_to_val, tvb, offset,
3072 optlen, to, "%s: %u %s", optp->name, to, g ? "minutes" : "seconds");
3073 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
3074 proto_tree_add_item(field_tree, hf_tcp_option_user_to_granularity, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
3075 proto_tree_add_item(field_tree, hf_tcp_option_user_to_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
3077 tcp_info_append_uint(pinfo, "USER_TO", to);
3080 /* This is called for SYN+ACK packets and the purpose is to verify that
3081 * the SCPS capabilities option has been successfully negotiated for the flow.
3082 * If the SCPS capabilities option was offered by only one party, the
3083 * proactively set scps_capable attribute of the flow (set upon seeing
3084 * the first instance of the SCPS option) is revoked.
3087 verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd)
3092 if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) {
3093 tcpd->flow1.scps_capable = 0;
3094 tcpd->flow2.scps_capable = 0;
3096 expert_add_info(pinfo, tf_syn, &ei_tcp_scps_capable);
3101 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
3102 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
3105 dissect_tcpopt_snack(const ip_tcp_opt *optp, tvbuff_t *tvb,
3106 int offset, guint optlen, packet_info *pinfo,
3107 proto_tree *opt_tree, void *data _U_)
3109 struct tcp_analysis *tcpd=NULL;
3110 guint16 relative_hole_offset;
3111 guint16 relative_hole_size;
3112 guint16 base_mss = 0;
3116 char null_modifier[] = "\0";
3117 char relative_modifier[] = "(relative)";
3118 char *modifier = null_modifier;
3119 proto_item *hidden_item;
3121 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
3122 offset, 1, ENC_BIG_ENDIAN);
3123 PROTO_ITEM_SET_HIDDEN(hidden_item);
3124 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
3125 offset + 1, 1, ENC_BIG_ENDIAN);
3126 PROTO_ITEM_SET_HIDDEN(hidden_item);
3128 tcpd = get_tcp_conversation_data(NULL,pinfo);
3130 /* The SNACK option reports missing data with a granularity of segments. */
3131 relative_hole_offset = tvb_get_ntohs(tvb, offset + 2);
3132 relative_hole_size = tvb_get_ntohs(tvb, offset + 4);
3134 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_snack, tvb,
3135 offset, optlen, TRUE);
3136 PROTO_ITEM_SET_HIDDEN(hidden_item);
3138 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_offset,
3139 tvb, offset, optlen, relative_hole_offset);
3140 PROTO_ITEM_SET_HIDDEN(hidden_item);
3142 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_size,
3143 tvb, offset, optlen, relative_hole_size);
3144 PROTO_ITEM_SET_HIDDEN(hidden_item);
3145 proto_tree_add_text(opt_tree, tvb, offset, optlen,
3146 "%s: Offset %u, Size %u", optp->name,
3147 relative_hole_offset, relative_hole_size);
3149 ack = tvb_get_ntohl(tvb, 8);
3151 if (tcp_relative_seq) {
3152 ack -= tcpd->rev->base_seq;
3153 modifier = relative_modifier;
3156 /* To aid analysis, we can use a simple but generally effective heuristic
3157 * to report the most likely boundaries of the missing data. If the
3158 * flow is scps_capable, we track the maximum sized segment that was
3159 * acknowledged by the receiver and use that as the reporting granularity.
3160 * This may be different from the negotiated MTU due to PMTUD or flows
3161 * that do not send max-sized segments.
3163 base_mss = tcpd->fwd->maxsizeacked;
3166 /* Scale the reported offset and hole size by the largest segment acked */
3167 hole_start = ack + (base_mss * relative_hole_offset);
3168 hole_end = hole_start + (base_mss * relative_hole_size);
3170 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_le,
3171 tvb, offset, optlen, hole_start);
3172 PROTO_ITEM_SET_HIDDEN(hidden_item);
3174 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_re,
3175 tvb, offset, optlen, hole_end);
3176 PROTO_ITEM_SET_HIDDEN(hidden_item);
3177 proto_tree_add_text(opt_tree, tvb, offset, optlen,
3178 "\tMissing Sequence %u - %u %s",
3179 hole_start, hole_end, modifier);
3181 tcp_info_append_uint(pinfo, "SNLE", hole_start);
3182 tcp_info_append_uint(pinfo, "SNRE", hole_end);
3184 expert_add_info_format(pinfo, NULL, &ei_tcp_option_snack_sequence, "SNACK Sequence %u - %u %s", hole_start, hole_end, modifier);
3190 PROBE_VERSION_UNSPEC = 0,
3191 PROBE_VERSION_1 = 1,
3192 PROBE_VERSION_2 = 2,
3196 /* Probe type definition. */
3204 PROBE_RESPONSE_SH = 5,
3205 PROBE_QUERY_INFO = 6,
3206 PROBE_RESPONSE_INFO = 7,
3207 PROBE_QUERY_INFO_SH = 8,
3208 PROBE_QUERY_INFO_SID = 9,
3213 static const value_string rvbd_probe_type_vs[] = {
3214 { PROBE_QUERY, "Probe Query" },
3215 { PROBE_RESPONSE, "Probe Response" },
3216 { PROBE_INTERNAL, "Probe Internal" },
3217 { PROBE_TRACE, "Probe Trace" },
3218 { PROBE_QUERY_SH, "Probe Query SH" },
3219 { PROBE_RESPONSE_SH, "Probe Response SH" },
3220 { PROBE_QUERY_INFO, "Probe Query Info" },
3221 { PROBE_RESPONSE_INFO, "Probe Response Info" },
3222 { PROBE_QUERY_INFO_SH, "Probe Query Info SH" },
3223 { PROBE_QUERY_INFO_SID, "Probe Query Info Store ID" },
3224 { PROBE_RST, "Probe Reset" },
3229 #define PROBE_OPTLEN_OFFSET 1
3231 #define PROBE_VERSION_TYPE_OFFSET 2
3232 #define PROBE_V1_RESERVED_OFFSET 3
3233 #define PROBE_V1_PROBER_OFFSET 4
3234 #define PROBE_V1_APPLI_VERSION_OFFSET 8
3235 #define PROBE_V1_PROXY_ADDR_OFFSET 8
3236 #define PROBE_V1_PROXY_PORT_OFFSET 12
3237 #define PROBE_V1_SH_CLIENT_ADDR_OFFSET 8
3238 #define PROBE_V1_SH_PROXY_ADDR_OFFSET 12
3239 #define PROBE_V1_SH_PROXY_PORT_OFFSET 16
3241 #define PROBE_V2_INFO_OFFSET 3
3243 #define PROBE_V2_INFO_CLIENT_ADDR_OFFSET 4
3244 #define PROBE_V2_INFO_STOREID_OFFSET 4
3246 #define PROBE_VERSION_MASK 0x01
3248 /* Probe Query Extra Info flags */
3249 #define RVBD_FLAGS_PROBE_LAST 0x01
3250 #define RVBD_FLAGS_PROBE_NCFE 0x04
3252 /* Probe Response Extra Info flags */
3253 #define RVBD_FLAGS_PROBE_SERVER 0x01
3254 #define RVBD_FLAGS_PROBE_SSLCERT 0x02
3255 #define RVBD_FLAGS_PROBE 0x10
3258 rvbd_probe_decode_version_type(const guint8 vt, guint8 *ver, guint8 *type)
3260 if (vt & PROBE_VERSION_MASK) {
3261 *ver = PROBE_VERSION_1;
3264 *ver = PROBE_VERSION_2;
3270 rvbd_probe_resp_add_info(proto_item *pitem, packet_info *pinfo, guint32 ip, guint16 port)
3272 proto_item_append_text(pitem, ", Server Steelhead: %s:%u", ip_to_str((guint8 *)&ip), port);
3274 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA+, ");
3278 dissect_tcpopt_rvbd_probe(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
3279 guint optlen, packet_info *pinfo, proto_tree *opt_tree,
3283 proto_tree *field_tree;
3286 rvbd_probe_decode_version_type(
3287 tvb_get_guint8(tvb, offset + PROBE_VERSION_TYPE_OFFSET),
3290 pitem = proto_tree_add_boolean_format_value(
3291 opt_tree, hf_tcp_option_rvbd_probe, tvb, offset, optlen, 1,
3292 "%s", val_to_str_const(type, rvbd_probe_type_vs, "Probe Unknown"));
3294 if (type >= PROBE_TYPE_MAX)
3297 /* optlen, type, ver are common for all probes */
3298 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe);
3299 pitem = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
3300 offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN);
3301 PROTO_ITEM_SET_HIDDEN(pitem);
3302 pitem = proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
3303 offset, 1, ENC_BIG_ENDIAN);
3304 PROTO_ITEM_SET_HIDDEN(pitem);
3305 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_optlen, tvb,
3306 offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN);
3308 if (ver == PROBE_VERSION_1) {
3312 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type1, tvb,
3313 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
3314 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
3315 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
3317 if (type == PROBE_INTERNAL)
3320 proto_tree_add_text(field_tree, tvb, offset + PROBE_V1_RESERVED_OFFSET,
3323 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_PROBER_OFFSET);
3324 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_prober, tvb,
3325 offset + PROBE_V1_PROBER_OFFSET, 4, ENC_BIG_ENDIAN);
3330 case PROBE_QUERY_SH:
3332 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_appli_ver, tvb,
3333 offset + PROBE_V1_APPLI_VERSION_OFFSET, 2,
3336 proto_item_append_text(pitem, ", CSH IP: %s", ip_to_str((guint8 *)&ip));
3339 /* Small look-ahead hack to distinguish S+ from S+* */
3340 #define PROBE_V1_QUERY_LEN 10
3341 const guint8 qinfo_hdr[] = { 0x4c, 0x04, 0x0c };
3343 /* tvb_memeql seems to be the only API that doesn't throw
3344 an exception in case of an error */
3345 if (tvb_memeql(tvb, offset + PROBE_V1_QUERY_LEN,
3346 qinfo_hdr, sizeof(qinfo_hdr)) == 0) {
3347 not_cfe = tvb_get_guint8(tvb, offset + PROBE_V1_QUERY_LEN +
3348 (int)sizeof(qinfo_hdr)) & RVBD_FLAGS_PROBE_NCFE;
3350 col_prepend_fstr(pinfo->cinfo, COL_INFO, "S%s, ",
3351 type == PROBE_TRACE ? "#" :
3352 not_cfe ? "+*" : "+");
3356 case PROBE_RESPONSE:
3357 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_PROXY_ADDR_OFFSET);
3358 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
3359 offset + PROBE_V1_PROXY_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
3361 port = tvb_get_ntohs(tvb, offset + PROBE_V1_PROXY_PORT_OFFSET);
3362 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
3363 offset + PROBE_V1_PROXY_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3365 rvbd_probe_resp_add_info(pitem, pinfo, ip, port);
3368 case PROBE_RESPONSE_SH:
3369 proto_tree_add_item(field_tree,
3370 hf_tcp_option_rvbd_probe_client, tvb,
3371 offset + PROBE_V1_SH_CLIENT_ADDR_OFFSET, 4,
3374 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_SH_PROXY_ADDR_OFFSET);
3375 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
3376 offset + PROBE_V1_SH_PROXY_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
3378 port = tvb_get_ntohs(tvb, offset + PROBE_V1_SH_PROXY_PORT_OFFSET);
3379 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
3380 offset + PROBE_V1_SH_PROXY_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3382 rvbd_probe_resp_add_info(pitem, pinfo, ip, port);
3386 else if (ver == PROBE_VERSION_2) {
3388 proto_item *flag_pi;
3389 proto_tree *flag_tree;
3392 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type2, tvb,
3393 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
3395 proto_tree_add_uint_format_value(
3396 field_tree, hf_tcp_option_rvbd_probe_version2, tvb,
3397 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver, "%u", ver);
3398 /* Use version1 for filtering purposes because version2 packet
3399 value is 0, but filtering is usually done for value 2 */
3400 ver_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
3401 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver);
3402 PROTO_ITEM_SET_HIDDEN(ver_pi);
3406 case PROBE_QUERY_INFO:
3407 case PROBE_QUERY_INFO_SH:
3408 case PROBE_QUERY_INFO_SID:
3409 flags = tvb_get_guint8(tvb, offset + PROBE_V2_INFO_OFFSET);
3410 flag_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_flags,
3411 tvb, offset + PROBE_V2_INFO_OFFSET,
3414 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
3415 proto_tree_add_item(flag_tree,
3416 hf_tcp_option_rvbd_probe_flag_not_cfe,
3417 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3418 proto_tree_add_item(flag_tree,
3419 hf_tcp_option_rvbd_probe_flag_last_notify,
3420 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3422 if (type == PROBE_QUERY_INFO_SH)
3423 proto_tree_add_item(flag_tree,
3424 hf_tcp_option_rvbd_probe_client, tvb,
3425 offset + PROBE_V2_INFO_CLIENT_ADDR_OFFSET,
3427 else if (type == PROBE_QUERY_INFO_SID)
3428 proto_tree_add_item(flag_tree,
3429 hf_tcp_option_rvbd_probe_storeid, tvb,
3430 offset + PROBE_V2_INFO_STOREID_OFFSET,
3433 if (type != PROBE_QUERY_INFO_SID &&
3434 (tvb_get_guint8(tvb, 13) & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK) &&
3435 (flags & RVBD_FLAGS_PROBE_LAST)) {
3436 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA++, ");
3441 case PROBE_RESPONSE_INFO:
3442 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
3443 tvb, offset + PROBE_V2_INFO_OFFSET,
3446 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
3447 proto_tree_add_item(flag_tree,
3448 hf_tcp_option_rvbd_probe_flag_probe_cache,
3449 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3450 proto_tree_add_item(flag_tree,
3451 hf_tcp_option_rvbd_probe_flag_sslcert,
3452 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3453 proto_tree_add_item(flag_tree,
3454 hf_tcp_option_rvbd_probe_flag_server_connected,
3455 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3459 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
3460 tvb, offset + PROBE_V2_INFO_OFFSET,
3468 TRPY_OPTNUM_OFFSET = 0,
3469 TRPY_OPTLEN_OFFSET = 1,
3471 TRPY_OPTIONS_OFFSET = 2,
3472 TRPY_SRC_ADDR_OFFSET = 4,
3473 TRPY_DST_ADDR_OFFSET = 8,
3474 TRPY_SRC_PORT_OFFSET = 12,
3475 TRPY_DST_PORT_OFFSET = 14,
3476 TRPY_CLIENT_PORT_OFFSET = 16
3480 #define RVBD_FLAGS_TRPY_MODE 0x0001
3481 #define RVBD_FLAGS_TRPY_OOB 0x0002
3482 #define RVBD_FLAGS_TRPY_CHKSUM 0x0004
3483 #define RVBD_FLAGS_TRPY_FW_RST 0x0100
3484 #define RVBD_FLAGS_TRPY_FW_RST_INNER 0x0200
3485 #define RVBD_FLAGS_TRPY_FW_RST_PROBE 0x0400
3487 static const true_false_string trpy_mode_str = {
3488 "Port Transparency",
3493 dissect_tcpopt_rvbd_trpy(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
3494 int offset, guint optlen, packet_info *pinfo,
3495 proto_tree *opt_tree, void *data _U_)
3497 proto_tree *field_tree;
3498 proto_tree *flag_tree;
3500 proto_item *flag_pi;
3502 guint16 sport, dport, flags;
3504 col_prepend_fstr(pinfo->cinfo, COL_INFO, "TRPY, ");
3506 pitem = proto_tree_add_boolean_format_value(
3507 opt_tree, hf_tcp_option_rvbd_trpy, tvb, offset, optlen, 1,
3510 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_trpy);
3511 pitem = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
3512 offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN);
3513 PROTO_ITEM_SET_HIDDEN(pitem);
3514 pitem = proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
3515 offset, 1, ENC_BIG_ENDIAN);
3516 PROTO_ITEM_SET_HIDDEN(pitem);
3517 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_optlen, tvb,
3518 offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN);
3520 flags = tvb_get_ntohs(tvb, offset + TRPY_OPTIONS_OFFSET);
3521 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_flags,
3522 tvb, offset + TRPY_OPTIONS_OFFSET,
3525 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_trpy_flags);
3526 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
3527 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3528 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
3529 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3530 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst,
3531 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3532 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_chksum,
3533 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3534 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_oob,
3535 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3536 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_mode,
3537 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3539 src = tvb_get_ipv4(tvb, offset + TRPY_SRC_ADDR_OFFSET);
3540 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src,
3541 tvb, offset + TRPY_SRC_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
3543 dst = tvb_get_ipv4(tvb, offset + TRPY_DST_ADDR_OFFSET);
3544 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst,
3545 tvb, offset + TRPY_DST_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
3547 sport = tvb_get_ntohs(tvb, offset + TRPY_SRC_PORT_OFFSET);
3548 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src_port,
3549 tvb, offset + TRPY_SRC_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3551 dport = tvb_get_ntohs(tvb, offset + TRPY_DST_PORT_OFFSET);
3552 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst_port,
3553 tvb, offset + TRPY_DST_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3555 proto_item_append_text(pitem, "%s:%u -> %s:%u",
3556 ip_to_str((guint8 *)&src), sport,
3557 ip_to_str((guint8 *)&dst), dport);
3559 /* Client port only set on SYN: optlen == 18 */
3560 if ((flags & RVBD_FLAGS_TRPY_OOB) && (optlen > TCPOLEN_RVBD_TRPY_MIN))
3561 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_client_port,
3562 tvb, offset + TRPY_CLIENT_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3564 /* Despite that we have the right TCP ports for other protocols,
3565 * the data is related to the Riverbed Optimization Protocol and
3566 * not understandable by normal protocol dissectors. If the sport
3567 * protocol is available then use that, otherwise just output it
3570 if (sport_handle != NULL) {
3571 conversation_t *conversation;
3572 conversation = find_conversation(pinfo->fd->num,
3573 &pinfo->src, &pinfo->dst, pinfo->ptype,
3574 pinfo->srcport, pinfo->destport, 0);
3575 if (conversation == NULL) {
3576 conversation = conversation_new(pinfo->fd->num,
3577 &pinfo->src, &pinfo->dst, pinfo->ptype,
3578 pinfo->srcport, pinfo->destport, 0);
3580 if (conversation->dissector_handle != sport_handle) {
3581 conversation_set_dissector(conversation, sport_handle);
3583 } else if (data_handle != NULL) {
3584 conversation_t *conversation;
3585 conversation = find_conversation(pinfo->fd->num,
3586 &pinfo->src, &pinfo->dst, pinfo->ptype,
3587 pinfo->srcport, pinfo->destport, 0);
3588 if (conversation == NULL) {
3589 conversation = conversation_new(pinfo->fd->num,
3590 &pinfo->src, &pinfo->dst, pinfo->ptype,
3591 pinfo->srcport, pinfo->destport, 0);
3593 if (conversation->dissector_handle != data_handle) {
3594 conversation_set_dissector(conversation, data_handle);
3599 static const ip_tcp_opt tcpopts[] = {
3602 "End of Option List (EOL)",
3610 "No-Operation (NOP)",
3618 "Maximum segment size",
3620 OPT_LEN_FIXED_LENGTH,
3628 OPT_LEN_FIXED_LENGTH,
3630 dissect_tcpopt_wscale
3636 OPT_LEN_FIXED_LENGTH,
3638 dissect_tcpopt_sack_perm,
3643 &ett_tcp_option_sack,
3644 OPT_LEN_VARIABLE_LENGTH,
3652 OPT_LEN_FIXED_LENGTH,
3660 OPT_LEN_FIXED_LENGTH,
3668 OPT_LEN_FIXED_LENGTH,
3670 dissect_tcpopt_timestamp
3676 OPT_LEN_VARIABLE_LENGTH,
3678 dissect_tcpopt_mptcp
3684 OPT_LEN_FIXED_LENGTH,
3692 OPT_LEN_FIXED_LENGTH,
3700 OPT_LEN_FIXED_LENGTH,
3706 "TCP MD5 signature",
3708 OPT_LEN_FIXED_LENGTH,
3714 "SCPS capabilities",
3715 &ett_tcp_option_scps,
3716 OPT_LEN_VARIABLE_LENGTH,
3722 "Selective Negative Acknowledgment",
3724 OPT_LEN_FIXED_LENGTH,
3726 dissect_tcpopt_snack
3730 "SCPS record boundary",
3732 OPT_LEN_FIXED_LENGTH,
3738 "SCPS corruption experienced",
3740 OPT_LEN_FIXED_LENGTH,
3748 OPT_LEN_FIXED_LENGTH,
3755 &ett_tcp_option_user_to,
3756 OPT_LEN_FIXED_LENGTH,
3758 dissect_tcpopt_user_to
3764 OPT_LEN_VARIABLE_LENGTH,
3765 TCPOLEN_RVBD_PROBE_MIN,
3766 dissect_tcpopt_rvbd_probe
3770 "Riverbed Transparency",
3772 OPT_LEN_FIXED_LENGTH,
3773 TCPOLEN_RVBD_TRPY_MIN,
3774 dissect_tcpopt_rvbd_trpy
3780 OPT_LEN_VARIABLE_LENGTH,
3788 OPT_LEN_VARIABLE_LENGTH,
3794 #define N_TCP_OPTS array_length(tcpopts)
3796 static ip_tcp_opt_type TCP_OPT_TYPES = {&hf_tcp_option_type, &ett_tcp_option_type,
3797 &hf_tcp_option_type_copy, &hf_tcp_option_type_class, &hf_tcp_option_type_number};
3799 /* Determine if there is a sub-dissector and call it; return TRUE
3800 if there was a sub-dissector, FALSE otherwise.
3802 This has been separated into a stand alone routine to other protocol
3803 dissectors can call to it, e.g., SOCKS. */
3805 static gboolean try_heuristic_first = FALSE;
3808 /* this function can be called with tcpd==NULL as from the msproxy dissector */
3810 decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
3811 proto_tree *tree, int src_port, int dst_port,
3812 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
3815 int low_port, high_port;
3816 int save_desegment_offset;
3817 guint32 save_desegment_len;
3819 /* Don't call subdissectors for keepalives. Even though they do contain
3820 * payload "data", it's just garbage. Display any data the keepalive
3821 * packet might contain though.
3823 if(tcpd && tcpd->ta) {
3824 if(tcpd->ta->flags&TCP_A_KEEP_ALIVE) {
3825 next_tvb = tvb_new_subset_remaining(tvb, offset);
3826 call_dissector(data_handle, next_tvb, pinfo, tree);
3831 if (tcp_no_subdissector_on_error && tcpd && tcpd->ta && tcpd->ta->flags & (TCP_A_RETRANSMISSION | TCP_A_OUT_OF_ORDER)) {
3832 /* Don't try to dissect a retransmission high chance that it will mess
3833 * subdissectors for protocols that require in-order delivery of the
3834 * PDUs. (i.e. DCE/RPCoverHTTP and encryption)
3838 next_tvb = tvb_new_subset_remaining(tvb, offset);
3840 /* determine if this packet is part of a conversation and call dissector */
3841 /* for the conversation if available */
3843 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP,
3844 src_port, dst_port, next_tvb, pinfo, tree, tcpinfo)) {
3845 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3849 if (try_heuristic_first) {
3850 /* do lookup with the heuristic subdissector table */
3851 save_desegment_offset = pinfo->desegment_offset;
3852 save_desegment_len = pinfo->desegment_len;
3853 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, tcpinfo)) {
3854 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3858 * They rejected the packet; make sure they didn't also request
3859 * desegmentation (we could just override the request, but
3860 * rejecting a packet *and* requesting desegmentation is a sign
3861 * of the dissector's code needing clearer thought, so we fail
3862 * so that the problem is made more obvious).
3864 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
3865 save_desegment_len == pinfo->desegment_len);
3868 /* Do lookups with the subdissector table.
3869 Try the server port captured on the SYN or SYN|ACK packet. After that
3870 try the port number with the lower value first, followed by the
3871 port number with the higher value. This means that, for packets
3872 where a dissector is registered for *both* port numbers:
3874 1) we pick the same dissector for traffic going in both directions;
3876 2) we prefer the port number that's more likely to be the right
3877 one (as that prefers well-known ports to reserved ports);
3879 although there is, of course, no guarantee that any such strategy
3880 will always pick the right port number.
3882 XXX - we ignore port numbers of 0, as some dissectors use a port
3883 number of 0 to disable the port. */
3885 if (tcpd && tcpd->server_port != 0 &&
3886 dissector_try_uint_new(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) {
3887 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3891 if (src_port > dst_port) {
3892 low_port = dst_port;
3893 high_port = src_port;
3895 low_port = src_port;
3896 high_port = dst_port;
3899 if (low_port != 0 &&
3900 dissector_try_uint_new(subdissector_table, low_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) {
3901 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3904 if (high_port != 0 &&
3905 dissector_try_uint_new(subdissector_table, high_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) {
3906 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3910 if (!try_heuristic_first) {
3911 /* do lookup with the heuristic subdissector table */
3912 save_desegment_offset = pinfo->desegment_offset;
3913 save_desegment_len = pinfo->desegment_len;
3914 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, tcpinfo)) {
3915 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3919 * They rejected the packet; make sure they didn't also request
3920 * desegmentation (we could just override the request, but
3921 * rejecting a packet *and* requesting desegmentation is a sign
3922 * of the dissector's code needing clearer thought, so we fail
3923 * so that the problem is made more obvious).
3925 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
3926 save_desegment_len == pinfo->desegment_len);
3929 /* Oh, well, we don't know this; dissect it as data. */
3930 call_dissector(data_handle,next_tvb, pinfo, tree);
3932 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3937 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
3938 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
3939 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
3940 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
3942 pinfo->want_pdu_tracking=0;
3945 if(is_tcp_segment) {
3946 /*qqq see if it is an unaligned PDU */
3947 if(tcpd && tcp_analyze_seq && (!tcp_desegment)) {
3949 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
3950 seq, nxtseq, tcpd->fwd->multisegment_pdus);
3954 /* if offset is -1 this means that this segment is known
3955 * to be fully inside a previously detected pdu
3956 * so we don't even need to try to dissect it either.
3959 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
3960 dst_port, tcpd, tcpinfo) ) {
3962 * We succeeded in handing off to a subdissector.
3964 * Is this a TCP segment or a reassembled chunk of
3967 if(is_tcp_segment) {
3968 /* if !visited, check want_pdu_tracking and
3969 store it in table */
3970 if(tcpd && (!pinfo->fd->flags.visited) &&
3971 tcp_analyze_seq && pinfo->want_pdu_tracking) {
3973 pdu_store_sequencenumber_of_next_pdu(
3976 nxtseq+pinfo->bytes_until_next_pdu,
3977 tcpd->fwd->multisegment_pdus);
3984 /* We got an exception. At this point the dissection is
3985 * completely aborted and execution will be transferred back
3986 * to (probably) the frame dissector.
3987 * Here we have to place whatever we want the dissector
3988 * to do before aborting the tcp dissection.
3991 * Is this a TCP segment or a reassembled chunk of TCP
3994 if(is_tcp_segment) {
3996 * It's from a TCP segment.
3998 * if !visited, check want_pdu_tracking and store it
4001 if(tcpd && (!pinfo->fd->flags.visited) && tcp_analyze_seq && pinfo->want_pdu_tracking) {
4003 pdu_store_sequencenumber_of_next_pdu(pinfo,
4005 nxtseq+pinfo->bytes_until_next_pdu,
4006 tcpd->fwd->multisegment_pdus);
4016 dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,
4017 guint32 nxtseq, guint32 sport, guint32 dport,
4018 proto_tree *tree, proto_tree *tcp_tree,
4019 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
4021 gboolean save_fragmented;
4023 /* Can we desegment this segment? */
4024 if (pinfo->can_desegment) {
4026 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
4027 tcp_tree, tcpd, tcpinfo);
4029 /* No - just call the subdissector.
4030 Mark this as fragmented, so if somebody throws an exception,
4031 we don't report it as a malformed frame. */
4032 save_fragmented = pinfo->fragmented;
4033 pinfo->fragmented = TRUE;
4034 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
4035 seq, nxtseq, TRUE, tcpd, tcpinfo);
4036 pinfo->fragmented = save_fragmented;
4041 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4043 guint8 th_off_x2; /* combines th_off and th_x2 */
4046 proto_tree *tcp_tree = NULL, *field_tree = NULL;
4047 proto_item *ti = NULL, *tf, *hidden_item;
4049 wmem_strbuf_t *flags_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
4050 static const gchar *flags[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR", "NS"};
4058 guint16 computed_cksum;
4059 guint16 real_window;
4060 guint length_remaining;
4061 gboolean desegment_ok;
4062 struct tcpinfo tcpinfo;
4063 struct tcpheader *tcph;
4064 proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL, *scaled_pi;
4065 conversation_t *conv=NULL;
4066 struct tcp_analysis *tcpd=NULL;
4067 struct tcp_per_packet_data_t *tcppd=NULL;
4069 proto_tree *checksum_tree;
4071 wmem_strbuf_append(flags_strbuf, "<None>");
4073 tcph=wmem_new(wmem_packet_scope(), struct tcpheader);
4074 SET_ADDRESS(&tcph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
4075 SET_ADDRESS(&tcph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
4077 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
4079 /* Clear out the Info column. */
4080 col_clear(pinfo->cinfo, COL_INFO);
4082 tcph->th_sport = tvb_get_ntohs(tvb, offset);
4083 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
4084 col_add_fstr(pinfo->cinfo, COL_INFO, "%s \xe2\x86\x92 %s", /* UTF8_RIGHTWARDS_ARROW */
4085 get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
4087 if (tcp_summary_in_tree) {
4088 ti = proto_tree_add_protocol_format(tree, proto_tcp, tvb, 0, -1,
4089 "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
4090 get_tcp_port(tcph->th_sport), tcph->th_sport,
4091 get_tcp_port(tcph->th_dport), tcph->th_dport);
4094 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, ENC_NA);
4096 tcp_tree = proto_item_add_subtree(ti, ett_tcp);
4098 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_srcport, tvb, offset, 2, tcph->th_sport,
4099 "%s (%u)", get_tcp_port(tcph->th_sport), tcph->th_sport);
4100 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, tcph->th_dport,
4101 "%s (%u)", get_tcp_port(tcph->th_dport), tcph->th_dport);
4102 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset, 2, tcph->th_sport);
4103 PROTO_ITEM_SET_HIDDEN(hidden_item);
4104 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, tcph->th_dport);
4105 PROTO_ITEM_SET_HIDDEN(hidden_item);
4107 /* If we're dissecting the headers of a TCP packet in an ICMP packet
4108 * then go ahead and put the sequence numbers in the tree now (because
4109 * they won't be put in later because the ICMP packet only contains up
4110 * to the sequence number).
4111 * We should only need to do this for IPv4 since IPv6 will hopefully
4112 * carry enough TCP payload for this dissector to put the sequence
4113 * numbers in via the regular code path.
4116 wmem_list_frame_t *frame;
4117 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
4118 if (proto_ip == (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))) {
4119 frame = wmem_list_frame_prev(frame);
4120 if (proto_icmp == (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))) {
4121 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
4127 /* Set the source and destination port numbers as soon as we get them,
4128 so that they're available to the "Follow TCP Stream" code even if
4129 we throw an exception dissecting the rest of the TCP header. */
4130 pinfo->ptype = PT_TCP;
4131 pinfo->srcport = tcph->th_sport;
4132 pinfo->destport = tcph->th_dport;
4134 tcph->th_seq = tvb_get_ntohl(tvb, offset + 4);
4135 tcph->th_ack = tvb_get_ntohl(tvb, offset + 8);
4136 th_off_x2 = tvb_get_guint8(tvb, offset + 12);
4137 tcph->th_flags = tvb_get_ntohs(tvb, offset + 12) & 0x0FFF;
4138 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
4139 real_window = tcph->th_win;
4140 tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
4142 /* find(or create if needed) the conversation for this tcp session */
4143 conv=find_or_create_conversation(pinfo);
4144 tcpd=get_tcp_conversation_data(conv,pinfo);
4146 /* If this is a SYN packet, then check if its seq-nr is different
4147 * from the base_seq of the retrieved conversation. If this is the
4148 * case, create a new conversation with the same addresses and ports
4149 * and set the TA_PORTS_REUSED flag. If the seq-nr is the same as
4150 * the base_seq, then do nothing so it will be marked as a retrans-
4153 if(tcpd && ((tcph->th_flags&(TH_SYN|TH_ACK))==TH_SYN) &&
4154 (tcpd->fwd->base_seq!=0) &&
4155 (tcph->th_seq!=tcpd->fwd->base_seq) ) {
4156 if (!(pinfo->fd->flags.visited)) {
4157 conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4158 tcpd=get_tcp_conversation_data(conv,pinfo);
4161 tcp_analyze_get_acked_struct(pinfo->fd->num, tcph->th_seq, tcph->th_ack, TRUE, tcpd);
4162 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
4166 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, tcpd->stream);
4167 PROTO_ITEM_SET_GENERATED(item);
4169 /* Copy the stream index into the header as well to make it available
4172 tcph->th_stream = tcpd->stream;
4175 /* Do we need to calculate timestamps relative to the tcp-stream? */
4176 if (tcp_calculate_ts) {
4177 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, 0);
4180 * Calculate the timestamps relative to this conversation (but only on the
4181 * first run when frames are accessed sequentially)
4183 if (!(pinfo->fd->flags.visited))
4184 tcp_calculate_timestamps(pinfo, tcpd, tcppd);
4188 * If we've been handed an IP fragment, we don't know how big the TCP
4189 * segment is, so don't do anything that requires that we know that.
4191 * The same applies if we're part of an error packet. (XXX - if the
4192 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
4193 * header says it is" length in the tvbuff, we could use that; such
4194 * a length might also be useful for handling packets where the IP
4195 * length is bigger than the actual data available in the frame; the
4196 * dissectors should trust that length, and then throw a
4197 * ReportedBoundsError exception when they go past the end of the frame.)
4199 * We also can't determine the segment length if the reported length
4200 * of the TCP packet is less than the TCP header length.
4202 reported_len = tvb_reported_length(tvb);
4204 if (!pinfo->fragmented && !pinfo->flags.in_error_pkt) {
4205 if (reported_len < tcph->th_hlen) {
4207 pi = proto_tree_add_text(tcp_tree, tvb, offset, 0,
4208 "Short segment. Segment/fragment does not contain a full TCP header"
4209 " (might be NMAP or someone else deliberately sending unusual packets)");
4210 PROTO_ITEM_SET_GENERATED(pi);
4211 expert_add_info(pinfo, pi, &ei_tcp_short_segment);
4212 tcph->th_have_seglen = FALSE;
4214 /* Compute the length of data in this segment. */
4215 tcph->th_seglen = reported_len - tcph->th_hlen;
4216 tcph->th_have_seglen = TRUE;
4221 pi = proto_tree_add_uint(ti, hf_tcp_len, tvb, offset+12, 1, tcph->th_seglen);
4222 PROTO_ITEM_SET_GENERATED(pi);
4227 /* handle TCP seq# analysis parse all new segments we see */
4228 if(tcp_analyze_seq) {
4229 if(!(pinfo->fd->flags.visited)) {
4230 tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd);
4232 if(tcpd && tcp_relative_seq) {
4233 (tcph->th_seq) -= tcpd->fwd->base_seq;
4234 if (tcph->th_flags & TH_ACK) {
4235 (tcph->th_ack) -= tcpd->rev->base_seq;
4240 /* re-calculate window size, based on scaling factor */
4241 if (!(tcph->th_flags&TH_SYN)) { /* SYNs are never scaled */
4242 if (tcpd && (tcpd->fwd->win_scale>=0)) {
4243 (tcph->th_win)<<=tcpd->fwd->win_scale;
4246 /* Don't have it stored, so use preference setting instead! */
4247 if (tcp_default_window_scaling>=0) {
4248 (tcph->th_win)<<=tcp_default_window_scaling;
4253 /* Compute the sequence number of next octet after this segment. */
4254 nxtseq = tcph->th_seq + tcph->th_seglen;
4257 tcph->th_have_seglen = FALSE;
4260 gboolean first_flag = TRUE;
4261 for (i = 0; i < 9; i++) {
4263 if (tcph->th_flags & bpos) {
4265 wmem_strbuf_truncate(flags_strbuf, 0);
4267 wmem_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ", flags[i]);
4271 if (tcph->th_flags & 0x0E00) {
4273 wmem_strbuf_truncate(flags_strbuf, 0);
4275 wmem_strbuf_append_printf(flags_strbuf, "%sReserved", first_flag ? "" : ", ");
4279 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] Seq=%u", wmem_strbuf_get_str(flags_strbuf), tcph->th_seq);
4280 if (tcph->th_flags&TH_ACK) {
4281 col_append_fstr(pinfo->cinfo, COL_INFO, " Ack=%u", tcph->th_ack);
4283 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", tcph->th_win);
4286 if (tcp_summary_in_tree) {
4287 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
4289 if(tcp_relative_seq) {
4290 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);
4292 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
4296 if (tcph->th_hlen < TCPH_MIN_LEN) {
4297 /* Give up at this point; we put the source and destination port in
4298 the tree, before fetching the header length, so that they'll
4299 show up if this is in the failing packet in an ICMP error packet,
4300 but it's now time to give up if the header length is bogus. */
4301 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
4302 tcph->th_hlen, TCPH_MIN_LEN);
4304 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
4305 "%u bytes (bogus, must be at least %u)", tcph->th_hlen,
4312 if (tcp_summary_in_tree) {
4313 if(tcph->th_flags&TH_ACK) {
4314 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
4316 if (tcph->th_have_seglen)
4317 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
4319 proto_item_set_len(ti, tcph->th_hlen);
4320 if (tcph->th_have_seglen) {
4321 if (nxtseq != tcph->th_seq) {
4322 if(tcp_relative_seq) {
4323 tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "%u (relative sequence number)", nxtseq);
4325 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
4327 PROTO_ITEM_SET_GENERATED(tf);
4332 tf = proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
4333 if (tcph->th_flags & TH_ACK) {
4334 if (tcp_relative_seq) {
4335 proto_item_append_text(tf, " (relative ack number)");
4338 /* Note if the ACK field is non-zero */
4339 if (tvb_get_ntohl(tvb, offset+8) != 0) {
4340 expert_add_info(pinfo, tf, &ei_tcp_ack_nonzero);
4345 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
4346 "%u bytes", tcph->th_hlen);
4347 tf = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_flags, tvb, offset + 12, 2,
4348 tcph->th_flags, "0x%03x (%s)", tcph->th_flags, wmem_strbuf_get_str(flags_strbuf));
4349 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
4350 proto_tree_add_boolean(field_tree, hf_tcp_flags_res, tvb, offset + 12, 1, tcph->th_flags);
4351 proto_tree_add_boolean(field_tree, hf_tcp_flags_ns, tvb, offset + 12, 1, tcph->th_flags);
4352 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
4353 proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, tvb, offset + 13, 1, tcph->th_flags);
4354 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
4355 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
4356 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
4357 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
4358 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
4359 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
4361 /* As discussed in bug 5541, it is better to use two separate
4362 * fields for the real and calculated window size.
4364 proto_tree_add_uint(tcp_tree, hf_tcp_window_size_value, tvb, offset + 14, 2, real_window);
4365 scaled_pi = proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win);
4366 PROTO_ITEM_SET_GENERATED(scaled_pi);
4368 if( !(tcph->th_flags&TH_SYN) && tcpd ) {
4369 switch (tcpd->fwd->win_scale) {
4373 gint16 win_scale = tcpd->fwd->win_scale;
4374 gboolean override_with_pref = FALSE;
4376 /* Use preference setting (if set) */
4377 if (tcp_default_window_scaling != WindowScaling_NotKnown) {
4378 win_scale = tcp_default_window_scaling;
4379 override_with_pref = TRUE;
4382 scaled_pi = proto_tree_add_int_format_value(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2,
4383 win_scale, "%d (%s)",
4385 (override_with_pref) ? "missing - taken from preference" : "unknown");
4386 PROTO_ITEM_SET_GENERATED(scaled_pi);
4391 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);
4392 PROTO_ITEM_SET_GENERATED(scaled_pi);
4396 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);
4397 PROTO_ITEM_SET_GENERATED(scaled_pi);
4402 if(tcph->th_flags & TH_SYN) {
4403 if(tcph->th_flags & TH_ACK) {
4404 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_sack, "Connection establish acknowledge (SYN+ACK): server port %s", get_tcp_port(tcph->th_sport));
4405 /* Save the server port to help determine dissector used */
4406 tcpd->server_port = tcph->th_sport;
4409 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_syn, "Connection establish request (SYN): server port %s",
4410 get_tcp_port(tcph->th_dport));
4411 /* Save the server port to help determine dissector used */
4412 tcpd->server_port = tcph->th_dport;
4415 if(tcph->th_flags & TH_FIN)
4416 /* XXX - find a way to know the server port and output only that one */
4417 expert_add_info(pinfo, tf_fin, &ei_tcp_connection_fin);
4418 if(tcph->th_flags & TH_RST)
4419 /* XXX - find a way to know the server port and output only that one */
4420 expert_add_info(pinfo, tf_rst, &ei_tcp_connection_rst);
4422 /* Supply the sequence number of the first byte and of the first byte
4423 after the segment. */
4424 tcpinfo.seq = tcph->th_seq;
4425 tcpinfo.nxtseq = nxtseq;
4426 tcpinfo.lastackseq = tcph->th_ack;
4428 /* Assume we'll pass un-reassembled data to subdissectors. */
4429 tcpinfo.is_reassembled = FALSE;
4432 * Assume, initially, that we can't desegment.
4434 pinfo->can_desegment = 0;
4435 th_sum = tvb_get_ntohs(tvb, offset + 16);
4436 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
4437 /* The packet isn't part of an un-reassembled fragmented datagram
4438 and isn't truncated. This means we have all the data, and thus
4439 can checksum it and, unless it's being returned in an error
4440 packet, are willing to allow subdissectors to request reassembly
4443 if (tcp_check_checksum) {
4444 /* We haven't turned checksum checking off; checksum it. */
4446 /* Set up the fields of the pseudo-header. */
4447 cksum_vec[0].ptr = (guint8 *)pinfo->src.data;
4448 cksum_vec[0].len = pinfo->src.len;
4449 cksum_vec[1].ptr = (guint8 *)pinfo->dst.data;
4450 cksum_vec[1].len = pinfo->dst.len;
4451 cksum_vec[2].ptr = (const guint8 *)phdr;
4452 switch (pinfo->src.type) {
4455 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
4456 cksum_vec[2].len = 4;
4460 phdr[0] = g_htonl(reported_len);
4461 phdr[1] = g_htonl(IP_PROTO_TCP);
4462 cksum_vec[2].len = 8;
4466 /* TCP runs only atop IPv4 and IPv6.... */
4467 DISSECTOR_ASSERT_NOT_REACHED();
4470 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, reported_len);
4471 cksum_vec[3].len = reported_len;
4472 computed_cksum = in_cksum(cksum_vec, 4);
4473 if (computed_cksum == 0 && th_sum == 0xffff) {
4474 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4475 offset + 16, 2, th_sum,
4476 "0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);
4478 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4479 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4480 offset + 16, 2, FALSE);
4481 PROTO_ITEM_SET_GENERATED(item);
4482 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4483 offset + 16, 2, FALSE);
4484 PROTO_ITEM_SET_GENERATED(item);
4485 expert_add_info(pinfo, item, &ei_tcp_checksum_ffff);
4487 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");
4489 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
4490 desegment_ok = TRUE;
4491 } else if (computed_cksum == 0) {
4492 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4493 offset + 16, 2, th_sum, "0x%04x [correct]", th_sum);
4495 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4496 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4497 offset + 16, 2, TRUE);
4498 PROTO_ITEM_SET_GENERATED(item);
4499 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4500 offset + 16, 2, FALSE);
4501 PROTO_ITEM_SET_GENERATED(item);
4503 /* Checksum is valid, so we're willing to desegment it. */
4504 desegment_ok = TRUE;
4506 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4507 offset + 16, 2, th_sum,
4508 "0x%04x [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]", th_sum,
4509 in_cksum_shouldbe(th_sum, computed_cksum));
4511 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4512 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4513 offset + 16, 2, FALSE);
4514 PROTO_ITEM_SET_GENERATED(item);
4515 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4516 offset + 16, 2, TRUE);
4517 PROTO_ITEM_SET_GENERATED(item);
4518 expert_add_info(pinfo, item, &ei_tcp_checksum_bad);
4520 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");
4522 /* Checksum is invalid, so we're not willing to desegment it. */
4523 desegment_ok = FALSE;
4524 pinfo->noreassembly_reason = " [incorrect TCP checksum]";
4527 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4528 offset + 16, 2, th_sum, "0x%04x [validation disabled]", th_sum);
4530 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4531 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4532 offset + 16, 2, FALSE);
4533 PROTO_ITEM_SET_GENERATED(item);
4534 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4535 offset + 16, 2, FALSE);
4536 PROTO_ITEM_SET_GENERATED(item);
4538 /* We didn't check the checksum, and don't care if it's valid,
4539 so we're willing to desegment it. */
4540 desegment_ok = TRUE;
4543 /* We don't have all the packet data, so we can't checksum it... */
4544 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4545 offset + 16, 2, th_sum, "0x%04x [unchecked, not all data available]", th_sum);
4547 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4548 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4549 offset + 16, 2, FALSE);
4550 PROTO_ITEM_SET_GENERATED(item);
4551 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4552 offset + 16, 2, FALSE);
4553 PROTO_ITEM_SET_GENERATED(item);
4555 /* ...and aren't willing to desegment it. */
4556 desegment_ok = FALSE;
4560 /* We're willing to desegment this. Is desegmentation enabled? */
4561 if (tcp_desegment) {
4562 /* Yes - is this segment being returned in an error packet? */
4563 if (!pinfo->flags.in_error_pkt) {
4564 /* No - indicate that we will desegment.
4565 We do NOT want to desegment segments returned in error
4566 packets, as they're not part of a TCP connection. */
4567 pinfo->can_desegment = 2;
4572 th_urp = tvb_get_ntohs(tvb, offset + 18);
4573 item = proto_tree_add_item(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, ENC_BIG_ENDIAN);
4574 if (tcph->th_flags & TH_URG) {
4575 /* Export the urgent pointer, for the benefit of protocols such as
4577 tcpinfo.urgent = TRUE;
4578 tcpinfo.urgent_pointer = th_urp;
4579 col_append_fstr(pinfo->cinfo, COL_INFO, " Urg=%u", th_urp);
4581 tcpinfo.urgent = FALSE;
4583 /* Note if the urgent pointer field is non-zero */
4584 expert_add_info(pinfo, item, &ei_tcp_urgent_pointer_non_zero);
4588 if (tcph->th_have_seglen) {
4589 col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", tcph->th_seglen);
4592 /* If there's more than just the fixed-length header (20 bytes), decode the options. */
4593 tcph->num_sack_ranges = 0;
4594 if (tcph->th_hlen > TCPH_MIN_LEN) {
4595 guint bc = (guint)MAX(0, tvb_length_remaining(tvb, offset + 20));
4597 optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
4599 if (tcp_tree != NULL) {
4600 /* If the frame has been sliced but the options field is at least 4 bytes, decode as much
4601 * of it as possible; otherwise, set optlen to zero. */
4604 guint8 *p_options = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset + 20, bc);
4606 tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
4607 bc, p_options, "Options: (%u bytes but truncated to %u bytes)", optlen, bc);
4613 guint8 *p_options = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset + 20, optlen);
4615 tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
4616 optlen, p_options, "Options: (%u bytes)", optlen);
4618 field_tree = proto_item_add_subtree(tf, ett_tcp_options);
4624 dissect_ip_tcp_options(tvb, offset + 20, optlen, tcpopts, N_TCP_OPTS, TCPOPT_EOL,
4625 &TCP_OPT_TYPES, &ei_tcp_opt_len_invalid, pinfo, field_tree, tf, tcph);
4628 if(!pinfo->fd->flags.visited) {
4629 if((tcph->th_flags & TH_SYN)==TH_SYN) {
4630 /* Check the validity of the window scale value
4632 verify_tcp_window_scaling((tcph->th_flags&TH_ACK)==TH_ACK,tcpd);
4635 if((tcph->th_flags & (TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
4636 /* If the SYN or the SYN+ACK offered SCPS capabilities,
4637 * validate the flow's bidirectional scps capabilities.
4638 * The or protects against broken implementations offering
4639 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
4641 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {
4642 verify_scps(pinfo, tf_syn, tcpd);
4647 /* Skip over header + options */
4648 offset += tcph->th_hlen;
4650 /* Check the packet length to see if there's more data
4651 (it could be an ACK-only packet) */
4652 length_remaining = MAX(0, tvb_length_remaining(tvb, offset));
4654 if (tcph->th_have_seglen) {
4655 if( data_out_file ) {
4656 reassemble_tcp( tcpd->stream, /* tcp stream index */
4657 tcph->th_seq, /* sequence number */
4658 tcph->th_ack, /* acknowledgment number */
4659 tcph->th_seglen, /* data length */
4660 (gchar*)tvb_get_ptr(tvb, offset, length_remaining), /* data */
4661 length_remaining, /* captured data length */
4662 ( tcph->th_flags & TH_SYN ), /* is syn set? */
4671 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
4672 if(tcp_analyze_seq) {
4673 guint32 use_seq = tcph->th_seq;
4674 guint32 use_ack = tcph->th_ack;
4675 /* May need to recover absolute values here... */
4676 if (tcp_relative_seq) {
4677 use_seq += tcpd->fwd->base_seq;
4678 if (tcph->th_flags & TH_ACK) {
4679 use_ack += tcpd->rev->base_seq;
4682 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd, use_seq, use_ack);
4685 /* handle conversation timestamps */
4686 if(tcp_calculate_ts) {
4687 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
4690 tap_queue_packet(tcp_tap, pinfo, tcph);
4693 /* If we're reassembling something whose length isn't known
4694 * beforehand, and that runs all the way to the end of
4695 * the data stream, a FIN indicates the end of the data
4696 * stream and thus the completion of reassembly, so we
4697 * need to explicitly check for that here.
4699 if(tcph->th_have_seglen && tcpd && (tcph->th_flags & TH_FIN)
4700 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ) {
4701 struct tcp_multisegment_pdu *msp;
4703 /* Is this the FIN that ended the data stream or is it a
4704 * retransmission of that FIN?
4706 if (tcpd->fwd->fin == 0 || tcpd->fwd->fin == pinfo->fd->num) {
4707 /* Either we haven't seen a FIN for this flow or we
4708 * have and it's this frame. Note that this is the FIN
4709 * for this flow, terminate reassembly and dissect the
4711 tcpd->fwd->fin = pinfo->fd->num;
4712 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq-1);
4714 fragment_head *ipfd_head;
4716 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,
4717 pinfo, msp->first_frame, NULL,
4718 tcph->th_seq - msp->seq,
4724 /* create a new TVB structure for desegmented data
4725 * datalen-1 to strip the dummy FIN byte off
4727 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
4729 /* add desegmented data to the data source list */
4730 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
4732 /* Show details of the reassembly */
4733 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
4735 /* call the payload dissector
4736 * but make sure we don't offer desegmentation any more
4738 pinfo->can_desegment = 0;
4740 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq,
4741 nxtseq, FALSE, tcpd, &tcpinfo);
4747 /* Yes. This is a retransmission of the final FIN (or it's
4748 * the final FIN transmitted via a different path).
4749 * XXX - we need to flag retransmissions a bit better.
4751 proto_tree_add_text(tcp_tree, tvb, 0, 0, "Retransmission of FIN from frame %u",
4756 if (tcpd && ((tcpd->fwd && tcpd->fwd->command) || (tcpd->rev && tcpd->rev->command))) {
4757 ti = proto_tree_add_text(tcp_tree, tvb, offset, 0, "Process Information");
4758 PROTO_ITEM_SET_GENERATED(ti);
4759 field_tree = proto_item_add_subtree(ti, ett_tcp_process_info);
4760 if (tcpd->fwd && tcpd->fwd->command) {
4761 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_dst_uid, tvb, 0, 0,
4762 tcpd->fwd->process_uid, "%u", tcpd->fwd->process_uid);
4763 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_dst_pid, tvb, 0, 0,
4764 tcpd->fwd->process_pid, "%u", tcpd->fwd->process_pid);
4765 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_dst_uname, tvb, 0, 0,
4766 tcpd->fwd->username, "%s", tcpd->fwd->username);
4767 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_dst_cmd, tvb, 0, 0,
4768 tcpd->fwd->command, "%s", tcpd->fwd->command);
4770 if (tcpd->rev && tcpd->rev->command) {
4771 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_src_uid, tvb, 0, 0,
4772 tcpd->rev->process_uid, "%u", tcpd->rev->process_uid);
4773 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_src_pid, tvb, 0, 0,
4774 tcpd->rev->process_pid, "%u", tcpd->rev->process_pid);
4775 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_src_uname, tvb, 0, 0,
4776 tcpd->rev->username, "%s", tcpd->rev->username);
4777 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_src_cmd, tvb, 0, 0,
4778 tcpd->rev->command, "%s", tcpd->rev->command);
4783 * XXX - what, if any, of this should we do if this is included in an
4784 * error packet? It might be nice to see the details of the packet
4785 * that caused the ICMP error, but it might not be nice to have the
4786 * dissector update state based on it.
4787 * Also, we probably don't want to run TCP taps on those packets.
4789 if (length_remaining != 0) {
4790 if (tcph->th_flags & TH_RST) {
4794 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
4796 * A TCP SHOULD allow a received RST segment to include data.
4799 * It has been suggested that a RST segment could contain
4800 * ASCII text that encoded and explained the cause of the
4801 * RST. No standard has yet been established for such
4804 * so for segments with RST we just display the data as text.
4806 proto_tree_add_text(tcp_tree, tvb, offset, length_remaining,
4808 tvb_format_text(tvb, offset, length_remaining));
4810 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
4811 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo);
4819 tcp_stream_count = 0;
4820 reassembly_table_init(&tcp_reassembly_table,
4821 &addresses_ports_reassembly_table_functions);
4825 proto_register_tcp(void)
4827 static hf_register_info hf[] = {
4830 { "Source Port", "tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
4834 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
4838 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
4842 { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
4846 { "Sequence number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
4850 { "Next sequence number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
4854 { "Acknowledgment number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
4858 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
4862 { "Flags", "tcp.flags", FT_UINT16, BASE_HEX, NULL, TH_MASK,
4865 { &hf_tcp_flags_res,
4866 { "Reserved", "tcp.flags.res", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RES,
4867 "Three reserved bits (must be zero)", HFILL }},
4870 { "Nonce", "tcp.flags.ns", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_NS,
4871 "ECN concealment protection (RFC 3540)", HFILL }},
4873 { &hf_tcp_flags_cwr,
4874 { "Congestion Window Reduced (CWR)", "tcp.flags.cwr", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_CWR,
4877 { &hf_tcp_flags_ecn,
4878 { "ECN-Echo", "tcp.flags.ecn", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ECN,
4881 { &hf_tcp_flags_urg,
4882 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_URG,
4885 { &hf_tcp_flags_ack,
4886 { "Acknowledgment", "tcp.flags.ack", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ACK,
4889 { &hf_tcp_flags_push,
4890 { "Push", "tcp.flags.push", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_PUSH,
4893 { &hf_tcp_flags_reset,
4894 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RST,
4897 { &hf_tcp_flags_syn,
4898 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_SYN,
4901 { &hf_tcp_flags_fin,
4902 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_FIN,
4905 { &hf_tcp_window_size_value,
4906 { "Window size value", "tcp.window_size_value", FT_UINT16, BASE_DEC, NULL, 0x0,
4907 "The window size value from the TCP header", HFILL }},
4909 /* 32 bits so we can present some values adjusted to window scaling */
4910 { &hf_tcp_window_size,
4911 { "Calculated window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
4912 "The scaled window size (if scaling has been used)", HFILL }},
4914 { &hf_tcp_window_size_scalefactor,
4915 { "Window size scaling factor", "tcp.window_size_scalefactor", FT_INT32, BASE_DEC, NULL, 0x0,
4916 "The window size scaling factor (-1 when unknown, -2 when no scaling is used)", HFILL }},
4919 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
4920 "Details at: http://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
4922 { &hf_tcp_checksum_good,
4923 { "Good Checksum", "tcp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4924 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
4926 { &hf_tcp_checksum_bad,
4927 { "Bad Checksum", "tcp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4928 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
4931 { "SEQ/ACK analysis", "tcp.analysis", FT_NONE, BASE_NONE, NULL, 0x0,
4932 "This frame has some of the TCP analysis shown", HFILL }},
4934 { &hf_tcp_analysis_flags,
4935 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
4936 "This frame has some of the TCP analysis flags set", HFILL }},
4938 { &hf_tcp_analysis_duplicate_ack,
4939 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
4940 "This is a duplicate ACK", HFILL }},
4942 { &hf_tcp_analysis_duplicate_ack_num,
4943 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
4944 "This is duplicate ACK number #", HFILL }},
4946 { &hf_tcp_analysis_duplicate_ack_frame,
4947 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4948 "This is a duplicate to the ACK in frame #", HFILL }},
4950 { &hf_tcp_continuation_to,
4951 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4952 "This is a continuation to the PDU in frame #", HFILL }},
4955 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
4958 { &hf_tcp_analysis_acks_frame,
4959 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4960 "Which previous segment is this an ACK for", HFILL}},
4962 { &hf_tcp_analysis_bytes_in_flight,
4963 { "Bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL, 0x0,
4964 "How many bytes are now in flight for this connection", HFILL}},
4966 { &hf_tcp_analysis_ack_rtt,
4967 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4968 "How long time it took to ACK the segment (RTT)", HFILL}},
4970 { &hf_tcp_analysis_rto,
4971 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4972 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL}},
4974 { &hf_tcp_analysis_rto_frame,
4975 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4976 "This is the frame we measure the RTO from", HFILL }},
4978 { &hf_tcp_urgent_pointer,
4979 { "Urgent pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
4982 { &hf_tcp_segment_overlap,
4983 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4984 "Segment overlaps with other segments", HFILL }},
4986 { &hf_tcp_segment_overlap_conflict,
4987 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4988 "Overlapping segments contained conflicting data", HFILL }},
4990 { &hf_tcp_segment_multiple_tails,
4991 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4992 "Several tails were found when reassembling the pdu", HFILL }},
4994 { &hf_tcp_segment_too_long_fragment,
4995 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4996 "Segment contained data past end of the pdu", HFILL }},
4998 { &hf_tcp_segment_error,
4999 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5000 "Reassembling error due to illegal segments", HFILL }},
5002 { &hf_tcp_segment_count,
5003 { "Segment count", "tcp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
5007 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5011 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
5012 "TCP Segments", HFILL }},
5014 { &hf_tcp_reassembled_in,
5015 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5016 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
5018 { &hf_tcp_reassembled_length,
5019 { "Reassembled TCP length", "tcp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
5020 "The total length of the reassembled payload", HFILL }},
5022 { &hf_tcp_reassembled_data,
5023 { "Reassembled TCP Data", "tcp.reassembled.data", FT_BYTES, BASE_NONE, NULL, 0x0,
5024 "The reassembled payload", HFILL }},
5026 { &hf_tcp_option_kind,
5027 { "Kind", "tcp.option_kind", FT_UINT8,
5028 BASE_DEC, VALS(tcp_option_kind_vs), 0x0, "This TCP option's kind", HFILL }},
5030 { &hf_tcp_option_len,
5031 { "Length", "tcp.option_len", FT_UINT8,
5032 BASE_DEC, NULL, 0x0, "Length of this TCP option in bytes (including kind and length fields)", HFILL }},
5035 { "TCP Options", "tcp.options", FT_BYTES,
5036 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5038 { &hf_tcp_option_mss,
5039 { "TCP MSS Option", "tcp.options.mss", FT_NONE,
5040 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5042 { &hf_tcp_option_mss_val,
5043 { "MSS Value", "tcp.options.mss_val", FT_UINT16,
5044 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5046 { &hf_tcp_option_wscale_shift,
5047 { "Shift count", "tcp.options.wscale.shift", FT_UINT8,
5048 BASE_DEC, NULL, 0x0, "Logarithmically encoded power of 2 scale factor", HFILL}},
5050 { &hf_tcp_option_wscale_multiplier,
5051 { "Multiplier", "tcp.options.wscale.multiplier", FT_UINT8,
5052 BASE_DEC, NULL, 0x0, "Multiply segment window size by this for scaled window size", HFILL}},
5054 { &hf_tcp_option_exp,
5055 { "TCP Option - Experimental", "tcp.options.experimental", FT_BYTES,
5056 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5058 { &hf_tcp_option_exp_data,
5059 { "Data", "tcp.options.experimental.data", FT_BYTES,
5060 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5062 { &hf_tcp_option_exp_magic_number,
5063 { "Magic Number", "tcp.options.experimental.magic_number", FT_UINT16,
5064 BASE_HEX, NULL, 0x0, NULL, HFILL}},
5066 { &hf_tcp_option_sack_perm,
5067 { "TCP SACK Permitted Option", "tcp.options.sack_perm",
5069 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5071 { &hf_tcp_option_sack,
5072 { "TCP SACK Option", "tcp.options.sack", FT_BOOLEAN,
5073 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5075 { &hf_tcp_option_sack_sle,
5076 {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32,
5077 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5079 { &hf_tcp_option_sack_sre,
5080 {"TCP SACK Right Edge", "tcp.options.sack_re", FT_UINT32,
5081 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5083 { &hf_tcp_option_sack_range_count,
5084 { "TCP SACK Count", "tcp.options.sack.count", FT_UINT8,
5085 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5087 { &hf_tcp_option_echo,
5088 { "TCP Echo Option", "tcp.options.echo", FT_BOOLEAN,
5089 BASE_NONE, NULL, 0x0, "TCP Sack Echo", HFILL}},
5091 { &hf_tcp_option_timestamp_tsval,
5092 { "Timestamp value", "tcp.options.timestamp.tsval", FT_UINT32,
5093 BASE_DEC, NULL, 0x0, "Value of sending machine's timestamp clock", HFILL}},
5095 { &hf_tcp_option_timestamp_tsecr,
5096 { "Timestamp echo reply", "tcp.options.timestamp.tsecr", FT_UINT32,
5097 BASE_DEC, NULL, 0x0, "Echoed timestamp from remote machine", HFILL}},
5099 { &hf_tcp_option_mptcp_subtype,
5100 { "Multipath TCP subtype", "tcp.options.mptcp.subtype", FT_UINT8,
5101 BASE_DEC, VALS(mptcp_subtype_vs), 0xF0, NULL, HFILL}},
5103 { &hf_tcp_option_mptcp_version,
5104 { "Multipath TCP version", "tcp.options.mptcp.version", FT_UINT8,
5105 BASE_DEC, NULL, 0x0F, NULL, HFILL}},
5107 { &hf_tcp_option_mptcp_flags,
5108 { "Multipath TCP flags", "tcp.options.mptcp.flags", FT_UINT8,
5109 BASE_HEX, NULL, 0x0, NULL, HFILL}},
5111 { &hf_tcp_option_mptcp_B_flag,
5112 { "Backup flag", "tcp.options.mptcp.backup.flag", FT_UINT8,
5113 BASE_DEC, NULL, 0x01, NULL, HFILL}},
5115 { &hf_tcp_option_mptcp_C_flag,
5116 { "Checksum required", "tcp.options.mptcp.checksumreq.flags", FT_UINT8,
5117 BASE_DEC, NULL, 0x80, NULL, HFILL}},
5119 { &hf_tcp_option_mptcp_S_flag,
5120 { "Use HMAC-SHA1", "tcp.options.mptcp.sha1.flag", FT_UINT8,
5121 BASE_DEC, NULL, 0x01, NULL, HFILL}},
5123 { &hf_tcp_option_mptcp_F_flag,
5124 { "DATA_FIN", "tcp.options.mptcp.datafin.flag", FT_UINT8,
5125 BASE_DEC, NULL, 0x10, NULL, HFILL}},
5127 { &hf_tcp_option_mptcp_m_flag,
5128 { "Data Sequence Number is 8 octets", "tcp.options.mptcp.dseqn8.flag", FT_UINT8,
5129 BASE_DEC, NULL, 0x08, NULL, HFILL}},
5131 { &hf_tcp_option_mptcp_M_flag,
5132 { "Data Sequence Number, Subflow Sequence Number, Data-level Length, Checksum present", "tcp.options.mptcp.dseqnpresent.flag", FT_UINT8,
5133 BASE_DEC, NULL, 0x04, NULL, HFILL}},
5135 { &hf_tcp_option_mptcp_a_flag,
5136 { "Data ACK is 8 octets", "tcp.options.mptcp.dataack8.flag", FT_UINT8,
5137 BASE_DEC, NULL, 0x02, NULL, HFILL}},
5139 { &hf_tcp_option_mptcp_A_flag,
5140 { "Data ACK is present", "tcp.options.mptcp.dataackpresent.flag", FT_UINT8,
5141 BASE_DEC, NULL, 0x01, NULL, HFILL}},
5143 { &hf_tcp_option_mptcp_address_id,
5144 { "Multipath TCP Address ID", "tcp.options.mptcp.addrid", FT_UINT8,
5145 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5147 { &hf_tcp_option_mptcp_sender_key,
5148 { "Multipath TCP Sender's Key", "tcp.options.mptcp.sendkey", FT_UINT64,
5149 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5151 { &hf_tcp_option_mptcp_recv_key,
5152 { "Multipath TCP Receiver's Key", "tcp.options.mptcp.recvkey", FT_UINT64,
5153 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5155 { &hf_tcp_option_mptcp_recv_token,
5156 { "Multipath TCP Receiver's Token", "tcp.options.mptcp.recvtok", FT_UINT32,
5157 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5159 { &hf_tcp_option_mptcp_sender_rand,
5160 { "Multipath TCP Sender's Random Number", "tcp.options.mptcp.sendrand", FT_UINT32,
5161 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5163 { &hf_tcp_option_mptcp_sender_trunc_mac,
5164 { "Multipath TCP Sender's Truncated MAC", "tcp.options.mptcp.sendtruncmac", FT_UINT64,
5165 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5167 { &hf_tcp_option_mptcp_sender_mac,
5168 { "Multipath TCP Sender's MAC", "tcp.options.mptcp.sendmac", FT_UINT32,
5169 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5171 { &hf_tcp_option_mptcp_data_ack,
5172 { "Multipath TCP Data ACK", "tcp.options.mptcp.dataack", FT_UINT64,
5173 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5175 { &hf_tcp_option_mptcp_data_seq_no,
5176 { "Multipath TCP Data Sequence Number", "tcp.options.mptcp.dataseqno", FT_UINT64,
5177 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5179 { &hf_tcp_option_mptcp_subflow_seq_no,
5180 { "Multipath TCP Subflow Sequence Number", "tcp.options.mptcp.subflowseqno", FT_UINT32,
5181 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5183 { &hf_tcp_option_mptcp_data_lvl_len,
5184 { "Multipath TCP Data-level Length", "tcp.options.mptcp.datalvllen", FT_UINT16,
5185 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5187 { &hf_tcp_option_mptcp_checksum,
5188 { "Multipath TCP Checksum", "tcp.options.mptcp.checksum", FT_UINT16,
5189 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5191 { &hf_tcp_option_mptcp_ipver,
5192 { "Multipath TCP IPVer", "tcp.options.mptcp.ipver", FT_UINT8,
5193 BASE_DEC, NULL, 0x0F, NULL, HFILL}},
5195 { &hf_tcp_option_mptcp_ipv4,
5196 { "Multipath TCP Address", "tcp.options.mptcp.ipv4", FT_IPv4,
5197 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5199 { &hf_tcp_option_mptcp_ipv6,
5200 { "Multipath TCP Address", "tcp.options.mptcp.ipv6", FT_IPv6,
5201 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5203 { &hf_tcp_option_mptcp_port,
5204 { "Multipath TCP Port", "tcp.options.mptcp.port", FT_UINT16,
5205 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5207 { &hf_tcp_option_cc,
5208 { "TCP CC Option", "tcp.options.cc", FT_BOOLEAN, BASE_NONE,
5209 NULL, 0x0, NULL, HFILL}},
5211 { &hf_tcp_option_qs,
5212 { "TCP QS Option", "tcp.options.qs", FT_BOOLEAN, BASE_NONE,
5213 NULL, 0x0, NULL, HFILL}},
5215 { &hf_tcp_option_type,
5216 { "Type", "tcp.options.type", FT_UINT8, BASE_DEC,
5217 NULL, 0x0, NULL, HFILL}},
5219 { &hf_tcp_option_type_copy,
5220 { "Copy on fragmentation", "tcp.options.type.copy", FT_BOOLEAN, 8,
5221 TFS(&tfs_yes_no), IPOPT_COPY_MASK, NULL, HFILL}},
5223 { &hf_tcp_option_type_class,
5224 { "Class", "tcp.options.type.class", FT_UINT8, BASE_DEC,
5225 VALS(ipopt_type_class_vals), IPOPT_CLASS_MASK, NULL, HFILL}},
5227 { &hf_tcp_option_type_number,
5228 { "Number", "tcp.options.type.number", FT_UINT8, BASE_DEC,
5229 VALS(ipopt_type_number_vals), IPOPT_NUMBER_MASK, NULL, HFILL}},
5231 { &hf_tcp_option_scps,
5232 { "TCP SCPS Capabilities Option", "tcp.options.scps",
5233 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5236 { &hf_tcp_option_scps_vector,
5237 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
5238 FT_UINT8, BASE_HEX, NULL, 0x0,
5241 { &hf_tcp_option_scps_binding,
5242 { "Binding Space (Community) ID",
5243 "tcp.options.scps.binding.id",
5244 FT_UINT8, BASE_DEC, NULL, 0x0,
5245 "TCP SCPS Extended Binding Space (Community) ID", HFILL}},
5247 { &hf_tcp_option_scps_binding_len,
5248 { "Extended Capability Length",
5249 "tcp.options.scps.binding.len",
5250 FT_UINT8, BASE_DEC, NULL, 0x0,
5251 "TCP SCPS Extended Capability Length in bytes", HFILL}},
5253 { &hf_tcp_option_snack,
5254 { "TCP Selective Negative Acknowledgment Option",
5255 "tcp.options.snack",
5256 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5259 { &hf_tcp_option_snack_offset,
5260 { "TCP SNACK Offset", "tcp.options.snack.offset",
5261 FT_UINT16, BASE_DEC, NULL, 0x0,
5264 { &hf_tcp_option_snack_size,
5265 { "TCP SNACK Size", "tcp.options.snack.size",
5266 FT_UINT16, BASE_DEC, NULL, 0x0,
5269 { &hf_tcp_option_snack_le,
5270 { "TCP SNACK Left Edge", "tcp.options.snack.le",
5271 FT_UINT16, BASE_DEC, NULL, 0x0,
5274 { &hf_tcp_option_snack_re,
5275 { "TCP SNACK Right Edge", "tcp.options.snack.re",
5276 FT_UINT16, BASE_DEC, NULL, 0x0,
5279 { &hf_tcp_scpsoption_flags_bets,
5280 { "Partial Reliability Capable (BETS)",
5281 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,
5282 TFS(&tfs_set_notset), 0x80, NULL, HFILL }},
5284 { &hf_tcp_scpsoption_flags_snack1,
5285 { "Short Form SNACK Capable (SNACK1)",
5286 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,
5287 TFS(&tfs_set_notset), 0x40, NULL, HFILL }},
5289 { &hf_tcp_scpsoption_flags_snack2,
5290 { "Long Form SNACK Capable (SNACK2)",
5291 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,
5292 TFS(&tfs_set_notset), 0x20, NULL, HFILL }},
5294 { &hf_tcp_scpsoption_flags_compress,
5295 { "Lossless Header Compression (COMP)",
5296 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,
5297 TFS(&tfs_set_notset), 0x10, NULL, HFILL }},
5299 { &hf_tcp_scpsoption_flags_nlts,
5300 { "Network Layer Timestamp (NLTS)",
5301 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,
5302 TFS(&tfs_set_notset), 0x8, NULL, HFILL }},
5304 { &hf_tcp_scpsoption_flags_reserved,
5306 "tcp.options.scpsflags.reserved", FT_UINT8, BASE_DEC,
5307 NULL, 0x7, NULL, HFILL }},
5309 { &hf_tcp_scpsoption_connection_id,
5311 "tcp.options.scps.binding",
5312 FT_UINT8, BASE_DEC, NULL, 0x0,
5313 "TCP SCPS Connection ID", HFILL}},
5315 { &hf_tcp_option_user_to,
5316 { "TCP User Timeout", "tcp.options.user_to", FT_BOOLEAN,
5317 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5319 { &hf_tcp_option_user_to_granularity,
5320 { "Granularity", "tcp.options.user_to_granularity", FT_BOOLEAN,
5321 16, TFS(&tcp_option_user_to_granularity), 0x8000, "TCP User Timeout Granularity", HFILL}},
5323 { &hf_tcp_option_user_to_val,
5324 { "User Timeout", "tcp.options.user_to_val", FT_UINT16,
5325 BASE_DEC, NULL, 0x7FFF, "TCP User Timeout Value", HFILL}},
5327 { &hf_tcp_option_rvbd_probe,
5328 { "Riverbed Probe", "tcp.options.rvbd.probe", FT_BOOLEAN,
5329 BASE_NONE, NULL, 0x0, "RVBD TCP Probe Option", HFILL }},
5331 { &hf_tcp_option_rvbd_probe_type1,
5332 { "Type", "tcp.options.rvbd.probe.type1",
5333 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
5335 { &hf_tcp_option_rvbd_probe_type2,
5336 { "Type", "tcp.options.rvbd.probe.type2",
5337 FT_UINT8, BASE_DEC, NULL, 0xFE, NULL, HFILL }},
5339 { &hf_tcp_option_rvbd_probe_version1,
5340 { "Version", "tcp.options.rvbd.probe.version",
5341 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
5343 { &hf_tcp_option_rvbd_probe_version2,
5344 { "Version", "tcp.options.rvbd.probe.version_raw",
5345 FT_UINT8, BASE_DEC, NULL, 0x01, "Version 2 Raw Value", HFILL }},
5347 { &hf_tcp_option_rvbd_probe_optlen,
5348 { "Length", "tcp.options.rvbd.probe.len",
5349 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5351 { &hf_tcp_option_rvbd_probe_prober,
5352 { "CSH IP", "tcp.options.rvbd.probe.prober",
5353 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5355 { &hf_tcp_option_rvbd_probe_proxy,
5356 { "SSH IP", "tcp.options.rvbd.probe.proxy.ip",
5357 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5359 { &hf_tcp_option_rvbd_probe_proxy_port,
5360 { "SSH Port", "tcp.options.rvbd.probe.proxy.port",
5361 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5363 { &hf_tcp_option_rvbd_probe_appli_ver,
5364 { "Application Version", "tcp.options.rvbd.probe.appli_ver",
5365 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5367 { &hf_tcp_option_rvbd_probe_client,
5368 { "Client IP", "tcp.options.rvbd.probe.client.ip",
5369 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5371 { &hf_tcp_option_rvbd_probe_storeid,
5372 { "CFE Store ID", "tcp.options.rvbd.probe.storeid",
5373 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5375 { &hf_tcp_option_rvbd_probe_flags,
5376 { "Probe Flags", "tcp.options.rvbd.probe.flags",
5377 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5379 { &hf_tcp_option_rvbd_probe_flag_not_cfe,
5380 { "Not CFE", "tcp.options.rvbd.probe.flags.notcfe",
5381 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_NCFE,
5384 { &hf_tcp_option_rvbd_probe_flag_last_notify,
5385 { "Last Notify", "tcp.options.rvbd.probe.flags.last",
5386 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_LAST,
5389 { &hf_tcp_option_rvbd_probe_flag_probe_cache,
5390 { "Disable Probe Cache on CSH", "tcp.options.rvbd.probe.flags.probe",
5391 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE,
5394 { &hf_tcp_option_rvbd_probe_flag_sslcert,
5395 { "SSL Enabled", "tcp.options.rvbd.probe.flags.ssl",
5396 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SSLCERT,
5399 { &hf_tcp_option_rvbd_probe_flag_server_connected,
5400 { "SSH outer to server established", "tcp.options.rvbd.probe.flags.server",
5401 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SERVER,
5404 { &hf_tcp_option_rvbd_trpy,
5405 { "Riverbed Transparency", "tcp.options.rvbd.trpy",
5406 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5407 "RVBD TCP Transparency Option", HFILL }},
5409 { &hf_tcp_option_rvbd_trpy_flags,
5410 { "Transparency Options", "tcp.options.rvbd.trpy.flags",
5411 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5413 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
5414 { "Enable FW traversal feature", "tcp.options.rvbd.trpy.flags.fw_rst_probe",
5415 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5416 RVBD_FLAGS_TRPY_FW_RST_PROBE,
5417 "Reset state created by probe on the nexthop firewall",
5420 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
5421 { "Enable Inner FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst_inner",
5422 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5423 RVBD_FLAGS_TRPY_FW_RST_INNER,
5424 "Reset state created by transparent inner on all firewalls"
5425 " before passing connection through",
5428 { &hf_tcp_option_rvbd_trpy_flag_fw_rst,
5429 { "Enable Transparency FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst",
5430 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5431 RVBD_FLAGS_TRPY_FW_RST,
5432 "Reset state created by probe on all firewalls before "
5433 "establishing transparent inner connection", HFILL }},
5435 { &hf_tcp_option_rvbd_trpy_flag_chksum,
5436 { "Reserved", "tcp.options.rvbd.trpy.flags.chksum",
5437 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5438 RVBD_FLAGS_TRPY_CHKSUM, NULL, HFILL }},
5440 { &hf_tcp_option_rvbd_trpy_flag_oob,
5441 { "Out of band connection", "tcp.options.rvbd.trpy.flags.oob",
5442 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5443 RVBD_FLAGS_TRPY_OOB, NULL, HFILL }},
5445 { &hf_tcp_option_rvbd_trpy_flag_mode,
5446 { "Transparency Mode", "tcp.options.rvbd.trpy.flags.mode",
5447 FT_BOOLEAN, 16, TFS(&trpy_mode_str),
5448 RVBD_FLAGS_TRPY_MODE, NULL, HFILL }},
5450 { &hf_tcp_option_rvbd_trpy_src,
5451 { "Src SH IP Addr", "tcp.options.rvbd.trpy.src.ip",
5452 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5454 { &hf_tcp_option_rvbd_trpy_dst,
5455 { "Dst SH IP Addr", "tcp.options.rvbd.trpy.dst.ip",
5456 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5458 { &hf_tcp_option_rvbd_trpy_src_port,
5459 { "Src SH Inner Port", "tcp.options.rvbd.trpy.src.port",
5460 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5462 { &hf_tcp_option_rvbd_trpy_dst_port,
5463 { "Dst SH Inner Port", "tcp.options.rvbd.trpy.dst.port",
5464 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5466 { &hf_tcp_option_rvbd_trpy_client_port,
5467 { "Out of band connection Client Port", "tcp.options.rvbd.trpy.client.port",
5468 FT_UINT16, BASE_DEC, NULL , 0x0, NULL, HFILL }},
5470 { &hf_tcp_option_fast_open,
5471 { "Fast Open", "tcp.options.tfo", FT_NONE,
5472 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5474 { &hf_tcp_option_fast_open_cookie_request,
5475 { "Fast Open Cookie Request", "tcp.options.tfo.request", FT_NONE,
5476 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5478 { &hf_tcp_option_fast_open_cookie,
5479 { "Fast Open Cookie", "tcp.options.tfo.cookie", FT_BYTES,
5480 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5483 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5484 "How long time has passed until the last frame of this PDU", HFILL}},
5487 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL, 0x0,
5488 "The size of this PDU", HFILL}},
5490 { &hf_tcp_pdu_last_frame,
5491 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5492 "This is the last frame of the PDU starting in this segment", HFILL }},
5494 { &hf_tcp_ts_relative,
5495 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5496 "Time relative to first frame in this TCP stream", HFILL}},
5499 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5500 "Time delta from previous frame in this TCP stream", HFILL}},
5502 { &hf_tcp_proc_src_uid,
5503 { "Source process user ID", "tcp.proc.srcuid", FT_UINT32, BASE_DEC, NULL, 0x0,
5506 { &hf_tcp_proc_src_pid,
5507 { "Source process ID", "tcp.proc.srcpid", FT_UINT32, BASE_DEC, NULL, 0x0,
5510 { &hf_tcp_proc_src_uname,
5511 { "Source process user name", "tcp.proc.srcuname", FT_STRING, BASE_NONE, NULL, 0x0,
5514 { &hf_tcp_proc_src_cmd,
5515 { "Source process name", "tcp.proc.srccmd", FT_STRING, BASE_NONE, NULL, 0x0,
5516 "Source process command name", HFILL}},
5518 { &hf_tcp_proc_dst_uid,
5519 { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32, BASE_DEC, NULL, 0x0,
5522 { &hf_tcp_proc_dst_pid,
5523 { "Destination process ID", "tcp.proc.dstpid", FT_UINT32, BASE_DEC, NULL, 0x0,
5526 { &hf_tcp_proc_dst_uname,
5527 { "Destination process user name", "tcp.proc.dstuname", FT_STRING, BASE_NONE, NULL, 0x0,
5530 { &hf_tcp_proc_dst_cmd,
5531 { "Destination process name", "tcp.proc.dstcmd", FT_STRING, BASE_NONE, NULL, 0x0,
5532 "Destination process command name", HFILL}},
5534 { &hf_tcp_segment_data,
5535 { "TCP segment data", "tcp.segment_data", FT_BYTES, BASE_NONE, NULL, 0x0,
5536 "A data segment used in reassembly of a lower-level protocol", HFILL}}
5539 static gint *ett[] = {
5542 &ett_tcp_option_type,
5544 &ett_tcp_option_timestamp,
5545 &ett_tcp_option_mptcp,
5546 &ett_tcp_option_wscale,
5547 &ett_tcp_option_sack,
5548 &ett_tcp_option_scps,
5549 &ett_tcp_option_scps_extended,
5550 &ett_tcp_option_user_to,
5551 &ett_tcp_option_exp,
5552 &ett_tcp_option_sack_perm,
5553 &ett_tcp_option_mss,
5554 &ett_tcp_opt_rvbd_probe,
5555 &ett_tcp_opt_rvbd_probe_flags,
5556 &ett_tcp_opt_rvbd_trpy,
5557 &ett_tcp_opt_rvbd_trpy_flags,
5558 &ett_tcp_analysis_faults,
5560 &ett_tcp_timestamps,
5564 &ett_tcp_process_info
5567 static const enum_val_t window_scaling_vals[] = {
5568 {"not-known", "Not known", WindowScaling_NotKnown},
5569 {"0", "0 (no scaling)", WindowScaling_0},
5570 {"1", "1 (multiply by 2)", WindowScaling_1},
5571 {"2", "2 (multiply by 4)", WindowScaling_2},
5572 {"3", "3 (multiply by 8)", WindowScaling_3},
5573 {"4", "4 (multiply by 16)", WindowScaling_4},
5574 {"5", "5 (multiply by 32)", WindowScaling_5},
5575 {"6", "6 (multiply by 64)", WindowScaling_6},
5576 {"7", "7 (multiply by 128)", WindowScaling_7},
5577 {"8", "8 (multiply by 256)", WindowScaling_8},
5578 {"9", "9 (multiply by 512)", WindowScaling_9},
5579 {"10", "10 (multiply by 1024)", WindowScaling_10},
5580 {"11", "11 (multiply by 2048)", WindowScaling_11},
5581 {"12", "12 (multiply by 4096)", WindowScaling_12},
5582 {"13", "13 (multiply by 8192)", WindowScaling_13},
5583 {"14", "14 (multiply by 16384)", WindowScaling_14},
5587 static ei_register_info ei[] = {
5588 { &ei_tcp_opt_len_invalid, { "tcp.option.len.invalid", PI_SEQUENCE, PI_NOTE, "Invalid length for option", EXPFILL }},
5589 { &ei_tcp_analysis_retransmission, { "tcp.analysis.retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) retransmission", EXPFILL }},
5590 { &ei_tcp_analysis_fast_retransmission, { "tcp.analysis.fast_retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) fast retransmission", EXPFILL }},
5591 { &ei_tcp_analysis_spurious_retransmission, { "tcp.analysis.spurious_retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) spurious retransmission", EXPFILL }},
5592 { &ei_tcp_analysis_out_of_order, { "tcp.analysis.out_of_order", PI_SEQUENCE, PI_WARN, "This frame is a (suspected) out-of-order segment", EXPFILL }},
5593 { &ei_tcp_analysis_reused_ports, { "tcp.analysis.reused_ports", PI_SEQUENCE, PI_NOTE, "A new tcp session is started with the same ports as an earlier session in this trace", EXPFILL }},
5594 { &ei_tcp_analysis_lost_packet, { "tcp.analysis.lost_segment", PI_SEQUENCE, PI_WARN, "Previous segment not captured (common at capture start)", EXPFILL }},
5595 { &ei_tcp_analysis_ack_lost_packet, { "tcp.analysis.ack_lost_segment", PI_SEQUENCE, PI_WARN, "ACKed segment that wasn't captured (common at capture start)", EXPFILL }},
5596 { &ei_tcp_analysis_window_update, { "tcp.analysis.window_update", PI_SEQUENCE, PI_CHAT, "TCP window update", EXPFILL }},
5597 { &ei_tcp_analysis_window_full, { "tcp.analysis.window_full", PI_SEQUENCE, PI_WARN, "TCP transmission window is now completely full", EXPFILL }},
5598 { &ei_tcp_analysis_keep_alive, { "tcp.analysis.keep_alive", PI_SEQUENCE, PI_NOTE, "TCP keep-alive segment", EXPFILL }},
5599 { &ei_tcp_analysis_keep_alive_ack, { "tcp.analysis.keep_alive_ack", PI_SEQUENCE, PI_NOTE, "ACK to a TCP keep-alive segment", EXPFILL }},
5600 { &ei_tcp_analysis_duplicate_ack, { "tcp.analysis.duplicate_ack", PI_SEQUENCE, PI_NOTE, "Duplicate ACK", EXPFILL }},
5601 { &ei_tcp_analysis_zero_window_probe, { "tcp.analysis.zero_window_probe", PI_SEQUENCE, PI_NOTE, "TCP Zero Window Probe", EXPFILL }},
5602 { &ei_tcp_analysis_zero_window, { "tcp.analysis.zero_window", PI_SEQUENCE, PI_WARN, "TCP Zero Window segment", EXPFILL }},
5603 { &ei_tcp_analysis_zero_window_probe_ack, { "tcp.analysis.zero_window_probe_ack", PI_SEQUENCE, PI_NOTE, "ACK to a TCP Zero Window Probe", EXPFILL }},
5604 { &ei_tcp_scps_capable, { "tcp.analysis.zero_window_probe_ack", PI_SEQUENCE, PI_NOTE, "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated", EXPFILL }},
5605 { &ei_tcp_option_snack_sequence, { "tcp.options.snack.sequence", PI_SEQUENCE, PI_NOTE, "SNACK Sequence", EXPFILL }},
5606 { &ei_tcp_short_segment, { "tcp.short_segment", PI_MALFORMED, PI_WARN, "Short segment", EXPFILL }},
5607 { &ei_tcp_ack_nonzero, { "tcp.ack.nonzero", PI_PROTOCOL, PI_NOTE, "The acknowledgment number field is nonzero while the ACK flag is not set", EXPFILL }},
5608 { &ei_tcp_connection_sack, { "tcp.connection.sack", PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK)", EXPFILL }},
5609 { &ei_tcp_connection_syn, { "tcp.connection.syn", PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN)", EXPFILL }},
5610 { &ei_tcp_connection_fin, { "tcp.connection.fin", PI_SEQUENCE, PI_CHAT, "Connection finish (FIN)", EXPFILL }},
5611 { &ei_tcp_connection_rst, { "tcp.connection.rst", PI_SEQUENCE, PI_CHAT, "Connection reset (RST)", EXPFILL }},
5612 { &ei_tcp_checksum_ffff, { "tcp.checksum.ffff", PI_CHECKSUM, PI_WARN, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)", EXPFILL }},
5613 { &ei_tcp_checksum_bad, { "tcp.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
5614 { &ei_tcp_urgent_pointer_non_zero, { "tcp.urgent_pointer.non_zero", PI_PROTOCOL, PI_NOTE, "The urgent pointer field is nonzero while the URG flag is not set", EXPFILL }}
5617 static build_valid_func tcp_da_src_values[1] = {tcp_src_value};
5618 static build_valid_func tcp_da_dst_values[1] = {tcp_dst_value};
5619 static build_valid_func tcp_da_both_values[2] = {tcp_src_value, tcp_dst_value};
5620 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}};
5621 static decode_as_t tcp_da = {"tcp", "Transport", "tcp.port", 3, 2, tcp_da_values, "TCP", "port(s) as",
5622 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
5624 module_t *tcp_module;
5625 expert_module_t* expert_tcp;
5627 proto_tcp = proto_register_protocol("Transmission Control Protocol", "TCP", "tcp");
5628 register_dissector("tcp", dissect_tcp, proto_tcp);
5629 proto_register_field_array(proto_tcp, hf, array_length(hf));
5630 proto_register_subtree_array(ett, array_length(ett));
5631 expert_tcp = expert_register_protocol(proto_tcp);
5632 expert_register_field_array(expert_tcp, ei, array_length(ei));
5634 /* subdissector code */
5635 subdissector_table = register_dissector_table("tcp.port",
5636 "TCP port", FT_UINT16, BASE_DEC);
5637 register_heur_dissector_list("tcp", &heur_subdissector_list);
5639 /* Register configuration preferences */
5640 tcp_module = prefs_register_protocol(proto_tcp, NULL);
5641 prefs_register_bool_preference(tcp_module, "summary_in_tree",
5642 "Show TCP summary in protocol tree",
5643 "Whether the TCP summary line should be shown in the protocol tree",
5644 &tcp_summary_in_tree);
5645 prefs_register_bool_preference(tcp_module, "check_checksum",
5646 "Validate the TCP checksum if possible",
5647 "Whether to validate the TCP checksum or not. "
5648 "(Invalid checksums will cause reassembly, if enabled, to fail.)",
5649 &tcp_check_checksum);
5650 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
5651 "Allow subdissector to reassemble TCP streams",
5652 "Whether subdissector can request TCP streams to be reassembled",
5654 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
5655 "Analyze TCP sequence numbers",
5656 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
5658 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
5659 "Relative sequence numbers",
5660 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
5661 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
5663 prefs_register_enum_preference(tcp_module, "default_window_scaling",
5664 "Scaling factor to use when not available from capture",
5665 "Make the TCP dissector use this scaling factor for streams where the signalled scaling factor "
5666 "is not visible in the capture",
5667 &tcp_default_window_scaling, window_scaling_vals, FALSE);
5669 /* Presumably a retired, unconditional version of what has been added back with the preference above... */
5670 prefs_register_obsolete_preference(tcp_module, "window_scaling");
5672 prefs_register_bool_preference(tcp_module, "track_bytes_in_flight",
5673 "Track number of bytes in flight",
5674 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "
5675 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
5676 "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",
5677 &tcp_track_bytes_in_flight);
5678 prefs_register_bool_preference(tcp_module, "calculate_timestamps",
5679 "Calculate conversation timestamps",
5680 "Calculate timestamps relative to the first frame and the previous frame in the tcp conversation",
5682 prefs_register_bool_preference(tcp_module, "try_heuristic_first",
5683 "Try heuristic sub-dissectors first",
5684 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
5685 &try_heuristic_first);
5686 prefs_register_bool_preference(tcp_module, "ignore_tcp_timestamps",
5687 "Ignore TCP Timestamps in summary",
5688 "Do not place the TCP Timestamps in the summary line",
5689 &tcp_ignore_timestamps);
5691 prefs_register_bool_preference(tcp_module, "no_subdissector_on_error",
5692 "Do not call subdissectors for error packets",
5693 "Do not call any subdissectors for Retransmitted or OutOfOrder segments",
5694 &tcp_no_subdissector_on_error);
5696 prefs_register_bool_preference(tcp_module, "dissect_experimental_options_with_magic",
5697 "TCP Experimental Options with a Magic Number",
5698 "Assume TCP Experimental Options (253, 254) have a Magic Number and use it for dissection",
5699 &tcp_exp_options_with_magic);
5701 register_init_routine(tcp_init);
5703 register_decode_as(&tcp_da);
5707 proto_reg_handoff_tcp(void)
5709 dissector_handle_t tcp_handle;
5711 tcp_handle = find_dissector("tcp");
5712 dissector_add_uint("ip.proto", IP_PROTO_TCP, tcp_handle);
5713 data_handle = find_dissector("data");
5714 sport_handle = find_dissector("sport");
5715 tcp_tap = register_tap("tcp");
5724 * indent-tabs-mode: nil
5727 * ex: set shiftwidth=4 tabstop=8 expandtab:
5728 * :indentSize=4:tabSize=8:noTabs=true: