aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dfilter-grammar.y166
-rw-r--r--dfilter-scanner.l21
-rw-r--r--dfilter.c69
-rw-r--r--dfilter.h4
-rw-r--r--file.c8
-rw-r--r--proto.c55
-rw-r--r--proto.h7
7 files changed, 294 insertions, 36 deletions
diff --git a/dfilter-grammar.y b/dfilter-grammar.y
index b49ac0b9ff..9a966985d0 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.25 1999/10/11 19:39:29 guy Exp $
+ * $Id: dfilter-grammar.y,v 1.26 1999/10/12 04:21:09 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -93,6 +93,13 @@ static GNode* dfilter_mknode_bytes_variable(gint id, gint offset, guint length);
static guint32 string_to_value(char *s);
static int ether_str_to_guint8_array(const char *s, guint8 *mac);
static int ipv6_str_to_guint8_array(const char *s, guint8 *ipv6);
+static guint dfilter_get_bytes_variable_offset(GNode *gnode);
+static guint dfilter_get_bytes_value_length(GNode* gnode);
+static void dfilter_set_bytes_variable_length(GNode *gnode, guint length);
+static guint dfilter_get_bytes_variable_length(GNode *gnode);
+static gint dfilter_get_bytes_variable_field_registered_length(GNode *gnode);
+static char* dfilter_get_variable_abbrev(GNode *gnode);
+static int check_bytes_variable_sanity(GNode *gnode);
/* This is the dfilter we're currently processing. It's how
* dfilter_compile communicates with us.
@@ -223,10 +230,56 @@ relation: numeric_variable numeric_relation numeric_value
| bytes_variable bytes_relation bytes_value
{
+ int a_len, b_len;
+
+ a_len = dfilter_get_bytes_variable_length($1);
+ b_len = dfilter_get_bytes_value_length($3);
+
+ if (a_len == 0) {
+ dfilter_set_bytes_variable_length($1, b_len);
+ a_len = b_len;
+ }
+
+ if (!check_bytes_variable_sanity($1)) {
+ YYERROR;
+ }
+
+ if (a_len != b_len) {
+ dfilter_fail("Field \"%s\" has %u byte%s being compared, but %u byte%s "
+ "were supplied.",
+ dfilter_get_variable_abbrev($1),
+ a_len, plurality(a_len, "", "s"),
+ b_len, plurality(b_len, "", "s"));
+ YYERROR;
+ }
+
$$ = dfilter_mknode_join($1, relation, $2, $3);
}
| bytes_variable bytes_relation bytes_variable
{
+ int a_len, b_len;
+
+ a_len = dfilter_get_bytes_variable_length($1);
+ b_len = dfilter_get_bytes_variable_length($3);
+
+ if (!check_bytes_variable_sanity($1)) {
+ YYERROR;
+ }
+
+ if (!check_bytes_variable_sanity($3)) {
+ YYERROR;
+ }
+
+ if (a_len != b_len) {
+ dfilter_fail("Fields \"%s\" and \"%s\" are being compared with "
+ "disparate lengths of %u byte%s and %u byte%s.",
+ dfilter_get_variable_abbrev($1),
+ dfilter_get_variable_abbrev($3),
+ a_len, plurality(a_len, "", "s"),
+ b_len, plurality(b_len, "", "s"));
+ YYERROR;
+ }
+
$$ = dfilter_mknode_join($1, relation, $2, $3);
}
@@ -304,8 +357,27 @@ bytes_value: T_VAL_BYTE_STRING
$$ = dfilter_mknode_bytes_value(barray);
g_free($1);
}
- ;
+ | T_VAL_NUMBER_STRING
+ {
+ guint32 val32 = string_to_value($1);
+ guint8 val8;
+ GByteArray *barray;
+
+ if (val32 > 0xff) {
+ dfilter_fail("The value \"%s\" cannot be stored in a single-byte byte-string. "
+ "Use the multi-byte \"xx:yy\" representation.", $1);
+ YYERROR;
+ }
+ val8 = (guint8) val32;
+ barray = g_byte_array_new();
+ global_df->list_of_byte_arrays = g_slist_append(global_df->list_of_byte_arrays, barray);
+ g_byte_array_append(barray, &val8, 1);
+
+ $$ = dfilter_mknode_bytes_value(barray);
+ g_free($1);
+ }
+ ;
numeric_variable: T_FT_UINT8 { $$ = dfilter_mknode_numeric_variable($1.id); }
| T_FT_UINT16 { $$ = dfilter_mknode_numeric_variable($1.id); }
@@ -532,6 +604,62 @@ dfilter_mknode_bytes_variable(gint id, gint offset, guint length)
return gnode;
}
+/* Gets length of variable represented by node from proto_register */
+static gint
+dfilter_get_bytes_variable_field_registered_length(GNode *gnode)
+{
+ dfilter_node *node = gnode->data;
+
+ /* Is this really a bytes_variable? */
+ g_assert(node->fill_array_func = fill_array_bytes_variable);
+
+ return proto_registrar_get_length(node->value.variable);
+}
+
+/* Sets the length of a bytes_variable node */
+static void
+dfilter_set_bytes_variable_length(GNode *gnode, guint length)
+{
+ dfilter_node *node = gnode->data;
+
+ /* Is this really a bytes_variable? */
+ g_assert(node->fill_array_func = fill_array_bytes_variable);
+
+ node->length = length;
+}
+
+/* Gets the length of a bytes_variable node */
+static guint
+dfilter_get_bytes_variable_length(GNode *gnode)
+{
+ dfilter_node *node = gnode->data;
+
+ /* Is this really a bytes_variable? */
+ g_assert(node->fill_array_func = fill_array_bytes_variable);
+
+ return node->length;
+}
+
+/* Gets the offset of a bytes_variable node */
+static guint
+dfilter_get_bytes_variable_offset(GNode *gnode)
+{
+ dfilter_node *node = gnode->data;
+
+ /* Is this really a bytes_variable? */
+ g_assert(node->fill_array_func = fill_array_bytes_variable);
+
+ return node->offset;
+}
+
+static char*
+dfilter_get_variable_abbrev(GNode *gnode)
+{
+ dfilter_node *node = gnode->data;
+
+ return proto_registrar_get_abbrev(node->value.variable);
+}
+
static GNode*
dfilter_mknode_numeric_value(guint32 val)
{
@@ -664,6 +792,17 @@ dfilter_mknode_bytes_value(GByteArray *barray)
return gnode;
}
+/* Given a node representing a bytes_value, returns
+ * the length of the byte array */
+static guint
+dfilter_get_bytes_value_length(GNode* gnode)
+{
+ dfilter_node *node = gnode->data;
+
+ g_assert(node->ntype == bytes);
+ return node->length;
+}
+
static guint32
string_to_value(char *s)
{
@@ -764,3 +903,26 @@ ipv6_str_to_guint8_array(const char *s, guint8 *ipv6)
return 1; /* read exactly 16 hex pairs */
}
+
+static int
+check_bytes_variable_sanity(GNode *gnode)
+{
+ int a_off, a_len, reg_len, t_off;
+
+ a_off = dfilter_get_bytes_variable_offset(gnode);
+ a_len = dfilter_get_bytes_variable_length(gnode);
+ reg_len = dfilter_get_bytes_variable_field_registered_length(gnode);
+
+ if (reg_len > 0) {
+ t_off = a_off >= 0 ? a_off : reg_len + a_off;
+ if (t_off + a_len > reg_len) {
+ dfilter_fail("The \"%s\" field is only %u byte%s wide, but "
+ "%u byte%s were supplied.",
+ dfilter_get_variable_abbrev(gnode),
+ reg_len, plurality(reg_len, "", "s"),
+ a_len, plurality(a_len, "", "s"));
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/dfilter-scanner.l b/dfilter-scanner.l
index b6bab0d9e2..1bf22ac53b 100644
--- a/dfilter-scanner.l
+++ b/dfilter-scanner.l
@@ -3,7 +3,7 @@
/* dfilter-scanner.l
* Scanner for display filters
*
- * $Id: dfilter-scanner.l,v 1.18 1999/10/11 17:04:33 deniel Exp $
+ * $Id: dfilter-scanner.l,v 1.19 1999/10/12 04:21:10 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -132,6 +132,25 @@ le|\<\= { dfilter_lval.operand = TOK_LE; return TOK_LE; }
return T_VAL_BYTE_RANGE;
}
+\[{whitespace}*-?[0-9]+{whitespace}*\] { /* range [ x ] */
+
+ char *byterange_string = g_strdup(yytext);
+ char *s = byterange_string + 1; /* I don't want the first '[' */
+ char *p;
+
+ /* Get the offset from the string */
+ if ((p = strtok(s, "]"))) {
+ dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
+ }
+ else {
+ g_free(byterange_string);
+ return 0;
+ }
+
+ dfilter_lval.byte_range.length = 0;
+ g_free(byterange_string);
+ return T_VAL_BYTE_RANGE;
+}
{hex}({hexsep}{hex})+ { /* byte string, any length */
dfilter_lval.string = g_strdup(yytext);
diff --git a/dfilter.c b/dfilter.c
index 56ac93d336..4f0486239a 100644
--- a/dfilter.c
+++ b/dfilter.c
@@ -1,7 +1,7 @@
/* dfilter.c
* Routines for display filters
*
- * $Id: dfilter.c,v 1.28 1999/10/11 17:04:34 deniel Exp $
+ * $Id: dfilter.c,v 1.29 1999/10/12 04:21:10 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -87,10 +87,10 @@ YYSTYPE yylval;
gchar dfilter_error_msg_buf[1024];
gchar *dfilter_error_msg; /* NULL when no error resulted */
-static gboolean dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8 *pd, guint len);
-static gboolean check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd, guint len);
-static gboolean check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd, guint len);
-static GArray* get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd, guint len);
+static gboolean dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8 *pd);
+static gboolean check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd);
+static gboolean check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd);
+static GArray* get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd);
static GArray* get_values_from_dfilter(dfilter_node *dnode, GNode *gnode);
static gboolean check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree);
static void clear_byte_array(gpointer data, gpointer user_data);
@@ -293,17 +293,17 @@ g_strcmp(gconstpointer a, gconstpointer b)
gboolean
-dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd, guint len)
+dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd)
{
gboolean retval;
if (dfcode == NULL)
return FALSE;
- retval = dfilter_apply_node(dfcode->dftree, ptree, pd, len);
+ retval = dfilter_apply_node(dfcode->dftree, ptree, pd);
return retval;
}
static gboolean
-dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd, guint len)
+dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd)
{
GNode *gnode_a, *gnode_b;
dfilter_node *dnode = (dfilter_node*) (gnode->data);
@@ -321,11 +321,11 @@ dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd, guint len)
case logical:
g_assert(gnode_a);
- return check_logical(dnode->value.logical, gnode_a, gnode_b, ptree, pd, len);
+ return check_logical(dnode->value.logical, gnode_a, gnode_b, ptree, pd);
case relation:
g_assert(gnode_a && gnode_b);
- return check_relation(dnode->value.relation, gnode_a, gnode_b, ptree, pd, len);
+ return check_relation(dnode->value.relation, gnode_a, gnode_b, ptree, pd);
case alternation:
g_assert_not_reached();
@@ -356,21 +356,21 @@ dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd, guint len)
}
static gboolean
-check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd, guint len)
+check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd)
{
- gboolean val_a = dfilter_apply_node(a, ptree, pd, len);
+ gboolean val_a = dfilter_apply_node(a, ptree, pd);
gboolean val_b;
switch(operand) {
case TOK_AND:
g_assert(b);
- return (val_a && dfilter_apply_node(b, ptree, pd, len));
+ return (val_a && dfilter_apply_node(b, ptree, pd));
case TOK_OR:
g_assert(b);
- return (val_a || dfilter_apply_node(b, ptree, pd, len));
+ return (val_a || dfilter_apply_node(b, ptree, pd));
case TOK_XOR:
g_assert(b);
- val_b = dfilter_apply_node(b, ptree, pd, len);
+ val_b = dfilter_apply_node(b, ptree, pd);
return ( ( val_a || val_b ) && ! ( val_a && val_b ) );
case TOK_NOT:
return (!val_a);
@@ -388,7 +388,7 @@ check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8
* faster.
*/
static gboolean
-check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8* pd, guint len)
+check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8* pd)
{
dfilter_node *node_a = (dfilter_node*) (a->data);
dfilter_node *node_b = (dfilter_node*) (b->data);
@@ -399,12 +399,12 @@ check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8
bytes_length = MIN(node_a->length, node_b->length);
bytes_offset = MIN(node_a->offset, node_b->offset);
if (node_a->ntype == variable)
- vals_a = get_values_from_ptree(node_a, ptree, pd, len);
+ vals_a = get_values_from_ptree(node_a, ptree, pd);
else
vals_a = get_values_from_dfilter(node_a, a);
if (node_b->ntype == variable)
- vals_b = get_values_from_ptree(node_b, ptree, pd, len);
+ vals_b = get_values_from_ptree(node_b, ptree, pd);
else
vals_b = get_values_from_dfilter(node_b, b);
@@ -426,7 +426,7 @@ check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree)
}
static GArray*
-get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd, guint len)
+get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd)
{
GArray *array;
int parent_protocol;
@@ -438,7 +438,6 @@ get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd,
sinfo.target = dnode->value.variable;
sinfo.result.array = array;
sinfo.packet_data = pd;
- sinfo.packet_len = len;
sinfo.traverse_func = dnode->fill_array_func;
/* Find the proto_tree subtree where we should start searching.*/
@@ -511,16 +510,36 @@ gboolean fill_array_bytes_variable(GNode *gnode, gpointer data)
proto_tree_search_info *sinfo = (proto_tree_search_info*)data;
field_info *fi = (field_info*) (gnode->data);
GByteArray *barray;
- guint start_of_data = fi->start + bytes_offset;
+ guint read_start, pkt_end;
if (fi->hfinfo->id == sinfo->target) {
- if (sinfo->packet_len >= start_of_data + bytes_length) {
- barray = g_byte_array_new();
- g_byte_array_append(barray, sinfo->packet_data + start_of_data, bytes_length);
- g_array_append_val(sinfo->result.array, barray);
+ if (bytes_offset < 0) {
+ /* Handle negative byte offsets */
+ bytes_offset = fi->length + bytes_offset;
+ if (bytes_offset < 0) {
+ goto FAIL;
+ }
+ }
+
+ /* Check to make sure offset exists for this field */
+ if (bytes_offset >= fi->length) {
+ goto FAIL;
}
+
+ pkt_end = fi->start + fi->length;
+ read_start = fi->start + bytes_offset;
+
+ /* Check to make sure entire length requested is inside field */
+ if (pkt_end < read_start + bytes_length) {
+ goto FAIL;
+ }
+
+ barray = g_byte_array_new();
+ g_byte_array_append(barray, sinfo->packet_data + read_start, bytes_length);
+ g_array_append_val(sinfo->result.array, barray);
}
+ FAIL:
return FALSE; /* FALSE = do not end traversal of GNode tree */
}
diff --git a/dfilter.h b/dfilter.h
index c5ad3c4055..bb4d5d868e 100644
--- a/dfilter.h
+++ b/dfilter.h
@@ -1,7 +1,7 @@
/* dfilter.h
* Definitions for display filters
*
- * $Id: dfilter.h,v 1.12 1999/10/11 14:58:01 gram Exp $
+ * $Id: dfilter.h,v 1.13 1999/10/12 04:21:11 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -61,6 +61,6 @@ void dfilter_destroy(dfilter *df);
dfilter* dfilter_compile(gchar* dfilter_text);
/* Apply compiled dfilter to a proto_tree */
-gboolean dfilter_apply(dfilter *df, proto_tree *ptree, const guint8* pd, guint len);
+gboolean dfilter_apply(dfilter *df, proto_tree *ptree, const guint8* pd);
#endif /* ! __DFILTER_H__ */
diff --git a/file.c b/file.c
index 0d87394374..1b7abe7e2a 100644
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
- * $Id: file.c,v 1.106 1999/10/11 14:58:02 gram Exp $
+ * $Id: file.c,v 1.107 1999/10/12 04:21:11 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -627,7 +627,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf
protocol_tree = proto_tree_create_root();
dissect_packet(buf, fdata, protocol_tree);
if( DFILTER_CONTAINS_FILTER(cf->dfcode) )
- fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd, fdata->cap_len);
+ fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
else
fdata->passed_dfilter = TRUE;
/* Apply color filters. */
@@ -639,7 +639,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf
continue;
}
if(dfilter_apply(color_filter(cf,crow)->c_colorfilter, protocol_tree,
- cf->pd, fdata->cap_len)){
+ cf->pd)){
color = crow;
break;
}
@@ -752,7 +752,7 @@ wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
if (DFILTER_CONTAINS_FILTER(cf->rfcode)) {
protocol_tree = proto_tree_create_root();
dissect_packet(buf, fdata, protocol_tree);
- passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd, fdata->cap_len);
+ passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
proto_tree_free(protocol_tree);
}
}
diff --git a/proto.c b/proto.c
index cefed2863f..4550814078 100644
--- a/proto.c
+++ b/proto.c
@@ -1,7 +1,7 @@
/* proto.c
* Routines for protocol tree
*
- * $Id: proto.c,v 1.33 1999/10/11 17:02:06 deniel Exp $
+ * $Id: proto.c,v 1.34 1999/10/12 04:21:12 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -725,6 +725,59 @@ proto_registrar_is_protocol(int n)
return FALSE;
}
+/* Returns length of field.
+ * 0 means undeterminable at time of registration
+ * -1 means the field is not registered. */
+gint
+proto_registrar_get_length(int n)
+{
+ struct header_field_info *hfinfo;
+
+ hfinfo = find_hfinfo_record(n);
+ if (!hfinfo)
+ return -1;
+
+ switch (hfinfo->type) {
+ case FT_TEXT_ONLY: /* not filterable */
+ case NUM_FIELD_TYPES: /* satisfy picky compilers */
+ return -1;
+
+ case FT_NONE:
+ case FT_BYTES:
+ case FT_BOOLEAN:
+ case FT_STRING:
+ case FT_DOUBLE:
+ case FT_ABSOLUTE_TIME:
+ case FT_RELATIVE_TIME:
+ return 0;
+
+ case FT_UINT8:
+ case FT_VALS_UINT8:
+ return 1;
+
+ case FT_UINT16:
+ case FT_VALS_UINT16:
+ return 2;
+
+ case FT_VALS_UINT24:
+ return 3;
+
+ case FT_UINT32:
+ case FT_VALS_UINT32:
+ case FT_IPXNET:
+ case FT_IPv4:
+ return 4;
+
+ case FT_ETHER:
+ return 6;
+
+ case FT_IPv6:
+ return 128;
+ }
+ g_assert_not_reached();
+ return -1;
+}
+
/* Looks for a protocol or a field in a proto_tree. Returns TRUE if
* it exists anywhere, or FALSE if it exists nowhere. */
gboolean
diff --git a/proto.h b/proto.h
index f60466a9e4..13d627a8b9 100644
--- a/proto.h
+++ b/proto.h
@@ -1,7 +1,7 @@
/* proto.h
* Definitions for protocol display
*
- * $Id: proto.h,v 1.15 1999/10/11 17:02:08 deniel Exp $
+ * $Id: proto.h,v 1.16 1999/10/12 04:21:13 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -183,6 +183,11 @@ int proto_registrar_get_parent(int n);
/* Is item #n a protocol? */
gboolean proto_registrar_is_protocol(int n);
+/* Get length of registered field according to field type.
+ * 0 means undeterminable at registration time.
+ * -1 means unknown field */
+gint proto_registrar_get_length(int n);
+
/* 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);