2 * Routines for TCP packet disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32 #include <epan/in_cksum.h>
34 #include <epan/packet.h>
35 #include <epan/addr_resolv.h>
36 #include <epan/ipproto.h>
37 #include <epan/ip_opts.h>
38 #include <epan/follow.h>
39 #include <epan/prefs.h>
40 #include <epan/emem.h>
41 #include "packet-tcp.h"
42 #include "packet-frame.h"
43 #include <epan/conversation.h>
44 #include <epan/reassemble.h>
46 #include <epan/slab.h>
47 #include <epan/expert.h>
49 static int tcp_tap = -1;
51 /* Place TCP summary in proto tree */
52 static gboolean tcp_summary_in_tree = TRUE;
55 * Flag to control whether to check the TCP checksum.
57 * In at least some Solaris network traces, there are packets with bad
58 * TCP checksums, but the traffic appears to indicate that the packets
59 * *were* received; the packets were probably sent by the host on which
60 * the capture was being done, on a network interface to which
61 * checksumming was offloaded, so that DLPI supplied an un-checksummed
62 * packet to the capture program but a checksummed packet got put onto
65 static gboolean tcp_check_checksum = FALSE;
67 extern FILE* data_out_file;
69 static int proto_tcp = -1;
70 static int hf_tcp_srcport = -1;
71 static int hf_tcp_dstport = -1;
72 static int hf_tcp_port = -1;
73 static int hf_tcp_stream = -1;
74 static int hf_tcp_seq = -1;
75 static int hf_tcp_nxtseq = -1;
76 static int hf_tcp_ack = -1;
77 static int hf_tcp_hdr_len = -1;
78 static int hf_tcp_flags = -1;
79 static int hf_tcp_flags_res = -1;
80 static int hf_tcp_flags_ns = -1;
81 static int hf_tcp_flags_cwr = -1;
82 static int hf_tcp_flags_ecn = -1;
83 static int hf_tcp_flags_urg = -1;
84 static int hf_tcp_flags_ack = -1;
85 static int hf_tcp_flags_push = -1;
86 static int hf_tcp_flags_reset = -1;
87 static int hf_tcp_flags_syn = -1;
88 static int hf_tcp_flags_fin = -1;
89 static int hf_tcp_window_size_value = -1;
90 static int hf_tcp_window_size = -1;
91 static int hf_tcp_window_size_scalefactor = -1;
92 static int hf_tcp_checksum = -1;
93 static int hf_tcp_checksum_bad = -1;
94 static int hf_tcp_checksum_good = -1;
95 static int hf_tcp_len = -1;
96 static int hf_tcp_urgent_pointer = -1;
97 static int hf_tcp_analysis_flags = -1;
98 static int hf_tcp_analysis_bytes_in_flight = -1;
99 static int hf_tcp_analysis_acks_frame = -1;
100 static int hf_tcp_analysis_ack_rtt = -1;
101 static int hf_tcp_analysis_rto = -1;
102 static int hf_tcp_analysis_rto_frame = -1;
103 static int hf_tcp_analysis_retransmission = -1;
104 static int hf_tcp_analysis_fast_retransmission = -1;
105 static int hf_tcp_analysis_out_of_order = -1;
106 static int hf_tcp_analysis_reused_ports = -1;
107 static int hf_tcp_analysis_lost_packet = -1;
108 static int hf_tcp_analysis_ack_lost_packet = -1;
109 static int hf_tcp_analysis_window_update = -1;
110 static int hf_tcp_analysis_window_full = -1;
111 static int hf_tcp_analysis_keep_alive = -1;
112 static int hf_tcp_analysis_keep_alive_ack = -1;
113 static int hf_tcp_analysis_duplicate_ack = -1;
114 static int hf_tcp_analysis_duplicate_ack_num = -1;
115 static int hf_tcp_analysis_duplicate_ack_frame = -1;
116 static int hf_tcp_analysis_zero_window = -1;
117 static int hf_tcp_analysis_zero_window_probe = -1;
118 static int hf_tcp_analysis_zero_window_probe_ack = -1;
119 static int hf_tcp_continuation_to = -1;
120 static int hf_tcp_pdu_time = -1;
121 static int hf_tcp_pdu_size = -1;
122 static int hf_tcp_pdu_last_frame = -1;
123 static int hf_tcp_reassembled_in = -1;
124 static int hf_tcp_reassembled_length = -1;
125 static int hf_tcp_segments = -1;
126 static int hf_tcp_segment = -1;
127 static int hf_tcp_segment_overlap = -1;
128 static int hf_tcp_segment_overlap_conflict = -1;
129 static int hf_tcp_segment_multiple_tails = -1;
130 static int hf_tcp_segment_too_long_fragment = -1;
131 static int hf_tcp_segment_error = -1;
132 static int hf_tcp_segment_count = -1;
133 static int hf_tcp_options = -1;
134 static int hf_tcp_option_kind = -1;
135 static int hf_tcp_option_len = -1;
136 static int hf_tcp_option_mss = -1;
137 static int hf_tcp_option_mss_val = -1;
138 static int hf_tcp_option_wscale_shift = -1;
139 static int hf_tcp_option_wscale_multiplier = -1;
140 static int hf_tcp_option_sack_perm = -1;
141 static int hf_tcp_option_sack = -1;
142 static int hf_tcp_option_sack_sle = -1;
143 static int hf_tcp_option_sack_sre = -1;
144 static int hf_tcp_option_echo = -1;
145 static int hf_tcp_option_echo_reply = -1;
146 static int hf_tcp_option_timestamp_tsval = -1;
147 static int hf_tcp_option_timestamp_tsecr = -1;
148 static int hf_tcp_option_cc = -1;
149 static int hf_tcp_option_ccnew = -1;
150 static int hf_tcp_option_ccecho = -1;
151 static int hf_tcp_option_md5 = -1;
152 static int hf_tcp_option_qs = -1;
153 static int hf_tcp_option_exp = -1;
154 static int hf_tcp_option_exp_data = -1;
156 static int hf_tcp_option_rvbd_probe = -1;
157 static int hf_tcp_option_rvbd_probe_version1 = -1;
158 static int hf_tcp_option_rvbd_probe_version2 = -1;
159 static int hf_tcp_option_rvbd_probe_type1 = -1;
160 static int hf_tcp_option_rvbd_probe_type2 = -1;
161 static int hf_tcp_option_rvbd_probe_optlen = -1;
162 static int hf_tcp_option_rvbd_probe_prober = -1;
163 static int hf_tcp_option_rvbd_probe_proxy = -1;
164 static int hf_tcp_option_rvbd_probe_client = -1;
165 static int hf_tcp_option_rvbd_probe_proxy_port = -1;
166 static int hf_tcp_option_rvbd_probe_appli_ver = -1;
167 static int hf_tcp_option_rvbd_probe_storeid = -1;
168 static int hf_tcp_option_rvbd_probe_flags = -1;
169 static int hf_tcp_option_rvbd_probe_flag_last_notify = -1;
170 static int hf_tcp_option_rvbd_probe_flag_server_connected = -1;
171 static int hf_tcp_option_rvbd_probe_flag_not_cfe = -1;
172 static int hf_tcp_option_rvbd_probe_flag_sslcert = -1;
173 static int hf_tcp_option_rvbd_probe_flag_probe_cache = -1;
175 static int hf_tcp_option_rvbd_trpy = -1;
176 static int hf_tcp_option_rvbd_trpy_flags = -1;
177 static int hf_tcp_option_rvbd_trpy_flag_mode = -1;
178 static int hf_tcp_option_rvbd_trpy_flag_oob = -1;
179 static int hf_tcp_option_rvbd_trpy_flag_chksum = -1;
180 static int hf_tcp_option_rvbd_trpy_flag_fw_rst = -1;
181 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_inner = -1;
182 static int hf_tcp_option_rvbd_trpy_flag_fw_rst_probe = -1;
183 static int hf_tcp_option_rvbd_trpy_src = -1;
184 static int hf_tcp_option_rvbd_trpy_dst = -1;
185 static int hf_tcp_option_rvbd_trpy_src_port = -1;
186 static int hf_tcp_option_rvbd_trpy_dst_port = -1;
187 static int hf_tcp_option_rvbd_trpy_client_port = -1;
189 static int hf_tcp_ts_relative = -1;
190 static int hf_tcp_ts_delta = -1;
191 static int hf_tcp_option_scps = -1;
192 static int hf_tcp_option_scps_vector = -1;
193 static int hf_tcp_option_scps_binding = -1;
194 static int hf_tcp_option_scps_binding_len = -1;
195 static int hf_tcp_scpsoption_flags_bets = -1;
196 static int hf_tcp_scpsoption_flags_snack1 = -1;
197 static int hf_tcp_scpsoption_flags_snack2 = -1;
198 static int hf_tcp_scpsoption_flags_compress = -1;
199 static int hf_tcp_scpsoption_flags_nlts = -1;
200 static int hf_tcp_scpsoption_flags_resv1 = -1;
201 static int hf_tcp_scpsoption_flags_resv2 = -1;
202 static int hf_tcp_scpsoption_flags_resv3 = -1;
203 static int hf_tcp_scpsoption_connection_id = -1;
204 static int hf_tcp_option_snack = -1;
205 static int hf_tcp_option_snack_offset = -1;
206 static int hf_tcp_option_snack_size = -1;
207 static int hf_tcp_option_snack_le = -1;
208 static int hf_tcp_option_snack_re = -1;
209 static int hf_tcp_option_mood = -1;
210 static int hf_tcp_option_mood_val = -1;
211 static int hf_tcp_option_user_to = -1;
212 static int hf_tcp_option_user_to_granularity = -1;
213 static int hf_tcp_option_user_to_val = -1;
214 static int hf_tcp_proc_src_uid = -1;
215 static int hf_tcp_proc_src_pid = -1;
216 static int hf_tcp_proc_src_uname = -1;
217 static int hf_tcp_proc_src_cmd = -1;
218 static int hf_tcp_proc_dst_uid = -1;
219 static int hf_tcp_proc_dst_pid = -1;
220 static int hf_tcp_proc_dst_uname = -1;
221 static int hf_tcp_proc_dst_cmd = -1;
222 static int hf_tcp_data = -1;
224 static gint ett_tcp = -1;
225 static gint ett_tcp_flags = -1;
226 static gint ett_tcp_options = -1;
227 static gint ett_tcp_option_timestamp = -1;
228 static gint ett_tcp_option_mss = -1;
229 static gint ett_tcp_option_wscale = -1;
230 static gint ett_tcp_option_sack = -1;
231 static gint ett_tcp_option_scps = -1;
232 static gint ett_tcp_option_scps_extended = -1;
233 static gint ett_tcp_option_user_to = -1;
234 static gint ett_tcp_option_exp = -1;
235 static gint ett_tcp_option_sack_perm = -1;
236 static gint ett_tcp_analysis = -1;
237 static gint ett_tcp_analysis_faults = -1;
238 static gint ett_tcp_timestamps = -1;
239 static gint ett_tcp_segments = -1;
240 static gint ett_tcp_segment = -1;
241 static gint ett_tcp_checksum = -1;
242 static gint ett_tcp_process_info = -1;
244 static gint ett_tcp_opt_rvbd_probe = -1;
245 static gint ett_tcp_opt_rvbd_probe_flags = -1;
246 static gint ett_tcp_opt_rvbd_trpy = -1;
247 static gint ett_tcp_opt_rvbd_trpy_flags = -1;
253 #define TCPOPT_NOP 1 /* Padding */
254 #define TCPOPT_EOL 0 /* End of options */
255 #define TCPOPT_MSS 2 /* Segment size negotiating */
256 #define TCPOPT_WINDOW 3 /* Window scaling */
257 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
258 #define TCPOPT_SACK 5 /* SACK Block */
259 #define TCPOPT_ECHO 6
260 #define TCPOPT_ECHOREPLY 7
261 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
263 #define TCPOPT_CCNEW 12
264 #define TCPOPT_CCECHO 13
265 #define TCPOPT_MD5 19 /* RFC2385 */
266 #define TCPOPT_SCPS 20 /* SCPS Capabilities */
267 #define TCPOPT_SNACK 21 /* SCPS SNACK */
268 #define TCPOPT_RECBOUND 22 /* SCPS Record Boundary */
269 #define TCPOPT_CORREXP 23 /* SCPS Corruption Experienced */
270 #define TCPOPT_MOOD 25 /* RFC5841 TCP Packet Mood */
271 #define TCPOPT_QS 27 /* RFC4782 */
272 #define TCPOPT_USER_TO 28 /* RFC5482 */
273 #define TCPOPT_EXP_FD 0xfd /* Experimental, reserved */
274 #define TCPOPT_EXP_FE 0xfe /* Experimental, reserved */
275 /* Non IANA registered option numbers */
276 #define TCPOPT_RVBD_PROBE 76 /* Riverbed probe option */
277 #define TCPOPT_RVBD_TRPY 78 /* Riverbed transparency option */
283 #define TCPOLEN_MSS 4
284 #define TCPOLEN_WINDOW 3
285 #define TCPOLEN_SACK_PERM 2
286 #define TCPOLEN_SACK_MIN 2
287 #define TCPOLEN_ECHO 6
288 #define TCPOLEN_ECHOREPLY 6
289 #define TCPOLEN_TIMESTAMP 10
291 #define TCPOLEN_CCNEW 6
292 #define TCPOLEN_CCECHO 6
293 #define TCPOLEN_MD5 18
294 #define TCPOLEN_SCPS 2
295 #define TCPOLEN_SNACK 6
296 #define TCPOLEN_RECBOUND 2
297 #define TCPOLEN_CORREXP 2
298 #define TCPOLEN_MOOD_MIN 2
300 #define TCPOLEN_USER_TO 4
301 #define TCPOLEN_RVBD_PROBE_MIN 3
302 #define TCPOLEN_RVBD_TRPY_MIN 16
303 #define TCPOLEN_EXP_MIN 2
305 static const true_false_string tcp_option_user_to_granularity = {
309 static const value_string tcp_option_kind_vs[] = {
310 { TCPOPT_EXP_FD, "Experimental 0xFD" },
311 { TCPOPT_EXP_FE, "Experimental 0xFE" },
312 { TCPOPT_WINDOW, "Window Scale" },
313 { TCPOPT_SACK_PERM, "SACK Permission" },
314 { TCPOPT_MSS, "MSS size" },
315 { TCPOPT_TIMESTAMP, "Timestamp" },
319 /* not all of the hf_fields below make sense for TCP but we have to provide
320 them anyways to comply with the api (which was aimed for ip fragment
322 static const fragment_items tcp_segment_items = {
327 &hf_tcp_segment_overlap,
328 &hf_tcp_segment_overlap_conflict,
329 &hf_tcp_segment_multiple_tails,
330 &hf_tcp_segment_too_long_fragment,
331 &hf_tcp_segment_error,
332 &hf_tcp_segment_count,
333 &hf_tcp_reassembled_in,
334 &hf_tcp_reassembled_length,
338 static dissector_table_t subdissector_table;
339 static heur_dissector_list_t heur_subdissector_list;
340 static dissector_handle_t data_handle;
341 static guint32 tcp_stream_index;
343 /* TCP structs and definitions */
345 /* **************************************************************************
346 * RTT, relative sequence numbers, window scaling & etc.
347 * **************************************************************************/
348 static gboolean tcp_analyze_seq = TRUE;
349 static gboolean tcp_relative_seq = TRUE;
350 static gboolean tcp_track_bytes_in_flight = TRUE;
351 static gboolean tcp_calculate_ts = FALSE;
353 /* SLAB allocator for tcp_unacked structures
355 SLAB_ITEM_TYPE_DEFINE(tcp_unacked_t)
356 static SLAB_FREE_LIST_DEFINE(tcp_unacked_t)
357 #define TCP_UNACKED_NEW(fi) \
358 SLAB_ALLOC(fi, tcp_unacked_t)
359 #define TCP_UNACKED_FREE(fi) \
360 SLAB_FREE(fi, tcp_unacked_t)
363 #define TCP_A_RETRANSMISSION 0x0001
364 #define TCP_A_LOST_PACKET 0x0002
365 #define TCP_A_ACK_LOST_PACKET 0x0004
366 #define TCP_A_KEEP_ALIVE 0x0008
367 #define TCP_A_DUPLICATE_ACK 0x0010
368 #define TCP_A_ZERO_WINDOW 0x0020
369 #define TCP_A_ZERO_WINDOW_PROBE 0x0040
370 #define TCP_A_ZERO_WINDOW_PROBE_ACK 0x0080
371 #define TCP_A_KEEP_ALIVE_ACK 0x0100
372 #define TCP_A_OUT_OF_ORDER 0x0200
373 #define TCP_A_FAST_RETRANSMISSION 0x0400
374 #define TCP_A_WINDOW_UPDATE 0x0800
375 #define TCP_A_WINDOW_FULL 0x1000
376 #define TCP_A_REUSED_PORTS 0x2000
380 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
381 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
382 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
383 struct tcp_analysis *tcpd);
386 struct tcp_analysis *
387 init_tcp_conversation_data(packet_info *pinfo)
389 struct tcp_analysis *tcpd;
391 /* Initialize the tcp protocol data structure to add to the tcp conversation */
392 tcpd=se_alloc0(sizeof(struct tcp_analysis));
393 tcpd->flow1.win_scale=-1;
394 tcpd->flow1.window = G_MAXUINT32;
395 tcpd->flow1.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
397 tcpd->flow1.username = NULL;
398 tcpd->flow1.command = NULL;
400 tcpd->flow2.window = G_MAXUINT32;
401 tcpd->flow2.win_scale=-1;
402 tcpd->flow2.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
404 tcpd->flow2.username = NULL;
405 tcpd->flow2.command = NULL;
407 tcpd->acked_table=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_analyze_acked_table");
408 tcpd->ts_first.secs=pinfo->fd->abs_ts.secs;
409 tcpd->ts_first.nsecs=pinfo->fd->abs_ts.nsecs;
410 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
411 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
412 tcpd->flow1.valid_bif = 1;
413 tcpd->flow2.valid_bif = 1;
414 tcpd->stream = tcp_stream_index++;
419 struct tcp_analysis *
420 get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)
423 struct tcp_analysis *tcpd;
425 /* Did the caller supply the conversation pointer? */
427 conv = find_or_create_conversation(pinfo);
429 /* Get the data for this conversation */
430 tcpd=conversation_get_proto_data(conv, proto_tcp);
432 /* If the conversation was just created or it matched a
433 * conversation with template options, tcpd will not
434 * have been initialized. So, initialize
435 * a new tcpd structure for the conversation.
438 tcpd = init_tcp_conversation_data(pinfo);
439 conversation_add_proto_data(conv, proto_tcp, tcpd);
446 /* check direction and get ua lists */
447 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
448 /* if the addresses are equal, match the ports instead */
450 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
453 tcpd->fwd=&(tcpd->flow1);
454 tcpd->rev=&(tcpd->flow2);
456 tcpd->fwd=&(tcpd->flow2);
457 tcpd->rev=&(tcpd->flow1);
464 /* Attach process info to a flow */
465 /* XXX - We depend on the TCP dissector finding the conversation first */
467 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) {
468 conversation_t *conv;
469 struct tcp_analysis *tcpd;
470 tcp_flow_t *flow = NULL;
472 conv = find_conversation(frame_num, local_addr, remote_addr, PT_TCP, local_port, remote_port, 0);
477 tcpd = conversation_get_proto_data(conv, proto_tcp);
482 if (CMP_ADDRESS(local_addr, &conv->key_ptr->addr1) == 0 && local_port == conv->key_ptr->port1) {
484 } else if (CMP_ADDRESS(remote_addr, &conv->key_ptr->addr1) == 0 && remote_port == conv->key_ptr->port1) {
487 if (!flow || flow->command) {
491 flow->process_uid = uid;
492 flow->process_pid = pid;
493 flow->username = se_strdup(username);
494 flow->command = se_strdup(command);
498 /* Calculate the timestamps relative to this conversation */
500 tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
501 struct tcp_per_packet_data_t *tcppd)
504 tcppd = se_alloc(sizeof(struct tcp_per_packet_data_t));
505 p_add_proto_data(pinfo->fd, proto_tcp, tcppd);
511 nstime_delta(&tcppd->ts_del, &pinfo->fd->abs_ts, &tcpd->ts_prev);
513 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
514 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
517 /* Add a subtree with the timestamps relative to this conversation */
519 tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
528 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "Timestamps");
529 PROTO_ITEM_SET_GENERATED(item);
530 tree=proto_item_add_subtree(item, ett_tcp_timestamps);
532 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
533 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);
534 PROTO_ITEM_SET_GENERATED(item);
537 tcppd = p_get_proto_data(pinfo->fd, proto_tcp);
540 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,
542 PROTO_ITEM_SET_GENERATED(item);
547 print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)
551 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);
552 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
553 tvb, 0, 0, msp->first_frame);
554 PROTO_ITEM_SET_GENERATED(item);
557 /* if we know that a PDU starts inside this segment, return the adjusted
558 offset to where that PDU starts or just return offset back
559 and let TCP try to find out what it can about this segment
562 scan_for_next_pdu(tvbuff_t *tvb, proto_tree *tcp_tree, packet_info *pinfo, int offset, guint32 seq, guint32 nxtseq, emem_tree_t *multisegment_pdus)
564 struct tcp_multisegment_pdu *msp=NULL;
566 if(!pinfo->fd->flags.visited){
567 msp=se_tree_lookup32_le(multisegment_pdus, seq-1);
569 /* If this is a continuation of a PDU started in a
570 * previous segment we need to update the last_frame
573 if(seq>msp->seq && seq<msp->nxtpdu){
574 msp->last_frame=pinfo->fd->num;
575 msp->last_frame_time=pinfo->fd->abs_ts;
576 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
579 /* If this segment is completely within a previous PDU
580 * then we just skip this packet
582 if(seq>msp->seq && nxtseq<=msp->nxtpdu){
585 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu){
586 offset+=msp->nxtpdu-seq;
592 /* First we try to find the start and transfer time for a PDU.
593 * We only print this for the very first segment of a PDU
594 * and only for PDUs spanning multiple segments.
595 * Se we look for if there was any multisegment PDU started
596 * just BEFORE the end of this segment. I.e. either inside this
597 * segment or in a previous segment.
598 * Since this might also match PDUs that are completely within
599 * this segment we also verify that the found PDU does span
600 * beyond the end of this segment.
602 msp=se_tree_lookup32_le(multisegment_pdus, nxtseq-1);
604 if(pinfo->fd->num==msp->first_frame) {
608 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);
609 PROTO_ITEM_SET_GENERATED(item);
611 nstime_delta(&ns, &msp->last_frame_time, &pinfo->fd->abs_ts);
612 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,
614 PROTO_ITEM_SET_GENERATED(item);
618 /* Second we check if this segment is part of a PDU started
619 * prior to the segment (seq-1)
621 msp=se_tree_lookup32_le(multisegment_pdus, seq-1);
623 /* If this segment is completely within a previous PDU
624 * then we just skip this packet
626 if(seq>msp->seq && nxtseq<=msp->nxtpdu){
627 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
631 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu){
632 offset+=msp->nxtpdu-seq;
641 /* if we saw a PDU that extended beyond the end of the segment,
642 use this function to remember where the next pdu starts
644 struct tcp_multisegment_pdu *
645 pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, emem_tree_t *multisegment_pdus)
647 struct tcp_multisegment_pdu *msp;
649 msp=se_alloc(sizeof(struct tcp_multisegment_pdu));
652 msp->first_frame=pinfo->fd->num;
653 msp->last_frame=pinfo->fd->num;
654 msp->last_frame_time=pinfo->fd->abs_ts;
656 se_tree_insert32(multisegment_pdus, seq, (void *)msp);
660 /* This is called for SYN and SYN+ACK packets and the purpose is to verify
661 * that we have seen window scaling in both directions.
662 * If we cant find window scaling being set in both directions
663 * that means it was present in the SYN but not in the SYN+ACK
664 * (or the SYN was missing) and then we disable the window scaling
665 * for this tcp session.
668 verify_tcp_window_scaling(gboolean is_synack, struct tcp_analysis *tcpd)
670 if( tcpd->fwd->win_scale==-1 ) {
671 /* We know window scaling will not be used as:
672 * a) this is the SYN and it does not have the WS option
673 * (we set the reverse win_scale also in case we miss
675 * b) this is the SYN/ACK and either the SYN packet has not
676 * been seen or it did have the WS option. As the SYN/ACK
677 * does not have the WS option, window scaling will not be used.
679 * Setting win_scale to -2 to indicate that we can
680 * trust the window_size value in the TCP header.
682 tcpd->fwd->win_scale = -2;
683 tcpd->rev->win_scale = -2;
685 } else if( is_synack && tcpd->rev->win_scale==-2 ) {
686 /* The SYN/ACK has the WS option, while the SYN did not,
687 * this should not happen, but the endpoints will not
688 * have used window scaling, so we will neither
690 tcpd->fwd->win_scale = -2;
694 /* if we saw a window scaling option, store it for future reference
697 pdu_store_window_scale_option(guint8 ws, struct tcp_analysis *tcpd)
700 tcpd->fwd->win_scale=ws;
703 /* when this function returns, it will (if createflag) populate the ta pointer.
706 tcp_analyze_get_acked_struct(guint32 frame, gboolean createflag, struct tcp_analysis *tcpd)
711 tcpd->ta=se_tree_lookup32(tcpd->acked_table, frame);
712 if((!tcpd->ta) && createflag){
713 tcpd->ta=se_alloc0(sizeof(struct tcp_acked));
714 se_tree_insert32(tcpd->acked_table, frame, (void *)tcpd->ta);
719 /* fwd contains a list of all segments processed but not yet ACKed in the
720 * same direction as the current segment.
721 * rev contains a list of all segments received but not yet ACKed in the
722 * opposite direction to the current segment.
724 * New segments are always added to the head of the fwd/rev lists.
728 tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint16 flags, guint32 window, struct tcp_analysis *tcpd)
730 tcp_unacked_t *ual=NULL;
731 tcp_unacked_t *prevual=NULL;
736 printf("analyze_sequence numbers frame:%u direction:%s\n",pinfo->fd->num,direction>=0?"FWD":"REW");
737 printf("FWD list lastflags:0x%04x base_seq:0x%08x:\n",tcpd->fwd->lastsegmentflags,tcpd->fwd->base_seq);for(ual=tcpd->fwd->segments;ual;ual=ual->next)printf("Frame:%d Seq:%d Nextseq:%d\n",ual->frame,ual->seq,ual->nextseq);
738 printf("REV list lastflags:0x%04x base_seq:0x%08x:\n",tcpd->rev->lastsegmentflags,tcpd->rev->base_seq);for(ual=tcpd->rev->segments;ual;ual=ual->next)printf("Frame:%d Seq:%d Nextseq:%d\n",ual->frame,ual->seq,ual->nextseq);
745 /* if this is the first segment for this list we need to store the
748 * Start relative seq and ack numbers at 1 if this
749 * is not a SYN packet. This makes the relative
750 * seq/ack numbers to be displayed correctly in the
751 * event that the SYN or SYN/ACK packet is not seen
752 * (this solves bug 1542)
754 if(tcpd->fwd->base_seq==0){
755 tcpd->fwd->base_seq = (flags & TH_SYN) ? seq : seq-1;
758 /* Only store reverse sequence if this isn't the SYN
759 * There's no guarantee that the ACK field of a SYN
760 * contains zeros; get the ISN from the first segment
761 * with the ACK bit set instead (usually the SYN/ACK).
763 if( (tcpd->rev->base_seq==0) && (flags & TH_ACK) ){
764 tcpd->rev->base_seq = (flags & TH_SYN) ? ack : ack-1;
767 if( flags & TH_ACK ){
768 tcpd->rev->valid_bif = 1;
772 * it is a zero window probe if
773 * the sequnece number is the next expected one
774 * the window in the other direction is 0
775 * the segment is exactly 1 byte
779 && seq==tcpd->fwd->nextseq
780 && tcpd->rev->window==0 ){
782 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
784 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
790 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
794 && (flags&(TH_RST|TH_FIN|TH_SYN))==0 ){
796 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
798 tcpd->ta->flags|=TCP_A_ZERO_WINDOW;
803 * If this segment is beyond the last seen nextseq we must
804 * have missed some previous segment
806 * We only check for this if we have actually seen segments prior to this
808 * RST packets are not checked for this.
810 if( tcpd->fwd->nextseq
811 && GT_SEQ(seq, tcpd->fwd->nextseq)
812 && (flags&(TH_RST))==0 ){
814 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
816 tcpd->ta->flags|=TCP_A_LOST_PACKET;
818 /* Disable BiF until an ACK is seen in the other direction */
819 tcpd->fwd->valid_bif = 0;
824 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
825 * to what should be the next sequence number.
826 * SYN/FIN/RST segments are never keepalives
829 if( (seglen==0||seglen==1)
830 && seq==(tcpd->fwd->nextseq-1)
831 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
833 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
835 tcpd->ta->flags|=TCP_A_KEEP_ALIVE;
839 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
840 * the previous seen segment and with a new window value
844 && window!=tcpd->fwd->window
845 && seq==tcpd->fwd->nextseq
846 && ack==tcpd->fwd->lastack
847 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
849 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
851 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
856 * If we know the window scaling
857 * and if this segment contains data ang goes all the way to the
858 * edge of the advertized window
859 * then we mark it as WINDOW FULL
860 * SYN/RST/FIN packets are never WINDOW FULL
864 && tcpd->rev->win_scale!=-1
865 && (seq+seglen)==(tcpd->rev->lastack+(tcpd->rev->window<<(tcpd->rev->win_scale==-2?0:tcpd->rev->win_scale)))
866 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
868 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
870 tcpd->ta->flags|=TCP_A_WINDOW_FULL;
875 * It is a keepalive ack if it repeats the previous ACK and if
876 * the last segment in the reverse direction was a keepalive
881 && window==tcpd->fwd->window
882 && seq==tcpd->fwd->nextseq
883 && ack==tcpd->fwd->lastack
884 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
885 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
887 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
889 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK;
894 /* ZERO WINDOW PROBE ACK
895 * It is a zerowindowprobe ack if it repeats the previous ACK and if
896 * the last segment in the reverse direction was a zerowindowprobe
897 * It also repeats the previous zero window indication
902 && window==tcpd->fwd->window
903 && seq==tcpd->fwd->nextseq
904 && ack==tcpd->fwd->lastack
905 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
906 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
908 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
910 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
916 * It is a duplicate ack if window/seq/ack is the same as the previous
917 * segment and if the segment length is 0
921 && window==tcpd->fwd->window
922 && seq==tcpd->fwd->nextseq
923 && ack==tcpd->fwd->lastack
924 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
925 tcpd->fwd->dupacknum++;
927 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
929 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
930 tcpd->ta->dupack_num=tcpd->fwd->dupacknum;
931 tcpd->ta->dupack_frame=tcpd->fwd->lastnondupack;
937 /* If this was NOT a dupack we must reset the dupack counters */
938 if( (!tcpd->ta) || !(tcpd->ta->flags&TCP_A_DUPLICATE_ACK) ){
939 tcpd->fwd->lastnondupack=pinfo->fd->num;
940 tcpd->fwd->dupacknum=0;
945 * If this segment acks beyond the 'max seq to be acked' in the other direction
946 * then that means we have missed packets going in the
949 * We only check this if we have actually seen some seq numbers
950 * in the other direction.
952 if( tcpd->rev->maxseqtobeacked
953 && GT_SEQ(ack, tcpd->rev->maxseqtobeacked )
954 && (flags&(TH_ACK))!=0 ){
957 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
959 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
960 /* update 'max seq to be acked' in the other direction so we dont get
961 * this indication again.
963 tcpd->rev->maxseqtobeacked=tcpd->rev->nextseq;
967 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
968 * If the segments contains data and if it does not advance
969 * sequence number it must be either of these three.
970 * Only test for this if we know what the seq number should be
971 * (tcpd->fwd->nextseq)
973 * Note that a simple KeepAlive is not a retransmission
976 && tcpd->fwd->nextseq
977 && (LT_SEQ(seq, tcpd->fwd->nextseq)) ){
980 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ){
981 goto finished_checking_retransmission_type;
984 /* If there were >=2 duplicate ACKs in the reverse direction
985 * (there might be duplicate acks missing from the trace)
986 * and if this sequence number matches those ACKs
987 * and if the packet occurs within 20ms of the last
989 * then this is a fast retransmission
991 t=(pinfo->fd->abs_ts.secs-tcpd->rev->lastacktime.secs)*1000000000;
992 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->rev->lastacktime.nsecs;
993 if( tcpd->rev->dupacknum>=2
994 && tcpd->rev->lastack==seq
997 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
999 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
1000 goto finished_checking_retransmission_type;
1003 /* If the segment came <3ms since the segment with the highest
1004 * seen sequence number and it doesn't look like a retransmission
1005 * then it is an OUT-OF-ORDER segment.
1006 * (3ms is an arbitrary number)
1008 t=(pinfo->fd->abs_ts.secs-tcpd->fwd->nextseqtime.secs)*1000000000;
1009 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->fwd->nextseqtime.nsecs;
1011 && tcpd->fwd->nextseq != seq + seglen ){
1013 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
1015 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
1016 goto finished_checking_retransmission_type;
1019 /* Then it has to be a generic retransmission */
1021 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
1023 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
1024 nstime_delta(&tcpd->ta->rto_ts, &pinfo->fd->abs_ts, &tcpd->fwd->nextseqtime);
1025 tcpd->ta->rto_frame=tcpd->fwd->nextseqframe;
1027 finished_checking_retransmission_type:
1030 nextseq = seq+seglen;
1031 if (seglen || flags&(TH_SYN|TH_FIN)) {
1032 /* add this new sequence number to the fwd list */
1033 TCP_UNACKED_NEW(ual);
1034 ual->next=tcpd->fwd->segments;
1035 tcpd->fwd->segments=ual;
1036 ual->frame=pinfo->fd->num;
1038 ual->ts=pinfo->fd->abs_ts;
1040 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
1041 if( (flags&(TH_SYN|TH_FIN)) ){
1044 ual->nextseq=nextseq;
1047 /* Store the highest number seen so far for nextseq so we can detect
1048 * when we receive segments that arrive with a "hole"
1049 * If we dont have anything since before, just store what we got.
1050 * ZeroWindowProbes are special and dont really advance the nextseq
1052 if(GT_SEQ(nextseq, tcpd->fwd->nextseq) || !tcpd->fwd->nextseq) {
1053 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ){
1054 tcpd->fwd->nextseq=nextseq;
1055 tcpd->fwd->nextseqframe=pinfo->fd->num;
1056 tcpd->fwd->nextseqtime.secs=pinfo->fd->abs_ts.secs;
1057 tcpd->fwd->nextseqtime.nsecs=pinfo->fd->abs_ts.nsecs;
1061 /* Store the highest continuous seq number seen so far for 'max seq to be acked',
1062 so we can detect TCP_A_ACK_LOST_PACKET contition
1064 if(EQ_SEQ(seq, tcpd->fwd->maxseqtobeacked) || !tcpd->fwd->maxseqtobeacked) {
1065 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ){
1066 tcpd->fwd->maxseqtobeacked=tcpd->fwd->nextseq;
1071 /* remember what the ack/window is so we can track window updates and retransmissions */
1072 tcpd->fwd->window=window;
1073 tcpd->fwd->lastack=ack;
1074 tcpd->fwd->lastacktime.secs=pinfo->fd->abs_ts.secs;
1075 tcpd->fwd->lastacktime.nsecs=pinfo->fd->abs_ts.nsecs;
1078 /* if there were any flags set for this segment we need to remember them
1079 * we only remember the flags for the very last segment though.
1082 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;
1084 tcpd->fwd->lastsegmentflags=0;
1088 /* remove all segments this ACKs and we dont need to keep around any more
1092 ual = tcpd->rev->segments;
1094 tcp_unacked_t *tmpual;
1096 /* If this ack matches the segment, process accordingly */
1097 if(ack==ual->nextseq){
1098 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
1099 tcpd->ta->frame_acked=ual->frame;
1100 nstime_delta(&tcpd->ta->ts, &pinfo->fd->abs_ts, &ual->ts);
1102 /* If this acknowledges a segment prior to this one, leave this segment alone and move on */
1103 else if (GT_SEQ(ual->nextseq,ack)){
1109 /* This segment is old, or an exact match. Delete the segment from the list */
1113 if (tcpd->rev->scps_capable) {
1114 /* Track largest segment successfully sent for SNACK analysis*/
1115 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked){
1116 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);
1121 tcpd->rev->segments = tmpual;
1122 TCP_UNACKED_FREE(ual);
1126 prevual->next = tmpual;
1127 TCP_UNACKED_FREE(ual);
1132 /* how many bytes of data are there in flight after this frame
1135 ual=tcpd->fwd->segments;
1136 if (tcp_track_bytes_in_flight && seglen!=0 && ual && tcpd->fwd->valid_bif) {
1137 guint32 first_seq, last_seq, in_flight;
1139 first_seq = ual->seq - tcpd->fwd->base_seq;
1140 last_seq = ual->nextseq - tcpd->fwd->base_seq;
1142 if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) {
1143 last_seq = ual->nextseq-tcpd->fwd->base_seq;
1145 if ((ual->seq-tcpd->fwd->base_seq)<first_seq) {
1146 first_seq = ual->seq-tcpd->fwd->base_seq;
1150 in_flight = last_seq-first_seq;
1152 if (in_flight>0 && in_flight<2000000000) {
1154 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
1156 tcpd->ta->bytes_in_flight = in_flight;
1163 * Prints results of the sequence number analysis concerning tcp segments
1164 * retransmitted or out-of-order
1167 tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,
1169 proto_tree * flags_tree,
1170 struct tcp_acked *ta
1173 proto_item * flags_item;
1175 /* TCP Rentransmission */
1176 if (ta->flags & TCP_A_RETRANSMISSION) {
1177 flags_item=proto_tree_add_none_format(flags_tree,
1178 hf_tcp_analysis_retransmission,
1180 "This frame is a (suspected) "
1183 PROTO_ITEM_SET_GENERATED(flags_item);
1184 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1185 "Retransmission (suspected)");
1187 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
1189 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {
1190 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
1191 tvb, 0, 0, &ta->rto_ts);
1192 PROTO_ITEM_SET_GENERATED(flags_item);
1193 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,
1194 tvb, 0, 0, ta->rto_frame);
1195 PROTO_ITEM_SET_GENERATED(flags_item);
1198 /* TCP Fast Rentransmission */
1199 if (ta->flags & TCP_A_FAST_RETRANSMISSION) {
1200 flags_item=proto_tree_add_none_format(flags_tree,
1201 hf_tcp_analysis_fast_retransmission,
1203 "This frame is a (suspected) fast"
1206 PROTO_ITEM_SET_GENERATED(flags_item);
1207 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1208 "Fast retransmission (suspected)");
1209 flags_item=proto_tree_add_none_format(flags_tree,
1210 hf_tcp_analysis_retransmission,
1212 "This frame is a (suspected) "
1215 PROTO_ITEM_SET_GENERATED(flags_item);
1216 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1217 "[TCP Fast Retransmission] ");
1219 /* TCP Out-Of-Order */
1220 if (ta->flags & TCP_A_OUT_OF_ORDER) {
1221 flags_item=proto_tree_add_none_format(flags_tree,
1222 hf_tcp_analysis_out_of_order,
1224 "This frame is a (suspected) "
1225 "out-of-order segment"
1227 PROTO_ITEM_SET_GENERATED(flags_item);
1228 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1229 "Out-Of-Order segment");
1230 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
1234 /* Prints results of the sequence number analysis concerning reused ports */
1236 tcp_sequence_number_analysis_print_reused(packet_info * pinfo,
1238 proto_tree * flags_tree,
1239 struct tcp_acked *ta
1242 proto_item * flags_item;
1244 /* TCP Ports Reused */
1245 if (ta->flags & TCP_A_REUSED_PORTS) {
1246 flags_item=proto_tree_add_none_format(flags_tree,
1247 hf_tcp_analysis_reused_ports,
1249 "A new tcp session is started with the same "
1250 "ports as an earlier session in this trace"
1252 PROTO_ITEM_SET_GENERATED(flags_item);
1253 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1254 "TCP Port numbers reused for new session");
1255 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1256 "[TCP Port numbers reused] ");
1260 /* Prints results of the sequence number analysis concerning lost tcp segments */
1262 tcp_sequence_number_analysis_print_lost(packet_info * pinfo,
1264 proto_tree * flags_tree,
1265 struct tcp_acked *ta
1268 proto_item * flags_item;
1270 /* TCP Lost Segment */
1271 if (ta->flags & TCP_A_LOST_PACKET) {
1272 flags_item=proto_tree_add_none_format(flags_tree,
1273 hf_tcp_analysis_lost_packet,
1275 "A segment before this frame was "
1278 PROTO_ITEM_SET_GENERATED(flags_item);
1279 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1280 "Previous segment lost (common at capture start)");
1281 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1282 "[TCP Previous segment lost] ");
1284 /* TCP Ack lost segment */
1285 if (ta->flags & TCP_A_ACK_LOST_PACKET) {
1286 flags_item=proto_tree_add_none_format(flags_tree,
1287 hf_tcp_analysis_ack_lost_packet,
1289 "This frame ACKs a segment we have "
1292 PROTO_ITEM_SET_GENERATED(flags_item);
1293 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1294 "ACKed lost segment (common at capture start)");
1295 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1296 "[TCP ACKed lost segment] ");
1300 /* Prints results of the sequence number analysis concerning tcp window */
1302 tcp_sequence_number_analysis_print_window(packet_info * pinfo,
1304 proto_tree * flags_tree,
1305 struct tcp_acked *ta
1308 proto_item * flags_item;
1310 /* TCP Window Update */
1311 if (ta->flags & TCP_A_WINDOW_UPDATE) {
1312 flags_item=proto_tree_add_none_format(flags_tree,
1313 hf_tcp_analysis_window_update,
1315 "This is a tcp window update"
1317 PROTO_ITEM_SET_GENERATED(flags_item);
1318 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_CHAT,
1320 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
1322 /* TCP Full Window */
1323 if (ta->flags & TCP_A_WINDOW_FULL) {
1324 flags_item=proto_tree_add_none_format(flags_tree,
1325 hf_tcp_analysis_window_full,
1327 "The transmission window is now "
1330 PROTO_ITEM_SET_GENERATED(flags_item);
1331 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1333 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
1337 /* Prints results of the sequence number analysis concerning tcp keepalive */
1339 tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,
1341 proto_tree * flags_tree,
1342 struct tcp_acked *ta
1345 proto_item * flags_item;
1348 if (ta->flags & TCP_A_KEEP_ALIVE){
1349 flags_item=proto_tree_add_none_format(flags_tree,
1350 hf_tcp_analysis_keep_alive,
1352 "This is a TCP keep-alive segment"
1354 PROTO_ITEM_SET_GENERATED(flags_item);
1355 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1357 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
1359 /* TCP Ack Keep Alive */
1360 if (ta->flags & TCP_A_KEEP_ALIVE_ACK) {
1361 flags_item=proto_tree_add_none_format(flags_tree,
1362 hf_tcp_analysis_keep_alive_ack,
1364 "This is an ACK to a TCP keep-alive "
1367 PROTO_ITEM_SET_GENERATED(flags_item);
1368 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1370 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
1374 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
1376 tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,
1378 proto_tree * flags_tree,
1379 struct tcp_acked *ta,
1383 proto_item * flags_item;
1385 /* TCP Duplicate ACK */
1386 if (ta->dupack_num) {
1387 if (ta->flags & TCP_A_DUPLICATE_ACK ) {
1388 flags_item=proto_tree_add_none_format(flags_tree,
1389 hf_tcp_analysis_duplicate_ack,
1391 "This is a TCP duplicate ack"
1393 PROTO_ITEM_SET_GENERATED(flags_item);
1394 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1395 "[TCP Dup ACK %u#%u] ",
1401 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
1402 tvb, 0, 0, ta->dupack_num);
1403 PROTO_ITEM_SET_GENERATED(flags_item);
1404 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
1405 tvb, 0, 0, ta->dupack_frame);
1406 PROTO_ITEM_SET_GENERATED(flags_item);
1407 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1408 "Duplicate ACK (#%u)",
1414 /* Prints results of the sequence number analysis concerning tcp zero window */
1416 tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,
1418 proto_tree * flags_tree,
1419 struct tcp_acked *ta
1422 proto_item * flags_item;
1424 /* TCP Zero Window Probe */
1425 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE) {
1426 flags_item=proto_tree_add_none_format(flags_tree,
1427 hf_tcp_analysis_zero_window_probe,
1429 "This is a TCP zero-window-probe"
1431 PROTO_ITEM_SET_GENERATED(flags_item);
1432 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1433 "Zero window probe");
1434 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
1436 /* TCP Zero Window */
1437 if (ta->flags&TCP_A_ZERO_WINDOW) {
1438 flags_item=proto_tree_add_none_format(flags_tree,
1439 hf_tcp_analysis_zero_window,
1441 "This is a ZeroWindow segment"
1443 PROTO_ITEM_SET_GENERATED(flags_item);
1444 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1446 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
1448 /* TCP Zero Window Probe Ack */
1449 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK) {
1450 flags_item=proto_tree_add_none_format(flags_tree,
1451 hf_tcp_analysis_zero_window_probe_ack,
1453 "This is an ACK to a TCP zero-window-probe"
1455 PROTO_ITEM_SET_GENERATED(flags_item);
1456 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1457 "Zero window probe ACK");
1458 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1459 "[TCP ZeroWindowProbeAck] ");
1464 /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */
1466 tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U_,
1468 proto_tree * flags_tree _U_,
1469 struct tcp_acked *ta
1472 proto_item * flags_item;
1474 if (tcp_track_bytes_in_flight) {
1475 flags_item=proto_tree_add_uint(flags_tree,
1476 hf_tcp_analysis_bytes_in_flight,
1477 tvb, 0, 0, ta->bytes_in_flight);
1479 PROTO_ITEM_SET_GENERATED(flags_item);
1484 tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd)
1486 struct tcp_acked *ta = NULL;
1489 proto_tree *flags_tree=NULL;
1495 tcp_analyze_get_acked_struct(pinfo->fd->num, FALSE, tcpd);
1502 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "SEQ/ACK analysis");
1503 PROTO_ITEM_SET_GENERATED(item);
1504 tree=proto_item_add_subtree(item, ett_tcp_analysis);
1506 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
1507 data we actually have */
1508 if(ta->frame_acked){
1509 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
1510 tvb, 0, 0, ta->frame_acked);
1511 PROTO_ITEM_SET_GENERATED(item);
1513 /* only display RTT if we actually have something we are acking */
1514 if( ta->ts.secs || ta->ts.nsecs ){
1515 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
1516 tvb, 0, 0, &ta->ts);
1517 PROTO_ITEM_SET_GENERATED(item);
1521 if(ta->bytes_in_flight) {
1522 /* print results for amount of data in flight */
1523 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta);
1527 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, 0, FALSE);
1528 PROTO_ITEM_SET_GENERATED(item);
1529 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);
1531 /* print results for reused tcp ports */
1532 tcp_sequence_number_analysis_print_reused(pinfo, tvb, flags_tree, ta);
1534 /* print results for retransmission and out-of-order segments */
1535 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, ta);
1537 /* print results for lost tcp segments */
1538 tcp_sequence_number_analysis_print_lost(pinfo, tvb, flags_tree, ta);
1540 /* print results for tcp window information */
1541 tcp_sequence_number_analysis_print_window(pinfo, tvb, flags_tree, ta);
1543 /* print results for tcp keep alive information */
1544 tcp_sequence_number_analysis_print_keepalive(pinfo, tvb, flags_tree, ta);
1546 /* print results for tcp duplicate acks */
1547 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);
1549 /* print results for tcp zero window */
1550 tcp_sequence_number_analysis_print_zero_window(pinfo, tvb, flags_tree, ta);
1557 print_tcp_fragment_tree(fragment_data *ipfd_head, proto_tree *tree, proto_tree *tcp_tree, packet_info *pinfo, tvbuff_t *next_tvb)
1559 proto_item *tcp_tree_item, *frag_tree_item;
1562 * The subdissector thought it was completely
1563 * desegmented (although the stuff at the
1564 * end may, in turn, require desegmentation),
1565 * so we show a tree with all segments.
1567 show_fragment_tree(ipfd_head, &tcp_segment_items,
1568 tree, pinfo, next_tvb, &frag_tree_item);
1570 * The toplevel fragment subtree is now
1571 * behind all desegmented data; move it
1572 * right behind the TCP tree.
1574 tcp_tree_item = proto_tree_get_parent(tcp_tree);
1575 if(frag_tree_item && tcp_tree_item) {
1576 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);
1580 /* **************************************************************************
1581 * End of tcp sequence number analysis
1582 * **************************************************************************/
1585 /* Minimum TCP header length. */
1586 #define TCPH_MIN_LEN 20
1588 /* Desegmentation of TCP streams */
1589 /* table to hold defragmented TCP streams */
1590 static GHashTable *tcp_fragment_table = NULL;
1592 /* functions to trace tcp segments */
1593 /* Enable desegmenting of TCP streams */
1594 static gboolean tcp_desegment = TRUE;
1597 desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
1598 guint32 seq, guint32 nxtseq,
1599 guint32 sport, guint32 dport,
1600 proto_tree *tree, proto_tree *tcp_tree,
1601 struct tcp_analysis *tcpd)
1603 struct tcpinfo *tcpinfo = pinfo->private_data;
1604 fragment_data *ipfd_head;
1605 int last_fragment_len;
1606 gboolean must_desegment;
1607 gboolean called_dissector;
1608 int another_pdu_follows;
1613 struct tcp_multisegment_pdu *msp;
1614 gboolean cleared_writable = col_get_writable(pinfo->cinfo);
1618 last_fragment_len = 0;
1619 must_desegment = FALSE;
1620 called_dissector = FALSE;
1621 another_pdu_follows = 0;
1625 * Initialize these to assume no desegmentation.
1626 * If that's not the case, these will be set appropriately
1627 * by the subdissector.
1629 pinfo->desegment_offset = 0;
1630 pinfo->desegment_len = 0;
1633 * Initialize this to assume that this segment will just be
1634 * added to the middle of a desegmented chunk of data, so
1635 * that we should show it all as data.
1636 * If that's not the case, it will be set appropriately.
1638 deseg_offset = offset;
1641 /* Have we seen this PDU before (and is it the start of a multi-
1644 if ((msp = se_tree_lookup32(tcpd->fwd->multisegment_pdus, seq))) {
1647 /* Yes. This could be because we've dissected this frame before
1648 * or because this is a retransmission of a previously-seen
1649 * segment. Either way, we don't need to hand it off to the
1650 * subdissector and we certainly don't want to re-add it to the
1651 * multisegment_pdus list: if we did, subsequent lookups would
1652 * find this retransmission instead of the original transmission
1653 * (breaking desegmentation if we'd already linked other segments
1654 * to the original transmission's entry).
1657 if (msp->first_frame == PINFO_FD_NUM(pinfo)) {
1659 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
1661 str = "Retransmitted ";
1662 /* TCP analysis already flags this (in COL_INFO) as a retransmission--if it's enabled */
1665 nbytes = tvb_reported_length_remaining(tvb, offset);
1666 proto_tree_add_bytes_format(tcp_tree, hf_tcp_data, tvb, offset,
1667 nbytes, NULL, "%sTCP segment data (%u byte%s)", str, nbytes,
1668 plurality(nbytes, "", "s"));
1672 /* Else, find the most previous PDU starting before this sequence number */
1673 msp = se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);
1676 if (msp && msp->seq <= seq && msp->nxtpdu > seq) {
1679 if (!PINFO_FD_VISITED(pinfo)) {
1680 msp->last_frame=pinfo->fd->num;
1681 msp->last_frame_time=pinfo->fd->abs_ts;
1684 /* OK, this PDU was found, which means the segment continues
1685 * a higher-level PDU and that we must desegment it.
1687 if (msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
1688 /* The dissector asked for the entire segment */
1689 len = tvb_length_remaining(tvb, offset);
1691 len = MIN(nxtseq, msp->nxtpdu) - seq;
1693 last_fragment_len = len;
1695 ipfd_head = fragment_add(tvb, offset, pinfo, msp->first_frame,
1696 tcp_fragment_table, seq - msp->seq, len,
1697 (LT_SEQ (nxtseq,msp->nxtpdu)) );
1699 if (msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
1700 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
1702 /* If we consumed the entire segment there is no
1703 * other pdu starting anywhere inside this segment.
1704 * So update nxtpdu to point at least to the start
1705 * of the next segment.
1706 * (If the subdissector asks for even more data we
1707 * will advance nxtpdu even furhter later down in
1710 msp->nxtpdu = nxtseq;
1713 if( (msp->nxtpdu < nxtseq)
1714 && (msp->nxtpdu >= seq)
1716 another_pdu_follows=msp->nxtpdu - seq;
1719 /* This segment was not found in our table, so it doesn't
1720 * contain a continuation of a higher-level PDU.
1721 * Call the normal subdissector.
1725 * Supply the sequence number of this segment. We set this here
1726 * because this segment could be after another in the same packet,
1727 * in which case seq was incremented at the end of the loop.
1731 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
1732 sport, dport, 0, 0, FALSE, tcpd);
1733 called_dissector = TRUE;
1735 /* Did the subdissector ask us to desegment some more data
1736 * before it could handle the packet?
1737 * If so we have to create some structures in our table but
1738 * this is something we only do the first time we see this
1741 if(pinfo->desegment_len) {
1742 if (!PINFO_FD_VISITED(pinfo))
1743 must_desegment = TRUE;
1746 * Set "deseg_offset" to the offset in "tvb"
1747 * of the first byte of data that the
1748 * subdissector didn't process.
1750 deseg_offset = offset + pinfo->desegment_offset;
1753 /* Either no desegmentation is necessary, or this is
1754 * segment contains the beginning but not the end of
1755 * a higher-level PDU and thus isn't completely
1762 /* is it completely desegmented? */
1765 * Yes, we think it is.
1766 * We only call subdissector for the last segment.
1767 * Note that the last segment may include more than what
1770 if(ipfd_head->reassembled_in == pinfo->fd->num) {
1772 * OK, this is the last segment.
1773 * Let's call the subdissector with the desegmented
1779 /* create a new TVB structure for desegmented data */
1780 next_tvb = tvb_new_child_real_data(tvb, ipfd_head->data,
1782 ipfd_head->datalen);
1784 /* add desegmented data to the data source list */
1785 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
1788 * Supply the sequence number of the first of the
1789 * reassembled bytes.
1791 tcpinfo->seq = msp->seq;
1793 /* indicate that this is reassembled data */
1794 tcpinfo->is_reassembled = TRUE;
1796 /* call subdissector */
1797 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, sport,
1798 dport, 0, 0, FALSE, tcpd);
1799 called_dissector = TRUE;
1802 * OK, did the subdissector think it was completely
1803 * desegmented, or does it think we need even more
1806 old_len = (int)(tvb_reported_length(next_tvb) - last_fragment_len);
1807 if (pinfo->desegment_len &&
1808 pinfo->desegment_offset<=old_len) {
1810 * "desegment_len" isn't 0, so it needs more
1811 * data for something - and "desegment_offset"
1812 * is before "old_len", so it needs more data
1813 * to dissect the stuff we thought was
1814 * completely desegmented (as opposed to the
1815 * stuff at the beginning being completely
1816 * desegmented, but the stuff at the end
1817 * being a new higher-level PDU that also
1818 * needs desegmentation).
1820 fragment_set_partial_reassembly(pinfo,msp->first_frame, tcp_fragment_table);
1822 /* Update msp->nxtpdu to point to the new next
1825 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1826 /* We want reassembly of at least one
1827 * more segment so set the nxtpdu
1828 * boundary to one byte into the next
1830 * This means that the next segment
1831 * will complete reassembly even if it
1832 * is only one single byte in length.
1834 msp->nxtpdu = seq + tvb_reported_length_remaining(tvb, offset) + 1;
1835 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1836 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
1837 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1839 msp->nxtpdu=seq + last_fragment_len + pinfo->desegment_len;
1842 /* Since we need at least some more data
1843 * there can be no pdu following in the
1844 * tail of this segment.
1846 another_pdu_follows = 0;
1847 offset += last_fragment_len;
1848 seq += last_fragment_len;
1849 if (tvb_length_remaining(tvb, offset) > 0)
1853 * Show the stuff in this TCP segment as
1854 * just raw TCP segment data.
1856 nbytes = another_pdu_follows > 0
1857 ? another_pdu_follows
1858 : tvb_reported_length_remaining(tvb, offset);
1859 proto_tree_add_bytes_format(tcp_tree, hf_tcp_data, tvb, offset,
1860 nbytes, NULL, "TCP segment data (%u byte%s)", nbytes,
1861 plurality(nbytes, "", "s"));
1863 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
1865 /* Did the subdissector ask us to desegment
1866 * some more data? This means that the data
1867 * at the beginning of this segment completed
1868 * a higher-level PDU, but the data at the
1869 * end of this segment started a higher-level
1870 * PDU but didn't complete it.
1872 * If so, we have to create some structures
1873 * in our table, but this is something we
1874 * only do the first time we see this packet.
1876 if(pinfo->desegment_len) {
1877 if (!PINFO_FD_VISITED(pinfo))
1878 must_desegment = TRUE;
1880 /* The stuff we couldn't dissect
1881 * must have come from this segment,
1882 * so it's all in "tvb".
1884 * "pinfo->desegment_offset" is
1885 * relative to the beginning of
1886 * "next_tvb"; we want an offset
1887 * relative to the beginning of "tvb".
1889 * First, compute the offset relative
1890 * to the *end* of "next_tvb" - i.e.,
1891 * the number of bytes before the end
1892 * of "next_tvb" at which the
1893 * subdissector stopped. That's the
1894 * length of "next_tvb" minus the
1895 * offset, relative to the beginning
1896 * of "next_tvb, at which the
1897 * subdissector stopped.
1899 deseg_offset = ipfd_head->datalen - pinfo->desegment_offset;
1901 /* "tvb" and "next_tvb" end at the
1902 * same byte of data, so the offset
1903 * relative to the end of "next_tvb"
1904 * of the byte at which we stopped
1905 * is also the offset relative to
1906 * the end of "tvb" of the byte at
1909 * Convert that back into an offset
1910 * relative to the beginninng of
1911 * "tvb", by taking the length of
1912 * "tvb" and subtracting the offset
1913 * relative to the end.
1915 deseg_offset = tvb_reported_length(tvb) - deseg_offset;
1921 if (must_desegment) {
1922 /* If the dissector requested "reassemble until FIN"
1923 * just set this flag for the flow and let reassembly
1924 * proceed at normal. We will check/pick up these
1925 * reassembled PDUs later down in dissect_tcp() when checking
1928 if (tcpd && pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
1929 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1932 * The sequence number at which the stuff to be desegmented
1933 * starts is the sequence number of the byte at an offset
1934 * of "deseg_offset" into "tvb".
1936 * The sequence number of the byte at an offset of "offset"
1937 * is "seq", i.e. the starting sequence number of this
1938 * segment, so the sequence number of the byte at
1939 * "deseg_offset" is "seq + (deseg_offset - offset)".
1941 deseg_seq = seq + (deseg_offset - offset);
1943 if (tcpd && ((nxtseq - deseg_seq) <= 1024*1024)
1944 && (!PINFO_FD_VISITED(pinfo))) {
1945 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1946 /* The subdissector asked to reassemble using the
1947 * entire next segment.
1948 * Just ask reassembly for one more byte
1949 * but set this msp flag so we can pick it up
1952 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
1953 nxtseq+1, tcpd->fwd->multisegment_pdus);
1954 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1956 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1957 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
1960 /* add this segment as the first one for this new pdu */
1961 fragment_add(tvb, deseg_offset, pinfo, msp->first_frame,
1962 tcp_fragment_table, 0, nxtseq - deseg_seq,
1963 LT_SEQ(nxtseq, msp->nxtpdu));
1967 if (!called_dissector || pinfo->desegment_len != 0) {
1968 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
1969 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
1971 * We know what frame this PDU is reassembled in;
1972 * let the user know.
1974 item = proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in, tvb, 0,
1975 0, ipfd_head->reassembled_in);
1976 PROTO_ITEM_SET_GENERATED(item);
1980 * Either we didn't call the subdissector at all (i.e.,
1981 * this is a segment that contains the middle of a
1982 * higher-level PDU, but contains neither the beginning
1983 * nor the end), or the subdissector couldn't dissect it
1984 * all, as some data was missing (i.e., it set
1985 * "pinfo->desegment_len" to the amount of additional
1988 if (pinfo->desegment_offset == 0) {
1990 * It couldn't, in fact, dissect any of it (the
1991 * first byte it couldn't dissect is at an offset
1992 * of "pinfo->desegment_offset" from the beginning
1993 * of the payload, and that's 0).
1994 * Just mark this as TCP.
1996 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
1997 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
2001 * Show what's left in the packet as just raw TCP segment
2003 * XXX - remember what protocol the last subdissector
2004 * was, and report it as a continuation of that, instead?
2006 nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
2007 proto_tree_add_bytes_format(tcp_tree, hf_tcp_data, tvb, deseg_offset,
2008 -1, NULL, "TCP segment data (%u byte%s)", nbytes,
2009 plurality(nbytes, "", "s"));
2011 pinfo->can_desegment = 0;
2012 pinfo->desegment_offset = 0;
2013 pinfo->desegment_len = 0;
2015 if(another_pdu_follows) {
2016 /* there was another pdu following this one. */
2017 pinfo->can_desegment = 2;
2018 /* we also have to prevent the dissector from changing the
2019 * PROTOCOL and INFO colums since what follows may be an
2020 * incomplete PDU and we dont want it be changed back from
2021 * <Protocol> to <TCP>
2022 * XXX There is no good way to block the PROTOCOL column
2023 * from being changed yet so we set the entire row unwritable.
2024 * The flag cleared_writable stores the initial state.
2026 col_set_fence(pinfo->cinfo, COL_INFO);
2027 cleared_writable |= col_get_writable(pinfo->cinfo);
2028 col_set_writable(pinfo->cinfo, FALSE);
2029 offset += another_pdu_follows;
2030 seq += another_pdu_follows;
2033 /* remove any blocking set above otherwise the
2034 * proto,colinfo tap will break
2036 if(cleared_writable) {
2037 col_set_writable(pinfo->cinfo, TRUE);
2043 * Loop for dissecting PDUs within a TCP stream; assumes that a PDU
2044 * consists of a fixed-length chunk of data that contains enough information
2045 * to determine the length of the PDU, followed by rest of the PDU.
2047 * The first three arguments are the arguments passed to the dissector
2048 * that calls this routine.
2050 * "proto_desegment" is the dissector's flag controlling whether it should
2051 * desegment PDUs that cross TCP segment boundaries.
2053 * "fixed_len" is the length of the fixed-length part of the PDU.
2055 * "get_pdu_len()" is a routine called to get the length of the PDU from
2056 * the fixed-length part of the PDU; it's passed "pinfo", "tvb" and "offset".
2058 * "dissect_pdu()" is the routine to dissect a PDU.
2061 tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2062 gboolean proto_desegment, guint fixed_len,
2063 guint (*get_pdu_len)(packet_info *, tvbuff_t *, int),
2064 dissector_t dissect_pdu)
2066 volatile int offset = 0;
2068 guint length_remaining;
2072 proto_item *item=NULL;
2075 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2077 * We use "tvb_ensure_length_remaining()" to make sure there actually
2078 * *is* data remaining. The protocol we're handling could conceivably
2079 * consists of a sequence of fixed-length PDUs, and therefore the
2080 * "get_pdu_len" routine might not actually fetch anything from
2081 * the tvbuff, and thus might not cause an exception to be thrown if
2082 * we've run past the end of the tvbuff.
2084 * This means we're guaranteed that "length_remaining" is positive.
2086 length_remaining = tvb_ensure_length_remaining(tvb, offset);
2089 * Can we do reassembly?
2091 if (proto_desegment && pinfo->can_desegment) {
2093 * Yes - is the fixed-length part of the PDU split across segment
2096 if (length_remaining < fixed_len) {
2098 * Yes. Tell the TCP dissector where the data for this message
2099 * starts in the data it handed us and that we need "some more
2100 * data." Don't tell it exactly how many bytes we need because
2101 * if/when we ask for even more (after the header) that will
2104 pinfo->desegment_offset = offset;
2105 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
2111 * Get the length of the PDU.
2113 plen = (*get_pdu_len)(pinfo, tvb, offset);
2114 if (plen < fixed_len) {
2118 * 1) the length value extracted from the fixed-length portion
2119 * doesn't include the fixed-length portion's length, and
2120 * was so large that, when the fixed-length portion's
2121 * length was added to it, the total length overflowed;
2123 * 2) the length value extracted from the fixed-length portion
2124 * includes the fixed-length portion's length, and the value
2125 * was less than the fixed-length portion's length, i.e. it
2128 * Report this as a bounds error.
2130 show_reported_bounds_error(tvb, pinfo, tree);
2135 * Do not display the the PDU length if it crosses the boundary of the
2136 * packet and no more packets are available.
2138 * XXX - we don't necessarily know whether more packets are
2139 * available; we might be doing a one-pass read through the
2140 * capture in TShark, or we might be doing a live capture in
2144 if (length_remaining >= plen || there are more packets)
2148 * Display the PDU length as a field
2150 item=proto_tree_add_uint(pinfo->tcp_tree, hf_tcp_pdu_size,
2151 tvb, offset, plen, plen);
2152 PROTO_ITEM_SET_GENERATED(item);
2155 item = proto_tree_add_text(pinfo->tcp_tree, tvb, offset, -1,
2156 "PDU Size: %u cut short at %u",plen,length_remaining);
2157 PROTO_ITEM_SET_GENERATED(item);
2162 /* give a hint to TCP where the next PDU starts
2163 * so that it can attempt to find it in case it starts
2164 * somewhere in the middle of a segment.
2166 if(!pinfo->fd->flags.visited && tcp_analyze_seq){
2167 guint remaining_bytes;
2168 remaining_bytes=tvb_reported_length_remaining(tvb, offset);
2169 if(plen>remaining_bytes){
2170 pinfo->want_pdu_tracking=2;
2171 pinfo->bytes_until_next_pdu=plen-remaining_bytes;
2176 * Can we do reassembly?
2178 if (proto_desegment && pinfo->can_desegment) {
2180 * Yes - is the PDU split across segment boundaries?
2182 if (length_remaining < plen) {
2184 * Yes. Tell the TCP dissector where the data for this message
2185 * starts in the data it handed us, and how many more bytes we
2188 pinfo->desegment_offset = offset;
2189 pinfo->desegment_len = plen - length_remaining;
2195 * Construct a tvbuff containing the amount of the payload we have
2196 * available. Make its reported length the amount of data in the PDU.
2198 * XXX - if reassembly isn't enabled. the subdissector will throw a
2199 * BoundsError exception, rather than a ReportedBoundsError exception.
2200 * We really want a tvbuff where the length is "length", the reported
2201 * length is "plen", and the "if the snapshot length were infinite"
2202 * length is the minimum of the reported length of the tvbuff handed
2203 * to us and "plen", with a new type of exception thrown if the offset
2204 * is within the reported length but beyond that third length, with
2205 * that exception getting the "Unreassembled Packet" error.
2207 length = length_remaining;
2210 next_tvb = tvb_new_subset(tvb, offset, length, plen);
2215 * Catch the ReportedBoundsError exception; if this particular message
2216 * happens to get a ReportedBoundsError exception, that doesn't mean
2217 * that we should stop dissecting PDUs within this frame or chunk of
2220 * If it gets a BoundsError, we can stop, as there's nothing more to
2221 * see, so we just re-throw it.
2223 pd_save = pinfo->private_data;
2225 (*dissect_pdu)(next_tvb, pinfo, tree);
2227 CATCH(BoundsError) {
2230 CATCH(ReportedBoundsError) {
2231 /* Restore the private_data structure in case one of the
2232 * called dissectors modified it (and, due to the exception,
2233 * was unable to restore it).
2235 pinfo->private_data = pd_save;
2236 show_reported_bounds_error(tvb, pinfo, tree);
2241 * Step to the next PDU.
2242 * Make sure we don't overflow.
2244 offset_before = offset;
2246 if (offset <= offset_before)
2252 tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val)
2254 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%u", abbrev, val);
2257 /* Supports the reporting the contents of a parsed SCPS capabilities vector */
2259 tcp_info_append_str(packet_info *pinfo, const char *abbrev, const char *val)
2261 col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%s]", abbrev, val);
2266 dissect_tcpopt_exp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2267 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2270 proto_tree *exp_tree;
2272 item = proto_tree_add_item(opt_tree, hf_tcp_option_exp, tvb,
2273 offset, optlen, FALSE);
2274 exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp);
2275 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, FALSE);
2276 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, FALSE);
2277 proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb,
2278 offset + 2, optlen - 2, FALSE);
2279 tcp_info_append_uint(pinfo, "Expxx", TRUE);
2284 dissect_tcpopt_sack_perm(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2285 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2288 proto_tree *exp_tree;
2290 item = proto_tree_add_boolean(opt_tree, hf_tcp_option_sack_perm, tvb, offset,
2292 exp_tree = proto_item_add_subtree(item, ett_tcp_option_sack_perm);
2293 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, FALSE);
2294 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, FALSE);
2295 tcp_info_append_uint(pinfo, "SACK_PERM", TRUE);
2299 dissect_tcpopt_mss(const ip_tcp_opt *optp, tvbuff_t *tvb,
2300 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2303 proto_tree *exp_tree;
2306 mss = tvb_get_ntohs(tvb, offset + 2);
2307 item = proto_tree_add_none_format(opt_tree, hf_tcp_option_mss, tvb, offset,
2308 optlen, "%s: %u bytes", optp->name, mss);
2309 exp_tree = proto_item_add_subtree(item, ett_tcp_option_mss);
2310 proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, FALSE);
2311 proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, FALSE);
2312 proto_tree_add_item(exp_tree, hf_tcp_option_mss_val, tvb, offset + 2, 2, FALSE);
2313 tcp_info_append_uint(pinfo, "MSS", mss);
2316 /* The window scale extension is defined in RFC 1323 */
2318 dissect_tcpopt_wscale(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2319 int offset, guint optlen _U_, packet_info *pinfo, proto_tree *opt_tree)
2322 proto_item *wscale_pi, *gen_pi;
2323 proto_tree *wscale_tree;
2324 struct tcp_analysis *tcpd=NULL;
2326 tcpd=get_tcp_conversation_data(NULL,pinfo);
2328 wscale_pi = proto_tree_add_text(opt_tree, tvb, offset, 3, "Window scale: ");
2329 wscale_tree = proto_item_add_subtree(wscale_pi, ett_tcp_option_wscale);
2331 proto_tree_add_item(wscale_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_NA);
2334 proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_NA);
2337 proto_tree_add_item(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1,
2339 shift = tvb_get_guint8(tvb, offset);
2341 gen_pi = proto_tree_add_uint(wscale_tree, hf_tcp_option_wscale_multiplier, tvb,
2342 offset, 1, 1 << shift);
2343 PROTO_ITEM_SET_GENERATED(gen_pi);
2344 val = tvb_get_guint8(tvb, offset);
2346 proto_item_append_text(wscale_pi, "%u (multiply by %u)", val, 1 << shift);
2348 tcp_info_append_uint(pinfo, "WS", 1 << shift);
2350 if(!pinfo->fd->flags.visited){
2351 pdu_store_window_scale_option(shift, tcpd);
2356 dissect_tcpopt_sack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2357 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2359 proto_tree *field_tree = NULL;
2360 proto_item *tf=NULL;
2361 proto_item *hidden_item;
2362 guint32 leftedge, rightedge;
2363 struct tcp_analysis *tcpd=NULL;
2366 if(tcp_analyze_seq && tcp_relative_seq){
2367 /* find(or create if needed) the conversation for this tcp session */
2368 tcpd=get_tcp_conversation_data(NULL,pinfo);
2371 base_ack=tcpd->rev->base_seq;
2375 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2377 PROTO_ITEM_SET_HIDDEN(hidden_item);
2378 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2379 offset + 1, 1, FALSE);
2380 PROTO_ITEM_SET_HIDDEN(hidden_item);
2382 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
2383 offset += 2; /* skip past type and length */
2384 optlen -= 2; /* subtract size of type and length */
2385 while (optlen > 0) {
2386 if (field_tree == NULL) {
2387 /* Haven't yet made a subtree out of this option. Do so. */
2388 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2389 hidden_item = proto_tree_add_boolean(field_tree, hf_tcp_option_sack, tvb,
2390 offset, optlen, TRUE);
2391 PROTO_ITEM_SET_HIDDEN(hidden_item);
2394 proto_tree_add_text(field_tree, tvb, offset, optlen,
2395 "(suboption would go past end of option)");
2398 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;
2399 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
2400 offset, 4, leftedge,
2401 "left edge = %u%s", leftedge,
2402 tcp_relative_seq ? " (relative)" : "");
2406 proto_tree_add_text(field_tree, tvb, offset, optlen,
2407 "(suboption would go past end of option)");
2410 /* XXX - check whether it goes past end of packet */
2411 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;
2413 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
2414 offset+4, 4, rightedge,
2415 "right edge = %u%s", rightedge,
2416 tcp_relative_seq ? " (relative)" : "");
2417 tcp_info_append_uint(pinfo, "SLE", leftedge);
2418 tcp_info_append_uint(pinfo, "SRE", rightedge);
2419 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);
2425 dissect_tcpopt_echo(const ip_tcp_opt *optp, tvbuff_t *tvb,
2426 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2428 proto_item *hidden_item;
2431 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2433 PROTO_ITEM_SET_HIDDEN(hidden_item);
2434 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2435 offset + 1, 1, FALSE);
2436 PROTO_ITEM_SET_HIDDEN(hidden_item);
2438 echo = tvb_get_ntohl(tvb, offset + 2);
2439 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_echo, tvb, offset,
2441 PROTO_ITEM_SET_HIDDEN(hidden_item);
2442 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2443 "%s: %u", optp->name, echo);
2444 tcp_info_append_uint(pinfo, "ECHO", echo);
2447 /* If set, do not put the TCP timestamp information on the summary line */
2448 static gboolean tcp_ignore_timestamps = FALSE;
2451 dissect_tcpopt_timestamp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
2452 int offset, guint optlen _U_, packet_info *pinfo, proto_tree *opt_tree)
2455 proto_tree *ts_tree;
2456 guint32 ts_val, ts_ecr;
2458 ti = proto_tree_add_text(opt_tree, tvb, offset, 10, "Timestamps: ");
2459 ts_tree = proto_item_add_subtree(ti, ett_tcp_option_timestamp);
2461 proto_tree_add_item(ts_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_NA);
2464 proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_NA);
2467 proto_tree_add_item(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset,
2469 ts_val = tvb_get_ntohl(tvb, offset);
2472 proto_tree_add_item(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset,
2474 ts_ecr = tvb_get_ntohl(tvb, offset);
2477 proto_item_append_text(ti, "TSval %u, TSecr %u", ts_val, ts_ecr);
2478 if (tcp_ignore_timestamps == FALSE) {
2479 tcp_info_append_uint(pinfo, "TSval", ts_val);
2480 tcp_info_append_uint(pinfo, "TSecr", ts_ecr);
2485 dissect_tcpopt_cc(const ip_tcp_opt *optp, tvbuff_t *tvb,
2486 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2488 proto_item *hidden_item;
2491 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2493 PROTO_ITEM_SET_HIDDEN(hidden_item);
2494 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2495 offset + 1, 1, FALSE);
2496 PROTO_ITEM_SET_HIDDEN(hidden_item);
2498 cc = tvb_get_ntohl(tvb, offset + 2);
2499 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_cc, tvb, offset,
2501 PROTO_ITEM_SET_HIDDEN(hidden_item);
2502 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2503 "%s: %u", optp->name, cc);
2504 tcp_info_append_uint(pinfo, "CC", cc);
2508 dissect_tcpopt_qs(const ip_tcp_opt *optp, tvbuff_t *tvb,
2509 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2511 /* Quick-Start TCP option, as defined by RFC4782 */
2512 static const value_string qs_rates[] = {
2518 { 5, "1.28 Mbit/s"},
2519 { 6, "2.56 Mbit/s"},
2520 { 7, "5.12 Mbit/s"},
2521 { 8, "10.24 Mbit/s"},
2522 { 9, "20.48 Mbit/s"},
2523 {10, "40.96 Mbit/s"},
2524 {11, "81.92 Mbit/s"},
2525 {12, "163.84 Mbit/s"},
2526 {13, "327.68 Mbit/s"},
2527 {14, "655.36 Mbit/s"},
2528 {15, "1.31072 Gbit/s"},
2531 static value_string_ext qs_rates_ext = VALUE_STRING_EXT_INIT(qs_rates);
2533 proto_item *hidden_item;
2535 guint8 rate = tvb_get_guint8(tvb, offset + 2) & 0x0f;
2537 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2539 PROTO_ITEM_SET_HIDDEN(hidden_item);
2540 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2541 offset + 1, 1, FALSE);
2542 PROTO_ITEM_SET_HIDDEN(hidden_item);
2544 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_qs, tvb, offset,
2546 PROTO_ITEM_SET_HIDDEN(hidden_item);
2547 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2548 "%s: Rate response, %s, TTL diff %u ", optp->name,
2549 val_to_str_ext(rate, &qs_rates_ext, "Unknown"),
2550 tvb_get_guint8(tvb, offset + 3));
2551 col_append_fstr(pinfo->cinfo, COL_INFO, " QSresp=%s", val_to_str_ext(rate, &qs_rates_ext, "Unknown"));
2556 dissect_tcpopt_scps(const ip_tcp_opt *optp, tvbuff_t *tvb,
2557 int offset, guint optlen, packet_info *pinfo,
2558 proto_tree *opt_tree)
2560 struct tcp_analysis *tcpd;
2561 proto_tree *field_tree = NULL;
2564 proto_item *tf = NULL, *hidden_item;
2565 gchar flags[64] = "<None>";
2566 gchar *fstr[] = {"BETS", "SNACK1", "SNACK2", "COMP", "NLTS", "RESV3", "RESV2", "RESV1"};
2571 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2573 PROTO_ITEM_SET_HIDDEN(hidden_item);
2574 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2575 offset + 1, 1, FALSE);
2576 PROTO_ITEM_SET_HIDDEN(hidden_item);
2578 tcpd = get_tcp_conversation_data(NULL,pinfo);
2580 /* check direction and get ua lists */
2581 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
2583 /* if the addresses are equal, match the ports instead */
2585 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
2589 flow =&(tcpd->flow1);
2591 flow =&(tcpd->flow2);
2593 /* If the option length == 4, this is a real SCPS capability option
2594 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
2595 * (SCPS-TP)" Section 3.2.3 for definition.
2598 capvector = tvb_get_guint8(tvb, offset + 2);
2601 /* Decode the capabilities vector for display */
2602 for (i = 0; i < 5; i++) {
2604 if (capvector & bpos) {
2606 g_strlcat(flags, ", ", 64);
2608 g_strlcat(flags, fstr[i], 64);
2612 /* If lossless header compression is offered, there will be a
2613 * single octet connectionId following the capabilities vector
2615 if (capvector & 0x10)
2616 connid = tvb_get_guint8(tvb, offset + 3);
2620 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector, tvb,
2621 offset, optlen, capvector,
2623 optp->name, capvector, flags);
2624 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_scps,
2625 tvb, offset, optlen, TRUE);
2626 PROTO_ITEM_SET_HIDDEN(hidden_item);
2628 field_tree = proto_item_add_subtree(tf, ett_tcp_option_scps);
2630 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_bets, tvb,
2631 offset + 2, 1, capvector);
2632 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_snack1, tvb,
2633 offset + 2, 1, capvector);
2634 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_snack2, tvb,
2635 offset + 2, 1, capvector);
2636 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_compress, tvb,
2637 offset + 2, 1, capvector);
2638 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_nlts, tvb,
2639 offset + 2, 1, capvector);
2640 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv3, tvb,
2641 offset + 2, 1, capvector);
2642 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv2, tvb,
2643 offset + 2, 1, capvector);
2644 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv1, tvb,
2645 offset + 2, 1, capvector);
2646 proto_tree_add_item(field_tree, hf_tcp_scpsoption_connection_id, tvb,
2649 tcp_info_append_str(pinfo, "SCPS", flags);
2651 flow->scps_capable = 1;
2654 tcp_info_append_uint(pinfo, "Connection ID", connid);
2656 /* The option length != 4, so this is an infamous "extended capabilities
2657 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2658 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
2660 * As the format of this option is only partially defined (it is
2661 * a community (or more likely vendor) defined format beyond that, so
2662 * at least for now, we only parse the standardized portion of the option.
2664 guint8 local_offset = 2;
2665 guint8 binding_space;
2666 guint8 extended_cap_length;
2668 if (flow->scps_capable != 1) {
2669 /* There was no SCPS capabilities option preceeding this */
2670 proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2671 tvb, offset, optlen, 0,
2672 "Illegal SCPS Extended Capabilities (%d bytes)",
2675 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2676 tvb, offset, optlen, 0,
2677 "SCPS Extended Capabilities (%d bytes)",
2679 field_tree=proto_item_add_subtree(tf, ett_tcp_option_scps_extended);
2681 /* There may be multiple binding spaces included in a single option,
2682 * so we will semi-parse each of the stacked binding spaces - skipping
2683 * over the octets following the binding space identifier and length.
2685 while (optlen > local_offset) {
2687 /* 1st octet is Extended Capability Binding Space */
2688 binding_space = tvb_get_guint8(tvb, (offset + local_offset));
2690 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
2691 * As defined by the specification, this length is exclusive of the
2692 * octets containing the extended capability type and length
2694 extended_cap_length =
2695 (tvb_get_guint8(tvb, (offset + local_offset + 1)) >> 4);
2697 /* Convert the extended capabilities length into bytes for display */
2698 extended_cap_length = (extended_cap_length << 1);
2700 proto_tree_add_item(field_tree, hf_tcp_option_scps_binding, tvb, offset + local_offset, 1, 0);
2701 proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding_len, tvb, offset + local_offset + 1, 1, extended_cap_length);
2703 /* Step past the binding space and length octets */
2706 proto_tree_add_text(field_tree, tvb, offset + local_offset,
2707 extended_cap_length,
2708 "Binding Space Data (%u bytes)",
2709 extended_cap_length);
2711 tcp_info_append_uint(pinfo, "EXCAP", binding_space);
2713 /* Step past the Extended capability data
2714 * Treat the extended capability data area as opaque;
2715 * If one desires to parse the extended capability data
2716 * (say, in a vendor aware build of wireshark), it would
2719 local_offset += extended_cap_length;
2726 dissect_tcpopt_user_to(const ip_tcp_opt *optp, tvbuff_t *tvb,
2727 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2729 proto_item *hidden_item, *tf;
2730 proto_tree *field_tree;
2734 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2736 PROTO_ITEM_SET_HIDDEN(hidden_item);
2737 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2738 offset + 1, 1, FALSE);
2739 PROTO_ITEM_SET_HIDDEN(hidden_item);
2741 g = tvb_get_ntohs(tvb, offset + 2) & 0x8000;
2742 to = tvb_get_ntohs(tvb, offset + 2) & 0x7FFF;
2743 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_user_to, tvb, offset,
2745 PROTO_ITEM_SET_HIDDEN(hidden_item);
2747 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_user_to_val, tvb, offset,
2748 optlen, to, "%s: %u %s", optp->name, to, g ? "minutes" : "seconds");
2749 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2750 proto_tree_add_item(field_tree, hf_tcp_option_user_to_granularity, tvb, offset + 2, 2, FALSE);
2751 proto_tree_add_item(field_tree, hf_tcp_option_user_to_val, tvb, offset + 2, 2, FALSE);
2753 tcp_info_append_uint(pinfo, "USER_TO", to);
2756 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2757 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
2760 dissect_tcpopt_snack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2761 int offset, guint optlen, packet_info *pinfo,
2762 proto_tree *opt_tree)
2764 struct tcp_analysis *tcpd=NULL;
2765 guint16 relative_hole_offset;
2766 guint16 relative_hole_size;
2767 guint16 base_mss = 0;
2771 char null_modifier[] = "\0";
2772 char relative_modifier[] = "(relative)";
2773 char *modifier = null_modifier;
2774 proto_item *hidden_item;
2776 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2778 PROTO_ITEM_SET_HIDDEN(hidden_item);
2779 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2780 offset + 1, 1, FALSE);
2781 PROTO_ITEM_SET_HIDDEN(hidden_item);
2783 tcpd = get_tcp_conversation_data(NULL,pinfo);
2785 /* The SNACK option reports missing data with a granualarity of segments. */
2786 relative_hole_offset = tvb_get_ntohs(tvb, offset + 2);
2787 relative_hole_size = tvb_get_ntohs(tvb, offset + 4);
2789 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_snack, tvb,
2790 offset, optlen, TRUE);
2791 PROTO_ITEM_SET_HIDDEN(hidden_item);
2793 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_offset,
2794 tvb, offset, optlen, relative_hole_offset);
2795 PROTO_ITEM_SET_HIDDEN(hidden_item);
2797 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_size,
2798 tvb, offset, optlen, relative_hole_size);
2799 PROTO_ITEM_SET_HIDDEN(hidden_item);
2800 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2801 "%s: Offset %u, Size %u", optp->name,
2802 relative_hole_offset, relative_hole_size);
2804 ack = tvb_get_ntohl(tvb, 8);
2806 if (tcp_relative_seq) {
2807 ack -= tcpd->rev->base_seq;
2808 modifier = relative_modifier;
2811 /* To aid analysis, we can use a simple but generally effective heuristic
2812 * to report the most likely boundaries of the missing data. If the
2813 * flow is scps_capable, we track the maximum sized segment that was
2814 * acknowledged by the receiver and use that as the reporting granularity.
2815 * This may be different from the negotiated MTU due to PMTUD or flows
2816 * that do not send max-sized segments.
2818 base_mss = tcpd->fwd->maxsizeacked;
2821 /* Scale the reported offset and hole size by the largest segment acked */
2822 hole_start = ack + (base_mss * relative_hole_offset);
2823 hole_end = hole_start + (base_mss * relative_hole_size);
2825 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_le,
2826 tvb, offset, optlen, hole_start);
2827 PROTO_ITEM_SET_HIDDEN(hidden_item);
2829 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_re,
2830 tvb, offset, optlen, hole_end);
2831 PROTO_ITEM_SET_HIDDEN(hidden_item);
2832 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2833 "\tMissing Sequence %u - %u %s",
2834 hole_start, hole_end, modifier);
2836 tcp_info_append_uint(pinfo, "SNLE", hole_start);
2837 tcp_info_append_uint(pinfo, "SNRE", hole_end);
2839 expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_NOTE,
2840 "SNACK Sequence %u - %u %s",
2841 hole_start, hole_end, modifier);
2846 dissect_tcpopt_mood(const ip_tcp_opt _U_*optp, tvbuff_t *tvb,
2847 int offset, guint optlen, packet_info *pinfo,
2848 proto_tree *opt_tree)
2850 /* Mood TCP option, as defined by RFC5841 */
2852 static const string_string mood_type[] = {
2856 { "%(", "Confused" },
2858 { ":O", "Surprised" },
2860 { ":@", "Frustrated" },
2862 { ":|", "Apathetic" },
2868 proto_item *hidden_item;
2869 proto_item *mood_item;
2871 mood = tvb_get_ephemeral_string(tvb, offset + 2, optlen-2);
2873 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_kind, tvb,
2875 PROTO_ITEM_SET_HIDDEN(hidden_item);
2876 hidden_item = proto_tree_add_item(opt_tree, hf_tcp_option_len, tvb,
2877 offset + 1, 1, FALSE);
2878 PROTO_ITEM_SET_HIDDEN(hidden_item);
2880 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_mood, tvb, offset+2, optlen-2, TRUE);
2882 PROTO_ITEM_SET_HIDDEN(hidden_item);
2884 mood_item = proto_tree_add_string_format_value(opt_tree, hf_tcp_option_mood_val, tvb, offset+2, optlen-2, mood,"%s (%s)", mood, str_to_str(mood, mood_type, "Unknown") );
2885 tcp_info_append_str(pinfo, "Mood", mood);
2887 expert_add_info_format(pinfo, mood_item, PI_PROTOCOL, PI_NOTE, "The packet Mood is %s (%s) (RFC 5841)", mood, str_to_str(mood, mood_type, "Unknown"));
2893 PROBE_VERSION_UNSPEC = 0,
2894 PROBE_VERSION_1 = 1,
2895 PROBE_VERSION_2 = 2,
2899 /* Probe type definition. */
2907 PROBE_RESPONSE_SH = 5,
2908 PROBE_QUERY_INFO = 6,
2909 PROBE_RESPONSE_INFO = 7,
2910 PROBE_QUERY_INFO_SH = 8,
2911 PROBE_QUERY_INFO_SID = 9,
2916 static const value_string rvbd_probe_type_vs[] = {
2917 { PROBE_QUERY, "Probe Query" },
2918 { PROBE_RESPONSE, "Probe Response" },
2919 { PROBE_INTERNAL, "Probe Internal" },
2920 { PROBE_TRACE, "Probe Trace" },
2921 { PROBE_QUERY_SH, "Probe Query SH" },
2922 { PROBE_RESPONSE_SH, "Probe Response SH" },
2923 { PROBE_QUERY_INFO, "Probe Query Info" },
2924 { PROBE_RESPONSE_INFO, "Probe Response Info" },
2925 { PROBE_QUERY_INFO_SH, "Probe Query Info SH" },
2926 { PROBE_QUERY_INFO_SID, "Probe Query Info Store ID" },
2927 { PROBE_RST, "Probe Reset" },
2932 #define PROBE_OPTLEN_OFFSET 1
2934 #define PROBE_VERSION_TYPE_OFFSET 2
2935 #define PROBE_V1_RESERVED_OFFSET 3
2936 #define PROBE_V1_PROBER_OFFSET 4
2937 #define PROBE_V1_APPLI_VERSION_OFFSET 8
2938 #define PROBE_V1_PROXY_ADDR_OFFSET 8
2939 #define PROBE_V1_PROXY_PORT_OFFSET 12
2940 #define PROBE_V1_SH_CLIENT_ADDR_OFFSET 8
2941 #define PROBE_V1_SH_PROXY_ADDR_OFFSET 12
2942 #define PROBE_V1_SH_PROXY_PORT_OFFSET 16
2944 #define PROBE_V2_INFO_OFFSET 3
2946 #define PROBE_V2_INFO_CLIENT_ADDR_OFFSET 4
2947 #define PROBE_V2_INFO_STOREID_OFFSET 4
2949 #define PROBE_VERSION_MASK 0x01
2951 /* Probe Query Extra Info flags */
2952 #define RVBD_FLAGS_PROBE_LAST 0x01
2953 #define RVBD_FLAGS_PROBE_NCFE 0x04
2955 /* Probe Response Extra Info flags */
2956 #define RVBD_FLAGS_PROBE_SERVER 0x01
2957 #define RVBD_FLAGS_PROBE_SSLCERT 0x02
2958 #define RVBD_FLAGS_PROBE 0x10
2961 rvbd_probe_decode_version_type(const guint8 vt, guint8 *ver, guint8 *type)
2963 if (vt & PROBE_VERSION_MASK) {
2964 *ver = PROBE_VERSION_1;
2967 *ver = PROBE_VERSION_2;
2973 rvbd_probe_resp_add_info(proto_item *pitem, packet_info *pinfo, guint32 ip, guint16 port)
2975 proto_item_append_text(pitem, ", Server Steelhead: %s:%u", ip_to_str((guint8 *)&ip), port);
2977 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA+, ");
2981 dissect_tcpopt_rvbd_probe(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
2982 guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2985 proto_tree *field_tree;
2988 rvbd_probe_decode_version_type(
2989 tvb_get_guint8(tvb, offset + PROBE_VERSION_TYPE_OFFSET),
2992 pitem = proto_tree_add_boolean_format_value(
2993 opt_tree, hf_tcp_option_rvbd_probe, tvb, offset, optlen, 1,
2994 "%s", val_to_str(type, rvbd_probe_type_vs, "Probe Unknown"));
2996 if (type >= PROBE_TYPE_MAX)
2999 /* optlen, type, ver are common for all probes */
3000 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe);
3001 pitem = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
3002 offset + PROBE_OPTLEN_OFFSET, 1, FALSE);
3003 PROTO_ITEM_SET_HIDDEN(pitem);
3004 pitem = proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
3006 PROTO_ITEM_SET_HIDDEN(pitem);
3007 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_optlen, tvb,
3008 offset + PROBE_OPTLEN_OFFSET, 1, FALSE);
3010 if (ver == PROBE_VERSION_1) {
3014 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type1, tvb,
3015 offset + PROBE_VERSION_TYPE_OFFSET, 1, FALSE);
3016 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
3017 offset + PROBE_VERSION_TYPE_OFFSET, 1, FALSE);
3019 if (type == PROBE_INTERNAL)
3022 proto_tree_add_text(field_tree, tvb, offset + PROBE_V1_RESERVED_OFFSET,
3025 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_PROBER_OFFSET);
3026 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_prober, tvb,
3027 offset + PROBE_V1_PROBER_OFFSET, 4, FALSE);
3032 case PROBE_QUERY_SH:
3034 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_appli_ver, tvb,
3035 offset + PROBE_V1_APPLI_VERSION_OFFSET, 2,
3038 proto_item_append_text(pitem, ", CSH IP: %s", ip_to_str((guint8 *)&ip));
3040 if (check_col(pinfo->cinfo, COL_INFO)) {
3041 /* Small look-ahead hack to distinguish S+ from S+* */
3042 #define PROBE_V1_QUERY_LEN 10
3043 const guint8 qinfo_hdr[] = { 0x4c, 0x04, 0x0c };
3045 /* tvb_memeql seems to be the only API that doesn't throw
3046 an exception in case of an error */
3047 if (tvb_memeql(tvb, offset + PROBE_V1_QUERY_LEN,
3048 qinfo_hdr, sizeof(qinfo_hdr)) == 0) {
3049 not_cfe = tvb_get_guint8(tvb, offset + PROBE_V1_QUERY_LEN +
3050 sizeof(qinfo_hdr)) & RVBD_FLAGS_PROBE_NCFE;
3052 col_prepend_fstr(pinfo->cinfo, COL_INFO, "S%s, ",
3053 type == PROBE_TRACE ? "#" :
3054 not_cfe ? "+*" : "+");
3058 case PROBE_RESPONSE:
3059 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_PROXY_ADDR_OFFSET);
3060 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
3061 offset + PROBE_V1_PROXY_ADDR_OFFSET, 4, FALSE);
3063 port = tvb_get_ntohs(tvb, offset + PROBE_V1_PROXY_PORT_OFFSET);
3064 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
3065 offset + PROBE_V1_PROXY_PORT_OFFSET, 2, FALSE);
3067 rvbd_probe_resp_add_info(pitem, pinfo, ip, port);
3070 case PROBE_RESPONSE_SH:
3071 proto_tree_add_item(field_tree,
3072 hf_tcp_option_rvbd_probe_client, tvb,
3073 offset + PROBE_V1_SH_CLIENT_ADDR_OFFSET, 4,
3076 ip = tvb_get_ipv4(tvb, offset + PROBE_V1_SH_PROXY_ADDR_OFFSET);
3077 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy, tvb,
3078 offset + PROBE_V1_SH_PROXY_ADDR_OFFSET, 4, FALSE);
3080 port = tvb_get_ntohs(tvb, offset + PROBE_V1_SH_PROXY_PORT_OFFSET);
3081 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_proxy_port, tvb,
3082 offset + PROBE_V1_SH_PROXY_PORT_OFFSET, 2, FALSE);
3084 rvbd_probe_resp_add_info(pitem, pinfo, ip, port);
3088 else if (ver == PROBE_VERSION_2) {
3090 proto_item *flag_pi;
3091 proto_tree *flag_tree;
3094 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_type2, tvb,
3095 offset + PROBE_VERSION_TYPE_OFFSET, 1, FALSE);
3097 proto_tree_add_uint_format_value(
3098 field_tree, hf_tcp_option_rvbd_probe_version2, tvb,
3099 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver, "%u", ver);
3100 /* Use version1 for filtering purposes because version2 packet
3101 value is 0, but filtering is usually done for value 2 */
3102 ver_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_version1, tvb,
3103 offset + PROBE_VERSION_TYPE_OFFSET, 1, ver);
3104 PROTO_ITEM_SET_HIDDEN(ver_pi);
3108 case PROBE_QUERY_INFO:
3109 case PROBE_QUERY_INFO_SH:
3110 case PROBE_QUERY_INFO_SID:
3111 flags = tvb_get_guint8(tvb, offset + PROBE_V2_INFO_OFFSET);
3112 flag_pi = proto_tree_add_uint(field_tree, hf_tcp_option_rvbd_probe_flags,
3113 tvb, offset + PROBE_V2_INFO_OFFSET,
3116 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
3117 proto_tree_add_item(flag_tree,
3118 hf_tcp_option_rvbd_probe_flag_not_cfe,
3119 tvb, offset + PROBE_V2_INFO_OFFSET, 1, FALSE);
3120 proto_tree_add_item(flag_tree,
3121 hf_tcp_option_rvbd_probe_flag_last_notify,
3122 tvb, offset + PROBE_V2_INFO_OFFSET, 1, FALSE);
3124 if (type == PROBE_QUERY_INFO_SH)
3125 proto_tree_add_item(flag_tree,
3126 hf_tcp_option_rvbd_probe_client, tvb,
3127 offset + PROBE_V2_INFO_CLIENT_ADDR_OFFSET,
3129 else if (type == PROBE_QUERY_INFO_SID)
3130 proto_tree_add_item(flag_tree,
3131 hf_tcp_option_rvbd_probe_storeid, tvb,
3132 offset + PROBE_V2_INFO_STOREID_OFFSET,
3135 if (type != PROBE_QUERY_INFO_SID &&
3136 check_col(pinfo->cinfo, COL_INFO) &&
3137 (tvb_get_guint8(tvb, 13) & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK) &&
3138 (flags & RVBD_FLAGS_PROBE_LAST)) {
3139 col_prepend_fstr(pinfo->cinfo, COL_INFO, "SA++, ");
3144 case PROBE_RESPONSE_INFO:
3145 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
3146 tvb, offset + PROBE_V2_INFO_OFFSET,
3149 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_probe_flags);
3150 proto_tree_add_item(flag_tree,
3151 hf_tcp_option_rvbd_probe_flag_probe_cache,
3152 tvb, offset + PROBE_V2_INFO_OFFSET, 1, FALSE);
3153 proto_tree_add_item(flag_tree,
3154 hf_tcp_option_rvbd_probe_flag_sslcert,
3155 tvb, offset + PROBE_V2_INFO_OFFSET, 1, FALSE);
3156 proto_tree_add_item(flag_tree,
3157 hf_tcp_option_rvbd_probe_flag_server_connected,
3158 tvb, offset + PROBE_V2_INFO_OFFSET, 1, FALSE);
3162 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_flags,
3163 tvb, offset + PROBE_V2_INFO_OFFSET,
3171 TRPY_OPTNUM_OFFSET = 0,
3172 TRPY_OPTLEN_OFFSET = 1,
3174 TRPY_OPTIONS_OFFSET = 2,
3175 TRPY_SRC_ADDR_OFFSET = 4,
3176 TRPY_DST_ADDR_OFFSET = 8,
3177 TRPY_SRC_PORT_OFFSET = 12,
3178 TRPY_DST_PORT_OFFSET = 14,
3179 TRPY_CLIENT_PORT_OFFSET = 16,
3183 #define RVBD_FLAGS_TRPY_MODE 0x0001
3184 #define RVBD_FLAGS_TRPY_OOB 0x0002
3185 #define RVBD_FLAGS_TRPY_CHKSUM 0x0004
3186 #define RVBD_FLAGS_TRPY_FW_RST 0x0100
3187 #define RVBD_FLAGS_TRPY_FW_RST_INNER 0x0200
3188 #define RVBD_FLAGS_TRPY_FW_RST_PROBE 0x0400
3190 static const true_false_string trpy_mode_str = {
3191 "Port Transparency",
3196 dissect_tcpopt_rvbd_trpy(const ip_tcp_opt *optp _U_, tvbuff_t *tvb,
3197 int offset, guint optlen, packet_info *pinfo,
3198 proto_tree *opt_tree)
3200 proto_tree *field_tree;
3201 proto_tree *flag_tree;
3203 proto_item *flag_pi;
3205 guint16 sport, dport, flags;
3206 static dissector_handle_t sport_handle = NULL;
3208 col_prepend_fstr(pinfo->cinfo, COL_INFO, "TRPY, ");
3210 pitem = proto_tree_add_boolean_format_value(
3211 opt_tree, hf_tcp_option_rvbd_trpy, tvb, offset, optlen, 1,
3214 field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_trpy);
3215 pitem = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb,
3216 offset + PROBE_OPTLEN_OFFSET, 1, FALSE);
3217 PROTO_ITEM_SET_HIDDEN(pitem);
3218 pitem = proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb,
3220 PROTO_ITEM_SET_HIDDEN(pitem);
3221 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_probe_optlen, tvb,
3222 offset + PROBE_OPTLEN_OFFSET, 1, FALSE);
3224 flags = tvb_get_ntohs(tvb, offset + TRPY_OPTIONS_OFFSET);
3225 flag_pi = proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_flags,
3226 tvb, offset + TRPY_OPTIONS_OFFSET,
3229 flag_tree = proto_item_add_subtree(flag_pi, ett_tcp_opt_rvbd_trpy_flags);
3230 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
3231 tvb, offset + TRPY_OPTIONS_OFFSET, 2, FALSE);
3232 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
3233 tvb, offset + TRPY_OPTIONS_OFFSET, 2, FALSE);
3234 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_fw_rst,
3235 tvb, offset + TRPY_OPTIONS_OFFSET, 2, FALSE);
3236 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_chksum,
3237 tvb, offset + TRPY_OPTIONS_OFFSET, 2, FALSE);
3238 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_oob,
3239 tvb, offset + TRPY_OPTIONS_OFFSET, 2, FALSE);
3240 proto_tree_add_item(flag_tree, hf_tcp_option_rvbd_trpy_flag_mode,
3241 tvb, offset + TRPY_OPTIONS_OFFSET, 2, FALSE);
3243 src = tvb_get_ipv4(tvb, offset + TRPY_SRC_ADDR_OFFSET);
3244 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src,
3245 tvb, offset + TRPY_SRC_ADDR_OFFSET, 4, FALSE);
3247 dst = tvb_get_ipv4(tvb, offset + TRPY_DST_ADDR_OFFSET);
3248 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst,
3249 tvb, offset + TRPY_DST_ADDR_OFFSET, 4, FALSE);
3251 sport = tvb_get_ntohs(tvb, offset + TRPY_SRC_PORT_OFFSET);
3252 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_src_port,
3253 tvb, offset + TRPY_SRC_PORT_OFFSET, 2, FALSE);
3255 dport = tvb_get_ntohs(tvb, offset + TRPY_DST_PORT_OFFSET);
3256 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_dst_port,
3257 tvb, offset + TRPY_DST_PORT_OFFSET, 2, FALSE);
3259 proto_item_append_text(pitem, "%s:%u -> %s:%u",
3260 ip_to_str((guint8 *)&src), sport,
3261 ip_to_str((guint8 *)&dst), dport);
3263 /* Client port only set on SYN: optlen == 18 */
3264 if ((flags & RVBD_FLAGS_TRPY_OOB) && (optlen > TCPOLEN_RVBD_TRPY_MIN))
3265 proto_tree_add_item(field_tree, hf_tcp_option_rvbd_trpy_client_port,
3266 tvb, offset + TRPY_CLIENT_PORT_OFFSET, 2, FALSE);
3268 /* We need to map this TCP session on our own dissector instead of what
3269 Wireshark thinks runs on these ports */
3270 if (sport_handle == NULL) {
3271 sport_handle = find_dissector("sport");
3273 if (sport_handle != NULL) {
3274 conversation_t *conversation;
3275 conversation = find_conversation(pinfo->fd->num,
3276 &pinfo->src, &pinfo->dst, pinfo->ptype,
3277 pinfo->srcport, pinfo->destport, 0);
3278 if (conversation == NULL) {
3279 conversation = conversation_new(pinfo->fd->num,
3280 &pinfo->src, &pinfo->dst, pinfo->ptype,
3281 pinfo->srcport, pinfo->destport, 0);
3283 if (conversation->dissector_handle != sport_handle) {
3284 conversation_set_dissector(conversation, sport_handle);
3289 static const ip_tcp_opt tcpopts[] = {
3292 "End of Option List (EOL)",
3300 "No-Operation (NOP)",
3308 "Maximum segment size",
3320 dissect_tcpopt_wscale
3328 dissect_tcpopt_sack_perm,
3333 &ett_tcp_option_sack,
3360 dissect_tcpopt_timestamp
3388 "TCP MD5 signature",
3396 "SCPS capabilities",
3397 &ett_tcp_option_scps,
3404 "Selective Negative Acknowledgement",
3408 dissect_tcpopt_snack
3412 "SCPS record boundary",
3420 "SCPS corruption experienced",
3445 &ett_tcp_option_user_to,
3448 dissect_tcpopt_user_to
3455 TCPOLEN_RVBD_PROBE_MIN,
3456 dissect_tcpopt_rvbd_probe
3460 "Riverbed Transparency",
3463 TCPOLEN_RVBD_TRPY_MIN,
3464 dissect_tcpopt_rvbd_trpy
3484 #define N_TCP_OPTS array_length(tcpopts)
3486 /* Determine if there is a sub-dissector and call it; return TRUE
3487 if there was a sub-dissector, FALSE otherwise.
3489 This has been separated into a stand alone routine to other protocol
3490 dissectors can call to it, e.g., SOCKS. */
3492 static gboolean try_heuristic_first = FALSE;
3495 /* this function can be called with tcpd==NULL as from the msproxy dissector */
3497 decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
3498 proto_tree *tree, int src_port, int dst_port,
3499 struct tcp_analysis *tcpd)
3502 int low_port, high_port;
3503 int save_desegment_offset;
3504 guint32 save_desegment_len;
3506 /* Don't call subdissectors for keepalives. Even though they do contain
3507 * payload "data", it's just garbage. Display any data the keepalive
3508 * packet might contain though.
3510 if(tcpd && tcpd->ta){
3511 if(tcpd->ta->flags&TCP_A_KEEP_ALIVE){
3512 next_tvb = tvb_new_subset_remaining(tvb, offset);
3513 call_dissector(data_handle, next_tvb, pinfo, tree);
3518 next_tvb = tvb_new_subset_remaining(tvb, offset);
3520 /* determine if this packet is part of a conversation and call dissector */
3521 /* for the conversation if available */
3523 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP,
3524 src_port, dst_port, next_tvb, pinfo, tree)){
3525 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3529 if (try_heuristic_first) {
3530 /* do lookup with the heuristic subdissector table */
3531 save_desegment_offset = pinfo->desegment_offset;
3532 save_desegment_len = pinfo->desegment_len;
3533 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
3534 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3538 * They rejected the packet; make sure they didn't also request
3539 * desegmentation (we could just override the request, but
3540 * rejecting a packet *and* requesting desegmentation is a sign
3541 * of the dissector's code needing clearer thought, so we fail
3542 * so that the problem is made more obvious).
3544 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
3545 save_desegment_len == pinfo->desegment_len);
3548 /* Do lookups with the subdissector table.
3549 We try the port number with the lower value first, followed by the
3550 port number with the higher value. This means that, for packets
3551 where a dissector is registered for *both* port numbers:
3553 1) we pick the same dissector for traffic going in both directions;
3555 2) we prefer the port number that's more likely to be the right
3556 one (as that prefers well-known ports to reserved ports);
3558 although there is, of course, no guarantee that any such strategy
3559 will always pick the right port number.
3561 XXX - we ignore port numbers of 0, as some dissectors use a port
3562 number of 0 to disable the port. */
3563 if (src_port > dst_port) {
3564 low_port = dst_port;
3565 high_port = src_port;
3567 low_port = src_port;
3568 high_port = dst_port;
3570 if (low_port != 0 &&
3571 dissector_try_uint(subdissector_table, low_port, next_tvb, pinfo, tree)){
3572 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3575 if (high_port != 0 &&
3576 dissector_try_uint(subdissector_table, high_port, next_tvb, pinfo, tree)){
3577 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3581 if (!try_heuristic_first) {
3582 /* do lookup with the heuristic subdissector table */
3583 save_desegment_offset = pinfo->desegment_offset;
3584 save_desegment_len = pinfo->desegment_len;
3585 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
3586 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3590 * They rejected the packet; make sure they didn't also request
3591 * desegmentation (we could just override the request, but
3592 * rejecting a packet *and* requesting desegmentation is a sign
3593 * of the dissector's code needing clearer thought, so we fail
3594 * so that the problem is made more obvious).
3596 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
3597 save_desegment_len == pinfo->desegment_len);
3600 /* Oh, well, we don't know this; dissect it as data. */
3601 call_dissector(data_handle,next_tvb, pinfo, tree);
3603 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
3608 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
3609 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
3610 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
3611 struct tcp_analysis *tcpd)
3613 pinfo->want_pdu_tracking=0;
3617 /*qqq see if it is an unaligned PDU */
3618 if(tcpd && tcp_analyze_seq && (!tcp_desegment)){
3620 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
3621 seq, nxtseq, tcpd->fwd->multisegment_pdus);
3625 /* if offset is -1 this means that this segment is known
3626 * to be fully inside a previously detected pdu
3627 * so we dont even need to try to dissect it either.
3630 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
3633 * We succeeded in handing off to a subdissector.
3635 * Is this a TCP segment or a reassembled chunk of
3639 /* if !visited, check want_pdu_tracking and
3640 store it in table */
3641 if(tcpd && (!pinfo->fd->flags.visited) &&
3642 tcp_analyze_seq && pinfo->want_pdu_tracking){
3644 pdu_store_sequencenumber_of_next_pdu(
3647 nxtseq+pinfo->bytes_until_next_pdu,
3648 tcpd->fwd->multisegment_pdus);
3655 /* We got an exception. At this point the dissection is
3656 * completely aborted and execution will be transfered back
3657 * to (probably) the frame dissector.
3658 * Here we have to place whatever we want the dissector
3659 * to do before aborting the tcp dissection.
3662 * Is this a TCP segment or a reassembled chunk of TCP
3667 * It's from a TCP segment.
3669 * if !visited, check want_pdu_tracking and store it
3672 if(tcpd && (!pinfo->fd->flags.visited) && tcp_analyze_seq && pinfo->want_pdu_tracking){
3674 pdu_store_sequencenumber_of_next_pdu(pinfo,
3676 nxtseq+pinfo->bytes_until_next_pdu,
3677 tcpd->fwd->multisegment_pdus);
3687 dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,
3688 guint32 nxtseq, guint32 sport, guint32 dport,
3689 proto_tree *tree, proto_tree *tcp_tree,
3690 struct tcp_analysis *tcpd)
3692 gboolean save_fragmented;
3694 /* Can we desegment this segment? */
3695 if (pinfo->can_desegment) {
3697 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
3700 /* No - just call the subdissector.
3701 Mark this as fragmented, so if somebody throws an exception,
3702 we don't report it as a malformed frame. */
3703 save_fragmented = pinfo->fragmented;
3704 pinfo->fragmented = TRUE;
3705 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
3706 seq, nxtseq, TRUE, tcpd);
3707 pinfo->fragmented = save_fragmented;
3712 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3714 guint8 th_off_x2; /* combines th_off and th_x2 */
3718 proto_tree *tcp_tree = NULL, *field_tree = NULL;
3719 proto_item *ti = NULL, *tf, *hidden_item;
3721 emem_strbuf_t *flags_strbuf = ep_strbuf_new_label("<None>");
3722 const gchar *flags[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR", "NS"};
3730 guint16 computed_cksum;
3731 guint16 real_window;
3732 guint length_remaining;
3733 gboolean desegment_ok;
3734 struct tcpinfo tcpinfo;
3735 struct tcpheader *tcph;
3736 proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL, *scaled_pi;
3737 conversation_t *conv=NULL;
3738 struct tcp_analysis *tcpd=NULL;
3739 struct tcp_per_packet_data_t *tcppd=NULL;
3741 proto_tree *checksum_tree;
3743 tcph=ep_alloc(sizeof(struct tcpheader));
3744 SET_ADDRESS(&tcph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
3745 SET_ADDRESS(&tcph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
3747 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
3749 /* Clear out the Info column. */
3750 col_clear(pinfo->cinfo, COL_INFO);
3752 tcph->th_sport = tvb_get_ntohs(tvb, offset);
3753 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
3754 col_append_fstr(pinfo->cinfo, COL_INFO, "%s > %s",
3755 get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
3757 if (tcp_summary_in_tree) {
3758 ti = proto_tree_add_protocol_format(tree, proto_tcp, tvb, 0, -1,
3759 "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
3760 get_tcp_port(tcph->th_sport), tcph->th_sport,
3761 get_tcp_port(tcph->th_dport), tcph->th_dport);
3764 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, FALSE);
3766 tcp_tree = proto_item_add_subtree(ti, ett_tcp);
3767 pinfo->tcp_tree=tcp_tree;
3769 proto_tree_add_uint_format(tcp_tree, hf_tcp_srcport, tvb, offset, 2, tcph->th_sport,
3770 "Source port: %s (%u)", get_tcp_port(tcph->th_sport), tcph->th_sport);
3771 proto_tree_add_uint_format(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, tcph->th_dport,
3772 "Destination port: %s (%u)", get_tcp_port(tcph->th_dport), tcph->th_dport);
3773 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset, 2, tcph->th_sport);
3774 PROTO_ITEM_SET_HIDDEN(hidden_item);
3775 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, tcph->th_dport);
3776 PROTO_ITEM_SET_HIDDEN(hidden_item);
3778 /* If we're dissecting the headers of a TCP packet in an ICMP packet
3779 * then go ahead and put the sequence numbers in the tree now (because
3780 * they won't be put in later because the ICMP packet only contains up
3781 * to the sequence number).
3782 * We should only need to do this for IPv4 since IPv6 will hopefully
3783 * carry enough TCP payload for this dissector to put the sequence
3784 * numbers in via the regular code path.
3786 if (pinfo->layer_names != NULL && pinfo->layer_names->str != NULL) {
3787 /* use strstr because g_strrstr is only present in glib2.0 and
3788 * g_str_has_suffix in glib2.2
3790 if (strstr(pinfo->layer_names->str, "icmp:ip") != NULL)
3791 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, FALSE);
3795 /* Set the source and destination port numbers as soon as we get them,
3796 so that they're available to the "Follow TCP Stream" code even if
3797 we throw an exception dissecting the rest of the TCP header. */
3798 pinfo->ptype = PT_TCP;
3799 pinfo->srcport = tcph->th_sport;
3800 pinfo->destport = tcph->th_dport;
3802 tcph->th_seq = tvb_get_ntohl(tvb, offset + 4);
3803 tcph->th_ack = tvb_get_ntohl(tvb, offset + 8);
3804 th_off_x2 = tvb_get_guint8(tvb, offset + 12);
3805 tcph->th_flags = tvb_get_ntohs(tvb, offset + 12) & 0x0FFF;
3806 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
3807 real_window = tcph->th_win;
3808 tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
3810 /* find(or create if needed) the conversation for this tcp session */
3811 conv=find_or_create_conversation(pinfo);
3812 tcpd=get_tcp_conversation_data(conv,pinfo);
3814 /* If this is a SYN packet, then check if it's seq-nr is different
3815 * from the base_seq of the retrieved conversation. If this is the
3816 * case, create a new conversation with the same addresses and ports
3817 * and set the TA_PORTS_REUSED flag. If the seq-nr is the same as
3818 * the base_seq, then do nothing so it will be marked as a retrans-
3821 if(tcpd && ((tcph->th_flags&(TH_SYN|TH_ACK))==TH_SYN) &&
3822 (tcpd->fwd->base_seq!=0) &&
3823 (tcph->th_seq!=tcpd->fwd->base_seq) ) {
3824 if (!(pinfo->fd->flags.visited)) {
3825 conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3826 tcpd=get_tcp_conversation_data(conv,pinfo);
3829 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
3830 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
3834 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, tcpd->stream);
3835 PROTO_ITEM_SET_GENERATED(item);
3838 /* Do we need to calculate timestamps relative to the tcp-stream? */
3839 if (tcp_calculate_ts) {
3840 tcppd = p_get_proto_data(pinfo->fd, proto_tcp);
3843 * Calculate the timestamps relative to this conversation (but only on the
3844 * first run when frames are accessed sequentially)
3846 if (!(pinfo->fd->flags.visited))
3847 tcp_calculate_timestamps(pinfo, tcpd, tcppd);
3851 * If we've been handed an IP fragment, we don't know how big the TCP
3852 * segment is, so don't do anything that requires that we know that.
3854 * The same applies if we're part of an error packet. (XXX - if the
3855 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
3856 * header says it is" length in the tvbuff, we could use that; such
3857 * a length might also be useful for handling packets where the IP
3858 * length is bigger than the actual data available in the frame; the
3859 * dissectors should trust that length, and then throw a
3860 * ReportedBoundsError exception when they go past the end of the frame.)
3862 * We also can't determine the segment length if the reported length
3863 * of the TCP packet is less than the TCP header length.
3865 reported_len = tvb_reported_length(tvb);
3867 if (!pinfo->fragmented && !pinfo->in_error_pkt) {
3868 if (reported_len < tcph->th_hlen) {
3870 pi = proto_tree_add_text(tcp_tree, tvb, offset, 0,
3871 "Short segment. Segment/fragment does not contain a full TCP header"
3872 " (might be NMAP or someone else deliberately sending unusual packets)");
3873 PROTO_ITEM_SET_GENERATED(pi);
3874 expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_WARN, "Short segment");
3875 tcph->th_have_seglen = FALSE;
3877 /* Compute the length of data in this segment. */
3878 tcph->th_seglen = reported_len - tcph->th_hlen;
3879 tcph->th_have_seglen = TRUE;
3881 if (tree) { /* Add the seglen as an invisible field */
3883 hidden_item = proto_tree_add_uint(ti, hf_tcp_len, tvb, offset+12, 1, tcph->th_seglen);
3884 PROTO_ITEM_SET_HIDDEN(hidden_item);
3889 /* handle TCP seq# analysis parse all new segments we see */
3890 if(tcp_analyze_seq){
3891 if(!(pinfo->fd->flags.visited)){
3892 tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd);
3894 if(tcpd && tcp_relative_seq) {
3895 (tcph->th_seq) -= tcpd->fwd->base_seq;
3896 (tcph->th_ack) -= tcpd->rev->base_seq;
3900 /* re-calculate window size, based on scaling factor */
3901 if (!(tcph->th_flags&TH_SYN)) { /* SYNs are never scaled */
3902 if (tcpd && (tcpd->fwd->win_scale>=0)) {
3903 (tcph->th_win)<<=tcpd->fwd->win_scale;
3907 /* Compute the sequence number of next octet after this segment. */
3908 nxtseq = tcph->th_seq + tcph->th_seglen;
3911 tcph->th_have_seglen = FALSE;
3913 if (check_col(pinfo->cinfo, COL_INFO) || tree) {
3914 gboolean first_flag = TRUE;
3915 for (i = 0; i < 9; i++) {
3917 if (tcph->th_flags & bpos) {
3919 ep_strbuf_truncate(flags_strbuf, 0);
3921 ep_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ", flags[i]);
3925 if (tcph->th_flags & 0x0E00) {
3927 ep_strbuf_truncate(flags_strbuf, 0);
3929 ep_strbuf_append_printf(flags_strbuf, "%sReserved", first_flag ? "" : ", ");
3933 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] Seq=%u", flags_strbuf->str, tcph->th_seq);
3934 if (tcph->th_flags&TH_ACK) {
3935 col_append_fstr(pinfo->cinfo, COL_INFO, " Ack=%u", tcph->th_ack);
3937 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", tcph->th_win);
3940 if (tcp_summary_in_tree) {
3941 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
3943 if(tcp_relative_seq){
3944 proto_tree_add_uint_format(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq, "Sequence number: %u (relative sequence number)", tcph->th_seq);
3946 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
3950 if (tcph->th_hlen < TCPH_MIN_LEN) {
3951 /* Give up at this point; we put the source and destination port in
3952 the tree, before fetching the header length, so that they'll
3953 show up if this is in the failing packet in an ICMP error packet,
3954 but it's now time to give up if the header length is bogus. */
3955 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
3956 tcph->th_hlen, TCPH_MIN_LEN);
3958 proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
3959 "Header length: %u bytes (bogus, must be at least %u)", tcph->th_hlen,
3966 if (tcp_summary_in_tree) {
3967 if(tcph->th_flags&TH_ACK){
3968 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
3970 if (tcph->th_have_seglen)
3971 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
3973 proto_item_set_len(ti, tcph->th_hlen);
3974 if (tcph->th_have_seglen) {
3975 if (nxtseq != tcph->th_seq) {
3976 if(tcp_relative_seq){
3977 tf=proto_tree_add_uint_format(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "Next sequence number: %u (relative sequence number)", nxtseq);
3979 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
3981 PROTO_ITEM_SET_GENERATED(tf);
3986 if (tcph->th_flags & TH_ACK) {
3988 if (tcp_relative_seq){
3989 proto_tree_add_uint_format(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack, "Acknowledgement number: %u (relative ack number)", tcph->th_ack);
3991 proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
3995 /* Verify that the ACK field is zero */
3996 ack = tvb_get_ntohl(tvb, offset+8);
3998 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, ack,
3999 "Acknowledgement Number: 0x%08x [should be 0x00000000 because ACK flag is not set]",
4001 expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN,
4002 "Acknowledgement number: Broken TCP. The acknowledge field is nonzero while the ACK flag is not set");
4007 proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
4008 "Header length: %u bytes", tcph->th_hlen);
4009 tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 12, 2,
4010 tcph->th_flags, "Flags: 0x%03x (%s)", tcph->th_flags, flags_strbuf->str);
4011 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
4012 proto_tree_add_boolean(field_tree, hf_tcp_flags_res, tvb, offset + 12, 1, tcph->th_flags);
4013 proto_tree_add_boolean(field_tree, hf_tcp_flags_ns, tvb, offset + 12, 1, tcph->th_flags);
4014 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
4015 proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, tvb, offset + 13, 1, tcph->th_flags);
4016 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
4017 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
4018 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
4019 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
4020 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
4021 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
4023 /* As discussed in bug 5541, it is better to use two separate
4024 * fields for the real and calculated window size.
4026 proto_tree_add_uint(tcp_tree, hf_tcp_window_size_value, tvb, offset + 14, 2, real_window);
4027 scaled_pi = proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win);
4028 PROTO_ITEM_SET_GENERATED(scaled_pi);
4030 if( !(tcph->th_flags&TH_SYN) && tcpd ) {
4031 switch (tcpd->fwd->win_scale) {
4034 scaled_pi = proto_tree_add_int_format(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2, tcpd->fwd->win_scale, "Window size scaling factor: %d (unknown)", tcpd->fwd->win_scale);
4035 PROTO_ITEM_SET_GENERATED(scaled_pi);
4039 scaled_pi = proto_tree_add_int_format(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2, tcpd->fwd->win_scale, "Window size scaling factor: %d (no window scaling used)", tcpd->fwd->win_scale);
4040 PROTO_ITEM_SET_GENERATED(scaled_pi);
4044 scaled_pi = proto_tree_add_int_format(tcp_tree, hf_tcp_window_size_scalefactor, tvb, offset + 14, 2, 1<<tcpd->fwd->win_scale, "Window size scaling factor: %d", 1<<tcpd->fwd->win_scale);
4045 PROTO_ITEM_SET_GENERATED(scaled_pi);
4050 if(tcph->th_flags & TH_SYN) {
4051 if(tcph->th_flags & TH_ACK)
4052 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK): server port %s",
4053 get_tcp_port(tcph->th_sport));
4055 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN): server port %s",
4056 get_tcp_port(tcph->th_dport));
4058 if(tcph->th_flags & TH_FIN)
4059 /* XXX - find a way to know the server port and output only that one */
4060 expert_add_info_format(pinfo, tf_fin, PI_SEQUENCE, PI_CHAT, "Connection finish (FIN)");
4061 if(tcph->th_flags & TH_RST)
4062 /* XXX - find a way to know the server port and output only that one */
4063 expert_add_info_format(pinfo, tf_rst, PI_SEQUENCE, PI_CHAT, "Connection reset (RST)");
4065 /* Supply the sequence number of the first byte and of the first byte
4066 after the segment. */
4067 tcpinfo.seq = tcph->th_seq;
4068 tcpinfo.nxtseq = nxtseq;
4069 tcpinfo.lastackseq = tcph->th_ack;
4071 /* Assume we'll pass un-reassembled data to subdissectors. */
4072 tcpinfo.is_reassembled = FALSE;
4074 pinfo->private_data = &tcpinfo;
4077 * Assume, initially, that we can't desegment.
4079 pinfo->can_desegment = 0;
4080 th_sum = tvb_get_ntohs(tvb, offset + 16);
4081 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
4082 /* The packet isn't part of an un-reassembled fragmented datagram
4083 and isn't truncated. This means we have all the data, and thus
4084 can checksum it and, unless it's being returned in an error
4085 packet, are willing to allow subdissectors to request reassembly
4088 if (tcp_check_checksum) {
4089 /* We haven't turned checksum checking off; checksum it. */
4091 /* Set up the fields of the pseudo-header. */
4092 cksum_vec[0].ptr = pinfo->src.data;
4093 cksum_vec[0].len = pinfo->src.len;
4094 cksum_vec[1].ptr = pinfo->dst.data;
4095 cksum_vec[1].len = pinfo->dst.len;
4096 cksum_vec[2].ptr = (const guint8 *)phdr;
4097 switch (pinfo->src.type) {
4100 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
4101 cksum_vec[2].len = 4;
4105 phdr[0] = g_htonl(reported_len);
4106 phdr[1] = g_htonl(IP_PROTO_TCP);
4107 cksum_vec[2].len = 8;
4111 /* TCP runs only atop IPv4 and IPv6.... */
4112 DISSECTOR_ASSERT_NOT_REACHED();
4115 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, reported_len);
4116 cksum_vec[3].len = reported_len;
4117 computed_cksum = in_cksum(cksum_vec, 4);
4118 if (computed_cksum == 0 && th_sum == 0xffff) {
4119 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
4120 offset + 16, 2, th_sum,
4121 "Checksum: 0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);
4123 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4124 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4125 offset + 16, 2, FALSE);
4126 PROTO_ITEM_SET_GENERATED(item);
4127 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4128 offset + 16, 2, FALSE);
4129 PROTO_ITEM_SET_GENERATED(item);
4130 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_WARN, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)");
4132 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");
4134 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
4135 desegment_ok = TRUE;
4136 } else if (computed_cksum == 0) {
4137 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
4138 offset + 16, 2, th_sum, "Checksum: 0x%04x [correct]", th_sum);
4140 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4141 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4142 offset + 16, 2, TRUE);
4143 PROTO_ITEM_SET_GENERATED(item);
4144 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4145 offset + 16, 2, FALSE);
4146 PROTO_ITEM_SET_GENERATED(item);
4148 /* Checksum is valid, so we're willing to desegment it. */
4149 desegment_ok = TRUE;
4150 } else if (th_sum == 0) {
4151 /* checksum is probably fine but checksum offload is used */
4152 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
4153 offset + 16, 2, th_sum, "Checksum: 0x%04x [Checksum Offloaded]", th_sum);
4155 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4156 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4157 offset + 16, 2, FALSE);
4158 PROTO_ITEM_SET_GENERATED(item);
4159 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4160 offset + 16, 2, FALSE);
4161 PROTO_ITEM_SET_GENERATED(item);
4163 /* Checksum is (probably) valid, so we're willing to desegment it. */
4164 desegment_ok = TRUE;
4166 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
4167 offset + 16, 2, th_sum,
4168 "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]", th_sum,
4169 in_cksum_shouldbe(th_sum, computed_cksum));
4171 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4172 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4173 offset + 16, 2, FALSE);
4174 PROTO_ITEM_SET_GENERATED(item);
4175 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4176 offset + 16, 2, TRUE);
4177 PROTO_ITEM_SET_GENERATED(item);
4178 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
4180 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");
4182 /* Checksum is invalid, so we're not willing to desegment it. */
4183 desegment_ok = FALSE;
4184 pinfo->noreassembly_reason = " [incorrect TCP checksum]";
4187 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
4188 offset + 16, 2, th_sum, "Checksum: 0x%04x [validation disabled]", th_sum);
4190 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4191 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4192 offset + 16, 2, FALSE);
4193 PROTO_ITEM_SET_GENERATED(item);
4194 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4195 offset + 16, 2, FALSE);
4196 PROTO_ITEM_SET_GENERATED(item);
4198 /* We didn't check the checksum, and don't care if it's valid,
4199 so we're willing to desegment it. */
4200 desegment_ok = TRUE;
4203 /* We don't have all the packet data, so we can't checksum it... */
4204 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
4205 offset + 16, 2, th_sum, "Checksum: 0x%04x [unchecked, not all data available]", th_sum);
4207 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
4208 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
4209 offset + 16, 2, FALSE);
4210 PROTO_ITEM_SET_GENERATED(item);
4211 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
4212 offset + 16, 2, FALSE);
4213 PROTO_ITEM_SET_GENERATED(item);
4215 /* ...and aren't willing to desegment it. */
4216 desegment_ok = FALSE;
4220 /* We're willing to desegment this. Is desegmentation enabled? */
4221 if (tcp_desegment) {
4222 /* Yes - is this segment being returned in an error packet? */
4223 if (!pinfo->in_error_pkt) {
4224 /* No - indicate that we will desegment.
4225 We do NOT want to desegment segments returned in error
4226 packets, as they're not part of a TCP connection. */
4227 pinfo->can_desegment = 2;
4232 th_urp = tvb_get_ntohs(tvb, offset + 18);
4233 if (tcph->th_flags & TH_URG) {
4234 /* Export the urgent pointer, for the benefit of protocols such as
4236 tcpinfo.urgent = TRUE;
4237 tcpinfo.urgent_pointer = th_urp;
4238 col_append_fstr(pinfo->cinfo, COL_INFO, " Urg=%u", th_urp);
4239 if (tcp_tree != NULL)
4240 proto_tree_add_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, th_urp);
4242 tcpinfo.urgent = FALSE;
4244 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, th_urp,
4245 "Urgent Pointer: 0x%04x [should be 0x0000 because URG flag is not set]",
4247 expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN,
4248 "Urgent Pointer: Broken TCP. The urgent pointer field is nonzero while the URG flag is not set");
4253 if (tcph->th_have_seglen) {
4254 col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", tcph->th_seglen);
4257 /* Decode TCP options, if any. */
4258 if (tcph->th_hlen > TCPH_MIN_LEN) {
4259 /* There's more than just the fixed-length header. Decode the
4261 optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
4262 tvb_ensure_bytes_exist(tvb, offset + 20, optlen);
4263 if (tcp_tree != NULL) {
4264 guint8 *p_options = ep_tvb_memdup(tvb, offset + 20, optlen);
4265 tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
4266 optlen, p_options, "Options: (%u bytes)", optlen);
4267 field_tree = proto_item_add_subtree(tf, ett_tcp_options);
4272 dissect_ip_tcp_options(tvb, offset + 20, optlen,
4273 tcpopts, N_TCP_OPTS, TCPOPT_EOL, pinfo, field_tree, tf);
4276 if(!pinfo->fd->flags.visited){
4277 if((tcph->th_flags & TH_SYN)==TH_SYN) {
4278 /* Check the validity of the window scale value
4280 verify_tcp_window_scaling((tcph->th_flags&TH_ACK)==TH_ACK,tcpd);
4283 if((tcph->th_flags & (TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
4284 /* If the SYN or the SYN+ACK offered SCPS capabilities,
4285 * validate the flow's bidirectional scps capabilities.
4286 * The or protects against broken implementations offering
4287 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
4289 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {
4290 if (tcpd->flow1.scps_capable && tcpd->flow2.scps_capable) {
4291 expert_add_info_format(pinfo, 0, PI_SEQUENCE, PI_NOTE,
4292 "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated");
4298 /* Skip over header + options */
4299 offset += tcph->th_hlen;
4301 /* Check the packet length to see if there's more data
4302 (it could be an ACK-only packet) */
4303 length_remaining = tvb_length_remaining(tvb, offset);
4305 if (tcph->th_have_seglen) {
4306 if( data_out_file ) {
4307 reassemble_tcp( tcpd->stream, /* tcp stream index */
4308 tcph->th_seq, /* sequence number */
4309 tcph->th_ack, /* acknowledgement number */
4310 tcph->th_seglen, /* data length */
4311 (gchar*)tvb_get_ptr(tvb, offset, length_remaining), /* data */
4312 length_remaining, /* captured data length */
4313 ( tcph->th_flags & TH_SYN ), /* is syn set? */
4321 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
4322 if(tcp_analyze_seq){
4323 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd);
4326 /* handle conversation timestamps */
4327 if(tcp_calculate_ts){
4328 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
4331 tap_queue_packet(tcp_tap, pinfo, tcph);
4334 /* A FIN packet might complete reassembly so we need to explicitly
4335 * check for this here.
4337 if(tcph->th_have_seglen && tcpd && (tcph->th_flags & TH_FIN)
4338 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ){
4339 struct tcp_multisegment_pdu *msp;
4341 /* find the most previous PDU starting before this sequence number */
4342 msp=se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq-1);
4344 fragment_data *ipfd_head;
4346 ipfd_head = fragment_add(tvb, offset, pinfo, msp->first_frame,
4348 tcph->th_seq - msp->seq,
4354 /* create a new TVB structure for desegmented data
4355 * datalen-1 to strip the dummy FIN byte off
4357 next_tvb = tvb_new_child_real_data(tvb, ipfd_head->data, ipfd_head->datalen, ipfd_head->datalen);
4359 /* add desegmented data to the data source list */
4360 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
4362 /* call the payload dissector
4363 * but make sure we don't offer desegmentation any more
4365 pinfo->can_desegment = 0;
4367 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq, nxtseq, FALSE, tcpd);
4369 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
4376 if (tcpd && ((tcpd->fwd && tcpd->fwd->command) || (tcpd->rev && tcpd->rev->command))) {
4377 ti = proto_tree_add_text(tcp_tree, tvb, offset, 0, "Process Information");
4378 PROTO_ITEM_SET_GENERATED(ti);
4379 field_tree = proto_item_add_subtree(ti, ett_tcp_process_info);
4380 if (tcpd->fwd && tcpd->fwd->command) {
4381 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_dst_uid, tvb, 0, 0,
4382 tcpd->fwd->process_uid, "%u", tcpd->fwd->process_uid);
4383 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_dst_pid, tvb, 0, 0,
4384 tcpd->fwd->process_pid, "%u", tcpd->fwd->process_pid);
4385 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_dst_uname, tvb, 0, 0,
4386 tcpd->fwd->username, "%s", tcpd->fwd->username);
4387 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_dst_cmd, tvb, 0, 0,
4388 tcpd->fwd->command, "%s", tcpd->fwd->command);
4390 if (tcpd->rev && tcpd->rev->command) {
4391 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_src_uid, tvb, 0, 0,
4392 tcpd->rev->process_uid, "%u", tcpd->rev->process_uid);
4393 proto_tree_add_uint_format_value(field_tree, hf_tcp_proc_src_pid, tvb, 0, 0,
4394 tcpd->rev->process_pid, "%u", tcpd->rev->process_pid);
4395 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_src_uname, tvb, 0, 0,
4396 tcpd->rev->username, "%s", tcpd->rev->username);
4397 proto_tree_add_string_format_value(field_tree, hf_tcp_proc_src_cmd, tvb, 0, 0,
4398 tcpd->rev->command, "%s", tcpd->rev->command);
4403 * XXX - what, if any, of this should we do if this is included in an
4404 * error packet? It might be nice to see the details of the packet
4405 * that caused the ICMP error, but it might not be nice to have the
4406 * dissector update state based on it.
4407 * Also, we probably don't want to run TCP taps on those packets.
4409 if (length_remaining != 0) {
4410 if (tcph->th_flags & TH_RST) {
4414 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
4416 * A TCP SHOULD allow a received RST segment to include data.
4419 * It has been suggested that a RST segment could contain
4420 * ASCII text that encoded and explained the cause of the
4421 * RST. No standard has yet been established for such
4424 * so for segments with RST we just display the data as text.
4426 proto_tree_add_text(tcp_tree, tvb, offset, length_remaining,
4428 tvb_format_text(tvb, offset, length_remaining));
4430 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
4431 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd);
4439 tcp_stream_index = 0;
4440 fragment_table_init(&tcp_fragment_table);
4444 proto_register_tcp(void)
4446 static hf_register_info hf[] = {
4449 { "Source Port", "tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
4453 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
4457 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
4461 { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
4465 { "Sequence number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
4469 { "Next sequence number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
4473 { "Acknowledgement number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
4477 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
4481 { "Flags", "tcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
4484 { &hf_tcp_flags_res,
4485 { "Reserved", "tcp.flags.res", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RES,
4486 "Three reserved bits (must be zero)", HFILL }},
4489 { "Nonce", "tcp.flags.ns", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_NS,
4490 "ECN concealment protection (RFC 3540)", HFILL }},
4492 { &hf_tcp_flags_cwr,
4493 { "Congestion Window Reduced (CWR)", "tcp.flags.cwr", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_CWR,
4496 { &hf_tcp_flags_ecn,
4497 { "ECN-Echo", "tcp.flags.ecn", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ECN,
4500 { &hf_tcp_flags_urg,
4501 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_URG,
4504 { &hf_tcp_flags_ack,
4505 { "Acknowledgement", "tcp.flags.ack", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_ACK,
4508 { &hf_tcp_flags_push,
4509 { "Push", "tcp.flags.push", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_PUSH,
4512 { &hf_tcp_flags_reset,
4513 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_RST,
4516 { &hf_tcp_flags_syn,
4517 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_SYN,
4520 { &hf_tcp_flags_fin,
4521 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 12, TFS(&tfs_set_notset), TH_FIN,
4524 { &hf_tcp_window_size_value,
4525 { "Window size value", "tcp.window_size_value", FT_UINT16, BASE_DEC, NULL, 0x0,
4526 "The window size value from the TCP header", HFILL }},
4528 /* 32 bits so we can present some values adjusted to window scaling */
4529 { &hf_tcp_window_size,
4530 { "Calculated window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
4531 "The scaled window size (if scaling has been used)", HFILL }},
4533 { &hf_tcp_window_size_scalefactor,
4534 { "Window size scaling factor", "tcp.window_size_scalefactor", FT_INT32, BASE_DEC, NULL, 0x0,
4535 "The window size scaling factor (-1 when unknown, -2 when no scaling is used)", HFILL }},
4538 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
4539 "Details at: http://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
4541 { &hf_tcp_checksum_good,
4542 { "Good Checksum", "tcp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4543 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
4545 { &hf_tcp_checksum_bad,
4546 { "Bad Checksum", "tcp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4547 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
4549 { &hf_tcp_analysis_flags,
4550 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
4551 "This frame has some of the TCP analysis flags set", HFILL }},
4553 { &hf_tcp_analysis_retransmission,
4554 { "Retransmission", "tcp.analysis.retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
4555 "This frame is a suspected TCP retransmission", HFILL }},
4557 { &hf_tcp_analysis_fast_retransmission,
4558 { "Fast Retransmission", "tcp.analysis.fast_retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
4559 "This frame is a suspected TCP fast retransmission", HFILL }},
4561 { &hf_tcp_analysis_out_of_order,
4562 { "Out Of Order", "tcp.analysis.out_of_order", FT_NONE, BASE_NONE, NULL, 0x0,
4563 "This frame is a suspected Out-Of-Order segment", HFILL }},
4565 { &hf_tcp_analysis_reused_ports,
4566 { "TCP Port numbers reused", "tcp.analysis.reused_ports", FT_NONE, BASE_NONE, NULL, 0x0,
4567 "A new tcp session has started with previously used port numbers", HFILL }},
4569 { &hf_tcp_analysis_lost_packet,
4570 { "Previous Segment Lost", "tcp.analysis.lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
4571 "A segment before this one was lost from the capture", HFILL }},
4573 { &hf_tcp_analysis_ack_lost_packet,
4574 { "ACKed Lost Packet", "tcp.analysis.ack_lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
4575 "This frame ACKs a lost segment", HFILL }},
4577 { &hf_tcp_analysis_window_update,
4578 { "Window update", "tcp.analysis.window_update", FT_NONE, BASE_NONE, NULL, 0x0,
4579 "This frame is a tcp window update", HFILL }},
4581 { &hf_tcp_analysis_window_full,
4582 { "Window full", "tcp.analysis.window_full", FT_NONE, BASE_NONE, NULL, 0x0,
4583 "This segment has caused the allowed window to become 100% full", HFILL }},
4585 { &hf_tcp_analysis_keep_alive,
4586 { "Keep Alive", "tcp.analysis.keep_alive", FT_NONE, BASE_NONE, NULL, 0x0,
4587 "This is a keep-alive segment", HFILL }},
4589 { &hf_tcp_analysis_keep_alive_ack,
4590 { "Keep Alive ACK", "tcp.analysis.keep_alive_ack", FT_NONE, BASE_NONE, NULL, 0x0,
4591 "This is an ACK to a keep-alive segment", HFILL }},
4593 { &hf_tcp_analysis_duplicate_ack,
4594 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
4595 "This is a duplicate ACK", HFILL }},
4597 { &hf_tcp_analysis_duplicate_ack_num,
4598 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
4599 "This is duplicate ACK number #", HFILL }},
4601 { &hf_tcp_analysis_duplicate_ack_frame,
4602 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4603 "This is a duplicate to the ACK in frame #", HFILL }},
4605 { &hf_tcp_continuation_to,
4606 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4607 "This is a continuation to the PDU in frame #", HFILL }},
4609 { &hf_tcp_analysis_zero_window_probe,
4610 { "Zero Window Probe", "tcp.analysis.zero_window_probe", FT_NONE, BASE_NONE, NULL, 0x0,
4611 "This is a zero-window-probe", HFILL }},
4613 { &hf_tcp_analysis_zero_window_probe_ack,
4614 { "Zero Window Probe Ack", "tcp.analysis.zero_window_probe_ack", FT_NONE, BASE_NONE, NULL, 0x0,
4615 "This is an ACK to a zero-window-probe", HFILL }},
4617 { &hf_tcp_analysis_zero_window,
4618 { "Zero Window", "tcp.analysis.zero_window", FT_NONE, BASE_NONE, NULL, 0x0,
4619 "This is a zero-window", HFILL }},
4622 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
4625 { &hf_tcp_analysis_acks_frame,
4626 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4627 "Which previous segment is this an ACK for", HFILL}},
4629 { &hf_tcp_analysis_bytes_in_flight,
4630 { "Bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL, 0x0,
4631 "How many bytes are now in flight for this connection", HFILL}},
4633 { &hf_tcp_analysis_ack_rtt,
4634 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4635 "How long time it took to ACK the segment (RTT)", HFILL}},
4637 { &hf_tcp_analysis_rto,
4638 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4639 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL}},
4641 { &hf_tcp_analysis_rto_frame,
4642 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4643 "This is the frame we measure the RTO from", HFILL }},
4645 { &hf_tcp_urgent_pointer,
4646 { "Urgent pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
4649 { &hf_tcp_segment_overlap,
4650 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4651 "Segment overlaps with other segments", HFILL }},
4653 { &hf_tcp_segment_overlap_conflict,
4654 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4655 "Overlapping segments contained conflicting data", HFILL }},
4657 { &hf_tcp_segment_multiple_tails,
4658 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4659 "Several tails were found when reassembling the pdu", HFILL }},
4661 { &hf_tcp_segment_too_long_fragment,
4662 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4663 "Segment contained data past end of the pdu", HFILL }},
4665 { &hf_tcp_segment_error,
4666 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4667 "Reassembling error due to illegal segments", HFILL }},
4669 { &hf_tcp_segment_count,
4670 { "Segment count", "tcp.segment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
4674 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4678 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
4679 "TCP Segments", HFILL }},
4681 { &hf_tcp_reassembled_in,
4682 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4683 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
4685 { &hf_tcp_reassembled_length,
4686 { "Reassembled TCP length", "tcp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
4687 "The total length of the reassembled payload", HFILL }},
4689 { &hf_tcp_option_kind,
4690 { "Kind", "tcp.option_kind", FT_UINT8,
4691 BASE_DEC, VALS(tcp_option_kind_vs), 0x0, "This TCP option's kind", HFILL }},
4693 { &hf_tcp_option_len,
4694 { "Length", "tcp.option_len", FT_UINT8,
4695 BASE_DEC, NULL, 0x0, "Length of this TCP option in bytes (including kind and length fields)", HFILL }},
4698 { "TCP Options", "tcp.options", FT_BYTES,
4699 BASE_NONE, NULL, 0x0, NULL, HFILL }},
4701 { &hf_tcp_option_mss,
4702 { "TCP MSS Option", "tcp.options.mss", FT_NONE,
4703 BASE_NONE, NULL, 0x0, NULL, HFILL }},
4705 { &hf_tcp_option_mss_val,
4706 { "MSS Value", "tcp.options.mss_val", FT_UINT16,
4707 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4709 { &hf_tcp_option_wscale_shift,
4710 { "Shift count", "tcp.options.wscale.shift", FT_UINT8,
4711 BASE_DEC, NULL, 0x0, "Logarithmically encoded power of 2 scale factor", HFILL}},
4713 { &hf_tcp_option_wscale_multiplier,
4714 { "Multiplier", "tcp.options.wscale.multiplier", FT_UINT8,
4715 BASE_DEC, NULL, 0x0, "Multiply segment window size by this for scaled window size", HFILL}},
4717 { &hf_tcp_option_exp,
4718 { "TCP Option - Experimental", "tcp.options.experimental", FT_BYTES,
4719 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4721 { &hf_tcp_option_exp_data,
4722 { "Data", "tcp.options.experimental.data", FT_BYTES,
4723 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4725 { &hf_tcp_option_sack_perm,
4726 { "TCP SACK Permitted Option", "tcp.options.sack_perm",
4728 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4730 { &hf_tcp_option_sack,
4731 { "TCP SACK Option", "tcp.options.sack", FT_BOOLEAN,
4732 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4734 { &hf_tcp_option_sack_sle,
4735 {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32,
4736 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4738 { &hf_tcp_option_sack_sre,
4739 {"TCP SACK Right Edge", "tcp.options.sack_re", FT_UINT32,
4740 BASE_DEC, NULL, 0x0, NULL, HFILL}},
4742 { &hf_tcp_option_echo,
4743 { "TCP Echo Option", "tcp.options.echo", FT_BOOLEAN,
4744 BASE_NONE, NULL, 0x0, "TCP Sack Echo", HFILL}},
4746 { &hf_tcp_option_echo_reply,
4747 { "TCP Echo Reply Option", "tcp.options.echo_reply",
4749 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4751 { &hf_tcp_option_timestamp_tsval,
4752 { "Timestamp value", "tcp.options.timestamp.tsval", FT_UINT32,
4753 BASE_DEC, NULL, 0x0, "Value of sending machine's timestamp clock", HFILL}},
4755 { &hf_tcp_option_timestamp_tsecr,
4756 { "Timestamp echo reply", "tcp.options.timestamp.tsecr", FT_UINT32,
4757 BASE_DEC, NULL, 0x0, "Echoed timestamp from remote machine", HFILL}},
4759 { &hf_tcp_option_cc,
4760 { "TCP CC Option", "tcp.options.cc", FT_BOOLEAN, BASE_NONE,
4761 NULL, 0x0, NULL, HFILL}},
4763 { &hf_tcp_option_ccnew,
4764 { "TCP CC New Option", "tcp.options.ccnew", FT_BOOLEAN,
4765 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4767 { &hf_tcp_option_ccecho,
4768 { "TCP CC Echo Option", "tcp.options.ccecho", FT_BOOLEAN,
4769 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4771 { &hf_tcp_option_md5,
4772 { "TCP MD5 Option", "tcp.options.md5", FT_BOOLEAN, BASE_NONE,
4773 NULL, 0x0, NULL, HFILL}},
4775 { &hf_tcp_option_qs,
4776 { "TCP QS Option", "tcp.options.qs", FT_BOOLEAN, BASE_NONE,
4777 NULL, 0x0, NULL, HFILL}},
4779 { &hf_tcp_option_scps,
4780 { "TCP SCPS Capabilities Option", "tcp.options.scps",
4781 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4784 { &hf_tcp_option_scps_vector,
4785 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
4786 FT_UINT8, BASE_DEC, NULL, 0x0,
4789 { &hf_tcp_option_scps_binding,
4790 { "Binding Space (Community) ID",
4791 "tcp.options.scps.binding.id",
4792 FT_UINT8, BASE_DEC, NULL, 0x0,
4793 "TCP SCPS Extended Binding Space (Community) ID", HFILL}},
4795 { &hf_tcp_option_scps_binding_len,
4796 { "Extended Capability Length",
4797 "tcp.options.scps.binding.len",
4798 FT_UINT8, BASE_DEC, NULL, 0x0,
4799 "TCP SCPS Extended Capability Length in bytes", HFILL}},
4801 { &hf_tcp_option_snack,
4802 { "TCP Selective Negative Acknowledgement Option",
4803 "tcp.options.snack",
4804 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4807 { &hf_tcp_option_snack_offset,
4808 { "TCP SNACK Offset", "tcp.options.snack.offset",
4809 FT_UINT16, BASE_DEC, NULL, 0x0,
4812 { &hf_tcp_option_snack_size,
4813 { "TCP SNACK Size", "tcp.options.snack.size",
4814 FT_UINT16, BASE_DEC, NULL, 0x0,
4817 { &hf_tcp_option_snack_le,
4818 { "TCP SNACK Left Edge", "tcp.options.snack.le",
4819 FT_UINT16, BASE_DEC, NULL, 0x0,
4822 { &hf_tcp_option_snack_re,
4823 { "TCP SNACK Right Edge", "tcp.options.snack.re",
4824 FT_UINT16, BASE_DEC, NULL, 0x0,
4827 { &hf_tcp_scpsoption_flags_bets,
4828 { "Partial Reliability Capable (BETS)",
4829 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,
4830 TFS(&tfs_set_notset), 0x80, NULL, HFILL }},
4832 { &hf_tcp_scpsoption_flags_snack1,
4833 { "Short Form SNACK Capable (SNACK1)",
4834 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,
4835 TFS(&tfs_set_notset), 0x40, NULL, HFILL }},
4837 { &hf_tcp_scpsoption_flags_snack2,
4838 { "Long Form SNACK Capable (SNACK2)",
4839 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,
4840 TFS(&tfs_set_notset), 0x20, NULL, HFILL }},
4842 { &hf_tcp_scpsoption_flags_compress,
4843 { "Lossless Header Compression (COMP)",
4844 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,
4845 TFS(&tfs_set_notset), 0x10, NULL, HFILL }},
4847 { &hf_tcp_scpsoption_flags_nlts,
4848 { "Network Layer Timestamp (NLTS)",
4849 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,
4850 TFS(&tfs_set_notset), 0x8, NULL, HFILL }},
4852 { &hf_tcp_scpsoption_flags_resv3,
4854 "tcp.options.scpsflags.reserved3", FT_BOOLEAN, 8,
4855 TFS(&tfs_set_notset), 0x4, NULL, HFILL }},
4857 { &hf_tcp_scpsoption_flags_resv2,
4859 "tcp.options.scpsflags.reserved2", FT_BOOLEAN, 8,
4860 TFS(&tfs_set_notset), 0x2, NULL, HFILL }},
4862 { &hf_tcp_scpsoption_flags_resv1,
4864 "tcp.options.scpsflags.reserved1", FT_BOOLEAN, 8,
4865 TFS(&tfs_set_notset), 0x1, NULL, HFILL }},
4867 { &hf_tcp_scpsoption_connection_id,
4869 "tcp.options.scps.binding",
4870 FT_UINT8, BASE_DEC, NULL, 0x0,
4871 "TCP SCPS Connection ID", HFILL}},
4873 { &hf_tcp_option_mood,
4874 { "TCP Mood Option", "tcp.options.mood", FT_BOOLEAN,
4875 BASE_NONE, NULL, 0x0, NULL, HFILL }},
4877 { &hf_tcp_option_mood_val,
4878 { "TCP Mood Option Value", "tcp.options.mood_val", FT_STRING,
4879 BASE_NONE, NULL, 0x0, NULL, HFILL}},
4881 { &hf_tcp_option_user_to,
4882 { "TCP User Timeout", "tcp.options.user_to", FT_BOOLEAN,
4883 BASE_NONE, NULL, 0x0, NULL, HFILL }},
4885 { &hf_tcp_option_user_to_granularity,
4886 { "Granularity", "tcp.options.user_to_granularity", FT_BOOLEAN,
4887 16, TFS(&tcp_option_user_to_granularity), 0x8000, "TCP User Timeout Granularity", HFILL}},
4889 { &hf_tcp_option_user_to_val,
4890 { "User Timeout", "tcp.options.user_to_val", FT_UINT16,
4891 BASE_DEC, NULL, 0x7FFF, "TCP User Timeout Value", HFILL}},
4893 { &hf_tcp_option_rvbd_probe,
4894 { "Riverbed Probe", "tcp.options.rvbd.probe", FT_BOOLEAN,
4895 BASE_NONE, NULL, 0x0, "RVBD TCP Probe Option", HFILL }},
4897 { &hf_tcp_option_rvbd_probe_type1,
4898 { "Type", "tcp.options.rvbd.probe.type1",
4899 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
4901 { &hf_tcp_option_rvbd_probe_type2,
4902 { "Type", "tcp.options.rvbd.probe.type2",
4903 FT_UINT8, BASE_DEC, NULL, 0xFE, NULL, HFILL }},
4905 { &hf_tcp_option_rvbd_probe_version1,
4906 { "Version", "tcp.options.rvbd.probe.version",
4907 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
4909 { &hf_tcp_option_rvbd_probe_version2,
4910 { "Version", "tcp.options.rvbd.probe.version_raw",
4911 FT_UINT8, BASE_DEC, NULL, 0x01, "Version 2 Raw Value", HFILL }},
4913 { &hf_tcp_option_rvbd_probe_optlen,
4914 { "Length", "tcp.options.rvbd.probe.len",
4915 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4917 { &hf_tcp_option_rvbd_probe_prober,
4918 { "CSH IP", "tcp.options.rvbd.probe.prober",
4919 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4921 { &hf_tcp_option_rvbd_probe_proxy,
4922 { "SSH IP", "tcp.options.rvbd.probe.proxy.ip",
4923 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4925 { &hf_tcp_option_rvbd_probe_proxy_port,
4926 { "SSH Port", "tcp.options.rvbd.probe.proxy.port",
4927 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4929 { &hf_tcp_option_rvbd_probe_appli_ver,
4930 { "Application Version", "tcp.options.rvbd.probe.appli_ver",
4931 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4933 { &hf_tcp_option_rvbd_probe_client,
4934 { "Client IP", "tcp.options.rvbd.probe.client.ip",
4935 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4937 { &hf_tcp_option_rvbd_probe_storeid,
4938 { "CFE Store ID", "tcp.options.rvbd.probe.storeid",
4939 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4941 { &hf_tcp_option_rvbd_probe_flags,
4942 { "Probe Flags", "tcp.options.rvbd.probe.flags",
4943 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
4945 { &hf_tcp_option_rvbd_probe_flag_not_cfe,
4946 { "Not CFE", "tcp.options.rvbd.probe.flags.notcfe",
4947 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_NCFE,
4950 { &hf_tcp_option_rvbd_probe_flag_last_notify,
4951 { "Last Notify", "tcp.options.rvbd.probe.flags.last",
4952 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_LAST,
4955 { &hf_tcp_option_rvbd_probe_flag_probe_cache,
4956 { "Disable Probe Cache on CSH", "tcp.options.rvbd.probe.flags.probe",
4957 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE,
4960 { &hf_tcp_option_rvbd_probe_flag_sslcert,
4961 { "SSL Enabled", "tcp.options.rvbd.probe.flags.ssl",
4962 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SSLCERT,
4965 { &hf_tcp_option_rvbd_probe_flag_server_connected,
4966 { "SSH outer to server established", "tcp.options.rvbd.probe.flags.server",
4967 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RVBD_FLAGS_PROBE_SERVER,
4970 { &hf_tcp_option_rvbd_trpy,
4971 { "Riverbed Transparency", "tcp.options.rvbd.trpy",
4972 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4973 "RVBD TCP Transparency Option", HFILL }},
4975 { &hf_tcp_option_rvbd_trpy_flags,
4976 { "Transparency Options", "tcp.options.rvbd.trpy.flags",
4977 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
4979 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_probe,
4980 { "Enable FW traversal feature", "tcp.options.rvbd.trpy.flags.fw_rst_probe",
4981 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
4982 RVBD_FLAGS_TRPY_FW_RST_PROBE,
4983 "Reset state created by probe on the nexthop firewall",
4986 { &hf_tcp_option_rvbd_trpy_flag_fw_rst_inner,
4987 { "Enable Inner FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst_inner",
4988 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
4989 RVBD_FLAGS_TRPY_FW_RST_INNER,
4990 "Reset state created by transparent inner on all firewalls"
4991 " before passing connection through",
4994 { &hf_tcp_option_rvbd_trpy_flag_fw_rst,
4995 { "Enable Transparency FW feature on All FWs", "tcp.options.rvbd.trpy.flags.fw_rst",
4996 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
4997 RVBD_FLAGS_TRPY_FW_RST,
4998 "Reset state created by probe on all firewalls before "
4999 "establishing transparent inner connection", HFILL }},
5001 { &hf_tcp_option_rvbd_trpy_flag_chksum,
5002 { "Reserved", "tcp.options.rvbd.trpy.flags.chksum",
5003 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5004 RVBD_FLAGS_TRPY_CHKSUM, NULL, HFILL }},
5006 { &hf_tcp_option_rvbd_trpy_flag_oob,
5007 { "Out of band connection", "tcp.options.rvbd.trpy.flags.oob",
5008 FT_BOOLEAN, 16, TFS(&tfs_set_notset),
5009 RVBD_FLAGS_TRPY_OOB, NULL, HFILL }},
5011 { &hf_tcp_option_rvbd_trpy_flag_mode,
5012 { "Transparency Mode", "tcp.options.rvbd.trpy.flags.mode",
5013 FT_BOOLEAN, 16, TFS(&trpy_mode_str),
5014 RVBD_FLAGS_TRPY_MODE, NULL, HFILL }},
5016 { &hf_tcp_option_rvbd_trpy_src,
5017 { "Src SH IP Addr", "tcp.options.rvbd.trpy.src.ip",
5018 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5020 { &hf_tcp_option_rvbd_trpy_dst,
5021 { "Dst SH IP Addr", "tcp.options.rvbd.trpy.dst.ip",
5022 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5024 { &hf_tcp_option_rvbd_trpy_src_port,
5025 { "Src SH Inner Port", "tcp.options.rvbd.trpy.src.port",
5026 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5028 { &hf_tcp_option_rvbd_trpy_dst_port,
5029 { "Dst SH Inner Port", "tcp.options.rvbd.trpy.dst.port",
5030 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5032 { &hf_tcp_option_rvbd_trpy_client_port,
5033 { "Out of band connection Client Port", "tcp.options.rvbd.trpy.client.port",
5034 FT_UINT16, BASE_DEC, NULL , 0x0, NULL, HFILL }},
5037 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5038 "How long time has passed until the last frame of this PDU", HFILL}},
5041 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL, 0x0,
5042 "The size of this PDU", HFILL}},
5044 { &hf_tcp_pdu_last_frame,
5045 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5046 "This is the last frame of the PDU starting in this segment", HFILL }},
5048 { &hf_tcp_ts_relative,
5049 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5050 "Time relative to first frame in this TCP stream", HFILL}},
5053 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
5054 "Time delta from previous frame in this TCP stream", HFILL}},
5056 { &hf_tcp_proc_src_uid,
5057 { "Source process user ID", "tcp.proc.srcuid", FT_UINT32, BASE_DEC, NULL, 0x0,
5060 { &hf_tcp_proc_src_pid,
5061 { "Source process ID", "tcp.proc.srcpid", FT_UINT32, BASE_DEC, NULL, 0x0,
5064 { &hf_tcp_proc_src_uname,
5065 { "Source process user name", "tcp.proc.srcuname", FT_STRING, BASE_NONE, NULL, 0x0,
5068 { &hf_tcp_proc_src_cmd,
5069 { "Source process name", "tcp.proc.srccmd", FT_STRING, BASE_NONE, NULL, 0x0,
5070 "Source process command name", HFILL}},
5072 { &hf_tcp_proc_dst_uid,
5073 { "Destination process user ID", "tcp.proc.dstuid", FT_UINT32, BASE_DEC, NULL, 0x0,
5076 { &hf_tcp_proc_dst_pid,
5077 { "Destination process ID", "tcp.proc.dstpid", FT_UINT32, BASE_DEC, NULL, 0x0,
5080 { &hf_tcp_proc_dst_uname,
5081 { "Destination process user name", "tcp.proc.dstuname", FT_STRING, BASE_NONE, NULL, 0x0,
5084 { &hf_tcp_proc_dst_cmd,
5085 { "Destination process name", "tcp.proc.dstcmd", FT_STRING, BASE_NONE, NULL, 0x0,
5086 "Destination process command name", HFILL}},
5089 { "TCP segment data", "tcp.data", FT_BYTES, BASE_NONE, NULL, 0x0,
5093 static gint *ett[] = {
5097 &ett_tcp_option_timestamp,
5098 &ett_tcp_option_wscale,
5099 &ett_tcp_option_sack,
5100 &ett_tcp_option_scps,
5101 &ett_tcp_option_scps_extended,
5102 &ett_tcp_option_user_to,
5103 &ett_tcp_option_exp,
5104 &ett_tcp_option_sack_perm,
5105 &ett_tcp_option_mss,
5106 &ett_tcp_opt_rvbd_probe,
5107 &ett_tcp_opt_rvbd_probe_flags,
5108 &ett_tcp_opt_rvbd_trpy,
5109 &ett_tcp_opt_rvbd_trpy_flags,
5110 &ett_tcp_analysis_faults,
5112 &ett_tcp_timestamps,
5116 &ett_tcp_process_info
5118 module_t *tcp_module;
5120 proto_tcp = proto_register_protocol("Transmission Control Protocol",
5122 register_dissector("tcp", dissect_tcp, proto_tcp);
5123 proto_register_field_array(proto_tcp, hf, array_length(hf));
5124 proto_register_subtree_array(ett, array_length(ett));
5126 /* subdissector code */
5127 subdissector_table = register_dissector_table("tcp.port",
5128 "TCP port", FT_UINT16, BASE_DEC);
5129 register_heur_dissector_list("tcp", &heur_subdissector_list);
5131 /* Register configuration preferences */
5132 tcp_module = prefs_register_protocol(proto_tcp, NULL);
5133 prefs_register_bool_preference(tcp_module, "summary_in_tree",
5134 "Show TCP summary in protocol tree",
5135 "Whether the TCP summary line should be shown in the protocol tree",
5136 &tcp_summary_in_tree);
5137 prefs_register_bool_preference(tcp_module, "check_checksum",
5138 "Validate the TCP checksum if possible",
5139 "Whether to validate the TCP checksum",
5140 &tcp_check_checksum);
5141 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
5142 "Allow subdissector to reassemble TCP streams",
5143 "Whether subdissector can request TCP streams to be reassembled",
5145 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
5146 "Analyze TCP sequence numbers",
5147 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
5149 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
5150 "Relative sequence numbers",
5151 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
5152 "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
5155 /* We now have tcp.window_size_value and tcp.window_size, so no need
5156 * anymore for the preference window_scaling
5158 prefs_register_obsolete_preference(tcp_module, "window_scaling");
5160 prefs_register_bool_preference(tcp_module, "track_bytes_in_flight",
5161 "Track number of bytes in flight",
5162 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "
5163 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
5164 "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",
5165 &tcp_track_bytes_in_flight);
5166 prefs_register_bool_preference(tcp_module, "calculate_timestamps",
5167 "Calculate conversation timestamps",
5168 "Calculate timestamps relative to the first frame and the previous frame in the tcp conversation",
5170 prefs_register_bool_preference(tcp_module, "try_heuristic_first",
5171 "Try heuristic sub-dissectors first",
5172 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
5173 &try_heuristic_first);
5174 prefs_register_bool_preference(tcp_module, "ignore_tcp_timestamps",
5175 "Ignore TCP Timestamps in summary",
5176 "Do not place the TCP Timestamps in the summary line",
5177 &tcp_ignore_timestamps);
5179 register_init_routine(tcp_init);
5183 proto_reg_handoff_tcp(void)
5185 dissector_handle_t tcp_handle;
5187 tcp_handle = find_dissector("tcp");
5188 dissector_add_uint("ip.proto", IP_PROTO_TCP, tcp_handle);
5189 data_handle = find_dissector("data");
5190 tcp_tap = register_tap("tcp");
5199 * indent-tabs-mode: nil
5202 * ex: set shiftwidth=4 tabstop=8 expandtab:
5203 * :indentSize=4:tabSize=8:noTabs=true: