This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

Difference between proto_tree_add_item and proto_tree_add_uint

0

Hi, I am writing a dissector in C and have a question in regards to what the differences are between proto_tree_add_item and proto_tree_add_uint. I have experiences Expert Info Warnings of "Trying to fetch an unsigned integer with length --" when using proto_tree_add_item with sizes above a certain amount. Switching this to proto_tree_add_uint results in these warnings disappearing. Under the hood, what is the difference between these two functions? This is the only conversation I've seen on the topic: https://www.wireshark.org/lists/wireshark-dev/201408/msg00296.html

[As reference I've including the functions as seen in proto.c]

/* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */

proto_item *

proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, guint32 value)

{ proto_item *pi = NULL;

header_field_info *hfinfo;

CHECK_FOR_NULL_TREE(tree);

TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

switch (hfinfo->type) {
    case FT_CHAR:
    case FT_UINT8:
    case FT_UINT16:
    case FT_UINT24:
    case FT_UINT32:
    case FT_FRAMENUM:
        pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
        proto_tree_set_uint(PNODE_FINFO(pi), value);
        break;

    default:
        DISSECTOR_ASSERT_NOT_REACHED();
}

return pi;

}

proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
const gint start, gint length, const guint encoding)

{

register header_field_info *hfinfo;

PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);

}

asked 21 Mar ‘17, 07:50

brownfox's gravatar image

brownfox
21338
accept rate: 0%

edited 21 Mar ‘17, 07:59


2 Answers:

1

Wireshark version?

Are you correctly matching the FT_XXX type in the hfindex structure with the length you're passing into the proto_xxx call? That is, for FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24 and FT_UINT32 length has to be 1, 1, 2, 3, or 4 respectively. For FT_UINT40, FT_UINT48, FT_UINT56 and FT_UINT64 the length has to be 5, 6, 7 or 8 respectively.

answered 21 Mar '17, 08:15

grahamb's gravatar image

grahamb ♦
19.8k330206
accept rate: 22%

I'm using version 2.3.0.

For example, one of my packets in the capture file contains a 32-byte SHA256 hash.

Here's the corresponding code:

proto_tree_add_uint(proto_tree, hf_proto_config_sha256_hash_frame, tvb, offset, CONFIG_SHA256_HASH_FRAME_LEN, ENC_LITTLE_ENDIAN); offset += CONFIG_SHA256_HASH_FRAME_LEN;

{&hf_proto_config_sha256_hash_frame, {"Config SHA256 Hash This Frame", "proto.config_sha256_hash_frame", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }

As a side note, there's an issue with the display in Wireshark using BASE_DEC but I believe that is due to a mistake in the generated capture file not being little endian.

(21 Mar '17, 08:33) brownfox

And what's the hfproto_config_sha256_hash_frame declaration?

Note that it doesn't make sense (to me at least) to show a SHA256 hash as a FT_UINTXX value, especially as a uint is limited to 8 bytes. You could use a FT_NONE type as is done for hashes in SSL, e.g. packet-ssl-utils.c function ssl_dissect_hnd_finished() with ssl_hfs.hs_sha_hash (declared in packet-ssl.c), passing in 32 for the length.

I would actually argue that hashes should be using FT_BYTES rather than FT_NONE as that's what they are, a sequence of bytes with arbitrary values.

(21 Mar '17, 09:38) grahamb ♦

My hf_proto_config_sha256_hash_frame is now

{"Config SHA256 Hash This Frame", "proto.config_sha256_hash_frame", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }

as you suggested. It works without error so thank you for that. I had initially chosen to display the hash as FT_UINT16 just as a placeholder before seeing how it was done in other protocols - thanks for the reference to SSL.

I think this is the solution though I'll try to fix the other fields first.

(21 Mar '17, 10:12) brownfox

1

The proto_tree_add functions perform the essential function of populating the tree with fields from the data packet at hand. The function which supports the most common operations in one is proto_tree_add_item(). It helps to do the following:

  • Retrieve the relevant value from the tvb (as defined by the header field used)
  • Add a tree item (when needed)
  • Highlight the data in the bytes pane

So basically all common functions are wrapped into one. The header field is important here, it defines much of the retrieval and representation of the value. It provides a lot of flexibility for most common situations.

But sometimes this is not enough. Sometimes you want more control over the actual value used for this field, which somehow cannot be provided by the functionality of the header field. Then you can resort to proto_tree_add_uint(). This does the same, but for value retrieval, that value is now passed via the function interface.

You say you run into trouble when using certain lengths, but not when using proto_tree_add_uint(). This for sure comes from the fact that the header field is no longer used for value retrieval, just highlighting.

answered 21 Mar '17, 08:06

Jaap's gravatar image

Jaap ♦
11.7k16101
accept rate: 14%