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_alloc(sizeof(struct tcp_analysis));
249 tcpd->flow1.segments=NULL;
250 tcpd->flow1.base_seq=0;
251 tcpd->flow1.lastack=0;
252 tcpd->flow1.lastacktime.secs=0;
253 tcpd->flow1.lastacktime.nsecs=0;
254 tcpd->flow1.lastnondupack=0;
255 tcpd->flow1.nextseq=0;
256 tcpd->flow1.nextseqtime.secs=0;
257 tcpd->flow1.nextseqtime.nsecs=0;
258 tcpd->flow1.nextseqframe=0;
259 tcpd->flow1.window=0;
260 tcpd->flow1.win_scale=-1;
261 tcpd->flow1.scps_capable=0;
262 tcpd->flow1.maxsizeacked=0;
264 tcpd->flow1.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
265 tcpd->flow2.segments=NULL;
266 tcpd->flow2.base_seq=0;
267 tcpd->flow2.lastack=0;
268 tcpd->flow2.lastacktime.secs=0;
269 tcpd->flow2.lastacktime.nsecs=0;
270 tcpd->flow2.lastnondupack=0;
271 tcpd->flow2.nextseq=0;
272 tcpd->flow2.nextseqtime.secs=0;
273 tcpd->flow2.nextseqtime.nsecs=0;
274 tcpd->flow2.nextseqframe=0;
275 tcpd->flow2.window=0;
276 tcpd->flow2.win_scale=-1;
277 tcpd->flow2.scps_capable=0;
278 tcpd->flow2.maxsizeacked=0;
280 tcpd->flow2.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
281 tcpd->acked_table=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_analyze_acked_table");
282 tcpd->ts_first.secs=pinfo->fd->abs_ts.secs;
283 tcpd->ts_first.nsecs=pinfo->fd->abs_ts.nsecs;
284 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
285 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
291 get_tcp_conversation(packet_info *pinfo)
293 conversation_t *conv=NULL;
295 /* Have we seen this conversation before? */
296 if( (conv=find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0)) == NULL){
297 /* No this is a new conversation. */
298 conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
303 struct tcp_analysis *
304 get_tcp_conversation_data(conversation_t *conv, packet_info *pinfo)
307 struct tcp_analysis *tcpd=NULL;
309 /* Did the caller supply the conversation pointer? */
311 conv = get_tcp_conversation(pinfo);
313 /* Get the data for this conversation */
314 tcpd=conversation_get_proto_data(conv, proto_tcp);
316 /* If the conversation was just created or it matched a
317 * conversation with template options, tcpd will not
318 * have been initialized. So, initialize
319 * a new tcpd structure for the conversation.
322 tcpd = init_tcp_conversation_data(pinfo);
323 conversation_add_proto_data(conv, proto_tcp, tcpd);
330 /* check direction and get ua lists */
331 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
332 /* if the addresses are equal, match the ports instead */
334 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
337 tcpd->fwd=&(tcpd->flow1);
338 tcpd->rev=&(tcpd->flow2);
340 tcpd->fwd=&(tcpd->flow2);
341 tcpd->rev=&(tcpd->flow1);
348 /* Calculate the timestamps relative to this conversation */
350 tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
351 struct tcp_per_packet_data_t *tcppd)
354 tcppd = se_alloc(sizeof(struct tcp_per_packet_data_t));
355 p_add_proto_data(pinfo->fd, proto_tcp, tcppd);
361 nstime_delta(&tcppd->ts_del, &pinfo->fd->abs_ts, &tcpd->ts_prev);
363 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
364 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
367 /* Add a subtree with the timestamps relative to this conversation */
369 tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
378 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "Timestamps");
379 PROTO_ITEM_SET_GENERATED(item);
380 tree=proto_item_add_subtree(item, ett_tcp_timestamps);
382 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
383 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);
384 PROTO_ITEM_SET_GENERATED(item);
387 tcppd = p_get_proto_data(pinfo->fd, proto_tcp);
390 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,
392 PROTO_ITEM_SET_GENERATED(item);
397 print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)
401 if (check_col(pinfo->cinfo, COL_INFO)){
402 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);
404 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
405 tvb, 0, 0, msp->first_frame);
406 PROTO_ITEM_SET_GENERATED(item);
409 /* if we know that a PDU starts inside this segment, return the adjusted
410 offset to where that PDU starts or just return offset back
411 and let TCP try to find out what it can about this segment
414 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)
416 struct tcp_multisegment_pdu *msp=NULL;
418 if(!pinfo->fd->flags.visited){
419 msp=se_tree_lookup32_le(multisegment_pdus, seq-1);
421 /* If this is a continuation of a PDU started in a
422 * previous segment we need to update the last_frame
425 if(seq>msp->seq && seq<msp->nxtpdu){
426 msp->last_frame=pinfo->fd->num;
427 msp->last_frame_time=pinfo->fd->abs_ts;
428 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
431 /* If this segment is completely within a previous PDU
432 * then we just skip this packet
434 if(seq>msp->seq && nxtseq<=msp->nxtpdu){
437 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu){
438 offset+=msp->nxtpdu-seq;
444 /* First we try to find the start and transfer time for a PDU.
445 * We only print this for the very first segment of a PDU
446 * and only for PDUs spanning multiple segments.
447 * Se we look for if there was any multisegment PDU started
448 * just BEFORE the end of this segment. I.e. either inside this
449 * segment or in a previous segment.
450 * Since this might also match PDUs that are completely within
451 * this segment we also verify that the found PDU does span
452 * beyond the end of this segment.
454 msp=se_tree_lookup32_le(multisegment_pdus, nxtseq-1);
456 if( (pinfo->fd->num==msp->first_frame)
461 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);
462 PROTO_ITEM_SET_GENERATED(item);
464 nstime_delta(&ns, &msp->last_frame_time, &pinfo->fd->abs_ts);
465 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,
467 PROTO_ITEM_SET_GENERATED(item);
471 /* Second we check if this segment is part of a PDU started
472 * prior to the segment (seq-1)
474 msp=se_tree_lookup32_le(multisegment_pdus, seq-1);
476 /* If this segment is completely within a previous PDU
477 * then we just skip this packet
479 if(seq>msp->seq && nxtseq<=msp->nxtpdu){
480 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
484 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu){
485 offset+=msp->nxtpdu-seq;
494 /* if we saw a PDU that extended beyond the end of the segment,
495 use this function to remember where the next pdu starts
497 struct tcp_multisegment_pdu *
498 pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, emem_tree_t *multisegment_pdus)
500 struct tcp_multisegment_pdu *msp;
502 msp=se_alloc(sizeof(struct tcp_multisegment_pdu));
505 msp->first_frame=pinfo->fd->num;
506 msp->last_frame=pinfo->fd->num;
507 msp->last_frame_time=pinfo->fd->abs_ts;
509 se_tree_insert32(multisegment_pdus, seq, (void *)msp);
513 /* This is called for SYN+ACK packets and the purpose is to verify that we
514 * have seen window scaling in both directions.
515 * If we cant find window scaling being set in both directions
516 * that means it was present in the SYN but not in the SYN+ACK
517 * (or the SYN was missing) and then we disable the window scaling
518 * for this tcp session.
521 verify_tcp_window_scaling(struct tcp_analysis *tcpd)
523 if( tcpd && ((tcpd->flow1.win_scale==-1) || (tcpd->flow2.win_scale==-1)) ){
524 tcpd->flow1.win_scale=-1;
525 tcpd->flow2.win_scale=-1;
529 /* if we saw a window scaling option, store it for future reference
532 pdu_store_window_scale_option(guint8 ws, struct tcp_analysis *tcpd)
535 tcpd->fwd->win_scale=ws;
539 tcp_get_relative_seq_ack(guint32 *seq, guint32 *ack, guint32 *win, struct tcp_analysis *tcpd)
541 if (tcpd && tcp_relative_seq) {
542 (*seq) -= tcpd->fwd->base_seq;
543 (*ack) -= tcpd->rev->base_seq;
544 if(tcpd->fwd->win_scale!=-1){
545 (*win)<<=tcpd->fwd->win_scale;
551 /* when this function returns, it will (if createflag) populate the ta pointer.
554 tcp_analyze_get_acked_struct(guint32 frame, gboolean createflag, struct tcp_analysis *tcpd)
559 tcpd->ta=se_tree_lookup32(tcpd->acked_table, frame);
560 if((!tcpd->ta) && createflag){
561 tcpd->ta=se_alloc(sizeof(struct tcp_acked));
562 tcpd->ta->frame_acked=0;
564 tcpd->ta->ts.nsecs=0;
566 tcpd->ta->dupack_num=0;
567 tcpd->ta->dupack_frame=0;
568 se_tree_insert32(tcpd->acked_table, frame, (void *)tcpd->ta);
573 /* fwd contains a list of all segments processed but not yet ACKed in the
574 * same direction as the current segment.
575 * rev contains a list of all segments received but not yet ACKed in the
576 * opposite direction to the current segment.
578 * New segments are always added to the head of the fwd/rev lists.
582 tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint8 flags, guint32 window, struct tcp_analysis *tcpd)
584 tcp_unacked_t *ual=NULL;
588 printf("analyze_sequence numbers frame:%u direction:%s\n",pinfo->fd->num,direction>=0?"FWD":"REW");
589 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);
590 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);
597 /* if this is the first segment for this list we need to store the
600 * Start relative seq and ack numbers at 1 if this
601 * is not a SYN packet. This makes the relative
602 * seq/ack numbers to be displayed correctly in the
603 * event that the SYN or SYN/ACK packet is not seen
604 * (this solves bug 1542)
606 if(tcpd->fwd->base_seq==0){
607 tcpd->fwd->base_seq = (flags & TH_SYN) ? seq : seq-1;
610 /* Only store reverse sequence if this isn't the SYN
611 * There's no guarantee that the ACK field of a SYN
612 * contains zeros; get the ISN from the first segment
613 * with the ACK bit set instead (usually the SYN/ACK).
615 if( (tcpd->rev->base_seq==0) && (flags & TH_ACK) ){
616 tcpd->rev->base_seq = (flags & TH_SYN) ? ack : ack-1;
621 * it is a zero window probe if
622 * the sequnece number is the next expected one
623 * the window in the other direction is 0
624 * the segment is exactly 1 byte
628 && seq==tcpd->fwd->nextseq
629 && tcpd->rev->window==0 ){
631 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
633 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
639 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
643 && (flags&(TH_RST|TH_FIN|TH_SYN))==0 ){
645 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
647 tcpd->ta->flags|=TCP_A_ZERO_WINDOW;
652 * If this segment is beyond the last seen nextseq we must
653 * have missed some previous segment
655 * We only check for this if we have actually seen segments prior to this
657 * RST packets are not checked for this.
659 if( tcpd->fwd->nextseq
660 && GT_SEQ(seq, tcpd->fwd->nextseq)
661 && (flags&(TH_RST))==0 ){
663 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
665 tcpd->ta->flags|=TCP_A_LOST_PACKET;
670 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
671 * to what should be the next sequence number.
672 * SYN/FIN/RST segments are never keepalives
675 if( (seglen==0||seglen==1)
676 && seq==(tcpd->fwd->nextseq-1)
677 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
679 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
681 tcpd->ta->flags|=TCP_A_KEEP_ALIVE;
685 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
686 * the previous seen segment and with a new window value
690 && window!=tcpd->fwd->window
691 && seq==tcpd->fwd->nextseq
692 && ack==tcpd->fwd->lastack
693 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
695 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
697 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
702 * If we know the window scaling
703 * and if this segment contains data ang goes all the way to the
704 * edge of the advertized window
705 * then we mark it as WINDOW FULL
706 * SYN/RST/FIN packets are never WINDOW FULL
710 && tcpd->fwd->win_scale!=-1
711 && tcpd->rev->win_scale!=-1
712 && (seq+seglen)==(tcpd->rev->lastack+(tcpd->rev->window<<tcpd->rev->win_scale))
713 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
715 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
717 tcpd->ta->flags|=TCP_A_WINDOW_FULL;
722 * It is a keepalive ack if it repeats the previous ACK and if
723 * the last segment in the reverse direction was a keepalive
728 && window==tcpd->fwd->window
729 && seq==tcpd->fwd->nextseq
730 && ack==tcpd->fwd->lastack
731 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
732 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
734 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
736 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK;
741 /* ZERO WINDOW PROBE ACK
742 * It is a zerowindowprobe ack if it repeats the previous ACK and if
743 * the last segment in the reverse direction was a zerowindowprobe
744 * It also repeats the previous zero window indication
749 && window==tcpd->fwd->window
750 && seq==tcpd->fwd->nextseq
751 && ack==tcpd->fwd->lastack
752 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
753 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
755 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
757 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
763 * It is a duplicate ack if window/seq/ack is the same as the previous
764 * segment and if the segment length is 0
768 && window==tcpd->fwd->window
769 && seq==tcpd->fwd->nextseq
770 && ack==tcpd->fwd->lastack
771 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
772 tcpd->fwd->dupacknum++;
774 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
776 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
777 tcpd->ta->dupack_num=tcpd->fwd->dupacknum;
778 tcpd->ta->dupack_frame=tcpd->fwd->lastnondupack;
784 /* If this was NOT a dupack we must reset the dupack counters */
785 if( (!tcpd->ta) || !(tcpd->ta->flags&TCP_A_DUPLICATE_ACK) ){
786 tcpd->fwd->lastnondupack=pinfo->fd->num;
787 tcpd->fwd->dupacknum=0;
792 * If this segment acks beyond the nextseqnum in the other direction
793 * then that means we have missed packets going in the
796 * We only check this if we have actually seen some seq numbers
797 * in the other direction.
799 if( tcpd->rev->nextseq
800 && GT_SEQ(ack, tcpd->rev->nextseq )
801 && (flags&(TH_ACK))!=0 ){
804 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
806 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
807 /* update nextseq in the other direction so we dont get
808 * this indication again.
810 tcpd->rev->nextseq=ack;
814 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
815 * If the segments contains data and if it does not advance
816 * sequence number it must be either of these three.
817 * Only test for this if we know what the seq number should be
818 * (tcpd->fwd->nextseq)
820 * Note that a simple KeepAlive is not a retransmission
823 && tcpd->fwd->nextseq
824 && (LT_SEQ(seq, tcpd->fwd->nextseq)) ){
827 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ){
828 goto finished_checking_retransmission_type;
831 /* If there were >=2 duplicate ACKs in the reverse direction
832 * (there might be duplicate acks missing from the trace)
833 * and if this sequence number matches those ACKs
834 * and if the packet occurs within 20ms of the last
836 * then this is a fast retransmission
838 t=(pinfo->fd->abs_ts.secs-tcpd->rev->lastacktime.secs)*1000000000;
839 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->rev->lastacktime.nsecs;
840 if( tcpd->rev->dupacknum>=2
841 && tcpd->rev->lastack==seq
844 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
846 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
847 goto finished_checking_retransmission_type;
850 /* If the segment came <3ms since the segment with the highest
851 * seen sequence number, then it is an OUT-OF-ORDER segment.
852 * (3ms is an arbitrary number)
854 t=(pinfo->fd->abs_ts.secs-tcpd->fwd->nextseqtime.secs)*1000000000;
855 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->fwd->nextseqtime.nsecs;
858 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
860 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
861 goto finished_checking_retransmission_type;
864 /* Then it has to be a generic retransmission */
866 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
868 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
869 nstime_delta(&tcpd->ta->rto_ts, &pinfo->fd->abs_ts, &tcpd->fwd->nextseqtime);
870 tcpd->ta->rto_frame=tcpd->fwd->nextseqframe;
872 finished_checking_retransmission_type:
875 /* add this new sequence number to the fwd list */
876 TCP_UNACKED_NEW(ual);
877 ual->next=tcpd->fwd->segments;
878 tcpd->fwd->segments=ual;
879 ual->frame=pinfo->fd->num;
881 ual->ts=pinfo->fd->abs_ts;
883 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
884 ual->nextseq=seq+seglen;
885 if( flags&(TH_SYN|TH_FIN) ){
889 /* Store the highest number seen so far for nextseq so we can detect
890 * when we receive segments that arrive with a "hole"
891 * If we dont have anything since before, just store what we got.
892 * ZeroWindowProbes are special and dont really advance the nextseq
894 if(GT_SEQ(ual->nextseq, tcpd->fwd->nextseq) || !tcpd->fwd->nextseq) {
895 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ){
896 tcpd->fwd->nextseq=ual->nextseq;
897 tcpd->fwd->nextseqframe=pinfo->fd->num;
898 tcpd->fwd->nextseqtime.secs=pinfo->fd->abs_ts.secs;
899 tcpd->fwd->nextseqtime.nsecs=pinfo->fd->abs_ts.nsecs;
904 /* remember what the ack/window is so we can track window updates and retransmissions */
905 tcpd->fwd->window=window;
906 tcpd->fwd->lastack=ack;
907 tcpd->fwd->lastacktime.secs=pinfo->fd->abs_ts.secs;
908 tcpd->fwd->lastacktime.nsecs=pinfo->fd->abs_ts.nsecs;
911 /* if there were any flags set for this segment we need to remember them
912 * we only remember the flags for the very last segment though.
915 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;
917 tcpd->fwd->lastsegmentflags=0;
921 /* remove all segments this ACKs and we dont need to keep around any more
924 /* first we remove all such segments at the head of the list */
925 while((ual=tcpd->rev->segments)){
926 tcp_unacked_t *tmpual;
927 if(ack==ual->nextseq){
928 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
929 tcpd->ta->frame_acked=ual->frame;
930 nstime_delta(&tcpd->ta->ts, &pinfo->fd->abs_ts, &ual->ts);
932 if(GT_SEQ(ual->nextseq,ack)){
936 /*qqq do the ACKs segment x delta y */
939 tmpual=tcpd->rev->segments->next;
941 if (tcpd->rev->scps_capable) {
942 /* Track largest segment successfully sent for SNACK analysis */
943 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) {
944 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);
948 TCP_UNACKED_FREE(ual);
949 tcpd->rev->segments=tmpual;
951 /* now we remove all such segments that are NOT at the head of the list */
952 ual=tcpd->rev->segments;
953 while(ual && ual->next){
954 tcp_unacked_t *tmpual;
955 if(GT_SEQ(ual->next->nextseq,ack)){
960 /*qqq do the ACKs segment x delta y */
963 tmpual=ual->next->next;
965 if (tcpd->rev->scps_capable) {
966 /* Track largest segment successfully sent for SNACK analysis*/
967 if ((ual->next->nextseq - ual->next->seq) > tcpd->fwd->maxsizeacked){
968 tcpd->fwd->maxsizeacked = (ual->next->nextseq - ual->next->seq);
972 TCP_UNACKED_FREE(ual->next);
977 /* how many bytes of data are there in flight after this frame
980 ual=tcpd->fwd->segments;
981 if (tcp_track_bytes_in_flight && seglen!=0 && ual) {
982 guint32 first_seq, last_seq, in_flight;
984 first_seq = ual->seq - tcpd->fwd->base_seq;
985 last_seq = ual->nextseq - tcpd->fwd->base_seq;
987 if ((ual->nextseq-tcpd->fwd->base_seq)>last_seq) {
988 last_seq = ual->nextseq-tcpd->fwd->base_seq;
990 if ((ual->seq-tcpd->fwd->base_seq)<first_seq) {
991 first_seq = ual->seq-tcpd->fwd->base_seq;
995 in_flight = last_seq-first_seq;
997 if (in_flight>0 && in_flight<2000000000) {
999 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
1001 tcpd->ta->bytes_in_flight = in_flight;
1008 * Prints results of the sequence number analysis concerning tcp segments
1009 * retransmitted or out-of-order
1012 tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,
1014 proto_tree * flags_tree,
1015 struct tcp_acked *ta
1018 proto_item * flags_item;
1020 /* TCP Rentransmission */
1021 if (ta->flags & TCP_A_RETRANSMISSION) {
1022 flags_item=proto_tree_add_none_format(flags_tree,
1023 hf_tcp_analysis_retransmission,
1025 "This frame is a (suspected) "
1028 PROTO_ITEM_SET_GENERATED(flags_item);
1029 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1030 "Retransmission (suspected)");
1032 if (check_col(pinfo->cinfo, COL_INFO)) {
1033 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
1035 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {
1036 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
1037 tvb, 0, 0, &ta->rto_ts);
1038 PROTO_ITEM_SET_GENERATED(flags_item);
1039 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,
1040 tvb, 0, 0, ta->rto_frame);
1041 PROTO_ITEM_SET_GENERATED(flags_item);
1044 /* TCP Fast Rentransmission */
1045 if (ta->flags & TCP_A_FAST_RETRANSMISSION) {
1046 flags_item=proto_tree_add_none_format(flags_tree,
1047 hf_tcp_analysis_fast_retransmission,
1049 "This frame is a (suspected) fast"
1052 PROTO_ITEM_SET_GENERATED(flags_item);
1053 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1054 "Fast retransmission (suspected)");
1055 flags_item=proto_tree_add_none_format(flags_tree,
1056 hf_tcp_analysis_retransmission,
1058 "This frame is a (suspected) "
1061 PROTO_ITEM_SET_GENERATED(flags_item);
1062 if (check_col(pinfo->cinfo, COL_INFO)) {
1063 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1064 "[TCP Fast Retransmission] ");
1067 /* TCP Out-Of-Order */
1068 if (ta->flags & TCP_A_OUT_OF_ORDER) {
1069 flags_item=proto_tree_add_none_format(flags_tree,
1070 hf_tcp_analysis_out_of_order,
1072 "This frame is a (suspected) "
1073 "out-of-order segment"
1075 PROTO_ITEM_SET_GENERATED(flags_item);
1076 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1077 "Out-Of-Order segment");
1078 if (check_col(pinfo->cinfo, COL_INFO)) {
1079 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
1084 /* Prints results of the sequence number analysis concerning reused ports */
1086 tcp_sequence_number_analysis_print_reused(packet_info * pinfo,
1088 proto_tree * flags_tree,
1089 struct tcp_acked *ta
1092 proto_item * flags_item;
1094 /* TCP Ports Reused */
1095 if (ta->flags & TCP_A_REUSED_PORTS) {
1096 flags_item=proto_tree_add_none_format(flags_tree,
1097 hf_tcp_analysis_reused_ports,
1099 "A new tcp session is started with the same "
1100 "ports as an earlier session in this trace"
1102 PROTO_ITEM_SET_GENERATED(flags_item);
1103 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1104 "TCP Port numbers reused for new session");
1105 if(check_col(pinfo->cinfo, COL_INFO)){
1106 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1107 "[TCP Port numbers reused] ");
1112 /* Prints results of the sequence number analysis concerning lost tcp segments */
1114 tcp_sequence_number_analysis_print_lost(packet_info * pinfo,
1116 proto_tree * flags_tree,
1117 struct tcp_acked *ta
1120 proto_item * flags_item;
1122 /* TCP Lost Segment */
1123 if (ta->flags & TCP_A_LOST_PACKET) {
1124 flags_item=proto_tree_add_none_format(flags_tree,
1125 hf_tcp_analysis_lost_packet,
1127 "A segment before this frame was "
1130 PROTO_ITEM_SET_GENERATED(flags_item);
1131 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1132 "Previous segment lost (common at capture start)");
1133 if(check_col(pinfo->cinfo, COL_INFO)){
1134 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1135 "[TCP Previous segment lost] ");
1138 /* TCP Ack lost segment */
1139 if (ta->flags & TCP_A_ACK_LOST_PACKET) {
1140 flags_item=proto_tree_add_none_format(flags_tree,
1141 hf_tcp_analysis_ack_lost_packet,
1143 "This frame ACKs a segment we have "
1146 PROTO_ITEM_SET_GENERATED(flags_item);
1147 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1148 "ACKed lost segment (common at capture start)");
1149 if(check_col(pinfo->cinfo, COL_INFO)){
1150 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1151 "[TCP ACKed lost segment] ");
1156 /* Prints results of the sequence number analysis concerning tcp window */
1158 tcp_sequence_number_analysis_print_window(packet_info * pinfo,
1160 proto_tree * flags_tree,
1161 struct tcp_acked *ta
1164 proto_item * flags_item;
1166 /* TCP Window Update */
1167 if (ta->flags & TCP_A_WINDOW_UPDATE) {
1168 flags_item=proto_tree_add_none_format(flags_tree,
1169 hf_tcp_analysis_window_update,
1171 "This is a tcp window update"
1173 PROTO_ITEM_SET_GENERATED(flags_item);
1174 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_CHAT,
1176 if (check_col(pinfo->cinfo, COL_INFO)) {
1177 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
1180 /* TCP Full Window */
1181 if (ta->flags & TCP_A_WINDOW_FULL) {
1182 flags_item=proto_tree_add_none_format(flags_tree,
1183 hf_tcp_analysis_window_full,
1185 "The transmission window is now "
1188 PROTO_ITEM_SET_GENERATED(flags_item);
1189 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1191 if (check_col(pinfo->cinfo, COL_INFO)) {
1192 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
1197 /* Prints results of the sequence number analysis concerning tcp keepalive */
1199 tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,
1201 proto_tree * flags_tree,
1202 struct tcp_acked *ta
1205 proto_item * flags_item;
1208 if (ta->flags & TCP_A_KEEP_ALIVE){
1209 flags_item=proto_tree_add_none_format(flags_tree,
1210 hf_tcp_analysis_keep_alive,
1212 "This is a TCP keep-alive segment"
1214 PROTO_ITEM_SET_GENERATED(flags_item);
1215 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1217 if (check_col(pinfo->cinfo, COL_INFO)) {
1218 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
1221 /* TCP Ack Keep Alive */
1222 if (ta->flags & TCP_A_KEEP_ALIVE_ACK) {
1223 flags_item=proto_tree_add_none_format(flags_tree,
1224 hf_tcp_analysis_keep_alive_ack,
1226 "This is an ACK to a TCP keep-alive "
1229 PROTO_ITEM_SET_GENERATED(flags_item);
1230 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1232 if (check_col(pinfo->cinfo, COL_INFO)) {
1233 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
1238 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
1240 tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,
1242 proto_tree * flags_tree,
1243 struct tcp_acked *ta,
1247 proto_item * flags_item;
1249 /* TCP Duplicate ACK */
1250 if (ta->dupack_num) {
1251 if (ta->flags & TCP_A_DUPLICATE_ACK ) {
1252 flags_item=proto_tree_add_none_format(flags_tree,
1253 hf_tcp_analysis_duplicate_ack,
1255 "This is a TCP duplicate ack"
1257 PROTO_ITEM_SET_GENERATED(flags_item);
1258 if (check_col(pinfo->cinfo, COL_INFO)) {
1259 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1260 "[TCP Dup ACK %u#%u] ",
1266 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
1267 tvb, 0, 0, ta->dupack_num);
1268 PROTO_ITEM_SET_GENERATED(flags_item);
1269 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
1270 tvb, 0, 0, ta->dupack_frame);
1271 PROTO_ITEM_SET_GENERATED(flags_item);
1272 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1273 "Duplicate ACK (#%u)",
1279 /* Prints results of the sequence number analysis concerning tcp zero window */
1281 tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,
1283 proto_tree * flags_tree,
1284 struct tcp_acked *ta
1287 proto_item * flags_item;
1289 /* TCP Zeor Window Probe */
1290 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE) {
1291 flags_item=proto_tree_add_none_format(flags_tree,
1292 hf_tcp_analysis_zero_window_probe,
1294 "This is a TCP zero-window-probe"
1296 PROTO_ITEM_SET_GENERATED(flags_item);
1297 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1298 "Zero window probe");
1299 if (check_col(pinfo->cinfo, COL_INFO)) {
1300 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
1303 /* TCP Zero Window */
1304 if (ta->flags&TCP_A_ZERO_WINDOW) {
1305 flags_item=proto_tree_add_none_format(flags_tree,
1306 hf_tcp_analysis_zero_window,
1308 "This is a ZeroWindow segment"
1310 PROTO_ITEM_SET_GENERATED(flags_item);
1311 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1313 if (check_col(pinfo->cinfo, COL_INFO)) {
1314 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
1317 /* TCP Zero Window Probe Ack */
1318 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK) {
1319 flags_item=proto_tree_add_none_format(flags_tree,
1320 hf_tcp_analysis_zero_window_probe_ack,
1322 "This is an ACK to a TCP zero-window-probe"
1324 PROTO_ITEM_SET_GENERATED(flags_item);
1325 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1326 "Zero window probe ACK");
1327 if (check_col(pinfo->cinfo, COL_INFO)) {
1328 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1329 "[TCP ZeroWindowProbeAck] ");
1335 /* Prints results of the sequence number analysis concerning how many bytes of data are in flight */
1337 tcp_sequence_number_analysis_print_bytes_in_flight(packet_info * pinfo _U_,
1339 proto_tree * flags_tree _U_,
1340 struct tcp_acked *ta
1343 proto_item * flags_item;
1345 if (tcp_track_bytes_in_flight) {
1346 flags_item=proto_tree_add_uint(flags_tree,
1347 hf_tcp_analysis_bytes_in_flight,
1348 tvb, 0, 0, ta->bytes_in_flight);
1350 PROTO_ITEM_SET_GENERATED(flags_item);
1355 tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd)
1357 struct tcp_acked *ta = NULL;
1360 proto_tree *flags_tree=NULL;
1366 tcp_analyze_get_acked_struct(pinfo->fd->num, FALSE, tcpd);
1373 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "SEQ/ACK analysis");
1374 PROTO_ITEM_SET_GENERATED(item);
1375 tree=proto_item_add_subtree(item, ett_tcp_analysis);
1377 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
1378 data we actually have */
1379 if(ta->frame_acked){
1380 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
1381 tvb, 0, 0, ta->frame_acked);
1382 PROTO_ITEM_SET_GENERATED(item);
1384 /* only display RTT if we actually have something we are acking */
1385 if( ta->ts.secs || ta->ts.nsecs ){
1386 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
1387 tvb, 0, 0, &ta->ts);
1388 PROTO_ITEM_SET_GENERATED(item);
1392 if(ta->bytes_in_flight) {
1393 /* print results for amount of data in flight */
1394 tcp_sequence_number_analysis_print_bytes_in_flight(pinfo, tvb, tree, ta);
1398 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, -1, FALSE);
1399 PROTO_ITEM_SET_GENERATED(item);
1400 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);
1402 /* print results for reused tcp ports */
1403 tcp_sequence_number_analysis_print_reused(pinfo, tvb, flags_tree, ta);
1405 /* print results for retransmission and out-of-order segments */
1406 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, ta);
1408 /* print results for lost tcp segments */
1409 tcp_sequence_number_analysis_print_lost(pinfo, tvb, flags_tree, ta);
1411 /* print results for tcp window information */
1412 tcp_sequence_number_analysis_print_window(pinfo, tvb, flags_tree, ta);
1414 /* print results for tcp keep alive information */
1415 tcp_sequence_number_analysis_print_keepalive(pinfo, tvb, flags_tree, ta);
1417 /* print results for tcp duplicate acks */
1418 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);
1420 /* print results for tcp zero window */
1421 tcp_sequence_number_analysis_print_zero_window(pinfo, tvb, flags_tree, ta);
1428 /* **************************************************************************
1429 * End of tcp sequence number analysis
1430 * **************************************************************************/
1433 /* Minimum TCP header length. */
1434 #define TCPH_MIN_LEN 20
1440 #define TCPOPT_NOP 1 /* Padding */
1441 #define TCPOPT_EOL 0 /* End of options */
1442 #define TCPOPT_MSS 2 /* Segment size negotiating */
1443 #define TCPOPT_WINDOW 3 /* Window scaling */
1444 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
1445 #define TCPOPT_SACK 5 /* SACK Block */
1446 #define TCPOPT_ECHO 6
1447 #define TCPOPT_ECHOREPLY 7
1448 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
1449 #define TCPOPT_CC 11
1450 #define TCPOPT_CCNEW 12
1451 #define TCPOPT_CCECHO 13
1452 #define TCPOPT_MD5 19 /* RFC2385 */
1453 #define TCPOPT_SCPS 20 /* SCPS Capabilties */
1454 #define TCPOPT_SNACK 21 /* SCPS SNACK */
1455 #define TCPOPT_RECBOUND 22 /* SCPS Record Boundary */
1456 #define TCPOPT_CORREXP 23 /* SCPS Corruption Experienced */
1457 #define TCPOPT_QS 27 /* RFC4782 */
1460 * TCP option lengths
1463 #define TCPOLEN_MSS 4
1464 #define TCPOLEN_WINDOW 3
1465 #define TCPOLEN_SACK_PERM 2
1466 #define TCPOLEN_SACK_MIN 2
1467 #define TCPOLEN_ECHO 6
1468 #define TCPOLEN_ECHOREPLY 6
1469 #define TCPOLEN_TIMESTAMP 10
1470 #define TCPOLEN_CC 6
1471 #define TCPOLEN_CCNEW 6
1472 #define TCPOLEN_CCECHO 6
1473 #define TCPOLEN_MD5 18
1474 #define TCPOLEN_SCPS 4
1475 #define TCPOLEN_SNACK 6
1476 #define TCPOLEN_RECBOUND 2
1477 #define TCPOLEN_CORREXP 2
1478 #define TCPOLEN_QS 8
1482 /* Desegmentation of TCP streams */
1483 /* table to hold defragmented TCP streams */
1484 static GHashTable *tcp_fragment_table = NULL;
1486 tcp_fragment_init(void)
1488 fragment_table_init(&tcp_fragment_table);
1491 /* functions to trace tcp segments */
1492 /* Enable desegmenting of TCP streams */
1493 static gboolean tcp_desegment = TRUE;
1496 desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
1497 guint32 seq, guint32 nxtseq,
1498 guint32 sport, guint32 dport,
1499 proto_tree *tree, proto_tree *tcp_tree,
1500 struct tcp_analysis *tcpd)
1502 struct tcpinfo *tcpinfo = pinfo->private_data;
1503 fragment_data *ipfd_head;
1504 int last_fragment_len;
1505 gboolean must_desegment;
1506 gboolean called_dissector;
1507 int another_pdu_follows;
1512 proto_item *frag_tree_item;
1513 proto_item *tcp_tree_item;
1514 struct tcp_multisegment_pdu *msp;
1518 last_fragment_len=0;
1519 must_desegment = FALSE;
1520 called_dissector = FALSE;
1521 another_pdu_follows = 0;
1525 * Initialize these to assume no desegmentation.
1526 * If that's not the case, these will be set appropriately
1527 * by the subdissector.
1529 pinfo->desegment_offset = 0;
1530 pinfo->desegment_len = 0;
1533 * Initialize this to assume that this segment will just be
1534 * added to the middle of a desegmented chunk of data, so
1535 * that we should show it all as data.
1536 * If that's not the case, it will be set appropriately.
1538 deseg_offset = offset;
1540 /* find the most previous PDU starting before this sequence number */
1542 msp = se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);
1544 if(msp && msp->seq<=seq && msp->nxtpdu>seq){
1547 if(!pinfo->fd->flags.visited){
1548 msp->last_frame=pinfo->fd->num;
1549 msp->last_frame_time=pinfo->fd->abs_ts;
1552 /* OK, this PDU was found, which means the segment continues
1553 a higher-level PDU and that we must desegment it.
1555 if(msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT){
1556 /* The dissector asked for the entire segment */
1557 len=tvb_length_remaining(tvb, offset);
1559 len=MIN(nxtseq, msp->nxtpdu) - seq;
1561 last_fragment_len = len;
1563 ipfd_head = fragment_add(tvb, offset, pinfo, msp->first_frame,
1567 (LT_SEQ (nxtseq,msp->nxtpdu)) );
1569 if(msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT){
1570 msp->flags&=(~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
1572 /* If we consumed the entire segment there is no
1573 * other pdu starting anywhere inside this segment.
1574 * So update nxtpdu to point at least to the start
1575 * of the next segment.
1576 * (If the subdissector asks for even more data we
1577 * will advance nxtpdu even furhter later down in
1583 if( (msp->nxtpdu<nxtseq)
1584 && (msp->nxtpdu>=seq)
1586 another_pdu_follows=msp->nxtpdu-seq;
1589 /* This segment was not found in our table, so it doesn't
1590 contain a continuation of a higher-level PDU.
1591 Call the normal subdissector.
1593 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
1594 sport, dport, 0, 0, FALSE, tcpd);
1595 called_dissector = TRUE;
1597 /* Did the subdissector ask us to desegment some more data
1598 before it could handle the packet?
1599 If so we have to create some structures in our table but
1600 this is something we only do the first time we see this
1603 if(pinfo->desegment_len) {
1604 if (!pinfo->fd->flags.visited)
1605 must_desegment = TRUE;
1608 * Set "deseg_offset" to the offset in "tvb"
1609 * of the first byte of data that the
1610 * subdissector didn't process.
1612 deseg_offset = offset + pinfo->desegment_offset;
1615 /* Either no desegmentation is necessary, or this is
1616 segment contains the beginning but not the end of
1617 a higher-level PDU and thus isn't completely
1624 /* is it completely desegmented? */
1627 * Yes, we think it is.
1628 * We only call subdissector for the last segment.
1629 * Note that the last segment may include more than what
1632 if(ipfd_head->reassembled_in==pinfo->fd->num){
1634 * OK, this is the last segment.
1635 * Let's call the subdissector with the desegmented
1641 /* create a new TVB structure for desegmented data */
1642 next_tvb = tvb_new_real_data(ipfd_head->data,
1643 ipfd_head->datalen, ipfd_head->datalen);
1645 /* add this tvb as a child to the original one */
1646 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1648 /* add desegmented data to the data source list */
1649 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
1652 * Supply the sequence number of the first of the
1653 * reassembled bytes.
1655 tcpinfo->seq = msp->seq;
1657 /* indicate that this is reassembled data */
1658 tcpinfo->is_reassembled = TRUE;
1660 /* call subdissector */
1661 process_tcp_payload(next_tvb, 0, pinfo, tree,
1662 tcp_tree, sport, dport, 0, 0, FALSE, tcpd);
1663 called_dissector = TRUE;
1666 * OK, did the subdissector think it was completely
1667 * desegmented, or does it think we need even more
1670 old_len=(int)(tvb_reported_length(next_tvb)-last_fragment_len);
1671 if(pinfo->desegment_len &&
1672 pinfo->desegment_offset<=old_len){
1674 * "desegment_len" isn't 0, so it needs more
1675 * data for something - and "desegment_offset"
1676 * is before "old_len", so it needs more data
1677 * to dissect the stuff we thought was
1678 * completely desegmented (as opposed to the
1679 * stuff at the beginning being completely
1680 * desegmented, but the stuff at the end
1681 * being a new higher-level PDU that also
1682 * needs desegmentation).
1684 fragment_set_partial_reassembly(pinfo,msp->first_frame,tcp_fragment_table);
1685 /* Update msp->nxtpdu to point to the new next
1688 if(pinfo->desegment_len==DESEGMENT_ONE_MORE_SEGMENT){
1689 /* We want reassembly of at least one
1690 * more segment so set the nxtpdu
1691 * boundary to one byte into the next
1693 * This means that the next segment
1694 * will complete reassembly even if it
1695 * is only one single byte in length.
1697 msp->nxtpdu=seq+tvb_reported_length_remaining(tvb, offset) + 1;
1698 msp->flags|=MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1700 msp->nxtpdu=seq + last_fragment_len + pinfo->desegment_len;
1702 /* Since we need at least some more data
1703 * there can be no pdu following in the
1704 * tail of this segment.
1706 another_pdu_follows=0;
1707 offset += last_fragment_len;
1708 seq += last_fragment_len;
1709 if (tvb_length_remaining(tvb, offset) > 0)
1713 * Show the stuff in this TCP segment as
1714 * just raw TCP segment data.
1716 nbytes = another_pdu_follows > 0
1717 ? another_pdu_follows
1718 : tvb_reported_length_remaining(tvb, offset);
1719 proto_tree_add_text(tcp_tree, tvb, offset, nbytes,
1720 "TCP segment data (%u byte%s)", nbytes,
1721 plurality(nbytes, "", "s"));
1724 * The subdissector thought it was completely
1725 * desegmented (although the stuff at the
1726 * end may, in turn, require desegmentation),
1727 * so we show a tree with all segments.
1729 show_fragment_tree(ipfd_head, &tcp_segment_items,
1730 tree, pinfo, next_tvb, &frag_tree_item);
1732 * The toplevel fragment subtree is now
1733 * behind all desegmented data; move it
1734 * right behind the TCP tree.
1736 tcp_tree_item = proto_tree_get_parent(tcp_tree);
1737 if(frag_tree_item && tcp_tree_item) {
1738 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);
1741 /* Did the subdissector ask us to desegment
1742 some more data? This means that the data
1743 at the beginning of this segment completed
1744 a higher-level PDU, but the data at the
1745 end of this segment started a higher-level
1746 PDU but didn't complete it.
1748 If so, we have to create some structures
1749 in our table, but this is something we
1750 only do the first time we see this packet.
1752 if(pinfo->desegment_len) {
1753 if (!pinfo->fd->flags.visited)
1754 must_desegment = TRUE;
1756 /* The stuff we couldn't dissect
1757 must have come from this segment,
1758 so it's all in "tvb".
1760 "pinfo->desegment_offset" is
1761 relative to the beginning of
1762 "next_tvb"; we want an offset
1763 relative to the beginning of "tvb".
1765 First, compute the offset relative
1766 to the *end* of "next_tvb" - i.e.,
1767 the number of bytes before the end
1768 of "next_tvb" at which the
1769 subdissector stopped. That's the
1770 length of "next_tvb" minus the
1771 offset, relative to the beginning
1772 of "next_tvb, at which the
1773 subdissector stopped.
1776 ipfd_head->datalen - pinfo->desegment_offset;
1778 /* "tvb" and "next_tvb" end at the
1779 same byte of data, so the offset
1780 relative to the end of "next_tvb"
1781 of the byte at which we stopped
1782 is also the offset relative to
1783 the end of "tvb" of the byte at
1786 Convert that back into an offset
1787 relative to the beginninng of
1788 "tvb", by taking the length of
1789 "tvb" and subtracting the offset
1790 relative to the end.
1792 deseg_offset=tvb_reported_length(tvb) - deseg_offset;
1798 if (must_desegment) {
1799 /* If the dissector requested "reassemble until FIN"
1800 * just set this flag for the flow and let reassembly
1801 * proceed at normal. We will check/pick up these
1802 * reassembled PDUs later down in dissect_tcp() when checking
1805 if(tcpd && pinfo->desegment_len==DESEGMENT_UNTIL_FIN) {
1806 tcpd->fwd->flags|=TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1809 * The sequence number at which the stuff to be desegmented
1810 * starts is the sequence number of the byte at an offset
1811 * of "deseg_offset" into "tvb".
1813 * The sequence number of the byte at an offset of "offset"
1814 * is "seq", i.e. the starting sequence number of this
1815 * segment, so the sequence number of the byte at
1816 * "deseg_offset" is "seq + (deseg_offset - offset)".
1818 deseg_seq = seq + (deseg_offset - offset);
1820 if(tcpd && ((nxtseq - deseg_seq) <= 1024*1024)
1821 && (!pinfo->fd->flags.visited) ){
1822 if(pinfo->desegment_len==DESEGMENT_ONE_MORE_SEGMENT){
1823 /* The subdissector asked to reassemble using the
1824 * entire next segment.
1825 * Just ask reassembly for one more byte
1826 * but set this msp flag so we can pick it up
1829 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1830 deseg_seq, nxtseq+1, tcpd->fwd->multisegment_pdus);
1831 msp->flags|=MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1833 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1834 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
1837 /* add this segment as the first one for this new pdu */
1838 fragment_add(tvb, deseg_offset, pinfo, msp->first_frame,
1842 LT_SEQ(nxtseq, msp->nxtpdu));
1846 if (!called_dissector || pinfo->desegment_len != 0) {
1847 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
1848 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
1850 * We know what frame this PDU is reassembled in;
1851 * let the user know.
1853 item=proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in,
1854 tvb, 0, 0, ipfd_head->reassembled_in);
1855 PROTO_ITEM_SET_GENERATED(item);
1859 * Either we didn't call the subdissector at all (i.e.,
1860 * this is a segment that contains the middle of a
1861 * higher-level PDU, but contains neither the beginning
1862 * nor the end), or the subdissector couldn't dissect it
1863 * all, as some data was missing (i.e., it set
1864 * "pinfo->desegment_len" to the amount of additional
1867 if (pinfo->desegment_offset == 0) {
1869 * It couldn't, in fact, dissect any of it (the
1870 * first byte it couldn't dissect is at an offset
1871 * of "pinfo->desegment_offset" from the beginning
1872 * of the payload, and that's 0).
1873 * Just mark this as TCP.
1875 if (check_col(pinfo->cinfo, COL_PROTOCOL)){
1876 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
1878 if (check_col(pinfo->cinfo, COL_INFO)){
1879 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
1884 * Show what's left in the packet as just raw TCP segment
1886 * XXX - remember what protocol the last subdissector
1887 * was, and report it as a continuation of that, instead?
1889 nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
1890 proto_tree_add_text(tcp_tree, tvb, deseg_offset, -1,
1891 "TCP segment data (%u byte%s)", nbytes,
1892 plurality(nbytes, "", "s"));
1894 pinfo->can_desegment=0;
1895 pinfo->desegment_offset = 0;
1896 pinfo->desegment_len = 0;
1898 if(another_pdu_follows){
1899 /* there was another pdu following this one. */
1900 pinfo->can_desegment=2;
1901 /* we also have to prevent the dissector from changing the
1902 * PROTOCOL and INFO colums since what follows may be an
1903 * incomplete PDU and we dont want it be changed back from
1904 * <Protocol> to <TCP>
1905 * XXX There is no good way to block the PROTOCOL column
1906 * from being changed yet so we set the entire row unwritable.
1908 col_set_fence(pinfo->cinfo, COL_INFO);
1909 col_set_writable(pinfo->cinfo, FALSE);
1910 offset += another_pdu_follows;
1911 seq += another_pdu_follows;
1917 * Loop for dissecting PDUs within a TCP stream; assumes that a PDU
1918 * consists of a fixed-length chunk of data that contains enough information
1919 * to determine the length of the PDU, followed by rest of the PDU.
1921 * The first three arguments are the arguments passed to the dissector
1922 * that calls this routine.
1924 * "proto_desegment" is the dissector's flag controlling whether it should
1925 * desegment PDUs that cross TCP segment boundaries.
1927 * "fixed_len" is the length of the fixed-length part of the PDU.
1929 * "get_pdu_len()" is a routine called to get the length of the PDU from
1930 * the fixed-length part of the PDU; it's passed "pinfo", "tvb" and "offset".
1932 * "dissect_pdu()" is the routine to dissect a PDU.
1935 tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1936 gboolean proto_desegment, guint fixed_len,
1937 guint (*get_pdu_len)(packet_info *, tvbuff_t *, int),
1938 dissector_t dissect_pdu)
1940 volatile int offset = 0;
1942 guint length_remaining;
1946 proto_item *item=NULL;
1948 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1950 * We use "tvb_ensure_length_remaining()" to make sure there actually
1951 * *is* data remaining. The protocol we're handling could conceivably
1952 * consists of a sequence of fixed-length PDUs, and therefore the
1953 * "get_pdu_len" routine might not actually fetch anything from
1954 * the tvbuff, and thus might not cause an exception to be thrown if
1955 * we've run past the end of the tvbuff.
1957 * This means we're guaranteed that "length_remaining" is positive.
1959 length_remaining = tvb_ensure_length_remaining(tvb, offset);
1962 * Can we do reassembly?
1964 if (proto_desegment && pinfo->can_desegment) {
1966 * Yes - is the fixed-length part of the PDU split across segment
1969 if (length_remaining < fixed_len) {
1971 * Yes. Tell the TCP dissector where the data for this message
1972 * starts in the data it handed us, and how many more bytes we
1975 pinfo->desegment_offset = offset;
1976 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1982 * Get the length of the PDU.
1984 plen = (*get_pdu_len)(pinfo, tvb, offset);
1985 if (plen < fixed_len) {
1989 * 1) the length value extracted from the fixed-length portion
1990 * doesn't include the fixed-length portion's length, and
1991 * was so large that, when the fixed-length portion's
1992 * length was added to it, the total length overflowed;
1994 * 2) the length value extracted from the fixed-length portion
1995 * includes the fixed-length portion's length, and the value
1996 * was less than the fixed-length portion's length, i.e. it
1999 * Report this as a bounds error.
2001 show_reported_bounds_error(tvb, pinfo, tree);
2005 * Display the PDU length as a field
2007 item=proto_tree_add_uint(pinfo->tcp_tree, hf_tcp_pdu_size, tvb, offset, plen, plen);
2008 PROTO_ITEM_SET_GENERATED(item);
2012 /* give a hint to TCP where the next PDU starts
2013 * so that it can attempt to find it in case it starts
2014 * somewhere in the middle of a segment.
2016 if(!pinfo->fd->flags.visited && tcp_analyze_seq){
2017 guint remaining_bytes;
2018 remaining_bytes=tvb_reported_length_remaining(tvb, offset);
2019 if(plen>remaining_bytes){
2020 pinfo->want_pdu_tracking=2;
2021 pinfo->bytes_until_next_pdu=plen-remaining_bytes;
2026 * Can we do reassembly?
2028 if (proto_desegment && pinfo->can_desegment) {
2030 * Yes - is the PDU split across segment boundaries?
2032 if (length_remaining < plen) {
2034 * Yes. Tell the TCP dissector where the data for this message
2035 * starts in the data it handed us, and how many more bytes we
2038 pinfo->desegment_offset = offset;
2039 pinfo->desegment_len = plen - length_remaining;
2045 * Construct a tvbuff containing the amount of the payload we have
2046 * available. Make its reported length the amount of data in the PDU.
2048 * XXX - if reassembly isn't enabled. the subdissector will throw a
2049 * BoundsError exception, rather than a ReportedBoundsError exception.
2050 * We really want a tvbuff where the length is "length", the reported
2051 * length is "plen", and the "if the snapshot length were infinite"
2052 * length is the minimum of the reported length of the tvbuff handed
2053 * to us and "plen", with a new type of exception thrown if the offset
2054 * is within the reported length but beyond that third length, with
2055 * that exception getting the "Unreassembled Packet" error.
2057 length = length_remaining;
2060 next_tvb = tvb_new_subset(tvb, offset, length, plen);
2065 * Catch the ReportedBoundsError exception; if this particular message
2066 * happens to get a ReportedBoundsError exception, that doesn't mean
2067 * that we should stop dissecting PDUs within this frame or chunk of
2070 * If it gets a BoundsError, we can stop, as there's nothing more to
2071 * see, so we just re-throw it.
2074 (*dissect_pdu)(next_tvb, pinfo, tree);
2076 CATCH(BoundsError) {
2079 CATCH(ReportedBoundsError) {
2080 show_reported_bounds_error(tvb, pinfo, tree);
2085 * Step to the next PDU.
2086 * Make sure we don't overflow.
2088 offset_before = offset;
2090 if (offset <= offset_before)
2096 tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val)
2098 if (check_col(pinfo->cinfo, COL_INFO))
2099 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%u", abbrev, val);
2102 /* Supports the reporting the contents of a parsed SCPS capabilities vector */
2104 tcp_info_append_str(packet_info *pinfo, const char *abbrev, const char *val)
2106 if (check_col(pinfo->cinfo, COL_INFO))
2107 col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%s]", abbrev, val);
2111 dissect_tcpopt_maxseg(const ip_tcp_opt *optp, tvbuff_t *tvb,
2112 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2114 proto_item *hidden_item;
2117 mss = tvb_get_ntohs(tvb, offset + 2);
2118 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_mss, tvb, offset,
2120 PROTO_ITEM_SET_HIDDEN(hidden_item);
2121 proto_tree_add_uint_format(opt_tree, hf_tcp_option_mss_val, tvb, offset,
2122 optlen, mss, "%s: %u bytes", optp->name, mss);
2123 tcp_info_append_uint(pinfo, "MSS", mss);
2127 dissect_tcpopt_wscale(const ip_tcp_opt *optp, tvbuff_t *tvb,
2128 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2130 proto_item *hidden_item;
2132 struct tcp_analysis *tcpd=NULL;
2134 tcpd=get_tcp_conversation_data(NULL,pinfo);
2136 ws = tvb_get_guint8(tvb, offset + 2);
2137 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_wscale, tvb,
2138 offset, optlen, TRUE);
2139 PROTO_ITEM_SET_HIDDEN(hidden_item);
2140 proto_tree_add_uint_format(opt_tree, hf_tcp_option_wscale_val, tvb,
2141 offset, optlen, ws, "%s: %u (multiply by %u)",
2142 optp->name, ws, 1 << ws);
2143 tcp_info_append_uint(pinfo, "WS", ws);
2144 if(!pinfo->fd->flags.visited && tcp_analyze_seq && tcp_relative_seq){
2145 pdu_store_window_scale_option(ws, tcpd);
2150 dissect_tcpopt_sack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2151 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2153 proto_tree *field_tree = NULL;
2154 proto_item *tf=NULL;
2155 proto_item *hidden_item;
2156 guint32 leftedge, rightedge;
2157 struct tcp_analysis *tcpd=NULL;
2160 if(tcp_analyze_seq && tcp_relative_seq){
2161 /* find(or create if needed) the conversation for this tcp session */
2162 tcpd=get_tcp_conversation_data(NULL,pinfo);
2165 base_ack=tcpd->rev->base_seq;
2169 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
2170 offset += 2; /* skip past type and length */
2171 optlen -= 2; /* subtract size of type and length */
2172 while (optlen > 0) {
2173 if (field_tree == NULL) {
2174 /* Haven't yet made a subtree out of this option. Do so. */
2175 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2176 hidden_item = proto_tree_add_boolean(field_tree, hf_tcp_option_sack, tvb,
2177 offset, optlen, TRUE);
2178 PROTO_ITEM_SET_HIDDEN(hidden_item);
2181 proto_tree_add_text(field_tree, tvb, offset, optlen,
2182 "(suboption would go past end of option)");
2185 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;
2186 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
2187 offset, 4, leftedge,
2188 "left edge = %u%s", leftedge,
2189 tcp_relative_seq ? " (relative)" : "");
2193 proto_tree_add_text(field_tree, tvb, offset, optlen,
2194 "(suboption would go past end of option)");
2197 /* XXX - check whether it goes past end of packet */
2198 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;
2200 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
2201 offset+4, 4, rightedge,
2202 "right edge = %u%s", rightedge,
2203 tcp_relative_seq ? " (relative)" : "");
2204 tcp_info_append_uint(pinfo, "SLE", leftedge);
2205 tcp_info_append_uint(pinfo, "SRE", rightedge);
2206 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);
2212 dissect_tcpopt_echo(const ip_tcp_opt *optp, tvbuff_t *tvb,
2213 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2215 proto_item *hidden_item;
2218 echo = tvb_get_ntohl(tvb, offset + 2);
2219 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_echo, tvb, offset,
2221 PROTO_ITEM_SET_HIDDEN(hidden_item);
2222 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2223 "%s: %u", optp->name, echo);
2224 tcp_info_append_uint(pinfo, "ECHO", echo);
2228 dissect_tcpopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
2229 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2231 proto_item *hidden_item;
2234 tsv = tvb_get_ntohl(tvb, offset + 2);
2235 tser = tvb_get_ntohl(tvb, offset + 6);
2236 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_time_stamp, tvb,
2237 offset, optlen, TRUE);
2238 PROTO_ITEM_SET_HIDDEN(hidden_item);
2239 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2240 "%s: TSval %u, TSecr %u", optp->name, tsv, tser);
2241 tcp_info_append_uint(pinfo, "TSV", tsv);
2242 tcp_info_append_uint(pinfo, "TSER", tser);
2246 dissect_tcpopt_cc(const ip_tcp_opt *optp, tvbuff_t *tvb,
2247 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2249 proto_item *hidden_item;
2252 cc = tvb_get_ntohl(tvb, offset + 2);
2253 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_cc, tvb, offset,
2255 PROTO_ITEM_SET_HIDDEN(hidden_item);
2256 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2257 "%s: %u", optp->name, cc);
2258 tcp_info_append_uint(pinfo, "CC", cc);
2262 dissect_tcpopt_qs(const ip_tcp_opt *optp, tvbuff_t *tvb,
2263 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2265 /* Quick-Start TCP option, as defined by RFC4782 */
2266 static const value_string qs_rates[] = {
2272 { 5, "1.28 Mbit/s"},
2273 { 6, "2.56 Mbit/s"},
2274 { 7, "5.12 Mbit/s"},
2275 { 8, "10.24 Mbit/s"},
2276 { 9, "20.48 Mbit/s"},
2277 {10, "40.96 Mbit/s"},
2278 {11, "81.92 Mbit/s"},
2279 {12, "163.84 Mbit/s"},
2280 {13, "327.68 Mbit/s"},
2281 {14, "655.36 Mbit/s"},
2282 {15, "1.31072 Gbit/s"},
2285 proto_item *hidden_item;
2287 guint8 rate = tvb_get_guint8(tvb, offset + 2) & 0x0f;
2289 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_qs, tvb, offset,
2291 PROTO_ITEM_SET_HIDDEN(hidden_item);
2292 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2293 "%s: Rate response, %s, TTL diff %u ", optp->name,
2294 val_to_str(rate, qs_rates, "Unknown"),
2295 tvb_get_guint8(tvb, offset + 3));
2296 if (check_col(pinfo->cinfo, COL_INFO))
2297 col_append_fstr(pinfo->cinfo, COL_INFO, " QSresp=%s", val_to_str(rate, qs_rates, "Unknown"));
2302 dissect_tcpopt_scps(const ip_tcp_opt *optp, tvbuff_t *tvb,
2303 int offset, guint optlen, packet_info *pinfo,
2304 proto_tree *opt_tree)
2306 struct tcp_analysis *tcpd=NULL;
2307 proto_tree *field_tree = NULL;
2310 proto_item *tf = NULL, *hidden_item;
2311 gchar flags[64] = "<None>";
2312 gchar *fstr[] = {"BETS", "SNACK1", "SNACK2", "COMP", "NLTS", "RESV1", "RESV2", "RESV3"};
2317 tcpd = get_tcp_conversation_data(NULL,pinfo);
2319 /* check direction and get ua lists */
2320 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
2322 /* if the addresses are equal, match the ports instead */
2324 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
2328 flow =&(tcpd->flow1);
2330 flow =&(tcpd->flow2);
2332 /* If the option length == 4, this is a real SCPS capability option
2333 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
2334 * (SCPS-TP)" Section 3.2.3 for definition.
2337 capvector = tvb_get_guint8(tvb, offset + 2);
2340 /* Decode the capabilities vector for display */
2341 for (i = 0; i < 5; i++) {
2343 if (capvector & bpos) {
2345 g_strlcat(flags, ", ", 64);
2347 g_strlcat(flags, fstr[i], 64);
2351 /* If lossless header compression is offered, there will be a
2352 * single octet connectionId following the capabilities vector
2354 if (capvector & 0x10)
2355 connid = tvb_get_guint8(tvb, offset + 3);
2359 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector, tvb,
2360 offset, optlen, capvector,
2362 optp->name, capvector, flags);
2363 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_scps,
2364 tvb, offset, optlen, TRUE);
2365 PROTO_ITEM_SET_HIDDEN(hidden_item);
2367 field_tree = proto_item_add_subtree(tf, ett_tcp_option_scps);
2369 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_bets, tvb,
2370 offset + 13, 1, capvector);
2371 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_snack1, tvb,
2372 offset + 13, 1, capvector);
2373 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_snack2, tvb,
2374 offset + 13, 1, capvector);
2375 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_compress, tvb,
2376 offset + 13, 1, capvector);
2377 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_nlts, tvb,
2378 offset + 13, 1, capvector);
2379 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv1, tvb,
2380 offset + 13, 1, capvector);
2381 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv2, tvb,
2382 offset + 13, 1, capvector);
2383 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv3, tvb,
2384 offset + 13, 1, capvector);
2386 tcp_info_append_str(pinfo, "SCPS", flags);
2388 flow->scps_capable = 1;
2391 tcp_info_append_uint(pinfo, "Connection ID", connid);
2394 /* The option length != 4, so this is an infamous "extended capabilities
2395 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2396 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
2398 * As the format of this option is only partially defined (it is
2399 * a community (or more likely vendor) defined format beyond that, so
2400 * at least for now, we only parse the standardized portion of the option.
2402 guint8 local_offset = 2;
2403 guint8 binding_space;
2404 guint8 extended_cap_length;
2406 if (flow->scps_capable != 1) {
2407 /* There was no SCPS capabilities option preceeding this */
2408 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2409 tvb, offset, optlen, 0, "%s: (%d %s)",
2410 "Illegal SCPS Extended Capabilities",
2415 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2416 tvb, offset, optlen, 0, "%s: (%d %s)",
2417 "SCPS Extended Capabilities",
2420 field_tree=proto_item_add_subtree(tf, ett_tcp_option_scps_extended);
2421 /* There may be multiple binding spaces included in a single option,
2422 * so we will semi-parse each of the stacked binding spaces - skipping
2423 * over the octets following the binding space identifier and length.
2426 while (optlen > local_offset) {
2427 proto_item *hidden_item;
2429 /* 1st octet is Extended Capability Binding Space */
2430 binding_space = tvb_get_guint8(tvb, (offset + local_offset));
2432 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
2433 * As defined by the specification, this length is exclusive of the
2434 * octets containing the extended capability type and length
2437 extended_cap_length =
2438 (tvb_get_guint8(tvb, (offset + local_offset + 1)) >> 4);
2440 /* Convert the extended capabilities length into bytes for display */
2441 extended_cap_length = (extended_cap_length << 1);
2443 proto_tree_add_text(field_tree, tvb, offset + local_offset, 2,
2444 "\tBinding Space %u",
2446 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding,
2447 tvb, (offset + local_offset), 1,
2450 PROTO_ITEM_SET_HIDDEN(hidden_item);
2452 /* Step past the binding space and length octets */
2455 proto_tree_add_text(field_tree, tvb, offset + local_offset,
2456 extended_cap_length,
2457 "\tBinding Space Data (%u bytes)",
2458 extended_cap_length);
2460 tcp_info_append_uint(pinfo, "EXCAP", binding_space);
2462 /* Step past the Extended capability data
2463 * Treat the extended capability data area as opaque;
2464 * If one desires to parse the extended capability data
2465 * (say, in a vendor aware build of wireshark), it would
2468 local_offset += extended_cap_length;
2474 /* This is called for SYN+ACK packets and the purpose is to verify that
2475 * the SCPS capabilities option has been successfully negotiated for the flow.
2476 * If the SCPS capabilities option was offered by only one party, the
2477 * proactively set scps_capable attribute of the flow (set upon seeing
2478 * the first instance of the SCPS option) is revoked.
2481 verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd)
2486 if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) {
2487 tcpd->flow1.scps_capable = 0;
2488 tcpd->flow2.scps_capable = 0;
2491 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_NOTE,
2492 "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated");
2497 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2498 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
2501 dissect_tcpopt_snack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2502 int offset, guint optlen, packet_info *pinfo,
2503 proto_tree *opt_tree)
2505 struct tcp_analysis *tcpd=NULL;
2506 guint16 relative_hole_offset;
2507 guint16 relative_hole_size;
2508 guint16 base_mss = 0;
2512 char null_modifier[] = "\0";
2513 char relative_modifier[] = "(relative)";
2514 char *modifier = null_modifier;
2515 proto_item *hidden_item;
2517 tcpd = get_tcp_conversation_data(NULL,pinfo);
2519 /* The SNACK option reports missing data with a granualarity of segments. */
2520 relative_hole_offset = tvb_get_ntohs(tvb, offset + 2);
2521 relative_hole_size = tvb_get_ntohs(tvb, offset + 4);
2523 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_snack, tvb,
2524 offset, optlen, TRUE);
2525 PROTO_ITEM_SET_HIDDEN(hidden_item);
2527 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_offset,
2528 tvb, offset, optlen, relative_hole_offset);
2529 PROTO_ITEM_SET_HIDDEN(hidden_item);
2531 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_size,
2532 tvb, offset, optlen, relative_hole_size);
2533 PROTO_ITEM_SET_HIDDEN(hidden_item);
2534 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2535 "%s: Offset %u, Size %u", optp->name,
2536 relative_hole_offset, relative_hole_size);
2538 ack = tvb_get_ntohl(tvb, 8);
2540 if (tcp_relative_seq) {
2541 ack -= tcpd->rev->base_seq;
2542 modifier = relative_modifier;
2545 /* To aid analysis, we can use a simple but generally effective heuristic
2546 * to report the most likely boundaries of the missing data. If the
2547 * flow is scps_capable, we track the maximum sized segment that was
2548 * acknowledged by the receiver and use that as the reporting granularity.
2549 * This may be different from the negotiated MTU due to PMTUD or flows
2550 * that do not send max-sized segments.
2552 base_mss = tcpd->fwd->maxsizeacked;
2555 proto_item *hidden_item;
2556 /* Scale the reported offset and hole size by the largest segment acked */
2557 hole_start = ack + (base_mss * relative_hole_offset);
2558 hole_end = hole_start + (base_mss * relative_hole_size);
2560 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_le,
2561 tvb, offset, optlen, hole_start);
2562 PROTO_ITEM_SET_HIDDEN(hidden_item);
2564 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_re,
2565 tvb, offset, optlen, hole_end);
2566 PROTO_ITEM_SET_HIDDEN(hidden_item);
2567 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2568 "\tMissing Sequence %u - %u %s",
2569 hole_start, hole_end, modifier);
2571 tcp_info_append_uint(pinfo, "SNLE", hole_start);
2572 tcp_info_append_uint(pinfo, "SNRE", hole_end);
2574 expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_NOTE,
2575 "SNACK Sequence %u - %u %s",
2576 hole_start, hole_end, modifier);
2580 static const ip_tcp_opt tcpopts[] = {
2599 "Maximum segment size",
2603 dissect_tcpopt_maxseg
2611 dissect_tcpopt_wscale
2624 &ett_tcp_option_sack,
2651 dissect_tcpopt_timestamp
2679 "TCP MD5 signature",
2688 &ett_tcp_option_scps,
2695 "Selective Negative Acknowledgement",
2699 dissect_tcpopt_snack
2703 "SCPS record boundary",
2711 "SCPS corruption experienced",
2727 #define N_TCP_OPTS (sizeof tcpopts / sizeof tcpopts[0])
2729 /* Determine if there is a sub-dissector and call it; return TRUE
2730 if there was a sub-dissector, FALSE otherwise.
2732 This has been separated into a stand alone routine to other protocol
2733 dissectors can call to it, e.g., SOCKS. */
2735 static gboolean try_heuristic_first = FALSE;
2738 /* this function can be called with tcpd==NULL as from the msproxy dissector */
2740 decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
2741 proto_tree *tree, int src_port, int dst_port,
2742 struct tcp_analysis *tcpd)
2745 int low_port, high_port;
2746 int save_desegment_offset;
2747 guint32 save_desegment_len;
2749 /* dont call subdissectors for keepalive or zerowindowprobes
2750 * even though they do contain payload "data"
2751 * keeaplives just contain garbage and zwp contain too little data (1 byte)
2754 if(tcpd && tcpd->ta){
2755 if(tcpd->ta->flags&(TCP_A_ZERO_WINDOW_PROBE|TCP_A_KEEP_ALIVE)){
2760 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
2762 /* determine if this packet is part of a conversation and call dissector */
2763 /* for the conversation if available */
2765 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP,
2766 src_port, dst_port, next_tvb, pinfo, tree)){
2767 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2771 if (try_heuristic_first) {
2772 /* do lookup with the heuristic subdissector table */
2773 save_desegment_offset = pinfo->desegment_offset;
2774 save_desegment_len = pinfo->desegment_len;
2775 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
2776 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2780 * They rejected the packet; make sure they didn't also request
2781 * desegmentation (we could just override the request, but
2782 * rejecting a packet *and* requesting desegmentation is a sign
2783 * of the dissector's code needing clearer thought, so we fail
2784 * so that the problem is made more obvious).
2786 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
2787 save_desegment_len == pinfo->desegment_len);
2790 /* Do lookups with the subdissector table.
2791 We try the port number with the lower value first, followed by the
2792 port number with the higher value. This means that, for packets
2793 where a dissector is registered for *both* port numbers:
2795 1) we pick the same dissector for traffic going in both directions;
2797 2) we prefer the port number that's more likely to be the right
2798 one (as that prefers well-known ports to reserved ports);
2800 although there is, of course, no guarantee that any such strategy
2801 will always pick the right port number.
2803 XXX - we ignore port numbers of 0, as some dissectors use a port
2804 number of 0 to disable the port. */
2805 if (src_port > dst_port) {
2806 low_port = dst_port;
2807 high_port = src_port;
2809 low_port = src_port;
2810 high_port = dst_port;
2812 if (low_port != 0 &&
2813 dissector_try_port(subdissector_table, low_port, next_tvb, pinfo, tree)){
2814 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2817 if (high_port != 0 &&
2818 dissector_try_port(subdissector_table, high_port, next_tvb, pinfo, tree)){
2819 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2823 if (!try_heuristic_first) {
2824 /* do lookup with the heuristic subdissector table */
2825 save_desegment_offset = pinfo->desegment_offset;
2826 save_desegment_len = pinfo->desegment_len;
2827 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
2828 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2832 * They rejected the packet; make sure they didn't also request
2833 * desegmentation (we could just override the request, but
2834 * rejecting a packet *and* requesting desegmentation is a sign
2835 * of the dissector's code needing clearer thought, so we fail
2836 * so that the problem is made more obvious).
2838 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
2839 save_desegment_len == pinfo->desegment_len);
2842 /* Oh, well, we don't know this; dissect it as data. */
2843 call_dissector(data_handle,next_tvb, pinfo, tree);
2845 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2850 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
2851 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
2852 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
2853 struct tcp_analysis *tcpd)
2855 pinfo->want_pdu_tracking=0;
2859 /*qqq see if it is an unaligned PDU */
2860 if(tcpd && tcp_analyze_seq && (!tcp_desegment)){
2862 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
2863 seq, nxtseq, tcpd->fwd->multisegment_pdus);
2867 /* if offset is -1 this means that this segment is known
2868 * to be fully inside a previously detected pdu
2869 * so we dont even need to try to dissect it either.
2872 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
2875 * We succeeded in handing off to a subdissector.
2877 * Is this a TCP segment or a reassembled chunk of
2881 /* if !visited, check want_pdu_tracking and
2882 store it in table */
2883 if(tcpd && (!pinfo->fd->flags.visited) &&
2884 tcp_analyze_seq && pinfo->want_pdu_tracking){
2886 pdu_store_sequencenumber_of_next_pdu(
2889 nxtseq+pinfo->bytes_until_next_pdu,
2890 tcpd->fwd->multisegment_pdus);
2897 /* We got an exception. At this point the dissection is
2898 * completely aborted and execution will be transfered back
2899 * to (probably) the frame dissector.
2900 * Here we have to place whatever we want the dissector
2901 * to do before aborting the tcp dissection.
2904 * Is this a TCP segment or a reassembled chunk of TCP
2909 * It's from a TCP segment.
2911 * if !visited, check want_pdu_tracking and store it
2914 if(tcpd && (!pinfo->fd->flags.visited) && tcp_analyze_seq && pinfo->want_pdu_tracking){
2916 pdu_store_sequencenumber_of_next_pdu(pinfo,
2918 nxtseq+pinfo->bytes_until_next_pdu,
2919 tcpd->fwd->multisegment_pdus);
2929 dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,
2930 guint32 nxtseq, guint32 sport, guint32 dport,
2931 proto_tree *tree, proto_tree *tcp_tree,
2932 struct tcp_analysis *tcpd)
2934 gboolean save_fragmented;
2936 /* Can we desegment this segment? */
2937 if (pinfo->can_desegment) {
2939 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
2942 /* No - just call the subdissector.
2943 Mark this as fragmented, so if somebody throws an exception,
2944 we don't report it as a malformed frame. */
2945 save_fragmented = pinfo->fragmented;
2946 pinfo->fragmented = TRUE;
2947 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
2948 seq, nxtseq, TRUE, tcpd);
2949 pinfo->fragmented = save_fragmented;
2954 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2956 guint8 th_off_x2; /* combines th_off and th_x2 */
2959 proto_tree *tcp_tree = NULL, *field_tree = NULL;
2960 proto_item *ti = NULL, *tf, *hidden_item;
2962 gchar *flags = "<None>";
2963 const gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR"};
2964 size_t fpos = 0, returned_length;
2972 guint16 computed_cksum;
2973 guint16 real_window;
2974 guint length_remaining;
2975 gboolean desegment_ok;
2976 struct tcpinfo tcpinfo;
2977 struct tcpheader *tcph;
2978 proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL;
2979 conversation_t *conv=NULL;
2980 struct tcp_analysis *tcpd=NULL;
2981 struct tcp_per_packet_data_t *tcppd=NULL;
2983 proto_tree *checksum_tree;
2987 tcph=ep_alloc(sizeof(struct tcpheader));
2988 SET_ADDRESS(&tcph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
2989 SET_ADDRESS(&tcph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
2991 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2992 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
2994 /* Clear out the Info column. */
2995 if (check_col(pinfo->cinfo, COL_INFO))
2996 col_clear(pinfo->cinfo, COL_INFO);
2998 tcph->th_sport = tvb_get_ntohs(tvb, offset);
2999 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
3000 if (check_col(pinfo->cinfo, COL_INFO)) {
3001 col_append_fstr(pinfo->cinfo, COL_INFO, "%s > %s",
3002 get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
3005 if (tcp_summary_in_tree) {
3006 ti = proto_tree_add_protocol_format(tree, proto_tcp, tvb, 0, -1,
3007 "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
3008 get_tcp_port(tcph->th_sport), tcph->th_sport,
3009 get_tcp_port(tcph->th_dport), tcph->th_dport);
3012 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, FALSE);
3014 tcp_tree = proto_item_add_subtree(ti, ett_tcp);
3015 pinfo->tcp_tree=tcp_tree;
3017 proto_tree_add_uint_format(tcp_tree, hf_tcp_srcport, tvb, offset, 2, tcph->th_sport,
3018 "Source port: %s (%u)", get_tcp_port(tcph->th_sport), tcph->th_sport);
3019 proto_tree_add_uint_format(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, tcph->th_dport,
3020 "Destination port: %s (%u)", get_tcp_port(tcph->th_dport), tcph->th_dport);
3021 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset, 2, tcph->th_sport);
3022 PROTO_ITEM_SET_HIDDEN(hidden_item);
3023 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, tcph->th_dport);
3024 PROTO_ITEM_SET_HIDDEN(hidden_item);
3026 /* If we're dissecting the headers of a TCP packet in an ICMP packet
3027 * then go ahead and put the sequence numbers in the tree now (because
3028 * they won't be put in later because the ICMP packet only contains up
3029 * to the sequence number).
3030 * We should only need to do this for IPv4 since IPv6 will hopefully
3031 * carry enough TCP payload for this dissector to put the sequence
3032 * numbers in via the regular code path.
3034 if (pinfo->layer_names != NULL && pinfo->layer_names->str != NULL) {
3035 /* use strstr because g_strrstr is only present in glib2.0 and
3036 * g_str_has_suffix in glib2.2
3038 if (strstr(pinfo->layer_names->str, "icmp:ip") != NULL)
3039 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, FALSE);
3043 /* Set the source and destination port numbers as soon as we get them,
3044 so that they're available to the "Follow TCP Stream" code even if
3045 we throw an exception dissecting the rest of the TCP header. */
3046 pinfo->ptype = PT_TCP;
3047 pinfo->srcport = tcph->th_sport;
3048 pinfo->destport = tcph->th_dport;
3050 tcph->th_seq = tvb_get_ntohl(tvb, offset + 4);
3051 tcph->th_ack = tvb_get_ntohl(tvb, offset + 8);
3052 th_off_x2 = tvb_get_guint8(tvb, offset + 12);
3053 tcph->th_flags = tvb_get_guint8(tvb, offset + 13);
3054 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
3055 real_window = tcph->th_win;
3056 tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
3058 /* find(or create if needed) the conversation for this tcp session */
3059 conv=get_tcp_conversation(pinfo);
3060 tcpd=get_tcp_conversation_data(conv,pinfo);
3062 item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 4, conv->index);
3063 PROTO_ITEM_SET_GENERATED(item);
3065 /* If this is a SYN packet, then check if it's seq-nr is different
3066 * from the base_seq of the retrieved conversation. If this is the
3067 * case, create a new conversation with the same addresses and ports
3068 * and set the TA_PORTS_REUSED flag. If the seq-nr is the same as
3069 * the base_seq, then do nothing so it will be marked as a retrans-
3072 if(tcpd && ((tcph->th_flags&(TH_SYN|TH_ACK))==TH_SYN) &&
3073 (tcpd->fwd->base_seq!=0) &&
3074 (tcph->th_seq!=tcpd->fwd->base_seq) ) {
3075 if (!(pinfo->fd->flags.visited)) {
3076 conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3077 tcpd=get_tcp_conversation_data(conv,pinfo);
3080 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
3081 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
3085 /* Do we need to calculate timestamps relative to the tcp-stream? */
3086 if (tcp_calculate_ts) {
3087 tcppd = p_get_proto_data(pinfo->fd, proto_tcp);
3090 * Calculate the timestamps relative to this conversation (but only on the
3091 * first run when frames are accessed sequentially)
3093 if (!(pinfo->fd->flags.visited))
3094 tcp_calculate_timestamps(pinfo, tcpd, tcppd);
3096 /* Fill the conversation timestamp columns */
3097 if (tcpd && check_col(pinfo->cinfo, COL_REL_CONV_TIME)) {
3098 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
3099 col_set_time(pinfo->cinfo, COL_REL_CONV_TIME, &ts, "tcp.time_relative");
3102 if (check_col(pinfo->cinfo, COL_DELTA_CONV_TIME)) {
3104 col_set_time(pinfo->cinfo, COL_DELTA_CONV_TIME, &tcppd->ts_del, "tcp.time_delta");
3110 * If we've been handed an IP fragment, we don't know how big the TCP
3111 * segment is, so don't do anything that requires that we know that.
3113 * The same applies if we're part of an error packet. (XXX - if the
3114 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
3115 * header says it is" length in the tvbuff, we could use that; such
3116 * a length might also be useful for handling packets where the IP
3117 * length is bigger than the actual data available in the frame; the
3118 * dissectors should trust that length, and then throw a
3119 * ReportedBoundsError exception when they go past the end of the frame.)
3121 * We also can't determine the segment length if the reported length
3122 * of the TCP packet is less than the TCP header length.
3124 reported_len = tvb_reported_length(tvb);
3126 if (!pinfo->fragmented && !pinfo->in_error_pkt) {
3127 if (reported_len < tcph->th_hlen) {
3129 pi = proto_tree_add_text(tcp_tree, tvb, offset, 0,
3130 "Short segment. Segment/fragment does not contain a full TCP header"
3131 " (might be NMAP or someone else deliberately sending unusual packets)");
3132 PROTO_ITEM_SET_GENERATED(pi);
3133 expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_WARN, "Short segment");
3134 tcph->th_have_seglen = FALSE;
3136 /* Compute the length of data in this segment. */
3137 tcph->th_seglen = reported_len - tcph->th_hlen;
3138 tcph->th_have_seglen = TRUE;
3140 if (tree) { /* Add the seglen as an invisible field */
3142 hidden_item = proto_tree_add_uint(ti, hf_tcp_len, tvb, offset, 4, tcph->th_seglen);
3143 PROTO_ITEM_SET_HIDDEN(hidden_item);
3148 /* handle TCP seq# analysis parse all new segments we see */
3149 if(tcp_analyze_seq){
3150 if(!(pinfo->fd->flags.visited)){
3151 tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd);
3153 if(tcp_relative_seq){
3154 tcp_get_relative_seq_ack(&(tcph->th_seq), &(tcph->th_ack), &(tcph->th_win), tcpd);
3158 /* Compute the sequence number of next octet after this segment. */
3159 nxtseq = tcph->th_seq + tcph->th_seglen;
3162 tcph->th_have_seglen = FALSE;
3164 if (check_col(pinfo->cinfo, COL_INFO) || tree) {
3165 #define MAX_FLAGS_LEN 64
3166 flags=ep_alloc(MAX_FLAGS_LEN);
3168 for (i = 0; i < 8; i++) {
3170 if (tcph->th_flags & bpos) {
3171 returned_length = g_snprintf(&flags[fpos], MAX_FLAGS_LEN-fpos, "%s%s",
3174 fpos += MIN(returned_length, MAX_FLAGS_LEN-fpos);
3179 if (check_col(pinfo->cinfo, COL_INFO)) {
3180 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] Seq=%u", flags, tcph->th_seq);
3181 if (tcph->th_flags&TH_ACK) {
3182 col_append_fstr(pinfo->cinfo, COL_INFO, " Ack=%u", tcph->th_ack);
3184 if (tcph->th_flags&TH_SYN) { /* SYNs are never scaled */
3185 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", real_window);
3187 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", tcph->th_win);
3192 if (tcp_summary_in_tree) {
3193 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
3195 if(tcp_relative_seq){
3196 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);
3198 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
3202 if (tcph->th_hlen < TCPH_MIN_LEN) {
3203 /* Give up at this point; we put the source and destination port in
3204 the tree, before fetching the header length, so that they'll
3205 show up if this is in the failing packet in an ICMP error packet,
3206 but it's now time to give up if the header length is bogus. */
3207 if (check_col(pinfo->cinfo, COL_INFO))
3208 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
3209 tcph->th_hlen, TCPH_MIN_LEN);
3211 proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
3212 "Header length: %u bytes (bogus, must be at least %u)", tcph->th_hlen,
3219 if (tcp_summary_in_tree) {
3220 if(tcph->th_flags&TH_ACK){
3221 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
3223 if (tcph->th_have_seglen)
3224 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
3226 proto_item_set_len(ti, tcph->th_hlen);
3227 if (tcph->th_have_seglen) {
3228 if (nxtseq != tcph->th_seq) {
3229 if(tcp_relative_seq){
3230 tf=proto_tree_add_uint_format(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "Next sequence number: %u (relative sequence number)", nxtseq);
3232 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
3234 PROTO_ITEM_SET_GENERATED(tf);
3237 if (tcph->th_flags & TH_ACK) {
3238 if(tcp_relative_seq){
3239 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);
3241 proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
3244 /* Verify that the ACK field is zero */
3245 if(tvb_get_ntohl(tvb, offset+8) != 0){
3246 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");
3249 proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
3250 "Header length: %u bytes", tcph->th_hlen);
3251 tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 13, 1,
3252 tcph->th_flags, "Flags: 0x%02x (%s)", tcph->th_flags, flags);
3253 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
3254 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
3255 proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, tvb, offset + 13, 1, tcph->th_flags);
3256 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
3257 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
3258 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
3259 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
3260 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
3261 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
3263 && (tcph->th_win!=real_window)
3264 && !(tcph->th_flags&TH_SYN) ){ /* SYNs are never scaled */
3265 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);
3267 proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, real_window);
3271 if(tcph->th_flags & TH_SYN) {
3272 if(tcph->th_flags & TH_ACK)
3273 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK): server port %s",
3274 get_tcp_port(tcph->th_sport));
3276 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN): server port %s",
3277 get_tcp_port(tcph->th_dport));
3279 if(tcph->th_flags & TH_FIN)
3280 /* XXX - find a way to know the server port and output only that one */
3281 expert_add_info_format(pinfo, tf_fin, PI_SEQUENCE, PI_CHAT, "Connection finish (FIN)");
3282 if(tcph->th_flags & TH_RST)
3283 /* XXX - find a way to know the server port and output only that one */
3284 expert_add_info_format(pinfo, tf_rst, PI_SEQUENCE, PI_CHAT, "Connection reset (RST)");
3286 /* Supply the sequence number of the first byte and of the first byte
3287 after the segment. */
3288 tcpinfo.seq = tcph->th_seq;
3289 tcpinfo.nxtseq = nxtseq;
3290 tcpinfo.lastackseq = tcph->th_ack;
3292 /* Assume we'll pass un-reassembled data to subdissectors. */
3293 tcpinfo.is_reassembled = FALSE;
3295 pinfo->private_data = &tcpinfo;
3298 * Assume, initially, that we can't desegment.
3300 pinfo->can_desegment = 0;
3301 th_sum = tvb_get_ntohs(tvb, offset + 16);
3302 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
3303 /* The packet isn't part of an un-reassembled fragmented datagram
3304 and isn't truncated. This means we have all the data, and thus
3305 can checksum it and, unless it's being returned in an error
3306 packet, are willing to allow subdissectors to request reassembly
3309 if (tcp_check_checksum) {
3310 /* We haven't turned checksum checking off; checksum it. */
3312 /* Set up the fields of the pseudo-header. */
3313 cksum_vec[0].ptr = pinfo->src.data;
3314 cksum_vec[0].len = pinfo->src.len;
3315 cksum_vec[1].ptr = pinfo->dst.data;
3316 cksum_vec[1].len = pinfo->dst.len;
3317 cksum_vec[2].ptr = (const guint8 *)phdr;
3318 switch (pinfo->src.type) {
3321 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
3322 cksum_vec[2].len = 4;
3326 phdr[0] = g_htonl(reported_len);
3327 phdr[1] = g_htonl(IP_PROTO_TCP);
3328 cksum_vec[2].len = 8;
3332 /* TCP runs only atop IPv4 and IPv6.... */
3333 DISSECTOR_ASSERT_NOT_REACHED();
3336 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, reported_len);
3337 cksum_vec[3].len = reported_len;
3338 computed_cksum = in_cksum(cksum_vec, 4);
3339 if (computed_cksum == 0 && th_sum == 0xffff) {
3340 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3341 offset + 16, 2, th_sum,
3342 "Checksum: 0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);
3344 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3345 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3346 offset + 16, 2, FALSE);
3347 PROTO_ITEM_SET_GENERATED(item);
3348 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3349 offset + 16, 2, FALSE);
3350 PROTO_ITEM_SET_GENERATED(item);
3351 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_WARN, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)");
3353 if (check_col(pinfo->cinfo, COL_INFO))
3354 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");
3356 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
3357 desegment_ok = TRUE;
3358 } else if (computed_cksum == 0) {
3359 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3360 offset + 16, 2, th_sum, "Checksum: 0x%04x [correct]", th_sum);
3362 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3363 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3364 offset + 16, 2, TRUE);
3365 PROTO_ITEM_SET_GENERATED(item);
3366 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3367 offset + 16, 2, FALSE);
3368 PROTO_ITEM_SET_GENERATED(item);
3370 /* Checksum is valid, so we're willing to desegment it. */
3371 desegment_ok = TRUE;
3372 } else if (th_sum == 0) {
3373 /* checksum is probably fine but checksum offload is used */
3374 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3375 offset + 16, 2, th_sum, "Checksum: 0x%04x [Checksum Offloaded]", th_sum);
3377 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3378 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3379 offset + 16, 2, FALSE);
3380 PROTO_ITEM_SET_GENERATED(item);
3381 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3382 offset + 16, 2, FALSE);
3383 PROTO_ITEM_SET_GENERATED(item);
3385 /* Checksum is (probably) valid, so we're willing to desegment it. */
3386 desegment_ok = TRUE;
3388 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3389 offset + 16, 2, th_sum,
3390 "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]", th_sum,
3391 in_cksum_shouldbe(th_sum, computed_cksum));
3393 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3394 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3395 offset + 16, 2, FALSE);
3396 PROTO_ITEM_SET_GENERATED(item);
3397 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3398 offset + 16, 2, TRUE);
3399 PROTO_ITEM_SET_GENERATED(item);
3400 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
3402 if (check_col(pinfo->cinfo, COL_INFO))
3403 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");
3405 /* Checksum is invalid, so we're not willing to desegment it. */
3406 desegment_ok = FALSE;
3407 pinfo->noreassembly_reason = " [incorrect TCP checksum]";
3410 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3411 offset + 16, 2, th_sum, "Checksum: 0x%04x [validation disabled]", th_sum);
3413 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3414 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3415 offset + 16, 2, FALSE);
3416 PROTO_ITEM_SET_GENERATED(item);
3417 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3418 offset + 16, 2, FALSE);
3419 PROTO_ITEM_SET_GENERATED(item);
3421 /* We didn't check the checksum, and don't care if it's valid,
3422 so we're willing to desegment it. */
3423 desegment_ok = TRUE;
3426 /* We don't have all the packet data, so we can't checksum it... */
3427 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3428 offset + 16, 2, th_sum, "Checksum: 0x%04x [unchecked, not all data available]", th_sum);
3430 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3431 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3432 offset + 16, 2, FALSE);
3433 PROTO_ITEM_SET_GENERATED(item);
3434 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3435 offset + 16, 2, FALSE);
3436 PROTO_ITEM_SET_GENERATED(item);
3438 /* ...and aren't willing to desegment it. */
3439 desegment_ok = FALSE;
3443 /* We're willing to desegment this. Is desegmentation enabled? */
3444 if (tcp_desegment) {
3445 /* Yes - is this segment being returned in an error packet? */
3446 if (!pinfo->in_error_pkt) {
3447 /* No - indicate that we will desegment.
3448 We do NOT want to desegment segments returned in error
3449 packets, as they're not part of a TCP connection. */
3450 pinfo->can_desegment = 2;
3455 if (tcph->th_flags & TH_URG) {
3456 th_urp = tvb_get_ntohs(tvb, offset + 18);
3457 /* Export the urgent pointer, for the benefit of protocols such as
3459 tcpinfo.urgent = TRUE;
3460 tcpinfo.urgent_pointer = th_urp;
3461 if (check_col(pinfo->cinfo, COL_INFO))
3462 col_append_fstr(pinfo->cinfo, COL_INFO, " Urg=%u", th_urp);
3463 if (tcp_tree != NULL)
3464 proto_tree_add_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, th_urp);
3466 tcpinfo.urgent = FALSE;
3468 if (tcph->th_have_seglen) {
3469 if (check_col(pinfo->cinfo, COL_INFO))
3470 col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", tcph->th_seglen);
3473 /* Decode TCP options, if any. */
3474 if (tcph->th_hlen > TCPH_MIN_LEN) {
3475 /* There's more than just the fixed-length header. Decode the
3477 optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
3478 tvb_ensure_bytes_exist(tvb, offset + 20, optlen);
3479 if (tcp_tree != NULL) {
3480 guint8 *p_options = ep_tvb_memdup(tvb, offset + 20, optlen);
3481 tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
3482 optlen, p_options, "Options: (%u bytes)", optlen);
3483 field_tree = proto_item_add_subtree(tf, ett_tcp_options);
3486 dissect_ip_tcp_options(tvb, offset + 20, optlen,
3487 tcpopts, N_TCP_OPTS, TCPOPT_EOL, pinfo, field_tree);
3490 if(!pinfo->fd->flags.visited){
3491 if((tcph->th_flags & (TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
3492 /* If there was window scaling in the SYN packet but none in the SYN+ACK
3493 * then we should just forget about the windowscaling completely.
3495 if(tcp_analyze_seq && tcp_relative_seq){
3496 verify_tcp_window_scaling(tcpd);
3498 /* If the SYN or the SYN+ACK offered SCPS capabilities,
3499 * validate the flow's bidirectional scps capabilities.
3500 * The or protects against broken implementations offering
3501 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
3503 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {
3504 verify_scps(pinfo, tf_syn, tcpd);
3509 /* Skip over header + options */
3510 offset += tcph->th_hlen;
3512 /* Check the packet length to see if there's more data
3513 (it could be an ACK-only packet) */
3514 length_remaining = tvb_length_remaining(tvb, offset);
3516 if (tcph->th_have_seglen) {
3517 if( data_out_file ) {
3518 reassemble_tcp( tcph->th_seq, /* sequence number */
3519 tcph->th_ack, /* acknowledgement number */
3520 tcph->th_seglen, /* data length */
3521 (gchar*)tvb_get_ptr(tvb, offset, length_remaining), /* data */
3522 length_remaining, /* captured data length */
3523 ( tcph->th_flags & TH_SYN ), /* is syn set? */
3531 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
3532 if(tcp_analyze_seq){
3533 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd);
3536 /* handle conversation timestamps */
3537 if(tcp_calculate_ts){
3538 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
3541 tap_queue_packet(tcp_tap, pinfo, tcph);
3544 /* A FIN packet might complete reassembly so we need to explicitly
3545 * check for this here.
3547 if(tcpd && (tcph->th_flags & TH_FIN)
3548 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ){
3549 struct tcp_multisegment_pdu *msp;
3551 /* find the most previous PDU starting before this sequence number */
3552 msp=se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq-1);
3554 fragment_data *ipfd_head;
3556 ipfd_head = fragment_add(tvb, offset, pinfo, msp->first_frame,
3558 tcph->th_seq - msp->seq,
3564 /* create a new TVB structure for desegmented data */
3565 next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen, ipfd_head->datalen);
3567 /* add this tvb as a child to the original one */
3568 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
3570 /* add desegmented data to the data source list */
3571 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
3573 /* call the payload dissector
3574 * but make sure we don't offer desegmentation any more
3576 pinfo->can_desegment = 0;
3578 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq, nxtseq, FALSE, tcpd);
3586 * XXX - what, if any, of this should we do if this is included in an
3587 * error packet? It might be nice to see the details of the packet
3588 * that caused the ICMP error, but it might not be nice to have the
3589 * dissector update state based on it.
3590 * Also, we probably don't want to run TCP taps on those packets.
3592 if (length_remaining != 0) {
3593 if (tcph->th_flags & TH_RST) {
3597 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
3599 * A TCP SHOULD allow a received RST segment to include data.
3602 * It has been suggested that a RST segment could contain
3603 * ASCII text that encoded and explained the cause of the
3604 * RST. No standard has yet been established for such
3607 * so for segments with RST we just display the data as text.
3609 proto_tree_add_text(tcp_tree, tvb, offset, length_remaining,
3611 tvb_format_text(tvb, offset, length_remaining));
3613 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
3614 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd);
3620 proto_register_tcp(void)
3622 static hf_register_info hf[] = {
3625 { "Source Port", "tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
3629 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3633 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
3637 { "Stream index", "tcp.stream", FT_UINT32, BASE_DEC, NULL, 0x0,
3641 { "Sequence number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
3645 { "Next sequence number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
3649 { "Acknowledgement number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
3653 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
3657 { "Flags", "tcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
3660 { &hf_tcp_flags_cwr,
3661 { "Congestion Window Reduced (CWR)", "tcp.flags.cwr", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_CWR,
3664 { &hf_tcp_flags_ecn,
3665 { "ECN-Echo", "tcp.flags.ecn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ECN,
3668 { &hf_tcp_flags_urg,
3669 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_URG,
3672 { &hf_tcp_flags_ack,
3673 { "Acknowledgement", "tcp.flags.ack", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ACK,
3676 { &hf_tcp_flags_push,
3677 { "Push", "tcp.flags.push", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_PUSH,
3680 { &hf_tcp_flags_reset,
3681 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_RST,
3684 { &hf_tcp_flags_syn,
3685 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_SYN,
3688 { &hf_tcp_flags_fin,
3689 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_FIN,
3692 /* 32 bits so we can present some values adjusted to window scaling */
3693 { &hf_tcp_window_size,
3694 { "Window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
3698 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
3699 "Details at: http://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
3701 { &hf_tcp_checksum_good,
3702 { "Good Checksum", "tcp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3703 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
3705 { &hf_tcp_checksum_bad,
3706 { "Bad Checksum", "tcp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3707 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
3709 { &hf_tcp_analysis_flags,
3710 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
3711 "This frame has some of the TCP analysis flags set", HFILL }},
3713 { &hf_tcp_analysis_retransmission,
3714 { "Retransmission", "tcp.analysis.retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
3715 "This frame is a suspected TCP retransmission", HFILL }},
3717 { &hf_tcp_analysis_fast_retransmission,
3718 { "Fast Retransmission", "tcp.analysis.fast_retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
3719 "This frame is a suspected TCP fast retransmission", HFILL }},
3721 { &hf_tcp_analysis_out_of_order,
3722 { "Out Of Order", "tcp.analysis.out_of_order", FT_NONE, BASE_NONE, NULL, 0x0,
3723 "This frame is a suspected Out-Of-Order segment", HFILL }},
3725 { &hf_tcp_analysis_reused_ports,
3726 { "TCP Port numbers reused", "tcp.analysis.reused_ports", FT_NONE, BASE_NONE, NULL, 0x0,
3727 "A new tcp session has started with previously used port numbers", HFILL }},
3729 { &hf_tcp_analysis_lost_packet,
3730 { "Previous Segment Lost", "tcp.analysis.lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
3731 "A segment before this one was lost from the capture", HFILL }},
3733 { &hf_tcp_analysis_ack_lost_packet,
3734 { "ACKed Lost Packet", "tcp.analysis.ack_lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
3735 "This frame ACKs a lost segment", HFILL }},
3737 { &hf_tcp_analysis_window_update,
3738 { "Window update", "tcp.analysis.window_update", FT_NONE, BASE_NONE, NULL, 0x0,
3739 "This frame is a tcp window update", HFILL }},
3741 { &hf_tcp_analysis_window_full,
3742 { "Window full", "tcp.analysis.window_full", FT_NONE, BASE_NONE, NULL, 0x0,
3743 "This segment has caused the allowed window to become 100% full", HFILL }},
3745 { &hf_tcp_analysis_keep_alive,
3746 { "Keep Alive", "tcp.analysis.keep_alive", FT_NONE, BASE_NONE, NULL, 0x0,
3747 "This is a keep-alive segment", HFILL }},
3749 { &hf_tcp_analysis_keep_alive_ack,
3750 { "Keep Alive ACK", "tcp.analysis.keep_alive_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3751 "This is an ACK to a keep-alive segment", HFILL }},
3753 { &hf_tcp_analysis_duplicate_ack,
3754 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3755 "This is a duplicate ACK", HFILL }},
3757 { &hf_tcp_analysis_duplicate_ack_num,
3758 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3759 "This is duplicate ACK number #", HFILL }},
3761 { &hf_tcp_analysis_duplicate_ack_frame,
3762 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3763 "This is a duplicate to the ACK in frame #", HFILL }},
3765 { &hf_tcp_continuation_to,
3766 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3767 "This is a continuation to the PDU in frame #", HFILL }},
3769 { &hf_tcp_analysis_zero_window_probe,
3770 { "Zero Window Probe", "tcp.analysis.zero_window_probe", FT_NONE, BASE_NONE, NULL, 0x0,
3771 "This is a zero-window-probe", HFILL }},
3773 { &hf_tcp_analysis_zero_window_probe_ack,
3774 { "Zero Window Probe Ack", "tcp.analysis.zero_window_probe_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3775 "This is an ACK to a zero-window-probe", HFILL }},
3777 { &hf_tcp_analysis_zero_window,
3778 { "Zero Window", "tcp.analysis.zero_window", FT_NONE, BASE_NONE, NULL, 0x0,
3779 "This is a zero-window", HFILL }},
3782 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
3785 { &hf_tcp_analysis_acks_frame,
3786 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3787 "Which previous segment is this an ACK for", HFILL}},
3789 { &hf_tcp_analysis_bytes_in_flight,
3790 { "Number of bytes in flight", "tcp.analysis.bytes_in_flight", FT_UINT32, BASE_DEC, NULL, 0x0,
3791 "How many bytes are now in flight for this connection", HFILL}},
3793 { &hf_tcp_analysis_ack_rtt,
3794 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3795 "How long time it took to ACK the segment (RTT)", HFILL}},
3797 { &hf_tcp_analysis_rto,
3798 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3799 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL}},
3801 { &hf_tcp_analysis_rto_frame,
3802 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3803 "This is the frame we measure the RTO from", HFILL }},
3805 { &hf_tcp_urgent_pointer,
3806 { "Urgent pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
3809 { &hf_tcp_segment_overlap,
3810 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3811 "Segment overlaps with other segments", HFILL }},
3813 { &hf_tcp_segment_overlap_conflict,
3814 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3815 "Overlapping segments contained conflicting data", HFILL }},
3817 { &hf_tcp_segment_multiple_tails,
3818 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3819 "Several tails were found when reassembling the pdu", HFILL }},
3821 { &hf_tcp_segment_too_long_fragment,
3822 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3823 "Segment contained data past end of the pdu", HFILL }},
3825 { &hf_tcp_segment_error,
3826 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3827 "Reassembling error due to illegal segments", HFILL }},
3830 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3831 "TCP Segment", HFILL }},
3834 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
3835 "TCP Segments", HFILL }},
3837 { &hf_tcp_reassembled_in,
3838 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3839 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
3842 { "TCP Options", "tcp.options", FT_BYTES,
3843 BASE_HEX, NULL, 0x0, "TCP Options", HFILL }},
3845 { &hf_tcp_option_mss,
3846 { "TCP MSS Option", "tcp.options.mss", FT_BOOLEAN,
3847 BASE_NONE, NULL, 0x0, "TCP MSS Option", HFILL }},
3849 { &hf_tcp_option_mss_val,
3850 { "TCP MSS Option Value", "tcp.options.mss_val", FT_UINT16,
3851 BASE_DEC, NULL, 0x0, "TCP MSS Option Value", HFILL}},
3853 { &hf_tcp_option_wscale,
3854 { "TCP Window Scale Option", "tcp.options.wscale",
3856 BASE_NONE, NULL, 0x0, "TCP Window Option", HFILL}},
3858 { &hf_tcp_option_wscale_val,
3859 { "TCP Windows Scale Option Value", "tcp.options.wscale_val",
3860 FT_UINT8, BASE_DEC, NULL, 0x0, "TCP Window Scale Value",
3863 { &hf_tcp_option_sack_perm,
3864 { "TCP Sack Perm Option", "tcp.options.sack_perm",
3866 BASE_NONE, NULL, 0x0, "TCP Sack Perm Option", HFILL}},
3868 { &hf_tcp_option_sack,
3869 { "TCP Sack Option", "tcp.options.sack", FT_BOOLEAN,
3870 BASE_NONE, NULL, 0x0, "TCP Sack Option", HFILL}},
3872 { &hf_tcp_option_sack_sle,
3873 {"TCP Sack Left Edge", "tcp.options.sack_le", FT_UINT32,
3874 BASE_DEC, NULL, 0x0, "TCP Sack Left Edge", HFILL}},
3876 { &hf_tcp_option_sack_sre,
3877 {"TCP Sack Right Edge", "tcp.options.sack_re", FT_UINT32,
3878 BASE_DEC, NULL, 0x0, "TCP Sack Right Edge", HFILL}},
3880 { &hf_tcp_option_echo,
3881 { "TCP Echo Option", "tcp.options.echo", FT_BOOLEAN,
3882 BASE_NONE, NULL, 0x0, "TCP Sack Echo", HFILL}},
3884 { &hf_tcp_option_echo_reply,
3885 { "TCP Echo Reply Option", "tcp.options.echo_reply",
3887 BASE_NONE, NULL, 0x0, "TCP Echo Reply Option", HFILL}},
3889 { &hf_tcp_option_time_stamp,
3890 { "TCP Time Stamp Option", "tcp.options.time_stamp",
3892 BASE_NONE, NULL, 0x0, "TCP Time Stamp Option", HFILL}},
3894 { &hf_tcp_option_cc,
3895 { "TCP CC Option", "tcp.options.cc", FT_BOOLEAN, BASE_NONE,
3896 NULL, 0x0, "TCP CC Option", HFILL}},
3898 { &hf_tcp_option_ccnew,
3899 { "TCP CC New Option", "tcp.options.ccnew", FT_BOOLEAN,
3900 BASE_NONE, NULL, 0x0, "TCP CC New Option", HFILL}},
3902 { &hf_tcp_option_ccecho,
3903 { "TCP CC Echo Option", "tcp.options.ccecho", FT_BOOLEAN,
3904 BASE_NONE, NULL, 0x0, "TCP CC Echo Option", HFILL}},
3906 { &hf_tcp_option_md5,
3907 { "TCP MD5 Option", "tcp.options.md5", FT_BOOLEAN, BASE_NONE,
3908 NULL, 0x0, "TCP MD5 Option", HFILL}},
3910 { &hf_tcp_option_qs,
3911 { "TCP QS Option", "tcp.options.qs", FT_BOOLEAN, BASE_NONE,
3912 NULL, 0x0, "TCP QS Option", HFILL}},
3914 { &hf_tcp_option_scps,
3915 { "TCP SCPS Capabilities Option", "tcp.options.scps",
3916 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3917 "TCP SCPS Capabilities Option", HFILL}},
3919 { &hf_tcp_option_scps_vector,
3920 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
3921 FT_UINT8, BASE_DEC, NULL, 0x0,
3922 "TCP SCPS Capabilities Vector", HFILL}},
3924 { &hf_tcp_option_scps_binding,
3925 { "TCP SCPS Extended Binding Spacce",
3926 "tcp.options.scps.binding",
3927 FT_UINT8, BASE_DEC, NULL, 0x0,
3928 "TCP SCPS Extended Binding Space", HFILL}},
3930 { &hf_tcp_option_snack,
3931 { "TCP Selective Negative Acknowledgement Option",
3932 "tcp.options.snack",
3933 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3934 "TCP Selective Negative Acknowledgement Option", HFILL}},
3936 { &hf_tcp_option_snack_offset,
3937 { "TCP SNACK Offset", "tcp.options.snack.offset",
3938 FT_UINT16, BASE_DEC, NULL, 0x0,
3939 "TCP SNACK Offset", HFILL}},
3941 { &hf_tcp_option_snack_size,
3942 { "TCP SNACK Size", "tcp.options.snack.size",
3943 FT_UINT16, BASE_DEC, NULL, 0x0,
3944 "TCP SNACK Size", HFILL}},
3946 { &hf_tcp_option_snack_le,
3947 { "TCP SNACK Left Edge", "tcp.options.snack.le",
3948 FT_UINT16, BASE_DEC, NULL, 0x0,
3949 "TCP SNACK Left Edge", HFILL}},
3951 { &hf_tcp_option_snack_re,
3952 { "TCP SNACK Right Edge", "tcp.options.snack.re",
3953 FT_UINT16, BASE_DEC, NULL, 0x0,
3954 "TCP SNACK Right Edge", HFILL}},
3956 { &hf_tcp_scpsoption_flags_bets,
3957 { "Partial Reliability Capable (BETS)",
3958 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,
3959 TFS(&flags_set_truth), 0x80, "", HFILL }},
3961 { &hf_tcp_scpsoption_flags_snack1,
3962 { "Short Form SNACK Capable (SNACK1)",
3963 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,
3964 TFS(&flags_set_truth), 0x40, "", HFILL }},
3966 { &hf_tcp_scpsoption_flags_snack2,
3967 { "Long Form SNACK Capable (SNACK2)",
3968 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,
3969 TFS(&flags_set_truth), 0x20, "", HFILL }},
3971 { &hf_tcp_scpsoption_flags_compress,
3972 { "Lossless Header Compression (COMP)",
3973 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,
3974 TFS(&flags_set_truth), 0x10, "", HFILL }},
3976 { &hf_tcp_scpsoption_flags_nlts,
3977 { "Network Layer Timestamp (NLTS)",
3978 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,
3979 TFS(&flags_set_truth), 0x8, "", HFILL }},
3981 { &hf_tcp_scpsoption_flags_resv1,
3983 "tcp.options.scpsflags.reserved1", FT_BOOLEAN, 8,
3984 TFS(&flags_set_truth), 0x4, "", HFILL }},
3986 { &hf_tcp_scpsoption_flags_resv2,
3988 "tcp.options.scpsflags.reserved2", FT_BOOLEAN, 8,
3989 TFS(&flags_set_truth), 0x2, "", HFILL }},
3991 { &hf_tcp_scpsoption_flags_resv3,
3993 "tcp.options.scpsflags.reserved3", FT_BOOLEAN, 8,
3994 TFS(&flags_set_truth), 0x1, "", HFILL }},
3997 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3998 "How long time has passed until the last frame of this PDU", HFILL}},
4001 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL, 0x0,
4002 "The size of this PDU", HFILL}},
4004 { &hf_tcp_pdu_last_frame,
4005 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4006 "This is the last frame of the PDU starting in this segment", HFILL }},
4008 { &hf_tcp_ts_relative,
4009 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4010 "Time relative to first frame in this TCP stream", HFILL}},
4013 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4014 "Time delta from previous frame in this TCP stream", HFILL}},
4017 static gint *ett[] = {
4021 &ett_tcp_option_sack,
4022 &ett_tcp_option_scps,
4023 &ett_tcp_option_scps_extended,
4024 &ett_tcp_analysis_faults,
4026 &ett_tcp_timestamps,
4031 module_t *tcp_module;
4033 proto_tcp = proto_register_protocol("Transmission Control Protocol",
4035 proto_register_field_array(proto_tcp, hf, array_length(hf));
4036 proto_register_subtree_array(ett, array_length(ett));
4038 /* subdissector code */
4039 subdissector_table = register_dissector_table("tcp.port",
4040 "TCP port", FT_UINT16, BASE_DEC);
4041 register_heur_dissector_list("tcp", &heur_subdissector_list);
4043 /* Register configuration preferences */
4044 tcp_module = prefs_register_protocol(proto_tcp, NULL);
4045 prefs_register_bool_preference(tcp_module, "summary_in_tree",
4046 "Show TCP summary in protocol tree",
4047 "Whether the TCP summary line should be shown in the protocol tree",
4048 &tcp_summary_in_tree);
4049 prefs_register_bool_preference(tcp_module, "check_checksum",
4050 "Validate the TCP checksum if possible",
4051 "Whether to validate the TCP checksum",
4052 &tcp_check_checksum);
4053 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
4054 "Allow subdissector to reassemble TCP streams",
4055 "Whether subdissector can request TCP streams to be reassembled",
4057 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
4058 "Analyze TCP sequence numbers",
4059 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
4061 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
4062 "Relative sequence numbers and window scaling",
4063 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
4064 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
4065 "This option will also try to track and adjust the window field according to any TCP window scaling options seen.",
4067 prefs_register_bool_preference(tcp_module, "track_bytes_in_flight",
4068 "Track number of bytes in flight",
4069 "Make the TCP dissector track the number on un-ACKed bytes of data are in flight per packet. "
4070 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
4071 "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",
4072 &tcp_track_bytes_in_flight);
4073 prefs_register_bool_preference(tcp_module, "calculate_timestamps",
4074 "Calculate conversation timestamps",
4075 "Calculate timestamps relative to the first frame and the previous frame in the tcp conversation",
4077 prefs_register_bool_preference(tcp_module, "try_heuristic_first",
4078 "Try heuristic sub-dissectors first",
4079 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
4080 &try_heuristic_first);
4082 register_init_routine(tcp_fragment_init);
4086 proto_reg_handoff_tcp(void)
4088 dissector_handle_t tcp_handle;
4090 tcp_handle = create_dissector_handle(dissect_tcp, proto_tcp);
4091 dissector_add("ip.proto", IP_PROTO_TCP, tcp_handle);
4092 data_handle = find_dissector("data");
4093 tcp_tap = register_tap("tcp");