diff options
author | Gilbert Ramirez <gram@alumni.rice.edu> | 2000-09-27 04:55:05 +0000 |
---|---|---|
committer | Gilbert Ramirez <gram@alumni.rice.edu> | 2000-09-27 04:55:05 +0000 |
commit | 83ec54675c19f25cfbb2e8a8863c6ee2191d8b0c (patch) | |
tree | 35d39e43d20aca160b96d8a85ddc2b80e4646f67 /epan/dfilter.c | |
parent | f881e13932e0ba390c26cce15d1334b2154a8062 (diff) |
First step in moving core Ethereal routines to libepan.
svn path=/trunk/; revision=2458
Diffstat (limited to 'epan/dfilter.c')
-rw-r--r-- | epan/dfilter.c | 1064 |
1 files changed, 1064 insertions, 0 deletions
diff --git a/epan/dfilter.c b/epan/dfilter.c new file mode 100644 index 0000000000..73fe5253e0 --- /dev/null +++ b/epan/dfilter.c @@ -0,0 +1,1064 @@ +/* dfilter.c + * Routines for display filters + * + * $Id: dfilter.c,v 1.1 2000/09/27 04:54:48 gram Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.org> + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#include <stdio.h> +#include <string.h> +#include <glib.h> + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include "proto.h" +#include "dfilter.h" +#include "util.h" +#include "dfilter-int.h" +#include "dfilter-grammar.h" + +int dfilter_parse(void); /* yacc entry-point */ + +#define DFILTER_LEX_ABBREV_OFFSET 2000 + +/* Balanced tree of abbreviations and IDs */ +GTree *dfilter_tokens = NULL; + +/* Comparision function for tree insertion. A wrapper around strcmp() */ +static int g_strcmp(gconstpointer a, gconstpointer b); + +/* Silly global variables used to pass parameter to check_relation_bytes() */ +int bytes_offset = 0; +int bytes_length = 0; + +YYSTYPE yylval; + +/* Global error message space for dfilter_compile errors */ +gchar dfilter_error_msg_buf[1024]; +gchar *dfilter_error_msg; /* NULL when no error resulted */ + +static gboolean dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8 *pd); +static gboolean check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd); +static gboolean check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd); +static GArray* get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd); +static GArray* get_values_from_dfilter(dfilter_node *dnode, GNode *gnode); +static gboolean check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree); +static void clear_byte_array(gpointer data, gpointer user_data); + +/* this is not so pretty. I need my own g_array "function" (macro) to + * retreive the pointer to the data stored in an array cell. I need this + * for type ether.. GArray makes it easy for me to store 6 bytes inside an array + * cell, but hard to retrieve it. + */ +#define g_array_index_ptr(a,s,i) (((guint8*) (a)->data) + (i*s)) + +extern int hf_text_only; /* in proto.c */ + +void +dfilter_init(void) +{ + int i, num_symbols, symbol; + char *s; + + dfilter_tokens = g_tree_new(g_strcmp); + + /* Add the header field and protocol abbrevs to the symbol table */ + num_symbols = proto_registrar_n(); + + for (i=0; i < num_symbols; i++) { + if (i == hf_text_only) { + continue; + } + s = proto_registrar_get_abbrev(i); + g_assert(s); /* Not Null */ + g_assert(s[0] != 0); /* Not empty string */ + /* Make sure we don't have duplicate abbreviation */ + if (g_tree_lookup(dfilter_tokens, s)) { + g_message("Already have abbreviation \"%s\"", s); + g_assert(0); + } + symbol = DFILTER_LEX_ABBREV_OFFSET + i; + g_tree_insert(dfilter_tokens, s, GINT_TO_POINTER(symbol)); + } +} + +void +dfilter_cleanup(void) +{ + if (dfilter_tokens) + g_tree_destroy(dfilter_tokens); +} + +/* Compiles the textual representation of the display filter into a tree + * of operations to perform. Can be called multiple times, compiling a new + * display filter each time, without having to clear any memory used, since + * dfilter_compile will take care of that automatically. + * + * Returns 0 on success, non-zero on failure. + * + * On success, sets the "dfilter *" pointed to by its second argument + * either to a null pointer (if the filter is a null filter, as + * generated by an all-blank string) or to a pointer to a newly-allocated + * dfilter structure (if the filter isn't null). + * + * On failure, "dfilter_error_msg" points to an appropriate error message. + * This error message is a global string, so another invocation of + * dfilter_compile will clear it. If the caller needs is stored, he + * needs to g_strdup it himself. + */ +int +dfilter_compile(gchar *dfilter_text, dfilter **dfp) +{ + dfilter *df; + int retval; + + g_assert(dfilter_text != NULL); + + df = dfilter_new(); + + /* tell the scanner to use the filter string as input */ + dfilter_scanner_text(dfilter_text); + + /* Assign global variable so dfilter_parse knows which dfilter we're + * talking about. Reset the global error message. + */ + global_df = df; + dfilter_error_msg = NULL; + + /* The magic happens right here. */ + retval = dfilter_parse(); + + /* clean up lex */ + dfilter_scanner_cleanup(); + + /* Errors not found by the parser may not cause the parse to + * fail; if "dfilter_error_msg" is set, it means somebody + * else called "dfilter_fail()", e.g. the lexical analyzer, + * so treat that as a parse error. */ + if (dfilter_error_msg != NULL) + retval = 1; + + if (retval != 0) { + if (dfilter_error_msg == NULL) { + snprintf(dfilter_error_msg_buf, sizeof(dfilter_error_msg_buf), + "Unable to parse filter string \"%s\".", + dfilter_text); + dfilter_error_msg = &dfilter_error_msg_buf[0]; + } + } + + /* Set global_df to NULL just to be tidy. */ + global_df = NULL; + + if (retval == 0) { + /* Success. Check if the filter is empty; if so, discard + * it and set "*dfp" to NULL, otherwise set "*dfp" to + * point to the filter. */ + if (df->dftree == NULL) { + /* The filter is empty. */ + dfilter_destroy(df); + df = NULL; + } + *dfp = df; + } else { + /* Failure. Destroy the filter. */ + dfilter_destroy(df); + df = NULL; + } + return retval; +} + +/* Allocates new dfilter, initializes values, and returns pointer to dfilter */ +dfilter* +dfilter_new(void) +{ + dfilter *df; + + df = g_malloc(sizeof(dfilter)); + + df->dftree = NULL; + df->node_memchunk = g_mem_chunk_new("df->node_memchunk", + sizeof(dfilter_node), 20 * sizeof(dfilter_node), G_ALLOC_ONLY); + df->list_of_byte_arrays = NULL; + df->list_of_strings = NULL; + + return df; +} + +static void +free_string(gpointer data, gpointer user_data) +{ + char *string = data; + if (string) + g_free(string); +} + +/* Frees all memory used by dfilter, and frees dfilter itself */ +void +dfilter_destroy(dfilter *df) +{ + if (!df) + return; + + if (df->dftree != NULL) + g_node_destroy(df->dftree); + + /* clear the memory that the tree was using for nodes */ + if (df->node_memchunk) + g_mem_chunk_reset(df->node_memchunk); + + /* clear the memory that the tree was using for byte arrays */ + if (df->list_of_byte_arrays) { + g_slist_foreach(df->list_of_byte_arrays, clear_byte_array, NULL); + g_slist_free(df->list_of_byte_arrays); + } + + /* clear the allocated strings */ + if (df->list_of_strings) { + g_slist_foreach(df->list_of_strings, free_string, NULL); + g_slist_free(df->list_of_strings); + } + + df->dftree = NULL; + df->list_of_byte_arrays = NULL; + df->list_of_strings = NULL; + + /* Git rid of memchunk */ + if (df->node_memchunk) + g_mem_chunk_destroy(df->node_memchunk); + + g_free(df); +} + + +static void +clear_byte_array(gpointer data, gpointer user_data) +{ + GByteArray *barray = data; + if (barray) + g_byte_array_free(barray, TRUE); +} + +/* Called when the yacc grammar finds a parsing error */ +void +dfilter_error(char *s) +{ +} + +/* Called when an error other than a parsing error occurs. */ +void +dfilter_fail(char *format, ...) +{ + va_list ap; + + /* If we've already reported one error, don't overwrite it with this + * one. */ + if (dfilter_error_msg != NULL) + return; + + va_start(ap, format); + vsnprintf(dfilter_error_msg_buf, sizeof dfilter_error_msg_buf, format, ap); + dfilter_error_msg = dfilter_error_msg_buf; + va_end(ap); +} + +/* lookup an abbreviation in our token tree, returing the ID # + * If the abbreviation doesn't exit, returns -1 */ +int dfilter_lookup_token(char *abbrev) +{ + int value; + + g_assert(abbrev != NULL); + value = GPOINTER_TO_INT(g_tree_lookup(dfilter_tokens, abbrev)); + + if (value < DFILTER_LEX_ABBREV_OFFSET) { + return -1; + } + return value - DFILTER_LEX_ABBREV_OFFSET; +} + +static int +g_strcmp(gconstpointer a, gconstpointer b) +{ + return strcmp((const char*)a, (const char*)b); +} + + +gboolean +dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd, guint pd_len) +{ + gboolean retval; + if (dfcode == NULL) + return FALSE; + retval = dfilter_apply_node(dfcode->dftree, ptree, pd); + return retval; +} + +static gboolean +dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd) +{ + GNode *gnode_a, *gnode_b; + dfilter_node *dnode = (dfilter_node*) (gnode->data); + + /* We'll get 2 NULLs if we don't have children */ + gnode_a = g_node_nth_child(gnode, 0); + gnode_b = g_node_nth_child(gnode, 1); + + switch(dnode->ntype) { + case variable: + /* We'll never see this case because if the parser finds the name of + * a variable, it will cause it to be an 'existence' operation. + */ + g_assert_not_reached(); + + case logical: + g_assert(gnode_a); + return check_logical(dnode->value.logical, gnode_a, gnode_b, ptree, pd); + + case relation: + g_assert(gnode_a && gnode_b); + return check_relation(dnode->value.relation, gnode_a, gnode_b, ptree, pd); + + case alternation: + g_assert_not_reached(); + /* not coded yet */ + + case numeric: + case floating: + case ipv4: + case ipv6: + case boolean: + case ether: + case string: + case abs_time: + case bytes: + case ipxnet: + /* the only time we'll see these at this point is if the display filter + * is really wacky. (like simply "192.168.1.1"). The parser as it stands + * now let these by. Just return TRUE */ + g_assert(!gnode_a && !gnode_b); + return TRUE; + + case existence: /* checking the existence of a protocol or hf*/ + g_assert(!gnode_a && !gnode_b); + return check_existence_in_ptree(dnode, ptree); + } + + g_assert_not_reached(); + return FALSE; +} + +static gboolean +check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd) +{ + gboolean val_a = dfilter_apply_node(a, ptree, pd); + gboolean val_b; + + switch(operand) { + case TOK_AND: + g_assert(b); + return (val_a && dfilter_apply_node(b, ptree, pd)); + case TOK_OR: + g_assert(b); + return (val_a || dfilter_apply_node(b, ptree, pd)); + case TOK_XOR: + g_assert(b); + val_b = dfilter_apply_node(b, ptree, pd); + return ( ( val_a || val_b ) && ! ( val_a && val_b ) ); + case TOK_NOT: + return (!val_a); + default: + g_assert_not_reached(); + } + g_assert_not_reached(); + return FALSE; +} + + +static void +free_array_of_byte_arrays(GArray *array) +{ + int i, len; + GByteArray *ba_ptr; + + len = array->len; + + for (i = 0; i < len ; i++) { + ba_ptr = g_array_index(array, GByteArray*, i); + g_byte_array_free(ba_ptr, TRUE); + } +} + +/* this is inefficient. I get arrays for both a and b that represent all the values present. That is, + * if a is bootp.option, e.g., i'll get an array showing all the bootp.option values in the protocol + * tree. Then I'll get an array for b, which more than likely is a single int, and then I'll compare + * them all. It makes my coding easier in the beginning, but I should change this to make it run + * faster. + */ +static gboolean +check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8* pd) +{ + dfilter_node *node_a = (dfilter_node*) (a->data); + dfilter_node *node_b = (dfilter_node*) (b->data); + GArray *vals_a, *vals_b; + gboolean retval; + + + bytes_length = MIN(node_a->length, node_b->length); + bytes_offset = MIN(node_a->offset, node_b->offset); + if (node_a->ntype == variable) + vals_a = get_values_from_ptree(node_a, ptree, pd); + else + vals_a = get_values_from_dfilter(node_a, a); + + if (node_b->ntype == variable) + vals_b = get_values_from_ptree(node_b, ptree, pd); + else + vals_b = get_values_from_dfilter(node_b, b); + + retval = node_a->check_relation_func(operand, vals_a, vals_b); + + /* Free GByteArrays alloated by fill_array_bytes_variable() */ + if (node_a->fill_array_variable_func == fill_array_bytes_variable) { + free_array_of_byte_arrays(vals_a); + } + + if (node_b->fill_array_variable_func == fill_array_bytes_variable) { + free_array_of_byte_arrays(vals_b); + } + + g_array_free(vals_a, FALSE); + g_array_free(vals_b, FALSE); + + return retval; +} + + +static gboolean +check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree) +{ + int target; + + target = dnode->value.variable; + return proto_check_for_protocol_or_field(ptree, target); +} + +static GArray* +get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd) +{ + GArray *result_array; + GPtrArray *finfo_array; + int i, len; + field_info *finfo; + + /* Prepare the array for results */ + g_assert(dnode->elem_size > 0); + result_array = g_array_new(FALSE, FALSE, dnode->elem_size); + + /* Cull the finfos from the proto_tree */ + finfo_array = proto_get_finfo_ptr_array(ptree, dnode->value.variable); + if (!finfo_array) { + return result_array; + } + + len = g_ptr_array_len(finfo_array); + + for (i = 0; i < len; i++) { + finfo = g_ptr_array_index(finfo_array, i); + dnode->fill_array_variable_func(finfo, result_array, pd); + } + + g_ptr_array_free(finfo_array, FALSE); + + return result_array; +} + + +void +fill_array_numeric_variable(field_info *finfo, GArray *array, const guint8 *pd) +{ + g_array_append_val(array, finfo->value.numeric); +} + +void +fill_array_floating_variable(field_info *finfo, GArray *array, const guint8 *pd) +{ + g_array_append_val(array, finfo->value.floating); +} + +void +fill_array_ether_variable(field_info *finfo, GArray *array, const guint8 *pd) +{ + /* hmmm, yes, I *can* copy a pointer instead of memcpy() */ + g_array_append_val(array, finfo->value.ether); +} + +void +fill_array_ipv4_variable(field_info *finfo, GArray *array, const guint8 *pd) +{ + /* hmmm, yes, I *can* copy a pointer instead of memcpy() */ + g_array_append_val(array, finfo->value.ipv4); +} + +void +fill_array_ipv6_variable(field_info *finfo, GArray *array, const guint8 *pd) +{ + /* hmmm, yes, I *can* copy a pointer instead of memcpy() */ + g_array_append_val(array, finfo->value.ipv6); +} + +void +fill_array_string_variable(field_info *finfo, GArray *array, const guint8 *pd) +{ + g_array_append_val(array, finfo->value.string); +} + +void +fill_array_bytes_variable(field_info *finfo, GArray *array, const guint8 *pd) +{ + GByteArray *barray; + guint read_start, pkt_end; + + if (bytes_offset < 0) { + /* Handle negative byte offsets */ + bytes_offset = finfo->length + bytes_offset; + if (bytes_offset < 0) { + return; + } + } + + /* Check to make sure offset exists for this field */ + if (bytes_offset >= finfo->length) { + return; + } + + pkt_end = finfo->start + finfo->length; + read_start = finfo->start + bytes_offset; + + /* Check to make sure entire length requested is inside field */ + if (pkt_end < read_start + bytes_length) { + return; + } + + barray = g_byte_array_new(); + g_byte_array_append(barray, pd + read_start, bytes_length); + g_array_append_val(array, barray); +} + +static GArray* +get_values_from_dfilter(dfilter_node *dnode, GNode *gnode) +{ + GArray *array; + + g_assert(dnode->elem_size > 0); + array = g_array_new(FALSE, FALSE, dnode->elem_size); + + g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, + dnode->fill_array_value_func, array); + return array; +} + +gboolean fill_array_numeric_value(GNode *gnode, gpointer data) +{ + GArray *array = (GArray*)data; + dfilter_node *dnode = (dfilter_node*) (gnode->data); + + g_array_append_val(array, dnode->value.numeric); + return FALSE; /* FALSE = do not end traversal of GNode tree */ +} + +gboolean fill_array_floating_value(GNode *gnode, gpointer data) +{ + GArray *array = (GArray*)data; + dfilter_node *dnode = (dfilter_node*) (gnode->data); + + g_array_append_val(array, dnode->value.floating); + return FALSE; /* FALSE = do not end traversal of GNode tree */ +} + +gboolean fill_array_ether_value(GNode *gnode, gpointer data) +{ + GArray *array = (GArray*)data; + dfilter_node *dnode = (dfilter_node*) (gnode->data); + + g_array_append_val(array, dnode->value.ether); + + return FALSE; /* FALSE = do not end traversal of GNode tree */ +} + +gboolean fill_array_ipv4_value(GNode *gnode, gpointer data) +{ + GArray *array = (GArray*)data; + dfilter_node *dnode = (dfilter_node*) (gnode->data); + + g_array_append_val(array, dnode->value.ipv4); + + return FALSE; /* FALSE = do not end traversal of GNode tree */ +} + +gboolean fill_array_ipv6_value(GNode *gnode, gpointer data) +{ + GArray *array = (GArray*)data; + dfilter_node *dnode = (dfilter_node*) (gnode->data); + + g_array_append_val(array, dnode->value.ipv6); + + return FALSE; /* FALSE = do not end traversal of GNode tree */ +} + +gboolean fill_array_bytes_value(GNode *gnode, gpointer data) +{ + GArray *array = (GArray*)data; + dfilter_node *dnode = (dfilter_node*) (gnode->data); + GByteArray *barray = dnode->value.bytes; + + g_array_append_val(array, barray); + + return FALSE; /* FALSE = do not end traversal of GNode tree */ +} + +gboolean fill_array_string_value(GNode *gnode, gpointer data) +{ + GArray *array = (GArray*)data; + dfilter_node *dnode = (dfilter_node*) (gnode->data); + + g_array_append_val(array, dnode->value.string); + + return FALSE; /* FALSE = do not end traversal of GNode tree */ +} + +gboolean check_relation_numeric(gint operand, GArray *a, GArray *b) +{ + int i, j, len_a, len_b; + guint32 val_a; + + len_a = a->len; + len_b = b->len; + + + switch(operand) { + case TOK_EQ: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, guint32, i); + for (j = 0; j < len_b; j++) { + if (val_a == g_array_index(b, guint32, j)) + return TRUE; + } + } + return FALSE; + + case TOK_NE: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, guint32, i); + for (j = 0; j < len_b; j++) { + if (val_a != g_array_index(b, guint32, j)) + return TRUE; + } + } + return FALSE; + + case TOK_GT: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, guint32, i); + for (j = 0; j < len_b; j++) { + if (val_a > g_array_index(b, guint32, j)) + return TRUE; + } + } + return FALSE; + + case TOK_GE: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, guint32, i); + for (j = 0; j < len_b; j++) { + if (val_a >= g_array_index(b, guint32, j)) + return TRUE; + } + } + return FALSE; + + case TOK_LT: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, guint32, i); + for (j = 0; j < len_b; j++) { + if (val_a < g_array_index(b, guint32, j)) + return TRUE; + } + } + return FALSE; + + case TOK_LE: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, guint32, i); + for (j = 0; j < len_b; j++) { + if (val_a <= g_array_index(b, guint32, j)) + return TRUE; + } + } + return FALSE; + + default: + g_assert_not_reached(); + } + + g_assert_not_reached(); + return FALSE; +} + +gboolean check_relation_floating(gint operand, GArray *a, GArray *b) +{ + int i, j, len_a, len_b; + double val_a; + + len_a = a->len; + len_b = b->len; + + + switch(operand) { + case TOK_EQ: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, double, i); + for (j = 0; j < len_b; j++) { + if (val_a == g_array_index(b, double, j)) + return TRUE; + } + } + return FALSE; + + case TOK_NE: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, double, i); + for (j = 0; j < len_b; j++) { + if (val_a != g_array_index(b, double, j)) + return TRUE; + } + } + return FALSE; + + case TOK_GT: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, double, i); + for (j = 0; j < len_b; j++) { + if (val_a > g_array_index(b, double, j)) + return TRUE; + } + } + return FALSE; + + case TOK_GE: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, double, i); + for (j = 0; j < len_b; j++) { + if (val_a >= g_array_index(b, double, j)) + return TRUE; + } + } + return FALSE; + + case TOK_LT: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, double, i); + for (j = 0; j < len_b; j++) { + if (val_a < g_array_index(b, double, j)) + return TRUE; + } + } + return FALSE; + + case TOK_LE: + for(i = 0; i < len_a; i++) { + val_a = g_array_index(a, double, i); + for (j = 0; j < len_b; j++) { + if (val_a <= g_array_index(b, double, j)) + return TRUE; + } + } + return FALSE; + + default: + g_assert_not_reached(); + } + + g_assert_not_reached(); + return FALSE; +} + +gboolean check_relation_ipv4(gint operand, GArray *a, GArray *b) +{ + int i, j, len_a, len_b; + ipv4_addr *ptr_a, *ptr_b; + + len_a = a->len; + len_b = b->len; + + + switch(operand) { + case TOK_EQ: + for(i = 0; i < len_a; i++) { + ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i); + for (j = 0; j < len_b; j++) { + ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j); + if (ipv4_addr_eq(ptr_a, ptr_b)) + return TRUE; + } + } + return FALSE; + + case TOK_NE: + for(i = 0; i < len_a; i++) { + ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i); + for (j = 0; j < len_b; j++) { + ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j); + if (ipv4_addr_ne(ptr_a, ptr_b)) + return TRUE; + } + } + return FALSE; + + case TOK_GT: + for(i = 0; i < len_a; i++) { + ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i); + for (j = 0; j < len_b; j++) { + ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j); + if (ipv4_addr_gt(ptr_a, ptr_b)) + return TRUE; + } + } + return FALSE; + + case TOK_GE: + for(i = 0; i < len_a; i++) { + ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i); + for (j = 0; j < len_b; j++) { + ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j); + if (ipv4_addr_ge(ptr_a, ptr_b)) + return TRUE; + } + } + return FALSE; + + case TOK_LT: + for(i = 0; i < len_a; i++) { + ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i); + for (j = 0; j < len_b; j++) { + ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j); + if (ipv4_addr_lt(ptr_a, ptr_b)) + return TRUE; + } + } + return FALSE; + + case TOK_LE: + for(i = 0; i < len_a; i++) { + ptr_a = (ipv4_addr*) g_array_index_ptr(a, sizeof(ipv4_addr), i); + for (j = 0; j < len_b; j++) { + ptr_b = (ipv4_addr*) g_array_index_ptr(b, sizeof(ipv4_addr), j); + if (ipv4_addr_le(ptr_a, ptr_b)) + return TRUE; + } + } + return FALSE; + } + + g_assert_not_reached(); + return FALSE; +} + +gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b) +{ + int i, j, len_a, len_b; + guint8 *ptr_a, *ptr_b; + + len_a = a->len; + len_b = b->len; + + + switch(operand) { + case TOK_EQ: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index_ptr(a, 16, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index_ptr(b, 16, j); + if (memcmp(ptr_a, ptr_b, 16) == 0) + return TRUE; + } + } + return FALSE; + + case TOK_NE: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index_ptr(a, 16, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index_ptr(b, 16, j); + if (memcmp(ptr_a, ptr_b, 16) != 0) + return TRUE; + } + } + return FALSE; + } + + g_assert_not_reached(); + return FALSE; +} + +gboolean check_relation_ether(gint operand, GArray *a, GArray *b) +{ + int i, j, len_a, len_b; + guint8 *ptr_a, *ptr_b; + + len_a = a->len; + len_b = b->len; + + + switch(operand) { + case TOK_EQ: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index_ptr(a, 6, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index_ptr(b, 6, j); + if (memcmp(ptr_a, ptr_b, 6) == 0) + return TRUE; + } + } + return FALSE; + + case TOK_NE: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index_ptr(a, 6, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index_ptr(b, 6, j); + if (memcmp(ptr_a, ptr_b, 6) != 0) + return TRUE; + } + } + return FALSE; + } + + g_assert_not_reached(); + return FALSE; +} + +gboolean check_relation_bytes(gint operand, GArray *a, GArray *b) +{ + int i, j, len_a, len_b; + GByteArray *ptr_a,*ptr_b; + + len_a = a->len; + len_b = b->len; + + + switch(operand) { + case TOK_EQ: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index(a, GByteArray*, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index(b, GByteArray*, j); + if (memcmp(ptr_a->data, ptr_b->data, bytes_length) == 0) + return TRUE; + } + } + return FALSE; + + case TOK_NE: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index(a, GByteArray*, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index(b, GByteArray*, j); + if (memcmp(ptr_a->data, ptr_b->data, bytes_length) != 0) + return TRUE; + } + } + return FALSE; + + case TOK_GT: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index(a, GByteArray*, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index(b, GByteArray*, j); + if (memcmp(ptr_a->data, ptr_b->data, bytes_length) > 0) + return TRUE; + } + } + return FALSE; + + case TOK_LT: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index(a, GByteArray*, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index(b, GByteArray*, j); + if (memcmp(ptr_a->data, ptr_b->data, bytes_length) < 0) + return TRUE; + } + } + return FALSE; + } + + g_assert_not_reached(); + return FALSE; +} + +gboolean check_relation_string(gint operand, GArray *a, GArray *b) +{ + int i, j, len_a, len_b; + char *ptr_a, *ptr_b; + + len_a = a->len; + len_b = b->len; + + + switch(operand) { + case TOK_EQ: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index(a, char*, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index(b, char*, j); + if (strcmp(ptr_a, ptr_b) == 0) + return TRUE; + } + } + return FALSE; + + case TOK_NE: + for(i = 0; i < len_a; i++) { + ptr_a = g_array_index(a, char*, i); + for (j = 0; j < len_b; j++) { + ptr_b = g_array_index(b, char*, j); + if (strcmp(ptr_a, ptr_b) != 0) + return TRUE; + } + } + return FALSE; + } + + g_assert_not_reached(); + return FALSE; +} + |