wireshark/gtk/sctp_stat.c

1467 lines
44 KiB
C

/*
* Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
*
* $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* 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 "epan/address.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
#define SCTP_ABORT_CHUNK_T_BIT 0x01
#define PARAMETER_TYPE_LENGTH 2
#define PARAMETER_LENGTH_LENGTH 2
#define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
#define PARAMETER_HEADER_OFFSET 0
#define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET
#define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
#define IPV6_ADDRESS_LENGTH 16
#define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
#define IPV4_ADDRESS_LENGTH 4
#define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
#define IPV4ADDRESS_PARAMETER_ID 0x0005
#define IPV6ADDRESS_PARAMETER_ID 0x0006
#define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
#define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
#define INIT_CHUNK_INITIAL_TSN_LENGTH 4
#define INIT_CHUNK_FIXED_PARAMTERS_LENGTH (INIT_CHUNK_INITIATE_TAG_LENGTH + \
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)
#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 )
static const value_string chunk_type_values[] = {
{ SCTP_DATA_CHUNK_ID, "DATA" },
{ SCTP_INIT_CHUNK_ID, "INIT" },
{ SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" },
{ SCTP_SACK_CHUNK_ID, "SACK" },
{ SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" },
{ SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" },
{ SCTP_ABORT_CHUNK_ID, "ABORT" },
{ SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" },
{ SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" },
{ SCTP_ERROR_CHUNK_ID, "ERROR" },
{ SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" },
{ SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" },
{ SCTP_ECNE_CHUNK_ID, "ECNE" },
{ SCTP_CWR_CHUNK_ID, "CWR" },
{ SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
{ SCTP_FORWARD_TSN_CHUNK_ID, "FORWARD TSN" },
{ SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF_ACK" },
{ SCTP_PKTDROP_CHUNK_ID, "PKTDROP" },
{ SCTP_ASCONF_CHUNK_ID, "ASCONF" },
{ SCTP_IETF_EXT, "IETF_EXTENSION" },
{ 0, NULL } };
#define FORWARD_STREAM 0
#define BACKWARD_STREAM 1
#define FORWARD_ADD_FORWARD_VTAG 2
#define BACKWARD_ADD_FORWARD_VTAG 3
#define BACKWARD_ADD_BACKWARD_VTAG 4
#define ADDRESS_FORWARD_STREAM 5
#define ADDRESS_BACKWARD_STREAM 6
#define ADDRESS_FORWARD_ADD_FORWARD_VTAG 7
#define ADDRESS_BACKWARD_ADD_FORWARD_VTAG 8
#define ADDRESS_BACKWARD_ADD_BACKWARD_VTAG 9
#define ASSOC_NOT_FOUND 10
static sctp_allassocs_info_t sctp_tapinfo_struct = {0, NULL, FALSE, NULL};
static
void free_first(gpointer data, gpointer user_data _U_)
{
g_free(data);
}
static void tsn_free(gpointer data, gpointer user_data _U_)
{
tsn_t *tsn;
tsn = (tsn_t *) data;
if (tsn->tsns != NULL)
{
g_list_foreach(tsn->tsns, free_first, NULL);
g_list_free(tsn->tsns);
tsn->tsns=NULL;
}
}
static void
reset(void *arg)
{
sctp_allassocs_info_t *tapdata = arg;
GList* list;
sctp_assoc_info_t * info;
list = g_list_first(tapdata->assoc_info_list);
while (list)
{
info = (sctp_assoc_info_t *) (list->data);
if (info->addr1 != NULL)
{
g_list_foreach(info->addr1, free_first, NULL);
g_list_free(info->addr1);
info->addr1 = NULL;
}
if (info->addr2 != NULL)
{
g_list_foreach(info->addr2,free_first, NULL);
g_list_free(info->addr2);
info->addr2 = NULL;
}
if (info->error_info_list != NULL)
{
g_list_foreach(info->error_info_list, free_first, NULL);
g_list_free(info->error_info_list);
info->error_info_list = NULL;
}
if (info->frame_numbers != NULL)
{
g_list_free(info->frame_numbers);
info->frame_numbers = NULL;
}
if (info->tsn1 != NULL)
{
g_list_foreach(info->tsn1, tsn_free, NULL);
g_list_free(info->tsn1);
info->tsn1 = NULL;
}
if (info->tsn2 != NULL)
{
g_list_foreach(info->tsn2, tsn_free, NULL);
g_list_free(info->tsn2);
info->tsn2 = NULL;
}
if (info->sack1 != NULL)
{
g_list_foreach(info->sack1, tsn_free, NULL);
g_list_free(info->sack1);
info->sack1 = NULL;
}
if (info->sack2 != NULL)
{
g_list_foreach(info->sack2, tsn_free, NULL);
g_list_free(info->sack2);
info->sack2 = NULL;
}
if (info->sort_tsn1 != NULL)
g_ptr_array_free(info->sort_tsn1, TRUE);
if (info->sort_tsn2 != NULL)
g_ptr_array_free(info->sort_tsn2, TRUE);
if (info->sort_sack1 != NULL)
g_ptr_array_free(info->sort_sack1, TRUE);
if (info->sort_sack2 != NULL)
g_ptr_array_free(info->sort_sack2, TRUE);
if (info->min_max != NULL)
{
g_slist_foreach(info->min_max, free_first, NULL);
info->min_max = NULL;
}
g_free(list->data);
list = g_list_next(list);
}
g_list_free(tapdata->assoc_info_list);
tapdata->sum_tvbs = 0;
tapdata->assoc_info_list = NULL;
}
static sctp_assoc_info_t *calc_checksum(struct _sctp_info *check_data, sctp_assoc_info_t *data)
{
gboolean ok = FALSE;
if (check_data->adler32_calculated)
{
data->n_adler32_calculated++;
if (check_data->adler32_correct)
data->n_adler32_correct++;
}
if (check_data->crc32c_calculated)
{
data->n_crc32c_calculated++;
if (check_data->crc32c_correct)
data->n_crc32c_correct++;
}
if (data->n_adler32_calculated > 0)
{
if ((float)(data->n_adler32_correct*1.0/data->n_adler32_calculated) > 0.5)
{
strcpy(data->checksum_type,"ADLER32");
data->n_checksum_errors=(data->n_adler32_calculated-data->n_adler32_correct);
ok = TRUE;
}
}
if (data->n_crc32c_calculated>0)
{
if ((float)(data->n_crc32c_correct*1.0/data->n_crc32c_calculated) > 0.5)
{
strcpy(data->checksum_type,"CRC32C");
data->n_checksum_errors=data->n_crc32c_calculated-data->n_crc32c_correct;
ok = TRUE;
}
}
if (!ok)
{
strcpy(data->checksum_type,"UNKNOWN");
data->n_checksum_errors=0;
}
return(data);
}
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(0);
if (a == NULL || b == NULL)
return(1);
/* assoc known*/
if ((a->port1 == b->port1) &&
(a->port2 == b->port2) &&
(a->verification_tag1 == b->verification_tag1) &&
((a->verification_tag1 != 0 ||
(b->verification_tag2 != 0))))
return(FORWARD_STREAM);
if ((a->port1 == b->port2) &&
(a->port2 == b->port1) &&
(a->verification_tag1 == b->verification_tag2))
return(BACKWARD_STREAM);
if ((a->port1 == b->port2) &&
(a->port2 == b->port1) &&
(a->verification_tag2 == b->verification_tag1))
return(BACKWARD_STREAM);
/*forward stream verifivation tag can be added*/
if ((a->port1 == b->port1) &&
(a->port2 == b->port2) &&
(a->verification_tag1 != 0) &&
(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) &&
(a->verification_tag1 !=0) &&
(b->verification_tag1 != 0) &&
(b->verification_tag2 == 0))
return(BACKWARD_ADD_BACKWARD_VTAG);
return(ASSOC_NOT_FOUND);
}
static gint sctp_assoc_address_cmp(gconstpointer aa, gconstpointer bb)
{
GList *srclist, *dstlist;
const struct _sctp_tmp_info* a = aa;
const struct _sctp_assoc_info* b = bb;
address *srcstore=NULL;
address *dststore=NULL;
address *src=NULL;
address *dst=NULL;
gboolean src_v4=FALSE;
gboolean src_v6=FALSE;
gboolean dst_v4=FALSE;
gboolean dst_v6=FALSE;
guint8* addr;
src = g_malloc(sizeof(address));
if (a->src.type == AT_IPv4)
{
src->type = AT_IPv4;
src->len = 4;
src_v4 = TRUE;
}
else if (a->src.type==AT_IPv6)
{
src->type = AT_IPv6;
src->len = 16;
src_v6 = TRUE;
}
addr = g_malloc(src->len);
memcpy(addr, a->src.data, src->len);
src->data = addr;
dst = g_malloc(sizeof(address));
if (a->dst.type == AT_IPv4)
{
dst->type = AT_IPv4;
dst->len = 4;
dst_v4 = TRUE;
}
else if (a->dst.type==AT_IPv6)
{
dst->type = AT_IPv6;
dst->len = 16;
dst_v6 = TRUE;
}
addr = g_malloc(dst->len);
memcpy(addr, a->dst.data, dst->len);
dst->data = addr;
srclist = g_list_first(b->addr1);
while (srclist)
{
srcstore = (address *) (srclist->data);
if (srcstore->type==AT_IPv4 && src_v4==TRUE)
{
if (*src->data==*srcstore->data && a->port1 == b->port1)
{
dstlist = g_list_first(b->addr2);
while (dstlist)
{
dststore = (address *) (dstlist->data);
if ((dststore->type==AT_IPv4 && dst_v4==TRUE) ||(dststore->type==AT_IPv6 && dst_v6==TRUE) )
{
if (*dst->data==*dststore->data && a->port2 == b->port2)
{
if ((a->verification_tag1 !=0)&& (b->verification_tag1 == 0)&& (b->verification_tag2 !=0))
return ADDRESS_FORWARD_ADD_FORWARD_VTAG;
else
return ADDRESS_FORWARD_STREAM;
}
else
dstlist=g_list_next(dstlist);
}
else
dstlist=g_list_next(dstlist);
}
srclist=g_list_next(srclist);
}
else
srclist=g_list_next(srclist);
}
else if (srcstore->type==AT_IPv6 && src_v6==TRUE)
{
if (*src->data == *srcstore->data && a->port1 == b->port1)
{
dstlist = g_list_first(b->addr2);
while (dstlist)
{
dststore = (address *) (dstlist->data);
if ((dststore->type==AT_IPv4 && dst_v4==TRUE) || (dststore->type==AT_IPv6 && dst_v6==TRUE))
{
if (*dst->data==*dststore->data && a->port2 == b->port2)
{
if ((a->verification_tag1 !=0)&& (b->verification_tag1 == 0)&& (b->verification_tag2 !=0))
return ADDRESS_FORWARD_ADD_FORWARD_VTAG;
else
return ADDRESS_FORWARD_STREAM;
}
else
dstlist=g_list_next(dstlist);
}
else
dstlist=g_list_next(dstlist);
}
srclist=g_list_next(srclist);
}
else
srclist=g_list_next(srclist);
}
else
srclist=g_list_next(srclist);
}
g_free(src);
g_free(dst);
src = g_malloc(sizeof(address));
if (a->dst.type == AT_IPv4)
{
src->type = AT_IPv4;
src->len = 4;
src_v4 = TRUE;
}
else if (a->dst.type==AT_IPv6)
{
src->type = AT_IPv6;
src->len = 16;
src_v6 = TRUE;
}
addr = g_malloc(src->len);
memcpy(addr, a->dst.data, src->len);
src->data = addr;
dst = g_malloc(sizeof(address));
if (a->src.type == AT_IPv4)
{
dst->type = AT_IPv4;
dst->len = 4;
dst_v4 = TRUE;
}
else if (a->src.type==AT_IPv6)
{
dst->type = AT_IPv6;
dst->len = 16;
dst_v6 = TRUE;
}
addr = g_malloc(dst->len);
memcpy(addr, a->src.data, dst->len);
dst->data = addr;
srclist = g_list_first(b->addr1);
while (srclist)
{
srcstore = (address *) (srclist->data);
if (srcstore->type==AT_IPv4 && src_v4==TRUE)
{
if (*src->data==*srcstore->data && a->port2 == b->port1)
{
dstlist = g_list_first(b->addr2);
while (dstlist)
{
dststore = (address *) (dstlist->data);
if ((dststore->type==AT_IPv4 && src_v4==TRUE) || (dststore->type==AT_IPv6 && src_v6==TRUE))
{
if (*dst->data==*dststore->data && a->port1 == b->port2)
{
if ((a->verification_tag1 ==b->verification_tag2)&& (b->verification_tag1 == 0))
return ADDRESS_BACKWARD_ADD_FORWARD_VTAG;
else if ((a->verification_tag1 !=0) && (b->verification_tag1 != 0)&& (b->verification_tag2 == 0))
return ADDRESS_BACKWARD_ADD_BACKWARD_VTAG;
else
return ADDRESS_BACKWARD_STREAM;
}
else
dstlist=g_list_next(dstlist);
}
else
dstlist=g_list_next(dstlist);
}
srclist=g_list_next(srclist);
}
else
srclist=g_list_next(srclist);
}
else if (srcstore->type==AT_IPv6 && src_v6==TRUE)
{
if (*src->data == *srcstore->data && a->port2 == b->port1)
{
dstlist = g_list_first(b->addr2);
while (dstlist)
{
dststore = (address *) (dstlist->data);
if ((dststore->type==AT_IPv4 && src_v4==TRUE) || (dststore->type==AT_IPv6 && src_v6==TRUE))
{
if (*dst->data==*dststore->data && a->port1 == b->port2)
{
if ((a->verification_tag1 ==b->verification_tag2)&& (b->verification_tag1 == 0))
return ADDRESS_BACKWARD_ADD_FORWARD_VTAG;
else if ((a->verification_tag1 !=0) && (b->verification_tag1 != 0)&& (b->verification_tag2 == 0))
return ADDRESS_BACKWARD_ADD_BACKWARD_VTAG;
else
return ADDRESS_BACKWARD_STREAM;
}
else
dstlist=g_list_next(dstlist);
}
else
dstlist=g_list_next(dstlist);
}
srclist=g_list_next(srclist);
}
else
srclist=g_list_next(srclist);
}
else
srclist=g_list_next(srclist);
}
g_free(src);
g_free(dst);
return ASSOC_NOT_FOUND;
}
static sctp_assoc_info_t * find_assoc(sctp_tmp_info_t * needle)
{
sctp_allassocs_info_t *assoc_info;
sctp_assoc_info_t *info = NULL;
GList* list;
guint8 cmp;
assoc_info = &sctp_tapinfo_struct;
if ((list = g_list_first(assoc_info->assoc_info_list))!=NULL)
{
while (list)
{
cmp=sctp_assoc_vtag_cmp(needle, (sctp_assoc_info_t*)(list->data));
/*if (cmp==ASSOC_NOT_FOUND)
{
cmp=sctp_assoc_address_cmp(needle, (sctp_assoc_info_t*)(list->data));
}*/
switch (cmp)
{
case FORWARD_STREAM:
info = (sctp_assoc_info_t*)(list->data);
info->direction = 1;
return info;
case BACKWARD_STREAM:
info = (sctp_assoc_info_t*)(list->data);
info->direction = 2;
return info;
case FORWARD_ADD_FORWARD_VTAG:
info = (sctp_assoc_info_t*)(list->data);
info->verification_tag1=needle->verification_tag1;
info->direction = 1;
return info;
case BACKWARD_ADD_FORWARD_VTAG:
info = (sctp_assoc_info_t*)(list->data);
info->verification_tag1=needle->verification_tag1;
info->direction = 2;
return info;
case BACKWARD_ADD_BACKWARD_VTAG:
info = (sctp_assoc_info_t*)(list->data);
info->verification_tag2=needle->verification_tag1;
info->direction = 2;
return info;
case ADDRESS_FORWARD_STREAM:
info = (sctp_assoc_info_t*)(list->data);
info->direction = 1;
info->check_address=TRUE;
return info;
case ADDRESS_BACKWARD_STREAM:
info = (sctp_assoc_info_t*)(list->data);
info->direction = 2;
info->check_address=TRUE;
return info;
case ADDRESS_FORWARD_ADD_FORWARD_VTAG:
info = (sctp_assoc_info_t*)(list->data);
info->verification_tag1=needle->verification_tag1;
info->direction = 1;
info->check_address=TRUE;
return info;
case ADDRESS_BACKWARD_ADD_FORWARD_VTAG:
info = (sctp_assoc_info_t*)(list->data);
info->verification_tag1=needle->verification_tag1;
info->direction = 2;
info->check_address=TRUE;
return info;
case ADDRESS_BACKWARD_ADD_BACKWARD_VTAG:
info = (sctp_assoc_info_t*)(list->data);
info->verification_tag2=needle->verification_tag1;
info->direction = 2;
info->check_address=TRUE;
return info;
}
list = g_list_next(list);
}
}
return NULL;
}
static sctp_assoc_info_t * add_chunk_count(address * vadd, sctp_assoc_info_t * info, guint32 direction, guint32 type)
{
GList *list;
address *v=NULL;
sctp_addr_chunk *ch=NULL;
guint8 * dat;
int i;
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))
{
ch->addr_count[type]++;
return info;
}
else
{
list = g_list_next(list);
}
}
else
list = g_list_next(list);
}
ch = g_malloc(sizeof(sctp_addr_chunk));
ch->direction = direction;
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++)
ch->addr_count[i] = 0;
ch->addr_count[type]++;
info->addr_chunk_count = g_list_append(info->addr_chunk_count, ch);
return info;
}
static sctp_assoc_info_t * add_address(address * vadd, sctp_assoc_info_t *info, guint8 direction)
{
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 (direction == 1)
info->addr1 = g_list_append(info->addr1, vadd);
else if (direction==2)
info->addr2 = g_list_append(info->addr2, vadd);
return info;
}
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;
sctp_tmp_info_t tmp_info;
sctp_assoc_info_t *info = NULL;
sctp_error_info_t *error = NULL;
char str[200];
guint16 type, length;
address *store = NULL;
tsn_t *tsn = NULL;
tsn_t *sack = NULL;
guint8 *t_s_n = NULL;
gboolean sackchunk = FALSE;
gboolean datachunk = FALSE;
guint32 max;
struct tsn_sort *tsn_s;
guint8* addr = NULL;
int i;
sctp_allassocs_info_t *assoc_info=NULL;
assoc_info = &sctp_tapinfo_struct;
sctp_info = (struct _sctp_info *) data;
max =0xFFFFFFFF;
type = sctp_info->ip_src.type;
if (type == AT_IPv4)
{
tmp_info.src.type = AT_IPv4;
tmp_info.src.len = 4;
}
else if (type == AT_IPv6)
{
tmp_info.src.type = AT_IPv6;
tmp_info.src.len = 16;
}
addr = g_malloc(tmp_info.src.len);
memcpy(addr, sctp_info->ip_src.data, tmp_info.src.len);
tmp_info.src.data = addr;
type = sctp_info->ip_dst.type;
if (type == AT_IPv4)
{
tmp_info.dst.type = AT_IPv4;
tmp_info.dst.len = 4;
}
else if (type == AT_IPv6)
{
tmp_info.dst.type = AT_IPv6;
tmp_info.dst.len = 16;
}
addr = g_malloc(tmp_info.dst.len);
memcpy(addr, sctp_info->ip_dst.data, tmp_info.dst.len);
tmp_info.dst.data = addr;
tmp_info.port1 = sctp_info->sport;
tmp_info.port2 = sctp_info->dport;
if (sctp_info->vtag_reflected)
{
tmp_info.verification_tag2 = sctp_info->verification_tag;
tmp_info.verification_tag1 = 0;
}
else
{
tmp_info.verification_tag1 = sctp_info->verification_tag;
tmp_info.verification_tag2 = 0;
}
tmp_info.n_tvbs = 0;
info = find_assoc(&tmp_info);
if (!info)
{
tmp_info.n_tvbs = sctp_info->number_of_tvbs;
sctp_tapinfo_struct.sum_tvbs+=sctp_info->number_of_tvbs;
if (sctp_info->number_of_tvbs > 0)
{
info = g_malloc(sizeof(sctp_assoc_info_t));
memset(info, 0, sizeof(sctp_assoc_info_t));
info->src.type = tmp_info.src.type;
info->src.len = tmp_info.src.len;
addr = g_malloc(tmp_info.dst.len);
memcpy(addr,(tmp_info.src.data), tmp_info.src.len);
info->src.data = addr;
info->dst.type = tmp_info.dst.type;
info->dst.len = tmp_info.dst.len;
addr = g_malloc(tmp_info.dst.len);
memcpy(addr, (tmp_info.dst.data), tmp_info.dst.len);
info->dst.data = addr;
info->port1 = tmp_info.port1;
info->port2 = tmp_info.port2;
info->verification_tag1 = tmp_info.verification_tag1;
info->verification_tag2 = tmp_info.verification_tag2;
info->n_tvbs = tmp_info.n_tvbs;
info->init = FALSE;
info->initack = FALSE;
info->direction = 0;
info = calc_checksum(sctp_info, info);
info->n_packets = 1;
info->error_info_list = NULL;
info->min_secs = 0xffffffff;
info->min_usecs = 0xffffffff;
info->max_secs = 0;
info->max_usecs = 0;
info->min_tsn2 = 0xFFFFFFFF;
info->min_tsn1 = 0xffffffff;
info->max_tsn1 = 0;
info->max_tsn2 = 0;
info->max_bytes1 = 0;
info->max_bytes2 = 0;
info->n_data_chunks = 0;
info->n_data_bytes = 0;
info->n_data_chunks_ep1 = 0;
info->n_data_bytes_ep1 = 0;
info->n_data_chunks_ep2 = 0;
info->n_data_bytes_ep2 = 0;
info->n_sack_chunks_ep1 = 0;
info->n_sack_chunks_ep2 = 0;
info->n_array_tsn1 = 0;
info->n_array_tsn2 = 0;
info->max_window1 = 0;
info->max_window2 = 0;
info->min_max = NULL;
info->sort_tsn1 = g_ptr_array_new();
info->sort_tsn2 = g_ptr_array_new();
info->sort_sack1 = g_ptr_array_new();
info->sort_sack2 = g_ptr_array_new();
for (i=0; i < NUM_CHUNKS; i++)
{
info->chunk_count[i] = 0;
info->ep1_chunk_count[i] = 0;
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))
{
tsn = g_malloc(sizeof(tsn_t));
sack = g_malloc(sizeof(tsn_t));
tsn->tsns = NULL;
sack->tsns = NULL;
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);
memcpy(addr, tmp_info.src.data, tmp_info.src.len);
tsn->src.data = addr;
addr = g_malloc(tmp_info.src.len);
memcpy(addr, tmp_info.src.data, tmp_info.src.len);
sack->src.data = addr;
sack->dst.type = tsn->dst.type = tmp_info.dst.type;
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;
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))
{
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;
}
sack->frame_number = tsn->frame_number = pinfo->fd->num;
}
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))
{
info->min_tsn1 = tvb_get_ntohl(sctp_info->tvb[0],INIT_CHUNK_INITIAL_TSN_OFFSET);
info->verification_tag2 = tvb_get_ntohl(sctp_info->tvb[0], INIT_CHUNK_INITIATE_TAG_OFFSET);
info->instream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
info->outstream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
for (chunk_number = 1; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
{
type = tvb_get_ntohs(sctp_info->tvb[chunk_number],0);
if (type == IPV4ADDRESS_PARAMETER_ID)
{
store = g_malloc(sizeof (address));
store->type = AT_IPv4;;
store->len = 4;
store->data = g_malloc(4);
tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(store->data),IPV4_ADDRESS_OFFSET, 4);
info = add_address(store, info, 1);
}
else if (type == IPV6ADDRESS_PARAMETER_ID)
{
store = g_malloc(sizeof (address));
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);
info = add_address(store, info, 1);
}
}
if (tvb_get_guint8(sctp_info->tvb[0],0) == SCTP_INIT_CHUNK_ID)
{
info->init = TRUE;
}
else
{
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));
}
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))
{
tsn = g_malloc(sizeof(tsn_t));
sack = g_malloc(sizeof(tsn_t));
tsn->tsns = NULL;
sack->tsns = NULL;
}
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);
}
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;
info->n_data_chunks++;
info->n_data_bytes+=length;
info->outstream1 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], DATA_CHUNK_TSN_OFFSET);
if (tsnumber < info->min_tsn1)
info->min_tsn1 = tsnumber;
if (tsnumber > info->max_tsn1)
{
length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
info->n_data_chunks_ep1++;
info->n_data_bytes_ep1+=length;
info->max_tsn1 = 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->offset = 0;
tsn_s->length = length-DATA_CHUNK_HEADER_LENGTH;
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)
{
tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
if (tsnumber < info->min_tsn2)
info->min_tsn2 = tsnumber;
if (tsnumber > info->max_tsn2)
info->max_tsn2 = tsnumber;
info->n_sack_chunks_ep2++;
length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
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->offset = 0;
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;
g_ptr_array_add(info->sort_sack2, tsn_s);
info->n_sack_chunks_ep2++;
}
}
}
if (info->verification_tag1 != 0 || info->verification_tag2 != 0)
{
store = g_malloc(sizeof (address));
store->type = tmp_info.src.type;
store->len = tmp_info.src.len;
addr = g_malloc(tmp_info.src.len);
memcpy(addr,(tmp_info.src.data),tmp_info.src.len);
store->data = addr;
info = add_address(store, info, 1);
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;
info = add_address(store, info, 2);
info->frame_numbers=g_list_prepend(info->frame_numbers,&(pinfo->fd->num));
if (datachunk == TRUE)
info->tsn1 = g_list_prepend(info->tsn1, tsn);
if (sackchunk == TRUE)
info->sack2 = g_list_prepend(info->sack2, sack);
sctp_tapinfo_struct.assoc_info_list = g_list_append(sctp_tapinfo_struct.assoc_info_list, info);
}
else
{
error = g_malloc(sizeof(sctp_error_info_t));
error->frame_number = pinfo->fd->num;
strcpy(str,"");
strcpy(error->chunk_info,"");
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"));
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"));
error->info_text = "INFOS";
info->error_info_list = g_list_append(info->error_info_list, error);
}
}
} /* endif (!info) */
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))
{
tsn = g_malloc(sizeof(tsn_t));
sack = g_malloc(sizeof(tsn_t));
tsn->tsns = NULL;
sack->tsns = NULL;
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);
memcpy(addr, tmp_info.src.data, tmp_info.src.len);
tsn->src.data = addr;
addr = g_malloc(tmp_info.src.len);
memcpy(addr, tmp_info.src.data, tmp_info.src.len);
sack->src.data = addr;
sack->dst.type = tsn->dst.type = tmp_info.dst.type;
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;
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))
{
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;
}
sack->frame_number = tsn->frame_number = pinfo->fd->num;
}
info->frame_numbers = g_list_prepend(info->frame_numbers,&(pinfo->fd->num));
store = g_malloc(sizeof (address));
store->type = tmp_info.src.type;
store->len = tmp_info.src.len;
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)
info = add_address(store, info, 1);
if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID) ||
((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID))
{
tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], INIT_CHUNK_INITIAL_TSN_OFFSET);
if (info->direction == 2)
{
if (tsnumber < info->min_tsn2)
info->min_tsn2 = tsnumber;
if (tsnumber > info->max_tsn2)
info->max_tsn2 = tsnumber;
info->instream2 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
info->outstream2 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
/*info->initack_dir=2;*/
info->tsn2 = g_list_prepend(info->tsn2, tsn);
}
else if (info->direction == 1)
{
if (tsnumber < info->min_tsn1)
info->min_tsn1 = tsnumber;
if (tsnumber > info->max_tsn1)
info->max_tsn1 = tsnumber;
info->instream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
info->outstream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
/*info->initack_dir=1;*/
info->tsn1 = g_list_prepend(info->tsn1, tsn);
}
info->chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
if (info->direction == 1)
info->ep1_chunk_count[tvb_get_guint8(sctp_info->tvb[0],0)]++;
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));
for (chunk_number = 1; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
{
type = tvb_get_ntohs(sctp_info->tvb[chunk_number],0);
if (type == IPV4ADDRESS_PARAMETER_ID)
{
store = g_malloc(sizeof (address));
store->type = AT_IPv4;;
store->len = 4;
store->data = g_malloc(4);
tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(store->data),IPV4_ADDRESS_OFFSET, 4);
info = add_address(store, info, info->direction);
}
else if (type == IPV6ADDRESS_PARAMETER_ID)
{
store = g_malloc(sizeof (address));
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);
info = add_address(store, info, info->direction);
}
}
if ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID)
{
info->initack = TRUE;
info->initack_dir = info->direction;
}
else
if ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID)
{
info->init = TRUE;
}
}
else
{
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))
{
sack = g_malloc(sizeof(tsn_t));
sack->tsns = NULL;
tsn = g_malloc(sizeof(tsn_t));
tsn->tsns = NULL;
}
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));
}
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);
}
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);
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;
length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
info->n_data_chunks++;
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->offset = 0;
tsn_s->length = length;
if (info->direction == 1)
{
if(tsnumber < info->min_tsn1)
info->min_tsn1 = tsnumber;
if ((info->init == TRUE || (info->initack == TRUE && info->initack_dir == 1))&& tsnumber >= info->min_tsn1 && tsnumber <= info->max_tsn1)
{
length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
info->n_data_chunks_ep1++;
info->n_data_bytes_ep1 += length;
}
if(tsnumber > info->max_tsn1)
{
info->max_tsn1 = tsnumber;
length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
info->n_data_chunks_ep1++;
info->n_data_bytes_ep1 += length;
}
if (info->init == FALSE)
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;
info->n_data_chunks_ep2++;
info->n_data_bytes_ep2+=length;
}
if(tsnumber > info->max_tsn2)
{
info->max_tsn2 = tsnumber;
length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
info->n_data_chunks_ep2++;
info->n_data_bytes_ep2+=length;
}
if (info->init == FALSE)
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)
{
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);
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->offset = 0;
tsn_s->length = tvb_get_ntohl(sctp_info->tvb[chunk_number], SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
if (info->direction == 2)
{
if(tsnumber < info->min_tsn1)
info->min_tsn1 = tsnumber;
if(tsnumber > info->max_tsn1)
info->max_tsn1 = tsnumber;
if (tsn_s->length > info->max_window1)
info->max_window1 = tsn_s->length;
g_ptr_array_add(info->sort_sack1, tsn_s);
info->n_sack_chunks_ep1++;
}
else if (info->direction == 1)
{
if(tsnumber < info->min_tsn2)
info->min_tsn2 = tsnumber;
if(tsnumber > info->max_tsn2)
info->max_tsn2 = tsnumber;
if (tsn_s->length > info->max_window2)
info->max_window2 = tsn_s->length;
g_ptr_array_add(info->sort_sack2, tsn_s);
info->n_sack_chunks_ep2++;
}
}
}
}
if (datachunk == TRUE)
{
if (info->direction == 1)
info->tsn1 = g_list_prepend(info->tsn1, tsn);
else if (info->direction == 2)
info->tsn2 = g_list_prepend(info->tsn2, tsn);
}
if (sackchunk == TRUE)
{
if (info->direction == 1)
info->sack2 = g_list_prepend(info->sack2, sack);
else if(info->direction == 2)
info->sack1 = g_list_prepend(info->sack1, sack);
}
info->n_tvbs += sctp_info->number_of_tvbs;
sctp_tapinfo_struct.sum_tvbs += sctp_info->number_of_tvbs;
info = calc_checksum(sctp_info, info);
info->n_packets++;
}
return(1);
}
/* 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)
{
if (sctp_tapinfo_struct.is_registered) {
protect_thread_critical_region();
remove_tap_listener(&sctp_tapinfo_struct);
unprotect_thread_critical_region();
sctp_tapinfo_struct.is_registered = FALSE;
}
}
void sctp_stat_scan(void)
{
if (!sctp_tapinfo_struct.is_registered)
register_tap_listener_sctp_stat();
}
const sctp_allassocs_info_t* sctp_stat_get_info(void)
{
return &sctp_tapinfo_struct;
}
static void sctp_update(void *dummy _U_)
{
if (get_stat_dlg()!=NULL)
sctp_stat_dlg_update();
}
void
register_tap_listener_sctp_stat(void)
{
GString *error_string;
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);
g_string_free(error_string, TRUE);
return;
}
sctp_tapinfo_struct.is_registered=TRUE;
}
}