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-ip.h"
43 #include "packet-frame.h"
44 #include <epan/conversation.h>
45 #include <epan/strutil.h>
46 #include <epan/reassemble.h>
48 #include <epan/slab.h>
49 #include <epan/expert.h>
51 static int tcp_tap = -1;
53 /* Place TCP summary in proto tree */
54 static gboolean tcp_summary_in_tree = TRUE;
57 * Flag to control whether to check the TCP checksum.
59 * In at least some Solaris network traces, there are packets with bad
60 * TCP checksums, but the traffic appears to indicate that the packets
61 * *were* received; the packets were probably sent by the host on which
62 * the capture was being done, on a network interface to which
63 * checksumming was offloaded, so that DLPI supplied an un-checksummed
64 * packet to the capture program but a checksummed packet got put onto
67 static gboolean tcp_check_checksum = FALSE;
69 extern FILE* data_out_file;
71 static int proto_tcp = -1;
72 static int hf_tcp_srcport = -1;
73 static int hf_tcp_dstport = -1;
74 static int hf_tcp_port = -1;
75 static int hf_tcp_seq = -1;
76 static int hf_tcp_nxtseq = -1;
77 static int hf_tcp_ack = -1;
78 static int hf_tcp_hdr_len = -1;
79 static int hf_tcp_flags = -1;
80 static int hf_tcp_flags_cwr = -1;
81 static int hf_tcp_flags_ecn = -1;
82 static int hf_tcp_flags_urg = -1;
83 static int hf_tcp_flags_ack = -1;
84 static int hf_tcp_flags_push = -1;
85 static int hf_tcp_flags_reset = -1;
86 static int hf_tcp_flags_syn = -1;
87 static int hf_tcp_flags_fin = -1;
88 static int hf_tcp_window_size = -1;
89 static int hf_tcp_checksum = -1;
90 static int hf_tcp_checksum_bad = -1;
91 static int hf_tcp_checksum_good = -1;
92 static int hf_tcp_len = -1;
93 static int hf_tcp_urgent_pointer = -1;
94 static int hf_tcp_analysis_flags = -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_calculate_ts = FALSE;
208 /* SLAB allocator for tcp_unacked structures
210 SLAB_ITEM_TYPE_DEFINE(tcp_unacked_t)
211 static SLAB_FREE_LIST_DEFINE(tcp_unacked_t)
212 #define TCP_UNACKED_NEW(fi) \
213 SLAB_ALLOC(fi, tcp_unacked_t)
214 #define TCP_UNACKED_FREE(fi) \
215 SLAB_FREE(fi, tcp_unacked_t)
218 #define TCP_A_RETRANSMISSION 0x0001
219 #define TCP_A_LOST_PACKET 0x0002
220 #define TCP_A_ACK_LOST_PACKET 0x0004
221 #define TCP_A_KEEP_ALIVE 0x0008
222 #define TCP_A_DUPLICATE_ACK 0x0010
223 #define TCP_A_ZERO_WINDOW 0x0020
224 #define TCP_A_ZERO_WINDOW_PROBE 0x0040
225 #define TCP_A_ZERO_WINDOW_PROBE_ACK 0x0080
226 #define TCP_A_KEEP_ALIVE_ACK 0x0100
227 #define TCP_A_OUT_OF_ORDER 0x0200
228 #define TCP_A_FAST_RETRANSMISSION 0x0400
229 #define TCP_A_WINDOW_UPDATE 0x0800
230 #define TCP_A_WINDOW_FULL 0x1000
231 #define TCP_A_REUSED_PORTS 0x2000
235 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
236 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
237 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
238 struct tcp_analysis *tcpd);
241 struct tcp_analysis *
242 init_tcp_conversation(packet_info *pinfo)
244 struct tcp_analysis *tcpd=NULL;
246 /* Initialize the tcp protocol datat structure to add to the tcp conversation */
247 tcpd=se_alloc(sizeof(struct tcp_analysis));
248 tcpd->flow1.segments=NULL;
249 tcpd->flow1.base_seq=0;
250 tcpd->flow1.lastack=0;
251 tcpd->flow1.lastacktime.secs=0;
252 tcpd->flow1.lastacktime.nsecs=0;
253 tcpd->flow1.lastnondupack=0;
254 tcpd->flow1.nextseq=0;
255 tcpd->flow1.nextseqtime.secs=0;
256 tcpd->flow1.nextseqtime.nsecs=0;
257 tcpd->flow1.nextseqframe=0;
258 tcpd->flow1.window=0;
259 tcpd->flow1.win_scale=-1;
260 tcpd->flow1.scps_capable=0;
261 tcpd->flow1.maxsizeacked=0;
263 tcpd->flow1.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
264 tcpd->flow2.segments=NULL;
265 tcpd->flow2.base_seq=0;
266 tcpd->flow2.lastack=0;
267 tcpd->flow2.lastacktime.secs=0;
268 tcpd->flow2.lastacktime.nsecs=0;
269 tcpd->flow2.lastnondupack=0;
270 tcpd->flow2.nextseq=0;
271 tcpd->flow2.nextseqtime.secs=0;
272 tcpd->flow2.nextseqtime.nsecs=0;
273 tcpd->flow2.nextseqframe=0;
274 tcpd->flow2.window=0;
275 tcpd->flow2.win_scale=-1;
276 tcpd->flow2.scps_capable=0;
277 tcpd->flow2.maxsizeacked=0;
279 tcpd->flow2.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
280 tcpd->acked_table=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_analyze_acked_table");
281 tcpd->ts_first.secs=pinfo->fd->abs_ts.secs;
282 tcpd->ts_first.nsecs=pinfo->fd->abs_ts.nsecs;
283 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
284 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
289 struct tcp_analysis *
290 new_tcp_conversation(packet_info *pinfo)
293 conversation_t *conv=NULL;
294 struct tcp_analysis *tcpd=NULL;
296 /* Create a new conversation. */
297 conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
298 tcpd = init_tcp_conversation(pinfo);
299 conversation_add_proto_data(conv, proto_tcp, tcpd);
301 /* check direction and get ua lists */
302 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
303 /* if the addresses are equal, match the ports instead */
305 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
308 tcpd->fwd=&(tcpd->flow1);
309 tcpd->rev=&(tcpd->flow2);
311 tcpd->fwd=&(tcpd->flow2);
312 tcpd->rev=&(tcpd->flow1);
319 struct tcp_analysis *
320 get_tcp_conversation_data(packet_info *pinfo)
323 conversation_t *conv=NULL;
324 struct tcp_analysis *tcpd=NULL;
326 /* Have we seen this conversation before? */
327 if( (conv=find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0)) == NULL){
328 /* No this is a new conversation. */
329 tcpd=new_tcp_conversation(pinfo);
331 /* Get the data for this conversation */
332 tcpd=conversation_get_proto_data(conv, proto_tcp);
334 /* If the conversation matched a conversation with template
335 * options, tcpd will not have been initialized. So, initialize
336 * a new tcpd structure for the conversation.
339 tcpd = init_tcp_conversation(pinfo);
340 conversation_add_proto_data(conv, proto_tcp, tcpd);
348 /* check direction and get ua lists */
349 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
350 /* if the addresses are equal, match the ports instead */
352 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
355 tcpd->fwd=&(tcpd->flow1);
356 tcpd->rev=&(tcpd->flow2);
358 tcpd->fwd=&(tcpd->flow2);
359 tcpd->rev=&(tcpd->flow1);
366 /* Calculate the timestamps relative to this conversation */
368 tcp_calculate_timestamps(packet_info *pinfo, struct tcp_analysis *tcpd,
369 struct tcp_per_packet_data_t *tcppd)
372 tcppd = se_alloc(sizeof(struct tcp_per_packet_data_t));
373 p_add_proto_data(pinfo->fd, proto_tcp, tcppd);
379 nstime_delta(&tcppd->ts_del, &pinfo->fd->abs_ts, &tcpd->ts_prev);
381 tcpd->ts_prev.secs=pinfo->fd->abs_ts.secs;
382 tcpd->ts_prev.nsecs=pinfo->fd->abs_ts.nsecs;
385 /* Add a subtree with the timestamps relative to this conversation */
387 tcp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
396 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "Timestamps");
397 PROTO_ITEM_SET_GENERATED(item);
398 tree=proto_item_add_subtree(item, ett_tcp_timestamps);
400 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
401 item = proto_tree_add_time(tree, hf_tcp_ts_relative, tvb, 0, 0, &ts);
402 PROTO_ITEM_SET_GENERATED(item);
405 tcppd = p_get_proto_data(pinfo->fd, proto_tcp);
408 item = proto_tree_add_time(tree, hf_tcp_ts_delta, tvb, 0, 0,
410 PROTO_ITEM_SET_GENERATED(item);
415 print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, struct tcp_multisegment_pdu *msp)
419 if (check_col(pinfo->cinfo, COL_INFO)){
420 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", msp->first_frame);
422 item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
423 tvb, 0, 0, msp->first_frame);
424 PROTO_ITEM_SET_GENERATED(item);
427 /* if we know that a PDU starts inside this segment, return the adjusted
428 offset to where that PDU starts or just return offset back
429 and let TCP try to find out what it can about this segment
432 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)
434 struct tcp_multisegment_pdu *msp=NULL;
436 if(!pinfo->fd->flags.visited){
437 msp=se_tree_lookup32_le(multisegment_pdus, seq-1);
439 /* If this is a continuation of a PDU started in a
440 * previous segment we need to update the last_frame
443 if(seq>msp->seq && seq<msp->nxtpdu){
444 msp->last_frame=pinfo->fd->num;
445 msp->last_frame_time=pinfo->fd->abs_ts;
446 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
449 /* If this segment is completely within a previous PDU
450 * then we just skip this packet
452 if(seq>msp->seq && nxtseq<=msp->nxtpdu){
455 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu){
456 offset+=msp->nxtpdu-seq;
462 /* First we try to find the start and transfer time for a PDU.
463 * We only print this for the very first segment of a PDU
464 * and only for PDUs spanning multiple segments.
465 * Se we look for if there was any multisegment PDU started
466 * just BEFORE the end of this segment. I.e. either inside this
467 * segment or in a previous segment.
468 * Since this might also match PDUs that are completely within
469 * this segment we also verify that the found PDU does span
470 * beyond the end of this segment.
472 msp=se_tree_lookup32_le(multisegment_pdus, nxtseq-1);
474 if( (pinfo->fd->num==msp->first_frame)
479 item=proto_tree_add_uint(tcp_tree, hf_tcp_pdu_last_frame, tvb, 0, 0, msp->last_frame);
480 PROTO_ITEM_SET_GENERATED(item);
482 nstime_delta(&ns, &msp->last_frame_time, &pinfo->fd->abs_ts);
483 item = proto_tree_add_time(tcp_tree, hf_tcp_pdu_time,
485 PROTO_ITEM_SET_GENERATED(item);
489 /* Second we check if this segment is part of a PDU started
490 * prior to the segment (seq-1)
492 msp=se_tree_lookup32_le(multisegment_pdus, seq-1);
494 /* If this segment is completely within a previous PDU
495 * then we just skip this packet
497 if(seq>msp->seq && nxtseq<=msp->nxtpdu){
498 print_pdu_tracking_data(pinfo, tvb, tcp_tree, msp);
502 if(seq<msp->nxtpdu && nxtseq>msp->nxtpdu){
503 offset+=msp->nxtpdu-seq;
512 /* if we saw a PDU that extended beyond the end of the segment,
513 use this function to remember where the next pdu starts
515 struct tcp_multisegment_pdu *
516 pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu, emem_tree_t *multisegment_pdus)
518 struct tcp_multisegment_pdu *msp;
520 msp=se_alloc(sizeof(struct tcp_multisegment_pdu));
523 msp->first_frame=pinfo->fd->num;
524 msp->last_frame=pinfo->fd->num;
525 msp->last_frame_time=pinfo->fd->abs_ts;
527 se_tree_insert32(multisegment_pdus, seq, (void *)msp);
531 /* This is called for SYN+ACK packets and the purpose is to verify that we
532 * have seen window scaling in both directions.
533 * If we cant find window scaling being set in both directions
534 * that means it was present in the SYN but not in the SYN+ACK
535 * (or the SYN was missing) and then we disable the window scaling
536 * for this tcp session.
539 verify_tcp_window_scaling(struct tcp_analysis *tcpd)
541 if( tcpd && ((tcpd->flow1.win_scale==-1) || (tcpd->flow2.win_scale==-1)) ){
542 tcpd->flow1.win_scale=-1;
543 tcpd->flow2.win_scale=-1;
547 /* if we saw a window scaling option, store it for future reference
550 pdu_store_window_scale_option(guint8 ws, struct tcp_analysis *tcpd)
553 tcpd->fwd->win_scale=ws;
557 tcp_get_relative_seq_ack(guint32 *seq, guint32 *ack, guint32 *win, struct tcp_analysis *tcpd)
559 if (tcpd && tcp_relative_seq) {
560 (*seq) -= tcpd->fwd->base_seq;
561 (*ack) -= tcpd->rev->base_seq;
562 if(tcpd->fwd->win_scale!=-1){
563 (*win)<<=tcpd->fwd->win_scale;
569 /* when this function returns, it will (if createflag) populate the ta pointer.
572 tcp_analyze_get_acked_struct(guint32 frame, gboolean createflag, struct tcp_analysis *tcpd)
577 tcpd->ta=se_tree_lookup32(tcpd->acked_table, frame);
578 if((!tcpd->ta) && createflag){
579 tcpd->ta=se_alloc(sizeof(struct tcp_acked));
580 tcpd->ta->frame_acked=0;
582 tcpd->ta->ts.nsecs=0;
584 tcpd->ta->dupack_num=0;
585 tcpd->ta->dupack_frame=0;
586 se_tree_insert32(tcpd->acked_table, frame, (void *)tcpd->ta);
591 /* fwd contains a list of all segments processed but not yet ACKed in the
592 * same direction as the current segment.
593 * rev contains a list of all segments received but not yet ACKed in the
594 * opposite direction to the current segment.
596 * New segments are always added to the head of the fwd/rev lists.
600 tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint8 flags, guint32 window, struct tcp_analysis *tcpd)
602 tcp_unacked_t *ual=NULL;
606 printf("analyze_sequence numbers frame:%u direction:%s\n",pinfo->fd->num,direction>=0?"FWD":"REW");
607 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);
608 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);
615 /* if this is the first segment for this list we need to store the
618 * Start relative seq and ack numbers at 1 if this
619 * is not a SYN packet. This makes the relative
620 * seq/ack numbers to be displayed correctly in the
621 * event that the SYN or SYN/ACK packet is not seen
622 * (this solves bug 1542)
624 if(tcpd->fwd->base_seq==0){
625 tcpd->fwd->base_seq = (flags & TH_SYN) ? seq : seq-1;
628 /* Only store reverse sequence if this isn't the SYN
629 * There's no guarantee that the ACK field of a SYN
630 * contains zeros; get the ISN from the first segment
631 * with the ACK bit set instead (usually the SYN/ACK).
633 if( (tcpd->rev->base_seq==0) && (flags & TH_ACK) ){
634 tcpd->rev->base_seq = (flags & TH_SYN) ? ack : ack-1;
639 * it is a zero window probe if
640 * the sequnece number is the next expected one
641 * the window in the other direction is 0
642 * the segment is exactly 1 byte
646 && seq==tcpd->fwd->nextseq
647 && tcpd->rev->window==0 ){
649 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
651 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
657 * a zero window packet has window == 0 but none of the SYN/FIN/RST set
661 && (flags&(TH_RST|TH_FIN|TH_SYN))==0 ){
663 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
665 tcpd->ta->flags|=TCP_A_ZERO_WINDOW;
670 * If this segment is beyond the last seen nextseq we must
671 * have missed some previous segment
673 * We only check for this if we have actually seen segments prior to this
675 * RST packets are not checked for this.
677 if( tcpd->fwd->nextseq
678 && GT_SEQ(seq, tcpd->fwd->nextseq)
679 && (flags&(TH_RST))==0 ){
681 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
683 tcpd->ta->flags|=TCP_A_LOST_PACKET;
688 * a keepalive contains 0 or 1 bytes of data and starts one byte prior
689 * to what should be the next sequence number.
690 * SYN/FIN/RST segments are never keepalives
693 if( (seglen==0||seglen==1)
694 && seq==(tcpd->fwd->nextseq-1)
695 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
697 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
699 tcpd->ta->flags|=TCP_A_KEEP_ALIVE;
703 * A window update is a 0 byte segment with the same SEQ/ACK numbers as
704 * the previous seen segment and with a new window value
708 && window!=tcpd->fwd->window
709 && seq==tcpd->fwd->nextseq
710 && ack==tcpd->fwd->lastack
711 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
713 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
715 tcpd->ta->flags|=TCP_A_WINDOW_UPDATE;
720 * If we know the window scaling
721 * and if this segment contains data ang goes all the way to the
722 * edge of the advertized window
723 * then we mark it as WINDOW FULL
724 * SYN/RST/FIN packets are never WINDOW FULL
728 && tcpd->fwd->win_scale!=-1
729 && tcpd->rev->win_scale!=-1
730 && (seq+seglen)==(tcpd->rev->lastack+(tcpd->rev->window<<tcpd->rev->win_scale))
731 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
733 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
735 tcpd->ta->flags|=TCP_A_WINDOW_FULL;
740 * It is a keepalive ack if it repeats the previous ACK and if
741 * the last segment in the reverse direction was a keepalive
746 && window==tcpd->fwd->window
747 && seq==tcpd->fwd->nextseq
748 && ack==tcpd->fwd->lastack
749 && (tcpd->rev->lastsegmentflags&TCP_A_KEEP_ALIVE)
750 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
752 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
754 tcpd->ta->flags|=TCP_A_KEEP_ALIVE_ACK;
759 /* ZERO WINDOW PROBE ACK
760 * It is a zerowindowprobe ack if it repeats the previous ACK and if
761 * the last segment in the reverse direction was a zerowindowprobe
762 * It also repeats the previous zero window indication
767 && window==tcpd->fwd->window
768 && seq==tcpd->fwd->nextseq
769 && ack==tcpd->fwd->lastack
770 && (tcpd->rev->lastsegmentflags&TCP_A_ZERO_WINDOW_PROBE)
771 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
773 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
775 tcpd->ta->flags|=TCP_A_ZERO_WINDOW_PROBE_ACK;
781 * It is a duplicate ack if window/seq/ack is the same as the previous
782 * segment and if the segment length is 0
786 && window==tcpd->fwd->window
787 && seq==tcpd->fwd->nextseq
788 && ack==tcpd->fwd->lastack
789 && (flags&(TH_SYN|TH_FIN|TH_RST))==0 ){
790 tcpd->fwd->dupacknum++;
792 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
794 tcpd->ta->flags|=TCP_A_DUPLICATE_ACK;
795 tcpd->ta->dupack_num=tcpd->fwd->dupacknum;
796 tcpd->ta->dupack_frame=tcpd->fwd->lastnondupack;
801 /* If this was NOT a dupack we must reset the dupack counters */
802 if( (!tcpd->ta) || !(tcpd->ta->flags&TCP_A_DUPLICATE_ACK) ){
803 tcpd->fwd->lastnondupack=pinfo->fd->num;
804 tcpd->fwd->dupacknum=0;
809 * If this segment acks beyond the nextseqnum in the other direction
810 * then that means we have missed packets going in the
813 * We only check this if we have actually seen some seq numbers
814 * in the other direction.
816 if( tcpd->rev->nextseq
817 && GT_SEQ(ack, tcpd->rev->nextseq )
818 && (flags&(TH_ACK))!=0 ){
821 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
823 tcpd->ta->flags|=TCP_A_ACK_LOST_PACKET;
824 /* update nextseq in the other direction so we dont get
825 * this indication again.
827 tcpd->rev->nextseq=ack;
831 /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER
832 * If the segments contains data and if it does not advance
833 * sequence number it must be either of these three.
834 * Only test for this if we know what the seq number should be
835 * (tcpd->fwd->nextseq)
837 * Note that a simple KeepAlive is not a retransmission
840 && tcpd->fwd->nextseq
841 && (LT_SEQ(seq, tcpd->fwd->nextseq)) ){
844 if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ){
845 goto finished_checking_retransmission_type;
848 /* If there were >=2 duplicate ACKs in the reverse direction
849 * (there might be duplicate acks missing from the trace)
850 * and if this sequence number matches those ACKs
851 * and if the packet occurs within 20ms of the last
853 * then this is a fast retransmission
855 t=(pinfo->fd->abs_ts.secs-tcpd->rev->lastacktime.secs)*1000000000;
856 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->rev->lastacktime.nsecs;
857 if( tcpd->rev->dupacknum>=2
858 && tcpd->rev->lastack==seq
861 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
863 tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
864 goto finished_checking_retransmission_type;
867 /* If the segment came <3ms since the segment with the highest
868 * seen sequence number, then it is an OUT-OF-ORDER segment.
869 * (3ms is an arbitrary number)
871 t=(pinfo->fd->abs_ts.secs-tcpd->fwd->nextseqtime.secs)*1000000000;
872 t=t+(pinfo->fd->abs_ts.nsecs)-tcpd->fwd->nextseqtime.nsecs;
875 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
877 tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
878 goto finished_checking_retransmission_type;
881 /* Then it has to be a generic retransmission */
883 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
885 tcpd->ta->flags|=TCP_A_RETRANSMISSION;
886 nstime_delta(&tcpd->ta->rto_ts, &pinfo->fd->abs_ts, &tcpd->fwd->nextseqtime);
887 tcpd->ta->rto_frame=tcpd->fwd->nextseqframe;
889 finished_checking_retransmission_type:
892 /* add this new sequence number to the fwd list */
893 TCP_UNACKED_NEW(ual);
894 ual->next=tcpd->fwd->segments;
895 tcpd->fwd->segments=ual;
896 ual->frame=pinfo->fd->num;
898 ual->ts=pinfo->fd->abs_ts;
900 /* next sequence number is seglen bytes away, plus SYN/FIN which counts as one byte */
901 ual->nextseq=seq+seglen;
902 if( flags&(TH_SYN|TH_FIN) ){
906 /* Store the highest number seen so far for nextseq so we can detect
907 * when we receive segments that arrive with a "hole"
908 * If we dont have anything since before, just store what we got.
909 * ZeroWindowProbes are special and dont really advance the nextseq
911 if(GT_SEQ(ual->nextseq, tcpd->fwd->nextseq) || !tcpd->fwd->nextseq) {
912 if( !tcpd->ta || !(tcpd->ta->flags&TCP_A_ZERO_WINDOW_PROBE) ){
913 tcpd->fwd->nextseq=ual->nextseq;
914 tcpd->fwd->nextseqframe=pinfo->fd->num;
915 tcpd->fwd->nextseqtime.secs=pinfo->fd->abs_ts.secs;
916 tcpd->fwd->nextseqtime.nsecs=pinfo->fd->abs_ts.nsecs;
921 /* remember what the ack/window is so we can track window updates and retransmissions */
922 tcpd->fwd->window=window;
923 tcpd->fwd->lastack=ack;
924 tcpd->fwd->lastacktime.secs=pinfo->fd->abs_ts.secs;
925 tcpd->fwd->lastacktime.nsecs=pinfo->fd->abs_ts.nsecs;
928 /* if there were any flags set for this segment we need to remember them
929 * we only remember the flags for the very last segment though.
932 tcpd->fwd->lastsegmentflags=tcpd->ta->flags;
934 tcpd->fwd->lastsegmentflags=0;
938 /* remove all segments this ACKs and we dont need to keep around any more
941 /* first we remove all such segments at the head of the list */
942 while((ual=tcpd->rev->segments)){
943 tcp_unacked_t *tmpual;
944 if(ack==ual->nextseq){
945 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
946 tcpd->ta->frame_acked=ual->frame;
947 nstime_delta(&tcpd->ta->ts, &pinfo->fd->abs_ts, &ual->ts);
949 if(GT_SEQ(ual->nextseq,ack)){
953 /*qqq do the ACKs segment x delta y */
956 tmpual=tcpd->rev->segments->next;
958 if (tcpd->rev->scps_capable) {
959 /* Track largest segment successfully sent for SNACK analysis */
960 if ((ual->nextseq - ual->seq) > tcpd->fwd->maxsizeacked) {
961 tcpd->fwd->maxsizeacked = (ual->nextseq - ual->seq);
965 TCP_UNACKED_FREE(ual);
966 tcpd->rev->segments=tmpual;
968 /* now we remove all such segments that are NOT at the head of the list */
969 ual=tcpd->rev->segments;
970 while(ual && ual->next){
971 tcp_unacked_t *tmpual;
972 if(GT_SEQ(ual->next->nextseq,ack)){
977 /*qqq do the ACKs segment x delta y */
980 tmpual=ual->next->next;
982 if (tcpd->rev->scps_capable) {
983 /* Track largest segment successfully sent for SNACK analysis*/
984 if ((ual->next->nextseq - ual->next->seq) > tcpd->fwd->maxsizeacked){
985 tcpd->fwd->maxsizeacked = (ual->next->nextseq - ual->next->seq);
989 TCP_UNACKED_FREE(ual->next);
997 * Prints results of the sequence number analysis concerning tcp segments
998 * retransmitted or out-of-order
1001 tcp_sequence_number_analysis_print_retransmission(packet_info * pinfo,
1003 proto_tree * flags_tree,
1004 struct tcp_acked *ta
1007 proto_item * flags_item;
1009 /* TCP Rentransmission */
1010 if (ta->flags & TCP_A_RETRANSMISSION) {
1011 flags_item=proto_tree_add_none_format(flags_tree,
1012 hf_tcp_analysis_retransmission,
1014 "This frame is a (suspected) "
1017 PROTO_ITEM_SET_GENERATED(flags_item);
1018 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1019 "Retransmission (suspected)");
1021 if (check_col(pinfo->cinfo, COL_INFO)) {
1022 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
1024 if (ta->rto_ts.secs || ta->rto_ts.nsecs) {
1025 flags_item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto,
1026 tvb, 0, 0, &ta->rto_ts);
1027 PROTO_ITEM_SET_GENERATED(flags_item);
1028 flags_item=proto_tree_add_uint(flags_tree, hf_tcp_analysis_rto_frame,
1029 tvb, 0, 0, ta->rto_frame);
1030 PROTO_ITEM_SET_GENERATED(flags_item);
1033 /* TCP Fast Rentransmission */
1034 if (ta->flags & TCP_A_FAST_RETRANSMISSION) {
1035 flags_item=proto_tree_add_none_format(flags_tree,
1036 hf_tcp_analysis_fast_retransmission,
1038 "This frame is a (suspected) fast"
1041 PROTO_ITEM_SET_GENERATED(flags_item);
1042 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1043 "Fast retransmission (suspected)");
1044 flags_item=proto_tree_add_none_format(flags_tree,
1045 hf_tcp_analysis_retransmission,
1047 "This frame is a (suspected) "
1050 PROTO_ITEM_SET_GENERATED(flags_item);
1051 if (check_col(pinfo->cinfo, COL_INFO)) {
1052 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1053 "[TCP Fast Retransmission] ");
1056 /* TCP Out-Of-Order */
1057 if (ta->flags & TCP_A_OUT_OF_ORDER) {
1058 flags_item=proto_tree_add_none_format(flags_tree,
1059 hf_tcp_analysis_out_of_order,
1061 "This frame is a (suspected) "
1062 "out-of-order segment"
1064 PROTO_ITEM_SET_GENERATED(flags_item);
1065 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1066 "Out-Of-Order segment");
1067 if (check_col(pinfo->cinfo, COL_INFO)) {
1068 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
1073 /* Prints results of the sequence number analysis concerning reused ports */
1075 tcp_sequence_number_analysis_print_reused(packet_info * pinfo,
1077 proto_tree * flags_tree,
1078 struct tcp_acked *ta
1081 proto_item * flags_item;
1083 /* TCP Ports Reused */
1084 if (ta->flags & TCP_A_REUSED_PORTS) {
1085 flags_item=proto_tree_add_none_format(flags_tree,
1086 hf_tcp_analysis_reused_ports,
1088 "A new tcp session is started with the same "
1089 "ports as an earlier session in this trace"
1091 PROTO_ITEM_SET_GENERATED(flags_item);
1092 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1093 "TCP Port numbers reused for new session");
1094 if(check_col(pinfo->cinfo, COL_INFO)){
1095 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1096 "[TCP Port numbers reused] ");
1101 /* Prints results of the sequence number analysis concerning lost tcp segments */
1103 tcp_sequence_number_analysis_print_lost(packet_info * pinfo,
1105 proto_tree * flags_tree,
1106 struct tcp_acked *ta
1109 proto_item * flags_item;
1111 /* TCP Lost Segment */
1112 if (ta->flags & TCP_A_LOST_PACKET) {
1113 flags_item=proto_tree_add_none_format(flags_tree,
1114 hf_tcp_analysis_lost_packet,
1116 "A segment before this frame was "
1119 PROTO_ITEM_SET_GENERATED(flags_item);
1120 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1121 "Previous segment lost (common at capture start)");
1122 if(check_col(pinfo->cinfo, COL_INFO)){
1123 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1124 "[TCP Previous segment lost] ");
1127 /* TCP Ack lost segment */
1128 if (ta->flags & TCP_A_ACK_LOST_PACKET) {
1129 flags_item=proto_tree_add_none_format(flags_tree,
1130 hf_tcp_analysis_ack_lost_packet,
1132 "This frame ACKs a segment we have "
1135 PROTO_ITEM_SET_GENERATED(flags_item);
1136 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1137 "ACKed lost segment (common at capture start)");
1138 if(check_col(pinfo->cinfo, COL_INFO)){
1139 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1140 "[TCP ACKed lost segment] ");
1145 /* Prints results of the sequence number analysis concerning tcp window */
1147 tcp_sequence_number_analysis_print_window(packet_info * pinfo,
1149 proto_tree * flags_tree,
1150 struct tcp_acked *ta
1153 proto_item * flags_item;
1155 /* TCP Window Update */
1156 if (ta->flags & TCP_A_WINDOW_UPDATE) {
1157 flags_item=proto_tree_add_none_format(flags_tree,
1158 hf_tcp_analysis_window_update,
1160 "This is a tcp window update"
1162 PROTO_ITEM_SET_GENERATED(flags_item);
1163 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_CHAT,
1165 if (check_col(pinfo->cinfo, COL_INFO)) {
1166 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] ");
1169 /* TCP Full Window */
1170 if (ta->flags & TCP_A_WINDOW_FULL) {
1171 flags_item=proto_tree_add_none_format(flags_tree,
1172 hf_tcp_analysis_window_full,
1174 "The transmission window is now "
1177 PROTO_ITEM_SET_GENERATED(flags_item);
1178 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1180 if (check_col(pinfo->cinfo, COL_INFO)) {
1181 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] ");
1186 /* Prints results of the sequence number analysis concerning tcp keepalive */
1188 tcp_sequence_number_analysis_print_keepalive(packet_info * pinfo,
1190 proto_tree * flags_tree,
1191 struct tcp_acked *ta
1194 proto_item * flags_item;
1197 if (ta->flags & TCP_A_KEEP_ALIVE){
1198 flags_item=proto_tree_add_none_format(flags_tree,
1199 hf_tcp_analysis_keep_alive,
1201 "This is a TCP keep-alive segment"
1203 PROTO_ITEM_SET_GENERATED(flags_item);
1204 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1206 if (check_col(pinfo->cinfo, COL_INFO)) {
1207 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
1210 /* TCP Ack Keep Alive */
1211 if (ta->flags & TCP_A_KEEP_ALIVE_ACK) {
1212 flags_item=proto_tree_add_none_format(flags_tree,
1213 hf_tcp_analysis_keep_alive_ack,
1215 "This is an ACK to a TCP keep-alive "
1218 PROTO_ITEM_SET_GENERATED(flags_item);
1219 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1221 if (check_col(pinfo->cinfo, COL_INFO)) {
1222 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
1227 /* Prints results of the sequence number analysis concerning tcp duplicate ack */
1229 tcp_sequence_number_analysis_print_duplicate(packet_info * pinfo,
1231 proto_tree * flags_tree,
1232 struct tcp_acked *ta,
1236 proto_item * flags_item;
1238 /* TCP Duplicate ACK */
1239 if (ta->dupack_num) {
1240 if (ta->flags & TCP_A_DUPLICATE_ACK ) {
1241 flags_item=proto_tree_add_none_format(flags_tree,
1242 hf_tcp_analysis_duplicate_ack,
1244 "This is a TCP duplicate ack"
1246 PROTO_ITEM_SET_GENERATED(flags_item);
1247 if (check_col(pinfo->cinfo, COL_INFO)) {
1248 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1249 "[TCP Dup ACK %u#%u] ",
1255 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
1256 tvb, 0, 0, ta->dupack_num);
1257 PROTO_ITEM_SET_GENERATED(flags_item);
1258 flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
1259 tvb, 0, 0, ta->dupack_frame);
1260 PROTO_ITEM_SET_GENERATED(flags_item);
1261 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1262 "Duplicate ACK (#%u)",
1268 /* Prints results of the sequence number analysis concerning tcp zero window */
1270 tcp_sequence_number_analysis_print_zero_window(packet_info * pinfo,
1272 proto_tree * flags_tree,
1273 struct tcp_acked *ta
1276 proto_item * flags_item;
1278 /* TCP Zeor Window Probe */
1279 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE) {
1280 flags_item=proto_tree_add_none_format(flags_tree,
1281 hf_tcp_analysis_zero_window_probe,
1283 "This is a TCP zero-window-probe"
1285 PROTO_ITEM_SET_GENERATED(flags_item);
1286 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1287 "Zero window probe");
1288 if (check_col(pinfo->cinfo, COL_INFO)) {
1289 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
1292 /* TCP Zero Window */
1293 if (ta->flags&TCP_A_ZERO_WINDOW) {
1294 flags_item=proto_tree_add_none_format(flags_tree,
1295 hf_tcp_analysis_zero_window,
1297 "This is a ZeroWindow segment"
1299 PROTO_ITEM_SET_GENERATED(flags_item);
1300 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN,
1302 if (check_col(pinfo->cinfo, COL_INFO)) {
1303 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
1306 /* TCP Zero Window Probe Ack */
1307 if (ta->flags & TCP_A_ZERO_WINDOW_PROBE_ACK) {
1308 flags_item=proto_tree_add_none_format(flags_tree,
1309 hf_tcp_analysis_zero_window_probe_ack,
1311 "This is an ACK to a TCP zero-window-probe"
1313 PROTO_ITEM_SET_GENERATED(flags_item);
1314 expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE,
1315 "Zero window probe ACK");
1316 if (check_col(pinfo->cinfo, COL_INFO)) {
1317 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO,
1318 "[TCP ZeroWindowProbeAck] ");
1325 tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct tcp_analysis *tcpd)
1327 struct tcp_acked *ta = NULL;
1330 proto_tree *flags_tree=NULL;
1336 tcp_analyze_get_acked_struct(pinfo->fd->num, FALSE, tcpd);
1343 item=proto_tree_add_text(parent_tree, tvb, 0, 0, "SEQ/ACK analysis");
1344 PROTO_ITEM_SET_GENERATED(item);
1345 tree=proto_item_add_subtree(item, ett_tcp_analysis);
1347 /* encapsulate all proto_tree_add_xxx in ifs so we only print what
1348 data we actually have */
1349 if(ta->frame_acked){
1350 item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
1351 tvb, 0, 0, ta->frame_acked);
1352 PROTO_ITEM_SET_GENERATED(item);
1354 /* only display RTT if we actually have something we are acking */
1355 if( ta->ts.secs || ta->ts.nsecs ){
1356 item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
1357 tvb, 0, 0, &ta->ts);
1358 PROTO_ITEM_SET_GENERATED(item);
1363 item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, -1, FALSE);
1364 PROTO_ITEM_SET_GENERATED(item);
1365 flags_tree=proto_item_add_subtree(item, ett_tcp_analysis);
1367 /* print results for reused tcp ports */
1368 tcp_sequence_number_analysis_print_reused(pinfo, tvb, flags_tree, ta);
1370 /* print results for retransmission and out-of-order segments */
1371 tcp_sequence_number_analysis_print_retransmission(pinfo, tvb, flags_tree, ta);
1373 /* print results for lost tcp segments */
1374 tcp_sequence_number_analysis_print_lost(pinfo, tvb, flags_tree, ta);
1376 /* print results for tcp window information */
1377 tcp_sequence_number_analysis_print_window(pinfo, tvb, flags_tree, ta);
1379 /* print results for tcp keep alive information */
1380 tcp_sequence_number_analysis_print_keepalive(pinfo, tvb, flags_tree, ta);
1382 /* print results for tcp duplicate acks */
1383 tcp_sequence_number_analysis_print_duplicate(pinfo, tvb, flags_tree, ta, tree);
1385 /* print results for tcp zero window */
1386 tcp_sequence_number_analysis_print_zero_window(pinfo, tvb, flags_tree, ta);
1392 /* **************************************************************************
1393 * End of tcp sequence number analysis
1394 * **************************************************************************/
1397 /* Minimum TCP header length. */
1398 #define TCPH_MIN_LEN 20
1404 #define TCPOPT_NOP 1 /* Padding */
1405 #define TCPOPT_EOL 0 /* End of options */
1406 #define TCPOPT_MSS 2 /* Segment size negotiating */
1407 #define TCPOPT_WINDOW 3 /* Window scaling */
1408 #define TCPOPT_SACK_PERM 4 /* SACK Permitted */
1409 #define TCPOPT_SACK 5 /* SACK Block */
1410 #define TCPOPT_ECHO 6
1411 #define TCPOPT_ECHOREPLY 7
1412 #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
1413 #define TCPOPT_CC 11
1414 #define TCPOPT_CCNEW 12
1415 #define TCPOPT_CCECHO 13
1416 #define TCPOPT_MD5 19 /* RFC2385 */
1417 #define TCPOPT_SCPS 20 /* SCPS Capabilties */
1418 #define TCPOPT_SNACK 21 /* SCPS SNACK */
1419 #define TCPOPT_QS 27 /* RFC4782 */
1422 * TCP option lengths
1425 #define TCPOLEN_MSS 4
1426 #define TCPOLEN_WINDOW 3
1427 #define TCPOLEN_SACK_PERM 2
1428 #define TCPOLEN_SACK_MIN 2
1429 #define TCPOLEN_ECHO 6
1430 #define TCPOLEN_ECHOREPLY 6
1431 #define TCPOLEN_TIMESTAMP 10
1432 #define TCPOLEN_CC 6
1433 #define TCPOLEN_CCNEW 6
1434 #define TCPOLEN_CCECHO 6
1435 #define TCPOLEN_MD5 18
1436 #define TCPOLEN_SCPS 4
1437 #define TCPOLEN_SNACK 6
1438 #define TCPOLEN_QS 8
1442 /* Desegmentation of TCP streams */
1443 /* table to hold defragmented TCP streams */
1444 static GHashTable *tcp_fragment_table = NULL;
1446 tcp_fragment_init(void)
1448 fragment_table_init(&tcp_fragment_table);
1451 /* functions to trace tcp segments */
1452 /* Enable desegmenting of TCP streams */
1453 static gboolean tcp_desegment = TRUE;
1456 desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
1457 guint32 seq, guint32 nxtseq,
1458 guint32 sport, guint32 dport,
1459 proto_tree *tree, proto_tree *tcp_tree,
1460 struct tcp_analysis *tcpd)
1462 struct tcpinfo *tcpinfo = pinfo->private_data;
1463 fragment_data *ipfd_head;
1464 int last_fragment_len;
1465 gboolean must_desegment;
1466 gboolean called_dissector;
1467 int another_pdu_follows;
1472 proto_item *frag_tree_item;
1473 proto_item *tcp_tree_item;
1474 struct tcp_multisegment_pdu *msp;
1478 last_fragment_len=0;
1479 must_desegment = FALSE;
1480 called_dissector = FALSE;
1481 another_pdu_follows = 0;
1485 * Initialize these to assume no desegmentation.
1486 * If that's not the case, these will be set appropriately
1487 * by the subdissector.
1489 pinfo->desegment_offset = 0;
1490 pinfo->desegment_len = 0;
1493 * Initialize this to assume that this segment will just be
1494 * added to the middle of a desegmented chunk of data, so
1495 * that we should show it all as data.
1496 * If that's not the case, it will be set appropriately.
1498 deseg_offset = offset;
1500 /* find the most previous PDU starting before this sequence number */
1502 msp = se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, seq-1);
1504 if(msp && msp->seq<=seq && msp->nxtpdu>seq){
1507 if(!pinfo->fd->flags.visited){
1508 msp->last_frame=pinfo->fd->num;
1509 msp->last_frame_time=pinfo->fd->abs_ts;
1512 /* OK, this PDU was found, which means the segment continues
1513 a higher-level PDU and that we must desegment it.
1515 if(msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT){
1516 /* The dissector asked for the entire segment */
1517 len=tvb_length_remaining(tvb, offset);
1519 len=MIN(nxtseq, msp->nxtpdu) - seq;
1521 last_fragment_len = len;
1523 ipfd_head = fragment_add(tvb, offset, pinfo, msp->first_frame,
1527 (LT_SEQ (nxtseq,msp->nxtpdu)) );
1529 if(msp->flags&MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT){
1530 msp->flags&=(~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
1532 /* If we consumed the entire segment there is no
1533 * other pdu starting anywhere inside this segment.
1534 * So update nxtpdu to point at least to the start
1535 * of the next segment.
1536 * (If the subdissector asks for even more data we
1537 * will advance nxtpdu even furhter later down in
1543 if( (msp->nxtpdu<nxtseq)
1544 && (msp->nxtpdu>=seq)
1546 another_pdu_follows=msp->nxtpdu-seq;
1549 /* This segment was not found in our table, so it doesn't
1550 contain a continuation of a higher-level PDU.
1551 Call the normal subdissector.
1553 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
1554 sport, dport, 0, 0, FALSE, tcpd);
1555 called_dissector = TRUE;
1557 /* Did the subdissector ask us to desegment some more data
1558 before it could handle the packet?
1559 If so we have to create some structures in our table but
1560 this is something we only do the first time we see this
1563 if(pinfo->desegment_len) {
1564 if (!pinfo->fd->flags.visited)
1565 must_desegment = TRUE;
1568 * Set "deseg_offset" to the offset in "tvb"
1569 * of the first byte of data that the
1570 * subdissector didn't process.
1572 deseg_offset = offset + pinfo->desegment_offset;
1575 /* Either no desegmentation is necessary, or this is
1576 segment contains the beginning but not the end of
1577 a higher-level PDU and thus isn't completely
1584 /* is it completely desegmented? */
1587 * Yes, we think it is.
1588 * We only call subdissector for the last segment.
1589 * Note that the last segment may include more than what
1592 if(ipfd_head->reassembled_in==pinfo->fd->num){
1594 * OK, this is the last segment.
1595 * Let's call the subdissector with the desegmented
1601 /* create a new TVB structure for desegmented data */
1602 next_tvb = tvb_new_real_data(ipfd_head->data,
1603 ipfd_head->datalen, ipfd_head->datalen);
1605 /* add this tvb as a child to the original one */
1606 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1608 /* add desegmented data to the data source list */
1609 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
1612 * Supply the sequence number of the first of the
1613 * reassembled bytes.
1615 tcpinfo->seq = msp->seq;
1617 /* indicate that this is reassembled data */
1618 tcpinfo->is_reassembled = TRUE;
1620 /* call subdissector */
1621 process_tcp_payload(next_tvb, 0, pinfo, tree,
1622 tcp_tree, sport, dport, 0, 0, FALSE, tcpd);
1623 called_dissector = TRUE;
1626 * OK, did the subdissector think it was completely
1627 * desegmented, or does it think we need even more
1630 old_len=(int)(tvb_reported_length(next_tvb)-last_fragment_len);
1631 if(pinfo->desegment_len &&
1632 pinfo->desegment_offset<=old_len){
1634 * "desegment_len" isn't 0, so it needs more
1635 * data for something - and "desegment_offset"
1636 * is before "old_len", so it needs more data
1637 * to dissect the stuff we thought was
1638 * completely desegmented (as opposed to the
1639 * stuff at the beginning being completely
1640 * desegmented, but the stuff at the end
1641 * being a new higher-level PDU that also
1642 * needs desegmentation).
1644 fragment_set_partial_reassembly(pinfo,msp->first_frame,tcp_fragment_table);
1645 /* Update msp->nxtpdu to point to the new next
1648 if(pinfo->desegment_len==DESEGMENT_ONE_MORE_SEGMENT){
1649 /* We want reassembly of at least one
1650 * more segment so set the nxtpdu
1651 * boundary to one byte into the next
1653 * This means that the next segment
1654 * will complete reassembly even if it
1655 * is only one single byte in length.
1657 msp->nxtpdu=seq+tvb_reported_length_remaining(tvb, offset) + 1;
1658 msp->flags|=MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1660 msp->nxtpdu=seq + last_fragment_len + pinfo->desegment_len;
1662 /* Since we need at least some more data
1663 * there can be no pdu following in the
1664 * tail of this segment.
1666 another_pdu_follows=0;
1667 offset += last_fragment_len;
1668 seq += last_fragment_len;
1669 if (tvb_length_remaining(tvb, offset) > 0)
1673 * Show the stuff in this TCP segment as
1674 * just raw TCP segment data.
1676 nbytes = another_pdu_follows > 0
1677 ? another_pdu_follows
1678 : tvb_reported_length_remaining(tvb, offset);
1679 proto_tree_add_text(tcp_tree, tvb, offset, nbytes,
1680 "TCP segment data (%u byte%s)", nbytes,
1681 plurality(nbytes, "", "s"));
1684 * The subdissector thought it was completely
1685 * desegmented (although the stuff at the
1686 * end may, in turn, require desegmentation),
1687 * so we show a tree with all segments.
1689 show_fragment_tree(ipfd_head, &tcp_segment_items,
1690 tree, pinfo, next_tvb, &frag_tree_item);
1692 * The toplevel fragment subtree is now
1693 * behind all desegmented data; move it
1694 * right behind the TCP tree.
1696 tcp_tree_item = proto_tree_get_parent(tcp_tree);
1697 if(frag_tree_item && tcp_tree_item) {
1698 proto_tree_move_item(tree, tcp_tree_item, frag_tree_item);
1701 /* Did the subdissector ask us to desegment
1702 some more data? This means that the data
1703 at the beginning of this segment completed
1704 a higher-level PDU, but the data at the
1705 end of this segment started a higher-level
1706 PDU but didn't complete it.
1708 If so, we have to create some structures
1709 in our table, but this is something we
1710 only do the first time we see this packet.
1712 if(pinfo->desegment_len) {
1713 if (!pinfo->fd->flags.visited)
1714 must_desegment = TRUE;
1716 /* The stuff we couldn't dissect
1717 must have come from this segment,
1718 so it's all in "tvb".
1720 "pinfo->desegment_offset" is
1721 relative to the beginning of
1722 "next_tvb"; we want an offset
1723 relative to the beginning of "tvb".
1725 First, compute the offset relative
1726 to the *end* of "next_tvb" - i.e.,
1727 the number of bytes before the end
1728 of "next_tvb" at which the
1729 subdissector stopped. That's the
1730 length of "next_tvb" minus the
1731 offset, relative to the beginning
1732 of "next_tvb, at which the
1733 subdissector stopped.
1736 ipfd_head->datalen - pinfo->desegment_offset;
1738 /* "tvb" and "next_tvb" end at the
1739 same byte of data, so the offset
1740 relative to the end of "next_tvb"
1741 of the byte at which we stopped
1742 is also the offset relative to
1743 the end of "tvb" of the byte at
1746 Convert that back into an offset
1747 relative to the beginninng of
1748 "tvb", by taking the length of
1749 "tvb" and subtracting the offset
1750 relative to the end.
1752 deseg_offset=tvb_reported_length(tvb) - deseg_offset;
1758 if (must_desegment) {
1759 /* If the dissector requested "reassemble until FIN"
1760 * just set this flag for the flow and let reassembly
1761 * proceed at normal. We will check/pick up these
1762 * reassembled PDUs later down in dissect_tcp() when checking
1765 if(tcpd && pinfo->desegment_len==DESEGMENT_UNTIL_FIN) {
1766 tcpd->fwd->flags|=TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1769 * The sequence number at which the stuff to be desegmented
1770 * starts is the sequence number of the byte at an offset
1771 * of "deseg_offset" into "tvb".
1773 * The sequence number of the byte at an offset of "offset"
1774 * is "seq", i.e. the starting sequence number of this
1775 * segment, so the sequence number of the byte at
1776 * "deseg_offset" is "seq + (deseg_offset - offset)".
1778 deseg_seq = seq + (deseg_offset - offset);
1780 if(tcpd && ((nxtseq - deseg_seq) <= 1024*1024)
1781 && (!pinfo->fd->flags.visited) ){
1782 if(pinfo->desegment_len==DESEGMENT_ONE_MORE_SEGMENT){
1783 /* The subdissector asked to reassemble using the
1784 * entire next segment.
1785 * Just ask reassembly for one more byte
1786 * but set this msp flag so we can pick it up
1789 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1790 deseg_seq, nxtseq+1, tcpd->fwd->multisegment_pdus);
1791 msp->flags|=MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1793 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1794 deseg_seq, nxtseq+pinfo->desegment_len, tcpd->fwd->multisegment_pdus);
1797 /* add this segment as the first one for this new pdu */
1798 fragment_add(tvb, deseg_offset, pinfo, msp->first_frame,
1802 LT_SEQ(nxtseq, msp->nxtpdu));
1806 if (!called_dissector || pinfo->desegment_len != 0) {
1807 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
1808 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
1810 * We know what frame this PDU is reassembled in;
1811 * let the user know.
1813 item=proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in,
1814 tvb, 0, 0, ipfd_head->reassembled_in);
1815 PROTO_ITEM_SET_GENERATED(item);
1819 * Either we didn't call the subdissector at all (i.e.,
1820 * this is a segment that contains the middle of a
1821 * higher-level PDU, but contains neither the beginning
1822 * nor the end), or the subdissector couldn't dissect it
1823 * all, as some data was missing (i.e., it set
1824 * "pinfo->desegment_len" to the amount of additional
1827 if (pinfo->desegment_offset == 0) {
1829 * It couldn't, in fact, dissect any of it (the
1830 * first byte it couldn't dissect is at an offset
1831 * of "pinfo->desegment_offset" from the beginning
1832 * of the payload, and that's 0).
1833 * Just mark this as TCP.
1835 if (check_col(pinfo->cinfo, COL_PROTOCOL)){
1836 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
1838 if (check_col(pinfo->cinfo, COL_INFO)){
1839 col_set_str(pinfo->cinfo, COL_INFO, "[TCP segment of a reassembled PDU]");
1844 * Show what's left in the packet as just raw TCP segment
1846 * XXX - remember what protocol the last subdissector
1847 * was, and report it as a continuation of that, instead?
1849 nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
1850 proto_tree_add_text(tcp_tree, tvb, deseg_offset, -1,
1851 "TCP segment data (%u byte%s)", nbytes,
1852 plurality(nbytes, "", "s"));
1854 pinfo->can_desegment=0;
1855 pinfo->desegment_offset = 0;
1856 pinfo->desegment_len = 0;
1858 if(another_pdu_follows){
1859 /* there was another pdu following this one. */
1860 pinfo->can_desegment=2;
1861 /* we also have to prevent the dissector from changing the
1862 * PROTOCOL and INFO colums since what follows may be an
1863 * incomplete PDU and we dont want it be changed back from
1864 * <Protocol> to <TCP>
1865 * XXX There is no good way to block the PROTOCOL column
1866 * from being changed yet so we set the entire row unwritable.
1868 col_set_fence(pinfo->cinfo, COL_INFO);
1869 col_set_writable(pinfo->cinfo, FALSE);
1870 offset += another_pdu_follows;
1871 seq += another_pdu_follows;
1877 * Loop for dissecting PDUs within a TCP stream; assumes that a PDU
1878 * consists of a fixed-length chunk of data that contains enough information
1879 * to determine the length of the PDU, followed by rest of the PDU.
1881 * The first three arguments are the arguments passed to the dissector
1882 * that calls this routine.
1884 * "proto_desegment" is the dissector's flag controlling whether it should
1885 * desegment PDUs that cross TCP segment boundaries.
1887 * "fixed_len" is the length of the fixed-length part of the PDU.
1889 * "get_pdu_len()" is a routine called to get the length of the PDU from
1890 * the fixed-length part of the PDU; it's passed "pinfo", "tvb" and "offset".
1892 * "dissect_pdu()" is the routine to dissect a PDU.
1895 tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1896 gboolean proto_desegment, guint fixed_len,
1897 guint (*get_pdu_len)(packet_info *, tvbuff_t *, int),
1898 dissector_t dissect_pdu)
1900 volatile int offset = 0;
1902 guint length_remaining;
1906 proto_item *item=NULL;
1908 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1910 * We use "tvb_ensure_length_remaining()" to make sure there actually
1911 * *is* data remaining. The protocol we're handling could conceivably
1912 * consists of a sequence of fixed-length PDUs, and therefore the
1913 * "get_pdu_len" routine might not actually fetch anything from
1914 * the tvbuff, and thus might not cause an exception to be thrown if
1915 * we've run past the end of the tvbuff.
1917 * This means we're guaranteed that "length_remaining" is positive.
1919 length_remaining = tvb_ensure_length_remaining(tvb, offset);
1922 * Can we do reassembly?
1924 if (proto_desegment && pinfo->can_desegment) {
1926 * Yes - is the fixed-length part of the PDU split across segment
1929 if (length_remaining < fixed_len) {
1931 * Yes. Tell the TCP dissector where the data for this message
1932 * starts in the data it handed us, and how many more bytes we
1935 pinfo->desegment_offset = offset;
1936 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1942 * Get the length of the PDU.
1944 plen = (*get_pdu_len)(pinfo, tvb, offset);
1945 if (plen < fixed_len) {
1949 * 1) the length value extracted from the fixed-length portion
1950 * doesn't include the fixed-length portion's length, and
1951 * was so large that, when the fixed-length portion's
1952 * length was added to it, the total length overflowed;
1954 * 2) the length value extracted from the fixed-length portion
1955 * includes the fixed-length portion's length, and the value
1956 * was less than the fixed-length portion's length, i.e. it
1959 * Report this as a bounds error.
1961 show_reported_bounds_error(tvb, pinfo, tree);
1965 * Display the PDU length as a field
1967 item=proto_tree_add_uint(pinfo->tcp_tree, hf_tcp_pdu_size, tvb, offset, plen, plen);
1968 PROTO_ITEM_SET_GENERATED(item);
1972 /* give a hint to TCP where the next PDU starts
1973 * so that it can attempt to find it in case it starts
1974 * somewhere in the middle of a segment.
1976 if(!pinfo->fd->flags.visited && tcp_analyze_seq){
1977 guint remaining_bytes;
1978 remaining_bytes=tvb_reported_length_remaining(tvb, offset);
1979 if(plen>remaining_bytes){
1980 pinfo->want_pdu_tracking=2;
1981 pinfo->bytes_until_next_pdu=plen-remaining_bytes;
1986 * Can we do reassembly?
1988 if (proto_desegment && pinfo->can_desegment) {
1990 * Yes - is the PDU split across segment boundaries?
1992 if (length_remaining < plen) {
1994 * Yes. Tell the TCP dissector where the data for this message
1995 * starts in the data it handed us, and how many more bytes we
1998 pinfo->desegment_offset = offset;
1999 pinfo->desegment_len = plen - length_remaining;
2005 * Construct a tvbuff containing the amount of the payload we have
2006 * available. Make its reported length the amount of data in the PDU.
2008 * XXX - if reassembly isn't enabled. the subdissector will throw a
2009 * BoundsError exception, rather than a ReportedBoundsError exception.
2010 * We really want a tvbuff where the length is "length", the reported
2011 * length is "plen", and the "if the snapshot length were infinite"
2012 * length is the minimum of the reported length of the tvbuff handed
2013 * to us and "plen", with a new type of exception thrown if the offset
2014 * is within the reported length but beyond that third length, with
2015 * that exception getting the "Unreassembled Packet" error.
2017 length = length_remaining;
2020 next_tvb = tvb_new_subset(tvb, offset, length, plen);
2025 * Catch the ReportedBoundsError exception; if this particular message
2026 * happens to get a ReportedBoundsError exception, that doesn't mean
2027 * that we should stop dissecting PDUs within this frame or chunk of
2030 * If it gets a BoundsError, we can stop, as there's nothing more to
2031 * see, so we just re-throw it.
2034 (*dissect_pdu)(next_tvb, pinfo, tree);
2036 CATCH(BoundsError) {
2039 CATCH(ReportedBoundsError) {
2040 show_reported_bounds_error(tvb, pinfo, tree);
2045 * Step to the next PDU.
2046 * Make sure we don't overflow.
2048 offset_before = offset;
2050 if (offset <= offset_before)
2056 tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val)
2058 if (check_col(pinfo->cinfo, COL_INFO))
2059 col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%u", abbrev, val);
2062 /* Supports the reporting the contents of a parsed SCPS capabilities vector */
2064 tcp_info_append_str(packet_info *pinfo, const char *abbrev, const char *val)
2066 if (check_col(pinfo->cinfo, COL_INFO))
2067 col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%s]", abbrev, val);
2071 dissect_tcpopt_maxseg(const ip_tcp_opt *optp, tvbuff_t *tvb,
2072 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2074 proto_item *hidden_item;
2077 mss = tvb_get_ntohs(tvb, offset + 2);
2078 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_mss, tvb, offset,
2080 PROTO_ITEM_SET_HIDDEN(hidden_item);
2081 proto_tree_add_uint_format(opt_tree, hf_tcp_option_mss_val, tvb, offset,
2082 optlen, mss, "%s: %u bytes", optp->name, mss);
2083 tcp_info_append_uint(pinfo, "MSS", mss);
2087 dissect_tcpopt_wscale(const ip_tcp_opt *optp, tvbuff_t *tvb,
2088 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2090 proto_item *hidden_item;
2092 struct tcp_analysis *tcpd=NULL;
2094 tcpd=get_tcp_conversation_data(pinfo);
2096 ws = tvb_get_guint8(tvb, offset + 2);
2097 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_wscale, tvb,
2098 offset, optlen, TRUE);
2099 PROTO_ITEM_SET_HIDDEN(hidden_item);
2100 proto_tree_add_uint_format(opt_tree, hf_tcp_option_wscale_val, tvb,
2101 offset, optlen, ws, "%s: %u (multiply by %u)",
2102 optp->name, ws, 1 << ws);
2103 tcp_info_append_uint(pinfo, "WS", ws);
2104 if(!pinfo->fd->flags.visited && tcp_analyze_seq && tcp_relative_seq){
2105 pdu_store_window_scale_option(ws, tcpd);
2110 dissect_tcpopt_sack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2111 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2113 proto_tree *field_tree = NULL;
2114 proto_item *tf=NULL;
2115 proto_item *hidden_item;
2116 guint32 leftedge, rightedge;
2117 struct tcp_analysis *tcpd=NULL;
2120 if(tcp_analyze_seq && tcp_relative_seq){
2121 /* find(or create if needed) the conversation for this tcp session */
2122 tcpd=get_tcp_conversation_data(pinfo);
2125 base_ack=tcpd->rev->base_seq;
2129 tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
2130 offset += 2; /* skip past type and length */
2131 optlen -= 2; /* subtract size of type and length */
2132 while (optlen > 0) {
2133 if (field_tree == NULL) {
2134 /* Haven't yet made a subtree out of this option. Do so. */
2135 field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
2136 hidden_item = proto_tree_add_boolean(field_tree, hf_tcp_option_sack, tvb,
2137 offset, optlen, TRUE);
2138 PROTO_ITEM_SET_HIDDEN(hidden_item);
2141 proto_tree_add_text(field_tree, tvb, offset, optlen,
2142 "(suboption would go past end of option)");
2145 leftedge = tvb_get_ntohl(tvb, offset)-base_ack;
2146 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
2147 offset, 4, leftedge,
2148 "left edge = %u%s", leftedge,
2149 tcp_relative_seq ? " (relative)" : "");
2153 proto_tree_add_text(field_tree, tvb, offset, optlen,
2154 "(suboption would go past end of option)");
2157 /* XXX - check whether it goes past end of packet */
2158 rightedge = tvb_get_ntohl(tvb, offset + 4)-base_ack;
2160 proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
2161 offset+4, 4, rightedge,
2162 "right edge = %u%s", rightedge,
2163 tcp_relative_seq ? " (relative)" : "");
2164 tcp_info_append_uint(pinfo, "SLE", leftedge);
2165 tcp_info_append_uint(pinfo, "SRE", rightedge);
2166 proto_item_append_text(field_tree, " %u-%u", leftedge, rightedge);
2172 dissect_tcpopt_echo(const ip_tcp_opt *optp, tvbuff_t *tvb,
2173 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2175 proto_item *hidden_item;
2178 echo = tvb_get_ntohl(tvb, offset + 2);
2179 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_echo, tvb, offset,
2181 PROTO_ITEM_SET_HIDDEN(hidden_item);
2182 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2183 "%s: %u", optp->name, echo);
2184 tcp_info_append_uint(pinfo, "ECHO", echo);
2188 dissect_tcpopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
2189 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2191 proto_item *hidden_item;
2194 tsv = tvb_get_ntohl(tvb, offset + 2);
2195 tser = tvb_get_ntohl(tvb, offset + 6);
2196 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_time_stamp, tvb,
2197 offset, optlen, TRUE);
2198 PROTO_ITEM_SET_HIDDEN(hidden_item);
2199 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2200 "%s: TSval %u, TSecr %u", optp->name, tsv, tser);
2201 tcp_info_append_uint(pinfo, "TSV", tsv);
2202 tcp_info_append_uint(pinfo, "TSER", tser);
2206 dissect_tcpopt_cc(const ip_tcp_opt *optp, tvbuff_t *tvb,
2207 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2209 proto_item *hidden_item;
2212 cc = tvb_get_ntohl(tvb, offset + 2);
2213 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_cc, tvb, offset,
2215 PROTO_ITEM_SET_HIDDEN(hidden_item);
2216 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2217 "%s: %u", optp->name, cc);
2218 tcp_info_append_uint(pinfo, "CC", cc);
2222 dissect_tcpopt_qs(const ip_tcp_opt *optp, tvbuff_t *tvb,
2223 int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
2225 /* Quick-Start TCP option, as defined by RFC4782 */
2226 static const value_string qs_rates[] = {
2232 { 5, "1.28 Mbit/s"},
2233 { 6, "2.56 Mbit/s"},
2234 { 7, "5.12 Mbit/s"},
2235 { 8, "10.24 Mbit/s"},
2236 { 9, "20.48 Mbit/s"},
2237 {10, "40.96 Mbit/s"},
2238 {11, "81.92 Mbit/s"},
2239 {12, "163.84 Mbit/s"},
2240 {13, "327.68 Mbit/s"},
2241 {14, "655.36 Mbit/s"},
2242 {15, "1.31072 Gbit/s"},
2245 proto_item *hidden_item;
2247 guint8 rate = tvb_get_guint8(tvb, offset + 2) & 0x0f;
2249 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_qs, tvb, offset,
2251 PROTO_ITEM_SET_HIDDEN(hidden_item);
2252 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2253 "%s: Rate response, %s, TTL diff %u ", optp->name,
2254 val_to_str(rate, qs_rates, "Unknown"),
2255 tvb_get_guint8(tvb, offset + 3));
2256 if (check_col(pinfo->cinfo, COL_INFO))
2257 col_append_fstr(pinfo->cinfo, COL_INFO, " QSresp=%s", val_to_str(rate, qs_rates, "Unknown"));
2262 dissect_tcpopt_scps(const ip_tcp_opt *optp, tvbuff_t *tvb,
2263 int offset, guint optlen, packet_info *pinfo,
2264 proto_tree *opt_tree)
2266 struct tcp_analysis *tcpd=NULL;
2267 proto_tree *field_tree = NULL;
2270 proto_item *tf = NULL, *hidden_item;
2271 gchar flags[64] = "<None>";
2272 gchar *fstr[] = {"BETS", "SNACK1", "SNACK2", "COMP", "NLTS", "RESV1", "RESV2", "RESV3" };
2277 tcpd = get_tcp_conversation_data(pinfo);
2279 /* check direction and get ua lists */
2280 direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
2282 /* if the addresses are equal, match the ports instead */
2284 direction= (pinfo->srcport > pinfo->destport)*2-1;
2288 flow =&(tcpd->flow1);
2290 flow =&(tcpd->flow2);
2292 /* If the option length == 4, this is a real SCPS capability option
2293 * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol
2294 * (SCPS-TP)" Section 3.2.3 for definition.
2297 capvector = tvb_get_guint8(tvb, offset + 2);
2300 /* Decode the capabilities vector for display */
2301 for (i = 0; i < 5; i++) {
2303 if (capvector & bpos) {
2305 g_strlcat(flags, ", ", 64);
2307 g_strlcat(flags, fstr[i], 64);
2311 /* If lossless header compression is offered, there will be a
2312 * single octet connectionId following the capabilities vector
2314 if (capvector & 0x10)
2315 connid = tvb_get_guint8(tvb, offset + 3);
2319 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector, tvb,
2320 offset, optlen, capvector,
2322 optp->name, capvector, flags);
2323 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_scps,
2324 tvb, offset, optlen, TRUE);
2325 PROTO_ITEM_SET_HIDDEN(hidden_item);
2327 field_tree = proto_item_add_subtree(tf, ett_tcp_option_scps);
2329 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_bets, tvb,
2330 offset + 13, 1, capvector);
2331 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_snack1, tvb,
2332 offset + 13, 1, capvector);
2333 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_snack2, tvb,
2334 offset + 13, 1, capvector);
2335 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_compress, tvb,
2336 offset + 13, 1, capvector);
2337 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_nlts, tvb,
2338 offset + 13, 1, capvector);
2339 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv1, tvb,
2340 offset + 13, 1, capvector);
2341 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv2, tvb,
2342 offset + 13, 1, capvector);
2343 proto_tree_add_boolean(field_tree, hf_tcp_scpsoption_flags_resv3, tvb,
2344 offset + 13, 1, capvector);
2346 tcp_info_append_str(pinfo, "SCPS", flags);
2348 flow->scps_capable = 1;
2351 tcp_info_append_uint(pinfo, "Connection ID", connid);
2354 /* The option length != 4, so this is an infamous "extended capabilities
2355 * option. See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2356 * Transport Protocol (SCPS-TP)" Section 3.2.5 for definition.
2358 * As the format of this option is only partially defined (it is
2359 * a community (or more likely vendor) defined format beyond that, so
2360 * at least for now, we only parse the standardized portion of the option.
2362 guint8 local_offset = 2;
2363 guint8 binding_space;
2364 guint8 extended_cap_length;
2366 if (flow->scps_capable != 1) {
2367 /* There was no SCPS capabilities option preceeding this */
2368 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2369 tvb, offset, optlen, 0, "%s: (%d %s)",
2370 "Illegal SCPS Extended Capabilities",
2375 tf = proto_tree_add_uint_format(opt_tree, hf_tcp_option_scps_vector,
2376 tvb, offset, optlen, 0, "%s: (%d %s)",
2377 "SCPS Extended Capabilities",
2380 field_tree=proto_item_add_subtree(tf, ett_tcp_option_scps_extended);
2381 /* There may be multiple binding spaces included in a single option,
2382 * so we will semi-parse each of the stacked binding spaces - skipping
2383 * over the octets following the binding space identifier and length.
2386 while (optlen > local_offset) {
2387 proto_item *hidden_item;
2389 /* 1st octet is Extended Capability Binding Space */
2390 binding_space = tvb_get_guint8(tvb, (offset + local_offset));
2392 /* 2nd octet (upper 4-bits) has binding space length in 16-bit words.
2393 * As defined by the specification, this length is exclusive of the
2394 * octets containing the extended capability type and length
2397 extended_cap_length =
2398 (tvb_get_guint8(tvb, (offset + local_offset + 1)) >> 4);
2400 /* Convert the extended capabilities length into bytes for display */
2401 extended_cap_length = (extended_cap_length << 1);
2403 proto_tree_add_text(field_tree, tvb, offset + local_offset, 2,
2404 "\tBinding Space %u",
2406 hidden_item = proto_tree_add_uint(field_tree, hf_tcp_option_scps_binding,
2407 tvb, (offset + local_offset), 1,
2410 PROTO_ITEM_SET_HIDDEN(hidden_item);
2412 /* Step past the binding space and length octets */
2415 proto_tree_add_text(field_tree, tvb, offset + local_offset,
2416 extended_cap_length,
2417 "\tBinding Space Data (%u bytes)",
2418 extended_cap_length);
2420 tcp_info_append_uint(pinfo, "EXCAP", binding_space);
2422 /* Step past the Extended capability data
2423 * Treat the extended capability data area as opaque;
2424 * If one desires to parse the extended capability data
2425 * (say, in a vendor aware build of wireshark), it would
2428 local_offset += extended_cap_length;
2434 /* This is called for SYN+ACK packets and the purpose is to verify that
2435 * the SCPS capabilities option has been successfully negotiated for the flow.
2436 * If the SCPS capabilities option was offered by only one party, the
2437 * proactively set scps_capable attribute of the flow (set upon seeing
2438 * the first instance of the SCPS option) is revoked.
2441 verify_scps(packet_info *pinfo, proto_item *tf_syn, struct tcp_analysis *tcpd)
2446 if ((!(tcpd->flow1.scps_capable)) || (!(tcpd->flow2.scps_capable))) {
2447 tcpd->flow1.scps_capable = 0;
2448 tcpd->flow2.scps_capable = 0;
2451 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_NOTE,
2452 "Connection establish request (SYN-ACK): SCPS Capabilities Negotiated");
2457 /* See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS
2458 * Transport Protocol (SCPS-TP)" Section 3.5 for definition of the SNACK option
2461 dissect_tcpopt_snack(const ip_tcp_opt *optp, tvbuff_t *tvb,
2462 int offset, guint optlen, packet_info *pinfo,
2463 proto_tree *opt_tree)
2465 struct tcp_analysis *tcpd=NULL;
2466 guint16 relative_hole_offset;
2467 guint16 relative_hole_size;
2468 guint16 base_mss = 0;
2472 char null_modifier[] = "\0";
2473 char relative_modifier[] = "(relative)";
2474 char *modifier = null_modifier;
2475 proto_item *hidden_item;
2477 tcpd = get_tcp_conversation_data(pinfo);
2479 /* The SNACK option reports missing data with a granualarity of segments. */
2480 relative_hole_offset = tvb_get_ntohs(tvb, offset + 2);
2481 relative_hole_size = tvb_get_ntohs(tvb, offset + 4);
2483 hidden_item = proto_tree_add_boolean(opt_tree, hf_tcp_option_snack, tvb,
2484 offset, optlen, TRUE);
2485 PROTO_ITEM_SET_HIDDEN(hidden_item);
2487 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_offset,
2488 tvb, offset, optlen, relative_hole_offset);
2489 PROTO_ITEM_SET_HIDDEN(hidden_item);
2491 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_size,
2492 tvb, offset, optlen, relative_hole_size);
2493 PROTO_ITEM_SET_HIDDEN(hidden_item);
2494 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2495 "%s: Offset %u, Size %u", optp->name,
2496 relative_hole_offset, relative_hole_size);
2498 ack = tvb_get_ntohl(tvb, 8);
2500 if (tcp_relative_seq == TRUE) {
2501 ack -= tcpd->rev->base_seq;
2502 modifier = relative_modifier;
2505 /* To aid analysis, we can use a simple but generally effective heuristic
2506 * to report the most likely boundaries of the missing data. If the
2507 * flow is scps_capable, we track the maximum sized segment that was
2508 * acknowledged by the receiver and use that as the reporting granularity.
2509 * This may be different from the negotiated MTU due to PMTUD or flows
2510 * that do not send max-sized segments.
2512 base_mss = tcpd->fwd->maxsizeacked;
2515 proto_item *hidden_item;
2516 /* Scale the reported offset and hole size by the largest segment acked */
2517 hole_start = ack + (base_mss * relative_hole_offset);
2518 hole_end = hole_start + (base_mss * relative_hole_size);
2520 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_le,
2521 tvb, offset, optlen, hole_start);
2522 PROTO_ITEM_SET_HIDDEN(hidden_item);
2524 hidden_item = proto_tree_add_uint(opt_tree, hf_tcp_option_snack_re,
2525 tvb, offset, optlen, hole_end);
2526 PROTO_ITEM_SET_HIDDEN(hidden_item);
2527 proto_tree_add_text(opt_tree, tvb, offset, optlen,
2528 "\tMissing Sequence %u - %u %s",
2529 hole_start, hole_end, modifier);
2531 tcp_info_append_uint(pinfo, "SNLE", hole_start);
2532 tcp_info_append_uint(pinfo, "SNRE", hole_end);
2534 expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_NOTE,
2535 "SNACK Sequence %u - %u %s",
2536 hole_start, hole_end, modifier);
2540 static const ip_tcp_opt tcpopts[] = {
2559 "Maximum segment size",
2563 dissect_tcpopt_maxseg
2571 dissect_tcpopt_wscale
2584 &ett_tcp_option_sack,
2611 dissect_tcpopt_timestamp
2639 "TCP MD5 signature",
2648 &ett_tcp_option_scps,
2655 "Selective Negative Acknowledgement",
2659 dissect_tcpopt_snack
2671 #define N_TCP_OPTS (sizeof tcpopts / sizeof tcpopts[0])
2673 /* Determine if there is a sub-dissector and call it; return TRUE
2674 if there was a sub-dissector, FALSE otherwise.
2676 This has been separated into a stand alone routine to other protocol
2677 dissectors can call to it, e.g., SOCKS. */
2679 static gboolean try_heuristic_first = FALSE;
2682 /* this function can be called with tcpd==NULL as from the msproxy dissector */
2684 decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
2685 proto_tree *tree, int src_port, int dst_port,
2686 struct tcp_analysis *tcpd)
2689 int low_port, high_port;
2690 int save_desegment_offset;
2691 guint32 save_desegment_len;
2693 /* dont call subdissectors for keepalive or zerowindowprobes
2694 * even though they do contain payload "data"
2695 * keeaplives just contain garbage and zwp contain too little data (1 byte)
2698 if(tcpd && tcpd->ta){
2699 if(tcpd->ta->flags&(TCP_A_ZERO_WINDOW_PROBE|TCP_A_KEEP_ALIVE)){
2704 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
2706 /* determine if this packet is part of a conversation and call dissector */
2707 /* for the conversation if available */
2709 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP,
2710 src_port, dst_port, next_tvb, pinfo, tree)){
2711 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2715 if (try_heuristic_first) {
2716 /* do lookup with the heuristic subdissector table */
2717 save_desegment_offset = pinfo->desegment_offset;
2718 save_desegment_len = pinfo->desegment_len;
2719 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
2720 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2724 * They rejected the packet; make sure they didn't also request
2725 * desegmentation (we could just override the request, but
2726 * rejecting a packet *and* requesting desegmentation is a sign
2727 * of the dissector's code needing clearer thought, so we fail
2728 * so that the problem is made more obvious).
2730 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
2731 save_desegment_len == pinfo->desegment_len);
2734 /* Do lookups with the subdissector table.
2735 We try the port number with the lower value first, followed by the
2736 port number with the higher value. This means that, for packets
2737 where a dissector is registered for *both* port numbers:
2739 1) we pick the same dissector for traffic going in both directions;
2741 2) we prefer the port number that's more likely to be the right
2742 one (as that prefers well-known ports to reserved ports);
2744 although there is, of course, no guarantee that any such strategy
2745 will always pick the right port number.
2747 XXX - we ignore port numbers of 0, as some dissectors use a port
2748 number of 0 to disable the port. */
2749 if (src_port > dst_port) {
2750 low_port = dst_port;
2751 high_port = src_port;
2753 low_port = src_port;
2754 high_port = dst_port;
2756 if (low_port != 0 &&
2757 dissector_try_port(subdissector_table, low_port, next_tvb, pinfo, tree)){
2758 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2761 if (high_port != 0 &&
2762 dissector_try_port(subdissector_table, high_port, next_tvb, pinfo, tree)){
2763 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2767 if (!try_heuristic_first) {
2768 /* do lookup with the heuristic subdissector table */
2769 save_desegment_offset = pinfo->desegment_offset;
2770 save_desegment_len = pinfo->desegment_len;
2771 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
2772 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2776 * They rejected the packet; make sure they didn't also request
2777 * desegmentation (we could just override the request, but
2778 * rejecting a packet *and* requesting desegmentation is a sign
2779 * of the dissector's code needing clearer thought, so we fail
2780 * so that the problem is made more obvious).
2782 DISSECTOR_ASSERT(save_desegment_offset == pinfo->desegment_offset &&
2783 save_desegment_len == pinfo->desegment_len);
2786 /* Oh, well, we don't know this; dissect it as data. */
2787 call_dissector(data_handle,next_tvb, pinfo, tree);
2789 pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
2794 process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
2795 proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
2796 guint32 seq, guint32 nxtseq, gboolean is_tcp_segment,
2797 struct tcp_analysis *tcpd)
2799 pinfo->want_pdu_tracking=0;
2803 /*qqq see if it is an unaligned PDU */
2804 if(tcpd && tcp_analyze_seq && (!tcp_desegment)){
2806 offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
2807 seq, nxtseq, tcpd->fwd->multisegment_pdus);
2811 /* if offset is -1 this means that this segment is known
2812 * to be fully inside a previously detected pdu
2813 * so we dont even need to try to dissect it either.
2816 decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
2819 * We succeeded in handing off to a subdissector.
2821 * Is this a TCP segment or a reassembled chunk of
2825 /* if !visited, check want_pdu_tracking and
2826 store it in table */
2827 if(tcpd && (!pinfo->fd->flags.visited) &&
2828 tcp_analyze_seq && pinfo->want_pdu_tracking){
2830 pdu_store_sequencenumber_of_next_pdu(
2833 nxtseq+pinfo->bytes_until_next_pdu,
2834 tcpd->fwd->multisegment_pdus);
2841 /* We got an exception. At this point the dissection is
2842 * completely aborted and execution will be transfered back
2843 * to (probably) the frame dissector.
2844 * Here we have to place whatever we want the dissector
2845 * to do before aborting the tcp dissection.
2848 * Is this a TCP segment or a reassembled chunk of TCP
2853 * It's from a TCP segment.
2855 * if !visited, check want_pdu_tracking and store it
2858 if(tcpd && (!pinfo->fd->flags.visited) && tcp_analyze_seq && pinfo->want_pdu_tracking){
2860 pdu_store_sequencenumber_of_next_pdu(pinfo,
2862 nxtseq+pinfo->bytes_until_next_pdu,
2863 tcpd->fwd->multisegment_pdus);
2873 dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,
2874 guint32 nxtseq, guint32 sport, guint32 dport,
2875 proto_tree *tree, proto_tree *tcp_tree,
2876 struct tcp_analysis *tcpd)
2878 gboolean save_fragmented;
2880 /* Can we desegment this segment? */
2881 if (pinfo->can_desegment) {
2883 desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
2886 /* No - just call the subdissector.
2887 Mark this as fragmented, so if somebody throws an exception,
2888 we don't report it as a malformed frame. */
2889 save_fragmented = pinfo->fragmented;
2890 pinfo->fragmented = TRUE;
2891 process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
2892 seq, nxtseq, TRUE, tcpd);
2893 pinfo->fragmented = save_fragmented;
2898 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2900 guint8 th_off_x2; /* combines th_off and th_x2 */
2903 proto_tree *tcp_tree = NULL, *field_tree = NULL;
2904 proto_item *ti = NULL, *tf, *hidden_item;
2906 gchar *flags = "<None>";
2907 const gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR" };
2908 size_t fpos = 0, returned_length;
2916 guint16 computed_cksum;
2917 guint16 real_window;
2918 guint length_remaining;
2919 gboolean desegment_ok;
2920 struct tcpinfo tcpinfo;
2921 struct tcpheader *tcph;
2922 proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL;
2923 struct tcp_analysis *tcpd=NULL;
2924 struct tcp_per_packet_data_t *tcppd=NULL;
2926 proto_tree *checksum_tree;
2930 tcph=ep_alloc(sizeof(struct tcpheader));
2931 SET_ADDRESS(&tcph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
2932 SET_ADDRESS(&tcph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
2934 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2935 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
2937 /* Clear out the Info column. */
2938 if (check_col(pinfo->cinfo, COL_INFO))
2939 col_clear(pinfo->cinfo, COL_INFO);
2941 tcph->th_sport = tvb_get_ntohs(tvb, offset);
2942 tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
2943 if (check_col(pinfo->cinfo, COL_INFO)) {
2944 col_append_fstr(pinfo->cinfo, COL_INFO, "%s > %s",
2945 get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
2948 if (tcp_summary_in_tree) {
2949 ti = proto_tree_add_protocol_format(tree, proto_tcp, tvb, 0, -1,
2950 "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
2951 get_tcp_port(tcph->th_sport), tcph->th_sport,
2952 get_tcp_port(tcph->th_dport), tcph->th_dport);
2955 ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, FALSE);
2957 tcp_tree = proto_item_add_subtree(ti, ett_tcp);
2958 pinfo->tcp_tree=tcp_tree;
2960 proto_tree_add_uint_format(tcp_tree, hf_tcp_srcport, tvb, offset, 2, tcph->th_sport,
2961 "Source port: %s (%u)", get_tcp_port(tcph->th_sport), tcph->th_sport);
2962 proto_tree_add_uint_format(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, tcph->th_dport,
2963 "Destination port: %s (%u)", get_tcp_port(tcph->th_dport), tcph->th_dport);
2964 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset, 2, tcph->th_sport);
2965 PROTO_ITEM_SET_HIDDEN(hidden_item);
2966 hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, tcph->th_dport);
2967 PROTO_ITEM_SET_HIDDEN(hidden_item);
2969 /* If we're dissecting the headers of a TCP packet in an ICMP packet
2970 * then go ahead and put the sequence numbers in the tree now (because
2971 * they won't be put in later because the ICMP packet only contains up
2972 * to the sequence number).
2973 * We should only need to do this for IPv4 since IPv6 will hopefully
2974 * carry enough TCP payload for this dissector to put the sequence
2975 * numbers in via the regular code path.
2977 if (pinfo->layer_names != NULL && pinfo->layer_names->str != NULL) {
2978 /* use strstr because g_strrstr is only present in glib2.0 and
2979 * g_str_has_suffix in glib2.2
2981 if (strstr(pinfo->layer_names->str, "icmp:ip") != NULL)
2982 proto_tree_add_item(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, FALSE);
2986 /* Set the source and destination port numbers as soon as we get them,
2987 so that they're available to the "Follow TCP Stream" code even if
2988 we throw an exception dissecting the rest of the TCP header. */
2989 pinfo->ptype = PT_TCP;
2990 pinfo->srcport = tcph->th_sport;
2991 pinfo->destport = tcph->th_dport;
2993 tcph->th_seq = tvb_get_ntohl(tvb, offset + 4);
2994 tcph->th_ack = tvb_get_ntohl(tvb, offset + 8);
2995 th_off_x2 = tvb_get_guint8(tvb, offset + 12);
2996 tcph->th_flags = tvb_get_guint8(tvb, offset + 13);
2997 tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
2998 real_window = tcph->th_win;
2999 tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
3001 /* find(or create if needed) the conversation for this tcp session */
3002 tcpd=get_tcp_conversation_data(pinfo);
3004 /* If this is a SYN packet, then check if it's seq-nr is different
3005 * from the base_seq of the retrieved conversation. If this is the
3006 * case, create a new conversation with the same addresses and ports
3007 * and set the TA_PORTS_REUSED flag. If the seq-nr is the same as
3008 * the base_seq, then do nothing so it will be marked as a retrans-
3011 if(tcpd && ((tcph->th_flags&(TH_SYN|TH_ACK))==TH_SYN) &&
3012 (tcpd->fwd->base_seq!=0) &&
3013 (tcph->th_seq!=tcpd->fwd->base_seq) ) {
3014 if (!(pinfo->fd->flags.visited))
3015 tcpd=new_tcp_conversation(pinfo);
3017 tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE, tcpd);
3018 tcpd->ta->flags|=TCP_A_REUSED_PORTS;
3022 /* Do we need to calculate timestamps relative to the tcp-stream? */
3023 if (tcp_calculate_ts) {
3025 tcppd = p_get_proto_data(pinfo->fd, proto_tcp);
3028 * Calculate the timestamps relative to this conversation (but only on the
3029 * first run when frames are accessed sequentially)
3031 if (!(pinfo->fd->flags.visited))
3032 tcp_calculate_timestamps(pinfo, tcpd, tcppd);
3034 /* Fill the conversation timestamp columns */
3035 if (tcpd && check_col(pinfo->cinfo, COL_REL_CONV_TIME)) {
3036 nstime_delta(&ts, &pinfo->fd->abs_ts, &tcpd->ts_first);
3037 col_set_time(pinfo->cinfo, COL_REL_CONV_TIME, &ts, "tcp.time_relative");
3040 if (check_col(pinfo->cinfo, COL_DELTA_CONV_TIME)) {
3042 col_set_time(pinfo->cinfo, COL_DELTA_CONV_TIME, &tcppd->ts_del, "tcp.time_delta");
3048 * If we've been handed an IP fragment, we don't know how big the TCP
3049 * segment is, so don't do anything that requires that we know that.
3051 * The same applies if we're part of an error packet. (XXX - if the
3052 * ICMP and ICMPv6 dissectors could set a "this is how big the IP
3053 * header says it is" length in the tvbuff, we could use that; such
3054 * a length might also be useful for handling packets where the IP
3055 * length is bigger than the actual data available in the frame; the
3056 * dissectors should trust that length, and then throw a
3057 * ReportedBoundsError exception when they go past the end of the frame.)
3059 * We also can't determine the segment length if the reported length
3060 * of the TCP packet is less than the TCP header length.
3062 reported_len = tvb_reported_length(tvb);
3064 if (!pinfo->fragmented && !pinfo->in_error_pkt) {
3065 if (reported_len < tcph->th_hlen) {
3067 pi = proto_tree_add_text(tcp_tree, tvb, offset, 0,
3068 "Short segment. Segment/fragment does not contain a full TCP header"
3069 " (might be NMAP or someone else deliberately sending unusual packets)");
3070 PROTO_ITEM_SET_GENERATED(pi);
3071 expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_WARN, "Short segment");
3072 tcph->th_have_seglen = FALSE;
3074 /* Compute the length of data in this segment. */
3075 tcph->th_seglen = reported_len - tcph->th_hlen;
3076 tcph->th_have_seglen = TRUE;
3078 if (tree) { /* Add the seglen as an invisible field */
3080 hidden_item = proto_tree_add_uint(ti, hf_tcp_len, tvb, offset, 4, tcph->th_seglen);
3081 PROTO_ITEM_SET_HIDDEN(hidden_item);
3086 /* handle TCP seq# analysis parse all new segments we see */
3087 if(tcp_analyze_seq){
3088 if(!(pinfo->fd->flags.visited)){
3089 tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd);
3091 if(tcp_relative_seq){
3092 tcp_get_relative_seq_ack(&(tcph->th_seq), &(tcph->th_ack), &(tcph->th_win), tcpd);
3096 /* Compute the sequence number of next octet after this segment. */
3097 nxtseq = tcph->th_seq + tcph->th_seglen;
3100 tcph->th_have_seglen = FALSE;
3102 if (check_col(pinfo->cinfo, COL_INFO) || tree) {
3103 #define MAX_FLAGS_LEN 64
3104 flags=ep_alloc(MAX_FLAGS_LEN);
3106 for (i = 0; i < 8; i++) {
3108 if (tcph->th_flags & bpos) {
3109 returned_length = g_snprintf(&flags[fpos], MAX_FLAGS_LEN-fpos, "%s%s",
3112 fpos += MIN(returned_length, MAX_FLAGS_LEN-fpos);
3117 if (check_col(pinfo->cinfo, COL_INFO)) {
3118 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] Seq=%u", flags, tcph->th_seq);
3119 if (tcph->th_flags&TH_ACK) {
3120 col_append_fstr(pinfo->cinfo, COL_INFO, " Ack=%u", tcph->th_ack);
3122 if (tcph->th_flags&TH_SYN) { /* SYNs are never scaled */
3123 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", real_window);
3125 col_append_fstr(pinfo->cinfo, COL_INFO, " Win=%u", tcph->th_win);
3130 if (tcp_summary_in_tree) {
3131 proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
3133 if(tcp_relative_seq){
3134 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);
3136 proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
3140 if (tcph->th_hlen < TCPH_MIN_LEN) {
3141 /* Give up at this point; we put the source and destination port in
3142 the tree, before fetching the header length, so that they'll
3143 show up if this is in the failing packet in an ICMP error packet,
3144 but it's now time to give up if the header length is bogus. */
3145 if (check_col(pinfo->cinfo, COL_INFO))
3146 col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
3147 tcph->th_hlen, TCPH_MIN_LEN);
3149 proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
3150 "Header length: %u bytes (bogus, must be at least %u)", tcph->th_hlen,
3157 if (tcp_summary_in_tree) {
3158 if(tcph->th_flags&TH_ACK){
3159 proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
3161 if (tcph->th_have_seglen)
3162 proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
3164 proto_item_set_len(ti, tcph->th_hlen);
3165 if (tcph->th_have_seglen) {
3166 if (nxtseq != tcph->th_seq) {
3167 if(tcp_relative_seq){
3168 tf=proto_tree_add_uint_format(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "Next sequence number: %u (relative sequence number)", nxtseq);
3170 tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
3172 PROTO_ITEM_SET_GENERATED(tf);
3175 if (tcph->th_flags & TH_ACK) {
3176 if(tcp_relative_seq){
3177 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);
3179 proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
3182 /* Verify that the ACK field is zero */
3183 if(tvb_get_ntohl(tvb, offset+8) != 0){
3184 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");
3187 proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
3188 "Header length: %u bytes", tcph->th_hlen);
3189 tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 13, 1,
3190 tcph->th_flags, "Flags: 0x%02x (%s)", tcph->th_flags, flags);
3191 field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
3192 proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
3193 proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, tvb, offset + 13, 1, tcph->th_flags);
3194 proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
3195 proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
3196 proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
3197 tf_rst = proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
3198 tf_syn = proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
3199 tf_fin = proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
3201 && (tcph->th_win!=real_window)
3202 && !(tcph->th_flags&TH_SYN) ){ /* SYNs are never scaled */
3203 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);
3205 proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, real_window);
3209 if(tcph->th_flags & TH_SYN) {
3210 if(tcph->th_flags & TH_ACK)
3211 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish acknowledge (SYN+ACK): server port %s",
3212 get_tcp_port(tcph->th_sport));
3214 expert_add_info_format(pinfo, tf_syn, PI_SEQUENCE, PI_CHAT, "Connection establish request (SYN): server port %s",
3215 get_tcp_port(tcph->th_dport));
3217 if(tcph->th_flags & TH_FIN)
3218 /* XXX - find a way to know the server port and output only that one */
3219 expert_add_info_format(pinfo, tf_fin, PI_SEQUENCE, PI_CHAT, "Connection finish (FIN)");
3220 if(tcph->th_flags & TH_RST)
3221 /* XXX - find a way to know the server port and output only that one */
3222 expert_add_info_format(pinfo, tf_rst, PI_SEQUENCE, PI_CHAT, "Connection reset (RST)");
3224 /* Supply the sequence number of the first byte and of the first byte
3225 after the segment. */
3226 tcpinfo.seq = tcph->th_seq;
3227 tcpinfo.nxtseq = nxtseq;
3228 tcpinfo.lastackseq = tcph->th_ack;
3230 /* Assume we'll pass un-reassembled data to subdissectors. */
3231 tcpinfo.is_reassembled = FALSE;
3233 pinfo->private_data = &tcpinfo;
3236 * Assume, initially, that we can't desegment.
3238 pinfo->can_desegment = 0;
3239 th_sum = tvb_get_ntohs(tvb, offset + 16);
3240 if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
3241 /* The packet isn't part of an un-reassembled fragmented datagram
3242 and isn't truncated. This means we have all the data, and thus
3243 can checksum it and, unless it's being returned in an error
3244 packet, are willing to allow subdissectors to request reassembly
3247 if (tcp_check_checksum) {
3248 /* We haven't turned checksum checking off; checksum it. */
3250 /* Set up the fields of the pseudo-header. */
3251 cksum_vec[0].ptr = pinfo->src.data;
3252 cksum_vec[0].len = pinfo->src.len;
3253 cksum_vec[1].ptr = pinfo->dst.data;
3254 cksum_vec[1].len = pinfo->dst.len;
3255 cksum_vec[2].ptr = (const guint8 *)&phdr;
3256 switch (pinfo->src.type) {
3259 phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
3260 cksum_vec[2].len = 4;
3264 phdr[0] = g_htonl(reported_len);
3265 phdr[1] = g_htonl(IP_PROTO_TCP);
3266 cksum_vec[2].len = 8;
3270 /* TCP runs only atop IPv4 and IPv6.... */
3271 DISSECTOR_ASSERT_NOT_REACHED();
3274 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, reported_len);
3275 cksum_vec[3].len = reported_len;
3276 computed_cksum = in_cksum(&cksum_vec[0], 4);
3277 if (computed_cksum == 0 && th_sum == 0xffff) {
3278 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3279 offset + 16, 2, th_sum,
3280 "Checksum: 0x%04x [should be 0x0000 (see RFC 1624)]", th_sum);
3282 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3283 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3284 offset + 16, 2, FALSE);
3285 PROTO_ITEM_SET_GENERATED(item);
3286 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3287 offset + 16, 2, FALSE);
3288 PROTO_ITEM_SET_GENERATED(item);
3289 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_WARN, "TCP Checksum 0xffff instead of 0x0000 (see RFC 1624)");
3291 if (check_col(pinfo->cinfo, COL_INFO))
3292 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM 0xFFFF]");
3294 /* Checksum is treated as valid on most systems, so we're willing to desegment it. */
3295 desegment_ok = TRUE;
3296 } else if (computed_cksum == 0) {
3297 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3298 offset + 16, 2, th_sum, "Checksum: 0x%04x [correct]", th_sum);
3300 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3301 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3302 offset + 16, 2, TRUE);
3303 PROTO_ITEM_SET_GENERATED(item);
3304 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3305 offset + 16, 2, FALSE);
3306 PROTO_ITEM_SET_GENERATED(item);
3308 /* Checksum is valid, so we're willing to desegment it. */
3309 desegment_ok = TRUE;
3310 } else if (th_sum == 0) {
3311 /* checksum is probably fine but checksum offload is used */
3312 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3313 offset + 16, 2, th_sum, "Checksum: 0x%04x [Checksum Offloaded]", th_sum);
3315 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3316 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3317 offset + 16, 2, FALSE);
3318 PROTO_ITEM_SET_GENERATED(item);
3319 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3320 offset + 16, 2, FALSE);
3321 PROTO_ITEM_SET_GENERATED(item);
3323 /* Checksum is (probably) valid, so we're willing to desegment it. */
3324 desegment_ok = TRUE;
3326 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3327 offset + 16, 2, th_sum,
3328 "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]", th_sum,
3329 in_cksum_shouldbe(th_sum, computed_cksum));
3331 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3332 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3333 offset + 16, 2, FALSE);
3334 PROTO_ITEM_SET_GENERATED(item);
3335 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3336 offset + 16, 2, TRUE);
3337 PROTO_ITEM_SET_GENERATED(item);
3338 expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
3340 if (check_col(pinfo->cinfo, COL_INFO))
3341 col_append_str(pinfo->cinfo, COL_INFO, " [TCP CHECKSUM INCORRECT]");
3343 /* Checksum is invalid, so we're not willing to desegment it. */
3344 desegment_ok = FALSE;
3345 pinfo->noreassembly_reason = " [incorrect TCP checksum]";
3348 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3349 offset + 16, 2, th_sum, "Checksum: 0x%04x [validation disabled]", th_sum);
3351 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3352 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3353 offset + 16, 2, FALSE);
3354 PROTO_ITEM_SET_GENERATED(item);
3355 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3356 offset + 16, 2, FALSE);
3357 PROTO_ITEM_SET_GENERATED(item);
3359 /* We didn't check the checksum, and don't care if it's valid,
3360 so we're willing to desegment it. */
3361 desegment_ok = TRUE;
3364 /* We don't have all the packet data, so we can't checksum it... */
3365 item = proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
3366 offset + 16, 2, th_sum, "Checksum: 0x%04x [unchecked, not all data available]", th_sum);
3368 checksum_tree = proto_item_add_subtree(item, ett_tcp_checksum);
3369 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_good, tvb,
3370 offset + 16, 2, FALSE);
3371 PROTO_ITEM_SET_GENERATED(item);
3372 item = proto_tree_add_boolean(checksum_tree, hf_tcp_checksum_bad, tvb,
3373 offset + 16, 2, FALSE);
3374 PROTO_ITEM_SET_GENERATED(item);
3376 /* ...and aren't willing to desegment it. */
3377 desegment_ok = FALSE;
3381 /* We're willing to desegment this. Is desegmentation enabled? */
3382 if (tcp_desegment) {
3383 /* Yes - is this segment being returned in an error packet? */
3384 if (!pinfo->in_error_pkt) {
3385 /* No - indicate that we will desegment.
3386 We do NOT want to desegment segments returned in error
3387 packets, as they're not part of a TCP connection. */
3388 pinfo->can_desegment = 2;
3393 if (tcph->th_flags & TH_URG) {
3394 th_urp = tvb_get_ntohs(tvb, offset + 18);
3395 /* Export the urgent pointer, for the benefit of protocols such as
3397 tcpinfo.urgent = TRUE;
3398 tcpinfo.urgent_pointer = th_urp;
3399 if (check_col(pinfo->cinfo, COL_INFO))
3400 col_append_fstr(pinfo->cinfo, COL_INFO, " Urg=%u", th_urp);
3401 if (tcp_tree != NULL)
3402 proto_tree_add_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, th_urp);
3404 tcpinfo.urgent = FALSE;
3406 if (tcph->th_have_seglen) {
3407 if (check_col(pinfo->cinfo, COL_INFO))
3408 col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", tcph->th_seglen);
3411 /* Decode TCP options, if any. */
3412 if (tcph->th_hlen > TCPH_MIN_LEN) {
3413 /* There's more than just the fixed-length header. Decode the
3415 optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
3416 tvb_ensure_bytes_exist(tvb, offset + 20, optlen);
3417 if (tcp_tree != NULL) {
3418 guint8 *p_options = ep_tvb_memdup(tvb, offset + 20, optlen);
3419 tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
3420 optlen, p_options, "Options: (%u bytes)", optlen);
3421 field_tree = proto_item_add_subtree(tf, ett_tcp_options);
3424 dissect_ip_tcp_options(tvb, offset + 20, optlen,
3425 tcpopts, N_TCP_OPTS, TCPOPT_EOL, pinfo, field_tree);
3428 if(!pinfo->fd->flags.visited){
3429 if((tcph->th_flags & (TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) {
3430 /* If there was window scaling in the SYN packet but none in the SYN+ACK
3431 * then we should just forget about the windowscaling completely.
3433 if(tcp_analyze_seq && tcp_relative_seq){
3434 verify_tcp_window_scaling(tcpd);
3436 /* If the SYN or the SYN+ACK offered SCPS capabilities,
3437 * validate the flow's bidirectional scps capabilities.
3438 * The or protects against broken implementations offering
3439 * SCPS capabilities on SYN+ACK even if it wasn't offered with the SYN
3441 if(tcpd && ((tcpd->rev->scps_capable) || (tcpd->fwd->scps_capable))) {
3442 verify_scps(pinfo, tf_syn, tcpd);
3447 /* Skip over header + options */
3448 offset += tcph->th_hlen;
3450 /* Check the packet length to see if there's more data
3451 (it could be an ACK-only packet) */
3452 length_remaining = tvb_length_remaining(tvb, offset);
3454 if (tcph->th_have_seglen) {
3455 if( data_out_file ) {
3456 reassemble_tcp( tcph->th_seq, /* sequence number */
3457 tcph->th_ack, /* acknowledgement number */
3458 tcph->th_seglen, /* data length */
3459 (gchar*)tvb_get_ptr(tvb, offset, length_remaining), /* data */
3460 length_remaining, /* captured data length */
3461 ( tcph->th_flags & TH_SYN ), /* is syn set? */
3469 /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
3470 if(tcp_analyze_seq){
3471 tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd);
3474 /* handle conversation timestamps */
3475 if(tcp_calculate_ts){
3476 tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
3479 tap_queue_packet(tcp_tap, pinfo, tcph);
3482 /* A FIN packet might complete reassembly so we need to explicitly
3483 * check for this here.
3485 if(tcpd && (tcph->th_flags & TH_FIN)
3486 && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ){
3487 struct tcp_multisegment_pdu *msp;
3489 /* find the most previous PDU starting before this sequence number */
3490 msp=se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq-1);
3492 fragment_data *ipfd_head;
3494 ipfd_head = fragment_add(tvb, offset, pinfo, msp->first_frame,
3496 tcph->th_seq - msp->seq,
3502 /* create a new TVB structure for desegmented data */
3503 next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen, ipfd_head->datalen);
3505 /* add this tvb as a child to the original one */
3506 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
3508 /* add desegmented data to the data source list */
3509 add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
3511 /* call the payload dissector
3512 * but make sure we don't offer desegmentation any more
3514 pinfo->can_desegment = 0;
3516 process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq, nxtseq, FALSE, tcpd);
3524 * XXX - what, if any, of this should we do if this is included in an
3525 * error packet? It might be nice to see the details of the packet
3526 * that caused the ICMP error, but it might not be nice to have the
3527 * dissector update state based on it.
3528 * Also, we probably don't want to run TCP taps on those packets.
3530 if (length_remaining != 0) {
3531 if (tcph->th_flags & TH_RST) {
3535 * 4.2.2.12 RST Segment: RFC-793 Section 3.4
3537 * A TCP SHOULD allow a received RST segment to include data.
3540 * It has been suggested that a RST segment could contain
3541 * ASCII text that encoded and explained the cause of the
3542 * RST. No standard has yet been established for such
3545 * so for segments with RST we just display the data as text.
3547 proto_tree_add_text(tcp_tree, tvb, offset, length_remaining,
3549 tvb_format_text(tvb, offset, length_remaining));
3551 dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
3552 tcph->th_sport, tcph->th_dport, tree, tcp_tree, tcpd);
3558 proto_register_tcp(void)
3560 static hf_register_info hf[] = {
3563 { "Source Port", "tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
3567 { "Destination Port", "tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
3571 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
3575 { "Sequence number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
3579 { "Next sequence number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
3583 { "Acknowledgement number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
3587 { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
3591 { "Flags", "tcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
3594 { &hf_tcp_flags_cwr,
3595 { "Congestion Window Reduced (CWR)", "tcp.flags.cwr", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_CWR,
3598 { &hf_tcp_flags_ecn,
3599 { "ECN-Echo", "tcp.flags.ecn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ECN,
3602 { &hf_tcp_flags_urg,
3603 { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_URG,
3606 { &hf_tcp_flags_ack,
3607 { "Acknowledgement", "tcp.flags.ack", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ACK,
3610 { &hf_tcp_flags_push,
3611 { "Push", "tcp.flags.push", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_PUSH,
3614 { &hf_tcp_flags_reset,
3615 { "Reset", "tcp.flags.reset", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_RST,
3618 { &hf_tcp_flags_syn,
3619 { "Syn", "tcp.flags.syn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_SYN,
3622 { &hf_tcp_flags_fin,
3623 { "Fin", "tcp.flags.fin", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_FIN,
3626 /* 32 bits so we can present some values adjusted to window scaling */
3627 { &hf_tcp_window_size,
3628 { "Window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
3632 { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
3633 "Details at: http://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL }},
3635 { &hf_tcp_checksum_good,
3636 { "Good Checksum", "tcp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3637 "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
3639 { &hf_tcp_checksum_bad,
3640 { "Bad Checksum", "tcp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3641 "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
3643 { &hf_tcp_analysis_flags,
3644 { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
3645 "This frame has some of the TCP analysis flags set", HFILL }},
3647 { &hf_tcp_analysis_retransmission,
3648 { "Retransmission", "tcp.analysis.retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
3649 "This frame is a suspected TCP retransmission", HFILL }},
3651 { &hf_tcp_analysis_fast_retransmission,
3652 { "Fast Retransmission", "tcp.analysis.fast_retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
3653 "This frame is a suspected TCP fast retransmission", HFILL }},
3655 { &hf_tcp_analysis_out_of_order,
3656 { "Out Of Order", "tcp.analysis.out_of_order", FT_NONE, BASE_NONE, NULL, 0x0,
3657 "This frame is a suspected Out-Of-Order segment", HFILL }},
3659 { &hf_tcp_analysis_reused_ports,
3660 { "TCP Port numbers reused", "tcp.analysis.reused_ports", FT_NONE, BASE_NONE, NULL, 0x0,
3661 "A new tcp session has started with previously used port numbers", HFILL }},
3663 { &hf_tcp_analysis_lost_packet,
3664 { "Previous Segment Lost", "tcp.analysis.lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
3665 "A segment before this one was lost from the capture", HFILL }},
3667 { &hf_tcp_analysis_ack_lost_packet,
3668 { "ACKed Lost Packet", "tcp.analysis.ack_lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
3669 "This frame ACKs a lost segment", HFILL }},
3671 { &hf_tcp_analysis_window_update,
3672 { "Window update", "tcp.analysis.window_update", FT_NONE, BASE_NONE, NULL, 0x0,
3673 "This frame is a tcp window update", HFILL }},
3675 { &hf_tcp_analysis_window_full,
3676 { "Window full", "tcp.analysis.window_full", FT_NONE, BASE_NONE, NULL, 0x0,
3677 "This segment has caused the allowed window to become 100% full", HFILL }},
3679 { &hf_tcp_analysis_keep_alive,
3680 { "Keep Alive", "tcp.analysis.keep_alive", FT_NONE, BASE_NONE, NULL, 0x0,
3681 "This is a keep-alive segment", HFILL }},
3683 { &hf_tcp_analysis_keep_alive_ack,
3684 { "Keep Alive ACK", "tcp.analysis.keep_alive_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3685 "This is an ACK to a keep-alive segment", HFILL }},
3687 { &hf_tcp_analysis_duplicate_ack,
3688 { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3689 "This is a duplicate ACK", HFILL }},
3691 { &hf_tcp_analysis_duplicate_ack_num,
3692 { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
3693 "This is duplicate ACK number #", HFILL }},
3695 { &hf_tcp_analysis_duplicate_ack_frame,
3696 { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3697 "This is a duplicate to the ACK in frame #", HFILL }},
3699 { &hf_tcp_continuation_to,
3700 { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3701 "This is a continuation to the PDU in frame #", HFILL }},
3703 { &hf_tcp_analysis_zero_window_probe,
3704 { "Zero Window Probe", "tcp.analysis.zero_window_probe", FT_NONE, BASE_NONE, NULL, 0x0,
3705 "This is a zero-window-probe", HFILL }},
3707 { &hf_tcp_analysis_zero_window_probe_ack,
3708 { "Zero Window Probe Ack", "tcp.analysis.zero_window_probe_ack", FT_NONE, BASE_NONE, NULL, 0x0,
3709 "This is an ACK to a zero-window-probe", HFILL }},
3711 { &hf_tcp_analysis_zero_window,
3712 { "Zero Window", "tcp.analysis.zero_window", FT_NONE, BASE_NONE, NULL, 0x0,
3713 "This is a zero-window", HFILL }},
3716 { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
3719 { &hf_tcp_analysis_acks_frame,
3720 { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3721 "Which previous segment is this an ACK for", HFILL}},
3723 { &hf_tcp_analysis_ack_rtt,
3724 { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3725 "How long time it took to ACK the segment (RTT)", HFILL}},
3727 { &hf_tcp_analysis_rto,
3728 { "The RTO for this segment was", "tcp.analysis.rto", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3729 "How long transmission was delayed before this segment was retransmitted (RTO)", HFILL}},
3731 { &hf_tcp_analysis_rto_frame,
3732 { "RTO based on delta from frame", "tcp.analysis.rto_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3733 "This is the frame we measure the RTO from", HFILL }},
3735 { &hf_tcp_urgent_pointer,
3736 { "Urgent pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
3739 { &hf_tcp_segment_overlap,
3740 { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3741 "Segment overlaps with other segments", HFILL }},
3743 { &hf_tcp_segment_overlap_conflict,
3744 { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3745 "Overlapping segments contained conflicting data", HFILL }},
3747 { &hf_tcp_segment_multiple_tails,
3748 { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3749 "Several tails were found when reassembling the pdu", HFILL }},
3751 { &hf_tcp_segment_too_long_fragment,
3752 { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3753 "Segment contained data past end of the pdu", HFILL }},
3755 { &hf_tcp_segment_error,
3756 { "Reassembling error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3757 "Reassembling error due to illegal segments", HFILL }},
3760 { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3761 "TCP Segment", HFILL }},
3764 { "Reassembled TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
3765 "TCP Segments", HFILL }},
3767 { &hf_tcp_reassembled_in,
3768 { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3769 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
3772 { "TCP Options", "tcp.options", FT_BYTES,
3773 BASE_HEX, NULL, 0x0, "TCP Options", HFILL }},
3775 { &hf_tcp_option_mss,
3776 { "TCP MSS Option", "tcp.options.mss", FT_BOOLEAN,
3777 BASE_NONE, NULL, 0x0, "TCP MSS Option", HFILL }},
3779 { &hf_tcp_option_mss_val,
3780 { "TCP MSS Option Value", "tcp.options.mss_val", FT_UINT16,
3781 BASE_DEC, NULL, 0x0, "TCP MSS Option Value", HFILL}},
3783 { &hf_tcp_option_wscale,
3784 { "TCP Window Scale Option", "tcp.options.wscale",
3786 BASE_NONE, NULL, 0x0, "TCP Window Option", HFILL}},
3788 { &hf_tcp_option_wscale_val,
3789 { "TCP Windows Scale Option Value", "tcp.options.wscale_val",
3790 FT_UINT8, BASE_DEC, NULL, 0x0, "TCP Window Scale Value",
3793 { &hf_tcp_option_sack_perm,
3794 { "TCP Sack Perm Option", "tcp.options.sack_perm",
3796 BASE_NONE, NULL, 0x0, "TCP Sack Perm Option", HFILL}},
3798 { &hf_tcp_option_sack,
3799 { "TCP Sack Option", "tcp.options.sack", FT_BOOLEAN,
3800 BASE_NONE, NULL, 0x0, "TCP Sack Option", HFILL}},
3802 { &hf_tcp_option_sack_sle,
3803 {"TCP Sack Left Edge", "tcp.options.sack_le", FT_UINT32,
3804 BASE_DEC, NULL, 0x0, "TCP Sack Left Edge", HFILL}},
3806 { &hf_tcp_option_sack_sre,
3807 {"TCP Sack Right Edge", "tcp.options.sack_re", FT_UINT32,
3808 BASE_DEC, NULL, 0x0, "TCP Sack Right Edge", HFILL}},
3810 { &hf_tcp_option_echo,
3811 { "TCP Echo Option", "tcp.options.echo", FT_BOOLEAN,
3812 BASE_NONE, NULL, 0x0, "TCP Sack Echo", HFILL}},
3814 { &hf_tcp_option_echo_reply,
3815 { "TCP Echo Reply Option", "tcp.options.echo_reply",
3817 BASE_NONE, NULL, 0x0, "TCP Echo Reply Option", HFILL}},
3819 { &hf_tcp_option_time_stamp,
3820 { "TCP Time Stamp Option", "tcp.options.time_stamp",
3822 BASE_NONE, NULL, 0x0, "TCP Time Stamp Option", HFILL}},
3824 { &hf_tcp_option_cc,
3825 { "TCP CC Option", "tcp.options.cc", FT_BOOLEAN, BASE_NONE,
3826 NULL, 0x0, "TCP CC Option", HFILL}},
3828 { &hf_tcp_option_ccnew,
3829 { "TCP CC New Option", "tcp.options.ccnew", FT_BOOLEAN,
3830 BASE_NONE, NULL, 0x0, "TCP CC New Option", HFILL}},
3832 { &hf_tcp_option_ccecho,
3833 { "TCP CC Echo Option", "tcp.options.ccecho", FT_BOOLEAN,
3834 BASE_NONE, NULL, 0x0, "TCP CC Echo Option", HFILL}},
3836 { &hf_tcp_option_md5,
3837 { "TCP MD5 Option", "tcp.options.md5", FT_BOOLEAN, BASE_NONE,
3838 NULL, 0x0, "TCP MD5 Option", HFILL}},
3840 { &hf_tcp_option_qs,
3841 { "TCP QS Option", "tcp.options.qs", FT_BOOLEAN, BASE_NONE,
3842 NULL, 0x0, "TCP QS Option", HFILL}},
3844 { &hf_tcp_option_scps,
3845 { "TCP SCPS Capabilities Option", "tcp.options.scps",
3846 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3847 "TCP SCPS Capabilities Option", HFILL}},
3849 { &hf_tcp_option_scps_vector,
3850 { "TCP SCPS Capabilities Vector", "tcp.options.scps.vector",
3851 FT_UINT8, BASE_DEC, NULL, 0x0,
3852 "TCP SCPS Capabilities Vector", HFILL}},
3854 { &hf_tcp_option_scps_binding,
3855 { "TCP SCPS Extended Binding Spacce",
3856 "tcp.options.scps.binding",
3857 FT_UINT8, BASE_DEC, NULL, 0x0,
3858 "TCP SCPS Extended Binding Space", HFILL}},
3860 { &hf_tcp_option_snack,
3861 { "TCP Selective Negative Acknowledgement Option",
3862 "tcp.options.snack",
3863 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3864 "TCP Selective Negative Acknowledgement Option", HFILL}},
3866 { &hf_tcp_option_snack_offset,
3867 { "TCP SNACK Offset", "tcp.options.snack.offset",
3868 FT_UINT16, BASE_DEC, NULL, 0x0,
3869 "TCP SNACK Offset", HFILL}},
3871 { &hf_tcp_option_snack_size,
3872 { "TCP SNACK Size", "tcp.options.snack.size",
3873 FT_UINT16, BASE_DEC, NULL, 0x0,
3874 "TCP SNACK Size", HFILL}},
3876 { &hf_tcp_option_snack_le,
3877 { "TCP SNACK Left Edge", "tcp.options.snack.le",
3878 FT_UINT16, BASE_DEC, NULL, 0x0,
3879 "TCP SNACK Left Edge", HFILL}},
3881 { &hf_tcp_option_snack_re,
3882 { "TCP SNACK Right Edge", "tcp.options.snack.re",
3883 FT_UINT16, BASE_DEC, NULL, 0x0,
3884 "TCP SNACK Right Edge", HFILL}},
3886 { &hf_tcp_scpsoption_flags_bets,
3887 { "Partial Reliability Capable (BETS)",
3888 "tcp.options.scpsflags.bets", FT_BOOLEAN, 8,
3889 TFS(&flags_set_truth), 0x80, "", HFILL }},
3891 { &hf_tcp_scpsoption_flags_snack1,
3892 { "Short Form SNACK Capable (SNACK1)",
3893 "tcp.options.scpsflags.snack1", FT_BOOLEAN, 8,
3894 TFS(&flags_set_truth), 0x40, "", HFILL }},
3896 { &hf_tcp_scpsoption_flags_snack2,
3897 { "Long Form SNACK Capable (SNACK2)",
3898 "tcp.options.scpsflags.snack2", FT_BOOLEAN, 8,
3899 TFS(&flags_set_truth), 0x20, "", HFILL }},
3901 { &hf_tcp_scpsoption_flags_compress,
3902 { "Lossless Header Compression (COMP)",
3903 "tcp.options.scpsflags.compress", FT_BOOLEAN, 8,
3904 TFS(&flags_set_truth), 0x10, "", HFILL }},
3906 { &hf_tcp_scpsoption_flags_nlts,
3907 { "Network Layer Timestamp (NLTS)",
3908 "tcp.options.scpsflags.nlts", FT_BOOLEAN, 8,
3909 TFS(&flags_set_truth), 0x8, "", HFILL }},
3911 { &hf_tcp_scpsoption_flags_resv1,
3913 "tcp.options.scpsflags.reserved1", FT_BOOLEAN, 8,
3914 TFS(&flags_set_truth), 0x4, "", HFILL }},
3916 { &hf_tcp_scpsoption_flags_resv2,
3918 "tcp.options.scpsflags.reserved2", FT_BOOLEAN, 8,
3919 TFS(&flags_set_truth), 0x2, "", HFILL }},
3921 { &hf_tcp_scpsoption_flags_resv3,
3923 "tcp.options.scpsflags.reserved3", FT_BOOLEAN, 8,
3924 TFS(&flags_set_truth), 0x1, "", HFILL }},
3927 { "Time until the last segment of this PDU", "tcp.pdu.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3928 "How long time has passed until the last frame of this PDU", HFILL}},
3931 { "PDU Size", "tcp.pdu.size", FT_UINT32, BASE_DEC, NULL, 0x0,
3932 "The size of this PDU", HFILL}},
3934 { &hf_tcp_pdu_last_frame,
3935 { "Last frame of this PDU", "tcp.pdu.last_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3936 "This is the last frame of the PDU starting in this segment", HFILL }},
3938 { &hf_tcp_ts_relative,
3939 { "Time since first frame in this TCP stream", "tcp.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3940 "Time relative to first frame in this TCP stream", HFILL}},
3943 { "Time since previous frame in this TCP stream", "tcp.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3944 "Time delta from previous frame in this TCP stream", HFILL}},
3947 static gint *ett[] = {
3951 &ett_tcp_option_sack,
3952 &ett_tcp_option_scps,
3953 &ett_tcp_option_scps_extended,
3954 &ett_tcp_analysis_faults,
3956 &ett_tcp_timestamps,
3961 module_t *tcp_module;
3963 proto_tcp = proto_register_protocol("Transmission Control Protocol",
3965 proto_register_field_array(proto_tcp, hf, array_length(hf));
3966 proto_register_subtree_array(ett, array_length(ett));
3968 /* subdissector code */
3969 subdissector_table = register_dissector_table("tcp.port",
3970 "TCP port", FT_UINT16, BASE_DEC);
3971 register_heur_dissector_list("tcp", &heur_subdissector_list);
3973 /* Register configuration preferences */
3974 tcp_module = prefs_register_protocol(proto_tcp, NULL);
3975 prefs_register_bool_preference(tcp_module, "summary_in_tree",
3976 "Show TCP summary in protocol tree",
3977 "Whether the TCP summary line should be shown in the protocol tree",
3978 &tcp_summary_in_tree);
3979 prefs_register_bool_preference(tcp_module, "check_checksum",
3980 "Validate the TCP checksum if possible",
3981 "Whether to validate the TCP checksum",
3982 &tcp_check_checksum);
3983 prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
3984 "Allow subdissector to reassemble TCP streams",
3985 "Whether subdissector can request TCP streams to be reassembled",
3987 prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
3988 "Analyze TCP sequence numbers",
3989 "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
3991 prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
3992 "Relative sequence numbers and window scaling",
3993 "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
3994 "To use this option you must also enable \"Analyze TCP sequence numbers\". "
3995 "This option will also try to track and adjust the window field according to any TCP window scaling options seen.",
3997 prefs_register_bool_preference(tcp_module, "calculate_timestamps",
3998 "Calculate conversation timestamps",
3999 "Calculate timestamps relative to the first frame and the previous frame in the tcp conversation",
4001 prefs_register_bool_preference(tcp_module, "try_heuristic_first",
4002 "Try heuristic sub-dissectors first",
4003 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
4004 &try_heuristic_first);
4006 register_init_routine(tcp_fragment_init);
4010 proto_reg_handoff_tcp(void)
4012 dissector_handle_t tcp_handle;
4014 tcp_handle = create_dissector_handle(dissect_tcp, proto_tcp);
4015 dissector_add("ip.proto", IP_PROTO_TCP, tcp_handle);
4016 data_handle = find_dissector("data");
4017 tcp_tap = register_tap("tcp");