4 * Parser for display filters
6 * $Id: dfilter-grammar.y,v 1.19 1999/09/29 22:11:50 gram Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>
40 #ifdef NEED_SNPRINTF_H
46 # include "snprintf.h"
71 #include "dfilter-int.h"
77 static GNode* dfilter_mknode_join(GNode *n1, enum node_type ntype, int operand, GNode *n2);
78 static GNode* dfilter_mknode_unary(int operand, GNode *n2);
79 static GNode* dfilter_mknode_numeric_variable(gint id);
80 static GNode* dfilter_mknode_numeric_value(guint32 val);
81 static GNode* dfilter_mknode_ether_value(gchar*);
82 static GNode* dfilter_mknode_ether_variable(gint id);
83 static GNode* dfilter_mknode_ipxnet_value(guint32);
84 static GNode* dfilter_mknode_ipxnet_variable(gint id);
85 static GNode* dfilter_mknode_ipv4_value(char *host);
86 static GNode* dfilter_mknode_ipv4_variable(gint id);
87 static GNode* dfilter_mknode_existence(gint id);
88 static GNode* dfilter_mknode_bytes_value(GByteArray *barray);
89 static GNode* dfilter_mknode_bytes_variable(gint id, gint offset, guint length);
91 static guint32 string_to_value(char *s);
92 static int ether_str_to_guint8_array(const char *s, guint8 *mac);
94 /* This is the dfilter we're currently processing. It's how
95 * dfilter_compile communicates with us.
97 dfilter *global_df = NULL;;
99 /* list of GNodes allocated during parsing. If the parsing fails, we'll
100 * use this list to free all the GNodes. If the parsing succeeds, we'll
101 * just clear this list since dfilter_clear_filter() will take care of
102 * freeing the GNodes when they're no longer needed.
104 GSList *gnode_slist = NULL;
109 gint operand; /* logical, relation, alternation */
112 gint type; /* using macros defined below, in this yacc grammar */
122 %type <node> statement expression relation
123 %type <node> numeric_value numeric_variable
124 %type <node> ether_value ether_variable
125 %type <node> ipxnet_value ipxnet_variable
126 %type <node> ipv4_value ipv4_variable
127 %type <node> variable_name
128 %type <node> bytes_value bytes_variable
130 %type <operand> numeric_relation
131 %type <operand> equality_relation
132 %type <operand> bytes_relation
134 %type <variable> any_variable_type
136 %token <variable> T_FT_UINT8
137 %token <variable> T_FT_UINT16
138 %token <variable> T_FT_UINT32
139 %token <variable> T_FT_ETHER
140 %token <variable> T_FT_IPv4
141 %token <variable> T_FT_NONE
142 %token <variable> T_FT_BYTES
143 %token <variable> T_FT_BOOLEAN
144 %token <variable> T_FT_STRING
145 %token <variable> T_FT_IPXNET
147 %token <string> T_VAL_UNQUOTED_STRING
148 %token <string> T_VAL_BYTE_STRING
149 %token <string> T_VAL_NUMBER_STRING
150 %token <byte_range> T_VAL_BYTE_RANGE
152 %token <operand> TOK_AND TOK_OR TOK_NOT TOK_XOR
153 %token <operand> TOK_EQ TOK_NE TOK_GT TOK_GE TOK_LT TOK_LE
154 %token <operand> TOK_TRUE TOK_FALSE
163 statement: expression
165 global_df->dftree = $1;
167 | /* NULL */ { global_df->dftree = NULL; }
170 expression: '(' expression ')' { $$ = $2; }
171 | expression TOK_AND expression { $$ = dfilter_mknode_join($1, logical, $2, $3); }
172 | expression TOK_OR expression { $$ = dfilter_mknode_join($1, logical, $2, $3); }
173 | expression TOK_XOR expression { $$ = dfilter_mknode_join($1, logical, $2, $3); }
174 | TOK_NOT expression { $$ = dfilter_mknode_unary(TOK_NOT, $2); }
175 | relation { $$ = $1; }
176 | variable_name { $$ = $1; }
177 | expression error { YYABORT; }
180 relation: numeric_variable numeric_relation numeric_value
182 $$ = dfilter_mknode_join($1, relation, $2, $3);
184 | numeric_variable numeric_relation numeric_variable
186 $$ = dfilter_mknode_join($1, relation, $2, $3);
189 | ether_variable equality_relation ether_value
191 $$ = dfilter_mknode_join($1, relation, $2, $3);
193 | ether_variable equality_relation ether_variable
195 $$ = dfilter_mknode_join($1, relation, $2, $3);
198 | ipxnet_variable equality_relation ipxnet_value
200 $$ = dfilter_mknode_join($1, relation, $2, $3);
202 | ipxnet_variable equality_relation ipxnet_variable
204 $$ = dfilter_mknode_join($1, relation, $2, $3);
208 | ipv4_variable numeric_relation ipv4_value
210 $$ = dfilter_mknode_join($1, relation, $2, $3);
212 | ipv4_variable numeric_relation ipv4_variable
214 $$ = dfilter_mknode_join($1, relation, $2, $3);
217 | bytes_variable bytes_relation bytes_value
219 $$ = dfilter_mknode_join($1, relation, $2, $3);
221 | bytes_variable bytes_relation bytes_variable
223 $$ = dfilter_mknode_join($1, relation, $2, $3);
229 numeric_value: T_VAL_NUMBER_STRING
231 $$ = dfilter_mknode_numeric_value(string_to_value($1));
236 ether_value: T_VAL_BYTE_STRING
238 $$ = dfilter_mknode_ether_value($1);
246 ipxnet_value: T_VAL_NUMBER_STRING
248 $$ = dfilter_mknode_ipxnet_value(string_to_value($1));
253 ipv4_value: T_VAL_UNQUOTED_STRING
255 $$ = dfilter_mknode_ipv4_value($1);
261 $$ = dfilter_mknode_ipv4_value($1);
266 bytes_value: T_VAL_BYTE_STRING
270 /* the next function appends to list_of_byte_arrays for me */
271 barray = byte_str_to_guint8_array($1);
272 $$ = dfilter_mknode_bytes_value(barray);
278 numeric_variable: T_FT_UINT8 { $$ = dfilter_mknode_numeric_variable($1.id); }
279 | T_FT_UINT16 { $$ = dfilter_mknode_numeric_variable($1.id); }
280 | T_FT_UINT32 { $$ = dfilter_mknode_numeric_variable($1.id); }
283 ether_variable: T_FT_ETHER { $$ = dfilter_mknode_ether_variable($1.id); }
286 ipxnet_variable: T_FT_IPXNET { $$ = dfilter_mknode_ipxnet_variable($1.id); }
289 ipv4_variable: T_FT_IPv4 { $$ = dfilter_mknode_ipv4_variable($1.id); }
292 variable_name: any_variable_type
297 if ($1.type == T_FT_BOOLEAN) {
298 /* Make "variable == TRUE" for BOOLEAN variable */
299 variable = dfilter_mknode_numeric_variable($1.id);
300 value = dfilter_mknode_numeric_value(TRUE);
301 $$ = dfilter_mknode_join(variable, relation, TOK_EQ, value);
304 $$ = dfilter_mknode_existence($1.id);
309 bytes_variable: any_variable_type T_VAL_BYTE_RANGE
311 $$ = dfilter_mknode_bytes_variable($1.id, $2.offset, $2.length);
315 any_variable_type: T_FT_UINT8 { $$ = $1; }
316 | T_FT_UINT16 { $$ = $1; }
317 | T_FT_UINT32 { $$ = $1; }
318 | T_FT_ETHER { $$ = $1; }
319 | T_FT_IPv4 { $$ = $1; }
320 | T_FT_IPXNET { $$ = $1; }
321 | T_FT_NONE { $$ = $1; }
322 | T_FT_BYTES { $$ = $1; }
323 | T_FT_BOOLEAN { $$ = $1; }
324 | T_FT_STRING { $$ = $1; }
327 numeric_relation: TOK_EQ { $$ = TOK_EQ; }
328 | TOK_NE { $$ = TOK_NE; }
329 | TOK_GT { $$ = TOK_GT; }
330 | TOK_GE { $$ = TOK_GE; }
331 | TOK_LT { $$ = TOK_LT; }
332 | TOK_LE { $$ = TOK_LE; }
335 equality_relation: TOK_EQ { $$ = TOK_EQ; }
336 | TOK_NE { $$ = TOK_NE; }
339 bytes_relation: TOK_EQ { $$ = TOK_EQ; }
340 | TOK_NE { $$ = TOK_NE; }
341 | TOK_GT { $$ = TOK_GT; }
342 | TOK_LT { $$ = TOK_LT; }
348 dfilter_mknode_join(GNode *n1, enum node_type ntype, int operand, GNode *n2)
350 dfilter_node *node_root;
353 node_root = g_mem_chunk_alloc(global_df->node_memchunk);
354 node_root->ntype = ntype;
355 node_root->elem_size = 0;
356 node_root->fill_array_func = NULL;
357 node_root->check_relation_func = NULL;
358 if (ntype == relation) {
359 node_root->value.relation = operand;
361 else if (ntype == logical) {
362 node_root->value.logical = operand;
365 g_assert_not_reached();
368 gnode_root = g_node_new(node_root);
369 g_node_append(gnode_root, n1);
370 g_node_append(gnode_root, n2);
372 gnode_slist = g_slist_append(gnode_slist, gnode_root);
377 dfilter_mknode_unary(int operand, GNode *n2)
379 dfilter_node *node_root;
382 node_root = g_mem_chunk_alloc(global_df->node_memchunk);
383 node_root->ntype = logical;
384 node_root->value.logical = operand;
385 node_root->elem_size = 0;
386 node_root->fill_array_func = NULL;
387 node_root->check_relation_func = NULL;
389 gnode_root = g_node_new(node_root);
390 g_node_append(gnode_root, n2);
392 gnode_slist = g_slist_append(gnode_slist, gnode_root);
398 dfilter_mknode_numeric_variable(gint id)
403 node = g_mem_chunk_alloc(global_df->node_memchunk);
404 node->ntype = variable;
405 node->elem_size = sizeof(guint32);
406 node->fill_array_func = fill_array_numeric_variable;
407 node->check_relation_func = check_relation_numeric;
408 node->value.variable = id;
409 gnode = g_node_new(node);
411 gnode_slist = g_slist_append(gnode_slist, gnode);
416 dfilter_mknode_ether_variable(gint id)
421 node = g_mem_chunk_alloc(global_df->node_memchunk);
422 node->ntype = variable;
423 node->elem_size = sizeof(guint8) * 6;
424 node->fill_array_func = fill_array_ether_variable;
425 node->check_relation_func = check_relation_ether;
426 node->value.variable = id;
427 gnode = g_node_new(node);
429 gnode_slist = g_slist_append(gnode_slist, gnode);
434 dfilter_mknode_ipxnet_variable(gint id)
439 node = g_mem_chunk_alloc(global_df->node_memchunk);
440 node->ntype = variable;
441 node->elem_size = sizeof(guint8) * 4;
442 node->fill_array_func = fill_array_numeric_variable; /* cheating ! */
443 node->check_relation_func = check_relation_numeric; /* cheating ! */
444 node->value.variable = id;
445 gnode = g_node_new(node);
447 gnode_slist = g_slist_append(gnode_slist, gnode);
452 dfilter_mknode_ipv4_variable(gint id)
457 node = g_mem_chunk_alloc(global_df->node_memchunk);
458 node->ntype = variable;
459 node->elem_size = sizeof(guint32);
460 node->fill_array_func = fill_array_numeric_variable; /* cheating ! */
461 node->check_relation_func = check_relation_numeric; /* cheating ! */
462 node->value.variable = id;
463 gnode = g_node_new(node);
465 gnode_slist = g_slist_append(gnode_slist, gnode);
470 dfilter_mknode_bytes_variable(gint id, gint offset, guint length)
475 node = g_mem_chunk_alloc(global_df->node_memchunk);
476 node->ntype = variable;
477 node->elem_size = sizeof(GByteArray*);
478 node->fill_array_func = fill_array_bytes_variable;
479 node->check_relation_func = check_relation_bytes;
480 node->value.variable = id;
481 node->offset = offset;
482 node->length = length;
483 gnode = g_node_new(node);
485 gnode_slist = g_slist_append(gnode_slist, gnode);
490 dfilter_mknode_numeric_value(guint32 val)
495 node = g_mem_chunk_alloc(global_df->node_memchunk);
496 node->ntype = numeric;
497 node->elem_size = sizeof(guint32);
498 node->fill_array_func = fill_array_numeric_value;
499 node->check_relation_func = check_relation_numeric;
500 node->value.numeric = val;
501 gnode = g_node_new(node);
503 gnode_slist = g_slist_append(gnode_slist, gnode);
507 /* Returns NULL on bad parse of ETHER value */
509 dfilter_mknode_ether_value(gchar *byte_string)
514 node = g_mem_chunk_alloc(global_df->node_memchunk);
516 node->elem_size = sizeof(guint8) * 6;
517 node->fill_array_func = fill_array_ether_value;
518 node->check_relation_func = check_relation_ether;
520 if (!ether_str_to_guint8_array(byte_string, &node->value.ether[0])) {
521 /* Rather than free the mem_chunk allocation, let it
522 * stay. It will be cleaned up in the next call to
524 dfilter_error_msg = &dfilter_error_msg_buf[0];
525 snprintf(dfilter_error_msg, sizeof(dfilter_error_msg_buf),
526 "\"%s\" is not a valid hardware address.", byte_string);
530 gnode = g_node_new(node);
531 gnode_slist = g_slist_append(gnode_slist, gnode);
536 dfilter_mknode_ipxnet_value(guint32 ipx_net_val)
541 node = g_mem_chunk_alloc(global_df->node_memchunk);
542 node->ntype = ipxnet;
543 node->elem_size = sizeof(guint8) * 4;
544 node->fill_array_func = fill_array_numeric_value; /* cheating ! */
545 node->check_relation_func = check_relation_numeric; /* cheating ! */
546 node->value.numeric = ipx_net_val;
547 gnode = g_node_new(node);
549 gnode_slist = g_slist_append(gnode_slist, gnode);
554 dfilter_mknode_ipv4_value(char *host)
559 node = g_mem_chunk_alloc(global_df->node_memchunk);
560 node->ntype = numeric;
561 node->elem_size = sizeof(guint32);
562 node->fill_array_func = fill_array_numeric_value; /* cheating ! */
563 node->check_relation_func = check_relation_numeric; /* cheating ! */
564 node->value.numeric = get_host_ipaddr(host);
565 node->value.numeric = htonl(node->value.numeric);
566 gnode = g_node_new(node);
568 gnode_slist = g_slist_append(gnode_slist, gnode);
573 dfilter_mknode_bytes_value(GByteArray *barray)
578 node = g_mem_chunk_alloc(global_df->node_memchunk);
580 node->elem_size = sizeof(GByteArray*);
581 node->fill_array_func = fill_array_bytes_value;
582 node->check_relation_func = check_relation_bytes;
583 node->value.bytes = barray;
584 node->offset = G_MAXINT;
585 node->length = barray->len;
586 gnode = g_node_new(node);
588 gnode_slist = g_slist_append(gnode_slist, gnode);
593 string_to_value(char *s)
598 val = strtoul(s, &endptr, 0);
599 /* I should probably check errno here */
605 dfilter_mknode_existence(gint id)
610 node = g_mem_chunk_alloc(global_df->node_memchunk);
611 node->ntype = existence;
612 node->elem_size = sizeof(guint32);
613 node->fill_array_func = NULL;
614 node->check_relation_func = NULL;
615 node->value.variable = id;
616 gnode = g_node_new(node);
618 gnode_slist = g_slist_append(gnode_slist, gnode);
623 /* converts a string representing an ether HW address
626 * Returns 0 on failure, 1 on success.
629 ether_str_to_guint8_array(const char *s, guint8 *mac)
631 char ether_str[18]; /* 2+1+2+1+2+1+2+1+2+1+2 + 1 */
635 if (strlen(s) > 17) {
638 strcpy(ether_str, s); /* local copy of string */
640 while ((p = strtok(str, "-:."))) {
641 /* catch short strings with too many hex bytes: 0.0.0.0.0.0.0 */
645 mac[i] = (guint8) strtoul(p, NULL, 16);
647 /* subsequent calls to strtok() require NULL as arg 1 */
651 return 0; /* failed to read 6 hex pairs */
653 return 1; /* read exactly 6 hex pairs */