HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-tcp.c
blobda8c1fd6d8b2198feee531444ca64feac8ea17f2
1 /* packet-tcp.c
2 * Routines for TCP packet disassembly
4 * $Id$
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.
25 #include "config.h"
27 #include <stdio.h>
28 #include <string.h>
29 #include <glib.h>
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>
44 #include <epan/tap.h>
46 #include "packet-tcp.h"
47 #include "packet-ip.h"
48 #include "packet-icmp.h"
50 static int tcp_tap = -1;
52 /* Place TCP summary in proto tree */
53 static gboolean tcp_summary_in_tree = TRUE;
56 * Flag to control whether to check the TCP checksum.
58 * In at least some Solaris network traces, there are packets with bad
59 * TCP checksums, but the traffic appears to indicate that the packets
60 * *were* received; the packets were probably sent by the host on which
61 * the capture was being done, on a network interface to which
62 * checksumming was offloaded, so that DLPI supplied an un-checksummed
63 * packet to the capture program but a checksummed packet got put onto
64 * the wire.
66 static gboolean tcp_check_checksum = FALSE;
69 * Window scaling values to be used when not known (set as a preference) */
70 enum scaling_window_value {
71 WindowScaling_NotKnown=-1,
72 WindowScaling_0=0,
73 WindowScaling_1,
74 WindowScaling_2,
75 WindowScaling_3,
76 WindowScaling_4,
77 WindowScaling_5,
78 WindowScaling_6,
79 WindowScaling_7,
80 WindowScaling_8,
81 WindowScaling_9,
82 WindowScaling_10,
83 WindowScaling_11,
84 WindowScaling_12,
85 WindowScaling_13,
86 WindowScaling_14
88 static gint tcp_default_window_scaling = (gint)WindowScaling_NotKnown;
91 extern FILE* data_out_file;
93 static int proto_tcp = -1;
94 static int hf_tcp_srcport = -1;
95 static int hf_tcp_dstport = -1;
96 static int hf_tcp_port = -1;
97 static int hf_tcp_stream = -1;
98 static int hf_tcp_seq = -1;
99 static int hf_tcp_nxtseq = -1;
100 static int hf_tcp_ack = -1;
101 static int hf_tcp_hdr_len = -1;
102 static int hf_tcp_flags = -1;
103 static int hf_tcp_flags_res = -1;
104 static int hf_tcp_flags_ns = -1;
105 static int hf_tcp_flags_cwr = -1;
106 static int hf_tcp_flags_ecn = -1;
107 static int hf_tcp_flags_urg = -1;
108 static int hf_tcp_flags_ack = -1;
109 static int hf_tcp_flags_push = -1;
110 static int hf_tcp_flags_reset = -1;
111 static int hf_tcp_flags_syn = -1;
112 static int hf_tcp_flags_fin = -1;
113 static int hf_tcp_window_size_value = -1;
114 static int hf_tcp_window_size = -1;
115 static int hf_tcp_window_size_scalefactor = -1;
116 static int hf_tcp_checksum = -1;
117 static int hf_tcp_checksum_bad = -1;
118 static int hf_tcp_checksum_good = -1;
119 static int hf_tcp_len = -1;
120 static int hf_tcp_urgent_pointer = -1;
121 static int hf_tcp_analysis = -1;
122 static int hf_tcp_analysis_flags = -1;
123 static int hf_tcp_analysis_bytes_in_flight = -1;
124 static int hf_tcp_analysis_acks_frame = -1;
125 static int hf_tcp_analysis_ack_rtt = -1;
126 static int hf_tcp_analysis_rto = -1;
127 static int hf_tcp_analysis_rto_frame = -1;
128 static int hf_tcp_analysis_duplicate_ack = -1;
129 static int hf_tcp_analysis_duplicate_ack_num = -1;
130 static int hf_tcp_analysis_duplicate_ack_frame = -1;
131 static int hf_tcp_continuation_to = -1;
132 static int hf_tcp_pdu_time = -1;
133 static int hf_tcp_pdu_size = -1;
134 static int hf_tcp_pdu_last_frame = -1;
135 static int hf_tcp_reassembled_in = -1;
136 static int hf_tcp_reassembled_length = -1;
137 static int hf_tcp_reassembled_data = -1;
138 static int hf_tcp_segments = -1;
139 static int hf_tcp_segment = -1;
140 static int hf_tcp_segment_overlap = -1;
141 static int hf_tcp_segment_overlap_conflict = -1;
142 static int hf_tcp_segment_multiple_tails = -1;
143 static int hf_tcp_segment_too_long_fragment = -1;
144 static int hf_tcp_segment_error = -1;
145 static int hf_tcp_segment_count = -1;
146 static int hf_tcp_options = -1;
147 static int hf_tcp_option_kind = -1;
148 static int hf_tcp_option_len = -1;
149 static int hf_tcp_option_mss = -1;
150 static int hf_tcp_option_mss_val = -1;
151 static int hf_tcp_option_wscale_shift = -1;
152 static int hf_tcp_option_wscale_multiplier = -1;
153 static int hf_tcp_option_sack_perm = -1;
154 static int hf_tcp_option_sack = -1;
155 static int hf_tcp_option_sack_sle = -1;
156 static int hf_tcp_option_sack_sre = -1;
157 static int hf_tcp_option_sack_range_count = -1;
158 static int hf_tcp_option_echo = -1;
159 static int hf_tcp_option_timestamp_tsval = -1;
160 static int hf_tcp_option_timestamp_tsecr = -1;
161 static int hf_tcp_option_cc = -1;
162 static int hf_tcp_option_qs = -1;
163 static int hf_tcp_option_exp = -1;
164 static int hf_tcp_option_exp_data = -1;
165 static int hf_tcp_option_exp_magic_number = -1;
167 static int hf_tcp_option_rvbd_probe = -1;
168 static int hf_tcp_option_rvbd_probe_version1 = -1;
169 static int hf_tcp_option_rvbd_probe_version2 = -1;
170 static int hf_tcp_option_rvbd_probe_type1 = -1;
171 static int hf_tcp_option_rvbd_probe_type2 = -1;
172 static int hf_tcp_option_rvbd_probe_optlen = -1;
173 static int hf_tcp_option_rvbd_probe_prober = -1;
174 static int hf_tcp_option_rvbd_probe_proxy = -1;
175 static int hf_tcp_option_rvbd_probe_client = -1;
176 static int hf_tcp_option_rvbd_probe_proxy_port = -1;
177 static int hf_tcp_option_rvbd_probe_appli_ver = -1;
178 static int hf_tcp_option_rvbd_probe_storeid = -1;
179 static int hf_tcp_option_rvbd_probe_flags = -1;
180 static int hf_tcp_option_rvbd_probe_flag_last_notify = -1;
181 static int hf_tcp_option_rvbd_probe_flag_server_connected = -1;
182 static int hf_tcp_option_rvbd_probe_flag_not_cfe = -1;
183 static int hf_tcp_option_rvbd_probe_flag_sslcert = -1;
184 static int hf_tcp_option_rvbd_probe_flag_probe_cache = -1;
186 static int hf_tcp_option_rvbd_trpy = -1;
187 static int hf_tcp_option_rvbd_trpy_flags = -1;
188 static int hf_tcp_option_rvbd_trpy_flag_mode = -1;
189 static int hf_tcp_option_rvbd_trpy_flag_oob = -1;
190 static int hf_tcp_option_rvbd_trpy_flag_chksum = -1;
191 static int hf_tcp_option_rvbd_trpy_flag_fw_rst = -1;
192 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_inner = -1;
193 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_probe = -1;
194 static int hf_tcp_option_rvbd_trpy_src = -1;
195 static int hf_tcp_option_rvbd_trpy_dst = -1;
196 static int hf_tcp_option_rvbd_trpy_src_port = -1;
197 static int hf_tcp_option_rvbd_trpy_dst_port = -1;
198 static int hf_tcp_option_rvbd_trpy_client_port = -1;
200 static int hf_tcp_option_mptcp_flags = -1;
201 static int hf_tcp_option_mptcp_B_flag = -1;
202 static int hf_tcp_option_mptcp_C_flag = -1;
203 static int hf_tcp_option_mptcp_S_flag = -1;
204 static int hf_tcp_option_mptcp_F_flag = -1;
205 static int hf_tcp_option_mptcp_m_flag = -1;
206 static int hf_tcp_option_mptcp_M_flag = -1;
207 static int hf_tcp_option_mptcp_a_flag = -1;
208 static int hf_tcp_option_mptcp_A_flag = -1;
209 static int hf_tcp_option_mptcp_subtype = -1;
210 static int hf_tcp_option_mptcp_version = -1;
211 static int hf_tcp_option_mptcp_address_id = -1;
212 static int hf_tcp_option_mptcp_recv_token = -1;
213 static int hf_tcp_option_mptcp_sender_key = -1;
214 static int hf_tcp_option_mptcp_recv_key = -1;
215 static int hf_tcp_option_mptcp_sender_rand = -1;
216 static int hf_tcp_option_mptcp_sender_trunc_mac = -1;
217 static int hf_tcp_option_mptcp_sender_mac = -1;
218 static int hf_tcp_option_mptcp_data_ack = -1;
219 static int hf_tcp_option_mptcp_data_seq_no = -1;
220 static int hf_tcp_option_mptcp_subflow_seq_no = -1;
221 static int hf_tcp_option_mptcp_data_lvl_len = -1;
222 static int hf_tcp_option_mptcp_checksum = -1;
223 static int hf_tcp_option_mptcp_ipver = -1;
224 static int hf_tcp_option_mptcp_ipv4 = -1;
225 static int hf_tcp_option_mptcp_ipv6 = -1;
226 static int hf_tcp_option_mptcp_port = -1;
227 static int hf_tcp_option_fast_open = -1;
228 static int hf_tcp_option_fast_open_cookie_request = -1;
229 static int hf_tcp_option_fast_open_cookie = -1;
231 static int hf_tcp_ts_relative = -1;
232 static int hf_tcp_ts_delta = -1;
233 static int hf_tcp_option_type = -1;
234 static int hf_tcp_option_type_copy = -1;
235 static int hf_tcp_option_type_class = -1;
236 static int hf_tcp_option_type_number = -1;
237 static int hf_tcp_option_scps = -1;
238 static int hf_tcp_option_scps_vector = -1;
239 static int hf_tcp_option_scps_binding = -1;
240 static int hf_tcp_option_scps_binding_len = -1;
241 static int hf_tcp_scpsoption_flags_bets = -1;
242 static int hf_tcp_scpsoption_flags_snack1 = -1;
243 static int hf_tcp_scpsoption_flags_snack2 = -1;
244 static int hf_tcp_scpsoption_flags_compress = -1;
245 static int hf_tcp_scpsoption_flags_nlts = -1;
246 static int hf_tcp_scpsoption_flags_reserved = -1;
247 static int hf_tcp_scpsoption_connection_id = -1;
248 static int hf_tcp_option_snack = -1;
249 static int hf_tcp_option_snack_offset = -1;
250 static int hf_tcp_option_snack_size = -1;
251 static int hf_tcp_option_snack_le = -1;
252 static int hf_tcp_option_snack_re = -1;
253 static int hf_tcp_option_user_to = -1;
254 static int hf_tcp_option_user_to_granularity = -1;
255 static int hf_tcp_option_user_to_val = -1;
256 static int hf_tcp_proc_src_uid = -1;
257 static int hf_tcp_proc_src_pid = -1;
258 static int hf_tcp_proc_src_uname = -1;
259 static int hf_tcp_proc_src_cmd = -1;
260 static int hf_tcp_proc_dst_uid = -1;
261 static int hf_tcp_proc_dst_pid = -1;
262 static int hf_tcp_proc_dst_uname = -1;
263 static int hf_tcp_proc_dst_cmd = -1;
264 static int hf_tcp_segment_data = -1;
266 static gint ett_tcp = -1;
267 static gint ett_tcp_flags = -1;
268 static gint ett_tcp_option_type = -1;
269 static gint ett_tcp_options = -1;
270 static gint ett_tcp_option_timestamp = -1;
271 static gint ett_tcp_option_mss = -1;
272 static gint ett_tcp_option_wscale = -1;
273 static gint ett_tcp_option_sack = -1;
274 static gint ett_tcp_option_scps = -1;
275 static gint ett_tcp_option_scps_extended = -1;
276 static gint ett_tcp_option_user_to = -1;
277 static gint ett_tcp_option_exp = -1;
278 static gint ett_tcp_option_sack_perm = -1;
279 static gint ett_tcp_analysis = -1;
280 static gint ett_tcp_analysis_faults = -1;
281 static gint ett_tcp_timestamps = -1;
282 static gint ett_tcp_segments = -1;
283 static gint ett_tcp_segment = -1;
284 static gint ett_tcp_checksum = -1;
285 static gint ett_tcp_process_info = -1;
286 static gint ett_tcp_option_mptcp = -1;
288 static gint ett_tcp_opt_rvbd_probe = -1;
289 static gint ett_tcp_opt_rvbd_probe_flags = -1;
290 static gint ett_tcp_opt_rvbd_trpy = -1;
291 static gint ett_tcp_opt_rvbd_trpy_flags = -1;
293 static expert_field ei_tcp_opt_len_invalid = EI_INIT;
294 static expert_field ei_tcp_analysis_retransmission = EI_INIT;
295 static expert_field ei_tcp_analysis_fast_retransmission = EI_INIT;
296 static expert_field ei_tcp_analysis_spurious_retransmission = EI_INIT;
297 static expert_field ei_tcp_analysis_out_of_order = EI_INIT;
298 static expert_field ei_tcp_analysis_reused_ports = EI_INIT;
299 static expert_field ei_tcp_analysis_lost_packet = EI_INIT;
300 static expert_field ei_tcp_analysis_ack_lost_packet = EI_INIT;
301 static expert_field ei_tcp_analysis_window_update = EI_INIT;
302 static expert_field ei_tcp_analysis_window_full = EI_INIT;
303 static expert_field ei_tcp_analysis_keep_alive = EI_INIT;
304 static expert_field ei_tcp_analysis_keep_alive_ack = EI_INIT;
305 static expert_field ei_tcp_analysis_duplicate_ack = EI_INIT;
306 static expert_field ei_tcp_analysis_zero_window_probe = EI_INIT;
307 static expert_field ei_tcp_analysis_zero_window = EI_INIT;
308 static expert_field ei_tcp_analysis_zero_window_probe_ack = EI_INIT;
309 static expert_field ei_tcp_scps_capable = EI_INIT;
310 static expert_field ei_tcp_option_snack_sequence = EI_INIT;
311 static expert_field ei_tcp_short_segment = EI_INIT;
312 static expert_field ei_tcp_ack_nonzero = EI_INIT;
313 static expert_field ei_tcp_connection_sack = EI_INIT;
314 static expert_field ei_tcp_connection_syn = EI_INIT;
315 static expert_field ei_tcp_connection_fin = EI_INIT;
316 static expert_field ei_tcp_connection_rst = EI_INIT;
317 static expert_field ei_tcp_checksum_ffff = EI_INIT;
318 static expert_field ei_tcp_checksum_bad = EI_INIT;
319 static expert_field ei_tcp_urgent_pointer_non_zero = EI_INIT;
321 /* Some protocols such as encrypted DCE/RPCoverHTTP have dependencies
322 * from one PDU to the next PDU and require that they are called in sequence.
323 * These protocols would not be able to handle PDUs coming out of order
324 * or for example when a PDU is seen twice, like for retransmissions.
325 * This preference can be set for such protocols to make sure that we don't
326 * invoke the subdissectors for retransmitted or out-of-order segments.
328 static gboolean tcp_no_subdissector_on_error = FALSE;
331 * FF: (draft-ietf-tcpm-experimental-options-03)
332 * With this flag set we assume the option structure for experimental
333 * codepoints (253, 254) has a magic number field (first field after the
334 * Kind and Length). The magic number is used to differentiate different
335 * experiments and thus will be used in data dissection.
337 static gboolean tcp_exp_options_with_magic = TRUE;
340 * TCP option
342 #define TCPOPT_NOP 1 /* Padding */
343 #define TCPOPT_EOL 0 /* End of options */
344 #define TCPOPT_MSS 2 /* Segment size negotiating */
345 #define TCPOPT_WINDOW 3 /* Window scaling */
346 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
347 #define TCPOPT_SACK 5 /* SACK Block */
348 #define TCPOPT_ECHO 6
349 #define TCPOPT_ECHOREPLY 7
350 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
351 #define TCPOPT_CC 11
352 #define TCPOPT_CCNEW 12
353 #define TCPOPT_CCECHO 13
354 #define TCPOPT_MD5 19 /* RFC2385 */
355 #define TCPOPT_MPTCP 0x1e /* Multipath TCP */
356 #define TCPOPT_SCPS 20 /* SCPS Capabilities */
357 #define TCPOPT_SNACK 21 /* SCPS SNACK */
358 #define TCPOPT_RECBOUND 22 /* SCPS Record Boundary */
359 #define TCPOPT_CORREXP 23 /* SCPS Corruption Experienced */
360 #define TCPOPT_QS 27 /* RFC4782 */
361 #define TCPOPT_USER_TO 28 /* RFC5482 */
362 #define TCPOPT_EXP_FD 0xfd /* Experimental, reserved */
363 #define TCPOPT_EXP_FE 0xfe /* Experimental, reserved */
364 /* Non IANA registered option numbers */
365 #define TCPOPT_RVBD_PROBE 76 /* Riverbed probe option */
366 #define TCPOPT_RVBD_TRPY 78 /* Riverbed transparency option */
369 * TCP option lengths
371 #define TCPOLEN_MSS 4
372 #define TCPOLEN_WINDOW 3
373 #define TCPOLEN_SACK_PERM 2
374 #define TCPOLEN_SACK_MIN 2
375 #define TCPOLEN_ECHO 6
376 #define TCPOLEN_ECHOREPLY 6
377 #define TCPOLEN_TIMESTAMP 10
378 #define TCPOLEN_CC 6
379 #define TCPOLEN_CCNEW 6
380 #define TCPOLEN_CCECHO 6
381 #define TCPOLEN_MD5 18
382 #define TCPOLEN_MPTCP_MIN 8
383 #define TCPOLEN_SCPS 4
384 #define TCPOLEN_SNACK 6
385 #define TCPOLEN_RECBOUND 2
386 #define TCPOLEN_CORREXP 2
387 #define TCPOLEN_QS 8
388 #define TCPOLEN_USER_TO 4
389 #define TCPOLEN_RVBD_PROBE_MIN 3
390 #define TCPOLEN_RVBD_TRPY_MIN 16
391 #define TCPOLEN_EXP_MIN 2
394 * Multipath TCP subtypes
396 #define TCPOPT_MPTCP_MP_CAPABLE 0x0 /* Multipath TCP Multipath Capable */
397 #define TCPOPT_MPTCP_MP_JOIN 0x1 /* Multipath TCP Join Connection */
398 #define TCPOPT_MPTCP_DSS 0x2 /* Multipath TCP Data Sequence Signal */
399 #define TCPOPT_MPTCP_ADD_ADDR 0x3 /* Multipath TCP Add Address */
400 #define TCPOPT_MPTCP_REMOVE_ADDR 0x4 /* Multipath TCP Remove Address */
401 #define TCPOPT_MPTCP_MP_PRIO 0x5 /* Multipath TCP Change Subflow Priority */
402 #define TCPOPT_MPTCP_MP_FAIL 0x6 /* Multipath TCP Fallback */
404 static const true_false_string tcp_option_user_to_granularity = {
405 "Minutes", "Seconds"
408 static const value_string tcp_option_kind_vs[] = {
409 { TCPOPT_EXP_FD, "Experimental 0xFD" },
410 { TCPOPT_EXP_FE, "Experimental 0xFE" },
411 { TCPOPT_WINDOW, "Window Scale" },
412 { TCPOPT_SACK_PERM, "SACK Permission" },
413 { TCPOPT_MSS, "MSS size" },
414 { TCPOPT_TIMESTAMP, "Timestamp" },
415 { TCPOPT_MPTCP, "Multipath TCP" },
416 { 0, NULL }
419 /* not all of the hf_fields below make sense for TCP but we have to provide
420 them anyways to comply with the API (which was aimed for IP fragment
421 reassembly) */
422 static const fragment_items tcp_segment_items = {
423 &ett_tcp_segment,
424 &ett_tcp_segments,
425 &hf_tcp_segments,
426 &hf_tcp_segment,
427 &hf_tcp_segment_overlap,
428 &hf_tcp_segment_overlap_conflict,
429 &hf_tcp_segment_multiple_tails,
430 &hf_tcp_segment_too_long_fragment,
431 &hf_tcp_segment_error,
432 &hf_tcp_segment_count,
433 &hf_tcp_reassembled_in,
434 &hf_tcp_reassembled_length,
435 &hf_tcp_reassembled_data,
436 "Segments"
439 static const value_string mptcp_subtype_vs[] = {
440 { TCPOPT_MPTCP_MP_CAPABLE, "Multipath Capable" },
441 { TCPOPT_MPTCP_MP_JOIN, "Join Connection" },
442 { TCPOPT_MPTCP_DSS, "Data Sequence Signal" },
443 { TCPOPT_MPTCP_ADD_ADDR, "Add Address"},
444 { TCPOPT_MPTCP_REMOVE_ADDR, "Remove Address" },
445 { TCPOPT_MPTCP_MP_PRIO, "Change Subflow Priority" },
446 { TCPOPT_MPTCP_MP_FAIL, "TCP Fallback" },
447 { 0, NULL }
450 static dissector_table_t subdissector_table;
451 static heur_dissector_list_t heur_subdissector_list;
452 static dissector_handle_t data_handle;
453 static dissector_handle_t sport_handle;
454 static guint32 tcp_stream_count;
456 /* TCP structs and definitions */
458 /* **************************************************************************
459 * RTT, relative sequence numbers, window scaling & etc.
460 * **************************************************************************/
461 static gboolean tcp_analyze_seq = TRUE;
462 static gboolean tcp_relative_seq = TRUE;
463 static gboolean tcp_track_bytes_in_flight = TRUE;
464 static gboolean tcp_calculate_ts = FALSE;
466 #define TCP_A_RETRANSMISSION 0x0001
467 #define TCP_A_LOST_PACKET 0x0002
468 #define TCP_A_ACK_LOST_PACKET 0x0004
469 #define TCP_A_KEEP_ALIVE 0x0008
470 #define TCP_A_DUPLICATE_ACK 0x0010
471 #define TCP_A_ZERO_WINDOW 0x0020
472 #define TCP_A_ZERO_WINDOW_PROBE 0x0040
473 #define TCP_A_ZERO_WINDOW_PROBE_ACK 0x0080
474 #define TCP_A_KEEP_ALIVE_ACK 0x0100
475 #define TCP_A_OUT_OF_ORDER 0x0200
476 #define TCP_A_FAST_RETRANSMISSION 0x0400
477 #define TCP_A_WINDOW_UPDATE 0x0800
478 #define TCP_A_WINDOW_FULL 0x1000
479 #define TCP_A_REUSED_PORTS 0x2000
480 #define TCP_A_SPURIOUS_RETRANSMISSION 0x4000
482 static void
483 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
484 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
485 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
486 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo);
489 struct tcp_analysis *
490 init_tcp_conversation_data(packet_info *pinfo)
492 struct tcp_analysis *tcpd;
494 /* Initialize the tcp protocol data structure to add to the tcp conversation */
495 tcpd=wmem_new0(wmem_file_scope(), struct tcp_analysis);
496 tcpd->flow1.win_scale=-1;
497 tcpd->flow1.window = G_MAXUINT32;
498 tcpd->flow1.multisegment_pdus=wmem_tree_new(wmem_file_scope());
500 tcpd->flow1.username = NULL;
501 tcpd->flow1.command = NULL;
503 tcpd->flow2.window = G_MAXUINT32;
504 tcpd->flow2.win_scale=-1;
505 tcpd->flow2.multisegment_pdus=wmem_tree_new(wmem_file_scope());
507 tcpd->flow2.username = NULL;
508 tcpd->flow2.command = NULL;
510 tcpd->acked_table=wmem_tree_new(wmem_file_scope());
511 tcpd->ts_first.secs=pinfo->fd->abs_ts.secs;
512 tcpd->ts_first.nsecs=pinfo->fd->abs_ts.nsecs;
513 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
514 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
515 tcpd->flow1.valid_bif = 1;
516 tcpd->flow2.valid_bif = 1;
517 tcpd->stream = tcp_stream_count++;
518 tcpd->server_port = 0;
520 return tcpd;
523 struct tcp_analysis *
524 get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)
526 int direction;
527 struct tcp_analysis *tcpd;
529 /* Did the caller supply the conversation pointer? */
530 if( conv==NULL )
531 conv = find_or_create_conversation(pinfo);
533 /* Get the data for this conversation */
534 tcpd=(struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
536 /* If the conversation was just created or it matched a
537 * conversation with template options, tcpd will not
538 * have been initialized. So, initialize
539 * a new tcpd structure for the conversation.
541 if (!tcpd) {
542 tcpd = init_tcp_conversation_data(pinfo);
543 conversation_add_proto_data(conv, proto_tcp, tcpd);
546 if (!tcpd) {
547 return NULL;
550 /* check direction and get ua lists */
551 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
552 /* if the addresses are equal, match the ports instead */
553 if(direction==0) {
554 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
556 if(direction>=0) {
557 tcpd->fwd=&(tcpd->flow1);
558 tcpd->rev=&(tcpd->flow2);
559 } else {
560 tcpd->fwd=&(tcpd->flow2);
561 tcpd->rev=&(tcpd->flow1);
564 tcpd->ta=NULL;
565 return tcpd;
568 /* Attach process info to a flow */
569 /* XXX - We depend on the TCP dissector finding the conversation first */
570 void
571 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) {
572 conversation_t *conv;
573 struct tcp_analysis *tcpd;
574 tcp_flow_t *flow = NULL;
576 conv = find_conversation(frame_num, local_addr, remote_addr, PT_TCP, local_port, remote_port, 0);
577 if (!conv) {
578 return;
581 tcpd = (struct tcp_analysis *)conversation_get_proto_data(conv, proto_tcp);
582 if (!tcpd) {
583 return;
586 if (CMP_ADDRESS(local_addr, &conv->key_ptr->addr1) == 0 && local_port == conv->key_ptr->port1) {
587 flow = &tcpd->flow1;
588 } else if (CMP_ADDRESS(remote_addr, &conv->key_ptr->addr1) == 0 && remote_port == conv->key_ptr->port1) {
589 flow = &tcpd->flow2;
591 if (!flow || flow->command) {
592 return;
595 flow->process_uid = uid;
596 flow->process_pid = pid;
597 flow->username = wmem_strdup(wmem_file_scope(), username);
598 flow->command = wmem_strdup(wmem_file_scope(), command);
601 /* Return the current stream count */
602 guint32 get_tcp_stream_count(void)
604 return tcp_stream_count;
607 /* Calculate the timestamps relative to this conversation */
608 static void
609 tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
610 struct tcp_per_packet_data_t *tcppd)
612 if( !tcppd ) {
613 tcppd = wmem_new(wmem_file_scope(), struct tcp_per_packet_data_t);
614 p_add_proto_data(pinfo->fd, proto_tcp, 0, tcppd);
617 if (!tcpd)
618 return;
620 nstime_delta(&tcppd->ts_del, &pinfo->fd->abs_ts, &tcpd->ts_prev);
622 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
623 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
626 /* Add a subtree with the timestamps relative to this conversation */
627 static void
628 tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
630 proto_item *item;
631 proto_tree *tree;
632 nstime_t ts;
634 if (!tcpd)
635 return;
637 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "Timestamps");
638 PROTO_ITEM_SET_GENERATED(item);
639 tree=proto_item_add_subtree(item, ett_tcp_timestamps);
641 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
642 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);
643 PROTO_ITEM_SET_GENERATED(item);
645 if( !tcppd )
646 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(pinfo->fd, proto_tcp, 0);
648 if( tcppd ) {
649 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,
650 &tcppd->ts_del);
651 PROTO_ITEM_SET_GENERATED(item);
655 static void
656 print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)
658 proto_item *item;
660 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);
661 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
662 tvb, 0, 0, msp->first_frame);
663 PROTO_ITEM_SET_GENERATED(item);
666 /* if we know that a PDU starts inside this segment, return the adjusted
667 offset to where that PDU starts or just return offset back
668 and let TCP try to find out what it can about this segment
670 static int
671 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)
673 struct tcp_multisegment_pdu *msp=NULL;
675 if(!pinfo->fd->flags.visited) {
676 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);
677 if(msp) {
678 /* If this is a continuation of a PDU started in a
679 * previous segment we need to update the last_frame
680 * variables.
682 if(seq>msp->seq && seq<msp->nxtpdu) {
683 msp->last_frame=pinfo->fd->num;
684 msp->last_frame_time=pinfo->fd->abs_ts;
685 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
688 /* If this segment is completely within a previous PDU
689 * then we just skip this packet
691 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {
692 return -1;
694 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {
695 offset+=msp->nxtpdu-seq;
696 return offset;
700 } else {
701 /* First we try to find the start and transfer time for a PDU.
702 * We only print this for the very first segment of a PDU
703 * and only for PDUs spanning multiple segments.
704 * Se we look for if there was any multisegment PDU started
705 * just BEFORE the end of this segment. I.e. either inside this
706 * segment or in a previous segment.
707 * Since this might also match PDUs that are completely within
708 * this segment we also verify that the found PDU does span
709 * beyond the end of this segment.
711 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, nxtseq-1);
712 if(msp) {
713 if(pinfo->fd->num==msp->first_frame) {
714 proto_item *item;
715 nstime_t ns;
717 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);
718 PROTO_ITEM_SET_GENERATED(item);
720 nstime_delta(&ns, &msp->last_frame_time, &pinfo->fd->abs_ts);
721 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,
722 tvb, 0, 0, &ns);
723 PROTO_ITEM_SET_GENERATED(item);
727 /* Second we check if this segment is part of a PDU started
728 * prior to the segment (seq-1)
730 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(multisegment_pdus, seq-1);
731 if(msp) {
732 /* If this segment is completely within a previous PDU
733 * then we just skip this packet
735 if(seq>msp->seq && nxtseq<=msp->nxtpdu) {
736 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
737 return -1;
740 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu) {
741 offset+=msp->nxtpdu-seq;
742 return offset;
747 return offset;
750 /* if we saw a PDU that extended beyond the end of the segment,
751 use this function to remember where the next pdu starts
753 struct tcp_multisegment_pdu *
754 pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, wmem_tree_t *multisegment_pdus)
756 struct tcp_multisegment_pdu *msp;
758 msp=wmem_new(wmem_file_scope(), struct tcp_multisegment_pdu);
759 msp->nxtpdu=nxtpdu;
760 msp->seq=seq;
761 msp->first_frame=pinfo->fd->num;
762 msp->last_frame=pinfo->fd->num;
763 msp->last_frame_time=pinfo->fd->abs_ts;
764 msp->flags=0;
765 wmem_tree_insert32(multisegment_pdus, seq, (void *)msp);
766 return msp;
769 /* This is called for SYN and SYN+ACK packets and the purpose is to verify
770 * that we have seen window scaling in both directions.
771 * If we cant find window scaling being set in both directions
772 * that means it was present in the SYN but not in the SYN+ACK
773 * (or the SYN was missing) and then we disable the window scaling
774 * for this tcp session.
776 static void
777 verify_tcp_window_scaling(gboolean is_synack, struct tcp_analysis *tcpd)
779 if( tcpd->fwd->win_scale==-1 ) {
780 /* We know window scaling will not be used as:
781 * a) this is the SYN and it does not have the WS option
782 * (we set the reverse win_scale also in case we miss
783 * the SYN/ACK)
784 * b) this is the SYN/ACK and either the SYN packet has not
785 * been seen or it did have the WS option. As the SYN/ACK
786 * does not have the WS option, window scaling will not be used.
788 * Setting win_scale to -2 to indicate that we can
789 * trust the window_size value in the TCP header.
791 tcpd->fwd->win_scale = -2;
792 tcpd->rev->win_scale = -2;
794 } else if( is_synack && tcpd->rev->win_scale==-2 ) {
795 /* The SYN/ACK has the WS option, while the SYN did not,
796 * this should not happen, but the endpoints will not
797 * have used window scaling, so we will neither
799 tcpd->fwd->win_scale = -2;
803 /* if we saw a window scaling option, store it for future reference
805 static void
806 pdu_store_window_scale_option(guint8 ws, struct tcp_analysis *tcpd)
808 if (tcpd)
809 tcpd->fwd->win_scale=ws;
812 /* when this function returns, it will (if createflag) populate the ta pointer.
814 static void
815 tcp_analyze_get_acked_struct(guint32 frame, guint32 seq, guint32 ack, gboolean createflag, struct tcp_analysis *tcpd)
817 wmem_tree_key_t key[] = {{1, &frame}, {1, &seq}, {1, &ack}, {0, NULL}};
819 if (!tcpd) {
820 return;
823 tcpd->ta = (struct tcp_acked *)wmem_tree_lookup32_array(tcpd->acked_table, key);
824 if((!tcpd->ta) && createflag) {
825 tcpd->ta = wmem_new0(wmem_file_scope(), struct tcp_acked);
826 wmem_tree_insert32_array(tcpd->acked_table, key, (void *)tcpd->ta);
831 /* fwd contains a list of all segments processed but not yet ACKed in the
832 * same direction as the current segment.
833 * rev contains a list of all segments received but not yet ACKed in the
834 * opposite direction to the current segment.
836 * New segments are always added to the head of the fwd/rev lists.
839 static void
840 tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint16 flags, guint32 window, struct tcp_analysis *tcpd)
842 tcp_unacked_t *ual=NULL;
843 tcp_unacked_t *prevual=NULL;
844 guint32 nextseq;
845 int ackcount;
847 #if 0
848 printf("\nanalyze_sequence numbers frame:%u\n",pinfo->fd->num);
849 printf("FWD list lastflags:0x%04x base_seq:%u:\n",tcpd->fwd->lastsegmentflags,tcpd->fwd->base_seq);
850 for(ual=tcpd->fwd->segments; ual; ual=ual->next)
851 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);
852 printf("REV list lastflags:0x%04x base_seq:%u:\n",tcpd->rev->lastsegmentflags,tcpd->rev->base_seq);
853 for(ual=tcpd->rev->segments; ual; ual=ual->next)
854 printf("Frame:%d Seq:%u Nextseq:%u\n",ual->frame,ual->seq,ual->nextseq);
855 #endif
857 if (!tcpd) {
858 return;
861 /* if this is the first segment for this list we need to store the
862 * base_seq
864 * Start relative seq and ack numbers at 1 if this
865 * is not a SYN packet. This makes the relative
866 * seq/ack numbers to be displayed correctly in the
867 * event that the SYN or SYN/ACK packet is not seen
868 * (this solves bug 1542)
870 if(tcpd->fwd->base_seq==0) {
871 tcpd->fwd->base_seq = (flags & TH_SYN) ? seq : seq-1;
874 /* Only store reverse sequence if this isn't the SYN
875 * There's no guarantee that the ACK field of a SYN
876 * contains zeros; get the ISN from the first segment
877 * with the ACK bit set instead (usually the SYN/ACK).
879 * If the SYN and SYN/ACK were received out-of-order,
880 * the ISN is ack-1. If we missed the SYN/ACK, but got
881 * the last ACK of the 3WHS, the ISN is ack-1. For all
882 * other packets the ISN is unknown, so ack-1 is
883 * as good a guess as ack.
885 if( (tcpd->rev->base_seq==0) && (flags & TH_ACK) ) {
886 tcpd->rev->base_seq = ack-1;
889 if( flags & TH_ACK ) {
890 tcpd->rev->valid_bif = 1;
893 /* ZERO WINDOW PROBE
894 * it is a zero window probe if
895 * the sequence number is the next expected one
896 * the window in the other direction is 0
897 * the segment is exactly 1 byte
899 /*QQQ tested*/
900 if( seglen==1
901 && seq==tcpd->fwd->nextseq
902 && tcpd->rev->window==0 ) {
903 if(!tcpd->ta) {
904 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
906 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
907 goto finished_fwd;
911 /* ZERO WINDOW
912 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
914 /*QQQ tested*/
915 if( window==0
916 && (flags&(TH_RST|TH_FIN|TH_SYN))==0 ) {
917 if(!tcpd->ta) {
918 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
920 tcpd->ta->flags|=TCP_A_ZERO_WINDOW;
924 /* LOST PACKET
925 * If this segment is beyond the last seen nextseq we must
926 * have missed some previous segment
928 * We only check for this if we have actually seen segments prior to this
929 * one.
930 * RST packets are not checked for this.
932 if( tcpd->fwd->nextseq
933 && GT_SEQ(seq, tcpd->fwd->nextseq)
934 && (flags&(TH_RST))==0 ) {
935 if(!tcpd->ta) {
936 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
938 tcpd->ta->flags|=TCP_A_LOST_PACKET;
940 /* Disable BiF until an ACK is seen in the other direction */
941 tcpd->fwd->valid_bif = 0;
945 /* KEEP ALIVE
946 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
947 * to what should be the next sequence number.
948 * SYN/FIN/RST segments are never keepalives
950 /*QQQ tested */
951 if( (seglen==0||seglen==1)
952 && seq==(tcpd->fwd->nextseq-1)
953 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
954 if(!tcpd->ta) {
955 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
957 tcpd->ta->flags|=TCP_A_KEEP_ALIVE;
960 /* WINDOW UPDATE
961 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
962 * the previous seen segment and with a new window value
964 if( seglen==0
965 && window
966 && window!=tcpd->fwd->window
967 && seq==tcpd->fwd->nextseq
968 && ack==tcpd->fwd->lastack
969 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
970 if(!tcpd->ta) {
971 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
973 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
977 /* WINDOW FULL
978 * If we know the window scaling
979 * and if this segment contains data and goes all the way to the
980 * edge of the advertised window
981 * then we mark it as WINDOW FULL
982 * SYN/RST/FIN packets are never WINDOW FULL
984 /*QQQ tested*/
985 if( seglen>0
986 && tcpd->rev->win_scale!=-1
987 && (seq+seglen)==(tcpd->rev->lastack+(tcpd->rev->window<<(tcpd->rev->win_scale==-2?0:tcpd->rev->win_scale)))
988 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
989 if(!tcpd->ta) {
990 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
992 tcpd->ta->flags|=TCP_A_WINDOW_FULL;
996 /* KEEP ALIVE ACK
997 * It is a keepalive ack if it repeats the previous ACK and if
998 * the last segment in the reverse direction was a keepalive
1000 /*QQQ tested*/
1001 if( seglen==0
1002 && window
1003 && window==tcpd->fwd->window
1004 && seq==tcpd->fwd->nextseq
1005 && ack==tcpd->fwd->lastack
1006 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
1007 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
1008 if(!tcpd->ta) {
1009 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1011 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK;
1012 goto finished_fwd;
1016 /* ZERO WINDOW PROBE ACK
1017 * It is a zerowindowprobe ack if it repeats the previous ACK and if
1018 * the last segment in the reverse direction was a zerowindowprobe
1019 * It also repeats the previous zero window indication
1021 /*QQQ tested*/
1022 if( seglen==0
1023 && window==0
1024 && window==tcpd->fwd->window
1025 && seq==tcpd->fwd->nextseq
1026 && ack==tcpd->fwd->lastack
1027 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
1028 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
1029 if(!tcpd->ta) {
1030 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1032 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
1033 goto finished_fwd;
1037 /* DUPLICATE ACK
1038 * It is a duplicate ack if window/seq/ack is the same as the previous
1039 * segment and if the segment length is 0
1041 if( seglen==0
1042 && window
1043 && window==tcpd->fwd->window
1044 && seq==tcpd->fwd->nextseq
1045 && ack==tcpd->fwd->lastack
1046 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ) {
1047 tcpd->fwd->dupacknum++;
1048 if(!tcpd->ta) {
1049 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1051 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
1052 tcpd->ta->dupack_num=tcpd->fwd->dupacknum;
1053 tcpd->ta->dupack_frame=tcpd->fwd->lastnondupack;
1058 finished_fwd:
1059 /* If this was NOT a dupack we must reset the dupack counters */
1060 if( (!tcpd->ta) || !(tcpd->ta->flags&TCP_A_DUPLICATE_ACK) ) {
1061 tcpd->fwd->lastnondupack=pinfo->fd->num;
1062 tcpd->fwd->dupacknum=0;
1066 /* ACKED LOST PACKET
1067 * If this segment acks beyond the 'max seq to be acked' in the other direction
1068 * then that means we have missed packets going in the
1069 * other direction
1071 * We only check this if we have actually seen some seq numbers
1072 * in the other direction.
1074 if( tcpd->rev->maxseqtobeacked
1075 && GT_SEQ(ack, tcpd->rev->maxseqtobeacked )
1076 && (flags&(TH_ACK))!=0 ) {
1077 /*QQQ tested*/
1078 if(!tcpd->ta) {
1079 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1081 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
1082 /* update 'max seq to be acked' in the other direction so we don't get
1083 * this indication again.
1085 tcpd->rev->maxseqtobeacked=tcpd->rev->nextseq;
1089 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
1090 * If the segment contains data (or is a SYN or a FIN) and
1091 * if it does not advance the sequence number, it must be one
1092 * of these three.
1093 * Only test for this if we know what the seq number should be
1094 * (tcpd->fwd->nextseq)
1096 * Note that a simple KeepAlive is not a retransmission
1098 if( (seglen>0 || flags&(TH_SYN|TH_FIN))
1099 && tcpd->fwd->nextseq
1100 && (LT_SEQ(seq, tcpd->fwd->nextseq)) ) {
1101 guint64 t;
1103 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ) {
1104 goto finished_checking_retransmission_type;
1107 /* If there were >=2 duplicate ACKs in the reverse direction
1108 * (there might be duplicate acks missing from the trace)
1109 * and if this sequence number matches those ACKs
1110 * and if the packet occurs within 20ms of the last
1111 * duplicate ack
1112 * then this is a fast retransmission
1114 t=(pinfo->fd->abs_ts.secs-tcpd->rev->lastacktime.secs)*1000000000;
1115 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->rev->lastacktime.nsecs;
1116 if( tcpd->rev->dupacknum>=2
1117 && tcpd->rev->lastack==seq
1118 && t<20000000 ) {
1119 if(!tcpd->ta) {
1120 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1122 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
1123 goto finished_checking_retransmission_type;
1126 /* If the segment came <3ms since the segment with the highest
1127 * seen sequence number and it doesn't look like a retransmission
1128 * then it is an OUT-OF-ORDER segment.
1129 * (3ms is an arbitrary number)
1131 t=(pinfo->fd->abs_ts.secs-tcpd->fwd->nextseqtime.secs)*1000000000;
1132 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->fwd->nextseqtime.nsecs;
1133 if( t<3000000
1134 && tcpd->fwd->nextseq != seq + seglen ) {
1135 if(!tcpd->ta) {
1136 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1138 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
1139 goto finished_checking_retransmission_type;
1142 /* Check for spurious retransmission. If the current seq + segment length
1143 * is less then the receivers lastask, the packet contains duplicated
1144 * data and may be considered spurious.
1146 if ( seq + seglen < tcpd->rev->lastack ) {
1147 if(!tcpd->ta){
1148 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1150 tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION;
1151 goto finished_checking_retransmission_type;
1154 /* Then it has to be a generic retransmission */
1155 if(!tcpd->ta) {
1156 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1158 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
1159 nstime_delta(&tcpd->ta->rto_ts, &pinfo->fd->abs_ts, &tcpd->fwd->nextseqtime);
1160 tcpd->ta->rto_frame=tcpd->fwd->nextseqframe;
1163 finished_checking_retransmission_type:
1165 nextseq = seq+seglen;
1166 if (seglen || flags&(TH_SYN|TH_FIN)) {
1167 /* add this new sequence number to the fwd list */
1168 ual = wmem_new(wmem_file_scope(), tcp_unacked_t);
1169 ual->next=tcpd->fwd->segments;
1170 tcpd->fwd->segments=ual;
1171 ual->frame=pinfo->fd->num;
1172 ual->seq=seq;
1173 ual->ts=pinfo->fd->abs_ts;
1175 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
1176 if( (flags&(TH_SYN|TH_FIN)) ) {
1177 nextseq+=1;
1179 ual->nextseq=nextseq;
1182 /* Store the highest number seen so far for nextseq so we can detect
1183 * when we receive segments that arrive with a "hole"
1184 * If we don't have anything since before, just store what we got.
1185 * ZeroWindowProbes are special and don't really advance the nextseq
1187 if(GT_SEQ(nextseq, tcpd->fwd->nextseq) || !tcpd->fwd->nextseq) {
1188 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
1189 tcpd->fwd->nextseq=nextseq;
1190 tcpd->fwd->nextseqframe=pinfo->fd->num;
1191 tcpd->fwd->nextseqtime.secs=pinfo->fd->abs_ts.secs;
1192 tcpd->fwd->nextseqtime.nsecs=pinfo->fd->abs_ts.nsecs;
1196 /* Store the highest continuous seq number seen so far for 'max seq to be acked',
1197 so we can detect TCP_A_ACK_LOST_PACKET condition
1199 if(EQ_SEQ(seq, tcpd->fwd->maxseqtobeacked) || !tcpd->fwd->maxseqtobeacked) {
1200 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ) {
1201 tcpd->fwd->maxseqtobeacked=tcpd->fwd->nextseq;
1206 /* remember what the ack/window is so we can track window updates and retransmissions */
1207 tcpd->fwd->window=window;
1208 tcpd->fwd->lastack=ack;
1209 tcpd->fwd->lastacktime.secs=pinfo->fd->abs_ts.secs;
1210 tcpd->fwd->lastacktime.nsecs=pinfo->fd->abs_ts.nsecs;
1213 /* if there were any flags set for this segment we need to remember them
1214 * we only remember the flags for the very last segment though.
1216 if(tcpd->ta) {
1217 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;
1218 } else {
1219 tcpd->fwd->lastsegmentflags=0;
1223 /* remove all segments this ACKs and we don't need to keep around any more
1225 ackcount=0;
1226 prevual = NULL;
1227 ual = tcpd->rev->segments;
1228 while(ual) {
1229 tcp_unacked_t *tmpual;
1231 /* If this ack matches the segment, process accordingly */
1232 if(ack==ual->nextseq) {
1233 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1234 tcpd->ta->frame_acked=ual->frame;
1235 nstime_delta(&tcpd->ta->ts, &pinfo->fd->abs_ts, &ual->ts);
1237 /* If this acknowledges part of the segment, adjust the segment info for the acked part */
1238 else if (GT_SEQ(ack, ual->seq) && LE_SEQ(ack, ual->nextseq)) {
1239 ual->seq = ack;
1240 continue;
1242 /* If this acknowledges a segment prior to this one, leave this segment alone and move on */
1243 else if (GT_SEQ(ual->nextseq,ack)) {
1244 prevual = ual;
1245 ual = ual->next;
1246 continue;
1249 /* This segment is old, or an exact match. Delete the segment from the list */
1250 ackcount++;
1251 tmpual=ual->next;
1253 if (tcpd->rev->scps_capable) {
1254 /* Track largest segment successfully sent for SNACK analysis*/
1255 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) {
1256 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);
1260 if (!prevual) {
1261 tcpd->rev->segments = tmpual;
1263 else{
1264 prevual->next = tmpual;
1266 wmem_free(wmem_file_scope(), ual);
1267 ual = tmpual;
1270 /* how many bytes of data are there in flight after this frame
1271 * was sent
1273 ual=tcpd->fwd->segments;
1274 if (tcp_track_bytes_in_flight && seglen!=0 && ual && tcpd->fwd->valid_bif) {
1275 guint32 first_seq, last_seq, in_flight;
1277 first_seq = ual->seq - tcpd->fwd->base_seq;
1278 last_seq = ual->nextseq - tcpd->fwd->base_seq;
1279 while (ual) {
1280 if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) {
1281 last_seq = ual->nextseq-tcpd->fwd->base_seq;
1283 if ((ual->seq-tcpd->fwd->base_seq)<first_seq) {
1284 first_seq = ual->seq-tcpd->fwd->base_seq;
1286 ual = ual->next;
1288 in_flight = last_seq-first_seq;
1290 if (in_flight>0 && in_flight<2000000000) {
1291 if(!tcpd->ta) {
1292 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, TRUE, tcpd);
1294 tcpd->ta->bytes_in_flight = in_flight;
1301 * Prints results of the sequence number analysis concerning tcp segments
1302 * retransmitted or out-of-order
1304 static void
1305 tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,
1306 tvbuff_t * tvb,
1307 proto_tree * flags_tree, proto_item * flags_item,
1308 struct tcp_acked *ta
1311 /* TCP Retransmission */
1312 if (ta->flags & TCP_A_RETRANSMISSION) {
1313 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
1315 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
1317 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {
1318 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
1319 tvb, 0, 0, &ta->rto_ts);
1320 PROTO_ITEM_SET_GENERATED(flags_item);
1321 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,
1322 tvb, 0, 0, ta->rto_frame);
1323 PROTO_ITEM_SET_GENERATED(flags_item);
1326 /* TCP Fast Retransmission */
1327 if (ta->flags & TCP_A_FAST_RETRANSMISSION) {
1328 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_fast_retransmission);
1329 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
1330 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1331 "[TCP Fast Retransmission] ");
1333 /* TCP Spurious Retransmission */
1334 if (ta->flags & TCP_A_SPURIOUS_RETRANSMISSION) {
1335 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_spurious_retransmission);
1336 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_retransmission);
1337 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1338 "[TCP Spurious Retransmission] ");
1341 /* TCP Out-Of-Order */
1342 if (ta->flags & TCP_A_OUT_OF_ORDER) {
1343 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_out_of_order);
1344 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
1348 /* Prints results of the sequence number analysis concerning reused ports */
1349 static void
1350 tcp_sequence_number_analysis_print_reused(packet_info * pinfo,
1351 proto_item * flags_item,
1352 struct tcp_acked *ta
1355 /* TCP Ports Reused */
1356 if (ta->flags & TCP_A_REUSED_PORTS) {
1357 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_reused_ports);
1358 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1359 "[TCP Port numbers reused] ");
1363 /* Prints results of the sequence number analysis concerning lost tcp segments */
1364 static void
1365 tcp_sequence_number_analysis_print_lost(packet_info * pinfo,
1366 proto_item * flags_item,
1367 struct tcp_acked *ta
1370 /* TCP Lost Segment */
1371 if (ta->flags & TCP_A_LOST_PACKET) {
1372 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_lost_packet);
1373 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1374 "[TCP Previous segment not captured] ");
1376 /* TCP Ack lost segment */
1377 if (ta->flags & TCP_A_ACK_LOST_PACKET) {
1378 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_ack_lost_packet);
1379 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1380 "[TCP ACKed unseen segment] ");
1384 /* Prints results of the sequence number analysis concerning tcp window */
1385 static void
1386 tcp_sequence_number_analysis_print_window(packet_info * pinfo,
1387 proto_item * flags_item,
1388 struct tcp_acked *ta
1391 /* TCP Window Update */
1392 if (ta->flags & TCP_A_WINDOW_UPDATE) {
1393 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_update);
1394 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
1396 /* TCP Full Window */
1397 if (ta->flags & TCP_A_WINDOW_FULL) {
1398 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_window_full);
1399 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
1403 /* Prints results of the sequence number analysis concerning tcp keepalive */
1404 static void
1405 tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,
1406 proto_item * flags_item,
1407 struct tcp_acked *ta
1410 /*TCP Keep Alive */
1411 if (ta->flags & TCP_A_KEEP_ALIVE) {
1412 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive);
1413 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
1415 /* TCP Ack Keep Alive */
1416 if (ta->flags & TCP_A_KEEP_ALIVE_ACK) {
1417 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_keep_alive_ack);
1418 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
1422 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
1423 static void
1424 tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,
1425 tvbuff_t * tvb,
1426 proto_tree * flags_tree,
1427 struct tcp_acked *ta,
1428 proto_tree * tree
1431 proto_item * flags_item;
1433 /* TCP Duplicate ACK */
1434 if (ta->dupack_num) {
1435 if (ta->flags & TCP_A_DUPLICATE_ACK ) {
1436 flags_item=proto_tree_add_none_format(flags_tree,
1437 hf_tcp_analysis_duplicate_ack,
1438 tvb, 0, 0,
1439 "This is a TCP duplicate ack"
1441 PROTO_ITEM_SET_GENERATED(flags_item);
1442 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1443 "[TCP Dup ACK %u#%u] ",
1444 ta->dupack_frame,
1445 ta->dupack_num
1449 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
1450 tvb, 0, 0, ta->dupack_num);
1451 PROTO_ITEM_SET_GENERATED(flags_item);
1452 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
1453 tvb, 0, 0, ta->dupack_frame);
1454 PROTO_ITEM_SET_GENERATED(flags_item);
1455 expert_add_info_format(pinfo, flags_item, &ei_tcp_analysis_duplicate_ack, "Duplicate ACK (#%u)", ta->dupack_num);
1459 /* Prints results of the sequence number analysis concerning tcp zero window */
1460 static void
1461 tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,
1462 proto_item * flags_item,
1463 struct tcp_acked *ta
1466 /* TCP Zero Window Probe */
1467 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE) {
1468 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe);
1469 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
1471 /* TCP Zero Window */
1472 if (ta->flags&TCP_A_ZERO_WINDOW) {
1473 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window);
1474 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
1476 /* TCP Zero Window Probe Ack */
1477 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK) {
1478 expert_add_info(pinfo, flags_item, &ei_tcp_analysis_zero_window_probe_ack);
1479 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1480 "[TCP ZeroWindowProbeAck] ");
1485 /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */
1486 static void
1487 tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U_,
1488 tvbuff_t * tvb _U_,
1489 proto_tree * flags_tree _U_,
1490 struct tcp_acked *ta
1493 proto_item * flags_item;
1495 if (tcp_track_bytes_in_flight) {
1496 flags_item=proto_tree_add_uint(flags_tree,
1497 hf_tcp_analysis_bytes_in_flight,
1498 tvb, 0, 0, ta->bytes_in_flight);
1500 PROTO_ITEM_SET_GENERATED(flags_item);
1504 static void
1505 tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree,
1506 struct tcp_analysis *tcpd, guint32 seq, guint32 ack)
1508 struct tcp_acked *ta = NULL;
1509 proto_item *item;
1510 proto_tree *tree;
1511 proto_tree *flags_tree=NULL;
1513 if (!tcpd) {
1514 return;
1516 if(!tcpd->ta) {
1517 tcp_analyze_get_acked_struct(pinfo->fd->num, seq, ack, FALSE, tcpd);
1519 ta=tcpd->ta;
1520 if(!ta) {
1521 return;
1524 item=proto_tree_add_item(parent_tree, hf_tcp_analysis, tvb, 0, 0, ENC_NA);
1525 PROTO_ITEM_SET_GENERATED(item);
1526 tree=proto_item_add_subtree(item, ett_tcp_analysis);
1528 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
1529 data we actually have */
1530 if(ta->frame_acked) {
1531 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
1532 tvb, 0, 0, ta->frame_acked);
1533 PROTO_ITEM_SET_GENERATED(item);
1535 /* only display RTT if we actually have something we are acking */
1536 if( ta->ts.secs || ta->ts.nsecs ) {
1537 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
1538 tvb, 0, 0, &ta->ts);
1539 PROTO_ITEM_SET_GENERATED(item);
1543 if(ta->bytes_in_flight) {
1544 /* print results for amount of data in flight */
1545 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta);
1548 if(ta->flags) {
1549 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, 0, ENC_NA);
1550 PROTO_ITEM_SET_GENERATED(item);
1551 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);
1553 /* print results for reused tcp ports */
1554 tcp_sequence_number_analysis_print_reused(pinfo, item, ta);
1556 /* print results for retransmission and out-of-order segments */
1557 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, item, ta);
1559 /* print results for lost tcp segments */
1560 tcp_sequence_number_analysis_print_lost(pinfo, item, ta);
1562 /* print results for tcp window information */
1563 tcp_sequence_number_analysis_print_window(pinfo, item, ta);
1565 /* print results for tcp keep alive information */
1566 tcp_sequence_number_analysis_print_keepalive(pinfo, item, ta);
1568 /* print results for tcp duplicate acks */
1569 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);
1571 /* print results for tcp zero window */
1572 tcp_sequence_number_analysis_print_zero_window(pinfo, item, ta);
1578 static void
1579 print_tcp_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *tcp_tree, packet_info *pinfo, tvbuff_t *next_tvb)
1581 proto_item *tcp_tree_item, *frag_tree_item;
1584 * The subdissector thought it was completely
1585 * desegmented (although the stuff at the
1586 * end may, in turn, require desegmentation),
1587 * so we show a tree with all segments.
1589 show_fragment_tree(ipfd_head, &tcp_segment_items,
1590 tree, pinfo, next_tvb, &frag_tree_item);
1592 * The toplevel fragment subtree is now
1593 * behind all desegmented data; move it
1594 * right behind the TCP tree.
1596 tcp_tree_item = proto_tree_get_parent(tcp_tree);
1597 if(frag_tree_item && tcp_tree_item) {
1598 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);
1602 /* **************************************************************************
1603 * End of tcp sequence number analysis
1604 * **************************************************************************/
1607 /* Minimum TCP header length. */
1608 #define TCPH_MIN_LEN 20
1610 /* Desegmentation of TCP streams */
1611 static reassembly_table tcp_reassembly_table;
1613 /* functions to trace tcp segments */
1614 /* Enable desegmenting of TCP streams */
1615 static gboolean tcp_desegment = TRUE;
1617 static void
1618 desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
1619 guint32 seq, guint32 nxtseq,
1620 guint32 sport, guint32 dport,
1621 proto_tree *tree, proto_tree *tcp_tree,
1622 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
1624 fragment_head *ipfd_head;
1625 int last_fragment_len;
1626 gboolean must_desegment;
1627 gboolean called_dissector;
1628 int another_pdu_follows;
1629 int deseg_offset;
1630 guint32 deseg_seq;
1631 gint nbytes;
1632 proto_item *item;
1633 struct tcp_multisegment_pdu *msp;
1634 gboolean cleared_writable = col_get_writable(pinfo->cinfo);
1636 again:
1637 ipfd_head = NULL;
1638 last_fragment_len = 0;
1639 must_desegment = FALSE;
1640 called_dissector = FALSE;
1641 another_pdu_follows = 0;
1642 msp = NULL;
1645 * Initialize these to assume no desegmentation.
1646 * If that's not the case, these will be set appropriately
1647 * by the subdissector.
1649 pinfo->desegment_offset = 0;
1650 pinfo->desegment_len = 0;
1653 * Initialize this to assume that this segment will just be
1654 * added to the middle of a desegmented chunk of data, so
1655 * that we should show it all as data.
1656 * If that's not the case, it will be set appropriately.
1658 deseg_offset = offset;
1660 if (tcpd) {
1661 /* Have we seen this PDU before (and is it the start of a multi-
1662 * segment PDU)?
1664 if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(tcpd->fwd->multisegment_pdus, seq))) {
1665 const char* str;
1667 /* Yes. This could be because we've dissected this frame before
1668 * or because this is a retransmission of a previously-seen
1669 * segment. Either way, we don't need to hand it off to the
1670 * subdissector and we certainly don't want to re-add it to the
1671 * multisegment_pdus list: if we did, subsequent lookups would
1672 * find this retransmission instead of the original transmission
1673 * (breaking desegmentation if we'd already linked other segments
1674 * to the original transmission's entry).
1677 if (msp->first_frame == PINFO_FD_NUM(pinfo)) {
1678 str = "";
1679 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
1680 } else {
1681 str = "Retransmitted ";
1682 /* TCP analysis already flags this (in COL_INFO) as a retransmission--if it's enabled */
1685 nbytes = MAX(0, tvb_reported_length_remaining(tvb, offset));
1686 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
1687 nbytes, NULL, "%sTCP segment data (%u byte%s)", str, nbytes,
1688 plurality(nbytes, "", "s"));
1689 return;
1692 /* Else, find the most previous PDU starting before this sequence number */
1693 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);
1696 if (msp && msp->seq <= seq && msp->nxtpdu > seq) {
1697 int len;
1699 if (!PINFO_FD_VISITED(pinfo)) {
1700 msp->last_frame=pinfo->fd->num;
1701 msp->last_frame_time=pinfo->fd->abs_ts;
1704 /* OK, this PDU was found, which means the segment continues
1705 * a higher-level PDU and that we must desegment it.
1707 if (msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
1708 /* The dissector asked for the entire segment */
1709 len = MAX(0, tvb_length_remaining(tvb, offset));
1710 } else {
1711 len = MIN(nxtseq, msp->nxtpdu) - seq;
1713 last_fragment_len = len;
1715 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,
1716 pinfo, msp->first_frame, NULL,
1717 seq - msp->seq, len,
1718 (LT_SEQ (nxtseq,msp->nxtpdu)) );
1720 if (!PINFO_FD_VISITED(pinfo)
1721 && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
1722 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
1724 /* If we consumed the entire segment there is no
1725 * other pdu starting anywhere inside this segment.
1726 * So update nxtpdu to point at least to the start
1727 * of the next segment.
1728 * (If the subdissector asks for even more data we
1729 * will advance nxtpdu even further later down in
1730 * the code.)
1732 msp->nxtpdu = nxtseq;
1735 if( (msp->nxtpdu < nxtseq)
1736 && (msp->nxtpdu >= seq)
1737 && (len > 0)) {
1738 another_pdu_follows=msp->nxtpdu - seq;
1740 } else {
1741 /* This segment was not found in our table, so it doesn't
1742 * contain a continuation of a higher-level PDU.
1743 * Call the normal subdissector.
1747 * Supply the sequence number of this segment. We set this here
1748 * because this segment could be after another in the same packet,
1749 * in which case seq was incremented at the end of the loop.
1751 tcpinfo->seq = seq;
1753 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
1754 sport, dport, 0, 0, FALSE, tcpd, tcpinfo);
1755 called_dissector = TRUE;
1757 /* Did the subdissector ask us to desegment some more data
1758 * before it could handle the packet?
1759 * If so we have to create some structures in our table but
1760 * this is something we only do the first time we see this
1761 * packet.
1763 if(pinfo->desegment_len) {
1764 if (!PINFO_FD_VISITED(pinfo))
1765 must_desegment = TRUE;
1768 * Set "deseg_offset" to the offset in "tvb"
1769 * of the first byte of data that the
1770 * subdissector didn't process.
1772 deseg_offset = offset + pinfo->desegment_offset;
1775 /* Either no desegmentation is necessary, or this is
1776 * segment contains the beginning but not the end of
1777 * a higher-level PDU and thus isn't completely
1778 * desegmented.
1780 ipfd_head = NULL;
1784 /* is it completely desegmented? */
1785 if (ipfd_head) {
1787 * Yes, we think it is.
1788 * We only call subdissector for the last segment.
1789 * Note that the last segment may include more than what
1790 * we needed.
1792 if(ipfd_head->reassembled_in == pinfo->fd->num) {
1794 * OK, this is the last segment.
1795 * Let's call the subdissector with the desegmented
1796 * data.
1798 tvbuff_t *next_tvb;
1799 int old_len;
1801 /* create a new TVB structure for desegmented data */
1802 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
1804 /* add desegmented data to the data source list */
1805 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
1808 * Supply the sequence number of the first of the
1809 * reassembled bytes.
1811 tcpinfo->seq = msp->seq;
1813 /* indicate that this is reassembled data */
1814 tcpinfo->is_reassembled = TRUE;
1816 /* call subdissector */
1817 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, sport,
1818 dport, 0, 0, FALSE, tcpd, tcpinfo);
1819 called_dissector = TRUE;
1822 * OK, did the subdissector think it was completely
1823 * desegmented, or does it think we need even more
1824 * data?
1826 old_len = (int)(tvb_reported_length(next_tvb) - last_fragment_len);
1827 if (pinfo->desegment_len &&
1828 pinfo->desegment_offset<=old_len) {
1830 * "desegment_len" isn't 0, so it needs more
1831 * data for something - and "desegment_offset"
1832 * is before "old_len", so it needs more data
1833 * to dissect the stuff we thought was
1834 * completely desegmented (as opposed to the
1835 * stuff at the beginning being completely
1836 * desegmented, but the stuff at the end
1837 * being a new higher-level PDU that also
1838 * needs desegmentation).
1840 fragment_set_partial_reassembly(&tcp_reassembly_table,
1841 pinfo, msp->first_frame, NULL);
1843 /* Update msp->nxtpdu to point to the new next
1844 * pdu boundary.
1846 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1847 /* We want reassembly of at least one
1848 * more segment so set the nxtpdu
1849 * boundary to one byte into the next
1850 * segment.
1851 * This means that the next segment
1852 * will complete reassembly even if it
1853 * is only one single byte in length.
1855 msp->nxtpdu = seq + MAX(0, tvb_reported_length_remaining(tvb, offset)) + 1;
1856 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1857 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
1858 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1859 } else {
1860 msp->nxtpdu=seq + last_fragment_len + pinfo->desegment_len;
1863 /* Since we need at least some more data
1864 * there can be no pdu following in the
1865 * tail of this segment.
1867 another_pdu_follows = 0;
1868 offset += last_fragment_len;
1869 seq += last_fragment_len;
1870 if (tvb_length_remaining(tvb, offset) > 0)
1871 goto again;
1872 } else {
1874 * Show the stuff in this TCP segment as
1875 * just raw TCP segment data.
1877 nbytes = another_pdu_follows > 0
1878 ? another_pdu_follows
1879 : MAX(0, tvb_reported_length_remaining(tvb, offset));
1880 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
1881 nbytes, NULL, "TCP segment data (%u byte%s)", nbytes,
1882 plurality(nbytes, "", "s"));
1884 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
1886 /* Did the subdissector ask us to desegment
1887 * some more data? This means that the data
1888 * at the beginning of this segment completed
1889 * a higher-level PDU, but the data at the
1890 * end of this segment started a higher-level
1891 * PDU but didn't complete it.
1893 * If so, we have to create some structures
1894 * in our table, but this is something we
1895 * only do the first time we see this packet.
1897 if(pinfo->desegment_len) {
1898 if (!PINFO_FD_VISITED(pinfo))
1899 must_desegment = TRUE;
1901 /* The stuff we couldn't dissect
1902 * must have come from this segment,
1903 * so it's all in "tvb".
1905 * "pinfo->desegment_offset" is
1906 * relative to the beginning of
1907 * "next_tvb"; we want an offset
1908 * relative to the beginning of "tvb".
1910 * First, compute the offset relative
1911 * to the *end* of "next_tvb" - i.e.,
1912 * the number of bytes before the end
1913 * of "next_tvb" at which the
1914 * subdissector stopped. That's the
1915 * length of "next_tvb" minus the
1916 * offset, relative to the beginning
1917 * of "next_tvb, at which the
1918 * subdissector stopped.
1920 deseg_offset = ipfd_head->datalen - pinfo->desegment_offset;
1922 /* "tvb" and "next_tvb" end at the
1923 * same byte of data, so the offset
1924 * relative to the end of "next_tvb"
1925 * of the byte at which we stopped
1926 * is also the offset relative to
1927 * the end of "tvb" of the byte at
1928 * which we stopped.
1930 * Convert that back into an offset
1931 * relative to the beginning of
1932 * "tvb", by taking the length of
1933 * "tvb" and subtracting the offset
1934 * relative to the end.
1936 deseg_offset = tvb_reported_length(tvb) - deseg_offset;
1942 if (must_desegment) {
1943 /* If the dissector requested "reassemble until FIN"
1944 * just set this flag for the flow and let reassembly
1945 * proceed at normal. We will check/pick up these
1946 * reassembled PDUs later down in dissect_tcp() when checking
1947 * for the FIN flag.
1949 if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
1950 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1953 * The sequence number at which the stuff to be desegmented
1954 * starts is the sequence number of the byte at an offset
1955 * of "deseg_offset" into "tvb".
1957 * The sequence number of the byte at an offset of "offset"
1958 * is "seq", i.e. the starting sequence number of this
1959 * segment, so the sequence number of the byte at
1960 * "deseg_offset" is "seq + (deseg_offset - offset)".
1962 deseg_seq = seq + (deseg_offset - offset);
1964 if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)
1965 && (!PINFO_FD_VISITED(pinfo))) {
1966 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1967 /* The subdissector asked to reassemble using the
1968 * entire next segment.
1969 * Just ask reassembly for one more byte
1970 * but set this msp flag so we can pick it up
1971 * above.
1973 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
1974 nxtseq+1, tcpd->fwd->multisegment_pdus);
1975 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1976 } else {
1977 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1978 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
1981 /* add this segment as the first one for this new pdu */
1982 fragment_add(&tcp_reassembly_table, tvb, deseg_offset,
1983 pinfo, msp->first_frame, NULL,
1984 0, nxtseq - deseg_seq,
1985 LT_SEQ(nxtseq, msp->nxtpdu));
1989 if (!called_dissector || pinfo->desegment_len != 0) {
1990 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
1991 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
1993 * We know what frame this PDU is reassembled in;
1994 * let the user know.
1996 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,
1997 0, ipfd_head->reassembled_in);
1998 PROTO_ITEM_SET_GENERATED(item);
2002 * Either we didn't call the subdissector at all (i.e.,
2003 * this is a segment that contains the middle of a
2004 * higher-level PDU, but contains neither the beginning
2005 * nor the end), or the subdissector couldn't dissect it
2006 * all, as some data was missing (i.e., it set
2007 * "pinfo->desegment_len" to the amount of additional
2008 * data it needs).
2010 if (pinfo->desegment_offset == 0) {
2012 * It couldn't, in fact, dissect any of it (the
2013 * first byte it couldn't dissect is at an offset
2014 * of "pinfo->desegment_offset" from the beginning
2015 * of the payload, and that's 0).
2016 * Just mark this as TCP.
2018 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
2019 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
2023 * Show what's left in the packet as just raw TCP segment
2024 * data.
2025 * XXX - remember what protocol the last subdissector
2026 * was, and report it as a continuation of that, instead?
2028 nbytes = MAX(0, tvb_reported_length_remaining(tvb, deseg_offset));
2029 proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, deseg_offset,
2030 -1, NULL, "TCP segment data (%u byte%s)", nbytes,
2031 plurality(nbytes, "", "s"));
2033 pinfo->can_desegment = 0;
2034 pinfo->desegment_offset = 0;
2035 pinfo->desegment_len = 0;
2037 if(another_pdu_follows) {
2038 /* there was another pdu following this one. */
2039 pinfo->can_desegment = 2;
2040 /* we also have to prevent the dissector from changing the
2041 * PROTOCOL and INFO columns since what follows may be an
2042 * incomplete PDU and we don't want it be changed back from
2043 * <Protocol> to <TCP>
2044 * XXX There is no good way to block the PROTOCOL column
2045 * from being changed yet so we set the entire row unwritable.
2046 * The flag cleared_writable stores the initial state.
2048 col_set_fence(pinfo->cinfo, COL_INFO);
2049 cleared_writable |= col_get_writable(pinfo->cinfo);
2050 col_set_writable(pinfo->cinfo, FALSE);
2051 offset += another_pdu_follows;
2052 seq += another_pdu_follows;
2053 goto again;
2054 } else {
2055 /* remove any blocking set above otherwise the
2056 * proto,colinfo tap will break
2058 if(cleared_writable) {
2059 col_set_writable(pinfo->cinfo, TRUE);
2065 * Loop for dissecting PDUs within a TCP stream; assumes that a PDU
2066 * consists of a fixed-length chunk of data that contains enough information
2067 * to determine the length of the PDU, followed by rest of the PDU.
2069 * The first three arguments are the arguments passed to the dissector
2070 * that calls this routine.
2072 * "proto_desegment" is the dissector's flag controlling whether it should
2073 * desegment PDUs that cross TCP segment boundaries.
2075 * "fixed_len" is the length of the fixed-length part of the PDU.
2077 * "get_pdu_len()" is a routine called to get the length of the PDU from
2078 * the fixed-length part of the PDU; it's passed "pinfo", "tvb" and "offset".
2080 * "dissect_pdu()" is the routine to dissect a PDU.
2082 void
2083 tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2084 gboolean proto_desegment, guint fixed_len,
2085 guint (*get_pdu_len)(packet_info *, tvbuff_t *, int),
2086 new_dissector_t dissect_pdu, void* dissector_data)
2088 volatile int offset = 0;
2089 int offset_before;
2090 guint length_remaining;
2091 guint plen;
2092 guint length;
2093 tvbuff_t *next_tvb;
2094 proto_item *item=NULL;
2095 void *pd_save;
2097 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2099 * We use "tvb_ensure_length_remaining()" to make sure there actually
2100 * *is* data remaining. The protocol we're handling could conceivably
2101 * consists of a sequence of fixed-length PDUs, and therefore the
2102 * "get_pdu_len" routine might not actually fetch anything from
2103 * the tvbuff, and thus might not cause an exception to be thrown if
2104 * we've run past the end of the tvbuff.
2106 * This means we're guaranteed that "length_remaining" is positive.
2108 length_remaining = tvb_ensure_length_remaining(tvb, offset);
2111 * Can we do reassembly?
2113 if (proto_desegment && pinfo->can_desegment) {
2115 * Yes - is the fixed-length part of the PDU split across segment
2116 * boundaries?
2118 if (length_remaining < fixed_len) {
2120 * Yes. Tell the TCP dissector where the data for this message
2121 * starts in the data it handed us and that we need "some more
2122 * data." Don't tell it exactly how many bytes we need because
2123 * if/when we ask for even more (after the header) that will
2124 * break reassembly.
2126 pinfo->desegment_offset = offset;
2127 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
2128 return;
2133 * Get the length of the PDU.
2135 plen = (*get_pdu_len)(pinfo, tvb, offset);
2136 if (plen < fixed_len) {
2138 * Either:
2140 * 1) the length value extracted from the fixed-length portion
2141 * doesn't include the fixed-length portion's length, and
2142 * was so large that, when the fixed-length portion's
2143 * length was added to it, the total length overflowed;
2145 * 2) the length value extracted from the fixed-length portion
2146 * includes the fixed-length portion's length, and the value
2147 * was less than the fixed-length portion's length, i.e. it
2148 * was bogus.
2150 * Report this as a bounds error.
2152 show_reported_bounds_error(tvb, pinfo, tree);
2153 return;
2156 /* give a hint to TCP where the next PDU starts
2157 * so that it can attempt to find it in case it starts
2158 * somewhere in the middle of a segment.
2160 if(!pinfo->fd->flags.visited && tcp_analyze_seq) {
2161 guint remaining_bytes;
2162 remaining_bytes = MAX(0, tvb_reported_length_remaining(tvb, offset));
2163 if(plen>remaining_bytes) {
2164 pinfo->want_pdu_tracking=2;
2165 pinfo->bytes_until_next_pdu=plen-remaining_bytes;
2170 * Can we do reassembly?
2172 if (proto_desegment && pinfo->can_desegment) {
2174 * Yes - is the PDU split across segment boundaries?
2176 if (length_remaining < plen) {
2178 * Yes. Tell the TCP dissector where the data for this message
2179 * starts in the data it handed us, and how many more bytes we
2180 * need, and return.
2182 pinfo->desegment_offset = offset;
2183 pinfo->desegment_len = plen - length_remaining;
2184 return;
2189 * Do not display the the PDU length if it crosses the boundary of the
2190 * packet and no more packets are available.
2192 * XXX - we don't necessarily know whether more packets are
2193 * available; we might be doing a one-pass read through the
2194 * capture in TShark, or we might be doing a live capture in
2195 * Wireshark.
2197 #if 0
2198 if (length_remaining >= plen || there are more packets)
2200 #endif
2202 * Display the PDU length as a field
2204 item=proto_tree_add_uint(tree ? tree->last_child : NULL,
2205 hf_tcp_pdu_size,
2206 tvb, offset, plen, plen);
2207 PROTO_ITEM_SET_GENERATED(item);
2208 #if 0
2209 } else {
2210 item = proto_tree_add_text(tree ? tree->last_child : NULL, tvb, offset, -1,
2211 "PDU Size: %u cut short at %u",plen,length_remaining);
2212 PROTO_ITEM_SET_GENERATED(item);
2214 #endif
2217 * Construct a tvbuff containing the amount of the payload we have
2218 * available. Make its reported length the amount of data in the PDU.
2220 length = length_remaining;
2221 if (length > plen)
2222 length = plen;
2223 next_tvb = tvb_new_subset(tvb, offset, length, plen);
2226 * Dissect the PDU.
2228 * If it gets an error that means there's no point in
2229 * dissecting any more PDUs, rethrow the exception in
2230 * question.
2232 * If it gets any other error, report it and continue, as that
2233 * means that PDU got an error, but that doesn't mean we should
2234 * stop dissecting PDUs within this frame or chunk of reassembled
2235 * data.
2237 pd_save = pinfo->private_data;
2238 TRY {
2239 (*dissect_pdu)(next_tvb, pinfo, tree, dissector_data);
2241 CATCH_NONFATAL_ERRORS {
2242 /* Restore the private_data structure in case one of the
2243 * called dissectors modified it (and, due to the exception,
2244 * was unable to restore it).
2246 pinfo->private_data = pd_save;
2247 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2249 ENDTRY;
2252 * Step to the next PDU.
2253 * Make sure we don't overflow.
2255 offset_before = offset;
2256 offset += plen;
2257 if (offset <= offset_before)
2258 break;
2262 static void
2263 tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val)
2265 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%u", abbrev, val);
2268 static void
2269 dissect_tcpopt_exp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2270 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2272 proto_item *item;
2273 proto_tree *exp_tree;
2274 proto_item *hidden_item;
2275 guint16 magic;
2277 item = proto_tree_add_item(opt_tree, hf_tcp_option_exp, tvb,
2278 offset, optlen, ENC_NA);
2279 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);
2280 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
2281 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2282 if (tcp_exp_options_with_magic && ((optlen - 2) > 0)) {
2283 magic = tvb_get_ntohs(tvb, offset + 2);
2284 proto_tree_add_item(exp_tree, hf_tcp_option_exp_magic_number, tvb,
2285 offset + 2, 2, ENC_BIG_ENDIAN);
2286 switch (magic) {
2287 case 0xf989:
2288 /* FF: draft-ietf-tcpm-fastopen-02, TCP Fast Open */
2289 hidden_item = proto_tree_add_item(exp_tree, hf_tcp_option_fast_open,
2290 tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2291 PROTO_ITEM_SET_HIDDEN(hidden_item);
2292 if ((optlen - 2) == 2) {
2293 /* Fast Open Cookie Request */
2294 proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie_request,
2295 tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2296 col_append_str(pinfo->cinfo, COL_INFO, " TFO=R");
2297 } else if ((optlen - 2) > 2) {
2298 /* Fast Open Cookie */
2299 proto_tree_add_item(exp_tree, hf_tcp_option_fast_open_cookie,
2300 tvb, offset + 4, optlen - 4, ENC_NA);
2301 col_append_str(pinfo->cinfo, COL_INFO, " TFO=C");
2303 break;
2304 default:
2305 /* Unknown magic number */
2306 break;
2308 } else {
2309 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,
2310 offset + 2, optlen - 2, ENC_NA);
2311 tcp_info_append_uint(pinfo, "Expxx", TRUE);
2315 static void
2316 dissect_tcpopt_sack_perm(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2317 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2319 proto_item *item;
2320 proto_tree *exp_tree;
2322 item = proto_tree_add_boolean(opt_tree, hf_tcp_option_sack_perm, tvb, offset,
2323 optlen, TRUE);
2324 exp_tree = proto_item_add_subtree(item, ett_tcp_option_sack_perm);
2325 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
2326 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2327 tcp_info_append_uint(pinfo, "SACK_PERM", TRUE);
2330 static void
2331 dissect_tcpopt_mss(const ip_tcp_opt *optp, tvbuff_t *tvb,
2332 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2334 proto_item *item;
2335 proto_tree *exp_tree;
2336 guint16 mss;
2338 mss = tvb_get_ntohs(tvb, offset + 2);
2339 item = proto_tree_add_none_format(opt_tree, hf_tcp_option_mss, tvb, offset,
2340 optlen, "%s: %u bytes", optp->name, mss);
2341 exp_tree = proto_item_add_subtree(item, ett_tcp_option_mss);
2342 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
2343 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2344 proto_tree_add_item(exp_tree, hf_tcp_option_mss_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2345 tcp_info_append_uint(pinfo, "MSS", mss);
2348 /* The window scale extension is defined in RFC 1323 */
2349 static void
2350 dissect_tcpopt_wscale(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2351 int offset, guint optlen _U_, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2353 guint8 val, shift;
2354 proto_item *wscale_pi, *gen_pi;
2355 proto_tree *wscale_tree;
2356 struct tcp_analysis *tcpd=NULL;
2358 tcpd=get_tcp_conversation_data(NULL,pinfo);
2360 wscale_pi = proto_tree_add_text(opt_tree, tvb, offset, 3, "Window scale: ");
2361 wscale_tree = proto_item_add_subtree(wscale_pi, ett_tcp_option_wscale);
2363 proto_tree_add_item(wscale_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_NA);
2364 offset += 1;
2366 proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_NA);
2367 offset += 1;
2369 proto_tree_add_item(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1,
2370 ENC_NA);
2371 shift = tvb_get_guint8(tvb, offset);
2373 gen_pi = proto_tree_add_uint(wscale_tree, hf_tcp_option_wscale_multiplier, tvb,
2374 offset, 1, 1 << shift);
2375 PROTO_ITEM_SET_GENERATED(gen_pi);
2376 val = tvb_get_guint8(tvb, offset);
2378 proto_item_append_text(wscale_pi, "%u (multiply by %u)", val, 1 << shift);
2380 tcp_info_append_uint(pinfo, "WS", 1 << shift);
2382 if(!pinfo->fd->flags.visited) {
2383 pdu_store_window_scale_option(shift, tcpd);
2387 static void
2388 dissect_tcpopt_sack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2389 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data)
2391 proto_tree *field_tree = NULL;
2392 proto_item *tf=NULL;
2393 proto_item *hidden_item;
2394 guint32 leftedge, rightedge;
2395 struct tcp_analysis *tcpd=NULL;
2396 struct tcpheader *tcph = (struct tcpheader *)data;
2397 guint32 base_ack=0;
2398 guint num_sack_ranges = 0;
2400 if(tcp_analyze_seq && tcp_relative_seq) {
2401 /* find(or create if needed) the conversation for this tcp session */
2402 tcpd=get_tcp_conversation_data(NULL,pinfo);
2404 if (tcpd) {
2405 base_ack=tcpd->rev->base_seq;
2409 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2410 offset, 1, ENC_BIG_ENDIAN);
2411 PROTO_ITEM_SET_HIDDEN(hidden_item);
2412 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2413 offset + 1, 1, ENC_BIG_ENDIAN);
2414 PROTO_ITEM_SET_HIDDEN(hidden_item);
2416 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
2417 offset += 2; /* skip past type and length */
2418 optlen -= 2; /* subtract size of type and length */
2419 while (optlen > 0) {
2420 if (field_tree == NULL) {
2421 /* Haven't yet made a subtree out of this option. Do so. */
2422 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2423 hidden_item = proto_tree_add_boolean(field_tree, hf_tcp_option_sack, tvb,
2424 offset, optlen, TRUE);
2425 PROTO_ITEM_SET_HIDDEN(hidden_item);
2427 if (optlen < 4) {
2428 proto_tree_add_text(field_tree, tvb, offset, optlen,
2429 "(suboption would go past end of option)");
2430 break;
2432 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;
2433 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
2434 offset, 4, leftedge,
2435 "left edge = %u%s", leftedge,
2436 tcp_relative_seq ? " (relative)" : "");
2438 optlen -= 4;
2439 if (optlen < 4) {
2440 proto_tree_add_text(field_tree, tvb, offset, optlen,
2441 "(suboption would go past end of option)");
2442 break;
2444 /* XXX - check whether it goes past end of packet */
2445 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;
2446 optlen -= 4;
2447 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
2448 offset+4, 4, rightedge,
2449 "right edge = %u%s", rightedge,
2450 tcp_relative_seq ? " (relative)" : "");
2451 tcp_info_append_uint(pinfo, "SLE", leftedge);
2452 tcp_info_append_uint(pinfo, "SRE", rightedge);
2453 num_sack_ranges++;
2455 /* Update tap info */
2456 if (tcph != NULL && (tcph->num_sack_ranges < MAX_TCP_SACK_RANGES)) {
2457 tcph->sack_left_edge[tcph->num_sack_ranges] = leftedge;
2458 tcph->sack_right_edge[tcph->num_sack_ranges] = rightedge;
2459 tcph->num_sack_ranges++;
2462 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);
2463 offset += 8;
2466 /* Show number of SACK ranges in this option as a generated field */
2467 tf = proto_tree_add_uint(field_tree, hf_tcp_option_sack_range_count,
2468 tvb, 0, 0, num_sack_ranges);
2469 PROTO_ITEM_SET_GENERATED(tf);
2472 static void
2473 dissect_tcpopt_echo(const ip_tcp_opt *optp, tvbuff_t *tvb,
2474 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2476 proto_item *hidden_item;
2477 guint32 echo;
2479 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2480 offset, 1, ENC_BIG_ENDIAN);
2481 PROTO_ITEM_SET_HIDDEN(hidden_item);
2482 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2483 offset + 1, 1, ENC_BIG_ENDIAN);
2484 PROTO_ITEM_SET_HIDDEN(hidden_item);
2486 echo = tvb_get_ntohl(tvb, offset + 2);
2487 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_echo, tvb, offset,
2488 optlen, TRUE);
2489 PROTO_ITEM_SET_HIDDEN(hidden_item);
2490 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2491 "%s: %u", optp->name, echo);
2492 tcp_info_append_uint(pinfo, "ECHO", echo);
2495 /* If set, do not put the TCP timestamp information on the summary line */
2496 static gboolean tcp_ignore_timestamps = FALSE;
2498 static void
2499 dissect_tcpopt_timestamp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2500 int offset, guint optlen _U_, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2502 proto_item *ti;
2503 proto_tree *ts_tree;
2504 guint32 ts_val, ts_ecr;
2506 ti = proto_tree_add_text(opt_tree, tvb, offset, 10, "Timestamps: ");
2507 ts_tree = proto_item_add_subtree(ti, ett_tcp_option_timestamp);
2509 proto_tree_add_item(ts_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_NA);
2510 offset += 1;
2512 proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_NA);
2513 offset += 1;
2515 proto_tree_add_item(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset,
2516 4, ENC_BIG_ENDIAN);
2517 ts_val = tvb_get_ntohl(tvb, offset);
2518 offset += 4;
2520 proto_tree_add_item(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset,
2521 4, ENC_BIG_ENDIAN);
2522 ts_ecr = tvb_get_ntohl(tvb, offset);
2523 /* offset += 4; */
2525 proto_item_append_text(ti, "TSval %u, TSecr %u", ts_val, ts_ecr);
2526 if (tcp_ignore_timestamps == FALSE) {
2527 tcp_info_append_uint(pinfo, "TSval", ts_val);
2528 tcp_info_append_uint(pinfo, "TSecr", ts_ecr);
2533 * The TCP Extensions for Multipath Operation with Multiple Addresses
2534 * are defined in draft-ietf-mptcp-multiaddressed-04
2536 * <http://tools.ietf.org/html/draft-ief-mptcp-multiaddressed-04>
2538 * Author: Andrei Maruseac <andrei.maruseac@intel.com>
2540 static void
2541 dissect_tcpopt_mptcp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2542 int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree, void *data _U_)
2544 proto_item *ti;
2545 proto_tree *mptcp_tree;
2547 proto_tree *mptcp_flags_tree;
2548 guint8 subtype;
2549 guint8 indx;
2550 guint8 flags;
2551 guint8 ipver;
2553 ti = proto_tree_add_text(opt_tree, tvb, offset, optlen, "Multipath TCP");
2554 mptcp_tree = proto_item_add_subtree(ti, ett_tcp_option_mptcp);
2556 proto_tree_add_item(mptcp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN);
2557 offset += 1;
2559 proto_tree_add_item(mptcp_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN);
2560 offset += 1;
2562 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_subtype, tvb,
2563 offset, 1, ENC_BIG_ENDIAN);
2565 subtype = tvb_get_guint8(tvb, offset) >> 4;
2566 proto_item_append_text(ti, ": %s", val_to_str(subtype, mptcp_subtype_vs, "Unknown (%d)"));
2567 switch (subtype) {
2568 case TCPOPT_MPTCP_MP_CAPABLE:
2569 proto_tree_add_item(mptcp_tree, hf_tcp_option_mptcp_version, tvb,
2570 offset, 1, ENC_BIG_ENDIAN);
2571 offset += 1;
2573 flags = tvb_get_guint8(tvb, offset);
2574 ti = proto_tree_add_uint(mptcp_tree, hf_tcp_option_mptcp_flags, tvb,
2575 offset, 1, flags);
2576 mptcp_flags_tree = proto_item_add_subtree(ti, ett_tcp_option_mptcp);
2578 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_C_flag,
2579 tvb, offset, 1, ENC_BIG_ENDIAN);
2580 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_S_flag,
2581 tvb, offset, 1, ENC_BIG_ENDIAN);
2582 offset += 1;
2584 if (optlen == 12 || optlen == 20) {
2585 proto_tree_add_item(mptcp_tree,
2586 hf_tcp_option_mptcp_sender_key, tvb, offset, 8, ENC_BIG_ENDIAN);
2587 offset += 8;
2590 if (optlen == 20) {
2591 proto_tree_add_item(mptcp_tree,
2592 hf_tcp_option_mptcp_recv_key, tvb, offset, 8, ENC_BIG_ENDIAN);
2594 break;
2596 case TCPOPT_MPTCP_MP_JOIN:
2597 switch (optlen) {
2598 case 12:
2599 flags = tvb_get_guint8(tvb, offset) & 0x01;
2600 ti = proto_tree_add_uint(mptcp_tree,
2601 hf_tcp_option_mptcp_flags, tvb,
2602 offset, 1, flags);
2603 mptcp_flags_tree = proto_item_add_subtree(ti,
2604 ett_tcp_option_mptcp);
2606 proto_tree_add_item(mptcp_flags_tree,
2607 hf_tcp_option_mptcp_B_flag, tvb, offset,
2608 1, ENC_BIG_ENDIAN);
2609 offset += 1;
2611 proto_tree_add_item(mptcp_tree,
2612 hf_tcp_option_mptcp_address_id, tvb, offset,
2613 1, ENC_BIG_ENDIAN);
2614 offset += 1;
2616 proto_tree_add_item(mptcp_tree,
2617 hf_tcp_option_mptcp_recv_token, tvb, offset,
2618 4, ENC_BIG_ENDIAN);
2619 offset += 4;
2621 proto_tree_add_item(mptcp_tree,
2622 hf_tcp_option_mptcp_sender_rand, tvb, offset,
2623 4, ENC_BIG_ENDIAN);
2624 break;
2626 case 16:
2627 flags = tvb_get_guint8(tvb, offset) & 0x01;
2628 ti = proto_tree_add_uint(mptcp_tree,
2629 hf_tcp_option_mptcp_flags, tvb,
2630 offset, 1, flags);
2631 mptcp_flags_tree = proto_item_add_subtree(ti,
2632 ett_tcp_option_mptcp);
2634 proto_tree_add_item(mptcp_flags_tree,
2635 hf_tcp_option_mptcp_B_flag, tvb, offset,
2636 1, ENC_BIG_ENDIAN);
2637 offset += 1;
2639 proto_tree_add_item(mptcp_tree,
2640 hf_tcp_option_mptcp_address_id, tvb, offset,
2641 1, ENC_BIG_ENDIAN);
2642 offset += 1;
2644 proto_tree_add_item(mptcp_tree,
2645 hf_tcp_option_mptcp_sender_trunc_mac, tvb, offset,
2646 8, ENC_BIG_ENDIAN);
2647 offset += 8;
2649 proto_tree_add_item(mptcp_tree,
2650 hf_tcp_option_mptcp_sender_rand, tvb, offset,
2651 4, ENC_BIG_ENDIAN);
2652 break;
2654 case 24:
2655 offset += 2;
2656 for (indx = 0; indx < 5; indx++) {
2657 proto_tree_add_item(mptcp_tree,
2658 hf_tcp_option_mptcp_sender_mac, tvb, offset,
2659 4, ENC_BIG_ENDIAN);
2660 offset += 4;
2662 break;
2664 default:
2665 break;
2667 break;
2669 case TCPOPT_MPTCP_DSS:
2670 offset += 1;
2671 flags = tvb_get_guint8(tvb, offset) & 0x1F;
2672 ti = proto_tree_add_uint(mptcp_tree, hf_tcp_option_mptcp_flags, tvb,
2673 offset, 1, flags);
2674 mptcp_flags_tree = proto_item_add_subtree(ti, ett_tcp_option_mptcp);
2676 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_F_flag,
2677 tvb, offset, 1, ENC_BIG_ENDIAN);
2678 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_m_flag,
2679 tvb, offset, 1, ENC_BIG_ENDIAN);
2680 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_M_flag,
2681 tvb, offset, 1, ENC_BIG_ENDIAN);
2682 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_a_flag,
2683 tvb, offset, 1, ENC_BIG_ENDIAN);
2684 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_A_flag,
2685 tvb, offset, 1, ENC_BIG_ENDIAN);
2686 offset += 1;
2688 if (flags & 1) {
2689 if (flags & 2) {
2690 proto_tree_add_item(mptcp_tree,
2691 hf_tcp_option_mptcp_data_ack, tvb, offset,
2692 8, ENC_BIG_ENDIAN);
2693 offset += 8;
2694 } else {
2695 proto_tree_add_item(mptcp_tree,
2696 hf_tcp_option_mptcp_data_ack, tvb, offset,
2697 4, ENC_BIG_ENDIAN);
2698 offset += 4;
2702 if (flags & 4) {
2703 if (flags & 8) {
2704 proto_tree_add_item(mptcp_tree,
2705 hf_tcp_option_mptcp_data_seq_no, tvb, offset,
2706 8, ENC_BIG_ENDIAN);
2707 offset += 8;
2708 } else {
2709 proto_tree_add_item(mptcp_tree,
2710 hf_tcp_option_mptcp_data_seq_no, tvb, offset,
2711 4, ENC_BIG_ENDIAN);
2712 offset += 4;
2715 proto_tree_add_item(mptcp_tree,
2716 hf_tcp_option_mptcp_subflow_seq_no, tvb, offset,
2717 4, ENC_BIG_ENDIAN);
2718 offset += 4;
2720 proto_tree_add_item(mptcp_tree,
2721 hf_tcp_option_mptcp_data_lvl_len, tvb, offset,
2722 2, ENC_BIG_ENDIAN);
2723 offset += 2;
2725 proto_tree_add_item(mptcp_tree,
2726 hf_tcp_option_mptcp_checksum, tvb, offset,
2727 2, ENC_BIG_ENDIAN);
2729 break;
2731 case TCPOPT_MPTCP_ADD_ADDR:
2732 proto_tree_add_item(mptcp_tree,
2733 hf_tcp_option_mptcp_ipver, tvb, offset, 1, ENC_BIG_ENDIAN);
2734 ipver = tvb_get_guint8(tvb, offset) & 0x0F;
2735 offset += 1;
2737 proto_tree_add_item(mptcp_tree,
2738 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2739 offset += 1;
2741 switch (ipver) {
2742 case 4:
2743 proto_tree_add_item(mptcp_tree,
2744 hf_tcp_option_mptcp_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
2745 offset += 4;
2746 break;
2748 case 6:
2749 proto_tree_add_item(mptcp_tree,
2750 hf_tcp_option_mptcp_ipv6, tvb, offset, 16, ENC_NA);
2751 offset += 16;
2752 break;
2754 default:
2755 break;
2758 if (optlen % 4 == 2) {
2759 proto_tree_add_item(mptcp_tree,
2760 hf_tcp_option_mptcp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2762 break;
2764 case TCPOPT_MPTCP_REMOVE_ADDR:
2765 offset += 1;
2766 proto_tree_add_item(mptcp_tree,
2767 hf_tcp_option_mptcp_address_id, tvb, offset,
2768 1, ENC_BIG_ENDIAN);
2769 break;
2771 case TCPOPT_MPTCP_MP_PRIO:
2772 flags = tvb_get_guint8(tvb, offset) & 0x01;
2773 ti = proto_tree_add_uint(mptcp_tree, hf_tcp_option_mptcp_flags, tvb,
2774 offset, 1, flags);
2775 mptcp_flags_tree = proto_item_add_subtree(ti, ett_tcp_option_mptcp);
2777 proto_tree_add_item(mptcp_flags_tree, hf_tcp_option_mptcp_B_flag,
2778 tvb, offset, 1, ENC_BIG_ENDIAN);
2779 offset += 1;
2781 if (optlen == 4) {
2782 proto_tree_add_item(mptcp_tree,
2783 hf_tcp_option_mptcp_address_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2785 break;
2787 case TCPOPT_MPTCP_MP_FAIL:
2788 offset += 1;
2789 offset += 1;
2790 proto_tree_add_item(mptcp_tree,
2791 hf_tcp_option_mptcp_data_seq_no, tvb, offset, 8, ENC_BIG_ENDIAN);
2792 break;
2794 default:
2795 break;
2799 static void
2800 dissect_tcpopt_cc(const ip_tcp_opt *optp, tvbuff_t *tvb,
2801 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2803 proto_item *hidden_item;
2804 guint32 cc;
2806 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2807 offset, 1, ENC_BIG_ENDIAN);
2808 PROTO_ITEM_SET_HIDDEN(hidden_item);
2809 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2810 offset + 1, 1, ENC_BIG_ENDIAN);
2811 PROTO_ITEM_SET_HIDDEN(hidden_item);
2813 cc = tvb_get_ntohl(tvb, offset + 2);
2814 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_cc, tvb, offset,
2815 optlen, TRUE);
2816 PROTO_ITEM_SET_HIDDEN(hidden_item);
2817 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2818 "%s: %u", optp->name, cc);
2819 tcp_info_append_uint(pinfo, "CC", cc);
2822 static void
2823 dissect_tcpopt_qs(const ip_tcp_opt *optp, tvbuff_t *tvb,
2824 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
2827 proto_item *hidden_item;
2829 guint8 rate = tvb_get_guint8(tvb, offset + 2) & 0x0f;
2831 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2832 offset, 1, ENC_BIG_ENDIAN);
2833 PROTO_ITEM_SET_HIDDEN(hidden_item);
2834 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2835 offset + 1, 1, ENC_BIG_ENDIAN);
2836 PROTO_ITEM_SET_HIDDEN(hidden_item);
2838 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_qs, tvb, offset,
2839 optlen, TRUE);
2840 PROTO_ITEM_SET_HIDDEN(hidden_item);
2841 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2842 "%s: Rate response, %s, TTL diff %u ", optp->name,
2843 val_to_str_ext_const(rate, &qs_rate_vals_ext, "Unknown"),
2844 tvb_get_guint8(tvb, offset + 3));
2845 col_append_fstr(pinfo->cinfo, COL_INFO, " QSresp=%s", val_to_str_ext_const(rate, &qs_rate_vals_ext, "Unknown"));
2849 static void
2850 dissect_tcpopt_scps(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2851 int offset, guint optlen, packet_info *pinfo,
2852 proto_tree *opt_tree, void *data _U_)
2854 struct tcp_analysis *tcpd;
2855 proto_tree *field_tree = NULL;
2856 tcp_flow_t *flow;
2857 int direction;
2858 proto_item *tf = NULL, *hidden_item;
2859 guint8 capvector;
2860 guint8 connid;
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 tcpd = get_tcp_conversation_data(NULL,pinfo);
2871 /* check direction and get ua lists */
2872 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
2874 /* if the addresses are equal, match the ports instead */
2875 if(direction==0) {
2876 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
2879 if(direction>=0)
2880 flow =&(tcpd->flow1);
2881 else
2882 flow =&(tcpd->flow2);
2884 /* If the option length == 4, this is a real SCPS capability option
2885 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
2886 * (SCPS-TP)" Section 3.2.3 for definition.
2888 if (optlen == 4) {
2889 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_scps,
2890 tvb, offset, optlen, TRUE);
2891 PROTO_ITEM_SET_HIDDEN(hidden_item);
2893 capvector = tvb_get_guint8(tvb, offset + 2);
2894 connid = tvb_get_guint8(tvb, offset + 3);
2896 tf = proto_tree_add_item(opt_tree, hf_tcp_option_scps_vector, tvb,
2897 offset + 2, 1, ENC_BIG_ENDIAN);
2898 field_tree = proto_item_add_subtree(tf, ett_tcp_option_scps);
2899 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_bets, tvb,
2900 offset + 2, 1, ENC_BIG_ENDIAN);
2901 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_snack1, tvb,
2902 offset + 2, 1, ENC_BIG_ENDIAN);
2903 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_snack2, tvb,
2904 offset + 2, 1, ENC_BIG_ENDIAN);
2905 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_compress, tvb,
2906 offset + 2, 1, ENC_BIG_ENDIAN);
2907 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_nlts, tvb,
2908 offset + 2, 1, ENC_BIG_ENDIAN);
2909 proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_reserved, tvb,
2910 offset + 2, 1, ENC_BIG_ENDIAN);
2912 if (capvector) {
2913 struct capvec
2915 guint8 mask;
2916 const gchar *str;
2917 } capvecs[] = {
2918 {0x80, "BETS"},
2919 {0x40, "SNACK1"},
2920 {0x20, "SNACK2"},
2921 {0x10, "COMP"},
2922 {0x08, "NLTS"},
2923 {0x07, "RESERVED"}
2925 gboolean anyflag = FALSE;
2926 guint i;
2928 col_append_str(pinfo->cinfo, COL_INFO, " SCPS[");
2929 for (i = 0; i < sizeof(capvecs)/sizeof(struct capvec); i++) {
2930 if (capvector & capvecs[i].mask) {
2931 proto_item_append_text(tf, "%s%s", anyflag ? ", " : " (",
2932 capvecs[i].str);
2933 col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s",
2934 anyflag ? ", " : "", capvecs[i].str);
2935 anyflag = TRUE;
2938 col_append_str(pinfo->cinfo, COL_INFO, "]");
2939 proto_item_append_text(tf, ")");
2942 proto_tree_add_item(field_tree, hf_tcp_scpsoption_connection_id, tvb,
2943 offset + 3, 1, ENC_BIG_ENDIAN);
2944 flow->scps_capable = 1;
2946 if (connid)
2947 tcp_info_append_uint(pinfo, "Connection ID", connid);
2948 } else {
2949 /* The option length != 4, so this is an infamous "extended capabilities
2950 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2951 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
2953 * As the format of this option is only partially defined (it is
2954 * a community (or more likely vendor) defined format beyond that, so
2955 * at least for now, we only parse the standardized portion of the option.
2957 guint8 local_offset = 2;
2958 guint8 binding_space;
2959 guint8 extended_cap_length;
2961 if (flow->scps_capable != 1) {
2962 /* There was no SCPS capabilities option preceding this */
2963 proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2964 tvb, offset, optlen, 0,
2965 "Illegal SCPS Extended Capabilities (%d bytes)",
2966 optlen);
2967 } else {
2968 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2969 tvb, offset, optlen, 0,
2970 "SCPS Extended Capabilities (%d bytes)",
2971 optlen);
2972 field_tree=proto_item_add_subtree(tf, ett_tcp_option_scps_extended);
2974 /* There may be multiple binding spaces included in a single option,
2975 * so we will semi-parse each of the stacked binding spaces - skipping
2976 * over the octets following the binding space identifier and length.
2978 while (optlen > local_offset) {
2980 /* 1st octet is Extended Capability Binding Space */
2981 binding_space = tvb_get_guint8(tvb, (offset + local_offset));
2983 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
2984 * As defined by the specification, this length is exclusive of the
2985 * octets containing the extended capability type and length
2987 extended_cap_length =
2988 (tvb_get_guint8(tvb, (offset + local_offset + 1)) >> 4);
2990 /* Convert the extended capabilities length into bytes for display */
2991 extended_cap_length = (extended_cap_length << 1);
2993 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding, tvb, offset + local_offset, 1, ENC_BIG_ENDIAN);
2994 proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding_len, tvb, offset + local_offset + 1, 1, extended_cap_length);
2996 /* Step past the binding space and length octets */
2997 local_offset += 2;
2999 proto_tree_add_text(field_tree, tvb, offset + local_offset,
3000 extended_cap_length,
3001 "Binding Space Data (%u bytes)",
3002 extended_cap_length);
3004 tcp_info_append_uint(pinfo, "EXCAP", binding_space);
3006 /* Step past the Extended capability data
3007 * Treat the extended capability data area as opaque;
3008 * If one desires to parse the extended capability data
3009 * (say, in a vendor aware build of wireshark), it would
3010 * be triggered here.
3012 local_offset += extended_cap_length;
3018 static void
3019 dissect_tcpopt_user_to(const ip_tcp_opt *optp, tvbuff_t *tvb,
3020 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree, void *data _U_)
3022 proto_item *hidden_item, *tf;
3023 proto_tree *field_tree;
3024 gboolean g;
3025 guint16 to;
3027 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
3028 offset, 1, ENC_BIG_ENDIAN);
3029 PROTO_ITEM_SET_HIDDEN(hidden_item);
3030 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
3031 offset + 1, 1, ENC_BIG_ENDIAN);
3032 PROTO_ITEM_SET_HIDDEN(hidden_item);
3034 g = tvb_get_ntohs(tvb, offset + 2) & 0x8000;
3035 to = tvb_get_ntohs(tvb, offset + 2) & 0x7FFF;
3036 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_user_to, tvb, offset,
3037 optlen, TRUE);
3038 PROTO_ITEM_SET_HIDDEN(hidden_item);
3040 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_user_to_val, tvb, offset,
3041 optlen, to, "%s: %u %s", optp->name, to, g ? "minutes" : "seconds");
3042 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
3043 proto_tree_add_item(field_tree, hf_tcp_option_user_to_granularity, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
3044 proto_tree_add_item(field_tree, hf_tcp_option_user_to_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
3046 tcp_info_append_uint(pinfo, "USER_TO", to);
3049 /* This is called for SYN+ACK packets and the purpose is to verify that
3050 * the SCPS capabilities option has been successfully negotiated for the flow.
3051 * If the SCPS capabilities option was offered by only one party, the
3052 * proactively set scps_capable attribute of the flow (set upon seeing
3053 * the first instance of the SCPS option) is revoked.
3055 static void
3056 verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd)
3058 tf_syn = 0x0;
3060 if(tcpd) {
3061 if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) {
3062 tcpd->flow1.scps_capable = 0;
3063 tcpd->flow2.scps_capable = 0;
3064 } else {
3065 expert_add_info(pinfo, tf_syn, &ei_tcp_scps_capable);
3070 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
3071 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
3073 static void
3074 dissect_tcpopt_snack(const ip_tcp_opt *optp, tvbuff_t *tvb,
3075 int offset, guint optlen, packet_info *pinfo,
3076 proto_tree *opt_tree, void *data _U_)
3078 struct tcp_analysis *tcpd=NULL;
3079 guint16 relative_hole_offset;
3080 guint16 relative_hole_size;
3081 guint16 base_mss = 0;
3082 guint32 ack;
3083 guint32 hole_start;
3084 guint32 hole_end;
3085 char null_modifier[] = "\0";
3086 char relative_modifier[] = "(relative)";
3087 char *modifier = null_modifier;
3088 proto_item *hidden_item;
3090 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
3091 offset, 1, ENC_BIG_ENDIAN);
3092 PROTO_ITEM_SET_HIDDEN(hidden_item);
3093 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
3094 offset + 1, 1, ENC_BIG_ENDIAN);
3095 PROTO_ITEM_SET_HIDDEN(hidden_item);
3097 tcpd = get_tcp_conversation_data(NULL,pinfo);
3099 /* The SNACK option reports missing data with a granularity of segments. */
3100 relative_hole_offset = tvb_get_ntohs(tvb, offset + 2);
3101 relative_hole_size = tvb_get_ntohs(tvb, offset + 4);
3103 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_snack, tvb,
3104 offset, optlen, TRUE);
3105 PROTO_ITEM_SET_HIDDEN(hidden_item);
3107 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_offset,
3108 tvb, offset, optlen, relative_hole_offset);
3109 PROTO_ITEM_SET_HIDDEN(hidden_item);
3111 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_size,
3112 tvb, offset, optlen, relative_hole_size);
3113 PROTO_ITEM_SET_HIDDEN(hidden_item);
3114 proto_tree_add_text(opt_tree, tvb, offset, optlen,
3115 "%s: Offset %u, Size %u", optp->name,
3116 relative_hole_offset, relative_hole_size);
3118 ack = tvb_get_ntohl(tvb, 8);
3120 if (tcp_relative_seq) {
3121 ack -= tcpd->rev->base_seq;
3122 modifier = relative_modifier;
3125 /* To aid analysis, we can use a simple but generally effective heuristic
3126 * to report the most likely boundaries of the missing data. If the
3127 * flow is scps_capable, we track the maximum sized segment that was
3128 * acknowledged by the receiver and use that as the reporting granularity.
3129 * This may be different from the negotiated MTU due to PMTUD or flows
3130 * that do not send max-sized segments.
3132 base_mss = tcpd->fwd->maxsizeacked;
3134 if (base_mss) {
3135 /* Scale the reported offset and hole size by the largest segment acked */
3136 hole_start = ack + (base_mss * relative_hole_offset);
3137 hole_end = hole_start + (base_mss * relative_hole_size);
3139 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_le,
3140 tvb, offset, optlen, hole_start);
3141 PROTO_ITEM_SET_HIDDEN(hidden_item);
3143 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_re,
3144 tvb, offset, optlen, hole_end);
3145 PROTO_ITEM_SET_HIDDEN(hidden_item);
3146 proto_tree_add_text(opt_tree, tvb, offset, optlen,
3147 "\tMissing Sequence %u - %u %s",
3148 hole_start, hole_end, modifier);
3150 tcp_info_append_uint(pinfo, "SNLE", hole_start);
3151 tcp_info_append_uint(pinfo, "SNRE", hole_end);
3153 expert_add_info_format(pinfo, NULL, &ei_tcp_option_snack_sequence, "SNACK Sequence %u - %u %s", hole_start, hole_end, modifier);
3157 enum
3159 PROBE_VERSION_UNSPEC = 0,
3160 PROBE_VERSION_1 = 1,
3161 PROBE_VERSION_2 = 2,
3162 PROBE_VERSION_MAX
3165 /* Probe type definition. */
3166 enum
3168 PROBE_QUERY = 0,
3169 PROBE_RESPONSE = 1,
3170 PROBE_INTERNAL = 2,
3171 PROBE_TRACE = 3,
3172 PROBE_QUERY_SH = 4,
3173 PROBE_RESPONSE_SH = 5,
3174 PROBE_QUERY_INFO = 6,
3175 PROBE_RESPONSE_INFO = 7,
3176 PROBE_QUERY_INFO_SH = 8,
3177 PROBE_QUERY_INFO_SID = 9,
3178 PROBE_RST = 10,
3179 PROBE_TYPE_MAX
3182 static const value_string rvbd_probe_type_vs[] = {
3183 { PROBE_QUERY, "Probe Query" },
3184 { PROBE_RESPONSE, "Probe Response" },
3185 { PROBE_INTERNAL, "Probe Internal" },
3186 { PROBE_TRACE, "Probe Trace" },
3187 { PROBE_QUERY_SH, "Probe Query SH" },
3188 { PROBE_RESPONSE_SH, "Probe Response SH" },
3189 { PROBE_QUERY_INFO, "Probe Query Info" },
3190 { PROBE_RESPONSE_INFO, "Probe Response Info" },
3191 { PROBE_QUERY_INFO_SH, "Probe Query Info SH" },
3192 { PROBE_QUERY_INFO_SID, "Probe Query Info Store ID" },
3193 { PROBE_RST, "Probe Reset" },
3194 { 0, NULL }
3198 #define PROBE_OPTLEN_OFFSET 1
3200 #define PROBE_VERSION_TYPE_OFFSET 2
3201 #define PROBE_V1_RESERVED_OFFSET 3
3202 #define PROBE_V1_PROBER_OFFSET 4
3203 #define PROBE_V1_APPLI_VERSION_OFFSET 8
3204 #define PROBE_V1_PROXY_ADDR_OFFSET 8
3205 #define PROBE_V1_PROXY_PORT_OFFSET 12
3206 #define PROBE_V1_SH_CLIENT_ADDR_OFFSET 8
3207 #define PROBE_V1_SH_PROXY_ADDR_OFFSET 12
3208 #define PROBE_V1_SH_PROXY_PORT_OFFSET 16
3210 #define PROBE_V2_INFO_OFFSET 3
3212 #define PROBE_V2_INFO_CLIENT_ADDR_OFFSET 4
3213 #define PROBE_V2_INFO_STOREID_OFFSET 4
3215 #define PROBE_VERSION_MASK 0x01
3217 /* Probe Query Extra Info flags */
3218 #define RVBD_FLAGS_PROBE_LAST 0x01
3219 #define RVBD_FLAGS_PROBE_NCFE 0x04
3221 /* Probe Response Extra Info flags */
3222 #define RVBD_FLAGS_PROBE_SERVER 0x01
3223 #define RVBD_FLAGS_PROBE_SSLCERT 0x02
3224 #define RVBD_FLAGS_PROBE 0x10
3226 static void
3227 rvbd_probe_decode_version_type(const guint8 vt, guint8 *ver, guint8 *type)
3229 if (vt & PROBE_VERSION_MASK) {
3230 *ver = PROBE_VERSION_1;
3231 *type = vt >> 4;
3232 } else {
3233 *ver = PROBE_VERSION_2;
3234 *type = vt >> 1;
3238 static void
3239 rvbd_probe_resp_add_info(proto_item *pitem, packet_info *pinfo, guint32 ip, guint16 port)
3241 proto_item_append_text(pitem, ", Server Steelhead: %s:%u", ip_to_str((guint8 *)&ip), port);
3243 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA+, ");
3246 static void
3247 dissect_tcpopt_rvbd_probe(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
3248 guint optlen, packet_info *pinfo, proto_tree *opt_tree,
3249 void *data _U_)
3251 guint8 ver, type;
3252 proto_tree *field_tree;
3253 proto_item *pitem;
3255 rvbd_probe_decode_version_type(
3256 tvb_get_guint8(tvb, offset + PROBE_VERSION_TYPE_OFFSET),
3257 &ver, &type);
3259 pitem = proto_tree_add_boolean_format_value(
3260 opt_tree, hf_tcp_option_rvbd_probe, tvb, offset, optlen, 1,
3261 "%s", val_to_str_const(type, rvbd_probe_type_vs, "Probe Unknown"));
3263 if (type >= PROBE_TYPE_MAX)
3264 return;
3266 /* optlen, type, ver are common for all probes */
3267 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe);
3268 pitem = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
3269 offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN);
3270 PROTO_ITEM_SET_HIDDEN(pitem);
3271 pitem = proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
3272 offset, 1, ENC_BIG_ENDIAN);
3273 PROTO_ITEM_SET_HIDDEN(pitem);
3274 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_optlen, tvb,
3275 offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN);
3277 if (ver == PROBE_VERSION_1) {
3278 guint32 ip;
3279 guint16 port;
3281 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type1, tvb,
3282 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
3283 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
3284 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
3286 if (type == PROBE_INTERNAL)
3287 return;
3289 proto_tree_add_text(field_tree, tvb, offset + PROBE_V1_RESERVED_OFFSET,
3290 1, "Reserved");
3292 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_PROBER_OFFSET);
3293 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_prober, tvb,
3294 offset + PROBE_V1_PROBER_OFFSET, 4, ENC_BIG_ENDIAN);
3296 switch (type) {
3298 case PROBE_QUERY:
3299 case PROBE_QUERY_SH:
3300 case PROBE_TRACE:
3301 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_appli_ver, tvb,
3302 offset + PROBE_V1_APPLI_VERSION_OFFSET, 2,
3303 ENC_BIG_ENDIAN);
3305 proto_item_append_text(pitem, ", CSH IP: %s", ip_to_str((guint8 *)&ip));
3308 /* Small look-ahead hack to distinguish S+ from S+* */
3309 #define PROBE_V1_QUERY_LEN 10
3310 const guint8 qinfo_hdr[] = { 0x4c, 0x04, 0x0c };
3311 int not_cfe = 0;
3312 /* tvb_memeql seems to be the only API that doesn't throw
3313 an exception in case of an error */
3314 if (tvb_memeql(tvb, offset + PROBE_V1_QUERY_LEN,
3315 qinfo_hdr, sizeof(qinfo_hdr)) == 0) {
3316 not_cfe = tvb_get_guint8(tvb, offset + PROBE_V1_QUERY_LEN +
3317 (int)sizeof(qinfo_hdr)) & RVBD_FLAGS_PROBE_NCFE;
3319 col_prepend_fstr(pinfo->cinfo, COL_INFO, "S%s, ",
3320 type == PROBE_TRACE ? "#" :
3321 not_cfe ? "+*" : "+");
3323 break;
3325 case PROBE_RESPONSE:
3326 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_PROXY_ADDR_OFFSET);
3327 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
3328 offset + PROBE_V1_PROXY_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
3330 port = tvb_get_ntohs(tvb, offset + PROBE_V1_PROXY_PORT_OFFSET);
3331 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
3332 offset + PROBE_V1_PROXY_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3334 rvbd_probe_resp_add_info(pitem, pinfo, ip, port);
3335 break;
3337 case PROBE_RESPONSE_SH:
3338 proto_tree_add_item(field_tree,
3339 hf_tcp_option_rvbd_probe_client, tvb,
3340 offset + PROBE_V1_SH_CLIENT_ADDR_OFFSET, 4,
3341 ENC_BIG_ENDIAN);
3343 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_SH_PROXY_ADDR_OFFSET);
3344 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
3345 offset + PROBE_V1_SH_PROXY_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
3347 port = tvb_get_ntohs(tvb, offset + PROBE_V1_SH_PROXY_PORT_OFFSET);
3348 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
3349 offset + PROBE_V1_SH_PROXY_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3351 rvbd_probe_resp_add_info(pitem, pinfo, ip, port);
3352 break;
3355 else if (ver == PROBE_VERSION_2) {
3356 proto_item *ver_pi;
3357 proto_item *flag_pi;
3358 proto_tree *flag_tree;
3359 guint8 flags;
3361 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type2, tvb,
3362 offset + PROBE_VERSION_TYPE_OFFSET, 1, ENC_BIG_ENDIAN);
3364 proto_tree_add_uint_format_value(
3365 field_tree, hf_tcp_option_rvbd_probe_version2, tvb,
3366 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver, "%u", ver);
3367 /* Use version1 for filtering purposes because version2 packet
3368 value is 0, but filtering is usually done for value 2 */
3369 ver_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
3370 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver);
3371 PROTO_ITEM_SET_HIDDEN(ver_pi);
3373 switch (type) {
3375 case PROBE_QUERY_INFO:
3376 case PROBE_QUERY_INFO_SH:
3377 case PROBE_QUERY_INFO_SID:
3378 flags = tvb_get_guint8(tvb, offset + PROBE_V2_INFO_OFFSET);
3379 flag_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_flags,
3380 tvb, offset + PROBE_V2_INFO_OFFSET,
3381 1, flags);
3383 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
3384 proto_tree_add_item(flag_tree,
3385 hf_tcp_option_rvbd_probe_flag_not_cfe,
3386 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3387 proto_tree_add_item(flag_tree,
3388 hf_tcp_option_rvbd_probe_flag_last_notify,
3389 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3391 if (type == PROBE_QUERY_INFO_SH)
3392 proto_tree_add_item(flag_tree,
3393 hf_tcp_option_rvbd_probe_client, tvb,
3394 offset + PROBE_V2_INFO_CLIENT_ADDR_OFFSET,
3395 4, ENC_BIG_ENDIAN);
3396 else if (type == PROBE_QUERY_INFO_SID)
3397 proto_tree_add_item(flag_tree,
3398 hf_tcp_option_rvbd_probe_storeid, tvb,
3399 offset + PROBE_V2_INFO_STOREID_OFFSET,
3400 4, ENC_BIG_ENDIAN);
3402 if (type != PROBE_QUERY_INFO_SID &&
3403 (tvb_get_guint8(tvb, 13) & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK) &&
3404 (flags & RVBD_FLAGS_PROBE_LAST)) {
3405 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA++, ");
3408 break;
3410 case PROBE_RESPONSE_INFO:
3411 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
3412 tvb, offset + PROBE_V2_INFO_OFFSET,
3413 1, ENC_BIG_ENDIAN);
3415 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
3416 proto_tree_add_item(flag_tree,
3417 hf_tcp_option_rvbd_probe_flag_probe_cache,
3418 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3419 proto_tree_add_item(flag_tree,
3420 hf_tcp_option_rvbd_probe_flag_sslcert,
3421 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3422 proto_tree_add_item(flag_tree,
3423 hf_tcp_option_rvbd_probe_flag_server_connected,
3424 tvb, offset + PROBE_V2_INFO_OFFSET, 1, ENC_BIG_ENDIAN);
3425 break;
3427 case PROBE_RST:
3428 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
3429 tvb, offset + PROBE_V2_INFO_OFFSET,
3430 1, ENC_BIG_ENDIAN);
3431 break;
3436 enum {
3437 TRPY_OPTNUM_OFFSET = 0,
3438 TRPY_OPTLEN_OFFSET = 1,
3440 TRPY_OPTIONS_OFFSET = 2,
3441 TRPY_SRC_ADDR_OFFSET = 4,
3442 TRPY_DST_ADDR_OFFSET = 8,
3443 TRPY_SRC_PORT_OFFSET = 12,
3444 TRPY_DST_PORT_OFFSET = 14,
3445 TRPY_CLIENT_PORT_OFFSET = 16
3448 /* Trpy Flags */
3449 #define RVBD_FLAGS_TRPY_MODE 0x0001
3450 #define RVBD_FLAGS_TRPY_OOB 0x0002
3451 #define RVBD_FLAGS_TRPY_CHKSUM 0x0004
3452 #define RVBD_FLAGS_TRPY_FW_RST 0x0100
3453 #define RVBD_FLAGS_TRPY_FW_RST_INNER 0x0200
3454 #define RVBD_FLAGS_TRPY_FW_RST_PROBE 0x0400
3456 static const true_false_string trpy_mode_str = {
3457 "Port Transparency",
3458 "Full Transparency"
3461 static void
3462 dissect_tcpopt_rvbd_trpy(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
3463 int offset, guint optlen, packet_info *pinfo,
3464 proto_tree *opt_tree, void *data _U_)
3466 proto_tree *field_tree;
3467 proto_tree *flag_tree;
3468 proto_item *pitem;
3469 proto_item *flag_pi;
3470 guint32 src, dst;
3471 guint16 sport, dport, flags;
3473 col_prepend_fstr(pinfo->cinfo, COL_INFO, "TRPY, ");
3475 pitem = proto_tree_add_boolean_format_value(
3476 opt_tree, hf_tcp_option_rvbd_trpy, tvb, offset, optlen, 1,
3477 "%s", "");
3479 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_trpy);
3480 pitem = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
3481 offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN);
3482 PROTO_ITEM_SET_HIDDEN(pitem);
3483 pitem = proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
3484 offset, 1, ENC_BIG_ENDIAN);
3485 PROTO_ITEM_SET_HIDDEN(pitem);
3486 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_optlen, tvb,
3487 offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN);
3489 flags = tvb_get_ntohs(tvb, offset + TRPY_OPTIONS_OFFSET);
3490 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_flags,
3491 tvb, offset + TRPY_OPTIONS_OFFSET,
3492 2, ENC_BIG_ENDIAN);
3494 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_trpy_flags);
3495 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
3496 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3497 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
3498 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3499 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst,
3500 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3501 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_chksum,
3502 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3503 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_oob,
3504 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3505 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_mode,
3506 tvb, offset + TRPY_OPTIONS_OFFSET, 2, ENC_BIG_ENDIAN);
3508 src = tvb_get_ipv4(tvb, offset + TRPY_SRC_ADDR_OFFSET);
3509 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src,
3510 tvb, offset + TRPY_SRC_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
3512 dst = tvb_get_ipv4(tvb, offset + TRPY_DST_ADDR_OFFSET);
3513 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst,
3514 tvb, offset + TRPY_DST_ADDR_OFFSET, 4, ENC_BIG_ENDIAN);
3516 sport = tvb_get_ntohs(tvb, offset + TRPY_SRC_PORT_OFFSET);
3517 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src_port,
3518 tvb, offset + TRPY_SRC_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3520 dport = tvb_get_ntohs(tvb, offset + TRPY_DST_PORT_OFFSET);
3521 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst_port,
3522 tvb, offset + TRPY_DST_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3524 proto_item_append_text(pitem, "%s:%u -> %s:%u",
3525 ip_to_str((guint8 *)&src), sport,
3526 ip_to_str((guint8 *)&dst), dport);
3528 /* Client port only set on SYN: optlen == 18 */
3529 if ((flags & RVBD_FLAGS_TRPY_OOB) && (optlen > TCPOLEN_RVBD_TRPY_MIN))
3530 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_client_port,
3531 tvb, offset + TRPY_CLIENT_PORT_OFFSET, 2, ENC_BIG_ENDIAN);
3533 /* Despite that we have the right TCP ports for other protocols,
3534 * the data is related to the Riverbed Optimization Protocol and
3535 * not understandable by normal protocol dissectors. If the sport
3536 * protocol is available then use that, otherwise just output it
3537 * as a hex-dump.
3539 if (sport_handle != NULL) {
3540 conversation_t *conversation;
3541 conversation = find_conversation(pinfo->fd->num,
3542 &pinfo->src, &pinfo->dst, pinfo->ptype,
3543 pinfo->srcport, pinfo->destport, 0);
3544 if (conversation == NULL) {
3545 conversation = conversation_new(pinfo->fd->num,
3546 &pinfo->src, &pinfo->dst, pinfo->ptype,
3547 pinfo->srcport, pinfo->destport, 0);
3549 if (conversation->dissector_handle != sport_handle) {
3550 conversation_set_dissector(conversation, sport_handle);
3552 } else if (data_handle != NULL) {
3553 conversation_t *conversation;
3554 conversation = find_conversation(pinfo->fd->num,
3555 &pinfo->src, &pinfo->dst, pinfo->ptype,
3556 pinfo->srcport, pinfo->destport, 0);
3557 if (conversation == NULL) {
3558 conversation = conversation_new(pinfo->fd->num,
3559 &pinfo->src, &pinfo->dst, pinfo->ptype,
3560 pinfo->srcport, pinfo->destport, 0);
3562 if (conversation->dissector_handle != data_handle) {
3563 conversation_set_dissector(conversation, data_handle);
3568 static const ip_tcp_opt tcpopts[] = {
3570 TCPOPT_EOL,
3571 "End of Option List (EOL)",
3572 NULL,
3573 OPT_LEN_NO_LENGTH,
3575 NULL,
3578 TCPOPT_NOP,
3579 "No-Operation (NOP)",
3580 NULL,
3581 OPT_LEN_NO_LENGTH,
3583 NULL,
3586 TCPOPT_MSS,
3587 "Maximum segment size",
3588 NULL,
3589 OPT_LEN_FIXED_LENGTH,
3590 TCPOLEN_MSS,
3591 dissect_tcpopt_mss
3594 TCPOPT_WINDOW,
3595 "Window scale",
3596 NULL,
3597 OPT_LEN_FIXED_LENGTH,
3598 TCPOLEN_WINDOW,
3599 dissect_tcpopt_wscale
3602 TCPOPT_SACK_PERM,
3603 "SACK permitted",
3604 NULL,
3605 OPT_LEN_FIXED_LENGTH,
3606 TCPOLEN_SACK_PERM,
3607 dissect_tcpopt_sack_perm,
3610 TCPOPT_SACK,
3611 "SACK",
3612 &ett_tcp_option_sack,
3613 OPT_LEN_VARIABLE_LENGTH,
3614 TCPOLEN_SACK_MIN,
3615 dissect_tcpopt_sack
3618 TCPOPT_ECHO,
3619 "Echo",
3620 NULL,
3621 OPT_LEN_FIXED_LENGTH,
3622 TCPOLEN_ECHO,
3623 dissect_tcpopt_echo
3626 TCPOPT_ECHOREPLY,
3627 "Echo reply",
3628 NULL,
3629 OPT_LEN_FIXED_LENGTH,
3630 TCPOLEN_ECHOREPLY,
3631 dissect_tcpopt_echo
3634 TCPOPT_TIMESTAMP,
3635 "Timestamps",
3636 NULL,
3637 OPT_LEN_FIXED_LENGTH,
3638 TCPOLEN_TIMESTAMP,
3639 dissect_tcpopt_timestamp
3642 TCPOPT_MPTCP,
3643 "Multipath TCP",
3644 NULL,
3645 OPT_LEN_VARIABLE_LENGTH,
3646 TCPOLEN_MPTCP_MIN,
3647 dissect_tcpopt_mptcp
3650 TCPOPT_CC,
3651 "CC",
3652 NULL,
3653 OPT_LEN_FIXED_LENGTH,
3654 TCPOLEN_CC,
3655 dissect_tcpopt_cc
3658 TCPOPT_CCNEW,
3659 "CC.NEW",
3660 NULL,
3661 OPT_LEN_FIXED_LENGTH,
3662 TCPOLEN_CCNEW,
3663 dissect_tcpopt_cc
3666 TCPOPT_CCECHO,
3667 "CC.ECHO",
3668 NULL,
3669 OPT_LEN_FIXED_LENGTH,
3670 TCPOLEN_CCECHO,
3671 dissect_tcpopt_cc
3674 TCPOPT_MD5,
3675 "TCP MD5 signature",
3676 NULL,
3677 OPT_LEN_FIXED_LENGTH,
3678 TCPOLEN_MD5,
3679 NULL
3682 TCPOPT_SCPS,
3683 "SCPS capabilities",
3684 &ett_tcp_option_scps,
3685 OPT_LEN_VARIABLE_LENGTH,
3686 TCPOLEN_SCPS,
3687 dissect_tcpopt_scps
3690 TCPOPT_SNACK,
3691 "Selective Negative Acknowledgment",
3692 NULL,
3693 OPT_LEN_FIXED_LENGTH,
3694 TCPOLEN_SNACK,
3695 dissect_tcpopt_snack
3698 TCPOPT_RECBOUND,
3699 "SCPS record boundary",
3700 NULL,
3701 OPT_LEN_FIXED_LENGTH,
3702 TCPOLEN_RECBOUND,
3703 NULL
3706 TCPOPT_CORREXP,
3707 "SCPS corruption experienced",
3708 NULL,
3709 OPT_LEN_FIXED_LENGTH,
3710 TCPOLEN_CORREXP,
3711 NULL
3714 TCPOPT_QS,
3715 "Quick-Start",
3716 NULL,
3717 OPT_LEN_FIXED_LENGTH,
3718 TCPOLEN_QS,
3719 dissect_tcpopt_qs
3722 TCPOPT_USER_TO,
3723 "User Timeout",
3724 &ett_tcp_option_user_to,
3725 OPT_LEN_FIXED_LENGTH,
3726 TCPOLEN_USER_TO,
3727 dissect_tcpopt_user_to
3730 TCPOPT_RVBD_PROBE,
3731 "Riverbed Probe",
3732 NULL,
3733 OPT_LEN_VARIABLE_LENGTH,
3734 TCPOLEN_RVBD_PROBE_MIN,
3735 dissect_tcpopt_rvbd_probe
3738 TCPOPT_RVBD_TRPY,
3739 "Riverbed Transparency",
3740 NULL,
3741 OPT_LEN_FIXED_LENGTH,
3742 TCPOLEN_RVBD_TRPY_MIN,
3743 dissect_tcpopt_rvbd_trpy
3746 TCPOPT_EXP_FD,
3747 "Experimental",
3748 NULL,
3749 OPT_LEN_VARIABLE_LENGTH,
3750 TCPOLEN_EXP_MIN,
3751 dissect_tcpopt_exp
3754 TCPOPT_EXP_FE,
3755 "Experimental",
3756 NULL,
3757 OPT_LEN_VARIABLE_LENGTH,
3758 TCPOLEN_EXP_MIN,
3759 dissect_tcpopt_exp
3763 #define N_TCP_OPTS array_length(tcpopts)
3765 static ip_tcp_opt_type TCP_OPT_TYPES = {&hf_tcp_option_type, &ett_tcp_option_type,
3766 &hf_tcp_option_type_copy, &hf_tcp_option_type_class, &hf_tcp_option_type_number};
3768 /* Determine if there is a sub-dissector and call it; return TRUE
3769 if there was a sub-dissector, FALSE otherwise.
3771 This has been separated into a stand alone routine to other protocol
3772 dissectors can call to it, e.g., SOCKS. */
3774 static gboolean try_heuristic_first = FALSE;
3777 /* this function can be called with tcpd==NULL as from the msproxy dissector */
3778 gboolean
3779 decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
3780 proto_tree *tree, int src_port, int dst_port,
3781 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
3783 tvbuff_t *next_tvb;
3784 int low_port, high_port;
3785 int save_desegment_offset;
3786 guint32 save_desegment_len;
3788 /* Don't call subdissectors for keepalives. Even though they do contain
3789 * payload "data", it's just garbage. Display any data the keepalive
3790 * packet might contain though.
3792 if(tcpd && tcpd->ta) {
3793 if(tcpd->ta->flags&TCP_A_KEEP_ALIVE) {
3794 next_tvb = tvb_new_subset_remaining(tvb, offset);
3795 call_dissector(data_handle, next_tvb, pinfo, tree);
3796 return TRUE;
3800 if (tcp_no_subdissector_on_error && tcpd && tcpd->ta && tcpd->ta->flags & (TCP_A_RETRANSMISSION | TCP_A_OUT_OF_ORDER)) {
3801 /* Don't try to dissect a retransmission high chance that it will mess
3802 * subdissectors for protocols that require in-order delivery of the
3803 * PDUs. (i.e. DCE/RPCoverHTTP and encryption)
3805 return FALSE;
3807 next_tvb = tvb_new_subset_remaining(tvb, offset);
3809 /* determine if this packet is part of a conversation and call dissector */
3810 /* for the conversation if available */
3812 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP,
3813 src_port, dst_port, next_tvb, pinfo, tree, tcpinfo)) {
3814 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3815 return TRUE;
3818 if (try_heuristic_first) {
3819 /* do lookup with the heuristic subdissector table */
3820 save_desegment_offset = pinfo->desegment_offset;
3821 save_desegment_len = pinfo->desegment_len;
3822 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, tcpinfo)) {
3823 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3824 return TRUE;
3827 * They rejected the packet; make sure they didn't also request
3828 * desegmentation (we could just override the request, but
3829 * rejecting a packet *and* requesting desegmentation is a sign
3830 * of the dissector's code needing clearer thought, so we fail
3831 * so that the problem is made more obvious).
3833 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
3834 save_desegment_len == pinfo->desegment_len);
3837 /* Do lookups with the subdissector table.
3838 Try the server port captured on the SYN or SYN|ACK packet. After that
3839 try the port number with the lower value first, followed by the
3840 port number with the higher value. This means that, for packets
3841 where a dissector is registered for *both* port numbers:
3843 1) we pick the same dissector for traffic going in both directions;
3845 2) we prefer the port number that's more likely to be the right
3846 one (as that prefers well-known ports to reserved ports);
3848 although there is, of course, no guarantee that any such strategy
3849 will always pick the right port number.
3851 XXX - we ignore port numbers of 0, as some dissectors use a port
3852 number of 0 to disable the port. */
3854 if (tcpd && tcpd->server_port != 0 &&
3855 dissector_try_uint_new(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) {
3856 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3857 return TRUE;
3860 if (src_port > dst_port) {
3861 low_port = dst_port;
3862 high_port = src_port;
3863 } else {
3864 low_port = src_port;
3865 high_port = dst_port;
3868 if (low_port != 0 &&
3869 dissector_try_uint_new(subdissector_table, low_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) {
3870 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3871 return TRUE;
3873 if (high_port != 0 &&
3874 dissector_try_uint_new(subdissector_table, high_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) {
3875 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3876 return TRUE;
3879 if (!try_heuristic_first) {
3880 /* do lookup with the heuristic subdissector table */
3881 save_desegment_offset = pinfo->desegment_offset;
3882 save_desegment_len = pinfo->desegment_len;
3883 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, tcpinfo)) {
3884 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3885 return TRUE;
3888 * They rejected the packet; make sure they didn't also request
3889 * desegmentation (we could just override the request, but
3890 * rejecting a packet *and* requesting desegmentation is a sign
3891 * of the dissector's code needing clearer thought, so we fail
3892 * so that the problem is made more obvious).
3894 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
3895 save_desegment_len == pinfo->desegment_len);
3898 /* Oh, well, we don't know this; dissect it as data. */
3899 call_dissector(data_handle,next_tvb, pinfo, tree);
3901 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3902 return FALSE;
3905 static void
3906 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
3907 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
3908 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
3909 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
3911 pinfo->want_pdu_tracking=0;
3913 TRY {
3914 if(is_tcp_segment) {
3915 /*qqq see if it is an unaligned PDU */
3916 if(tcpd && tcp_analyze_seq && (!tcp_desegment)) {
3917 if(seq || nxtseq) {
3918 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
3919 seq, nxtseq, tcpd->fwd->multisegment_pdus);
3923 /* if offset is -1 this means that this segment is known
3924 * to be fully inside a previously detected pdu
3925 * so we don't even need to try to dissect it either.
3927 if( (offset!=-1) &&
3928 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
3929 dst_port, tcpd, tcpinfo) ) {
3931 * We succeeded in handing off to a subdissector.
3933 * Is this a TCP segment or a reassembled chunk of
3934 * TCP payload?
3936 if(is_tcp_segment) {
3937 /* if !visited, check want_pdu_tracking and
3938 store it in table */
3939 if(tcpd && (!pinfo->fd->flags.visited) &&
3940 tcp_analyze_seq && pinfo->want_pdu_tracking) {
3941 if(seq || nxtseq) {
3942 pdu_store_sequencenumber_of_next_pdu(
3943 pinfo,
3944 seq,
3945 nxtseq+pinfo->bytes_until_next_pdu,
3946 tcpd->fwd->multisegment_pdus);
3952 CATCH_ALL {
3953 /* We got an exception. At this point the dissection is
3954 * completely aborted and execution will be transferred back
3955 * to (probably) the frame dissector.
3956 * Here we have to place whatever we want the dissector
3957 * to do before aborting the tcp dissection.
3960 * Is this a TCP segment or a reassembled chunk of TCP
3961 * payload?
3963 if(is_tcp_segment) {
3965 * It's from a TCP segment.
3967 * if !visited, check want_pdu_tracking and store it
3968 * in table
3970 if(tcpd && (!pinfo->fd->flags.visited) && tcp_analyze_seq && pinfo->want_pdu_tracking) {
3971 if(seq || nxtseq) {
3972 pdu_store_sequencenumber_of_next_pdu(pinfo,
3973 seq,
3974 nxtseq+pinfo->bytes_until_next_pdu,
3975 tcpd->fwd->multisegment_pdus);
3979 RETHROW;
3981 ENDTRY;
3984 void
3985 dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,
3986 guint32 nxtseq, guint32 sport, guint32 dport,
3987 proto_tree *tree, proto_tree *tcp_tree,
3988 struct tcp_analysis *tcpd, struct tcpinfo *tcpinfo)
3990 gboolean save_fragmented;
3992 /* Can we desegment this segment? */
3993 if (pinfo->can_desegment) {
3994 /* Yes. */
3995 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
3996 tcp_tree, tcpd, tcpinfo);
3997 } else {
3998 /* No - just call the subdissector.
3999 Mark this as fragmented, so if somebody throws an exception,
4000 we don't report it as a malformed frame. */
4001 save_fragmented = pinfo->fragmented;
4002 pinfo->fragmented = TRUE;
4003 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
4004 seq, nxtseq, TRUE, tcpd, tcpinfo);
4005 pinfo->fragmented = save_fragmented;
4009 static void
4010 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4012 guint8 th_off_x2; /* combines th_off and th_x2 */
4013 guint16 th_sum;
4014 guint16 th_urp;
4015 proto_tree *tcp_tree = NULL, *field_tree = NULL;
4016 proto_item *ti = NULL, *tf, *hidden_item;
4017 int offset = 0;
4018 wmem_strbuf_t *flags_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
4019 static const gchar *flags[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR", "NS"};
4020 gint i;
4021 guint bpos;
4022 guint optlen;
4023 guint32 nxtseq = 0;
4024 guint reported_len;
4025 vec_t cksum_vec[4];
4026 guint32 phdr[2];
4027 guint16 computed_cksum;
4028 guint16 real_window;
4029 guint length_remaining;
4030 gboolean desegment_ok;
4031 struct tcpinfo tcpinfo;
4032 struct tcpheader *tcph;
4033 proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL, *scaled_pi;
4034 conversation_t *conv=NULL;
4035 struct tcp_analysis *tcpd=NULL;
4036 struct tcp_per_packet_data_t *tcppd=NULL;
4037 proto_item *item;
4038 proto_tree *checksum_tree;
4040 wmem_strbuf_append(flags_strbuf, "<None>");
4042 tcph=wmem_new(wmem_packet_scope(), struct tcpheader);
4043 SET_ADDRESS(&tcph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
4044 SET_ADDRESS(&tcph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
4046 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
4048 /* Clear out the Info column. */
4049 col_clear(pinfo->cinfo, COL_INFO);
4051 tcph->th_sport = tvb_get_ntohs(tvb, offset);
4052 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
4053 col_add_fstr(pinfo->cinfo, COL_INFO, "%s \xe2\x86\x92 %s", /* UTF8_RIGHTWARDS_ARROW */
4054 get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
4055 if (tree) {
4056 if (tcp_summary_in_tree) {
4057 ti = proto_tree_add_protocol_format(tree, proto_tcp, tvb, 0, -1,
4058 "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
4059 get_tcp_port(tcph->th_sport), tcph->th_sport,
4060 get_tcp_port(tcph->th_dport), tcph->th_dport);
4062 else {
4063 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, ENC_NA);
4065 tcp_tree = proto_item_add_subtree(ti, ett_tcp);
4067 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_srcport, tvb, offset, 2, tcph->th_sport,
4068 "%s (%u)", get_tcp_port(tcph->th_sport), tcph->th_sport);
4069 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, tcph->th_dport,
4070 "%s (%u)", get_tcp_port(tcph->th_dport), tcph->th_dport);
4071 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset, 2, tcph->th_sport);
4072 PROTO_ITEM_SET_HIDDEN(hidden_item);
4073 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, tcph->th_dport);
4074 PROTO_ITEM_SET_HIDDEN(hidden_item);
4076 /* If we're dissecting the headers of a TCP packet in an ICMP packet
4077 * then go ahead and put the sequence numbers in the tree now (because
4078 * they won't be put in later because the ICMP packet only contains up
4079 * to the sequence number).
4080 * We should only need to do this for IPv4 since IPv6 will hopefully
4081 * carry enough TCP payload for this dissector to put the sequence
4082 * numbers in via the regular code path.
4085 wmem_list_frame_t *frame;
4086 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
4087 if (proto_ip == (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))) {
4088 frame = wmem_list_frame_prev(frame);
4089 if (proto_icmp == (gint) GPOINTER_TO_UINT(wmem_list_frame_data(frame))) {
4090 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
4096 /* Set the source and destination port numbers as soon as we get them,
4097 so that they're available to the "Follow TCP Stream" code even if
4098 we throw an exception dissecting the rest of the TCP header. */
4099 pinfo->ptype = PT_TCP;
4100 pinfo->srcport = tcph->th_sport;
4101 pinfo->destport = tcph->th_dport;
4103 tcph->th_seq = tvb_get_ntohl(tvb, offset + 4);
4104 tcph->th_ack = tvb_get_ntohl(tvb, offset + 8);
4105 th_off_x2 = tvb_get_guint8(tvb, offset + 12);
4106 tcph->th_flags = tvb_get_ntohs(tvb, offset + 12) & 0x0FFF;
4107 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
4108 real_window = tcph->th_win;
4109 tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
4111 /* find(or create if needed) the conversation for this tcp session */
4112 conv=find_or_create_conversation(pinfo);
4113 tcpd=get_tcp_conversation_data(conv,pinfo);
4115 /* If this is a SYN packet, then check if its seq-nr is different
4116 * from the base_seq of the retrieved conversation. If this is the
4117 * case, create a new conversation with the same addresses and ports
4118 * and set the TA_PORTS_REUSED flag. If the seq-nr is the same as
4119 * the base_seq, then do nothing so it will be marked as a retrans-
4120 * mission later.
4122 if(tcpd && ((tcph->th_flags&(TH_SYN|TH_ACK))==TH_SYN) &&
4123 (tcpd->fwd->base_seq!=0) &&
4124 (tcph->th_seq!=tcpd->fwd->base_seq) ) {
4125 if (!(pinfo->fd->flags.visited)) {
4126 conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4127 tcpd=get_tcp_conversation_data(conv,pinfo);
4129 if(!tcpd->ta)
4130 tcp_analyze_get_acked_struct(pinfo->fd->num, tcph->th_seq, tcph->th_ack, TRUE, tcpd);
4131 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
4134 if (tcpd) {
4135 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, tcpd->stream);
4136 PROTO_ITEM_SET_GENERATED(item);
4138 /* Copy the stream index into the header as well to make it available
4139 * to tap listeners.
4141 tcph->th_stream = tcpd->stream;
4144 /* Do we need to calculate timestamps relative to the tcp-stream? */
4145 if (tcp_calculate_ts) {
4146 tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(pinfo->fd, proto_tcp, 0);
4149 * Calculate the timestamps relative to this conversation (but only on the
4150 * first run when frames are accessed sequentially)
4152 if (!(pinfo->fd->flags.visited))
4153 tcp_calculate_timestamps(pinfo, tcpd, tcppd);
4157 * If we've been handed an IP fragment, we don't know how big the TCP
4158 * segment is, so don't do anything that requires that we know that.
4160 * The same applies if we're part of an error packet. (XXX - if the
4161 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
4162 * header says it is" length in the tvbuff, we could use that; such
4163 * a length might also be useful for handling packets where the IP
4164 * length is bigger than the actual data available in the frame; the
4165 * dissectors should trust that length, and then throw a
4166 * ReportedBoundsError exception when they go past the end of the frame.)
4168 * We also can't determine the segment length if the reported length
4169 * of the TCP packet is less than the TCP header length.
4171 reported_len = tvb_reported_length(tvb);
4173 if (!pinfo->fragmented && !pinfo->flags.in_error_pkt) {
4174 if (reported_len < tcph->th_hlen) {
4175 proto_item *pi;
4176 pi = proto_tree_add_text(tcp_tree, tvb, offset, 0,
4177 "Short segment. Segment/fragment does not contain a full TCP header"
4178 " (might be NMAP or someone else deliberately sending unusual packets)");
4179 PROTO_ITEM_SET_GENERATED(pi);
4180 expert_add_info(pinfo, pi, &ei_tcp_short_segment);
4181 tcph->th_have_seglen = FALSE;
4182 } else {
4183 /* Compute the length of data in this segment. */
4184 tcph->th_seglen = reported_len - tcph->th_hlen;
4185 tcph->th_have_seglen = TRUE;
4187 if (tree) {
4188 proto_item *pi;
4190 pi = proto_tree_add_uint(ti, hf_tcp_len, tvb, offset+12, 1, tcph->th_seglen);
4191 PROTO_ITEM_SET_GENERATED(pi);
4196 /* handle TCP seq# analysis parse all new segments we see */
4197 if(tcp_analyze_seq) {
4198 if(!(pinfo->fd->flags.visited)) {
4199 tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd);
4201 if(tcpd && tcp_relative_seq) {
4202 (tcph->th_seq) -= tcpd->fwd->base_seq;
4203 if (tcph->th_flags & TH_ACK) {
4204 (tcph->th_ack) -= tcpd->rev->base_seq;
4209 /* re-calculate window size, based on scaling factor */
4210 if (!(tcph->th_flags&TH_SYN)) { /* SYNs are never scaled */
4211 if (tcpd && (tcpd->fwd->win_scale>=0)) {
4212 (tcph->th_win)<<=tcpd->fwd->win_scale;
4214 else {
4215 /* Don't have it stored, so use preference setting instead! */
4216 if (tcp_default_window_scaling>=0) {
4217 (tcph->th_win)<<=tcp_default_window_scaling;
4222 /* Compute the sequence number of next octet after this segment. */
4223 nxtseq = tcph->th_seq + tcph->th_seglen;
4225 } else
4226 tcph->th_have_seglen = FALSE;
4229 gboolean first_flag = TRUE;
4230 for (i = 0; i < 9; i++) {
4231 bpos = 1 << i;
4232 if (tcph->th_flags & bpos) {
4233 if (first_flag) {
4234 wmem_strbuf_truncate(flags_strbuf, 0);
4236 wmem_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ", flags[i]);
4237 first_flag = FALSE;
4240 if (tcph->th_flags & 0x0E00) {
4241 if (first_flag) {
4242 wmem_strbuf_truncate(flags_strbuf, 0);
4244 wmem_strbuf_append_printf(flags_strbuf, "%sReserved", first_flag ? "" : ", ");
4248 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] Seq=%u", wmem_strbuf_get_str(flags_strbuf), tcph->th_seq);
4249 if (tcph->th_flags&TH_ACK) {
4250 col_append_fstr(pinfo->cinfo, COL_INFO, " Ack=%u", tcph->th_ack);
4252 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", tcph->th_win);
4254 if (tree) {
4255 if (tcp_summary_in_tree) {
4256 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
4258 if(tcp_relative_seq) {
4259 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);
4260 } else {
4261 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
4265 if (tcph->th_hlen < TCPH_MIN_LEN) {
4266 /* Give up at this point; we put the source and destination port in
4267 the tree, before fetching the header length, so that they'll
4268 show up if this is in the failing packet in an ICMP error packet,
4269 but it's now time to give up if the header length is bogus. */
4270 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
4271 tcph->th_hlen, TCPH_MIN_LEN);
4272 if (tree) {
4273 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
4274 "%u bytes (bogus, must be at least %u)", tcph->th_hlen,
4275 TCPH_MIN_LEN);
4277 return;
4280 if (tree) {
4281 if (tcp_summary_in_tree) {
4282 if(tcph->th_flags&TH_ACK) {
4283 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
4285 if (tcph->th_have_seglen)
4286 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
4288 proto_item_set_len(ti, tcph->th_hlen);
4289 if (tcph->th_have_seglen) {
4290 if (nxtseq != tcph->th_seq) {
4291 if(tcp_relative_seq) {
4292 tf=proto_tree_add_uint_format_value(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "%u (relative sequence number)", nxtseq);
4293 } else {
4294 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
4296 PROTO_ITEM_SET_GENERATED(tf);
4301 tf = proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
4302 if (tcph->th_flags & TH_ACK) {
4303 if (tcp_relative_seq) {
4304 proto_item_append_text(tf, " (relative ack number)");
4306 } else {
4307 /* Note if the ACK field is non-zero */
4308 if (tvb_get_ntohl(tvb, offset+8) != 0) {
4309 expert_add_info(pinfo, tf, &ei_tcp_ack_nonzero);
4313 if (tree) {
4314 proto_tree_add_uint_format_value(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
4315 "%u bytes", tcph->th_hlen);
4316 tf = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_flags, tvb, offset + 12, 2,
4317 tcph->th_flags, "0x%03x (%s)", tcph->th_flags, wmem_strbuf_get_str(flags_strbuf));
4318 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
4319 proto_tree_add_boolean(field_tree, hf_tcp_flags_res, tvb, offset + 12, 1, tcph->th_flags);
4320 proto_tree_add_boolean(field_tree, hf_tcp_flags_ns, tvb, offset + 12, 1, tcph->th_flags);
4321 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
4322 proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, tvb, offset + 13, 1, tcph->th_flags);
4323 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
4324 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
4325 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
4326 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
4327 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
4328 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
4330 /* As discussed in bug 5541, it is better to use two separate
4331 * fields for the real and calculated window size.
4333 proto_tree_add_uint(tcp_tree, hf_tcp_window_size_value, tvb, offset + 14, 2, real_window);
4334 scaled_pi = proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win);
4335 PROTO_ITEM_SET_GENERATED(scaled_pi);
4337 if( !(tcph->th_flags&TH_SYN) && tcpd ) {
4338 switch (tcpd->fwd->win_scale) {
4340 case -1:
4342 gint16 win_scale = tcpd->fwd->win_scale;
4343 gboolean override_with_pref = FALSE;
4345 /* Use preference setting (if set) */
4346 if (tcp_default_window_scaling != WindowScaling_NotKnown) {
4347 win_scale = tcp_default_window_scaling;
4348 override_with_pref = TRUE;
4351 scaled_pi = proto_tree_add_int_format_value(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2,
4352 win_scale, "%d (%s)",
4353 win_scale,
4354 (override_with_pref) ? "missing - taken from preference" : "unknown");
4355 PROTO_ITEM_SET_GENERATED(scaled_pi);
4357 break;
4359 case -2:
4360 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);
4361 PROTO_ITEM_SET_GENERATED(scaled_pi);
4362 break;
4364 default:
4365 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);
4366 PROTO_ITEM_SET_GENERATED(scaled_pi);
4371 if(tcph->th_flags & TH_SYN) {
4372 if(tcph->th_flags & TH_ACK) {
4373 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));
4374 /* Save the server port to help determine dissector used */
4375 tcpd->server_port = tcph->th_sport;
4377 else {
4378 expert_add_info_format(pinfo, tf_syn, &ei_tcp_connection_syn, "Connection establish request (SYN): server port %s",
4379 get_tcp_port(tcph->th_dport));
4380 /* Save the server port to help determine dissector used */
4381 tcpd->server_port = tcph->th_dport;
4384 if(tcph->th_flags & TH_FIN)
4385 /* XXX - find a way to know the server port and output only that one */
4386 expert_add_info(pinfo, tf_fin, &ei_tcp_connection_fin);
4387 if(tcph->th_flags & TH_RST)
4388 /* XXX - find a way to know the server port and output only that one */
4389 expert_add_info(pinfo, tf_rst, &ei_tcp_connection_rst);
4391 /* Supply the sequence number of the first byte and of the first byte
4392 after the segment. */
4393 tcpinfo.seq = tcph->th_seq;
4394 tcpinfo.nxtseq = nxtseq;
4395 tcpinfo.lastackseq = tcph->th_ack;
4397 /* Assume we'll pass un-reassembled data to subdissectors. */
4398 tcpinfo.is_reassembled = FALSE;
4401 * Assume, initially, that we can't desegment.
4403 pinfo->can_desegment = 0;
4404 th_sum = tvb_get_ntohs(tvb, offset + 16);
4405 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
4406 /* The packet isn't part of an un-reassembled fragmented datagram
4407 and isn't truncated. This means we have all the data, and thus
4408 can checksum it and, unless it's being returned in an error
4409 packet, are willing to allow subdissectors to request reassembly
4410 on it. */
4412 if (tcp_check_checksum) {
4413 /* We haven't turned checksum checking off; checksum it. */
4415 /* Set up the fields of the pseudo-header. */
4416 cksum_vec[0].ptr = (guint8 *)pinfo->src.data;
4417 cksum_vec[0].len = pinfo->src.len;
4418 cksum_vec[1].ptr = (guint8 *)pinfo->dst.data;
4419 cksum_vec[1].len = pinfo->dst.len;
4420 cksum_vec[2].ptr = (const guint8 *)phdr;
4421 switch (pinfo->src.type) {
4423 case AT_IPv4:
4424 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
4425 cksum_vec[2].len = 4;
4426 break;
4428 case AT_IPv6:
4429 phdr[0] = g_htonl(reported_len);
4430 phdr[1] = g_htonl(IP_PROTO_TCP);
4431 cksum_vec[2].len = 8;
4432 break;
4434 default:
4435 /* TCP runs only atop IPv4 and IPv6.... */
4436 DISSECTOR_ASSERT_NOT_REACHED();
4437 break;
4439 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, reported_len);
4440 cksum_vec[3].len = reported_len;
4441 computed_cksum = in_cksum(cksum_vec, 4);
4442 if (computed_cksum == 0 && th_sum == 0xffff) {
4443 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4444 offset + 16, 2, th_sum,
4445 "0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);
4447 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4448 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4449 offset + 16, 2, FALSE);
4450 PROTO_ITEM_SET_GENERATED(item);
4451 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4452 offset + 16, 2, FALSE);
4453 PROTO_ITEM_SET_GENERATED(item);
4454 expert_add_info(pinfo, item, &ei_tcp_checksum_ffff);
4456 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");
4458 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
4459 desegment_ok = TRUE;
4460 } else if (computed_cksum == 0) {
4461 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4462 offset + 16, 2, th_sum, "0x%04x [correct]", th_sum);
4464 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4465 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4466 offset + 16, 2, TRUE);
4467 PROTO_ITEM_SET_GENERATED(item);
4468 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4469 offset + 16, 2, FALSE);
4470 PROTO_ITEM_SET_GENERATED(item);
4472 /* Checksum is valid, so we're willing to desegment it. */
4473 desegment_ok = TRUE;
4474 } else {
4475 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4476 offset + 16, 2, th_sum,
4477 "0x%04x [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]", th_sum,
4478 in_cksum_shouldbe(th_sum, computed_cksum));
4480 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4481 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4482 offset + 16, 2, FALSE);
4483 PROTO_ITEM_SET_GENERATED(item);
4484 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4485 offset + 16, 2, TRUE);
4486 PROTO_ITEM_SET_GENERATED(item);
4487 expert_add_info(pinfo, item, &ei_tcp_checksum_bad);
4489 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");
4491 /* Checksum is invalid, so we're not willing to desegment it. */
4492 desegment_ok = FALSE;
4493 pinfo->noreassembly_reason = " [incorrect TCP checksum]";
4495 } else {
4496 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4497 offset + 16, 2, th_sum, "0x%04x [validation disabled]", th_sum);
4499 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4500 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4501 offset + 16, 2, FALSE);
4502 PROTO_ITEM_SET_GENERATED(item);
4503 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4504 offset + 16, 2, FALSE);
4505 PROTO_ITEM_SET_GENERATED(item);
4507 /* We didn't check the checksum, and don't care if it's valid,
4508 so we're willing to desegment it. */
4509 desegment_ok = TRUE;
4511 } else {
4512 /* We don't have all the packet data, so we can't checksum it... */
4513 item = proto_tree_add_uint_format_value(tcp_tree, hf_tcp_checksum, tvb,
4514 offset + 16, 2, th_sum, "0x%04x [unchecked, not all data available]", th_sum);
4516 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4517 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4518 offset + 16, 2, FALSE);
4519 PROTO_ITEM_SET_GENERATED(item);
4520 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4521 offset + 16, 2, FALSE);
4522 PROTO_ITEM_SET_GENERATED(item);
4524 /* ...and aren't willing to desegment it. */
4525 desegment_ok = FALSE;
4528 if (desegment_ok) {
4529 /* We're willing to desegment this. Is desegmentation enabled? */
4530 if (tcp_desegment) {
4531 /* Yes - is this segment being returned in an error packet? */
4532 if (!pinfo->flags.in_error_pkt) {
4533 /* No - indicate that we will desegment.
4534 We do NOT want to desegment segments returned in error
4535 packets, as they're not part of a TCP connection. */
4536 pinfo->can_desegment = 2;
4541 th_urp = tvb_get_ntohs(tvb, offset + 18);
4542 item = proto_tree_add_item(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, ENC_BIG_ENDIAN);
4543 if (tcph->th_flags & TH_URG) {
4544 /* Export the urgent pointer, for the benefit of protocols such as
4545 rlogin. */
4546 tcpinfo.urgent = TRUE;
4547 tcpinfo.urgent_pointer = th_urp;
4548 col_append_fstr(pinfo->cinfo, COL_INFO, " Urg=%u", th_urp);
4549 } else {
4550 tcpinfo.urgent = FALSE;
4551 if (th_urp) {
4552 /* Note if the urgent pointer field is non-zero */
4553 expert_add_info(pinfo, item, &ei_tcp_urgent_pointer_non_zero);
4557 if (tcph->th_have_seglen) {
4558 col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", tcph->th_seglen);
4561 /* If there's more than just the fixed-length header (20 bytes), decode the options. */
4562 tcph->num_sack_ranges = 0;
4563 if (tcph->th_hlen > TCPH_MIN_LEN) {
4564 guint bc = (guint)MAX(0, tvb_length_remaining(tvb, offset + 20));
4566 optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
4568 if (tcp_tree != NULL) {
4569 /* If the frame has been sliced but the options field is at least 4 bytes, decode as much
4570 * of it as possible; otherwise, set optlen to zero. */
4571 if (bc < optlen) {
4572 if (bc >= 4) {
4573 guint8 *p_options = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset + 20, bc);
4575 tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
4576 bc, p_options, "Options: (%u bytes but truncated to %u bytes)", optlen, bc);
4577 optlen = bc;
4578 } else {
4579 optlen = 0;
4581 } else {
4582 guint8 *p_options = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset + 20, optlen);
4584 tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
4585 optlen, p_options, "Options: (%u bytes)", optlen);
4587 field_tree = proto_item_add_subtree(tf, ett_tcp_options);
4588 } else {
4589 tf = NULL;
4590 field_tree = NULL;
4592 if (optlen)
4593 dissect_ip_tcp_options(tvb, offset + 20, optlen, tcpopts, N_TCP_OPTS, TCPOPT_EOL,
4594 &TCP_OPT_TYPES, &ei_tcp_opt_len_invalid, pinfo, field_tree, tf, tcph);
4597 if(!pinfo->fd->flags.visited) {
4598 if((tcph->th_flags & TH_SYN)==TH_SYN) {
4599 /* Check the validity of the window scale value
4601 verify_tcp_window_scaling((tcph->th_flags&TH_ACK)==TH_ACK,tcpd);
4604 if((tcph->th_flags & (TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
4605 /* If the SYN or the SYN+ACK offered SCPS capabilities,
4606 * validate the flow's bidirectional scps capabilities.
4607 * The or protects against broken implementations offering
4608 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
4610 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {
4611 verify_scps(pinfo, tf_syn, tcpd);
4616 /* Skip over header + options */
4617 offset += tcph->th_hlen;
4619 /* Check the packet length to see if there's more data
4620 (it could be an ACK-only packet) */
4621 length_remaining = MAX(0, tvb_length_remaining(tvb, offset));
4623 if (tcph->th_have_seglen) {
4624 if( data_out_file ) {
4625 reassemble_tcp( tcpd->stream, /* tcp stream index */
4626 tcph->th_seq, /* sequence number */
4627 tcph->th_ack, /* acknowledgment number */
4628 tcph->th_seglen, /* data length */
4629 (gchar*)tvb_get_ptr(tvb, offset, length_remaining), /* data */
4630 length_remaining, /* captured data length */
4631 ( tcph->th_flags & TH_SYN ), /* is syn set? */
4632 &pinfo->net_src,
4633 &pinfo->net_dst,
4634 pinfo->srcport,
4635 pinfo->destport);
4639 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
4640 if(tcp_analyze_seq) {
4641 guint32 use_seq = tcph->th_seq;
4642 guint32 use_ack = tcph->th_ack;
4643 /* May need to recover absolute values here... */
4644 if (tcp_relative_seq) {
4645 use_seq += tcpd->fwd->base_seq;
4646 if (tcph->th_flags & TH_ACK) {
4647 use_ack += tcpd->rev->base_seq;
4650 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd, use_seq, use_ack);
4653 /* handle conversation timestamps */
4654 if(tcp_calculate_ts) {
4655 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
4658 tap_queue_packet(tcp_tap, pinfo, tcph);
4661 /* If we're reassembling something whose length isn't known
4662 * beforehand, and that runs all the way to the end of
4663 * the data stream, a FIN indicates the end of the data
4664 * stream and thus the completion of reassembly, so we
4665 * need to explicitly check for that here.
4667 if(tcph->th_have_seglen && tcpd && (tcph->th_flags & TH_FIN)
4668 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ) {
4669 struct tcp_multisegment_pdu *msp;
4671 /* Is this the FIN that ended the data stream or is it a
4672 * retransmission of that FIN?
4674 if (tcpd->fwd->fin == 0 || tcpd->fwd->fin == pinfo->fd->num) {
4675 /* Either we haven't seen a FIN for this flow or we
4676 * have and it's this frame. Note that this is the FIN
4677 * for this flow, terminate reassembly and dissect the
4678 * results. */
4679 tcpd->fwd->fin = pinfo->fd->num;
4680 msp=(struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq-1);
4681 if(msp) {
4682 fragment_head *ipfd_head;
4684 ipfd_head = fragment_add(&tcp_reassembly_table, tvb, offset,
4685 pinfo, msp->first_frame, NULL,
4686 tcph->th_seq - msp->seq,
4687 tcph->th_seglen,
4688 FALSE );
4689 if(ipfd_head) {
4690 tvbuff_t *next_tvb;
4692 /* create a new TVB structure for desegmented data
4693 * datalen-1 to strip the dummy FIN byte off
4695 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
4697 /* add desegmented data to the data source list */
4698 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
4700 /* Show details of the reassembly */
4701 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
4703 /* call the payload dissector
4704 * but make sure we don't offer desegmentation any more
4706 pinfo->can_desegment = 0;
4708 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq,
4709 nxtseq, FALSE, tcpd, &tcpinfo);
4711 return;
4714 } else {
4715 /* Yes. This is a retransmission of the final FIN (or it's
4716 * the final FIN transmitted via a different path).
4717 * XXX - we need to flag retransmissions a bit better.
4719 proto_tree_add_text(tcp_tree, tvb, 0, 0, "Retransmission of FIN from frame %u",
4720 tcpd->fwd->fin);
4724 if (tcpd && ((tcpd->fwd && tcpd->fwd->command) || (tcpd->rev && tcpd->rev->command))) {
4725 ti = proto_tree_add_text(tcp_tree, tvb, offset, 0, "Process Information");
4726 PROTO_ITEM_SET_GENERATED(ti);
4727 field_tree = proto_item_add_subtree(ti, ett_tcp_process_info);
4728 if (tcpd->fwd && tcpd->fwd->command) {
4729 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_dst_uid, tvb, 0, 0,
4730 tcpd->fwd->process_uid, "%u", tcpd->fwd->process_uid);
4731 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_dst_pid, tvb, 0, 0,
4732 tcpd->fwd->process_pid, "%u", tcpd->fwd->process_pid);
4733 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_dst_uname, tvb, 0, 0,
4734 tcpd->fwd->username, "%s", tcpd->fwd->username);
4735 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_dst_cmd, tvb, 0, 0,
4736 tcpd->fwd->command, "%s", tcpd->fwd->command);
4738 if (tcpd->rev && tcpd->rev->command) {
4739 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_src_uid, tvb, 0, 0,
4740 tcpd->rev->process_uid, "%u", tcpd->rev->process_uid);
4741 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_src_pid, tvb, 0, 0,
4742 tcpd->rev->process_pid, "%u", tcpd->rev->process_pid);
4743 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_src_uname, tvb, 0, 0,
4744 tcpd->rev->username, "%s", tcpd->rev->username);
4745 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_src_cmd, tvb, 0, 0,
4746 tcpd->rev->command, "%s", tcpd->rev->command);
4751 * XXX - what, if any, of this should we do if this is included in an
4752 * error packet? It might be nice to see the details of the packet
4753 * that caused the ICMP error, but it might not be nice to have the
4754 * dissector update state based on it.
4755 * Also, we probably don't want to run TCP taps on those packets.
4757 if (length_remaining != 0) {
4758 if (tcph->th_flags & TH_RST) {
4760 * RFC1122 says:
4762 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
4764 * A TCP SHOULD allow a received RST segment to include data.
4766 * DISCUSSION
4767 * It has been suggested that a RST segment could contain
4768 * ASCII text that encoded and explained the cause of the
4769 * RST. No standard has yet been established for such
4770 * data.
4772 * so for segments with RST we just display the data as text.
4774 proto_tree_add_text(tcp_tree, tvb, offset, length_remaining,
4775 "Reset cause: %s",
4776 tvb_format_text(tvb, offset, length_remaining));
4777 } else {
4778 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
4779 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd, &tcpinfo);
4784 static void
4785 tcp_init(void)
4787 tcp_stream_count = 0;
4788 reassembly_table_init(&tcp_reassembly_table,
4789 &addresses_ports_reassembly_table_functions);
4792 void
4793 proto_register_tcp(void)
4795 static hf_register_info hf[] = {
4797 { &hf_tcp_srcport,
4798 { "Source Port", "tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
4799 NULL, HFILL }},
4801 { &hf_tcp_dstport,
4802 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
4803 NULL, HFILL }},
4805 { &hf_tcp_port,
4806 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
4807 NULL, HFILL }},
4809 { &hf_tcp_stream,
4810 { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
4811 NULL, HFILL }},
4813 { &hf_tcp_seq,
4814 { "Sequence number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
4815 NULL, HFILL }},
4817 { &hf_tcp_nxtseq,
4818 { "Next sequence number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
4819 NULL, HFILL }},
4821 { &hf_tcp_ack,
4822 { "Acknowledgment number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
4823 NULL, HFILL }},
4825 { &hf_tcp_hdr_len,
4826 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
4827 NULL, HFILL }},
4829 { &hf_tcp_flags,
4830 { "Flags", "tcp.flags", FT_UINT16, BASE_HEX, NULL, TH_MASK,
4831 NULL, HFILL }},
4833 { &hf_tcp_flags_res,
4834 { "Reserved", "tcp.flags.res", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RES,
4835 "Three reserved bits (must be zero)", HFILL }},
4837 { &hf_tcp_flags_ns,
4838 { "Nonce", "tcp.flags.ns", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_NS,
4839 "ECN concealment protection (RFC 3540)", HFILL }},
4841 { &hf_tcp_flags_cwr,
4842 { "Congestion Window Reduced (CWR)", "tcp.flags.cwr", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_CWR,
4843 NULL, HFILL }},
4845 { &hf_tcp_flags_ecn,
4846 { "ECN-Echo", "tcp.flags.ecn", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ECN,
4847 NULL, HFILL }},
4849 { &hf_tcp_flags_urg,
4850 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_URG,
4851 NULL, HFILL }},
4853 { &hf_tcp_flags_ack,
4854 { "Acknowledgment", "tcp.flags.ack", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ACK,
4855 NULL, HFILL }},
4857 { &hf_tcp_flags_push,
4858 { "Push", "tcp.flags.push", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_PUSH,
4859 NULL, HFILL }},
4861 { &hf_tcp_flags_reset,
4862 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RST,
4863 NULL, HFILL }},
4865 { &hf_tcp_flags_syn,
4866 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_SYN,
4867 NULL, HFILL }},
4869 { &hf_tcp_flags_fin,
4870 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_FIN,
4871 NULL, HFILL }},
4873 { &hf_tcp_window_size_value,
4874 { "Window size value", "tcp.window_size_value", FT_UINT16, BASE_DEC, NULL, 0x0,
4875 "The window size value from the TCP header", HFILL }},
4877 /* 32 bits so we can present some values adjusted to window scaling */
4878 { &hf_tcp_window_size,
4879 { "Calculated window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
4880 "The scaled window size (if scaling has been used)", HFILL }},
4882 { &hf_tcp_window_size_scalefactor,
4883 { "Window size scaling factor", "tcp.window_size_scalefactor", FT_INT32, BASE_DEC, NULL, 0x0,
4884 "The window size scaling factor (-1 when unknown, -2 when no scaling is used)", HFILL }},
4886 { &hf_tcp_checksum,
4887 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
4888 "Details at: http://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
4890 { &hf_tcp_checksum_good,
4891 { "Good Checksum", "tcp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4892 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
4894 { &hf_tcp_checksum_bad,
4895 { "Bad Checksum", "tcp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4896 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
4898 { &hf_tcp_analysis,
4899 { "SEQ/ACK analysis", "tcp.analysis", FT_NONE, BASE_NONE, NULL, 0x0,
4900 "This frame has some of the TCP analysis shown", HFILL }},
4902 { &hf_tcp_analysis_flags,
4903 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
4904 "This frame has some of the TCP analysis flags set", HFILL }},
4906 { &hf_tcp_analysis_duplicate_ack,
4907 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
4908 "This is a duplicate ACK", HFILL }},
4910 { &hf_tcp_analysis_duplicate_ack_num,
4911 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
4912 "This is duplicate ACK number #", HFILL }},
4914 { &hf_tcp_analysis_duplicate_ack_frame,
4915 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4916 "This is a duplicate to the ACK in frame #", HFILL }},
4918 { &hf_tcp_continuation_to,
4919 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4920 "This is a continuation to the PDU in frame #", HFILL }},
4922 { &hf_tcp_len,
4923 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
4924 NULL, HFILL}},
4926 { &hf_tcp_analysis_acks_frame,
4927 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4928 "Which previous segment is this an ACK for", HFILL}},
4930 { &hf_tcp_analysis_bytes_in_flight,
4931 { "Bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL, 0x0,
4932 "How many bytes are now in flight for this connection", HFILL}},
4934 { &hf_tcp_analysis_ack_rtt,
4935 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4936 "How long time it took to ACK the segment (RTT)", HFILL}},
4938 { &hf_tcp_analysis_rto,
4939 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4940 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL}},
4942 { &hf_tcp_analysis_rto_frame,
4943 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4944 "This is the frame we measure the RTO from", HFILL }},
4946 { &hf_tcp_urgent_pointer,
4947 { "Urgent pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
4948 NULL, HFILL }},
4950 { &hf_tcp_segment_overlap,
4951 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4952 "Segment overlaps with other segments", HFILL }},
4954 { &hf_tcp_segment_overlap_conflict,
4955 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4956 "Overlapping segments contained conflicting data", HFILL }},
4958 { &hf_tcp_segment_multiple_tails,
4959 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4960 "Several tails were found when reassembling the pdu", HFILL }},
4962 { &hf_tcp_segment_too_long_fragment,
4963 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4964 "Segment contained data past end of the pdu", HFILL }},
4966 { &hf_tcp_segment_error,
4967 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4968 "Reassembling error due to illegal segments", HFILL }},
4970 { &hf_tcp_segment_count,
4971 { "Segment count", "tcp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
4972 NULL, HFILL }},
4974 { &hf_tcp_segment,
4975 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4976 NULL, HFILL }},
4978 { &hf_tcp_segments,
4979 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
4980 "TCP Segments", HFILL }},
4982 { &hf_tcp_reassembled_in,
4983 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4984 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
4986 { &hf_tcp_reassembled_length,
4987 { "Reassembled TCP length", "tcp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
4988 "The total length of the reassembled payload", HFILL }},
4990 { &hf_tcp_reassembled_data,
4991 { "Reassembled TCP Data", "tcp.reassembled.data", FT_BYTES, BASE_NONE, NULL, 0x0,
4992 "The reassembled payload", HFILL }},
4994 { &hf_tcp_option_kind,
4995 { "Kind", "tcp.option_kind", FT_UINT8,
4996 BASE_DEC, VALS(tcp_option_kind_vs), 0x0, "This TCP option's kind", HFILL }},
4998 { &hf_tcp_option_len,
4999 { "Length", "tcp.option_len", FT_UINT8,
5000 BASE_DEC, NULL, 0x0, "Length of this TCP option in bytes (including kind and length fields)", HFILL }},
5002 { &hf_tcp_options,
5003 { "TCP Options", "tcp.options", FT_BYTES,
5004 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5006 { &hf_tcp_option_mss,
5007 { "TCP MSS Option", "tcp.options.mss", FT_NONE,
5008 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5010 { &hf_tcp_option_mss_val,
5011 { "MSS Value", "tcp.options.mss_val", FT_UINT16,
5012 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5014 { &hf_tcp_option_wscale_shift,
5015 { "Shift count", "tcp.options.wscale.shift", FT_UINT8,
5016 BASE_DEC, NULL, 0x0, "Logarithmically encoded power of 2 scale factor", HFILL}},
5018 { &hf_tcp_option_wscale_multiplier,
5019 { "Multiplier", "tcp.options.wscale.multiplier", FT_UINT8,
5020 BASE_DEC, NULL, 0x0, "Multiply segment window size by this for scaled window size", HFILL}},
5022 { &hf_tcp_option_exp,
5023 { "TCP Option - Experimental", "tcp.options.experimental", FT_BYTES,
5024 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5026 { &hf_tcp_option_exp_data,
5027 { "Data", "tcp.options.experimental.data", FT_BYTES,
5028 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5030 { &hf_tcp_option_exp_magic_number,
5031 { "Magic Number", "tcp.options.experimental.magic_number", FT_UINT16,
5032 BASE_HEX, NULL, 0x0, NULL, HFILL}},
5034 { &hf_tcp_option_sack_perm,
5035 { "TCP SACK Permitted Option", "tcp.options.sack_perm",
5036 FT_BOOLEAN,
5037 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5039 { &hf_tcp_option_sack,
5040 { "TCP SACK Option", "tcp.options.sack", FT_BOOLEAN,
5041 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5043 { &hf_tcp_option_sack_sle,
5044 {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32,
5045 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5047 { &hf_tcp_option_sack_sre,
5048 {"TCP SACK Right Edge", "tcp.options.sack_re", FT_UINT32,
5049 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5051 { &hf_tcp_option_sack_range_count,
5052 { "TCP SACK Count", "tcp.options.sack.count", FT_UINT8,
5053 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5055 { &hf_tcp_option_echo,
5056 { "TCP Echo Option", "tcp.options.echo", FT_BOOLEAN,
5057 BASE_NONE, NULL, 0x0, "TCP Sack Echo", HFILL}},
5059 { &hf_tcp_option_timestamp_tsval,
5060 { "Timestamp value", "tcp.options.timestamp.tsval", FT_UINT32,
5061 BASE_DEC, NULL, 0x0, "Value of sending machine's timestamp clock", HFILL}},
5063 { &hf_tcp_option_timestamp_tsecr,
5064 { "Timestamp echo reply", "tcp.options.timestamp.tsecr", FT_UINT32,
5065 BASE_DEC, NULL, 0x0, "Echoed timestamp from remote machine", HFILL}},
5067 { &hf_tcp_option_mptcp_subtype,
5068 { "Multipath TCP subtype", "tcp.options.mptcp.subtype", FT_UINT8,
5069 BASE_DEC, VALS(mptcp_subtype_vs), 0xF0, NULL, HFILL}},
5071 { &hf_tcp_option_mptcp_version,
5072 { "Multipath TCP version", "tcp.options.mptcp.version", FT_UINT8,
5073 BASE_DEC, NULL, 0x0F, NULL, HFILL}},
5075 { &hf_tcp_option_mptcp_flags,
5076 { "Multipath TCP flags", "tcp.options.mptcp.flags", FT_UINT8,
5077 BASE_HEX, NULL, 0x0, NULL, HFILL}},
5079 { &hf_tcp_option_mptcp_B_flag,
5080 { "Backup flag", "tcp.options.mptcp.backup.flag", FT_UINT8,
5081 BASE_DEC, NULL, 0x01, NULL, HFILL}},
5083 { &hf_tcp_option_mptcp_C_flag,
5084 { "Checksum required", "tcp.options.mptcp.checksumreq.flags", FT_UINT8,
5085 BASE_DEC, NULL, 0x80, NULL, HFILL}},
5087 { &hf_tcp_option_mptcp_S_flag,
5088 { "Use HMAC-SHA1", "tcp.options.mptcp.sha1.flag", FT_UINT8,
5089 BASE_DEC, NULL, 0x01, NULL, HFILL}},
5091 { &hf_tcp_option_mptcp_F_flag,
5092 { "DATA_FIN", "tcp.options.mptcp.datafin.flag", FT_UINT8,
5093 BASE_DEC, NULL, 0x10, NULL, HFILL}},
5095 { &hf_tcp_option_mptcp_m_flag,
5096 { "Data Sequence Number is 8 octets", "tcp.options.mptcp.dseqn8.flag", FT_UINT8,
5097 BASE_DEC, NULL, 0x08, NULL, HFILL}},
5099 { &hf_tcp_option_mptcp_M_flag,
5100 { "Data Sequence Number, Subflow Sequence Number, Data-level Length, Checksum present", "tcp.options.mptcp.dseqnpresent.flag", FT_UINT8,
5101 BASE_DEC, NULL, 0x04, NULL, HFILL}},
5103 { &hf_tcp_option_mptcp_a_flag,
5104 { "Data ACK is 8 octets", "tcp.options.mptcp.dataack8.flag", FT_UINT8,
5105 BASE_DEC, NULL, 0x02, NULL, HFILL}},
5107 { &hf_tcp_option_mptcp_A_flag,
5108 { "Data ACK is present", "tcp.options.mptcp.dataackpresent.flag", FT_UINT8,
5109 BASE_DEC, NULL, 0x01, NULL, HFILL}},
5111 { &hf_tcp_option_mptcp_address_id,
5112 { "Multipath TCP Address ID", "tcp.options.mptcp.addrid", FT_UINT8,
5113 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5115 { &hf_tcp_option_mptcp_sender_key,
5116 { "Multipath TCP Sender's Key", "tcp.options.mptcp.sendkey", FT_UINT64,
5117 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5119 { &hf_tcp_option_mptcp_recv_key,
5120 { "Multipath TCP Receiver's Key", "tcp.options.mptcp.recvkey", FT_UINT64,
5121 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5123 { &hf_tcp_option_mptcp_recv_token,
5124 { "Multipath TCP Receiver's Token", "tcp.options.mptcp.recvtok", FT_UINT32,
5125 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5127 { &hf_tcp_option_mptcp_sender_rand,
5128 { "Multipath TCP Sender's Random Number", "tcp.options.mptcp.sendrand", FT_UINT32,
5129 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5131 { &hf_tcp_option_mptcp_sender_trunc_mac,
5132 { "Multipath TCP Sender's Truncated MAC", "tcp.options.mptcp.sendtruncmac", FT_UINT64,
5133 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5135 { &hf_tcp_option_mptcp_sender_mac,
5136 { "Multipath TCP Sender's MAC", "tcp.options.mptcp.sendmac", FT_UINT32,
5137 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5139 { &hf_tcp_option_mptcp_data_ack,
5140 { "Multipath TCP Data ACK", "tcp.options.mptcp.dataack", FT_UINT64,
5141 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5143 { &hf_tcp_option_mptcp_data_seq_no,
5144 { "Multipath TCP Data Sequence Number", "tcp.options.mptcp.dataseqno", FT_UINT64,
5145 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5147 { &hf_tcp_option_mptcp_subflow_seq_no,
5148 { "Multipath TCP Subflow Sequence Number", "tcp.options.mptcp.subflowseqno", FT_UINT32,
5149 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5151 { &hf_tcp_option_mptcp_data_lvl_len,
5152 { "Multipath TCP Data-level Length", "tcp.options.mptcp.datalvllen", FT_UINT16,
5153 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5155 { &hf_tcp_option_mptcp_checksum,
5156 { "Multipath TCP Checksum", "tcp.options.mptcp.checksum", FT_UINT16,
5157 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5159 { &hf_tcp_option_mptcp_ipver,
5160 { "Multipath TCP IPVer", "tcp.options.mptcp.ipver", FT_UINT8,
5161 BASE_DEC, NULL, 0x0F, NULL, HFILL}},
5163 { &hf_tcp_option_mptcp_ipv4,
5164 { "Multipath TCP Address", "tcp.options.mptcp.ipv4", FT_IPv4,
5165 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5167 { &hf_tcp_option_mptcp_ipv6,
5168 { "Multipath TCP Address", "tcp.options.mptcp.ipv6", FT_IPv6,
5169 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5171 { &hf_tcp_option_mptcp_port,
5172 { "Multipath TCP Port", "tcp.options.mptcp.port", FT_UINT16,
5173 BASE_DEC, NULL, 0x0, NULL, HFILL}},
5175 { &hf_tcp_option_cc,
5176 { "TCP CC Option", "tcp.options.cc", FT_BOOLEAN, BASE_NONE,
5177 NULL, 0x0, NULL, HFILL}},
5179 { &hf_tcp_option_qs,
5180 { "TCP QS Option", "tcp.options.qs", FT_BOOLEAN, BASE_NONE,
5181 NULL, 0x0, NULL, HFILL}},
5183 { &hf_tcp_option_type,
5184 { "Type", "tcp.options.type", FT_UINT8, BASE_DEC,
5185 NULL, 0x0, NULL, HFILL}},
5187 { &hf_tcp_option_type_copy,
5188 { "Copy on fragmentation", "tcp.options.type.copy", FT_BOOLEAN, 8,
5189 TFS(&tfs_yes_no), IPOPT_COPY_MASK, NULL, HFILL}},
5191 { &hf_tcp_option_type_class,
5192 { "Class", "tcp.options.type.class", FT_UINT8, BASE_DEC,
5193 VALS(ipopt_type_class_vals), IPOPT_CLASS_MASK, NULL, HFILL}},
5195 { &hf_tcp_option_type_number,
5196 { "Number", "tcp.options.type.number", FT_UINT8, BASE_DEC,
5197 VALS(ipopt_type_number_vals), IPOPT_NUMBER_MASK, NULL, HFILL}},
5199 { &hf_tcp_option_scps,
5200 { "TCP SCPS Capabilities Option", "tcp.options.scps",
5201 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5202 NULL, HFILL}},
5204 { &hf_tcp_option_scps_vector,
5205 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
5206 FT_UINT8, BASE_HEX, NULL, 0x0,
5207 NULL, HFILL}},
5209 { &hf_tcp_option_scps_binding,
5210 { "Binding Space (Community) ID",
5211 "tcp.options.scps.binding.id",
5212 FT_UINT8, BASE_DEC, NULL, 0x0,
5213 "TCP SCPS Extended Binding Space (Community) ID", HFILL}},
5215 { &hf_tcp_option_scps_binding_len,
5216 { "Extended Capability Length",
5217 "tcp.options.scps.binding.len",
5218 FT_UINT8, BASE_DEC, NULL, 0x0,
5219 "TCP SCPS Extended Capability Length in bytes", HFILL}},
5221 { &hf_tcp_option_snack,
5222 { "TCP Selective Negative Acknowledgment Option",
5223 "tcp.options.snack",
5224 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5225 NULL, HFILL}},
5227 { &hf_tcp_option_snack_offset,
5228 { "TCP SNACK Offset", "tcp.options.snack.offset",
5229 FT_UINT16, BASE_DEC, NULL, 0x0,
5230 NULL, HFILL}},
5232 { &hf_tcp_option_snack_size,
5233 { "TCP SNACK Size", "tcp.options.snack.size",
5234 FT_UINT16, BASE_DEC, NULL, 0x0,
5235 NULL, HFILL}},
5237 { &hf_tcp_option_snack_le,
5238 { "TCP SNACK Left Edge", "tcp.options.snack.le",
5239 FT_UINT16, BASE_DEC, NULL, 0x0,
5240 NULL, HFILL}},
5242 { &hf_tcp_option_snack_re,
5243 { "TCP SNACK Right Edge", "tcp.options.snack.re",
5244 FT_UINT16, BASE_DEC, NULL, 0x0,
5245 NULL, HFILL}},
5247 { &hf_tcp_scpsoption_flags_bets,
5248 { "Partial Reliability Capable (BETS)",
5249 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,
5250 TFS(&tfs_set_notset), 0x80, NULL, HFILL }},
5252 { &hf_tcp_scpsoption_flags_snack1,
5253 { "Short Form SNACK Capable (SNACK1)",
5254 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,
5255 TFS(&tfs_set_notset), 0x40, NULL, HFILL }},
5257 { &hf_tcp_scpsoption_flags_snack2,
5258 { "Long Form SNACK Capable (SNACK2)",
5259 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,
5260 TFS(&tfs_set_notset), 0x20, NULL, HFILL }},
5262 { &hf_tcp_scpsoption_flags_compress,
5263 { "Lossless Header Compression (COMP)",
5264 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,
5265 TFS(&tfs_set_notset), 0x10, NULL, HFILL }},
5267 { &hf_tcp_scpsoption_flags_nlts,
5268 { "Network Layer Timestamp (NLTS)",
5269 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,
5270 TFS(&tfs_set_notset), 0x8, NULL, HFILL }},
5272 { &hf_tcp_scpsoption_flags_reserved,
5273 { "Reserved",
5274 "tcp.options.scpsflags.reserved", FT_UINT8, BASE_DEC,
5275 NULL, 0x7, NULL, HFILL }},
5277 { &hf_tcp_scpsoption_connection_id,
5278 { "Connection ID",
5279 "tcp.options.scps.binding",
5280 FT_UINT8, BASE_DEC, NULL, 0x0,
5281 "TCP SCPS Connection ID", HFILL}},
5283 { &hf_tcp_option_user_to,
5284 { "TCP User Timeout", "tcp.options.user_to", FT_BOOLEAN,
5285 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5287 { &hf_tcp_option_user_to_granularity,
5288 { "Granularity", "tcp.options.user_to_granularity", FT_BOOLEAN,
5289 16, TFS(&tcp_option_user_to_granularity), 0x8000, "TCP User Timeout Granularity", HFILL}},
5291 { &hf_tcp_option_user_to_val,
5292 { "User Timeout", "tcp.options.user_to_val", FT_UINT16,
5293 BASE_DEC, NULL, 0x7FFF, "TCP User Timeout Value", HFILL}},
5295 { &hf_tcp_option_rvbd_probe,
5296 { "Riverbed Probe", "tcp.options.rvbd.probe", FT_BOOLEAN,
5297 BASE_NONE, NULL, 0x0, "RVBD TCP Probe Option", HFILL }},
5299 { &hf_tcp_option_rvbd_probe_type1,
5300 { "Type", "tcp.options.rvbd.probe.type1",
5301 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
5303 { &hf_tcp_option_rvbd_probe_type2,
5304 { "Type", "tcp.options.rvbd.probe.type2",
5305 FT_UINT8, BASE_DEC, NULL, 0xFE, NULL, HFILL }},
5307 { &hf_tcp_option_rvbd_probe_version1,
5308 { "Version", "tcp.options.rvbd.probe.version",
5309 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
5311 { &hf_tcp_option_rvbd_probe_version2,
5312 { "Version", "tcp.options.rvbd.probe.version_raw",
5313 FT_UINT8, BASE_DEC, NULL, 0x01, "Version 2 Raw Value", HFILL }},
5315 { &hf_tcp_option_rvbd_probe_optlen,
5316 { "Length", "tcp.options.rvbd.probe.len",
5317 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5319 { &hf_tcp_option_rvbd_probe_prober,
5320 { "CSH IP", "tcp.options.rvbd.probe.prober",
5321 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5323 { &hf_tcp_option_rvbd_probe_proxy,
5324 { "SSH IP", "tcp.options.rvbd.probe.proxy.ip",
5325 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5327 { &hf_tcp_option_rvbd_probe_proxy_port,
5328 { "SSH Port", "tcp.options.rvbd.probe.proxy.port",
5329 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5331 { &hf_tcp_option_rvbd_probe_appli_ver,
5332 { "Application Version", "tcp.options.rvbd.probe.appli_ver",
5333 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5335 { &hf_tcp_option_rvbd_probe_client,
5336 { "Client IP", "tcp.options.rvbd.probe.client.ip",
5337 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5339 { &hf_tcp_option_rvbd_probe_storeid,
5340 { "CFE Store ID", "tcp.options.rvbd.probe.storeid",
5341 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5343 { &hf_tcp_option_rvbd_probe_flags,
5344 { "Probe Flags", "tcp.options.rvbd.probe.flags",
5345 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5347 { &hf_tcp_option_rvbd_probe_flag_not_cfe,
5348 { "Not CFE", "tcp.options.rvbd.probe.flags.notcfe",
5349 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_NCFE,
5350 NULL, HFILL }},
5352 { &hf_tcp_option_rvbd_probe_flag_last_notify,
5353 { "Last Notify", "tcp.options.rvbd.probe.flags.last",
5354 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_LAST,
5355 NULL, HFILL }},
5357 { &hf_tcp_option_rvbd_probe_flag_probe_cache,
5358 { "Disable Probe Cache on CSH", "tcp.options.rvbd.probe.flags.probe",
5359 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE,
5360 NULL, HFILL }},
5362 { &hf_tcp_option_rvbd_probe_flag_sslcert,
5363 { "SSL Enabled", "tcp.options.rvbd.probe.flags.ssl",
5364 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SSLCERT,
5365 NULL, HFILL }},
5367 { &hf_tcp_option_rvbd_probe_flag_server_connected,
5368 { "SSH outer to server established", "tcp.options.rvbd.probe.flags.server",
5369 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SERVER,
5370 NULL, HFILL }},
5372 { &hf_tcp_option_rvbd_trpy,
5373 { "Riverbed Transparency", "tcp.options.rvbd.trpy",
5374 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5375 "RVBD TCP Transparency Option", HFILL }},
5377 { &hf_tcp_option_rvbd_trpy_flags,
5378 { "Transparency Options", "tcp.options.rvbd.trpy.flags",
5379 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5381 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
5382 { "Enable FW traversal feature", "tcp.options.rvbd.trpy.flags.fw_rst_probe",
5383 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5384 RVBD_FLAGS_TRPY_FW_RST_PROBE,
5385 "Reset state created by probe on the nexthop firewall",
5386 HFILL }},
5388 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
5389 { "Enable Inner FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst_inner",
5390 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5391 RVBD_FLAGS_TRPY_FW_RST_INNER,
5392 "Reset state created by transparent inner on all firewalls"
5393 " before passing connection through",
5394 HFILL }},
5396 { &hf_tcp_option_rvbd_trpy_flag_fw_rst,
5397 { "Enable Transparency FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst",
5398 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5399 RVBD_FLAGS_TRPY_FW_RST,
5400 "Reset state created by probe on all firewalls before "
5401 "establishing transparent inner connection", HFILL }},
5403 { &hf_tcp_option_rvbd_trpy_flag_chksum,
5404 { "Reserved", "tcp.options.rvbd.trpy.flags.chksum",
5405 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5406 RVBD_FLAGS_TRPY_CHKSUM, NULL, HFILL }},
5408 { &hf_tcp_option_rvbd_trpy_flag_oob,
5409 { "Out of band connection", "tcp.options.rvbd.trpy.flags.oob",
5410 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5411 RVBD_FLAGS_TRPY_OOB, NULL, HFILL }},
5413 { &hf_tcp_option_rvbd_trpy_flag_mode,
5414 { "Transparency Mode", "tcp.options.rvbd.trpy.flags.mode",
5415 FT_BOOLEAN, 16, TFS(&trpy_mode_str),
5416 RVBD_FLAGS_TRPY_MODE, NULL, HFILL }},
5418 { &hf_tcp_option_rvbd_trpy_src,
5419 { "Src SH IP Addr", "tcp.options.rvbd.trpy.src.ip",
5420 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5422 { &hf_tcp_option_rvbd_trpy_dst,
5423 { "Dst SH IP Addr", "tcp.options.rvbd.trpy.dst.ip",
5424 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5426 { &hf_tcp_option_rvbd_trpy_src_port,
5427 { "Src SH Inner Port", "tcp.options.rvbd.trpy.src.port",
5428 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5430 { &hf_tcp_option_rvbd_trpy_dst_port,
5431 { "Dst SH Inner Port", "tcp.options.rvbd.trpy.dst.port",
5432 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5434 { &hf_tcp_option_rvbd_trpy_client_port,
5435 { "Out of band connection Client Port", "tcp.options.rvbd.trpy.client.port",
5436 FT_UINT16, BASE_DEC, NULL , 0x0, NULL, HFILL }},
5438 { &hf_tcp_option_fast_open,
5439 { "Fast Open", "tcp.options.tfo", FT_NONE,
5440 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5442 { &hf_tcp_option_fast_open_cookie_request,
5443 { "Fast Open Cookie Request", "tcp.options.tfo.request", FT_NONE,
5444 BASE_NONE, NULL, 0x0, NULL, HFILL }},
5446 { &hf_tcp_option_fast_open_cookie,
5447 { "Fast Open Cookie", "tcp.options.tfo.cookie", FT_BYTES,
5448 BASE_NONE, NULL, 0x0, NULL, HFILL}},
5450 { &hf_tcp_pdu_time,
5451 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5452 "How long time has passed until the last frame of this PDU", HFILL}},
5454 { &hf_tcp_pdu_size,
5455 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL, 0x0,
5456 "The size of this PDU", HFILL}},
5458 { &hf_tcp_pdu_last_frame,
5459 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5460 "This is the last frame of the PDU starting in this segment", HFILL }},
5462 { &hf_tcp_ts_relative,
5463 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5464 "Time relative to first frame in this TCP stream", HFILL}},
5466 { &hf_tcp_ts_delta,
5467 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5468 "Time delta from previous frame in this TCP stream", HFILL}},
5470 { &hf_tcp_proc_src_uid,
5471 { "Source process user ID", "tcp.proc.srcuid", FT_UINT32, BASE_DEC, NULL, 0x0,
5472 NULL, HFILL}},
5474 { &hf_tcp_proc_src_pid,
5475 { "Source process ID", "tcp.proc.srcpid", FT_UINT32, BASE_DEC, NULL, 0x0,
5476 NULL, HFILL}},
5478 { &hf_tcp_proc_src_uname,
5479 { "Source process user name", "tcp.proc.srcuname", FT_STRING, BASE_NONE, NULL, 0x0,
5480 NULL, HFILL}},
5482 { &hf_tcp_proc_src_cmd,
5483 { "Source process name", "tcp.proc.srccmd", FT_STRING, BASE_NONE, NULL, 0x0,
5484 "Source process command name", HFILL}},
5486 { &hf_tcp_proc_dst_uid,
5487 { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32, BASE_DEC, NULL, 0x0,
5488 NULL, HFILL}},
5490 { &hf_tcp_proc_dst_pid,
5491 { "Destination process ID", "tcp.proc.dstpid", FT_UINT32, BASE_DEC, NULL, 0x0,
5492 NULL, HFILL}},
5494 { &hf_tcp_proc_dst_uname,
5495 { "Destination process user name", "tcp.proc.dstuname", FT_STRING, BASE_NONE, NULL, 0x0,
5496 NULL, HFILL}},
5498 { &hf_tcp_proc_dst_cmd,
5499 { "Destination process name", "tcp.proc.dstcmd", FT_STRING, BASE_NONE, NULL, 0x0,
5500 "Destination process command name", HFILL}},
5502 { &hf_tcp_segment_data,
5503 { "TCP segment data", "tcp.segment_data", FT_BYTES, BASE_NONE, NULL, 0x0,
5504 "A data segment used in reassembly of a lower-level protocol", HFILL}}
5507 static gint *ett[] = {
5508 &ett_tcp,
5509 &ett_tcp_flags,
5510 &ett_tcp_option_type,
5511 &ett_tcp_options,
5512 &ett_tcp_option_timestamp,
5513 &ett_tcp_option_mptcp,
5514 &ett_tcp_option_wscale,
5515 &ett_tcp_option_sack,
5516 &ett_tcp_option_scps,
5517 &ett_tcp_option_scps_extended,
5518 &ett_tcp_option_user_to,
5519 &ett_tcp_option_exp,
5520 &ett_tcp_option_sack_perm,
5521 &ett_tcp_option_mss,
5522 &ett_tcp_opt_rvbd_probe,
5523 &ett_tcp_opt_rvbd_probe_flags,
5524 &ett_tcp_opt_rvbd_trpy,
5525 &ett_tcp_opt_rvbd_trpy_flags,
5526 &ett_tcp_analysis_faults,
5527 &ett_tcp_analysis,
5528 &ett_tcp_timestamps,
5529 &ett_tcp_segments,
5530 &ett_tcp_segment,
5531 &ett_tcp_checksum,
5532 &ett_tcp_process_info
5535 static const enum_val_t window_scaling_vals[] = {
5536 {"not-known", "Not known", WindowScaling_NotKnown},
5537 {"0", "0 (no scaling)", WindowScaling_0},
5538 {"1", "1 (multiply by 2)", WindowScaling_1},
5539 {"2", "2 (multiply by 4)", WindowScaling_2},
5540 {"3", "3 (multiply by 8)", WindowScaling_3},
5541 {"4", "4 (multiply by 16)", WindowScaling_4},
5542 {"5", "5 (multiply by 32)", WindowScaling_5},
5543 {"6", "6 (multiply by 64)", WindowScaling_6},
5544 {"7", "7 (multiply by 128)", WindowScaling_7},
5545 {"8", "8 (multiply by 256)", WindowScaling_8},
5546 {"9", "9 (multiply by 512)", WindowScaling_9},
5547 {"10", "10 (multiply by 1024)", WindowScaling_10},
5548 {"11", "11 (multiply by 2048)", WindowScaling_11},
5549 {"12", "12 (multiply by 4096)", WindowScaling_12},
5550 {"13", "13 (multiply by 8192)", WindowScaling_13},
5551 {"14", "14 (multiply by 16384)", WindowScaling_14},
5552 {NULL, NULL, -1}
5555 static ei_register_info ei[] = {
5556 { &ei_tcp_opt_len_invalid, { "tcp.option.len.invalid", PI_SEQUENCE, PI_NOTE, "Invalid length for option", EXPFILL }},
5557 { &ei_tcp_analysis_retransmission, { "tcp.analysis.retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) retransmission", EXPFILL }},
5558 { &ei_tcp_analysis_fast_retransmission, { "tcp.analysis.fast_retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) fast retransmission", EXPFILL }},
5559 { &ei_tcp_analysis_spurious_retransmission, { "tcp.analysis.spurious_retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) spurious retransmission", EXPFILL }},
5560 { &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 }},
5561 { &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 }},
5562 { &ei_tcp_analysis_lost_packet, { "tcp.analysis.lost_segment", PI_SEQUENCE, PI_WARN, "Previous segment not captured (common at capture start)", EXPFILL }},
5563 { &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 }},
5564 { &ei_tcp_analysis_window_update, { "tcp.analysis.window_update", PI_SEQUENCE, PI_CHAT, "TCP window update", EXPFILL }},
5565 { &ei_tcp_analysis_window_full, { "tcp.analysis.window_full", PI_SEQUENCE, PI_WARN, "TCP transmission window is now completely full", EXPFILL }},
5566 { &ei_tcp_analysis_keep_alive, { "tcp.analysis.keep_alive", PI_SEQUENCE, PI_NOTE, "TCP keep-alive segment", EXPFILL }},
5567 { &ei_tcp_analysis_keep_alive_ack, { "tcp.analysis.keep_alive_ack", PI_SEQUENCE, PI_NOTE, "ACK to a TCP keep-alive segment", EXPFILL }},
5568 { &ei_tcp_analysis_duplicate_ack, { "tcp.analysis.duplicate_ack", PI_SEQUENCE, PI_NOTE, "Duplicate ACK", EXPFILL }},
5569 { &ei_tcp_analysis_zero_window_probe, { "tcp.analysis.zero_window_probe", PI_SEQUENCE, PI_NOTE, "TCP Zero Window Probe", EXPFILL }},
5570 { &ei_tcp_analysis_zero_window, { "tcp.analysis.zero_window", PI_SEQUENCE, PI_WARN, "TCP Zero Window segment", EXPFILL }},
5571 { &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 }},
5572 { &ei_tcp_scps_capable, { "tcp.analysis.zero_window_probe_ack", PI_SEQUENCE, PI_NOTE, "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated", EXPFILL }},
5573 { &ei_tcp_option_snack_sequence, { "tcp.options.snack.sequence", PI_SEQUENCE, PI_NOTE, "SNACK Sequence", EXPFILL }},
5574 { &ei_tcp_short_segment, { "tcp.short_segment", PI_MALFORMED, PI_WARN, "Short segment", EXPFILL }},
5575 { &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 }},
5576 { &ei_tcp_connection_sack, { "tcp.connection.sack", PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK)", EXPFILL }},
5577 { &ei_tcp_connection_syn, { "tcp.connection.syn", PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN)", EXPFILL }},
5578 { &ei_tcp_connection_fin, { "tcp.connection.fin", PI_SEQUENCE, PI_CHAT, "Connection finish (FIN)", EXPFILL }},
5579 { &ei_tcp_connection_rst, { "tcp.connection.rst", PI_SEQUENCE, PI_CHAT, "Connection reset (RST)", EXPFILL }},
5580 { &ei_tcp_checksum_ffff, { "tcp.checksum.ffff", PI_CHECKSUM, PI_WARN, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)", EXPFILL }},
5581 { &ei_tcp_checksum_bad, { "tcp.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
5582 { &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 }}
5585 module_t *tcp_module;
5586 expert_module_t* expert_tcp;
5588 proto_tcp = proto_register_protocol("Transmission Control Protocol",
5589 "TCP", "tcp");
5590 register_dissector("tcp", dissect_tcp, proto_tcp);
5591 proto_register_field_array(proto_tcp, hf, array_length(hf));
5592 proto_register_subtree_array(ett, array_length(ett));
5593 expert_tcp = expert_register_protocol(proto_tcp);
5594 expert_register_field_array(expert_tcp, ei, array_length(ei));
5596 /* subdissector code */
5597 subdissector_table = register_dissector_table("tcp.port",
5598 "TCP port", FT_UINT16, BASE_DEC);
5599 register_heur_dissector_list("tcp", &heur_subdissector_list);
5601 /* Register configuration preferences */
5602 tcp_module = prefs_register_protocol(proto_tcp, NULL);
5603 prefs_register_bool_preference(tcp_module, "summary_in_tree",
5604 "Show TCP summary in protocol tree",
5605 "Whether the TCP summary line should be shown in the protocol tree",
5606 &tcp_summary_in_tree);
5607 prefs_register_bool_preference(tcp_module, "check_checksum",
5608 "Validate the TCP checksum if possible",
5609 "Whether to validate the TCP checksum or not. "
5610 "(Invalid checksums will cause reassembly, if enabled, to fail.)",
5611 &tcp_check_checksum);
5612 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
5613 "Allow subdissector to reassemble TCP streams",
5614 "Whether subdissector can request TCP streams to be reassembled",
5615 &tcp_desegment);
5616 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
5617 "Analyze TCP sequence numbers",
5618 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
5619 &tcp_analyze_seq);
5620 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
5621 "Relative sequence numbers",
5622 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
5623 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
5624 &tcp_relative_seq);
5625 prefs_register_enum_preference(tcp_module, "default_window_scaling",
5626 "Scaling factor to use when not available from capture",
5627 "Make the TCP dissector use this scaling factor for streams where the signalled scaling factor "
5628 "is not visible in the capture",
5629 &tcp_default_window_scaling, window_scaling_vals, FALSE);
5631 /* Presumably a retired, unconditional version of what has been added back with the preference above... */
5632 prefs_register_obsolete_preference(tcp_module, "window_scaling");
5634 prefs_register_bool_preference(tcp_module, "track_bytes_in_flight",
5635 "Track number of bytes in flight",
5636 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "
5637 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
5638 "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",
5639 &tcp_track_bytes_in_flight);
5640 prefs_register_bool_preference(tcp_module, "calculate_timestamps",
5641 "Calculate conversation timestamps",
5642 "Calculate timestamps relative to the first frame and the previous frame in the tcp conversation",
5643 &tcp_calculate_ts);
5644 prefs_register_bool_preference(tcp_module, "try_heuristic_first",
5645 "Try heuristic sub-dissectors first",
5646 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
5647 &try_heuristic_first);
5648 prefs_register_bool_preference(tcp_module, "ignore_tcp_timestamps",
5649 "Ignore TCP Timestamps in summary",
5650 "Do not place the TCP Timestamps in the summary line",
5651 &tcp_ignore_timestamps);
5653 prefs_register_bool_preference(tcp_module, "no_subdissector_on_error",
5654 "Do not call subdissectors for error packets",
5655 "Do not call any subdissectors for Retransmitted or OutOfOrder segments",
5656 &tcp_no_subdissector_on_error);
5658 prefs_register_bool_preference(tcp_module, "dissect_experimental_options_with_magic",
5659 "TCP Experimental Options with a Magic Number",
5660 "Assume TCP Experimental Options (253, 254) have a Magic Number and use it for dissection",
5661 &tcp_exp_options_with_magic);
5663 register_init_routine(tcp_init);
5666 void
5667 proto_reg_handoff_tcp(void)
5669 dissector_handle_t tcp_handle;
5671 tcp_handle = find_dissector("tcp");
5672 dissector_add_uint("ip.proto", IP_PROTO_TCP, tcp_handle);
5673 data_handle = find_dissector("data");
5674 sport_handle = find_dissector("sport");
5675 tcp_tap = register_tap("tcp");
5679 * Editor modelines
5681 * Local Variables:
5682 * c-basic-offset: 4
5683 * tab-width: 8
5684 * indent-tabs-mode: nil
5685 * End:
5687 * ex: set shiftwidth=4 tabstop=8 expandtab:
5688 * :indentSize=4:tabSize=8:noTabs=true: