More completely decode the frame control field of an FDDI frame.
[obnox/wireshark/wip.git] / dfilter-grammar.y
index dbdfa5d5989de6a8a3e66a29d9e3ae21001e6596..c8ab1c54b8d3e2ff45bd76f7b844cd3eb6e8edd3 100644 (file)
@@ -3,7 +3,7 @@
 /* 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>
@@ -25,8 +25,6 @@
  * 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);
@@ -83,19 +91,12 @@ static GNode* dfilter_mknode_boolean_value(gint truth_value);
 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;;
 
 %}
 
@@ -103,9 +104,7 @@ GByteArray* byte_str_to_guint8_array(const char *s);
        gint            operand;        /* logical, relation, alternation */
        gint            variable;
        GNode*          node;
-       gchar*          id;
-       GByteArray*     bytes;
-       guint8          ether[6];
+       gchar*          string;
        struct {
                gint    offset;
                guint   length;
@@ -138,9 +137,9 @@ GByteArray* byte_str_to_guint8_array(const char *s);
 %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
@@ -156,9 +155,9 @@ GByteArray* byte_str_to_guint8_array(const char *s);
 
 statement: expression
                {
-                       dfilter_tree = $1;
+                       global_df->dftree = $1;
                }
-       |       /* NULL */ { dfilter_tree = NULL; }
+       |       /* NULL */ { global_df->dftree = NULL; }
        ;
 
 expression:    '(' expression ')' { $$ = $2; }
@@ -228,55 +227,52 @@ relation: numeric_variable numeric_relation numeric_value
        ;
 
 
-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);
-       }
        ;
 
 
@@ -342,38 +338,13 @@ bytes_relation:           TOK_EQ { $$ = TOK_EQ; }
 
 %%
 
-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;
@@ -401,7 +372,7 @@ 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 = g_mem_chunk_alloc(global_df->node_memchunk);
        node_root->ntype = logical;
        node_root->value.logical = operand;
        node_root->elem_size = 0;
@@ -421,7 +392,7 @@ dfilter_mknode_numeric_variable(gint id)
        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;
@@ -438,7 +409,7 @@ dfilter_mknode_ether_variable(gint id)
        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;
@@ -455,7 +426,7 @@ dfilter_mknode_ipxnet_variable(gint id)
        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 ! */
@@ -472,7 +443,7 @@ dfilter_mknode_ipv4_variable(gint id)
        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 ! */
@@ -489,7 +460,7 @@ dfilter_mknode_bytes_variable(gint id, gint offset, guint length)
        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;
@@ -508,7 +479,7 @@ dfilter_mknode_boolean_variable(gint id)
        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 ! */
@@ -525,7 +496,7 @@ dfilter_mknode_numeric_value(guint32 val)
        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;
@@ -536,19 +507,28 @@ dfilter_mknode_numeric_value(guint32 val)
        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;
@@ -560,7 +540,7 @@ dfilter_mknode_ipxnet_value(guint32 ipx_net_val)
        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 ! */
@@ -577,7 +557,7 @@ dfilter_mknode_ipv4_value(char *host)
        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 ! */
@@ -595,7 +575,7 @@ dfilter_mknode_bytes_value(GByteArray *barray)
        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;
@@ -614,7 +594,7 @@ dfilter_mknode_boolean_value(gint truth_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;
@@ -643,7 +623,7 @@ dfilter_mknode_existence(gint id)
        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;
@@ -653,3 +633,37 @@ dfilter_mknode_existence(gint id)
 
        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 */
+}
+