From: Michael Mann Date: Fri, 13 Oct 2017 04:28:50 +0000 (-0400) Subject: Add ptvcursor APIs that return the values it retrieves X-Git-Url: http://git.samba.org/?p=metze%2Fwireshark%2Fwip.git;a=commitdiff_plain;h=337f49243faeab6796c12e434928823606dda195 Add ptvcursor APIs that return the values it retrieves ptvcursor_add_ret_uint ptvcursor_add_ret_int ptvcursor_add_ret_string ptvcursor_add_ret_boolean Change-Id: I41fa91b1ab805778d34a61215830b12a1331e864 Reviewed-on: https://code.wireshark.org/review/23895 Reviewed-by: Michael Mann Petri-Dish: Michael Mann Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols index 35c70f4437..637fa8e35c 100644 --- a/debian/libwireshark0.symbols +++ b/debian/libwireshark0.symbols @@ -1223,6 +1223,10 @@ libwireshark.so.0 libwireshark0 #MINVER# protocols_module@Base 1.9.1 ptvcursor_add@Base 1.9.1 ptvcursor_add_no_advance@Base 1.9.1 + ptvcursor_add_ret_boolean@Base 2.5.0 + ptvcursor_add_ret_int@Base 2.5.0 + ptvcursor_add_ret_string@Base 2.5.0 + ptvcursor_add_ret_uint@Base 2.5.0 ptvcursor_add_text_with_subtree@Base 1.9.1 ptvcursor_add_with_subtree@Base 1.9.1 ptvcursor_advance@Base 1.9.1 diff --git a/doc/README.dissector b/doc/README.dissector index 737848d8f1..89a1e75900 100644 --- a/doc/README.dissector +++ b/doc/README.dissector @@ -3529,6 +3529,22 @@ the ptvcursor advances its cursor so the next call to ptvcursor_add starts where this call finished. The 'encoding' parameter is relevant for certain type of fields (See above under proto_tree_add_item()). +proto_item* +ptvcursor_add_ret_uint(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, guint32 *retval); + Like ptvcursor_add, but returns uint value retreived + +proto_item* +ptvcursor_add_ret_int(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, gint32 *retval); + Like ptvcursor_add, but returns int value retreived + +proto_item* +ptvcursor_add_ret_string(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, wmem_allocator_t *scope, const guint8 **retval); + Like ptvcursor_add, but returns string retreived + +proto_item* +ptvcursor_add_ret_boolean(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, gboolean *retval); + Like ptvcursor_add, but returns boolean value retreived + proto_item* ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length, const guint encoding) Like ptvcursor_add, but does not advance the internal cursor. diff --git a/epan/proto.c b/epan/proto.c index 5bbf5ca001..129fac57ca 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -2086,6 +2086,32 @@ tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi) } } + +/* + * Validates that field length bytes are available starting from + * start (pos/neg). Throws an exception if they aren't. + */ +static void +test_length(header_field_info *hfinfo, tvbuff_t *tvb, + gint start, gint length, const guint encoding) +{ + gint size = length; + + if (!tvb) + return; + + if ((hfinfo->type == FT_STRINGZ) || + ((encoding & ENC_VARINT_PROTOBUF) && (IS_FT_UINT(hfinfo->type) || IS_FT_UINT(hfinfo->type)))) { + /* If we're fetching until the end of the TVB, only validate + * that the offset is within range. + */ + if (length == -1) + size = 0; + } + + tvb_ensure_bytes_exist(tvb, start, size); +} + /* Add an item to a proto_tree, using the text label registered to that item; the item is extracted from the tvbuff handed to it. */ static proto_item * @@ -2678,6 +2704,233 @@ proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, return proto_tree_add_node(tree, new_fi); } +/* Gets data from tvbuff, adds it to proto_tree, increments offset, + * and returns proto_item* and uint value retreived*/ +proto_item * +ptvcursor_add_ret_uint(ptvcursor_t *ptvc, int hfindex, gint length, + const guint encoding, guint32 *retval) +{ + field_info *new_fi; + header_field_info *hfinfo; + gint item_length; + int offset; + guint32 value; + + offset = ptvc->offset; + PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); + + switch (hfinfo->type){ + case FT_CHAR: + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + break; + default: + REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(), + "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32", + hfinfo->abbrev)); + } + + get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding); + test_length(hfinfo, ptvc->tvb, offset, item_length, encoding); + + /* I believe it's ok if this is called with a NULL tree */ + /* XXX - modify if we ever support EBCDIC FT_CHAR */ + value = get_uint_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding); + + if (retval) { + *retval = value; + if (hfinfo->bitmask) { + /* Mask out irrelevant portions */ + *retval &= (guint32)(hfinfo->bitmask); + /* Shift bits */ + *retval >>= hfinfo_bitshift(hfinfo); + } + } + + ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length, + item_length, encoding); + + CHECK_FOR_NULL_TREE(ptvc->tree); + + /* Coast clear. Try and fake it */ + TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); + + new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length); + + return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb, + offset, length, encoding); +} + +/* Gets data from tvbuff, adds it to proto_tree, increments offset, + * and returns proto_item* and int value retreived*/ +proto_item * +ptvcursor_add_ret_int(ptvcursor_t *ptvc, int hfindex, gint length, + const guint encoding, gint32 *retval) +{ + field_info *new_fi; + header_field_info *hfinfo; + gint item_length; + int offset; + guint32 value; + + offset = ptvc->offset; + PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); + + switch (hfinfo->type){ + case FT_INT8: + case FT_INT16: + case FT_INT24: + case FT_INT32: + break; + default: + REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(), + "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32", + hfinfo->abbrev)); + } + + get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding); + test_length(hfinfo, ptvc->tvb, offset, item_length, encoding); + + /* I believe it's ok if this is called with a NULL tree */ + /* XXX - modify if we ever support EBCDIC FT_CHAR */ + value = get_int_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding); + + if (retval) { + gint no_of_bits; + *retval = value; + if (hfinfo->bitmask) { + /* Mask out irrelevant portions */ + *retval &= (guint32)(hfinfo->bitmask); + /* Shift bits */ + *retval >>= hfinfo_bitshift(hfinfo); + } + no_of_bits = ws_count_ones(hfinfo->bitmask); + *retval = ws_sign_ext32(*retval, no_of_bits); + } + + ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length, + item_length, encoding); + + CHECK_FOR_NULL_TREE(ptvc->tree); + + /* Coast clear. Try and fake it */ + TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); + + new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length); + + return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb, + offset, length, encoding); +} + +/* Gets data from tvbuff, adds it to proto_tree, increments offset, + * and returns proto_item* and string value retreived */ +proto_item* +ptvcursor_add_ret_string(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, wmem_allocator_t *scope, const guint8 **retval) +{ + header_field_info *hfinfo; + field_info *new_fi; + const guint8 *value; + gint item_length; + int offset; + + offset = ptvc->offset; + + PROTO_REGISTRAR_GET_NTH(hf, hfinfo); + + switch (hfinfo->type){ + case FT_STRING: + value = get_string_value(scope, ptvc->tvb, offset, length, &item_length, encoding); + break; + case FT_STRINGZ: + value = get_stringz_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding); + break; + case FT_UINT_STRING: + value = get_uint_string_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding); + break; + case FT_STRINGZPAD: + value = get_stringzpad_value(scope, ptvc->tvb, offset, length, &item_length, encoding); + break; + default: + REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(), + "field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, or FT_STRINGZPAD", + hfinfo->abbrev)); + } + + if (retval) + *retval = value; + + ptvc->offset += item_length; + + CHECK_FOR_NULL_TREE(ptvc->tree); + + TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo); + + new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length); + + return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb, + offset, length, encoding); +} + +/* Gets data from tvbuff, adds it to proto_tree, increments offset, + * and returns proto_item* and boolean value retreived */ +proto_item* +ptvcursor_add_ret_boolean(ptvcursor_t* ptvc, int hfindex, gint length, const guint encoding, gboolean *retval) +{ + header_field_info *hfinfo; + field_info *new_fi; + gint item_length; + int offset; + guint64 value, bitval; + + offset = ptvc->offset; + PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); + + if (hfinfo->type != FT_BOOLEAN) { + REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(), + "field %s is not of type FT_BOOLEAN", hfinfo->abbrev)); + } + + /* length validation for native number encoding caught by get_uint64_value() */ + /* length has to be -1 or > 0 regardless of encoding */ + if (length < -1 || length == 0) + REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(), + "Invalid length %d passed to proto_tree_add_item_ret_uint", + length)); + + if (encoding & ENC_STRING) { + REPORT_DISSECTOR_BUG("wrong encoding"); + } + + get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding); + test_length(hfinfo, ptvc->tvb, offset, item_length, encoding); + + /* I believe it's ok if this is called with a NULL tree */ + value = get_uint64_value(ptvc->tree, ptvc->tvb, offset, length, encoding); + + if (retval) { + bitval = value; + if (hfinfo->bitmask) { + /* Mask out irrelevant portions */ + bitval &= hfinfo->bitmask; + } + *retval = (bitval != 0); + } + + ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length, + item_length, encoding); + + CHECK_FOR_NULL_TREE(ptvc->tree); + + TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo); + + new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length); + + return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb, + offset, length, encoding); +} + proto_item * proto_tree_add_item_ret_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start, gint length, const guint encoding, guint64 *retval) @@ -2906,30 +3159,6 @@ proto_tree_add_item_ret_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, tvb, start, length, encoding, scope, retval, &length); } -/* - * Validates that field length bytes are available starting from - * start (pos/neg). Throws an exception if they aren't. - */ -static void -test_length(header_field_info *hfinfo, tvbuff_t *tvb, - gint start, gint length, const guint encoding) -{ - gint size = length; - - if (!tvb) - return; - - if ((hfinfo->type == FT_STRINGZ) || - ((encoding & ENC_VARINT_PROTOBUF) && (IS_FT_UINT(hfinfo->type) || IS_FT_UINT(hfinfo->type)))) { - /* If we're fetching until the end of the TVB, only validate - * that the offset is within range. - */ - if (length == -1) - size = 0; - } - - tvb_ensure_bytes_exist(tvb, start, size); -} /* Gets data from tvbuff, adds it to proto_tree, increments offset, and returns proto_item* */ diff --git a/epan/ptvcursor.h b/epan/ptvcursor.h index ad85c312a3..8462a969cd 100644 --- a/epan/ptvcursor.h +++ b/epan/ptvcursor.h @@ -45,6 +45,29 @@ WS_DLL_PUBLIC proto_item* ptvcursor_add(ptvcursor_t* ptvc, int hf, gint length, const guint encoding); +/* Gets data from tvbuff, adds it to proto_tree, increments offset, + * and returns proto_item* and uint value retreived*/ +WS_DLL_PUBLIC +proto_item* +ptvcursor_add_ret_uint(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, guint32 *retval); + +/* Gets data from tvbuff, adds it to proto_tree, increments offset, + * and returns proto_item* and int value retreived */ +WS_DLL_PUBLIC +proto_item* +ptvcursor_add_ret_int(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, gint32 *retval); + +/* Gets data from tvbuff, adds it to proto_tree, increments offset, + * and returns proto_item* and string value retreived */ +WS_DLL_PUBLIC +proto_item* +ptvcursor_add_ret_string(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, wmem_allocator_t *scope, const guint8 **retval); + +/* Gets data from tvbuff, adds it to proto_tree, increments offset, + * and returns proto_item* and boolean value retreived */ +WS_DLL_PUBLIC +proto_item* +ptvcursor_add_ret_boolean(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, gboolean *retval); /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment * offset, and returns proto_item* */