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
This commit is contained in:
Ulf Lamping 2007-08-16 22:03:10 +00:00
parent 1ac635cd7d
commit 4b215597ae
9 changed files with 247 additions and 14 deletions

View 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 \

49
epan/dissector_filters.c Normal file
View File

@ -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);
}

60
epan/dissector_filters.h Normal file
View File

@ -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 */

View 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

View 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

View 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

View 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;
}

View 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

View 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