diff options
author | Michael Mann <mmann78@netscape.net> | 2016-01-17 22:12:59 -0500 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2016-01-20 16:56:54 +0000 |
commit | a2b1f3998cb138587dd4e8b19f6e7c41f9563b8a (patch) | |
tree | 6592276d4c1e52f7d7ab24db578671b93a55426f /epan/dissectors/packet-tcp.c | |
parent | 4c330cc0e4c735a255dc325f68d3e0acbbacbae2 (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.c | 57 |
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); |