aboutsummaryrefslogtreecommitdiffstats
path: root/dfilter-grammar.y
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>1999-07-07 22:52:57 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>1999-07-07 22:52:57 +0000
commit07f42b5b31f9523deeb147226521f77a2c8dd797 (patch)
treec720d2a42f11c9d14ac1a161eb785b438c2c4b14 /dfilter-grammar.y
parentfba49cfe85d4b23ebbffa97fae126a379e913ecd (diff)
Created a new protocol tree implementation and a new display filter
mechanism that is built into ethereal. Wiretap is now used to read all file formats. Libpcap is used only for capturing. svn path=/trunk/; revision=342
Diffstat (limited to 'dfilter-grammar.y')
-rw-r--r--dfilter-grammar.y640
1 files changed, 640 insertions, 0 deletions
diff --git a/dfilter-grammar.y b/dfilter-grammar.y
new file mode 100644
index 0000000000..83490243f8
--- /dev/null
+++ b/dfilter-grammar.y
@@ -0,0 +1,640 @@
+%{
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifndef __GLIB_H__
+#include <glib.h>
+#endif
+
+#include <string.h> /* during testing */
+
+#ifndef _STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifndef __PROTO_H__
+#include "proto.h"
+#endif
+
+#ifndef __PACKET_H__
+#include "packet.h"
+#endif
+
+#ifndef __DFILTER_H__
+#include "dfilter.h"
+#endif
+
+#ifndef __RESOLV_H__
+#include "resolv.h"
+#endif
+
+void dfilter_yacc_init(void);
+static void dfilter_print_parse_tree(GNode *gnode);
+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(char *a, char *b, char *c, char *d, char *e, char *f);
+static GNode* dfilter_mknode_ether_variable(gint id);
+static GNode* dfilter_mknode_ipv4_value(char *host);
+static GNode* dfilter_mknode_ipv4_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, gint length);
+static GNode* dfilter_mknode_boolean_value(gint truth_value);
+static GNode* dfilter_mknode_boolean_variable(gint id);
+
+static guint32 string_to_value(char *s);
+
+/* 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;
+
+%}
+
+%union {
+ gint operand; /* logical, relation, alternation */
+ gint variable;
+ GNode* node;
+ gchar* id;
+ GByteArray* bytes;
+}
+
+%type <node> statement expression relation
+%type <node> numeric_value numeric_variable
+%type <node> ether_value ether_variable
+%type <node> ipv4_value ipv4_variable
+%type <node> protocol_name
+%type <node> bytes_value bytes_variable
+%type <node> boolean_value boolean_variable
+
+%type <operand> numeric_relation
+%type <operand> ether_relation
+%type <operand> bytes_relation
+%type <operand> boolean_relation
+
+%type <bytes> byte_range
+%type <variable> any_variable_type
+%type <operand> exists_operand
+
+%token <variable> T_FT_UINT8
+%token <variable> T_FT_UINT16
+%token <variable> T_FT_UINT32
+%token <variable> T_FT_ETHER
+%token <variable> T_FT_IPv4
+%token <variable> T_FT_NONE
+%token <variable> T_FT_BYTES
+%token <variable> T_FT_BOOLEAN
+%token <variable> T_FT_STRING
+
+%token <id> T_VAL_ID
+
+%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_EXIST TOK_EXISTS
+%token <operand> TOK_TRUE TOK_FALSE
+
+%type <operand> type_eq
+%type <operand> type_ne
+%type <operand> type_gt
+%type <operand> type_ge
+%type <operand> type_lt
+%type <operand> type_le
+
+%left TOK_AND
+%left TOK_OR
+%left TOK_XOR
+%nonassoc TOK_NOT
+
+%%
+
+statement: expression
+ {
+ dfilter_tree = $1;
+ }
+ | /* NULL */ { dfilter_tree = NULL; }
+ ;
+
+expression: '(' expression ')' { $$ = $2; }
+ | expression TOK_AND expression { $$ = dfilter_mknode_join($1, logical, $2, $3); }
+ | expression TOK_OR expression { $$ = dfilter_mknode_join($1, logical, $2, $3); }
+ | TOK_NOT expression { $$ = dfilter_mknode_unary(TOK_NOT, $2); }
+ | relation { $$ = $1; }
+ | protocol_name { $$ = $1; }
+ ;
+
+relation: numeric_variable numeric_relation numeric_value
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | numeric_value numeric_relation numeric_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | numeric_variable numeric_relation numeric_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+
+ | ether_variable ether_relation ether_value
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | ether_value ether_relation ether_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | ether_variable ether_relation ether_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+
+
+ | ipv4_variable numeric_relation ipv4_value
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | ipv4_value numeric_relation ipv4_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | ipv4_variable numeric_relation ipv4_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+
+ | bytes_variable bytes_relation bytes_value
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | bytes_value bytes_relation bytes_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | bytes_variable bytes_relation bytes_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+
+ | boolean_variable boolean_relation boolean_value
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | boolean_value boolean_relation boolean_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+ | boolean_variable boolean_relation boolean_variable
+ {
+ $$ = dfilter_mknode_join($1, relation, $2, $3);
+ }
+
+ | exists_operand any_variable_type { $$ = dfilter_mknode_existence($2); }
+
+ ;
+
+
+numeric_value: T_VAL_ID { $$ = dfilter_mknode_numeric_value(string_to_value($1)); }
+ ;
+
+ether_value: T_VAL_ID ':' T_VAL_ID ':' T_VAL_ID ':' T_VAL_ID ':' T_VAL_ID ':' T_VAL_ID
+ {
+ $$ = dfilter_mknode_ether_value($1, $3, $5, $7, $9, $11);
+ g_free($1);
+ g_free($3);
+ g_free($5);
+ g_free($7);
+ g_free($9);
+ g_free($11);
+ }
+ ;
+
+ipv4_value: T_VAL_ID { $$ = dfilter_mknode_ipv4_value($1); }
+ ;
+
+bytes_value: numeric_variable
+ | byte_range { $$ = dfilter_mknode_bytes_value($1); }
+ ;
+
+byte_range: T_VAL_ID ':' T_VAL_ID
+ {
+ GByteArray *barray = g_byte_array_new();
+ guint8 val;
+ char *endptr;
+
+ dfilter_list_byte_arrays = g_slist_append(dfilter_list_byte_arrays, barray);
+ val = (guint8) strtoul($1, &endptr, 16);
+ g_byte_array_append(barray, &val, 1);
+ val = (guint8) strtoul($3, &endptr, 16);
+ $$ = g_byte_array_append(barray, &val, 1);
+ }
+
+ | byte_range ':' T_VAL_ID
+ {
+ guint8 val;
+ char *endptr;
+
+ val = (guint8) strtoul($3, &endptr, 16);
+ $$ = g_byte_array_append($1, &val, 1);
+ }
+ ;
+
+boolean_value: TOK_TRUE { $$ = dfilter_mknode_boolean_value($1); }
+ | TOK_FALSE { $$ = dfilter_mknode_boolean_value($1); }
+ ;
+
+
+numeric_variable: T_FT_UINT8 { $$ = dfilter_mknode_numeric_variable($1); }
+ | T_FT_UINT16 { $$ = dfilter_mknode_numeric_variable($1); }
+ | T_FT_UINT32 { $$ = dfilter_mknode_numeric_variable($1); }
+ ;
+
+ether_variable: T_FT_ETHER { $$ = dfilter_mknode_ether_variable($1); }
+ ;
+
+ipv4_variable: T_FT_IPv4 { $$ = dfilter_mknode_ipv4_variable($1); }
+ ;
+
+protocol_name: T_FT_NONE { $$ = dfilter_mknode_existence($1); }
+ ;
+
+bytes_variable: any_variable_type '[' T_VAL_ID ':' T_VAL_ID ']'
+ {
+ $$ = dfilter_mknode_bytes_variable($1, string_to_value($3), string_to_value($5));
+ }
+ | any_variable_type '[' T_VAL_ID ']'
+ {
+ $$ = dfilter_mknode_bytes_variable($1, string_to_value($3), 0);
+ }
+ ;
+
+boolean_variable: T_FT_BOOLEAN { $$ = dfilter_mknode_boolean_variable($1); }
+ ;
+
+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_NONE { $$ = $1; }
+ | T_FT_BYTES { $$ = $1; }
+ | T_FT_BOOLEAN { $$ = $1; }
+ | T_FT_STRING { $$ = $1; }
+ ;
+
+numeric_relation: type_eq { $$ = $1; }
+ | type_ne { $$ = $1; }
+ | type_gt { $$ = $1; }
+ | type_ge { $$ = $1; }
+ | type_lt { $$ = $1; }
+ | type_le { $$ = $1; }
+ ;
+
+ether_relation: type_eq { $$ = $1; }
+ | type_ne { $$ = $1; }
+ ;
+
+bytes_relation: type_eq { $$ = $1; }
+ | type_ne { $$ = $1; }
+ | type_gt { $$ = $1; }
+ | type_lt { $$ = $1; }
+ ;
+
+boolean_relation: type_eq { $$ = $1; }
+ | type_ne { $$ = $1; }
+ ;
+
+exists_operand: TOK_EXIST { $$ = $1; }
+ | TOK_EXISTS { $$ = $1; }
+ | '?' { $$ = TOK_EXIST; }
+ ;
+
+type_eq: TOK_EQ { $$ = $1; }
+ | '=' '=' { $$ = TOK_EQ; }
+ ;
+
+type_ne: TOK_NE { $$ = $1; }
+ | '!' '=' { $$ = TOK_NE; }
+ ;
+
+type_gt: TOK_GT { $$ = $1; }
+ | '>' { $$ = TOK_GT; }
+ ;
+
+type_ge: TOK_GE { $$ = $1; }
+ | '>' '=' { $$ = TOK_GE; }
+ ;
+
+type_lt: TOK_LT { $$ = $1; }
+ | '<' { $$ = TOK_LT; }
+ ;
+
+type_le: TOK_LE { $$ = $1; }
+ | '<' '=' { $$ = TOK_LE; }
+ ;
+
+
+%%
+
+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->ntype = ntype;
+ node_root->elem_size = 0;
+ node_root->fill_array_func = NULL;
+ node_root->check_relation_func = NULL;
+ if (ntype == relation) {
+ node_root->value.relation = operand;
+ }
+ else if (ntype == logical) {
+ node_root->value.logical = operand;
+ }
+ else {
+ g_assert_not_reached();
+ }
+
+ gnode_root = g_node_new(node_root);
+ g_node_append(gnode_root, n1);
+ g_node_append(gnode_root, n2);
+
+ return gnode_root;
+}
+
+static GNode*
+dfilter_mknode_unary(int operand, GNode *n2)
+{
+ dfilter_node *node_root;
+ GNode *gnode_root;
+
+ node_root = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node_root->ntype = logical;
+ node_root->value.logical = operand;
+ node_root->elem_size = 0;
+ node_root->fill_array_func = NULL;
+ node_root->check_relation_func = NULL;
+
+ gnode_root = g_node_new(node_root);
+ g_node_append(gnode_root, n2);
+
+ return gnode_root;
+}
+
+
+static GNode*
+dfilter_mknode_numeric_variable(gint id)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = variable;
+ node->elem_size = sizeof(guint32);
+ node->fill_array_func = fill_array_numeric_variable;
+ node->check_relation_func = check_relation_numeric;
+ node->value.variable = id;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_ether_variable(gint id)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = variable;
+ node->elem_size = sizeof(guint8) * 6;
+ node->fill_array_func = fill_array_ether_variable;
+ node->check_relation_func = check_relation_ether;
+ node->value.variable = id;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_ipv4_variable(gint id)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ 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->value.variable = id;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_bytes_variable(gint id, gint offset, gint length)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = variable;
+ /*node->elem_size = length * sizeof(guint8);*/
+ node->elem_size = sizeof(GByteArray*);
+ node->fill_array_func = fill_array_bytes_variable;
+ node->check_relation_func = check_relation_bytes;
+ node->value.variable = id;
+ node->offset = offset;
+ node->length = length;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_boolean_variable(gint id)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = variable;
+ node->elem_size = sizeof(guint32);
+ node->fill_array_func = fill_array_boolean_variable; /* cheating ! */
+ node->check_relation_func = check_relation_boolean; /* cheating ! */
+ node->value.variable = id;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_numeric_value(guint32 val)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = numeric;
+ node->elem_size = sizeof(guint32);
+ node->fill_array_func = fill_array_numeric_value;
+ node->check_relation_func = check_relation_numeric;
+ node->value.numeric = val;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_ether_value(char *a, char *b, char *c, char *d, char *e, char *f)
+{
+ dfilter_node *node;
+ GNode *gnode;
+ char *endptr;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = ether;
+ node->elem_size = sizeof(guint8) * 6;
+ node->fill_array_func = fill_array_ether_value;
+ node->check_relation_func = check_relation_ether;
+
+ node->value.ether[0] = (guint8) strtoul(a, &endptr, 16);
+ node->value.ether[1] = (guint8) strtoul(b, &endptr, 16);
+ node->value.ether[2] = (guint8) strtoul(c, &endptr, 16);
+ node->value.ether[3] = (guint8) strtoul(d, &endptr, 16);
+ node->value.ether[4] = (guint8) strtoul(e, &endptr, 16);
+ node->value.ether[5] = (guint8) strtoul(f, &endptr, 16);
+
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_ipv4_value(char *host)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ 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);
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_bytes_value(GByteArray *barray)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = bytes;
+ /*node->elem_size = barray->len * sizeof(guint8);*/
+ node->elem_size = sizeof(GByteArray*);
+ node->fill_array_func = fill_array_bytes_value;
+ node->check_relation_func = check_relation_bytes;
+ node->value.bytes = barray;
+ node->offset = G_MAXINT;
+ node->length = barray->len;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static GNode*
+dfilter_mknode_boolean_value(gint truth_value)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = numeric;
+ node->elem_size = sizeof(guint32);
+ node->fill_array_func = fill_array_boolean_value;
+ node->check_relation_func = check_relation_boolean;
+ node->value.boolean = truth_value == TOK_TRUE ? TRUE : FALSE;
+ gnode = g_node_new(node);
+
+ return gnode;
+}
+
+static guint32
+string_to_value(char *s)
+{
+ char *endptr;
+ guint32 val;
+
+ val = strtoul(s, &endptr, 0);
+ /* I should probably check errno here */
+
+ return (guint32)val;
+}
+
+static GNode*
+dfilter_mknode_existence(gint id)
+{
+ dfilter_node *node;
+ GNode *gnode;
+
+ node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node->ntype = existence;
+ node->elem_size = sizeof(guint32);
+ node->fill_array_func = NULL;
+ node->check_relation_func = NULL;
+ node->value.variable = id;
+ gnode = g_node_new(node);
+
+ return gnode;
+}