aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-tcp.c
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2016-01-17 22:12:59 -0500
committerMichael Mann <mmann78@netscape.net>2016-01-20 16:56:54 +0000
commita2b1f3998cb138587dd4e8b19f6e7c41f9563b8a (patch)
tree6592276d4c1e52f7d7ab24db578671b93a55426f /epan/dissectors/packet-tcp.c
parent4c330cc0e4c735a255dc325f68d3e0acbbacbae2 (diff)
Better handle TCP conversations when ports are reused.
Bug: 12022 Change-Id: Icce6a8eeff7fa4171b2d706c6be578a007d151f3 Reviewed-on: https://code.wireshark.org/review/13381 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/dissectors/packet-tcp.c')
-rw-r--r--epan/dissectors/packet-tcp.c57
1 files changed, 54 insertions, 3 deletions
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
index b244ee1c97..72820f5103 100644
--- a/epan/dissectors/packet-tcp.c
+++ b/epan/dissectors/packet-tcp.c
@@ -4938,7 +4938,8 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
struct tcpinfo tcpinfo;
struct tcpheader *tcph;
proto_item *tf_syn = NULL, *tf_fin = NULL, *tf_rst = NULL, *scaled_pi;
- conversation_t *conv=NULL;
+ conversation_t *conv=NULL, *other_conv;
+ guint32 save_last_frame = 0;
struct tcp_analysis *tcpd=NULL;
struct tcp_per_packet_data_t *tcppd=NULL;
proto_item *item;
@@ -5006,8 +5007,26 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
real_window = tcph->th_win;
tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
- /* find(or create if needed) the conversation for this tcp session */
- conv=find_or_create_conversation(pinfo);
+ /* find(or create if needed) the conversation for this tcp session
+ * This is a slight deviation from find_or_create_conversation so it's
+ * done manually. This is done to save the last frame of the conversation
+ * in case a new conversation is found and the previous conversation needs
+ * to be adjusted,
+ */
+ if((conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0)) != NULL) {
+ /* Update how far the conversation reaches */
+ if (pinfo->fd->num > conv->last_frame) {
+ save_last_frame = conv->last_frame;
+ conv->last_frame = pinfo->fd->num;
+ }
+ }
+ else {
+ conv = conversation_new(pinfo->fd->num, &pinfo->src,
+ &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
tcpd=get_tcp_conversation_data(conv,pinfo);
/* If this is a SYN packet, then check if its seq-nr is different
@@ -5022,6 +5041,10 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
(tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET) &&
(tcph->th_seq!=tcpd->fwd->base_seq) ) {
if (!(pinfo->fd->flags.visited)) {
+ /* Reset the last frame seen in the conversation */
+ if (save_last_frame > 0)
+ conv->last_frame = save_last_frame;
+
conv=conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
tcpd=get_tcp_conversation_data(conv,pinfo);
}
@@ -5029,6 +5052,34 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
tcp_analyze_get_acked_struct(pinfo->fd->num, tcph->th_seq, tcph->th_ack, TRUE, tcpd);
tcpd->ta->flags|=TCP_A_REUSED_PORTS;
}
+ /* If this is a SYN/ACK packet, then check if its seq-nr is different
+ * from the base_seq of the retrieved conversation. If this is the
+ * case, try to find a conversation with the same addresses and ports
+ * and set the TA_PORTS_REUSED flag. If the seq-nr is the same as
+ * the base_seq, then do nothing so it will be marked as a retrans-
+ * mission later.
+ * XXX - Is this affected by MPTCP which can use multiple SYNs?
+ */
+ if(tcpd && ((tcph->th_flags&(TH_SYN|TH_ACK))==(TH_SYN|TH_ACK)) &&
+ (tcpd->fwd->static_flags & TCP_S_BASE_SEQ_SET) &&
+ (tcph->th_seq!=tcpd->fwd->base_seq) ) {
+ if (!(pinfo->fd->flags.visited)) {
+ /* Reset the last frame seen in the conversation */
+ if (save_last_frame > 0)
+ conv->last_frame = save_last_frame;
+ }
+
+ other_conv = find_conversation(pinfo->fd->num, &pinfo->dst, &pinfo->src, pinfo->ptype, pinfo->destport, pinfo->srcport, 0);
+ if (other_conv != NULL)
+ {
+ conv = other_conv;
+ tcpd=get_tcp_conversation_data(conv,pinfo);
+ }
+
+ if(!tcpd->ta)
+ tcp_analyze_get_acked_struct(pinfo->fd->num, tcph->th_seq, tcph->th_ack, TRUE, tcpd);
+ tcpd->ta->flags|=TCP_A_REUSED_PORTS;
+ }
if (tcpd) {
item = proto_tree_add_uint(tcp_tree, hf_tcp_stream, tvb, offset, 0, tcpd->stream);