/* dfilter-grammar.y
* Parser for display filters
*
- * $Id: dfilter-grammar.y,v 1.18 1999/09/15 06:13:19 gram Exp $
+ * $Id: dfilter-grammar.y,v 1.37 1999/11/15 06:32:11 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
#endif
#include <string.h>
+#include <errno.h>
+#include <math.h>
#ifndef _STDLIB_H
#include <stdlib.h>
static GNode* dfilter_mknode_unary(int operand, GNode *n2);
static GNode* dfilter_mknode_numeric_variable(gint id);
static GNode* dfilter_mknode_numeric_value(guint32 val);
+static GNode* dfilter_mknode_floating_variable(gint id);
+static GNode* dfilter_mknode_floating_value(double val);
static GNode* dfilter_mknode_ether_value(gchar*);
static GNode* dfilter_mknode_ether_variable(gint id);
static GNode* dfilter_mknode_ipxnet_value(guint32);
static GNode* dfilter_mknode_ipxnet_variable(gint id);
-static GNode* dfilter_mknode_ipv4_value(char *host);
+static GNode* dfilter_mknode_ipv4_value(char *host, int nmask_bits);
static GNode* dfilter_mknode_ipv4_variable(gint id);
+static GNode* dfilter_mknode_ipv6_value(char *host);
+static GNode* dfilter_mknode_ipv6_variable(gint id);
static GNode* dfilter_mknode_existence(gint id);
static GNode* dfilter_mknode_bytes_value(GByteArray *barray);
static GNode* dfilter_mknode_bytes_variable(gint id, gint offset, guint length);
-static guint32 string_to_value(char *s);
+static guint32 string_to_guint32(char *s, gboolean *success);
+static double string_to_double(char *s, gboolean *success);
static int ether_str_to_guint8_array(const char *s, guint8 *mac);
+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.
*/
-dfilter *global_df = NULL;;
-
-/* list of GNodes allocated during parsing. If the parsing fails, we'll
- * use this list to free all the GNodes. If the parsing succeeds, we'll
- * just clear this list since dfilter_clear_filter() will take care of
- * freeing the GNodes when they're no longer needed.
- */
-GSList *gnode_slist = NULL;
+dfilter *global_df = NULL;
%}
%type <node> statement expression relation
%type <node> numeric_value numeric_variable
+%type <node> floating_value floating_variable
%type <node> ether_value ether_variable
%type <node> ipxnet_value ipxnet_variable
%type <node> ipv4_value ipv4_variable
+%type <node> ipv6_value ipv6_variable
%type <node> variable_name
%type <node> bytes_value bytes_variable
%token <variable> T_FT_UINT8
%token <variable> T_FT_UINT16
%token <variable> T_FT_UINT32
+%token <variable> T_FT_INT8
+%token <variable> T_FT_INT16
+%token <variable> T_FT_INT32
%token <variable> T_FT_ETHER
%token <variable> T_FT_IPv4
+%token <variable> T_FT_IPv6
%token <variable> T_FT_NONE
%token <variable> T_FT_BYTES
%token <variable> T_FT_BOOLEAN
%token <variable> T_FT_STRING
%token <variable> T_FT_IPXNET
+%token <variable> T_FT_DOUBLE
%token <string> T_VAL_UNQUOTED_STRING
%token <string> T_VAL_BYTE_STRING
-%token <string> T_VAL_NUMBER_STRING
%token <byte_range> T_VAL_BYTE_RANGE
%token <operand> TOK_AND TOK_OR TOK_NOT TOK_XOR
%token <operand> TOK_EQ TOK_NE TOK_GT TOK_GE TOK_LT TOK_LE
-%token <operand> TOK_TRUE TOK_FALSE
+%expect 4
%left TOK_AND
-%left TOK_OR
-%left TOK_XOR
+%left TOK_OR TOK_XOR
%nonassoc TOK_NOT
%%
{
global_df->dftree = $1;
}
- | /* NULL */ { global_df->dftree = NULL; }
+ | /* NULL */ { if (global_df != NULL) global_df->dftree = NULL; }
;
expression: '(' expression ')' { $$ = $2; }
| TOK_NOT expression { $$ = dfilter_mknode_unary(TOK_NOT, $2); }
| relation { $$ = $1; }
| variable_name { $$ = $1; }
+ | expression error { YYABORT; }
;
relation: numeric_variable numeric_relation numeric_value
$$ = dfilter_mknode_join($1, relation, $2, $3);
}
+ | floating_variable numeric_relation floating_value
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | floating_variable numeric_relation floating_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+
| ether_variable equality_relation ether_value
{
$$ = dfilter_mknode_join($1, relation, $2, $3);
$$ = dfilter_mknode_join($1, relation, $2, $3);
}
+ | ipv6_variable equality_relation ipv6_value
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | ipv6_variable equality_relation ipv6_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+
| 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 "
+ "%s supplied.",
+ dfilter_get_variable_abbrev($1),
+ a_len, plurality(a_len, "", "s"),
+ b_len, plurality(b_len, "", "s"),
+ plurality(b_len, "was", "were"));
+ 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);
}
;
-numeric_value: T_VAL_NUMBER_STRING
+numeric_value: T_VAL_UNQUOTED_STRING
{
- $$ = dfilter_mknode_numeric_value(string_to_value($1));
+ gboolean success;
+ $$ = dfilter_mknode_numeric_value(string_to_guint32($1, &success));
g_free($1);
+ if (!success) {
+ YYERROR;
+ }
}
;
}
;
-ipxnet_value: T_VAL_NUMBER_STRING
+ipxnet_value: T_VAL_UNQUOTED_STRING
{
- $$ = dfilter_mknode_ipxnet_value(string_to_value($1));
+ gboolean success;
+ $$ = dfilter_mknode_ipxnet_value(string_to_guint32($1, &success));
g_free($1);
+ if (!success) {
+ YYERROR;
+ }
+ }
+ ;
+
+floating_value: T_VAL_UNQUOTED_STRING
+ {
+ gboolean success;
+ $$ = dfilter_mknode_floating_value(string_to_double($1, &success));
+ g_free($1);
+ if (!success) {
+ YYERROR;
+ }
+ }
+
+ | T_VAL_BYTE_STRING
+ {
+ /* e.g., 0.0, 0.1, 0.01 ... */
+ gboolean success;
+ $$ = dfilter_mknode_floating_value(string_to_double($1, &success));
+ g_free($1);
+ if (!success) {
+ YYERROR;
+ }
}
;
ipv4_value: T_VAL_UNQUOTED_STRING
+ {
+ $$ = dfilter_mknode_ipv4_value($1, 32);
+ g_free($1);
+ if ($$ == NULL) {
+ YYERROR;
+ }
+ }
+
+ | T_VAL_BYTE_STRING
+ {
+ $$ = dfilter_mknode_ipv4_value($1, 32);
+ g_free($1);
+ if ($$ == NULL) {
+ YYERROR;
+ }
+ }
+
+ | T_VAL_UNQUOTED_STRING '/' T_VAL_UNQUOTED_STRING
+ {
+ gboolean success;
+ guint32 nmask_bits;
+
+ nmask_bits = string_to_guint32($3, &success);
+ if (!success) {
+ g_free($1);
+ g_free($3);
+ YYERROR;
+ }
+
+ if (nmask_bits > 32) {
+ dfilter_fail("The number of netmask bits in \"%s/%s\" should "
+ "be between 0 and 32.", $1, $3);
+ g_free($1);
+ g_free($3);
+ YYERROR;
+ }
+
+ $$ = dfilter_mknode_ipv4_value($1, nmask_bits);
+ g_free($1);
+ g_free($3);
+ if ($$ == NULL) {
+ YYERROR;
+ }
+ }
+
+ | T_VAL_BYTE_STRING '/' T_VAL_UNQUOTED_STRING
+ {
+ gboolean success;
+ guint32 nmask_bits;
+
+ nmask_bits = string_to_guint32($3, &success);
+ if (!success) {
+ g_free($1);
+ g_free($3);
+ YYERROR;
+ }
+
+ if (nmask_bits > 32) {
+ dfilter_fail("The number of netmask bits in \"%s/%s\" should "
+ "be between 0 and 32.", $1, $3);
+ g_free($1);
+ g_free($3);
+ YYERROR;
+ }
+ $$ = dfilter_mknode_ipv4_value($1, nmask_bits);
+ g_free($1);
+ g_free($3);
+ if ($$ == NULL) {
+ YYERROR;
+ }
+ }
+ ;
+
+ipv6_value: T_VAL_UNQUOTED_STRING
{
- $$ = dfilter_mknode_ipv4_value($1);
+ $$ = dfilter_mknode_ipv6_value($1);
g_free($1);
+ if ($$ == NULL) {
+ YYERROR;
+ }
}
| T_VAL_BYTE_STRING
{
- $$ = dfilter_mknode_ipv4_value($1);
+ $$ = dfilter_mknode_ipv6_value($1);
g_free($1);
+ if ($$ == NULL) {
+ YYERROR;
+ }
}
;
$$ = dfilter_mknode_bytes_value(barray);
g_free($1);
}
- ;
+ | T_VAL_UNQUOTED_STRING
+ {
+ gboolean success;
+ guint32 val32;
+ guint8 val8;
+ GByteArray *barray;
+
+ val32 = string_to_guint32($1, &success);
+ if (!success) {
+ g_free($1);
+ YYERROR;
+ }
+ 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);
+ g_free($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); }
| T_FT_UINT32 { $$ = dfilter_mknode_numeric_variable($1.id); }
+ | T_FT_INT8 { $$ = dfilter_mknode_numeric_variable($1.id); }
+ | T_FT_INT16 { $$ = dfilter_mknode_numeric_variable($1.id); }
+ | T_FT_INT32 { $$ = dfilter_mknode_numeric_variable($1.id); }
;
ether_variable: T_FT_ETHER { $$ = dfilter_mknode_ether_variable($1.id); }
;
+floating_variable: T_FT_DOUBLE { $$ = dfilter_mknode_floating_variable($1.id); }
+ ;
+
ipxnet_variable: T_FT_IPXNET { $$ = dfilter_mknode_ipxnet_variable($1.id); }
;
ipv4_variable: T_FT_IPv4 { $$ = dfilter_mknode_ipv4_variable($1.id); }
;
+ipv6_variable: T_FT_IPv6 { $$ = dfilter_mknode_ipv6_variable($1.id); }
+ ;
+
variable_name: any_variable_type
{
GNode *variable;
}
;
-any_variable_type: T_FT_UINT8 { $$ = $1; }
- | T_FT_UINT16 { $$ = $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; }
- | T_FT_STRING { $$ = $1; }
+any_variable_type: T_FT_UINT8 { $$ = $1; }
+ | T_FT_UINT16 { $$ = $1; }
+ | T_FT_UINT32 { $$ = $1; }
+ | T_FT_INT8 { $$ = $1; }
+ | T_FT_INT16 { $$ = $1; }
+ | T_FT_INT32 { $$ = $1; }
+ | T_FT_DOUBLE { $$ = $1; }
+ | T_FT_ETHER { $$ = $1; }
+ | T_FT_IPv4 { $$ = $1; }
+ | T_FT_IPv6 { $$ = $1; }
+ | T_FT_IPXNET { $$ = $1; }
+ | T_FT_NONE { $$ = $1; }
+ | T_FT_BYTES { $$ = $1; }
+ | T_FT_BOOLEAN { $$ = $1; }
+ | T_FT_STRING { $$ = $1; }
;
numeric_relation: TOK_EQ { $$ = TOK_EQ; }
g_node_append(gnode_root, n1);
g_node_append(gnode_root, n2);
- gnode_slist = g_slist_append(gnode_slist, gnode_root);
return gnode_root;
}
gnode_root = g_node_new(node_root);
g_node_append(gnode_root, n2);
- gnode_slist = g_slist_append(gnode_slist, gnode_root);
return gnode_root;
}
node->value.variable = id;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
return gnode;
}
node->value.variable = id;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_floating_variable(gint id)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
+ node->ntype = variable;
+ node->elem_size = sizeof(double);
+ node->fill_array_func = fill_array_floating_variable;
+ node->check_relation_func = check_relation_floating;
+ node->value.variable = id;
+ gnode = g_node_new(node);
+
return gnode;
}
node->value.variable = id;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
return gnode;
}
node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
- node->elem_size = sizeof(guint32);
- node->fill_array_func = fill_array_numeric_variable; /* cheating ! */
- node->check_relation_func = check_relation_numeric; /* cheating ! */
+ node->elem_size = sizeof(ipv4_addr);
+ node->fill_array_func = fill_array_ipv4_variable;
+ node->check_relation_func = check_relation_ipv4;
+ node->value.variable = id;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_ipv6_variable(gint id)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
+ node->ntype = variable;
+ node->elem_size = 16;
+ node->fill_array_func = fill_array_ipv6_variable;
+ node->check_relation_func = check_relation_ipv6;
node->value.variable = id;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
return gnode;
}
node->length = length;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
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)
{
node->value.numeric = val;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_floating_value(double val)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
+ node->ntype = floating;
+ node->elem_size = sizeof(double);
+ node->fill_array_func = fill_array_floating_value;
+ node->check_relation_func = check_relation_floating;
+ node->value.floating = val;
+ gnode = g_node_new(node);
+
return gnode;
}
if (!ether_str_to_guint8_array(byte_string, &node->value.ether[0])) {
/* Rather than free the mem_chunk allocation, let it
- * stay. It will be cleaned up in the next call to
- * dfilter_clear() */
- dfilter_error_msg = &dfilter_error_msg_buf[0];
- snprintf(dfilter_error_msg, sizeof(dfilter_error_msg_buf),
- "\"%s\" is not a valid hardware address.", byte_string);
+ * stay. It will be cleaned up when "dfilter_compile()"
+ * calls "dfilter_destroy()". */
+ dfilter_fail("\"%s\" is not a valid hardware address.",
+ byte_string);
return NULL;
}
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
return gnode;
}
node->value.numeric = ipx_net_val;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
return gnode;
}
+/* Returns NULL on bad parse of IP value */
static GNode*
-dfilter_mknode_ipv4_value(char *host)
+dfilter_mknode_ipv4_value(char *host, int nmask_bits)
{
dfilter_node *node;
GNode *gnode;
+ guint32 addr;
node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = numeric;
- node->elem_size = sizeof(guint32);
- node->fill_array_func = fill_array_numeric_value; /* cheating ! */
- node->check_relation_func = check_relation_numeric; /* cheating ! */
- node->value.numeric = get_host_ipaddr(host);
- node->value.numeric = htonl(node->value.numeric);
+ node->elem_size = sizeof(ipv4_addr);
+ node->fill_array_func = fill_array_ipv4_value;
+ node->check_relation_func = check_relation_ipv4;
+ if (!get_host_ipaddr(host, &addr)) {
+ /* Rather than free the mem_chunk allocation, let it
+ * stay. It will be cleaned up when "dfilter_compile()"
+ * calls "dfilter_destroy()". */
+ dfilter_fail("\"%s\" isn't a valid host name or IP address.",
+ host);
+ return NULL;
+ }
+ ipv4_addr_set_host_order_addr(&node->value.ipv4, addr);
+ ipv4_addr_set_netmask_bits(&node->value.ipv4, nmask_bits);
+
gnode = g_node_new(node);
+ return gnode;
+}
+
+/* Returns NULL on bad parse of IPv6 value */
+static GNode*
+dfilter_mknode_ipv6_value(char *host)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
+ node->ntype = ipv6;
+ node->elem_size = 16;
+ node->fill_array_func = fill_array_ipv6_value;
+ node->check_relation_func = check_relation_ipv6;
- gnode_slist = g_slist_append(gnode_slist, gnode);
+ if (!get_host_ipaddr6(host, (struct e_in6_addr*)&node->value.ipv6[0])) {
+ /* Rather than free the mem_chunk allocation, let it
+ * stay. It will be cleaned up when "dfilter_compile()"
+ * calls "dfilter_destroy()". */
+ dfilter_fail("\"%s\" isn't a valid IPv6 address.",
+ host);
+ return NULL;
+ }
+
+ gnode = g_node_new(node);
return gnode;
}
node->length = barray->len;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
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)
+string_to_guint32(char *s, gboolean *success)
{
char *endptr;
guint32 val;
val = strtoul(s, &endptr, 0);
- /* I should probably check errno here */
+ *success = TRUE;
+ if (endptr == s || *endptr != '\0') {
+ /* This isn't a valid number. */
+ dfilter_fail("\"%s\" is not a valid number.", s);
+ *success = FALSE;
+ }
+ if (errno == ERANGE) {
+ *success = FALSE;
+ if (val == ULONG_MAX) {
+ dfilter_fail("\"%s\" causes an integer overflow.", s);
+ }
+ else {
+ dfilter_fail("\"%s\" is not an integer.", s);
+ }
+ }
return (guint32)val;
}
+
+static double
+string_to_double(char *s, gboolean *success)
+{
+ char *endptr = NULL;
+ double retval;
+
+ retval = strtod(s, &endptr);
+ *success = TRUE;
+
+ if (endptr == s) {
+ dfilter_fail("\"%s\" is not a valid floating-point number.", s);
+ *success = FALSE;
+ }
+
+ if (errno == ERANGE) {
+ *success = FALSE;
+ if (retval == 0) {
+ dfilter_fail("\"%s\" causes a floating-point underflow.", s);
+ }
+ else if (retval == HUGE_VAL) {
+ dfilter_fail("\"%s\" causes a floating-point overflow.", s);
+ }
+ else {
+ dfilter_fail("\"%s\" is not a valid floating-point.", s);
+ }
+ }
+ return retval;
+}
static GNode*
dfilter_mknode_existence(gint id)
node->value.variable = id;
gnode = g_node_new(node);
- gnode_slist = g_slist_append(gnode_slist, gnode);
return gnode;
}
return 1; /* read exactly 6 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 %s supplied.",
+ dfilter_get_variable_abbrev(gnode),
+ reg_len, plurality(reg_len, "", "s"),
+ a_len, plurality(a_len, "", "s"),
+ plurality(a_len, "was", "were"));
+ return 0;
+ }
+ }
+ return 1;
+}