/* dfilter-grammar.y
* Parser for display filters
*
- * $Id: dfilter-grammar.y,v 1.7 1999/08/12 15:10:48 gram Exp $
+ * $Id: dfilter-grammar.y,v 1.14 1999/08/20 21:19:27 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#define yylex dfilter_lex
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
# include <netinet/in.h>
#endif
+#ifdef NEED_SNPRINTF_H
+# ifdef HAVE_STDARG_H
+# include <stdarg.h>
+# else
+# include <varargs.h>
+# endif
+# include "snprintf.h"
+#endif
+
#ifndef __GLIB_H__
#include <glib.h>
#endif
-#include <string.h> /* during testing */
+#include <string.h>
#ifndef _STDLIB_H
#include <stdlib.h>
#include "dfilter.h"
#endif
+#include "dfilter-int.h"
+
#ifndef __RESOLV_H__
#include "resolv.h"
#endif
-void dfilter_yacc_init(void);
static GNode* dfilter_mknode_join(GNode *n1, enum node_type ntype, int operand, GNode *n2);
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_ether_value(guint8*);
+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_boolean_variable(gint id);
static guint32 string_to_value(char *s);
+static int ether_str_to_guint8_array(const char *s, guint8 *mac);
-/* space for dfilter_nodes */
-GMemChunk *gmc_dfilter_nodes = NULL;
-
-/* this is how we pass display filter tree (dfcode) back to calling routine */
-GNode *dfilter_tree = NULL;
-
-/* list of byte arrays we allocate during parse. We can traverse this list
- * faster than the tree when we go back and free the byte arrays */
-GSList *dfilter_list_byte_arrays = NULL;
-
-/* In dfilter-scanner.l */
-GByteArray* byte_str_to_guint8_array(const char *s);
+/* This is the dfilter we're currently processing. It's how
+ * dfilter_compile communicates with us.
+ */
+dfilter *global_df = NULL;;
%}
gint operand; /* logical, relation, alternation */
gint variable;
GNode* node;
- gchar* id;
- GByteArray* bytes;
- guint8 ether[6];
+ gchar* string;
struct {
gint offset;
guint length;
%token <variable> T_FT_STRING
%token <variable> T_FT_IPXNET
-%token <id> T_VAL_UNQUOTED_STRING
-%token <ether> T_VAL_ETHER
-%token <bytes> T_VAL_BYTES
+%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
statement: expression
{
- dfilter_tree = $1;
+ global_df->dftree = $1;
}
- | /* NULL */ { dfilter_tree = NULL; }
+ | /* NULL */ { global_df->dftree = NULL; }
;
expression: '(' expression ')' { $$ = $2; }
;
-numeric_value: T_VAL_UNQUOTED_STRING
+numeric_value: T_VAL_NUMBER_STRING
{
$$ = dfilter_mknode_numeric_value(string_to_value($1));
g_free($1);
}
;
-ether_value: T_VAL_ETHER
- {
- $$ = dfilter_mknode_ether_value($1);
- }
- ;
-
-ipxnet_value: T_VAL_UNQUOTED_STRING
- {
- $$ = dfilter_mknode_ipxnet_value(string_to_value($1));
+ether_value: T_VAL_BYTE_STRING
+ {
+ $$ = dfilter_mknode_ether_value($1);
+ g_free($1);
+ if ($$ == NULL) {
+ YYERROR;
}
+ }
;
-ipv4_value: T_VAL_UNQUOTED_STRING
+ipxnet_value: T_VAL_NUMBER_STRING
{
- $$ = dfilter_mknode_ipv4_value($1);
+ $$ = dfilter_mknode_ipxnet_value(string_to_value($1));
g_free($1);
}
;
-bytes_value: T_VAL_BYTES
- { /* 2 - 5, or > 6 bytes */
- $$ = dfilter_mknode_bytes_value($1);
- }
+ipv4_value: T_VAL_UNQUOTED_STRING
+ {
+ $$ = dfilter_mknode_ipv4_value($1);
+ g_free($1);
+ }
+
+ | T_VAL_BYTE_STRING
+ {
+ $$ = dfilter_mknode_ipv4_value($1);
+ g_free($1);
+ }
+ ;
- | T_VAL_UNQUOTED_STRING
- { /* one or 4 bytes */
+bytes_value: T_VAL_BYTE_STRING
+ {
GByteArray *barray;
- /* the next function appends to dfilter_list_byte_arrays for me */
+ /* the next function appends to list_of_byte_arrays for me */
barray = byte_str_to_guint8_array($1);
$$ = dfilter_mknode_bytes_value(barray);
g_free($1);
}
-
- | T_VAL_ETHER
- { /* 6 bytes */
- GByteArray *barray = g_byte_array_new();
-
- dfilter_list_byte_arrays = g_slist_append(dfilter_list_byte_arrays, barray);
- g_byte_array_append(barray, $1, 6);
- $$ = dfilter_mknode_bytes_value(barray);
- }
;
%%
-void
-dfilter_yacc_init(void)
-{
- if (gmc_dfilter_nodes)
- g_mem_chunk_destroy(gmc_dfilter_nodes);
-
- gmc_dfilter_nodes = g_mem_chunk_new("gmc_dfilter_nodes",
- sizeof(dfilter_node), 50 * sizeof(dfilter_node),
- G_ALLOC_ONLY);
-
- if (dfilter_list_byte_arrays) {
- /* clear the byte arrays */
- g_slist_free(dfilter_list_byte_arrays);
- }
-
-}
-
-void
-dfilter_yacc_cleanup(void)
-{
- if (gmc_dfilter_nodes)
- g_mem_chunk_destroy(gmc_dfilter_nodes);
-}
-
-
static GNode*
dfilter_mknode_join(GNode *n1, enum node_type ntype, int operand, GNode *n2)
{
dfilter_node *node_root;
GNode *gnode_root;
- node_root = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node_root = g_mem_chunk_alloc(global_df->node_memchunk);
node_root->ntype = ntype;
node_root->elem_size = 0;
node_root->fill_array_func = NULL;
dfilter_node *node_root;
GNode *gnode_root;
- node_root = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node_root = g_mem_chunk_alloc(global_df->node_memchunk);
node_root->ntype = logical;
node_root->value.logical = operand;
node_root->elem_size = 0;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ 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;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(guint8) * 6;
node->fill_array_func = fill_array_ether_variable;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(guint8) * 4;
node->fill_array_func = fill_array_numeric_variable; /* cheating ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ 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 ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(GByteArray*);
node->fill_array_func = fill_array_bytes_variable;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(guint32);
node->fill_array_func = fill_array_boolean_variable; /* cheating ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ 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;
return gnode;
}
+/* Returns NULL on bad parse of ETHER value */
static GNode*
-dfilter_mknode_ether_value(guint8 *ether_bytes)
+dfilter_mknode_ether_value(gchar *byte_string)
{
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = ether;
node->elem_size = sizeof(guint8) * 6;
node->fill_array_func = fill_array_ether_value;
node->check_relation_func = check_relation_ether;
- memcpy(&node->value.ether, ether_bytes, 6);
+ 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);
+ return NULL;
+ }
gnode = g_node_new(node);
return gnode;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = ipxnet;
node->elem_size = sizeof(guint8) * 4;
node->fill_array_func = fill_array_numeric_value; /* cheating ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ 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 ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = bytes;
node->elem_size = sizeof(GByteArray*);
node->fill_array_func = fill_array_bytes_value;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = numeric;
node->elem_size = sizeof(guint32);
node->fill_array_func = fill_array_boolean_value;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = existence;
node->elem_size = sizeof(guint32);
node->fill_array_func = NULL;
return gnode;
}
+
+/* converts a string representing an ether HW address
+ * to a guint8 array.
+ *
+ * Returns 0 on failure, 1 on success.
+ */
+static int
+ether_str_to_guint8_array(const char *s, guint8 *mac)
+{
+ char ether_str[18]; /* 2+1+2+1+2+1+2+1+2+1+2 + 1 */
+ char *p, *str;
+ int i = 0;
+
+ if (strlen(s) > 17) {
+ return 0;
+ }
+ strcpy(ether_str, s); /* local copy of string */
+ str = ether_str;
+ while ((p = strtok(str, "-:."))) {
+ /* catch short strings with too many hex bytes: 0.0.0.0.0.0.0 */
+ if (i > 5) {
+ return 0;
+ }
+ mac[i] = (guint8) strtoul(p, NULL, 16);
+ i++;
+ /* subsequent calls to strtok() require NULL as arg 1 */
+ str = NULL;
+ }
+ if (i != 6)
+ return 0; /* failed to read 6 hex pairs */
+ else
+ return 1; /* read exactly 6 hex pairs */
+}
+