Have "get_host_ipaddr()" return a Boolean indicating whether it
[obnox/wireshark/wip.git] / dfilter.c
1 /* dfilter.c
2  * Routines for display filters
3  *
4  * $Id: dfilter.c,v 1.25 1999/10/11 03:03:10 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_fail()", 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                         dfilter_error_msg = &dfilter_error_msg_buf[0];
183                 }
184         }
185
186         /* Clear the list of allocated nodes */
187         if (gnode_slist) {
188                 g_slist_free(gnode_slist);
189                 gnode_slist = NULL;
190         }
191
192         return retval;
193 }
194
195 /* clear the current filter, w/o clearing memchunk area which is where we'll
196  * put new nodes in a future filter */
197 void
198 dfilter_clear_filter(dfilter *df)
199 {
200         if (!df)
201                 return;
202
203         if (df->dftext)
204                 g_free(df->dftext);
205
206         if (df->dftree != NULL)
207                 g_node_destroy(df->dftree);
208
209         /* clear the memory that the tree was using for nodes */
210         if (df->node_memchunk)
211                 g_mem_chunk_reset(df->node_memchunk);
212
213         /* clear the memory that the tree was using for byte arrays */
214         if (df->list_of_byte_arrays) {
215                 g_slist_foreach(df->list_of_byte_arrays, clear_byte_array, NULL);
216                 g_slist_free(df->list_of_byte_arrays);
217         }
218
219         df->dftext = NULL;
220         df->dftree = NULL;
221         df->list_of_byte_arrays = NULL;
222 }
223
224 /* Allocates new dfilter, initializes values, and returns pointer to dfilter */
225 dfilter*
226 dfilter_new(void)
227 {
228         dfilter *df;
229
230         df = g_malloc(sizeof(dfilter));
231
232         df->dftext = NULL;
233         df->dftree = NULL;
234         df->node_memchunk = g_mem_chunk_new("df->node_memchunk",
235                 sizeof(dfilter_node), 20 * sizeof(dfilter_node), G_ALLOC_ONLY);
236         df->list_of_byte_arrays = NULL;
237
238         return df;
239 }
240
241 /* Frees all memory used by dfilter, and frees dfilter itself */
242 void
243 dfilter_destroy(dfilter *df)
244 {
245         if (!df)
246                 return;
247
248         dfilter_clear_filter(df);
249
250         /* Git rid of memchunk */
251         if (df->node_memchunk)
252                 g_mem_chunk_destroy(df->node_memchunk);
253
254         g_free(df);
255 }
256
257
258 static void
259 clear_byte_array(gpointer data, gpointer user_data)
260 {
261         GByteArray *barray = data;
262         if (barray)
263                 g_byte_array_free(barray, TRUE);
264 }
265
266 /* Called when the yacc grammar finds a parsing error */
267 void
268 dfilter_error(char *s)
269 {
270         /* The only data we have to worry about freeing is the
271          * data used by any GNodes that were allocated during
272          * parsing. The data in those Gnodes will be cleared
273          * later via df->node_memchunk. Use gnode_slist to
274          * clear the GNodes, and set global_df to NULL just
275          * to be tidy.
276          */
277         global_df = NULL;
278
279         /* I don't want to call g_node_destroy on each GNode ptr,
280          * since that function frees any children. That could
281          * mess me up later in the list if I try to free a GNode
282          * that has already been freed. So, I'll unlink the
283          * children firs,t then call g_node_destroy on each GNode ptr.
284          */
285         if (!gnode_slist)
286                 return;
287
288         g_slist_foreach(gnode_slist, unlink_gnode_children, NULL);
289         g_slist_foreach(gnode_slist, destroy_gnode, NULL);
290
291         /* notice we don't clear gnode_slist itself. dfilter_compile()
292          * will take care of that.
293          */
294 }
295
296 /* Called when an error other than a parsing error occurs. */
297 void
298 dfilter_fail(char *format, ...)
299 {
300   va_list    ap;
301
302   /* If we've already reported one error, don't overwrite it with this
303    * one. */
304   if (dfilter_error_msg != NULL)
305     return;
306
307   va_start(ap, format);
308   vsnprintf(dfilter_error_msg_buf, sizeof dfilter_error_msg_buf, format, ap);
309   dfilter_error_msg = dfilter_error_msg_buf;
310   va_end(ap);
311 }
312
313 static void
314 unlink_gnode_children(gpointer gnode_ptr, gpointer user_data)
315 {
316         if (gnode_ptr)
317                 g_node_unlink((GNode*) gnode_ptr);
318 }
319
320 static void
321 destroy_gnode(gpointer gnode_ptr, gpointer user_data)
322 {
323         if (gnode_ptr)
324                 g_node_destroy((GNode*) gnode_ptr);
325 }
326
327
328 /* lookup an abbreviation in our token tree, returing the ID #
329  * If the abbreviation doesn't exit, returns -1 */
330 int dfilter_lookup_token(char *abbrev)
331 {
332         int value;
333
334         g_assert(abbrev != NULL);
335         value =  GPOINTER_TO_INT(g_tree_lookup(dfilter_tokens, abbrev));
336
337         if (value < DFILTER_LEX_ABBREV_OFFSET) {
338                 return -1;
339         }
340         return value - DFILTER_LEX_ABBREV_OFFSET;
341 }
342
343 static int
344 g_strcmp(gconstpointer a, gconstpointer b)
345 {
346         return strcmp((const char*)a, (const char*)b);
347 }
348
349
350 gboolean
351 dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd)
352 {
353         gboolean retval;
354         if (dfcode == NULL)
355                 return FALSE;
356         retval = dfilter_apply_node(dfcode->dftree, ptree, pd);
357         return retval;
358 }
359
360 static gboolean
361 dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd)
362 {
363         GNode           *gnode_a, *gnode_b;
364         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
365
366         /* We'll get 2 NULLs if we don't have children */
367         gnode_a = g_node_nth_child(gnode, 0);
368         gnode_b = g_node_nth_child(gnode, 1);
369
370         switch(dnode->ntype) {
371         case variable:
372                 /* We'll never see this case because if the parser finds the name of
373                  * a variable, it will cause it to be an 'existence' operation.
374                  */
375                 g_assert_not_reached();
376
377         case logical:
378                 g_assert(gnode_a);
379                 return check_logical(dnode->value.logical, gnode_a, gnode_b, ptree, pd);
380
381         case relation:
382                 g_assert(gnode_a && gnode_b);
383                 return check_relation(dnode->value.relation, gnode_a, gnode_b, ptree, pd);
384
385         case alternation:
386                 g_assert_not_reached();
387                 /* not coded yet */
388         
389         case numeric:
390         case ipv4:
391         case boolean:
392         case ether:
393         case string:
394         case abs_time:
395         case bytes:
396         case ipxnet:
397                 /* the only time we'll see these at this point is if the display filter
398                  * is really wacky. (like simply "192.168.1.1"). The parser as it stands
399                  * now let these by. Just return TRUE */
400                 g_assert(!gnode_a && !gnode_b);
401                 return TRUE;
402
403         case existence: /* checking the existence of a protocol or hf*/
404                 g_assert(!gnode_a && !gnode_b);
405                 return check_existence_in_ptree(dnode, ptree);
406         }
407
408         g_assert_not_reached();
409         return FALSE;
410 }
411
412 static gboolean
413 check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd)
414 {
415         gboolean val_a = dfilter_apply_node(a, ptree, pd);
416         gboolean val_b;
417
418         switch(operand) {
419         case TOK_AND:
420                 g_assert(b);
421                 return (val_a && dfilter_apply_node(b, ptree, pd));
422         case TOK_OR:
423                 g_assert(b);
424                 return (val_a || dfilter_apply_node(b, ptree, pd));
425         case TOK_XOR:
426                 g_assert(b);
427                 val_b = dfilter_apply_node(b, ptree, pd);
428                 return ( ( val_a || val_b ) && ! ( val_a && val_b ) );
429         case TOK_NOT:
430                 return (!val_a);
431         default:
432                 g_assert_not_reached();
433         }       
434         g_assert_not_reached();
435         return FALSE;
436 }
437
438 /* this is inefficient. I get arrays for both a and b that represent all the values present. That is,
439  * if a is bootp.option, e.g., i'll get an array showing all the bootp.option values in the protocol
440  * tree. Then I'll get an array for b, which more than likely is a single int, and then I'll compare
441  * them all. It makes my coding easier in the beginning, but I should change this to make it run
442  * faster.
443  */
444 static gboolean
445 check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8* pd)
446 {
447         dfilter_node    *node_a = (dfilter_node*) (a->data);
448         dfilter_node    *node_b = (dfilter_node*) (b->data);
449         GArray          *vals_a, *vals_b;
450         gboolean        retval;
451
452
453         bytes_length = MIN(node_a->length, node_b->length);
454         bytes_offset = MIN(node_a->offset, node_b->offset);
455         if (node_a->ntype == variable)
456                 vals_a = get_values_from_ptree(node_a, ptree, pd);
457         else
458                 vals_a = get_values_from_dfilter(node_a, a);
459
460         if (node_b->ntype == variable)
461                 vals_b = get_values_from_ptree(node_b, ptree, pd);
462         else
463                 vals_b = get_values_from_dfilter(node_b, b);
464
465         retval =  node_a->check_relation_func(operand, vals_a, vals_b);
466
467         g_array_free(vals_a, FALSE);
468         g_array_free(vals_b, FALSE);
469
470         return retval;
471 }
472
473 static gboolean
474 check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree)
475 {
476         int             target;
477
478         target = dnode->value.variable;
479         return proto_check_for_protocol_or_field(ptree, target);
480 }
481
482 static GArray*
483 get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd)
484 {
485         GArray          *array;
486         int             parent_protocol;
487         proto_tree_search_info sinfo;
488
489         g_assert(dnode->elem_size > 0);
490         array = g_array_new(FALSE, FALSE, dnode->elem_size);
491
492         sinfo.target = dnode->value.variable;
493         sinfo.result.array = array;
494         sinfo.packet_data = pd;
495         sinfo.traverse_func = dnode->fill_array_func;
496
497         /* Find the proto_tree subtree where we should start searching.*/
498         if (proto_registrar_is_protocol(sinfo.target)) {
499                 proto_find_protocol_multi(ptree, sinfo.target,
500                                 (GNodeTraverseFunc)proto_get_field_values, &sinfo);
501         }
502         else {
503                 parent_protocol = proto_registrar_get_parent(sinfo.target);
504                 if (parent_protocol >= 0) {
505                         proto_find_protocol_multi(ptree, parent_protocol,
506                                         (GNodeTraverseFunc)proto_get_field_values, &sinfo);
507                 }
508         }
509
510         return array;
511 }
512
513 static GArray*
514 get_values_from_dfilter(dfilter_node *dnode, GNode *gnode)
515 {
516         GArray          *array;
517
518         g_assert(dnode->elem_size > 0);
519         array = g_array_new(FALSE, FALSE, dnode->elem_size);
520
521         g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, dnode->fill_array_func, array);
522 /*      dnode->fill_array_func(gnode, array);*/
523         return array;
524 }
525
526 gboolean fill_array_numeric_variable(GNode *gnode, gpointer data)
527 {
528         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
529         field_info              *fi = (field_info*) (gnode->data);
530
531         if (fi->hfinfo->id == sinfo->target) {
532                 g_array_append_val(sinfo->result.array, fi->value.numeric);
533         }
534
535         return FALSE; /* FALSE = do not end traversal of GNode tree */
536 }
537
538 gboolean fill_array_ether_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.ether);
545         }
546
547         return FALSE; /* FALSE = do not end traversal of GNode tree */
548 }
549
550 gboolean fill_array_bytes_variable(GNode *gnode, gpointer data)
551 {
552         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
553         field_info              *fi = (field_info*) (gnode->data);
554         GByteArray              *barray;
555
556         if (fi->hfinfo->id == sinfo->target) {
557                 barray = g_byte_array_new();
558                 /*list_of_byte_arrays = g_slist_append(list_of_byte_arrays, barray);*/
559                 g_byte_array_append(barray, sinfo->packet_data + fi->start + bytes_offset, bytes_length);
560                 g_array_append_val(sinfo->result.array, barray);
561         }
562
563         return FALSE; /* FALSE = do not end traversal of GNode tree */
564 }
565
566 gboolean fill_array_numeric_value(GNode *gnode, gpointer data)
567 {
568         GArray          *array = (GArray*)data;
569         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
570
571         g_array_append_val(array, dnode->value.numeric);
572         return FALSE; /* FALSE = do not end traversal of GNode tree */
573 }
574
575 gboolean fill_array_ether_value(GNode *gnode, gpointer data)
576 {
577         GArray          *array = (GArray*)data;
578         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
579
580         g_array_append_val(array, dnode->value.ether);
581
582         return FALSE; /* FALSE = do not end traversal of GNode tree */
583 }
584
585 gboolean fill_array_bytes_value(GNode *gnode, gpointer data)
586 {
587         GArray          *array = (GArray*)data;
588         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
589         GByteArray      *barray = dnode->value.bytes;
590
591         g_array_append_val(array, barray);
592
593         return FALSE; /* FALSE = do not end traversal of GNode tree */
594 }
595
596 gboolean check_relation_numeric(gint operand, GArray *a, GArray *b)
597 {
598         int     i, j, len_a, len_b;
599         guint32 val_a;
600
601         len_a = a->len;
602         len_b = b->len;
603
604
605         switch(operand) {
606         case TOK_EQ:
607                 for(i = 0; i < len_a; i++) {
608                         val_a = g_array_index(a, guint32, i);
609                         for (j = 0; j < len_b; j++) {
610                                 if (val_a == g_array_index(b, guint32, j))
611                                         return TRUE;
612                         }
613                 }
614                 return FALSE;
615
616         case TOK_NE:
617                 for(i = 0; i < len_a; i++) {
618                         val_a = g_array_index(a, guint32, i);
619                         for (j = 0; j < len_b; j++) {
620                                 if (val_a != g_array_index(b, guint32, j))
621                                         return TRUE;
622                         }
623                 }
624                 return FALSE;
625
626         case TOK_GT:
627                 for(i = 0; i < len_a; i++) {
628                         val_a = g_array_index(a, guint32, i);
629                         for (j = 0; j < len_b; j++) {
630                                 if (val_a > g_array_index(b, guint32, j))
631                                         return TRUE;
632                         }
633                 }
634                 return FALSE;
635
636         case TOK_GE:
637                 for(i = 0; i < len_a; i++) {
638                         val_a = g_array_index(a, guint32, i);
639                         for (j = 0; j < len_b; j++) {
640                                 if (val_a >= g_array_index(b, guint32, j))
641                                         return TRUE;
642                         }
643                 }
644                 return FALSE;
645
646         case TOK_LT:
647                 for(i = 0; i < len_a; i++) {
648                         val_a = g_array_index(a, guint32, i);
649                         for (j = 0; j < len_b; j++) {
650                                 if (val_a < g_array_index(b, guint32, j))
651                                         return TRUE;
652                         }
653                 }
654                 return FALSE;
655
656         case TOK_LE:
657                 for(i = 0; i < len_a; i++) {
658                         val_a = g_array_index(a, guint32, i);
659                         for (j = 0; j < len_b; j++) {
660                                 if (val_a <= g_array_index(b, guint32, j))
661                                         return TRUE;
662                         }
663                 }
664                 return FALSE;
665
666         default:
667                 g_assert_not_reached();
668         }
669
670         g_assert_not_reached();
671         return FALSE;
672 }
673
674
675 gboolean check_relation_ether(gint operand, GArray *a, GArray *b)
676 {
677         int     i, j, len_a, len_b;
678         guint8  *ptr_a, *ptr_b;
679
680         len_a = a->len;
681         len_b = b->len;
682
683
684         switch(operand) {
685         case TOK_EQ:
686                 for(i = 0; i < len_a; i++) {
687                         ptr_a = g_array_index_ptr(a, 6, i);
688                         for (j = 0; j < len_b; j++) {
689                                 ptr_b = g_array_index_ptr(b, 6, j);
690                                 if (memcmp(ptr_a, ptr_b, 6) == 0)
691                                         return TRUE;
692                         }
693                 }
694                 return FALSE;
695
696         case TOK_NE:
697                 for(i = 0; i < len_a; i++) {
698                         ptr_a = g_array_index_ptr(a, 6, i);
699                         for (j = 0; j < len_b; j++) {
700                                 ptr_b = g_array_index_ptr(b, 6, j);
701                                 if (memcmp(ptr_a, ptr_b, 6) != 0)
702                                         return TRUE;
703                         }
704                 }
705                 return FALSE;
706         }
707
708         g_assert_not_reached();
709         return FALSE;
710 }
711
712 gboolean check_relation_bytes(gint operand, GArray *a, GArray *b)
713 {
714         int     i, j, len_a, len_b;
715         GByteArray      *ptr_a,*ptr_b;
716
717         len_a = a->len;
718         len_b = b->len;
719
720
721         switch(operand) {
722         case TOK_EQ:
723                 for(i = 0; i < len_a; i++) {
724                         ptr_a = g_array_index(a, GByteArray*, i);
725                         for (j = 0; j < len_b; j++) {
726                                 ptr_b = g_array_index(b, GByteArray*, j);
727                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) == 0)
728                                         return TRUE;
729                         }
730                 }
731                 return FALSE;
732
733         case TOK_NE:
734                 for(i = 0; i < len_a; i++) {
735                         ptr_a = g_array_index(a, GByteArray*, i);
736                         for (j = 0; j < len_b; j++) {
737                                 ptr_b = g_array_index(b, GByteArray*, j);
738                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) != 0)
739                                         return TRUE;
740                         }
741                 }
742                 return FALSE;
743
744         case TOK_GT:
745                 for(i = 0; i < len_a; i++) {
746                         ptr_a = g_array_index(a, GByteArray*, i);
747                         for (j = 0; j < len_b; j++) {
748                                 ptr_b = g_array_index(b, GByteArray*, j);
749                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) > 0)
750                                         return TRUE;
751                         }
752                 }
753                 return FALSE;
754
755         case TOK_LT:
756                 for(i = 0; i < len_a; i++) {
757                         ptr_a = g_array_index(a, GByteArray*, i);
758                         for (j = 0; j < len_b; j++) {
759                                 ptr_b = g_array_index(b, GByteArray*, j);
760                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) < 0)
761                                         return TRUE;
762                         }
763                 }
764                 return FALSE;
765         }
766
767         g_assert_not_reached();
768         return FALSE;
769 }