Removed from the display filter/proto_tree code the assumption that
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 29 Aug 1999 04:06:43 +0000 (04:06 +0000)
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 29 Aug 1999 04:06:43 +0000 (04:06 +0000)
a protocol occurs only once in a packet. Because of encapsulation (IP within
IP), a protocol can occur more than once. I don't have a packet trace
showing such a packet, but the code should handle it now. The one thing
that it cannot do, though, is differentiate the levels. It might be
nice to say:
ip{1}.src == 192.168.1.1 && ipx{2}.dst == 10.0.0.1

In the dfilter grammar I had left IPXNET variables out of the list
of variables that could be checked for existence. Now you can check
for the existence of ipx.srcnet and ipx.dstnet. Hurrah.

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

dfilter-grammar.y
dfilter.c
proto.c
proto.h

index c7a631b534d8938c21e1d95354467347ab7de75c..96a814804f02624eb72e3c827e75f6fd9979e053 100644 (file)
@@ -3,7 +3,7 @@
 /* dfilter-grammar.y
  * Parser for display filters
  *
- * $Id: dfilter-grammar.y,v 1.16 1999/08/27 19:27:09 gram Exp $
+ * $Id: dfilter-grammar.y,v 1.17 1999/08/29 04:06:42 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -299,6 +299,7 @@ any_variable_type:  T_FT_UINT8 { $$ = $1; }
        |               T_FT_UINT32 { $$ = $1; }
        |               T_FT_ETHER { $$ = $1; }
        |               T_FT_IPv4 { $$ = $1; }
+       |               T_FT_IPXNET { $$ = $1; }
        |               T_FT_NONE { $$ = $1; }
        |               T_FT_BYTES { $$ = $1; }
        |               T_FT_BOOLEAN { $$ = $1; }
index a271a5c1b172da986e7d725c7a09361fb22311be..c81f93d2c5f8f72c5cc3d4d4a19b0225cbf345c8 100644 (file)
--- a/dfilter.c
+++ b/dfilter.c
@@ -1,7 +1,7 @@
 /* dfilter.c
  * Routines for display filters
  *
- * $Id: dfilter.c,v 1.16 1999/08/26 06:20:48 gram Exp $
+ * $Id: dfilter.c,v 1.17 1999/08/29 04:06:43 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -445,16 +445,10 @@ check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8
 static gboolean
 check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree)
 {
-       int             target_field;
-       proto_tree      *subtree;
+       int             target;
 
-       target_field = dnode->value.variable;
-       subtree = proto_find_field(ptree, target_field);
-
-       if (subtree)
-               return TRUE;
-       else
-               return FALSE;
+       target = dnode->value.variable;
+       return proto_check_for_protocol_or_field(ptree, target);
 }
 
 static GArray*
@@ -462,33 +456,29 @@ get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd)
 {
        GArray          *array;
        int             parent_protocol;
-       int             target_field;
-       proto_tree      *subtree = NULL; /* where the parent protocol's sub-tree starts */
        proto_tree_search_info sinfo;
 
        g_assert(dnode->elem_size > 0);
        array = g_array_new(FALSE, FALSE, dnode->elem_size);
 
-       target_field = dnode->value.variable;
+       sinfo.target = dnode->value.variable;
+       sinfo.result.array = array;
+       sinfo.packet_data = pd;
+       sinfo.traverse_func = dnode->fill_array_func;
 
        /* Find the proto_tree subtree where we should start searching.*/
-       if (proto_registrar_is_protocol(target_field)) {
-               subtree = proto_find_protocol(ptree, target_field);
+       if (proto_registrar_is_protocol(sinfo.target)) {
+               proto_find_protocol_multi(ptree, sinfo.target,
+                               (GNodeTraverseFunc)proto_get_field_values, &sinfo);
        }
        else {
-               parent_protocol = proto_registrar_get_parent(target_field);
+               parent_protocol = proto_registrar_get_parent(sinfo.target);
                if (parent_protocol >= 0) {
-                       subtree = proto_find_protocol(ptree, parent_protocol);
+                       proto_find_protocol_multi(ptree, parent_protocol,
+                                       (GNodeTraverseFunc)proto_get_field_values, &sinfo);
                }
        }
 
-       if (subtree) {
-               sinfo.target_field = target_field;
-               sinfo.result_array = array;
-               sinfo.packet_data = pd;
-               proto_get_field_values(subtree, dnode->fill_array_func, &sinfo);
-       }
-
        return array;
 }
 
@@ -510,8 +500,8 @@ gboolean fill_array_numeric_variable(GNode *gnode, gpointer data)
        proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
        field_info              *fi = (field_info*) (gnode->data);
 
-       if (fi->hfinfo->id == sinfo->target_field) {
-               g_array_append_val(sinfo->result_array, fi->value.numeric);
+       if (fi->hfinfo->id == sinfo->target) {
+               g_array_append_val(sinfo->result.array, fi->value.numeric);
        }
 
        return FALSE; /* FALSE = do not end traversal of GNode tree */
@@ -522,8 +512,8 @@ gboolean fill_array_ether_variable(GNode *gnode, gpointer data)
        proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
        field_info              *fi = (field_info*) (gnode->data);
 
-       if (fi->hfinfo->id == sinfo->target_field) {
-               g_array_append_val(sinfo->result_array, fi->value.ether);
+       if (fi->hfinfo->id == sinfo->target) {
+               g_array_append_val(sinfo->result.array, fi->value.ether);
        }
 
        return FALSE; /* FALSE = do not end traversal of GNode tree */
@@ -535,11 +525,11 @@ gboolean fill_array_bytes_variable(GNode *gnode, gpointer data)
        field_info              *fi = (field_info*) (gnode->data);
        GByteArray              *barray;
 
-       if (fi->hfinfo->id == sinfo->target_field) {
+       if (fi->hfinfo->id == sinfo->target) {
                barray = g_byte_array_new();
                /*list_of_byte_arrays = g_slist_append(list_of_byte_arrays, barray);*/
                g_byte_array_append(barray, sinfo->packet_data + fi->start + bytes_offset, bytes_length);
-               g_array_append_val(sinfo->result_array, barray);
+               g_array_append_val(sinfo->result.array, barray);
        }
 
        return FALSE; /* FALSE = do not end traversal of GNode tree */
@@ -550,8 +540,8 @@ gboolean fill_array_boolean_variable(GNode *gnode, gpointer data)
        proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
        field_info              *fi = (field_info*) (gnode->data);
 
-       if (fi->hfinfo->id == sinfo->target_field) {
-               g_array_append_val(sinfo->result_array, fi->value.boolean);
+       if (fi->hfinfo->id == sinfo->target) {
+               g_array_append_val(sinfo->result.array, fi->value.boolean);
        }
 
        return FALSE; /* FALSE = do not end traversal of GNode tree */
diff --git a/proto.c b/proto.c
index 931cccd7634f12df585ed0809216c47cfbf4fa63..f46166b6166908d5d494f61f2d15e0a856e4e6c5 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -1,7 +1,7 @@
 /* proto.c
  * Routines for protocol tree
  *
- * $Id: proto.c,v 1.18 1999/08/26 07:01:43 gram Exp $
+ * $Id: proto.c,v 1.19 1999/08/29 04:06:43 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -79,7 +79,8 @@ static proto_item *
 proto_tree_add_item_value(proto_tree *tree, int hfindex, gint start,
        gint length, int include_format, int visible, va_list ap);
 
-static gboolean proto_check_id(GNode *node, gpointer data);
+static gboolean check_for_protocol_or_field_id(GNode *node, gpointer data);
+static gboolean check_for_field_within_protocol(GNode *node, gpointer data);
 
 static int proto_register_field_init(header_field_info *hfinfo, int parent);
 
@@ -668,77 +669,92 @@ proto_registrar_is_protocol(int n)
                return FALSE;
 }
 
-typedef struct find_id_info {
-       int     target;
-       GNode   *result;
-} find_id_info;
-
-/* looks for a protocol or a header field in a proto_tree. Assumes that protocols
- * are at the top level, and header fields only occur underneath their parent's
- * subtree. Returns NULL if field not found 
- */
-proto_item*
-proto_find_field(proto_tree* tree, int id)
+/* Looks for a protocol or a field in a proto_tree. Returns TRUE if
+ * it exists anywhere, or FALSE if it exists nowhere. */
+gboolean
+proto_check_for_protocol_or_field(proto_tree* tree, int id)
 {
-       find_id_info    fiinfo;
-       int             parent_protocol;
-       proto_tree      *subtree;
+       proto_tree_search_info  sinfo;
 
-       fiinfo.target = id;
-       fiinfo.result = NULL;
+       sinfo.target = id;
+       sinfo.result.node = NULL;
+       sinfo.parent = -1;
+       sinfo.traverse_func = NULL;
 
-       /* do a quicker check if field is a protocol */
+       /* do a quicker check if target is a protocol */
        if (proto_registrar_is_protocol(id) == TRUE) {
-               return proto_find_protocol(tree, id);
+               proto_find_protocol_multi(tree, id, &check_for_protocol_or_field_id, &sinfo);
+       }
+       else {
+               /* find the field's parent protocol */
+               sinfo.parent = proto_registrar_get_parent(id);
+
+               /* Go through each protocol subtree, checking if the protocols
+                * is the parent protocol of the field that we're looking for.
+                * We may have protocols that occur more than once (e.g., IP in IP),
+                * so we do indeed have to check all protocol subtrees, looking
+                * for the parent protocol. That's why proto_find_protocol()
+                * is not used --- it assumes a protocol occurs only once. */
+               g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                                               check_for_field_within_protocol, &sinfo);
        }
 
-       /* find the field's parent protocol */
-       parent_protocol = proto_registrar_get_parent(id);
-       subtree = proto_find_protocol(tree, parent_protocol);
-
-       /* if there is a tree with that protocol, search it for the field */
-       if (subtree)
-               g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, proto_check_id, &fiinfo);
-
-       return (proto_item*) fiinfo.result;
+       if (sinfo.result.node)
+               return TRUE;
+       else
+               return FALSE;
 }
 
-
-/* Looks for a protocol at the top layer of the tree.
- *  Assumption: a protocol can occur only once in a proto_tree.
- */
-proto_item*
-proto_find_protocol(proto_tree* tree, int protocol_id)
+static gboolean
+check_for_protocol_or_field_id(GNode *node, gpointer data)
 {
-       find_id_info    fiinfo;
-
-       fiinfo.target = protocol_id;
-       fiinfo.result = NULL;
+       field_info              *fi = (field_info*) (node->data);
+       proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
 
-       g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, proto_check_id, &fiinfo);
-       return (proto_item*) fiinfo.result;
+       if (fi) { /* !fi == the top most container node which holds nothing */
+               if (fi->hfinfo->id == sinfo->target) {
+                       sinfo->result.node = node;
+                       return TRUE; /* halt traversal */
+               }
+       }
+       return FALSE; /* keep traversing */
 }
 
-
 static gboolean
-proto_check_id(GNode *node, gpointer data)
+check_for_field_within_protocol(GNode *node, gpointer data)
 {
-       field_info      *fi = (field_info*) (node->data);
-       find_id_info    *fiinfo = (find_id_info*) data;
+       field_info              *fi = (field_info*) (node->data);
+       proto_tree_search_info  *sinfo = (proto_tree_search_info*) data;
 
        if (fi) { /* !fi == the top most container node which holds nothing */
-               if (fi->hfinfo->id == fiinfo->target) {
-                       fiinfo->result = node;
-                       return TRUE; /* halt traversal */
+               if (fi->hfinfo->id == sinfo->parent) {
+                       g_node_traverse(node, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                                       check_for_protocol_or_field_id, sinfo);
+                       if (sinfo->result.node)
+                               return TRUE; /* halt traversal */
                }
        }
        return FALSE; /* keep traversing */
 }
 
+/* Looks for a protocol at the top layer of the tree. The protocol can occur
+ * more than once, for those encapsulated protocols. For each protocol subtree
+ * that is found, the callback function is called.
+ */
 void
-proto_get_field_values(proto_tree* subtree, GNodeTraverseFunc fill_array_func, proto_tree_search_info *sinfo)
+proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
+                       proto_tree_search_info *sinfo)
+{
+       g_assert(callback != NULL);
+       g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, callback, (gpointer*)sinfo);
+}
+
+/* Simple wrappter to traverse all nodes, calling the sinfo traverse function with sinfo as an arg */
+gboolean
+proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo)
 {
-       g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, fill_array_func, sinfo);
+       g_node_traverse((GNode*)subtree, G_IN_ORDER, G_TRAVERSE_ALL, -1, sinfo->traverse_func, (gpointer*)sinfo);
+       return TRUE; /* halt */
 }
 
 /* Dumps the contents of the registration database to stdout. An indepedent program can take
diff --git a/proto.h b/proto.h
index 5a124f7449b08bbfda5ddc999bea432330789c15..a7ade0ad7d9992510b2384f7609dd1f7c008a0e6 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -1,7 +1,7 @@
 /* proto.h
  * Definitions for protocol display
  *
- * $Id: proto.h,v 1.8 1999/08/26 07:01:44 gram Exp $
+ * $Id: proto.h,v 1.9 1999/08/29 04:06:43 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -112,10 +112,16 @@ typedef struct field_info {
 } field_info;
 
 
+/* used when calling proto search functions */
 typedef struct proto_tree_search_info {
-       int             target_field;
-       GArray          *result_array;
-       const guint8    *packet_data;
+       int                     target;
+       int                     parent;
+       const guint8            *packet_data;
+       GNodeTraverseFunc       traverse_func;
+       union {
+               GArray                  *array;
+               GNode                   *node;
+       }                       result;
 } proto_tree_search_info;
 
 /* Sets up memory used by proto routines. Called at program startup */
@@ -173,10 +179,19 @@ int proto_registrar_get_parent(int n);
 /* Is item #n a protocol? */
 gboolean proto_registrar_is_protocol(int n);
 
-proto_item* proto_find_field(proto_tree* tree, int id);
-proto_item* proto_find_protocol(proto_tree* tree, int protocol_id);
-void proto_get_field_values(proto_tree* subtree, GNodeTraverseFunc fill_array_func,
-       proto_tree_search_info *sinfo);
+/* Checks for existence any protocol or field within a tree.
+ * TRUE = found, FALSE = not found */
+gboolean proto_check_for_protocol_or_field(proto_tree* tree, int id);
+
+/* Search for a protocol subtree, which can occur more than once, and for each successful
+ * find, call the calback function, passing sinfo as the second argument */
+void proto_find_protocol_multi(proto_tree* tree, int target, GNodeTraverseFunc callback,
+                       proto_tree_search_info *sinfo);
+
+/* Just a wrapper to call sinfo->traverse_func() for all nodes in the subtree, with the GNode
+ * and sinfo as the two arguments to sinfo->traverse_func(). Useful when you have to process
+ * all nodes in a subtree. */
+gboolean proto_get_field_values(proto_tree* subtree, proto_tree_search_info *sinfo);
 
 /* Dumps a glossary of the protocol and field registrations to STDOUT */
 void proto_registrar_dump(void);