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_cwr = -1;
80 static int hf_tcp_flags_ecn = -1;
81 static int hf_tcp_flags_urg = -1;
82 static int hf_tcp_flags_ack = -1;
83 static int hf_tcp_flags_push = -1;
84 static int hf_tcp_flags_reset = -1;
85 static int hf_tcp_flags_syn = -1;
86 static int hf_tcp_flags_fin = -1;
87 static int hf_tcp_window_size = -1;
88 static int hf_tcp_checksum = -1;
89 static int hf_tcp_checksum_bad = -1;
90 static int hf_tcp_checksum_good = -1;
91 static int hf_tcp_len = -1;
92 static int hf_tcp_urgent_pointer = -1;
93 static int hf_tcp_analysis_flags = -1;
94 static int hf_tcp_analysis_bytes_in_flight = -1;
95 static int hf_tcp_analysis_acks_frame = -1;
96 static int hf_tcp_analysis_ack_rtt = -1;
97 static int hf_tcp_analysis_rto = -1;
98 static int hf_tcp_analysis_rto_frame = -1;
99 static int hf_tcp_analysis_retransmission = -1;
100 static int hf_tcp_analysis_fast_retransmission = -1;
101 static int hf_tcp_analysis_out_of_order = -1;
102 static int hf_tcp_analysis_reused_ports = -1;
103 static int hf_tcp_analysis_lost_packet = -1;
104 static int hf_tcp_analysis_ack_lost_packet = -1;
105 static int hf_tcp_analysis_window_update = -1;
106 static int hf_tcp_analysis_window_full = -1;
107 static int hf_tcp_analysis_keep_alive = -1;
108 static int hf_tcp_analysis_keep_alive_ack = -1;
109 static int hf_tcp_analysis_duplicate_ack = -1;
110 static int hf_tcp_analysis_duplicate_ack_num = -1;
111 static int hf_tcp_analysis_duplicate_ack_frame = -1;
112 static int hf_tcp_analysis_zero_window = -1;
113 static int hf_tcp_analysis_zero_window_probe = -1;
114 static int hf_tcp_analysis_zero_window_probe_ack = -1;
115 static int hf_tcp_continuation_to = -1;
116 static int hf_tcp_pdu_time = -1;
117 static int hf_tcp_pdu_size = -1;
118 static int hf_tcp_pdu_last_frame = -1;
119 static int hf_tcp_reassembled_in = -1;
120 static int hf_tcp_segments = -1;
121 static int hf_tcp_segment = -1;
122 static int hf_tcp_segment_overlap = -1;
123 static int hf_tcp_segment_overlap_conflict = -1;
124 static int hf_tcp_segment_multiple_tails = -1;
125 static int hf_tcp_segment_too_long_fragment = -1;
126 static int hf_tcp_segment_error = -1;
127 static int hf_tcp_options = -1;
128 static int hf_tcp_option_mss = -1;
129 static int hf_tcp_option_mss_val = -1;
130 static int hf_tcp_option_wscale = -1;
131 static int hf_tcp_option_wscale_val = -1;
132 static int hf_tcp_option_sack_perm = -1;
133 static int hf_tcp_option_sack = -1;
134 static int hf_tcp_option_sack_sle = -1;
135 static int hf_tcp_option_sack_sre = -1;
136 static int hf_tcp_option_echo = -1;
137 static int hf_tcp_option_echo_reply = -1;
138 static int hf_tcp_option_time_stamp = -1;
139 static int hf_tcp_option_cc = -1;
140 static int hf_tcp_option_ccnew = -1;
141 static int hf_tcp_option_ccecho = -1;
142 static int hf_tcp_option_md5 = -1;
143 static int hf_tcp_option_qs = -1;
144 static int hf_tcp_ts_relative = -1;
145 static int hf_tcp_ts_delta = -1;
146 static int hf_tcp_option_scps = -1;
147 static int hf_tcp_option_scps_vector = -1;
148 static int hf_tcp_option_scps_binding = -1;
149 static int hf_tcp_scpsoption_flags_bets = -1;
150 static int hf_tcp_scpsoption_flags_snack1 = -1;
151 static int hf_tcp_scpsoption_flags_snack2 = -1;
152 static int hf_tcp_scpsoption_flags_compress = -1;
153 static int hf_tcp_scpsoption_flags_nlts = -1;
154 static int hf_tcp_scpsoption_flags_resv1 = -1;
155 static int hf_tcp_scpsoption_flags_resv2 = -1;
156 static int hf_tcp_scpsoption_flags_resv3 = -1;
157 static int hf_tcp_option_snack = -1;
158 static int hf_tcp_option_snack_offset = -1;
159 static int hf_tcp_option_snack_size = -1;
160 static int hf_tcp_option_snack_le = -1;
161 static int hf_tcp_option_snack_re = -1;
163 static gint ett_tcp = -1;
164 static gint ett_tcp_flags = -1;
165 static gint ett_tcp_options = -1;
166 static gint ett_tcp_option_sack = -1;
167 static gint ett_tcp_option_scps = -1;
168 static gint ett_tcp_option_scps_extended = -1;
169 static gint ett_tcp_analysis = -1;
170 static gint ett_tcp_analysis_faults = -1;
171 static gint ett_tcp_timestamps = -1;
172 static gint ett_tcp_segments = -1;
173 static gint ett_tcp_segment = -1;
174 static gint ett_tcp_checksum = -1;
177 /* not all of the hf_fields below make sense for TCP but we have to provide
178 them anyways to comply with the api (which was aimed for ip fragment
180 static const fragment_items tcp_segment_items = {
185 &hf_tcp_segment_overlap,
186 &hf_tcp_segment_overlap_conflict,
187 &hf_tcp_segment_multiple_tails,
188 &hf_tcp_segment_too_long_fragment,
189 &hf_tcp_segment_error,
190 &hf_tcp_reassembled_in,
194 static dissector_table_t subdissector_table;
195 static heur_dissector_list_t heur_subdissector_list;
196 static dissector_handle_t data_handle;
198 /* TCP structs and definitions */
200 /* **************************************************************************
202 * RTT and reltive sequence numbers.
203 * **************************************************************************/
204 static gboolean tcp_analyze_seq = TRUE;
205 static gboolean tcp_relative_seq = TRUE;
206 static gboolean tcp_track_bytes_in_flight = TRUE;
207 static gboolean tcp_calculate_ts = FALSE;
209 /* SLAB allocator for tcp_unacked structures
211 SLAB_ITEM_TYPE_DEFINE(tcp_unacked_t)
212 static SLAB_FREE_LIST_DEFINE(tcp_unacked_t)
213 #define TCP_UNACKED_NEW(fi) \
214 SLAB_ALLOC(fi, tcp_unacked_t)
215 #define TCP_UNACKED_FREE(fi) \
216 SLAB_FREE(fi, tcp_unacked_t)
219 #define TCP_A_RETRANSMISSION 0x0001
220 #define TCP_A_LOST_PACKET 0x0002
221 #define TCP_A_ACK_LOST_PACKET 0x0004
222 #define TCP_A_KEEP_ALIVE 0x0008
223 #define TCP_A_DUPLICATE_ACK 0x0010
224 #define TCP_A_ZERO_WINDOW 0x0020
225 #define TCP_A_ZERO_WINDOW_PROBE 0x0040
226 #define TCP_A_ZERO_WINDOW_PROBE_ACK 0x0080
227 #define TCP_A_KEEP_ALIVE_ACK 0x0100
228 #define TCP_A_OUT_OF_ORDER 0x0200
229 #define TCP_A_FAST_RETRANSMISSION 0x0400
230 #define TCP_A_WINDOW_UPDATE 0x0800
231 #define TCP_A_WINDOW_FULL 0x1000
232 #define TCP_A_REUSED_PORTS 0x2000
236 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
237 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
238 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
239 struct tcp_analysis *tcpd);
242 struct tcp_analysis *
243 init_tcp_conversation_data(packet_info *pinfo)
245 struct tcp_analysis *tcpd=NULL;
247 /* Initialize the tcp protocol datat structure to add to the tcp conversation */
248 tcpd=se_alloc0(sizeof(struct tcp_analysis));
249 memset(&tcpd->flow1, 0, sizeof(tcp_flow_t));
250 memset(&tcpd->flow2, 0, sizeof(tcp_flow_t));
251 tcpd->flow1.win_scale=-1;
252 tcpd->flow1.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
253 tcpd->flow2.win_scale=-1;
254 tcpd->flow2.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
255 tcpd->acked_table=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_analyze_acked_table");
256 tcpd->ts_first.secs=pinfo->fd->abs_ts.secs;
257 tcpd->ts_first.nsecs=pinfo->fd->abs_ts.nsecs;
258 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
259 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
265 get_tcp_conversation(packet_info *pinfo)
267 conversation_t *conv=NULL;
269 /* Have we seen this conversation before? */
270 if( (conv=find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0)) == NULL){
271 /* No this is a new conversation. */
272 conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
277 struct tcp_analysis *
278 get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)
281 struct tcp_analysis *tcpd=NULL;
283 /* Did the caller supply the conversation pointer? */
285 conv = get_tcp_conversation(pinfo);
287 /* Get the data for this conversation */
288 tcpd=conversation_get_proto_data(conv, proto_tcp);
290 /* If the conversation was just created or it matched a
291 * conversation with template options, tcpd will not
292 * have been initialized. So, initialize
293 * a new tcpd structure for the conversation.
296 tcpd = init_tcp_conversation_data(pinfo);
297 conversation_add_proto_data(conv, proto_tcp, tcpd);
304 /* check direction and get ua lists */
305 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
306 /* if the addresses are equal, match the ports instead */
308 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
311 tcpd->fwd=&(tcpd->flow1);
312 tcpd->rev=&(tcpd->flow2);
314 tcpd->fwd=&(tcpd->flow2);
315 tcpd->rev=&(tcpd->flow1);
322 /* Calculate the timestamps relative to this conversation */
324 tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
325 struct tcp_per_packet_data_t *tcppd)
328 tcppd = se_alloc(sizeof(struct tcp_per_packet_data_t));
329 p_add_proto_data(pinfo->fd, proto_tcp, tcppd);
335 nstime_delta(&tcppd->ts_del, &pinfo->fd->abs_ts, &tcpd->ts_prev);
337 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
338 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
341 /* Add a subtree with the timestamps relative to this conversation */
343 tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
352 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "Timestamps");
353 PROTO_ITEM_SET_GENERATED(item);
354 tree=proto_item_add_subtree(item, ett_tcp_timestamps);
356 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
357 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);
358 PROTO_ITEM_SET_GENERATED(item);
361 tcppd = p_get_proto_data(pinfo->fd, proto_tcp);
364 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,
366 PROTO_ITEM_SET_GENERATED(item);
371 print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)
375 if (check_col(pinfo->cinfo, COL_INFO)){
376 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);
378 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
379 tvb, 0, 0, msp->first_frame);
380 PROTO_ITEM_SET_GENERATED(item);
383 /* if we know that a PDU starts inside this segment, return the adjusted
384 offset to where that PDU starts or just return offset back
385 and let TCP try to find out what it can about this segment
388 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)
390 struct tcp_multisegment_pdu *msp=NULL;
392 if(!pinfo->fd->flags.visited){
393 msp=se_tree_lookup32_le(multisegment_pdus, seq-1);
395 /* If this is a continuation of a PDU started in a
396 * previous segment we need to update the last_frame
399 if(seq>msp->seq && seq<msp->nxtpdu){
400 msp->last_frame=pinfo->fd->num;
401 msp->last_frame_time=pinfo->fd->abs_ts;
402 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
405 /* If this segment is completely within a previous PDU
406 * then we just skip this packet
408 if(seq>msp->seq && nxtseq<=msp->nxtpdu){
411 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu){
412 offset+=msp->nxtpdu-seq;
418 /* First we try to find the start and transfer time for a PDU.
419 * We only print this for the very first segment of a PDU
420 * and only for PDUs spanning multiple segments.
421 * Se we look for if there was any multisegment PDU started
422 * just BEFORE the end of this segment. I.e. either inside this
423 * segment or in a previous segment.
424 * Since this might also match PDUs that are completely within
425 * this segment we also verify that the found PDU does span
426 * beyond the end of this segment.
428 msp=se_tree_lookup32_le(multisegment_pdus, nxtseq-1);
430 if( (pinfo->fd->num==msp->first_frame)
435 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);
436 PROTO_ITEM_SET_GENERATED(item);
438 nstime_delta(&ns, &msp->last_frame_time, &pinfo->fd->abs_ts);
439 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,
441 PROTO_ITEM_SET_GENERATED(item);
445 /* Second we check if this segment is part of a PDU started
446 * prior to the segment (seq-1)
448 msp=se_tree_lookup32_le(multisegment_pdus, seq-1);
450 /* If this segment is completely within a previous PDU
451 * then we just skip this packet
453 if(seq>msp->seq && nxtseq<=msp->nxtpdu){
454 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
458 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu){
459 offset+=msp->nxtpdu-seq;
468 /* if we saw a PDU that extended beyond the end of the segment,
469 use this function to remember where the next pdu starts
471 struct tcp_multisegment_pdu *
472 pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, emem_tree_t *multisegment_pdus)
474 struct tcp_multisegment_pdu *msp;
476 msp=se_alloc(sizeof(struct tcp_multisegment_pdu));
479 msp->first_frame=pinfo->fd->num;
480 msp->last_frame=pinfo->fd->num;
481 msp->last_frame_time=pinfo->fd->abs_ts;
483 se_tree_insert32(multisegment_pdus, seq, (void *)msp);
487 /* This is called for SYN+ACK packets and the purpose is to verify that we
488 * have seen window scaling in both directions.
489 * If we cant find window scaling being set in both directions
490 * that means it was present in the SYN but not in the SYN+ACK
491 * (or the SYN was missing) and then we disable the window scaling
492 * for this tcp session.
495 verify_tcp_window_scaling(struct tcp_analysis *tcpd)
497 if( tcpd && ((tcpd->flow1.win_scale==-1) || (tcpd->flow2.win_scale==-1)) ){
498 tcpd->flow1.win_scale=-1;
499 tcpd->flow2.win_scale=-1;
503 /* if we saw a window scaling option, store it for future reference
506 pdu_store_window_scale_option(guint8 ws, struct tcp_analysis *tcpd)
509 tcpd->fwd->win_scale=ws;
513 tcp_get_relative_seq_ack(guint32 *seq, guint32 *ack, guint32 *win, struct tcp_analysis *tcpd)
515 if (tcpd && tcp_relative_seq) {
516 (*seq) -= tcpd->fwd->base_seq;
517 (*ack) -= tcpd->rev->base_seq;
518 if(tcpd->fwd->win_scale!=-1){
519 (*win)<<=tcpd->fwd->win_scale;
525 /* when this function returns, it will (if createflag) populate the ta pointer.
528 tcp_analyze_get_acked_struct(guint32 frame, gboolean createflag, struct tcp_analysis *tcpd)
533 tcpd->ta=se_tree_lookup32(tcpd->acked_table, frame);
534 if((!tcpd->ta) && createflag){
535 tcpd->ta=se_alloc0(sizeof(struct tcp_acked));
536 se_tree_insert32(tcpd->acked_table, frame, (void *)tcpd->ta);
541 /* fwd contains a list of all segments processed but not yet ACKed in the
542 * same direction as the current segment.
543 * rev contains a list of all segments received but not yet ACKed in the
544 * opposite direction to the current segment.
546 * New segments are always added to the head of the fwd/rev lists.
550 tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint8 flags, guint32 window, struct tcp_analysis *tcpd)
552 tcp_unacked_t *ual=NULL;
556 printf("analyze_sequence numbers frame:%u direction:%s\n",pinfo->fd->num,direction>=0?"FWD":"REW");
557 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);
558 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);
565 /* if this is the first segment for this list we need to store the
568 * Start relative seq and ack numbers at 1 if this
569 * is not a SYN packet. This makes the relative
570 * seq/ack numbers to be displayed correctly in the
571 * event that the SYN or SYN/ACK packet is not seen
572 * (this solves bug 1542)
574 if(tcpd->fwd->base_seq==0){
575 tcpd->fwd->base_seq = (flags & TH_SYN) ? seq : seq-1;
578 /* Only store reverse sequence if this isn't the SYN
579 * There's no guarantee that the ACK field of a SYN
580 * contains zeros; get the ISN from the first segment
581 * with the ACK bit set instead (usually the SYN/ACK).
583 if( (tcpd->rev->base_seq==0) && (flags & TH_ACK) ){
584 tcpd->rev->base_seq = (flags & TH_SYN) ? ack : ack-1;
589 * it is a zero window probe if
590 * the sequnece number is the next expected one
591 * the window in the other direction is 0
592 * the segment is exactly 1 byte
596 && seq==tcpd->fwd->nextseq
597 && tcpd->rev->window==0 ){
599 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
601 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
607 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
611 && (flags&(TH_RST|TH_FIN|TH_SYN))==0 ){
613 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
615 tcpd->ta->flags|=TCP_A_ZERO_WINDOW;
620 * If this segment is beyond the last seen nextseq we must
621 * have missed some previous segment
623 * We only check for this if we have actually seen segments prior to this
625 * RST packets are not checked for this.
627 if( tcpd->fwd->nextseq
628 && GT_SEQ(seq, tcpd->fwd->nextseq)
629 && (flags&(TH_RST))==0 ){
631 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
633 tcpd->ta->flags|=TCP_A_LOST_PACKET;
638 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
639 * to what should be the next sequence number.
640 * SYN/FIN/RST segments are never keepalives
643 if( (seglen==0||seglen==1)
644 && seq==(tcpd->fwd->nextseq-1)
645 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
647 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
649 tcpd->ta->flags|=TCP_A_KEEP_ALIVE;
653 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
654 * the previous seen segment and with a new window value
658 && window!=tcpd->fwd->window
659 && seq==tcpd->fwd->nextseq
660 && ack==tcpd->fwd->lastack
661 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
663 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
665 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
670 * If we know the window scaling
671 * and if this segment contains data ang goes all the way to the
672 * edge of the advertized window
673 * then we mark it as WINDOW FULL
674 * SYN/RST/FIN packets are never WINDOW FULL
678 && tcpd->fwd->win_scale!=-1
679 && tcpd->rev->win_scale!=-1
680 && (seq+seglen)==(tcpd->rev->lastack+(tcpd->rev->window<<tcpd->rev->win_scale))
681 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
683 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
685 tcpd->ta->flags|=TCP_A_WINDOW_FULL;
690 * It is a keepalive ack if it repeats the previous ACK and if
691 * the last segment in the reverse direction was a keepalive
696 && window==tcpd->fwd->window
697 && seq==tcpd->fwd->nextseq
698 && ack==tcpd->fwd->lastack
699 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
700 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
702 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
704 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK;
709 /* ZERO WINDOW PROBE ACK
710 * It is a zerowindowprobe ack if it repeats the previous ACK and if
711 * the last segment in the reverse direction was a zerowindowprobe
712 * It also repeats the previous zero window indication
717 && window==tcpd->fwd->window
718 && seq==tcpd->fwd->nextseq
719 && ack==tcpd->fwd->lastack
720 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
721 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
723 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
725 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
731 * It is a duplicate ack if window/seq/ack is the same as the previous
732 * segment and if the segment length is 0
736 && window==tcpd->fwd->window
737 && seq==tcpd->fwd->nextseq
738 && ack==tcpd->fwd->lastack
739 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
740 tcpd->fwd->dupacknum++;
742 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
744 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
745 tcpd->ta->dupack_num=tcpd->fwd->dupacknum;
746 tcpd->ta->dupack_frame=tcpd->fwd->lastnondupack;
752 /* If this was NOT a dupack we must reset the dupack counters */
753 if( (!tcpd->ta) || !(tcpd->ta->flags&TCP_A_DUPLICATE_ACK) ){
754 tcpd->fwd->lastnondupack=pinfo->fd->num;
755 tcpd->fwd->dupacknum=0;
760 * If this segment acks beyond the nextseqnum in the other direction
761 * then that means we have missed packets going in the
764 * We only check this if we have actually seen some seq numbers
765 * in the other direction.
767 if( tcpd->rev->nextseq
768 && GT_SEQ(ack, tcpd->rev->nextseq )
769 && (flags&(TH_ACK))!=0 ){
772 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
774 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
775 /* update nextseq in the other direction so we dont get
776 * this indication again.
778 tcpd->rev->nextseq=ack;
782 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
783 * If the segments contains data and if it does not advance
784 * sequence number it must be either of these three.
785 * Only test for this if we know what the seq number should be
786 * (tcpd->fwd->nextseq)
788 * Note that a simple KeepAlive is not a retransmission
791 && tcpd->fwd->nextseq
792 && (LT_SEQ(seq, tcpd->fwd->nextseq)) ){
795 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ){
796 goto finished_checking_retransmission_type;
799 /* If there were >=2 duplicate ACKs in the reverse direction
800 * (there might be duplicate acks missing from the trace)
801 * and if this sequence number matches those ACKs
802 * and if the packet occurs within 20ms of the last
804 * then this is a fast retransmission
806 t=(pinfo->fd->abs_ts.secs-tcpd->rev->lastacktime.secs)*1000000000;
807 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->rev->lastacktime.nsecs;
808 if( tcpd->rev->dupacknum>=2
809 && tcpd->rev->lastack==seq
812 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
814 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
815 goto finished_checking_retransmission_type;
818 /* If the segment came <3ms since the segment with the highest
819 * seen sequence number, then it is an OUT-OF-ORDER segment.
820 * (3ms is an arbitrary number)
822 t=(pinfo->fd->abs_ts.secs-tcpd->fwd->nextseqtime.secs)*1000000000;
823 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->fwd->nextseqtime.nsecs;
826 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
828 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
829 goto finished_checking_retransmission_type;
832 /* Then it has to be a generic retransmission */
834 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
836 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
837 nstime_delta(&tcpd->ta->rto_ts, &pinfo->fd->abs_ts, &tcpd->fwd->nextseqtime);
838 tcpd->ta->rto_frame=tcpd->fwd->nextseqframe;
840 finished_checking_retransmission_type:
843 /* add this new sequence number to the fwd list */
844 TCP_UNACKED_NEW(ual);
845 ual->next=tcpd->fwd->segments;
846 tcpd->fwd->segments=ual;
847 ual->frame=pinfo->fd->num;
849 ual->ts=pinfo->fd->abs_ts;
851 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
852 ual->nextseq=seq+seglen;
853 if( flags&(TH_SYN|TH_FIN) ){
857 /* Store the highest number seen so far for nextseq so we can detect
858 * when we receive segments that arrive with a "hole"
859 * If we dont have anything since before, just store what we got.
860 * ZeroWindowProbes are special and dont really advance the nextseq
862 if(GT_SEQ(ual->nextseq, tcpd->fwd->nextseq) || !tcpd->fwd->nextseq) {
863 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ){
864 tcpd->fwd->nextseq=ual->nextseq;
865 tcpd->fwd->nextseqframe=pinfo->fd->num;
866 tcpd->fwd->nextseqtime.secs=pinfo->fd->abs_ts.secs;
867 tcpd->fwd->nextseqtime.nsecs=pinfo->fd->abs_ts.nsecs;
872 /* remember what the ack/window is so we can track window updates and retransmissions */
873 tcpd->fwd->window=window;
874 tcpd->fwd->lastack=ack;
875 tcpd->fwd->lastacktime.secs=pinfo->fd->abs_ts.secs;
876 tcpd->fwd->lastacktime.nsecs=pinfo->fd->abs_ts.nsecs;
879 /* if there were any flags set for this segment we need to remember them
880 * we only remember the flags for the very last segment though.
883 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;
885 tcpd->fwd->lastsegmentflags=0;
889 /* remove all segments this ACKs and we dont need to keep around any more
892 /* first we remove all such segments at the head of the list */
893 while((ual=tcpd->rev->segments)){
894 tcp_unacked_t *tmpual;
895 if(ack==ual->nextseq){
896 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
897 tcpd->ta->frame_acked=ual->frame;
898 nstime_delta(&tcpd->ta->ts, &pinfo->fd->abs_ts, &ual->ts);
900 if(GT_SEQ(ual->nextseq,ack)){
904 /*qqq do the ACKs segment x delta y */
907 tmpual=tcpd->rev->segments->next;
909 if (tcpd->rev->scps_capable) {
910 /* Track largest segment successfully sent for SNACK analysis */
911 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) {
912 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);
916 TCP_UNACKED_FREE(ual);
917 tcpd->rev->segments=tmpual;
919 /* now we remove all such segments that are NOT at the head of the list */
920 ual=tcpd->rev->segments;
921 while(ual && ual->next){
922 tcp_unacked_t *tmpual;
923 if(GT_SEQ(ual->next->nextseq,ack)){
928 /*qqq do the ACKs segment x delta y */
931 tmpual=ual->next->next;
933 if (tcpd->rev->scps_capable) {
934 /* Track largest segment successfully sent for SNACK analysis*/
935 if ((ual->next->nextseq - ual->next->seq) > tcpd->fwd->maxsizeacked){
936 tcpd->fwd->maxsizeacked = (ual->next->nextseq - ual->next->seq);
940 TCP_UNACKED_FREE(ual->next);
945 /* how many bytes of data are there in flight after this frame
948 ual=tcpd->fwd->segments;
949 if (tcp_track_bytes_in_flight && seglen!=0 && ual) {
950 guint32 first_seq, last_seq, in_flight;
952 first_seq = ual->seq - tcpd->fwd->base_seq;
953 last_seq = ual->nextseq - tcpd->fwd->base_seq;
955 if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) {
956 last_seq = ual->nextseq-tcpd->fwd->base_seq;
958 if ((ual->seq-tcpd->fwd->base_seq)<first_seq) {
959 first_seq = ual->seq-tcpd->fwd->base_seq;
963 in_flight = last_seq-first_seq;
965 if (in_flight>0 && in_flight<2000000000) {
967 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
969 tcpd->ta->bytes_in_flight = in_flight;
976 * Prints results of the sequence number analysis concerning tcp segments
977 * retransmitted or out-of-order
980 tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,
982 proto_tree * flags_tree,
986 proto_item * flags_item;
988 /* TCP Rentransmission */
989 if (ta->flags & TCP_A_RETRANSMISSION) {
990 flags_item=proto_tree_add_none_format(flags_tree,
991 hf_tcp_analysis_retransmission,
993 "This frame is a (suspected) "
996 PROTO_ITEM_SET_GENERATED(flags_item);
997 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
998 "Retransmission (suspected)");
1000 if (check_col(pinfo->cinfo, COL_INFO)) {
1001 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
1003 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {
1004 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
1005 tvb, 0, 0, &ta->rto_ts);
1006 PROTO_ITEM_SET_GENERATED(flags_item);
1007 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,
1008 tvb, 0, 0, ta->rto_frame);
1009 PROTO_ITEM_SET_GENERATED(flags_item);
1012 /* TCP Fast Rentransmission */
1013 if (ta->flags & TCP_A_FAST_RETRANSMISSION) {
1014 flags_item=proto_tree_add_none_format(flags_tree,
1015 hf_tcp_analysis_fast_retransmission,
1017 "This frame is a (suspected) fast"
1020 PROTO_ITEM_SET_GENERATED(flags_item);
1021 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1022 "Fast retransmission (suspected)");
1023 flags_item=proto_tree_add_none_format(flags_tree,
1024 hf_tcp_analysis_retransmission,
1026 "This frame is a (suspected) "
1029 PROTO_ITEM_SET_GENERATED(flags_item);
1030 if (check_col(pinfo->cinfo, COL_INFO)) {
1031 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1032 "[TCP Fast Retransmission] ");
1035 /* TCP Out-Of-Order */
1036 if (ta->flags & TCP_A_OUT_OF_ORDER) {
1037 flags_item=proto_tree_add_none_format(flags_tree,
1038 hf_tcp_analysis_out_of_order,
1040 "This frame is a (suspected) "
1041 "out-of-order segment"
1043 PROTO_ITEM_SET_GENERATED(flags_item);
1044 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1045 "Out-Of-Order segment");
1046 if (check_col(pinfo->cinfo, COL_INFO)) {
1047 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
1052 /* Prints results of the sequence number analysis concerning reused ports */
1054 tcp_sequence_number_analysis_print_reused(packet_info * pinfo,
1056 proto_tree * flags_tree,
1057 struct tcp_acked *ta
1060 proto_item * flags_item;
1062 /* TCP Ports Reused */
1063 if (ta->flags & TCP_A_REUSED_PORTS) {
1064 flags_item=proto_tree_add_none_format(flags_tree,
1065 hf_tcp_analysis_reused_ports,
1067 "A new tcp session is started with the same "
1068 "ports as an earlier session in this trace"
1070 PROTO_ITEM_SET_GENERATED(flags_item);
1071 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1072 "TCP Port numbers reused for new session");
1073 if(check_col(pinfo->cinfo, COL_INFO)){
1074 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1075 "[TCP Port numbers reused] ");
1080 /* Prints results of the sequence number analysis concerning lost tcp segments */
1082 tcp_sequence_number_analysis_print_lost(packet_info * pinfo,
1084 proto_tree * flags_tree,
1085 struct tcp_acked *ta
1088 proto_item * flags_item;
1090 /* TCP Lost Segment */
1091 if (ta->flags & TCP_A_LOST_PACKET) {
1092 flags_item=proto_tree_add_none_format(flags_tree,
1093 hf_tcp_analysis_lost_packet,
1095 "A segment before this frame was "
1098 PROTO_ITEM_SET_GENERATED(flags_item);
1099 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1100 "Previous segment lost (common at capture start)");
1101 if(check_col(pinfo->cinfo, COL_INFO)){
1102 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1103 "[TCP Previous segment lost] ");
1106 /* TCP Ack lost segment */
1107 if (ta->flags & TCP_A_ACK_LOST_PACKET) {
1108 flags_item=proto_tree_add_none_format(flags_tree,
1109 hf_tcp_analysis_ack_lost_packet,
1111 "This frame ACKs a segment we have "
1114 PROTO_ITEM_SET_GENERATED(flags_item);
1115 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1116 "ACKed lost segment (common at capture start)");
1117 if(check_col(pinfo->cinfo, COL_INFO)){
1118 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1119 "[TCP ACKed lost segment] ");
1124 /* Prints results of the sequence number analysis concerning tcp window */
1126 tcp_sequence_number_analysis_print_window(packet_info * pinfo,
1128 proto_tree * flags_tree,
1129 struct tcp_acked *ta
1132 proto_item * flags_item;
1134 /* TCP Window Update */
1135 if (ta->flags & TCP_A_WINDOW_UPDATE) {
1136 flags_item=proto_tree_add_none_format(flags_tree,
1137 hf_tcp_analysis_window_update,
1139 "This is a tcp window update"
1141 PROTO_ITEM_SET_GENERATED(flags_item);
1142 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_CHAT,
1144 if (check_col(pinfo->cinfo, COL_INFO)) {
1145 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
1148 /* TCP Full Window */
1149 if (ta->flags & TCP_A_WINDOW_FULL) {
1150 flags_item=proto_tree_add_none_format(flags_tree,
1151 hf_tcp_analysis_window_full,
1153 "The transmission window is now "
1156 PROTO_ITEM_SET_GENERATED(flags_item);
1157 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1159 if (check_col(pinfo->cinfo, COL_INFO)) {
1160 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
1165 /* Prints results of the sequence number analysis concerning tcp keepalive */
1167 tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,
1169 proto_tree * flags_tree,
1170 struct tcp_acked *ta
1173 proto_item * flags_item;
1176 if (ta->flags & TCP_A_KEEP_ALIVE){
1177 flags_item=proto_tree_add_none_format(flags_tree,
1178 hf_tcp_analysis_keep_alive,
1180 "This is a TCP keep-alive segment"
1182 PROTO_ITEM_SET_GENERATED(flags_item);
1183 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1185 if (check_col(pinfo->cinfo, COL_INFO)) {
1186 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
1189 /* TCP Ack Keep Alive */
1190 if (ta->flags & TCP_A_KEEP_ALIVE_ACK) {
1191 flags_item=proto_tree_add_none_format(flags_tree,
1192 hf_tcp_analysis_keep_alive_ack,
1194 "This is an ACK to a TCP keep-alive "
1197 PROTO_ITEM_SET_GENERATED(flags_item);
1198 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1200 if (check_col(pinfo->cinfo, COL_INFO)) {
1201 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
1206 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
1208 tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,
1210 proto_tree * flags_tree,
1211 struct tcp_acked *ta,
1215 proto_item * flags_item;
1217 /* TCP Duplicate ACK */
1218 if (ta->dupack_num) {
1219 if (ta->flags & TCP_A_DUPLICATE_ACK ) {
1220 flags_item=proto_tree_add_none_format(flags_tree,
1221 hf_tcp_analysis_duplicate_ack,
1223 "This is a TCP duplicate ack"
1225 PROTO_ITEM_SET_GENERATED(flags_item);
1226 if (check_col(pinfo->cinfo, COL_INFO)) {
1227 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1228 "[TCP Dup ACK %u#%u] ",
1234 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
1235 tvb, 0, 0, ta->dupack_num);
1236 PROTO_ITEM_SET_GENERATED(flags_item);
1237 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
1238 tvb, 0, 0, ta->dupack_frame);
1239 PROTO_ITEM_SET_GENERATED(flags_item);
1240 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1241 "Duplicate ACK (#%u)",
1247 /* Prints results of the sequence number analysis concerning tcp zero window */
1249 tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,
1251 proto_tree * flags_tree,
1252 struct tcp_acked *ta
1255 proto_item * flags_item;
1257 /* TCP Zero Window Probe */
1258 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE) {
1259 flags_item=proto_tree_add_none_format(flags_tree,
1260 hf_tcp_analysis_zero_window_probe,
1262 "This is a TCP zero-window-probe"
1264 PROTO_ITEM_SET_GENERATED(flags_item);
1265 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1266 "Zero window probe");
1267 if (check_col(pinfo->cinfo, COL_INFO)) {
1268 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
1271 /* TCP Zero Window */
1272 if (ta->flags&TCP_A_ZERO_WINDOW) {
1273 flags_item=proto_tree_add_none_format(flags_tree,
1274 hf_tcp_analysis_zero_window,
1276 "This is a ZeroWindow segment"
1278 PROTO_ITEM_SET_GENERATED(flags_item);
1279 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1281 if (check_col(pinfo->cinfo, COL_INFO)) {
1282 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
1285 /* TCP Zero Window Probe Ack */
1286 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK) {
1287 flags_item=proto_tree_add_none_format(flags_tree,
1288 hf_tcp_analysis_zero_window_probe_ack,
1290 "This is an ACK to a TCP zero-window-probe"
1292 PROTO_ITEM_SET_GENERATED(flags_item);
1293 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1294 "Zero window probe ACK");
1295 if (check_col(pinfo->cinfo, COL_INFO)) {
1296 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1297 "[TCP ZeroWindowProbeAck] ");
1303 /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */
1305 tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U_,
1307 proto_tree * flags_tree _U_,
1308 struct tcp_acked *ta
1311 proto_item * flags_item;
1313 if (tcp_track_bytes_in_flight) {
1314 flags_item=proto_tree_add_uint(flags_tree,
1315 hf_tcp_analysis_bytes_in_flight,
1316 tvb, 0, 0, ta->bytes_in_flight);
1318 PROTO_ITEM_SET_GENERATED(flags_item);
1323 tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd)
1325 struct tcp_acked *ta = NULL;
1328 proto_tree *flags_tree=NULL;
1334 tcp_analyze_get_acked_struct(pinfo->fd->num, FALSE, tcpd);
1341 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "SEQ/ACK analysis");
1342 PROTO_ITEM_SET_GENERATED(item);
1343 tree=proto_item_add_subtree(item, ett_tcp_analysis);
1345 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
1346 data we actually have */
1347 if(ta->frame_acked){
1348 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
1349 tvb, 0, 0, ta->frame_acked);
1350 PROTO_ITEM_SET_GENERATED(item);
1352 /* only display RTT if we actually have something we are acking */
1353 if( ta->ts.secs || ta->ts.nsecs ){
1354 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
1355 tvb, 0, 0, &ta->ts);
1356 PROTO_ITEM_SET_GENERATED(item);
1360 if(ta->bytes_in_flight) {
1361 /* print results for amount of data in flight */
1362 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta);
1366 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, 0, FALSE);
1367 PROTO_ITEM_SET_GENERATED(item);
1368 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);
1370 /* print results for reused tcp ports */
1371 tcp_sequence_number_analysis_print_reused(pinfo, tvb, flags_tree, ta);
1373 /* print results for retransmission and out-of-order segments */
1374 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, ta);
1376 /* print results for lost tcp segments */
1377 tcp_sequence_number_analysis_print_lost(pinfo, tvb, flags_tree, ta);
1379 /* print results for tcp window information */
1380 tcp_sequence_number_analysis_print_window(pinfo, tvb, flags_tree, ta);
1382 /* print results for tcp keep alive information */
1383 tcp_sequence_number_analysis_print_keepalive(pinfo, tvb, flags_tree, ta);
1385 /* print results for tcp duplicate acks */
1386 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);
1388 /* print results for tcp zero window */
1389 tcp_sequence_number_analysis_print_zero_window(pinfo, tvb, flags_tree, ta);
1396 print_tcp_fragment_tree(fragment_data *ipfd_head, proto_tree *tree, proto_tree *tcp_tree, packet_info *pinfo, tvbuff_t *next_tvb)
1398 proto_item *tcp_tree_item, *frag_tree_item;
1401 * The subdissector thought it was completely
1402 * desegmented (although the stuff at the
1403 * end may, in turn, require desegmentation),
1404 * so we show a tree with all segments.
1406 show_fragment_tree(ipfd_head, &tcp_segment_items,
1407 tree, pinfo, next_tvb, &frag_tree_item);
1409 * The toplevel fragment subtree is now
1410 * behind all desegmented data; move it
1411 * right behind the TCP tree.
1413 tcp_tree_item = proto_tree_get_parent(tcp_tree);
1414 if(frag_tree_item && tcp_tree_item) {
1415 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);
1419 /* **************************************************************************
1420 * End of tcp sequence number analysis
1421 * **************************************************************************/
1424 /* Minimum TCP header length. */
1425 #define TCPH_MIN_LEN 20
1431 #define TCPOPT_NOP 1 /* Padding */
1432 #define TCPOPT_EOL 0 /* End of options */
1433 #define TCPOPT_MSS 2 /* Segment size negotiating */
1434 #define TCPOPT_WINDOW 3 /* Window scaling */
1435 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
1436 #define TCPOPT_SACK 5 /* SACK Block */
1437 #define TCPOPT_ECHO 6
1438 #define TCPOPT_ECHOREPLY 7
1439 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
1440 #define TCPOPT_CC 11
1441 #define TCPOPT_CCNEW 12
1442 #define TCPOPT_CCECHO 13
1443 #define TCPOPT_MD5 19 /* RFC2385 */
1444 #define TCPOPT_SCPS 20 /* SCPS Capabilities */
1445 #define TCPOPT_SNACK 21 /* SCPS SNACK */
1446 #define TCPOPT_RECBOUND 22 /* SCPS Record Boundary */
1447 #define TCPOPT_CORREXP 23 /* SCPS Corruption Experienced */
1448 #define TCPOPT_QS 27 /* RFC4782 */
1451 * TCP option lengths
1454 #define TCPOLEN_MSS 4
1455 #define TCPOLEN_WINDOW 3
1456 #define TCPOLEN_SACK_PERM 2
1457 #define TCPOLEN_SACK_MIN 2
1458 #define TCPOLEN_ECHO 6
1459 #define TCPOLEN_ECHOREPLY 6
1460 #define TCPOLEN_TIMESTAMP 10
1461 #define TCPOLEN_CC 6
1462 #define TCPOLEN_CCNEW 6
1463 #define TCPOLEN_CCECHO 6
1464 #define TCPOLEN_MD5 18
1465 #define TCPOLEN_SCPS 4
1466 #define TCPOLEN_SNACK 6
1467 #define TCPOLEN_RECBOUND 2
1468 #define TCPOLEN_CORREXP 2
1469 #define TCPOLEN_QS 8
1473 /* Desegmentation of TCP streams */
1474 /* table to hold defragmented TCP streams */
1475 static GHashTable *tcp_fragment_table = NULL;
1477 tcp_fragment_init(void)
1479 fragment_table_init(&tcp_fragment_table);
1482 /* functions to trace tcp segments */
1483 /* Enable desegmenting of TCP streams */
1484 static gboolean tcp_desegment = TRUE;
1487 desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
1488 guint32 seq, guint32 nxtseq,
1489 guint32 sport, guint32 dport,
1490 proto_tree *tree, proto_tree *tcp_tree,
1491 struct tcp_analysis *tcpd)
1493 struct tcpinfo *tcpinfo = pinfo->private_data;
1494 fragment_data *ipfd_head;
1495 int last_fragment_len;
1496 gboolean must_desegment;
1497 gboolean called_dissector;
1498 int another_pdu_follows;
1503 struct tcp_multisegment_pdu *msp;
1507 last_fragment_len=0;
1508 must_desegment = FALSE;
1509 called_dissector = FALSE;
1510 another_pdu_follows = 0;
1514 * Initialize these to assume no desegmentation.
1515 * If that's not the case, these will be set appropriately
1516 * by the subdissector.
1518 pinfo->desegment_offset = 0;
1519 pinfo->desegment_len = 0;
1522 * Initialize this to assume that this segment will just be
1523 * added to the middle of a desegmented chunk of data, so
1524 * that we should show it all as data.
1525 * If that's not the case, it will be set appropriately.
1527 deseg_offset = offset;
1529 /* find the most previous PDU starting before this sequence number */
1531 msp = se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);
1533 if(msp && msp->seq<=seq && msp->nxtpdu>seq){
1536 if(!pinfo->fd->flags.visited){
1537 msp->last_frame=pinfo->fd->num;
1538 msp->last_frame_time=pinfo->fd->abs_ts;
1541 /* OK, this PDU was found, which means the segment continues
1542 a higher-level PDU and that we must desegment it.
1544 if(msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT){
1545 /* The dissector asked for the entire segment */
1546 len=tvb_length_remaining(tvb, offset);
1548 len=MIN(nxtseq, msp->nxtpdu) - seq;
1550 last_fragment_len = len;
1552 ipfd_head = fragment_add(tvb, offset, pinfo, msp->first_frame,
1556 (LT_SEQ (nxtseq,msp->nxtpdu)) );
1558 if(msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT){
1559 msp->flags&=(~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
1561 /* If we consumed the entire segment there is no
1562 * other pdu starting anywhere inside this segment.
1563 * So update nxtpdu to point at least to the start
1564 * of the next segment.
1565 * (If the subdissector asks for even more data we
1566 * will advance nxtpdu even furhter later down in
1572 if( (msp->nxtpdu<nxtseq)
1573 && (msp->nxtpdu>=seq)
1575 another_pdu_follows=msp->nxtpdu-seq;
1578 /* This segment was not found in our table, so it doesn't
1579 contain a continuation of a higher-level PDU.
1580 Call the normal subdissector.
1582 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
1583 sport, dport, 0, 0, FALSE, tcpd);
1584 called_dissector = TRUE;
1586 /* Did the subdissector ask us to desegment some more data
1587 before it could handle the packet?
1588 If so we have to create some structures in our table but
1589 this is something we only do the first time we see this
1592 if(pinfo->desegment_len) {
1593 if (!pinfo->fd->flags.visited)
1594 must_desegment = TRUE;
1597 * Set "deseg_offset" to the offset in "tvb"
1598 * of the first byte of data that the
1599 * subdissector didn't process.
1601 deseg_offset = offset + pinfo->desegment_offset;
1604 /* Either no desegmentation is necessary, or this is
1605 segment contains the beginning but not the end of
1606 a higher-level PDU and thus isn't completely
1613 /* is it completely desegmented? */
1616 * Yes, we think it is.
1617 * We only call subdissector for the last segment.
1618 * Note that the last segment may include more than what
1621 if(ipfd_head->reassembled_in==pinfo->fd->num){
1623 * OK, this is the last segment.
1624 * Let's call the subdissector with the desegmented
1630 /* create a new TVB structure for desegmented data */
1631 next_tvb = tvb_new_real_data(ipfd_head->data,
1632 ipfd_head->datalen, ipfd_head->datalen);
1634 /* add this tvb as a child to the original one */
1635 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1637 /* add desegmented data to the data source list */
1638 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
1641 * Supply the sequence number of the first of the
1642 * reassembled bytes.
1644 tcpinfo->seq = msp->seq;
1646 /* indicate that this is reassembled data */
1647 tcpinfo->is_reassembled = TRUE;
1649 /* call subdissector */
1650 process_tcp_payload(next_tvb, 0, pinfo, tree,
1651 tcp_tree, sport, dport, 0, 0, FALSE, tcpd);
1652 called_dissector = TRUE;
1655 * OK, did the subdissector think it was completely
1656 * desegmented, or does it think we need even more
1659 old_len=(int)(tvb_reported_length(next_tvb)-last_fragment_len);
1660 if(pinfo->desegment_len &&
1661 pinfo->desegment_offset<=old_len){
1663 * "desegment_len" isn't 0, so it needs more
1664 * data for something - and "desegment_offset"
1665 * is before "old_len", so it needs more data
1666 * to dissect the stuff we thought was
1667 * completely desegmented (as opposed to the
1668 * stuff at the beginning being completely
1669 * desegmented, but the stuff at the end
1670 * being a new higher-level PDU that also
1671 * needs desegmentation).
1673 fragment_set_partial_reassembly(pinfo,msp->first_frame,tcp_fragment_table);
1674 /* Update msp->nxtpdu to point to the new next
1677 if(pinfo->desegment_len==DESEGMENT_ONE_MORE_SEGMENT){
1678 /* We want reassembly of at least one
1679 * more segment so set the nxtpdu
1680 * boundary to one byte into the next
1682 * This means that the next segment
1683 * will complete reassembly even if it
1684 * is only one single byte in length.
1686 msp->nxtpdu=seq+tvb_reported_length_remaining(tvb, offset) + 1;
1687 msp->flags|=MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1689 msp->nxtpdu=seq + last_fragment_len + pinfo->desegment_len;
1691 /* Since we need at least some more data
1692 * there can be no pdu following in the
1693 * tail of this segment.
1695 another_pdu_follows=0;
1696 offset += last_fragment_len;
1697 seq += last_fragment_len;
1698 if (tvb_length_remaining(tvb, offset) > 0)
1702 * Show the stuff in this TCP segment as
1703 * just raw TCP segment data.
1705 nbytes = another_pdu_follows > 0
1706 ? another_pdu_follows
1707 : tvb_reported_length_remaining(tvb, offset);
1708 proto_tree_add_text(tcp_tree, tvb, offset, nbytes,
1709 "TCP segment data (%u byte%s)", nbytes,
1710 plurality(nbytes, "", "s"));
1712 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
1714 /* Did the subdissector ask us to desegment
1715 some more data? This means that the data
1716 at the beginning of this segment completed
1717 a higher-level PDU, but the data at the
1718 end of this segment started a higher-level
1719 PDU but didn't complete it.
1721 If so, we have to create some structures
1722 in our table, but this is something we
1723 only do the first time we see this packet.
1725 if(pinfo->desegment_len) {
1726 if (!pinfo->fd->flags.visited)
1727 must_desegment = TRUE;
1729 /* The stuff we couldn't dissect
1730 must have come from this segment,
1731 so it's all in "tvb".
1733 "pinfo->desegment_offset" is
1734 relative to the beginning of
1735 "next_tvb"; we want an offset
1736 relative to the beginning of "tvb".
1738 First, compute the offset relative
1739 to the *end* of "next_tvb" - i.e.,
1740 the number of bytes before the end
1741 of "next_tvb" at which the
1742 subdissector stopped. That's the
1743 length of "next_tvb" minus the
1744 offset, relative to the beginning
1745 of "next_tvb, at which the
1746 subdissector stopped.
1749 ipfd_head->datalen - pinfo->desegment_offset;
1751 /* "tvb" and "next_tvb" end at the
1752 same byte of data, so the offset
1753 relative to the end of "next_tvb"
1754 of the byte at which we stopped
1755 is also the offset relative to
1756 the end of "tvb" of the byte at
1759 Convert that back into an offset
1760 relative to the beginninng of
1761 "tvb", by taking the length of
1762 "tvb" and subtracting the offset
1763 relative to the end.
1765 deseg_offset=tvb_reported_length(tvb) - deseg_offset;
1771 if (must_desegment) {
1772 /* If the dissector requested "reassemble until FIN"
1773 * just set this flag for the flow and let reassembly
1774 * proceed at normal. We will check/pick up these
1775 * reassembled PDUs later down in dissect_tcp() when checking
1778 if(tcpd && pinfo->desegment_len==DESEGMENT_UNTIL_FIN) {
1779 tcpd->fwd->flags|=TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1782 * The sequence number at which the stuff to be desegmented
1783 * starts is the sequence number of the byte at an offset
1784 * of "deseg_offset" into "tvb".
1786 * The sequence number of the byte at an offset of "offset"
1787 * is "seq", i.e. the starting sequence number of this
1788 * segment, so the sequence number of the byte at
1789 * "deseg_offset" is "seq + (deseg_offset - offset)".
1791 deseg_seq = seq + (deseg_offset - offset);
1793 if(tcpd && ((nxtseq - deseg_seq) <= 1024*1024)
1794 && (!pinfo->fd->flags.visited) ){
1795 if(pinfo->desegment_len==DESEGMENT_ONE_MORE_SEGMENT){
1796 /* The subdissector asked to reassemble using the
1797 * entire next segment.
1798 * Just ask reassembly for one more byte
1799 * but set this msp flag so we can pick it up
1802 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1803 deseg_seq, nxtseq+1, tcpd->fwd->multisegment_pdus);
1804 msp->flags|=MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1806 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1807 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
1810 /* add this segment as the first one for this new pdu */
1811 fragment_add(tvb, deseg_offset, pinfo, msp->first_frame,
1815 LT_SEQ(nxtseq, msp->nxtpdu));
1819 if (!called_dissector || pinfo->desegment_len != 0) {
1820 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
1821 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
1823 * We know what frame this PDU is reassembled in;
1824 * let the user know.
1826 item=proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in,
1827 tvb, 0, 0, ipfd_head->reassembled_in);
1828 PROTO_ITEM_SET_GENERATED(item);
1832 * Either we didn't call the subdissector at all (i.e.,
1833 * this is a segment that contains the middle of a
1834 * higher-level PDU, but contains neither the beginning
1835 * nor the end), or the subdissector couldn't dissect it
1836 * all, as some data was missing (i.e., it set
1837 * "pinfo->desegment_len" to the amount of additional
1840 if (pinfo->desegment_offset == 0) {
1842 * It couldn't, in fact, dissect any of it (the
1843 * first byte it couldn't dissect is at an offset
1844 * of "pinfo->desegment_offset" from the beginning
1845 * of the payload, and that's 0).
1846 * Just mark this as TCP.
1848 if (check_col(pinfo->cinfo, COL_PROTOCOL)){
1849 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
1851 if (check_col(pinfo->cinfo, COL_INFO)){
1852 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
1857 * Show what's left in the packet as just raw TCP segment
1859 * XXX - remember what protocol the last subdissector
1860 * was, and report it as a continuation of that, instead?
1862 nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
1863 proto_tree_add_text(tcp_tree, tvb, deseg_offset, -1,
1864 "TCP segment data (%u byte%s)", nbytes,
1865 plurality(nbytes, "", "s"));
1867 pinfo->can_desegment=0;
1868 pinfo->desegment_offset = 0;
1869 pinfo->desegment_len = 0;
1871 if(another_pdu_follows){
1872 /* there was another pdu following this one. */
1873 pinfo->can_desegment=2;
1874 /* we also have to prevent the dissector from changing the
1875 * PROTOCOL and INFO colums since what follows may be an
1876 * incomplete PDU and we dont want it be changed back from
1877 * <Protocol> to <TCP>
1878 * XXX There is no good way to block the PROTOCOL column
1879 * from being changed yet so we set the entire row unwritable.
1881 col_set_fence(pinfo->cinfo, COL_INFO);
1882 col_set_writable(pinfo->cinfo, FALSE);
1883 offset += another_pdu_follows;
1884 seq += another_pdu_follows;
1890 * Loop for dissecting PDUs within a TCP stream; assumes that a PDU
1891 * consists of a fixed-length chunk of data that contains enough information
1892 * to determine the length of the PDU, followed by rest of the PDU.
1894 * The first three arguments are the arguments passed to the dissector
1895 * that calls this routine.
1897 * "proto_desegment" is the dissector's flag controlling whether it should
1898 * desegment PDUs that cross TCP segment boundaries.
1900 * "fixed_len" is the length of the fixed-length part of the PDU.
1902 * "get_pdu_len()" is a routine called to get the length of the PDU from
1903 * the fixed-length part of the PDU; it's passed "pinfo", "tvb" and "offset".
1905 * "dissect_pdu()" is the routine to dissect a PDU.
1908 tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1909 gboolean proto_desegment, guint fixed_len,
1910 guint (*get_pdu_len)(packet_info *, tvbuff_t *, int),
1911 dissector_t dissect_pdu)
1913 volatile int offset = 0;
1915 guint length_remaining;
1919 proto_item *item=NULL;
1921 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1923 * We use "tvb_ensure_length_remaining()" to make sure there actually
1924 * *is* data remaining. The protocol we're handling could conceivably
1925 * consists of a sequence of fixed-length PDUs, and therefore the
1926 * "get_pdu_len" routine might not actually fetch anything from
1927 * the tvbuff, and thus might not cause an exception to be thrown if
1928 * we've run past the end of the tvbuff.
1930 * This means we're guaranteed that "length_remaining" is positive.
1932 length_remaining = tvb_ensure_length_remaining(tvb, offset);
1935 * Can we do reassembly?
1937 if (proto_desegment && pinfo->can_desegment) {
1939 * Yes - is the fixed-length part of the PDU split across segment
1942 if (length_remaining < fixed_len) {
1944 * Yes. Tell the TCP dissector where the data for this message
1945 * starts in the data it handed us, and how many more bytes we
1948 pinfo->desegment_offset = offset;
1949 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1955 * Get the length of the PDU.
1957 plen = (*get_pdu_len)(pinfo, tvb, offset);
1958 if (plen < fixed_len) {
1962 * 1) the length value extracted from the fixed-length portion
1963 * doesn't include the fixed-length portion's length, and
1964 * was so large that, when the fixed-length portion's
1965 * length was added to it, the total length overflowed;
1967 * 2) the length value extracted from the fixed-length portion
1968 * includes the fixed-length portion's length, and the value
1969 * was less than the fixed-length portion's length, i.e. it
1972 * Report this as a bounds error.
1974 show_reported_bounds_error(tvb, pinfo, tree);
1978 * Display the PDU length as a field
1980 item=proto_tree_add_uint(pinfo->tcp_tree, hf_tcp_pdu_size, tvb, offset, plen, plen);
1981 PROTO_ITEM_SET_GENERATED(item);
1985 /* give a hint to TCP where the next PDU starts
1986 * so that it can attempt to find it in case it starts
1987 * somewhere in the middle of a segment.
1989 if(!pinfo->fd->flags.visited && tcp_analyze_seq){
1990 guint remaining_bytes;
1991 remaining_bytes=tvb_reported_length_remaining(tvb, offset);
1992 if(plen>remaining_bytes){
1993 pinfo->want_pdu_tracking=2;
1994 pinfo->bytes_until_next_pdu=plen-remaining_bytes;
1999 * Can we do reassembly?
2001 if (proto_desegment && pinfo->can_desegment) {
2003 * Yes - is the PDU split across segment boundaries?
2005 if (length_remaining < plen) {
2007 * Yes. Tell the TCP dissector where the data for this message
2008 * starts in the data it handed us, and how many more bytes we
2011 pinfo->desegment_offset = offset;
2012 pinfo->desegment_len = plen - length_remaining;
2018 * Construct a tvbuff containing the amount of the payload we have
2019 * available. Make its reported length the amount of data in the PDU.
2021 * XXX - if reassembly isn't enabled. the subdissector will throw a
2022 * BoundsError exception, rather than a ReportedBoundsError exception.
2023 * We really want a tvbuff where the length is "length", the reported
2024 * length is "plen", and the "if the snapshot length were infinite"
2025 * length is the minimum of the reported length of the tvbuff handed
2026 * to us and "plen", with a new type of exception thrown if the offset
2027 * is within the reported length but beyond that third length, with
2028 * that exception getting the "Unreassembled Packet" error.
2030 length = length_remaining;
2033 next_tvb = tvb_new_subset(tvb, offset, length, plen);
2038 * Catch the ReportedBoundsError exception; if this particular message
2039 * happens to get a ReportedBoundsError exception, that doesn't mean
2040 * that we should stop dissecting PDUs within this frame or chunk of
2043 * If it gets a BoundsError, we can stop, as there's nothing more to
2044 * see, so we just re-throw it.
2047 (*dissect_pdu)(next_tvb, pinfo, tree);
2049 CATCH(BoundsError) {
2052 CATCH(ReportedBoundsError) {
2053 show_reported_bounds_error(tvb, pinfo, tree);
2058 * Step to the next PDU.
2059 * Make sure we don't overflow.
2061 offset_before = offset;
2063 if (offset <= offset_before)
2069 tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val)
2071 if (check_col(pinfo->cinfo, COL_INFO))
2072 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%u", abbrev, val);
2075 /* Supports the reporting the contents of a parsed SCPS capabilities vector */
2077 tcp_info_append_str(packet_info *pinfo, const char *abbrev, const char *val)
2079 if (check_col(pinfo->cinfo, COL_INFO))
2080 col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%s]", abbrev, val);
2084 dissect_tcpopt_maxseg(const ip_tcp_opt *optp, tvbuff_t *tvb,
2085 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2087 proto_item *hidden_item;
2090 mss = tvb_get_ntohs(tvb, offset + 2);
2091 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_mss, tvb, offset,
2093 PROTO_ITEM_SET_HIDDEN(hidden_item);
2094 proto_tree_add_uint_format(opt_tree, hf_tcp_option_mss_val, tvb, offset,
2095 optlen, mss, "%s: %u bytes", optp->name, mss);
2096 tcp_info_append_uint(pinfo, "MSS", mss);
2100 dissect_tcpopt_wscale(const ip_tcp_opt *optp, tvbuff_t *tvb,
2101 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2103 proto_item *hidden_item;
2105 struct tcp_analysis *tcpd=NULL;
2107 tcpd=get_tcp_conversation_data(NULL,pinfo);
2109 ws = tvb_get_guint8(tvb, offset + 2);
2110 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_wscale, tvb,
2111 offset, optlen, TRUE);
2112 PROTO_ITEM_SET_HIDDEN(hidden_item);
2113 proto_tree_add_uint_format(opt_tree, hf_tcp_option_wscale_val, tvb,
2114 offset, optlen, ws, "%s: %u (multiply by %u)",
2115 optp->name, ws, 1 << ws);
2116 tcp_info_append_uint(pinfo, "WS", ws);
2117 if(!pinfo->fd->flags.visited && tcp_analyze_seq && tcp_relative_seq){
2118 pdu_store_window_scale_option(ws, tcpd);
2123 dissect_tcpopt_sack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2124 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2126 proto_tree *field_tree = NULL;
2127 proto_item *tf=NULL;
2128 proto_item *hidden_item;
2129 guint32 leftedge, rightedge;
2130 struct tcp_analysis *tcpd=NULL;
2133 if(tcp_analyze_seq && tcp_relative_seq){
2134 /* find(or create if needed) the conversation for this tcp session */
2135 tcpd=get_tcp_conversation_data(NULL,pinfo);
2138 base_ack=tcpd->rev->base_seq;
2142 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
2143 offset += 2; /* skip past type and length */
2144 optlen -= 2; /* subtract size of type and length */
2145 while (optlen > 0) {
2146 if (field_tree == NULL) {
2147 /* Haven't yet made a subtree out of this option. Do so. */
2148 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2149 hidden_item = proto_tree_add_boolean(field_tree, hf_tcp_option_sack, tvb,
2150 offset, optlen, TRUE);
2151 PROTO_ITEM_SET_HIDDEN(hidden_item);
2154 proto_tree_add_text(field_tree, tvb, offset, optlen,
2155 "(suboption would go past end of option)");
2158 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;
2159 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
2160 offset, 4, leftedge,
2161 "left edge = %u%s", leftedge,
2162 tcp_relative_seq ? " (relative)" : "");
2166 proto_tree_add_text(field_tree, tvb, offset, optlen,
2167 "(suboption would go past end of option)");
2170 /* XXX - check whether it goes past end of packet */
2171 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;
2173 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
2174 offset+4, 4, rightedge,
2175 "right edge = %u%s", rightedge,
2176 tcp_relative_seq ? " (relative)" : "");
2177 tcp_info_append_uint(pinfo, "SLE", leftedge);
2178 tcp_info_append_uint(pinfo, "SRE", rightedge);
2179 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);
2185 dissect_tcpopt_echo(const ip_tcp_opt *optp, tvbuff_t *tvb,
2186 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2188 proto_item *hidden_item;
2191 echo = tvb_get_ntohl(tvb, offset + 2);
2192 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_echo, tvb, offset,
2194 PROTO_ITEM_SET_HIDDEN(hidden_item);
2195 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2196 "%s: %u", optp->name, echo);
2197 tcp_info_append_uint(pinfo, "ECHO", echo);
2201 dissect_tcpopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
2202 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2204 proto_item *hidden_item;
2207 tsv = tvb_get_ntohl(tvb, offset + 2);
2208 tser = tvb_get_ntohl(tvb, offset + 6);
2209 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_time_stamp, tvb,
2210 offset, optlen, TRUE);
2211 PROTO_ITEM_SET_HIDDEN(hidden_item);
2212 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2213 "%s: TSval %u, TSecr %u", optp->name, tsv, tser);
2214 tcp_info_append_uint(pinfo, "TSV", tsv);
2215 tcp_info_append_uint(pinfo, "TSER", tser);
2219 dissect_tcpopt_cc(const ip_tcp_opt *optp, tvbuff_t *tvb,
2220 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2222 proto_item *hidden_item;
2225 cc = tvb_get_ntohl(tvb, offset + 2);
2226 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_cc, tvb, offset,
2228 PROTO_ITEM_SET_HIDDEN(hidden_item);
2229 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2230 "%s: %u", optp->name, cc);
2231 tcp_info_append_uint(pinfo, "CC", cc);
2235 dissect_tcpopt_qs(const ip_tcp_opt *optp, tvbuff_t *tvb,
2236 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2238 /* Quick-Start TCP option, as defined by RFC4782 */
2239 static const value_string qs_rates[] = {
2245 { 5, "1.28 Mbit/s"},
2246 { 6, "2.56 Mbit/s"},
2247 { 7, "5.12 Mbit/s"},
2248 { 8, "10.24 Mbit/s"},
2249 { 9, "20.48 Mbit/s"},
2250 {10, "40.96 Mbit/s"},
2251 {11, "81.92 Mbit/s"},
2252 {12, "163.84 Mbit/s"},
2253 {13, "327.68 Mbit/s"},
2254 {14, "655.36 Mbit/s"},
2255 {15, "1.31072 Gbit/s"},
2258 proto_item *hidden_item;
2260 guint8 rate = tvb_get_guint8(tvb, offset + 2) & 0x0f;
2262 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_qs, tvb, offset,
2264 PROTO_ITEM_SET_HIDDEN(hidden_item);
2265 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2266 "%s: Rate response, %s, TTL diff %u ", optp->name,
2267 val_to_str(rate, qs_rates, "Unknown"),
2268 tvb_get_guint8(tvb, offset + 3));
2269 if (check_col(pinfo->cinfo, COL_INFO))
2270 col_append_fstr(pinfo->cinfo, COL_INFO, " QSresp=%s", val_to_str(rate, qs_rates, "Unknown"));
2275 dissect_tcpopt_scps(const ip_tcp_opt *optp, tvbuff_t *tvb,
2276 int offset, guint optlen, packet_info *pinfo,
2277 proto_tree *opt_tree)
2279 struct tcp_analysis *tcpd=NULL;
2280 proto_tree *field_tree = NULL;
2283 proto_item *tf = NULL, *hidden_item;
2284 gchar flags[64] = "<None>";
2285 gchar *fstr[] = {"BETS", "SNACK1", "SNACK2", "COMP", "NLTS", "RESV1", "RESV2", "RESV3"};
2290 tcpd = get_tcp_conversation_data(NULL,pinfo);
2292 /* check direction and get ua lists */
2293 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
2295 /* if the addresses are equal, match the ports instead */
2297 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
2301 flow =&(tcpd->flow1);
2303 flow =&(tcpd->flow2);
2305 /* If the option length == 4, this is a real SCPS capability option
2306 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
2307 * (SCPS-TP)" Section 3.2.3 for definition.
2310 capvector = tvb_get_guint8(tvb, offset + 2);
2313 /* Decode the capabilities vector for display */
2314 for (i = 0; i < 5; i++) {
2316 if (capvector & bpos) {
2318 g_strlcat(flags, ", ", 64);
2320 g_strlcat(flags, fstr[i], 64);
2324 /* If lossless header compression is offered, there will be a
2325 * single octet connectionId following the capabilities vector
2327 if (capvector & 0x10)
2328 connid = tvb_get_guint8(tvb, offset + 3);
2332 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector, tvb,
2333 offset, optlen, capvector,
2335 optp->name, capvector, flags);
2336 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_scps,
2337 tvb, offset, optlen, TRUE);
2338 PROTO_ITEM_SET_HIDDEN(hidden_item);
2340 field_tree = proto_item_add_subtree(tf, ett_tcp_option_scps);
2342 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_bets, tvb,
2343 offset + 13, 1, capvector);
2344 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_snack1, tvb,
2345 offset + 13, 1, capvector);
2346 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_snack2, tvb,
2347 offset + 13, 1, capvector);
2348 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_compress, tvb,
2349 offset + 13, 1, capvector);
2350 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_nlts, tvb,
2351 offset + 13, 1, capvector);
2352 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv1, tvb,
2353 offset + 13, 1, capvector);
2354 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv2, tvb,
2355 offset + 13, 1, capvector);
2356 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv3, tvb,
2357 offset + 13, 1, capvector);
2359 tcp_info_append_str(pinfo, "SCPS", flags);
2361 flow->scps_capable = 1;
2364 tcp_info_append_uint(pinfo, "Connection ID", connid);
2367 /* The option length != 4, so this is an infamous "extended capabilities
2368 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2369 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
2371 * As the format of this option is only partially defined (it is
2372 * a community (or more likely vendor) defined format beyond that, so
2373 * at least for now, we only parse the standardized portion of the option.
2375 guint8 local_offset = 2;
2376 guint8 binding_space;
2377 guint8 extended_cap_length;
2379 if (flow->scps_capable != 1) {
2380 /* There was no SCPS capabilities option preceeding this */
2381 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2382 tvb, offset, optlen, 0, "%s: (%d %s)",
2383 "Illegal SCPS Extended Capabilities",
2388 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2389 tvb, offset, optlen, 0, "%s: (%d %s)",
2390 "SCPS Extended Capabilities",
2393 field_tree=proto_item_add_subtree(tf, ett_tcp_option_scps_extended);
2394 /* There may be multiple binding spaces included in a single option,
2395 * so we will semi-parse each of the stacked binding spaces - skipping
2396 * over the octets following the binding space identifier and length.
2399 while (optlen > local_offset) {
2400 proto_item *hidden_item;
2402 /* 1st octet is Extended Capability Binding Space */
2403 binding_space = tvb_get_guint8(tvb, (offset + local_offset));
2405 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
2406 * As defined by the specification, this length is exclusive of the
2407 * octets containing the extended capability type and length
2410 extended_cap_length =
2411 (tvb_get_guint8(tvb, (offset + local_offset + 1)) >> 4);
2413 /* Convert the extended capabilities length into bytes for display */
2414 extended_cap_length = (extended_cap_length << 1);
2416 proto_tree_add_text(field_tree, tvb, offset + local_offset, 2,
2417 "\tBinding Space %u",
2419 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding,
2420 tvb, (offset + local_offset), 1,
2423 PROTO_ITEM_SET_HIDDEN(hidden_item);
2425 /* Step past the binding space and length octets */
2428 proto_tree_add_text(field_tree, tvb, offset + local_offset,
2429 extended_cap_length,
2430 "\tBinding Space Data (%u bytes)",
2431 extended_cap_length);
2433 tcp_info_append_uint(pinfo, "EXCAP", binding_space);
2435 /* Step past the Extended capability data
2436 * Treat the extended capability data area as opaque;
2437 * If one desires to parse the extended capability data
2438 * (say, in a vendor aware build of wireshark), it would
2441 local_offset += extended_cap_length;
2447 /* This is called for SYN+ACK packets and the purpose is to verify that
2448 * the SCPS capabilities option has been successfully negotiated for the flow.
2449 * If the SCPS capabilities option was offered by only one party, the
2450 * proactively set scps_capable attribute of the flow (set upon seeing
2451 * the first instance of the SCPS option) is revoked.
2454 verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd)
2459 if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) {
2460 tcpd->flow1.scps_capable = 0;
2461 tcpd->flow2.scps_capable = 0;
2464 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_NOTE,
2465 "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated");
2470 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2471 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
2474 dissect_tcpopt_snack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2475 int offset, guint optlen, packet_info *pinfo,
2476 proto_tree *opt_tree)
2478 struct tcp_analysis *tcpd=NULL;
2479 guint16 relative_hole_offset;
2480 guint16 relative_hole_size;
2481 guint16 base_mss = 0;
2485 char null_modifier[] = "\0";
2486 char relative_modifier[] = "(relative)";
2487 char *modifier = null_modifier;
2488 proto_item *hidden_item;
2490 tcpd = get_tcp_conversation_data(NULL,pinfo);
2492 /* The SNACK option reports missing data with a granualarity of segments. */
2493 relative_hole_offset = tvb_get_ntohs(tvb, offset + 2);
2494 relative_hole_size = tvb_get_ntohs(tvb, offset + 4);
2496 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_snack, tvb,
2497 offset, optlen, TRUE);
2498 PROTO_ITEM_SET_HIDDEN(hidden_item);
2500 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_offset,
2501 tvb, offset, optlen, relative_hole_offset);
2502 PROTO_ITEM_SET_HIDDEN(hidden_item);
2504 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_size,
2505 tvb, offset, optlen, relative_hole_size);
2506 PROTO_ITEM_SET_HIDDEN(hidden_item);
2507 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2508 "%s: Offset %u, Size %u", optp->name,
2509 relative_hole_offset, relative_hole_size);
2511 ack = tvb_get_ntohl(tvb, 8);
2513 if (tcp_relative_seq) {
2514 ack -= tcpd->rev->base_seq;
2515 modifier = relative_modifier;
2518 /* To aid analysis, we can use a simple but generally effective heuristic
2519 * to report the most likely boundaries of the missing data. If the
2520 * flow is scps_capable, we track the maximum sized segment that was
2521 * acknowledged by the receiver and use that as the reporting granularity.
2522 * This may be different from the negotiated MTU due to PMTUD or flows
2523 * that do not send max-sized segments.
2525 base_mss = tcpd->fwd->maxsizeacked;
2528 proto_item *hidden_item;
2529 /* Scale the reported offset and hole size by the largest segment acked */
2530 hole_start = ack + (base_mss * relative_hole_offset);
2531 hole_end = hole_start + (base_mss * relative_hole_size);
2533 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_le,
2534 tvb, offset, optlen, hole_start);
2535 PROTO_ITEM_SET_HIDDEN(hidden_item);
2537 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_re,
2538 tvb, offset, optlen, hole_end);
2539 PROTO_ITEM_SET_HIDDEN(hidden_item);
2540 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2541 "\tMissing Sequence %u - %u %s",
2542 hole_start, hole_end, modifier);
2544 tcp_info_append_uint(pinfo, "SNLE", hole_start);
2545 tcp_info_append_uint(pinfo, "SNRE", hole_end);
2547 expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_NOTE,
2548 "SNACK Sequence %u - %u %s",
2549 hole_start, hole_end, modifier);
2553 static const ip_tcp_opt tcpopts[] = {
2572 "Maximum segment size",
2576 dissect_tcpopt_maxseg
2584 dissect_tcpopt_wscale
2597 &ett_tcp_option_sack,
2624 dissect_tcpopt_timestamp
2652 "TCP MD5 signature",
2660 "SCPS capabilities",
2661 &ett_tcp_option_scps,
2668 "Selective Negative Acknowledgement",
2672 dissect_tcpopt_snack
2676 "SCPS record boundary",
2684 "SCPS corruption experienced",
2700 #define N_TCP_OPTS (sizeof tcpopts / sizeof tcpopts[0])
2702 /* Determine if there is a sub-dissector and call it; return TRUE
2703 if there was a sub-dissector, FALSE otherwise.
2705 This has been separated into a stand alone routine to other protocol
2706 dissectors can call to it, e.g., SOCKS. */
2708 static gboolean try_heuristic_first = FALSE;
2711 /* this function can be called with tcpd==NULL as from the msproxy dissector */
2713 decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
2714 proto_tree *tree, int src_port, int dst_port,
2715 struct tcp_analysis *tcpd)
2718 int low_port, high_port;
2719 int save_desegment_offset;
2720 guint32 save_desegment_len;
2722 /* dont call subdissectors for keepalive or zerowindowprobes
2723 * even though they do contain payload "data"
2724 * keeaplives just contain garbage and zwp contain too little data (1 byte)
2727 if(tcpd && tcpd->ta){
2728 if(tcpd->ta->flags&(TCP_A_ZERO_WINDOW_PROBE|TCP_A_KEEP_ALIVE)){
2733 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
2735 /* determine if this packet is part of a conversation and call dissector */
2736 /* for the conversation if available */
2738 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP,
2739 src_port, dst_port, next_tvb, pinfo, tree)){
2740 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2744 if (try_heuristic_first) {
2745 /* do lookup with the heuristic subdissector table */
2746 save_desegment_offset = pinfo->desegment_offset;
2747 save_desegment_len = pinfo->desegment_len;
2748 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
2749 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2753 * They rejected the packet; make sure they didn't also request
2754 * desegmentation (we could just override the request, but
2755 * rejecting a packet *and* requesting desegmentation is a sign
2756 * of the dissector's code needing clearer thought, so we fail
2757 * so that the problem is made more obvious).
2759 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
2760 save_desegment_len == pinfo->desegment_len);
2763 /* Do lookups with the subdissector table.
2764 We try the port number with the lower value first, followed by the
2765 port number with the higher value. This means that, for packets
2766 where a dissector is registered for *both* port numbers:
2768 1) we pick the same dissector for traffic going in both directions;
2770 2) we prefer the port number that's more likely to be the right
2771 one (as that prefers well-known ports to reserved ports);
2773 although there is, of course, no guarantee that any such strategy
2774 will always pick the right port number.
2776 XXX - we ignore port numbers of 0, as some dissectors use a port
2777 number of 0 to disable the port. */
2778 if (src_port > dst_port) {
2779 low_port = dst_port;
2780 high_port = src_port;
2782 low_port = src_port;
2783 high_port = dst_port;
2785 if (low_port != 0 &&
2786 dissector_try_port(subdissector_table, low_port, next_tvb, pinfo, tree)){
2787 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2790 if (high_port != 0 &&
2791 dissector_try_port(subdissector_table, high_port, next_tvb, pinfo, tree)){
2792 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2796 if (!try_heuristic_first) {
2797 /* do lookup with the heuristic subdissector table */
2798 save_desegment_offset = pinfo->desegment_offset;
2799 save_desegment_len = pinfo->desegment_len;
2800 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
2801 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2805 * They rejected the packet; make sure they didn't also request
2806 * desegmentation (we could just override the request, but
2807 * rejecting a packet *and* requesting desegmentation is a sign
2808 * of the dissector's code needing clearer thought, so we fail
2809 * so that the problem is made more obvious).
2811 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
2812 save_desegment_len == pinfo->desegment_len);
2815 /* Oh, well, we don't know this; dissect it as data. */
2816 call_dissector(data_handle,next_tvb, pinfo, tree);
2818 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2823 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
2824 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
2825 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
2826 struct tcp_analysis *tcpd)
2828 pinfo->want_pdu_tracking=0;
2832 /*qqq see if it is an unaligned PDU */
2833 if(tcpd && tcp_analyze_seq && (!tcp_desegment)){
2835 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
2836 seq, nxtseq, tcpd->fwd->multisegment_pdus);
2840 /* if offset is -1 this means that this segment is known
2841 * to be fully inside a previously detected pdu
2842 * so we dont even need to try to dissect it either.
2845 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
2848 * We succeeded in handing off to a subdissector.
2850 * Is this a TCP segment or a reassembled chunk of
2854 /* if !visited, check want_pdu_tracking and
2855 store it in table */
2856 if(tcpd && (!pinfo->fd->flags.visited) &&
2857 tcp_analyze_seq && pinfo->want_pdu_tracking){
2859 pdu_store_sequencenumber_of_next_pdu(
2862 nxtseq+pinfo->bytes_until_next_pdu,
2863 tcpd->fwd->multisegment_pdus);
2870 /* We got an exception. At this point the dissection is
2871 * completely aborted and execution will be transfered back
2872 * to (probably) the frame dissector.
2873 * Here we have to place whatever we want the dissector
2874 * to do before aborting the tcp dissection.
2877 * Is this a TCP segment or a reassembled chunk of TCP
2882 * It's from a TCP segment.
2884 * if !visited, check want_pdu_tracking and store it
2887 if(tcpd && (!pinfo->fd->flags.visited) && tcp_analyze_seq && pinfo->want_pdu_tracking){
2889 pdu_store_sequencenumber_of_next_pdu(pinfo,
2891 nxtseq+pinfo->bytes_until_next_pdu,
2892 tcpd->fwd->multisegment_pdus);
2902 dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,
2903 guint32 nxtseq, guint32 sport, guint32 dport,
2904 proto_tree *tree, proto_tree *tcp_tree,
2905 struct tcp_analysis *tcpd)
2907 gboolean save_fragmented;
2909 /* Can we desegment this segment? */
2910 if (pinfo->can_desegment) {
2912 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
2915 /* No - just call the subdissector.
2916 Mark this as fragmented, so if somebody throws an exception,
2917 we don't report it as a malformed frame. */
2918 save_fragmented = pinfo->fragmented;
2919 pinfo->fragmented = TRUE;
2920 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
2921 seq, nxtseq, TRUE, tcpd);
2922 pinfo->fragmented = save_fragmented;
2927 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2929 guint8 th_off_x2; /* combines th_off and th_x2 */
2932 proto_tree *tcp_tree = NULL, *field_tree = NULL;
2933 proto_item *ti = NULL, *tf, *hidden_item;
2935 emem_strbuf_t *flags_strbuf = ep_strbuf_new_label("<None>");
2936 const gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR"};
2944 guint16 computed_cksum;
2945 guint16 real_window;
2946 guint length_remaining;
2947 gboolean desegment_ok;
2948 struct tcpinfo tcpinfo;
2949 struct tcpheader *tcph;
2950 proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL;
2951 conversation_t *conv=NULL;
2952 struct tcp_analysis *tcpd=NULL;
2953 struct tcp_per_packet_data_t *tcppd=NULL;
2955 proto_tree *checksum_tree;
2959 tcph=ep_alloc(sizeof(struct tcpheader));
2960 SET_ADDRESS(&tcph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
2961 SET_ADDRESS(&tcph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
2963 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2964 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
2966 /* Clear out the Info column. */
2967 if (check_col(pinfo->cinfo, COL_INFO))
2968 col_clear(pinfo->cinfo, COL_INFO);
2970 tcph->th_sport = tvb_get_ntohs(tvb, offset);
2971 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
2972 if (check_col(pinfo->cinfo, COL_INFO)) {
2973 col_append_fstr(pinfo->cinfo, COL_INFO, "%s > %s",
2974 get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
2977 if (tcp_summary_in_tree) {
2978 ti = proto_tree_add_protocol_format(tree, proto_tcp, tvb, 0, -1,
2979 "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
2980 get_tcp_port(tcph->th_sport), tcph->th_sport,
2981 get_tcp_port(tcph->th_dport), tcph->th_dport);
2984 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, FALSE);
2986 tcp_tree = proto_item_add_subtree(ti, ett_tcp);
2987 pinfo->tcp_tree=tcp_tree;
2989 proto_tree_add_uint_format(tcp_tree, hf_tcp_srcport, tvb, offset, 2, tcph->th_sport,
2990 "Source port: %s (%u)", get_tcp_port(tcph->th_sport), tcph->th_sport);
2991 proto_tree_add_uint_format(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, tcph->th_dport,
2992 "Destination port: %s (%u)", get_tcp_port(tcph->th_dport), tcph->th_dport);
2993 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset, 2, tcph->th_sport);
2994 PROTO_ITEM_SET_HIDDEN(hidden_item);
2995 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, tcph->th_dport);
2996 PROTO_ITEM_SET_HIDDEN(hidden_item);
2998 /* If we're dissecting the headers of a TCP packet in an ICMP packet
2999 * then go ahead and put the sequence numbers in the tree now (because
3000 * they won't be put in later because the ICMP packet only contains up
3001 * to the sequence number).
3002 * We should only need to do this for IPv4 since IPv6 will hopefully
3003 * carry enough TCP payload for this dissector to put the sequence
3004 * numbers in via the regular code path.
3006 if (pinfo->layer_names != NULL && pinfo->layer_names->str != NULL) {
3007 /* use strstr because g_strrstr is only present in glib2.0 and
3008 * g_str_has_suffix in glib2.2
3010 if (strstr(pinfo->layer_names->str, "icmp:ip") != NULL)
3011 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, FALSE);
3015 /* Set the source and destination port numbers as soon as we get them,
3016 so that they're available to the "Follow TCP Stream" code even if
3017 we throw an exception dissecting the rest of the TCP header. */
3018 pinfo->ptype = PT_TCP;
3019 pinfo->srcport = tcph->th_sport;
3020 pinfo->destport = tcph->th_dport;
3022 tcph->th_seq = tvb_get_ntohl(tvb, offset + 4);
3023 tcph->th_ack = tvb_get_ntohl(tvb, offset + 8);
3024 th_off_x2 = tvb_get_guint8(tvb, offset + 12);
3025 tcph->th_flags = tvb_get_guint8(tvb, offset + 13);
3026 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
3027 real_window = tcph->th_win;
3028 tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
3030 /* find(or create if needed) the conversation for this tcp session */
3031 conv=get_tcp_conversation(pinfo);
3032 tcpd=get_tcp_conversation_data(conv,pinfo);
3034 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, conv->index);
3035 PROTO_ITEM_SET_GENERATED(item);
3037 /* If this is a SYN packet, then check if it's seq-nr is different
3038 * from the base_seq of the retrieved conversation. If this is the
3039 * case, create a new conversation with the same addresses and ports
3040 * and set the TA_PORTS_REUSED flag. If the seq-nr is the same as
3041 * the base_seq, then do nothing so it will be marked as a retrans-
3044 if(tcpd && ((tcph->th_flags&(TH_SYN|TH_ACK))==TH_SYN) &&
3045 (tcpd->fwd->base_seq!=0) &&
3046 (tcph->th_seq!=tcpd->fwd->base_seq) ) {
3047 if (!(pinfo->fd->flags.visited)) {
3048 conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3049 tcpd=get_tcp_conversation_data(conv,pinfo);
3052 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
3053 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
3057 /* Do we need to calculate timestamps relative to the tcp-stream? */
3058 if (tcp_calculate_ts) {
3059 tcppd = p_get_proto_data(pinfo->fd, proto_tcp);
3062 * Calculate the timestamps relative to this conversation (but only on the
3063 * first run when frames are accessed sequentially)
3065 if (!(pinfo->fd->flags.visited))
3066 tcp_calculate_timestamps(pinfo, tcpd, tcppd);
3068 /* Fill the conversation timestamp columns */
3069 if (tcpd && check_col(pinfo->cinfo, COL_REL_CONV_TIME)) {
3070 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
3071 col_set_time(pinfo->cinfo, COL_REL_CONV_TIME, &ts, "tcp.time_relative");
3074 if (check_col(pinfo->cinfo, COL_DELTA_CONV_TIME)) {
3076 col_set_time(pinfo->cinfo, COL_DELTA_CONV_TIME, &tcppd->ts_del, "tcp.time_delta");
3082 * If we've been handed an IP fragment, we don't know how big the TCP
3083 * segment is, so don't do anything that requires that we know that.
3085 * The same applies if we're part of an error packet. (XXX - if the
3086 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
3087 * header says it is" length in the tvbuff, we could use that; such
3088 * a length might also be useful for handling packets where the IP
3089 * length is bigger than the actual data available in the frame; the
3090 * dissectors should trust that length, and then throw a
3091 * ReportedBoundsError exception when they go past the end of the frame.)
3093 * We also can't determine the segment length if the reported length
3094 * of the TCP packet is less than the TCP header length.
3096 reported_len = tvb_reported_length(tvb);
3098 if (!pinfo->fragmented && !pinfo->in_error_pkt) {
3099 if (reported_len < tcph->th_hlen) {
3101 pi = proto_tree_add_text(tcp_tree, tvb, offset, 0,
3102 "Short segment. Segment/fragment does not contain a full TCP header"
3103 " (might be NMAP or someone else deliberately sending unusual packets)");
3104 PROTO_ITEM_SET_GENERATED(pi);
3105 expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_WARN, "Short segment");
3106 tcph->th_have_seglen = FALSE;
3108 /* Compute the length of data in this segment. */
3109 tcph->th_seglen = reported_len - tcph->th_hlen;
3110 tcph->th_have_seglen = TRUE;
3112 if (tree) { /* Add the seglen as an invisible field */
3114 hidden_item = proto_tree_add_uint(ti, hf_tcp_len, tvb, offset+12, 1, tcph->th_seglen);
3115 PROTO_ITEM_SET_HIDDEN(hidden_item);
3120 /* handle TCP seq# analysis parse all new segments we see */
3121 if(tcp_analyze_seq){
3122 if(!(pinfo->fd->flags.visited)){
3123 tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd);
3125 if(tcp_relative_seq){
3126 tcp_get_relative_seq_ack(&(tcph->th_seq), &(tcph->th_ack), &(tcph->th_win), tcpd);
3130 /* Compute the sequence number of next octet after this segment. */
3131 nxtseq = tcph->th_seq + tcph->th_seglen;
3134 tcph->th_have_seglen = FALSE;
3136 if (check_col(pinfo->cinfo, COL_INFO) || tree) {
3137 gboolean first_flag = TRUE;
3138 for (i = 0; i < 8; i++) {
3140 if (tcph->th_flags & bpos) {
3142 ep_strbuf_truncate(flags_strbuf, 0);
3144 ep_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ", fstr[i]);
3150 if (check_col(pinfo->cinfo, COL_INFO)) {
3151 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] Seq=%u", flags_strbuf->str, tcph->th_seq);
3152 if (tcph->th_flags&TH_ACK) {
3153 col_append_fstr(pinfo->cinfo, COL_INFO, " Ack=%u", tcph->th_ack);
3155 if (tcph->th_flags&TH_SYN) { /* SYNs are never scaled */
3156 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", real_window);
3158 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", tcph->th_win);
3163 if (tcp_summary_in_tree) {
3164 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
3166 if(tcp_relative_seq){
3167 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);
3169 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
3173 if (tcph->th_hlen < TCPH_MIN_LEN) {
3174 /* Give up at this point; we put the source and destination port in
3175 the tree, before fetching the header length, so that they'll
3176 show up if this is in the failing packet in an ICMP error packet,
3177 but it's now time to give up if the header length is bogus. */
3178 if (check_col(pinfo->cinfo, COL_INFO))
3179 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
3180 tcph->th_hlen, TCPH_MIN_LEN);
3182 proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
3183 "Header length: %u bytes (bogus, must be at least %u)", tcph->th_hlen,
3190 if (tcp_summary_in_tree) {
3191 if(tcph->th_flags&TH_ACK){
3192 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
3194 if (tcph->th_have_seglen)
3195 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
3197 proto_item_set_len(ti, tcph->th_hlen);
3198 if (tcph->th_have_seglen) {
3199 if (nxtseq != tcph->th_seq) {
3200 if(tcp_relative_seq){
3201 tf=proto_tree_add_uint_format(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "Next sequence number: %u (relative sequence number)", nxtseq);
3203 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
3205 PROTO_ITEM_SET_GENERATED(tf);
3208 if (tcph->th_flags & TH_ACK) {
3209 if(tcp_relative_seq){
3210 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);
3212 proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
3215 /* Verify that the ACK field is zero */
3216 if(tvb_get_ntohl(tvb, offset+8) != 0){
3217 proto_tree_add_text(tcp_tree, tvb, offset+8, 4,"Acknowledgement number: Broken TCP. The acknowledge field is nonzero while the ACK flag is not set");
3220 proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
3221 "Header length: %u bytes", tcph->th_hlen);
3222 tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 13, 1,
3223 tcph->th_flags, "Flags: 0x%02x (%s)", tcph->th_flags, flags_strbuf->str);
3224 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
3225 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
3226 proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, tvb, offset + 13, 1, tcph->th_flags);
3227 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
3228 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
3229 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
3230 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
3231 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
3232 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
3234 && (tcph->th_win!=real_window)
3235 && !(tcph->th_flags&TH_SYN) ){ /* SYNs are never scaled */
3236 proto_tree_add_uint_format(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win, "Window size: %u (scaled)", tcph->th_win);
3238 proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, real_window);
3242 if(tcph->th_flags & TH_SYN) {
3243 if(tcph->th_flags & TH_ACK)
3244 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK): server port %s",
3245 get_tcp_port(tcph->th_sport));
3247 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN): server port %s",
3248 get_tcp_port(tcph->th_dport));
3250 if(tcph->th_flags & TH_FIN)
3251 /* XXX - find a way to know the server port and output only that one */
3252 expert_add_info_format(pinfo, tf_fin, PI_SEQUENCE, PI_CHAT, "Connection finish (FIN)");
3253 if(tcph->th_flags & TH_RST)
3254 /* XXX - find a way to know the server port and output only that one */
3255 expert_add_info_format(pinfo, tf_rst, PI_SEQUENCE, PI_CHAT, "Connection reset (RST)");
3257 /* Supply the sequence number of the first byte and of the first byte
3258 after the segment. */
3259 tcpinfo.seq = tcph->th_seq;
3260 tcpinfo.nxtseq = nxtseq;
3261 tcpinfo.lastackseq = tcph->th_ack;
3263 /* Assume we'll pass un-reassembled data to subdissectors. */
3264 tcpinfo.is_reassembled = FALSE;
3266 pinfo->private_data = &tcpinfo;
3269 * Assume, initially, that we can't desegment.
3271 pinfo->can_desegment = 0;
3272 th_sum = tvb_get_ntohs(tvb, offset + 16);
3273 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
3274 /* The packet isn't part of an un-reassembled fragmented datagram
3275 and isn't truncated. This means we have all the data, and thus
3276 can checksum it and, unless it's being returned in an error
3277 packet, are willing to allow subdissectors to request reassembly
3280 if (tcp_check_checksum) {
3281 /* We haven't turned checksum checking off; checksum it. */
3283 /* Set up the fields of the pseudo-header. */
3284 cksum_vec[0].ptr = pinfo->src.data;
3285 cksum_vec[0].len = pinfo->src.len;
3286 cksum_vec[1].ptr = pinfo->dst.data;
3287 cksum_vec[1].len = pinfo->dst.len;
3288 cksum_vec[2].ptr = (const guint8 *)phdr;
3289 switch (pinfo->src.type) {
3292 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
3293 cksum_vec[2].len = 4;
3297 phdr[0] = g_htonl(reported_len);
3298 phdr[1] = g_htonl(IP_PROTO_TCP);
3299 cksum_vec[2].len = 8;
3303 /* TCP runs only atop IPv4 and IPv6.... */
3304 DISSECTOR_ASSERT_NOT_REACHED();
3307 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, reported_len);
3308 cksum_vec[3].len = reported_len;
3309 computed_cksum = in_cksum(cksum_vec, 4);
3310 if (computed_cksum == 0 && th_sum == 0xffff) {
3311 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3312 offset + 16, 2, th_sum,
3313 "Checksum: 0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);
3315 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3316 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3317 offset + 16, 2, FALSE);
3318 PROTO_ITEM_SET_GENERATED(item);
3319 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3320 offset + 16, 2, FALSE);
3321 PROTO_ITEM_SET_GENERATED(item);
3322 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_WARN, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)");
3324 if (check_col(pinfo->cinfo, COL_INFO))
3325 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");
3327 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
3328 desegment_ok = TRUE;
3329 } else if (computed_cksum == 0) {
3330 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3331 offset + 16, 2, th_sum, "Checksum: 0x%04x [correct]", th_sum);
3333 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3334 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3335 offset + 16, 2, TRUE);
3336 PROTO_ITEM_SET_GENERATED(item);
3337 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3338 offset + 16, 2, FALSE);
3339 PROTO_ITEM_SET_GENERATED(item);
3341 /* Checksum is valid, so we're willing to desegment it. */
3342 desegment_ok = TRUE;
3343 } else if (th_sum == 0) {
3344 /* checksum is probably fine but checksum offload is used */
3345 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3346 offset + 16, 2, th_sum, "Checksum: 0x%04x [Checksum Offloaded]", th_sum);
3348 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3349 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3350 offset + 16, 2, FALSE);
3351 PROTO_ITEM_SET_GENERATED(item);
3352 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3353 offset + 16, 2, FALSE);
3354 PROTO_ITEM_SET_GENERATED(item);
3356 /* Checksum is (probably) valid, so we're willing to desegment it. */
3357 desegment_ok = TRUE;
3359 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3360 offset + 16, 2, th_sum,
3361 "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]", th_sum,
3362 in_cksum_shouldbe(th_sum, computed_cksum));
3364 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3365 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3366 offset + 16, 2, FALSE);
3367 PROTO_ITEM_SET_GENERATED(item);
3368 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3369 offset + 16, 2, TRUE);
3370 PROTO_ITEM_SET_GENERATED(item);
3371 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
3373 if (check_col(pinfo->cinfo, COL_INFO))
3374 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");
3376 /* Checksum is invalid, so we're not willing to desegment it. */
3377 desegment_ok = FALSE;
3378 pinfo->noreassembly_reason = " [incorrect TCP checksum]";
3381 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3382 offset + 16, 2, th_sum, "Checksum: 0x%04x [validation disabled]", th_sum);
3384 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3385 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3386 offset + 16, 2, FALSE);
3387 PROTO_ITEM_SET_GENERATED(item);
3388 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3389 offset + 16, 2, FALSE);
3390 PROTO_ITEM_SET_GENERATED(item);
3392 /* We didn't check the checksum, and don't care if it's valid,
3393 so we're willing to desegment it. */
3394 desegment_ok = TRUE;
3397 /* We don't have all the packet data, so we can't checksum it... */
3398 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3399 offset + 16, 2, th_sum, "Checksum: 0x%04x [unchecked, not all data available]", th_sum);
3401 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3402 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3403 offset + 16, 2, FALSE);
3404 PROTO_ITEM_SET_GENERATED(item);
3405 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3406 offset + 16, 2, FALSE);
3407 PROTO_ITEM_SET_GENERATED(item);
3409 /* ...and aren't willing to desegment it. */
3410 desegment_ok = FALSE;
3414 /* We're willing to desegment this. Is desegmentation enabled? */
3415 if (tcp_desegment) {
3416 /* Yes - is this segment being returned in an error packet? */
3417 if (!pinfo->in_error_pkt) {
3418 /* No - indicate that we will desegment.
3419 We do NOT want to desegment segments returned in error
3420 packets, as they're not part of a TCP connection. */
3421 pinfo->can_desegment = 2;
3426 if (tcph->th_flags & TH_URG) {
3427 th_urp = tvb_get_ntohs(tvb, offset + 18);
3428 /* Export the urgent pointer, for the benefit of protocols such as
3430 tcpinfo.urgent = TRUE;
3431 tcpinfo.urgent_pointer = th_urp;
3432 if (check_col(pinfo->cinfo, COL_INFO))
3433 col_append_fstr(pinfo->cinfo, COL_INFO, " Urg=%u", th_urp);
3434 if (tcp_tree != NULL)
3435 proto_tree_add_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, th_urp);
3437 tcpinfo.urgent = FALSE;
3439 if (tcph->th_have_seglen) {
3440 if (check_col(pinfo->cinfo, COL_INFO))
3441 col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", tcph->th_seglen);
3444 /* Decode TCP options, if any. */
3445 if (tcph->th_hlen > TCPH_MIN_LEN) {
3446 /* There's more than just the fixed-length header. Decode the
3448 optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
3449 tvb_ensure_bytes_exist(tvb, offset + 20, optlen);
3450 if (tcp_tree != NULL) {
3451 guint8 *p_options = ep_tvb_memdup(tvb, offset + 20, optlen);
3452 tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
3453 optlen, p_options, "Options: (%u bytes)", optlen);
3454 field_tree = proto_item_add_subtree(tf, ett_tcp_options);
3457 dissect_ip_tcp_options(tvb, offset + 20, optlen,
3458 tcpopts, N_TCP_OPTS, TCPOPT_EOL, pinfo, field_tree);
3461 if(!pinfo->fd->flags.visited){
3462 if((tcph->th_flags & (TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
3463 /* If there was window scaling in the SYN packet but none in the SYN+ACK
3464 * then we should just forget about the windowscaling completely.
3466 if(tcp_analyze_seq && tcp_relative_seq){
3467 verify_tcp_window_scaling(tcpd);
3469 /* If the SYN or the SYN+ACK offered SCPS capabilities,
3470 * validate the flow's bidirectional scps capabilities.
3471 * The or protects against broken implementations offering
3472 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
3474 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {
3475 verify_scps(pinfo, tf_syn, tcpd);
3480 /* Skip over header + options */
3481 offset += tcph->th_hlen;
3483 /* Check the packet length to see if there's more data
3484 (it could be an ACK-only packet) */
3485 length_remaining = tvb_length_remaining(tvb, offset);
3487 if (tcph->th_have_seglen) {
3488 if( data_out_file ) {
3489 reassemble_tcp( tcph->th_seq, /* sequence number */
3490 tcph->th_ack, /* acknowledgement number */
3491 tcph->th_seglen, /* data length */
3492 (gchar*)tvb_get_ptr(tvb, offset, length_remaining), /* data */
3493 length_remaining, /* captured data length */
3494 ( tcph->th_flags & TH_SYN ), /* is syn set? */
3502 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
3503 if(tcp_analyze_seq){
3504 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd);
3507 /* handle conversation timestamps */
3508 if(tcp_calculate_ts){
3509 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
3512 tap_queue_packet(tcp_tap, pinfo, tcph);
3515 /* A FIN packet might complete reassembly so we need to explicitly
3516 * check for this here.
3518 if(tcpd && (tcph->th_flags & TH_FIN)
3519 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ){
3520 struct tcp_multisegment_pdu *msp;
3522 /* find the most previous PDU starting before this sequence number */
3523 msp=se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq-1);
3525 fragment_data *ipfd_head;
3527 ipfd_head = fragment_add(tvb, offset, pinfo, msp->first_frame,
3529 tcph->th_seq - msp->seq,
3535 /* create a new TVB structure for desegmented data */
3536 next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen, ipfd_head->datalen);
3538 /* add this tvb as a child to the original one */
3539 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
3541 /* add desegmented data to the data source list */
3542 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
3544 /* call the payload dissector
3545 * but make sure we don't offer desegmentation any more
3547 pinfo->can_desegment = 0;
3549 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq, nxtseq, FALSE, tcpd);
3551 print_tcp_fragment_tree(ipfd_head, tree, tcp_tree, pinfo, next_tvb);
3559 * XXX - what, if any, of this should we do if this is included in an
3560 * error packet? It might be nice to see the details of the packet
3561 * that caused the ICMP error, but it might not be nice to have the
3562 * dissector update state based on it.
3563 * Also, we probably don't want to run TCP taps on those packets.
3565 if (length_remaining != 0) {
3566 if (tcph->th_flags & TH_RST) {
3570 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
3572 * A TCP SHOULD allow a received RST segment to include data.
3575 * It has been suggested that a RST segment could contain
3576 * ASCII text that encoded and explained the cause of the
3577 * RST. No standard has yet been established for such
3580 * so for segments with RST we just display the data as text.
3582 proto_tree_add_text(tcp_tree, tvb, offset, length_remaining,
3584 tvb_format_text(tvb, offset, length_remaining));
3586 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
3587 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd);
3593 proto_register_tcp(void)
3595 static hf_register_info hf[] = {
3598 { "Source Port", "tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
3602 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3606 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
3610 { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
3614 { "Sequence number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
3618 { "Next sequence number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
3622 { "Acknowledgement number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
3626 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
3630 { "Flags", "tcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
3633 { &hf_tcp_flags_cwr,
3634 { "Congestion Window Reduced (CWR)", "tcp.flags.cwr", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_CWR,
3637 { &hf_tcp_flags_ecn,
3638 { "ECN-Echo", "tcp.flags.ecn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ECN,
3641 { &hf_tcp_flags_urg,
3642 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_URG,
3645 { &hf_tcp_flags_ack,
3646 { "Acknowledgement", "tcp.flags.ack", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ACK,
3649 { &hf_tcp_flags_push,
3650 { "Push", "tcp.flags.push", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_PUSH,
3653 { &hf_tcp_flags_reset,
3654 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_RST,
3657 { &hf_tcp_flags_syn,
3658 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_SYN,
3661 { &hf_tcp_flags_fin,
3662 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_FIN,
3665 /* 32 bits so we can present some values adjusted to window scaling */
3666 { &hf_tcp_window_size,
3667 { "Window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
3671 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
3672 "Details at: http://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
3674 { &hf_tcp_checksum_good,
3675 { "Good Checksum", "tcp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3676 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
3678 { &hf_tcp_checksum_bad,
3679 { "Bad Checksum", "tcp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3680 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
3682 { &hf_tcp_analysis_flags,
3683 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
3684 "This frame has some of the TCP analysis flags set", HFILL }},
3686 { &hf_tcp_analysis_retransmission,
3687 { "Retransmission", "tcp.analysis.retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
3688 "This frame is a suspected TCP retransmission", HFILL }},
3690 { &hf_tcp_analysis_fast_retransmission,
3691 { "Fast Retransmission", "tcp.analysis.fast_retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
3692 "This frame is a suspected TCP fast retransmission", HFILL }},
3694 { &hf_tcp_analysis_out_of_order,
3695 { "Out Of Order", "tcp.analysis.out_of_order", FT_NONE, BASE_NONE, NULL, 0x0,
3696 "This frame is a suspected Out-Of-Order segment", HFILL }},
3698 { &hf_tcp_analysis_reused_ports,
3699 { "TCP Port numbers reused", "tcp.analysis.reused_ports", FT_NONE, BASE_NONE, NULL, 0x0,
3700 "A new tcp session has started with previously used port numbers", HFILL }},
3702 { &hf_tcp_analysis_lost_packet,
3703 { "Previous Segment Lost", "tcp.analysis.lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
3704 "A segment before this one was lost from the capture", HFILL }},
3706 { &hf_tcp_analysis_ack_lost_packet,
3707 { "ACKed Lost Packet", "tcp.analysis.ack_lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
3708 "This frame ACKs a lost segment", HFILL }},
3710 { &hf_tcp_analysis_window_update,
3711 { "Window update", "tcp.analysis.window_update", FT_NONE, BASE_NONE, NULL, 0x0,
3712 "This frame is a tcp window update", HFILL }},
3714 { &hf_tcp_analysis_window_full,
3715 { "Window full", "tcp.analysis.window_full", FT_NONE, BASE_NONE, NULL, 0x0,
3716 "This segment has caused the allowed window to become 100% full", HFILL }},
3718 { &hf_tcp_analysis_keep_alive,
3719 { "Keep Alive", "tcp.analysis.keep_alive", FT_NONE, BASE_NONE, NULL, 0x0,
3720 "This is a keep-alive segment", HFILL }},
3722 { &hf_tcp_analysis_keep_alive_ack,
3723 { "Keep Alive ACK", "tcp.analysis.keep_alive_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3724 "This is an ACK to a keep-alive segment", HFILL }},
3726 { &hf_tcp_analysis_duplicate_ack,
3727 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3728 "This is a duplicate ACK", HFILL }},
3730 { &hf_tcp_analysis_duplicate_ack_num,
3731 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3732 "This is duplicate ACK number #", HFILL }},
3734 { &hf_tcp_analysis_duplicate_ack_frame,
3735 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3736 "This is a duplicate to the ACK in frame #", HFILL }},
3738 { &hf_tcp_continuation_to,
3739 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3740 "This is a continuation to the PDU in frame #", HFILL }},
3742 { &hf_tcp_analysis_zero_window_probe,
3743 { "Zero Window Probe", "tcp.analysis.zero_window_probe", FT_NONE, BASE_NONE, NULL, 0x0,
3744 "This is a zero-window-probe", HFILL }},
3746 { &hf_tcp_analysis_zero_window_probe_ack,
3747 { "Zero Window Probe Ack", "tcp.analysis.zero_window_probe_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3748 "This is an ACK to a zero-window-probe", HFILL }},
3750 { &hf_tcp_analysis_zero_window,
3751 { "Zero Window", "tcp.analysis.zero_window", FT_NONE, BASE_NONE, NULL, 0x0,
3752 "This is a zero-window", HFILL }},
3755 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
3758 { &hf_tcp_analysis_acks_frame,
3759 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3760 "Which previous segment is this an ACK for", HFILL}},
3762 { &hf_tcp_analysis_bytes_in_flight,
3763 { "Number of bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL, 0x0,
3764 "How many bytes are now in flight for this connection", HFILL}},
3766 { &hf_tcp_analysis_ack_rtt,
3767 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3768 "How long time it took to ACK the segment (RTT)", HFILL}},
3770 { &hf_tcp_analysis_rto,
3771 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3772 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL}},
3774 { &hf_tcp_analysis_rto_frame,
3775 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3776 "This is the frame we measure the RTO from", HFILL }},
3778 { &hf_tcp_urgent_pointer,
3779 { "Urgent pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
3782 { &hf_tcp_segment_overlap,
3783 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3784 "Segment overlaps with other segments", HFILL }},
3786 { &hf_tcp_segment_overlap_conflict,
3787 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3788 "Overlapping segments contained conflicting data", HFILL }},
3790 { &hf_tcp_segment_multiple_tails,
3791 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3792 "Several tails were found when reassembling the pdu", HFILL }},
3794 { &hf_tcp_segment_too_long_fragment,
3795 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3796 "Segment contained data past end of the pdu", HFILL }},
3798 { &hf_tcp_segment_error,
3799 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3800 "Reassembling error due to illegal segments", HFILL }},
3803 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3804 "TCP Segment", HFILL }},
3807 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
3808 "TCP Segments", HFILL }},
3810 { &hf_tcp_reassembled_in,
3811 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3812 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
3815 { "TCP Options", "tcp.options", FT_BYTES,
3816 BASE_HEX, NULL, 0x0, "TCP Options", HFILL }},
3818 { &hf_tcp_option_mss,
3819 { "TCP MSS Option", "tcp.options.mss", FT_BOOLEAN,
3820 BASE_NONE, NULL, 0x0, "TCP MSS Option", HFILL }},
3822 { &hf_tcp_option_mss_val,
3823 { "TCP MSS Option Value", "tcp.options.mss_val", FT_UINT16,
3824 BASE_DEC, NULL, 0x0, "TCP MSS Option Value", HFILL}},
3826 { &hf_tcp_option_wscale,
3827 { "TCP Window Scale Option", "tcp.options.wscale",
3829 BASE_NONE, NULL, 0x0, "TCP Window Option", HFILL}},
3831 { &hf_tcp_option_wscale_val,
3832 { "TCP Windows Scale Option Value", "tcp.options.wscale_val",
3833 FT_UINT8, BASE_DEC, NULL, 0x0, "TCP Window Scale Value",
3836 { &hf_tcp_option_sack_perm,
3837 { "TCP Sack Perm Option", "tcp.options.sack_perm",
3839 BASE_NONE, NULL, 0x0, "TCP Sack Perm Option", HFILL}},
3841 { &hf_tcp_option_sack,
3842 { "TCP Sack Option", "tcp.options.sack", FT_BOOLEAN,
3843 BASE_NONE, NULL, 0x0, "TCP Sack Option", HFILL}},
3845 { &hf_tcp_option_sack_sle,
3846 {"TCP Sack Left Edge", "tcp.options.sack_le", FT_UINT32,
3847 BASE_DEC, NULL, 0x0, "TCP Sack Left Edge", HFILL}},
3849 { &hf_tcp_option_sack_sre,
3850 {"TCP Sack Right Edge", "tcp.options.sack_re", FT_UINT32,
3851 BASE_DEC, NULL, 0x0, "TCP Sack Right Edge", HFILL}},
3853 { &hf_tcp_option_echo,
3854 { "TCP Echo Option", "tcp.options.echo", FT_BOOLEAN,
3855 BASE_NONE, NULL, 0x0, "TCP Sack Echo", HFILL}},
3857 { &hf_tcp_option_echo_reply,
3858 { "TCP Echo Reply Option", "tcp.options.echo_reply",
3860 BASE_NONE, NULL, 0x0, "TCP Echo Reply Option", HFILL}},
3862 { &hf_tcp_option_time_stamp,
3863 { "TCP Time Stamp Option", "tcp.options.time_stamp",
3865 BASE_NONE, NULL, 0x0, "TCP Time Stamp Option", HFILL}},
3867 { &hf_tcp_option_cc,
3868 { "TCP CC Option", "tcp.options.cc", FT_BOOLEAN, BASE_NONE,
3869 NULL, 0x0, "TCP CC Option", HFILL}},
3871 { &hf_tcp_option_ccnew,
3872 { "TCP CC New Option", "tcp.options.ccnew", FT_BOOLEAN,
3873 BASE_NONE, NULL, 0x0, "TCP CC New Option", HFILL}},
3875 { &hf_tcp_option_ccecho,
3876 { "TCP CC Echo Option", "tcp.options.ccecho", FT_BOOLEAN,
3877 BASE_NONE, NULL, 0x0, "TCP CC Echo Option", HFILL}},
3879 { &hf_tcp_option_md5,
3880 { "TCP MD5 Option", "tcp.options.md5", FT_BOOLEAN, BASE_NONE,
3881 NULL, 0x0, "TCP MD5 Option", HFILL}},
3883 { &hf_tcp_option_qs,
3884 { "TCP QS Option", "tcp.options.qs", FT_BOOLEAN, BASE_NONE,
3885 NULL, 0x0, "TCP QS Option", HFILL}},
3887 { &hf_tcp_option_scps,
3888 { "TCP SCPS Capabilities Option", "tcp.options.scps",
3889 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3890 "TCP SCPS Capabilities Option", HFILL}},
3892 { &hf_tcp_option_scps_vector,
3893 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
3894 FT_UINT8, BASE_DEC, NULL, 0x0,
3895 "TCP SCPS Capabilities Vector", HFILL}},
3897 { &hf_tcp_option_scps_binding,
3898 { "TCP SCPS Extended Binding Spacce",
3899 "tcp.options.scps.binding",
3900 FT_UINT8, BASE_DEC, NULL, 0x0,
3901 "TCP SCPS Extended Binding Space", HFILL}},
3903 { &hf_tcp_option_snack,
3904 { "TCP Selective Negative Acknowledgement Option",
3905 "tcp.options.snack",
3906 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3907 "TCP Selective Negative Acknowledgement Option", HFILL}},
3909 { &hf_tcp_option_snack_offset,
3910 { "TCP SNACK Offset", "tcp.options.snack.offset",
3911 FT_UINT16, BASE_DEC, NULL, 0x0,
3912 "TCP SNACK Offset", HFILL}},
3914 { &hf_tcp_option_snack_size,
3915 { "TCP SNACK Size", "tcp.options.snack.size",
3916 FT_UINT16, BASE_DEC, NULL, 0x0,
3917 "TCP SNACK Size", HFILL}},
3919 { &hf_tcp_option_snack_le,
3920 { "TCP SNACK Left Edge", "tcp.options.snack.le",
3921 FT_UINT16, BASE_DEC, NULL, 0x0,
3922 "TCP SNACK Left Edge", HFILL}},
3924 { &hf_tcp_option_snack_re,
3925 { "TCP SNACK Right Edge", "tcp.options.snack.re",
3926 FT_UINT16, BASE_DEC, NULL, 0x0,
3927 "TCP SNACK Right Edge", HFILL}},
3929 { &hf_tcp_scpsoption_flags_bets,
3930 { "Partial Reliability Capable (BETS)",
3931 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,
3932 TFS(&flags_set_truth), 0x80, "", HFILL }},
3934 { &hf_tcp_scpsoption_flags_snack1,
3935 { "Short Form SNACK Capable (SNACK1)",
3936 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,
3937 TFS(&flags_set_truth), 0x40, "", HFILL }},
3939 { &hf_tcp_scpsoption_flags_snack2,
3940 { "Long Form SNACK Capable (SNACK2)",
3941 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,
3942 TFS(&flags_set_truth), 0x20, "", HFILL }},
3944 { &hf_tcp_scpsoption_flags_compress,
3945 { "Lossless Header Compression (COMP)",
3946 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,
3947 TFS(&flags_set_truth), 0x10, "", HFILL }},
3949 { &hf_tcp_scpsoption_flags_nlts,
3950 { "Network Layer Timestamp (NLTS)",
3951 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,
3952 TFS(&flags_set_truth), 0x8, "", HFILL }},
3954 { &hf_tcp_scpsoption_flags_resv1,
3956 "tcp.options.scpsflags.reserved1", FT_BOOLEAN, 8,
3957 TFS(&flags_set_truth), 0x4, "", HFILL }},
3959 { &hf_tcp_scpsoption_flags_resv2,
3961 "tcp.options.scpsflags.reserved2", FT_BOOLEAN, 8,
3962 TFS(&flags_set_truth), 0x2, "", HFILL }},
3964 { &hf_tcp_scpsoption_flags_resv3,
3966 "tcp.options.scpsflags.reserved3", FT_BOOLEAN, 8,
3967 TFS(&flags_set_truth), 0x1, "", HFILL }},
3970 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3971 "How long time has passed until the last frame of this PDU", HFILL}},
3974 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL, 0x0,
3975 "The size of this PDU", HFILL}},
3977 { &hf_tcp_pdu_last_frame,
3978 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3979 "This is the last frame of the PDU starting in this segment", HFILL }},
3981 { &hf_tcp_ts_relative,
3982 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3983 "Time relative to first frame in this TCP stream", HFILL}},
3986 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3987 "Time delta from previous frame in this TCP stream", HFILL}},
3990 static gint *ett[] = {
3994 &ett_tcp_option_sack,
3995 &ett_tcp_option_scps,
3996 &ett_tcp_option_scps_extended,
3997 &ett_tcp_analysis_faults,
3999 &ett_tcp_timestamps,
4004 module_t *tcp_module;
4006 proto_tcp = proto_register_protocol("Transmission Control Protocol",
4008 proto_register_field_array(proto_tcp, hf, array_length(hf));
4009 proto_register_subtree_array(ett, array_length(ett));
4011 /* subdissector code */
4012 subdissector_table = register_dissector_table("tcp.port",
4013 "TCP port", FT_UINT16, BASE_DEC);
4014 register_heur_dissector_list("tcp", &heur_subdissector_list);
4016 /* Register configuration preferences */
4017 tcp_module = prefs_register_protocol(proto_tcp, NULL);
4018 prefs_register_bool_preference(tcp_module, "summary_in_tree",
4019 "Show TCP summary in protocol tree",
4020 "Whether the TCP summary line should be shown in the protocol tree",
4021 &tcp_summary_in_tree);
4022 prefs_register_bool_preference(tcp_module, "check_checksum",
4023 "Validate the TCP checksum if possible",
4024 "Whether to validate the TCP checksum",
4025 &tcp_check_checksum);
4026 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
4027 "Allow subdissector to reassemble TCP streams",
4028 "Whether subdissector can request TCP streams to be reassembled",
4030 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
4031 "Analyze TCP sequence numbers",
4032 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
4034 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
4035 "Relative sequence numbers and window scaling",
4036 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
4037 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
4038 "This option will also try to track and adjust the window field according to any TCP window scaling options seen.",
4040 prefs_register_bool_preference(tcp_module, "track_bytes_in_flight",
4041 "Track number of bytes in flight",
4042 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "
4043 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
4044 "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",
4045 &tcp_track_bytes_in_flight);
4046 prefs_register_bool_preference(tcp_module, "calculate_timestamps",
4047 "Calculate conversation timestamps",
4048 "Calculate timestamps relative to the first frame and the previous frame in the tcp conversation",
4050 prefs_register_bool_preference(tcp_module, "try_heuristic_first",
4051 "Try heuristic sub-dissectors first",
4052 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
4053 &try_heuristic_first);
4055 register_init_routine(tcp_fragment_init);
4059 proto_reg_handoff_tcp(void)
4061 dissector_handle_t tcp_handle;
4063 tcp_handle = create_dissector_handle(dissect_tcp, proto_tcp);
4064 dissector_add("ip.proto", IP_PROTO_TCP, tcp_handle);
4065 data_handle = find_dissector("data");
4066 tcp_tap = register_tap("tcp");