First time here? Check out the FAQ!
THIS IS A TEST INSTANCE. Feel free to ask and answer questions, but take care to avoid triggering too many notifications.
0

Dissector plugin: binary-coded-decimal encoding

Writing a Wireshark dissector plugin in C++. The protocol I'm trying to parse uses the uncommon packed binary-coded-decimal format for all of its integers.

Normally, when I want to add an item of length length at offset offset, I write:

proto_tree_add_item(body, fields.foo, tvb, offset, length, ENC_LITTLE_ENDIAN);
proto_tree_add_item(body, fields.foo, tvb, offset, length, ENC_NA); // big-endian int
proto_tree_add_item(body, fields.foo, tvb, offset, length, ENC_ASCII); // string

... etc. I also need to register the field array with:

proto_register_field_array(handle, field_array, array_length(field_array));

... where the field_array is an array of hf_register_info, like this:

static hf_register_info field_array[] = {
    { &fields.foo, { "Foo Field", "protocol.foo", FT_UINT48, BASE_DEC } },
    // etc. other fields
};

... supposing my example is a 6-byte packed BCD (capable of holding 12 decimal digits).

This all works nicely when I'm parsing sensible protocols that send uint32, ASCII, int64, etc., over the wire. But there appears to be no built-in Wireshark encoding for packed BCDs.

I can see a hacky work-around to parse it as raw data, and then write a function to translate the raw data into the correct value (or use something like tvb_bcd_dig_to_wmem_packet_str), and then use proto_item_set_text to set the item to my desired representation.

Is there a better way?

anton's avatar
1
anton
asked 2018-01-04 02:42:11 +0000, updated 2018-01-04 02:42:47 +0000
edit flag offensive 0 remove flag close merge delete

Comments

add a comment see more comments

2 Answers

0

If you search for tvb_bcd_dig... in the code base you can find many examples on how people have dealt with it. If you are planning to commit your dissector to Wireshark, write it in C not C++. Regards Anders

Anders's avatar
5k
Anders
answered 2018-01-04 05:13:26 +0000
grahamb's avatar
23.8k
grahamb
updated 2018-01-05 10:29:12 +0000
edit flag offensive 0 remove flag delete link

Comments

Thank you: I did come across that function as well, but as it turns out, it wasn't necessary for my particular dissector. (I'm not planning to commit the dissector to Wireshark: it's too specific).

anton's avatar anton (2018-01-04 05:34:04 +0000) edit
add a comment see more comments
0

No particular encoding is necessary to make Wireshark display the value nicely. A binary-coded-decimal is like a plain integer, except that the value needs to be translated as if it were decimal.

So 56 (decimal value) for example will be transmitted (assuming big-endian / network-byte-order on the wire) as 0000 0000 0101 0110 or 0056 (hex). All that is needed is to register the field as a FT_UINTX (e.g. UINT32 for 4 byte Packed BCD, UINT40 for 5 byte, etc.) with BASE_HEX representation.

static hf_register_info field_array[] = {
    { &fields.foo, { "Foo Field", "protocol.foo", FT_UINT48, BASE_HEX } },
    // etc. other fields
}; // works for 6-byte packed BCD

And in the dissecting function itself, add the item:

proto_tree_add_item(body, fields.foo, tvb, offset, length, ENC_NA);

As for actually turning the BCD bytes into an integer, we can just write a function to transform BCDs to unsigned, e.g.:

#include <cstdint>

uint64_t bcd_to_uint(const char* start, const size_t bytes)
{
    uint64_t value = 0;
    for (size_t i = 0; i < bytes; ++i)
    {
        uint8_t data = start[i] - '0';
        value += ((data >> 4) * 10 + (data & 0x0f)) * ipow(100, bytes - i - 1);
        // right-shift unsigned will fill with 0s
        // integer promotion will prevent overflow up to UINT_MAX
        // ipow(base, exp) returns base to the power of exp, returns uint64
    }
    return value;
}
anton's avatar
1
anton
answered 2018-01-04 04:58:46 +0000
grahamb's avatar
23.8k
grahamb
updated 2018-01-05 10:29:37 +0000
edit flag offensive 0 remove flag delete link

Comments

add a comment see more comments

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account. This space is reserved only for answers. If you would like to engage in a discussion, please instead post a comment under the question or an answer that you would like to discuss.

Add Answer