aboutsummaryrefslogtreecommitdiffstats
path: root/epan/proto.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2012-02-29 17:13:43 +0000
committerAnders Broman <anders.broman@ericsson.com>2012-02-29 17:13:43 +0000
commit597047d2538c76def069e7bec4e76ee1e9f32ed6 (patch)
tree90c2633596356248e327458b05771f9a09a13338 /epan/proto.c
parent501216eb8a2a4ed9028eb8e987ec5716b7317955 (diff)
From Mike Morrin:
The attached patches add the ability to dissect split bit-strings as discussed under bug 6797. proto_tree_add_split_bits_ret_val() proto_tree_add_split_bits_crumb() svn path=/trunk/; revision=41246
Diffstat (limited to 'epan/proto.c')
-rw-r--r--epan/proto.c156
1 files changed, 141 insertions, 15 deletions
diff --git a/epan/proto.c b/epan/proto.c
index 777e08c224..45978dd286 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -7301,13 +7301,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
if (tot_no_bits & 0x07)
length++;
- if (no_of_bits < 9){
- value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
- }else if(no_of_bits < 17){
- value = tvb_get_bits16(tvb, bit_offset, no_of_bits, encoding);
- }else if(no_of_bits < 33){
- value = tvb_get_bits32(tvb, bit_offset, no_of_bits, encoding);
- }else if(no_of_bits < 65){
+ if(no_of_bits < 65){
value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
}else{
DISSECTOR_ASSERT_NOT_REACHED();
@@ -7387,6 +7381,144 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb
}
proto_item *
+proto_tree_add_split_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
+ const gint bit_offset, const crumb_spec_t *crumb_spec,
+ guint64 *return_value)
+{
+ proto_item *pi;
+ gint octet_offset, mask_initial_bit_offset, mask_greatest_bit_offset = 0;
+ guint octet_length;
+ guint8 i = 0;
+ char *bf_str = NULL, lbl_str[ITEM_LABEL_LENGTH];
+ header_field_info *hf_field;
+ guint64 value = 0, composite_bitmask = 0, composite_bitmap = 0;
+ const true_false_string *tfstring;
+
+ /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
+ PROTO_REGISTRAR_GET_NTH(hf_index, hf_field);
+
+ if(hf_field -> bitmask != 0) {
+ REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val with field '%s' (%s) with bitmask != 0",
+ hf_field->abbrev, hf_field->name));
+ }
+
+ mask_initial_bit_offset = bit_offset % 8;
+
+ while(crumb_spec[i].crumb_bit_length != 0)
+ {
+ guint64 crumb_mask, crumb_value;
+ guint8 crumb_end_bit_offset;
+
+ DISSECTOR_ASSERT(i < 64);
+ crumb_value = tvb_get_bits64(tvb, bit_offset + crumb_spec[i].crumb_bit_offset, crumb_spec[i].crumb_bit_length, ENC_BIG_ENDIAN);
+ value += crumb_value;
+
+ /* the bitmask is 64 bit, left-aligned, starting at the first bit of the octet containing the initial offset */
+ /* if the mask is beyond 32 bits, then give up on bit map display
+ this could be improved in future, probably showing a table of 32 or 64 bits per row */
+ if (mask_greatest_bit_offset < 32)
+ {
+ crumb_end_bit_offset = mask_initial_bit_offset + crumb_spec[i].crumb_bit_offset + crumb_spec[i].crumb_bit_length;
+ crumb_mask = (1 << crumb_spec[i].crumb_bit_length) - 1;
+
+ if(crumb_end_bit_offset > mask_greatest_bit_offset)
+ {
+ mask_greatest_bit_offset = crumb_end_bit_offset;
+ }
+ composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
+ composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
+ }
+ /* shift left for the next segment */
+ value <<= crumb_spec[++i].crumb_bit_length;
+ }
+ if(return_value){
+ *return_value=value;
+ }
+
+ /* Coast clear. Try and fake it */
+ TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
+
+ /* initialise the fromat string */
+ bf_str=ep_alloc(256);
+ bf_str[0] = '\0';
+
+ octet_offset = bit_offset >> 3;
+
+ /* round up mask length to nearest octet */
+ octet_length = ((mask_greatest_bit_offset + 7) >> 3);
+ mask_greatest_bit_offset = octet_length << 3;
+
+ /* as noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb,
+ it would be a useful enhancement to eliminate this restriction. */
+ if (mask_greatest_bit_offset <= 32)
+ {
+ other_decode_bitfield_value(bf_str, (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
+ (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
+ mask_greatest_bit_offset);
+ }
+
+ switch(hf_field->type){
+ case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
+ /* Boolean field */
+ tfstring = (const true_false_string *) &tfs_true_false;
+ if (hf_field->strings)
+ tfstring = (const true_false_string *) hf_field->strings;
+ return proto_tree_add_boolean_format(tree, hf_index, tvb, octet_offset, octet_length, (guint32)value,
+ "%s = %s: %s",
+ bf_str, hf_field->name,
+ (guint32)value ? tfstring->true_string : tfstring->false_string);
+ break;
+
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ pi = proto_tree_add_uint(tree, hf_index, tvb, octet_offset, octet_length, (guint32)value);
+ fill_label_uint(PITEM_FINFO(pi), lbl_str);
+ break;
+
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ pi = proto_tree_add_int(tree, hf_index, tvb, octet_offset, octet_length, (gint32)value);
+ fill_label_int(PITEM_FINFO(pi), lbl_str);
+ break;
+
+ case FT_UINT64:
+ pi = proto_tree_add_uint64(tree, hf_index, tvb, octet_offset, octet_length, value);
+ fill_label_uint64(PITEM_FINFO(pi), lbl_str);
+ break;
+
+ case FT_INT64:
+ pi = proto_tree_add_int64(tree, hf_index, tvb, octet_offset, octet_length, (gint64)value);
+ fill_label_int64(PITEM_FINFO(pi), lbl_str);
+ break;
+
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ return NULL;
+ break;
+ }
+ proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
+ return pi;
+}
+
+void
+proto_tree_add_split_bits_crumb(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const gint bit_offset,
+ const crumb_spec_t *crumb_spec, guint16 crumb_index)
+{
+ header_field_info *hf_info;
+
+ PROTO_REGISTRAR_GET_NTH(hf_index, hf_info);
+ proto_tree_add_text(tree, tvb, bit_offset >> 3, ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
+ "%s crumb %d of %s (decoded above)",
+ decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
+ tvb_get_bits(tvb, bit_offset, crumb_spec[crumb_index].crumb_bit_length, ENC_BIG_ENDIAN)),
+ crumb_index, hf_info->name);
+}
+
+proto_item *
proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
const gint bit_offset, const gint no_of_bits,
guint64 *return_value, const guint encoding)
@@ -7436,14 +7568,8 @@ _proto_tree_add_bits_format_value(proto_tree *tree, const int hf_index,
if (tot_no_bits & 0x07)
length++;
- if (no_of_bits < 9){
- value = tvb_get_bits8(tvb, bit_offset, no_of_bits);
- }else if(no_of_bits < 17){
- value = tvb_get_bits16(tvb, bit_offset, no_of_bits, FALSE);
- }else if(no_of_bits < 33){
- value = tvb_get_bits32(tvb, bit_offset, no_of_bits, FALSE);
- }else if(no_of_bits < 65){
- value = tvb_get_bits64(tvb, bit_offset, no_of_bits, FALSE);
+ if(no_of_bits < 65){
+ value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
}else{
DISSECTOR_ASSERT_NOT_REACHED();
return NULL;