aboutsummaryrefslogtreecommitdiffstats
path: root/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'gtk')
-rw-r--r--gtk/Makefile.am1
-rw-r--r--gtk/Makefile.common8
-rw-r--r--gtk/sctp_assoc_analyse.c805
-rw-r--r--gtk/sctp_byte_graph_dlg.c1185
-rw-r--r--gtk/sctp_error_dlg.c297
-rw-r--r--gtk/sctp_graph_dlg.c1108
-rw-r--r--gtk/sctp_stat.c1351
-rw-r--r--gtk/sctp_stat.h322
-rw-r--r--gtk/sctp_stat_dlg.c590
9 files changed, 5666 insertions, 1 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index eb176a58ef..5573528845 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -77,6 +77,7 @@ noinst_HEADERS = \
rtp_stream.h \
rtp_stream_dlg.h \
sat.h \
+ sctp_stat.h \
service_response_time_table.h \
stream_prefs.h \
summary_dlg.h \
diff --git a/gtk/Makefile.common b/gtk/Makefile.common
index 2037131579..8143a92785 100644
--- a/gtk/Makefile.common
+++ b/gtk/Makefile.common
@@ -70,6 +70,10 @@ ETHEREAL_GTK_SRC = \
range_utils.c \
recent.c \
rtp_stream.c \
+ sctp_stat.c \
+ sctp_graph_dlg.c \
+ sctp_byte_graph_dlg.c \
+ sctp_error_dlg.c \
service_response_time_table.c \
simple_dialog.c \
stream_prefs.c \
@@ -120,7 +124,9 @@ ETHEREAL_TAP_SRC = \
rpc_stat.c \
rtp_analysis.c \
rtp_stream_dlg.c \
- tcp_graph.c \
+ sctp_assoc_analyse.c \
+ sctp_stat_dlg.c \
sip_stat.c \
smb_stat.c \
+ tcp_graph.c \
wsp_stat.c
diff --git a/gtk/sctp_assoc_analyse.c b/gtk/sctp_assoc_analyse.c
new file mode 100644
index 0000000000..66e84b1cbb
--- /dev/null
+++ b/gtk/sctp_assoc_analyse.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
+ *
+ * $Id: sctp_assoc_analyse.c 11436 2004-07-19 21:42:01Z tuexen $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <string.h> //for memmove
+#include "globals.h"
+#include "simple_dialog.h"
+#include <epan/epan_dissect.h>
+#include "epan/filesystem.h"
+#include "register.h"
+#include "tap_menu.h"
+#include "dlg_utils.h"
+#include "ui_util.h"
+#include "main.h"
+#include "compat_macros.h"
+
+#include "sctp_stat.h"
+
+
+void
+decrease_childcount(struct sctp_analyse *parent)
+{
+ if (parent->num_children>0)
+ parent->num_children--;
+}
+
+void
+increase_childcount(struct sctp_analyse *parent)
+{
+ parent->num_children++;
+}
+
+void
+set_child(struct sctp_udata *child, struct sctp_analyse *parent)
+{
+ parent->children=g_list_append(parent->children, child);
+}
+
+void
+remove_child(struct sctp_udata *child, struct sctp_analyse *parent)
+{
+ parent->children=g_list_remove(parent->children, child);
+}
+
+static void
+on_destroy(GtkObject *object _U_, gpointer user_data)
+{
+struct sctp_analyse *u_data;
+guint16 i, j;
+GList *list;
+struct sctp_udata *child_data;
+
+u_data=(struct sctp_analyse*)user_data;
+
+ if (u_data->window)
+ {
+ gtk_grab_remove(GTK_WIDGET(u_data->window));
+ gtk_widget_destroy(GTK_WIDGET(u_data->window));
+ }
+ if (u_data->num_children>0)
+ {
+ j=u_data->num_children;
+ for (i=0; i<j; i++)
+ {
+ list=g_list_last(u_data->children);
+ child_data=(struct sctp_udata *)list->data;
+ gtk_grab_remove(GTK_WIDGET(child_data->io->window));
+ gtk_widget_destroy(GTK_WIDGET(child_data->io->window));
+ list=g_list_previous(list);
+ }
+ g_list_free(u_data->children);
+ u_data->children = NULL;
+ }
+ g_free(u_data->analyse_nb->page2);
+ g_free(u_data->analyse_nb->page3);
+ g_free(u_data->analyse_nb);
+ if (sctp_stat_get_info()->children!=NULL)
+ {
+ remove_analyse_child(u_data);
+ decrease_analyse_childcount();
+ }
+ g_free(u_data);
+}
+
+static void
+on_notebook_switch_page()
+{
+}
+
+static void on_error_bt()
+{
+
+ sctp_error_dlg_show();
+}
+
+static void on_close_dlg(GtkWidget *widget _U_, struct sctp_analyse* u_data)
+{
+
+ if (u_data->window)
+ {
+ gtk_grab_remove(GTK_WIDGET(u_data->window));
+ gtk_widget_destroy(GTK_WIDGET(u_data->window));
+ }
+}
+
+static void on_graph1_dlg(GtkWidget *widget _U_, struct sctp_analyse* u_data)
+{
+ create_graph(1, u_data);
+}
+
+static void on_graph2_dlg(GtkWidget *widget _U_, struct sctp_analyse* u_data)
+{
+ create_graph(2, u_data);
+}
+
+static void on_graph_byte1_dlg(GtkWidget *widget _U_, struct sctp_analyse* u_data)
+{
+ create_byte_graph(1, u_data);
+}
+
+static void on_graph_byte2_dlg(GtkWidget *widget _U_, struct sctp_analyse* u_data)
+{
+ create_byte_graph(2, u_data);
+}
+
+void
+update_analyse_dlg(struct sctp_analyse* u_data)
+{
+gchar label_txt[50];
+gchar *data[1];
+gchar field[1][32];
+gint added_row;
+GList *list;
+struct sockaddr_in *v4=NULL;
+struct sockaddr_in6 *v6=NULL;
+struct sockaddr_storage *store=NULL;
+
+if (u_data->assoc==NULL)
+ return;
+
+ if (u_data->window != NULL)
+ {
+ gtk_clist_clear(GTK_CLIST(u_data->analyse_nb->page2->clist));
+ gtk_clist_clear(GTK_CLIST(u_data->analyse_nb->page3->clist));
+ }
+
+
+ g_snprintf(label_txt, 50,"Checksum Type: %s",u_data->assoc->checksum_type);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->checktype), label_txt);
+ g_snprintf(label_txt, 50,"Checksum Errors: %u",u_data->assoc->n_checksum_errors);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->checksum), label_txt);
+ g_snprintf(label_txt, 50,"Bundling Errors: %u",u_data->assoc->n_bundling_errors);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->bundling), label_txt);
+ g_snprintf(label_txt, 50,"Padding Errors: %u",u_data->assoc->n_padding_errors);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->padding), label_txt);
+ g_snprintf(label_txt, 50,"Length Errors: %u",u_data->assoc->n_length_errors);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->length), label_txt);
+ g_snprintf(label_txt, 50,"Value Errors: %u",u_data->assoc->n_value_errors);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->value), label_txt);
+ g_snprintf(label_txt, 50,"No of Data Chunks from EP1 to EP2: %u",u_data->assoc->n_data_chunks_ep1);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->chunks_ep1), label_txt);
+ g_snprintf(label_txt, 50,"No of Data Bytes from EP1 to EP2: %u",u_data->assoc->n_data_bytes_ep1);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->bytes_ep1), label_txt);
+ g_snprintf(label_txt, 50,"No of Data Chunks from EP2 to EP1: %u",u_data->assoc->n_data_chunks_ep2);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->chunks_ep2), label_txt);
+ g_snprintf(label_txt, 50,"No of Data Bytes from EP2 to EP1: %u",u_data->assoc->n_data_bytes_ep2);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->bytes_ep2), label_txt);
+
+ if (u_data->assoc->init==TRUE)
+ gtk_frame_set_label(GTK_FRAME (u_data->analyse_nb->page2->addr_frame), "Complete list of IP-Addresses as provided in the INIT-Chunk");
+ else if (u_data->assoc->initack==TRUE && u_data->assoc->initack_dir==1)
+ gtk_frame_set_label(GTK_FRAME (u_data->analyse_nb->page2->addr_frame), "Complete list of IP-Addresses as provided in the INITACK-Chunk");
+ else
+ gtk_frame_set_label(GTK_FRAME (u_data->analyse_nb->page2->addr_frame), "List of used IP-Addresses");
+
+
+
+ if (u_data->assoc->addr1!=NULL)
+ {
+ list = g_list_first(u_data->assoc->addr1);
+ while (list)
+ {
+ data[0]=&field[0][0];
+ store = (struct sockaddr_storage *) (list->data);
+ if (store->ss_family==AF_INET)
+ {
+ v4 = (struct sockaddr_in *)(list->data);
+ g_snprintf(field[0], 30, "%s", ip_to_str((const guint8 *)&(v4->sin_addr.s_addr)));
+ }
+ else if (store->ss_family==AF_INET6)
+ {
+ v6 = (struct sockaddr_in6 *)(list->data);
+ g_snprintf(field[0], 30, "%s", ip6_to_str((const struct e_in6_addr *)&(v6->sin6_addr.s6_addr)));
+ }
+ added_row = gtk_clist_append(GTK_CLIST(u_data->analyse_nb->page2->clist), data);
+ gtk_clist_set_row_data(GTK_CLIST(u_data->analyse_nb->page2->clist), added_row, u_data->assoc);
+ list = g_list_next(list);
+ }
+ }
+ else
+ {
+ return;
+ }
+ g_snprintf(label_txt, 50,"Port: %u",u_data->assoc->port1);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page2->port), label_txt);
+ g_snprintf(label_txt, 50,"Sent Verification Tag: 0x%x",u_data->assoc->verification_tag1);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page2->veritag), label_txt);
+
+ if (u_data->assoc->init==TRUE || (u_data->assoc->initack==TRUE && u_data->assoc->initack_dir==1))
+ {
+ g_snprintf(label_txt, 50,"Requested Number of Inbound Streams: %u",u_data->assoc->instream1);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page2->max_in), label_txt);
+ g_snprintf(label_txt, 50,"Minimum Number of Inbound Streams: %u",((u_data->assoc->instream1>u_data->assoc->outstream2)?u_data->assoc->outstream2:u_data->assoc->instream1));
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page2->min_in), label_txt);
+
+ g_snprintf(label_txt, 50,"Provided Number of Outbound Streams: %u",u_data->assoc->outstream1);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page2->max_out), label_txt);
+ g_snprintf(label_txt, 50,"Minimum Number of Outbound Streams: %u",((u_data->assoc->outstream1>u_data->assoc->instream2)?u_data->assoc->instream2:u_data->assoc->outstream1));
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page2->max_out), label_txt);
+ }
+ else
+ {
+ g_snprintf(label_txt, 50,"Used Number of Inbound Streams: %u",u_data->assoc->instream1);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page2->max_in), label_txt);
+ g_snprintf(label_txt, 50,"Used Number of Outbound Streams: %u",u_data->assoc->outstream1);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page2->max_out), label_txt);
+ }
+
+ if (u_data->assoc->initack==TRUE && u_data->assoc->initack_dir==2)
+ gtk_frame_set_label(GTK_FRAME (u_data->analyse_nb->page3->addr_frame), "Complete list of IP-Addresses as provided in the INITACK-Chunk");
+ else
+ gtk_frame_set_label(GTK_FRAME (u_data->analyse_nb->page3->addr_frame), "List of used IP-Addresses");
+
+
+ if (u_data->assoc->addr2!=NULL)
+ {
+
+ list = g_list_first(u_data->assoc->addr2);
+
+ while (list)
+ {
+ data[0]=&field[0][0];
+ store = (struct sockaddr_storage *) (list->data);
+ if (store->ss_family==AF_INET)
+ {
+ v4 = (struct sockaddr_in *)(list->data);
+ g_snprintf(field[0], 30, "%s", ip_to_str((const guint8 *)&(v4->sin_addr.s_addr)));
+ }
+ else if (store->ss_family==AF_INET6)
+ {
+ v6 = (struct sockaddr_in6 *)(list->data);
+ g_snprintf(field[0], 30, "%s", ip6_to_str((const struct e_in6_addr *)&(v6->sin6_addr.s6_addr)));
+ }
+ added_row = gtk_clist_append(GTK_CLIST(u_data->analyse_nb->page3->clist), data);
+ gtk_clist_set_row_data(GTK_CLIST(u_data->analyse_nb->page3->clist), added_row, u_data->assoc);
+ list = g_list_next(list);
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ g_snprintf(label_txt, 50,"Port: %u",u_data->assoc->port2);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page3->port), label_txt);
+ g_snprintf(label_txt, 50,"Sent Verification Tag: 0x%x",u_data->assoc->verification_tag2);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page3->veritag), label_txt);
+
+ if (u_data->assoc->initack==TRUE)
+ {
+ g_snprintf(label_txt, 50,"Requested Number of Inbound Streams: %u",u_data->assoc->instream2);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page3->max_in), label_txt);
+ g_snprintf(label_txt, 50,"Minimum Number of Inbound Streams: %u",((u_data->assoc->instream2>u_data->assoc->outstream1)?u_data->assoc->outstream1:u_data->assoc->instream2));
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page3->min_in), label_txt);
+
+ g_snprintf(label_txt, 50,"Provided Number of Outbound Streams: %u",u_data->assoc->outstream2);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page3->max_out), label_txt);
+ g_snprintf(label_txt, 50,"Minimum Number of Outbound Streams: %u",((u_data->assoc->outstream2>u_data->assoc->instream1)?u_data->assoc->instream1:u_data->assoc->outstream2));
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page3->min_out), label_txt);
+ }
+ else
+ {
+ g_snprintf(label_txt, 50,"Used Number of Inbound Streams: %u",u_data->assoc->instream2);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page3->max_in), label_txt);
+ g_snprintf(label_txt, 50,"Used Number of Outbound Streams: %u",u_data->assoc->outstream2);
+ gtk_label_set_text(GTK_LABEL(u_data->analyse_nb->page3->min_out), label_txt);
+ }
+}
+
+static void analyse_window_set_title(struct sctp_analyse *u_data)
+{
+ char *title;
+ if(!u_data->window){
+ return;
+ }
+ title = g_strdup_printf("SCTP Analyse Association: %s Port1 %u Port2 %u",
+ cf_get_display_name(&cfile), u_data->assoc->port1, u_data->assoc->port2);
+ gtk_window_set_title(GTK_WINDOW(u_data->window), title);
+ g_free(title);
+}
+
+void create_analyse_window(struct sctp_analyse* u_data)
+{
+ GtkWidget *window = NULL;
+ GtkWidget *notebook;
+ GtkWidget *main_vb, *page1, *page2, *page3, *hbox, *vbox_l, *vbox_r, *addr_hb, *stat_fr;
+ GtkWidget *hbox_l1, *hbox_l2,*label, *h_button_box;
+ GtkWidget *error_bt, *close_bt, *graph_bt1, *graph_bt2;
+
+ u_data->analyse_nb = g_malloc(sizeof(struct notes));
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
+ SIGNAL_CONNECT(window, "destroy", on_destroy,u_data);
+
+ /* Container for each row of widgets */
+ main_vb = gtk_vbox_new(FALSE, 2);
+ gtk_container_border_width(GTK_CONTAINER(main_vb), 2);
+ gtk_container_add(GTK_CONTAINER(window), main_vb);
+ gtk_widget_show(main_vb);
+
+ /* Start a notebook for flipping between sets of changes */
+ notebook = gtk_notebook_new();
+ gtk_container_add(GTK_CONTAINER(main_vb), notebook);
+ OBJECT_SET_DATA(window, "notebook", notebook);
+ SIGNAL_CONNECT(notebook, "switch_page", on_notebook_switch_page,NULL);
+
+ page1 = gtk_vbox_new(FALSE, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(page1), 8);
+
+ u_data->analyse_nb->checktype = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->checktype, TRUE, TRUE, 0);
+
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->checktype),0,0);
+
+ u_data->analyse_nb->checksum = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->checksum, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->checksum),0,0);
+
+ u_data->analyse_nb->bundling = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->bundling, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->bundling),0,0);
+
+ u_data->analyse_nb->padding = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->padding, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->padding),0,0);
+
+ u_data->analyse_nb->length = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->length, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->length),0,0);
+
+ u_data->analyse_nb->value = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->value, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->value),0,0);
+
+
+ u_data->analyse_nb->chunks_ep1 = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->chunks_ep1, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->chunks_ep1),0,0);
+ u_data->analyse_nb->bytes_ep1 = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->bytes_ep1, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->bytes_ep1),0,0);
+ u_data->analyse_nb->chunks_ep2 = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->chunks_ep2, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->chunks_ep2),0,0);
+ u_data->analyse_nb->bytes_ep2 = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(page1), u_data->analyse_nb->bytes_ep2, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->bytes_ep2),0,0);
+
+ hbox = gtk_hbutton_box_new();
+ gtk_box_pack_start(GTK_BOX(page1), hbox, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX (hbox), 0);
+ gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (hbox), 4, 0);
+ gtk_widget_show(hbox);
+
+ error_bt = gtk_button_new_with_label ("Show Errors");
+ gtk_box_pack_start(GTK_BOX(hbox), error_bt, FALSE, FALSE, 0);
+ gtk_widget_show(error_bt);
+ SIGNAL_CONNECT(error_bt, "clicked", on_error_bt, NULL);
+
+
+ close_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+ gtk_box_pack_start(GTK_BOX(hbox), close_bt, FALSE, FALSE, 0);
+ gtk_widget_show(close_bt);
+ SIGNAL_CONNECT(close_bt, "clicked", on_close_dlg, u_data);
+
+ /* tab */
+ label = gtk_label_new(" Statistics ");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page1, label);
+
+
+ /* page for endpoint 1 */
+ page2 = gtk_vbox_new(FALSE, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(page2), 8);
+
+ u_data->analyse_nb->page2 = g_malloc(sizeof(struct page));
+
+ u_data->analyse_nb->page2->addr_frame = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(page2), u_data->analyse_nb->page2->addr_frame);
+
+ addr_hb = gtk_hbox_new(FALSE, 3);
+ gtk_container_border_width(GTK_CONTAINER(addr_hb), 5);
+ gtk_container_add(GTK_CONTAINER(u_data->analyse_nb->page2->addr_frame), addr_hb);
+
+ u_data->analyse_nb->page2->scrolled_window = scrolled_window_new(NULL, NULL);
+ WIDGET_SET_SIZE(u_data->analyse_nb->page2->scrolled_window, 560, 100);
+
+ u_data->analyse_nb->page2->clist = gtk_clist_new(1);
+ gtk_widget_show(u_data->analyse_nb->page2->clist);
+
+ gtk_clist_set_column_width(GTK_CLIST(u_data->analyse_nb->page2->clist), 0, 200);
+ gtk_clist_set_column_justification(GTK_CLIST(u_data->analyse_nb->page2->clist), 0, GTK_JUSTIFY_LEFT);
+
+ gtk_container_add(GTK_CONTAINER(u_data->analyse_nb->page2->scrolled_window),
+ u_data->analyse_nb->page2->clist);
+
+ gtk_box_pack_start(GTK_BOX(addr_hb), u_data->analyse_nb->page2->scrolled_window, TRUE, TRUE, 0);
+ gtk_widget_show(u_data->analyse_nb->page2->scrolled_window);
+
+ stat_fr = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(page2), stat_fr);
+
+ hbox = gtk_hbox_new(FALSE,3);
+ gtk_container_border_width(GTK_CONTAINER(hbox), 5);
+ gtk_container_add(GTK_CONTAINER(stat_fr), hbox);
+
+ vbox_l=gtk_vbox_new(FALSE, 3);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox_l, TRUE, TRUE, 0);
+
+ hbox_l1=gtk_hbox_new(FALSE,3);
+ gtk_box_pack_start(GTK_BOX(vbox_l), hbox_l1, TRUE, TRUE, 0);
+
+ u_data->analyse_nb->page2->port = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(hbox_l1), u_data->analyse_nb->page2->port, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page2->port),0,0);
+
+ hbox_l2=gtk_hbox_new(FALSE,3);
+ gtk_box_pack_start(GTK_BOX(vbox_l), hbox_l2, TRUE, TRUE, 0);
+
+
+ u_data->analyse_nb->page2->veritag = gtk_label_new("");
+
+ gtk_box_pack_start(GTK_BOX(hbox_l2), u_data->analyse_nb->page2->veritag, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page2->veritag),0,0);
+ gtk_widget_show(vbox_l);
+
+ vbox_r=gtk_vbox_new(FALSE, 3);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox_r, TRUE, TRUE, 0);
+
+ u_data->analyse_nb->page2->max_in = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox_r), u_data->analyse_nb->page2->max_in, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page2->max_in),0,0);
+ u_data->analyse_nb->page2->min_in = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox_r), u_data->analyse_nb->page2->min_in, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page2->min_in),0,0);
+
+ u_data->analyse_nb->page2->max_out = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox_r), u_data->analyse_nb->page2->max_out, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page2->max_out),0,0);
+ u_data->analyse_nb->page2->min_out = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox_r), u_data->analyse_nb->page2->min_out, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page2->min_out),0,0);
+
+
+ gtk_widget_show(vbox_r);
+
+ h_button_box=gtk_hbutton_box_new();
+ gtk_box_pack_start(GTK_BOX(page2), h_button_box, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(h_button_box), 10);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX (h_button_box), GTK_BUTTONBOX_SPREAD);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX (h_button_box), 0);
+ gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (h_button_box), 4, 0);
+ gtk_widget_show(h_button_box);
+
+ graph_bt1 = gtk_button_new_with_label("Graph TSN");
+ gtk_box_pack_start(GTK_BOX(h_button_box), graph_bt1, FALSE, FALSE, 0);
+ gtk_widget_show(graph_bt1);
+ SIGNAL_CONNECT(graph_bt1, "clicked", on_graph1_dlg,u_data);
+
+ graph_bt2 = gtk_button_new_with_label("Graph Bytes");
+ gtk_box_pack_start(GTK_BOX(h_button_box), graph_bt2, FALSE, FALSE, 0);
+ gtk_widget_show(graph_bt2);
+ SIGNAL_CONNECT(graph_bt2, "clicked", on_graph_byte1_dlg,u_data);
+
+ close_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+ gtk_box_pack_start(GTK_BOX(h_button_box), close_bt, FALSE, FALSE, 0);
+ gtk_widget_show(close_bt);
+ SIGNAL_CONNECT(close_bt, "clicked", on_close_dlg, u_data);
+
+ label = gtk_label_new(" Endpoint 1 ");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page2, label);
+
+/* same page for endpoint 2*/
+ page3 = gtk_vbox_new(FALSE, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(page3), 8);
+ u_data->analyse_nb->page3 = g_malloc(sizeof(struct page));
+ u_data->analyse_nb->page3->addr_frame = gtk_frame_new(NULL);
+
+ gtk_container_add(GTK_CONTAINER(page3), u_data->analyse_nb->page3->addr_frame);
+
+ addr_hb = gtk_hbox_new(FALSE, 3);
+ gtk_container_border_width(GTK_CONTAINER(addr_hb), 5);
+ gtk_container_add(GTK_CONTAINER(u_data->analyse_nb->page3->addr_frame), addr_hb);
+
+ u_data->analyse_nb->page3->scrolled_window = scrolled_window_new(NULL, NULL);
+ WIDGET_SET_SIZE(u_data->analyse_nb->page3->scrolled_window, 560, 100);
+ u_data->analyse_nb->page3->scrolled_window = scrolled_window_new(NULL, NULL);
+ WIDGET_SET_SIZE(u_data->analyse_nb->page3->scrolled_window, 560, 100);
+ u_data->analyse_nb->page3->clist = gtk_clist_new(1);
+ gtk_widget_show(u_data->analyse_nb->page3->clist);
+
+ gtk_clist_set_column_width(GTK_CLIST(u_data->analyse_nb->page3->clist), 0, 200);
+ gtk_clist_set_column_justification(GTK_CLIST(u_data->analyse_nb->page3->clist), 0, GTK_JUSTIFY_LEFT);
+
+ gtk_container_add(GTK_CONTAINER(u_data->analyse_nb->page3->scrolled_window),
+ u_data->analyse_nb->page3->clist);
+
+ gtk_box_pack_start(GTK_BOX(addr_hb), u_data->analyse_nb->page3->scrolled_window, TRUE, TRUE, 0);
+ gtk_widget_show(u_data->analyse_nb->page3->scrolled_window);
+
+ stat_fr = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(page3), stat_fr);
+
+ hbox = gtk_hbox_new(FALSE,3);
+ gtk_container_border_width(GTK_CONTAINER(hbox), 5);
+ gtk_container_add(GTK_CONTAINER(stat_fr), hbox);
+
+ vbox_l=gtk_vbox_new(FALSE, 3);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox_l, TRUE, TRUE, 0);
+
+ hbox_l1=gtk_hbox_new(FALSE,3);
+ gtk_box_pack_start(GTK_BOX(vbox_l), hbox_l1, TRUE, TRUE, 0);
+
+ u_data->analyse_nb->page3->port = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(hbox_l1), u_data->analyse_nb->page3->port, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page3->port),0,0);
+
+ hbox_l2=gtk_hbox_new(FALSE,3);
+ gtk_box_pack_start(GTK_BOX(vbox_l), hbox_l2, TRUE, TRUE, 0);
+
+
+ u_data->analyse_nb->page3->veritag = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(hbox_l2), u_data->analyse_nb->page3->veritag, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page3->veritag),0,0);
+ gtk_widget_show(vbox_l);
+
+ vbox_r=gtk_vbox_new(FALSE, 3);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox_r, TRUE, TRUE, 0);
+
+ u_data->analyse_nb->page3->max_in = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox_r), u_data->analyse_nb->page3->max_in, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page3->max_in),0,0);
+ u_data->analyse_nb->page3->min_in = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox_r), u_data->analyse_nb->page3->min_in, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page3->min_in),0,0);
+
+ u_data->analyse_nb->page3->max_out = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox_r), u_data->analyse_nb->page3->max_out, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page3->max_out),0,0);
+ u_data->analyse_nb->page3->min_out = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox_r), u_data->analyse_nb->page3->min_out, TRUE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC(u_data->analyse_nb->page3->min_out),0,0);
+
+ gtk_widget_show(vbox_r);
+
+ h_button_box=gtk_hbutton_box_new();
+ gtk_box_pack_start(GTK_BOX(page3), h_button_box, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(h_button_box), 10);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX (h_button_box), GTK_BUTTONBOX_SPREAD);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX (h_button_box), 0);
+ gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (h_button_box), 4, 0);
+ gtk_widget_show(h_button_box);
+
+ graph_bt1 = gtk_button_new_with_label("Graph");
+ gtk_box_pack_start(GTK_BOX(h_button_box), graph_bt1, FALSE, FALSE, 0);
+ gtk_widget_show(graph_bt1);
+ SIGNAL_CONNECT(graph_bt1, "clicked", on_graph2_dlg, u_data);
+
+ graph_bt2 = gtk_button_new_with_label("Graph Bytes");
+ gtk_box_pack_start(GTK_BOX(h_button_box), graph_bt2, FALSE, FALSE, 0);
+ gtk_widget_show(graph_bt2);
+ SIGNAL_CONNECT(graph_bt2, "clicked", on_graph_byte2_dlg,u_data);
+
+
+ close_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+ gtk_box_pack_start(GTK_BOX(h_button_box), close_bt, FALSE, FALSE, 0);
+ gtk_widget_show(close_bt);
+ SIGNAL_CONNECT(close_bt, "clicked", on_close_dlg, u_data);
+
+ label = gtk_label_new(" Endpoint 2 ");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page3, label);
+
+ /* show all notebooks */
+ gtk_widget_show_all(notebook);
+
+ gtk_widget_show(window);
+
+ u_data->window=window;
+ analyse_window_set_title(u_data);
+
+ update_analyse_dlg(u_data);
+}
+
+
+
+void assoc_analyse(sctp_assoc_info_t* assoc)
+{
+struct sctp_analyse* u_data;
+
+ u_data = g_malloc(sizeof(struct sctp_analyse));
+ u_data->assoc=assoc;
+ u_data->window=NULL;
+ u_data->analyse_nb=NULL;
+ u_data->children=NULL;
+ u_data->num_children=0;
+ set_analyse_child(u_data);
+ increase_analyse_childcount();
+
+ create_analyse_window(u_data);
+}
+
+
+void sctp_analyse_cb(struct sctp_analyse* u_data)
+{
+guint32 ip_src;
+guint16 srcport;
+guint32 ip_dst;
+guint16 dstport;
+GList *list, *srclist, *dstlist;
+dfilter_t *sfcode;
+capture_file *cf;
+epan_dissect_t *edt;
+gint err;
+gchar *err_info;
+gboolean frame_matched;
+frame_data *fdata;
+gchar filter_text[256];
+sctp_assoc_info_t* assoc=NULL;
+struct sockaddr_in *src, *dst;
+
+ strcpy(filter_text,"sctp && ip");
+ if (!dfilter_compile(filter_text, &sfcode)) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, dfilter_error_msg);
+ return;
+ }
+
+ cf = &cfile;
+ fdata = cf->current_frame;
+
+ /* we are on the selected frame now */
+ if (fdata == NULL)
+ return; /* if we exit here it's an error */
+
+ /* dissect the current frame */
+ if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
+ cf->pd, fdata->cap_len, &err, &err_info)) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ cf_read_error_message(err, err_info), cf->filename);
+ return;
+ }
+
+ edt = epan_dissect_new(TRUE, FALSE);
+ epan_dissect_prime_dfilter(edt, sfcode);
+ epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
+ frame_matched = dfilter_apply_edt(sfcode, edt);
+
+ /* if it is not an sctp frame, show the dialog */
+
+ if (frame_matched != 1) {
+ epan_dissect_free(edt);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Please choose an SCTP packet!");
+ return;
+ }
+
+ g_memmove(&ip_src, edt->pi.src.data, 4);
+ g_memmove(&ip_dst, edt->pi.dst.data, 4);
+ srcport = edt->pi.srcport;
+ dstport = edt->pi.destport;
+
+ list = g_list_first(sctp_stat_get_info()->assoc_info_list);
+
+ while (list)
+ {
+ assoc = (sctp_assoc_info_t*)(list->data);
+
+ if (assoc->port1 == srcport && assoc->port2 == dstport)
+ {
+ srclist = g_list_first(assoc->addr1);
+ while(srclist)
+ {
+ src = (struct sockaddr_in *)(srclist->data);
+ if (src->sin_addr.s_addr == ip_src)
+ {
+ dstlist = g_list_first(assoc->addr2);
+ while(dstlist)
+ {
+ dst = (struct sockaddr_in *)(dstlist->data);
+ if (dst->sin_addr.s_addr == ip_dst)
+ {
+ u_data->assoc=assoc;
+ create_analyse_window(u_data);
+ return;
+ }
+ else
+ dstlist = g_list_next(dstlist);
+ }
+ }
+ else
+ srclist = g_list_next(srclist);
+ }
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Assoc not found!");
+ return;
+ }
+ else if (assoc->port2 == srcport && assoc->port1 == dstport)
+ {
+ srclist = g_list_first(assoc->addr2);
+ while(srclist)
+ {
+ src = (struct sockaddr_in *)(srclist->data);
+ if (src->sin_addr.s_addr == ip_src)
+ {
+ dstlist = g_list_first(assoc->addr1);
+ while(dstlist)
+ {
+ dst = (struct sockaddr_in *)(dstlist->data);
+ if (dst->sin_addr.s_addr == ip_dst)
+ {
+ u_data->assoc=assoc;
+ create_analyse_window(u_data);
+ return;
+ }
+ else
+ dstlist = g_list_next(dstlist);
+ }
+ }
+ else
+ srclist = g_list_next(srclist);
+ }
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "Assoc not found!");
+ return;
+ }
+ else
+ list = g_list_next(list);
+
+ }
+}
+
+
+void sctp_analyse_start(GtkWidget *w _U_, gpointer data _U_)
+{
+struct sctp_analyse * u_data;
+
+ /* Register the tap listener */
+ if (sctp_stat_get_info()->is_registered==FALSE)
+ register_tap_listener_sctp_stat();
+
+ sctp_stat_scan();
+
+ /* Show the dialog box with the list of streams */
+ u_data = g_malloc(sizeof(struct sctp_analyse));
+ u_data->assoc=NULL;
+ u_data->children=NULL;
+ u_data->analyse_nb=NULL;
+ u_data->window=NULL;
+ u_data->num_children=0;
+
+ sctp_analyse_cb(u_data);
+}
+
+
+void
+register_tap_listener_sctp_analyse(void)
+{
+ register_tap_menu_item("SCTP/Analyse Association", REGISTER_TAP_GROUP_NONE,
+ sctp_analyse_start, NULL, NULL, NULL);
+}
diff --git a/gtk/sctp_byte_graph_dlg.c b/gtk/sctp_byte_graph_dlg.c
new file mode 100644
index 0000000000..55ace70ec2
--- /dev/null
+++ b/gtk/sctp_byte_graph_dlg.c
@@ -0,0 +1,1185 @@
+/*
+ * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
+ *
+ * $Id: sctp_byte_graph_dlg.c 11436 2004-07-19 21:42:01Z tuexen $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "globals.h"
+#include "epan/filesystem.h"
+#include "../color.h"
+#include "tap_menu.h"
+#include "dlg_utils.h"
+#include "ui_util.h"
+#include "main.h"
+#include "compat_macros.h"
+#include "simple_dialog.h"
+#include "sctp_stat.h"
+
+#define DEFAULT_PIXELS_PER_TICK 2
+#define MAX_PIXELS_PER_TICK 4
+#define AUTO_MAX_YSCALE 0
+#define MAX_TICK_VALUES 5
+#define DEFAULT_TICK_VALUE 3
+#define MAX_YSCALE 22
+#define MAX_COUNT_TYPES 3
+
+#define COUNT_TYPE_FRAMES 0
+#define COUNT_TYPE_BYTES 1
+#define COUNT_TYPE_ADVANCED 2
+
+#define LEFT_BORDER 60
+#define RIGHT_BORDER 10
+#define TOP_BORDER 10
+#define BOTTOM_BORDER 50
+
+#define SUB_32(a, b) a-b
+#define MINI(a,b) (a<b)?a:b
+#define MAXI(a,b) (a>b)?a:b
+
+struct chunk_header {
+ guint8 type;
+ guint8 flags;
+ guint16 length;
+};
+
+struct data_chunk_header {
+ guint8 type;
+ guint8 flags;
+ guint16 length;
+ guint32 tsn;
+ guint16 sid;
+ guint16 ssn;
+ guint32 ppi;
+};
+
+struct init_chunk_header {
+ guint8 type;
+ guint8 flags;
+ guint16 length;
+ guint32 initiate_tag;
+ guint32 a_rwnd;
+ guint16 mos;
+ guint16 mis;
+ guint32 initial_tsn;
+};
+
+struct sack_chunk_header {
+ guint8 type;
+ guint8 flags;
+ guint16 length;
+ guint32 cum_tsn_ack;
+ guint32 a_rwnd;
+ guint16 nr_of_gaps;
+ guint16 nr_of_dups;
+ guint8 tsns[0];
+};
+
+struct gaps {
+ guint16 start;
+ guint16 end;
+};
+
+
+
+static void sctp_graph_set_title(struct sctp_udata *u_data);
+static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data);
+
+
+gint tsn_cmp(gconstpointer aa, gconstpointer bb)
+{
+ const struct tsn_sort* a = aa;
+ const struct tsn_sort* b = bb;
+
+ if (a->tsnumber<b->tsnumber) return -1;
+ if (a->tsnumber==b->tsnumber) return 0;
+ if (a->tsnumber>b->tsnumber) return 1;
+
+ return 0;
+}
+
+static void draw_sack_graph(struct sctp_udata *u_data)
+{
+GdkColor red_color = {0, 65535, 0, 0};
+GdkColor green_color = {0, 0, 65535, 0};
+GdkGC *red_gc, *green_gc;
+guint32 diff;
+GArray *array=NULL;
+guint32 min_tsn=0, max_tsn=0;
+guint32 i, size=0, start, end;
+gboolean more=FALSE;
+#if GTK_MAJOR_VERSION < 2
+ GdkColormap *colormap;
+#endif
+
+ red_gc = gdk_gc_new(u_data->io->draw_area->window);
+#if GTK_MAJOR_VERSION < 2
+ colormap = gtk_widget_get_colormap (u_data->io->draw_area);
+ if (!gdk_color_alloc (colormap, &red_color))
+ {
+ g_warning ("Couldn't allocate color");
+ }
+
+ gdk_gc_set_foreground(red_gc, &red_color);
+#else
+ gdk_gc_set_rgb_fg_color(red_gc, &red_color);
+#endif
+
+ green_gc = gdk_gc_new(u_data->io->draw_area->window);
+#if GTK_MAJOR_VERSION < 2
+ colormap = gtk_widget_get_colormap (u_data->io->draw_area);
+ if (!gdk_color_alloc (colormap, &green_color))
+ {
+ g_warning ("Couldn't allocate color");
+ }
+
+ gdk_gc_set_foreground(green_gc, &green_color);
+#else
+ gdk_gc_set_rgb_fg_color(green_gc, &green_color);
+#endif
+
+ if (u_data->dir==1)
+ {
+ array = u_data->assoc->sort_sack1;
+ size=u_data->assoc->n_sack_chunks_ep1;
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=0;
+ max_tsn=u_data->assoc->max_bytes1;
+ }
+ else
+ {
+ min_tsn=u_data->io->tmp_min_tsn1;
+ max_tsn=u_data->io->tmp_max_tsn1;
+ }
+ }
+ else if (u_data->dir==2)
+ {
+ array = u_data->assoc->sort_sack2;
+ size=u_data->assoc->n_sack_chunks_ep2;
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=0;
+ max_tsn=u_data->assoc->max_bytes2;
+ }
+ else
+ {
+ min_tsn=u_data->io->tmp_min_tsn2;
+ max_tsn=u_data->io->tmp_max_tsn2;
+ }
+ }
+
+
+ for (i=0; i<size; i++)
+ {
+ diff=g_array_index(array, struct tsn_sort, i).secs*1000000+g_array_index(array, struct tsn_sort, i).usecs-u_data->io->min_x;
+ start=g_array_index(array, struct tsn_sort, i).offset;
+ end = start + g_array_index(array, struct tsn_sort, i).length;
+ if (end>max_tsn)
+ {
+ end=max_tsn;
+ more=TRUE;
+ }
+
+ if (start>=min_tsn)
+ {
+ gdk_draw_line(u_data->io->pixmap,red_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(start,min_tsn))*u_data->io->y_interval)),
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)));
+ if (more==TRUE)
+ {
+ gdk_draw_line(u_data->io->pixmap,green_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)),
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end+10,min_tsn))*u_data->io->y_interval)));
+ more=FALSE;
+ }
+ }
+
+ }
+#if GTK_MAJOR_VERSION >= 2
+ g_object_unref(G_OBJECT(red_gc));
+ g_object_unref(G_OBJECT(green_gc));
+#endif
+}
+
+
+static void draw_tsn_graph(struct sctp_udata *u_data)
+{
+GArray *array=NULL;
+guint32 min_tsn=0, max_tsn=0;
+guint32 diff, i, size=0, start, end;
+
+ if (u_data->dir==1)
+ {
+ array = u_data->assoc->sort_tsn1;
+ size=u_data->assoc->n_data_chunks_ep1;
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=0;
+ max_tsn=u_data->assoc->max_bytes1;
+ }
+ else
+ {
+ min_tsn=u_data->io->tmp_min_tsn1;
+ max_tsn=u_data->io->tmp_max_tsn1;
+ }
+ }
+ else if (u_data->dir==2)
+ {
+ array = u_data->assoc->sort_tsn2;
+ size=u_data->assoc->n_data_chunks_ep2;
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=0;
+ max_tsn=u_data->assoc->max_bytes2;
+ }
+ else
+ {
+ min_tsn=u_data->io->tmp_min_tsn2;
+ max_tsn=u_data->io->tmp_max_tsn2;
+ }
+ }
+
+ for (i=0; i<size; i++)
+ {
+ diff=g_array_index(array, struct tsn_sort, i).secs*1000000+g_array_index(array, struct tsn_sort, i).usecs-u_data->io->min_x;
+ start=g_array_index(array, struct tsn_sort, i).offset;
+ end = start + g_array_index(array, struct tsn_sort, i).length;
+ //printf("i=%u, start=%u, end=%u\n",i, start, end);
+ if (start>=min_tsn)
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(start,min_tsn))*u_data->io->y_interval)),
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)));
+
+ }
+
+}
+
+
+static void sctp_graph_draw(struct sctp_udata *u_data)
+{
+int length, lwidth, j, b;
+guint32 label_width, label_height, distance=5, i, e, sec, w, start, a;
+char label_string[15];
+gfloat dis;
+
+#if GTK_MAJOR_VERSION < 2
+ GdkFont *font;
+#else
+ PangoLayout *layout;
+#endif
+
+ if (u_data->io->x1_tmp_sec==0 && u_data->io->x1_tmp_usec==0)
+ u_data->io->offset=0;
+ else
+ u_data->io->offset=5;
+
+ u_data->io->min_x=u_data->io->x1_tmp_sec*1000000+u_data->io->x1_tmp_usec;
+ u_data->io->max_x=u_data->io->x2_tmp_sec*1000000+u_data->io->x2_tmp_usec;
+ u_data->io->tmp_width=u_data->io->max_x-u_data->io->min_x;
+
+ if (u_data->dir==1)
+ {
+ if (u_data->io->tmp==FALSE)
+ {
+ if (u_data->assoc->sort_tsn1!=NULL)// || u_data->assoc->sack1!=NULL)
+ u_data->io->max_y=u_data->io->tmp_max_tsn1 - u_data->io->tmp_min_tsn1;
+ else
+ u_data->io->max_y= 0;
+ u_data->io->min_y = 0;
+ }
+ else
+ {
+ u_data->io->max_y = u_data->io->tmp_max_tsn1;
+ u_data->io->min_y = u_data->io->tmp_min_tsn1;
+ }
+ }
+ else if (u_data->dir==2)
+ {
+ if (u_data->io->tmp==FALSE)
+ {
+ if (u_data->assoc->tsn2!=NULL)// || u_data->assoc->sack2!=NULL)
+ u_data->io->max_y=u_data->io->tmp_max_tsn2 -u_data->io->tmp_min_tsn2;
+ else
+ u_data->io->max_y= 0;
+ u_data->io->min_y = 0;
+ }
+ else
+ {
+ u_data->io->max_y = u_data->io->tmp_max_tsn2;
+ u_data->io->min_y = u_data->io->tmp_min_tsn2;
+ }
+ }
+ gdk_draw_rectangle(u_data->io->pixmap, u_data->io->draw_area->style->white_gc,
+ TRUE, 0, 0, u_data->io->draw_area->allocation.width,
+ u_data->io->draw_area->allocation.height);
+
+ distance=5;
+ //x_axis
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc, LEFT_BORDER+u_data->io->offset,u_data->io->pixmap_height-BOTTOM_BORDER,u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset, u_data->io->pixmap_height-BOTTOM_BORDER);
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset, u_data->io->pixmap_height-BOTTOM_BORDER, u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset-5, u_data->io->pixmap_height-BOTTOM_BORDER-5);
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset, u_data->io->pixmap_height-BOTTOM_BORDER, u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset-5, u_data->io->pixmap_height-BOTTOM_BORDER+5);
+ u_data->io->axis_width=u_data->io->pixmap_width-LEFT_BORDER-RIGHT_BORDER-u_data->io->offset;
+
+ u_data->io->x_interval = (u_data->io->axis_width*1.0)/u_data->io->tmp_width;
+
+ e=0;
+ if (u_data->io->x_interval<1)
+ {
+ dis=1/u_data->io->x_interval;
+ while (dis >1)
+ {
+ dis/=10;
+ e++;
+ }
+ distance=1;
+ for (i=0; i<=e+1; i++)
+ distance*=10;
+ }
+ else
+ distance=5;
+
+#if GTK_MAJOR_VERSION < 2
+ font = u_data->io->draw_area->style->font;
+#endif
+
+#if GTK_MAJOR_VERSION < 2
+ label_width=gdk_string_width(font, label_string);
+ label_height=gdk_string_height(font, label_string);
+#else
+ g_snprintf(label_string, 15, "%d", 0);
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
+ pango_layout_get_pixel_size(layout, &label_width, &label_height);
+
+#endif
+
+ if (u_data->io->x1_tmp_usec==0)
+ sec=u_data->io->x1_tmp_sec;
+ else
+ sec=u_data->io->x1_tmp_sec+1;
+
+ if (u_data->io->offset!=0)
+ {
+ g_snprintf(label_string, 15, "%u", u_data->io->x1_tmp_sec);
+#if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
+ LEFT_BORDER-10,
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ label_string);
+#else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+
+ gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ LEFT_BORDER-10,
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ layout);
+#endif
+}
+ w=(guint32)(500/(guint32)(distance*u_data->io->x_interval));
+ if (w==0)
+ w=1;
+ if (w==4)
+ {
+ w=5;
+ a=distance/10;
+ b=10+(((u_data->io->min_x/100000)-1)%5);
+ }
+ else
+ {
+ a=distance/5;
+ b=0;
+ }
+
+ if (a>1000000)
+ start=u_data->io->min_x/1000000*1000000;
+ else
+ {
+ start=u_data->io->min_x/100000;
+ if (start%2!=0)
+ start--;
+ start*=100000;
+ }
+
+
+ for (i=start, j=b; i<=u_data->io->max_x; i+=a, j++)
+ {
+ if (i>=u_data->io->min_x && i%1000000!=0)
+ {
+ length=5;
+ g_snprintf(label_string, 15, "%d", i%1000000);
+
+ if (j%w==0)
+ {
+ length=10;
+
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-lwidth/2),
+ u_data->io->pixmap_height-BOTTOM_BORDER+10,
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-lwidth/2),
+ u_data->io->pixmap_height-BOTTOM_BORDER+10,
+ layout);
+ #endif
+
+ }
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER+length);
+ }
+
+ if (i%1000000==0)
+ {
+ sec=i/1000000;
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER+10);
+
+ g_snprintf(label_string, 15, "%d", sec);
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+
+ gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ layout);
+ #endif
+ }
+ }
+
+ strcpy(label_string, "sec");
+
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,
+ font,
+ u_data->io->draw_area->style->black_gc,
+ u_data->io->pixmap_width-RIGHT_BORDER-10,
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(u_data->io->pixmap,
+ u_data->io->draw_area->style->black_gc,
+ u_data->io->pixmap_width-RIGHT_BORDER-10,
+ u_data->io->pixmap_height-BOTTOM_BORDER+25,
+ layout);
+ #endif
+
+ distance=5;
+
+ //y-axis
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc, LEFT_BORDER,TOP_BORDER-u_data->io->offset,LEFT_BORDER,u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset);
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,LEFT_BORDER,TOP_BORDER-u_data->io->offset, LEFT_BORDER-5, TOP_BORDER-u_data->io->offset+5);
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,LEFT_BORDER,TOP_BORDER-u_data->io->offset, LEFT_BORDER+5, TOP_BORDER-u_data->io->offset+5);
+
+ u_data->io->y_interval = ((u_data->io->pixmap_height-TOP_BORDER-BOTTOM_BORDER)*1.0)/(u_data->io->max_y-u_data->io->min_y);
+
+ e=0;
+ if (u_data->io->y_interval<1)
+ {
+ dis=1/u_data->io->y_interval;
+ while (dis >1)
+ {
+ dis/=10;
+ e++;
+ }
+ distance=1;
+ for (i=0; i<=e; i++)
+ distance=distance*10;
+ }
+
+ if (u_data->io->max_y>0)
+ {
+ for (i=u_data->io->min_y/distance*distance; i<=u_data->io->max_y; i+=distance/5)
+ {
+ if (i>=u_data->io->min_y)
+ {
+ length=5;
+ g_snprintf(label_string, 15, "%d", i);
+
+ if (i%distance==0 || (distance<=5 && u_data->io->y_interval>10))
+ {
+ length=10;
+
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
+ LEFT_BORDER-length-lwidth-5,
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval-3),
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ LEFT_BORDER-length-lwidth-5,
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval-3),
+ layout);
+ #endif
+ }
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,LEFT_BORDER-length,
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval)
+ ,LEFT_BORDER,
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval));
+ }
+ }
+}
+else
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
+}
+
+
+static void sctp_graph_redraw(struct sctp_udata *u_data)
+{
+sctp_graph_t *ios;
+
+ u_data->io->needs_redraw=TRUE;
+
+ sctp_graph_draw(u_data);
+ switch (u_data->io->graph_type)
+ {
+ case 0:
+ draw_sack_graph(u_data);
+ draw_tsn_graph(u_data);
+ break;
+ case 1: draw_tsn_graph(u_data);
+ break;
+ case 2:
+ draw_sack_graph(u_data);
+ break;
+ }
+ ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
+
+ if(!ios){
+ exit(10);
+ }
+
+
+ gdk_draw_pixmap(u_data->io->draw_area->window,
+ u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
+ ios->pixmap,
+ 0,0,
+ 0, 0,
+ u_data->io->draw_area->allocation.width,
+ u_data->io->draw_area->allocation.height);
+}
+
+
+static void on_sack_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+ u_data = (struct sctp_udata *) u_data;
+ u_data->io->graph_type=2;
+ sctp_graph_redraw(u_data);
+}
+
+static void on_tsn_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+ u_data->io->graph_type=1;
+ sctp_graph_redraw(u_data);
+}
+
+static void on_both_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+ u_data->io->graph_type=0;
+ sctp_graph_redraw(u_data);
+}
+
+static void
+sctp_graph_close_cb(GtkWidget* widget _U_, gpointer u_data)
+{
+struct sctp_udata *udata;
+int dir;
+
+ udata = (struct sctp_udata *)u_data;
+ dir=udata->dir-1;
+ gtk_grab_remove(GTK_WIDGET(udata->io->window));
+ gtk_widget_destroy(GTK_WIDGET(udata->io->window));
+
+}
+
+
+
+static gint
+configure_event(GtkWidget *widget, GdkEventConfigure *event _U_, struct sctp_udata *u_data)
+{
+ if(!u_data->io){
+ exit(10);
+ }
+
+ if(u_data->io->pixmap){
+ gdk_pixmap_unref(u_data->io->pixmap);
+ u_data->io->pixmap=NULL;
+ }
+
+ u_data->io->pixmap=gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+ u_data->io->pixmap_width=widget->allocation.width;
+ u_data->io->pixmap_height=widget->allocation.height;
+
+ gdk_draw_rectangle(u_data->io->pixmap,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+ return TRUE;
+}
+
+static gint
+expose_event(GtkWidget *widget, GdkEventExpose *event)
+{
+sctp_graph_t *ios;
+
+ ios=(sctp_graph_t *)OBJECT_GET_DATA(widget, "sctp_graph_t");
+ if(!ios){
+ exit(10);
+ }
+
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ ios->pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
+}
+
+
+static void
+on_zoomin_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+sctp_min_max_t *tmp_minmax;
+
+ if (u_data->io->rectangle==TRUE)
+ {
+ tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
+
+ u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
+ u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
+ u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
+ u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
+ tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
+ tmp_minmax->tmp_min_usecs= u_data->io->x1_tmp_usec;
+ tmp_minmax->tmp_max_secs= u_data->io->x2_tmp_sec;
+ tmp_minmax->tmp_max_usecs= u_data->io->x2_tmp_usec;
+ tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
+ tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
+ tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
+ tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
+ u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
+ u_data->io->length = g_slist_length(u_data->assoc->min_max);
+ u_data->io->tmp=TRUE;
+ u_data->io->rectangle=FALSE;
+ sctp_graph_redraw(u_data);
+ }
+}
+
+static void
+on_zoomout_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+sctp_min_max_t *tmp_minmax, *mm;
+gint l;
+
+
+ l = g_slist_length(u_data->assoc->min_max);
+
+ if (u_data->assoc->min_max!=NULL)
+ {
+ mm=(sctp_min_max_t *)((u_data->assoc->min_max)->data);
+ u_data->assoc->min_max=g_slist_remove(u_data->assoc->min_max, mm);
+ g_free(mm);
+
+ if (l>2)
+ {
+ tmp_minmax = (sctp_min_max_t *)u_data->assoc->min_max->data;
+ u_data->io->x1_tmp_sec=tmp_minmax->tmp_min_secs;
+ u_data->io->x1_tmp_usec=tmp_minmax->tmp_min_usecs;
+ u_data->io->x2_tmp_sec=tmp_minmax->tmp_max_secs;
+ u_data->io->x2_tmp_usec=tmp_minmax->tmp_max_usecs;
+ u_data->io->tmp_min_tsn1=tmp_minmax->tmp_min_tsn1;
+ u_data->io->tmp_max_tsn1=tmp_minmax->tmp_max_tsn1;
+ u_data->io->tmp_min_tsn2=tmp_minmax->tmp_min_tsn2;
+ u_data->io->tmp_max_tsn2=tmp_minmax->tmp_max_tsn2;
+ u_data->io->tmp=TRUE;
+ }
+ else
+ {
+ u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
+ u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
+ u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
+ u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
+ u_data->io->tmp_min_tsn1=0;
+ u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
+ u_data->io->tmp_min_tsn2=0;
+ u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
+ u_data->io->tmp=FALSE;
+ }
+ }
+ else
+ {
+ u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
+ u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
+ u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
+ u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
+ u_data->io->tmp_min_tsn1=0;
+ u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
+ u_data->io->tmp_min_tsn2=0;
+ u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
+ u_data->io->tmp=FALSE;
+ }
+ sctp_graph_redraw(u_data);
+}
+
+
+static gint
+on_button_press (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
+{
+sctp_graph_t *ios;
+
+ if (u_data->io->rectangle==TRUE)
+ {
+ gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->white_gc,
+ FALSE,
+ (gint)MINI(u_data->io->x_old,u_data->io->x_new),
+ (gint)MINI(u_data->io->y_old,u_data->io->y_new),
+ (gint)abs(u_data->io->x_new-u_data->io->x_old),
+ (gint)abs(u_data->io->y_new-u_data->io->y_old));
+ ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
+
+ if(!ios){
+ exit(10);
+ }
+
+ gdk_draw_pixmap(u_data->io->draw_area->window,
+ u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
+ ios->pixmap,
+ 0,0,
+ 0, 0,
+ (gint)abs(u_data->io->x_new-u_data->io->x_old),
+ (gint)abs(u_data->io->y_new-u_data->io->y_old));
+ sctp_graph_redraw(u_data);
+
+ }
+
+ u_data->io->x_old=event->x;
+ u_data->io->y_old=event->y;
+ if (u_data->io->y_old>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
+ u_data->io->y_old=u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
+ if (u_data->io->x_old<LEFT_BORDER+u_data->io->offset)
+ u_data->io->x_old=LEFT_BORDER+u_data->io->offset;
+ u_data->io->rectangle=FALSE;
+
+ return TRUE;
+}
+
+
+static gint
+on_button_release (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
+{
+sctp_graph_t *ios;
+guint32 helpx;
+guint32 helpy, x1_tmp, x2_tmp;
+
+if (event->y>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
+ event->y = u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
+if (event->x < LEFT_BORDER+u_data->io->offset)
+ event->x = LEFT_BORDER+u_data->io->offset;
+
+ if (abs(event->x-u_data->io->x_old)>10 || abs(event->y-u_data->io->y_old)>10)
+ {
+ gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ FALSE,
+ (gint)MINI(u_data->io->x_old,event->x), (gint)MINI(u_data->io->y_old,event->y),
+ (gint)abs(event->x-u_data->io->x_old),
+ (gint)abs(event->y-u_data->io->y_old));
+ ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
+
+ if(!ios){
+ exit(10);
+ }
+
+ gdk_draw_pixmap(u_data->io->draw_area->window,
+ u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
+ ios->pixmap,
+ 0,0,
+ 0, 0,
+ u_data->io->draw_area->allocation.width,
+ u_data->io->draw_area->allocation.height);
+
+ x1_tmp=u_data->io->min_x+((u_data->io->x_old-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width);
+ x2_tmp=u_data->io->min_x+((event->x-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width);
+ helpx=MINI(x1_tmp, x2_tmp);
+ if (helpx==x2_tmp)
+ {
+ x2_tmp=x1_tmp;
+ x1_tmp=helpx;
+ }
+ u_data->io->x1_tmp_sec=(guint32)x1_tmp/1000000;
+ u_data->io->x1_tmp_usec=x1_tmp%1000000;
+ u_data->io->x2_tmp_sec=(guint32)x2_tmp/1000000;
+ u_data->io->x2_tmp_usec=x2_tmp%1000000;
+
+ u_data->io->y1_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->y_old)/u_data->io->y_interval);
+ u_data->io->y2_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-event->y)/u_data->io->y_interval);
+ helpy = MINI(u_data->io->y1_tmp, u_data->io->y2_tmp);
+ u_data->io->y2_tmp = MAXI(u_data->io->y1_tmp, u_data->io->y2_tmp);
+ u_data->io->y1_tmp = helpy;
+ u_data->io->x_new=event->x;
+ u_data->io->y_new=event->y;
+ u_data->io->rectangle=TRUE;
+
+ }
+ return TRUE;
+}
+
+
+static void init_sctp_graph_window(struct sctp_udata *u_data)
+{
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *bt_close, *sack_bt, *tsn_bt, *both_bt, *zoomin_bt, *zoomout_bt;
+ GtkTooltips *tooltip_in, *tooltip_out;
+
+ /* create the main window */
+
+ u_data->io->window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_widget_set_name(u_data->io->window, "SCTP Graphics");
+
+ vbox=gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(u_data->io->window), vbox);
+ gtk_widget_show(vbox);
+
+ create_draw_area(vbox, u_data);
+
+ sctp_graph_set_title(u_data);
+
+ hbox = gtk_hbutton_box_new();
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX (hbox), 0);
+ gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
+ gtk_widget_show(hbox);
+
+ sack_bt = gtk_button_new_with_label ("Adv. Rec. Window");
+ gtk_box_pack_start(GTK_BOX(hbox), sack_bt, FALSE, FALSE, 0);
+ gtk_widget_show(sack_bt);
+
+ gtk_signal_connect(GTK_OBJECT(sack_bt), "clicked", (GtkSignalFunc)on_sack_bt, u_data);
+
+ tsn_bt = gtk_button_new_with_label ("Data bytes sent");
+ gtk_box_pack_start(GTK_BOX(hbox), tsn_bt, FALSE, FALSE, 0);
+ gtk_widget_show(tsn_bt);
+ SIGNAL_CONNECT(tsn_bt, "clicked", on_tsn_bt, u_data);
+
+ both_bt = gtk_button_new_with_label ("Show both");
+ gtk_box_pack_start(GTK_BOX(hbox), both_bt, FALSE, FALSE, 0);
+ gtk_widget_show(both_bt);
+ SIGNAL_CONNECT(both_bt, "clicked", on_both_bt, u_data);
+
+ zoomin_bt = gtk_button_new_with_label ("Zoom in");
+ gtk_box_pack_start(GTK_BOX(hbox), zoomin_bt, FALSE, FALSE, 0);
+ gtk_widget_show(zoomin_bt);
+ SIGNAL_CONNECT(zoomin_bt, "clicked", on_zoomin_bt, u_data);
+ tooltip_in = gtk_tooltips_new();
+ gtk_tooltips_set_tip(tooltip_in, zoomin_bt, "Draw a rectangle around the area you want to zoom in", NULL);
+
+ zoomout_bt = gtk_button_new_with_label ("Zoom out");
+ gtk_box_pack_start(GTK_BOX(hbox), zoomout_bt, FALSE, FALSE, 0);
+ gtk_widget_show(zoomout_bt);
+ SIGNAL_CONNECT(zoomout_bt, "clicked", on_zoomout_bt, u_data);
+ tooltip_out = gtk_tooltips_new();
+ gtk_tooltips_set_tip(tooltip_out, zoomout_bt, "Zoom out one step", NULL);
+
+
+ bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+ gtk_box_pack_start(GTK_BOX(hbox), bt_close, FALSE, FALSE, 0);
+ gtk_widget_show(bt_close);
+ SIGNAL_CONNECT(bt_close, "clicked", sctp_graph_close_cb, u_data);
+
+ gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_press_event",(GtkSignalFunc)on_button_press, u_data);
+ gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_release_event",(GtkSignalFunc)on_button_release, u_data);
+ gtk_widget_set_events(u_data->io->draw_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
+ //dlg_set_cancel(u_data->io->window, bt_close);
+
+
+ gtk_widget_show(u_data->io->window);
+}
+
+static void sctp_graph_set_title(struct sctp_udata *u_data)
+{
+ char *title;
+
+ if(!u_data->io->window){
+ return;
+ }
+ title = g_strdup_printf("SCTP Data and Adv.Rcv.Window over Time: %s Port1 %u Port2 %u Endpoint %u",
+ cf_get_display_name(&cfile), u_data->parent->assoc->port1, u_data->parent->assoc->port2, u_data->dir);
+ gtk_window_set_title(GTK_WINDOW(u_data->io->window), title);
+ g_free(title);
+}
+
+
+static void
+gtk_sctpgraph_init(struct sctp_udata *u_data)
+{
+sctp_graph_t *io;
+int dir;
+sctp_min_max_t* tmp_minmax;
+
+ io=g_malloc(sizeof(sctp_graph_t));
+ io->needs_redraw=TRUE;
+ io->x_interval=1000;
+ io->window=NULL;
+ io->draw_area=NULL;
+ io->pixmap=NULL;
+ io->pixmap_width=800;
+ io->pixmap_height=600;
+ io->graph_type=0;
+ dir=u_data->dir-1;
+ u_data->io=io;
+
+
+ u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
+ u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
+ u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
+ u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
+ u_data->io->tmp_min_tsn1=0;
+ u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
+ u_data->io->tmp_min_tsn2=0;
+ u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
+ u_data->io->tmp=FALSE;
+ tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
+ tmp_minmax->tmp_min_secs = u_data->assoc->min_secs;
+ tmp_minmax->tmp_min_usecs=u_data->assoc->min_usecs;
+ tmp_minmax->tmp_max_secs=u_data->assoc->max_secs;
+ tmp_minmax->tmp_max_usecs=u_data->assoc->max_usecs;
+ tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
+ tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
+ tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
+ tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
+ u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
+
+ /* build the GUI */
+ init_sctp_graph_window(u_data);
+ sctp_graph_redraw(u_data);
+}
+
+
+static gint
+quit(GtkObject *object _U_, gpointer user_data)
+{
+struct sctp_udata *u_data=(struct sctp_udata*)user_data;
+
+ decrease_childcount(u_data->parent);
+ remove_child(u_data, u_data->parent);
+ g_free(u_data->io);
+ u_data->assoc->min_max = NULL;
+ g_free(u_data);
+ return TRUE;
+}
+
+
+static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data)
+{
+ u_data->io->draw_area=gtk_drawing_area_new();
+ SIGNAL_CONNECT(u_data->io->draw_area, "destroy", quit, u_data);
+ OBJECT_SET_DATA(u_data->io->draw_area, "sctp_graph_t", u_data->io);
+
+ WIDGET_SET_SIZE(u_data->io->draw_area, u_data->io->pixmap_width, u_data->io->pixmap_height);
+
+ /* signals needed to handle backing pixmap */
+ SIGNAL_CONNECT(u_data->io->draw_area, "expose_event", expose_event, NULL);
+ SIGNAL_CONNECT(u_data->io->draw_area, "configure_event", configure_event, u_data);
+
+ gtk_widget_show(u_data->io->draw_area);
+ gtk_box_pack_start(GTK_BOX(box), u_data->io->draw_area, TRUE, TRUE, 0);
+}
+
+void insertion(GArray *array, guint32 N)
+{
+ guint32 i, j;
+ guint32 v;
+ struct tsn_sort help;
+
+ for (i=1; i<N; i++)
+ {
+ v = g_array_index(array, struct tsn_sort, i).tsnumber;
+ j=i;
+ while (g_array_index(array, struct tsn_sort, j-1).tsnumber > v)
+ {
+ help=g_array_index(array, struct tsn_sort, j);
+ g_array_index(array, struct tsn_sort, j)=g_array_index(array, struct tsn_sort, j-1);
+ g_array_index(array, struct tsn_sort, j-1)=help;
+ j--;
+ }
+ g_array_index(array, struct tsn_sort, j).tsnumber=v;
+ }
+}
+
+void set_arw_offsets(struct sctp_udata *u_data)
+{
+GArray *s_array=NULL, *t_array=NULL;
+guint32 i, j=0;
+
+ if (u_data->assoc->n_sack_chunks_ep1>0)
+ {
+ s_array=u_data->assoc->sort_sack1;
+ t_array=u_data->assoc->sort_tsn1;
+ insertion(s_array,u_data->assoc->n_sack_chunks_ep1);
+
+ for (i=0; i<u_data->assoc->n_sack_chunks_ep1; i++)
+ {
+ while (g_array_index(s_array, struct tsn_sort, i).tsnumber>g_array_index(t_array, struct tsn_sort, j).tsnumber)
+ {
+ j++;
+ }
+ g_array_index(s_array, struct tsn_sort, i).offset=g_array_index(t_array, struct tsn_sort, j).offset
+ +g_array_index(t_array, struct tsn_sort, j).length;
+ }
+
+ u_data->assoc->sort_sack1=s_array;
+ }
+
+ if (u_data->assoc->n_sack_chunks_ep2>0)
+ {
+ s_array=u_data->assoc->sort_sack2;
+ t_array=u_data->assoc->sort_tsn2;
+ insertion(s_array,u_data->assoc->n_sack_chunks_ep2);
+ j=0;
+ for (i=0; i<u_data->assoc->n_sack_chunks_ep2; i++)
+ {
+ while (g_array_index(s_array, struct tsn_sort, i).tsnumber>g_array_index(t_array, struct tsn_sort, j).tsnumber)
+ {
+ j++;
+ }
+ g_array_index(s_array, struct tsn_sort, i).offset=g_array_index(t_array, struct tsn_sort, j).offset
+ + g_array_index(t_array, struct tsn_sort, j).length;
+ }
+ u_data->assoc->sort_sack2=s_array;
+ }
+}
+
+void compute_offsets(struct sctp_udata *u_data)
+{
+struct tsn_sort t_sort, sort;
+GArray *array=NULL;
+guint32 i;
+guint32 sum=0;
+guint32 tsntmp=0;
+
+ if (u_data->assoc->n_array_tsn1>0)
+ {
+ array=u_data->assoc->sort_tsn1;
+ insertion(array,u_data->assoc->n_array_tsn1);
+
+ for (i=0; i<u_data->assoc->n_array_tsn1; i++)
+ {
+ g_array_index(array, struct tsn_sort, i).offset=sum;
+ if (g_array_index(array, struct tsn_sort, i).tsnumber>tsntmp)
+ sum+=g_array_index(array, struct tsn_sort, i).length;
+ tsntmp=t_sort.tsnumber;
+ }
+ u_data->assoc->max_bytes1=g_array_index(array, struct tsn_sort, i-1).offset+g_array_index(array, struct tsn_sort, i-1).length;
+ sort=g_array_index(array, struct tsn_sort,i-1);
+ u_data->assoc->sort_tsn1=array;
+ }
+ if (u_data->assoc->n_array_tsn2>0)
+ {
+ sum=0;
+ array=u_data->assoc->sort_tsn2;
+ insertion(array,u_data->assoc->n_array_tsn2);
+
+ for (i=0; i<u_data->assoc->n_array_tsn2; i++)
+ {
+ g_array_index(array, struct tsn_sort, i).offset=sum;
+ if (g_array_index(array, struct tsn_sort, i).tsnumber>tsntmp)
+ sum+=g_array_index(array, struct tsn_sort, i).length;
+ tsntmp=t_sort.tsnumber;
+ }
+
+ u_data->assoc->max_bytes2=g_array_index(array, struct tsn_sort, u_data->assoc->n_data_chunks_ep2-1).offset+g_array_index(array, struct tsn_sort, u_data->assoc->n_data_chunks_ep2-1).length;
+ u_data->assoc->sort_tsn2=array;
+ }
+}
+
+void create_byte_graph(guint16 dir, struct sctp_analyse* userdata)
+{
+struct sctp_udata *u_data;
+
+ u_data=g_malloc(sizeof(struct sctp_udata));
+ u_data->assoc=g_malloc(sizeof(sctp_assoc_info_t));
+ u_data->assoc=userdata->assoc;
+ u_data->io=NULL;
+ u_data->dir = dir;
+ u_data->parent = userdata;
+ set_child(u_data, u_data->parent);
+ increase_childcount(u_data->parent);
+ compute_offsets(u_data);
+ set_arw_offsets(u_data);
+ gtk_sctpgraph_init(u_data);
+
+}
+
diff --git a/gtk/sctp_error_dlg.c b/gtk/sctp_error_dlg.c
new file mode 100644
index 0000000000..bb30eb1586
--- /dev/null
+++ b/gtk/sctp_error_dlg.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
+ *
+ * $Id: sctp_error_dlg.c 11436 2004-07-19 21:42:01Z tuexen $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "globals.h"
+#include "epan/filesystem.h"
+
+#include "tap_menu.h"
+#include "dlg_utils.h"
+#include "ui_util.h"
+#include "main.h"
+#include "compat_macros.h"
+
+#include "sctp_stat.h"
+/*#include "sctp_assoc_analyse.h"*/
+
+
+static GtkWidget *sctp_error_dlg=NULL;
+static GtkWidget *clist = NULL;
+static GList *last_list = NULL;
+static sctp_error_info_t* selected_packet = NULL;/* current selection */
+//static sctp_assoc_info_t* selected_assoc = NULL;
+extern GtkWidget *main_display_filter_widget;
+
+
+#define NUM_COLS 3
+
+typedef struct column_arrows {
+ GtkWidget *table;
+ GtkWidget *ascend_pm;
+ GtkWidget *descend_pm;
+} column_arrows;
+
+
+static void
+dlg_destroy(void)
+{
+ sctp_error_dlg=NULL;
+}
+
+static void add_to_clist(sctp_error_info_t* errinfo)
+{
+ gint added_row, i;
+ gchar *data[NUM_COLS];
+ gchar field[NUM_COLS][30];
+
+ for (i=0; i<NUM_COLS; i++)
+ data[i]=&field[i][0];
+
+ /*printf("errinfo=%s\n",errinfo->chunk_info);*/
+
+ g_snprintf(field[0], 20, "%u", errinfo->frame_number);
+ g_snprintf(field[1], 20, "%s", errinfo->chunk_info);
+ g_snprintf(field[2], 20, "%s", errinfo->info_text);
+
+ added_row = gtk_clist_append(GTK_CLIST(clist), data);
+
+ /* set data pointer of last row to point to user data for that row */
+ gtk_clist_set_row_data(GTK_CLIST(clist), added_row, errinfo);
+}
+
+static void
+sctp_error_on_unselect(GtkButton *button _U_, gpointer user_data _U_)
+{
+ gtk_clist_unselect_all(GTK_CLIST(clist));
+}
+
+void sctp_error_dlg_update(GList *list)
+{
+GList *ilist=NULL;
+printf("dlg_update\n");
+ if (sctp_error_dlg != NULL) {
+ gtk_clist_clear(GTK_CLIST(clist));
+printf("vor ilist\n");
+ ilist=list;
+ if (ilist==NULL)
+ printf("=NULL\n");
+ printf("nach ilist\n");
+
+ while (ilist)
+ {
+ printf("while\n");
+ add_to_clist((sctp_error_info_t*)(ilist->data));
+ ilist = g_list_next(ilist);
+ }
+
+ sctp_error_on_unselect(NULL, NULL);
+ }
+printf("vor last_list\n");
+ last_list = ilist;
+}
+
+static void
+sctp_error_on_select_row(GtkCList *clist,
+ gint row,
+ gint column _U_,
+ GdkEventButton *event _U_,
+ gpointer user_data _U_)
+{
+selected_packet = gtk_clist_get_row_data(GTK_CLIST(clist), row);
+}
+
+
+
+static void
+sctp_error_on_frame (GtkButton *button _U_, gpointer user_data _U_)
+{
+
+ if (selected_packet==NULL)
+ return;
+
+ if (selected_packet)
+ goto_frame(&cfile, selected_packet->frame_number);
+}
+
+
+static void
+sctp_error_on_close (GtkButton *button _U_, gpointer user_data _U_)
+{
+ gtk_grab_remove(sctp_error_dlg);
+ gtk_widget_destroy(sctp_error_dlg);
+}
+
+static void
+gtk_sctperror_dlg(void)
+{
+ GtkWidget *sctp_error_dlg_w;
+ GtkWidget *vbox1;
+ GtkWidget *scrolledwindow1;
+ GtkWidget *hbuttonbox2;
+ GtkWidget *bt_unselect;
+ GtkWidget *bt_frame;
+ GtkWidget *bt_close;
+
+ gchar *titles[NUM_COLS] = {"Framenumber","Chunk Types", "Info"};
+ column_arrows *col_arrows;
+ GtkStyle *win_style;
+ GtkWidget *column_lb;
+ int i;
+
+ sctp_error_dlg_w = window_new (GTK_WINDOW_TOPLEVEL, "Ethereal: SCTP Associations");
+ gtk_window_set_position (GTK_WINDOW (sctp_error_dlg_w), GTK_WIN_POS_CENTER);
+ SIGNAL_CONNECT(sctp_error_dlg_w, "destroy", dlg_destroy,NULL);
+
+ /* Container for each row of widgets */
+ vbox1 = gtk_vbox_new(FALSE, 2);
+ gtk_container_border_width(GTK_CONTAINER(vbox1), 8);
+ gtk_container_add(GTK_CONTAINER(sctp_error_dlg_w), vbox1);
+ gtk_widget_show(vbox1);
+
+/* sctp_error_dlg_w = gtk_dialog_new();
+ gtk_window_set_title (GTK_WINDOW (sctp_error_dlg_w), "Ethereal: SCTP Malformed Packets");
+
+ dialog_vbox1 = GTK_DIALOG (sctp_error_dlg_w)->vbox;
+ gtk_widget_show (dialog_vbox1);
+
+ vbox1 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox1);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox1, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox1), 8);*/
+
+ scrolledwindow1 = scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scrolledwindow1);
+ gtk_box_pack_start (GTK_BOX (vbox1), scrolledwindow1, TRUE, TRUE, 0);
+
+ clist = gtk_clist_new (NUM_COLS);
+ gtk_widget_show (clist);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow1), clist);
+ WIDGET_SET_SIZE(clist, 500, 200);
+
+ gtk_clist_set_column_width (GTK_CLIST (clist), 0, 100);
+ gtk_clist_set_column_width (GTK_CLIST (clist), 1, 200);
+ gtk_clist_set_column_width (GTK_CLIST (clist), 2, 200);
+
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_LEFT);
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_LEFT);
+
+ gtk_clist_column_titles_show (GTK_CLIST (clist));
+
+ gtk_clist_set_sort_column(GTK_CLIST(clist), 0);
+ gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_ASCENDING);
+
+ gtk_widget_show(sctp_error_dlg_w);
+
+ col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
+ win_style = gtk_widget_get_style(scrolledwindow1);
+
+ for (i=0; i<NUM_COLS; i++) {
+ col_arrows[i].table = gtk_table_new(2, 2, FALSE);
+ gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
+ column_lb = gtk_label_new(titles[i]);
+ gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+ gtk_widget_show(column_lb);
+
+ gtk_clist_set_column_widget(GTK_CLIST(clist), i, col_arrows[i].table);
+ gtk_widget_show(col_arrows[i].table);
+ }
+
+
+ hbuttonbox2 = gtk_hbutton_box_new ();
+ gtk_widget_show (hbuttonbox2);
+ gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox2, FALSE, FALSE, 0);
+ gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox2), 5);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_SPREAD);
+
+
+ bt_unselect = gtk_button_new_with_label ("Unselect");
+ gtk_widget_show (bt_unselect);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_unselect);
+
+ bt_frame = gtk_button_new_with_label ("Go to Frame");
+ gtk_widget_show (bt_frame);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_frame);
+
+ bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+ gtk_widget_show (bt_close);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_close);
+
+ SIGNAL_CONNECT(sctp_error_dlg_w, "destroy", dlg_destroy, NULL);
+ SIGNAL_CONNECT(clist, "select_row", sctp_error_on_select_row, NULL);
+ SIGNAL_CONNECT(bt_unselect, "clicked", sctp_error_on_unselect, NULL);
+ SIGNAL_CONNECT(bt_frame, "clicked", sctp_error_on_frame, NULL);
+ SIGNAL_CONNECT(bt_close, "clicked", sctp_error_on_close, NULL);
+
+ sctp_error_dlg = sctp_error_dlg_w;
+
+
+}
+
+
+void sctp_error_dlg_show(sctp_assoc_info_t* assoc)
+{
+GList *list;
+
+printf("dlg_show\n");
+
+ //selected_assoc=(sctp_assoc_info_t*)get_selected_assoc();
+ list =assoc->error_info_list;
+ if (sctp_error_dlg != NULL) {
+ /* There's already a dialog box; reactivate it. */
+ reactivate_window(sctp_error_dlg);
+ /* Another list since last call? */
+ if (list != last_list) {
+ sctp_error_dlg_update(list);
+ }
+ }
+ else {
+ printf("else\n");
+ /* Create and show the dialog box */
+ gtk_sctperror_dlg();
+ sctp_error_dlg_update(list);
+ }
+}
+
+
+/*void sctp_error_start(GtkWidget *w _U_, gpointer data _U_)
+{
+ if (sctp_stat_get_info()->is_registered==FALSE)
+ register_tap_listener_sctp_stat();
+ sctp_stat_scan();
+ sctp_error_dlg_show(sctp_stat_get_info()->error_info_list);
+}*/
+
+/****************************************************************************/
+/*void
+register_tap_listener_sctp_error_dlg(void)
+{
+ register_tap_menu_item("SCTP/Show All Malformed Packets...", REGISTER_TAP_GROUP_NONE,
+ sctp_error_start, NULL, NULL, NULL);
+}*/
diff --git a/gtk/sctp_graph_dlg.c b/gtk/sctp_graph_dlg.c
new file mode 100644
index 0000000000..604805383c
--- /dev/null
+++ b/gtk/sctp_graph_dlg.c
@@ -0,0 +1,1108 @@
+/*
+ * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
+ *
+ * $Id: sctp_graph_dlg.c 11436 2004-07-19 21:42:01Z tuexen $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "globals.h"
+#include "epan/filesystem.h"
+#include "../color.h"
+#include "tap_menu.h"
+#include "dlg_utils.h"
+#include "ui_util.h"
+#include "main.h"
+#include "compat_macros.h"
+#include "simple_dialog.h"
+#include "sctp_stat.h"
+
+#define DEFAULT_PIXELS_PER_TICK 2
+#define MAX_PIXELS_PER_TICK 4
+#define AUTO_MAX_YSCALE 0
+#define MAX_TICK_VALUES 5
+#define DEFAULT_TICK_VALUE 3
+#define MAX_YSCALE 22
+#define MAX_COUNT_TYPES 3
+
+#define COUNT_TYPE_FRAMES 0
+#define COUNT_TYPE_BYTES 1
+#define COUNT_TYPE_ADVANCED 2
+
+#define LEFT_BORDER 50
+#define RIGHT_BORDER 10
+#define TOP_BORDER 10
+#define BOTTOM_BORDER 50
+
+#define SUB_32(a, b) a-b
+#define MINI(a,b) (a<b)?a:b
+#define MAXI(a,b) (a>b)?a:b
+
+struct chunk_header {
+ guint8 type;
+ guint8 flags;
+ guint16 length;
+};
+
+struct data_chunk_header {
+ guint8 type;
+ guint8 flags;
+ guint16 length;
+ guint32 tsn;
+ guint16 sid;
+ guint16 ssn;
+ guint32 ppi;
+};
+
+struct init_chunk_header {
+ guint8 type;
+ guint8 flags;
+ guint16 length;
+ guint32 initiate_tag;
+ guint32 a_rwnd;
+ guint16 mos;
+ guint16 mis;
+ guint32 initial_tsn;
+};
+
+struct sack_chunk_header {
+ guint8 type;
+ guint8 flags;
+ guint16 length;
+ guint32 cum_tsn_ack;
+ guint32 a_rwnd;
+ guint16 nr_of_gaps;
+ guint16 nr_of_dups;
+ guint8 tsns[0];
+};
+
+struct gaps {
+ guint16 start;
+ guint16 end;
+};
+
+
+
+static void sctp_graph_set_title(struct sctp_udata *u_data);
+static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data);
+
+
+static void draw_sack_graph(struct sctp_udata *u_data)
+{
+tsn_t *sack;
+GList *list=NULL, *tlist;
+guint16 gap_start=0, gap_end=0, i, j, nr;
+guint8 type;
+guint32 tsnumber, max_tsn=0, min_tsn=0;
+GdkColor red_color = {0, 65535, 0, 0};
+GdkColor green_color = {0, 0, 65535, 0};
+GdkGC *red_gc, *green_gc;
+struct sack_chunk_header *sack_header;
+struct gaps *gap;
+guint32 max_num, diff;
+#if GTK_MAJOR_VERSION < 2
+ GdkColormap *colormap;
+#endif
+
+ red_gc = gdk_gc_new(u_data->io->draw_area->window);
+ #if GTK_MAJOR_VERSION < 2
+ colormap = gtk_widget_get_colormap (u_data->io->draw_area);
+ if (!gdk_color_alloc (colormap, &red_color)){
+ g_warning ("Couldn't allocate color");
+ }
+
+ gdk_gc_set_foreground(red_gc, &red_color);
+ #else
+ gdk_gc_set_rgb_fg_color(red_gc, &red_color);
+ #endif
+
+ green_gc = gdk_gc_new(u_data->io->draw_area->window);
+ #if GTK_MAJOR_VERSION < 2
+ colormap = gtk_widget_get_colormap (u_data->io->draw_area);
+ if (!gdk_color_alloc (colormap, &green_color)){
+ g_warning ("Couldn't allocate color");
+ }
+
+ gdk_gc_set_foreground(green_gc, &green_color);
+ #else
+ gdk_gc_set_rgb_fg_color(green_gc, &green_color);
+ #endif
+
+ if (u_data->dir==2)
+ {
+
+ list = g_list_last(u_data->assoc->sack2);
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=u_data->assoc->min_tsn2;
+ max_tsn=u_data->assoc->max_tsn2;
+ }
+ else
+ {
+ min_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_min_tsn2;
+ max_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_max_tsn2;
+ }
+ }
+ else if (u_data->dir==1)
+ {
+ list = g_list_last(u_data->assoc->sack1);
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=u_data->assoc->min_tsn1;
+ max_tsn=u_data->assoc->max_tsn1;
+ }
+ else
+ {
+ min_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_min_tsn1;
+ max_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_max_tsn1;
+ }
+ }
+
+ while (list)
+ {
+ sack = (tsn_t*) (list->data);
+ tlist = g_list_first(sack->tsns);
+ while (tlist)
+ {
+ type = ((struct chunk_header *)tlist->data)->type;
+
+ if (type == SCTP_SACK_CHUNK_ID)
+ {
+ sack_header =(struct sack_chunk_header *)tlist->data;
+ nr=ntohs(sack_header->nr_of_gaps);
+ tsnumber = ntohl(sack_header->cum_tsn_ack);
+ if (nr>0)
+ {
+ gap = (struct gaps *)(sack_header->tsns+(4*(nr-1)));
+ gap_start=ntohs(gap->start);
+ gap_end = ntohs(gap->end);
+ max_num=gap_end+tsnumber;
+ }
+ else
+ max_num=tsnumber;
+
+ if (sack->secs>=u_data->io->x1_tmp_sec)
+ {
+ if (nr>0)
+ {
+ for(i=0;i<nr; i++)
+ {
+ for (j=gap_start; j<=gap_end; j++)
+ {
+ diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
+ gdk_draw_arc(u_data->io->pixmap,green_gc,TRUE,
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(j+tsnumber,min_tsn))*u_data->io->y_interval)),
+ 3, 3,0, (64*360) );
+ }
+ }
+ }
+ if (tsnumber>=min_tsn)
+ {
+ diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
+ gdk_draw_arc(u_data->io->pixmap,red_gc,TRUE,
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(tsnumber,min_tsn))*u_data->io->y_interval)),
+ 3, 3,0, (64*360) );
+ }
+ }
+ tlist = g_list_next(tlist);
+ }
+ }
+ list = g_list_previous(list);
+ }
+ #if GTK_MAJOR_VERSION >= 2
+ g_object_unref(G_OBJECT(red_gc));
+ g_object_unref(G_OBJECT(green_gc));
+ #endif
+}
+
+
+static void draw_tsn_graph(struct sctp_udata *u_data)
+{
+tsn_t *tsn;
+GList *list=NULL, *tlist;
+guint8 type;
+guint32 tsnumber=0, min_tsn=0, max_tsn=0;
+guint32 min_secs=0, diff;
+
+ if (u_data->dir==1)
+ {
+ list = g_list_last(u_data->assoc->tsn1);
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=u_data->assoc->min_tsn1;
+ max_tsn=u_data->assoc->max_tsn1;
+ }
+ else
+ {
+ min_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_min_tsn1;
+ max_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_max_tsn1;
+ }
+ }
+ else if (u_data->dir==2)
+ {
+ list = g_list_last(u_data->assoc->tsn2);
+ if (u_data->io->tmp==FALSE)
+ {
+ min_tsn=u_data->assoc->min_tsn2;
+ max_tsn=u_data->assoc->max_tsn2;
+ }
+ else
+ {
+ min_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_min_tsn2;
+ max_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_max_tsn2;
+ }
+ }
+
+ while (list)
+ {
+ tsn = (tsn_t*) (list->data);
+ tlist = g_list_first(tsn->tsns);
+ while (tlist)
+ {
+ type = ((struct chunk_header *)tlist->data)->type;
+ if (type == SCTP_DATA_CHUNK_ID)
+ tsnumber = ntohl(((struct data_chunk_header *)tlist->data)->tsn);
+
+ if (tsnumber>=min_tsn && tsnumber<=max_tsn && tsn->secs>=min_secs)
+ {
+ diff=tsn->secs*1000000+tsn->usecs-u_data->io->min_x;
+ gdk_draw_arc(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,TRUE,
+ (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(tsnumber,min_tsn))*u_data->io->y_interval)),
+ 3, 3, 0, (64*360));
+ }
+ tlist = g_list_next(tlist);
+ }
+ list = g_list_previous(list);
+ }
+
+}
+
+
+static void sctp_graph_draw(struct sctp_udata *u_data)
+{
+int length, lwidth, j, b;
+guint32 label_width, label_height, distance=5, i, e, sec, w, start, a;
+char label_string[15];
+gfloat dis;
+
+ #if GTK_MAJOR_VERSION < 2
+ GdkFont *font;
+ #else
+ PangoLayout *layout;
+ #endif
+
+ if (u_data->io->x1_tmp_sec==0 && u_data->io->x1_tmp_usec==0)
+ u_data->io->offset=0;
+ else
+ u_data->io->offset=5;
+
+ u_data->io->min_x=u_data->io->x1_tmp_sec*1000000+u_data->io->x1_tmp_usec;
+ u_data->io->max_x=u_data->io->x2_tmp_sec*1000000+u_data->io->x2_tmp_usec;
+ u_data->io->tmp_width=u_data->io->max_x-u_data->io->min_x;
+
+ if (u_data->dir==1)
+ {
+ if (u_data->io->tmp==FALSE)
+ {
+ if (u_data->assoc->tsn1!=NULL || u_data->assoc->sack1!=NULL)
+ u_data->io->max_y=u_data->io->tmp_max_tsn1 - u_data->io->tmp_min_tsn1;
+ else
+ u_data->io->max_y= 0;
+ u_data->io->min_y = 0;
+ }
+ else
+ {
+ u_data->io->max_y = u_data->io->tmp_max_tsn1;
+ u_data->io->min_y = u_data->io->tmp_min_tsn1;
+ }
+ }
+ else if (u_data->dir==2)
+ {
+ if (u_data->io->tmp==FALSE)
+ {
+ if (u_data->assoc->tsn2!=NULL || u_data->assoc->sack2!=NULL)
+ u_data->io->max_y=u_data->io->tmp_max_tsn2 -u_data->io->tmp_min_tsn2;
+ else
+ u_data->io->max_y= 0;
+ u_data->io->min_y = 0;
+ }
+ else
+ {
+ u_data->io->max_y = u_data->io->tmp_max_tsn2;
+ u_data->io->min_y = u_data->io->tmp_min_tsn2;
+ }
+ }
+
+ gdk_draw_rectangle(u_data->io->pixmap,
+ u_data->io->draw_area->style->white_gc,
+ TRUE,
+ 0, 0,
+ u_data->io->draw_area->allocation.width,
+ u_data->io->draw_area->allocation.height);
+
+ distance=5;
+ //x_axis
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc, LEFT_BORDER+u_data->io->offset,u_data->io->pixmap_height-BOTTOM_BORDER,u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset, u_data->io->pixmap_height-BOTTOM_BORDER);
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset, u_data->io->pixmap_height-BOTTOM_BORDER, u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset-5, u_data->io->pixmap_height-BOTTOM_BORDER-5);
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset, u_data->io->pixmap_height-BOTTOM_BORDER, u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset-5, u_data->io->pixmap_height-BOTTOM_BORDER+5);
+ u_data->io->axis_width=u_data->io->pixmap_width-LEFT_BORDER-RIGHT_BORDER-u_data->io->offset;
+
+ u_data->io->x_interval = (u_data->io->axis_width*1.0)/u_data->io->tmp_width;
+
+ e=0;
+ if (u_data->io->x_interval<1)
+ {
+ dis=1/u_data->io->x_interval;
+ while (dis >1)
+ {
+ dis/=10;
+ e++;
+ }
+ distance=1;
+ for (i=0; i<=e+1; i++)
+ distance*=10;
+ }
+ else
+ distance=5;
+
+ #if GTK_MAJOR_VERSION < 2
+ font = u_data->io->draw_area->style->font;
+ #endif
+
+ #if GTK_MAJOR_VERSION < 2
+ label_width=gdk_string_width(font, label_string);
+ label_height=gdk_string_height(font, label_string);
+ #else
+ g_snprintf(label_string, 15, "%d", 0);
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
+ pango_layout_get_pixel_size(layout, &label_width, &label_height);
+
+ #endif
+
+ if (u_data->io->x1_tmp_usec==0)
+ sec=u_data->io->x1_tmp_sec;
+ else
+ sec=u_data->io->x1_tmp_sec+1;
+
+
+ if (u_data->io->offset!=0)
+ {
+ g_snprintf(label_string, 15, "%u", u_data->io->x1_tmp_sec);
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
+ LEFT_BORDER-10,
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+
+ gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ LEFT_BORDER-10,
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ layout);
+ #endif
+}
+
+ w=(guint32)(500/(guint32)(distance*u_data->io->x_interval));
+ if (w==0)
+ w=1;
+ if (w==4)
+ {
+ w=5;
+ a=distance/10;
+ b=10+(((u_data->io->min_x/100000)-1)%5);
+ }
+ else
+ {
+ a=distance/5;
+ b=0;
+ }
+
+ if (a>1000000)
+ start=u_data->io->min_x/1000000*1000000;
+ else
+ {
+ start=u_data->io->min_x/100000;
+ if (start%2!=0)
+ start--;
+ start*=100000;
+ }
+
+
+ for (i=start, j=b; i<=u_data->io->max_x; i+=a, j++)
+ {
+ if (i>=u_data->io->min_x && i%1000000!=0)
+ {
+ length=5;
+ g_snprintf(label_string, 15, "%d", i%1000000);
+
+ if (j%w==0)
+ {
+ length=10;
+
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-lwidth/2),
+ u_data->io->pixmap_height-BOTTOM_BORDER+10,
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-lwidth/2),
+ u_data->io->pixmap_height-BOTTOM_BORDER+10,
+ layout);
+ #endif
+ }
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER+length);
+ }
+
+ if (i%1000000==0)
+ {
+ sec=i/1000000;
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER+10);
+
+ g_snprintf(label_string, 15, "%d", sec);
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+
+ gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ layout);
+ #endif
+ }
+ }
+
+ strcpy(label_string, "sec");
+
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,
+ font,
+ u_data->io->draw_area->style->black_gc,
+ u_data->io->pixmap_width-RIGHT_BORDER-10,
+ u_data->io->pixmap_height-BOTTOM_BORDER+20,
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(u_data->io->pixmap,
+ u_data->io->draw_area->style->black_gc,
+ u_data->io->pixmap_width-RIGHT_BORDER-10,
+ u_data->io->pixmap_height-BOTTOM_BORDER+25,
+ layout);
+ #endif
+
+ distance=5;
+
+ //y-axis
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc, LEFT_BORDER,TOP_BORDER-u_data->io->offset,LEFT_BORDER,u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset);
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,LEFT_BORDER,TOP_BORDER-u_data->io->offset, LEFT_BORDER-5, TOP_BORDER-u_data->io->offset+5);
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,LEFT_BORDER,TOP_BORDER-u_data->io->offset, LEFT_BORDER+5, TOP_BORDER-u_data->io->offset+5);
+
+ u_data->io->y_interval = ((u_data->io->pixmap_height-TOP_BORDER-BOTTOM_BORDER)*1.0)/(u_data->io->max_y-u_data->io->min_y);
+
+ e=0;
+ if (u_data->io->y_interval<1)
+ {
+ dis=1/u_data->io->y_interval;
+ while (dis >1)
+ {
+ dis/=10;
+ e++;
+ }
+ distance=1;
+ for (i=0; i<=e; i++)
+ distance=distance*10;
+ }
+
+ if (u_data->io->max_y>0)
+ {
+ for (i=u_data->io->min_y/distance*distance; i<=u_data->io->max_y; i+=distance/5)
+ {
+ if (i>=u_data->io->min_y)
+ {
+ length=5;
+ g_snprintf(label_string, 15, "%d", i);
+
+ if (i%distance==0 || (distance<=5 && u_data->io->y_interval>10))
+ {
+ length=10;
+
+ #if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
+ LEFT_BORDER-length-lwidth-5,
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval-3),
+ label_string);
+ #else
+ memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ LEFT_BORDER-length-lwidth-5,
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval-3),
+ layout);
+ #endif
+ }
+ gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,LEFT_BORDER-length,
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval)
+ ,LEFT_BORDER,
+ (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval));
+ }
+ }
+ }
+ else
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
+}
+
+
+static void sctp_graph_redraw(struct sctp_udata *u_data)
+{
+sctp_graph_t *ios;
+
+ u_data->io->needs_redraw=TRUE;
+
+ sctp_graph_draw(u_data);
+ switch (u_data->io->graph_type)
+ {
+ case 0:
+ draw_sack_graph(u_data);
+ draw_tsn_graph(u_data);
+ break;
+ case 1: draw_tsn_graph(u_data);
+ break;
+ case 2:
+ draw_sack_graph(u_data);
+ break;
+ }
+ ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
+
+ if(!ios){
+ exit(10);
+ }
+
+
+ gdk_draw_pixmap(u_data->io->draw_area->window,
+ u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
+ ios->pixmap,
+ 0,0,
+ 0, 0,
+ u_data->io->draw_area->allocation.width,
+ u_data->io->draw_area->allocation.height);
+}
+
+
+static void on_sack_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+
+ u_data = (struct sctp_udata *) u_data;
+ u_data->io->graph_type=2;
+ sctp_graph_redraw(u_data);
+}
+
+static void on_tsn_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+
+ u_data->io->graph_type=1;
+ sctp_graph_redraw(u_data);
+}
+
+static void on_both_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+
+ u_data->io->graph_type=0;
+ sctp_graph_redraw(u_data);
+}
+
+static void
+sctp_graph_close_cb(GtkWidget* widget _U_, gpointer u_data)
+{
+struct sctp_udata *udata;
+int dir;
+
+ udata = (struct sctp_udata *)u_data;
+ dir=udata->dir-1;
+ gtk_grab_remove(GTK_WIDGET(udata->io->window));
+ gtk_widget_destroy(GTK_WIDGET(udata->io->window));
+
+}
+
+
+
+static gint
+configure_event(GtkWidget *widget, GdkEventConfigure *event _U_, struct sctp_udata *u_data)
+{
+ if(!u_data->io){
+ exit(10);
+ }
+
+ if(u_data->io->pixmap){
+ gdk_pixmap_unref(u_data->io->pixmap);
+ u_data->io->pixmap=NULL;
+ }
+
+ u_data->io->pixmap=gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+ u_data->io->pixmap_width=widget->allocation.width;
+ u_data->io->pixmap_height=widget->allocation.height;
+
+ gdk_draw_rectangle(u_data->io->pixmap,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ return TRUE;
+}
+
+static gint
+expose_event(GtkWidget *widget, GdkEventExpose *event)
+{
+ sctp_graph_t *ios;
+
+ ios=(sctp_graph_t *)OBJECT_GET_DATA(widget, "sctp_graph_t");
+ if(!ios){
+ exit(10);
+ }
+
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ ios->pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
+}
+
+
+static void
+on_zoomin_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+sctp_min_max_t *tmp_minmax;
+
+ if (u_data->io->rectangle==TRUE)
+ {
+ tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
+
+ u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
+ u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
+ u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
+ u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
+ tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
+ tmp_minmax->tmp_min_usecs= u_data->io->x1_tmp_usec;
+ tmp_minmax->tmp_max_secs= u_data->io->x2_tmp_sec;
+ tmp_minmax->tmp_max_usecs= u_data->io->x2_tmp_usec;
+ tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
+ tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
+ tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
+ tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
+ u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
+ u_data->io->length = g_slist_length(u_data->assoc->min_max);
+ u_data->io->tmp=TRUE;
+ u_data->io->rectangle=FALSE;
+ sctp_graph_redraw(u_data);
+ }
+}
+
+static void
+on_zoomout_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
+{
+sctp_min_max_t *tmp_minmax, *mm;
+gint l;
+
+
+ l = g_slist_length(u_data->assoc->min_max);
+
+ if (u_data->assoc->min_max!=NULL)
+ {
+ mm=(sctp_min_max_t *)((u_data->assoc->min_max)->data);
+ u_data->assoc->min_max=g_slist_remove(u_data->assoc->min_max, mm);
+ g_free(mm);
+ if (l>2)
+ {
+ tmp_minmax = (sctp_min_max_t *)u_data->assoc->min_max->data;
+ u_data->io->x1_tmp_sec=tmp_minmax->tmp_min_secs;
+ u_data->io->x1_tmp_usec=tmp_minmax->tmp_min_usecs;
+ u_data->io->x2_tmp_sec=tmp_minmax->tmp_max_secs;
+ u_data->io->x2_tmp_usec=tmp_minmax->tmp_max_usecs;
+ u_data->io->tmp_min_tsn1=tmp_minmax->tmp_min_tsn1;
+ u_data->io->tmp_max_tsn1=tmp_minmax->tmp_max_tsn1;
+ u_data->io->tmp_min_tsn2=tmp_minmax->tmp_min_tsn2;
+ u_data->io->tmp_max_tsn2=tmp_minmax->tmp_max_tsn2;
+ u_data->io->tmp=TRUE;
+ }
+ else
+ {
+ u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
+ u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
+ u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
+ u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
+ u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
+ u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
+ u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
+ u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
+ u_data->io->tmp=FALSE;
+ }
+ }
+ else
+ {
+ u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
+ u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
+ u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
+ u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
+ u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
+ u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
+ u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
+ u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
+ u_data->io->tmp=FALSE;
+ }
+
+ sctp_graph_redraw(u_data);
+}
+
+
+static gint
+on_button_press (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
+{
+sctp_graph_t *ios;
+
+ if (u_data->io->rectangle==TRUE)
+ {
+ gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->white_gc,
+ FALSE,
+ (gint)MINI(u_data->io->x_old,u_data->io->x_new),
+ (gint)MINI(u_data->io->y_old,u_data->io->y_new),
+ (gint)abs(u_data->io->x_new-u_data->io->x_old),
+ (gint)abs(u_data->io->y_new-u_data->io->y_old));
+ ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
+
+ if(!ios){
+ exit(10);
+ }
+
+ gdk_draw_pixmap(u_data->io->draw_area->window,
+ u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
+ ios->pixmap,
+ 0,0,
+ 0, 0,
+ (gint)abs(u_data->io->x_new-u_data->io->x_old),
+ (gint)abs(u_data->io->y_new-u_data->io->y_old));
+ sctp_graph_redraw(u_data);
+
+ }
+
+ u_data->io->x_old=event->x;
+ u_data->io->y_old=event->y;
+ if (u_data->io->y_old>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
+ u_data->io->y_old=u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
+ if (u_data->io->x_old<LEFT_BORDER+u_data->io->offset)
+ u_data->io->x_old=LEFT_BORDER+u_data->io->offset;
+ u_data->io->rectangle=FALSE;
+
+ return TRUE;
+}
+
+
+static gint
+on_button_release (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
+{
+sctp_graph_t *ios;
+guint32 helpx;
+guint32 helpy, x1_tmp, x2_tmp;
+
+if (event->y>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
+ event->y = u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
+if (event->x < LEFT_BORDER+u_data->io->offset)
+ event->x = LEFT_BORDER+u_data->io->offset;
+ if (abs(event->x-u_data->io->x_old)>10 || abs(event->y-u_data->io->y_old)>10)
+ {
+ gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
+ FALSE,
+ (gint)MINI(u_data->io->x_old,event->x), (gint)MINI(u_data->io->y_old,event->y),
+ (gint)abs(event->x-u_data->io->x_old),
+ (gint)abs(event->y-u_data->io->y_old));
+ ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
+
+ if(!ios){
+ exit(10);
+ }
+
+ gdk_draw_pixmap(u_data->io->draw_area->window,
+ u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
+ ios->pixmap,
+ 0,0,
+ 0, 0,
+ u_data->io->draw_area->allocation.width,
+ u_data->io->draw_area->allocation.height);
+
+ x1_tmp=u_data->io->min_x+((u_data->io->x_old-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width);
+ x2_tmp=u_data->io->min_x+((event->x-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width);
+ helpx=MINI(x1_tmp, x2_tmp);
+ if (helpx==x2_tmp)
+ {
+ x2_tmp=x1_tmp;
+ x1_tmp=helpx;
+ }
+ u_data->io->x1_tmp_sec=(guint32)x1_tmp/1000000;
+ u_data->io->x1_tmp_usec=x1_tmp%1000000;
+ u_data->io->x2_tmp_sec=(guint32)x2_tmp/1000000;
+ u_data->io->x2_tmp_usec=x2_tmp%1000000;
+
+ u_data->io->y1_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->y_old)/u_data->io->y_interval);
+ u_data->io->y2_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-event->y)/u_data->io->y_interval);
+ helpy = MINI(u_data->io->y1_tmp, u_data->io->y2_tmp);
+ u_data->io->y2_tmp = MAXI(u_data->io->y1_tmp, u_data->io->y2_tmp);
+ u_data->io->y1_tmp = helpy;
+ u_data->io->x_new=event->x;
+ u_data->io->y_new=event->y;
+ u_data->io->rectangle=TRUE;
+
+ }
+
+ return TRUE;
+}
+
+
+static void init_sctp_graph_window(struct sctp_udata *u_data)
+{
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *bt_close, *sack_bt, *tsn_bt, *both_bt, *zoomin_bt, *zoomout_bt;
+ GtkTooltips *tooltip_in, *tooltip_out;
+
+ /* create the main window */
+
+ u_data->io->window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_widget_set_name(u_data->io->window, "SCTP Graphics");
+
+ vbox=gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(u_data->io->window), vbox);
+ gtk_widget_show(vbox);
+
+ create_draw_area(vbox, u_data);
+
+ sctp_graph_set_title(u_data);
+
+ hbox = gtk_hbutton_box_new();
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX (hbox), 0);
+ gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
+ gtk_widget_show(hbox);
+
+ sack_bt = gtk_button_new_with_label ("Show Sacks");
+ gtk_box_pack_start(GTK_BOX(hbox), sack_bt, FALSE, FALSE, 0);
+ gtk_widget_show(sack_bt);
+
+ gtk_signal_connect(GTK_OBJECT(sack_bt), "clicked", (GtkSignalFunc)on_sack_bt, u_data);
+
+ tsn_bt = gtk_button_new_with_label ("Show TSNs");
+ gtk_box_pack_start(GTK_BOX(hbox), tsn_bt, FALSE, FALSE, 0);
+ gtk_widget_show(tsn_bt);
+ SIGNAL_CONNECT(tsn_bt, "clicked", on_tsn_bt, u_data);
+
+ both_bt = gtk_button_new_with_label ("Show both");
+ gtk_box_pack_start(GTK_BOX(hbox), both_bt, FALSE, FALSE, 0);
+ gtk_widget_show(both_bt);
+ SIGNAL_CONNECT(both_bt, "clicked", on_both_bt, u_data);
+
+ zoomin_bt = gtk_button_new_with_label ("Zoom in");
+ gtk_box_pack_start(GTK_BOX(hbox), zoomin_bt, FALSE, FALSE, 0);
+ gtk_widget_show(zoomin_bt);
+ SIGNAL_CONNECT(zoomin_bt, "clicked", on_zoomin_bt, u_data);
+ tooltip_in = gtk_tooltips_new();
+ gtk_tooltips_set_tip(tooltip_in, zoomin_bt, "Draw a rectangle around the area you want to zoom in", NULL);
+
+ zoomout_bt = gtk_button_new_with_label ("Zoom out");
+ gtk_box_pack_start(GTK_BOX(hbox), zoomout_bt, FALSE, FALSE, 0);
+ gtk_widget_show(zoomout_bt);
+ SIGNAL_CONNECT(zoomout_bt, "clicked", on_zoomout_bt, u_data);
+ tooltip_out = gtk_tooltips_new();
+ gtk_tooltips_set_tip(tooltip_out, zoomout_bt, "Zoom out one step", NULL);
+
+
+ bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+ gtk_box_pack_start(GTK_BOX(hbox), bt_close, FALSE, FALSE, 0);
+ gtk_widget_show(bt_close);
+ SIGNAL_CONNECT(bt_close, "clicked", sctp_graph_close_cb, u_data);
+
+ gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_press_event",(GtkSignalFunc)on_button_press, u_data);
+ gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_release_event",(GtkSignalFunc)on_button_release, u_data);
+ gtk_widget_set_events(u_data->io->draw_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
+ //dlg_set_cancel(u_data->io->window, bt_close);
+
+ gtk_widget_show(u_data->io->window);
+}
+
+static void sctp_graph_set_title(struct sctp_udata *u_data)
+{
+ char *title;
+
+ if(!u_data->io->window){
+ return;
+ }
+ title = g_strdup_printf("SCTP TSNs and Sacks over Time: %s Port1 %u Port2 %u Endpoint %u",
+ cf_get_display_name(&cfile), u_data->parent->assoc->port1, u_data->parent->assoc->port2, u_data->dir);
+ gtk_window_set_title(GTK_WINDOW(u_data->io->window), title);
+ g_free(title);
+}
+
+
+static void
+gtk_sctpgraph_init(struct sctp_udata *u_data)
+{
+sctp_graph_t *io;
+int dir;
+sctp_min_max_t* tmp_minmax;
+
+ io=g_malloc(sizeof(sctp_graph_t));
+ io->needs_redraw=TRUE;
+ io->x_interval=1000;
+ io->window=NULL;
+ io->draw_area=NULL;
+ io->pixmap=NULL;
+ io->pixmap_width=800;
+ io->pixmap_height=600;
+ io->graph_type=0;
+ dir=u_data->dir-1;
+
+ u_data->io=io;
+ u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
+ u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
+ u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
+ u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
+ u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
+ u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
+ u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
+ u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
+ u_data->io->tmp=FALSE;
+
+ tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
+ tmp_minmax->tmp_min_secs = u_data->assoc->min_secs;
+ tmp_minmax->tmp_min_usecs=u_data->assoc->min_usecs;
+ tmp_minmax->tmp_max_secs=u_data->assoc->max_secs;
+ tmp_minmax->tmp_max_usecs=u_data->assoc->max_usecs;
+ tmp_minmax->tmp_min_tsn2=u_data->assoc->min_tsn2;
+ tmp_minmax->tmp_min_tsn1=u_data->assoc->min_tsn1;
+ tmp_minmax->tmp_max_tsn1=u_data->assoc->max_tsn1;
+ tmp_minmax->tmp_max_tsn2=u_data->assoc->max_tsn2;
+ u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
+
+ /* build the GUI */
+ init_sctp_graph_window(u_data);
+ sctp_graph_redraw(u_data);
+
+}
+
+
+static gint
+quit(GtkObject *object _U_, gpointer user_data)
+{
+struct sctp_udata *u_data=(struct sctp_udata*)user_data;
+
+ decrease_childcount(u_data->parent);
+ remove_child(u_data, u_data->parent);
+
+ g_free(u_data->io);
+
+ u_data->assoc->min_max = NULL;
+ g_free(u_data);
+ return TRUE;
+}
+
+
+static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data)
+{
+
+ u_data->io->draw_area=gtk_drawing_area_new();
+ SIGNAL_CONNECT(u_data->io->draw_area, "destroy", quit, u_data);
+ OBJECT_SET_DATA(u_data->io->draw_area, "sctp_graph_t", u_data->io);
+
+ WIDGET_SET_SIZE(u_data->io->draw_area, u_data->io->pixmap_width, u_data->io->pixmap_height);
+
+ /* signals needed to handle backing pixmap */
+ SIGNAL_CONNECT(u_data->io->draw_area, "expose_event", expose_event, NULL);
+ SIGNAL_CONNECT(u_data->io->draw_area, "configure_event", configure_event, u_data);
+
+ gtk_widget_show(u_data->io->draw_area);
+ gtk_box_pack_start(GTK_BOX(box), u_data->io->draw_area, TRUE, TRUE, 0);
+}
+
+
+
+void create_graph(guint16 dir, struct sctp_analyse* userdata)
+{
+struct sctp_udata *u_data;
+
+ u_data=g_malloc(sizeof(struct sctp_udata));
+ u_data->assoc=g_malloc(sizeof(sctp_assoc_info_t));
+ u_data->assoc=userdata->assoc;
+ u_data->io=NULL;
+ u_data->dir = dir;
+ u_data->parent = userdata;
+ set_child(u_data, u_data->parent);
+ increase_childcount(u_data->parent);
+ gtk_sctpgraph_init(u_data);
+
+}
+
diff --git a/gtk/sctp_stat.c b/gtk/sctp_stat.c
new file mode 100644
index 0000000000..46c01dde09
--- /dev/null
+++ b/gtk/sctp_stat.c
@@ -0,0 +1,1351 @@
+/*
+ * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
+ *
+ * $Id: sctp_stat.c 11436 2004-07-19 21:42:01Z tuexen $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <gtk/gtk.h>
+#include "simple_dialog.h" /* Both is used for error handling */
+#include "globals.h"
+#include "epan/packet_info.h" /* Needed for packet_info */
+#include "tap.h" /* Needed for register_tap_listener */
+#include "tap_menu.h"
+#include "dlg_utils.h"
+#include "compat_macros.h"
+#include "register.h"
+#include <string.h>
+#include "sctp_stat.h"
+#include <math.h>
+
+
+#define SCTP_HEARTBEAT_CHUNK_ID 4
+#define SCTP_HEARTBEAT_ACK_CHUNK_ID 5
+#define SCTP_ABORT_CHUNK_ID 6
+#define SCTP_SHUTDOWN_CHUNK_ID 7
+#define SCTP_SHUTDOWN_ACK_CHUNK_ID 8
+#define SCTP_ERROR_CHUNK_ID 9
+#define SCTP_COOKIE_ECHO_CHUNK_ID 10
+#define SCTP_COOKIE_ACK_CHUNK_ID 11
+#define SCTP_ECNE_CHUNK_ID 12
+#define SCTP_CWR_CHUNK_ID 13
+#define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
+#define SCTP_FORWARD_TSN_CHUNK_ID 192
+#define SCTP_ASCONF_ACK_CHUNK_ID 0x80
+#define SCTP_PKTDROP_CHUNK_ID 0X81
+#define SCTP_ASCONF_CHUNK_ID 0XC1
+#define SCTP_IETF_EXT 255
+
+#define SCTP_ABORT_CHUNK_T_BIT 0x01
+
+
+#define PARAMETER_TYPE_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_HEADER_OFFSET 0
+#define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+
+#define IPV6_ADDRESS_LENGTH 16
+#define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+#define IPV4_ADDRESS_LENGTH 4
+#define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+#define IPV4ADDRESS_PARAMETER_ID 0x0005
+#define IPV6ADDRESS_PARAMETER_ID 0x0006
+
+#define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
+#define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
+#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
+#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
+ SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
+
+
+
+static const value_string chunk_type_values[] = {
+ { SCTP_DATA_CHUNK_ID, "DATA" },
+ { SCTP_INIT_CHUNK_ID, "INIT" },
+ { SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" },
+ { SCTP_SACK_CHUNK_ID, "SACK" },
+ { SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" },
+ { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" },
+ { SCTP_ABORT_CHUNK_ID, "ABORT" },
+ { SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" },
+ { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" },
+ { SCTP_ERROR_CHUNK_ID, "ERROR" },
+ { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" },
+ { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" },
+ { SCTP_ECNE_CHUNK_ID, "ECNE" },
+ { SCTP_CWR_CHUNK_ID, "CWR" },
+ { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
+ { SCTP_FORWARD_TSN_CHUNK_ID, "FORWARD TSN" },
+ { SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF_ACK" },
+ { SCTP_PKTDROP_CHUNK_ID, "PKTDROP" },
+ { SCTP_ASCONF_CHUNK_ID, "ASCONF" },
+ { SCTP_IETF_EXT, "IETF_EXTENSION" },
+ { 0, NULL } };
+
+
+ #define FORWARD_STREAM 0
+ #define BACKWARD_STREAM 1
+ #define FORWARD_ADD_FORWARD_VTAG 2
+ #define BACKWARD_ADD_FORWARD_VTAG 3
+ #define BACKWARD_ADD_BACKWARD_VTAG 4
+ #define ADDRESS_FORWARD_STREAM 5
+ #define ADDRESS_BACKWARD_STREAM 6
+ #define ADDRESS_FORWARD_ADD_FORWARD_VTAG 7
+ #define ADDRESS_BACKWARD_ADD_FORWARD_VTAG 8
+ #define ADDRESS_BACKWARD_ADD_BACKWARD_VTAG 9
+ #define ASSOC_NOT_FOUND 10
+
+
+static sctp_allassocs_info_t sctp_tapinfo_struct = {0, NULL, FALSE, NULL};
+
+
+static
+void free_first(gpointer data, gpointer user_data _U_)
+{
+ fflush(stdout);
+ g_free(data);
+}
+
+void tsn_free(gpointer data, gpointer user_data _U_)
+{
+tsn_t *tsn;
+ tsn = (tsn_t *) data;
+ if (tsn->tsns!=NULL)
+ {
+ g_list_foreach(tsn->tsns, free_first, NULL);
+ g_list_free(tsn->tsns);
+ tsn->tsns=NULL;
+ }
+}
+
+void
+reset(sctp_allassocs_info_t *tapdata )
+{
+GList* list;
+sctp_assoc_info_t * info;
+
+ list = g_list_first(tapdata->assoc_info_list);
+ while (list)
+ {
+ info = (sctp_assoc_info_t *) (list->data);
+
+ if (info->addr1!=NULL)
+ {
+ g_list_foreach(info->addr1, free_first, NULL);
+ g_list_free(info->addr1);
+ info->addr1 = NULL;
+ }
+
+ if (info->addr2!=NULL)
+ {
+ g_list_foreach(info->addr2,free_first, NULL);
+ g_list_free(info->addr2);
+ info->addr2 = NULL;
+ }
+
+ if (info->error_info_list!=NULL)
+ {
+ g_list_foreach(info->error_info_list, free_first, NULL);
+ g_list_free(info->error_info_list);
+ info->error_info_list = NULL;
+ }
+
+ if (info->frame_numbers!=NULL)
+ {
+ g_list_free(info->frame_numbers);
+ info->frame_numbers = NULL;
+ }
+
+ if (info->tsn1!=NULL)
+ {
+ g_list_foreach(info->tsn1,tsn_free, NULL);
+ g_list_free(info->tsn1);
+ info->tsn1 = NULL;
+ }
+
+ if (info->tsn2!=NULL)
+ {
+ g_list_foreach(info->tsn2,tsn_free, NULL);
+ g_list_free(info->tsn2);
+ info->tsn2 = NULL;
+ }
+
+ if (info->sack1!=NULL)
+ {
+ g_list_foreach(info->sack1,tsn_free, NULL);
+ g_list_free(info->sack1);
+ info->sack1 = NULL;
+ }
+
+ if (info->sack2!=NULL)
+ {
+ g_list_foreach(info->sack2,tsn_free, NULL);
+ g_list_free(info->sack2);
+ info->sack2 = NULL;
+ }
+
+ if (info->sort_tsn1!=NULL)
+ g_array_free(info->sort_tsn1, TRUE);
+
+ if (info->sort_tsn2!=NULL)
+ g_array_free(info->sort_tsn2, TRUE);
+
+ if (info->sort_sack1!=NULL)
+ g_array_free(info->sort_sack1, TRUE);
+
+ if (info->sort_sack2!=NULL)
+ g_array_free(info->sort_sack2, TRUE);
+
+ if (info->min_max!=NULL)
+ {
+ g_slist_foreach(info->min_max,free_first, NULL);
+ info->min_max = NULL;
+ }
+
+ g_free(list->data);
+ list = g_list_next(list);
+ }
+ g_list_free(tapdata->assoc_info_list);
+ tapdata->sum_tvbs=0;
+ tapdata->assoc_info_list=NULL;
+}
+
+
+static sctp_assoc_info_t * calc_checksum(struct _sctp_info * check_data, sctp_assoc_info_t * data)
+{
+guint8 ok=0;
+
+if (check_data->adler32_calculated)
+{
+ data->n_adler32_calculated++;
+ if (check_data->adler32_correct)
+ data->n_adler32_correct++;
+}
+if (check_data->crc32c_calculated)
+{
+ data->n_crc32c_calculated++;
+ if (check_data->crc32c_correct)
+ data->n_crc32c_correct++;
+}
+if (data->n_adler32_calculated>0)
+{
+ if ((float)(data->n_adler32_correct*1.0/data->n_adler32_calculated)>0.5)
+ {
+ strcpy(data->checksum_type,"ADLER32");
+ data->n_checksum_errors=(data->n_adler32_calculated-data->n_adler32_correct);
+ ok=1;
+ }
+}
+
+if (data->n_crc32c_calculated>0)
+{
+ if ((float)(data->n_crc32c_correct*1.0/data->n_crc32c_calculated)>0.5)
+ {
+ strcpy(data->checksum_type,"CRC32C");
+ data->n_checksum_errors=data->n_crc32c_calculated-data->n_crc32c_correct;
+ ok=1;
+ }
+}
+
+if (ok==0)
+{
+ strcpy(data->checksum_type,"UNKNOWN");
+ data->n_checksum_errors=0;
+}
+
+ return data;
+
+}
+
+
+gint sctp_assoc_vtag_cmp(gconstpointer aa, gconstpointer bb)
+{
+
+ const struct _sctp_assoc_info* a = aa;
+ const struct _sctp_assoc_info* b = bb;
+
+ if (a==b)
+ return 0;
+
+ if (a==NULL || b==NULL)
+ return 1;
+
+ /* assoc known*/
+ if ((a->port1 == b->port1)
+ && (a->port2 == b->port2)
+ && (a->verification_tag1 == b->verification_tag1)
+ && ((a->verification_tag1!=0 || b->verification_tag2 !=0)))
+ return FORWARD_STREAM;
+
+ if ((a->port1 == b->port2)
+ && (a->port2 == b->port1)
+ && (a->verification_tag1 == b->verification_tag2))
+ return BACKWARD_STREAM;
+
+ /*forward stream verifivation tag can be added*/
+ if ((a->port1 == b->port1)
+ && (a->port2 == b->port2)
+ && (a->verification_tag1 !=0)
+ && (b->verification_tag1 == 0)
+ && (b->verification_tag2 !=0))
+ return FORWARD_ADD_FORWARD_VTAG;
+ if ((a->port1 == b->port2)
+ && (a->port2 == b->port1)
+ && (a->verification_tag1 ==b->verification_tag2)
+ && (b->verification_tag1 == 0))
+ return BACKWARD_ADD_FORWARD_VTAG;
+ /*backward stream verification tag can be added */
+ if ((a->port1 == b->port2)
+ && (a->port2 == b->port1)
+ && (a->verification_tag1 !=0)
+ && (b->verification_tag1 != 0)
+ && (b->verification_tag2 == 0))
+ return BACKWARD_ADD_BACKWARD_VTAG;
+
+ return ASSOC_NOT_FOUND;
+}
+
+
+gint sctp_assoc_address_cmp(gconstpointer aa, gconstpointer bb)
+{
+GList *srclist, *dstlist;
+const struct _sctp_tmp_info* a = aa; //tmp_info
+const struct _sctp_assoc_info* b = bb; //info
+struct sockaddr_storage *store=NULL;
+struct sockaddr_storage *srcstore=NULL;
+struct sockaddr_storage *dststore=NULL;
+struct sockaddr_in *src=NULL;
+struct sockaddr_in6 *src6=NULL;
+struct sockaddr_in *infosrc=NULL;
+struct sockaddr_in *infodst=NULL;
+struct sockaddr_in6 *infosrc6=NULL;
+struct sockaddr_in *dst=NULL;
+struct sockaddr_in6 *dst6=NULL;
+struct sockaddr_in6 *infodst6=NULL;
+gboolean src_v4=FALSE;
+gboolean src_v6=FALSE;
+gboolean dst_v4=FALSE;
+gboolean dst_v6=FALSE;
+
+ store = g_malloc(sizeof(struct sockaddr_storage));
+ g_memmove(store, &(a->src),sizeof(struct sockaddr_storage));
+ if (store->ss_family==AF_INET)
+ {
+ src = g_malloc(sizeof(struct sockaddr_in));
+ g_memmove(src, &(a->src),sizeof(struct sockaddr_in));
+ src_v4=TRUE;
+ }
+ else if (store->ss_family==AF_INET6)
+ {
+ src6 = g_malloc(sizeof(struct sockaddr_in6));
+ g_memmove(src6, &(a->src),sizeof(struct sockaddr_in6));
+ src_v6=TRUE;
+ }
+
+ g_memmove(store, &(a->dst),sizeof(struct sockaddr_storage));
+ if (store->ss_family==AF_INET)
+ {
+ dst = g_malloc(sizeof(struct sockaddr_in));
+ g_memmove(dst, &(a->dst),sizeof(struct sockaddr_in));
+ dst_v4=TRUE;
+ }
+ else if (store->ss_family==AF_INET6)
+ {
+ dst6 = g_malloc(sizeof(struct sockaddr_in6));
+ g_memmove(dst6, &(a->dst),sizeof(struct sockaddr_in6));
+ dst_v6=TRUE;
+ }
+
+ srclist = g_list_first(b->addr1);
+ while (srclist)
+ {
+ srcstore = (struct sockaddr_storage *) (srclist->data);
+ if (srcstore->ss_family==AF_INET && src_v4==TRUE)
+ {
+ infosrc=(struct sockaddr_in *) (srclist->data);
+ if (src->sin_addr.s_addr==infosrc->sin_addr.s_addr && a->port1 == b->port1)
+ {
+ dstlist = g_list_first(b->addr2);
+ while (dstlist)
+ {
+ dststore = (struct sockaddr_storage *) (dstlist->data);
+ if (dststore->ss_family==AF_INET && dst_v4==TRUE)
+ {
+ infodst=(struct sockaddr_in *) (dstlist->data);
+ if (dst->sin_addr.s_addr==infodst->sin_addr.s_addr && a->port2 == b->port2)
+ {
+ if ((a->verification_tag1 !=0)&& (b->verification_tag1 == 0)&& (b->verification_tag2 !=0))
+ return ADDRESS_FORWARD_ADD_FORWARD_VTAG;
+ else
+ return ADDRESS_FORWARD_STREAM;
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ else if (dststore->ss_family==AF_INET6 && dst_v6==TRUE)
+ {
+ infodst6=(struct sockaddr_in6 *) (dstlist->data);
+ if (dst6->sin6_addr.s6_addr==infodst6->sin6_addr.s6_addr && a->port2 == b->port2)
+ {
+ if ((a->verification_tag1 !=0)&& (b->verification_tag1 == 0)&& (b->verification_tag2 !=0))
+ return ADDRESS_FORWARD_ADD_FORWARD_VTAG;
+ else
+ return ADDRESS_FORWARD_STREAM;
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ srclist=g_list_next(srclist);
+ }
+ else
+ srclist=g_list_next(srclist);
+ }
+ else if (srcstore->ss_family==AF_INET6 && src_v6==TRUE)
+ {
+ infosrc6=(struct sockaddr_in6 *) (srclist->data);
+ if (src6->sin6_addr.s6_addr==infosrc6->sin6_addr.s6_addr && a->port1 == b->port1)
+ {
+ dstlist = g_list_first(b->addr2);
+ while (dstlist)
+ {
+ dststore = (struct sockaddr_storage *) (dstlist->data);
+ if (dststore->ss_family==AF_INET && dst_v4==TRUE)
+ {
+ infodst=(struct sockaddr_in *) (dstlist->data);
+ if (dst->sin_addr.s_addr==infodst->sin_addr.s_addr && a->port2 == b->port2)
+ {
+ if ((a->verification_tag1 !=0)&& (b->verification_tag1 == 0)&& (b->verification_tag2 !=0))
+ return ADDRESS_FORWARD_ADD_FORWARD_VTAG;
+ else
+ return ADDRESS_FORWARD_STREAM;
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ else if (dststore->ss_family==AF_INET6 && dst_v6==TRUE)
+ {
+ infodst6=(struct sockaddr_in6 *) (dstlist->data);
+ if (dst6->sin6_addr.s6_addr==infodst6->sin6_addr.s6_addr && a->port2 == b->port2)
+ {
+ if ((a->verification_tag1 !=0)&& (b->verification_tag1 == 0)&& (b->verification_tag2 !=0))
+ return ADDRESS_FORWARD_ADD_FORWARD_VTAG;
+ else
+ return ADDRESS_FORWARD_STREAM;
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ srclist=g_list_next(srclist);
+ }
+ else
+ srclist=g_list_next(srclist);
+ }
+ else
+ srclist=g_list_next(srclist);
+ }
+
+ g_free(src);
+ g_free(dst);
+ g_free(src6);
+ g_free(dst6);
+ g_free(store);
+
+ store = g_malloc(sizeof(struct sockaddr_storage));
+ g_memmove(store, &(a->dst),sizeof(struct sockaddr_storage));
+ if (store->ss_family==AF_INET)
+ {
+ src = g_malloc(sizeof(struct sockaddr_in));
+ g_memmove(src, &(a->dst),sizeof(struct sockaddr_in));
+ src_v4=TRUE;
+ }
+ else if (store->ss_family==AF_INET6)
+ {
+ src6 = g_malloc(sizeof(struct sockaddr_in6));
+ g_memmove(src6, &(a->dst),sizeof(struct sockaddr_in6));
+ src_v6=TRUE;
+ }
+
+ g_memmove(store, &(a->src),sizeof(struct sockaddr_storage));
+ if (store->ss_family==AF_INET)
+ {
+ dst = g_malloc(sizeof(struct sockaddr_in));
+ g_memmove(dst, &(a->src),sizeof(struct sockaddr_in));
+ dst_v4=TRUE;
+ }
+ else if (store->ss_family==AF_INET6)
+ {
+ dst6 = g_malloc(sizeof(struct sockaddr_in6));
+ g_memmove(dst6, &(a->src),sizeof(struct sockaddr_in6));
+ dst_v6=TRUE;
+ }
+
+ srclist = g_list_first(b->addr1);
+ while (srclist)
+ {
+ srcstore = (struct sockaddr_storage *) (srclist->data);
+ if (srcstore->ss_family==AF_INET && src_v4==TRUE)
+ {
+ infosrc=(struct sockaddr_in *) (srclist->data);
+ if (src->sin_addr.s_addr==infosrc->sin_addr.s_addr && a->port2 == b->port1)
+ {
+ dstlist = g_list_first(b->addr2);
+ while (dstlist)
+ {
+ dststore = (struct sockaddr_storage *) (dstlist->data);
+ if (dststore->ss_family==AF_INET && src_v4==TRUE)
+ {
+ infodst=(struct sockaddr_in *) (dstlist->data);
+ if (dst->sin_addr.s_addr==infodst->sin_addr.s_addr && a->port1 == b->port2)
+ {
+ if ((a->verification_tag1 ==b->verification_tag2)&& (b->verification_tag1 == 0))
+ return ADDRESS_BACKWARD_ADD_FORWARD_VTAG;
+ else if ((a->verification_tag1 !=0) && (b->verification_tag1 != 0)&& (b->verification_tag2 == 0))
+ return ADDRESS_BACKWARD_ADD_BACKWARD_VTAG;
+ else
+ return ADDRESS_BACKWARD_STREAM;
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ else if (dststore->ss_family==AF_INET6 && src_v6==TRUE)
+ {
+ infodst6=(struct sockaddr_in6 *) (dstlist->data);
+ if (dst6->sin6_addr.s6_addr==infodst6->sin6_addr.s6_addr && a->port1 == b->port2)
+ {
+
+ if ((a->verification_tag1 ==b->verification_tag2)&& (b->verification_tag1 == 0))
+ return ADDRESS_BACKWARD_ADD_FORWARD_VTAG;
+ else if ((a->verification_tag1 !=0) && (b->verification_tag1 != 0)&& (b->verification_tag2 == 0))
+ return ADDRESS_BACKWARD_ADD_BACKWARD_VTAG;
+ else
+ return ADDRESS_BACKWARD_STREAM;
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ srclist=g_list_next(srclist);
+ }
+ else
+ srclist=g_list_next(srclist);
+ }
+ else if (srcstore->ss_family==AF_INET6 && src_v6==TRUE)
+ {
+ infosrc6=(struct sockaddr_in6 *) (srclist->data);
+ if (src6->sin6_addr.s6_addr==infosrc6->sin6_addr.s6_addr && a->port2 == b->port1)
+ {
+ dstlist = g_list_first(b->addr2);
+ while (dstlist)
+ {
+ dststore = (struct sockaddr_storage *) (dstlist->data);
+ if (dststore->ss_family==AF_INET && src_v4==TRUE)
+ {
+ infodst=(struct sockaddr_in *) (dstlist->data);
+ if (dst->sin_addr.s_addr==infodst->sin_addr.s_addr && a->port1 == b->port2)
+ {
+ if ((a->verification_tag1 ==b->verification_tag2)&& (b->verification_tag1 == 0))
+ return ADDRESS_BACKWARD_ADD_FORWARD_VTAG;
+ else if ((a->verification_tag1 !=0) && (b->verification_tag1 != 0)&& (b->verification_tag2 == 0))
+ return ADDRESS_BACKWARD_ADD_BACKWARD_VTAG;
+ else
+ return ADDRESS_BACKWARD_STREAM;
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ else if (dststore->ss_family==AF_INET6 && src_v6==TRUE)
+ {
+ infodst6=(struct sockaddr_in6 *) (dstlist->data);
+ if (dst6->sin6_addr.s6_addr==infodst6->sin6_addr.s6_addr && a->port1 == b->port2)
+ {
+ if ((a->verification_tag1 ==b->verification_tag2)&& (b->verification_tag1 == 0))
+ return ADDRESS_BACKWARD_ADD_FORWARD_VTAG;
+ else if ((a->verification_tag1 !=0) && (b->verification_tag1 != 0)&& (b->verification_tag2 == 0))
+ return ADDRESS_BACKWARD_ADD_BACKWARD_VTAG;
+ else
+ return ADDRESS_BACKWARD_STREAM;
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ else
+ dstlist=g_list_next(dstlist);
+ }
+ srclist=g_list_next(srclist);
+ }
+ else
+ srclist=g_list_next(srclist);
+ }
+ else
+ srclist=g_list_next(srclist);
+ }
+
+
+ g_free(src);
+ g_free(dst);
+ g_free(src6);
+ g_free(dst6);
+ g_free(store);
+ return ASSOC_NOT_FOUND;
+}
+
+
+
+
+
+
+sctp_assoc_info_t * find_assoc(sctp_tmp_info_t * needle)
+{
+sctp_allassocs_info_t *assoc_info;
+sctp_assoc_info_t *info = NULL;
+GList* list;
+guint8 cmp;
+
+ assoc_info = &sctp_tapinfo_struct;
+ if ((list = g_list_first(assoc_info->assoc_info_list))!=NULL)
+ {
+ while (list)
+ {
+ cmp=sctp_assoc_vtag_cmp(needle, (sctp_assoc_info_t*)(list->data));
+ if (cmp==ASSOC_NOT_FOUND)
+ {
+ cmp=sctp_assoc_address_cmp(needle, (sctp_assoc_info_t*)(list->data));
+ }
+ switch (cmp)
+ {
+ case FORWARD_STREAM:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->direction = 1;
+ return info;
+ case BACKWARD_STREAM:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->direction = 2;
+ return info;
+ case FORWARD_ADD_FORWARD_VTAG:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->verification_tag1=needle->verification_tag1;
+ info->direction = 1;
+ return info;
+ case BACKWARD_ADD_FORWARD_VTAG:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->verification_tag1=needle->verification_tag1;
+ info->direction = 2;
+ return info;
+ case BACKWARD_ADD_BACKWARD_VTAG:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->verification_tag2=needle->verification_tag1;
+ info->direction = 2;
+ return info;
+ case ADDRESS_FORWARD_STREAM:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->direction = 1;
+ info->check_address=TRUE;
+ return info;
+ case ADDRESS_BACKWARD_STREAM:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->direction = 2;
+ info->check_address=TRUE;
+ return info;
+ case ADDRESS_FORWARD_ADD_FORWARD_VTAG:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->verification_tag1=needle->verification_tag1;
+ info->direction = 1;
+ info->check_address=TRUE;
+ return info;
+ case ADDRESS_BACKWARD_ADD_FORWARD_VTAG:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->verification_tag1=needle->verification_tag1;
+ info->direction = 2;
+ info->check_address=TRUE;
+ return info;
+ case ADDRESS_BACKWARD_ADD_BACKWARD_VTAG:
+ info = (sctp_assoc_info_t*)(list->data);
+ info->verification_tag2=needle->verification_tag1;
+ info->direction = 2;
+ info->check_address=TRUE;
+ return info;
+ }
+
+ list = g_list_next(list);
+ }
+ }
+ return NULL;
+}
+
+sctp_assoc_info_t * add_address(struct sockaddr_storage * vadd, sctp_assoc_info_t *info, guint8 direction)
+{
+GList *list;
+struct sockaddr_in *v4, *v4add=NULL;
+struct sockaddr_in6 *v6, *v6add=NULL;
+struct sockaddr_storage *v;
+
+ if (direction == 1)
+ list = g_list_first(info->addr1);
+ else
+ list = g_list_first(info->addr2);
+
+ while (list)
+ {
+ v = (struct sockaddr_storage *) (list->data);
+ if (v->ss_family == AF_INET && vadd->ss_family == AF_INET)
+ {
+ v4 = (struct sockaddr_in *)(list->data);
+ v4add = (struct sockaddr_in *) vadd;
+ if (v4add->sin_addr.s_addr!=v4->sin_addr.s_addr)
+ list = g_list_next(list);
+ else
+ {
+ g_free(v4add);
+ return info;
+ }
+ }
+ else if (v->ss_family == AF_INET6 && vadd->ss_family == AF_INET6)
+ {
+ v6 = (struct sockaddr_in6 *)(list->data);
+ v6add = (struct sockaddr_in6 *) vadd;
+ if (v6add->sin6_addr.s6_addr!=v6->sin6_addr.s6_addr)
+ list = g_list_next(list);
+ else
+ {
+ g_free(v6add);
+ return info;
+ }
+ }
+ else
+ list= g_list_next(list);
+ }
+
+ if (direction == 1)
+ info->addr1 = g_list_append(info->addr1, vadd);
+ else if (direction==2)
+ info->addr2 = g_list_append(info->addr2, vadd);
+
+ return info;
+}
+
+static int
+packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , void *data _U_)
+{
+struct _sctp_info *sctp_info;
+guint32 chunk_number=0, ip, tsnumber;
+sctp_tmp_info_t tmp_info;
+sctp_assoc_info_t *info = NULL;
+sctp_error_info_t *error = NULL;
+char str[200];
+guint16 type, length;
+struct sockaddr_in v4n;
+struct sockaddr_in6 v6n;
+struct sockaddr_storage *store=NULL;
+tsn_t *tsn=NULL;
+tsn_t *sack=NULL;
+guint8 *t_s_n=NULL;
+gboolean sackchunk=FALSE;
+gboolean datachunk=FALSE;
+guint32 max;
+struct tsn_sort tsn_s;
+
+ sctp_allassocs_info_t *assoc_info=NULL;
+ assoc_info = &sctp_tapinfo_struct;
+
+ sctp_info = (struct _sctp_info *) data;
+ max =0xFFFFFFFF;
+
+ type = pinfo->src.type;
+ if (type == AT_IPv4)
+ {
+ v4n.sin_family = AF_INET;
+ v4n.sin_port = 0;
+ g_memmove(&(v4n.sin_addr.s_addr), pinfo->src.data, 4);
+ g_memmove(&(tmp_info.src), &v4n, sizeof(struct sockaddr_in));
+ }
+ else if (type == AT_IPv6)
+ {
+ v6n.sin6_family=AF_INET6;
+ v6n.sin6_port = 0;
+ g_memmove(&(v6n.sin6_addr.s6_addr), pinfo->src.data, 16);
+ g_memmove(&(tmp_info.src), &v6n, sizeof(struct sockaddr_in6));
+ }
+ type = pinfo->dst.type;
+
+ if (type == AT_IPv4)
+ {
+ v4n.sin_family=AF_INET;
+ v4n.sin_port = 0;
+ g_memmove(&(v4n.sin_addr.s_addr), pinfo->dst.data, 4);
+ g_memmove(&(tmp_info.dst), &v4n, sizeof(struct sockaddr_in));
+ }
+ else if (type == AT_IPv6)
+ {
+ v6n.sin6_family=AF_INET6;
+ v6n.sin6_port = 0;
+ g_memmove(&(v6n.sin6_addr.s6_addr), pinfo->dst.data, 16);
+ g_memmove(&(tmp_info.dst), &v6n, sizeof(struct sockaddr_in6));
+ }
+
+ tmp_info.port1 = pinfo->srcport;
+ tmp_info.port2 = pinfo->destport;
+ tmp_info.verification_tag1=sctp_info->verification_tag;
+ tmp_info.verification_tag2=0;
+ tmp_info.n_tvbs=0;
+
+
+ info=find_assoc(&tmp_info);
+ if (!info)
+ {
+ tmp_info.n_tvbs = sctp_info->number_of_tvbs;
+ sctp_tapinfo_struct.sum_tvbs+=sctp_info->number_of_tvbs;
+
+
+ if (sctp_info->number_of_tvbs>0)
+ {
+ info = g_malloc(sizeof(sctp_assoc_info_t));
+ memset(info, 0, sizeof(sctp_assoc_info_t));
+ g_memmove(info, &tmp_info, sizeof(sctp_tmp_info_t));
+
+ info->init=FALSE;
+ info->initack=FALSE;
+ info->direction=0;
+ info=calc_checksum(sctp_info, info);
+ info->n_packets=1;
+ info->error_info_list=NULL;
+ info->min_secs=0xffffffff;
+ info->min_usecs=0xffffffff;
+ info->max_secs=0;
+ info->max_usecs=0;
+ info->min_tsn2=0xFFFFFFFF;
+ info->min_tsn1=0xffffffff;
+ info->max_tsn1=0;
+ info->max_tsn2=0;
+ info->max_bytes1=0;
+ info->max_bytes2=0;
+ info->n_data_chunks=0;
+ info->n_data_bytes=0;
+ info->n_data_chunks_ep1=0;
+ info->n_data_bytes_ep1=0;
+ info->n_data_chunks_ep2=0;
+ info->n_data_bytes_ep2=0;
+ info->n_sack_chunks_ep1=0;
+ info->n_sack_chunks_ep2=0;
+ info->n_array_tsn1=0;
+ info->n_array_tsn2=0;
+ info->max_window1=0;
+ info->max_window2=0;
+ info->min_max=NULL;
+ info->sort_tsn1=g_array_new(FALSE, FALSE, sizeof(struct tsn_sort));
+ info->sort_tsn2=g_array_new(FALSE, FALSE, sizeof(struct tsn_sort));
+ info->sort_sack1=g_array_new(FALSE, FALSE, sizeof(struct tsn_sort));
+ info->sort_sack2=g_array_new(FALSE, FALSE, sizeof(struct tsn_sort));
+
+ if (((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_INIT_CHUNK_ID) ||
+ ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_INIT_ACK_CHUNK_ID) ||
+ ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_DATA_CHUNK_ID) ||
+ ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_SACK_CHUNK_ID))
+ {
+ tsn = g_malloc(sizeof(tsn_t));
+ sack = g_malloc(sizeof(tsn_t));
+ tsn->tsns = NULL;
+ tsn->src = tmp_info.src;
+ tsn->dst = tmp_info.dst;
+ tsn->secs = (guint32)pinfo->fd->rel_secs;
+ tsn->usecs = (guint32)pinfo->fd->rel_usecs;
+ if (((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_DATA_CHUNK_ID) ||
+ ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_SACK_CHUNK_ID))
+ {
+ if (tsn->secs<info->min_secs)
+ {
+ info->min_secs=tsn->secs;
+ info->min_usecs=tsn->usecs;
+ }
+ else if (tsn->secs==info->min_secs && tsn->usecs < info->min_usecs)
+ info->min_usecs=tsn->usecs;
+
+ if (tsn->secs>info->max_secs)
+ {
+ info->max_secs=tsn->secs;
+ info->max_usecs=tsn->usecs;
+ }
+ else if (tsn->secs==info->max_secs && tsn->usecs > info->max_usecs)
+ info->max_usecs=tsn->usecs;
+ }
+
+ tsn->frame_number = pinfo->fd->num;
+ g_memmove(sack, tsn, sizeof(tsn_t));
+
+ }
+ if ((tvb_get_guint8(sctp_info->tvb[0],0)==SCTP_INIT_CHUNK_ID) || (tvb_get_guint8(sctp_info->tvb[0],0)==SCTP_INIT_ACK_CHUNK_ID))
+ {
+ info->min_tsn1 = tvb_get_ntohl(sctp_info->tvb[0],INIT_CHUNK_INITIAL_TSN_OFFSET);
+ info->verification_tag2=tvb_get_ntohl(sctp_info->tvb[0], INIT_CHUNK_INITIATE_TAG_OFFSET);
+ info->instream1=tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
+ info->outstream1=tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
+ for (chunk_number = 1; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
+ {
+ type = tvb_get_ntohs(sctp_info->tvb[chunk_number],0);
+ if (type == IPV4ADDRESS_PARAMETER_ID)
+ {
+ v4n.sin_family=AF_INET;
+ v4n.sin_port = 0;
+ ip=tvb_get_ntohl(sctp_info->tvb[chunk_number],4);
+ ip=htonl(ip);
+ v4n.sin_addr.s_addr=ip;
+ store = g_malloc(sizeof(struct sockaddr_storage));
+ g_memmove(store,&v4n, sizeof(struct sockaddr_in));
+ info = add_address(store, info, 1);
+ }
+ else if (type == IPV6ADDRESS_PARAMETER_ID)
+ {
+ v6n.sin6_family=AF_INET6;
+ v6n.sin6_port = 0;
+ tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)&(v6n.sin6_addr.s6_addr),IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH);
+ store = g_malloc(sizeof(struct sockaddr_storage));
+ g_memmove(store, &v6n, sizeof(struct sockaddr_in6));
+ info = add_address(store, info, 1);
+ }
+ }
+ if (tvb_get_guint8(sctp_info->tvb[0],0)==SCTP_INIT_CHUNK_ID)
+ {
+ info->init=TRUE;
+ }
+ else
+ {
+ info->initack_dir=1;
+ info->initack=TRUE;
+ }
+ }
+ else
+ for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
+ {
+ if (tvb_get_guint8(sctp_info->tvb[chunk_number],0)==SCTP_DATA_CHUNK_ID)
+ {
+ length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ info->n_data_chunks++;
+ info->n_data_bytes+=length;
+ info->outstream1=tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
+ tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], DATA_CHUNK_TSN_OFFSET);
+ if (tsnumber<info->min_tsn1)
+ info->min_tsn1=tsnumber;
+ if (tsnumber>info->max_tsn1)
+ {
+ length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ info->n_data_chunks_ep1++;
+ info->n_data_bytes_ep1+=length;
+ info->max_tsn1=tsnumber;
+ }
+
+ t_s_n = g_malloc(16);
+ tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, 16);
+ tsn->tsns = g_list_append(tsn->tsns, t_s_n);
+ datachunk = TRUE;
+ tsn_s.tsnumber=tsnumber;
+ tsn_s.secs=tsn->secs;
+ tsn_s.usecs=tsn->usecs;
+ tsn_s.offset=0;
+ tsn_s.length=length-16;
+ info->sort_tsn1=g_array_append_val(info->sort_tsn1, tsn_s);
+ info->n_array_tsn1++;
+ }
+ if (tvb_get_guint8(sctp_info->tvb[chunk_number],0)==SCTP_SACK_CHUNK_ID)
+ {
+ tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
+ if (tsnumber<info->min_tsn2)
+ info->min_tsn2=tsnumber;
+ if (tsnumber>info->max_tsn2)
+ info->max_tsn2=tsnumber;
+ info->n_sack_chunks_ep2++;
+ length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ t_s_n = g_malloc(length);
+ tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, length);
+ sack->tsns = g_list_append(sack->tsns, t_s_n);
+ sackchunk=TRUE;
+ tsn_s.tsnumber=tsnumber;
+ tsn_s.secs=tsn->secs;
+ tsn_s.usecs=tsn->usecs;
+ tsn_s.offset=0;
+ tsn_s.length= tvb_get_ntohl(sctp_info->tvb[chunk_number], SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
+ if (tsn_s.length>info->max_window1)
+ info->max_window1=tsn_s.length;
+ info->sort_sack2=g_array_append_val(info->sort_sack2, tsn_s);
+ info->n_sack_chunks_ep2++;
+ }
+
+ }
+ if (info->verification_tag1!=0 || info->verification_tag2!=0)
+ {
+ store = g_malloc(sizeof (struct sockaddr_storage));
+ g_memmove(store,&(tmp_info.src),sizeof(struct sockaddr_storage));
+ info = add_address(store, info, 1);
+ store = g_malloc(sizeof (struct sockaddr_storage));
+ g_memmove(store,&(tmp_info.dst),sizeof(struct sockaddr_storage));
+ info = add_address(store, info, 2);
+ info->frame_numbers=g_list_prepend(info->frame_numbers,&(pinfo->fd->num));
+ if (datachunk==TRUE)
+ info->tsn1 = g_list_prepend(info->tsn1, tsn);
+ if (sackchunk == TRUE)
+ info->sack2 = g_list_prepend(info->sack2, sack);
+ sctp_tapinfo_struct.assoc_info_list = g_list_append(sctp_tapinfo_struct.assoc_info_list, info);
+ }
+ else
+ {
+ error = g_malloc(sizeof(sctp_error_info_t));
+ error->frame_number = pinfo->fd->num;
+ strcpy(str,"");
+ strcpy(error->chunk_info,"");
+ if ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_INIT_CHUNK_ID)
+ strcpy(error->chunk_info, val_to_str(tvb_get_guint8(sctp_info->tvb[0],0),chunk_type_values,"Reserved"));
+ else
+ for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
+ strcat(error->chunk_info, val_to_str(tvb_get_guint8(sctp_info->tvb[chunk_number],0),chunk_type_values,"Reserved"));
+ error->info_text="INFOS";
+ info->error_info_list = g_list_append(info->error_info_list, error);
+ }
+ }
+ }
+ else
+ {
+ if (((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_INIT_ACK_CHUNK_ID) ||
+ ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_DATA_CHUNK_ID) ||
+ ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_SACK_CHUNK_ID))
+ {
+
+ tsn = g_malloc(sizeof(tsn_t));
+ sack = g_malloc(sizeof(tsn_t));
+ tsn->tsns = NULL;
+ tsn->src = tmp_info.src;
+ tsn->dst = tmp_info.dst;
+ tsn->secs = (guint32)pinfo->fd->rel_secs;
+ tsn->usecs = (guint32)pinfo->fd->rel_usecs;
+ if (((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_DATA_CHUNK_ID) ||
+ ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_SACK_CHUNK_ID))
+ {
+ if (tsn->secs<info->min_secs)
+ {
+ info->min_secs=tsn->secs;
+ info->min_usecs=tsn->usecs;
+ }
+ else if (tsn->secs==info->min_secs && tsn->usecs<info->min_usecs)
+ info->min_usecs=tsn->usecs;
+
+ if (tsn->secs>info->max_secs)
+ {
+ info->max_secs=tsn->secs;
+ info->max_usecs=tsn->usecs;
+ }
+ else if (tsn->secs==info->max_secs && tsn->usecs > info->max_usecs)
+ info->max_usecs=tsn->usecs;
+ }
+ tsn->frame_number = pinfo->fd->num;
+ g_memmove(sack, tsn, sizeof(tsn_t));
+ }
+ info->frame_numbers=g_list_prepend(info->frame_numbers,&(pinfo->fd->num));
+
+ if (info->direction==1)
+ {
+ store = g_malloc(sizeof (struct sockaddr_storage));
+ g_memmove(store,&(tmp_info.src),sizeof(struct sockaddr_storage));
+ info = add_address(store, info, 1);
+ store = g_malloc(sizeof (struct sockaddr_storage));
+ g_memmove(store,&(tmp_info.dst),sizeof(struct sockaddr_storage));
+ info = add_address(store, info, 2);
+ }
+ else if (info->direction==2)
+ {
+ store = g_malloc(sizeof (struct sockaddr_storage));
+ g_memmove(store,&(tmp_info.src),sizeof(struct sockaddr_storage));
+ info = add_address(store, info, 2);
+ store = g_malloc(sizeof (struct sockaddr_storage));
+ g_memmove(store,&(tmp_info.dst),sizeof(struct sockaddr_storage));
+ info = add_address(store, info, 1);
+ }
+ if ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_INIT_ACK_CHUNK_ID)
+ {
+ tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], INIT_CHUNK_INITIAL_TSN_OFFSET);
+
+ if (info->direction==2)
+ {
+ if (tsnumber<info->min_tsn2)
+ info->min_tsn2 = tsnumber;
+ if (tsnumber > info->max_tsn2)
+ info->max_tsn2 = tsnumber;
+ info->instream2=tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
+ info->outstream2=tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
+ info->initack_dir=2;
+ info->tsn2 = g_list_prepend(info->tsn2, tsn);
+ }
+ else if (info->direction==1)
+ {
+ if (tsnumber<info->min_tsn1)
+ info->min_tsn1 = tsnumber;
+ if (tsnumber > info->max_tsn1)
+ info->max_tsn1 = tsnumber;
+ info->instream1=tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
+ info->outstream1=tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
+ info->initack_dir=1;
+ info->tsn1 = g_list_prepend(info->tsn1, tsn);
+ }
+ for (chunk_number = 1; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
+ {
+ type = tvb_get_ntohs(sctp_info->tvb[chunk_number],0);
+ if (type == IPV4ADDRESS_PARAMETER_ID)
+ {
+ v4n.sin_family=AF_INET;
+ v4n.sin_port = 0;
+ ip=tvb_get_ntohl(sctp_info->tvb[chunk_number],4);
+ ip=htonl(ip);
+ v4n.sin_addr.s_addr=ip;
+ store = g_malloc(sizeof(struct sockaddr_storage));
+ g_memmove(store, &v4n, sizeof(struct sockaddr_in));
+ info = add_address(store, info, info->direction);
+ }
+ else if (type == IPV6ADDRESS_PARAMETER_ID)
+ {
+ v6n.sin6_family=AF_INET6;
+ v6n.sin6_port = 0;
+ tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)&(v6n.sin6_addr.s6_addr),IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH);
+ store = g_malloc(sizeof(struct sockaddr_storage));
+ g_memmove(store, &v6n, sizeof(struct sockaddr_in6));
+ info = add_address(store, info, info->direction);
+ }
+
+ }
+ info->initack=TRUE;
+ }
+ else
+ {
+ for (chunk_number = 0; chunk_number < sctp_info->number_of_tvbs; chunk_number++)
+ {
+ if ((tvb_get_guint8(sctp_info->tvb[0],0))==SCTP_DATA_CHUNK_ID)
+ {
+ tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], DATA_CHUNK_TSN_OFFSET);
+ t_s_n = g_malloc(16);
+ tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, 16);
+ tsn->tsns = g_list_append(tsn->tsns, t_s_n);
+ datachunk = TRUE;
+ length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ info->n_data_chunks++;
+ info->n_data_bytes+=length;
+ tsn_s.tsnumber=tsnumber;
+ tsn_s.secs=tsn->secs;
+ tsn_s.usecs=tsn->usecs;
+ tsn_s.offset=0;
+ tsn_s.length=length-16;
+
+ if (info->direction == 1)
+ {
+ if(tsnumber<info->min_tsn1)
+ info->min_tsn1 = tsnumber;
+ if ((info->init==TRUE || (info->initack==TRUE && info->initack_dir==1))&& tsnumber==info->min_tsn1 && tsnumber<=info->max_tsn1)
+ {
+ length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ info->n_data_chunks_ep1++;
+ info->n_data_bytes_ep1+=length;
+ }
+ if(tsnumber>info->max_tsn1)
+ {
+ info->max_tsn1 = tsnumber;
+ length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ info->n_data_chunks_ep1++;
+ info->n_data_bytes_ep1+=length;
+ }
+ if (info->init==FALSE)
+ info->outstream1=tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
+ if (info->initack==FALSE)
+ info->instream2=tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
+
+ info->sort_tsn1=g_array_append_val(info->sort_tsn1, tsn_s);
+ info->n_array_tsn1++;
+ }
+ else if (info->direction == 2)
+ {
+
+ if(tsnumber<info->min_tsn2)
+ info->min_tsn2 = tsnumber;
+
+ if ((info->initack==TRUE && info->initack_dir==2)&& tsnumber==info->min_tsn2 && tsnumber<=info->max_tsn2)
+ {
+ length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ info->n_data_chunks_ep2++;
+ info->n_data_bytes_ep2+=length;
+ }
+ if(tsnumber>info->max_tsn2)
+ {
+ info->max_tsn2 = tsnumber;
+ length=tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ info->n_data_chunks_ep2++;
+ info->n_data_bytes_ep2+=length;
+ }
+ if (info->init==FALSE)
+ info->instream1=tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
+ if (info->initack==FALSE)
+ info->outstream2=tvb_get_ntohs((sctp_info->tvb)[chunk_number], DATA_CHUNK_STREAM_ID_OFFSET)+1;
+
+ info->sort_tsn2=g_array_append_val(info->sort_tsn2, tsn_s);
+ info->n_array_tsn2++;
+ }
+ }
+ else if (tvb_get_guint8(sctp_info->tvb[chunk_number],0)==SCTP_SACK_CHUNK_ID)
+ {
+ tsnumber = tvb_get_ntohl((sctp_info->tvb)[chunk_number], SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
+ length = tvb_get_ntohs(sctp_info->tvb[chunk_number], CHUNK_LENGTH_OFFSET);
+ t_s_n = g_malloc(length);
+ tvb_memcpy(sctp_info->tvb[chunk_number], (guint8 *)(t_s_n),0, length);
+ sack->tsns = g_list_append(sack->tsns, t_s_n);
+ sackchunk=TRUE;
+ tsn_s.tsnumber=tsnumber;
+ tsn_s.secs=tsn->secs;
+ tsn_s.usecs=tsn->usecs;
+ tsn_s.offset=0;
+ tsn_s.length= tvb_get_ntohl(sctp_info->tvb[chunk_number], SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
+
+
+ if (info->direction == 2)
+ {
+ if(tsnumber<info->min_tsn1)
+ info->min_tsn1 = tsnumber;
+ if(tsnumber>info->max_tsn1)
+ info->max_tsn1 = tsnumber;
+ if (tsn_s.length>info->max_window1)
+ info->max_window1=tsn_s.length;
+ info->sort_sack1=g_array_append_val(info->sort_sack1, tsn_s);
+ info->n_sack_chunks_ep1++;
+ }
+ else if (info->direction == 1)
+ {
+
+ if(tsnumber<info->min_tsn2)
+ info->min_tsn2 = tsnumber;
+ if(tsnumber>info->max_tsn2)
+ info->max_tsn2 = tsnumber;
+ if (tsn_s.length>info->max_window2)
+ info->max_window2=tsn_s.length;
+ info->sort_sack2=g_array_append_val(info->sort_sack2, tsn_s);
+ info->n_sack_chunks_ep2++;
+ }
+
+ }
+
+ }
+
+ }
+ if (datachunk==TRUE)
+ {
+ if (info->direction == 1)
+ info->tsn1 = g_list_prepend(info->tsn1, tsn);
+ else if (info->direction == 2)
+ info->tsn2 = g_list_prepend(info->tsn2, tsn);
+ }
+ if (sackchunk==TRUE)
+ {
+ if (info->direction == 1)
+ info->sack2 = g_list_prepend(info->sack2, sack);
+ else if(info->direction == 2)
+ info->sack1 = g_list_prepend(info->sack1, sack);
+ }
+
+ info->n_tvbs+=sctp_info->number_of_tvbs;
+ sctp_tapinfo_struct.sum_tvbs+=sctp_info->number_of_tvbs;
+ info = calc_checksum(sctp_info, info);
+ info->n_packets++;
+
+ }
+
+ return(1);
+}
+
+
+/* XXX just copied from gtk/rpc_stat.c */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
+/****************************************************************************/
+void
+remove_tap_listener_sctp_stat(void)
+{
+ if (sctp_tapinfo_struct.is_registered) {
+ protect_thread_critical_region();
+ remove_tap_listener(&sctp_tapinfo_struct);
+ unprotect_thread_critical_region();
+ sctp_tapinfo_struct.is_registered = FALSE;
+ }
+}
+
+
+void sctp_stat_scan(void)
+{
+ if (!sctp_tapinfo_struct.is_registered)
+ register_tap_listener_sctp_stat();
+}
+
+const sctp_allassocs_info_t* sctp_stat_get_info(void)
+{
+ return &sctp_tapinfo_struct;
+}
+
+
+static void
+gtk_sctpstat_init(char *dummy _U_)
+{
+
+}
+
+static void sctp_update(void)
+{
+ if (get_stat_dlg()!=NULL)
+ sctp_stat_dlg_update();
+}
+
+void
+register_tap_listener_sctp_stat(void)
+{
+GString *error_string;
+
+if (!sctp_tapinfo_struct.is_registered)
+{
+register_ethereal_tap("sctp",gtk_sctpstat_init);
+ if ((error_string = register_tap_listener("sctp", &sctp_tapinfo_struct, NULL, (void *)reset, packet, (void *)sctp_update))) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
+ g_string_free(error_string, TRUE);
+ return;
+ }
+ sctp_tapinfo_struct.is_registered=TRUE;
+ }
+
+
+}
diff --git a/gtk/sctp_stat.h b/gtk/sctp_stat.h
new file mode 100644
index 0000000000..6f9e99f4b7
--- /dev/null
+++ b/gtk/sctp_stat.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
+ *
+ * $Id: sctp_stat.h 11436 2004-07-19 21:42:01Z tuexen $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <epan/dissectors/packet-sctp.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#define SCTP_DATA_CHUNK_ID 0
+#define SCTP_INIT_CHUNK_ID 1
+#define SCTP_INIT_ACK_CHUNK_ID 2
+#define SCTP_SACK_CHUNK_ID 3
+
+#define CHUNK_TYPE_LENGTH 1
+#define CHUNK_FLAGS_LENGTH 1
+#define CHUNK_LENGTH_LENGTH 2
+
+#define CHUNK_HEADER_OFFSET 0
+#define CHUNK_TYPE_OFFSET CHUNK_HEADER_OFFSET
+#define CHUNK_FLAGS_OFFSET (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
+#define CHUNK_LENGTH_OFFSET (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
+#define CHUNK_VALUE_OFFSET (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
+
+#define INIT_CHUNK_INITIATE_TAG_LENGTH 4
+#define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
+#define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
+#define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH 2
+
+
+#define INIT_CHUNK_INITIATE_TAG_OFFSET CHUNK_VALUE_OFFSET
+#define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (INIT_CHUNK_INITIATE_TAG_OFFSET + \
+ INIT_CHUNK_INITIATE_TAG_LENGTH )
+#define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
+ INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
+#define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
+ INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
+#define INIT_CHUNK_INITIAL_TSN_OFFSET (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
+ INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
+
+#define DATA_CHUNK_TSN_LENGTH 4
+#define DATA_CHUNK_TSN_OFFSET (CHUNK_VALUE_OFFSET + 0)
+#define DATA_CHUNK_STREAM_ID_OFFSET (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
+
+
+typedef struct _v4address {
+ address_type type;
+ int len;
+ guint32 data;
+} v4address;
+
+typedef struct _tsn {
+ guint32 frame_number;
+ guint32 secs; /* Absolute seconds */
+ guint32 usecs;
+ struct sockaddr_storage src;
+ struct sockaddr_storage dst;
+ GList *tsns;
+} tsn_t;
+
+typedef struct _sctp_tmp_info {
+ struct sockaddr_storage src;
+ struct sockaddr_storage dst;
+ guint16 port1;
+ guint16 port2;
+ guint32 verification_tag1;
+ guint32 verification_tag2;
+ guint32 n_tvbs;
+}sctp_tmp_info_t;
+
+typedef struct _sctp_min_max {
+ guint32 tmp_min_secs;
+ guint32 tmp_min_usecs;
+ guint32 tmp_max_secs;
+ guint32 tmp_max_usecs;
+ guint32 tmp_min_tsn1;
+ guint32 tmp_min_tsn2;
+ guint32 tmp_max_tsn1;
+ guint32 tmp_max_tsn2;
+ gint tmp_secs;
+} sctp_min_max_t;
+
+struct tsn_sort{
+ guint32 tsnumber;
+ guint32 secs;
+ guint32 usecs;
+ guint32 offset;
+ guint32 length;
+};
+
+
+typedef struct _sctp_assoc_info {
+ //guint16 assoc_id;
+ struct sockaddr_storage src;
+ struct sockaddr_storage dst;
+ guint16 port1;
+ guint16 port2;
+ guint32 verification_tag1;
+ guint32 verification_tag2;
+ guint32 n_tvbs;
+ GList *addr1;
+ GList *addr2;
+ guint16 instream1;
+ guint16 outstream1;
+ guint16 instream2;
+ guint16 outstream2;
+ guint32 n_adler32_calculated;
+ guint32 n_adler32_correct;
+ guint32 n_crc32c_calculated;
+ guint32 n_crc32c_correct;
+ char checksum_type[8];
+ guint32 n_checksum_errors;
+ guint32 n_bundling_errors;
+ guint32 n_padding_errors;
+ guint32 n_length_errors;
+ guint32 n_value_errors;
+ guint32 n_data_chunks;
+ guint32 n_data_bytes;
+ guint32 n_packets;
+ guint32 n_data_chunks_ep1;
+ guint32 n_data_bytes_ep1;
+ guint32 n_data_chunks_ep2;
+ guint32 n_data_bytes_ep2;
+ guint32 n_sack_chunks_ep1;
+ guint32 n_sack_chunks_ep2;
+ guint32 n_array_tsn1;
+ guint32 n_array_tsn2;
+ guint32 max_window1;
+ guint32 max_window2;
+ gboolean init;
+ gboolean initack;
+ guint8 initack_dir;
+ guint8 direction;
+ guint32 min_secs;
+ guint32 min_usecs;
+ guint32 max_secs;
+ guint32 max_usecs;
+ guint32 min_tsn1;
+ guint32 min_tsn2;
+ guint32 max_tsn1;
+ guint32 max_tsn2;
+ guint32 max_bytes1;
+ guint32 max_bytes2;
+ GSList *min_max;
+ GList *frame_numbers;
+ GList *tsn1;
+ GArray *sort_tsn1;
+ GArray *sort_sack1;
+ GList *sack1;
+ GList *tsn2;
+ GArray *sort_tsn2;
+ GArray *sort_sack2;
+ GList *sack2;
+ gboolean check_address;
+ GList* error_info_list;
+} sctp_assoc_info_t;
+
+typedef struct _sctp_error_info {
+ guint32 frame_number;
+ char chunk_info[200];
+ char *info_text;
+} sctp_error_info_t;
+
+
+typedef struct _sctp_allassocs_info {
+guint32 sum_tvbs;
+GList* assoc_info_list;
+gboolean is_registered;
+GList* children;
+} sctp_allassocs_info_t;
+
+
+//Data structures for sctp_assoc_analyse
+
+struct notes {
+ GtkWidget *checktype;
+ GtkWidget *checksum;
+ GtkWidget *bundling;
+ GtkWidget *padding;
+ GtkWidget *length;
+ GtkWidget *value;
+ GtkWidget *chunks_ep1;
+ GtkWidget *bytes_ep1;
+ GtkWidget *chunks_ep2;
+ GtkWidget *bytes_ep2;
+ struct page *page2;
+ struct page *page3;
+};
+
+struct page {
+ GtkWidget *addr_frame;
+ GtkWidget *scrolled_window;
+ GtkWidget *clist;
+ GtkWidget *port;
+ GtkWidget *veritag;
+ GtkWidget *max_in;
+ GtkWidget *min_in;
+ GtkWidget *max_out;
+ GtkWidget *min_out;
+};
+
+struct sctp_analyse {
+ sctp_assoc_info_t* assoc;
+ GtkWidget* window;
+ struct notes *analyse_nb;
+ GList *children;
+ guint16 num_children;
+};
+
+//Data Structures for sctp_graph_dlg
+
+typedef struct _sctp_graph_t {
+ gboolean needs_redraw;
+ gfloat x_interval;
+ gfloat y_interval;
+ GtkWidget *window;
+ GtkWidget *draw_area;
+ GdkPixmap *pixmap;
+ int pixmap_width;
+ int pixmap_height;
+ int graph_type;
+ gdouble x_old;
+ gdouble y_old;
+ gdouble x_new;
+ gdouble y_new;
+ guint16 offset;
+ guint16 length;
+ gboolean tmp;
+ gboolean rectangle;
+ guint32 x1_tmp_sec;
+ guint32 x2_tmp_sec;
+ guint32 x1_tmp_usec;
+ guint32 x2_tmp_usec;
+ guint32 tmp_width;
+ guint32 axis_width;
+ guint32 y1_tmp;
+ guint32 y2_tmp;
+ guint32 tmp_min_tsn1;
+ guint32 tmp_max_tsn1;
+ guint32 tmp_min_tsn2;
+ guint32 tmp_max_tsn2;
+ guint32 min_x;
+ guint32 max_x;
+ guint32 min_y;
+ guint32 max_y;
+} sctp_graph_t;
+
+
+
+struct sctp_udata {
+ sctp_assoc_info_t * assoc;
+ sctp_graph_t *io;
+ struct sctp_analyse* parent;
+ guint16 dir;
+};
+
+
+void register_tap_listener_sctp_stat(void);
+
+const sctp_allassocs_info_t* sctp_stat_get_info(void);
+
+void sctp_stat_scan(void);
+
+void remove_tap_listener_sctp_stat(void);
+
+void reset(sctp_allassocs_info_t *tapdata _U_);
+
+
+void assoc_analyse(sctp_assoc_info_t* assoc);
+
+const sctp_assoc_info_t* get_selected_assoc(void);
+
+void create_graph(guint16 dir, struct sctp_analyse* u_data);
+
+void create_byte_graph(guint16 dir, struct sctp_analyse* u_data);
+
+void sctp_error_dlg_show();
+
+void sctp_stat_dlg_update(void);
+
+GtkWidget *get_stat_dlg(void);
+
+void update_analyse_dlg(struct sctp_analyse* u_data);
+
+void sctp_analyse_start(GtkWidget *w _U_, gpointer data _U_);
+
+void increase_childcount(struct sctp_analyse *parent);
+
+void decrease_childcount(struct sctp_analyse *parent);
+
+void set_child(struct sctp_udata *child, struct sctp_analyse *parent);
+
+void remove_child(struct sctp_udata *child, struct sctp_analyse *parent);
+
+void decrease_analyse_childcount();
+
+void increase_analyse_childcount();
+
+void set_analyse_child(struct sctp_analyse *child);
+
+void remove_analyse_child(struct sctp_analyse *child);
+
diff --git a/gtk/sctp_stat_dlg.c b/gtk/sctp_stat_dlg.c
new file mode 100644
index 0000000000..efeaf1ae3e
--- /dev/null
+++ b/gtk/sctp_stat_dlg.c
@@ -0,0 +1,590 @@
+/*
+ * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
+ *
+ * $Id: sctp_stat_dlg.c 11436 2004-07-19 21:42:01Z tuexen $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include "globals.h"
+#include "epan/filesystem.h"
+
+#include "image/clist_ascend.xpm"
+#include "image/clist_descend.xpm"
+
+#include "tap_menu.h"
+#include "dlg_utils.h"
+#include "ui_util.h"
+#include "main.h"
+#include "compat_macros.h"
+
+#include "sctp_stat.h"
+
+
+static GtkWidget *sctp_stat_dlg=NULL;
+static GtkWidget *clist = NULL;
+static GList *last_list = NULL;
+static gchar *filter_string = NULL;
+static sctp_assoc_info_t* selected_stream = NULL; /* current selection */
+extern GtkWidget *main_display_filter_widget;
+static sctp_allassocs_info_t *sctp_assocs=NULL;
+static guint16 n_children=0;
+
+#define NUM_COLS 7
+#define FRAME_LIMIT 8
+
+typedef struct column_arrows {
+ GtkWidget *table;
+ GtkWidget *ascend_pm;
+ GtkWidget *descend_pm;
+} column_arrows;
+
+
+static void
+dlg_destroy(void)
+{
+guint32 i, j;
+GList *list;
+struct sctp_analyse *child_data;
+
+ j=n_children;
+ for (i=0; i<j; i++)
+ {
+ list=g_list_last(sctp_assocs->children);
+ child_data=(struct sctp_analyse *)list->data;
+ gtk_grab_remove(GTK_WIDGET(child_data->window));
+ gtk_widget_destroy(GTK_WIDGET(child_data->window));
+ list=g_list_previous(list);
+ }
+ g_list_free(sctp_assocs->children);
+ sctp_assocs->children = NULL;
+ sctp_stat_dlg=NULL;
+}
+
+void
+decrease_analyse_childcount()
+{
+ n_children--;
+}
+
+void
+increase_analyse_childcount()
+{
+ n_children++;
+}
+
+void
+set_analyse_child(struct sctp_analyse *child)
+{
+ sctp_assocs->children=g_list_append(sctp_assocs->children, child);
+}
+
+void
+remove_analyse_child(struct sctp_analyse *child)
+{
+ sctp_assocs->children=g_list_remove(sctp_assocs->children, child);
+}
+
+
+static void add_to_clist(sctp_assoc_info_t* assinfo)
+{
+ gint added_row, i;
+ gchar *data[NUM_COLS];
+ gchar field[NUM_COLS][30];
+
+ for (i=0; i<NUM_COLS; i++)
+ data[i]=&field[i][0];
+
+ g_snprintf(field[0], 20, "%u", assinfo->port1);
+ g_snprintf(field[1], 20, "%u", assinfo->port2);
+ g_snprintf(field[2], 20, "%u", assinfo->n_packets);
+ g_snprintf(field[3], 20, "%s", assinfo->checksum_type);
+ g_snprintf(field[4], 20, "%u", assinfo->n_checksum_errors);
+ g_snprintf(field[5], 20, "%u", assinfo->n_data_chunks);
+ g_snprintf(field[6], 20, "%u", assinfo->n_data_bytes);
+
+ added_row = gtk_clist_append(GTK_CLIST(clist), data);
+ gtk_clist_set_row_data(GTK_CLIST(clist), added_row, assinfo);
+}
+
+static void
+sctp_stat_on_unselect(GtkButton *button _U_, gpointer user_data _U_)
+{
+ gtk_clist_unselect_all(GTK_CLIST(clist));
+}
+
+void sctp_stat_dlg_update(void)
+{
+GList *list;
+
+ list=(sctp_stat_get_info()->assoc_info_list);
+ if (sctp_stat_dlg != NULL)
+ {
+ gtk_clist_clear(GTK_CLIST(clist));
+
+ list = g_list_first(sctp_stat_get_info()->assoc_info_list);
+
+ while (list)
+ {
+ add_to_clist((sctp_assoc_info_t*)(list->data));
+ list = g_list_next(list);
+ }
+
+ sctp_stat_on_unselect(NULL, NULL);
+ }
+ last_list = list;
+}
+
+static void
+sctp_stat_on_select_row(GtkCList *clist, gint row, gint column _U_,
+ GdkEventButton *event _U_, gpointer user_data _U_)
+{
+gchar *text[1];
+guint16 port1, port2;
+guint32 checksum, data_chunks, data_bytes, packets;
+GList *list;
+sctp_assoc_info_t* assoc;
+
+ selected_stream = gtk_clist_get_row_data(GTK_CLIST(clist), row);
+
+ gtk_clist_get_text(GTK_CLIST(clist), row, 0, text);
+ port1=atoi(text[0]);
+ gtk_clist_get_text(GTK_CLIST(clist), row, 1, text);
+ port2=atoi(text[0]);
+ gtk_clist_get_text(GTK_CLIST(clist), row, 2, text);
+ packets=atoi(text[0]);
+ gtk_clist_get_text(GTK_CLIST(clist), row, 4, text);
+ checksum=atoi(text[0]);
+ gtk_clist_get_text(GTK_CLIST(clist), row, 5, text);
+ data_chunks=atoi(text[0]);
+
+ gtk_clist_get_text(GTK_CLIST(clist), row, 6, text);
+ data_bytes=atoi(text[0]);
+
+ list = g_list_first(sctp_assocs->assoc_info_list);
+
+ while (list)
+ {
+ assoc = (sctp_assoc_info_t*)(list->data);
+ if (assoc->port1==port1 && assoc->port2==port2 &&
+ assoc->n_packets==packets && assoc->n_checksum_errors==checksum
+ && assoc->n_data_chunks==data_chunks && assoc->n_data_bytes==data_bytes)
+ {
+ selected_stream=assoc;
+ break;
+ }
+ list=g_list_next(list);
+ }
+}
+
+static void
+sctp_stat_on_apply_filter (GtkButton *button _U_, gpointer user_data _U_)
+{
+ main_filter_packets(&cfile, filter_string, FALSE);
+}
+
+static void
+sctp_stat_on_filter (GtkButton *button _U_, gpointer user_data _U_)
+{
+gchar *f_string = NULL;
+guint32 framenumber=0;
+GList *list, *srclist, *dstlist;
+gchar *str=NULL;
+GString *gstring=NULL;
+struct sockaddr_in *infosrc=NULL;
+struct sockaddr_in *infodst=NULL;
+
+ if (selected_stream==NULL)
+ return;
+
+ if (selected_stream->n_packets>FRAME_LIMIT)
+ {
+ if (selected_stream->check_address==FALSE)
+ {
+ f_string = g_strdup_printf(
+ "((sctp.srcport==%u && sctp.dstport==%u && ((sctp.verification_tag==0x%x && sctp.verification_tag!=0x0) || "
+ "(sctp.verification_tag==0x0 && sctp.initiate_tag==0x%x) || "
+ "(sctp.verification_tag==0x%x && (sctp.abort_t_bit==1 || sctp.shutdown_complete_t_bit==1)))) ||"
+ " (sctp.srcport==%u && sctp.dstport==%u && ((sctp.verification_tag==0x%x && sctp.verification_tag!=0x0) || "
+ "(sctp.verification_tag==0x0 && sctp.initiate_tag==0x%x) ||"
+ "(sctp.verification_tag==0x%x && (sctp.abort_t_bit==1 || sctp.shutdown_complete_t_bit==1)))))",
+ selected_stream->port1,
+ selected_stream->port2,
+ selected_stream->verification_tag1,
+ selected_stream->verification_tag2,
+ selected_stream->verification_tag2,
+ selected_stream->port2,
+ selected_stream->port1,
+ selected_stream->verification_tag2,
+ selected_stream->verification_tag1,
+ selected_stream->verification_tag1);
+ filter_string = f_string;
+ }
+ else
+ {
+ srclist = g_list_first(selected_stream->addr1);
+ infosrc=(struct sockaddr_in *) (srclist->data);
+ gstring = g_string_new(g_strdup_printf("((sctp.srcport==%u && sctp.dstport==%u && (ip.src==%s",
+ selected_stream->port1, selected_stream->port2, ip_to_str((const guint8 *)&(infosrc->sin_addr.s_addr))));
+ srclist= g_list_next(srclist);
+
+ while (srclist)
+ {
+ infosrc=(struct sockaddr_in *) (srclist->data);
+ str =g_strdup_printf("|| ip.src==%s",ip_to_str((const guint8 *)&(infosrc->sin_addr.s_addr)));
+ g_string_append(gstring, str);
+ srclist= g_list_next(srclist);
+ }
+
+ dstlist = g_list_first(selected_stream->addr2);
+ infodst=(struct sockaddr_in *) (dstlist->data);
+ str = g_strdup_printf(") && (ip.dst==%s",ip_to_str((const guint8 *)&(infodst->sin_addr.s_addr)));
+ g_string_append(gstring, str);
+ dstlist= g_list_next(dstlist);
+ while (dstlist)
+ {
+ infodst=(struct sockaddr_in *) (dstlist->data);
+ str =g_strdup_printf("|| ip.dst==%s",ip_to_str((const guint8 *)&(infodst->sin_addr.s_addr)));
+ g_string_append(gstring, str);
+ dstlist= g_list_next(dstlist);
+ }
+
+ srclist = g_list_first(selected_stream->addr1);
+ infosrc=(struct sockaddr_in *) (srclist->data);
+ str = g_strdup_printf(")) || (sctp.dstport==%u && sctp.srcport==%u && (ip.dst==%s",
+ selected_stream->port1, selected_stream->port2, ip_to_str((const guint8 *)&(infosrc->sin_addr.s_addr)));
+ g_string_append(gstring, str);
+ srclist= g_list_next(srclist);
+
+ while (srclist)
+ {
+ infosrc=(struct sockaddr_in *) (srclist->data);
+ str =g_strdup_printf("|| ip.dst==%s",ip_to_str((const guint8 *)&(infosrc->sin_addr.s_addr)));
+ g_string_append(gstring, str);
+ srclist= g_list_next(srclist);
+ }
+
+ dstlist = g_list_first(selected_stream->addr2);
+ infodst=(struct sockaddr_in *) (dstlist->data);
+ str = g_strdup_printf(") && (ip.src==%s",ip_to_str((const guint8 *)&(infodst->sin_addr.s_addr)));
+ g_string_append(gstring, str);
+ dstlist= g_list_next(dstlist);
+ while (dstlist)
+ {
+ infodst=(struct sockaddr_in *) (dstlist->data);
+ str =g_strdup_printf("|| ip.src==%s",ip_to_str((const guint8 *)&(infodst->sin_addr.s_addr)));
+ g_string_append(gstring, str);
+ dstlist= g_list_next(dstlist);
+ }
+ str = g_strdup_printf(")))");
+ g_string_append(gstring, str);
+ filter_string = gstring->str;
+ }
+ }
+ else
+ {
+ list = g_list_first(selected_stream->frame_numbers);
+ framenumber = *((guint32 *)(list->data));
+ gstring = g_string_new(g_strdup_printf("frame.number==%u",framenumber));
+ list = g_list_next(list);
+ while (list)
+ {
+ framenumber = *((guint32 *)(list->data));
+ str =g_strdup_printf(" || frame.number==%u",framenumber);
+ g_string_append(gstring, str);
+ list = g_list_next(list);
+ }
+ filter_string = gstring->str;
+ }
+ gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), filter_string);
+}
+
+
+static void
+sctp_stat_on_close (GtkButton *button _U_, gpointer user_data _U_)
+{
+ gtk_grab_remove(sctp_stat_dlg);
+ gtk_widget_destroy(sctp_stat_dlg);
+}
+
+static void
+sctp_stat_on_analyse (GtkButton *button _U_, gpointer user_data _U_)
+{
+ if (selected_stream==NULL)
+ return;
+
+ if (selected_stream)
+ assoc_analyse(selected_stream);
+}
+
+static gint
+clist_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
+{
+ char *text1 = NULL;
+ char *text2 = NULL;
+ int i1, i2;
+
+ GtkCListRow *row1 = (GtkCListRow *) ptr1;
+ GtkCListRow *row2 = (GtkCListRow *) ptr2;
+
+ text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
+ text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
+
+ switch(clist->sort_column){
+ case 0:
+ case 2:
+ return strcmp (text1, text2);
+ case 1:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ i1=atoi(text1);
+ i2=atoi(text2);
+ return i1-i2;
+ }
+ g_assert_not_reached();
+ return 0;
+}
+
+static void
+clist_click_column_cb(GtkCList *list, gint column, gpointer data)
+{
+ column_arrows *col_arrows = (column_arrows *) data;
+ int i;
+ gtk_clist_freeze(list);
+
+ for (i = 0; i < NUM_COLS; i++) {
+ gtk_widget_hide(col_arrows[i].ascend_pm);
+ gtk_widget_hide(col_arrows[i].descend_pm);
+ }
+
+ if (column == list->sort_column) {
+ if (list->sort_type == GTK_SORT_ASCENDING) {
+ list->sort_type = GTK_SORT_DESCENDING;
+ gtk_widget_show(col_arrows[column].descend_pm);
+ } else {
+ list->sort_type = GTK_SORT_ASCENDING;
+ gtk_widget_show(col_arrows[column].ascend_pm);
+ }
+ } else {
+ list->sort_type = GTK_SORT_DESCENDING;
+ gtk_widget_show(col_arrows[column].descend_pm);
+ gtk_clist_set_sort_column(list, column);
+ }
+ gtk_clist_thaw(list);
+
+ gtk_clist_sort(list);
+}
+
+static void
+gtk_sctpstat_dlg(void)
+{
+GtkWidget *sctp_stat_dlg_w;
+GtkWidget *vbox1;
+GtkWidget *scrolledwindow1;
+GtkWidget *hbuttonbox2;
+GtkWidget *bt_unselect;
+GtkWidget *bt_filter, *bt_afilter;
+GtkWidget *bt_close;
+GtkWidget *bt_analyse;
+
+gchar *titles[NUM_COLS] = {"Port 1","Port 2", "No of Packets", "Checksum", "No of Errors", "Data Chunks", "Data Bytes"};
+column_arrows *col_arrows;
+GdkBitmap *ascend_bm, *descend_bm;
+GdkPixmap *ascend_pm, *descend_pm;
+GtkStyle *win_style;
+GtkWidget *column_lb;
+int i;
+
+ sctp_stat_dlg_w = window_new (GTK_WINDOW_TOPLEVEL, "Ethereal: SCTP Associations");
+ gtk_window_set_position (GTK_WINDOW (sctp_stat_dlg_w), GTK_WIN_POS_CENTER);
+ SIGNAL_CONNECT(sctp_stat_dlg_w, "destroy", dlg_destroy,NULL);
+
+ /* Container for each row of widgets */
+ vbox1 = gtk_vbox_new(FALSE, 2);
+ gtk_container_border_width(GTK_CONTAINER(vbox1), 8);
+ gtk_container_add(GTK_CONTAINER(sctp_stat_dlg_w), vbox1);
+ gtk_widget_show(vbox1);
+
+ scrolledwindow1 = scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scrolledwindow1);
+ gtk_box_pack_start (GTK_BOX (vbox1), scrolledwindow1, TRUE, TRUE, 0);
+
+ clist = gtk_clist_new (NUM_COLS);
+ gtk_widget_show (clist);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow1), clist);
+ WIDGET_SET_SIZE(clist, 700, 200);
+
+ gtk_clist_set_column_width (GTK_CLIST (clist), 0, 50);
+ gtk_clist_set_column_width (GTK_CLIST (clist), 1, 50);
+ gtk_clist_set_column_width (GTK_CLIST (clist), 2, 100);
+ gtk_clist_set_column_width (GTK_CLIST (clist), 3, 100);
+ gtk_clist_set_column_width (GTK_CLIST (clist), 4, 100);
+ gtk_clist_set_column_width (GTK_CLIST (clist), 5, 100);
+ gtk_clist_set_column_width (GTK_CLIST (clist), 6, 100);
+
+
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 3, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 4, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 5, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist), 6, GTK_JUSTIFY_CENTER);
+ gtk_clist_column_titles_show (GTK_CLIST (clist));
+
+ gtk_clist_set_compare_func(GTK_CLIST(clist), clist_sort_column);
+ gtk_clist_set_sort_column(GTK_CLIST(clist), 0);
+ gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_ASCENDING);
+
+ gtk_widget_show(sctp_stat_dlg_w);
+
+ col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
+ win_style = gtk_widget_get_style(scrolledwindow1);
+
+ ascend_pm = gdk_pixmap_create_from_xpm_d(scrolledwindow1->window,
+ &ascend_bm,
+ &win_style->bg[GTK_STATE_NORMAL],
+ (gchar **)clist_ascend_xpm);
+ descend_pm = gdk_pixmap_create_from_xpm_d(scrolledwindow1->window,
+ &descend_bm,
+ &win_style->bg[GTK_STATE_NORMAL],
+ (gchar **)clist_descend_xpm);
+ for (i=0; i<NUM_COLS; i++)
+ {
+ col_arrows[i].table = gtk_table_new(2, 2, FALSE);
+ gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
+ column_lb = gtk_label_new(titles[i]);
+ gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+ gtk_widget_show(column_lb);
+ col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
+ gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+ col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
+ gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+ /* make src-ip be the default sort order */
+ if (i == 0)
+ {
+ gtk_widget_show(col_arrows[i].ascend_pm);
+ }
+
+ gtk_clist_set_column_widget(GTK_CLIST(clist), i, col_arrows[i].table);
+ gtk_widget_show(col_arrows[i].table);
+ }
+
+ SIGNAL_CONNECT(clist, "click-column", clist_click_column_cb, col_arrows);
+
+ hbuttonbox2 = gtk_hbutton_box_new();
+ gtk_box_pack_start(GTK_BOX(vbox1), hbuttonbox2, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(hbuttonbox2), 10);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_SPREAD);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX (hbuttonbox2), 0);
+ gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (hbuttonbox2), 4, 0);
+ gtk_widget_show(hbuttonbox2);
+
+ bt_unselect = gtk_button_new_with_label ("Unselect");
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_unselect);
+ gtk_widget_show (bt_unselect);
+
+ bt_filter = gtk_button_new_with_label ("Set filter");
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_filter);
+ gtk_widget_show (bt_filter);
+
+ bt_afilter = gtk_button_new_with_label ("Apply filter");
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_afilter);
+ gtk_widget_show (bt_afilter);
+
+ bt_analyse = gtk_button_new_with_label ("Analyse");
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_analyse);
+ gtk_widget_show (bt_analyse);
+
+ bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), bt_close);
+ gtk_widget_show (bt_close);
+
+ SIGNAL_CONNECT(sctp_stat_dlg_w, "destroy", dlg_destroy, NULL);
+ SIGNAL_CONNECT(clist, "select_row", sctp_stat_on_select_row, NULL);
+ SIGNAL_CONNECT(bt_unselect, "clicked", sctp_stat_on_unselect, NULL);
+ SIGNAL_CONNECT(bt_filter, "clicked", sctp_stat_on_filter, NULL);
+ SIGNAL_CONNECT(bt_afilter, "clicked", sctp_stat_on_apply_filter, NULL);
+ SIGNAL_CONNECT(bt_analyse, "clicked", sctp_stat_on_analyse, NULL);
+ SIGNAL_CONNECT(bt_close, "clicked", sctp_stat_on_close, NULL);
+
+ sctp_stat_dlg = sctp_stat_dlg_w;
+ retap_packets(&cfile);
+
+}
+
+
+void sctp_stat_dlg_show()
+{
+ if (sctp_stat_dlg != NULL)
+ {
+ /* There's already a dialog box; reactivate it. */
+ reactivate_window(sctp_stat_dlg);
+ /* Another list since last call? */
+ if ((sctp_stat_get_info()->assoc_info_list) != last_list)
+ sctp_stat_dlg_update();
+ }
+ else
+ {
+ /* Create and show the dialog box */
+ gtk_sctpstat_dlg();
+ sctp_stat_dlg_update();
+ }
+}
+
+
+void sctp_stat_start(GtkWidget *w _U_, gpointer data _U_)
+{
+
+ sctp_assocs = g_malloc(sizeof(sctp_allassocs_info_t));
+ sctp_assocs = (sctp_allassocs_info_t*)sctp_stat_get_info();
+ /* Register the tap listener */
+ if (sctp_stat_get_info()->is_registered==FALSE)
+ register_tap_listener_sctp_stat();
+ /* (redissect all packets) */
+ sctp_stat_scan();
+
+ /* Show the dialog box with the list of streams */
+ //sctp_stat_dlg_show(sctp_stat_get_info()->assoc_info_list);
+ sctp_stat_dlg_show();
+}
+
+/****************************************************************************/
+void
+register_tap_listener_sctp_stat_dlg(void)
+{
+ register_tap_menu_item("SCTP/Show All Associations...", REGISTER_TAP_GROUP_NONE,
+ sctp_stat_start, NULL, NULL, NULL);
+}
+
+
+GtkWidget* get_stat_dlg(void)
+{
+ return sctp_stat_dlg;
+}