[Reassembly] Fix a reassembly case where the two fragments are in the same
authorAndersBroman <anders.broman@ericsson.com>
Tue, 17 Mar 2015 11:59:27 +0000 (12:59 +0100)
committerAnders Broman <a.broman58@gmail.com>
Wed, 18 Mar 2015 05:32:06 +0000 (05:32 +0000)
frame
but in different SCTP DATA chunks, whitout the patch the message is
reassembled in both chunks leading to duplicated upper layer PDU:s in the
frame.

Change-Id: Ie31142c38c728018178947544b571622447d8e8f
Reviewed-on: https://code.wireshark.org/review/7716
Reviewed-by: Anders Broman <a.broman58@gmail.com>
epan/reassemble.c
epan/reassemble.h

index a10ff209cbf489d117ca9771f87c3ab50015411b..c7bb6a51b33d5e4b867b95afbac9a8fb29e7f915 100644 (file)
@@ -819,6 +819,7 @@ fragment_reassembled(reassembly_table *table, fragment_head *fd_head,
        }
        fd_head->flags |= FD_DEFRAGMENTED;
        fd_head->reassembled_in = pinfo->fd->num;
+       fd_head->reas_in_layer_num = pinfo->curr_layer_num;
 }
 
 static void
@@ -909,6 +910,7 @@ fragment_add_work(fragment_head *fd_head, tvbuff_t *tvb, const int offset,
                                fd_head->flags &= (~FD_TOOLONGFRAGMENT) & (~FD_MULTIPLETAILS);
                                fd_head->datalen=0;
                                fd_head->reassembled_in=0;
+                               fd_head->reas_in_layer_num = 0;
                        } else {
                                /*
                                 * No.  Bail out since we have no idea what to
@@ -1187,6 +1189,7 @@ fragment_add_work(fragment_head *fd_head, tvbuff_t *tvb, const int offset,
           allows us to skip any trailing fragments */
        fd_head->flags |= FD_DEFRAGMENTED;
        fd_head->reassembled_in=pinfo->fd->num;
+       fd_head->reas_in_layer_num = pinfo->curr_layer_num;
 
        /* we don't throw until here to avoid leaking old_data and others */
        if (fd_head->error) {
@@ -1538,6 +1541,7 @@ fragment_defragment_and_free (fragment_head *fd_head, const packet_info *pinfo)
         */
        fd_head->flags |= FD_DEFRAGMENTED;
        fd_head->reassembled_in=pinfo->fd->num;
+       fd_head->reas_in_layer_num = pinfo->curr_layer_num;
 }
 
 /*
@@ -1595,6 +1599,7 @@ fragment_add_seq_work(fragment_head *fd_head, tvbuff_t *tvb, const int offset,
                fd_head->flags &= (~FD_TOOLONGFRAGMENT) & (~FD_MULTIPLETAILS);
                fd_head->datalen=0;
                fd_head->reassembled_in=0;
+               fd_head->reas_in_layer_num = 0;
        }
 
 
@@ -1843,6 +1848,7 @@ fragment_add_seq_common(reassembly_table *table, tvbuff_t *tvb,
                        if (orig_keyp != NULL)
                                *orig_keyp = NULL;
                        fd_head->reassembled_in=pinfo->fd->num;
+                       fd_head->reas_in_layer_num = pinfo->curr_layer_num;
                        return fd_head;
                }
 
@@ -2088,6 +2094,7 @@ fragment_start_seq_check(reassembly_table *table, const packet_info *pinfo,
                fd_head->flags = FD_BLOCKSEQUENCE|FD_DATALEN_SET;
                fd_head->tvb_data = NULL;
                fd_head->reassembled_in = 0;
+               fd_head->reas_in_layer_num = 0;
                fd_head->error = NULL;
 
                insert_fd_head(table, fd_head, pinfo, id, data);
@@ -2167,7 +2174,7 @@ process_reassembled_data(tvbuff_t *tvb, const int offset, packet_info *pinfo,
        gboolean update_col_info;
        proto_item *frag_tree_item;
 
-       if (fd_head != NULL && pinfo->fd->num == fd_head->reassembled_in) {
+       if (fd_head != NULL && pinfo->fd->num == fd_head->reassembled_in && pinfo->curr_layer_num == fd_head->reas_in_layer_num) {
                /*
                 * OK, we've reassembled this.
                 * Is this something that's been reassembled from more
index 75991a1a784bdb9e571de787d80353fafaaea2af..f2980573dc6d3ca9227e40379e0964cc44331d6c 100644 (file)
 
 typedef struct _fragment_item {
        struct _fragment_item *next;
-       guint32 frame;  /* XXX - does this apply to reassembly heads? */
-       guint32 offset; /* XXX - does this apply to reassembly heads? */
-       guint32 len;    /* XXX - does this apply to reassembly heads? */
-       guint32 fragment_nr_offset; /* offset for frame numbering, for sequences, where the
-                                    * provided fragment number of the first fragment does
-                                    * not start with 0
-                                    * XXX - does this apply only to reassembly heads? */
-       guint32 datalen; /* Only valid in first item of list and when
-                          * flags&FD_DATALEN_SET is set;
-                          * number of bytes or (if flags&FD_BLOCKSEQUENCE set)
-                          * segments in the datagram */
-       guint32 reassembled_in; /* frame where this PDU was reassembled,
-                                  only valid in the first item of the list
-                                  and when FD_DEFRAGMENTED is set*/
-       guint32 flags;  /* XXX - do some of these apply only to reassembly
-                          heads and others only to fragments within
-                          a reassembly? */
+       guint32 frame;                                  /* XXX - does this apply to reassembly heads? */
+       guint32 offset;                                 /* XXX - does this apply to reassembly heads? */
+       guint32 len;                                    /* XXX - does this apply to reassembly heads? */
+       guint32 fragment_nr_offset;             /**< offset for frame numbering, for sequences, where the
+                                                                        * provided fragment number of the first fragment does
+                                                                        * not start with 0
+                                                                        * XXX - does this apply only to reassembly heads? */
+       guint32 datalen;                                /**< Only valid in first item of list and when
+                                                                        * flags&FD_DATALEN_SET is set;
+                                                                        * number of bytes or (if flags&FD_BLOCKSEQUENCE set)
+                                                                        * segments in the datagram */
+       guint32 reassembled_in;                 /**< frame where this PDU was reassembled,
+                                                                                only valid in the first item of the list
+                                                                                and when FD_DEFRAGMENTED is set*/
+       guint8 reas_in_layer_num;               /**< The current "depth" or layer number in the current frame where reassembly was completed.
+                                                                        * Example: in SCTP there can be several data chunks and we want the reassemblied tvb for the final
+                                                                        * segment only.
+                                                                        */
+       guint32 flags;                                  /**< XXX - do some of these apply only to reassembly
+                                                                                heads and others only to fragments within
+                                                                                a reassembly? */
        tvbuff_t *tvb_data;
-
-       /*
+       /**
         * Null if the reassembly had no error; non-null if it had
         * an error, in which case it's the string for the error.
         *