From Oleg Terletsky: Support for SCTP chunk counters. Modified to handle bundling...
authortuexen <tuexen@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 20 Mar 2005 12:02:00 +0000 (12:02 +0000)
committertuexen <tuexen@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 20 Mar 2005 12:02:00 +0000 (12:02 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@13823 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
Makefile.common
epan/dissectors/packet-sctp.c
gtk/Makefile.common
gtk/conversations_sctp.c [new file with mode: 0644]
gtk/sctp_chunk_stat.c [new file with mode: 0644]
tap-iousers.c
tap-sctpchunkstat.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index a5ca29ac33de44626fb34e1f5ae714d5d1d3140c..1e5ace70afc0260d92c416ff09f958da59c93aa3 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1862,6 +1862,7 @@ Thierry Martin          <thierry.martin [AT] accellent-group.com> {
 Oleg Terletsky          <oleg.terletsky [AT] comverse.com> {
        LWRES support
        AgentX support
+       SCTP chunk statistic
 }
 
 Michael Lum             <mlum [AT] telostech.com> {
index aca585176ed97c6e5c0429fc83c9b272f835ea2a..a105566ac49dba1735f15d7452b95e1059b4cb73 100644 (file)
@@ -125,6 +125,7 @@ TETHEREAL_TAP_SRC = \
        tap-protohierstat.c     \
        tap-rpcstat.c   \
        tap-rpcprogs.c  \
+       tap-sctpchunkstat.c     \
        tap-sipstat.c \
        tap-smbsids.c   \
        tap-smbstat.c   \
index 4332142fdd7511234034953a837d264ac8d2ef21..095eb04f3a857d5ae4df7731e1e64e89a74cd872 100644 (file)
@@ -1902,9 +1902,6 @@ dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, pr
     flags_item = NULL;
   };
 
-  /* FIXME
-  sctp_info.msg_type = type;
-  */
   /* now dissect the chunk value */
   switch(type) {
   case SCTP_DATA_CHUNK_ID:
@@ -2174,12 +2171,11 @@ dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   memset(&sctp_info, 0, sizeof(struct _sctp_info));
   sctp_info.verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
   
-  /* FIXME
+  /* FIXME: Do we need to put this into _sctp_info? */
   sctp_info.sport = pinfo->srcport;
   sctp_info.dport = pinfo->destport;
   SET_ADDRESS(&sctp_info.ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
   SET_ADDRESS(&sctp_info.ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
-  */
   
   dissect_sctp_packet(tvb, pinfo, tree, FALSE);
   if (!pinfo->in_error_pkt)
index ec6c35d7d01a1694111dd8cd9ca4e5d3c012664e..4dce286c70a19516b1abae28dd19946f934bf452 100644 (file)
@@ -106,11 +106,13 @@ ETHEREAL_TAP_SRC = \
        ansi_a_stat.c   \
        ansi_map_stat.c \
        bootp_stat.c    \
+       sctp_chunk_stat.c       \
        conversations_eth.c     \
        conversations_fc.c      \
        conversations_fddi.c    \
        conversations_ip.c      \
        conversations_ipx.c     \
+       conversations_sctp.c    \
        conversations_tcpip.c   \
        conversations_tr.c      \
        conversations_udpip.c   \
@@ -145,6 +147,7 @@ ETHEREAL_TAP_SRC = \
        stats_tree_stat.c       \
        sctp_assoc_analyse.c    \
        sctp_stat_dlg.c \
+#      sctp_chunk_stat_dlg.c   \
        sip_stat.c      \
        smb_stat.c      \
        tcp_graph.c     \
diff --git a/gtk/conversations_sctp.c b/gtk/conversations_sctp.c
new file mode 100644 (file)
index 0000000..1b9a94b
--- /dev/null
@@ -0,0 +1,96 @@
+/* conversations_sctp.c
+ * conversations_sctp   2005 Oleg Terletsky <oleg.terletsky@comverse.com>
+ *
+ * $Id:$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <string.h>
+#include "epan/packet.h"
+#include "tap_menu.h"
+#include <epan/tap.h>
+#include "../register.h"
+#include "conversations_table.h"
+#include <epan/dissectors/packet-sctp.h>
+
+
+static int
+sctp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
+{
+       const struct _sctp_info *sctphdr=vip;
+
+       add_conversation_table_data((conversations_table *)pct, 
+               &sctphdr->ip_src, 
+               &sctphdr->ip_dst, 
+               sctphdr->sport, 
+               sctphdr->dport, 
+               1, 
+               pinfo->fd->pkt_len, 
+               SAT_NONE, 
+               PT_SCTP);
+
+
+       return 1;
+}
+
+
+
+static void
+sctp_conversation_init(char *optarg)
+{
+       char *filter=NULL;
+
+       if(!strncmp(optarg,"conv,sctp,",10)){
+               filter=optarg+10;
+       } else {
+               filter=NULL;
+       }
+
+       init_conversation_table(FALSE, "SCTP", "sctp", filter, sctp_conversation_packet);
+
+}
+
+
+static void
+sctp_conversation_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+       sctp_conversation_init("conv,sctp");
+}
+
+
+void
+register_tap_listener_sctp_conversation(void)
+{
+       register_ethereal_tap("conv,sctp", sctp_conversation_init);
+
+       register_tap_menu_item("SCTP", REGISTER_TAP_GROUP_CONVERSATION_LIST,
+           sctp_conversation_cb, NULL, NULL, NULL);
+
+    register_conversation_table(FALSE, "SCTP", "sctp", NULL /*filter*/, sctp_conversation_packet);
+}
diff --git a/gtk/sctp_chunk_stat.c b/gtk/sctp_chunk_stat.c
new file mode 100644 (file)
index 0000000..8d8eee0
--- /dev/null
@@ -0,0 +1,351 @@
+/* sctp_chunk_stat.c
+ * SCTP chunk counter for ethereal
+ * Copyright 2005 Oleg Terletsky oleg.terletsky@comverse.com
+ *
+ * $Id:$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include <epan/packet_info.h>
+#include <epan/epan.h>
+#include <epan/value_string.h>
+
+#include "tap_menu.h"
+#include <epan/tap.h>
+#include "../register.h"
+#include <epan/dissectors/packet-sctp.h>
+#include "gtk_stat_util.h"
+#include "compat_macros.h"
+#include "../simple_dialog.h"
+#include "dlg_utils.h"
+#include "../file.h"
+#include "../globals.h"
+#include "../tap_dfilter_dlg.h"
+#include "tap_dfilter_dlg.h"
+#include "ui_util.h"
+
+
+static void sctpstat_init(char *optarg);
+
+static tap_dfilter_dlg sctp_stat_dlg = {
+       "SCTP Statisctics",
+       "sctp,stat",
+       sctpstat_init,
+       -1
+};
+
+typedef struct sctp_ep {
+       struct sctp_ep* next;
+       address src;
+       address dst;
+       guint16 sport;
+       guint16 dport;
+       guint32 chunk_count[256];
+} sctp_ep_t;
+
+/* used to keep track of the statistics for an entire program interface */
+typedef struct _sctp_stat_t {
+       GtkWidget  *win;
+       GtkWidget  *vbox;
+       char       *filter;
+       GtkWidget  *scrolled_window;
+       GtkCList   *table;
+       guint32    number_of_packets;
+       sctp_ep_t* ep_list;
+} sctpstat_t;
+
+typedef struct _sctp_info sctp_into_t;
+
+#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 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_AUTH_CHUNK_ID           0x16
+#define SCTP_ASCONF_ACK_CHUNK_ID      0x80
+#define SCTP_PKTDROP_CHUNK_ID        0x81
+#define SCTP_FORWARD_TSN_CHUNK_ID     0xC0
+#define SCTP_ASCONF_CHUNK_ID         0xC1
+#define SCTP_IETF_EXT                0xFF
+
+#define CHUNK_TYPE_OFFSET 0
+#define CHUNK_TYPE(x)(tvb_get_guint8((x), CHUNK_TYPE_OFFSET))
+
+static void
+sctpstat_reset(void *phs)
+{
+       sctpstat_t* sctp_stat = (sctpstat_t *)phs;
+       sctp_ep_t* list = (sctp_ep_t*)sctp_stat->ep_list;
+       sctp_ep_t* tmp = NULL;
+       guint16 chunk_type;
+       
+       if(!list)
+               return;
+
+       for(tmp = list; tmp ; tmp=tmp->next)
+               for(chunk_type = 0; chunk_type < 256; chunk_type++)
+                       tmp->chunk_count[chunk_type] = 0;
+
+       sctp_stat->number_of_packets = 0;
+}
+
+sctp_ep_t* alloc_sctp_ep(struct _sctp_info *si)
+{
+       sctp_ep_t* ep;
+       guint16 chunk_type;
+
+       if(!si)
+               return NULL;
+
+       if (!(ep = g_malloc(sizeof(sctp_ep_t))))
+               return NULL;
+       
+       COPY_ADDRESS(&ep->src,&si->ip_src);
+       COPY_ADDRESS(&ep->dst,&si->ip_dst);
+       ep->sport = si->sport;
+       ep->dport = si->dport;
+       ep->next = NULL;
+       for(chunk_type = 0; chunk_type < 256; chunk_type++)
+               ep->chunk_count[chunk_type] = 0;
+       return ep;
+}
+
+static int
+sctpstat_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi)
+{
+
+       sctpstat_t *hs=(sctpstat_t *)phs;
+       sctp_ep_t *tmp = NULL, *te = NULL;
+       struct _sctp_info *si = (struct _sctp_info *) phi;
+       guint32 tvb_number;
+       guint8 chunk_type;
+       
+       if (!hs)
+               return (0);
+               
+       hs->number_of_packets++;
+       if(!hs->ep_list) {
+               hs->ep_list = alloc_sctp_ep(si);
+               te = hs->ep_list;
+       } else {
+               for(tmp=hs->ep_list ; tmp ; tmp=tmp->next) {
+                       if((!CMP_ADDRESS(&tmp->src,&si->ip_src)) &&
+                          (!CMP_ADDRESS(&tmp->dst,&si->ip_dst)) &&
+                          (tmp->sport == si->sport) &&
+                          (tmp->dport == si->dport)) {
+                               te = tmp;
+                               break;
+                       }
+               }
+               if(!te) {
+                       if ((te = alloc_sctp_ep(si))) {
+                               te->next = hs->ep_list;
+                               hs->ep_list = te;
+                       }
+               }
+       }
+
+       if(!te)
+               return (0);
+
+       
+       if (si->number_of_tvbs > 0) {
+               chunk_type = CHUNK_TYPE(si->tvb[0]);
+               if ((chunk_type == SCTP_INIT_CHUNK_ID) ||
+                   (chunk_type == SCTP_INIT_ACK_CHUNK_ID)) {
+                       (te->chunk_count[chunk_type])++;
+               } else {
+                       for(tvb_number = 0; tvb_number < si->number_of_tvbs; tvb_number++) {
+                               (te->chunk_count[CHUNK_TYPE(si->tvb[tvb_number])])++;
+                       }
+               }
+       }
+       return (1);
+}
+
+
+static void
+sctpstat_draw(void *phs)
+{
+       sctpstat_t *hs=(sctpstat_t *)phs;
+       sctp_ep_t* list = hs->ep_list, *tmp=0;
+       char *str[14];
+       int i=0;
+
+       for(i=0;i<14;i++) {
+               str[i]=g_malloc(sizeof(char[256]));
+       }
+       /* Now print Message and Reason Counter Table */
+       /* clear list before printing */
+       gtk_clist_clear(hs->table);
+
+
+       for(tmp = list ; tmp ; tmp=tmp->next) {
+               
+               g_snprintf(str[0],  sizeof(char[256]),"%s", address_to_str(&tmp->src));
+               g_snprintf(str[1],  sizeof(char[256]),"%u", tmp->sport);
+               g_snprintf(str[2],  sizeof(char[256]),"%s", address_to_str(&tmp->dst));
+               g_snprintf(str[3],  sizeof(char[256]),"%u", tmp->dport);
+               g_snprintf(str[4],  sizeof(char[256]),"%u", tmp->chunk_count[SCTP_DATA_CHUNK_ID]);
+               g_snprintf(str[5],  sizeof(char[256]),"%u", tmp->chunk_count[SCTP_SACK_CHUNK_ID]);
+               g_snprintf(str[6],  sizeof(char[256]),"%u", tmp->chunk_count[SCTP_HEARTBEAT_CHUNK_ID]);
+               g_snprintf(str[7],  sizeof(char[256]),"%u", tmp->chunk_count[SCTP_HEARTBEAT_ACK_CHUNK_ID]);
+               g_snprintf(str[8],  sizeof(char[256]),"%u", tmp->chunk_count[SCTP_INIT_CHUNK_ID]);
+               g_snprintf(str[9],  sizeof(char[256]),"%u", tmp->chunk_count[SCTP_INIT_ACK_CHUNK_ID]);
+               g_snprintf(str[10], sizeof(char[256]),"%u", tmp->chunk_count[SCTP_COOKIE_ECHO_CHUNK_ID]);
+               g_snprintf(str[11], sizeof(char[256]),"%u", tmp->chunk_count[SCTP_COOKIE_ACK_CHUNK_ID]);
+               g_snprintf(str[12], sizeof(char[256]),"%u", tmp->chunk_count[SCTP_ABORT_CHUNK_ID]);
+               g_snprintf(str[13], sizeof(char[256]),"%u", tmp->chunk_count[SCTP_ERROR_CHUNK_ID]);
+
+               gtk_clist_append(hs->table, str);
+       }
+
+       gtk_widget_show(GTK_WIDGET(hs->table));
+
+}
+
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+static void
+win_destroy_cb(GtkWindow *win _U_, gpointer data)
+{
+       sctpstat_t *hs=(sctpstat_t *)data;
+
+       protect_thread_critical_region();
+       remove_tap_listener(hs);
+       unprotect_thread_critical_region();
+
+       if(hs->filter){
+               g_free(hs->filter);
+               hs->filter=NULL;
+       }
+       g_free(hs);
+}
+
+
+static gchar *titles[]={"Source IP",
+                       "Sourse port",
+                       "Dest IP",
+                       "Dest port",
+                       "DATA",
+                       "SACK",
+                       "HBEAT",
+                       "HBEAT_ACK",
+                       "INIT",
+                       "INIT_ACK",
+                       "COOKIE",
+                       "COOKIE_ACK",
+                       "ABORT",
+                       "ERROR" };
+
+static void
+sctpstat_init(char *optarg)
+{
+       sctpstat_t *hs;
+       char *filter=NULL;
+       GString *error_string;
+       GtkWidget *bbox;
+       GtkWidget *close_bt;
+
+       if(strncmp(optarg,"sctp,stat,",11) == 0){
+               filter=optarg+11;
+       } else {
+               filter=g_malloc(1);
+               *filter='\0';
+       }
+
+       hs=g_malloc(sizeof(sctpstat_t));
+       hs->filter=g_strdup(filter);
+       hs->ep_list = NULL;
+       hs->number_of_packets = 0;
+       sctpstat_reset(hs);
+
+       hs->win=window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: SCTP chunk statistics");
+       gtk_window_set_default_size(GTK_WINDOW(hs->win), 400, 200);
+
+       hs->vbox=gtk_vbox_new(FALSE, 3);
+       gtk_container_set_border_width(GTK_CONTAINER(hs->vbox), 12);
+
+       init_main_stat_window(hs->win, hs->vbox, "SCTP chunk counter", filter);
+
+       /* init a scrolled window*/
+       hs->scrolled_window = scrolled_window_new(NULL, NULL);
+
+       hs->table = create_stat_table(hs->scrolled_window, hs->vbox, 14, titles);
+
+       error_string=register_tap_listener("sctp", hs, filter, 
+                                          sctpstat_reset, 
+                                          sctpstat_packet, 
+                                          sctpstat_draw);
+       if(error_string){
+               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
+               g_string_free(error_string, TRUE);
+               g_free(hs->filter);
+               g_free(hs);
+               return;
+       }
+
+       /* Button row. */
+       bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+       gtk_box_pack_end(GTK_BOX(hs->vbox), bbox, FALSE, FALSE, 0);
+
+       close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
+       window_set_cancel_button(hs->win, close_bt, window_cancel_button_cb);
+
+       SIGNAL_CONNECT(hs->win, "delete_event", window_delete_event_cb, NULL);
+       SIGNAL_CONNECT(hs->win, "destroy", win_destroy_cb, hs);
+
+       gtk_widget_show_all(hs->win);
+       window_present(hs->win);
+
+       cf_retap_packets(&cfile);
+}
+
+void
+register_tap_listener_sctpstat(void)
+{
+       register_ethereal_tap("sctp,stat", sctpstat_init);
+
+       register_tap_menu_item("SCTP Chunk", REGISTER_TAP_GROUP_NONE,
+                              gtk_tap_dfilter_dlg_cb, NULL, NULL, &(sctp_stat_dlg));
+}
index e1a93d07df5039810db01aa4aaa889aeef62819a..4d0ed164fccdfe9b5bf2a250543fd95fb5612c48 100644 (file)
@@ -43,6 +43,7 @@
 #include <epan/dissectors/packet-tcp.h>
 #include <epan/dissectors/packet-udp.h>
 #include <epan/dissectors/packet-eth.h>
+#include <epan/dissectors/packet-sctp.h>
 #include <epan/dissectors/packet-tr.h>
 #include <epan/dissectors/packet-fc.h>
 #include <epan/dissectors/packet-fddi.h>
@@ -127,6 +128,65 @@ iousers_udpip_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
 }
 
 
+static int
+iousers_sctp_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vsctp)
+{
+       io_users_t *iu=arg;
+       const struct _sctp_info* sctph = vsctp;
+       char name1[256],name2[256], s_sport[10], s_dport[10];
+       io_users_item_t *iui;
+       int direction=0;
+
+       sprintf(s_sport,"%d",sctph->sport);
+       sprintf(s_dport,"%d",sctph->dport);
+       
+       if(sctph->sport > sctph->dport) {
+               direction=0;
+               snprintf(name1,256,"%s:%s",address_to_str(&sctph->ip_src),s_sport);     
+               snprintf(name2,256,"%s:%s",address_to_str(&sctph->ip_dst),s_dport);     
+       } else if(sctph->sport < sctph->dport) {
+               direction=1;
+               snprintf(name1,256,"%s:%s",address_to_str(&sctph->ip_src),s_sport);     
+               snprintf(name2,256,"%s:%s",address_to_str(&sctph->ip_dst),s_dport);     
+       } else {
+               direction=0;
+               snprintf(name1,256,"%s:%s",address_to_str(&sctph->ip_src),s_sport);     
+               snprintf(name2,256,"%s:%s",address_to_str(&sctph->ip_dst),s_dport);     
+       }
+
+       for(iui=iu->items;iui;iui=iui->next){
+               if((!strcmp(iui->name1, name1))
+                && (!strcmp(iui->name2, name2)) ){
+                       break;
+               }
+       }
+
+       if(!iui){
+                iui=g_malloc(sizeof(io_users_item_t));
+                iui->next=iu->items;
+                iu->items=iui;
+/*              iui->addr1=NULL;*/
+                iui->name1=strdup(name1);
+/*              iui->addr2=NULL;*/
+                iui->name2=strdup(name2);
+                iui->frames1=0;
+                iui->frames2=0;
+                iui->bytes1=0;
+                iui->bytes2=0;
+        }
+
+       if(direction){
+                iui->frames1++;
+                iui->bytes1+=pinfo->fd->pkt_len;
+        } else {
+                iui->frames2++;
+                iui->bytes2+=pinfo->fd->pkt_len;
+        }
+
+        return 1;
+}
+
+
 static int
 iousers_tcpip_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vtcph)
 {
@@ -599,6 +659,15 @@ iousers_init(char *optarg)
                tap_type="ip";
                tap_type_name="IPv4";
                packet_func=iousers_ip_packet;
+       } else if(!strncmp(optarg,"conv,sctp",9)) {
+               if(optarg[9]==','){
+                               filter=optarg+10;
+               } else {
+                        filter=NULL;
+                }
+               tap_type="sctp";
+               tap_type_name="SCTP";
+               packet_func=iousers_sctp_packet;
        } else {
                fprintf(stderr, "tethereal: invalid \"-z conv,<type>[,<filter>]\" argument\n");
                fprintf(stderr,"   <type> must be one of\n");
@@ -607,6 +676,7 @@ iousers_init(char *optarg)
                fprintf(stderr,"      \"fddi\"\n");
                fprintf(stderr,"      \"ip\"\n");
                fprintf(stderr,"      \"ipx\"\n");
+               fprintf(stderr,"      \"sctp\"\n");
                fprintf(stderr,"      \"tcp\"\n");
                fprintf(stderr,"      \"tr\"\n");
                fprintf(stderr,"      \"udp\"\n");
diff --git a/tap-sctpchunkstat.c b/tap-sctpchunkstat.c
new file mode 100644 (file)
index 0000000..8cdf8e5
--- /dev/null
@@ -0,0 +1,265 @@
+/* tap_sctpchunkstat.c
+ * SCTP chunk counter for ethereal
+ * Copyright 2005 Oleg Terletsky <oleg.terletsky@comverse.com>
+ *
+ * $Id:$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/* With MSVC and a libethereal.dll this file needs to import some variables 
+   in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */  
+#define _NEED_VAR_IMPORT_
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+#include "epan/packet_info.h"
+#include "epan/addr_resolv.h"
+#include <epan/tap.h>
+#include "epan/value_string.h"
+#include "register.h"
+#include <epan/dissectors/packet-sctp.h>
+
+typedef struct sctp_ep {
+       struct sctp_ep* next;
+       address src;
+       address dst;
+       guint16 sport;
+       guint16 dport;
+       guint32 chunk_count[256];
+} sctp_ep_t;
+
+
+/* used to keep track of the statistics for an entire program interface */
+typedef struct _sctpstat_t {
+       char*      filter;
+       guint32    number_of_packets;
+       sctp_ep_t* ep_list;
+} sctpstat_t;
+
+
+#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 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_AUTH_CHUNK_ID            0x16
+#define SCTP_ASCONF_ACK_CHUNK_ID      0x80
+#define SCTP_PKTDROP_CHUNK_ID         0x81
+#define SCTP_FORWARD_TSN_CHUNK_ID     0xC0
+#define SCTP_ASCONF_CHUNK_ID          0xC1
+#define SCTP_IETF_EXT                 0xFF
+
+#define CHUNK_TYPE_OFFSET 0
+#define CHUNK_TYPE(x)(tvb_get_guint8((x), CHUNK_TYPE_OFFSET))
+
+
+extern gchar* address_to_str(const address *);
+
+
+static void
+sctpstat_reset(void *phs)
+{
+       sctpstat_t* sctp_stat = (sctpstat_t *)phs;
+       sctp_ep_t* list = (sctp_ep_t*)sctp_stat->ep_list;
+       sctp_ep_t* tmp = NULL;
+       guint16 chunk_type;
+       
+       if(!list)
+               return;
+
+       for(tmp = list; tmp ; tmp=tmp->next)
+               for(chunk_type = 0; chunk_type < 256; chunk_type++)
+                       tmp->chunk_count[chunk_type] = 0;
+
+       sctp_stat->number_of_packets = 0;
+}
+
+
+sctp_ep_t* alloc_sctp_ep(struct _sctp_info *si)
+{
+       sctp_ep_t* ep;
+       guint16 chunk_type;
+
+       if(!si)
+               return NULL;
+
+       if (!(ep = g_malloc(sizeof(sctp_ep_t))))
+               return NULL;
+       
+       COPY_ADDRESS(&ep->src,&si->ip_src);
+       COPY_ADDRESS(&ep->dst,&si->ip_dst);
+       ep->sport = si->sport;
+       ep->dport = si->dport;
+       ep->next = NULL;
+       for(chunk_type = 0; chunk_type < 256; chunk_type++)
+               ep->chunk_count[chunk_type] = 0;
+       return ep;
+}
+
+
+       
+
+static int
+sctpstat_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi)
+{
+
+       sctpstat_t *hs=(sctpstat_t *)phs;
+       sctp_ep_t *tmp = NULL, *te = NULL;
+       struct _sctp_info *si = (struct _sctp_info *) phi;
+       guint32 tvb_number;
+       guint8 chunk_type;
+       
+       if (!hs)
+               return (0);
+               
+       hs->number_of_packets++;
+       
+       if(!hs->ep_list) {
+               hs->ep_list = alloc_sctp_ep(si);
+               te = hs->ep_list;
+       } else {
+               for(tmp=hs->ep_list ; tmp ; tmp=tmp->next)
+               {
+                       if((!CMP_ADDRESS(&tmp->src,&si->ip_src)) &&
+                          (!CMP_ADDRESS(&tmp->dst,&si->ip_dst)) &&
+                          (tmp->sport == si->sport) &&
+                          (tmp->dport == si->dport))
+                       {
+                               te = tmp;
+                               break;
+                       }
+               }
+               if(!te) {
+                       if ((te = alloc_sctp_ep(si))) {
+                               te->next = hs->ep_list;
+                               hs->ep_list = te;
+                       }
+               }
+       }
+
+       if(!te)
+               return (0);
+
+       
+       if (si->number_of_tvbs > 0) {
+               chunk_type = CHUNK_TYPE(si->tvb[0]);
+               if ((chunk_type == SCTP_INIT_CHUNK_ID) ||
+                   (chunk_type == SCTP_INIT_ACK_CHUNK_ID)) {
+                       te->chunk_count[chunk_type]++;
+               } else {
+                       for(tvb_number = 0; tvb_number < si->number_of_tvbs; tvb_number++)
+                               te->chunk_count[CHUNK_TYPE(si->tvb[tvb_number])]++;
+               }
+       }
+       return (1);
+}
+
+
+static void
+sctpstat_draw(void *phs)
+{
+       sctpstat_t *hs=(sctpstat_t *)phs;
+       sctp_ep_t* list = hs->ep_list, *tmp;
+
+       printf("-------------------------------------------- SCTP Statistics --------------------------------------------------------------------------\n");
+       printf("|  Total packets RX/TX %u\n", hs->number_of_packets);
+       printf("---------------------------------------------------------------------------------------------------------------------------------------\n");
+       printf("|   Source IP   |PortA|    Dest. IP   |PortB|  DATA  |  SACK  |  HBEAT |HBEATACK|  INIT  | INITACK| COOKIE |COOKIACK| ABORT  |  ERROR |\n");
+       printf("---------------------------------------------------------------------------------------------------------------------------------------\n");
+       
+       for(tmp = list ; tmp ; tmp=tmp->next) {
+               printf("|%15s|%5u|%15s|%5u|%8u|%8u|%8u|%8u|%8u|%8u|%8u|%8u|%8u|%8u|\n",
+                      address_to_str(&tmp->src),tmp->sport,
+                      address_to_str(&tmp->dst),tmp->dport,
+                      tmp->chunk_count[SCTP_DATA_CHUNK_ID],
+                      tmp->chunk_count[SCTP_SACK_CHUNK_ID],
+                      tmp->chunk_count[SCTP_HEARTBEAT_CHUNK_ID],
+                      tmp->chunk_count[SCTP_HEARTBEAT_ACK_CHUNK_ID],
+                      tmp->chunk_count[SCTP_INIT_CHUNK_ID],
+                      tmp->chunk_count[SCTP_INIT_ACK_CHUNK_ID],
+                      tmp->chunk_count[SCTP_COOKIE_ECHO_CHUNK_ID],
+                      tmp->chunk_count[SCTP_COOKIE_ACK_CHUNK_ID],
+                      tmp->chunk_count[SCTP_ABORT_CHUNK_ID],
+                      tmp->chunk_count[SCTP_ERROR_CHUNK_ID]);
+       }
+       printf("---------------------------------------------------------------------------------------------------------------------------------------\n");
+}
+
+
+static void
+sctpstat_init(char *optarg)
+{
+       sctpstat_t *hs;
+       char *filter=NULL;
+       GString *error_string;
+
+       if(!strncmp(optarg,"sctp,stat,",11)){
+               filter=optarg+11;
+       } else {
+               filter=g_malloc(1);
+               *filter='\0';
+       }
+
+       hs = g_malloc(sizeof(sctpstat_t));
+       hs->filter=g_malloc(strlen(filter)+1);
+       hs->ep_list = NULL;
+       hs->number_of_packets = 0;
+       strcpy(hs->filter, filter);
+
+       sctpstat_reset(hs);
+
+       error_string=register_tap_listener("sctp", hs, filter, NULL, sctpstat_packet, sctpstat_draw);
+       if(error_string){
+               /* error, we failed to attach to the tap. clean up */
+               g_free(hs->filter);
+               g_free(hs);
+
+               fprintf(stderr, "tethereal: Couldn't register sctp,stat tap: %s\n",
+                   error_string->str);
+               g_string_free(error_string, TRUE);
+               exit(1);
+       }
+}
+
+
+void
+register_tap_listener_sctpstat(void)
+{
+       register_ethereal_tap("sctp,stat", sctpstat_init);
+}