ge, >= Greater than or Equal to
le, <= Less than or Equal to
+An additional operater exists that is expressed only in English, not
+punctuation:
+
+ contains Does the protocol, byte-string, or string contain a value
+
Furthermore, each protocol field is typed. The types are:
Unsigned integer (either 8-bit, 16-bit, 24-bit, or 32-bit)
This means that you must escape backslashes with backslashes inside
double quotes:
- smb.path == "\\\\SERVER\\SHARE"
+ smb.path contains "\\\\SERVER\\SHARE"
to look for \\SERVER\SHARE in "smb.path".
ge, >= Greater than or Equal to
le, <= Less than or Equal to
+An additional operater exists that is expressed only in English, not
+punctuation:
+
+ contains Does the protocol, byte-string, or string contain a value
+
Furthermore, each protocol field is typed. The types are:
Unsigned integer (either 8-bit, 16-bit, 24-bit, or 32-bit)
This means that you must escape backslashes with backslashes inside
double quotes:
- smb.path == "\\\\SERVER\\SHARE"
+ smb.path contains "\\\\SERVER\\SHARE"
to look for \\SERVER\SHARE in "smb.path".
/*
- * $Id: dfvm.c,v 1.9 2002/10/16 16:32:59 gram Exp $
+ * $Id: dfvm.c,v 1.10 2003/08/27 15:23:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
arg1->value.numeric, arg2->value.numeric);
break;
+ case ANY_CONTAINS:
+ accum = any_test(df, fvalue_contains,
+ arg1->value.numeric, arg2->value.numeric);
+ break;
+
case NOT:
accum = !accum;
break;
/*
- * $Id: dfvm.h,v 1.8 2002/10/16 16:32:59 gram Exp $
+ * $Id: dfvm.h,v 1.9 2003/08/27 15:23:04 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
ANY_GE,
ANY_LT,
ANY_LE,
+ ANY_CONTAINS,
MK_RANGE
} dfvm_opcode_t;
/*
- * $Id: gencode.c,v 1.10 2003/06/13 10:03:25 guy Exp $
+ * $Id: gencode.c,v 1.11 2003/08/27 15:23:04 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
case TEST_OP_LE:
gen_relation(dfw, ANY_LE, st_arg1, st_arg2);
break;
+
+ case TEST_OP_CONTAINS:
+ gen_relation(dfw, ANY_CONTAINS, st_arg1, st_arg2);
+ break;
}
}
-/* $Id: grammar.lemon,v 1.5 2003/07/25 03:44:01 gram Exp $ */
+/* $Id: grammar.lemon,v 1.6 2003/08/27 15:23:04 gram Exp $ */
%include {
#ifdef HAVE_CONFIG_H
/* Associativity */
%left TEST_AND.
%left TEST_OR.
-%nonassoc TEST_EQ TEST_NE TEST_LT TEST_LE TEST_GT TEST_GE.
+%nonassoc TEST_EQ TEST_NE TEST_LT TEST_LE TEST_GT TEST_GE TEST_CONTAINS.
%right TEST_NOT.
/* Top-level targets */
rel_op2(O) ::= TEST_GE. { O = TEST_OP_GE; }
rel_op2(O) ::= TEST_LT. { O = TEST_OP_LT; }
rel_op2(O) ::= TEST_LE. { O = TEST_OP_LE; }
+rel_op2(O) ::= TEST_CONTAINS. { O = TEST_OP_CONTAINS; }
%{
/*
- * $Id: scanner.l,v 1.8 2003/07/25 03:44:01 gram Exp $
+ * $Id: scanner.l,v 1.9 2003/08/27 15:23:04 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
"lt" return simple(TOKEN_TEST_LT);
"<=" return simple(TOKEN_TEST_LE);
"le" return simple(TOKEN_TEST_LE);
+"contains" return simple(TOKEN_TEST_CONTAINS);
"!" return simple(TOKEN_TEST_NOT);
"not" return simple(TOKEN_TEST_NOT);
case TOKEN_TEST_GE:
case TOKEN_TEST_LT:
case TOKEN_TEST_LE:
+ case TOKEN_TEST_CONTAINS:
case TOKEN_TEST_NOT:
case TOKEN_TEST_AND:
case TOKEN_TEST_OR:
/*
- * $Id: semcheck.c,v 1.18 2003/07/25 03:44:01 gram Exp $
+ * $Id: semcheck.c,v 1.19 2003/08/27 15:23:04 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* and possibly some modifications of syntax tree nodes. */
static void
check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func,
+ gboolean allow_partial_value,
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
stnode_t *new_st;
}
else if (type2 == STTYPE_UNPARSED) {
s = stnode_data(st_arg2);
- fvalue = fvalue_from_unparsed(ftype1, s, dfilter_fail);
+ fvalue = fvalue_from_unparsed(ftype1, s, allow_partial_value, dfilter_fail);
if (!fvalue) {
/* check value_string */
fvalue = mk_fvalue_from_val_string(hfinfo1, s);
}
static void
-check_relation_LHS_STRING(FtypeCanFunc can_func _U_, stnode_t *st_node,
+check_relation_LHS_STRING(FtypeCanFunc can_func _U_, gboolean allow_partial_value _U_,
+ stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
stnode_t *new_st;
sttype_test_set2_args(st_node, new_st, st_arg2);
stnode_free(st_arg1);
}
- else if (type2 == STTYPE_STRING) {
+ else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED) {
/* Well now that's silly... */
dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.",
stnode_data(st_arg1),
}
static void
-check_relation_LHS_UNPARSED(FtypeCanFunc can_func _U_, stnode_t *st_node,
+check_relation_LHS_UNPARSED(FtypeCanFunc can_func _U_, gboolean allow_partial_value,
+ stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
stnode_t *new_st;
ftype2 = hfinfo2->type;
s = stnode_data(st_arg1);
- fvalue = fvalue_from_unparsed(ftype2, s, dfilter_fail);
+ fvalue = fvalue_from_unparsed(ftype2, s, allow_partial_value, dfilter_fail);
if (!fvalue) {
/* check value_string */
fvalue = mk_fvalue_from_val_string(hfinfo2, s);
sttype_test_set2_args(st_node, new_st, st_arg2);
stnode_free(st_arg1);
}
- else if (type2 == STTYPE_STRING) {
+ else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED) {
/* Well now that's silly... */
dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.",
stnode_data(st_arg1),
THROW(TypeError);
}
else if (type2 == STTYPE_RANGE) {
+ /* XXX - is this right? */
s = stnode_data(st_arg1);
- fvalue = fvalue_from_unparsed(FT_BYTES, s, dfilter_fail);
+ fvalue = fvalue_from_unparsed(FT_BYTES, s, allow_partial_value, dfilter_fail);
if (!fvalue) {
THROW(TypeError);
}
}
static void
-check_relation_LHS_RANGE(FtypeCanFunc can_func _U_, stnode_t *st_node,
+check_relation_LHS_RANGE(FtypeCanFunc can_func _U_, gboolean allow_partial_value,
+ stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
stnode_t *new_st;
}
else if (type2 == STTYPE_UNPARSED) {
s = stnode_data(st_arg2);
- fvalue = fvalue_from_unparsed(FT_BYTES, s, dfilter_fail);
+ fvalue = fvalue_from_unparsed(FT_BYTES, s, allow_partial_value, dfilter_fail);
if (!fvalue) {
THROW(TypeError);
}
/* Check the semantics of any relational test. */
static void
-check_relation(const char *relation_string, FtypeCanFunc can_func, stnode_t *st_node,
+check_relation(const char *relation_string, gboolean allow_partial_value,
+ FtypeCanFunc can_func, stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
{
switch (stnode_type_id(st_arg1)) {
case STTYPE_FIELD:
- check_relation_LHS_FIELD(relation_string, can_func, st_node, st_arg1, st_arg2);
+ check_relation_LHS_FIELD(relation_string, can_func,
+ allow_partial_value, st_node, st_arg1, st_arg2);
break;
case STTYPE_STRING:
- check_relation_LHS_STRING(can_func, st_node, st_arg1, st_arg2);
+ check_relation_LHS_STRING(can_func,
+ allow_partial_value, st_node, st_arg1, st_arg2);
break;
case STTYPE_RANGE:
- check_relation_LHS_RANGE(can_func, st_node, st_arg1, st_arg2);
+ check_relation_LHS_RANGE(can_func,
+ allow_partial_value, st_node, st_arg1, st_arg2);
break;
case STTYPE_UNPARSED:
- check_relation_LHS_UNPARSED(can_func, st_node, st_arg1, st_arg2);
+ check_relation_LHS_UNPARSED(can_func,
+ allow_partial_value, st_node, st_arg1, st_arg2);
break;
case STTYPE_UNINITIALIZED:
break;
case TEST_OP_EQ:
- check_relation("==", ftype_can_eq, st_node, st_arg1, st_arg2);
+ check_relation("==", FALSE, ftype_can_eq, st_node, st_arg1, st_arg2);
break;
case TEST_OP_NE:
- check_relation("!=", ftype_can_ne, st_node, st_arg1, st_arg2);
+ check_relation("!=", FALSE, ftype_can_ne, st_node, st_arg1, st_arg2);
break;
case TEST_OP_GT:
- check_relation(">", ftype_can_gt, st_node, st_arg1, st_arg2);
+ check_relation(">", FALSE, ftype_can_gt, st_node, st_arg1, st_arg2);
break;
case TEST_OP_GE:
- check_relation(">=", ftype_can_ge, st_node, st_arg1, st_arg2);
+ check_relation(">=", FALSE, ftype_can_ge, st_node, st_arg1, st_arg2);
break;
case TEST_OP_LT:
- check_relation("<", ftype_can_lt, st_node, st_arg1, st_arg2);
+ check_relation("<", FALSE, ftype_can_lt, st_node, st_arg1, st_arg2);
break;
case TEST_OP_LE:
- check_relation("<=", ftype_can_le, st_node, st_arg1, st_arg2);
+ check_relation("<=", FALSE, ftype_can_le, st_node, st_arg1, st_arg2);
+ break;
+ case TEST_OP_CONTAINS:
+ check_relation("contains", TRUE, ftype_can_contains, st_node, st_arg1, st_arg2);
break;
+
+ default:
+ g_assert_not_reached();
}
}
/*
- * $Id: sttype-test.c,v 1.3 2002/08/28 20:40:56 jmayer Exp $
+ * $Id: sttype-test.c,v 1.4 2003/08/27 15:23:05 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
return 2;
case TEST_OP_LE:
return 2;
+ case TEST_OP_CONTAINS:
+ return 2;
}
g_assert_not_reached();
return -1;
/*
- * $Id: sttype-test.h,v 1.3 2002/08/28 20:40:56 jmayer Exp $
+ * $Id: sttype-test.h,v 1.4 2003/08/27 15:23:05 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
TEST_OP_GT,
TEST_OP_GE,
TEST_OP_LT,
- TEST_OP_LE
+ TEST_OP_LE,
+ TEST_OP_CONTAINS
} test_op_t;
void
/*
- * $Id: ftype-bytes.c,v 1.16 2003/07/25 03:44:02 gram Exp $
+ * $Id: ftype-bytes.c,v 1.17 2003/08/27 15:23:05 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <string.h>
#include <ctype.h>
#include <epan/resolv.h>
+#include <epan/strutil.h>
#include <epan/int-64bit.h>
#define ETHER_LEN 6
}
static gboolean
-val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+bytes_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
GByteArray *bytes;
guint8 val;
}
static gboolean
-ether_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+ether_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value, LogFunc logfunc)
{
guint8 *mac;
* up as an Ethernet host name if it does, and if that fails,
* we'll log a message.
*/
- if (val_from_unparsed(fv, s, NULL)) {
+ if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
+ if (fv->value.bytes->len > ETHER_LEN) {
+ logfunc("\"%s\" contains too many bytes to be a valid Ethernet address.",
+ s);
+ return FALSE;
+ }
+ else if (fv->value.bytes->len < ETHER_LEN && !allow_partial_value) {
+ logfunc("\"%s\" contains too few bytes to be a valid Ethernet address.",
+ s);
+ return FALSE;
+ }
+
return TRUE;
}
}
static gboolean
-ipv6_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+ipv6_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
guint8 buffer[16];
}
static gboolean
-u64_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+u64_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
guint8 buffer[8];
}
static gboolean
-i64_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+i64_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
guint8 buffer[8];
return (memcmp(a->data, b->data, a->len) <= 0);
}
+static gboolean
+cmp_contains(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ GByteArray *a = fv_a->value.bytes;
+ GByteArray *b = fv_b->value.bytes;
+
+ if (epan_memmem(a->data, a->len, b->data, b->len)) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
void
ftype_register_bytes(void)
{
0, /* wire_size */
bytes_fvalue_new, /* new_value */
bytes_fvalue_free, /* free_value */
- val_from_unparsed, /* val_from_unparsed */
+ bytes_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
bytes_to_repr, /* val_to_string_repr */
bytes_repr_len, /* len_string_repr */
cmp_ge,
cmp_lt,
cmp_le,
+ cmp_contains,
len,
slice,
0, /* wire_size */
bytes_fvalue_new, /* new_value */
bytes_fvalue_free, /* free_value */
- val_from_unparsed, /* val_from_unparsed */
+ bytes_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
bytes_to_repr, /* val_to_string_repr */
bytes_repr_len, /* len_string_repr */
cmp_ge,
cmp_lt,
cmp_le,
+ cmp_contains,
len,
slice,
cmp_ge,
cmp_lt,
cmp_le,
+ cmp_contains,
len,
slice,
cmp_ge,
cmp_lt,
cmp_le,
+ cmp_contains,
len,
slice,
cmp_ge,
cmp_lt,
cmp_le,
+ NULL, /* cmp_contains */
len,
slice,
cmp_ge_i64,
cmp_lt_i64,
cmp_le_i64,
+ NULL, /* cmp_contains */
len,
slice,
/*
- * $Id: ftype-double.c,v 1.10 2003/07/31 03:52:43 guy Exp $
+ * $Id: ftype-double.c,v 1.11 2003/08/27 15:23:06 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
}
static gboolean
-val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
char *endptr = NULL;
cmp_ge,
cmp_lt,
cmp_le,
+ NULL, /* cmp_contains */
NULL,
NULL,
cmp_ge,
cmp_lt,
cmp_le,
+ NULL, /* cmp_contains */
NULL,
NULL,
/*
- * $Id: ftype-integer.c,v 1.14 2003/07/25 03:44:02 gram Exp $
+ * $Id: ftype-integer.c,v 1.15 2003/08/27 15:23:06 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
}
static gboolean
-val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
char *endptr;
}
static gboolean
-ipxnet_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+ipxnet_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
guint32 val;
gboolean known;
* up as an IPX network name if it does, and if that fails,
* we'll log a message.
*/
- if (val_from_unparsed(fv, s, NULL)) {
+ if (val_from_unparsed(fv, s, TRUE, NULL)) {
return TRUE;
}
u_cmp_ge,
u_cmp_lt,
u_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
u_cmp_ge,
u_cmp_lt,
u_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
u_cmp_ge,
u_cmp_lt,
u_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
u_cmp_ge,
u_cmp_lt,
u_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
s_cmp_ge,
s_cmp_lt,
s_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
s_cmp_ge,
s_cmp_lt,
s_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
s_cmp_ge,
s_cmp_lt,
s_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
s_cmp_ge,
s_cmp_lt,
s_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
NULL, /* cmp_ge */
NULL, /* cmp_lt */
NULL, /* cmp_le */
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
u_cmp_ge,
u_cmp_lt,
u_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
u_cmp_ge,
u_cmp_lt,
u_cmp_le,
+ NULL, /* cmp_contains */
NULL, /* len */
NULL, /* slice */
/*
- * $Id: ftype-ipv4.c,v 1.12 2003/07/31 04:18:01 guy Exp $
+ * $Id: ftype-ipv4.c,v 1.13 2003/08/27 15:23:07 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
}
static gboolean
-val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
guint32 addr;
unsigned int nmask_bits;
}
/* XXX - this is inefficient */
- nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, logfunc);
+ nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, FALSE, logfunc);
g_free(s_copy);
if (!nmask_fvalue) {
return FALSE;
cmp_ge,
cmp_lt,
cmp_le,
+ NULL, /* cmp_contains */
NULL,
NULL,
/*
- * $Id: ftype-none.c,v 1.6 2003/07/25 03:44:03 gram Exp $
+ * $Id: ftype-none.c,v 1.7 2003/08/27 15:23:07 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
NULL,
NULL,
NULL,
+ NULL, /* cmp_contains */
NULL,
NULL,
/*
- * $Id: ftype-string.c,v 1.12 2003/07/30 22:25:35 guy Exp $
+ * $Id: ftype-string.c,v 1.13 2003/08/27 15:23:07 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
return TRUE;
}
+static gboolean
+val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
+{
+ fvalue_t *fv_bytes;
+ /* Does this look like a byte-string? */
+ fv_bytes = fvalue_from_unparsed(FT_BYTES, s, TRUE, NULL);
+ if (fv_bytes) {
+ /* Copy the bytes over to a string and terminate it
+ * with a NUL. XXX - what if the user embeds a NUL
+ * in the middle of the byte string? */
+ int num_bytes = fv_bytes->value.bytes->len;
+
+ fv->value.string = g_malloc(num_bytes + 1);
+ memcpy(fv->value.string, fv->value.bytes->data, num_bytes);
+ fv->value.string[num_bytes] = '\0';
+
+ fvalue_free(fv_bytes);
+ return TRUE;
+ }
+ else {
+ /* Just turn it into a string */
+ return val_from_string(fv, s, logfunc);
+ }
+ g_assert_not_reached();
+}
+
static guint
len(fvalue_t *fv)
{
return (strcmp(a->value.string, b->value.string) <= 0);
}
+static gboolean
+cmp_contains(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ /* According to
+ * http://www.introl.com/introl-demo/Libraries/C/ANSI_C/string/strstr.html
+ * strstr() returns a non-NULL value if needle is an empty
+ * string. We don't that behavior for cmp_contains. */
+ if (strlen(fv_b->value.string) == 0) {
+ return FALSE;
+ }
+
+ if (strstr(fv_a->value.string, fv_b->value.string)) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
void
ftype_register_string(void)
{
0, /* wire_size */
string_fvalue_new, /* new_value */
string_fvalue_free, /* free_value */
- val_from_string, /* val_from_unparsed */
+ val_from_unparsed, /* val_from_unparsed */
val_from_string, /* val_from_string */
string_to_repr, /* val_to_string_repr */
string_repr_len, /* len_string_repr */
cmp_ge,
cmp_lt,
cmp_le,
+ cmp_contains, /* cmp_contains */
len,
slice,
0,
string_fvalue_new,
string_fvalue_free,
- val_from_string, /* val_from_unparsed */
+ val_from_unparsed, /* val_from_unparsed */
val_from_string, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
cmp_ge,
cmp_lt,
cmp_le,
+ cmp_contains, /* cmp_contains */
len,
slice,
0,
string_fvalue_new,
string_fvalue_free,
- val_from_string, /* val_from_unparsed */
+ val_from_unparsed, /* val_from_unparsed */
val_from_string, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
cmp_ge,
cmp_lt,
cmp_le,
+ cmp_contains, /* cmp_contains */
len,
slice,
/*
- * $Id: ftype-time.c,v 1.20 2003/07/30 22:50:39 guy Exp $
+ * $Id: ftype-time.c,v 1.21 2003/08/27 15:23:07 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
}
static gboolean
-relative_val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
+relative_val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
{
char *curptr, *endptr;
return FALSE;
}
+static gboolean
+absolute_val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
+{
+ return absolute_val_from_string(fv, s, logfunc);
+}
+
static void
time_fvalue_new(fvalue_t *fv)
{
0,
time_fvalue_new,
NULL,
- absolute_val_from_string, /* val_from_unparsed */
+ absolute_val_from_unparsed, /* val_from_unparsed */
absolute_val_from_string, /* val_from_string */
absolute_val_to_repr, /* val_to_string_repr */
absolute_val_repr_len, /* len_string_repr */
cmp_ge,
cmp_lt,
cmp_le,
+ NULL, /* cmp_contains */
+
NULL,
NULL
};
cmp_ge,
cmp_lt,
cmp_le,
+ NULL, /* cmp_contains */
+
NULL,
NULL
};
/*
- * $Id: ftype-tvbuff.c,v 1.9 2003/07/25 03:44:03 gram Exp $
+ * $Id: ftype-tvbuff.c,v 1.10 2003/08/27 15:23:08 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <ftypes-int.h>
#include <epan/gdebug.h>
+#define tvb_is_private fvalue_gboolean1
+
static void
value_new(fvalue_t *fv)
{
fv->value.tvb = NULL;
+ fv->tvb_is_private = FALSE;
+}
+
+static void
+value_free(fvalue_t *fv)
+{
+ if (fv->tvb_is_private) {
+ tvb_free_chain(fv->value.tvb);
+ }
}
fv->value.tvb = value;
}
+static void
+free_tvb_data(void *data)
+{
+ g_free(data);
+}
+
+
+static gboolean
+val_from_string(fvalue_t *fv, char *s, LogFunc logfunc _U_)
+{
+ tvbuff_t *new_tvb;
+ guint8 *private_data;
+
+ /* Make a tvbuff from the string. We can drop the
+ * terminating NUL. */
+ private_data = g_memdup(s, strlen(s));
+ new_tvb = tvb_new_real_data(private_data,
+ strlen(s), strlen(s));
+
+ /* Let the tvbuff know how to delete the data. */
+ tvb_set_free_cb(new_tvb, free_tvb_data);
+
+ /* And let us know that we need to free the tvbuff */
+ fv->tvb_is_private = TRUE;
+ fv->value.tvb = new_tvb;
+ return TRUE;
+}
+
+static gboolean
+val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
+{
+ fvalue_t *fv_bytes;
+ tvbuff_t *new_tvb;
+ guint8 *private_data;
+
+ /* Does this look like a byte string? */
+ fv_bytes = fvalue_from_unparsed(FT_BYTES, s, TRUE, NULL);
+ if (fv_bytes) {
+ /* Make a tvbuff from the bytes */
+ private_data = g_memdup(fv_bytes->value.bytes->data,
+ fv_bytes->value.bytes->len);
+ new_tvb = tvb_new_real_data(private_data,
+ fv_bytes->value.bytes->len,
+ fv_bytes->value.bytes->len);
+
+ /* Let the tvbuff know how to delete the data. */
+ tvb_set_free_cb(new_tvb, free_tvb_data);
+
+ /* And let us know that we need to free the tvbuff */
+ fv->tvb_is_private = TRUE;
+ fv->value.tvb = new_tvb;
+ return TRUE;
+ }
+ else {
+ /* Treat it as a string. */
+ return val_from_string(fv, s, logfunc);
+ }
+ g_assert_not_reached();
+}
+
static gpointer
value_get(fvalue_t *fv)
{
}
}
+static gboolean
+cmp_contains(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ if (tvb_find_tvb(fv_a->value.tvb, fv_b->value.tvb, 0) > -1) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
void
ftype_register_tvbuff(void)
{
static ftype_t protocol_type = {
- "FT_PROTOCOL",
- "protocol",
- 0,
- value_new,
- NULL,
- NULL, /* val_from_unparsed */
- NULL, /* val_from_string */
+ "FT_PROTOCOL", /* name */
+ "protocol", /* pretty_name */
+ 0, /* wire_size */
+ value_new, /* new_value */
+ value_free, /* free_value */
+ val_from_unparsed, /* val_from_unparsed */
+ val_from_string, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
NULL,
NULL,
NULL,
+ cmp_contains, /* cmp_contains */
len,
slice,
/*
- * $Id: ftypes-int.h,v 1.9 2003/07/25 03:44:03 gram Exp $
+ * $Id: ftypes-int.h,v 1.10 2003/08/27 15:23:08 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
typedef void (*FvalueNewFunc)(fvalue_t*);
typedef void (*FvalueFreeFunc)(fvalue_t*);
-typedef gboolean (*FvalueFromUnparsed)(fvalue_t*, char*, LogFunc);
+typedef gboolean (*FvalueFromUnparsed)(fvalue_t*, char*, gboolean, LogFunc);
typedef gboolean (*FvalueFromString)(fvalue_t*, char*, LogFunc);
typedef void (*FvalueToStringRepr)(fvalue_t*, ftrepr_t, char*);
typedef int (*FvalueStringReprLen)(fvalue_t*, ftrepr_t);
FvalueCmp cmp_ge;
FvalueCmp cmp_lt;
FvalueCmp cmp_le;
+ FvalueCmp cmp_contains;
FvalueLen len;
FvalueSlice slice;
/*
- * $Id: ftypes.c,v 1.10 2003/07/25 03:44:03 gram Exp $
+ * $Id: ftypes.c,v 1.11 2003/08/27 15:23:08 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
return ft->cmp_le ? TRUE : FALSE;
}
+gboolean
+ftype_can_contains(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->cmp_contains ? TRUE : FALSE;
+}
+
/* ---------------------------------------------------------- */
/* Allocate and initialize an fvalue_t, given an ftype */
}
fvalue_t*
-fvalue_from_unparsed(ftenum_t ftype, char *s, LogFunc logfunc)
+fvalue_from_unparsed(ftenum_t ftype, char *s, gboolean allow_partial_value, LogFunc logfunc)
{
fvalue_t *fv;
fv = fvalue_new(ftype);
if (fv->ftype->val_from_unparsed) {
- if (fv->ftype->val_from_unparsed(fv, s, logfunc)) {
+ if (fv->ftype->val_from_unparsed(fv, s, allow_partial_value, logfunc)) {
return fv;
}
}
g_assert(a->ftype->cmp_le);
return a->ftype->cmp_le(a, b);
}
+
+gboolean
+fvalue_contains(fvalue_t *a, fvalue_t *b)
+{
+ /* XXX - check compatibility of a and b */
+ g_assert(a->ftype->cmp_contains);
+ return a->ftype->cmp_contains(a, b);
+}
/* ftypes.h
* Definitions for field types
*
- * $Id: ftypes.h,v 1.18 2003/07/25 03:44:04 gram Exp $
+ * $Id: ftypes.h,v 1.19 2003/08/27 15:23:08 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
gboolean
ftype_can_le(enum ftenum ftype);
+gboolean
+ftype_can_contains(enum ftenum ftype);
+
/* ---------------- FVALUE ----------------- */
#include <epan/ipv4.h>
nstime_t time;
tvbuff_t *tvb;
} value;
+
+ /* The following is provided for private use
+ * by the fvalue. */
+ gboolean fvalue_gboolean1;
+
} fvalue_t;
fvalue_t*
typedef void (*LogFunc)(char*,...);
fvalue_t*
-fvalue_from_unparsed(ftenum_t ftype, char *s, LogFunc log);
+fvalue_from_unparsed(ftenum_t ftype, char *s, gboolean allow_partial_value, LogFunc logfunc);
fvalue_t*
-fvalue_from_string(ftenum_t ftype, char *s, LogFunc log);
+fvalue_from_string(ftenum_t ftype, char *s, LogFunc logfunc);
/* Returns the length of the string required to hold the
* string representation of the the field value.
gboolean
fvalue_le(fvalue_t *a, fvalue_t *b);
+gboolean
+fvalue_contains(fvalue_t *a, fvalue_t *b);
+
guint
fvalue_length(fvalue_t *fv);
/* strutil.c
* String utility routines
*
- * $Id: strutil.c,v 1.11 2003/08/01 01:39:00 guy Exp $
+ * $Id: strutil.c,v 1.12 2003/08/27 15:23:02 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
*p = '\0';
return cur;
}
+
+/* Return the first occurrence of needle in haystack.
+ * If not found, return NULL.
+ * If either haystack or needle has 0 length, return NULL.
+ * Algorithm copied from GNU's glibc 2.3.2 memcmp() */
+const guint8 *
+epan_memmem(const guint8 *haystack, guint haystack_len,
+ const guint8 *needle, guint needle_len)
+{
+ const guint8 *begin;
+ const guint8 *const last_possible
+ = haystack + haystack_len - needle_len;
+
+ if (needle_len == 0) {
+ return NULL;
+ }
+
+ if (needle_len > haystack_len) {
+ return NULL;
+ }
+
+ for (begin = haystack ; begin <= last_possible; ++begin) {
+ if (begin[0] == needle[0] &&
+ !memcmp(&begin[1], needle + 1,
+ needle_len - 1)) {
+ return begin;
+ }
+ }
+
+ return NULL;
+}
/* strutil.h
* String utility definitions
*
- * $Id: strutil.h,v 1.10 2003/07/04 03:41:00 gram Exp $
+ * $Id: strutil.h,v 1.11 2003/08/27 15:23:02 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
gchar* bytes_to_str(const guint8 *, int);
gchar* bytes_to_str_punct(const guint8 *, int, gchar punct);
+const guint8 * epan_memmem(const guint8 *haystack, guint haystack_len,
+ const guint8 *needle, guint needle_len);
+
/* Surround a string or a macro, resolved to a string, with double quotes */
#define _STRINGIFY(a) # a
#define STRINGIFY(a) _STRINGIFY(a)
* the data of a backing tvbuff, or can be a composite of
* other tvbuffs.
*
- * $Id: tvbuff.c,v 1.48 2003/08/08 08:19:50 guy Exp $
+ * $Id: tvbuff.c,v 1.49 2003/08/27 15:23:02 gram Exp $
*
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
*
{
return tvb->ds_tvb;
}
+
+/* Find a needle tvbuff within a haystack tvbuff. */
+gint
+tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
+{
+ guint haystack_abs_offset, haystack_abs_length;
+ const guint8 *haystack_data;
+ const guint8 *needle_data;
+ const guint needle_len = needle_tvb->length;
+ const guint8 *location;
+
+ /* Get pointers to the tvbuffs' data. */
+ haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
+ needle_data = tvb_get_ptr(needle_tvb, 0, -1);
+
+ check_offset_length(haystack_tvb, haystack_offset, -1,
+ &haystack_abs_offset, &haystack_abs_length);
+
+ location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
+ needle_data, needle_len);
+
+ if (location) {
+ return location - haystack_data;
+ }
+ else {
+ return -1;
+ }
+
+ return -1;
+}
* the data of a backing tvbuff, or can be a composite of
* other tvbuffs.
*
- * $Id: tvbuff.h,v 1.33 2003/06/12 08:33:31 guy Exp $
+ * $Id: tvbuff.h,v 1.34 2003/08/27 15:23:03 gram Exp $
*
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
*
extern tvbuff_t *tvb_get_ds_tvb(tvbuff_t *tvb);
+/* Locate a sub-tvbuff within another tvbuff, starting at position
+ * 'haystack_offset'. Returns the index of the beginning of 'needle' within
+ * 'haystack', or -1 if 'needle' is not found. The index is relative
+ * to the start of 'haystack', not 'haystack_offset'. */
+extern gint tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb,
+ gint haystack_offset);
+
/************** END OF ACCESSORS ****************/
#endif /* __TVBUFF_H__ */
* Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com> and
* Guy Harris <guy@alum.mit.edu>
*
- * $Id: dfilter_expr_dlg.c,v 1.35 2003/08/25 00:15:02 guy Exp $
+ * $Id: dfilter_expr_dlg.c,v 1.36 2003/08/27 15:23:10 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
if (ftype_can_le(ftype) ||
(ftype_can_slice(ftype) && ftype_can_le(FT_BYTES)))
add_relation_list(relation_list, "<=");
+ if (ftype_can_contains(ftype) ||
+ (ftype_can_slice(ftype) && ftype_can_contains(FT_BYTES)))
+ add_relation_list(relation_list, "contains");
/*
* And show the list.
can_compare = ftype_can_ge(ftype);
else if (strcmp(item_str, "<=") == 0)
can_compare = ftype_can_le(ftype);
+ else if (strcmp(item_str, "contains") == 0)
+ can_compare = ftype_can_contains(ftype);
else
can_compare = TRUE; /* not a comparison */
if (!can_compare) {
* for the type of the field; if a range string was
* specified, must be valid for FT_BYTES.
*/
- fvalue = fvalue_from_unparsed(ftype, stripped_value_str,
- dfilter_report_bad_value);
+ if (strcmp(item_str, "contains") == 0) {
+ fvalue = fvalue_from_unparsed(ftype, stripped_value_str, TRUE,
+ dfilter_report_bad_value);
+ }
+ else {
+ fvalue = fvalue_from_unparsed(ftype, stripped_value_str, FALSE,
+ dfilter_report_bad_value);
+ }
if (fvalue == NULL) {
/*
* It's not valid.
"""
#
-# $Id: dfilter-test.py,v 1.2 2003/07/25 03:44:05 gram Exp $
+# $Id: dfilter-test.py,v 1.3 2003/08/27 15:23:11 gram Exp $
#
# Copyright (C) 2003 by Gilbert Ramirez <gram@alumni.rice.edu>
#
return self.DFilterCount(pkt_nfs,
"nfs.fattr3.size == 264000", 0)
+ def ck_contains_1(self):
+ return self.DFilterCount(pkt_ipx_rip,
+ "ipx.src.node contains a3", 1)
+
+ def ck_contains_2(self):
+ return self.DFilterCount(pkt_ipx_rip,
+ "ipx.src.node contains a3:e3", 1)
+
+ def ck_contains_3(self):
+ return self.DFilterCount(pkt_ipx_rip,
+ "ipx.src.node contains 00:aa:00:a3:e3:a4", 1)
+
+ def ck_contains_4(self):
+ return self.DFilterCount(pkt_ipx_rip,
+ "ipx.src.node contains aa:e3", 0)
+
tests = [
ck_eq_1,
ck_bytes_2,
ck_uint64_1,
ck_uint64_2,
+ ck_contains_1,
+ ck_contains_2,
+ ck_contains_3,
+ ck_contains_4,
]
return self.DFilterCount(pkt_tftp,
'tftp.type == "junk"', 0)
+ def ck_contains_1(self):
+ return self.DFilterCount(pkt_http,
+ 'http.request.method contains "E"', 1)
+
+ def ck_contains_2(self):
+ return self.DFilterCount(pkt_http,
+ 'http.request.method contains "EA"', 1)
+
+ def ck_contains_3(self):
+ return self.DFilterCount(pkt_http,
+ 'http.request.method contains "HEAD"', 1)
+
+ def ck_contains_4(self):
+ return self.DFilterCount(pkt_http,
+ 'http.request.method contains "POST"', 0)
+
+ def ck_contains_5(self):
+ return self.DFilterCount(pkt_http,
+ 'http.request.method contains 50:4f:53:54"', 0) # "POST"
+
+ def ck_contains_6(self):
+ return self.DFilterCount(pkt_http,
+ 'http.request.method contains 48:45:41:44"', 1) # "HEAD"
tests = [
# ck_slice_8,
ck_stringz_1,
ck_stringz_2,
+ ck_contains_1,
+ ck_contains_2,
+ ck_contains_3,
+ ck_contains_4,
+ ck_contains_5,
]
"ip[-1] == 0x86", 0)
+ def ck_contains_1(self):
+ return self.DFilterCount(pkt_http,
+ "eth contains 6b", 1)
+
+ def ck_contains_2(self):
+ return self.DFilterCount(pkt_http,
+ "eth contains 09:6b:88", 1)
+
+ def ck_contains_3(self):
+ return self.DFilterCount(pkt_http,
+ "eth contains 00:e0:81:00:b0:28:00:09:6b:88:f5:c9:08:00", 1)
+
+ def ck_contains_4(self):
+ return self.DFilterCount(pkt_http,
+ "eth contains ff:ff:ff", 0)
+
+ def ck_contains_5(self):
+ return self.DFilterCount(pkt_http,
+ 'http contains "HEAD"', 1)
+
tests = [
ck_slice_1,
# XXX
# ck_slice_4,
# ck_slice_5,
+ ck_contains_1,
+ ck_contains_2,
+ ck_contains_3,
+ ck_contains_4,
+ ck_contains_5,
]