aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-tcp.c')
-rw-r--r--epan/dissectors/packet-tcp.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
index 83b5ce97b2..2e70592a04 100644
--- a/epan/dissectors/packet-tcp.c
+++ b/epan/dissectors/packet-tcp.c
@@ -2525,6 +2525,8 @@ finished_fwd:
goto finished_checking_retransmission_type;
}
+ nextseq = seq+seglen;
+
gboolean precedence_count = tcp_fastrt_precedence;
do {
switch(precedence_count) {
@@ -2548,6 +2550,31 @@ finished_fwd:
tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
goto finished_checking_retransmission_type;
}
+
+ /* Look for this segment in reported SACK ranges,
+ * if not present this might very well be a FAST Retrans,
+ * when the conditions above (timing, number of retrans) are still true */
+ if( seq_not_advanced
+ && t<20000000
+ && tcpd->rev->tcp_analyze_seq_info->dupacknum>=2
+ && tcpd->rev->tcp_analyze_seq_info->num_sack_ranges > 0) {
+
+ gboolean is_sacked = FALSE;
+ int i=0;
+ while( !is_sacked && i<tcpd->rev->tcp_analyze_seq_info->num_sack_ranges ) {
+ is_sacked = ((seq >= tcpd->rev->tcp_analyze_seq_info->sack_left_edge[i++])
+ && (nextseq <= tcpd->rev->tcp_analyze_seq_info->sack_right_edge[i]));
+ }
+
+ /* fine, it's probably a Fast Retrans triggered by the SACK sender algo */
+ if(!is_sacked) {
+ if(!tcpd->ta)
+ tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);
+ tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
+ goto finished_checking_retransmission_type;
+ }
+ }
+
precedence_count=!precedence_count;
break;
@@ -5596,6 +5623,31 @@ dissect_tcpopt_sack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d
}
}
+ /* Late discovery of a 'false' Window Update in presence of SACK option,
+ * which means we are dealing with a Dup ACK rather than a Window Update.
+ * Classify accordingly by removing the UPDATE and adding the DUP flags.
+ * Mostly a copy/paste from tcp_analyze_sequence_number(), ensure consistency
+ * whenever the latter changes.
+ * see Issue #14937
+ */
+ if( tcp_analyze_seq && tcpd && tcpd->ta && tcpd->ta->flags&TCP_A_WINDOW_UPDATE ) {
+
+ /* MPTCP tolerates duplicate acks in some circumstances, see RFC 8684 4. */
+ if(tcpd->mptcp_analysis && (tcpd->mptcp_analysis->mp_operations!=tcpd->fwd->mp_operations)) {
+ /* just ignore this DUPLICATE ACK */
+ } else {
+ tcpd->fwd->tcp_analyze_seq_info->dupacknum++;
+
+ /* no initialization required of the tcpd->ta as this code would
+ * be unreachable otherwise
+ */
+ tcpd->ta->flags &= ~TCP_A_WINDOW_UPDATE;
+ tcpd->ta->flags |= TCP_A_DUPLICATE_ACK;
+ tcpd->ta->dupack_num=tcpd->fwd->tcp_analyze_seq_info->dupacknum;
+ tcpd->ta->dupack_frame=tcpd->fwd->tcp_analyze_seq_info->lastnondupack;
+ }
+ }
+
ti = proto_tree_add_item(tree, proto_tcp_option_sack, tvb, offset, -1, ENC_NA);
field_tree = proto_item_add_subtree(ti, ett_tcp_option_sack);