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".
This commit is contained in:
parent
0853ddd1cb
commit
b83658d8a4
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -348,3 +348,8 @@ class case_raw_modifier(unittest.TestCase):
|
|||
def test_raw2(self, checkDFilterCount):
|
||||
dfilter = '@s7comm.blockinfo.blocktype == 30:fe'
|
||||
checkDFilterCount(dfilter, 1)
|
||||
|
||||
def test_raw_ref(self, checkDFilterCountWithSelectedFrame):
|
||||
dfilter = '@s7comm.blockinfo.blocktype == ${@s7comm.blockinfo.blocktype}'
|
||||
# select frame 3, expect 2 frames out of 3.
|
||||
checkDFilterCountWithSelectedFrame(dfilter, 2, 3)
|
||||
|
|
Loading…
Reference in New Issue