Ethereal-dev: [Ethereal-dev] some dfilter work

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Ed Warnicke <hagbard@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 26 Dec 2000 02:31:18 -0500 (EST)
I've attacked implementing some of the changes from last weeks 
discussion.

I haven't extended range types from FT_BYTES to other types.

I have changed the way ranges work in the following sense.

[i:j] 

still works the way it always did, [offset:length]

[i]

will now always choose the element of offset i (length 1).

[i-j]

will select all element from offset i to offset j

and you can string these three forms together with a comma(,) 
which concatentate the selected bits together

[i,j,l:k,m-n]

roughly the grammar is 

bytes_variable  	=	T_FT_BYTES "[" range "]"

range 		= 	range-element
		|
			range-element "," range

range-element	= 	NUM ":" NUM
		|	NUM
		| 	NUM "-" NUM

What I want to know is:

Does this seem like an improvement to people?  

If so I will extend this to the rest of the sequence types as 
discussed.  

I've attatched a patch and a tar file containing two new source
files ethereal/epan/drange.{c,h} containing these changes.

Please try this out and let me know how it works for you.  

Ed

Attachment: drange.tar.gz
Description: tar file containing ethereal/epan/drange.{c,h}

? cscope.out
? out
? epan/drange.h
? epan/drange.c
? epan/Makefile.am.new
Index: epan/Makefile.am
===================================================================
RCS file: /cvsroot/ethereal/epan/Makefile.am,v
retrieving revision 1.14
diff -u -r1.14 Makefile.am
--- Makefile.am	2000/11/20 16:18:08	1.14
+++ Makefile.am	2000/12/26 06:58:35
@@ -46,6 +46,8 @@
 	dfilter-scanner.l	\
 	dfilter.c		\
 	dfilter.h		\
+	drange.c		\
+	drange.h		\
 	epan.c			\
 	epan.h			\
 	except.c		\
Index: epan/dfilter-grammar.y
===================================================================
RCS file: /cvsroot/ethereal/epan/dfilter-grammar.y,v
retrieving revision 1.2
diff -u -r1.2 dfilter-grammar.y
--- dfilter-grammar.y	2000/12/22 12:05:36	1.2
+++ dfilter-grammar.y	2000/12/26 06:58:35
@@ -70,6 +70,7 @@
 #endif
 
 #include "dfilter-int.h"
+#include "drange.h"
 
 #ifndef __RESOLV_H__
 #include "resolv.h"
@@ -91,21 +92,33 @@
 static GNode* dfilter_mknode_ipv6_variable(gint id);
 static GNode* dfilter_mknode_existence(gint id);
 static GNode* dfilter_mknode_bytes_value(GByteArray *barray);
-static GNode* dfilter_mknode_bytes_variable(gint id, gint offset, guint length, gboolean to_the_end);
+static GNode* dfilter_mknode_bytes_variable(gint id, drange* range);
 static GNode* dfilter_mknode_string_value(char *s);
 static GNode* dfilter_mknode_string_variable(gint id);
 
 static guint32 string_to_guint32(char *s, gboolean *success);
 static double string_to_double(char *s, gboolean *success);
 static int ether_str_to_guint8_array(const char *s, guint8 *mac);
-static guint dfilter_get_bytes_variable_offset(GNode *gnode);
 static guint dfilter_get_bytes_value_length(GNode* gnode);
-static void dfilter_set_bytes_variable_length(GNode *gnode, guint length);
-static guint dfilter_get_bytes_variable_length(GNode *gnode);
-static gint dfilter_get_bytes_variable_field_registered_length(GNode *gnode);
 static char* dfilter_get_variable_abbrev(GNode *gnode);
-static int check_bytes_variable_sanity(GNode *gnode);
 
+static drange_node* byte_string_to_drange_node(gchar* s, gboolean *success);
+static drange_node* string_to_drange_node(gchar* s, gboolean *success);
+static gboolean dfilter_is_range_variable(GNode *gnode);
+static gboolean dfilter_range_variable_has_total_length(GNode *gnode);
+static gint dfilter_get_range_variable_total_length(GNode *gnode);
+static int check_range_variable_sanity(GNode *gnode);
+static gint dfilter_get_range_variable_field_registered_length(GNode *gnode);
+static drange* null_to_drange(drange* range);
+
+static void check_range_variable_sanity_iterator(gpointer data, gpointer user_data);
+
+typedef struct _check_range_variable_sanity_iterator_arg{
+  gint max_length;
+  gboolean *success;
+  gchar* variable_abbrev;
+} check_range_variable_sanity_iterator_arg;
+
 /* This is the dfilter we're currently processing. It's how
  * dfilter_compile communicates with us.
  */
@@ -125,6 +138,7 @@
 		gint	offset;
 		guint	length;
 	} byte_range;
+        drange* range;
 }
 
 %type <node>	statement expression relation
@@ -138,6 +152,8 @@
 %type <node>	variable_name
 %type <node>	bytes_value bytes_variable
 
+%type <range>   range
+
 %type <operand>	numeric_relation
 %type <operand>	equality_relation
 %type <operand>	bytes_relation
@@ -169,6 +185,7 @@
 
 %token <operand>	TOK_AND TOK_OR TOK_NOT TOK_XOR
 %token <operand>	TOK_EQ TOK_NE TOK_GT TOK_GE TOK_LT TOK_LE
+%token <operand>        TOK_BRA TOK_KET TOK_COMMA
 
 %expect 4
 %left TOK_AND
@@ -261,20 +278,19 @@
 	|	bytes_variable bytes_relation bytes_value
 		{
 			int a_len, b_len;
+			gboolean a_has_length;
 
-			a_len = dfilter_get_bytes_variable_length($1);
+			a_len = b_len = 0;
+			a_has_length = dfilter_range_variable_has_total_length($1);
+			if(a_has_length)
+			  a_len = dfilter_get_range_variable_total_length($1);
 			b_len = dfilter_get_bytes_value_length($3);
 
-			if (a_len == 0) {
-				dfilter_set_bytes_variable_length($1, b_len);
-				a_len = b_len;
-			}
-
-			if (!check_bytes_variable_sanity($1)) {
+			if (!check_range_variable_sanity($1)) {
 				YYERROR;
 			}
 
-			if (a_len != b_len) {
+			if (a_has_length && a_len != b_len) {
 				dfilter_fail("Field \"%s\" has %u byte%s being compared, but %u byte%s "
 					"%s supplied.",
 					dfilter_get_variable_abbrev($1),
@@ -283,25 +299,32 @@
 					       plurality(b_len, "was", "were"));
 				YYERROR;
 			}
-
 			$$ = dfilter_mknode_join($1, relation, $2, $3);
 		}
 	|	bytes_variable bytes_relation bytes_variable
 		{
 			int a_len, b_len;
+			gboolean a_has_length;
+			gboolean b_has_length;
 
-			a_len = dfilter_get_bytes_variable_length($1);
-			b_len = dfilter_get_bytes_variable_length($3);
+			a_len = b_len = 0;
 
-			if (!check_bytes_variable_sanity($1)) {
+			a_has_length = dfilter_range_variable_has_total_length($1);
+			b_has_length = dfilter_range_variable_has_total_length($3);
+			if(a_has_length)
+			  a_len = dfilter_get_range_variable_total_length($1);
+			if(b_has_length)
+			  b_len = dfilter_get_range_variable_total_length($3);
+
+			if (!check_range_variable_sanity($1)) {
 				YYERROR;
 			}
 
-			if (!check_bytes_variable_sanity($3)) {
+			if (!check_range_variable_sanity($3)) {
 				YYERROR;
 			}
 
-			if (a_len != b_len) {
+			if (a_has_length && b_has_length && a_len != b_len) {
 				dfilter_fail("Fields \"%s\" and \"%s\" are being compared with "
 					"disparate lengths of %u byte%s and %u byte%s.",
 					dfilter_get_variable_abbrev($1),
@@ -548,18 +571,74 @@
 string_variable:	T_FT_STRING	{ $$ = dfilter_mknode_string_variable($1.id); }
 	;
 
-bytes_variable:		T_FT_BYTES T_VAL_BYTE_RANGE
+bytes_variable:		T_FT_BYTES TOK_BRA range TOK_KET
 		{
-			$$ = dfilter_mknode_bytes_variable($1.id, $2.offset, $2.length, FALSE);
+			$$ = dfilter_mknode_bytes_variable($1.id,$3);
 		}
 
         |               T_FT_BYTES      
                 {
-		        $$ = dfilter_mknode_bytes_variable($1.id, 0, 0, TRUE);
+		        $$ = dfilter_mknode_bytes_variable($1.id, NULL);
 		}
 
 	;
 
+
+range:                  T_VAL_BYTE_STRING
+                {
+		        drange* dr;
+                        drange_node* drnode;
+			gboolean success;
+			dr = drange_new();
+			drnode = byte_string_to_drange_node($1,&success);
+			if(success == FALSE){
+			  dfilter_fail("%s is not a range",$1);
+			  YYERROR;
+			}
+			drange_prepend_drange_node(dr,drnode);
+			$$ = dr;
+		}
+        |               T_VAL_BYTE_STRING TOK_COMMA range
+                {
+                        drange_node* drnode;
+			gboolean success;
+			drnode = byte_string_to_drange_node($1,&success);
+			if(success == FALSE){
+			  dfilter_fail("%s is not a range",$1);
+			  YYERROR;
+			}
+			drange_prepend_drange_node($3,drnode);
+			$$ = $3;
+		}
+        |               T_VAL_UNQUOTED_STRING
+                {
+		        drange* dr;
+                        drange_node* drnode;
+			gboolean success;
+
+			dr = drange_new();
+			drnode = string_to_drange_node($1,&success);
+			if(success == FALSE){
+			  dfilter_fail("%s is not a range",$1);
+			  YYERROR;
+			}
+			drange_prepend_drange_node(dr,drnode);
+			$$ = dr;
+		}
+        |               T_VAL_UNQUOTED_STRING TOK_COMMA range
+                {
+                        drange_node* drnode;
+			gboolean success;
+			drnode = string_to_drange_node($1,&success);
+			if(success == FALSE){
+			  dfilter_fail("%s is not a range",$1);
+			  YYERROR;
+			}
+			drange_prepend_drange_node($3,drnode);
+			$$ = $3;
+		}
+        ;
+
 variable_name:		any_variable_type
                 {
 		GNode	*variable;
@@ -792,10 +871,11 @@
 }
 
 static GNode*
-dfilter_mknode_bytes_variable(gint id, gint offset, guint length, gboolean to_the_end)
+dfilter_mknode_bytes_variable(gint id, drange* range)
 {
 	dfilter_node	*node;
 	GNode		*gnode;
+	range = null_to_drange(range);
 
 	node = g_mem_chunk_alloc(global_df->node_memchunk);
 	node->ntype = variable;
@@ -804,62 +884,12 @@
 	node->fill_array_value_func = NULL;
 	node->check_relation_func = check_relation_bytes;
 	node->value.variable = id;
-	node->offset = offset;
-	node->length = length;
-	node->to_the_end = to_the_end;
+	node->range = range;
 	gnode = g_node_new(node);
-
+      	
 	return gnode;
 }
 
-/* Gets length of variable represented by node from proto_register */
-static gint
-dfilter_get_bytes_variable_field_registered_length(GNode *gnode)
-{
-	dfilter_node	*node = gnode->data;
-
-	/* Is this really a bytes_variable? */
-	g_assert(node->fill_array_variable_func == fill_array_bytes_variable);
-
-	return proto_registrar_get_length(node->value.variable);
-}
-
-/* Sets the length of a bytes_variable node */
-static void
-dfilter_set_bytes_variable_length(GNode *gnode, guint length)
-{
-	dfilter_node	*node = gnode->data;
-
-	/* Is this really a bytes_variable? */
-	g_assert(node->fill_array_variable_func == fill_array_bytes_variable);
-
-	node->length = length;
-}
-
-/* Gets the length of a bytes_variable node */
-static guint
-dfilter_get_bytes_variable_length(GNode *gnode)
-{
-	dfilter_node	*node = gnode->data;
-
-	/* Is this really a bytes_variable? */
-	g_assert(node->fill_array_variable_func == fill_array_bytes_variable);
-
-	return node->length;
-}
-
-/* Gets the offset of a bytes_variable node */
-static guint
-dfilter_get_bytes_variable_offset(GNode *gnode)
-{
-	dfilter_node	*node = gnode->data;
-
-	/* Is this really a bytes_variable? */
-	g_assert(node->fill_array_variable_func == fill_array_bytes_variable);
-
-	return node->offset;
-}
-
 static char*
 dfilter_get_variable_abbrev(GNode *gnode)
 {
@@ -1166,26 +1196,184 @@
 }
 
 
+/* We aren't really trying to convert a byte_string into a drange_node,
+ * but the scanner may have mistaken a range like 23:25 for a 
+ * byte string, so we correct for that here ( as the alternative 
+ * involves a MAJOR overhaul of a lot of other code.
+ */
+static drange_node* byte_string_to_drange_node(gchar* s, gboolean *success){
+  drange_node* drnode;
+  gint str_len, offset, length;
+  gboolean is_dash;
+  offset = 0;
+  length = 0;
+  is_dash = FALSE;
+  str_len = strlen(s);
+  drnode = NULL;
+  *success = FALSE;
+  if(str_len < 6){ /* are we any bigger than xx:yy ? */
+    drnode = string_to_drange_node(s,success);
+  }
+  return drnode;
+}
+
+/* convert a string like i:j or i-j into a drange_node */
+
+static drange_node* string_to_drange_node(gchar* s, gboolean *success){
+
+  drange_node* drnode;
+  gchar **str_array,*endptr;
+  gint str_len, offset, length,split_len;
+  gboolean is_dash,to_the_end;
+  offset = 0;
+  length = 0;
+  is_dash = FALSE;
+  to_the_end = FALSE;
+
+  str_len = strlen(s);
+  drnode = NULL;
+  *success = FALSE;
+
+  str_array = g_strsplit(s,":",2);
+  split_len = strlen(str_array[0]);
+  if( ( str_array[0] != NULL ) && ( split_len != str_len )){
+    offset = strtol(str_array[0],&endptr,10);
+    if( *endptr == '\0'){
+      if(str_array[1] != NULL){
+	length = strtol(str_array[1],&endptr,10);
+	if(*endptr == '\0'){
+	  *success = TRUE;
+	}
+      }
+    }
+  }
+  else {
+    g_strfreev(str_array);
+    str_array = g_strsplit(s,"-",2);
+    split_len = strlen(str_array[0]);
+    if( ( str_array[0] != NULL ) && ( split_len != str_len )){
+      is_dash = TRUE;
+      offset = strtol(str_array[0],&endptr,10);
+      if( *endptr == '\0'){
+	if(str_array[1] != NULL){
+	  length = strtol(str_array[1],&endptr,10);
+	  if(*endptr == '\0'){
+	    *success = TRUE;
+	  }
+	}
+	else if(s[str_len-1] == '-'){
+	  to_the_end = TRUE;
+	  *success = TRUE;
+	  is_dash = FALSE;
+	}
+      }
+    }
+    else {
+      offset = strtol(str_array[0],&endptr,10);
+      length = 1;
+      if( *endptr == '\0'){
+	*success = TRUE;
+      }
+    }
+  }
+  g_strfreev(str_array);
+  if(is_dash){
+    length = (length + 1) - offset;
+  }
+  if( *success ) {
+    drnode = drange_node_new();
+    drange_node_set_offset(drnode,offset);
+    drange_node_set_length(drnode,length);
+    drange_node_set_to_the_end(drnode,to_the_end);
+  }
+  return drnode;
+}
+
+static gboolean dfilter_is_range_variable(GNode *gnode){
+	dfilter_node	*node = gnode->data;
+	return (node->fill_array_variable_func == fill_array_bytes_variable);
+}
+
+static gboolean dfilter_range_variable_has_total_length(GNode *gnode){
+  	dfilter_node	*node = gnode->data;
+	return (drange_has_total_length(node->range));
+}
+
+static gint dfilter_get_range_variable_total_length(GNode *gnode){
+  	dfilter_node	*node = gnode->data;
+	return (drange_get_total_length(node->range));
+}
+
+/* Gets length of variable represented by node from proto_register */
+static gint
+dfilter_get_range_variable_field_registered_length(GNode *gnode)
+{
+	dfilter_node	*node = gnode->data;
+
+	/* Is this really a range_variable? */
+	g_assert(dfilter_is_range_variable(gnode));
+
+	return proto_registrar_get_length(node->value.variable);
+}
+
 static int
-check_bytes_variable_sanity(GNode *gnode)
+check_range_variable_sanity(GNode *gnode)
 {
-	int a_off, a_len, reg_len, t_off;
 
-	a_off = dfilter_get_bytes_variable_offset(gnode);
-	a_len = dfilter_get_bytes_variable_length(gnode);
-	reg_len = dfilter_get_bytes_variable_field_registered_length(gnode);
-
-	if (reg_len > 0) {
-		t_off = a_off >= 0 ? a_off : reg_len + a_off;
-		if (t_off + a_len > reg_len) {
-			dfilter_fail("The \"%s\" field is only %u byte%s wide, but "
-				"%u byte%s %s supplied.",
-				dfilter_get_variable_abbrev(gnode),
-				reg_len, plurality(reg_len, "", "s"),
-				a_len, plurality(a_len, "", "s"),
-				       plurality(a_len, "was", "were"));
-			return 0;
-		}
-	}
-	return 1;
+	dfilter_node* node;
+	gboolean success;
+	check_range_variable_sanity_iterator_arg* arg;
+
+	arg = g_malloc(sizeof(check_range_variable_sanity_iterator_arg));
+
+	node = gnode->data;
+	arg->max_length = dfilter_get_range_variable_field_registered_length(gnode);
+	success = TRUE;
+	arg->success = &success;
+	arg->variable_abbrev = dfilter_get_variable_abbrev(gnode);
+	drange_foreach_drange_node(node->range,check_range_variable_sanity_iterator, arg);
+	g_free(arg);
+	return ( success );
+}
+
+static void check_range_variable_sanity_iterator(gpointer data, gpointer user_data){
+  check_range_variable_sanity_iterator_arg* arg;
+  drange_node* drnode;
+  gboolean *success_ptr;
+  gint a_off, a_len, a_to_the_end,t_off;
+  arg = (check_range_variable_sanity_iterator_arg*)user_data;
+
+  success_ptr = arg->success;
+  if(*(success_ptr) == TRUE){    
+    drnode = (drange_node*)data;
+    a_off = drange_node_get_offset(drnode);
+    a_len = drange_node_get_length(drnode);
+    a_to_the_end = drange_node_get_to_the_end(drnode);
+    if(arg->max_length > 0){
+      t_off = a_off >= 0 ? a_off : arg->max_length + a_off;
+      if( a_to_the_end == FALSE && ( t_off + a_len > arg->max_length ) ){
+	dfilter_fail("The \"%s\" field is only %u byte%s wide, but "
+		     "%u byte%s %s supplied.",
+		     arg->variable_abbrev,
+		     arg->max_length, plurality(arg->max_length, "", "s"),
+		     a_len, plurality(a_len, "", "s"),
+		     plurality(a_len, "was", "were"));
+	*(success_ptr) = FALSE;
+      }
+    }
+  }
+}
+
+static drange* null_to_drange(drange* range){
+  drange*         dr;
+  drange_node*    drnode;
+  dr = range;
+  if(dr == NULL){
+    drnode = drange_node_new();
+    drange_node_set_offset(drnode,0);
+    drange_node_set_to_the_end(drnode,TRUE);
+    dr = drange_new();
+    drange_prepend_drange_node(dr,drnode);
+  }  
+  return dr;
 }
Index: epan/dfilter-int.h
===================================================================
RCS file: /cvsroot/ethereal/epan/dfilter-int.h,v
retrieving revision 1.2
diff -u -r1.2 dfilter-int.h
--- dfilter-int.h	2000/12/22 12:05:36	1.2
+++ dfilter-int.h	2000/12/26 06:58:35
@@ -31,6 +31,8 @@
 #include "ipv4.h"
 #endif
 
+#include "drange.h"
+
 /* in dfilter-scanner.l */
 GByteArray *byte_str_to_guint8_array(const char *s);
 void dfilter_scanner_text(char*);
@@ -140,6 +142,9 @@
 
         /* used to indicate range should go to end of sequence */
         gboolean                        to_the_end;
+
+        /* used to handle many ranges */
+        drange* range;
 } dfilter_node;
 
 /* lookup an abbreviation in our token hash, returing the ID # */
Index: epan/dfilter-scanner.l
===================================================================
RCS file: /cvsroot/ethereal/epan/dfilter-scanner.l,v
retrieving revision 1.1
diff -u -r1.1 dfilter-scanner.l
--- dfilter-scanner.l	2000/09/27 04:54:48	1.1
+++ dfilter-scanner.l	2000/12/26 06:58:35
@@ -115,53 +115,9 @@
 ge|\>\=		{ dfilter_lval.operand = TOK_GE; return TOK_GE; }
 lt|\<		{ dfilter_lval.operand = TOK_LT; return TOK_LT; }
 le|\<\=		{ dfilter_lval.operand = TOK_LE; return TOK_LE; }
-
-\[{whitespace}*-?[0-9]+{whitespace}*:{whitespace}*[0-9]+{whitespace}*\] { /* range [ x : y ] */
-
-	char	*byterange_string = g_strdup(yytext);
-	char	*s = byterange_string + 1; /* I don't want the first '[' */
-	char	*p;
-
-	/* Get the offset from the string */
-	if ((p = strtok(s, ":"))) {
-		dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
-	}
-	else {
-		g_free(byterange_string);
-		return 0;
-	}
-
-	/* Get the Length from the string */
-	if ((p = strtok(NULL, "]"))) {
-		dfilter_lval.byte_range.length = strtoul(p, NULL, 10);
-	}
-	else {
-		g_free(byterange_string);
-		return 0;
-	}
-	g_free(byterange_string);
-	return T_VAL_BYTE_RANGE;
-}
-
-\[{whitespace}*-?[0-9]+{whitespace}*\] { /* range [ x  ] */
-
-	char	*byterange_string = g_strdup(yytext);
-	char	*s = byterange_string + 1; /* I don't want the first '[' */
-	char	*p;
-
-	/* Get the offset from the string */
-	if ((p = strtok(s, "]"))) {
-		dfilter_lval.byte_range.offset = strtol(p, NULL, 10);
-	}
-	else {
-		g_free(byterange_string);
-		return 0;
-	}
-
-	dfilter_lval.byte_range.length = 0;
-	g_free(byterange_string);
-	return T_VAL_BYTE_RANGE;
-}
+\[              { dfilter_lval.operand = TOK_BRA; return TOK_BRA; }
+\]              { dfilter_lval.operand = TOK_KET; return TOK_KET; }
+\,              { dfilter_lval.operand = TOK_COMMA; return TOK_COMMA; }
 
 {hex}({hexsep}{hex})+ {			/* byte string, any length */
 	dfilter_lval.string = g_strdup(yytext);
Index: epan/dfilter.c
===================================================================
RCS file: /cvsroot/ethereal/epan/dfilter.c,v
retrieving revision 1.3
diff -u -r1.3 dfilter.c
--- dfilter.c	2000/12/22 12:05:36	1.3
+++ dfilter.c	2000/12/26 06:58:36
@@ -44,6 +44,9 @@
 #include "dfilter-int.h"
 #include "dfilter-grammar.h"
 
+/* This should eventually be removed */
+#include "strutil.h"
+
 int dfilter_parse(void); /* yacc entry-point */
 
 #define DFILTER_LEX_ABBREV_OFFSET	2000
@@ -58,6 +61,7 @@
 int bytes_offset = 0;
 int bytes_length = 0;
 gboolean bytes_to_the_end = FALSE;
+drange* current_range = NULL;
 
 YYSTYPE yylval;
 
@@ -72,6 +76,14 @@
 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);
+static void pack_byte_array(gpointer data, gpointer user_data);
+
+typedef struct _pack_byte_array_arg {
+  GByteArray* barray;
+  drange* dr;
+  field_info* finfo;
+  const guint8* pd;
+} pack_byte_array_arg;
 
 /* 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
@@ -139,7 +151,6 @@
 {
 	dfilter *df;
 	int retval;
-
 	g_assert(dfilter_text != NULL);
 
 	df = dfilter_new();
@@ -165,7 +176,6 @@
 	 * 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),
@@ -174,7 +184,6 @@
 			dfilter_error_msg = &dfilter_error_msg_buf[0];
 		}
 	}
-
 	/* Set global_df to NULL just to be tidy. */
 	global_df = NULL;
 
@@ -430,8 +439,7 @@
 	dfilter_node	*node_b = (dfilter_node*) (b->data);
 	GArray		*vals_a, *vals_b;
 	gboolean	retval;
-
-
+	
 	if (node_a->ntype == variable)
 		vals_a = get_values_from_ptree(node_a, ptree, pd);
 	else
@@ -455,7 +463,6 @@
 
 	g_array_free(vals_a, FALSE);
 	g_array_free(vals_b, FALSE);
-
 	return retval;
 }
 
@@ -489,6 +496,8 @@
 	bytes_length = dnode->length;
 	bytes_to_the_end = dnode->to_the_end;
 
+	current_range = dnode->range;
+
 	/* Cull the finfos from the proto_tree */
 	finfo_array = proto_get_finfo_ptr_array(ptree, dnode->value.variable);
 	if (!finfo_array) {
@@ -550,38 +559,15 @@
 void
 fill_array_bytes_variable(field_info *finfo, GArray *array, const guint8 *pd)
 {
-	GByteArray		*barray;
-	guint			read_start, pkt_end, read_len;
-
-	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;
-	if(bytes_to_the_end){
-	        read_len = pkt_end - read_start;;
-	}
-	else {
-	        read_len = bytes_length;
-	}
-	/* Check to make sure entire length requested is inside field */
-	if (pkt_end < read_start + read_len) {
-		return;
-	}
-
-	barray = g_byte_array_new();
-	g_byte_array_append(barray, pd + read_start, read_len);
-	g_array_append_val(array, barray);
+	pack_byte_array_arg*  arg;
+	arg = g_malloc(sizeof(pack_byte_array_arg));
+	arg->barray = g_byte_array_new();
+	arg->dr = current_range;
+	arg->finfo = finfo;
+	arg->pd = pd;
+	drange_foreach_drange_node(arg->dr,pack_byte_array,arg);
+	g_array_append_val(array,arg->barray);
+	g_free(arg);
 }
 
 static GArray*
@@ -985,7 +971,6 @@
 	len_a = a->len;
 	len_b = b->len;
 
-
 	switch(operand) {
 	case TOK_EQ:
 		for(i = 0; i < len_a; i++) {
@@ -1083,4 +1068,47 @@
 	g_assert_not_reached();
 	return FALSE;
 }
+
+static void pack_byte_array(gpointer data, gpointer user_data){
+  pack_byte_array_arg* arg;
+  drange_node* drnode;
+  guint			read_start, pkt_end, read_len;
+  gboolean to_the_end;
+  gint offset, length;
+  arg = (pack_byte_array_arg*)user_data;
+  drnode = (drange_node*)data;
+  
+  offset = drange_node_get_offset(drnode);
+  length = drange_node_get_length(drnode);
+  to_the_end = drange_node_get_to_the_end(drnode);
+
+  if (offset < 0) {
+    /* Handle negative byte offsets */
+    offset = arg->finfo->length + offset;
+    if (offset < 0) {
+      return;
+    }
+  }
+  
+  /* Check to make sure offset exists for this field */
+  if (offset >= arg->finfo->length) {
+    return;
+  }
+  
+  pkt_end = arg->finfo->start + arg->finfo->length;
+  read_start = arg->finfo->start + offset;
+  if(to_the_end){
+    read_len = pkt_end - read_start;;
+  }
+  else {
+    read_len = length;
+  }
+  /* Check to make sure entire length requested is inside field */
+  if (pkt_end < read_start + read_len) {
+    return;
+  }
+  
+  arg->barray = g_byte_array_append(arg->barray, arg->pd + read_start, read_len);
+  return;
+}