From 9865b6346f6442bc8326cde55e5f012250748131 Mon Sep 17 00:00:00 2001 From: Luis Ontanon Date: Mon, 30 Jul 2007 23:32:47 +0000 Subject: [PATCH] As per Ulf's request add ${proto.field} macros that will use the value of the given field has in the last selected packet. svn path=/trunk/; revision=22427 --- epan/dfilter/dfilter-macro.c | 67 ++++++++++++++++++++++++++++++++++-- epan/dfilter/dfilter-macro.h | 2 ++ epan/proto.c | 4 +-- epan/proto.h | 3 ++ file.c | 5 ++- 5 files changed, 74 insertions(+), 7 deletions(-) diff --git a/epan/dfilter/dfilter-macro.c b/epan/dfilter/dfilter-macro.c index 9098d65162..2f154ce92f 100644 --- a/epan/dfilter/dfilter-macro.c +++ b/epan/dfilter/dfilter-macro.c @@ -37,10 +37,55 @@ #include #include #include +#include + +typedef struct { + const char* name; + gboolean usable; + char* repr; +} fvt_cache_entry_t; static uat_t* dfilter_macro_uat = NULL; static dfilter_macro_t* macros = NULL; static guint num_macros; +static GHashTable* fvt_cache = NULL; + +static gboolean free_value(gpointer k _U_, gpointer v, gpointer u _U_) { + fvt_cache_entry_t* e = v; + if (e->repr) g_free(e->repr); + g_free(e); + return TRUE; +} + +static gboolean fvt_cache_cb(proto_node * node, gpointer data _U_) { + field_info* finfo = node->finfo; + fvt_cache_entry_t* e; + + if (!finfo) return FALSE; + + if ((e = g_hash_table_lookup(fvt_cache,finfo->hfinfo->abbrev))) { + e->usable = FALSE; + } else if (finfo->value.ftype->val_to_string_repr) { + switch (finfo->hfinfo->type) { + case FT_NONE: + case FT_PROTOCOL: + return FALSE; + default: + break; + } + e = g_malloc(sizeof(fvt_cache_entry_t)); + e->name = finfo->hfinfo->abbrev, + e->repr = fvalue_to_string_repr(&(finfo->value), FTREPR_DFILTER, NULL); + e->usable = TRUE; + g_hash_table_insert(fvt_cache,(void*)finfo->hfinfo->abbrev,e); + } + return FALSE; +} + +void dfilter_macro_build_ftv_cache(void* tree_root) { + g_hash_table_foreach_remove(fvt_cache,free_value,NULL); + proto_tree_traverse_in_order(tree_root, fvt_cache_cb, NULL); +} void dfilter_macro_foreach(dfilter_macro_cb_t cb, void* data) { guint i; @@ -101,6 +146,7 @@ static gchar* dfilter_macro_resolve(gchar* name, gchar** args, const gchar** err GString* text; int argc = 0; dfilter_macro_t* m = NULL; + fvt_cache_entry_t* e; int* arg_pos_p; gchar** parts; gchar* ret; @@ -115,8 +161,17 @@ static gchar* dfilter_macro_resolve(gchar* name, gchar** args, const gchar** err } if (!m) { - *error = ep_strdup_printf("macro '%s' does not exist", name); - return NULL; + if (fvt_cache && (e = g_hash_table_lookup(fvt_cache,name) )) { + if(e->usable) { + return e->repr; + } else { + *error = ep_strdup_printf("macro '%s' is unusable", name); + return NULL; + } + } else { + *error = ep_strdup_printf("macro '%s' does not exist", name); + return NULL; + } } if (args) { @@ -221,7 +276,7 @@ gchar* dfilter_macro_apply(const gchar* text, guint depth, const gchar** error) } break; } case NAME: { - if ( isalnum((guchar)c) || c == '_' ) { + if ( isalnum((int)c) || c == '_' || c == '-' || c == '.' ) { g_string_append_c(name,c); } else if ( c == ':') { state = ARGS; @@ -482,8 +537,14 @@ void dfilter_macro_init(void) { macro_update, macro_free, uat_fields); + + fvt_cache = g_hash_table_new(g_str_hash,g_str_equal); } void dfilter_macro_get_uat(void** p) { *p = dfilter_macro_uat; } + + + + diff --git a/epan/dfilter/dfilter-macro.h b/epan/dfilter/dfilter-macro.h index 50c1cec04c..9646570d7b 100644 --- a/epan/dfilter/dfilter-macro.h +++ b/epan/dfilter/dfilter-macro.h @@ -54,4 +54,6 @@ void dfilter_macro_init(void); void dfilter_macro_get_uat(void**); +void dfilter_macro_build_ftv_cache(void* tree_root); + #endif /* _DFILTER_MACRO_H */ diff --git a/epan/proto.c b/epan/proto.c index 9727210cf0..79f7085030 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -409,8 +409,6 @@ proto_cleanup(void) } -typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer); - static gboolean proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func, gpointer data) @@ -439,7 +437,7 @@ proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func, return FALSE; } -static gboolean +gboolean proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func, gpointer data) { diff --git a/epan/proto.h b/epan/proto.h index 7a8a133289..f1580ca54c 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -317,7 +317,10 @@ typedef proto_node proto_item; ((proto_item) ? FI_SET_FLAG((proto_item)->finfo, FI_URL) : 0) typedef void (*proto_tree_foreach_func)(proto_node *, gpointer); +typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer); +extern gboolean proto_tree_traverse_in_order(proto_tree *tree, + proto_tree_traverse_func func, gpointer data); extern void proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func, gpointer data); diff --git a/file.c b/file.c index 05acf43ee0..bc1bdc2409 100644 --- a/file.c +++ b/file.c @@ -75,6 +75,7 @@ #include #include #include +#include #include "file_util.h" @@ -3251,7 +3252,9 @@ cf_select_packet(capture_file *cf, int row) epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame, NULL); - + + dfilter_macro_build_ftv_cache(cf->edt->tree); + cf_callback_invoke(cf_cb_packet_selected, cf); }