diff options
author | Irene RĂ¼ngeler <I.Ruengeler@fh-muenster.de> | 2013-10-29 12:11:23 +0000 |
---|---|---|
committer | Irene RĂ¼ngeler <I.Ruengeler@fh-muenster.de> | 2013-10-29 12:11:23 +0000 |
commit | 6d3988ffd378867ef0c2d8e398d275ccef1a0de1 (patch) | |
tree | c6aa452602cfad633be208f5ed5d531ba09a4a69 /ui/tap-sctp-analysis.c | |
parent | 9f3740b414d8e4dd7312aa7f7d4486907106947e (diff) | |
download | wireshark-6d3988ffd378867ef0c2d8e398d275ccef1a0de1.tar.gz |
Make the packet analysis for SCTP independent from GTK and QT.
svn path=/trunk/; revision=52945
Diffstat (limited to 'ui/tap-sctp-analysis.c')
-rw-r--r-- | ui/tap-sctp-analysis.c | 1391 |
1 files changed, 1391 insertions, 0 deletions
diff --git a/ui/tap-sctp-analysis.c b/ui/tap-sctp-analysis.c new file mode 100644 index 0000000000..a45f39b51b --- /dev/null +++ b/ui/tap-sctp-analysis.c @@ -0,0 +1,1391 @@ +/* + * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de> + * + * $Id: sctp_stat.c 52814 2013-10-24 14:32:22Z tuexen $ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include "epan/packet_info.h" +#include "epan/tap.h" +#include "epan/address.h" +#include "epan/strutil.h" +#include "epan/value_string.h" +#include "ui/tap-sctp-analysis.h" + +#include "ui/simple_dialog.h" + +#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" }, + { SCTP_NR_SACK_CHUNK_ID, "NR_SACK" }, + { SCTP_AUTH_CHUNK_ID, "AUTH" }, + { 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 = (sctp_allassocs_info_t *)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) + { + g_strlcpy(data->checksum_type,"ADLER32",8); + 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) + { + g_strlcpy(data->checksum_type,"CRC32C",8); + data->n_checksum_errors=data->n_crc32c_calculated-data->n_crc32c_correct; + ok = TRUE; + } + } + + if (!ok) + { + g_strlcpy(data->checksum_type,"UNKNOWN",8); + data->n_checksum_errors=0; + } + + return(data); + +} + + +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); + + if ((a->port1 == b->port1) && + (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); /* 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 || + (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) && + (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 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_last(assoc_info->assoc_info_list))!=NULL) + { + while (list) + { + cmp=sctp_assoc_vtag_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_previous(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 (ADDRESSES_EQUAL(vadd, v)) + { + if (IS_SCTP_CHUNK_TYPE(type)) + ch->addr_count[type]++; + else + ch->addr_count[OTHER_CHUNKS_INDEX]++; + return info; + } + else + { + list = g_list_next(list); + } + } + else + list = g_list_next(list); + } + ch = (sctp_addr_chunk *)g_malloc(sizeof(sctp_addr_chunk)); + ch->direction = direction; + ch->addr = (address *)g_malloc(sizeof(address)); + ch->addr->type = vadd->type; + ch->addr->len = vadd->len; + dat = (guint8 *)g_malloc(vadd->len); + memcpy(dat, vadd->data, vadd->len); + ch->addr->data = dat; + for (i=0; i < NUM_CHUNKS; i++) + ch->addr_count[i] = 0; + + 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; +} + +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 (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); + + 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,framenumber; + sctp_tmp_info_t tmp_info; + sctp_assoc_info_t *info = NULL; + sctp_error_info_t *error = NULL; + guint16 type, length = 0; + address *store = NULL; + tsn_t *tsn = NULL; + tsn_t *sack = NULL; + guint8 *t_s_n = NULL; + gboolean sackchunk = FALSE; + gboolean datachunk = FALSE; + gboolean forwardchunk = FALSE; + struct tsn_sort *tsn_s; + guint8* addr = NULL; + int i; + guint8 idx = 0; + + sctp_info = (struct _sctp_info *) data; + + framenumber=pinfo->fd->num; + + 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; + } + else + { + tmp_info.src.type = AT_NONE; + tmp_info.src.len = 0; + } + + addr = (guint8 *)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; + } + else + { + tmp_info.dst.type = AT_NONE; + tmp_info.dst.len = 0; + } + + addr = (guint8 *)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; + if (tvb_get_guint8(sctp_info->tvb[0],0) == SCTP_INIT_CHUNK_ID) + { + tmp_info.initiate_tag = tvb_get_ntohl(sctp_info->tvb[0], 4); + } + else + { + tmp_info.initiate_tag = 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 = (sctp_assoc_info_t *)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 = (guint8 *)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 = (guint8 *)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->initiate_tag = tmp_info.initiate_tag; + info->n_tvbs = tmp_info.n_tvbs; + info->init = FALSE; + info->initack = FALSE; + info->check_address = 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->n_forward_chunks = 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) || + ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID) || + ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_FORWARD_TSN_CHUNK_ID)) + { + tsn = (tsn_t *)g_malloc(sizeof(tsn_t)); + sack = (tsn_t *)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 = (guint8 *)g_malloc(tmp_info.src.len); + memcpy(addr, tmp_info.src.data, tmp_info.src.len); + tsn->src.data = addr; + addr = (guint8 *)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 = (guint8 *)g_malloc(tmp_info.dst.len); + memcpy(addr, tmp_info.dst.data, tmp_info.dst.len); + tsn->dst.data = addr; + addr = (guint8 *)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->rel_ts.secs; + sack->usecs=tsn->usecs = (guint32)pinfo->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_NR_SACK_CHUNK_ID) || + ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_FORWARD_TSN_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 = (address *)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 = (address *)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; + } + + 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_NR_SACK_CHUNK_ID) && + ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_FORWARD_TSN_CHUNK_ID)) + { + tsn = (tsn_t *)g_malloc(sizeof(tsn_t)); + sack = (tsn_t *)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++) + { + 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)) + { + 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; + info->outstream1 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1; + } + if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_FORWARD_TSN_CHUNK_ID)) + { + forwardchunk = TRUE; + length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET); + info->n_forward_chunks++; + } + if (datachunk || forwardchunk) + { + + 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) + { + if (datachunk) + { + info->n_data_chunks_ep1++; + info->n_data_bytes_ep1+=length; + } + else + info->n_forward_chunks_ep1++; + info->max_tsn1 = tsnumber; + } + if (tsn->first_tsn == 0) + tsn->first_tsn = tsnumber; + if (datachunk) + { + t_s_n = (guint8 *)g_malloc(16); + tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, 16); + } + else + { + t_s_n = (guint8 *)g_malloc(length); + tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, length); + } + tsn->tsns = g_list_append(tsn->tsns, t_s_n); + tsn_s = (struct tsn_sort *)g_malloc(sizeof(struct tsn_sort)); + tsn_s->tsnumber = tsnumber; + tsn_s->secs = tsn->secs = (guint32)pinfo->rel_ts.secs; + tsn_s->usecs = tsn->usecs = (guint32)pinfo->rel_ts.nsecs/1000; + tsn_s->offset = 0; + tsn_s->framenumber = framenumber; + if (datachunk) + tsn_s->length = length-DATA_CHUNK_HEADER_LENGTH; + else + 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; + 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) || + (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) + info->min_tsn2 = tsnumber; + if (tsnumber > info->max_tsn2) + info->max_tsn2 = tsnumber; + length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET); + if (sack->first_tsn == 0) + sack->first_tsn = tsnumber; + t_s_n = (guint8 *)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 = (struct tsn_sort *)g_malloc(sizeof(struct tsn_sort)); + tsn_s->tsnumber = tsnumber; + tsn_s->secs = tsn->secs = (guint32)pinfo->rel_ts.secs; + tsn_s->usecs = tsn->usecs = (guint32)pinfo->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++; + } + } + } + if (info->verification_tag1 != 0 || info->verification_tag2 != 0) + { + store = (address *)g_malloc(sizeof (address)); + store->type = tmp_info.src.type; + store->len = tmp_info.src.len; + addr = (guint8 *)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 = (address *)g_malloc(sizeof (address)); + store->type = tmp_info.dst.type; + store->len = tmp_info.dst.len; + addr = (guint8 *)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 || forwardchunk) + 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 = (sctp_error_info_t *)g_malloc(sizeof(sctp_error_info_t)); + error->frame_number = pinfo->fd->num; + error->chunk_info[0] = '\0'; + if ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID) + 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++) + 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); + } + } + } /* 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) || + ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID) || + ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_FORWARD_TSN_CHUNK_ID)) + { + + tsn = (tsn_t *)g_malloc(sizeof(tsn_t)); + sack = (tsn_t *)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 = (guint8 *)g_malloc(tmp_info.src.len); + memcpy(addr, tmp_info.src.data, tmp_info.src.len); + tsn->src.data = addr; + addr = (guint8 *)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 = (guint8 *)g_malloc(tmp_info.dst.len); + memcpy(addr, tmp_info.dst.data, tmp_info.dst.len); + tsn->dst.data = addr; + addr = (guint8 *)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->rel_ts.secs; + sack->usecs=tsn->usecs = (guint32)pinfo->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_NR_SACK_CHUNK_ID) || + ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_FORWARD_TSN_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 = (address *)g_malloc(sizeof (address)); + store->type = tmp_info.src.type; + store->len = tmp_info.src.len; + addr = (guint8 *)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 = (address *)g_malloc(sizeof (address)); + store->type = tmp_info.dst.type; + store->len = tmp_info.dst.len; + addr = (guint8 *)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); + } + + 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[idx]++; + else + 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); + if (type == IPV4ADDRESS_PARAMETER_ID) + { + store = (address *)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 = (address *)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) && + ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_NR_SACK_CHUNK_ID) && + ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_FORWARD_TSN_CHUNK_ID)) + { + sack = (tsn_t *)g_malloc(sizeof(tsn_t)); + sack->tsns = NULL; + sack->first_tsn = 0; + tsn = (tsn_t *)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++) + { + 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->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)) + datachunk = TRUE; + if (((tvb_get_guint8(sctp_info->tvb[chunk_number],0)) == SCTP_FORWARD_TSN_CHUNK_ID)) + forwardchunk = TRUE; + if (datachunk || forwardchunk) + { + tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], DATA_CHUNK_TSN_OFFSET); + if (tsn->first_tsn == 0) + tsn->first_tsn = tsnumber; + if (datachunk) + { + t_s_n = (guint8 *)g_malloc(16); + tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, 16); + 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; + } + else + { + length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET); + t_s_n = (guint8 *)g_malloc(length); + tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, length); + info->n_forward_chunks++; + } + tsn->tsns = g_list_append(tsn->tsns, t_s_n); + + tsn_s = (struct tsn_sort *)g_malloc(sizeof(struct tsn_sort)); + tsn_s->tsnumber = tsnumber; + tsn_s->secs = tsn->secs = (guint32)pinfo->rel_ts.secs; + tsn_s->usecs = tsn->usecs = (guint32)pinfo->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) + info->min_tsn1 = tsnumber; + if ((info->init == TRUE || (info->initack == TRUE && info->initack_dir == 1))&& tsnumber >= info->min_tsn1 && tsnumber <= info->max_tsn1) + { + if (datachunk) + { + info->n_data_chunks_ep1++; + info->n_data_bytes_ep1 += length; + } + else if (forwardchunk) + { + info->n_forward_chunks_ep1++; + } + } + if(tsnumber > info->max_tsn1) + { + info->max_tsn1 = tsnumber; + if (datachunk) + { + info->n_data_chunks_ep1++; + info->n_data_bytes_ep1 += length; + } + else if (forwardchunk) + { + info->n_forward_chunks_ep1++; + } + } + if (datachunk) + { + 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) + { + if (datachunk) + { + 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; + } + else if (forwardchunk) + { + info->n_forward_chunks_ep2++; + } + } + if(tsnumber > info->max_tsn2) + { + info->max_tsn2 = tsnumber; + if (datachunk) + { + 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; + } + else if (forwardchunk) + { + info->n_forward_chunks_ep2++; + } + } + if (datachunk) + { + 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) || + (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 = (guint8 *)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 = (struct tsn_sort *)g_malloc(sizeof(struct tsn_sort)); + tsn_s->tsnumber = tsnumber; + tsn_s->secs = tsn->secs = (guint32)pinfo->rel_ts.secs; + tsn_s->usecs = tsn->usecs = (guint32)pinfo->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) + 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 || forwardchunk) + { + 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); +} + + +/****************************************************************************/ +void +remove_tap_listener_sctp_stat(void) +{ + if (sctp_tapinfo_struct.is_registered) { + remove_tap_listener(&sctp_tapinfo_struct); + 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, 0, reset, packet, NULL))) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str); + g_string_free(error_string, TRUE); + return; + } + sctp_tapinfo_struct.is_registered=TRUE; + } +} |