2001-02-01 20:31:21 +00:00
|
|
|
/*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2001-02-01 20:31:21 +00:00
|
|
|
* Copyright 2001 Gerald Combs
|
|
|
|
*
|
2018-02-08 16:59:17 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2001-02-01 20:31:21 +00:00
|
|
|
*/
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "dfvm.h"
|
|
|
|
|
2021-11-11 00:54:00 +00:00
|
|
|
#include <ftypes/ftypes.h>
|
2021-06-18 18:21:42 +00:00
|
|
|
#include <wsutil/ws_assert.h>
|
2013-11-10 13:14:09 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
dfvm_insn_t*
|
|
|
|
dfvm_insn_new(dfvm_opcode_t op)
|
|
|
|
{
|
|
|
|
dfvm_insn_t *insn;
|
|
|
|
|
|
|
|
insn = g_new(dfvm_insn_t, 1);
|
|
|
|
insn->op = op;
|
|
|
|
insn->arg1 = NULL;
|
|
|
|
insn->arg2 = NULL;
|
|
|
|
insn->arg3 = NULL;
|
2007-11-28 22:44:37 +00:00
|
|
|
insn->arg4 = NULL;
|
2001-02-01 20:21:25 +00:00
|
|
|
return insn;
|
|
|
|
}
|
|
|
|
|
2002-04-08 20:11:31 +00:00
|
|
|
static void
|
|
|
|
dfvm_value_free(dfvm_value_t *v)
|
|
|
|
{
|
|
|
|
switch (v->type) {
|
|
|
|
case FVALUE:
|
2021-11-11 00:54:00 +00:00
|
|
|
fvalue_free(v->value.fvalue);
|
2002-04-08 20:11:31 +00:00
|
|
|
break;
|
|
|
|
case DRANGE:
|
|
|
|
drange_free(v->value.drange);
|
|
|
|
break;
|
2021-03-21 10:06:17 +00:00
|
|
|
case PCRE:
|
2021-11-12 15:55:14 +00:00
|
|
|
ws_regex_free(v->value.pcre);
|
2021-03-21 10:06:17 +00:00
|
|
|
break;
|
2002-04-08 20:11:31 +00:00
|
|
|
default:
|
|
|
|
/* nothing */
|
|
|
|
;
|
|
|
|
}
|
|
|
|
g_free(v);
|
|
|
|
}
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
void
|
|
|
|
dfvm_insn_free(dfvm_insn_t *insn)
|
|
|
|
{
|
|
|
|
if (insn->arg1) {
|
|
|
|
dfvm_value_free(insn->arg1);
|
|
|
|
}
|
|
|
|
if (insn->arg2) {
|
|
|
|
dfvm_value_free(insn->arg2);
|
|
|
|
}
|
|
|
|
if (insn->arg3) {
|
|
|
|
dfvm_value_free(insn->arg3);
|
|
|
|
}
|
2007-11-28 22:44:37 +00:00
|
|
|
if (insn->arg4) {
|
|
|
|
dfvm_value_free(insn->arg4);
|
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
g_free(insn);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dfvm_value_t*
|
|
|
|
dfvm_value_new(dfvm_value_type_t type)
|
|
|
|
{
|
|
|
|
dfvm_value_t *v;
|
|
|
|
|
|
|
|
v = g_new(dfvm_value_t, 1);
|
|
|
|
v->type = type;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2022-03-21 11:13:02 +00:00
|
|
|
char *
|
|
|
|
dfvm_value_tostr(dfvm_value_t *v)
|
|
|
|
{
|
|
|
|
char *s, *aux;
|
|
|
|
|
|
|
|
if (!v)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
switch (v->type) {
|
|
|
|
case HFINFO:
|
|
|
|
s = ws_strdup(v->value.hfinfo->abbrev);
|
|
|
|
break;
|
|
|
|
case FVALUE:
|
|
|
|
aux = fvalue_to_debug_repr(NULL, v->value.fvalue);
|
|
|
|
s = ws_strdup_printf("%s <%s>",
|
|
|
|
aux, fvalue_type_name(v->value.fvalue));
|
|
|
|
g_free(aux);
|
|
|
|
break;
|
|
|
|
case DRANGE:
|
|
|
|
s = drange_tostr(v->value.drange);
|
|
|
|
break;
|
|
|
|
case PCRE:
|
|
|
|
s = ws_strdup(ws_regex_pattern(v->value.pcre));
|
|
|
|
break;
|
|
|
|
case REGISTER:
|
|
|
|
s = ws_strdup_printf("reg#%u", v->value.numeric);
|
|
|
|
break;
|
|
|
|
case FUNCTION_DEF:
|
|
|
|
s = ws_strdup(v->value.funcdef->name);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
s = ws_strdup("FIXME");
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
void
|
2012-02-29 05:58:45 +00:00
|
|
|
dfvm_dump(FILE *f, dfilter_t *df)
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
|
|
|
int id, length;
|
|
|
|
dfvm_insn_t *insn;
|
2022-03-21 11:13:02 +00:00
|
|
|
dfvm_value_t *arg1, *arg2, *arg3, *arg4;
|
|
|
|
char *arg1_str, *arg2_str, *arg3_str, *arg4_str;
|
2014-02-25 20:42:35 +00:00
|
|
|
|
2015-02-13 19:02:43 +00:00
|
|
|
/* First dump the constant initializations */
|
|
|
|
fprintf(f, "Constants:\n");
|
2012-02-29 05:58:45 +00:00
|
|
|
length = df->consts->len;
|
|
|
|
for (id = 0; id < length; id++) {
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2022-03-21 11:13:02 +00:00
|
|
|
insn = g_ptr_array_index(df->consts, id);
|
2012-02-29 05:58:45 +00:00
|
|
|
arg1 = insn->arg1;
|
|
|
|
arg2 = insn->arg2;
|
2022-03-21 11:13:02 +00:00
|
|
|
arg1_str = dfvm_value_tostr(arg1);
|
|
|
|
arg2_str = dfvm_value_tostr(arg2);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2012-02-29 05:58:45 +00:00
|
|
|
switch (insn->op) {
|
|
|
|
case PUT_FVALUE:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d PUT_FVALUE\t%s -> %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2012-02-29 05:58:45 +00:00
|
|
|
break;
|
2021-03-21 10:06:17 +00:00
|
|
|
case PUT_PCRE:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d PUT_PCRE \t%s -> %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2021-03-21 10:06:17 +00:00
|
|
|
break;
|
2012-02-29 05:58:45 +00:00
|
|
|
case CHECK_EXISTS:
|
|
|
|
case READ_TREE:
|
|
|
|
case CALL_FUNCTION:
|
|
|
|
case MK_RANGE:
|
2021-12-13 01:06:01 +00:00
|
|
|
case ALL_EQ:
|
2012-02-29 05:58:45 +00:00
|
|
|
case ANY_EQ:
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
case ALL_NE:
|
2012-02-29 05:58:45 +00:00
|
|
|
case ANY_NE:
|
|
|
|
case ANY_GT:
|
|
|
|
case ANY_GE:
|
|
|
|
case ANY_LT:
|
|
|
|
case ANY_LE:
|
|
|
|
case ANY_BITWISE_AND:
|
|
|
|
case ANY_CONTAINS:
|
|
|
|
case ANY_MATCHES:
|
2018-04-14 16:07:22 +00:00
|
|
|
case ANY_IN_RANGE:
|
2012-02-29 05:58:45 +00:00
|
|
|
case NOT:
|
|
|
|
case RETURN:
|
|
|
|
case IF_TRUE_GOTO:
|
|
|
|
case IF_FALSE_GOTO:
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2012-02-29 05:58:45 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-03-21 11:13:02 +00:00
|
|
|
|
|
|
|
g_free(arg1_str);
|
|
|
|
g_free(arg2_str);
|
2012-02-29 05:58:45 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 19:02:43 +00:00
|
|
|
fprintf(f, "\nInstructions:\n");
|
|
|
|
/* Now dump the operations */
|
2012-02-29 05:58:45 +00:00
|
|
|
length = df->insns->len;
|
2001-02-01 20:21:25 +00:00
|
|
|
for (id = 0; id < length; id++) {
|
|
|
|
|
2022-03-21 11:13:02 +00:00
|
|
|
insn = g_ptr_array_index(df->insns, id);
|
2001-02-01 20:21:25 +00:00
|
|
|
arg1 = insn->arg1;
|
|
|
|
arg2 = insn->arg2;
|
|
|
|
arg3 = insn->arg3;
|
|
|
|
arg4 = insn->arg4;
|
2022-03-21 11:13:02 +00:00
|
|
|
arg1_str = dfvm_value_tostr(arg1);
|
|
|
|
arg2_str = dfvm_value_tostr(arg2);
|
|
|
|
arg3_str = dfvm_value_tostr(arg3);
|
|
|
|
arg4_str = dfvm_value_tostr(arg4);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
switch (insn->op) {
|
|
|
|
case CHECK_EXISTS:
|
|
|
|
fprintf(f, "%05d CHECK_EXISTS\t%s\n",
|
2022-03-21 11:13:02 +00:00
|
|
|
id, arg1_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_TREE:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d READ_TREE\t\t%s -> %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
2009-01-21 05:26:40 +00:00
|
|
|
case CALL_FUNCTION:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d CALL_FUNCTION\t%s(",
|
|
|
|
id, arg1_str);
|
|
|
|
if (arg3_str) {
|
|
|
|
fprintf(f, "%s", arg3_str);
|
2009-01-21 05:26:40 +00:00
|
|
|
}
|
2022-03-21 11:13:02 +00:00
|
|
|
if (arg4_str) {
|
|
|
|
fprintf(f, ", %s", arg4_str);
|
2009-01-21 05:26:40 +00:00
|
|
|
}
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, ") -> %s\n", arg2_str);
|
2021-03-21 10:06:17 +00:00
|
|
|
break;
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
case MK_RANGE:
|
2005-10-31 03:33:14 +00:00
|
|
|
arg3 = insn->arg3;
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d MK_RANGE\t\t%s[%s] -> %s\n",
|
|
|
|
id, arg1_str, arg2_str, arg3_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
2021-12-13 01:06:01 +00:00
|
|
|
case ALL_EQ:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ALL_EQ\t\t%s === %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2021-12-13 01:06:01 +00:00
|
|
|
break;
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
case ANY_EQ:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_EQ\t\t%s == %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
case ALL_NE:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ALL_NE\t\t%s != %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
break;
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
case ANY_NE:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_NE\t\t%s !== %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_GT:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_GT\t\t%s > %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_GE:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_GE\t\t%s >= %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_LT:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_LT\t\t%s < %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_LE:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_LE\t\t%s <= %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
2004-02-27 12:00:32 +00:00
|
|
|
case ANY_BITWISE_AND:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_BITWISE_AND\t%s & %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2004-02-27 12:00:32 +00:00
|
|
|
break;
|
|
|
|
|
2003-12-19 04:40:24 +00:00
|
|
|
case ANY_CONTAINS:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_CONTAINS\t%s contains %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2003-12-19 04:40:24 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_MATCHES:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_MATCHES\t%s matches %s\n",
|
|
|
|
id, arg1_str, arg2_str);
|
2003-12-19 04:40:24 +00:00
|
|
|
break;
|
|
|
|
|
2018-04-14 16:07:22 +00:00
|
|
|
case ANY_IN_RANGE:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d ANY_IN_RANGE\t%s in { %s .. %s }\n",
|
|
|
|
id, arg1_str, arg2_str, arg3_str);
|
2018-04-14 16:07:22 +00:00
|
|
|
break;
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
case NOT:
|
|
|
|
fprintf(f, "%05d NOT\n", id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RETURN:
|
|
|
|
fprintf(f, "%05d RETURN\n", id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IF_TRUE_GOTO:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d IF_TRUE_GOTO\t%u\n",
|
2001-02-01 20:21:25 +00:00
|
|
|
id, arg1->value.numeric);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IF_FALSE_GOTO:
|
2022-03-21 11:13:02 +00:00
|
|
|
fprintf(f, "%05d IF_FALSE_GOTO\t%u\n",
|
2001-02-01 20:21:25 +00:00
|
|
|
id, arg1->value.numeric);
|
|
|
|
break;
|
|
|
|
|
2022-03-21 11:13:02 +00:00
|
|
|
case PUT_FVALUE:
|
|
|
|
case PUT_PCRE:
|
|
|
|
/* We already dumped these */
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-03-21 11:13:02 +00:00
|
|
|
|
|
|
|
g_free(arg1_str);
|
|
|
|
g_free(arg2_str);
|
|
|
|
g_free(arg3_str);
|
|
|
|
g_free(arg4_str);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reads a field from the proto_tree and loads the fvalues into a register,
|
|
|
|
* if that field has not already been read. */
|
|
|
|
static gboolean
|
2002-10-16 16:32:59 +00:00
|
|
|
read_tree(dfilter_t *df, proto_tree *tree, header_field_info *hfinfo, int reg)
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
|
|
|
GPtrArray *finfos;
|
|
|
|
field_info *finfo;
|
|
|
|
int i, len;
|
2022-03-21 11:43:28 +00:00
|
|
|
GSList *fvalues = NULL;
|
2002-10-16 16:32:59 +00:00
|
|
|
gboolean found_something = FALSE;
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
/* Already loaded in this run of the dfilter? */
|
|
|
|
if (df->attempted_load[reg]) {
|
|
|
|
if (df->registers[reg]) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
df->attempted_load[reg] = TRUE;
|
|
|
|
|
2002-10-16 16:32:59 +00:00
|
|
|
while (hfinfo) {
|
|
|
|
finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
|
2012-06-11 02:09:48 +00:00
|
|
|
if ((finfos == NULL) || (g_ptr_array_len(finfos) == 0)) {
|
2002-10-16 16:32:59 +00:00
|
|
|
hfinfo = hfinfo->same_name_next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
found_something = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = finfos->len;
|
|
|
|
for (i = 0; i < len; i++) {
|
2022-03-21 11:43:28 +00:00
|
|
|
finfo = g_ptr_array_index(finfos, i);
|
|
|
|
fvalues = g_slist_prepend(fvalues, &finfo->value);
|
2002-10-16 16:32:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hfinfo = hfinfo->same_name_next;
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
2002-10-16 16:32:59 +00:00
|
|
|
|
|
|
|
if (!found_something) {
|
|
|
|
return FALSE;
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
df->registers[reg] = fvalues;
|
2018-04-24 20:34:26 +00:00
|
|
|
// These values are referenced only, do not try to free it later.
|
|
|
|
df->owns_memory[reg] = FALSE;
|
2001-02-01 20:21:25 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-24 20:34:26 +00:00
|
|
|
/* Put a constant value in a register. These will not be cleared by
|
|
|
|
* free_register_overhead. */
|
2001-02-01 20:21:25 +00:00
|
|
|
static gboolean
|
|
|
|
put_fvalue(dfilter_t *df, fvalue_t *fv, int reg)
|
|
|
|
{
|
2022-03-21 11:43:28 +00:00
|
|
|
df->registers[reg] = g_slist_prepend(NULL, fv);
|
2018-04-24 20:34:26 +00:00
|
|
|
df->owns_memory[reg] = FALSE;
|
2001-02-01 20:21:25 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-03-21 10:06:17 +00:00
|
|
|
/* Put a constant PCRE in a register. These will not be cleared by
|
|
|
|
* free_register_overhead. */
|
|
|
|
static gboolean
|
2021-11-12 15:55:14 +00:00
|
|
|
put_pcre(dfilter_t *df, ws_regex_t *pcre, int reg)
|
2021-03-21 10:06:17 +00:00
|
|
|
{
|
2022-03-21 11:43:28 +00:00
|
|
|
df->registers[reg] = g_slist_prepend(NULL, pcre);
|
2021-03-21 10:06:17 +00:00
|
|
|
df->owns_memory[reg] = FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
enum match_how {
|
|
|
|
MATCH_ANY,
|
|
|
|
MATCH_ALL
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef gboolean (*DFVMMatchFunc)(const fvalue_t*, const fvalue_t*);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
static gboolean
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
cmp_test(dfilter_t *df, enum match_how how, DFVMMatchFunc match_func, int reg1, int reg2)
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2022-03-21 11:43:28 +00:00
|
|
|
GSList *list_a, *list_b;
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
gboolean want_all = (how == MATCH_ALL);
|
|
|
|
gboolean want_any = (how == MATCH_ANY);
|
|
|
|
gboolean have_match;
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
list_a = df->registers[reg1];
|
|
|
|
|
|
|
|
while (list_a) {
|
|
|
|
list_b = df->registers[reg2];
|
|
|
|
while (list_b) {
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
have_match = match_func(list_a->data, list_b->data);
|
|
|
|
if (want_all && !have_match) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (want_any && have_match) {
|
2001-02-01 20:21:25 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2022-03-21 11:43:28 +00:00
|
|
|
list_b = g_slist_next(list_b);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
2022-03-21 11:43:28 +00:00
|
|
|
list_a = g_slist_next(list_a);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
/* want_all || !want_any */
|
|
|
|
return want_all;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline gboolean
|
|
|
|
any_test(dfilter_t *df, DFVMMatchFunc cmp, int reg1, int reg2)
|
|
|
|
{
|
|
|
|
/* cmp(A) <=> cmp(a1) OR cmp(a2) OR cmp(a3) OR ... */
|
|
|
|
return cmp_test(df, MATCH_ANY, cmp, reg1, reg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline gboolean
|
|
|
|
all_test(dfilter_t *df, DFVMMatchFunc cmp, int reg1, int reg2)
|
|
|
|
{
|
|
|
|
/* cmp(A) <=> cmp(a1) AND cmp(a2) AND cmp(a3) AND ... */
|
|
|
|
return cmp_test(df, MATCH_ALL, cmp, reg1, reg2);
|
|
|
|
}
|
|
|
|
|
2021-12-13 01:06:01 +00:00
|
|
|
static inline gboolean
|
|
|
|
all_eq(dfilter_t *df, int reg1, int reg2)
|
|
|
|
{
|
|
|
|
/* A all_eq B <=> a1 == b1 AND a2 == b2 AND a3 == b3 AND ... */
|
|
|
|
return all_test(df, fvalue_eq, reg1, reg2);
|
|
|
|
}
|
|
|
|
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
static inline gboolean
|
|
|
|
any_eq(dfilter_t *df, int reg1, int reg2)
|
|
|
|
{
|
|
|
|
/* A any_eq B <=> a1 == b1 OR a2 == b2 OR a3 == b3 OR ... */
|
|
|
|
return any_test(df, fvalue_eq, reg1, reg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline gboolean
|
|
|
|
any_ne(dfilter_t *df, int reg1, int reg2)
|
|
|
|
{
|
|
|
|
/* A any_ne B <=> a1 != b1 OR a2 != b2 OR a3 != b3 OR ... */
|
|
|
|
return any_test(df, fvalue_ne, reg1, reg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline gboolean
|
|
|
|
all_ne(dfilter_t *df, int reg1, int reg2)
|
|
|
|
{
|
|
|
|
/* A all_ne B <=> a1 != b1 AND a2 != b2 AND a3 != b3 AND ... */
|
|
|
|
return all_test(df, fvalue_ne, reg1, reg2);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 10:06:17 +00:00
|
|
|
static gboolean
|
|
|
|
any_matches(dfilter_t *df, int reg1, int reg2)
|
|
|
|
{
|
2022-03-21 11:43:28 +00:00
|
|
|
GSList *list_a, *list_b;
|
2021-03-21 10:06:17 +00:00
|
|
|
|
|
|
|
list_a = df->registers[reg1];
|
|
|
|
|
|
|
|
while (list_a) {
|
|
|
|
list_b = df->registers[reg2];
|
|
|
|
while (list_b) {
|
2022-03-21 11:43:28 +00:00
|
|
|
if (fvalue_matches(list_a->data, list_b->data)) {
|
2021-03-21 10:06:17 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2022-03-21 11:43:28 +00:00
|
|
|
list_b = g_slist_next(list_b);
|
2021-03-21 10:06:17 +00:00
|
|
|
}
|
2022-03-21 11:43:28 +00:00
|
|
|
list_a = g_slist_next(list_a);
|
2021-03-21 10:06:17 +00:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2018-04-14 16:07:22 +00:00
|
|
|
static gboolean
|
|
|
|
any_in_range(dfilter_t *df, int reg1, int reg2, int reg3)
|
|
|
|
{
|
2022-03-21 11:43:28 +00:00
|
|
|
GSList *list1, *list_low, *list_high;
|
|
|
|
fvalue_t *low, *high, *value;
|
2018-04-14 16:07:22 +00:00
|
|
|
|
|
|
|
list1 = df->registers[reg1];
|
|
|
|
list_low = df->registers[reg2];
|
|
|
|
list_high = df->registers[reg3];
|
|
|
|
|
|
|
|
/* The first register contains the values associated with a field, the
|
|
|
|
* second and third arguments are expected to be a single value for the
|
|
|
|
* lower and upper bound respectively. These cannot be fields and thus
|
|
|
|
* the list length MUST be one. This should have been enforced by
|
|
|
|
* grammar.lemon.
|
|
|
|
*/
|
2022-03-21 11:43:28 +00:00
|
|
|
ws_assert(list_low && !g_slist_next(list_low));
|
|
|
|
ws_assert(list_high && !g_slist_next(list_high));
|
|
|
|
low = list_low->data;
|
|
|
|
high = list_high->data;
|
2018-04-14 16:07:22 +00:00
|
|
|
|
|
|
|
while (list1) {
|
2022-03-21 11:43:28 +00:00
|
|
|
value = list1->data;
|
2018-04-14 16:07:22 +00:00
|
|
|
if (fvalue_ge(value, low) && fvalue_le(value, high)) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
2022-03-21 11:43:28 +00:00
|
|
|
list1 = g_slist_next(list1);
|
2018-04-14 16:07:22 +00:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2018-04-24 20:34:26 +00:00
|
|
|
static void
|
|
|
|
free_owned_register(gpointer data, gpointer user_data _U_)
|
|
|
|
{
|
|
|
|
fvalue_t *value = (fvalue_t *)data;
|
2021-11-11 00:54:00 +00:00
|
|
|
fvalue_free(value);
|
2018-04-24 20:34:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Clear registers that were populated during evaluation (leaving constants
|
|
|
|
* intact). If we created the values, then these will be freed as well. */
|
2001-02-01 20:21:25 +00:00
|
|
|
static void
|
|
|
|
free_register_overhead(dfilter_t* df)
|
|
|
|
{
|
2009-10-18 23:25:33 +00:00
|
|
|
guint i;
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < df->num_registers; i++) {
|
2007-11-28 22:13:50 +00:00
|
|
|
df->attempted_load[i] = FALSE;
|
2001-02-01 20:21:25 +00:00
|
|
|
if (df->registers[i]) {
|
2018-04-24 20:34:26 +00:00
|
|
|
if (df->owns_memory[i]) {
|
2022-03-21 11:43:28 +00:00
|
|
|
g_slist_foreach(df->registers[i], free_owned_register, NULL);
|
2018-04-24 20:34:26 +00:00
|
|
|
df->owns_memory[i] = FALSE;
|
|
|
|
}
|
2022-03-21 11:43:28 +00:00
|
|
|
g_slist_free(df->registers[i]);
|
2007-11-28 22:13:50 +00:00
|
|
|
df->registers[i] = NULL;
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Takes the list of fvalue_t's in a register, uses fvalue_slice()
|
|
|
|
* to make a new list of fvalue_t's (which are ranges, or byte-slices),
|
|
|
|
* and puts the new list into a new register. */
|
|
|
|
static void
|
2013-03-05 06:16:45 +00:00
|
|
|
mk_range(dfilter_t *df, int from_reg, int to_reg, drange_t *d_range)
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2022-03-21 11:43:28 +00:00
|
|
|
GSList *from_list, *to_list;
|
2001-02-01 20:21:25 +00:00
|
|
|
fvalue_t *old_fv, *new_fv;
|
|
|
|
|
|
|
|
to_list = NULL;
|
|
|
|
from_list = df->registers[from_reg];
|
|
|
|
|
|
|
|
while (from_list) {
|
2012-06-02 15:52:42 +00:00
|
|
|
old_fv = (fvalue_t*)from_list->data;
|
2008-06-23 20:24:52 +00:00
|
|
|
new_fv = fvalue_slice(old_fv, d_range);
|
2001-02-27 19:23:30 +00:00
|
|
|
/* Assert here because semcheck.c should have
|
2001-02-01 20:21:25 +00:00
|
|
|
* already caught the cases in which a slice
|
|
|
|
* cannot be made. */
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert(new_fv);
|
2022-03-21 11:43:28 +00:00
|
|
|
to_list = g_slist_prepend(to_list, new_fv);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2022-03-21 11:43:28 +00:00
|
|
|
from_list = g_slist_next(from_list);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
df->registers[to_reg] = to_list;
|
2018-04-24 20:34:26 +00:00
|
|
|
df->owns_memory[to_reg] = TRUE;
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gboolean
|
2002-05-09 23:50:34 +00:00
|
|
|
dfvm_apply(dfilter_t *df, proto_tree *tree)
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2007-11-28 22:13:50 +00:00
|
|
|
int id, length;
|
2001-02-01 20:21:25 +00:00
|
|
|
gboolean accum = TRUE;
|
|
|
|
dfvm_insn_t *insn;
|
|
|
|
dfvm_value_t *arg1;
|
|
|
|
dfvm_value_t *arg2;
|
2006-05-02 14:26:17 +00:00
|
|
|
dfvm_value_t *arg3 = NULL;
|
|
|
|
dfvm_value_t *arg4 = NULL;
|
2002-10-16 16:32:59 +00:00
|
|
|
header_field_info *hfinfo;
|
2022-03-21 11:43:28 +00:00
|
|
|
GSList *param1;
|
|
|
|
GSList *param2;
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert(tree);
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
length = df->insns->len;
|
|
|
|
|
|
|
|
for (id = 0; id < length; id++) {
|
|
|
|
|
|
|
|
AGAIN:
|
2012-06-02 15:52:42 +00:00
|
|
|
insn = (dfvm_insn_t *)g_ptr_array_index(df->insns, id);
|
2001-02-01 20:21:25 +00:00
|
|
|
arg1 = insn->arg1;
|
|
|
|
arg2 = insn->arg2;
|
|
|
|
|
|
|
|
switch (insn->op) {
|
|
|
|
case CHECK_EXISTS:
|
2002-10-16 16:32:59 +00:00
|
|
|
hfinfo = arg1->value.hfinfo;
|
|
|
|
while(hfinfo) {
|
|
|
|
accum = proto_check_for_protocol_or_field(tree,
|
2007-04-10 18:31:36 +00:00
|
|
|
hfinfo->id);
|
2002-10-16 16:32:59 +00:00
|
|
|
if (accum) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
hfinfo = hfinfo->same_name_next;
|
|
|
|
}
|
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_TREE:
|
|
|
|
accum = read_tree(df, tree,
|
2002-10-16 16:32:59 +00:00
|
|
|
arg1->value.hfinfo, arg2->value.numeric);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
2006-05-02 14:26:17 +00:00
|
|
|
case CALL_FUNCTION:
|
|
|
|
arg3 = insn->arg3;
|
|
|
|
arg4 = insn->arg4;
|
2009-01-21 05:26:40 +00:00
|
|
|
param1 = NULL;
|
|
|
|
param2 = NULL;
|
|
|
|
if (arg3) {
|
|
|
|
param1 = df->registers[arg3->value.numeric];
|
|
|
|
}
|
|
|
|
if (arg4) {
|
|
|
|
param2 = df->registers[arg4->value.numeric];
|
|
|
|
}
|
|
|
|
accum = arg1->value.funcdef->function(param1, param2,
|
|
|
|
&df->registers[arg2->value.numeric]);
|
2018-04-24 20:34:26 +00:00
|
|
|
// functions create a new value, so own it.
|
|
|
|
df->owns_memory[arg2->value.numeric] = TRUE;
|
2006-05-02 14:26:17 +00:00
|
|
|
break;
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
case MK_RANGE:
|
|
|
|
arg3 = insn->arg3;
|
|
|
|
mk_range(df,
|
|
|
|
arg1->value.numeric, arg2->value.numeric,
|
2001-02-27 19:23:30 +00:00
|
|
|
arg3->value.drange);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
2021-12-13 01:06:01 +00:00
|
|
|
case ALL_EQ:
|
|
|
|
accum = all_eq(df, arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
case ANY_EQ:
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
accum = any_eq(df, arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ALL_NE:
|
|
|
|
accum = all_ne(df, arg1->value.numeric, arg2->value.numeric);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_NE:
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
accum = any_ne(df, arg1->value.numeric, arg2->value.numeric);
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_GT:
|
|
|
|
accum = any_test(df, fvalue_gt,
|
|
|
|
arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_GE:
|
|
|
|
accum = any_test(df, fvalue_ge,
|
|
|
|
arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_LT:
|
|
|
|
accum = any_test(df, fvalue_lt,
|
|
|
|
arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ANY_LE:
|
|
|
|
accum = any_test(df, fvalue_le,
|
|
|
|
arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
2004-02-27 12:00:32 +00:00
|
|
|
case ANY_BITWISE_AND:
|
|
|
|
accum = any_test(df, fvalue_bitwise_and,
|
|
|
|
arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
2003-08-27 15:23:11 +00:00
|
|
|
case ANY_CONTAINS:
|
|
|
|
accum = any_test(df, fvalue_contains,
|
|
|
|
arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
2003-12-06 16:35:20 +00:00
|
|
|
case ANY_MATCHES:
|
2021-03-21 10:06:17 +00:00
|
|
|
accum = any_matches(df,
|
2003-12-06 16:35:20 +00:00
|
|
|
arg1->value.numeric, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
|
2018-04-14 16:07:22 +00:00
|
|
|
case ANY_IN_RANGE:
|
|
|
|
arg3 = insn->arg3;
|
|
|
|
accum = any_in_range(df, arg1->value.numeric,
|
|
|
|
arg2->value.numeric,
|
|
|
|
arg3->value.numeric);
|
|
|
|
break;
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
case NOT:
|
|
|
|
accum = !accum;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RETURN:
|
|
|
|
free_register_overhead(df);
|
|
|
|
return accum;
|
|
|
|
|
|
|
|
case IF_TRUE_GOTO:
|
|
|
|
if (accum) {
|
|
|
|
id = arg1->value.numeric;
|
|
|
|
goto AGAIN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IF_FALSE_GOTO:
|
|
|
|
if (!accum) {
|
|
|
|
id = arg1->value.numeric;
|
|
|
|
goto AGAIN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2007-11-28 22:44:37 +00:00
|
|
|
case PUT_FVALUE:
|
|
|
|
#if 0
|
2015-02-13 19:02:43 +00:00
|
|
|
/* These were handled in the constants initialization */
|
2007-11-28 22:44:37 +00:00
|
|
|
accum = put_fvalue(df,
|
|
|
|
arg1->value.fvalue, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
#endif
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2021-03-21 10:06:17 +00:00
|
|
|
case PUT_PCRE:
|
|
|
|
#if 0
|
|
|
|
/* These were handled in the constants initialization */
|
|
|
|
accum = put_pcre(df,
|
|
|
|
arg1->value.pcre, arg2->value.numeric);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
default:
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2001-02-01 20:21:25 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2001-02-01 20:21:25 +00:00
|
|
|
return FALSE; /* to appease the compiler */
|
|
|
|
}
|
2007-11-28 22:44:37 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
dfvm_init_const(dfilter_t *df)
|
|
|
|
{
|
|
|
|
int id, length;
|
|
|
|
dfvm_insn_t *insn;
|
|
|
|
dfvm_value_t *arg1;
|
|
|
|
dfvm_value_t *arg2;
|
|
|
|
|
|
|
|
length = df->consts->len;
|
|
|
|
|
|
|
|
for (id = 0; id < length; id++) {
|
|
|
|
|
2012-06-02 15:52:42 +00:00
|
|
|
insn = (dfvm_insn_t *)g_ptr_array_index(df->consts, id);
|
2007-11-28 22:44:37 +00:00
|
|
|
arg1 = insn->arg1;
|
|
|
|
arg2 = insn->arg2;
|
|
|
|
|
|
|
|
switch (insn->op) {
|
|
|
|
case PUT_FVALUE:
|
|
|
|
put_fvalue(df,
|
|
|
|
arg1->value.fvalue, arg2->value.numeric);
|
|
|
|
break;
|
2021-03-21 10:06:17 +00:00
|
|
|
case PUT_PCRE:
|
|
|
|
put_pcre(df,
|
|
|
|
arg1->value.pcre, arg2->value.numeric);
|
|
|
|
break;
|
2007-11-28 22:44:37 +00:00
|
|
|
case CHECK_EXISTS:
|
|
|
|
case READ_TREE:
|
|
|
|
case CALL_FUNCTION:
|
|
|
|
case MK_RANGE:
|
2021-12-13 01:06:01 +00:00
|
|
|
case ALL_EQ:
|
2007-11-28 22:44:37 +00:00
|
|
|
case ANY_EQ:
|
dfilter: Fix "!=" relation to be free of contradictions
Wireshark defines the relation of equality A == B as
A any_eq B <=> An == Bn for at least one An, Bn.
More accurately I think this is (formally) an equivalence
relation, not true equality.
Whichever definition for "==" we choose we must keep the
definition of "!=" as !(A == B), otherwise it will
lead to logical contradictions like (A == B) AND (A != B)
being true.
Fix the '!=' relation to match the definition of equality:
A != B <=> !(A == B) <=> A all_ne B <=> An != Bn, for
every n.
This has been the recomended way to write "not equal" for a
long time in the documentation, even to the point where != was
deprecated, but it just wasn't implemented consistently in the
language, which has understandably been a persistent source
of confusion. Even a field that is normally well-behaved
with "!=" like "ip.src" or "ip.dst" will produce unexpected
results with encapsulations like IP-over-IP.
The opcode ALL_NE could have been implemented in the compiler
instead using NOT and ANY_EQ but I chose to implement it in
bytecode. It just seemed more elegant and efficient
but the difference was not very significant.
Keep around "~=" for any_ne relation, in case someone depends
on that, and because we don't have an operator for true equality:
A strict_equal B <=> A all_eq B <=> !(A any_ne B).
If there is only one value then any_ne and all_ne are the same
comparison operation.
Implementing this change did not require fixing any tests so it
is unlikely the relation "~=" (any_ne) will be very useful.
Note that the behaviour of the '<' (less than) comparison relation
is a separate, more subtle issue. In the general case the definition
of '<' that is used is only a partial order.
2021-10-18 20:07:06 +00:00
|
|
|
case ALL_NE:
|
2007-11-28 22:44:37 +00:00
|
|
|
case ANY_NE:
|
|
|
|
case ANY_GT:
|
|
|
|
case ANY_GE:
|
|
|
|
case ANY_LT:
|
|
|
|
case ANY_LE:
|
|
|
|
case ANY_BITWISE_AND:
|
|
|
|
case ANY_CONTAINS:
|
|
|
|
case ANY_MATCHES:
|
2018-04-14 16:07:22 +00:00
|
|
|
case ANY_IN_RANGE:
|
2007-11-28 22:44:37 +00:00
|
|
|
case NOT:
|
|
|
|
case RETURN:
|
|
|
|
case IF_TRUE_GOTO:
|
|
|
|
case IF_FALSE_GOTO:
|
|
|
|
default:
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2007-11-28 22:44:37 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2015-02-13 19:02:43 +00:00
|
|
|
|
|
|
|
/*
|
2019-07-26 18:43:17 +00:00
|
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
2015-02-13 19:02:43 +00:00
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: t
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
|
|
*/
|