Make the dfilter code support multiple header_field_info's with

the same name (abbreviation). Thus, if multiple protocols or fields
are registered with the same name, you can still filter on the name
and have the filtering work as expected.

svn path=/trunk/; revision=6434
This commit is contained in:
Gilbert Ramirez 2002-10-16 16:32:59 +00:00
parent e0cf132365
commit 1ba73660c0
4 changed files with 101 additions and 59 deletions

View File

@ -1,5 +1,5 @@
/*
* $Id: dfilter.c,v 1.12 2002/09/09 21:04:15 guy Exp $
* $Id: dfilter.c,v 1.13 2002/10/16 16:32:59 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -135,9 +135,9 @@ dfilter_free(dfilter_t *df)
free_insns(df->insns);
}
if (df->interesting_fields) {
g_free(df->interesting_fields);
}
if (df->interesting_fields) {
g_free(df->interesting_fields);
}
g_free(df->registers);
g_free(df->attempted_load);
@ -250,8 +250,8 @@ dfilter_compile(gchar *text, dfilter_t **dfp)
dfilter = dfilter_new();
dfilter->insns = dfw->insns;
dfw->insns = NULL;
dfilter->interesting_fields = dfw_interesting_fields(dfw,
&dfilter->num_interesting_fields);
dfilter->interesting_fields = dfw_interesting_fields(dfw,
&dfilter->num_interesting_fields);
/* Initialize run-time space */
dfilter->num_registers = dfw->next_register;

View File

@ -1,5 +1,5 @@
/*
* $Id: dfvm.c,v 1.8 2002/08/28 20:40:55 jmayer Exp $
* $Id: dfvm.c,v 1.9 2002/10/16 16:32:59 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -107,12 +107,12 @@ dfvm_dump(FILE *f, GPtrArray *insns)
switch (insn->op) {
case CHECK_EXISTS:
fprintf(f, "%05d CHECK_EXISTS\t%s\n",
id, proto_registrar_get_abbrev(arg1->value.numeric));
id, arg1->value.hfinfo->abbrev);
break;
case READ_TREE:
fprintf(f, "%05d READ_TREE\t\t%s -> reg#%d\n",
id, proto_registrar_get_abbrev(arg1->value.numeric),
id, arg1->value.hfinfo->abbrev,
arg2->value.numeric);
break;
@ -187,12 +187,13 @@ dfvm_dump(FILE *f, GPtrArray *insns)
/* Reads a field from the proto_tree and loads the fvalues into a register,
* if that field has not already been read. */
static gboolean
read_tree(dfilter_t *df, proto_tree *tree, int field_id, int reg)
read_tree(dfilter_t *df, proto_tree *tree, header_field_info *hfinfo, int reg)
{
GPtrArray *finfos;
field_info *finfo;
int i, len;
GList *fvalues = NULL;
gboolean found_something = FALSE;
/* Already loaded in this run of the dfilter? */
if (df->attempted_load[reg]) {
@ -206,20 +207,32 @@ read_tree(dfilter_t *df, proto_tree *tree, int field_id, int reg)
df->attempted_load[reg] = TRUE;
finfos = proto_get_finfo_ptr_array(tree, field_id);
if (!finfos) {
while (hfinfo) {
finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
if (!finfos) {
hfinfo = hfinfo->same_name_next;
continue;
}
else if (g_ptr_array_len(finfos) == 0) {
hfinfo = hfinfo->same_name_next;
continue;
}
else {
found_something = TRUE;
}
len = finfos->len;
for (i = 0; i < len; i++) {
finfo = g_ptr_array_index(finfos, i);
fvalues = g_list_prepend(fvalues, finfo->value);
}
hfinfo = hfinfo->same_name_next;
}
if (!found_something) {
return FALSE;
}
else if (g_ptr_array_len(finfos) == 0) {
return FALSE;
}
len = finfos->len;
for (i = 0; i < len; i++) {
finfo = g_ptr_array_index(finfos, i);
fvalues = g_list_prepend(fvalues, finfo->value);
}
fvalues = g_list_reverse(fvalues);
df->registers[reg] = fvalues;
return TRUE;
@ -308,6 +321,7 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
dfvm_value_t *arg1;
dfvm_value_t *arg2;
dfvm_value_t *arg3;
header_field_info *hfinfo;
g_assert(tree);
@ -329,13 +343,22 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
switch (insn->op) {
case CHECK_EXISTS:
accum = proto_check_for_protocol_or_field(tree,
arg1->value.numeric);
hfinfo = arg1->value.hfinfo;
while(hfinfo) {
accum = proto_check_for_protocol_or_field(tree,
arg1->value.hfinfo->id);
if (accum) {
break;
}
else {
hfinfo = hfinfo->same_name_next;
}
}
break;
case READ_TREE:
accum = read_tree(df, tree,
arg1->value.numeric, arg2->value.numeric);
arg1->value.hfinfo, arg2->value.numeric);
break;
case PUT_FVALUE:

View File

@ -1,5 +1,5 @@
/*
* $Id: dfvm.h,v 1.7 2002/08/28 20:40:55 jmayer Exp $
* $Id: dfvm.h,v 1.8 2002/10/16 16:32:59 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -32,7 +32,7 @@
typedef enum {
EMPTY,
FVALUE,
FIELD_ID,
HFINFO,
INSN_NUMBER,
REGISTER,
INTEGER,
@ -43,9 +43,10 @@ typedef struct {
dfvm_value_type_t type;
union {
fvalue_t *fvalue;
guint32 numeric;
drange *drange;
fvalue_t *fvalue;
guint32 numeric;
drange *drange;
header_field_info *hfinfo;
} value;
} dfvm_value_t;

View File

@ -1,5 +1,5 @@
/*
* $Id: gencode.c,v 1.7 2002/08/28 20:40:55 jmayer Exp $
* $Id: gencode.c,v 1.8 2002/10/16 16:32:59 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -45,45 +45,54 @@ dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn)
/* returns register number */
static int
dfw_append_read_tree(dfwork_t *dfw, int field_id)
dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo)
{
dfvm_insn_t *insn;
dfvm_value_t *val1, *val2;
int reg = -1;
/* Rewind to find the first field of this name. */
while (hfinfo->same_name_prev) {
hfinfo = hfinfo->same_name_prev;
}
/* Keep track of which registers
* were used for which field_id's so that we
* were used for which hfinfo's so that we
* can re-use registers. */
reg = GPOINTER_TO_UINT(
g_hash_table_lookup(dfw->loaded_fields,
GINT_TO_POINTER(field_id)));
g_hash_table_lookup(dfw->loaded_fields, hfinfo));
if (reg) {
/* Reg's are stored in has as reg+1, so
* that the non-existence of a field_id in
* that the non-existence of a hfinfo in
* the hash, or 0, can be differentiated from
* a field_id being loaded into register #0. */
* a hfinfo being loaded into register #0. */
reg--;
}
else {
reg = dfw->next_register++;
g_hash_table_insert(dfw->loaded_fields,
GUINT_TO_POINTER(field_id),
GUINT_TO_POINTER(reg + 1));
hfinfo, GUINT_TO_POINTER(reg + 1));
insn = dfvm_insn_new(READ_TREE);
val1 = dfvm_value_new(HFINFO);
val1->value.hfinfo = hfinfo;
val2 = dfvm_value_new(REGISTER);
val2->value.numeric = reg;
insn->arg1 = val1;
insn->arg2 = val2;
dfw_append_insn(dfw, insn);
while (hfinfo) {
/* Record the FIELD_ID in hash of interesting fields. */
g_hash_table_insert(dfw->interesting_fields,
GINT_TO_POINTER(hfinfo->id),
GUINT_TO_POINTER(TRUE));
hfinfo = hfinfo->same_name_next;
}
/* Record the FIELD_ID in hash of interesting fields. */
g_hash_table_insert(dfw->interesting_fields,
GINT_TO_POINTER(field_id), GUINT_TO_POINTER(TRUE));
}
insn = dfvm_insn_new(READ_TREE);
val1 = dfvm_value_new(FIELD_ID);
val1->value.numeric = field_id;
val2 = dfvm_value_new(REGISTER);
val2->value.numeric = reg;
insn->arg1 = val1;
insn->arg2 = val2;
dfw_append_insn(dfw, insn);
return reg;
}
@ -119,7 +128,7 @@ dfw_append_mk_range(dfwork_t *dfw, stnode_t *node)
dfvm_value_t *val;
hfinfo = sttype_range_hfinfo(node);
hf_reg = dfw_append_read_tree(dfw, hfinfo->id);
hf_reg = dfw_append_read_tree(dfw, hfinfo);
insn = dfvm_insn_new(MK_RANGE);
@ -159,7 +168,7 @@ gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_ar
if (type1 == STTYPE_FIELD) {
hfinfo = stnode_data(st_arg1);
reg1 = dfw_append_read_tree(dfw, hfinfo->id);
reg1 = dfw_append_read_tree(dfw, hfinfo);
insn = dfvm_insn_new(IF_FALSE_GOTO);
jmp1 = dfvm_value_new(INSN_NUMBER);
@ -178,7 +187,7 @@ gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_ar
if (type2 == STTYPE_FIELD) {
hfinfo = stnode_data(st_arg2);
reg2 = dfw_append_read_tree(dfw, hfinfo->id);
reg2 = dfw_append_read_tree(dfw, hfinfo);
insn = dfvm_insn_new(IF_FALSE_GOTO);
jmp2 = dfvm_value_new(INSN_NUMBER);
@ -229,16 +238,25 @@ gen_test(dfwork_t *dfw, stnode_t *st_node)
break;
case TEST_OP_EXISTS:
val1 = dfvm_value_new(FIELD_ID);
val1 = dfvm_value_new(HFINFO);
hfinfo = stnode_data(st_arg1);
val1->value.numeric = hfinfo->id;
/* Rewind to find the first field of this name. */
while (hfinfo->same_name_prev) {
hfinfo = hfinfo->same_name_prev;
}
val1->value.hfinfo = hfinfo;
insn = dfvm_insn_new(CHECK_EXISTS);
insn->arg1 = val1;
dfw_append_insn(dfw, insn);
/* Record the FIELD_ID in hash of interesting fields. */
g_hash_table_insert(dfw->interesting_fields,
GINT_TO_POINTER(hfinfo->id), GUINT_TO_POINTER(TRUE));
/* Record the FIELD_ID in hash of interesting fields. */
while (hfinfo) {
g_hash_table_insert(dfw->interesting_fields,
GINT_TO_POINTER(hfinfo->id),
GUINT_TO_POINTER(TRUE));
hfinfo = hfinfo->same_name_next;
}
break;