Add a "contains" operator for byte-strings, strings, and tvbuffs (protocols).
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 27 Aug 2003 15:23:11 +0000 (15:23 +0000)
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 27 Aug 2003 15:23:11 +0000 (15:23 +0000)
The search uses a naive approach; more work is required to add a
Boyer-Moore Search algorithm.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@8280 f5534014-38df-0310-8fa8-9805f1628bb7

27 files changed:
doc/ethereal.pod.template
doc/tethereal.pod.template
epan/dfilter/dfvm.c
epan/dfilter/dfvm.h
epan/dfilter/gencode.c
epan/dfilter/grammar.lemon
epan/dfilter/scanner.l
epan/dfilter/semcheck.c
epan/dfilter/sttype-test.c
epan/dfilter/sttype-test.h
epan/ftypes/ftype-bytes.c
epan/ftypes/ftype-double.c
epan/ftypes/ftype-integer.c
epan/ftypes/ftype-ipv4.c
epan/ftypes/ftype-none.c
epan/ftypes/ftype-string.c
epan/ftypes/ftype-time.c
epan/ftypes/ftype-tvbuff.c
epan/ftypes/ftypes-int.h
epan/ftypes/ftypes.c
epan/ftypes/ftypes.h
epan/strutil.c
epan/strutil.h
epan/tvbuff.c
epan/tvbuff.h
gtk/dfilter_expr_dlg.c
tools/dfilter-test.py

index ef09184443d8d1f6d2bdaeb40e1585d5e0e70163..8774d8863611d24570bc8bbb4fbc1dde264ccbd9 100644 (file)
@@ -1384,6 +1384,11 @@ abbreviations:
     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)
@@ -1480,7 +1485,7 @@ Use of octal to look for "HEAD":
 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".
 
index 248ad436e8dc8b5705b1366ce2cdfa1a9bcd0789..7e439c76eec4ed909a3fa20aa1971174b32af86c 100644 (file)
@@ -599,6 +599,11 @@ abbreviations:
     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)
@@ -695,7 +700,7 @@ Use of octal to look for "HEAD":
 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".
 
index 0be9fc692db6f84f35b4de30746229d80b730ee5..85753468f12ff5fc57cbc1653f60bc9c72527978 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -403,6 +403,11 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
                                                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;
index c97faae5fb62a67983460919d34f2a652a38b505..efeb478962498b5dd9c0f922dff5e75629f5ca7e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -67,6 +67,7 @@ typedef enum {
        ANY_GE,
        ANY_LT,
        ANY_LE,
+       ANY_CONTAINS,
        MK_RANGE
 
 } dfvm_opcode_t;
index 1d23d93bc6935313924b7734d97b472c420c45ec..333fdacf381cc738d25aa24fdd27871e6487d38f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -319,6 +319,10 @@ gen_test(dfwork_t *dfw, stnode_t *st_node)
                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;
        }
 }
 
index 35310adf7dc6518225bad4e868e529b5bf56e355..c1148920349e4266232c0f8ec7be6fc104c234c1 100644 (file)
@@ -1,4 +1,4 @@
-/* $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
@@ -108,7 +108,7 @@ shifting 3 more symbols. */
 /* 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 */
@@ -247,6 +247,7 @@ rel_op2(O) ::= TEST_GT.  { O = TEST_OP_GT; }
 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; }
 
 
 
index ca23626457abb5f8cded292f1b344f62ff65d9f3..563c08b8554a3a01a04f633a1d52e0f1e9bbe5be 100644 (file)
@@ -1,6 +1,6 @@
 %{
 /*
- * $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>
@@ -77,6 +77,7 @@ GString* quoted_string = NULL;
 "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);
@@ -221,6 +222,7 @@ simple(int token)
                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:
index faba2942d4ea43cfae6a01f3541159e0a9331e09..8bcf967d59ab82b33411d2edf4ca64b8610bd2a0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -260,6 +260,7 @@ is_bytes_type(enum ftenum type)
  * 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;
@@ -318,7 +319,7 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func,
        }
        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);
@@ -358,7 +359,8 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func,
 }
 
 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;
@@ -389,7 +391,7 @@ check_relation_LHS_STRING(FtypeCanFunc can_func _U_, stnode_t *st_node,
                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),
@@ -412,7 +414,8 @@ check_relation_LHS_STRING(FtypeCanFunc can_func _U_, stnode_t *st_node,
 }
 
 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;
@@ -430,7 +433,7 @@ check_relation_LHS_UNPARSED(FtypeCanFunc can_func _U_, stnode_t *st_node,
                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);
@@ -443,7 +446,7 @@ check_relation_LHS_UNPARSED(FtypeCanFunc can_func _U_, stnode_t *st_node,
                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),
@@ -451,8 +454,9 @@ check_relation_LHS_UNPARSED(FtypeCanFunc can_func _U_, stnode_t *st_node,
                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);
                }
@@ -529,7 +533,8 @@ check_drange_sanity(stnode_t *st)
 }
 
 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;
@@ -589,7 +594,7 @@ check_relation_LHS_RANGE(FtypeCanFunc can_func _U_, stnode_t *st_node,
        }
        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);
                }
@@ -609,21 +614,26 @@ check_relation_LHS_RANGE(FtypeCanFunc can_func _U_, stnode_t *st_node,
 
 /* 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:
@@ -664,23 +674,29 @@ check_test(stnode_t *st_node)
                        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();
        }
 }
 
index d559bff19e7ab66af07e59af299266ad9850522a..f6f917f1fce5e73de385a5fed36226a92c25256d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -90,6 +90,8 @@ num_operands(test_op_t op)
                        return 2;
                case TEST_OP_LE:
                        return 2;
+               case TEST_OP_CONTAINS:
+                       return 2;
        }
        g_assert_not_reached();
        return -1;
index a4d017f15452adbd1801a8833a8f31cc99c5ea85..f662a5b097383e9caf71e169edf8356bb5fce544 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -35,7 +35,8 @@ typedef enum {
        TEST_OP_GT,
        TEST_OP_GE,
        TEST_OP_LT,
-       TEST_OP_LE
+       TEST_OP_LE,
+       TEST_OP_CONTAINS
 } test_op_t;
 
 void
index 25c2f445ec7b34983034e22ce7b8b0719d00bafc..e0e859fab759530c704a7f7b5ddd0076fef0d295 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <epan/resolv.h>
+#include <epan/strutil.h>
 #include <epan/int-64bit.h>
 
 #define ETHER_LEN      6
@@ -129,7 +130,7 @@ is_byte_sep(guint8 c)
 }
 
 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;
@@ -226,7 +227,7 @@ val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
 }
 
 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;
 
@@ -235,7 +236,18 @@ ether_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
         * 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;
        }
 
@@ -251,7 +263,7 @@ ether_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
 }
 
 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];
 
@@ -265,7 +277,7 @@ ipv6_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
 }
 
 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];
 
@@ -279,7 +291,7 @@ u64_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
 }
 
 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];
 
@@ -577,6 +589,20 @@ cmp_le_i64(fvalue_t *fv_a, fvalue_t *fv_b)
        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)
 {
@@ -587,7 +613,7 @@ 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 */
@@ -606,6 +632,7 @@ ftype_register_bytes(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               cmp_contains,
 
                len,
                slice,
@@ -617,7 +644,7 @@ 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 */
@@ -636,6 +663,7 @@ ftype_register_bytes(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               cmp_contains,
 
                len,
                slice,
@@ -666,6 +694,7 @@ ftype_register_bytes(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               cmp_contains,
 
                len,
                slice,
@@ -696,6 +725,7 @@ ftype_register_bytes(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               cmp_contains,
 
                len,
                slice,
@@ -726,6 +756,7 @@ ftype_register_bytes(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               NULL,                           /* cmp_contains */
 
                len,
                slice,
@@ -756,6 +787,7 @@ ftype_register_bytes(void)
                cmp_ge_i64,
                cmp_lt_i64,
                cmp_le_i64,
+               NULL,                           /* cmp_contains */
 
                len,
                slice,
index fb1bfcd36f62e71112ea9d1ef3504d69f1458807..27fba9aaf4117261b51132062a63f3998f158df7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -51,7 +51,7 @@ value_get_floating(fvalue_t *fv)
 }
 
 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;
 
@@ -181,6 +181,7 @@ ftype_register_double(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,
                NULL,
@@ -211,6 +212,7 @@ ftype_register_double(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,
                NULL,
index 818b6cce7ab24c1c85f9e088e4b7222dae284471..0bba4d218bc8cf8d33e490d68b829b6691f713b0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -49,7 +49,7 @@ get_integer(fvalue_t *fv)
 }
 
 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;
 
@@ -78,7 +78,7 @@ val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
 }
 
 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;
@@ -88,7 +88,7 @@ ipxnet_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
         * 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;
        }
 
@@ -242,6 +242,7 @@ ftype_register_integers(void)
                u_cmp_ge,
                u_cmp_lt,
                u_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -271,6 +272,7 @@ ftype_register_integers(void)
                u_cmp_ge,
                u_cmp_lt,
                u_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -300,6 +302,7 @@ ftype_register_integers(void)
                u_cmp_ge,
                u_cmp_lt,
                u_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -329,6 +332,7 @@ ftype_register_integers(void)
                u_cmp_ge,
                u_cmp_lt,
                u_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -358,6 +362,7 @@ ftype_register_integers(void)
                s_cmp_ge,
                s_cmp_lt,
                s_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -387,6 +392,7 @@ ftype_register_integers(void)
                s_cmp_ge,
                s_cmp_lt,
                s_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -416,6 +422,7 @@ ftype_register_integers(void)
                s_cmp_ge,
                s_cmp_lt,
                s_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -445,6 +452,7 @@ ftype_register_integers(void)
                s_cmp_ge,
                s_cmp_lt,
                s_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -474,6 +482,7 @@ ftype_register_integers(void)
                NULL,                           /* cmp_ge */
                NULL,                           /* cmp_lt */
                NULL,                           /* cmp_le */
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -504,6 +513,7 @@ ftype_register_integers(void)
                u_cmp_ge,
                u_cmp_lt,
                u_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
@@ -534,6 +544,7 @@ ftype_register_integers(void)
                u_cmp_ge,
                u_cmp_lt,
                u_cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,                           /* len */
                NULL,                           /* slice */
index cad03ef251aed7fd4abc4f363e803209cf927f83..c5362bfbcaeb1f719c3e05c6af4fd7b2225247d3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -45,7 +45,7 @@ value_get(fvalue_t *fv)
 }
 
 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;
@@ -99,7 +99,7 @@ val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
                }
 
                /* 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;
@@ -202,6 +202,7 @@ ftype_register_ipv4(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               NULL,                           /* cmp_contains */
 
                NULL,
                NULL,
index bf6cd400eb97b94822715d233d5ba369cf24c865..46c1822a80307c6fa6acee3534513d8ac07c4d56 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -57,6 +57,7 @@ ftype_register_none(void)
                NULL,
                NULL,
                NULL,
+               NULL,                           /* cmp_contains */
 
                NULL,
                NULL,
index 5cac0e79661784e6e795c5359b918acc9e1dbbf6..bb2c088ebefdbf295fd794030211a58fb559d60b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -117,6 +117,32 @@ val_from_string(fvalue_t *fv, char *s, LogFunc logfunc _U_)
        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)
 {
@@ -170,6 +196,25 @@ cmp_le(fvalue_t *a, fvalue_t *b)
        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)
 {
@@ -180,7 +225,7 @@ 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 */
@@ -199,6 +244,7 @@ ftype_register_string(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               cmp_contains,                   /* cmp_contains */
 
                len,
                slice,
@@ -209,7 +255,7 @@ ftype_register_string(void)
                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 */
@@ -228,6 +274,7 @@ ftype_register_string(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               cmp_contains,                   /* cmp_contains */
 
                len,
                slice,
@@ -238,7 +285,7 @@ ftype_register_string(void)
                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 */
@@ -257,6 +304,7 @@ ftype_register_string(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               cmp_contains,                   /* cmp_contains */
 
                len,
                slice,
index dd04fa6cb9a407760b97b3c8f13af792a0769a2f..d926d3036596ec48f6dc171c1425955bf7428a6a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -167,7 +167,7 @@ get_nsecs(char *startp, int *nsecs)
 }
 
 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;
 
@@ -277,6 +277,12 @@ fail:
        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)
 {
@@ -337,7 +343,7 @@ ftype_register_time(void)
                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 */
@@ -356,6 +362,8 @@ ftype_register_time(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               NULL,                           /* cmp_contains */
+
                NULL,
                NULL
        };
@@ -384,6 +392,8 @@ ftype_register_time(void)
                cmp_ge,
                cmp_lt,
                cmp_le,
+               NULL,                           /* cmp_contains */
+
                NULL,
                NULL
        };
index 43050f9f9f317eedef1b96cb55260131e8fa8fc7..c648086a3fa7957fe21c675f97af9badc5251ff0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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);
+       }
 }
 
 
@@ -41,6 +52,66 @@ value_set(fvalue_t *fv, gpointer value, gboolean already_copied)
        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)
 {
@@ -74,18 +145,29 @@ slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
        }
 }
 
+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 */
 
@@ -103,6 +185,7 @@ ftype_register_tvbuff(void)
                NULL,
                NULL,
                NULL,
+               cmp_contains,                   /* cmp_contains */
 
                len,
                slice,
index d6922ef7c9f911f0f8bab966ad96f3f7063bb803..2ba2e2fde360a67fdf16497f487d005ebe6a89d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -29,7 +29,7 @@
 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);
@@ -74,6 +74,7 @@ struct _ftype_t {
        FvalueCmp               cmp_ge;
        FvalueCmp               cmp_lt;
        FvalueCmp               cmp_le;
+       FvalueCmp               cmp_contains;
 
        FvalueLen               len;
        FvalueSlice             slice;
index aa2239397f8e9a16080c0af73f3bcdd4a6adb09f..58f4afda603229345c53b466cc395591a7d211b6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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>
@@ -198,6 +198,15 @@ ftype_can_le(enum ftenum ftype)
        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 */
@@ -236,13 +245,13 @@ fvalue_free(fvalue_t *fv)
 }
 
 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;
                }
        }
@@ -507,3 +516,11 @@ fvalue_le(fvalue_t *a, fvalue_t *b)
        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);
+}
index 1e224cbf53c6afa96e0465f8cddc926ebf4a680b..74f4f2b705e0b54099807d9fd15da91ccee15ecf 100644 (file)
@@ -1,7 +1,7 @@
 /* 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>
@@ -120,6 +120,9 @@ ftype_can_lt(enum ftenum ftype);
 gboolean
 ftype_can_le(enum ftenum ftype);
 
+gboolean
+ftype_can_contains(enum ftenum ftype);
+
 /* ---------------- FVALUE ----------------- */
 
 #include <epan/ipv4.h>
@@ -141,6 +144,11 @@ typedef struct {
                nstime_t        time;
                tvbuff_t        *tvb;
        } value;
+
+       /* The following is provided for private use
+        * by the fvalue. */
+       gboolean        fvalue_gboolean1;
+
 } fvalue_t;
 
 fvalue_t*
@@ -152,10 +160,10 @@ fvalue_free(fvalue_t *fv);
 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.
@@ -213,6 +221,9 @@ fvalue_lt(fvalue_t *a, fvalue_t *b);
 gboolean
 fvalue_le(fvalue_t *a, fvalue_t *b);
 
+gboolean
+fvalue_contains(fvalue_t *a, fvalue_t *b);
+
 guint
 fvalue_length(fvalue_t *fv);
 
index 45ea39dbffef50b806553c84899ee360d8cbc03d..93b5b1ef5fadc6deba9b7453b125d80388e7a6e5 100644 (file)
@@ -1,7 +1,7 @@
 /* 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>
@@ -301,3 +301,34 @@ bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct) {
   *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;
+}
index 78aabe3dd2826bb0993227dbf4e703824741d6e6..e9792c6e94fb8459f80650eb179f0a3df614a3cf 100644 (file)
@@ -1,7 +1,7 @@
 /* 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>
@@ -35,6 +35,9 @@ gchar*     format_text(const guchar *line, int len);
 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)
index b161a8110e9bceabc575c2d292fbc87bea41626c..65997123bcbaed7d276ee52ef76a6e269c82c56f 100644 (file)
@@ -9,7 +9,7 @@
  *             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>
  *
@@ -2141,3 +2141,33 @@ tvb_get_ds_tvb(tvbuff_t *tvb)
 {
        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;
+}
index 6dd756a03c8b4702f6ba533420cff3d0cd91928d..156de931facaf82ee4d1a178b099504daddc4d41 100644 (file)
@@ -9,7 +9,7 @@
  *             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>
  *
@@ -435,6 +435,13 @@ extern gchar *tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len);
 
 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__ */
index a91c8c68e3a0a4e786e9912814598e40664d4fe3..20c79e19d934528474f600cee3470108f228b561 100644 (file)
@@ -7,7 +7,7 @@
  * 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>
@@ -280,6 +280,9 @@ show_relations(GtkWidget *relation_label, GtkWidget *relation_list,
        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.
@@ -883,6 +886,8 @@ dfilter_expr_dlg_accept_cb(GtkWidget *w, gpointer filter_te_arg)
         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) {
@@ -928,8 +933,14 @@ dfilter_expr_dlg_accept_cb(GtkWidget *w, gpointer filter_te_arg)
          * 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.
index 2e801a4e4d6b2bdba995935b738612722a37da16..58ca3ccae572dfd63374e35d46964052dddb42a4 100755 (executable)
@@ -4,7 +4,7 @@ Test-suite to test ethereal's dfilter mechanism.
 """
 
 #
-# $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>
 #  
@@ -454,6 +454,22 @@ class Bytes(Test):
                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,
@@ -482,6 +498,10 @@ class Bytes(Test):
                ck_bytes_2,
                ck_uint64_1,
                ck_uint64_2,
+               ck_contains_1,
+               ck_contains_2,
+               ck_contains_3,
+               ck_contains_4,
                ]
 
 
@@ -967,6 +987,29 @@ class String(Test):
                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 = [
@@ -995,6 +1038,11 @@ class String(Test):
 #              ck_slice_8,
                ck_stringz_1,
                ck_stringz_2,
+               ck_contains_1,
+               ck_contains_2,
+               ck_contains_3,
+               ck_contains_4,
+               ck_contains_5,
                ]
 
 
@@ -1124,6 +1172,26 @@ class TVB(Test):
                        "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,
@@ -1132,6 +1200,11 @@ class TVB(Test):
 # XXX
 #              ck_slice_4,
 #              ck_slice_5,
+               ck_contains_1,
+               ck_contains_2,
+               ck_contains_3,
+               ck_contains_4,
+               ck_contains_5,
                ]