In "dissect_eth()", update "pi.len" and "pi.captured_len" regardless of
[obnox/wireshark/wip.git] / dfilter.c
1 /* dfilter.c
2  * Routines for display filters
3  *
4  * $Id: dfilter.c,v 1.32 1999/11/15 06:32:13 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
98 /* this is not so pretty. I need my own g_array "function" (macro) to
99  * retreive the pointer to the data stored in an array cell. I need this
100  * for type ether.. GArray makes it easy for me to store 6 bytes inside an array
101  * cell, but hard to retrieve it.
102  */
103 #define g_array_index_ptr(a,s,i)      (((guint8*) (a)->data) + (i*s))
104
105 void
106 dfilter_init(void)
107 {
108         int i, num_symbols, symbol;
109         char *s;
110
111         dfilter_tokens = g_tree_new(g_strcmp);
112
113         /* Add the header field and protocol abbrevs to the symbol table */
114         num_symbols = proto_registrar_n();
115         for (i=0; i < num_symbols; i++) {
116                 s = proto_registrar_get_abbrev(i);
117                 if (s) {
118                         symbol = DFILTER_LEX_ABBREV_OFFSET + i;
119                         g_tree_insert(dfilter_tokens, s, GINT_TO_POINTER(symbol));
120                 }
121         }
122 }
123
124 void
125 dfilter_cleanup(void)
126 {
127         if (dfilter_tokens)
128                 g_tree_destroy(dfilter_tokens);
129 }
130
131 /* Compiles the textual representation of the display filter into a tree
132  * of operations to perform. Can be called multiple times, compiling a new
133  * display filter each time, without having to clear any memory used, since
134  * dfilter_compile will take care of that automatically.
135  * 
136  * Returns 0 on success, non-zero on failure.
137  *
138  * On success, sets the "dfilter *" pointed to by its second argument
139  * either to a null pointer (if the filter is a null filter, as
140  * generated by an all-blank string) or to a pointer to a newly-allocated
141  * dfilter structure (if the filter isn't null).
142  *
143  * On failure, "dfilter_error_msg" points to an appropriate error message.
144  * This error message is a global string, so another invocation of
145  * dfilter_compile will clear it. If the caller needs is stored, he
146  * needs to g_strdup it himself.
147  */
148 int
149 dfilter_compile(gchar *dfilter_text, dfilter **dfp)
150 {
151         dfilter *df;
152         int retval;
153
154         g_assert(dfilter_text != NULL);
155
156         df = dfilter_new();
157
158         /* tell the scanner to use the filter string as input */
159         dfilter_scanner_text(dfilter_text);
160
161         /* Assign global variable so dfilter_parse knows which dfilter we're
162          * talking about. Reset the global error message.
163          */
164         global_df = df;
165         dfilter_error_msg = NULL;
166
167         /* The magic happens right here. */
168         retval = dfilter_parse();
169
170         /* clean up lex */
171         dfilter_scanner_cleanup();
172
173         /* Errors not found by the parser may not cause the parse to
174          * fail; if "dfilter_error_msg" is set, it means somebody
175          * else called "dfilter_fail()", e.g. the lexical analyzer,
176          * so treat that as a parse error. */
177         if (dfilter_error_msg != NULL)
178                 retval = 1;
179
180         if (retval != 0) {
181                 if (dfilter_error_msg == NULL) {
182                         snprintf(dfilter_error_msg_buf, sizeof(dfilter_error_msg_buf),
183                                 "Unable to parse filter string \"%s\".",
184                                 dfilter_text);
185                         dfilter_error_msg = &dfilter_error_msg_buf[0];
186                 }
187         }
188
189         /* Set global_df to NULL just to be tidy. */
190         global_df = NULL;
191
192         if (retval == 0) {
193                 /* Success.  Check if the filter is empty; if so, discard
194                  * it and set "*dfp" to NULL, otherwise set "*dfp" to
195                  * point to the filter. */
196                 if (df->dftree == NULL) {
197                         /* The filter is empty. */
198                         dfilter_destroy(df);
199                         df = NULL;
200                 }
201                 *dfp = df;
202         } else {
203                 /* Failure.  Destroy the filter. */
204                 dfilter_destroy(df);
205                 df = NULL;
206         }
207         return retval;
208 }
209
210 /* Allocates new dfilter, initializes values, and returns pointer to dfilter */
211 dfilter*
212 dfilter_new(void)
213 {
214         dfilter *df;
215
216         df = g_malloc(sizeof(dfilter));
217
218         df->dftree = NULL;
219         df->node_memchunk = g_mem_chunk_new("df->node_memchunk",
220                 sizeof(dfilter_node), 20 * sizeof(dfilter_node), G_ALLOC_ONLY);
221         df->list_of_byte_arrays = NULL;
222
223         return df;
224 }
225
226 /* Frees all memory used by dfilter, and frees dfilter itself */
227 void
228 dfilter_destroy(dfilter *df)
229 {
230         if (!df)
231                 return;
232
233         if (df->dftree != NULL)
234                 g_node_destroy(df->dftree);
235
236         /* clear the memory that the tree was using for nodes */
237         if (df->node_memchunk)
238                 g_mem_chunk_reset(df->node_memchunk);
239
240         /* clear the memory that the tree was using for byte arrays */
241         if (df->list_of_byte_arrays) {
242                 g_slist_foreach(df->list_of_byte_arrays, clear_byte_array, NULL);
243                 g_slist_free(df->list_of_byte_arrays);
244         }
245
246         df->dftree = NULL;
247         df->list_of_byte_arrays = NULL;
248
249         /* Git rid of memchunk */
250         if (df->node_memchunk)
251                 g_mem_chunk_destroy(df->node_memchunk);
252
253         g_free(df);
254 }
255
256
257 static void
258 clear_byte_array(gpointer data, gpointer user_data)
259 {
260         GByteArray *barray = data;
261         if (barray)
262                 g_byte_array_free(barray, TRUE);
263 }
264
265 /* Called when the yacc grammar finds a parsing error */
266 void
267 dfilter_error(char *s)
268 {
269 }
270
271 /* Called when an error other than a parsing error occurs. */
272 void
273 dfilter_fail(char *format, ...)
274 {
275         va_list    ap;
276
277         /* If we've already reported one error, don't overwrite it with this
278          * one. */
279         if (dfilter_error_msg != NULL)
280                 return;
281
282         va_start(ap, format);
283         vsnprintf(dfilter_error_msg_buf, sizeof dfilter_error_msg_buf, format, ap);
284         dfilter_error_msg = dfilter_error_msg_buf;
285         va_end(ap);
286 }
287
288 /* lookup an abbreviation in our token tree, returing the ID #
289  * If the abbreviation doesn't exit, returns -1 */
290 int dfilter_lookup_token(char *abbrev)
291 {
292         int value;
293
294         g_assert(abbrev != NULL);
295         value =  GPOINTER_TO_INT(g_tree_lookup(dfilter_tokens, abbrev));
296
297         if (value < DFILTER_LEX_ABBREV_OFFSET) {
298                 return -1;
299         }
300         return value - DFILTER_LEX_ABBREV_OFFSET;
301 }
302
303 static int
304 g_strcmp(gconstpointer a, gconstpointer b)
305 {
306         return strcmp((const char*)a, (const char*)b);
307 }
308
309
310 gboolean
311 dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd)
312 {
313         gboolean retval;
314         if (dfcode == NULL)
315                 return FALSE;
316         retval = dfilter_apply_node(dfcode->dftree, ptree, pd);
317         return retval;
318 }
319
320 static gboolean
321 dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd)
322 {
323         GNode           *gnode_a, *gnode_b;
324         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
325
326         /* We'll get 2 NULLs if we don't have children */
327         gnode_a = g_node_nth_child(gnode, 0);
328         gnode_b = g_node_nth_child(gnode, 1);
329
330         switch(dnode->ntype) {
331         case variable:
332                 /* We'll never see this case because if the parser finds the name of
333                  * a variable, it will cause it to be an 'existence' operation.
334                  */
335                 g_assert_not_reached();
336
337         case logical:
338                 g_assert(gnode_a);
339                 return check_logical(dnode->value.logical, gnode_a, gnode_b, ptree, pd);
340
341         case relation:
342                 g_assert(gnode_a && gnode_b);
343                 return check_relation(dnode->value.relation, gnode_a, gnode_b, ptree, pd);
344
345         case alternation:
346                 g_assert_not_reached();
347                 /* not coded yet */
348         
349         case numeric:
350         case floating:
351         case ipv4:
352         case ipv6:
353         case boolean:
354         case ether:
355         case string:
356         case abs_time:
357         case bytes:
358         case ipxnet:
359                 /* the only time we'll see these at this point is if the display filter
360                  * is really wacky. (like simply "192.168.1.1"). The parser as it stands
361                  * now let these by. Just return TRUE */
362                 g_assert(!gnode_a && !gnode_b);
363                 return TRUE;
364
365         case existence: /* checking the existence of a protocol or hf*/
366                 g_assert(!gnode_a && !gnode_b);
367                 return check_existence_in_ptree(dnode, ptree);
368         }
369
370         g_assert_not_reached();
371         return FALSE;
372 }
373
374 static gboolean
375 check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd)
376 {
377         gboolean val_a = dfilter_apply_node(a, ptree, pd);
378         gboolean val_b;
379
380         switch(operand) {
381         case TOK_AND:
382                 g_assert(b);
383                 return (val_a && dfilter_apply_node(b, ptree, pd));
384         case TOK_OR:
385                 g_assert(b);
386                 return (val_a || dfilter_apply_node(b, ptree, pd));
387         case TOK_XOR:
388                 g_assert(b);
389                 val_b = dfilter_apply_node(b, ptree, pd);
390                 return ( ( val_a || val_b ) && ! ( val_a && val_b ) );
391         case TOK_NOT:
392                 return (!val_a);
393         default:
394                 g_assert_not_reached();
395         }       
396         g_assert_not_reached();
397         return FALSE;
398 }
399
400 /* this is inefficient. I get arrays for both a and b that represent all the values present. That is,
401  * if a is bootp.option, e.g., i'll get an array showing all the bootp.option values in the protocol
402  * tree. Then I'll get an array for b, which more than likely is a single int, and then I'll compare
403  * them all. It makes my coding easier in the beginning, but I should change this to make it run
404  * faster.
405  */
406 static gboolean
407 check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8* pd)
408 {
409         dfilter_node    *node_a = (dfilter_node*) (a->data);
410         dfilter_node    *node_b = (dfilter_node*) (b->data);
411         GArray          *vals_a, *vals_b;
412         gboolean        retval;
413
414
415         bytes_length = MIN(node_a->length, node_b->length);
416         bytes_offset = MIN(node_a->offset, node_b->offset);
417         if (node_a->ntype == variable)
418                 vals_a = get_values_from_ptree(node_a, ptree, pd);
419         else
420                 vals_a = get_values_from_dfilter(node_a, a);
421
422         if (node_b->ntype == variable)
423                 vals_b = get_values_from_ptree(node_b, ptree, pd);
424         else
425                 vals_b = get_values_from_dfilter(node_b, b);
426
427         retval =  node_a->check_relation_func(operand, vals_a, vals_b);
428
429         g_array_free(vals_a, FALSE);
430         g_array_free(vals_b, FALSE);
431
432         return retval;
433 }
434
435 static gboolean
436 check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree)
437 {
438         int             target;
439
440         target = dnode->value.variable;
441         return proto_check_for_protocol_or_field(ptree, target);
442 }
443
444 static GArray*
445 get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd)
446 {
447         GArray          *array;
448         int             parent_protocol;
449         proto_tree_search_info sinfo;
450
451         g_assert(dnode->elem_size > 0);
452         array = g_array_new(FALSE, FALSE, dnode->elem_size);
453
454         sinfo.target = dnode->value.variable;
455         sinfo.result.array = array;
456         sinfo.packet_data = pd;
457         sinfo.traverse_func = dnode->fill_array_func;
458
459         /* Find the proto_tree subtree where we should start searching.*/
460         if (proto_registrar_is_protocol(sinfo.target)) {
461                 proto_find_protocol_multi(ptree, sinfo.target,
462                                 (GNodeTraverseFunc)proto_get_field_values, &sinfo);
463         }
464         else {
465                 parent_protocol = proto_registrar_get_parent(sinfo.target);
466                 if (parent_protocol >= 0) {
467                         proto_find_protocol_multi(ptree, parent_protocol,
468                                         (GNodeTraverseFunc)proto_get_field_values, &sinfo);
469                 }
470         }
471
472         return array;
473 }
474
475 static GArray*
476 get_values_from_dfilter(dfilter_node *dnode, GNode *gnode)
477 {
478         GArray          *array;
479
480         g_assert(dnode->elem_size > 0);
481         array = g_array_new(FALSE, FALSE, dnode->elem_size);
482
483         g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, dnode->fill_array_func, array);
484         return array;
485 }
486
487 gboolean fill_array_numeric_variable(GNode *gnode, gpointer data)
488 {
489         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
490         field_info              *fi = (field_info*) (gnode->data);
491
492         if (fi->hfinfo->id == sinfo->target) {
493                 g_array_append_val(sinfo->result.array, fi->value.numeric);
494         }
495
496         return FALSE; /* FALSE = do not end traversal of GNode tree */
497 }
498
499 gboolean fill_array_floating_variable(GNode *gnode, gpointer data)
500 {
501         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
502         field_info              *fi = (field_info*) (gnode->data);
503
504         if (fi->hfinfo->id == sinfo->target) {
505                 g_array_append_val(sinfo->result.array, fi->value.floating);
506         }
507
508         return FALSE; /* FALSE = do not end traversal of GNode tree */
509 }
510
511 gboolean fill_array_ether_variable(GNode *gnode, gpointer data)
512 {
513         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
514         field_info              *fi = (field_info*) (gnode->data);
515
516         if (fi->hfinfo->id == sinfo->target) {
517                 g_array_append_val(sinfo->result.array, fi->value.ether);
518         }
519
520         return FALSE; /* FALSE = do not end traversal of GNode tree */
521 }
522
523 gboolean fill_array_ipv4_variable(GNode *gnode, gpointer data)
524 {
525         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
526         field_info              *fi = (field_info*) (gnode->data);
527
528         if (fi->hfinfo->id == sinfo->target) {
529                 g_array_append_val(sinfo->result.array, fi->value.ipv4);
530         }
531
532         return FALSE; /* FALSE = do not end traversal of GNode tree */
533 }
534 gboolean fill_array_ipv6_variable(GNode *gnode, gpointer data)
535 {
536         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
537         field_info              *fi = (field_info*) (gnode->data);
538
539         if (fi->hfinfo->id == sinfo->target) {
540                 g_array_append_val(sinfo->result.array, fi->value.ipv6);
541         }
542
543         return FALSE; /* FALSE = do not end traversal of GNode tree */
544 }
545
546 gboolean fill_array_bytes_variable(GNode *gnode, gpointer data)
547 {
548         proto_tree_search_info  *sinfo = (proto_tree_search_info*)data;
549         field_info              *fi = (field_info*) (gnode->data);
550         GByteArray              *barray;
551         guint                   read_start, pkt_end;
552
553         if (fi->hfinfo->id == sinfo->target) {
554                 if (bytes_offset < 0) {
555                         /* Handle negative byte offsets */
556                         bytes_offset = fi->length + bytes_offset;
557                         if (bytes_offset < 0) {
558                                 goto FAIL;
559                         }
560                 }
561
562                 /* Check to make sure offset exists for this field */
563                 if (bytes_offset >= fi->length) {
564                         goto FAIL;
565                 }
566
567                 pkt_end = fi->start + fi->length;
568                 read_start = fi->start + bytes_offset;
569
570                 /* Check to make sure entire length requested is inside field */
571                 if (pkt_end < read_start + bytes_length) {
572                         goto FAIL;
573                 }
574
575                 barray = g_byte_array_new();
576                 g_byte_array_append(barray, sinfo->packet_data + read_start, bytes_length);
577                 g_array_append_val(sinfo->result.array, barray);
578         }
579
580  FAIL:
581         return FALSE; /* FALSE = do not end traversal of GNode tree */
582 }
583
584 gboolean fill_array_numeric_value(GNode *gnode, gpointer data)
585 {
586         GArray          *array = (GArray*)data;
587         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
588
589         g_array_append_val(array, dnode->value.numeric);
590         return FALSE; /* FALSE = do not end traversal of GNode tree */
591 }
592
593 gboolean fill_array_floating_value(GNode *gnode, gpointer data)
594 {
595         GArray          *array = (GArray*)data;
596         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
597
598         g_array_append_val(array, dnode->value.floating);
599         return FALSE; /* FALSE = do not end traversal of GNode tree */
600 }
601
602 gboolean fill_array_ether_value(GNode *gnode, gpointer data)
603 {
604         GArray          *array = (GArray*)data;
605         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
606
607         g_array_append_val(array, dnode->value.ether);
608
609         return FALSE; /* FALSE = do not end traversal of GNode tree */
610 }
611
612 gboolean fill_array_ipv4_value(GNode *gnode, gpointer data)
613 {
614         GArray          *array = (GArray*)data;
615         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
616
617         g_array_append_val(array, dnode->value.ipv4);
618
619         return FALSE; /* FALSE = do not end traversal of GNode tree */
620 }
621
622 gboolean fill_array_ipv6_value(GNode *gnode, gpointer data)
623 {
624         GArray          *array = (GArray*)data;
625         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
626
627         g_array_append_val(array, dnode->value.ipv6);
628
629         return FALSE; /* FALSE = do not end traversal of GNode tree */
630 }
631
632 gboolean fill_array_bytes_value(GNode *gnode, gpointer data)
633 {
634         GArray          *array = (GArray*)data;
635         dfilter_node    *dnode = (dfilter_node*) (gnode->data);
636         GByteArray      *barray = dnode->value.bytes;
637
638         g_array_append_val(array, barray);
639
640         return FALSE; /* FALSE = do not end traversal of GNode tree */
641 }
642
643 gboolean check_relation_numeric(gint operand, GArray *a, GArray *b)
644 {
645         int     i, j, len_a, len_b;
646         guint32 val_a;
647
648         len_a = a->len;
649         len_b = b->len;
650
651
652         switch(operand) {
653         case TOK_EQ:
654                 for(i = 0; i < len_a; i++) {
655                         val_a = g_array_index(a, guint32, i);
656                         for (j = 0; j < len_b; j++) {
657                                 if (val_a == g_array_index(b, guint32, j))
658                                         return TRUE;
659                         }
660                 }
661                 return FALSE;
662
663         case TOK_NE:
664                 for(i = 0; i < len_a; i++) {
665                         val_a = g_array_index(a, guint32, i);
666                         for (j = 0; j < len_b; j++) {
667                                 if (val_a != g_array_index(b, guint32, j))
668                                         return TRUE;
669                         }
670                 }
671                 return FALSE;
672
673         case TOK_GT:
674                 for(i = 0; i < len_a; i++) {
675                         val_a = g_array_index(a, guint32, i);
676                         for (j = 0; j < len_b; j++) {
677                                 if (val_a > g_array_index(b, guint32, j))
678                                         return TRUE;
679                         }
680                 }
681                 return FALSE;
682
683         case TOK_GE:
684                 for(i = 0; i < len_a; i++) {
685                         val_a = g_array_index(a, guint32, i);
686                         for (j = 0; j < len_b; j++) {
687                                 if (val_a >= g_array_index(b, guint32, j))
688                                         return TRUE;
689                         }
690                 }
691                 return FALSE;
692
693         case TOK_LT:
694                 for(i = 0; i < len_a; i++) {
695                         val_a = g_array_index(a, guint32, i);
696                         for (j = 0; j < len_b; j++) {
697                                 if (val_a < g_array_index(b, guint32, j))
698                                         return TRUE;
699                         }
700                 }
701                 return FALSE;
702
703         case TOK_LE:
704                 for(i = 0; i < len_a; i++) {
705                         val_a = g_array_index(a, guint32, i);
706                         for (j = 0; j < len_b; j++) {
707                                 if (val_a <= g_array_index(b, guint32, j))
708                                         return TRUE;
709                         }
710                 }
711                 return FALSE;
712
713         default:
714                 g_assert_not_reached();
715         }
716
717         g_assert_not_reached();
718         return FALSE;
719 }
720
721 gboolean check_relation_floating(gint operand, GArray *a, GArray *b)
722 {
723         int     i, j, len_a, len_b;
724         double  val_a;
725
726         len_a = a->len;
727         len_b = b->len;
728
729
730         switch(operand) {
731         case TOK_EQ:
732                 for(i = 0; i < len_a; i++) {
733                         val_a = g_array_index(a, double, i);
734                         for (j = 0; j < len_b; j++) {
735                                 if (val_a == g_array_index(b, double, j))
736                                         return TRUE;
737                         }
738                 }
739                 return FALSE;
740
741         case TOK_NE:
742                 for(i = 0; i < len_a; i++) {
743                         val_a = g_array_index(a, double, i);
744                         for (j = 0; j < len_b; j++) {
745                                 if (val_a != g_array_index(b, double, j))
746                                         return TRUE;
747                         }
748                 }
749                 return FALSE;
750
751         case TOK_GT:
752                 for(i = 0; i < len_a; i++) {
753                         val_a = g_array_index(a, double, i);
754                         for (j = 0; j < len_b; j++) {
755                                 if (val_a > g_array_index(b, double, j))
756                                         return TRUE;
757                         }
758                 }
759                 return FALSE;
760
761         case TOK_GE:
762                 for(i = 0; i < len_a; i++) {
763                         val_a = g_array_index(a, double, i);
764                         for (j = 0; j < len_b; j++) {
765                                 if (val_a >= g_array_index(b, double, j))
766                                         return TRUE;
767                         }
768                 }
769                 return FALSE;
770
771         case TOK_LT:
772                 for(i = 0; i < len_a; i++) {
773                         val_a = g_array_index(a, double, i);
774                         for (j = 0; j < len_b; j++) {
775                                 if (val_a < g_array_index(b, double, j))
776                                         return TRUE;
777                         }
778                 }
779                 return FALSE;
780
781         case TOK_LE:
782                 for(i = 0; i < len_a; i++) {
783                         val_a = g_array_index(a, double, i);
784                         for (j = 0; j < len_b; j++) {
785                                 if (val_a <= g_array_index(b, double, j))
786                                         return TRUE;
787                         }
788                 }
789                 return FALSE;
790
791         default:
792                 g_assert_not_reached();
793         }
794
795         g_assert_not_reached();
796         return FALSE;
797 }
798
799 gboolean check_relation_ipv4(gint operand, GArray *a, GArray *b)
800 {
801         int             i, j, len_a, len_b;
802         ipv4_addr       *ptr_a, *ptr_b;
803
804         len_a = a->len;
805         len_b = b->len;
806
807
808         switch(operand) {
809         case TOK_EQ:
810                 for(i = 0; i < len_a; i++) {
811                         ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
812                         for (j = 0; j < len_b; j++) {
813                                 ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
814                                 if (ipv4_addr_eq(ptr_a, ptr_b))
815                                         return TRUE;
816                         }
817                 }
818                 return FALSE;
819
820         case TOK_NE:
821                 for(i = 0; i < len_a; i++) {
822                         ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
823                         for (j = 0; j < len_b; j++) {
824                                 ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
825                                 if (!ipv4_addr_eq(ptr_a, ptr_b))
826                                         return TRUE;
827                         }
828                 }
829                 return FALSE;
830
831         case TOK_GT:
832                 for(i = 0; i < len_a; i++) {
833                         ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
834                         for (j = 0; j < len_b; j++) {
835                                 ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
836                                 if (ipv4_addr_gt(ptr_a, ptr_b))
837                                         return TRUE;
838                         }
839                 }
840                 return FALSE;
841
842         case TOK_GE:
843                 for(i = 0; i < len_a; i++) {
844                         ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
845                         for (j = 0; j < len_b; j++) {
846                                 ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
847                                 if (ipv4_addr_ge(ptr_a, ptr_b))
848                                         return TRUE;
849                         }
850                 }
851                 return FALSE;
852
853         case TOK_LT:
854                 for(i = 0; i < len_a; i++) {
855                         ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
856                         for (j = 0; j < len_b; j++) {
857                                 ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
858                                 if (ipv4_addr_lt(ptr_a, ptr_b))
859                                         return TRUE;
860                         }
861                 }
862                 return FALSE;
863
864         case TOK_LE:
865                 for(i = 0; i < len_a; i++) {
866                         ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i);
867                         for (j = 0; j < len_b; j++) {
868                                 ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j);
869                                 if (ipv4_addr_le(ptr_a, ptr_b))
870                                         return TRUE;
871                         }
872                 }
873                 return FALSE;
874         }
875
876         g_assert_not_reached();
877         return FALSE;
878 }
879
880 gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b)
881 {
882         int     i, j, len_a, len_b;
883         guint8  *ptr_a, *ptr_b;
884
885         len_a = a->len;
886         len_b = b->len;
887
888
889         switch(operand) {
890         case TOK_EQ:
891                 for(i = 0; i < len_a; i++) {
892                         ptr_a = g_array_index_ptr(a, 16, i);
893                         for (j = 0; j < len_b; j++) {
894                                 ptr_b = g_array_index_ptr(b, 16, j);
895                                 if (memcmp(ptr_a, ptr_b, 16) == 0)
896                                         return TRUE;
897                         }
898                 }
899                 return FALSE;
900
901         case TOK_NE:
902                 for(i = 0; i < len_a; i++) {
903                         ptr_a = g_array_index_ptr(a, 16, i);
904                         for (j = 0; j < len_b; j++) {
905                                 ptr_b = g_array_index_ptr(b, 16, j);
906                                 if (memcmp(ptr_a, ptr_b, 16) != 0)
907                                         return TRUE;
908                         }
909                 }
910                 return FALSE;
911         }
912
913         g_assert_not_reached();
914         return FALSE;
915 }
916
917 gboolean check_relation_ether(gint operand, GArray *a, GArray *b)
918 {
919         int     i, j, len_a, len_b;
920         guint8  *ptr_a, *ptr_b;
921
922         len_a = a->len;
923         len_b = b->len;
924
925
926         switch(operand) {
927         case TOK_EQ:
928                 for(i = 0; i < len_a; i++) {
929                         ptr_a = g_array_index_ptr(a, 6, i);
930                         for (j = 0; j < len_b; j++) {
931                                 ptr_b = g_array_index_ptr(b, 6, j);
932                                 if (memcmp(ptr_a, ptr_b, 6) == 0)
933                                         return TRUE;
934                         }
935                 }
936                 return FALSE;
937
938         case TOK_NE:
939                 for(i = 0; i < len_a; i++) {
940                         ptr_a = g_array_index_ptr(a, 6, i);
941                         for (j = 0; j < len_b; j++) {
942                                 ptr_b = g_array_index_ptr(b, 6, j);
943                                 if (memcmp(ptr_a, ptr_b, 6) != 0)
944                                         return TRUE;
945                         }
946                 }
947                 return FALSE;
948         }
949
950         g_assert_not_reached();
951         return FALSE;
952 }
953
954 gboolean check_relation_bytes(gint operand, GArray *a, GArray *b)
955 {
956         int     i, j, len_a, len_b;
957         GByteArray      *ptr_a,*ptr_b;
958
959         len_a = a->len;
960         len_b = b->len;
961
962
963         switch(operand) {
964         case TOK_EQ:
965                 for(i = 0; i < len_a; i++) {
966                         ptr_a = g_array_index(a, GByteArray*, i);
967                         for (j = 0; j < len_b; j++) {
968                                 ptr_b = g_array_index(b, GByteArray*, j);
969                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) == 0)
970                                         return TRUE;
971                         }
972                 }
973                 return FALSE;
974
975         case TOK_NE:
976                 for(i = 0; i < len_a; i++) {
977                         ptr_a = g_array_index(a, GByteArray*, i);
978                         for (j = 0; j < len_b; j++) {
979                                 ptr_b = g_array_index(b, GByteArray*, j);
980                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) != 0)
981                                         return TRUE;
982                         }
983                 }
984                 return FALSE;
985
986         case TOK_GT:
987                 for(i = 0; i < len_a; i++) {
988                         ptr_a = g_array_index(a, GByteArray*, i);
989                         for (j = 0; j < len_b; j++) {
990                                 ptr_b = g_array_index(b, GByteArray*, j);
991                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) > 0)
992                                         return TRUE;
993                         }
994                 }
995                 return FALSE;
996
997         case TOK_LT:
998                 for(i = 0; i < len_a; i++) {
999                         ptr_a = g_array_index(a, GByteArray*, i);
1000                         for (j = 0; j < len_b; j++) {
1001                                 ptr_b = g_array_index(b, GByteArray*, j);
1002                                 if (memcmp(ptr_a->data, ptr_b->data, bytes_length) < 0)
1003                                         return TRUE;
1004                         }
1005                 }
1006                 return FALSE;
1007         }
1008
1009         g_assert_not_reached();
1010         return FALSE;
1011 }