aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorJoão Valverde <j@v6e.pt>2022-10-25 13:03:08 +0100
committerJoão Valverde <j@v6e.pt>2022-10-31 21:02:39 +0000
commitb83658d8a4137290ed81d9886cc5f3fa7dff1e1c (patch)
tree255092465361d0fd0d71e700546a4d81680922e3 /epan
parent0853ddd1cb9c94e83bba5ac2608c8de0dc94dae4 (diff)
dfilter: Add suport for raw addressing with references
Extends raw adressing syntax to wok with references. The syntax is @field1 == ${@field2} This requires replicating the logic to load field references, but using raw values instead. We use separate hash tables for that, namely "references" vs "raw_references".
Diffstat (limited to 'epan')
-rw-r--r--epan/dfilter/dfilter-int.h4
-rw-r--r--epan/dfilter/dfilter-macro.c4
-rw-r--r--epan/dfilter/dfilter.c39
-rw-r--r--epan/dfilter/dfvm.c40
-rw-r--r--epan/dfilter/dfvm.h3
-rw-r--r--epan/dfilter/gencode.c5
-rw-r--r--epan/dfilter/grammar.lemon1
7 files changed, 80 insertions, 16 deletions
diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h
index 9b16393db8..ad38e368d6 100644
--- a/epan/dfilter/dfilter-int.h
+++ b/epan/dfilter/dfilter-int.h
@@ -34,6 +34,7 @@ struct epan_dfilter {
GPtrArray *deprecated;
char *expanded_text;
GHashTable *references;
+ GHashTable *raw_references;
char *syntax_tree_str;
/* Used to pass arguments to functions. List of Lists (list of registers). */
GSList *function_stack;
@@ -52,6 +53,7 @@ typedef struct {
int next_register;
GPtrArray *deprecated;
GHashTable *references; /* hfinfo -> pointer to array of references */
+ GHashTable *raw_references; /* hfinfo -> pointer to array of references */
char *expanded_text;
stloc_t err_loc;
} dfwork_t;
@@ -119,7 +121,7 @@ dfilter_fvalue_from_charconst(dfwork_t *dfw, ftenum_t ftype, stnode_t *st);
const char *tokenstr(int token);
df_reference_t *
-reference_new(const field_info *finfo);
+reference_new(const field_info *finfo, gboolean raw);
void
reference_free(df_reference_t *ref);
diff --git a/epan/dfilter/dfilter-macro.c b/epan/dfilter/dfilter-macro.c
index ef693c4f5b..06e11e2d1d 100644
--- a/epan/dfilter/dfilter-macro.c
+++ b/epan/dfilter/dfilter-macro.c
@@ -111,6 +111,10 @@ static gboolean start_is_field_reference(const char *start)
/* This violates constness but we will restore the original string. */
*(char *)end = '\0';
/* Search for name in registered fields. */
+
+ if (start[0] == '@')
+ start++;
+
hfinfo = dfilter_resolve_unparsed(NULL, start);
/* Restore mangled string. */
*(char *)end = saved_c;
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c
index e74d454e27..3466b04271 100644
--- a/epan/dfilter/dfilter.c
+++ b/epan/dfilter/dfilter.c
@@ -202,6 +202,7 @@ dfilter_free(dfilter_t *df)
g_free(df->interesting_fields);
g_hash_table_destroy(df->references);
+ g_hash_table_destroy(df->raw_references);
if (df->deprecated)
g_ptr_array_unref(df->deprecated);
@@ -235,6 +236,10 @@ dfwork_new(void)
g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify)free_refs_array);
+ dfw->raw_references =
+ g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify)free_refs_array);
+
return dfw;
}
@@ -261,6 +266,10 @@ dfwork_free(dfwork_t *dfw)
g_hash_table_destroy(dfw->references);
}
+ if (dfw->raw_references) {
+ g_hash_table_destroy(dfw->raw_references);
+ }
+
if (dfw->insns) {
free_insns(dfw->insns);
}
@@ -504,6 +513,8 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
dfw->expanded_text = NULL;
dfilter->references = dfw->references;
dfw->references = NULL;
+ dfilter->raw_references = dfw->raw_references;
+ dfw->raw_references = NULL;
if (save_tree) {
ws_assert(tree_str);
@@ -658,8 +669,8 @@ compare_ref_layer(gconstpointer _a, gconstpointer _b)
return a->proto_layer_num - b->proto_layer_num;
}
-void
-dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
+static void
+load_references(GHashTable *table, proto_tree *tree, gboolean raw)
{
GHashTableIter iter;
GPtrArray *finfos;
@@ -668,13 +679,13 @@ dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
GPtrArray *refs;
int i, len;
- if (g_hash_table_size(df->references) == 0) {
+ if (g_hash_table_size(table) == 0) {
/* Nothing to do. */
return;
}
- g_hash_table_iter_init( &iter, df->references);
- while (g_hash_table_iter_next (&iter, (void **)&hfinfo, (void **)&refs)) {
+ g_hash_table_iter_init(&iter, table);
+ while (g_hash_table_iter_next(&iter, (void **)&hfinfo, (void **)&refs)) {
/* If we have a previous array free the data */
g_ptr_array_set_size(refs, 0);
@@ -688,7 +699,7 @@ dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
len = finfos->len;
for (i = 0; i < len; i++) {
finfo = g_ptr_array_index(finfos, i);
- g_ptr_array_add(refs, reference_new(finfo));
+ g_ptr_array_add(refs, reference_new(finfo, raw));
}
hfinfo = hfinfo->same_name_next;
@@ -698,12 +709,24 @@ dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
}
}
+void
+dfilter_load_field_references(const dfilter_t *df, proto_tree *tree)
+{
+ load_references(df->references, tree, FALSE);
+ load_references(df->raw_references, tree, TRUE);
+}
+
df_reference_t *
-reference_new(const field_info *finfo)
+reference_new(const field_info *finfo, gboolean raw)
{
df_reference_t *ref = g_new(df_reference_t, 1);
ref->hfinfo = finfo->hfinfo;
- ref->value = fvalue_dup(&finfo->value);
+ if (raw) {
+ ref->value = dfvm_get_raw_fvalue(finfo);
+ }
+ else {
+ ref->value = fvalue_dup(&finfo->value);
+ }
ref->proto_layer_num = finfo->proto_layer_num;
return ref;
}
diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c
index 38951fc96d..ad1f41bbcd 100644
--- a/epan/dfilter/dfvm.c
+++ b/epan/dfilter/dfvm.c
@@ -509,6 +509,28 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references)
}
}
+ if (print_references && g_hash_table_size(df->raw_references) > 0) {
+ wmem_strbuf_append(buf, "\nRaw references:\n");
+ g_hash_table_iter_init(&ref_iter, df->raw_references);
+ while (g_hash_table_iter_next(&ref_iter, &key, &value)) {
+ const char *abbrev = ((header_field_info *)key)->abbrev;
+ GPtrArray *refs_array = value;
+ df_reference_t *ref;
+
+ wmem_strbuf_append_printf(buf, "${@%s} = {", abbrev);
+ for (i = 0; i < refs_array->len; i++) {
+ if (i != 0) {
+ wmem_strbuf_append(buf, ", ");
+ }
+ ref = refs_array->pdata[i];
+ str = fvalue_to_debug_repr(NULL, ref->value);
+ wmem_strbuf_append_printf(buf, "%s <%s>", str, fvalue_type_name(ref->value));
+ g_free(str);
+ }
+ wmem_strbuf_append(buf, "}\n");
+ }
+ }
+
return wmem_strbuf_finalize(buf);
}
@@ -563,8 +585,8 @@ drange_contains_layer(drange_t *dr, int num, int length)
return FALSE;
}
-static fvalue_t *
-get_raw_fvalue(field_info *fi)
+fvalue_t *
+dfvm_get_raw_fvalue(const field_info *fi)
{
GByteArray *bytes;
fvalue_t *fv;
@@ -614,7 +636,7 @@ filter_finfo_fvalues(GSList *fvalues, GPtrArray *finfos, drange_t *range, gboole
if (cookie == layer) {
if (cookie_matches) {
if (raw)
- fv = get_raw_fvalue(finfo);
+ fv = dfvm_get_raw_fvalue(finfo);
else
fv = &finfo->value;
fvalues = g_slist_prepend(fvalues, fv);
@@ -625,7 +647,7 @@ filter_finfo_fvalues(GSList *fvalues, GPtrArray *finfos, drange_t *range, gboole
cookie_matches = drange_contains_layer(range, layer, length);
if (cookie_matches) {
if (raw)
- fv = get_raw_fvalue(finfo);
+ fv = dfvm_get_raw_fvalue(finfo);
else
fv = &finfo->value;
fvalues = g_slist_prepend(fvalues, fv);
@@ -686,7 +708,7 @@ read_tree(dfilter_t *df, proto_tree *tree,
for (i = 0; i < len; i++) {
finfo = g_ptr_array_index(finfos, i);
if (raw)
- fv = get_raw_fvalue(finfo);
+ fv = dfvm_get_raw_fvalue(finfo);
else
fv = &finfo->value;
fvalues = g_slist_prepend(fvalues, fv);
@@ -759,8 +781,11 @@ read_reference(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *arg2,
{
GPtrArray *refs;
drange_t *range = NULL;
+ gboolean raw;
header_field_info *hfinfo = arg1->value.hfinfo;
+ raw = arg1->type == RAW_HFINFO;
+
int reg = arg2->value.numeric;
if (arg3) {
@@ -779,7 +804,10 @@ read_reference(dfilter_t *df, dfvm_value_t *arg1, dfvm_value_t *arg2,
df->attempted_load[reg] = TRUE;
- refs = g_hash_table_lookup(df->references, hfinfo);
+ if (raw)
+ refs = g_hash_table_lookup(df->raw_references, hfinfo);
+ else
+ refs = g_hash_table_lookup(df->references, hfinfo);
if (refs == NULL || refs->len == 0) {
df->registers[reg] = NULL;
return FALSE;
diff --git a/epan/dfilter/dfvm.h b/epan/dfilter/dfvm.h
index 8d58f73a74..554b2bf8ee 100644
--- a/epan/dfilter/dfvm.h
+++ b/epan/dfilter/dfvm.h
@@ -148,4 +148,7 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references)
gboolean
dfvm_apply(dfilter_t *df, proto_tree *tree);
+fvalue_t *
+dfvm_get_raw_fvalue(const field_info *fi);
+
#endif
diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c
index 2cafeec761..8653d487bc 100644
--- a/epan/dfilter/gencode.c
+++ b/epan/dfilter/gencode.c
@@ -237,7 +237,10 @@ dfw_append_read_reference(dfwork_t *dfw, header_field_info *hfinfo,
dfw_append_insn(dfw, insn);
refs_array = g_ptr_array_new_with_free_func((GDestroyNotify)reference_free);
- g_hash_table_insert(dfw->references, hfinfo, refs_array);
+ if (raw)
+ g_hash_table_insert(dfw->raw_references, hfinfo, refs_array);
+ else
+ g_hash_table_insert(dfw->references, hfinfo, refs_array);
/* Record the FIELD_ID in hash of interesting fields. */
while (hfinfo) {
diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon
index f1bed6ccef..a2297895e2 100644
--- a/epan/dfilter/grammar.lemon
+++ b/epan/dfilter/grammar.lemon
@@ -192,6 +192,7 @@ reference(R) ::= DOLLAR LBRACE field(F) RBRACE.
/* convert field to reference */
R = stnode_new(STTYPE_REFERENCE, sttype_field_hfinfo(F), NULL, stnode_location(F));
sttype_field_set_drange(R, sttype_field_drange_steal(F));
+ sttype_field_set_raw(R, sttype_field_raw(F));
stnode_free(F);
}