diff options
author | Gilbert Ramirez <gram@alumni.rice.edu> | 1999-08-29 04:06:43 +0000 |
---|---|---|
committer | Gilbert Ramirez <gram@alumni.rice.edu> | 1999-08-29 04:06:43 +0000 |
commit | 10adb4dbee68f56d84113be57d69552ac2ec3491 (patch) | |
tree | 64351550987cfe17c4f34caa05b2f3d272879ffa | |
parent | 0d9fcad21c78b7cd7bb244c2cdc994813b804574 (diff) | |
download | wireshark-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.y | 3 | ||||
-rw-r--r-- | dfilter.c | 54 | ||||
-rw-r--r-- | proto.c | 116 | ||||
-rw-r--r-- | proto.h | 31 |
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; } @@ -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 */ @@ -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 @@ -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); |