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.c81
1 files changed, 69 insertions, 12 deletions
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
index e081266f80..dcb8e2bcd0 100644
--- a/epan/dissectors/packet-tcp.c
+++ b/epan/dissectors/packet-tcp.c
@@ -246,6 +246,7 @@ get_tcp_conversation_data(packet_info *pinfo)
tcpd->flow1.nextseqframe=0;
tcpd->flow1.window=0;
tcpd->flow1.win_scale=-1;
+ tcpd->flow1.flags=0;
tcpd->flow1.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
tcpd->flow2.segments=NULL;
tcpd->flow2.base_seq=0;
@@ -259,6 +260,7 @@ get_tcp_conversation_data(packet_info *pinfo)
tcpd->flow2.nextseqframe=0;
tcpd->flow2.window=0;
tcpd->flow2.win_scale=-1;
+ tcpd->flow2.flags=0;
tcpd->flow2.multisegment_pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_multisegment_pdus");
tcpd->acked_table=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "tcp_analyze_acked_table");
@@ -1291,6 +1293,16 @@ again:
}
if (must_desegment) {
+ /* If the dissector requested "reassemble until FIN"
+ * just set this flag for the flow and let reassembly
+ * proceed at normal. We will check/pick up these
+ * reassembled PDUs later down in dissect_tcp() when checking
+ * for the FIN flag.
+ */
+ if(pinfo->desegment_len==DESEGMENT_UNTIL_FIN){
+ tcpd->fwd->flags|=TCP_FLOW_REASSEMBLE_UNTIL_FIN;
+ }
+
/*
* The sequence number at which the stuff to be desegmented
* starts is the sequence number of the byte at an offset
@@ -1303,19 +1315,18 @@ again:
*/
deseg_seq = seq + (deseg_offset - offset);
- if ((nxtseq - deseg_seq) <= 1024*1024) {
- if(!pinfo->fd->flags.visited){
- msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
- nxtseq + pinfo->desegment_len, tcpd);
-
- /* add this segment as the first one for this new pdu */
- fragment_add(tvb, deseg_offset, pinfo, msp->first_frame,
- tcp_fragment_table,
- 0,
- nxtseq - deseg_seq,
- LT_SEQ(nxtseq, msp->nxtpdu));
+ if( ((nxtseq - deseg_seq) <= 1024*1024)
+ && (!pinfo->fd->flags.visited) ){
+ msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
+ nxtseq + pinfo->desegment_len, tcpd);
+
+ /* add this segment as the first one for this new pdu */
+ fragment_add(tvb, deseg_offset, pinfo, msp->first_frame,
+ tcp_fragment_table,
+ 0,
+ nxtseq - deseg_seq,
+ LT_SEQ(nxtseq, msp->nxtpdu));
}
- }
}
if (!called_dissector || pinfo->desegment_len != 0) {
@@ -2465,6 +2476,52 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
tap_queue_packet(tcp_tap, pinfo, tcph);
+
+ /* A FIN packet might complete reassembly so we need to explicitely
+ * check for this here.
+ * If this segment completes reassembly we add the FIN as a final dummy
+ * byte to the reassembled PDU and check if reassembly completed successfully
+ */
+ if( (tcph->th_flags & TH_FIN)
+ && (tcpd->fwd->flags&TCP_FLOW_REASSEMBLE_UNTIL_FIN) ){
+ struct tcp_multisegment_pdu *msp;
+
+ /* find the most previous PDU starting before this sequence number */
+ msp=se_tree_lookup32_le(tcpd->fwd->multisegment_pdus, tcph->th_seq-1);
+ if(msp){
+ fragment_data *ipfd_head;
+
+ ipfd_head = fragment_add(tvb, offset-1, pinfo, msp->first_frame,
+ tcp_fragment_table,
+ tcph->th_seq - msp->seq,
+ 1,
+ FALSE );
+ if(ipfd_head){
+ tvbuff_t *next_tvb;
+
+ /* create a new TVB structure for desegmented data
+ * datalen-1 to strip the dummy FIN byte off
+ */
+ next_tvb = tvb_new_real_data(ipfd_head->data, ipfd_head->datalen-1, ipfd_head->datalen-1);
+
+ /* add this tvb as a child to the original one */
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* add desegmented data to the data source list */
+ add_new_data_source(pinfo, next_tvb, "Reassembled TCP");
+
+ /* call the payload dissector
+ * but make sure we dont offer desegmentation any more
+ */
+ pinfo->can_desegment = 0;
+
+ process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq, nxtseq, FALSE, tcpd);
+
+ return;
+ }
+ }
+ }
+
/*
* XXX - what, if any, of this should we do if this is included in an
* error packet? It might be nice to see the details of the packet