experimental feature: dissector filters
authorulfl <ulfl@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 16 Aug 2007 22:03:10 +0000 (22:03 +0000)
committerulfl <ulfl@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 16 Aug 2007 22:03:10 +0000 (22:03 +0000)
add the possibility, that a dissector writer can provide (usually non-trivial) display filters specific for the protocol in question (with an example in packet-dcerpc-pn-io.c), that will appear in the GUI

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@22530 f5534014-38df-0310-8fa8-9805f1628bb7

epan/Makefile.common
epan/dissector_filters.c [new file with mode: 0644]
epan/dissector_filters.h [new file with mode: 0644]
epan/libwireshark.def
gtk/gui_stat_menu.h
gtk/menu.c
gtk/tcp_graph.c
plugins/profinet/packet-dcerpc-pn-io.c
stat_menu.h

index 22108570b61dfc782b255ff3d4229c325767745d..919ebebf257eee54f9cd1257f9ff251226975f60 100644 (file)
@@ -43,6 +43,7 @@ LIBWIRESHARK_SRC =            \
        crc32.c                 \
        crc6.c                  \
        crcdrm.c                \
+       dissector_filters.c             \
        emem.c                  \
        epan.c                  \
        ex-opt.c                \
@@ -152,6 +153,7 @@ LIBWIRESHARK_INCLUDES =     \
        crc32.h                 \
        crcdrm.h                \
        diam_dict.h             \
+       dissector_filters.h             \
        dtd.h                   \
        dtd_parse.h             \
        emem.h                  \
diff --git a/epan/dissector_filters.c b/epan/dissector_filters.c
new file mode 100644 (file)
index 0000000..681f0c4
--- /dev/null
@@ -0,0 +1,49 @@
+/* dissector_filters.c
+ * Routines for dissector generated display filters
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include "packet.h"
+
+#include "dissector_filters.h"
+
+
+GList *dissector_filter_list = NULL;
+
+
+void register_dissector_filter(const char *name, is_filter_valid_func is_filter_valid, build_filter_string_func build_filter_string) {
+    dissector_filter_t *entry;
+
+    entry = g_malloc(sizeof(dissector_filter_t));
+
+    entry->name                 = name;
+    entry->is_filter_valid      = is_filter_valid;
+    entry->build_filter_string  = build_filter_string;
+
+    dissector_filter_list = g_list_append(dissector_filter_list, entry);
+}
+
diff --git a/epan/dissector_filters.h b/epan/dissector_filters.h
new file mode 100644 (file)
index 0000000..b19a813
--- /dev/null
@@ -0,0 +1,60 @@
+/* dissector_filters.h
+ * Routines for dissector generated display filters
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __DISSECTOR_FILTERS_H__
+#define __DISSECTOR_FILTERS_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* callback function definition: is a filter available for this packet? */
+typedef gboolean (*is_filter_valid_func)(packet_info *pinfo);
+
+/* callback function definition: return the available filter for this packet or NULL if no filter is available */
+typedef const gchar* (*build_filter_string_func)(packet_info *pinfo);
+
+
+/* register a dissector filter */
+extern void register_dissector_filter(const char *name, is_filter_valid_func is_filter_valid, build_filter_string_func build_filter_string);
+
+
+
+/*** THE FOLLOWING SHOULD NOT BE USED BY ANY DISSECTORS!!! ***/
+
+typedef struct dissector_filter_s {
+    const char *                name;
+    is_filter_valid_func        is_filter_valid;
+    build_filter_string_func    build_filter_string;
+} dissector_filter_t;
+
+WS_VAR_IMPORT GList *dissector_filter_list;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* dissector_filters.h */
index 107899180168a5e941f7f454a8fd4f75ef11cad5..2527ac302d6b909a2fb87b881e31b9216b3c5dbe 100644 (file)
@@ -137,6 +137,7 @@ dissector_change_string
 dissector_delete
 dissector_delete_string
 dissector_dump_decodes
+dissector_filter_list           DATA
 dissector_get_port_handle
 dissector_get_string_handle
 dissector_handle_get_protocol_index
@@ -678,6 +679,7 @@ register_ber_syntax_dissector
 register_count
 register_dissector
 register_dissector_table
+register_dissector_filter
 register_final_registration_routine
 register_giop_user
 register_giop_user_module
index 40124c1d4952838e8688ae5c60595eb2cc3b5564..72cbb75a05510fe9a78f3ed7bb0a67fb79a53eba 100644 (file)
@@ -65,8 +65,8 @@ extern void register_stat_menu_item(
     const char *name, 
     register_stat_group_t group,
     GtkItemFactoryCallback callback,
-    gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
-    gboolean (*selected_tree_row_enabled)(field_info *),
+    gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
+    gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
     gpointer callback_data);
 
 #ifdef __cplusplus
index 0483dcf1014da72510bd21679e919c48de4a8a35..8307f033f23b9b9235f9a0a1036986b1edad51b6 100644 (file)
@@ -40,6 +40,7 @@
 #include <epan/tap.h>
 #include <epan/timestamp.h>
 #include <epan/ipproto.h>
+#include <epan/dissector_filters.h>
 
 #include "about_dlg.h"
 #include "capture_dlg.h"
@@ -99,8 +100,8 @@ typedef struct _menu_item {
     gboolean enabled;
     GtkItemFactoryCallback callback;
     gpointer callback_data;
-    gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *);
-    gboolean (*selected_tree_row_enabled)(field_info *);
+    gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data);
+    gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data);
     GList *children;
 } menu_item_t;
 
@@ -855,6 +856,59 @@ main_menu_new(GtkAccelGroup ** table) {
   return menubar;
 }
 
+
+void menu_dissector_filter_cb(  GtkWidget *widget,
+                                gpointer callback_data,
+                                guint callback_action)
+{
+    dissector_filter_t      *filter_entry = callback_data;
+    GtkWidget                  *filter_te;
+    const char              *buf;    
+
+
+    filter_te = OBJECT_GET_DATA(popup_menu_object, E_DFILTER_TE_KEY);
+
+    /* XXX - this gets the packet_info of the last dissected packet, */
+    /* which is not necessarily the last selected packet */
+    /* e.g. "Update list of packets in real time" won't work correct */
+    buf = filter_entry->build_filter_string(&cfile.edt->pi);
+
+       gtk_entry_set_text(GTK_ENTRY(filter_te), buf);
+
+       /* Run the display filter so it goes in effect - even if it's the
+          same as the previous display filter. */
+       main_filter_packets(&cfile, buf, TRUE);
+
+    g_free( (void *) buf);
+}
+
+gboolean menu_dissector_filter_spe_cb(frame_data *fd, epan_dissect_t *edt, gpointer callback_data) {
+    dissector_filter_t *filter_entry = callback_data;
+
+    /* XXX - this gets the packet_info of the last dissected packet, */
+    /* which is not necessarily the last selected packet */
+    /* e.g. "Update list of packets in real time" won't work correct */
+    return (edt != NULL) ? filter_entry->is_filter_valid(&edt->pi) : FALSE;
+}
+
+void menu_dissector_filter(void) {
+    GList *list_entry = dissector_filter_list;
+    dissector_filter_t *filter_entry;
+
+    while(list_entry != NULL) {
+        filter_entry = list_entry->data;
+
+        register_stat_menu_item(filter_entry->name, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER,
+            menu_dissector_filter_cb,
+            menu_dissector_filter_spe_cb,
+            NULL /* selected_tree_row_enabled */,
+            filter_entry);
+
+        list_entry = g_list_next(list_entry);
+    }
+}
+
+
 static void
 menus_init(void) {
   if (initialize) {
@@ -888,6 +942,7 @@ menus_init(void) {
                }
 #endif
 
+    menu_dissector_filter();
     merge_all_tap_menus(tap_menu_tree_root);
 
     /* Initialize enabled/disabled state of menu items */
@@ -926,8 +981,8 @@ static GList * tap_menu_item_add(
     char *name,
     gint group,
     GtkItemFactoryCallback callback,
-    gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
-    gboolean (*selected_tree_row_enabled)(field_info *),
+    gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
+    gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
     gpointer callback_data,
        GList *curnode)
 {
@@ -980,8 +1035,8 @@ register_stat_menu_item(
     const char *name,
     register_stat_group_t group,
     GtkItemFactoryCallback callback,
-    gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
-    gboolean (*selected_tree_row_enabled)(field_info *),
+    gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
+    gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
     gpointer callback_data)
 {
     /*static const char toolspath[] = "/Statistics/";*/
@@ -1006,6 +1061,7 @@ register_stat_menu_item(
     case(REGISTER_STAT_GROUP_TELEPHONY): toolspath = "/Statistics/"; break;
     case(REGISTER_STAT_GROUP_NONE): toolspath = "/Statistics/"; break;
     case(REGISTER_ANALYZE_GROUP_NONE): toolspath = "/Analyze/"; break;
+    case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER): toolspath = "/Analyze/Conversation Filter/"; break;
 #ifdef HAVE_LUA_5_1
     case(REGISTER_TOOLS_GROUP_NONE):
                toolspath = "/Tools/";
@@ -1137,6 +1193,8 @@ static guint merge_tap_menus_layered(GList *node, gint group) {
                 break;
             case(REGISTER_ANALYZE_GROUP_NONE):
                 break;
+            case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER):
+                break;
 #ifdef HAVE_LUA_5_1
             case(REGISTER_TOOLS_GROUP_NONE):
                 break;
@@ -1145,7 +1203,7 @@ static guint merge_tap_menus_layered(GList *node, gint group) {
                 g_assert_not_reached();
             }
 #endif
-            gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, 2);
+            gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, /* callback_type */ 2);
             set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
             added++;
         }
@@ -1213,6 +1271,10 @@ void merge_all_tap_menus(GList *node) {
                entry->path = "/Analyze/";
         /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
     }
+    if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER)) {
+               entry->path = "/Analyze/Conversation Filter/";
+        /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
+    }
 #ifdef HAVE_LUA_5_1
     if (merge_tap_menus_layered(node, REGISTER_TOOLS_GROUP_NONE)) {
         /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
@@ -2308,7 +2370,7 @@ walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
                 * based on its return value.
                 */
                if (node_data->selected_packet_enabled != NULL)
-                       node_data->enabled = node_data->selected_packet_enabled(fd, edt);
+                       node_data->enabled = node_data->selected_packet_enabled(fd, edt, node_data->callback_data);
        } else {
                /*
                 * It's an interior node; call
@@ -2418,7 +2480,7 @@ set_menus_for_selected_packet(capture_file *cf)
   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/UDP",
       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/PN-CBA Server",
-      cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0) : FALSE);
+      cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
   set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
       cf->current_frame != NULL && decode_as_ok());
   set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
@@ -2467,7 +2529,7 @@ walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
                 * based on its return value.
                 */
                if (node_data->selected_tree_row_enabled != NULL)
-                       node_data->enabled = node_data->selected_tree_row_enabled(fi);
+                       node_data->enabled = node_data->selected_tree_row_enabled(fi, node_data->callback_data);
        } else {
                /*
                 * It's an interior node; call
index 114a8d91c0919e1a92323aea6ca0277d19dee160..b423671aa46665ff14f552e169d14cfdb0cc1256 100644 (file)
@@ -4007,7 +4007,7 @@ static int rint (double x)
 #endif
 
 
-static gboolean tcp_graph_selected_packet_enabled(frame_data *current_frame, epan_dissect_t *edt)
+static gboolean tcp_graph_selected_packet_enabled(frame_data *current_frame, epan_dissect_t *edt, gpointer callback_data _U_)
 {
     return current_frame != NULL ? (edt->pi.ipproto == IP_PROTO_TCP) : FALSE;
 }
index a4ad213d425a3024b99eeee2c0e8da60c1f7a16e..0eee3afd15c87c86afd3692c4fcfdf4db13a56eb 100644 (file)
@@ -61,6 +61,7 @@
 #include <epan/emem.h>
 #include <epan/dissectors/packet-dcerpc.h>
 #include <epan/expert.h>
+#include <epan/dissector_filters.h>
 
 #include "packet-pn.h"
 
@@ -5921,6 +5922,59 @@ dissect_PNIO_heur(tvbuff_t *tvb,
 }
 
 
+
+gboolean
+pn_io_ar_conv_valid(packet_info *pinfo)
+{
+    return (pinfo->profinet_type == 10);
+}
+
+char *
+pn_io_ar_conv_filter(packet_info *pinfo)
+{
+    pnio_ar_t *ar = pinfo->profinet_conv;
+    char* buf;
+
+    if(pinfo->profinet_type != 10) {
+        return NULL;
+    }
+
+    buf = g_strdup_printf(
+        "pn_io.ar_uuid == %s || "                                   /* ARUUID */
+        "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s) || "   /* Alarm CR (contr -> dev) */
+        "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s)",      /* Alarm CR (dev -> contr) */
+        guid_to_str((const e_guid_t*) &ar->aruuid),
+        ar->controlleralarmref, ether_to_str((const guint8 *)ar->controllermac),
+        ar->devicealarmref, ether_to_str((const guint8 *)ar->devicemac));
+    return buf;
+}
+
+char *
+pn_io_ar_conv_data_filter(packet_info *pinfo)
+{
+    pnio_ar_t *ar = pinfo->profinet_conv;
+    char* buf;
+
+    if(pinfo->profinet_type != 10) {
+        return NULL;
+    }
+
+    buf = g_strdup_printf(
+        "pn_io.ar_uuid == %s || "                                           /* ARUUID */
+        "(pn_rt.frame_id == 0x%x && eth.src == %s && eth.dst == %s) || "    /* Input CR && dev MAC -> contr MAC */
+        "(pn_rt.frame_id == 0x%x && eth.src == %s && eth.dst == %s) || "    /* Output CR && contr MAC -> dev MAC */
+        "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s) || "           /* Alarm CR (contr -> dev) */
+        "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s)",              /* Alarm CR (dev -> contr) */
+        guid_to_str((const e_guid_t*) &ar->aruuid),
+        ar->inputframeid, ether_to_str((const guint8 *)ar->devicemac), ether_to_str((const guint8 *)ar->controllermac),
+        ar->outputframeid, ether_to_str((const guint8 *)ar->controllermac), ether_to_str((const guint8 *)ar->devicemac),
+        ar->controlleralarmref, ether_to_str((const guint8 *)ar->controllermac),
+        ar->devicealarmref, ether_to_str((const guint8 *)ar->devicemac));
+    return buf;
+}
+
+
+
 /* the PNIO dcerpc interface table */
 static dcerpc_sub_dissector pn_io_dissectors[] = {
 { 0, "Connect", dissect_IPNIO_rqst, dissect_IPNIO_resp },
@@ -6636,6 +6690,9 @@ proto_register_pn_io (void)
        proto_register_subtree_array (ett, array_length (ett));
 
        register_init_routine(pnio_reinit);
+
+    register_dissector_filter("PN-IO AR", pn_io_ar_conv_valid, pn_io_ar_conv_filter);
+    register_dissector_filter("PN-IO AR (with data)", pn_io_ar_conv_valid, pn_io_ar_conv_data_filter);
 }
 
 void
index 142cc5b47e272acf64d33d629c22b8a4acbd8735..d52b4c9353c36e7a630ed506bfdd63d9ed5f61c8 100644 (file)
@@ -50,7 +50,8 @@ typedef enum {
     REGISTER_STAT_GROUP_RESPONSE_TIME,
     REGISTER_STAT_GROUP_TELEPHONY,
     /* XXX - split into telephony and VoIP? */
-       REGISTER_ANALYZE_GROUP_NONE
+       REGISTER_ANALYZE_GROUP_NONE,
+       REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER
 #ifdef HAVE_LUA_5_1
        ,REGISTER_TOOLS_GROUP_NONE
 #endif