The dfilter yacc grammar now keeps track of every GNode that it allocates.
[obnox/wireshark/wip.git] / dfilter.c
1 /* dfilter.c
2  * Routines for display filters
3  *
4  * $Id: dfilter.c,v 1.16 1999/08/26 06:20:48 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #ifndef _STDIO_H
35 #include <stdio.h>
36 #endif
37
38 #ifndef _STRING_H
39 #include <string.h>
40 #endif
41
42 #ifdef NEED_SNPRINTF_H
43 # ifdef HAVE_STDARG_H
44 #  include <stdarg.h>
45 # else
46 #  include <varargs.h>
47 # endif
48 # include "snprintf.h"
49 #endif
50
51 #ifndef __G_LIB_H__
52 #include <glib.h>
53 #endif
54
55 #ifndef __PROTO_H__
56 #include "proto.h"
57 #endif
58
59 #ifndef __DFILTER_H__
60 #include "dfilter.h"
61 #endif
62
63 #ifndef __UTIL_H__
64 #include "util.h"
65 #endif
66
67 #include "dfilter-int.h"
68 #include "dfilter-grammar.h"
69
70 int dfilter_parse(void); /* yacc entry-point */
71
72 #define DFILTER_LEX_ABBREV_OFFSET       2000
73
74 /* Balanced tree of abbreviations and IDs */
75 GTree *dfilter_tokens = NULL;
76
77 /* Comparision function for tree insertion. A wrapper around strcmp() */
78 static int g_strcmp(gconstpointer a, gconstpointer b);
79
80 /* Silly global variables used to pass parameter to check_relation_bytes() */
81 int bytes_offset = 0;
82 int bytes_length = 0;
83
84 YYSTYPE yylval;
85
86 /* Global error message space for dfilter_compile errors */
87 gchar dfilter_error_msg_buf[1024];
88 gchar *dfilter_error_msg;       /* NULL when no error resulted */
89
90 static gboolean dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8 *pd);
91 static gboolean check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd);
92 static gboolean check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd);
93 static GArray* get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd);
94 static GArray* get_values_from_dfilter(dfilter_node *dnode, GNode *gnode);
95 static gboolean check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree);
96 static void clear_byte_array(gpointer data, gpointer user_data);
97 static void unlink_gnode_children(gpointer gnode_ptr, gpointer user_data);
98 static void destroy_gnode(gpointer gnode_ptr, gpointer user_data);
99
100 /* this is not so pretty. I need my own g_array "function" (macro) to
101  * retreive the pointer to the data stored in an array cell. I need this
102  * for type ether.. GArray makes it easy for me to store 6 bytes inside an array
103  * cell, but hard to retrieve it.
104  */
105 #define g_array_index_ptr(a,s,i)      (((guint8*) (a)->data) + (i*s))
106
107 void
108 dfilter_init(void)
109 {
110         int i, num_symbols, symbol;
111         char *s;
112
113         dfilter_tokens = g_tree_new(g_strcmp);
114
115         /* Add the header field and protocol abbrevs to the symbol table */
116         num_symbols = proto_registrar_n();
117         for (i=0; i < num_symbols; i++) {
118                 s = proto_registrar_get_abbrev(i);
119                 if (s) {
120                         symbol = DFILTER_LEX_ABBREV_OFFSET + i;
121                         g_tree_insert(dfilter_tokens, s, GINT_TO_POINTER(symbol));
122                 }
123         }
124 }
125
126 void
127 dfilter_cleanup(void)
128 {
129         if (dfilter_tokens)
130                 g_tree_destroy(dfilter_tokens);
131 }
132
133 /* Compiles the textual representation of the display filter into a tree
134  * of operations to perform. Can be called multiple times, compiling a new
135  * display filter each time, without having to clear any memory used, since
136  * dfilter_compile will take care of that automatically.
137  * 
138  * Returns 0 on success, non-zero on failure.
139  * If a failure, dfilter_error_msg points to an appropriate error message.
140  * This error message is a global string, so another invocation of
141  * dfilter_compile will clear it. If the caller needs is stored, he
142  * needs to g_strdup it himself.
143  */
144 int
145 dfilter_compile(dfilter *df, gchar *dfilter_text)
146 {
147         int retval;
148
149         g_assert(dfilter_text != NULL);
150
151         dfilter_clear_filter(df);
152         df->dftext = g_strdup(dfilter_text);
153
154         /* tell the scanner to use this string as input */
155         dfilter_scanner_text(df->dftext);
156
157         /* Assign global variable so dfilter_parse knows which dfilter we're
158          * talking about. Reset the global error message. We don't have to set
159          * gnode_slist since it will always be NULL by the time we get here.
160          */
161         global_df = df;
162         dfilter_error_msg = NULL;
163
164         /* The magic happens right here. */
165         retval = dfilter_parse();
166
167         /* clean up lex */
168         dfilter_scanner_cleanup();
169
170         /* If a parse error occurred, fill in a generic error message
171          * if one was not created during parsing. */
172         if (retval != 0) {
173                 if (dfilter_error_msg == NULL) {
174                         dfilter_error_msg = &dfilter_error_msg_buf[0];
175                         snprintf(dfilter_error_msg, sizeof(dfilter_error_msg_buf),
176                                 "Unable to parse filter string \"%s\".",
177                                 dfilter_text);
178                 }
179         }
180
181         /* Clear the list of allocated nodes */
182         if (gnode_slist) {
183                 g_slist_free(gnode_slist);
184                 gnode_slist = NULL;
185         }
186
187         return retval;
188 }
189
190 /* clear the current filter, w/o clearing memchunk area which is where we'll
191  * put new nodes in a future filter */
192 void
193 dfilter_clear_filter(dfilter *df)
194 {
195         if (!df)
196                 return;
197
198         if (df->dftext)
199                 g_free(df->dftext);
200
201         if (df->dftree != NULL)
202                 g_node_destroy(df->dftree);
203
204         /* clear the memory that the tree was using for nodes */
205         if (df->node_memchunk)
206                 g_mem_chunk_reset(df->node_memchunk);
207
208         /* clear the memory that the tree was using for byte arrays */
209         if (df->list_of_byte_arrays) {
210                 g_slist_foreach(df->list_of_byte_arrays, clear_byte_array, NULL);
211                 g_slist_free(df->list_of_byte_arrays);
212         }
213
214         df->dftext = NULL;
215         df->dftree = NULL;
216         df->list_of_byte_arrays = NULL;
217 }
218
219 /* Allocates new dfilter, initializes values, and returns pointer to dfilter */
220 dfilter*
221 dfilter_new(void)
222 {
223         dfilter *df;
224
225         df = g_malloc(sizeof(dfilter));
226
227         df->dftext = NULL;
228         df->dftree = NULL;
229         df->node_memchunk = g_mem_chunk_new("df->node_memchunk",
230                 sizeof(dfilter_node), 20 * sizeof(dfilter_node), G_ALLOC_ONLY);
231         df->list_of_byte_arrays = NULL;
232
233         return df;
234 }
235
236 /* Frees all memory used by dfilter, and frees dfilter itself */
237 void
238 dfilter_destroy(dfilter *df)
239 {
240         if (!df)
241                 return;
242
243         dfilter_clear_filter(df);
244
245         /* Git rid of memchunk */
246         if (df->node_memchunk)
247                 g_mem_chunk_destroy(df->node_memchunk);
248
249         g_free(df);
250 }
251
252
253 static void
254 clear_byte_array(gpointer data, gpointer user_data)
255 {
256         GByteArray *barray = data;
257         if (barray)
258                 g_byte_array_free(barray, TRUE);
259 }
260
261 /* Called when the yacc grammar finds a parsing error */
262 void
263 dfilter_error(char *s)
264 {
265         /* The only data we have to worry about freeing is the
266          * data used by any GNodes that were allocated during
267          * parsing. The data in those Gnodes will be cleared
268          * later via df->node_memchunk. Use gnode_slist to
269          * clear the GNodes, and set global_df to NULL just
270          * to be tidy.
271          */
272         global_df = NULL;
273
274         /* I don't want to call g_node_destroy on each GNode ptr,
275          * since that function frees any children. That could
276          * mess me up later in the list if I try to free a GNode
277          * that has already been freed. So, I'll unlink the
278          * children firs,t then call g_node_destroy on each GNode ptr.
279          */
280         if (!gnode_slist)
281                 return;
282
283         g_slist_foreach(gnode_slist, unlink_gnode_children, NULL);
284         g_slist_foreach(gnode_slist, destroy_gnode, NULL);
285
286         /* notice we don't clear gnode_slist itself. dfilter_compile()
287          * will take care of that.
288          */
289 }
290
291 static void
292 unlink_gnode_children(gpointer gnode_ptr, gpointer user_data)
293 {
294         if (gnode_ptr)
295                 g_node_unlink((GNode*) gnode_ptr);
296 }
297
298 static void
299 destroy_gnode(gpointer gnode_ptr, gpointer user_data)
300 {
301         if (gnode_ptr)
302                 g_node_destroy((GNode*) gnode_ptr);
303 }
304
305
306 /* lookup an abbreviation in our token tree, returing the ID #
307  * If the abbreviation doesn't exit, returns 0 */
308 int dfilter_lookup_token(char *abbrev)
309 {
310         int value;
311
312         g_assert(abbrev != NULL);
313         value =  GPOINTER_TO_INT(g_tree_lookup(dfilter_tokens, abbrev));
314
315         if (value < DFILTER_LEX_ABBREV_OFFSET) {
316                 return 0;
317         }
318         return value - DFILTER_LEX_ABBREV_OFFSET;
319 }
320
321 static int
322 g_strcmp(gconstpointer a, gconstpointer b)
323 {
324         return strcmp((const char*)a, (const char*)b);
325 }
326
327
328 gboolean
329 dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd)
330 {
331         gboolean retval;
332         retval = dfilter_apply_node(dfcode->dftree, ptree, pd);
333         return retval;
334 }
335
336 static gboolean
337 dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd)
338 {
339         GNode           *gnode_a, *gnode_b;
340         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
341
342         /* We'll get 2 NULLs if we don't have children */
343         gnode_a = g_node_nth_child(gnode, 0);
344         gnode_b = g_node_nth_child(gnode, 1);
345
346         switch(dnode->ntype) {
347         case variable:
348                 /* We'll never see this case because if the parser finds the name of
349                  * a variable, it will cause it to be an 'existence' operation.
350                  */
351                 g_assert_not_reached();
352
353         case logical:
354                 return check_logical(dnode->value.logical, gnode_a, gnode_b, ptree, pd);
355
356         case relation:
357                 g_assert(gnode_a && gnode_b);
358                 return check_relation(dnode->value.relation, gnode_a, gnode_b, ptree, pd);
359
360         case alternation:
361                 g_assert_not_reached();
362                 /* not coded yet */
363         
364         case numeric:
365         case ipv4:
366         case boolean:
367         case ether:
368         case string:
369         case abs_time:
370         case bytes:
371         case ipxnet:
372                 /* the only time we'll see these at this point is if the display filter
373                  * is really wacky. (like simply "192.168.1.1"). The parser as it stands
374                  * now let these by. Just return TRUE */
375                 g_assert(!gnode_a && !gnode_b);
376                 return TRUE;
377
378         case existence: /* checking the existence of a protocol or hf*/
379                 g_assert(!gnode_a && !gnode_b);
380                 return check_existence_in_ptree(dnode, ptree);
381         }
382
383         g_assert_not_reached();
384         return FALSE;
385 }
386
387 static gboolean
388 check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd)
389 {
390         gboolean val_a = dfilter_apply_node(a, ptree, pd);
391         gboolean val_b;
392
393         switch(operand) {
394         case TOK_AND:
395                 return (val_a && dfilter_apply_node(b, ptree, pd));
396         case TOK_OR:
397                 return (val_a || dfilter_apply_node(b, ptree, pd));
398         case TOK_XOR:
399                 val_b = dfilter_apply_node(b, ptree, pd);
400                 return ( ( val_a || val_b ) && ! ( val_a && val_b ) );
401         case TOK_NOT:
402                 return (!val_a);
403         default:
404                 g_assert_not_reached();
405         }       
406         g_assert_not_reached();
407         return FALSE;
408 }
409
410 /* this is inefficient. I get arrays for both a and b that represent all the values present. That is,
411  * if a is bootp.option, e.g., i'll get an array showing all the bootp.option values in the protocol
412  * tree. Then I'll get an array for b, which more than likely is a single int, and then I'll compare
413  * them all. It makes my coding easier in the beginning, but I should change this to make it run
414  * faster.
415  */
416 static gboolean
417 check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8* pd)
418 {
419         dfilter_node    *node_a = (dfilter_node*) (a->data);
420         dfilter_node    *node_b = (dfilter_node*) (b->data);
421         GArray          *vals_a, *vals_b;
422         gboolean        retval;
423
424
425         bytes_length = MIN(node_a->length, node_b->length);
426         bytes_offset = MIN(node_a->offset, node_b->offset);
427         if (node_a->ntype == variable)
428                 vals_a = get_values_from_ptree(node_a, ptree, pd);
429         else
430                 vals_a = get_values_from_dfilter(node_a, a);
431
432         if (node_b->ntype == variable)
433                 vals_b = get_values_from_ptree(node_b, ptree, pd);
434         else
435                 vals_b = get_values_from_dfilter(node_b, b);
436
437         retval =  node_a->check_relation_func(operand, vals_a, vals_b);
438
439         g_array_free(vals_a, FALSE);
440         g_array_free(vals_b, FALSE);
441
442         return retval;
443 }
444
445 static gboolean
446 check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree)
447 {
448         int             target_field;
449         proto_tree      *subtree;
450
451         target_field = dnode->value.variable;
452         subtree = proto_find_field(ptree, target_field);
453
454         if (subtree)
455                 return TRUE;
456         else
457                 return FALSE;
458 }
459
460 static GArray*
461 get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd)
462 {
463         GArray          *array;
464         int             parent_protocol;
465         int             target_field;
466         proto_tree      *subtree = NULL; /* where the parent protocol's sub-tree starts */
467         proto_tree_search_info sinfo;
468
469         g_assert(dnode->elem_size > 0);
470         array = g_array_new(FALSE, FALSE, dnode->elem_size);
471
472         target_field = dnode->value.variable;
473
474         /* Find the proto_tree subtree where we should start searching.*/
475         if (proto_registrar_is_protocol(target_field)) {
476                 subtree = proto_find_protocol(ptree, target_field);
477         }
478         else {
479                 parent_protocol = proto_registrar_get_parent(target_field);
480                 if (parent_protocol >= 0) {
481                         subtree = proto_find_protocol(ptree, parent_protocol);
482                 }
483         }
484
485         if (subtree) {
486                 sinfo.target_field = target_field;
487                 sinfo.result_array = array;
488                 sinfo.packet_data = pd;
489                 proto_get_field_values(subtree, dnode->fill_array_func, &sinfo);
490         }
491
492         return array;
493 }
494
495 static GArray*
496 get_values_from_dfilter(dfilter_node *dnode, GNode *gnode)
497 {
498         GArray          *array;
499
500         g_assert(dnode->elem_size > 0);
501         array = g_array_new(FALSE, FALSE, dnode->elem_size);
502
503         g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, dnode->fill_array_func, array);
504 /*      dnode->fill_array_func(gnode, array);*/
505         return array;
506 }
507
508 gboolean fill_array_numeric_variable(GNode *gnode, gpointer data)
509 {
510         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
511         field_info              *fi = (field_info*) (gnode->data);
512
513         if (fi->hfinfo->id == sinfo->target_field) {
514                 g_array_append_val(sinfo->result_array, fi->value.numeric);
515         }
516
517         return FALSE; /* FALSE = do not end traversal of GNode tree */
518 }
519
520 gboolean fill_array_ether_variable(GNode *gnode, gpointer data)
521 {
522         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
523         field_info              *fi = (field_info*) (gnode->data);
524
525         if (fi->hfinfo->id == sinfo->target_field) {
526                 g_array_append_val(sinfo->result_array, fi->value.ether);
527         }
528
529         return FALSE; /* FALSE = do not end traversal of GNode tree */
530 }
531
532 gboolean fill_array_bytes_variable(GNode *gnode, gpointer data)
533 {
534         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
535         field_info              *fi = (field_info*) (gnode->data);
536         GByteArray              *barray;
537
538         if (fi->hfinfo->id == sinfo->target_field) {
539                 barray = g_byte_array_new();
540                 /*list_of_byte_arrays = g_slist_append(list_of_byte_arrays, barray);*/
541                 g_byte_array_append(barray, sinfo->packet_data + fi->start + bytes_offset, bytes_length);
542                 g_array_append_val(sinfo->result_array, barray);
543         }
544
545         return FALSE; /* FALSE = do not end traversal of GNode tree */
546 }
547
548 gboolean fill_array_boolean_variable(GNode *gnode, gpointer data)
549 {
550         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
551         field_info              *fi = (field_info*) (gnode->data);
552
553         if (fi->hfinfo->id == sinfo->target_field) {
554                 g_array_append_val(sinfo->result_array, fi->value.boolean);
555         }
556
557         return FALSE; /* FALSE = do not end traversal of GNode tree */
558 }
559
560 gboolean fill_array_numeric_value(GNode *gnode, gpointer data)
561 {
562         GArray          *array = (GArray*)data;
563         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
564
565         g_array_append_val(array, dnode->value.numeric);
566
567         return FALSE; /* FALSE = do not end traversal of GNode tree */
568 }
569
570 gboolean fill_array_ether_value(GNode *gnode, gpointer data)
571 {
572         GArray          *array = (GArray*)data;
573         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
574
575         g_array_append_val(array, dnode->value.ether);
576
577         return FALSE; /* FALSE = do not end traversal of GNode tree */
578 }
579
580 gboolean fill_array_bytes_value(GNode *gnode, gpointer data)
581 {
582         GArray          *array = (GArray*)data;
583         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
584         GByteArray      *barray = dnode->value.bytes;
585
586         g_array_append_val(array, barray);
587
588         return FALSE; /* FALSE = do not end traversal of GNode tree */
589 }
590
591 gboolean fill_array_boolean_value(GNode *gnode, gpointer data)
592 {
593         GArray          *array = (GArray*)data;
594         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
595
596         g_array_append_val(array, dnode->value.boolean);
597
598         return FALSE; /* FALSE = do not end traversal of GNode tree */
599 }
600
601
602 gboolean check_relation_numeric(gint operand, GArray *a, GArray *b)
603 {
604         int     i, j, len_a, len_b;
605         guint32 val_a;
606
607         len_a = a->len;
608         len_b = b->len;
609
610
611         switch(operand) {
612         case TOK_EQ:
613                 for(i = 0; i < len_a; i++) {
614                         val_a = g_array_index(a, guint32, i);
615                         for (j = 0; j < len_b; j++) {
616                                 if (val_a == g_array_index(b, guint32, j))
617                                         return TRUE;
618                         }
619                 }
620                 return FALSE;
621
622         case TOK_NE:
623                 for(i = 0; i < len_a; i++) {
624                         val_a = g_array_index(a, guint32, i);
625                         for (j = 0; j < len_b; j++) {
626                                 if (val_a != g_array_index(b, guint32, j))
627                                         return TRUE;
628                         }
629                 }
630                 return FALSE;
631
632         case TOK_GT:
633                 for(i = 0; i < len_a; i++) {
634                         val_a = g_array_index(a, guint32, i);
635                         for (j = 0; j < len_b; j++) {
636                                 if (val_a > g_array_index(b, guint32, j))
637                                         return TRUE;
638                         }
639                 }
640                 return FALSE;
641
642         case TOK_GE:
643                 for(i = 0; i < len_a; i++) {
644                         val_a = g_array_index(a, guint32, i);
645                         for (j = 0; j < len_b; j++) {
646                                 if (val_a >= g_array_index(b, guint32, j))
647                                         return TRUE;
648                         }
649                 }
650                 return FALSE;
651
652         case TOK_LT:
653                 for(i = 0; i < len_a; i++) {
654                         val_a = g_array_index(a, guint32, i);
655                         for (j = 0; j < len_b; j++) {
656                                 if (val_a < g_array_index(b, guint32, j))
657                                         return TRUE;
658                         }
659                 }
660                 return FALSE;
661
662         case TOK_LE:
663                 for(i = 0; i < len_a; i++) {
664                         val_a = g_array_index(a, guint32, i);
665                         for (j = 0; j < len_b; j++) {
666                                 if (val_a <= g_array_index(b, guint32, j))
667                                         return TRUE;
668                         }
669                 }
670                 return FALSE;
671
672         default:
673                 g_assert_not_reached();
674         }
675
676         g_assert_not_reached();
677         return FALSE;
678 }
679
680
681 gboolean check_relation_ether(gint operand, GArray *a, GArray *b)
682 {
683         int     i, j, len_a, len_b;
684         guint8  *ptr_a, *ptr_b;
685
686         len_a = a->len;
687         len_b = b->len;
688
689
690         switch(operand) {
691         case TOK_EQ:
692                 for(i = 0; i < len_a; i++) {
693                         ptr_a = g_array_index_ptr(a, 6, i);
694                         for (j = 0; j < len_b; j++) {
695                                 ptr_b = g_array_index_ptr(b, 6, j);
696                                 if (memcmp(ptr_a, ptr_b, 6) == 0)
697                                         return TRUE;
698                         }
699                 }
700                 return FALSE;
701
702         case TOK_NE:
703                 for(i = 0; i < len_a; i++) {
704                         ptr_a = g_array_index_ptr(a, 6, i);
705                         for (j = 0; j < len_b; j++) {
706                                 ptr_b = g_array_index_ptr(b, 6, j);
707                                 if (memcmp(ptr_a, ptr_b, 6) != 0)
708                                         return TRUE;
709                         }
710                 }
711                 return FALSE;
712         }
713
714         g_assert_not_reached();
715         return FALSE;
716 }
717
718 gboolean check_relation_bytes(gint operand, GArray *a, GArray *b)
719 {
720         int     i, j, len_a, len_b;
721         GByteArray      *ptr_a,*ptr_b;
722
723         len_a = a->len;
724         len_b = b->len;
725
726
727         switch(operand) {
728         case TOK_EQ:
729                 for(i = 0; i < len_a; i++) {
730                         ptr_a = g_array_index(a, GByteArray*, i);
731                         for (j = 0; j < len_b; j++) {
732                                 ptr_b = g_array_index(b, GByteArray*, j);
733                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) == 0)
734                                         return TRUE;
735                         }
736                 }
737                 return FALSE;
738
739         case TOK_NE:
740                 for(i = 0; i < len_a; i++) {
741                         ptr_a = g_array_index(a, GByteArray*, i);
742                         for (j = 0; j < len_b; j++) {
743                                 ptr_b = g_array_index(b, GByteArray*, j);
744                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) != 0)
745                                         return TRUE;
746                         }
747                 }
748                 return FALSE;
749
750         case TOK_GT:
751                 for(i = 0; i < len_a; i++) {
752                         ptr_a = g_array_index(a, GByteArray*, i);
753                         for (j = 0; j < len_b; j++) {
754                                 ptr_b = g_array_index(b, GByteArray*, j);
755                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) > 0)
756                                         return TRUE;
757                         }
758                 }
759                 return FALSE;
760
761         case TOK_LT:
762                 for(i = 0; i < len_a; i++) {
763                         ptr_a = g_array_index(a, GByteArray*, i);
764                         for (j = 0; j < len_b; j++) {
765                                 ptr_b = g_array_index(b, GByteArray*, j);
766                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) < 0)
767                                         return TRUE;
768                         }
769                 }
770                 return FALSE;
771         }
772
773         g_assert_not_reached();
774         return FALSE;
775 }
776
777 gboolean check_relation_boolean(gint operand, GArray *a, GArray *b)
778 {
779         int     i, j, len_a, len_b;
780         guint32 val_a;
781
782         len_a = a->len;
783         len_b = b->len;
784
785
786         switch(operand) {
787         case TOK_EQ:
788                 for(i = 0; i < len_a; i++) {
789                         val_a = g_array_index(a, guint32, i);
790                         for (j = 0; j < len_b; j++) {
791                                 if (val_a == g_array_index(b, guint32, j))
792                                         return TRUE;
793                         }
794                 }
795                 return FALSE;
796
797         case TOK_NE:
798                 for(i = 0; i < len_a; i++) {
799                         val_a = g_array_index(a, guint32, i);
800                         for (j = 0; j < len_b; j++) {
801                                 if (val_a != g_array_index(b, guint32, j))
802                                         return TRUE;
803                         }
804                 }
805                 return FALSE;
806
807         default:
808                 g_assert_not_reached();
809         }
810
811         g_assert_not_reached();
812         return FALSE;
813 }
814