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