protect_thread_critical_region, unprotect_thread_critical_region are no-ops, cleanup...
[metze/wireshark/wip.git] / ui / gtk / sctp_stat.c
1 /*
2  * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <math.h>
29
30 #include <gtk/gtk.h>
31
32 #include "epan/packet_info.h"
33 #include <epan/tap.h>
34 #include "epan/address.h"
35 #include <epan/strutil.h>
36
37 #include "ui/simple_dialog.h"
38
39 #include "ui/gtk/dlg_utils.h"
40 #include "ui/gtk/sctp_stat.h"
41 #include "ui/gtk/main.h"
42
43 #define SCTP_ABORT_CHUNK_T_BIT        0x01
44
45 #define PARAMETER_TYPE_LENGTH            2
46 #define PARAMETER_LENGTH_LENGTH          2
47 #define PARAMETER_HEADER_LENGTH          (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
48
49 #define PARAMETER_HEADER_OFFSET          0
50 #define PARAMETER_TYPE_OFFSET            PARAMETER_HEADER_OFFSET
51 #define PARAMETER_LENGTH_OFFSET          (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
52 #define PARAMETER_VALUE_OFFSET           (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
53
54 #define IPV6_ADDRESS_LENGTH 16
55 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
56 #define IPV4_ADDRESS_LENGTH 4
57 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
58 #define IPV4ADDRESS_PARAMETER_ID             0x0005
59 #define IPV6ADDRESS_PARAMETER_ID             0x0006
60
61 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH    4
62 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
63 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
64 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
65                                                  SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
66
67 #define INIT_CHUNK_INITIAL_TSN_LENGTH                4
68 #define INIT_CHUNK_FIXED_PARAMTERS_LENGTH            (INIT_CHUNK_INITIATE_TAG_LENGTH + \
69                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
70                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
71                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
72                                                       INIT_CHUNK_INITIAL_TSN_LENGTH)
73 #define CHUNK_HEADER_LENGTH           (CHUNK_TYPE_LENGTH + \
74                                        CHUNK_FLAGS_LENGTH + \
75                                        CHUNK_LENGTH_LENGTH)
76 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET  (INIT_CHUNK_INITIAL_TSN_OFFSET + \
77                                                       INIT_CHUNK_INITIAL_TSN_LENGTH )
78
79 static const value_string chunk_type_values[] = {
80   { SCTP_DATA_CHUNK_ID,              "DATA" },
81   { SCTP_INIT_CHUNK_ID,              "INIT" },
82   { SCTP_INIT_ACK_CHUNK_ID,          "INIT_ACK" },
83   { SCTP_SACK_CHUNK_ID,              "SACK" },
84   { SCTP_HEARTBEAT_CHUNK_ID,         "HEARTBEAT" },
85   { SCTP_HEARTBEAT_ACK_CHUNK_ID,     "HEARTBEAT_ACK" },
86   { SCTP_ABORT_CHUNK_ID,             "ABORT" },
87   { SCTP_SHUTDOWN_CHUNK_ID,          "SHUTDOWN" },
88   { SCTP_SHUTDOWN_ACK_CHUNK_ID,      "SHUTDOWN_ACK" },
89   { SCTP_ERROR_CHUNK_ID,             "ERROR" },
90   { SCTP_COOKIE_ECHO_CHUNK_ID,       "COOKIE_ECHO" },
91   { SCTP_COOKIE_ACK_CHUNK_ID,        "COOKIE_ACK" },
92   { SCTP_ECNE_CHUNK_ID,              "ECNE" },
93   { SCTP_CWR_CHUNK_ID,               "CWR" },
94   { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
95   { SCTP_FORWARD_TSN_CHUNK_ID,       "FORWARD TSN" },
96   { SCTP_ASCONF_ACK_CHUNK_ID,        "ASCONF_ACK" },
97   { SCTP_PKTDROP_CHUNK_ID,           "PKTDROP" },
98   { SCTP_ASCONF_CHUNK_ID,            "ASCONF" },
99   { SCTP_IETF_EXT,                   "IETF_EXTENSION" },
100   { SCTP_NR_SACK_CHUNK_ID,           "NR_SACK" },
101   { SCTP_AUTH_CHUNK_ID,              "AUTH" },
102   { 0,                               NULL } };
103
104
105 #define FORWARD_STREAM                     0
106 #define BACKWARD_STREAM                    1
107 #define FORWARD_ADD_FORWARD_VTAG           2
108 #define BACKWARD_ADD_FORWARD_VTAG          3
109 #define BACKWARD_ADD_BACKWARD_VTAG         4
110 #define ADDRESS_FORWARD_STREAM             5
111 #define ADDRESS_BACKWARD_STREAM            6
112 #define ADDRESS_FORWARD_ADD_FORWARD_VTAG   7
113 #define ADDRESS_BACKWARD_ADD_FORWARD_VTAG  8
114 #define ADDRESS_BACKWARD_ADD_BACKWARD_VTAG 9
115 #define ASSOC_NOT_FOUND                    10
116
117 static sctp_allassocs_info_t sctp_tapinfo_struct = {0, NULL, FALSE, NULL};
118
119 static
120 void free_first(gpointer data, gpointer user_data _U_)
121 {
122         g_free(data);
123 }
124
125 static void tsn_free(gpointer data, gpointer user_data _U_)
126 {
127         tsn_t *tsn;
128
129         tsn = (tsn_t *) data;
130         if (tsn->tsns != NULL)
131         {
132                 g_list_foreach(tsn->tsns, free_first, NULL);
133                 g_list_free(tsn->tsns);
134                 tsn->tsns=NULL;
135         }
136 }
137
138
139 static void reset(void *arg)
140 {
141         sctp_allassocs_info_t *tapdata = arg;
142         GList* list;
143         sctp_assoc_info_t * info;
144
145         list = g_list_first(tapdata->assoc_info_list);
146         while (list)
147         {
148                 info = (sctp_assoc_info_t *) (list->data);
149
150                 if (info->addr1 != NULL)
151                 {
152                         g_list_foreach(info->addr1, free_first, NULL);
153                         g_list_free(info->addr1);
154                         info->addr1 = NULL;
155                 }
156
157                 if (info->addr2 != NULL)
158                 {
159                         g_list_foreach(info->addr2,free_first, NULL);
160                         g_list_free(info->addr2);
161                         info->addr2 = NULL;
162                 }
163
164                 if (info->error_info_list != NULL)
165                 {
166                         g_list_foreach(info->error_info_list, free_first, NULL);
167                         g_list_free(info->error_info_list);
168                         info->error_info_list = NULL;
169                 }
170
171                 if (info->frame_numbers != NULL)
172                 {
173                         g_list_free(info->frame_numbers);
174                         info->frame_numbers = NULL;
175                 }
176
177                 if (info->tsn1 != NULL)
178                 {
179                         g_list_foreach(info->tsn1, tsn_free, NULL);
180                         g_list_free(info->tsn1);
181                         info->tsn1 = NULL;
182                 }
183
184                 if (info->tsn2 != NULL)
185                 {
186                         g_list_foreach(info->tsn2, tsn_free, NULL);
187                         g_list_free(info->tsn2);
188                         info->tsn2 = NULL;
189                 }
190
191                 if (info->sack1 != NULL)
192                 {
193                         g_list_foreach(info->sack1, tsn_free, NULL);
194                         g_list_free(info->sack1);
195                         info->sack1 = NULL;
196                 }
197
198                 if (info->sack2 != NULL)
199                 {
200                         g_list_foreach(info->sack2, tsn_free, NULL);
201                         g_list_free(info->sack2);
202                         info->sack2 = NULL;
203                 }
204
205                 if (info->sort_tsn1 != NULL)
206                         g_ptr_array_free(info->sort_tsn1, TRUE);
207
208                 if (info->sort_tsn2 != NULL)
209                         g_ptr_array_free(info->sort_tsn2, TRUE);
210
211                 if (info->sort_sack1 != NULL)
212                         g_ptr_array_free(info->sort_sack1, TRUE);
213
214                 if (info->sort_sack2 != NULL)
215                         g_ptr_array_free(info->sort_sack2, TRUE);
216
217                 if (info->min_max != NULL)
218                 {
219                         g_slist_foreach(info->min_max, free_first, NULL);
220                         info->min_max = NULL;
221                 }
222
223                 g_free(list->data);
224                 list = g_list_next(list);
225         }
226         g_list_free(tapdata->assoc_info_list);
227         tapdata->sum_tvbs = 0;
228         tapdata->assoc_info_list = NULL;
229 }
230
231
232 static sctp_assoc_info_t *calc_checksum(struct _sctp_info *check_data, sctp_assoc_info_t *data)
233 {
234         gboolean ok = FALSE;
235
236         if (check_data->adler32_calculated)
237         {
238                 data->n_adler32_calculated++;
239                 if (check_data->adler32_correct)
240                         data->n_adler32_correct++;
241         }
242         if (check_data->crc32c_calculated)
243         {
244                 data->n_crc32c_calculated++;
245                 if (check_data->crc32c_correct)
246                         data->n_crc32c_correct++;
247         }
248         if (data->n_adler32_calculated > 0)
249         {
250                 if ((float)(data->n_adler32_correct*1.0/data->n_adler32_calculated) > 0.5)
251                 {
252                         g_strlcpy(data->checksum_type,"ADLER32",8);
253                         data->n_checksum_errors=(data->n_adler32_calculated-data->n_adler32_correct);
254                         ok = TRUE;
255                 }
256         }
257
258         if (data->n_crc32c_calculated>0)
259         {
260                 if ((float)(data->n_crc32c_correct*1.0/data->n_crc32c_calculated) > 0.5)
261                 {
262                         g_strlcpy(data->checksum_type,"CRC32C",8);
263                         data->n_checksum_errors=data->n_crc32c_calculated-data->n_crc32c_correct;
264                         ok = TRUE;
265                 }
266         }
267
268         if (!ok)
269         {
270                 g_strlcpy(data->checksum_type,"UNKNOWN",8);
271                 data->n_checksum_errors=0;
272         }
273
274         return(data);
275
276 }
277
278
279 /* XXX: Some versions of gcc warn about "breaking strict aliasing rules"
280         for 'a' in the following (given the way this function is called).
281         As a workaround we'll define the function parameters to match
282         how this function is actually called.  */
283 /*******
284 static gint sctp_assoc_vtag_cmp(gconstpointer aa, gconstpointer bb)
285 {
286         const struct _sctp_assoc_info* a = aa;
287         const struct _sctp_assoc_info* b = bb;
288         if (a == b)
289                 return(FORWARD_STREAM);
290 ********/
291
292 static gint sctp_assoc_vtag_cmp(const sctp_tmp_info_t *a, const sctp_assoc_info_t *b)
293 {
294
295         if (a == NULL || b == NULL)
296                 return(ASSOC_NOT_FOUND);
297
298         if ((a->port1 == b->port1) &&
299             (a->port2 == b->port2) &&
300             (a->verification_tag1 == b->verification_tag1) && a->verification_tag1==0 && a->initiate_tag != 0 &&
301             (a->initiate_tag != b->initiate_tag ))
302                 return(ASSOC_NOT_FOUND);   /* two INITs that belong to different assocs */
303
304         /* assoc known*/
305         if ((a->port1 == b->port1) &&
306             (a->port2 == b->port2) &&
307             (a->verification_tag1 == b->verification_tag1) &&
308             ((a->verification_tag1 != 0 ||
309              (b->verification_tag2 != 0))))
310                 return(FORWARD_STREAM);
311
312         /* ABORT, vtag reflected */
313         if ((a->port1 == b->port1) &&
314             (a->port2 == b->port2) &&
315             (a->verification_tag2 == b->verification_tag2) &&
316             (a->verification_tag1 == 0 && b->verification_tag1 != 0))
317                 return(FORWARD_STREAM);
318
319         if ((a->port1 == b->port2) &&
320             (a->port2 == b->port1) &&
321             (a->verification_tag1 == b->verification_tag2) &&
322             (a->verification_tag1 != 0))
323                 return(BACKWARD_STREAM);
324
325         if ((a->port1 == b->port2) &&
326             (a->port2 == b->port1) &&
327             (a->verification_tag2 == b->verification_tag1) &&
328             (a->verification_tag2 != 0))
329                 return(BACKWARD_STREAM);
330
331         /* ABORT, vtag reflected */
332         if ((a->port1 == b->port2) &&
333             (a->port2 == b->port1) &&
334             (a->verification_tag2 == b->verification_tag1) &&
335             (a->verification_tag1 == 0 && b->verification_tag2 != 0))
336                 return(BACKWARD_STREAM);
337
338         /*forward stream verifivation tag can be added*/
339         if ((a->port1 == b->port1) &&
340             (a->port2 == b->port2) &&
341             (a->verification_tag1 != 0) &&
342             (b->verification_tag1 == 0) &&
343             (b->verification_tag2 !=0))
344                 return (FORWARD_ADD_FORWARD_VTAG);
345
346         if ((a->port1 == b->port2) &&
347             (a->port2 == b->port1) &&
348             (a->verification_tag1 == b->verification_tag2) &&
349             (b->verification_tag1 == 0))
350                 return (BACKWARD_ADD_FORWARD_VTAG);
351
352         /*backward stream verification tag can be added */
353         if ((a->port1 == b->port2) &&
354             (a->port2 == b->port1) &&
355             (a->verification_tag1 !=0) &&
356             (b->verification_tag1 != 0) &&
357             (b->verification_tag2 == 0))
358                 return(BACKWARD_ADD_BACKWARD_VTAG);
359
360         return(ASSOC_NOT_FOUND);
361 }
362
363 static sctp_assoc_info_t * find_assoc(sctp_tmp_info_t * needle)
364 {
365         sctp_allassocs_info_t *assoc_info;
366         sctp_assoc_info_t *info = NULL;
367         GList* list;
368         guint8 cmp;
369
370         assoc_info = &sctp_tapinfo_struct;
371         if ((list = g_list_last(assoc_info->assoc_info_list))!=NULL)
372         {
373                 while (list)
374                 {
375                         cmp=sctp_assoc_vtag_cmp(needle, (sctp_assoc_info_t*)(list->data));
376
377                         /*if (cmp==ASSOC_NOT_FOUND)
378                         {
379                                 cmp=sctp_assoc_address_cmp(needle, (sctp_assoc_info_t*)(list->data));
380                         }*/
381                         switch (cmp)
382                         {
383                         case FORWARD_STREAM:
384                                 info = (sctp_assoc_info_t*)(list->data);
385                                 info->direction = 1;
386                                 return info;
387                         case BACKWARD_STREAM:
388                                 info = (sctp_assoc_info_t*)(list->data);
389                                 info->direction = 2;
390                                 return info;
391                         case FORWARD_ADD_FORWARD_VTAG:
392                                 info = (sctp_assoc_info_t*)(list->data);
393                                 info->verification_tag1=needle->verification_tag1;
394                                 info->direction = 1;
395                                 return info;
396                         case BACKWARD_ADD_FORWARD_VTAG:
397                                 info = (sctp_assoc_info_t*)(list->data);
398                                 info->verification_tag1=needle->verification_tag1;
399                                 info->direction = 2;
400                                 return info;
401                         case BACKWARD_ADD_BACKWARD_VTAG:
402                                 info = (sctp_assoc_info_t*)(list->data);
403                                 info->verification_tag2=needle->verification_tag1;
404                                 info->direction = 2;
405                                 return info;
406                         case ADDRESS_FORWARD_STREAM:
407                                 info = (sctp_assoc_info_t*)(list->data);
408                                 info->direction = 1;
409                                 info->check_address=TRUE;
410                                 return info;
411                         case ADDRESS_BACKWARD_STREAM:
412                                 info = (sctp_assoc_info_t*)(list->data);
413                                 info->direction = 2;
414                                 info->check_address=TRUE;
415                                 return info;
416                         case ADDRESS_FORWARD_ADD_FORWARD_VTAG:
417                                 info = (sctp_assoc_info_t*)(list->data);
418                                 info->verification_tag1=needle->verification_tag1;
419                                 info->direction = 1;
420                                 info->check_address=TRUE;
421                                 return info;
422                         case ADDRESS_BACKWARD_ADD_FORWARD_VTAG:
423                                 info = (sctp_assoc_info_t*)(list->data);
424                                 info->verification_tag1=needle->verification_tag1;
425                                 info->direction = 2;
426                                 info->check_address=TRUE;
427                                 return info;
428                         case ADDRESS_BACKWARD_ADD_BACKWARD_VTAG:
429                                 info = (sctp_assoc_info_t*)(list->data);
430                                 info->verification_tag2=needle->verification_tag1;
431                                 info->direction = 2;
432                                 info->check_address=TRUE;
433                                 return info;
434                         }
435
436                         list = g_list_previous(list);
437                 }
438         }
439         return NULL;
440 }
441
442 static sctp_assoc_info_t * add_chunk_count(address * vadd, sctp_assoc_info_t * info, guint32 direction, guint32 type)
443 {
444         GList *list;
445         address *v=NULL;
446         sctp_addr_chunk *ch=NULL;
447         guint8 * dat;
448         int i;
449
450         list = g_list_first(info->addr_chunk_count);
451
452         while (list)
453         {
454                 ch = (sctp_addr_chunk *)(list->data);
455                 if (ch->direction == direction)
456                 {
457                         v = (address *) (ch->addr);
458                         if (ADDRESSES_EQUAL(vadd, v))
459                         {
460                                 if (IS_SCTP_CHUNK_TYPE(type))
461                                         ch->addr_count[type]++;
462                                 else
463                                         ch->addr_count[OTHER_CHUNKS_INDEX]++;
464                                 return info;
465                         }
466                         else
467                         {
468                                 list = g_list_next(list);
469                         }
470                 }
471                 else
472                         list = g_list_next(list);
473         }
474         ch = g_malloc(sizeof(sctp_addr_chunk));
475         ch->direction = direction;
476         ch->addr = g_malloc(sizeof(address));
477         ch->addr->type = vadd->type;
478         ch->addr->len = vadd->len;
479         dat = g_malloc(vadd->len);
480         memcpy(dat, vadd->data, vadd->len);
481         ch->addr->data = dat;
482         for (i=0; i < NUM_CHUNKS; i++)
483                 ch->addr_count[i] = 0;
484
485         if (IS_SCTP_CHUNK_TYPE(type))
486                 ch->addr_count[type]++;
487         else
488                 ch->addr_count[OTHER_CHUNKS_INDEX]++;
489
490         info->addr_chunk_count = g_list_append(info->addr_chunk_count, ch);
491         return info;
492 }
493
494 static sctp_assoc_info_t * add_address(address * vadd, sctp_assoc_info_t *info, guint8 direction)
495 {
496         GList *list;
497         address *v=NULL;
498
499         if (direction == 1)
500                 list = g_list_first(info->addr1);
501         else
502                 list = g_list_first(info->addr2);
503
504         while (list)
505         {
506                 v = (address *) (list->data);
507                 if (ADDRESSES_EQUAL(vadd, v)) {
508                         g_free(vadd);
509                         return info;
510                 }
511                 list = g_list_next(list);
512         }
513
514         if (direction == 1)
515                 info->addr1 = g_list_append(info->addr1, vadd);
516         else if (direction==2)
517                 info->addr2 = g_list_append(info->addr2, vadd);
518
519         return info;
520 }
521
522 static int
523 packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const void *data)
524 {
525         struct _sctp_info *sctp_info;
526         guint32 chunk_number = 0, tsnumber,framenumber;
527         sctp_tmp_info_t tmp_info;
528         sctp_assoc_info_t *info = NULL;
529         sctp_error_info_t *error = NULL;
530         guint16 type, length;
531         address *store = NULL;
532         tsn_t   *tsn = NULL;
533         tsn_t   *sack = NULL;
534         guint8  *t_s_n = NULL;
535         gboolean sackchunk = FALSE;
536         gboolean datachunk = FALSE;
537         struct tsn_sort *tsn_s;
538         guint8* addr = NULL;
539         int i;
540         guint8 idx = 0;
541
542         sctp_info = (struct _sctp_info *) data;
543
544         framenumber=pinfo->fd->num;
545
546         type = sctp_info->ip_src.type;
547
548         if (type == AT_IPv4)
549         {
550                 tmp_info.src.type = AT_IPv4;
551                 tmp_info.src.len  = 4;
552         }
553         else if (type == AT_IPv6)
554         {
555                 tmp_info.src.type = AT_IPv6;
556                 tmp_info.src.len  = 16;
557         }
558         else
559         {
560                 tmp_info.src.type = AT_NONE;
561                 tmp_info.src.len  = 0;
562         }
563
564         addr = g_malloc(tmp_info.src.len);
565         memcpy(addr, sctp_info->ip_src.data, tmp_info.src.len);
566         tmp_info.src.data = addr;
567
568         type = sctp_info->ip_dst.type;
569
570         if (type == AT_IPv4)
571         {
572                 tmp_info.dst.type = AT_IPv4;
573                 tmp_info.dst.len  = 4;
574         }
575         else if (type == AT_IPv6)
576         {
577                 tmp_info.dst.type = AT_IPv6;
578                 tmp_info.dst.len  = 16;
579         }
580         else
581         {
582                 tmp_info.dst.type = AT_NONE;
583                 tmp_info.dst.len  = 0;
584         }
585
586         addr = g_malloc(tmp_info.dst.len);
587         memcpy(addr, sctp_info->ip_dst.data, tmp_info.dst.len);
588         tmp_info.dst.data = addr;
589
590         tmp_info.port1 = sctp_info->sport;
591         tmp_info.port2 = sctp_info->dport;
592
593         if (sctp_info->vtag_reflected)
594         {
595                 tmp_info.verification_tag2 = sctp_info->verification_tag;
596                 tmp_info.verification_tag1 = 0;
597         }
598         else
599         {
600                 tmp_info.verification_tag1 = sctp_info->verification_tag;
601                 tmp_info.verification_tag2 = 0;
602         }
603         tmp_info.n_tvbs = 0;
604         if (tvb_get_guint8(sctp_info->tvb[0],0) == SCTP_INIT_CHUNK_ID)
605         {
606                 tmp_info.initiate_tag = tvb_get_ntohl(sctp_info->tvb[0], 4);
607         }
608         else
609         {
610                 tmp_info.initiate_tag = 0;
611         }
612
613         info = find_assoc(&tmp_info);
614         if (!info)
615         {
616                 tmp_info.n_tvbs = sctp_info->number_of_tvbs;
617                 sctp_tapinfo_struct.sum_tvbs+=sctp_info->number_of_tvbs;
618
619                 if (sctp_info->number_of_tvbs > 0)
620                 {
621                         info = g_malloc(sizeof(sctp_assoc_info_t));
622                         memset(info, 0, sizeof(sctp_assoc_info_t));
623                         info->src.type = tmp_info.src.type;
624                         info->src.len  = tmp_info.src.len;
625                         addr = g_malloc(tmp_info.dst.len);
626                         memcpy(addr,(tmp_info.src.data), tmp_info.src.len);
627                         info->src.data = addr;
628                         info->dst.type = tmp_info.dst.type;
629                         info->dst.len  = tmp_info.dst.len;
630                         addr = g_malloc(tmp_info.dst.len);
631                         memcpy(addr, (tmp_info.dst.data), tmp_info.dst.len);
632                         info->dst.data = addr;
633                         info->port1 = tmp_info.port1;
634                         info->port2 = tmp_info.port2;
635                         info->verification_tag1 = tmp_info.verification_tag1;
636                         info->verification_tag2 = tmp_info.verification_tag2;
637                         info->initiate_tag      = tmp_info.initiate_tag;
638                         info->n_tvbs            = tmp_info.n_tvbs;
639                         info->init              = FALSE;
640                         info->initack           = FALSE;
641                         info->check_address     = FALSE;
642                         info->direction         = 0;
643                         info = calc_checksum(sctp_info, info);
644                         info->n_packets         = 1;
645                         info->error_info_list   = NULL;
646                         info->min_secs          = 0xffffffff;
647                         info->min_usecs         = 0xffffffff;
648                         info->max_secs          = 0;
649                         info->max_usecs         = 0;
650                         info->min_tsn2          = 0xFFFFFFFF;
651                         info->min_tsn1          = 0xffffffff;
652                         info->max_tsn1          = 0;
653                         info->max_tsn2          = 0;
654                         info->max_bytes1        = 0;
655                         info->max_bytes2        = 0;
656                         info->n_data_chunks     = 0;
657                         info->n_data_bytes      = 0;
658                         info->n_data_chunks_ep1 = 0;
659                         info->n_data_bytes_ep1  = 0;
660                         info->n_data_chunks_ep2 = 0;
661                         info->n_data_bytes_ep2  = 0;
662                         info->n_sack_chunks_ep1 = 0;
663                         info->n_sack_chunks_ep2 = 0;
664                         info->n_array_tsn1      = 0;
665                         info->n_array_tsn2      = 0;
666                         info->max_window1       = 0;
667                         info->max_window2       = 0;
668                         info->min_max           = NULL;
669                         info->sort_tsn1         = g_ptr_array_new();
670                         info->sort_tsn2         = g_ptr_array_new();
671                         info->sort_sack1        = g_ptr_array_new();
672                         info->sort_sack2        = g_ptr_array_new();
673                         for (i=0; i < NUM_CHUNKS; i++)
674                         {
675                                 info->chunk_count[i] = 0;
676                                 info->ep1_chunk_count[i] = 0;
677                                 info->ep2_chunk_count[i] = 0;
678                         }
679                         info->addr_chunk_count = NULL;
680
681                         if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID) ||
682                             ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID) ||
683                             ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) ||
684                             ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID) ||
685                             ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID))
686                         {
687                                 tsn  = g_malloc(sizeof(tsn_t));
688                                 sack = g_malloc(sizeof(tsn_t));
689                                 tsn->tsns  = NULL;
690                                 tsn->first_tsn = 0;
691                                 sack->tsns = NULL;
692                                 sack->first_tsn = 0;
693                                 sack->src.type=tsn->src.type = tmp_info.src.type;
694                                 sack->src.len=tsn->src.len   = tmp_info.src.len;
695                                 addr = g_malloc(tmp_info.src.len);
696                                 memcpy(addr, tmp_info.src.data, tmp_info.src.len);
697                                 tsn->src.data = addr;
698                                 addr = g_malloc(tmp_info.src.len);
699                                 memcpy(addr, tmp_info.src.data, tmp_info.src.len);
700                                 sack->src.data = addr;
701                                 sack->dst.type = tsn->dst.type = tmp_info.dst.type;
702                                 sack->dst.len  =tsn->dst.len   = tmp_info.dst.len;
703                                 addr = g_malloc(tmp_info.dst.len);
704                                 memcpy(addr, tmp_info.dst.data, tmp_info.dst.len);
705                                 tsn->dst.data = addr;
706                                 addr = g_malloc(tmp_info.dst.len);
707                                 memcpy(addr, tmp_info.dst.data, tmp_info.dst.len);
708                                 sack->dst.data = addr;
709                                 sack->secs=tsn->secs   = (guint32)pinfo->fd->rel_ts.secs;
710                                 sack->usecs=tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
711                                 if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) ||
712                                     ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID) ||
713                                     ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID))
714                                 {
715                                         if (tsn->secs < info->min_secs)
716                                         {
717                                                 info->min_secs  = tsn->secs;
718                                                 info->min_usecs = tsn->usecs;
719                                         }
720                                         else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
721                                                 info->min_usecs = tsn->usecs;
722
723                                         if (tsn->secs > info->max_secs)
724                                         {
725                                                 info->max_secs  = tsn->secs;
726                                                 info->max_usecs = tsn->usecs;
727                                         }
728                                         else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
729                                                 info->max_usecs = tsn->usecs;
730                                 }
731
732                                 sack->frame_number = tsn->frame_number = pinfo->fd->num;
733                         }
734                         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))
735                         {
736                                 info->min_tsn1 = tvb_get_ntohl(sctp_info->tvb[0],INIT_CHUNK_INITIAL_TSN_OFFSET);
737                                 info->verification_tag2 = tvb_get_ntohl(sctp_info->tvb[0], INIT_CHUNK_INITIATE_TAG_OFFSET);
738                                 info->instream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
739                                 info->outstream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
740                                 for (chunk_number = 1; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
741                                 {
742                                 type = tvb_get_ntohs(sctp_info->tvb[chunk_number],0);
743                                         if (type == IPV4ADDRESS_PARAMETER_ID)
744                                         {
745                                                 store = g_malloc(sizeof (address));
746                                                 store->type = AT_IPv4;
747                                                 store->len  = 4;
748                                                 store->data = g_malloc(4);
749                                                 tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(store->data),IPV4_ADDRESS_OFFSET, 4);
750                                                 info = add_address(store, info, 1);
751                                         }
752                                         else if (type == IPV6ADDRESS_PARAMETER_ID)
753                                         {
754                                                 store = g_malloc(sizeof (address));
755                                                 store->type = AT_IPv6;
756                                                 store->len  = 16;
757                                                 store->data = g_malloc(16);
758                                                 tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(store->data),IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH);
759                                                 info = add_address(store, info, 1);
760                                         }
761                                 }
762
763                                 if (tvb_get_guint8(sctp_info->tvb[0],0) == SCTP_INIT_CHUNK_ID)
764                                 {
765                                         info->init = TRUE;
766                                 }
767                                 else
768                                 {
769                                         info->initack_dir = 1;
770                                         info->initack     = TRUE;
771                                 }
772
773                                 idx = tvb_get_guint8(sctp_info->tvb[0],0);
774                                 if (!IS_SCTP_CHUNK_TYPE(idx))
775                                         idx = OTHER_CHUNKS_INDEX;
776
777                                 info->chunk_count[idx]++;
778                                 info->ep1_chunk_count[idx]++;
779                                 info = add_chunk_count(&tmp_info.src, info, 1, idx);
780                         }
781                         else
782                         {
783                                 if (((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_INIT_CHUNK_ID) &&
784                                     ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_INIT_ACK_CHUNK_ID) &&
785                                     ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_DATA_CHUNK_ID) &&
786                                     ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_SACK_CHUNK_ID) &&
787                                     ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_NR_SACK_CHUNK_ID))
788                                 {
789                                         tsn  = g_malloc(sizeof(tsn_t));
790                                         sack = g_malloc(sizeof(tsn_t));
791                                         tsn->tsns  = NULL;
792                                         sack->tsns = NULL;
793                                         tsn->first_tsn = 0;
794                                         sack->first_tsn = 0;
795                                 }
796                                 for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
797                                 {
798                                         idx = tvb_get_guint8(sctp_info->tvb[0],0);
799                                         if (!IS_SCTP_CHUNK_TYPE(idx))
800                                                 idx = OTHER_CHUNKS_INDEX;
801
802                                         info->chunk_count[idx]++;
803                                         info->ep1_chunk_count[idx]++;
804                                         info = add_chunk_count(&tmp_info.src, info, 1, idx);
805
806                                         if (tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_DATA_CHUNK_ID)
807                                         {
808                                                 length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
809                                                 info->n_data_chunks++;
810                                                 info->n_data_bytes+=length;
811                                                 info->outstream1 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
812                                                 tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], DATA_CHUNK_TSN_OFFSET);
813                                                 if (tsnumber < info->min_tsn1)
814                                                         info->min_tsn1 = tsnumber;
815                                                 if (tsnumber > info->max_tsn1)
816                                                 {
817                                                         length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
818                                                         info->n_data_chunks_ep1++;
819                                                         info->n_data_bytes_ep1+=length;
820                                                         info->max_tsn1 = tsnumber;
821                                                 }
822                                                 if (tsn->first_tsn == 0)
823                                                         tsn->first_tsn = tsnumber;
824                                                 t_s_n = g_malloc(16);
825                                                 tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, 16);
826                                                 tsn->tsns = g_list_append(tsn->tsns, t_s_n);
827                                                 datachunk = TRUE;
828                                                 tsn_s = g_malloc(sizeof(struct tsn_sort));
829                                                 tsn_s->tsnumber = tsnumber;
830                                                 tsn_s->secs     = tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
831                                                 tsn_s->usecs    = tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
832                                                 tsn_s->offset   = 0;
833                                                 tsn_s->framenumber = framenumber;
834                                                 tsn_s->length   = length-DATA_CHUNK_HEADER_LENGTH;
835                                                 if (tsn->secs < info->min_secs)
836                                                 {
837                                                         info->min_secs  = tsn->secs;
838                                                         info->min_usecs = tsn->usecs;
839                                                 }
840                                                 else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
841                                                         info->min_usecs = tsn->usecs;
842
843                                                 if (tsn->secs > info->max_secs)
844                                                 {
845                                                         info->max_secs  = tsn->secs;
846                                                         info->max_usecs = tsn->usecs;
847                                                 }
848                                                 else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
849                                                         info->max_usecs = tsn->usecs;
850                                                 g_ptr_array_add(info->sort_tsn1, tsn_s);
851                                                 info->n_array_tsn1++;
852                                         }
853                                         if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_SACK_CHUNK_ID) ||
854                                             (tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_NR_SACK_CHUNK_ID) )
855                                         {
856                                                 tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
857                                                 if (tsnumber < info->min_tsn2)
858                                                         info->min_tsn2 = tsnumber;
859                                                 if (tsnumber > info->max_tsn2)
860                                                         info->max_tsn2 = tsnumber;
861                                                 info->n_sack_chunks_ep2++;
862                                                 length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
863                                                 if (sack->first_tsn == 0)
864                                                         sack->first_tsn = tsnumber;
865                                                 t_s_n = g_malloc(length);
866                                                 tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, length);
867                                                 sack->tsns = g_list_append(sack->tsns, t_s_n);
868                                                 sackchunk = TRUE;
869                                                 tsn_s = g_malloc(sizeof(struct tsn_sort));
870                                                 tsn_s->tsnumber = tsnumber;
871                                                 tsn_s->secs     = tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
872                                                 tsn_s->usecs    = tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
873                                                 tsn_s->offset   = 0;
874                                                 tsn_s->framenumber = framenumber;
875                                                 tsn_s->length   =  tvb_get_ntohl(sctp_info->tvb[chunk_number], SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
876                                                 if (tsn_s->length > info->max_window1)
877                                                         info->max_window1 = tsn_s->length;
878                                                 if (tsn->secs < info->min_secs)
879                                                 {
880                                                         info->min_secs  = tsn->secs;
881                                                         info->min_usecs = tsn->usecs;
882                                                 }
883                                                 else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
884                                                         info->min_usecs = tsn->usecs;
885
886                                                 if (tsn->secs > info->max_secs)
887                                                 {
888                                                         info->max_secs  = tsn->secs;
889                                                         info->max_usecs = tsn->usecs;
890                                                 }
891                                                 else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
892                                                         info->max_usecs = tsn->usecs;
893                                                 g_ptr_array_add(info->sort_sack2, tsn_s);
894                                                 info->n_sack_chunks_ep2++;
895                                         }
896                                 }
897                         }
898                         if (info->verification_tag1 != 0 || info->verification_tag2 != 0)
899                         {
900                                 store = g_malloc(sizeof (address));
901                                 store->type = tmp_info.src.type;
902                                 store->len  = tmp_info.src.len;
903                                 addr = g_malloc(tmp_info.src.len);
904                                 memcpy(addr,(tmp_info.src.data),tmp_info.src.len);
905                                 store->data = addr;
906                                 info  = add_address(store, info, 1);
907                                 store = g_malloc(sizeof (address));
908                                 store->type = tmp_info.dst.type;
909                                 store->len  = tmp_info.dst.len;
910                                 addr = g_malloc(tmp_info.dst.len);
911                                 memcpy(addr,(tmp_info.dst.data),tmp_info.dst.len);
912                                 store->data = addr;
913                                 info = add_address(store, info, 2);
914                                 info->frame_numbers=g_list_prepend(info->frame_numbers,&(pinfo->fd->num));
915                                 if (datachunk == TRUE)
916                                         info->tsn1 = g_list_prepend(info->tsn1, tsn);
917                                 if (sackchunk == TRUE)
918                                         info->sack2 = g_list_prepend(info->sack2, sack);
919                                 sctp_tapinfo_struct.assoc_info_list = g_list_append(sctp_tapinfo_struct.assoc_info_list, info);
920                         }
921                         else
922                         {
923                                 error = g_malloc(sizeof(sctp_error_info_t));
924                                 error->frame_number = pinfo->fd->num;
925                                 error->chunk_info[0] = '\0';
926                                 if ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID)
927                                         g_strlcpy(error->chunk_info, val_to_str(tvb_get_guint8(sctp_info->tvb[0],0),chunk_type_values,"Reserved"), 200);
928                                 else
929                                         for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
930                                                 g_strlcat(error->chunk_info, val_to_str(tvb_get_guint8(sctp_info->tvb[chunk_number],0),chunk_type_values,"Reserved"), 200);
931                                 error->info_text = "INFOS";
932                                 info->error_info_list = g_list_append(info->error_info_list, error);
933                         }
934                 }
935         } /* endif (!info) */
936         else
937         {
938                 if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID) ||
939                     ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID) ||
940                     ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) ||
941                     ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID) ||
942                     ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID))
943                 {
944
945                         tsn  = g_malloc(sizeof(tsn_t));
946                         sack = g_malloc(sizeof(tsn_t));
947                         tsn->tsns  = NULL;
948                         tsn->first_tsn = 0;
949                         sack->tsns = NULL;
950                         sack->first_tsn = 0;
951                         sack->src.type = tsn->src.type = tmp_info.src.type;
952                         sack->src.len  = tsn->src.len = tmp_info.src.len;
953                         addr = g_malloc(tmp_info.src.len);
954                         memcpy(addr, tmp_info.src.data, tmp_info.src.len);
955                         tsn->src.data = addr;
956                         addr = g_malloc(tmp_info.src.len);
957                         memcpy(addr, tmp_info.src.data, tmp_info.src.len);
958                         sack->src.data = addr;
959                         sack->dst.type = tsn->dst.type = tmp_info.dst.type;
960                         sack->dst.len  = tsn->dst.len = tmp_info.dst.len;
961                         addr = g_malloc(tmp_info.dst.len);
962                         memcpy(addr, tmp_info.dst.data, tmp_info.dst.len);
963                         tsn->dst.data = addr;
964                         addr = g_malloc(tmp_info.dst.len);
965                         memcpy(addr, tmp_info.dst.data, tmp_info.dst.len);
966                         sack->dst.data = addr;
967                         sack->secs=tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
968                         sack->usecs=tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
969                         if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) ||
970                         ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_SACK_CHUNK_ID) ||
971                         ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_NR_SACK_CHUNK_ID))
972                         {
973                                 if (tsn->secs < info->min_secs)
974                                 {
975                                         info->min_secs  = tsn->secs;
976                                         info->min_usecs = tsn->usecs;
977                                 }
978                                 else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
979                                         info->min_usecs = tsn->usecs;
980
981                                 if (tsn->secs > info->max_secs)
982                                         {
983                                                 info->max_secs  = tsn->secs;
984                                                 info->max_usecs = tsn->usecs;
985                                         }
986                                         else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
987                                                 info->max_usecs = tsn->usecs;
988                         }
989                         sack->frame_number = tsn->frame_number = pinfo->fd->num;
990                 }
991                 info->frame_numbers = g_list_prepend(info->frame_numbers,&(pinfo->fd->num));
992
993                 store = g_malloc(sizeof (address));
994                 store->type = tmp_info.src.type;
995                 store->len  = tmp_info.src.len;
996                 addr = g_malloc(tmp_info.src.len);
997                 memcpy(addr,(tmp_info.src.data),tmp_info.src.len);
998                 store->data = addr;
999
1000                 if (info->direction == 1)
1001                         info = add_address(store, info, 1);
1002                 else if (info->direction == 2)
1003                         info = add_address(store, info, 2);
1004
1005                 store = g_malloc(sizeof (address));
1006                 store->type = tmp_info.dst.type;
1007                 store->len  = tmp_info.dst.len;
1008                 addr = g_malloc(tmp_info.dst.len);
1009                 memcpy(addr,(tmp_info.dst.data),tmp_info.dst.len);
1010                 store->data = addr;
1011
1012                 if (info->direction == 1)
1013                         info = add_address(store, info, 2);
1014                 else if (info->direction == 2)
1015                         info = add_address(store, info, 1);
1016
1017                 if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID) ||
1018                     ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID))
1019                 {
1020                         tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], INIT_CHUNK_INITIAL_TSN_OFFSET);
1021
1022                         if (info->direction == 2)
1023                         {
1024                                 if (tsnumber < info->min_tsn2)
1025                                         info->min_tsn2 = tsnumber;
1026                                 if (tsnumber > info->max_tsn2)
1027                                         info->max_tsn2 = tsnumber;
1028                                 info->instream2 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
1029                                 info->outstream2 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
1030                                 /*info->initack_dir=2;*/
1031                                 info->tsn2 = g_list_prepend(info->tsn2, tsn);
1032                         }
1033                         else if (info->direction == 1)
1034                         {
1035                                 if (tsnumber < info->min_tsn1)
1036                                         info->min_tsn1 = tsnumber;
1037                                 if (tsnumber > info->max_tsn1)
1038                                         info->max_tsn1 = tsnumber;
1039                                 info->instream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
1040                                 info->outstream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
1041                                 /*info->initack_dir=1;*/
1042                                 info->tsn1 = g_list_prepend(info->tsn1, tsn);
1043                         }
1044
1045                         idx = tvb_get_guint8(sctp_info->tvb[0],0);
1046                         if (!IS_SCTP_CHUNK_TYPE(idx))
1047                                 idx = OTHER_CHUNKS_INDEX;
1048                         info->chunk_count[idx]++;
1049                         if (info->direction == 1)
1050                                 info->ep1_chunk_count[idx]++;
1051                         else
1052                                 info->ep2_chunk_count[idx]++;
1053                         info = add_chunk_count(&tmp_info.src, info, info->direction, idx);
1054                         for (chunk_number = 1; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
1055                         {
1056                                 type = tvb_get_ntohs(sctp_info->tvb[chunk_number],0);
1057                                         if (type == IPV4ADDRESS_PARAMETER_ID)
1058                                         {
1059                                                 store = g_malloc(sizeof (address));
1060                                                 store->type = AT_IPv4;
1061                                                 store->len  = 4;
1062                                                 store->data = g_malloc(4);
1063                                                 tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(store->data),IPV4_ADDRESS_OFFSET, 4);
1064                                                 info = add_address(store, info, info->direction);
1065                                         }
1066                                         else if (type == IPV6ADDRESS_PARAMETER_ID)
1067                                         {
1068                                                 store = g_malloc(sizeof (address));
1069                                                 store->type = AT_IPv6;
1070                                                 store->len  = 16;
1071                                                 store->data = g_malloc(16);
1072                                                 tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(store->data),IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH);
1073                                                 info = add_address(store, info, info->direction);
1074                                         }
1075                                         }
1076                         if ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID)
1077                         {
1078                                 info->initack = TRUE;
1079                                 info->initack_dir = info->direction;
1080                         }
1081                         else
1082                         if ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID)
1083                         {
1084                                 info->init = TRUE;
1085                         }
1086                 }
1087                 else
1088                 {
1089                         if (((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_INIT_ACK_CHUNK_ID) &&
1090                             ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_DATA_CHUNK_ID) &&
1091                             ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_SACK_CHUNK_ID) &&
1092                             ((tvb_get_guint8(sctp_info->tvb[0],0)) != SCTP_NR_SACK_CHUNK_ID))
1093                         {
1094                                 sack = g_malloc(sizeof(tsn_t));
1095                                 sack->tsns = NULL;
1096                                 sack->first_tsn = 0;
1097                                 tsn = g_malloc(sizeof(tsn_t));
1098                                 tsn->tsns = NULL;
1099                                 tsn->first_tsn = 0;
1100                         }
1101                         for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
1102                         {
1103                                 idx = tvb_get_guint8(sctp_info->tvb[chunk_number],0);
1104                                 if (!IS_SCTP_CHUNK_TYPE(idx))
1105                                         idx = OTHER_CHUNKS_INDEX;
1106
1107                                 info->chunk_count[idx]++;
1108                                 if (info->direction == 1)
1109                                         info->ep1_chunk_count[idx]++;
1110                                 else
1111                                         info->ep2_chunk_count[idx]++;
1112                                 info = add_chunk_count(&tmp_info.src, info,info->direction, idx);
1113
1114                                 if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0)) == SCTP_DATA_CHUNK_ID)
1115                                 {
1116                                         tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], DATA_CHUNK_TSN_OFFSET);
1117                                         if (tsn->first_tsn == 0)
1118                                                 tsn->first_tsn = tsnumber;
1119                                         t_s_n = g_malloc(16);
1120                                         tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, 16);
1121                                         tsn->tsns = g_list_append(tsn->tsns, t_s_n);
1122                                         datachunk = TRUE;
1123                                         length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
1124                                         info->n_data_chunks++;
1125                                         info->n_data_bytes+=length;
1126                                         tsn_s = g_malloc(sizeof(struct tsn_sort));
1127                                         tsn_s->tsnumber = tsnumber;
1128                                         tsn_s->secs  = tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
1129                                         tsn_s->usecs = tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
1130                                         tsn_s->offset = 0;
1131                                         tsn_s->framenumber = framenumber;
1132                                         tsn_s->length = length;
1133
1134                                         if (tsn->secs < info->min_secs)
1135                                         {
1136                                                 info->min_secs  = tsn->secs;
1137                                                 info->min_usecs = tsn->usecs;
1138                                         }
1139                                         else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
1140                                                 info->min_usecs = tsn->usecs;
1141
1142                                         if (tsn->secs > info->max_secs)
1143                                         {
1144                                                 info->max_secs  = tsn->secs;
1145                                                 info->max_usecs = tsn->usecs;
1146                                         }
1147                                         else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
1148                                                 info->max_usecs = tsn->usecs;
1149
1150                                         if (info->direction == 1)
1151                                         {
1152                                                 if(tsnumber < info->min_tsn1)
1153                                                         info->min_tsn1 = tsnumber;
1154                                                 if ((info->init == TRUE || (info->initack == TRUE && info->initack_dir == 1))&& tsnumber >= info->min_tsn1 && tsnumber <= info->max_tsn1)
1155                                                 {
1156                                                         length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
1157                                                         info->n_data_chunks_ep1++;
1158                                                         info->n_data_bytes_ep1 += length;
1159                                                 }
1160                                                 if(tsnumber > info->max_tsn1)
1161                                                 {
1162                                                         info->max_tsn1 = tsnumber;
1163                                                         length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
1164                                                         info->n_data_chunks_ep1++;
1165                                                         info->n_data_bytes_ep1 += length;
1166                                                 }
1167                                                 if (info->init == FALSE)
1168                                                         info->outstream1 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
1169                                                 if (info->initack == FALSE)
1170                                                         info->instream2 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
1171
1172                                                 g_ptr_array_add(info->sort_tsn1, tsn_s);
1173                                                 info->n_array_tsn1++;
1174                                         }
1175                                         else if (info->direction == 2)
1176                                         {
1177
1178                                                 if(tsnumber < info->min_tsn2)
1179                                                         info->min_tsn2 = tsnumber;
1180
1181                                                 if ((info->initack == TRUE && info->initack_dir == 2)&& tsnumber >= info->min_tsn2 && tsnumber <= info->max_tsn2)
1182                                                 {
1183                                                         length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
1184                                                         info->n_data_chunks_ep2++;
1185                                                         info->n_data_bytes_ep2+=length;
1186                                                 }
1187                                                 if(tsnumber > info->max_tsn2)
1188                                                 {
1189                                                         info->max_tsn2 = tsnumber;
1190                                                         length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET)-DATA_CHUNK_HEADER_LENGTH;
1191                                                         info->n_data_chunks_ep2++;
1192                                                         info->n_data_bytes_ep2+=length;
1193                                                 }
1194                                                 if (info->init == FALSE)
1195                                                         info->instream1 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
1196                                                 if (info->initack == FALSE)
1197                                                         info->outstream2 = tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
1198
1199                                                 g_ptr_array_add(info->sort_tsn2, tsn_s);
1200                                                 info->n_array_tsn2++;
1201                                         }
1202                                 }
1203                                 else if ((tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_SACK_CHUNK_ID) ||
1204                                          (tvb_get_guint8(sctp_info->tvb[chunk_number],0) == SCTP_NR_SACK_CHUNK_ID))
1205                                 {
1206                                         tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1207                                         length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
1208                                         if (sack->first_tsn == 0)
1209                                                 sack->first_tsn = tsnumber;
1210                                         t_s_n = g_malloc(length);
1211                                         tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, length);
1212                                         sack->tsns = g_list_append(sack->tsns, t_s_n);
1213                                         sackchunk = TRUE;
1214                                         tsn_s = g_malloc(sizeof(struct tsn_sort));
1215                                         tsn_s->tsnumber = tsnumber;
1216                                         tsn_s->secs   = tsn->secs = (guint32)pinfo->fd->rel_ts.secs;
1217                                         tsn_s->usecs  = tsn->usecs = (guint32)pinfo->fd->rel_ts.nsecs/1000;
1218                                         tsn_s->offset = 0;
1219                                         tsn_s->framenumber = framenumber;
1220                                         tsn_s->length = tvb_get_ntohl(sctp_info->tvb[chunk_number], SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1221
1222                                         if (tsn->secs < info->min_secs)
1223                                         {
1224                                                 info->min_secs  = tsn->secs;
1225                                                 info->min_usecs = tsn->usecs;
1226                                         }
1227                                         else if (tsn->secs == info->min_secs && tsn->usecs < info->min_usecs)
1228                                                 info->min_usecs = tsn->usecs;
1229
1230                                         if (tsn->secs > info->max_secs)
1231                                         {
1232                                                 info->max_secs  = tsn->secs;
1233                                                 info->max_usecs = tsn->usecs;
1234                                         }
1235                                         else if (tsn->secs == info->max_secs && tsn->usecs > info->max_usecs)
1236                                                 info->max_usecs = tsn->usecs;
1237
1238
1239                                         if (info->direction == 2)
1240                                         {
1241                                                 if(tsnumber < info->min_tsn1)
1242                                                         info->min_tsn1 = tsnumber;
1243                                                 if(tsnumber > info->max_tsn1)
1244                                                         info->max_tsn1 = tsnumber;
1245                                                 if (tsn_s->length > info->max_window1)
1246                                                                 info->max_window1 = tsn_s->length;
1247                                                 g_ptr_array_add(info->sort_sack1, tsn_s);
1248                                                 info->n_sack_chunks_ep1++;
1249                                         }
1250                                         else if (info->direction == 1)
1251                                         {
1252
1253                                                 if(tsnumber < info->min_tsn2)
1254                                                         info->min_tsn2 = tsnumber;
1255                                                 if(tsnumber > info->max_tsn2)
1256                                                         info->max_tsn2 = tsnumber;
1257                                                 if (tsn_s->length > info->max_window2)
1258                                                                 info->max_window2 = tsn_s->length;
1259                                                 g_ptr_array_add(info->sort_sack2, tsn_s);
1260                                                 info->n_sack_chunks_ep2++;
1261                                         }
1262
1263                                 }
1264                         }
1265
1266                 }
1267                 if (datachunk == TRUE)
1268                 {
1269                         if (info->direction == 1)
1270                                 info->tsn1 = g_list_prepend(info->tsn1, tsn);
1271                         else if (info->direction == 2)
1272                                 info->tsn2 = g_list_prepend(info->tsn2, tsn);
1273                 }
1274                 if (sackchunk == TRUE)
1275                 {
1276                         if (info->direction == 1)
1277                                         info->sack2 = g_list_prepend(info->sack2, sack);
1278                                 else if(info->direction == 2)
1279                                         info->sack1 = g_list_prepend(info->sack1, sack);
1280                 }
1281                 info->n_tvbs += sctp_info->number_of_tvbs;
1282                 sctp_tapinfo_struct.sum_tvbs += sctp_info->number_of_tvbs;
1283                 info = calc_checksum(sctp_info, info);
1284                 info->n_packets++;
1285         }
1286         return(1);
1287 }
1288
1289
1290 /****************************************************************************/
1291 void
1292 remove_tap_listener_sctp_stat(void)
1293 {
1294         if (sctp_tapinfo_struct.is_registered) {
1295                 remove_tap_listener(&sctp_tapinfo_struct);
1296                 sctp_tapinfo_struct.is_registered = FALSE;
1297         }
1298 }
1299
1300
1301 void sctp_stat_scan(void)
1302 {
1303         if (!sctp_tapinfo_struct.is_registered)
1304                 register_tap_listener_sctp_stat();
1305 }
1306
1307 const sctp_allassocs_info_t* sctp_stat_get_info(void)
1308 {
1309         return &sctp_tapinfo_struct;
1310 }
1311
1312
1313 static void sctp_update(void *dummy _U_)
1314 {
1315         if (get_stat_dlg()!=NULL)
1316                 sctp_stat_dlg_update();
1317 }
1318
1319 void
1320 register_tap_listener_sctp_stat(void)
1321 {
1322         GString *error_string;
1323
1324         if (!sctp_tapinfo_struct.is_registered)
1325         {
1326                 if ((error_string = register_tap_listener("sctp", &sctp_tapinfo_struct, NULL, 0, reset, packet, sctp_update))) {
1327                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
1328                         g_string_free(error_string, TRUE);
1329                         return;
1330                 }
1331                 sctp_tapinfo_struct.is_registered=TRUE;
1332         }
1333 }