2 * Routines for display filters
4 * $Id: dfilter.c,v 1.32 1999/11/15 06:32:13 gram Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
42 #ifdef NEED_SNPRINTF_H
48 # include "snprintf.h"
67 #include "dfilter-int.h"
68 #include "dfilter-grammar.h"
70 int dfilter_parse(void); /* yacc entry-point */
72 #define DFILTER_LEX_ABBREV_OFFSET 2000
74 /* Balanced tree of abbreviations and IDs */
75 GTree *dfilter_tokens = NULL;
77 /* Comparision function for tree insertion. A wrapper around strcmp() */
78 static int g_strcmp(gconstpointer a, gconstpointer b);
80 /* Silly global variables used to pass parameter to check_relation_bytes() */
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 */
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);
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.
103 #define g_array_index_ptr(a,s,i) (((guint8*) (a)->data) + (i*s))
108 int i, num_symbols, symbol;
111 dfilter_tokens = g_tree_new(g_strcmp);
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);
118 symbol = DFILTER_LEX_ABBREV_OFFSET + i;
119 g_tree_insert(dfilter_tokens, s, GINT_TO_POINTER(symbol));
125 dfilter_cleanup(void)
128 g_tree_destroy(dfilter_tokens);
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.
136 * Returns 0 on success, non-zero on failure.
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).
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.
149 dfilter_compile(gchar *dfilter_text, dfilter **dfp)
154 g_assert(dfilter_text != NULL);
158 /* tell the scanner to use the filter string as input */
159 dfilter_scanner_text(dfilter_text);
161 /* Assign global variable so dfilter_parse knows which dfilter we're
162 * talking about. Reset the global error message.
165 dfilter_error_msg = NULL;
167 /* The magic happens right here. */
168 retval = dfilter_parse();
171 dfilter_scanner_cleanup();
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)
181 if (dfilter_error_msg == NULL) {
182 snprintf(dfilter_error_msg_buf, sizeof(dfilter_error_msg_buf),
183 "Unable to parse filter string \"%s\".",
185 dfilter_error_msg = &dfilter_error_msg_buf[0];
189 /* Set global_df to NULL just to be tidy. */
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. */
203 /* Failure. Destroy the filter. */
210 /* Allocates new dfilter, initializes values, and returns pointer to dfilter */
216 df = g_malloc(sizeof(dfilter));
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;
226 /* Frees all memory used by dfilter, and frees dfilter itself */
228 dfilter_destroy(dfilter *df)
233 if (df->dftree != NULL)
234 g_node_destroy(df->dftree);
236 /* clear the memory that the tree was using for nodes */
237 if (df->node_memchunk)
238 g_mem_chunk_reset(df->node_memchunk);
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);
247 df->list_of_byte_arrays = NULL;
249 /* Git rid of memchunk */
250 if (df->node_memchunk)
251 g_mem_chunk_destroy(df->node_memchunk);
258 clear_byte_array(gpointer data, gpointer user_data)
260 GByteArray *barray = data;
262 g_byte_array_free(barray, TRUE);
265 /* Called when the yacc grammar finds a parsing error */
267 dfilter_error(char *s)
271 /* Called when an error other than a parsing error occurs. */
273 dfilter_fail(char *format, ...)
277 /* If we've already reported one error, don't overwrite it with this
279 if (dfilter_error_msg != NULL)
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;
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)
294 g_assert(abbrev != NULL);
295 value = GPOINTER_TO_INT(g_tree_lookup(dfilter_tokens, abbrev));
297 if (value < DFILTER_LEX_ABBREV_OFFSET) {
300 return value - DFILTER_LEX_ABBREV_OFFSET;
304 g_strcmp(gconstpointer a, gconstpointer b)
306 return strcmp((const char*)a, (const char*)b);
311 dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd)
316 retval = dfilter_apply_node(dfcode->dftree, ptree, pd);
321 dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8* pd)
323 GNode *gnode_a, *gnode_b;
324 dfilter_node *dnode = (dfilter_node*) (gnode->data);
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);
330 switch(dnode->ntype) {
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.
335 g_assert_not_reached();
339 return check_logical(dnode->value.logical, gnode_a, gnode_b, ptree, pd);
342 g_assert(gnode_a && gnode_b);
343 return check_relation(dnode->value.relation, gnode_a, gnode_b, ptree, pd);
346 g_assert_not_reached();
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);
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);
370 g_assert_not_reached();
375 check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd)
377 gboolean val_a = dfilter_apply_node(a, ptree, pd);
383 return (val_a && dfilter_apply_node(b, ptree, pd));
386 return (val_a || dfilter_apply_node(b, ptree, pd));
389 val_b = dfilter_apply_node(b, ptree, pd);
390 return ( ( val_a || val_b ) && ! ( val_a && val_b ) );
394 g_assert_not_reached();
396 g_assert_not_reached();
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
407 check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8* pd)
409 dfilter_node *node_a = (dfilter_node*) (a->data);
410 dfilter_node *node_b = (dfilter_node*) (b->data);
411 GArray *vals_a, *vals_b;
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);
420 vals_a = get_values_from_dfilter(node_a, a);
422 if (node_b->ntype == variable)
423 vals_b = get_values_from_ptree(node_b, ptree, pd);
425 vals_b = get_values_from_dfilter(node_b, b);
427 retval = node_a->check_relation_func(operand, vals_a, vals_b);
429 g_array_free(vals_a, FALSE);
430 g_array_free(vals_b, FALSE);
436 check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree)
440 target = dnode->value.variable;
441 return proto_check_for_protocol_or_field(ptree, target);
445 get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, const guint8 *pd)
449 proto_tree_search_info sinfo;
451 g_assert(dnode->elem_size > 0);
452 array = g_array_new(FALSE, FALSE, dnode->elem_size);
454 sinfo.target = dnode->value.variable;
455 sinfo.result.array = array;
456 sinfo.packet_data = pd;
457 sinfo.traverse_func = dnode->fill_array_func;
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);
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);
476 get_values_from_dfilter(dfilter_node *dnode, GNode *gnode)
480 g_assert(dnode->elem_size > 0);
481 array = g_array_new(FALSE, FALSE, dnode->elem_size);
483 g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1, dnode->fill_array_func, array);
487 gboolean fill_array_numeric_variable(GNode *gnode, gpointer data)
489 proto_tree_search_info *sinfo = (proto_tree_search_info*)data;
490 field_info *fi = (field_info*) (gnode->data);
492 if (fi->hfinfo->id == sinfo->target) {
493 g_array_append_val(sinfo->result.array, fi->value.numeric);
496 return FALSE; /* FALSE = do not end traversal of GNode tree */
499 gboolean fill_array_floating_variable(GNode *gnode, gpointer data)
501 proto_tree_search_info *sinfo = (proto_tree_search_info*)data;
502 field_info *fi = (field_info*) (gnode->data);
504 if (fi->hfinfo->id == sinfo->target) {
505 g_array_append_val(sinfo->result.array, fi->value.floating);
508 return FALSE; /* FALSE = do not end traversal of GNode tree */
511 gboolean fill_array_ether_variable(GNode *gnode, gpointer data)
513 proto_tree_search_info *sinfo = (proto_tree_search_info*)data;
514 field_info *fi = (field_info*) (gnode->data);
516 if (fi->hfinfo->id == sinfo->target) {
517 g_array_append_val(sinfo->result.array, fi->value.ether);
520 return FALSE; /* FALSE = do not end traversal of GNode tree */
523 gboolean fill_array_ipv4_variable(GNode *gnode, gpointer data)
525 proto_tree_search_info *sinfo = (proto_tree_search_info*)data;
526 field_info *fi = (field_info*) (gnode->data);
528 if (fi->hfinfo->id == sinfo->target) {
529 g_array_append_val(sinfo->result.array, fi->value.ipv4);
532 return FALSE; /* FALSE = do not end traversal of GNode tree */
534 gboolean fill_array_ipv6_variable(GNode *gnode, gpointer data)
536 proto_tree_search_info *sinfo = (proto_tree_search_info*)data;
537 field_info *fi = (field_info*) (gnode->data);
539 if (fi->hfinfo->id == sinfo->target) {
540 g_array_append_val(sinfo->result.array, fi->value.ipv6);
543 return FALSE; /* FALSE = do not end traversal of GNode tree */
546 gboolean fill_array_bytes_variable(GNode *gnode, gpointer data)
548 proto_tree_search_info *sinfo = (proto_tree_search_info*)data;
549 field_info *fi = (field_info*) (gnode->data);
551 guint read_start, pkt_end;
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) {
562 /* Check to make sure offset exists for this field */
563 if (bytes_offset >= fi->length) {
567 pkt_end = fi->start + fi->length;
568 read_start = fi->start + bytes_offset;
570 /* Check to make sure entire length requested is inside field */
571 if (pkt_end < read_start + bytes_length) {
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);
581 return FALSE; /* FALSE = do not end traversal of GNode tree */
584 gboolean fill_array_numeric_value(GNode *gnode, gpointer data)
586 GArray *array = (GArray*)data;
587 dfilter_node *dnode = (dfilter_node*) (gnode->data);
589 g_array_append_val(array, dnode->value.numeric);
590 return FALSE; /* FALSE = do not end traversal of GNode tree */
593 gboolean fill_array_floating_value(GNode *gnode, gpointer data)
595 GArray *array = (GArray*)data;
596 dfilter_node *dnode = (dfilter_node*) (gnode->data);
598 g_array_append_val(array, dnode->value.floating);
599 return FALSE; /* FALSE = do not end traversal of GNode tree */
602 gboolean fill_array_ether_value(GNode *gnode, gpointer data)
604 GArray *array = (GArray*)data;
605 dfilter_node *dnode = (dfilter_node*) (gnode->data);
607 g_array_append_val(array, dnode->value.ether);
609 return FALSE; /* FALSE = do not end traversal of GNode tree */
612 gboolean fill_array_ipv4_value(GNode *gnode, gpointer data)
614 GArray *array = (GArray*)data;
615 dfilter_node *dnode = (dfilter_node*) (gnode->data);
617 g_array_append_val(array, dnode->value.ipv4);
619 return FALSE; /* FALSE = do not end traversal of GNode tree */
622 gboolean fill_array_ipv6_value(GNode *gnode, gpointer data)
624 GArray *array = (GArray*)data;
625 dfilter_node *dnode = (dfilter_node*) (gnode->data);
627 g_array_append_val(array, dnode->value.ipv6);
629 return FALSE; /* FALSE = do not end traversal of GNode tree */
632 gboolean fill_array_bytes_value(GNode *gnode, gpointer data)
634 GArray *array = (GArray*)data;
635 dfilter_node *dnode = (dfilter_node*) (gnode->data);
636 GByteArray *barray = dnode->value.bytes;
638 g_array_append_val(array, barray);
640 return FALSE; /* FALSE = do not end traversal of GNode tree */
643 gboolean check_relation_numeric(gint operand, GArray *a, GArray *b)
645 int i, j, len_a, len_b;
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))
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))
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))
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))
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))
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))
714 g_assert_not_reached();
717 g_assert_not_reached();
721 gboolean check_relation_floating(gint operand, GArray *a, GArray *b)
723 int i, j, len_a, len_b;
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))
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))
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))
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))
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))
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))
792 g_assert_not_reached();
795 g_assert_not_reached();
799 gboolean check_relation_ipv4(gint operand, GArray *a, GArray *b)
801 int i, j, len_a, len_b;
802 ipv4_addr *ptr_a, *ptr_b;
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))
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))
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))
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))
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))
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))
876 g_assert_not_reached();
880 gboolean check_relation_ipv6(gint operand, GArray *a, GArray *b)
882 int i, j, len_a, len_b;
883 guint8 *ptr_a, *ptr_b;
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)
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)
913 g_assert_not_reached();
917 gboolean check_relation_ether(gint operand, GArray *a, GArray *b)
919 int i, j, len_a, len_b;
920 guint8 *ptr_a, *ptr_b;
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)
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)
950 g_assert_not_reached();
954 gboolean check_relation_bytes(gint operand, GArray *a, GArray *b)
956 int i, j, len_a, len_b;
957 GByteArray *ptr_a,*ptr_b;
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)
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)
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)
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)
1009 g_assert_not_reached();