aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>1999-08-29 04:06:43 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>1999-08-29 04:06:43 +0000
commit10adb4dbee68f56d84113be57d69552ac2ec3491 (patch)
tree64351550987cfe17c4f34caa05b2f3d272879ffa
parent0d9fcad21c78b7cd7bb244c2cdc994813b804574 (diff)
downloadwireshark-10adb4dbee68f56d84113be57d69552ac2ec3491.tar.gz
wireshark-10adb4dbee68f56d84113be57d69552ac2ec3491.tar.bz2
wireshark-10adb4dbee68f56d84113be57d69552ac2ec3491.zip
Removed from the display filter/proto_tree code the assumption that
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. svn path=/trunk/; revision=608
-rw-r--r--dfilter-grammar.y3
-rw-r--r--dfilter.c54
-rw-r--r--proto.c116
-rw-r--r--proto.h31
4 files changed, 113 insertions, 91 deletions
diff --git a/dfilter-grammar.y b/dfilter-grammar.y
index c7a631b534..96a814804f 100644
--- a/dfilter-grammar.y
+++ b/dfilter-grammar.y
@@ -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; }
diff --git a/dfilter.c b/dfilter.c
index a271a5c1b1..c81f93d2c5 100644
--- 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 931cccd763..f46166b616 100644
--- 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 5a124f7449..a7ade0ad7d 100644
--- 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);