aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dfilter/dfilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dfilter/dfilter.c')
-rw-r--r--epan/dfilter/dfilter.c77
1 files changed, 75 insertions, 2 deletions
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c
index a185956b12..987653cfdc 100644
--- a/epan/dfilter/dfilter.c
+++ b/epan/dfilter/dfilter.c
@@ -199,6 +199,8 @@ dfilter_free(dfilter_t *df)
g_free(df->interesting_fields);
+ g_hash_table_destroy(df->references);
+
if (df->deprecated)
g_ptr_array_unref(df->deprecated);
@@ -209,11 +211,30 @@ dfilter_free(dfilter_t *df)
g_free(df);
}
+static void free_reference(gpointer data)
+{
+ /* List data is not owned by us. */
+ GSList **fvalues_ptr = data;
+ if (*fvalues_ptr)
+ g_slist_free(*fvalues_ptr);
+ g_free(fvalues_ptr);
+}
+
static dfwork_t*
dfwork_new(void)
{
- return g_new0(dfwork_t, 1);
+ dfwork_t *dfw = g_new0(dfwork_t, 1);
+
+ dfw->references =
+ g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, free_reference);
+
+ dfw->loaded_references =
+ g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify)dfvm_value_unref);
+
+ return dfw;
}
static void
@@ -231,6 +252,14 @@ dfwork_free(dfwork_t *dfw)
g_hash_table_destroy(dfw->interesting_fields);
}
+ if (dfw->references) {
+ g_hash_table_destroy(dfw->references);
+ }
+
+ if (dfw->loaded_references) {
+ g_hash_table_destroy(dfw->loaded_references);
+ }
+
if (dfw->insns) {
free_insns(dfw->insns);
}
@@ -279,6 +308,9 @@ const char *tokenstr(int token)
case TOKEN_DOTDOT: return "DOTDOT";
case TOKEN_LPAREN: return "LPAREN";
case TOKEN_RPAREN: return "RPAREN";
+ case TOKEN_REFERENCE: return "REFERENCE";
+ case TOKEN_REF_OPEN: return "REF_OPEN";
+ case TOKEN_REF_CLOSE: return "REF_CLOSE";
}
return "<unknown>";
}
@@ -446,6 +478,8 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
dfilter->interesting_fields = dfw_interesting_fields(dfw,
&dfilter->num_interesting_fields);
dfilter->expanded_text = ws_strdup(expanded_text);
+ dfilter->references = dfw->references;
+ dfw->references = NULL;
/* Initialize run-time space */
dfilter->num_registers = dfw->next_register;
@@ -559,7 +593,7 @@ dfilter_log_full(const char *domain, enum ws_log_level level,
return;
}
- char *str = dfvm_dump_str(NULL, df);
+ char *str = dfvm_dump_str(NULL, df, TRUE);
if (G_UNLIKELY(msg == NULL))
ws_log_write_always_full(domain, level, file, line, func, "\n%s", str);
else
@@ -567,6 +601,45 @@ dfilter_log_full(const char *domain, enum ws_log_level level,
g_free(str);
}
+void
+dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
+{
+ GHashTableIter iter;
+ GPtrArray *finfos;
+ field_info *finfo;
+ header_field_info *hfinfo;
+ GSList **fvalues_ptr;
+ int i, len;
+
+ if (g_hash_table_size(df->references) == 0) {
+ /* Nothing to do. */
+ return;
+ }
+
+ g_hash_table_iter_init( &iter, df->references);
+ while (g_hash_table_iter_next (&iter, (void **)&hfinfo, (void **)&fvalues_ptr)) {
+ /* If we have a previous list free it leaving the data alone */
+ g_slist_free(*fvalues_ptr);
+ *fvalues_ptr = NULL;
+
+ while (hfinfo) {
+ finfos = proto_find_finfo(tree, hfinfo->id);
+ if ((finfos == NULL) || (g_ptr_array_len(finfos) == 0)) {
+ hfinfo = hfinfo->same_name_next;
+ continue;
+ }
+
+ len = finfos->len;
+ for (i = 0; i < len; i++) {
+ finfo = g_ptr_array_index(finfos, i);
+ *fvalues_ptr = g_slist_prepend(*fvalues_ptr, &finfo->value);
+ }
+
+ hfinfo = hfinfo->same_name_next;
+ }
+ }
+}
+
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*