57ac05be7f8fb6910577c675a1f0340f9c26b025
[obnox/wireshark/wip.git] / dfilter.c
1 /* dfilter.c
2  * Routines for display filters
3  *
4  * $Id: dfilter.c,v 1.18 1999/08/30 15:51:43 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;
449
450         target = dnode->value.variable;
451         return proto_check_for_protocol_or_field(ptree, target);
452 }
453
454 static GArray*
455 get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd)
456 {
457         GArray          *array;
458         int             parent_protocol;
459         proto_tree_search_info sinfo;
460
461         g_assert(dnode->elem_size > 0);
462         array = g_array_new(FALSE, FALSE, dnode->elem_size);
463
464         sinfo.target = dnode->value.variable;
465         sinfo.result.array = array;
466         sinfo.packet_data = pd;
467         sinfo.traverse_func = dnode->fill_array_func;
468
469         /* Find the proto_tree subtree where we should start searching.*/
470         if (proto_registrar_is_protocol(sinfo.target)) {
471                 proto_find_protocol_multi(ptree, sinfo.target,
472                                 (GNodeTraverseFunc)proto_get_field_values, &sinfo);
473         }
474         else {
475                 parent_protocol = proto_registrar_get_parent(sinfo.target);
476                 if (parent_protocol >= 0) {
477                         proto_find_protocol_multi(ptree, parent_protocol,
478                                         (GNodeTraverseFunc)proto_get_field_values, &sinfo);
479                 }
480         }
481
482         return array;
483 }
484
485 static GArray*
486 get_values_from_dfilter(dfilter_node *dnode, GNode *gnode)
487 {
488         GArray          *array;
489
490         g_assert(dnode->elem_size > 0);
491         array = g_array_new(FALSE, FALSE, dnode->elem_size);
492
493         g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, dnode->fill_array_func, array);
494 /*      dnode->fill_array_func(gnode, array);*/
495         return array;
496 }
497
498 gboolean fill_array_numeric_variable(GNode *gnode, gpointer data)
499 {
500         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
501         field_info              *fi = (field_info*) (gnode->data);
502
503         if (fi->hfinfo->id == sinfo->target) {
504                 g_array_append_val(sinfo->result.array, fi->value.numeric);
505         }
506
507         return FALSE; /* FALSE = do not end traversal of GNode tree */
508 }
509
510 gboolean fill_array_ether_variable(GNode *gnode, gpointer data)
511 {
512         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
513         field_info              *fi = (field_info*) (gnode->data);
514
515         if (fi->hfinfo->id == sinfo->target) {
516                 g_array_append_val(sinfo->result.array, fi->value.ether);
517         }
518
519         return FALSE; /* FALSE = do not end traversal of GNode tree */
520 }
521
522 gboolean fill_array_bytes_variable(GNode *gnode, gpointer data)
523 {
524         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
525         field_info              *fi = (field_info*) (gnode->data);
526         GByteArray              *barray;
527
528         if (fi->hfinfo->id == sinfo->target) {
529                 barray = g_byte_array_new();
530                 /*list_of_byte_arrays = g_slist_append(list_of_byte_arrays, barray);*/
531                 g_byte_array_append(barray, sinfo->packet_data + fi->start + bytes_offset, bytes_length);
532                 g_array_append_val(sinfo->result.array, barray);
533         }
534
535         return FALSE; /* FALSE = do not end traversal of GNode tree */
536 }
537
538 gboolean fill_array_boolean_variable(GNode *gnode, gpointer data)
539 {
540         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
541         field_info              *fi = (field_info*) (gnode->data);
542
543         if (fi->hfinfo->id == sinfo->target) {
544                 g_array_append_val(sinfo->result.array, fi->value.boolean);
545         }
546
547         return FALSE; /* FALSE = do not end traversal of GNode tree */
548 }
549
550 gboolean fill_array_numeric_value(GNode *gnode, gpointer data)
551 {
552         GArray          *array = (GArray*)data;
553         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
554
555         g_array_append_val(array, dnode->value.numeric);
556         return FALSE; /* FALSE = do not end traversal of GNode tree */
557 }
558
559 gboolean fill_array_ether_value(GNode *gnode, gpointer data)
560 {
561         GArray          *array = (GArray*)data;
562         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
563
564         g_array_append_val(array, dnode->value.ether);
565
566         return FALSE; /* FALSE = do not end traversal of GNode tree */
567 }
568
569 gboolean fill_array_bytes_value(GNode *gnode, gpointer data)
570 {
571         GArray          *array = (GArray*)data;
572         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
573         GByteArray      *barray = dnode->value.bytes;
574
575         g_array_append_val(array, barray);
576
577         return FALSE; /* FALSE = do not end traversal of GNode tree */
578 }
579
580 gboolean fill_array_boolean_value(GNode *gnode, gpointer data)
581 {
582         GArray          *array = (GArray*)data;
583         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
584
585         g_array_append_val(array, dnode->value.boolean);
586
587         return FALSE; /* FALSE = do not end traversal of GNode tree */
588 }
589
590
591 gboolean check_relation_numeric(gint operand, GArray *a, GArray *b)
592 {
593         int     i, j, len_a, len_b;
594         guint32 val_a;
595
596         len_a = a->len;
597         len_b = b->len;
598
599
600         switch(operand) {
601         case TOK_EQ:
602                 for(i = 0; i < len_a; i++) {
603                         val_a = g_array_index(a, guint32, i);
604                         for (j = 0; j < len_b; j++) {
605                                 if (val_a == g_array_index(b, guint32, j))
606                                         return TRUE;
607                         }
608                 }
609                 return FALSE;
610
611         case TOK_NE:
612                 for(i = 0; i < len_a; i++) {
613                         val_a = g_array_index(a, guint32, i);
614                         for (j = 0; j < len_b; j++) {
615                                 if (val_a != g_array_index(b, guint32, j))
616                                         return TRUE;
617                         }
618                 }
619                 return FALSE;
620
621         case TOK_GT:
622                 for(i = 0; i < len_a; i++) {
623                         val_a = g_array_index(a, guint32, i);
624                         for (j = 0; j < len_b; j++) {
625                                 if (val_a > g_array_index(b, guint32, j))
626                                         return TRUE;
627                         }
628                 }
629                 return FALSE;
630
631         case TOK_GE:
632                 for(i = 0; i < len_a; i++) {
633                         val_a = g_array_index(a, guint32, i);
634                         for (j = 0; j < len_b; j++) {
635                                 if (val_a >= g_array_index(b, guint32, j))
636                                         return TRUE;
637                         }
638                 }
639                 return FALSE;
640
641         case TOK_LT:
642                 for(i = 0; i < len_a; i++) {
643                         val_a = g_array_index(a, guint32, i);
644                         for (j = 0; j < len_b; j++) {
645                                 if (val_a < g_array_index(b, guint32, j))
646                                         return TRUE;
647                         }
648                 }
649                 return FALSE;
650
651         case TOK_LE:
652                 for(i = 0; i < len_a; i++) {
653                         val_a = g_array_index(a, guint32, i);
654                         for (j = 0; j < len_b; j++) {
655                                 if (val_a <= g_array_index(b, guint32, j))
656                                         return TRUE;
657                         }
658                 }
659                 return FALSE;
660
661         default:
662                 g_assert_not_reached();
663         }
664
665         g_assert_not_reached();
666         return FALSE;
667 }
668
669
670 gboolean check_relation_ether(gint operand, GArray *a, GArray *b)
671 {
672         int     i, j, len_a, len_b;
673         guint8  *ptr_a, *ptr_b;
674
675         len_a = a->len;
676         len_b = b->len;
677
678
679         switch(operand) {
680         case TOK_EQ:
681                 for(i = 0; i < len_a; i++) {
682                         ptr_a = g_array_index_ptr(a, 6, i);
683                         for (j = 0; j < len_b; j++) {
684                                 ptr_b = g_array_index_ptr(b, 6, j);
685                                 if (memcmp(ptr_a, ptr_b, 6) == 0)
686                                         return TRUE;
687                         }
688                 }
689                 return FALSE;
690
691         case TOK_NE:
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
703         g_assert_not_reached();
704         return FALSE;
705 }
706
707 gboolean check_relation_bytes(gint operand, GArray *a, GArray *b)
708 {
709         int     i, j, len_a, len_b;
710         GByteArray      *ptr_a,*ptr_b;
711
712         len_a = a->len;
713         len_b = b->len;
714
715
716         switch(operand) {
717         case TOK_EQ:
718                 for(i = 0; i < len_a; i++) {
719                         ptr_a = g_array_index(a, GByteArray*, i);
720                         for (j = 0; j < len_b; j++) {
721                                 ptr_b = g_array_index(b, GByteArray*, j);
722                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) == 0)
723                                         return TRUE;
724                         }
725                 }
726                 return FALSE;
727
728         case TOK_NE:
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_GT:
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_LT:
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
762         g_assert_not_reached();
763         return FALSE;
764 }
765
766 gboolean check_relation_boolean(gint operand, GArray *a, GArray *b)
767 {
768         int     i, j, len_a, len_b;
769         guint32 val_a;
770
771         len_a = a->len;
772         len_b = b->len;
773
774
775         switch(operand) {
776         case TOK_EQ:
777                 for(i = 0; i < len_a; i++) {
778                         val_a = g_array_index(a, guint32, i);
779                         for (j = 0; j < len_b; j++) {
780                                 if (val_a == g_array_index(b, guint32, j))
781                                         return TRUE;
782                         }
783                 }
784                 return FALSE;
785
786         case TOK_NE:
787                 for(i = 0; i < len_a; i++) {
788                         val_a = g_array_index(a, guint32, i);
789                         for (j = 0; j < len_b; j++) {
790                                 if (val_a != g_array_index(b, guint32, j))
791                                         return TRUE;
792                         }
793                 }
794                 return FALSE;
795
796         default:
797                 g_assert_not_reached();
798         }
799
800         g_assert_not_reached();
801         return FALSE;
802 }
803