From 4b215597ae8c4c05f590224b390cfbc218a93166 Mon Sep 17 00:00:00 2001 From: Ulf Lamping Date: Thu, 16 Aug 2007 22:03:10 +0000 Subject: [PATCH] experimental feature: dissector filters 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 svn path=/trunk/; revision=22530 --- epan/Makefile.common | 2 + epan/dissector_filters.c | 49 +++++++++++++++ epan/dissector_filters.h | 60 +++++++++++++++++++ epan/libwireshark.def | 2 + gtk/gui_stat_menu.h | 4 +- gtk/menu.c | 82 ++++++++++++++++++++++---- gtk/tcp_graph.c | 2 +- plugins/profinet/packet-dcerpc-pn-io.c | 57 ++++++++++++++++++ stat_menu.h | 3 +- 9 files changed, 247 insertions(+), 14 deletions(-) create mode 100644 epan/dissector_filters.c create mode 100644 epan/dissector_filters.h diff --git a/epan/Makefile.common b/epan/Makefile.common index 22108570b6..919ebebf25 100644 --- a/epan/Makefile.common +++ b/epan/Makefile.common @@ -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 index 0000000000..681f0c4301 --- /dev/null +++ b/epan/dissector_filters.c @@ -0,0 +1,49 @@ +/* dissector_filters.c + * Routines for dissector generated display filters + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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 +#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 index 0000000000..b19a8135cc --- /dev/null +++ b/epan/dissector_filters.h @@ -0,0 +1,60 @@ +/* dissector_filters.h + * Routines for dissector generated display filters + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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 */ diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 1078991801..2527ac302d 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -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 diff --git a/gtk/gui_stat_menu.h b/gtk/gui_stat_menu.h index 40124c1d49..72cbb75a05 100644 --- a/gtk/gui_stat_menu.h +++ b/gtk/gui_stat_menu.h @@ -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 diff --git a/gtk/menu.c b/gtk/menu.c index 0483dcf101..8307f033f2 100644 --- a/gtk/menu.c +++ b/gtk/menu.c @@ -40,6 +40,7 @@ #include #include #include +#include #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 diff --git a/gtk/tcp_graph.c b/gtk/tcp_graph.c index 114a8d91c0..b423671aa4 100644 --- a/gtk/tcp_graph.c +++ b/gtk/tcp_graph.c @@ -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; } diff --git a/plugins/profinet/packet-dcerpc-pn-io.c b/plugins/profinet/packet-dcerpc-pn-io.c index a4ad213d42..0eee3afd15 100644 --- a/plugins/profinet/packet-dcerpc-pn-io.c +++ b/plugins/profinet/packet-dcerpc-pn-io.c @@ -61,6 +61,7 @@ #include #include #include +#include #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 diff --git a/stat_menu.h b/stat_menu.h index 142cc5b47e..d52b4c9353 100644 --- a/stat_menu.h +++ b/stat_menu.h @@ -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