6fa05ccbe8fe0b4c374f070a6fd00e1369c6ffe9
[obnox/wireshark/wip.git] / dfilter.c
1 /* dfilter.c
2  * Routines for display filters
3  *
4  * $Id: dfilter.c,v 1.24 1999/10/07 21:47:18 guy 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         /* Errors not found by the parser may not cause the parse to
171          * fail; if "dfilter_error_msg" is set, it means somebody
172          * else called "dfilter_error()", e.g. the lexical analyzer,
173          * so treat that as a parse error. */
174         if (dfilter_error_msg != NULL)
175                 retval = 1;
176
177         if (retval != 0) {
178                 if (dfilter_error_msg == NULL) {
179                         snprintf(dfilter_error_msg_buf, sizeof(dfilter_error_msg_buf),
180                                 "Unable to parse filter string \"%s\".",
181                                 dfilter_text);
182                 } else {
183                         /* An error message was supplied; use it in the
184                          * error we display. */
185                         snprintf(dfilter_error_msg_buf, sizeof(dfilter_error_msg_buf),
186                                 "Unable to parse filter string \"%s\": %s.",
187                                 dfilter_text, dfilter_error_msg);
188                 }
189                 dfilter_error_msg = &dfilter_error_msg_buf[0];
190         }
191
192         /* Clear the list of allocated nodes */
193         if (gnode_slist) {
194                 g_slist_free(gnode_slist);
195                 gnode_slist = NULL;
196         }
197
198         return retval;
199 }
200
201 /* clear the current filter, w/o clearing memchunk area which is where we'll
202  * put new nodes in a future filter */
203 void
204 dfilter_clear_filter(dfilter *df)
205 {
206         if (!df)
207                 return;
208
209         if (df->dftext)
210                 g_free(df->dftext);
211
212         if (df->dftree != NULL)
213                 g_node_destroy(df->dftree);
214
215         /* clear the memory that the tree was using for nodes */
216         if (df->node_memchunk)
217                 g_mem_chunk_reset(df->node_memchunk);
218
219         /* clear the memory that the tree was using for byte arrays */
220         if (df->list_of_byte_arrays) {
221                 g_slist_foreach(df->list_of_byte_arrays, clear_byte_array, NULL);
222                 g_slist_free(df->list_of_byte_arrays);
223         }
224
225         df->dftext = NULL;
226         df->dftree = NULL;
227         df->list_of_byte_arrays = NULL;
228 }
229
230 /* Allocates new dfilter, initializes values, and returns pointer to dfilter */
231 dfilter*
232 dfilter_new(void)
233 {
234         dfilter *df;
235
236         df = g_malloc(sizeof(dfilter));
237
238         df->dftext = NULL;
239         df->dftree = NULL;
240         df->node_memchunk = g_mem_chunk_new("df->node_memchunk",
241                 sizeof(dfilter_node), 20 * sizeof(dfilter_node), G_ALLOC_ONLY);
242         df->list_of_byte_arrays = NULL;
243
244         return df;
245 }
246
247 /* Frees all memory used by dfilter, and frees dfilter itself */
248 void
249 dfilter_destroy(dfilter *df)
250 {
251         if (!df)
252                 return;
253
254         dfilter_clear_filter(df);
255
256         /* Git rid of memchunk */
257         if (df->node_memchunk)
258                 g_mem_chunk_destroy(df->node_memchunk);
259
260         g_free(df);
261 }
262
263
264 static void
265 clear_byte_array(gpointer data, gpointer user_data)
266 {
267         GByteArray *barray = data;
268         if (barray)
269                 g_byte_array_free(barray, TRUE);
270 }
271
272 /* Called when the yacc grammar finds a parsing error */
273 void
274 dfilter_error(char *s)
275 {
276         /* Remember the error message we were handed, unless it's
277          * the boring "parse error" message used by YACC.
278          */
279         if (strcmp(s, "parse error") != 0)
280                 dfilter_error_msg = s;
281
282         /* The only data we have to worry about freeing is the
283          * data used by any GNodes that were allocated during
284          * parsing. The data in those Gnodes will be cleared
285          * later via df->node_memchunk. Use gnode_slist to
286          * clear the GNodes, and set global_df to NULL just
287          * to be tidy.
288          */
289         global_df = NULL;
290
291         /* I don't want to call g_node_destroy on each GNode ptr,
292          * since that function frees any children. That could
293          * mess me up later in the list if I try to free a GNode
294          * that has already been freed. So, I'll unlink the
295          * children firs,t then call g_node_destroy on each GNode ptr.
296          */
297         if (!gnode_slist)
298                 return;
299
300         g_slist_foreach(gnode_slist, unlink_gnode_children, NULL);
301         g_slist_foreach(gnode_slist, destroy_gnode, NULL);
302
303         /* notice we don't clear gnode_slist itself. dfilter_compile()
304          * will take care of that.
305          */
306 }
307
308 static void
309 unlink_gnode_children(gpointer gnode_ptr, gpointer user_data)
310 {
311         if (gnode_ptr)
312                 g_node_unlink((GNode*) gnode_ptr);
313 }
314
315 static void
316 destroy_gnode(gpointer gnode_ptr, gpointer user_data)
317 {
318         if (gnode_ptr)
319                 g_node_destroy((GNode*) gnode_ptr);
320 }
321
322
323 /* lookup an abbreviation in our token tree, returing the ID #
324  * If the abbreviation doesn't exit, returns -1 */
325 int dfilter_lookup_token(char *abbrev)
326 {
327         int value;
328
329         g_assert(abbrev != NULL);
330         value =  GPOINTER_TO_INT(g_tree_lookup(dfilter_tokens, abbrev));
331
332         if (value < DFILTER_LEX_ABBREV_OFFSET) {
333                 return -1;
334         }
335         return value - DFILTER_LEX_ABBREV_OFFSET;
336 }
337
338 static int
339 g_strcmp(gconstpointer a, gconstpointer b)
340 {
341         return strcmp((const char*)a, (const char*)b);
342 }
343
344
345 gboolean
346 dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd)
347 {
348         gboolean retval;
349         if (dfcode == NULL)
350                 return FALSE;
351         retval = dfilter_apply_node(dfcode->dftree, ptree, pd);
352         return retval;
353 }
354
355 static gboolean
356 dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd)
357 {
358         GNode           *gnode_a, *gnode_b;
359         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
360
361         /* We'll get 2 NULLs if we don't have children */
362         gnode_a = g_node_nth_child(gnode, 0);
363         gnode_b = g_node_nth_child(gnode, 1);
364
365         switch(dnode->ntype) {
366         case variable:
367                 /* We'll never see this case because if the parser finds the name of
368                  * a variable, it will cause it to be an 'existence' operation.
369                  */
370                 g_assert_not_reached();
371
372         case logical:
373                 g_assert(gnode_a);
374                 return check_logical(dnode->value.logical, gnode_a, gnode_b, ptree, pd);
375
376         case relation:
377                 g_assert(gnode_a && gnode_b);
378                 return check_relation(dnode->value.relation, gnode_a, gnode_b, ptree, pd);
379
380         case alternation:
381                 g_assert_not_reached();
382                 /* not coded yet */
383         
384         case numeric:
385         case ipv4:
386         case boolean:
387         case ether:
388         case string:
389         case abs_time:
390         case bytes:
391         case ipxnet:
392                 /* the only time we'll see these at this point is if the display filter
393                  * is really wacky. (like simply "192.168.1.1"). The parser as it stands
394                  * now let these by. Just return TRUE */
395                 g_assert(!gnode_a && !gnode_b);
396                 return TRUE;
397
398         case existence: /* checking the existence of a protocol or hf*/
399                 g_assert(!gnode_a && !gnode_b);
400                 return check_existence_in_ptree(dnode, ptree);
401         }
402
403         g_assert_not_reached();
404         return FALSE;
405 }
406
407 static gboolean
408 check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd)
409 {
410         gboolean val_a = dfilter_apply_node(a, ptree, pd);
411         gboolean val_b;
412
413         switch(operand) {
414         case TOK_AND:
415                 g_assert(b);
416                 return (val_a && dfilter_apply_node(b, ptree, pd));
417         case TOK_OR:
418                 g_assert(b);
419                 return (val_a || dfilter_apply_node(b, ptree, pd));
420         case TOK_XOR:
421                 g_assert(b);
422                 val_b = dfilter_apply_node(b, ptree, pd);
423                 return ( ( val_a || val_b ) && ! ( val_a && val_b ) );
424         case TOK_NOT:
425                 return (!val_a);
426         default:
427                 g_assert_not_reached();
428         }       
429         g_assert_not_reached();
430         return FALSE;
431 }
432
433 /* this is inefficient. I get arrays for both a and b that represent all the values present. That is,
434  * if a is bootp.option, e.g., i'll get an array showing all the bootp.option values in the protocol
435  * tree. Then I'll get an array for b, which more than likely is a single int, and then I'll compare
436  * them all. It makes my coding easier in the beginning, but I should change this to make it run
437  * faster.
438  */
439 static gboolean
440 check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8* pd)
441 {
442         dfilter_node    *node_a = (dfilter_node*) (a->data);
443         dfilter_node    *node_b = (dfilter_node*) (b->data);
444         GArray          *vals_a, *vals_b;
445         gboolean        retval;
446
447
448         bytes_length = MIN(node_a->length, node_b->length);
449         bytes_offset = MIN(node_a->offset, node_b->offset);
450         if (node_a->ntype == variable)
451                 vals_a = get_values_from_ptree(node_a, ptree, pd);
452         else
453                 vals_a = get_values_from_dfilter(node_a, a);
454
455         if (node_b->ntype == variable)
456                 vals_b = get_values_from_ptree(node_b, ptree, pd);
457         else
458                 vals_b = get_values_from_dfilter(node_b, b);
459
460         retval =  node_a->check_relation_func(operand, vals_a, vals_b);
461
462         g_array_free(vals_a, FALSE);
463         g_array_free(vals_b, FALSE);
464
465         return retval;
466 }
467
468 static gboolean
469 check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree)
470 {
471         int             target;
472
473         target = dnode->value.variable;
474         return proto_check_for_protocol_or_field(ptree, target);
475 }
476
477 static GArray*
478 get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd)
479 {
480         GArray          *array;
481         int             parent_protocol;
482         proto_tree_search_info sinfo;
483
484         g_assert(dnode->elem_size > 0);
485         array = g_array_new(FALSE, FALSE, dnode->elem_size);
486
487         sinfo.target = dnode->value.variable;
488         sinfo.result.array = array;
489         sinfo.packet_data = pd;
490         sinfo.traverse_func = dnode->fill_array_func;
491
492         /* Find the proto_tree subtree where we should start searching.*/
493         if (proto_registrar_is_protocol(sinfo.target)) {
494                 proto_find_protocol_multi(ptree, sinfo.target,
495                                 (GNodeTraverseFunc)proto_get_field_values, &sinfo);
496         }
497         else {
498                 parent_protocol = proto_registrar_get_parent(sinfo.target);
499                 if (parent_protocol >= 0) {
500                         proto_find_protocol_multi(ptree, parent_protocol,
501                                         (GNodeTraverseFunc)proto_get_field_values, &sinfo);
502                 }
503         }
504
505         return array;
506 }
507
508 static GArray*
509 get_values_from_dfilter(dfilter_node *dnode, GNode *gnode)
510 {
511         GArray          *array;
512
513         g_assert(dnode->elem_size > 0);
514         array = g_array_new(FALSE, FALSE, dnode->elem_size);
515
516         g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, dnode->fill_array_func, array);
517 /*      dnode->fill_array_func(gnode, array);*/
518         return array;
519 }
520
521 gboolean fill_array_numeric_variable(GNode *gnode, gpointer data)
522 {
523         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
524         field_info              *fi = (field_info*) (gnode->data);
525
526         if (fi->hfinfo->id == sinfo->target) {
527                 g_array_append_val(sinfo->result.array, fi->value.numeric);
528         }
529
530         return FALSE; /* FALSE = do not end traversal of GNode tree */
531 }
532
533 gboolean fill_array_ether_variable(GNode *gnode, gpointer data)
534 {
535         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
536         field_info              *fi = (field_info*) (gnode->data);
537
538         if (fi->hfinfo->id == sinfo->target) {
539                 g_array_append_val(sinfo->result.array, fi->value.ether);
540         }
541
542         return FALSE; /* FALSE = do not end traversal of GNode tree */
543 }
544
545 gboolean fill_array_bytes_variable(GNode *gnode, gpointer data)
546 {
547         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
548         field_info              *fi = (field_info*) (gnode->data);
549         GByteArray              *barray;
550
551         if (fi->hfinfo->id == sinfo->target) {
552                 barray = g_byte_array_new();
553                 /*list_of_byte_arrays = g_slist_append(list_of_byte_arrays, barray);*/
554                 g_byte_array_append(barray, sinfo->packet_data + fi->start + bytes_offset, bytes_length);
555                 g_array_append_val(sinfo->result.array, barray);
556         }
557
558         return FALSE; /* FALSE = do not end traversal of GNode tree */
559 }
560
561 gboolean fill_array_numeric_value(GNode *gnode, gpointer data)
562 {
563         GArray          *array = (GArray*)data;
564         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
565
566         g_array_append_val(array, dnode->value.numeric);
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 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 }