aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dfilter/dfvm.c
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2018-04-14 18:07:22 +0200
committerAnders Broman <a.broman58@gmail.com>2018-04-18 03:47:02 +0000
commit1ff82572ca62096520d0c6529fcc0ecee518206d (patch)
tree51d0894d456188ceca615cb677d4f7996abe8f3f /epan/dfilter/dfvm.c
parent4a156da068269aae75d79cd08e579754c52a0c43 (diff)
dfilter: add range support to set membership operator ("f in {x .. y}")
Allow "tcp.srcport in {1662 1663 1664}" to be abbreviated to "tcp.srcport in {1662 .. 1664}". The range operator is supported for any field value which supports the "<=" and "=>" operators and thus works for integers, IP addresses, etc. The naive mapping "tcp.srcport >= 1662 and tcp.srcport <= 1664" is not used because it does not have the intended effect with fields that have multiple occurrences (e.g. tcp.port). Each condition could be satisfied by an other value. Therefore a new DVFM instruction (ANY_IN_RANGE) is added to test the range condition against each individual field value. Bug: 14180 Change-Id: I53c2d0f9bc9d4f0ffaabde9a83442122965c95f7 Reviewed-on: https://code.wireshark.org/review/26945 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dfilter/dfvm.c')
-rw-r--r--epan/dfilter/dfvm.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c
index cf7c0362f0..f93fd50edf 100644
--- a/epan/dfilter/dfvm.c
+++ b/epan/dfilter/dfvm.c
@@ -118,6 +118,7 @@ dfvm_dump(FILE *f, dfilter_t *df)
case ANY_BITWISE_AND:
case ANY_CONTAINS:
case ANY_MATCHES:
+ case ANY_IN_RANGE:
case NOT:
case RETURN:
case IF_TRUE_GOTO:
@@ -252,6 +253,12 @@ dfvm_dump(FILE *f, dfilter_t *df)
id, arg1->value.numeric, arg2->value.numeric);
break;
+ case ANY_IN_RANGE:
+ fprintf(f, "%05d ANY_IN_RANGE\treg#%u in range reg#%u,reg#%u\n",
+ id, arg1->value.numeric, arg2->value.numeric,
+ arg3->value.numeric);
+ break;
+
case NOT:
fprintf(f, "%05d NOT\n", id);
break;
@@ -357,6 +364,37 @@ any_test(dfilter_t *df, FvalueCmpFunc cmp, int reg1, int reg2)
return FALSE;
}
+static gboolean
+any_in_range(dfilter_t *df, int reg1, int reg2, int reg3)
+{
+ GList *list1, *list_low, *list_high;
+ fvalue_t *low, *high;
+
+ 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.
+ */
+ g_assert(list_low && !g_list_next(list_low));
+ g_assert(list_high && !g_list_next(list_high));
+ low = (fvalue_t *)list_low->data;
+ high = (fvalue_t *)list_high->data;
+
+ while (list1) {
+ fvalue_t *value = (fvalue_t *)list1->data;
+ if (fvalue_ge(value, low) && fvalue_le(value, high)) {
+ return TRUE;
+ }
+ list1 = g_list_next(list1);
+ }
+ return FALSE;
+}
+
/* Free the list nodes w/o freeing the memory that each
* list node points to. */
@@ -515,6 +553,13 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
arg1->value.numeric, arg2->value.numeric);
break;
+ case ANY_IN_RANGE:
+ arg3 = insn->arg3;
+ accum = any_in_range(df, arg1->value.numeric,
+ arg2->value.numeric,
+ arg3->value.numeric);
+ break;
+
case NOT:
accum = !accum;
break;
@@ -589,6 +634,7 @@ dfvm_init_const(dfilter_t *df)
case ANY_BITWISE_AND:
case ANY_CONTAINS:
case ANY_MATCHES:
+ case ANY_IN_RANGE:
case NOT:
case RETURN:
case IF_TRUE_GOTO: