Wireshark-dev: Re: [Wireshark-dev] Suggested enhancements for WireShark
From: "Anders Broman \(AL/EAB\)" <anders.broman@xxxxxxxxxxxx>
Date: Tue, 27 Mar 2007 13:45:37 +0200
Hi,
I'm looking at something simmilar where a number of bits are added to
the tree and where the bit position
In the octet(s) are variable. I think this can be useful in bit oriented
protocol where a number of bit
Can be otional and a fixed mask is useless. This is jut prototype code:

Offset and length is given in bits making it possible to add:
..10 10..   Foo 10
Or
.101 0...   Foo 10

proto_item *
h263_proto_tree_add_bits(proto_tree *tree, int hf_index, tvbuff_t *tvb,
gint bit_offset, gint no_of_bits)
{
	gint offset;
	guint length;
	char *str;
	header_field_info *hfinfo;
	guint32 value = 0;
	int bit;
	guint32 mask, tmp;
	gboolean is_bytealigned = FALSE;
	guint8 mask8	= 0xff;
	guint16 mask16	= 0xffff;
	guint32 mask24	= 0xffffff;
	guint32 mask32	= 0xffffffff;
	guint8 shift;
	int i;
	const char *format = NULL;

	if((bit_offset&0x7)==0)
		is_bytealigned = TRUE;

	hfinfo = proto_registrar_get_nth(hf_index);

	offset = bit_offset>>3;
	length = ((bit_offset&0x7)+no_of_bits)>>3;
	length = length +1;

	if (no_of_bits < 2){
		/* Single bit */
		mask8 = mask8 >>(bit_offset&0x7);
		value = tvb_get_guint8(tvb,offset) & mask8;
		mask = 0x80;
		shift = 8-((bit_offset + no_of_bits)&0x7);
		value = value >> shift;
		mask = mask >> shift;
		length = 1;
	}else if(no_of_bits < 9){
		/* One or 2 bytes */
		if(length == 1){
			/* Spans 1 byte */
			mask8 = mask8>>(bit_offset&0x7);
			value = tvb_get_guint8(tvb,offset)&mask8;
			mask = 0x80;
		}else{
			/* Spans 2 bytes */	
			mask16 = mask16>>(bit_offset&0x7);
			value = tvb_get_ntohs(tvb,offset) & mask16;
			mask = 0x8000;
		}
		shift = 8-((bit_offset + no_of_bits)&0x7);
		value = value >> shift;
		mask = mask >> shift;
		
	}else if (no_of_bits < 17){
		/* 2 or 3 bytes */
		if(length == 2){
			/* Spans 2 bytes */
			mask16 = mask16>>(bit_offset&0x7);
			value = tvb_get_ntohs(tvb,offset) & mask16;
			mask = 0x8000;
		}else{
			/* Spans 3 bytes */	
			mask24 = mask24>>(bit_offset&0x7);
			value = tvb_get_ntoh24(tvb,offset) & mask24;
			mask = 0x800000;
		}
		shift = 8-((bit_offset + no_of_bits)&0x7);

		value = value >> shift;
		mask = mask >> shift;

	}else if (no_of_bits < 25){
		/* 3 or 4 bytes */
		if(length == 3){
			/* Spans 3 bytes */
			mask24 = mask24>>(bit_offset&0x7);
			value = tvb_get_ntoh24(tvb,offset) & mask24;
			mask = 0x800000;
		}else{
			/* Spans 4 bytes */	
			mask32 = mask32>>(bit_offset&0x7);
			value = tvb_get_ntohl(tvb,offset) & mask32;
			mask = 0x800000;
		}
		shift = 8-((bit_offset + no_of_bits)&0x7);

		value = value >> shift;
		mask = mask >> shift;

	}else if (no_of_bits < 33){
		/* 4 or 5 bytes */

	}else{
		g_assert_not_reached();
	}

	/* prepare the string */
	str=ep_alloc(256);
	g_snprintf(str, 256, "");
	for(bit=0;bit<((int)(bit_offset&0x07));bit++){
		if(bit&&(!(bit%4))){
			strcat(str, " ");
		}
		strcat(str,".");
		mask = mask>>1;
	}
	/* read the bits for the int */
	for(i=0;i<no_of_bits;i++){
		if(bit&&(!(bit%4))){
			strcat(str, " ");
		}
		if(bit&&(!(bit%8))){
			length+=1;
			strcat(str, " ");
		}
		bit++;
		tmp = value & mask;
		if(tmp != 0){
			strcat(str, "1");
		} else {
			strcat(str, "0");
		}
		mask = mask>>1;
	}
	for(;bit%8;bit++){
		if(bit&&(!(bit%4))){
			strcat(str, " ");
		}
		strcat(str,".");
	}


	strcat(str," = ");
	strcat(str,hfinfo->name);
	if (no_of_bits== 1){
		/* Boolean field */
		if (hfinfo->strings) {
			const true_false_string		*tfstring =
&tfs_true_false;
			tfstring = (const struct true_false_string*)
hfinfo->strings;

			return proto_tree_add_boolean_format(tree,
hf_index, tvb, offset, length, value,
				"%s: %s",
				str,
				value ? tfstring->true_string :
tfstring->false_string);
		}

	}
	/* 2 - 32 bits field */

	if (hfinfo->strings) {
		return proto_tree_add_uint_format(tree, hf_index, tvb,
offset, length, value,
                      "%s: %s",
					  str,
					  val_to_str(value,
cVALS(hfinfo->strings), "Unknown"), value);
	}
	switch(hfinfo->display){
	case BASE_DEC:
		return proto_tree_add_uint_format(tree, hf_index, tvb,
offset, length, value,
	                 "%s: %u",
					  str,
					  value);
		break;
	case BASE_HEX:
		return proto_tree_add_uint_format(tree, hf_index, tvb,
offset, length, value,
	                 "%s: %x",
					  str,
					  value);
		break;
	default:
		DISSECTOR_ASSERT_NOT_REACHED();
		return NULL;
		;
	}

}

Best regards
Anders 

-----Original Message-----
From: wireshark-dev-bounces@xxxxxxxxxxxxx
[mailto:wireshark-dev-bounces@xxxxxxxxxxxxx] On Behalf Of Alexey Neyman
Sent: den 27 mars 2007 13:25
To: wireshark-dev@xxxxxxxxxxxxx
Subject: [Wireshark-dev] Suggested enhancements for WireShark

Hi All,

Suggest 2 enhancements to WireShark:

1. (format_value.diff)

Make the proto_tree_add_*_format_value() functions prepend the bitmask
indicators (those dots, zeros and ones) to bitfields. This makes it
easier to format bitfields where only the value need to be formatted in
some special way.

Currently, there are no uses of proto_tree_add_(int|uint|
boolean)_format_value() with bitfields, with one exception. The
exception is in the packet-bvlc.c file, and the usage is weird: there, a
bitmask of 0xFFFF is applied to a 16-bit integer - which is obviously
pointless. 
Thus, no existing usage of these functions will be harmed.

2. (add_bitmask_text.diff)

Provide somewhat more flexible tool for bitmask dissection. The new
function, proto_tree_add_bitmask_text() is described in the patch, which
updates doc/README.developer as well.

Regards,
Alexey.