Fix build by #if 0 out unused de_sgsap_tmsi() function.
[obnox/wireshark/wip.git] / gtk / sctp_stat.c
index e86dd812c72ef010e12172ab423cec06ee07d59d..16359fea9ff08e6a221c10d4eaf6bffa565ff738 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
  *
  * $Id$
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
+
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
-
 #include <stdio.h>
-#include <gtk/gtk.h>
-#include "simple_dialog.h"      /* Both is used for error handling */
-#include "globals.h"
-#include "epan/packet_info.h"   /* Needed for packet_info */
-#include <epan/tap.h>           /* Needed for register_tap_listener */
-#include "dlg_utils.h"
-#include "compat_macros.h"
-#include "register.h"
 #include <string.h>
-#include "sctp_stat.h"
 #include <math.h>
+
+#include <gtk/gtk.h>
+
+#include "epan/packet_info.h"
+#include <epan/tap.h>
 #include "epan/address.h"
+#include <epan/strutil.h>
+
+#include "../simple_dialog.h"
 
-#define SCTP_HEARTBEAT_CHUNK_ID          4
-#define SCTP_HEARTBEAT_ACK_CHUNK_ID      5
-#define SCTP_ABORT_CHUNK_ID              6
-#define SCTP_SHUTDOWN_CHUNK_ID           7
-#define SCTP_SHUTDOWN_ACK_CHUNK_ID       8
-#define SCTP_ERROR_CHUNK_ID              9
-#define SCTP_COOKIE_ECHO_CHUNK_ID       10
-#define SCTP_COOKIE_ACK_CHUNK_ID        11
-#define SCTP_ECNE_CHUNK_ID              12
-#define SCTP_CWR_CHUNK_ID               13
-#define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
-#define SCTP_FORWARD_TSN_CHUNK_ID      192
-#define SCTP_ASCONF_ACK_CHUNK_ID      0x80
-#define SCTP_PKTDROP_CHUNK_ID         0X81
-#define SCTP_ASCONF_CHUNK_ID          0XC1
-#define SCTP_IETF_EXT                  255
+#include "gtk/dlg_utils.h"
+#include "gtk/sctp_stat.h"
+#include "gtk/main.h"
 
 #define SCTP_ABORT_CHUNK_T_BIT        0x01
 
                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
-                                                      INIT_CHUNK_INITIAL_TSN_LENGTH)   
+                                                      INIT_CHUNK_INITIAL_TSN_LENGTH)
 #define CHUNK_HEADER_LENGTH           (CHUNK_TYPE_LENGTH + \
                                        CHUNK_FLAGS_LENGTH + \
                                        CHUNK_LENGTH_LENGTH)
 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET  (INIT_CHUNK_INITIAL_TSN_OFFSET + \
-                                                      INIT_CHUNK_INITIAL_TSN_LENGTH ) 
+                                                      INIT_CHUNK_INITIAL_TSN_LENGTH )
 
 static const value_string chunk_type_values[] = {
   { SCTP_DATA_CHUNK_ID,              "DATA" },
@@ -114,6 +99,8 @@ static const value_string chunk_type_values[] = {
   { SCTP_PKTDROP_CHUNK_ID,           "PKTDROP" },
   { SCTP_ASCONF_CHUNK_ID,            "ASCONF" },
   { SCTP_IETF_EXT,                   "IETF_EXTENSION" },
+  { SCTP_NR_SACK_CHUNK_ID,           "NR_SACK" },
+  { SCTP_AUTH_CHUNK_ID,              "AUTH" },
   { 0,                               NULL } };
 
 
@@ -150,8 +137,8 @@ static void tsn_free(gpointer data, gpointer user_data _U_)
        }
 }
 
-static void
-reset(void *arg)
+
+static void reset(void *arg)
 {
        sctp_allassocs_info_t *tapdata = arg;
        GList* list;
@@ -264,7 +251,7 @@ static sctp_assoc_info_t *calc_checksum(struct _sctp_info *check_data, sctp_asso
        {
                if ((float)(data->n_adler32_correct*1.0/data->n_adler32_calculated) > 0.5)
                {
-                       strcpy(data->checksum_type,"ADLER32");
+                       g_strlcpy(data->checksum_type,"ADLER32",8);
                        data->n_checksum_errors=(data->n_adler32_calculated-data->n_adler32_correct);
                        ok = TRUE;
                }
@@ -274,7 +261,7 @@ static sctp_assoc_info_t *calc_checksum(struct _sctp_info *check_data, sctp_asso
        {
                if ((float)(data->n_crc32c_correct*1.0/data->n_crc32c_calculated) > 0.5)
                {
-                       strcpy(data->checksum_type,"CRC32C");
+                       g_strlcpy(data->checksum_type,"CRC32C",8);
                        data->n_checksum_errors=data->n_crc32c_calculated-data->n_crc32c_correct;
                        ok = TRUE;
                }
@@ -282,7 +269,7 @@ static sctp_assoc_info_t *calc_checksum(struct _sctp_info *check_data, sctp_asso
 
        if (!ok)
        {
-               strcpy(data->checksum_type,"UNKNOWN");
+               g_strlcpy(data->checksum_type,"UNKNOWN",8);
                data->n_checksum_errors=0;
        }
 
@@ -291,14 +278,21 @@ static sctp_assoc_info_t *calc_checksum(struct _sctp_info *check_data, sctp_asso
 }
 
 
+/* XXX: Some versions of gcc warn about "breaking strict aliasing rules"
+        for 'a' in the following (given the way this function is called).
+        As a workaround we'll define the function parameters to match
+        how this function is actually called.  */
+/*******
 static gint sctp_assoc_vtag_cmp(gconstpointer aa, gconstpointer bb)
 {
-
        const struct _sctp_assoc_info* a = aa;
        const struct _sctp_assoc_info* b = bb;
-
        if (a == b)
                return(FORWARD_STREAM);
+********/
+
+static gint sctp_assoc_vtag_cmp(const sctp_tmp_info_t *a, const sctp_assoc_info_t *b)
+{
 
        if (a == NULL || b == NULL)
                return(ASSOC_NOT_FOUND);
@@ -307,28 +301,42 @@ static gint sctp_assoc_vtag_cmp(gconstpointer aa, gconstpointer bb)
            (a->port2 == b->port2) &&
            (a->verification_tag1 == b->verification_tag1) && a->verification_tag1==0 && a->initiate_tag != 0 &&
            (a->initiate_tag != b->initiate_tag ))
-               return(ASSOC_NOT_FOUND);
+               return(ASSOC_NOT_FOUND);   /* two INITs that belong to different assocs */
 
        /* assoc known*/
        if ((a->port1 == b->port1) &&
            (a->port2 == b->port2) &&
            (a->verification_tag1 == b->verification_tag1) &&
-           ((a->verification_tag1 != 0 || 
+           ((a->verification_tag1 != 0 ||
             (b->verification_tag2 != 0))))
                return(FORWARD_STREAM);
 
+       /* ABORT, vtag reflected */
+       if ((a->port1 == b->port1) &&
+           (a->port2 == b->port2) &&
+           (a->verification_tag2 == b->verification_tag2) &&
+           (a->verification_tag1 == 0 && b->verification_tag1 != 0))
+               return(FORWARD_STREAM);
+
        if ((a->port1 == b->port2) &&
            (a->port2 == b->port1) &&
            (a->verification_tag1 == b->verification_tag2) &&
            (a->verification_tag1 != 0))
                return(BACKWARD_STREAM);
-               
+
        if ((a->port1 == b->port2) &&
            (a->port2 == b->port1) &&
            (a->verification_tag2 == b->verification_tag1) &&
            (a->verification_tag2 != 0))
                return(BACKWARD_STREAM);
 
+       /* ABORT, vtag reflected */
+       if ((a->port1 == b->port2) &&
+           (a->port2 == b->port1) &&
+           (a->verification_tag2 == b->verification_tag1) &&
+           (a->verification_tag1 == 0 && b->verification_tag2 != 0))
+               return(BACKWARD_STREAM);
+
        /*forward stream verifivation tag can be added*/
        if ((a->port1 == b->port1) &&
            (a->port2 == b->port2) &&
@@ -336,13 +344,13 @@ static gint sctp_assoc_vtag_cmp(gconstpointer aa, gconstpointer bb)
            (b->verification_tag1 == 0) &&
            (b->verification_tag2 !=0))
                return (FORWARD_ADD_FORWARD_VTAG);
-               
+
        if ((a->port1 == b->port2) &&
            (a->port2 == b->port1) &&
            (a->verification_tag1 == b->verification_tag2) &&
            (b->verification_tag1 == 0))
                return (BACKWARD_ADD_FORWARD_VTAG);
-               
+
        /*backward stream verification tag can be added */
        if ((a->port1 == b->port2) &&
            (a->port2 == b->port1) &&
@@ -397,7 +405,7 @@ static sctp_assoc_info_t * find_assoc(sctp_tmp_info_t * needle)
                                info->verification_tag2=needle->verification_tag1;
                                info->direction = 2;
                                return info;
-                       case ADDRESS_FORWARD_STREAM:    
+                       case ADDRESS_FORWARD_STREAM:
                                info = (sctp_assoc_info_t*)(list->data);
                                info->direction = 1;
                                info->check_address=TRUE;
@@ -441,17 +449,20 @@ static sctp_assoc_info_t * add_chunk_count(address * vadd, sctp_assoc_info_t * i
        guint8 * dat;
        int i;
 
-               list = g_list_first(info->addr_chunk_count);
-               
+       list = g_list_first(info->addr_chunk_count);
+
        while (list)
        {
                ch = (sctp_addr_chunk *)(list->data);
                if (ch->direction == direction)
                {
                        v = (address *) (ch->addr);
-                       if (*(vadd->data)==*(v->data))
+                       if (ADDRESSES_EQUAL(vadd, v))
                        {
-                               ch->addr_count[type]++;
+                               if (IS_SCTP_CHUNK_TYPE(type))
+                                       ch->addr_count[type]++;
+                               else
+                                       ch->addr_count[OTHER_CHUNKS_INDEX]++;
                                return info;
                        }
                        else
@@ -464,17 +475,21 @@ static sctp_assoc_info_t * add_chunk_count(address * vadd, sctp_assoc_info_t * i
        }
        ch = g_malloc(sizeof(sctp_addr_chunk));
        ch->direction = direction;
-       ch->addr = g_malloc(sizeof(address)); 
+       ch->addr = g_malloc(sizeof(address));
        ch->addr->type = vadd->type;
        ch->addr->len = vadd->len;
        dat = g_malloc(vadd->len);
        memcpy(dat, vadd->data, vadd->len);
        ch->addr->data = dat;
-       for (i=0; i<13; i++)
+       for (i=0; i < NUM_CHUNKS; i++)
                ch->addr_count[i] = 0;
-       ch->addr_count[type]++;
+
+       if (IS_SCTP_CHUNK_TYPE(type))
+               ch->addr_count[type]++;
+       else
+               ch->addr_count[OTHER_CHUNKS_INDEX]++;
+
        info->addr_chunk_count = g_list_append(info->addr_chunk_count, ch);
-       
        return info;
 }
 
@@ -482,49 +497,26 @@ static sctp_assoc_info_t * add_address(address * vadd, sctp_assoc_info_t *info,
 {
        GList *list;
        address *v=NULL;
-       
+
        if (direction == 1)
                list = g_list_first(info->addr1);
        else
                list = g_list_first(info->addr2);
-               
+
        while (list)
        {
                v = (address *) (list->data);
-               if (v->type == AT_IPv4 && vadd->type == AT_IPv4)
-               {
-                       if (*vadd->data!=*v->data)
-                       {
-                               list = g_list_next(list);
-                       }
-                       else
-                       {
-                               g_free(vadd);
-                               return info;
-                       }
-               }
-               else if (v->type == AT_IPv6 && vadd->type == AT_IPv6)
-               {
-                       if (strcmp(ip6_to_str((const struct e_in6_addr *)(vadd->data)), ip6_to_str((const struct e_in6_addr *)v->data)))
-                       {
-                               list = g_list_next(list);
-                       }
-                       else
-                       {
-                               g_free(vadd);
-                               return info;
-                       }
-               }
-               else
-               {
-                       list = g_list_next(list);
+               if (ADDRESSES_EQUAL(vadd, v)) {
+                       g_free(vadd);
+                       return info;
                }
+               list = g_list_next(list);
        }
 
        if (direction == 1)
                info->addr1 = g_list_append(info->addr1, vadd);
        else if (direction==2)
-               info->addr2 = g_list_append(info->addr2, vadd); 
+               info->addr2 = g_list_append(info->addr2, vadd);
 
        return info;
 }
@@ -533,7 +525,7 @@ static int
 packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const void *data)
 {
        struct _sctp_info *sctp_info;
-       guint32 chunk_number = 0, tsnumber;
+       guint32 chunk_number = 0, tsnumber,framenumber;
        sctp_tmp_info_t tmp_info;
        sctp_assoc_info_t *info = NULL;
        sctp_error_info_t *error = NULL;
@@ -549,6 +541,7 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
        struct tsn_sort *tsn_s;
        guint8* addr = NULL;
        int i;
+       guint8 idx = 0;
 
        sctp_allassocs_info_t *assoc_info=NULL;
        assoc_info = &sctp_tapinfo_struct;
@@ -556,6 +549,8 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
        sctp_info = (struct _sctp_info *) data;
        max =0xFFFFFFFF;
 
+       framenumber=pinfo->fd->num;
+
        type = sctp_info->ip_src.type;
 
        if (type == AT_IPv4)
@@ -568,7 +563,12 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                tmp_info.src.type = AT_IPv6;
                tmp_info.src.len  = 16;
        }
-       
+       else
+       {
+               tmp_info.src.type = AT_NONE;
+               tmp_info.src.len  = 0;
+       }
+
        addr = g_malloc(tmp_info.src.len);
        memcpy(addr, sctp_info->ip_src.data, tmp_info.src.len);
        tmp_info.src.data = addr;
@@ -585,7 +585,12 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                tmp_info.dst.type = AT_IPv6;
                tmp_info.dst.len  = 16;
        }
-       
+       else
+       {
+               tmp_info.dst.type = AT_NONE;
+               tmp_info.dst.len  = 0;
+       }
+
        addr = g_malloc(tmp_info.dst.len);
        memcpy(addr, sctp_info->ip_dst.data, tmp_info.dst.len);
        tmp_info.dst.data = addr;
@@ -680,16 +685,19 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                info->ep2_chunk_count[i] = 0;
                        }
                        info->addr_chunk_count = NULL;
-                       
+
                        if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID) ||
                            ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID) ||
                            ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) ||
-                           ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID))
+                           ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID) ||
+                           ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID))
                        {
                                tsn  = g_malloc(sizeof(tsn_t));
                                sack = g_malloc(sizeof(tsn_t));
                                tsn->tsns  = NULL;
+                               tsn->first_tsn = 0;
                                sack->tsns = NULL;
+                               sack->first_tsn = 0;
                                sack->src.type=tsn->src.type = tmp_info.src.type;
                                sack->src.len=tsn->src.len   = tmp_info.src.len;
                                addr = g_malloc(tmp_info.src.len);
@@ -709,7 +717,8 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                sack->secs=tsn->secs   = (guint32)pinfo->fd->rel_ts.secs;
                                sack->usecs=tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
                                if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) ||
-                                       ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID))
+                                   ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID) ||
+                                   ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID))
                                {
                                        if (tsn->secs < info->min_secs)
                                        {
@@ -754,11 +763,11 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                                store->type = AT_IPv6;;
                                                store->len  = 16;
                                                store->data = g_malloc(16);
-                                               tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(store->data),IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH);     
+                                               tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(store->data),IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH);
                                                info = add_address(store, info, 1);
                                        }
                                }
-                               
+
                                if (tvb_get_guint8(sctp_info->tvb[0],0) == SCTP_INIT_CHUNK_ID)
                                {
                                        info->init = TRUE;
@@ -768,36 +777,40 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                        info->initack_dir = 1;
                                        info->initack     = TRUE;
                                }
-                               info->chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
-                               info->ep1_chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
-                               info = add_chunk_count(&tmp_info.src, info, 1, tvb_get_guint8(sctp_info->tvb[0],0));
+
+                               idx = tvb_get_guint8(sctp_info->tvb[0],0);
+                               if (!IS_SCTP_CHUNK_TYPE(idx))
+                                       idx = OTHER_CHUNKS_INDEX;
+
+                               info->chunk_count[idx]++;
+                               info->ep1_chunk_count[idx]++;
+                               info = add_chunk_count(&tmp_info.src, info, 1, idx);
                        }
                        else
                        {
                                if (((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_INIT_CHUNK_ID) &&
                                    ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_INIT_ACK_CHUNK_ID) &&
                                    ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_DATA_CHUNK_ID) &&
-                                   ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_SACK_CHUNK_ID))
+                                   ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_SACK_CHUNK_ID) &&
+                                   ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_NR_SACK_CHUNK_ID))
                                {
                                        tsn  = g_malloc(sizeof(tsn_t));
                                        sack = g_malloc(sizeof(tsn_t));
                                        tsn->tsns  = NULL;
                                        sack->tsns = NULL;
+                                       tsn->first_tsn = 0;
+                                       sack->first_tsn = 0;
                                }
                                for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
                                {
-                                       if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0)) < 12)
-                                       {
-                                               info->chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
-                                               info->ep1_chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
-                                               info = add_chunk_count(&tmp_info.src, info, 1, tvb_get_guint8(sctp_info->tvb[0],0));
-                                       }
-                                       else
-                                       {
-                                               info->chunk_count[12]++;
-                                               info->ep1_chunk_count[12]++;
-                                               info = add_chunk_count(&tmp_info.src, info, 1, 12);
-                                       }
+                                       idx = tvb_get_guint8(sctp_info->tvb[0],0);
+                                       if (!IS_SCTP_CHUNK_TYPE(idx))
+                                               idx = OTHER_CHUNKS_INDEX;
+
+                                       info->chunk_count[idx]++;
+                                       info->ep1_chunk_count[idx]++;
+                                       info = add_chunk_count(&tmp_info.src, info, 1, idx);
+
                                        if (tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_DATA_CHUNK_ID)
                                        {
                                                length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
@@ -814,20 +827,39 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                                        info->n_data_bytes_ep1+=length;
                                                        info->max_tsn1 = tsnumber;
                                                }
+                                               if (tsn->first_tsn == 0)
+                                                       tsn->first_tsn = tsnumber;
                                                t_s_n = g_malloc(16);
                                                tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, 16);
                                                tsn->tsns = g_list_append(tsn->tsns, t_s_n);
                                                datachunk = TRUE;
                                                tsn_s = g_malloc(sizeof(struct tsn_sort));
                                                tsn_s->tsnumber = tsnumber;
-                                               tsn_s->secs     = tsn->secs;
-                                               tsn_s->usecs    = tsn->usecs;
+                                               tsn_s->secs     = tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
+                                               tsn_s->usecs    = tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
                                                tsn_s->offset   = 0;
+                                               tsn_s->framenumber = framenumber;
                                                tsn_s->length   = length-DATA_CHUNK_HEADER_LENGTH;
+                                               if (tsn->secs < info->min_secs)
+                                               {
+                                                       info->min_secs  = tsn->secs;
+                                                       info->min_usecs = tsn->usecs;
+                                               }
+                                               else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
+                                                       info->min_usecs = tsn->usecs;
+
+                                               if (tsn->secs > info->max_secs)
+                                               {
+                                                       info->max_secs  = tsn->secs;
+                                                       info->max_usecs = tsn->usecs;
+                                               }
+                                               else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
+                                                       info->max_usecs = tsn->usecs;
                                                g_ptr_array_add(info->sort_tsn1, tsn_s);
                                                info->n_array_tsn1++;
                                        }
-                                       if (tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_SACK_CHUNK_ID)
+                                       if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_SACK_CHUNK_ID) ||
+                                           (tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_NR_SACK_CHUNK_ID) )
                                        {
                                                tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
                                                if (tsnumber < info->min_tsn2)
@@ -836,18 +868,36 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                                        info->max_tsn2 = tsnumber;
                                                info->n_sack_chunks_ep2++;
                                                length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+                                               if (sack->first_tsn == 0)
+                                                       sack->first_tsn = tsnumber;
                                                t_s_n = g_malloc(length);
                                                tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, length);
                                                sack->tsns = g_list_append(sack->tsns, t_s_n);
                                                sackchunk = TRUE;
                                                tsn_s = g_malloc(sizeof(struct tsn_sort));
                                                tsn_s->tsnumber = tsnumber;
-                                               tsn_s->secs     = tsn->secs;
-                                               tsn_s->usecs    = tsn->usecs;
+                                               tsn_s->secs     = tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
+                                               tsn_s->usecs    = tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
                                                tsn_s->offset   = 0;
+                                               tsn_s->framenumber = framenumber;
                                                tsn_s->length   =  tvb_get_ntohl(sctp_info->tvb[chunk_number], SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
                                                if (tsn_s->length > info->max_window1)
                                                        info->max_window1 = tsn_s->length;
+                                               if (tsn->secs < info->min_secs)
+                                               {
+                                                       info->min_secs  = tsn->secs;
+                                                       info->min_usecs = tsn->usecs;
+                                               }
+                                               else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
+                                                       info->min_usecs = tsn->usecs;
+
+                                               if (tsn->secs > info->max_secs)
+                                               {
+                                                       info->max_secs  = tsn->secs;
+                                                       info->max_usecs = tsn->usecs;
+                                               }
+                                               else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
+                                                       info->max_usecs = tsn->usecs;
                                                g_ptr_array_add(info->sort_sack2, tsn_s);
                                                info->n_sack_chunks_ep2++;
                                        }
@@ -880,13 +930,13 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                        {
                                error = g_malloc(sizeof(sctp_error_info_t));
                                error->frame_number = pinfo->fd->num;
-                               strcpy(str,"");
-                               strcpy(error->chunk_info,"");
+                               str[0] = '\0';
+                               error->chunk_info[0] = '\0';
                                if ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID)
-                                       strcpy(error->chunk_info, val_to_str(tvb_get_guint8(sctp_info->tvb[0],0),chunk_type_values,"Reserved"));
+                                       g_strlcpy(error->chunk_info, val_to_str(tvb_get_guint8(sctp_info->tvb[0],0),chunk_type_values,"Reserved"), 200);
                                else
                                        for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
-                                               strcat(error->chunk_info, val_to_str(tvb_get_guint8(sctp_info->tvb[chunk_number],0),chunk_type_values,"Reserved"));
+                                               g_strlcat(error->chunk_info, val_to_str(tvb_get_guint8(sctp_info->tvb[chunk_number],0),chunk_type_values,"Reserved"), 200);
                                error->info_text = "INFOS";
                                info->error_info_list = g_list_append(info->error_info_list, error);
                        }
@@ -897,13 +947,16 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID) ||
                    ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID) ||
                    ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) ||
-                   ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID))
+                   ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID) ||
+                   ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID))
                {
 
                        tsn  = g_malloc(sizeof(tsn_t));
                        sack = g_malloc(sizeof(tsn_t));
                        tsn->tsns  = NULL;
+                       tsn->first_tsn = 0;
                        sack->tsns = NULL;
+                       sack->first_tsn = 0;
                        sack->src.type = tsn->src.type = tmp_info.src.type;
                        sack->src.len  = tsn->src.len = tmp_info.src.len;
                        addr = g_malloc(tmp_info.src.len);
@@ -916,14 +969,15 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                        sack->dst.len  = tsn->dst.len = tmp_info.dst.len;
                        addr = g_malloc(tmp_info.dst.len);
                        memcpy(addr, tmp_info.dst.data, tmp_info.dst.len);
-                       tsn->dst.data = addr;                   
+                       tsn->dst.data = addr;
                        addr = g_malloc(tmp_info.dst.len);
                        memcpy(addr, tmp_info.dst.data, tmp_info.dst.len);
                        sack->dst.data = addr;
                        sack->secs=tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
                        sack->usecs=tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
                        if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) ||
-                       ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID))
+                       ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID) ||
+                       ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID))
                        {
                                if (tsn->secs < info->min_secs)
                                {
@@ -951,19 +1005,19 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                addr = g_malloc(tmp_info.src.len);
                memcpy(addr,(tmp_info.src.data),tmp_info.src.len);
                store->data = addr;
-                       
+
                if (info->direction == 1)
                        info = add_address(store, info, 1);
                else if (info->direction == 2)
                        info = add_address(store, info, 2);
-                       
+
                store = g_malloc(sizeof (address));
                store->type = tmp_info.dst.type;
                store->len  = tmp_info.dst.len;
                addr = g_malloc(tmp_info.dst.len);
                memcpy(addr,(tmp_info.dst.data),tmp_info.dst.len);
                store->data = addr;
-               
+
                if (info->direction == 1)
                        info = add_address(store, info, 2);
                else if (info->direction == 2)
@@ -996,12 +1050,16 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                /*info->initack_dir=1;*/
                                info->tsn1 = g_list_prepend(info->tsn1, tsn);
                        }
-                       info->chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
+
+                       idx = tvb_get_guint8(sctp_info->tvb[0],0);
+                       if (!IS_SCTP_CHUNK_TYPE(idx))
+                               idx = OTHER_CHUNKS_INDEX;
+                       info->chunk_count[idx]++;
                        if (info->direction == 1)
-                               info->ep1_chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
+                               info->ep1_chunk_count[idx]++;
                        else
-                               info->ep2_chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
-                       info = add_chunk_count(&tmp_info.src, info, info->direction, tvb_get_guint8(sctp_info->tvb[0],0));
+                               info->ep2_chunk_count[idx]++;
+                       info = add_chunk_count(&tmp_info.src, info, info->direction, idx);
                        for (chunk_number = 1; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
                        {
                                type = tvb_get_ntohs(sctp_info->tvb[chunk_number],0);
@@ -1039,36 +1097,34 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                {
                        if (((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_INIT_ACK_CHUNK_ID) &&
                            ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_DATA_CHUNK_ID) &&
-                           ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_SACK_CHUNK_ID))
+                           ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_SACK_CHUNK_ID) &&
+                           ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_NR_SACK_CHUNK_ID))
                        {
                                sack = g_malloc(sizeof(tsn_t));
                                sack->tsns = NULL;
+                               sack->first_tsn = 0;
                                tsn = g_malloc(sizeof(tsn_t));
                                tsn->tsns = NULL;
+                               tsn->first_tsn = 0;
                        }
                        for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
                        {
-                               if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0)) < 12)
-                               {
-                                       info->chunk_count[tvb_get_guint8(sctp_info->tvb[chunk_number],0)]++;
-                                       if (info->direction == 1)
-                                               info->ep1_chunk_count[tvb_get_guint8(sctp_info->tvb[chunk_number],0)]++;
-                                       else
-                                               info->ep2_chunk_count[tvb_get_guint8(sctp_info->tvb[chunk_number],0)]++;
-                                       info = add_chunk_count(&tmp_info.src, info,info->direction, tvb_get_guint8(sctp_info->tvb[chunk_number],0));
-                               }
+                               idx = tvb_get_guint8(sctp_info->tvb[chunk_number],0);
+                               if (!IS_SCTP_CHUNK_TYPE(idx))
+                                       idx = OTHER_CHUNKS_INDEX;
+
+                               info->chunk_count[idx]++;
+                               if (info->direction == 1)
+                                       info->ep1_chunk_count[idx]++;
                                else
-                               {
-                                       info->chunk_count[12]++;
-                                       if (info->direction == 1)
-                                               info->ep1_chunk_count[12]++;
-                                       else
-                                               info->ep2_chunk_count[12]++;
-                                       info = add_chunk_count(&tmp_info.src, info, info->direction,12);
-                               }
+                                       info->ep2_chunk_count[idx]++;
+                               info = add_chunk_count(&tmp_info.src, info,info->direction, idx);
+
                                if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0)) == SCTP_DATA_CHUNK_ID)
                                {
                                        tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], DATA_CHUNK_TSN_OFFSET);
+                                       if (tsn->first_tsn == 0)
+                                               tsn->first_tsn = tsnumber;
                                        t_s_n = g_malloc(16);
                                        tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, 16);
                                        tsn->tsns = g_list_append(tsn->tsns, t_s_n);
@@ -1078,11 +1134,28 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                        info->n_data_bytes+=length;
                                        tsn_s = g_malloc(sizeof(struct tsn_sort));
                                        tsn_s->tsnumber = tsnumber;
-                                       tsn_s->secs  = tsn->secs;
-                                       tsn_s->usecs = tsn->usecs;
+                                       tsn_s->secs  = tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
+                                       tsn_s->usecs = tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
                                        tsn_s->offset = 0;
+                                       tsn_s->framenumber = framenumber;
                                        tsn_s->length = length;
-       
+
+                                       if (tsn->secs < info->min_secs)
+                                       {
+                                               info->min_secs  = tsn->secs;
+                                               info->min_usecs = tsn->usecs;
+                                       }
+                                       else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
+                                               info->min_usecs = tsn->usecs;
+
+                                       if (tsn->secs > info->max_secs)
+                                       {
+                                               info->max_secs  = tsn->secs;
+                                               info->max_usecs = tsn->usecs;
+                                       }
+                                       else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
+                                               info->max_usecs = tsn->usecs;
+
                                        if (info->direction == 1)
                                        {
                                                if(tsnumber < info->min_tsn1)
@@ -1104,16 +1177,16 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                                        info->outstream1 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
                                                if (info->initack == FALSE)
                                                        info->instream2 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
-       
+
                                                g_ptr_array_add(info->sort_tsn1, tsn_s);
                                                info->n_array_tsn1++;
                                        }
                                        else if (info->direction == 2)
                                        {
-       
+
                                                if(tsnumber < info->min_tsn2)
                                                        info->min_tsn2 = tsnumber;
-       
+
                                                if ((info->initack == TRUE && info->initack_dir == 2)&& tsnumber >= info->min_tsn2 && tsnumber <= info->max_tsn2)
                                                {
                                                        length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
@@ -1131,27 +1204,47 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                                        info->instream1 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
                                                if (info->initack == FALSE)
                                                        info->outstream2 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
-       
+
                                                g_ptr_array_add(info->sort_tsn2, tsn_s);
                                                info->n_array_tsn2++;
                                        }
                                }
-                               else if (tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_SACK_CHUNK_ID)
+                               else if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_SACK_CHUNK_ID) ||
+                                        (tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_NR_SACK_CHUNK_ID))
                                {
                                        tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
                                        length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+                                       if (sack->first_tsn == 0)
+                                               sack->first_tsn = tsnumber;
                                        t_s_n = g_malloc(length);
                                        tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, length);
                                        sack->tsns = g_list_append(sack->tsns, t_s_n);
                                        sackchunk = TRUE;
                                        tsn_s = g_malloc(sizeof(struct tsn_sort));
                                        tsn_s->tsnumber = tsnumber;
-                                       tsn_s->secs   = tsn->secs;
-                                       tsn_s->usecs  = tsn->usecs;
+                                       tsn_s->secs   = tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
+                                       tsn_s->usecs  = tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
                                        tsn_s->offset = 0;
+                                       tsn_s->framenumber = framenumber;
                                        tsn_s->length = tvb_get_ntohl(sctp_info->tvb[chunk_number], SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
-       
-       
+
+                                       if (tsn->secs < info->min_secs)
+                                       {
+                                               info->min_secs  = tsn->secs;
+                                               info->min_usecs = tsn->usecs;
+                                       }
+                                       else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
+                                               info->min_usecs = tsn->usecs;
+
+                                       if (tsn->secs > info->max_secs)
+                                       {
+                                               info->max_secs  = tsn->secs;
+                                               info->max_usecs = tsn->usecs;
+                                       }
+                                       else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
+                                               info->max_usecs = tsn->usecs;
+
+
                                        if (info->direction == 2)
                                        {
                                                if(tsnumber < info->min_tsn1)
@@ -1165,7 +1258,7 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                        }
                                        else if (info->direction == 1)
                                        {
-       
+
                                                if(tsnumber < info->min_tsn2)
                                                        info->min_tsn2 = tsnumber;
                                                if(tsnumber > info->max_tsn2)
@@ -1175,7 +1268,7 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
                                                g_ptr_array_add(info->sort_sack2, tsn_s);
                                                info->n_sack_chunks_ep2++;
                                        }
-                                       
+
                                }
                        }
 
@@ -1203,10 +1296,6 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v
 }
 
 
-/* XXX just copied from gtk/rpc_stat.c */
-void protect_thread_critical_region(void);
-void unprotect_thread_critical_region(void);
-
 /****************************************************************************/
 void
 remove_tap_listener_sctp_stat(void)
@@ -1245,8 +1334,8 @@ register_tap_listener_sctp_stat(void)
 
        if (!sctp_tapinfo_struct.is_registered)
        {
-               if ((error_string = register_tap_listener("sctp", &sctp_tapinfo_struct, NULL, reset, packet, sctp_update))) {
-                       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
+               if ((error_string = register_tap_listener("sctp", &sctp_tapinfo_struct, NULL, 0, reset, packet, sctp_update))) {
+                       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
                        g_string_free(error_string, TRUE);
                        return;
                }