Ask Your Question

Capitalising hex strings in dissector field output?

asked 2020-06-24 06:18:53 +0000

brett323 gravatar image


Is there a way to capitalise hex output in the field output like we can with the string formatter "0x%04X"?

I'm using that to add the details to the INFO column but not sure how to get similar formatting in the dissected fields:


For example, I have the field is being output like below:

DMX message number: PACKED_SIM_GROUP_M3UA_S (0xcfdc)

But I'd prefer to have the hex number printed as 0xCFDC (just makes it simpler for us to see the message number).

I am poking around the source for proto_tree_add_item to pin down where the actual hex digit printing occurs ... haven't figured it out yet.

In my dissector I'm doing this:

            static const value_string dmxMessageNumber[] = {
                { 0xCFDC, "PACKED_SIM_GROUP_M3UA_S" },

             proto_tree_add_item(dmx_tree, hf_emb_msg_header_t_number, tvb, 
                                 offset, 2, ENC_LITTLE_ENDIAN);

            { &hf_emb_msg_header_t_number,
               {"DMX message number", "emb.dmx.number",
                   FT_UINT16, BASE_HEX, VALS(dmxMessageNumber), 
                   0x0, "DX message number (message_number_t)", HFILL}},

Thanks, Brett.

edit retag flag offensive close merge delete


I guess one workaround would be to simply use the column editing mode to copy the hex number in my dmxMessageNumber array so it's part of the text output string, something like:


That would only take a few seconds to do for all 120+ array members I have at the moment.

In that case, is there any way to suppress the output of the (0xcfdc)?

brett323 gravatar imagebrett323 ( 2020-06-24 06:26:36 +0000 )edit

Ah huh, in PROTO.C I think I've found where the actual formatting is done?

So I could get it to print all hex strings capitalised by modifying this function and recompiling?

hfinfo_char_value_format_display(int display, char buf[7], guint32 value)
    char *ptr = &buf[6];
    static const gchar hex_digits[16] =
    { '0', '1', '2', '3', '4', '5', '6', '7',
      '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

            case BASE_HEX:
                *(--ptr) = hex_digits[value & 0x0F];
                value >>= 4;
                *(--ptr) = hex_digits[value & 0x0F];
                *(--ptr) = 'x';
brett323 gravatar imagebrett323 ( 2020-06-24 06:42:26 +0000 )edit

Nope and nope. I've modified in EPAN/PROTO.C and also a similar one I found in EPAN/PRINT.C and neither had any effect:

static gboolean
print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
                      guint length, packet_char_enc encoding)

    static gchar binhex[16] = {
        '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
brett323 gravatar imagebrett323 ( 2020-06-24 06:56:32 +0000 )edit

I'm a big fan of "patch and pray" coding so maybe try changing epan/to_str.c. Or maybe a better long term solution is to use BASE_CUSTOM: doc/README.dissector

For integer fields (FT_UINT* and FT_INT*), this variable represents the
base in which you would like the value displayed. The acceptable bases


BASE_DEC, BASE_HEX, and BASE_OCT are decimal, hexadecimal, and octal,
respectively. BASE_DEC_HEX and BASE_HEX_DEC display value in two bases
(the 1st representation followed by the 2nd in parenthesis).

BASE_CUSTOM allows one to specify a callback function pointer that will
format the value.
Chuckc gravatar imageChuckc ( 2020-06-24 13:06:31 +0000 )edit

Ha ha, indeed! It's also a good way to figure out how things work.

I did consider BASE_CUSTOM when I came upon it in the code but then also saw a comment in PROTO.C that said:

case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */

So I discounted it without further investigation - I'll have a proper look at how it works.

And you're right about TO_STR.C ... patched that one and now all my hex strings are capitalised ... happiness ;)

static inline char
low_nibble_of_octet_to_hex(guint8 oct)
    /* At least one version of Apple's C compiler/linker is buggy, causing
       a complaint from the linker about the "literal C string section"
       not ending with '\0' if we initialize a 16-element "char" array with
       a 16-character string, the fact that initializing such an array with
       such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
       '\0' byte in the string ...
brett323 gravatar imagebrett323 ( 2020-06-24 21:15:47 +0000 )edit

2 Answers

Sort by ยป oldest newest most voted

answered 2020-06-24 21:32:52 +0000

Guy Harris gravatar image

updated 2020-06-25 07:50:19 +0000

grahamb gravatar image

Perhaps this would be better done as a general preference so users, rather than dissector writers, can choose whether to show a-f or A-F in hex displays?

Or should we just say "capital letters" and be done with it?

edit flag offensive delete link more


I'd be happy with that. For me, I just find it instantly clearer to read 0xABCD rather than 0xabcd.

brett323 gravatar imagebrett323 ( 2020-06-25 07:56:04 +0000 )edit

answered 2020-06-25 04:19:06 +0000

brett323 gravatar image

updated 2020-06-25 05:54:31 +0000

Thanks for the advice Chuck - using BASE_CUSTOM was exactly what I needed!

A little convoluted but I found a good example of what I needed to implement in one of the GSM Abis dissectors (epan/dissectors/packet-gsm_abis_oml.c) .

I created five new functions - one each to handle bytes (0x%02X) & words (0x%04X), and then three to handle outputs that included value strings.

Revisiting my original example, I now call print_dmx_message which both prints out the message name and also prints the message number in upper case hex:

static void
print_dmx_message(gchar *result, guint16 message_number )
    /* print message name and number 0xABCD (or 0x000A, etc.) */
    const gchar *tmp = NULL;

    tmp = try_val_to_str(message_number, dmxMessageNumber);
    if (tmp)
        g_snprintf(result, ITEM_LABEL_LENGTH, "%s (0x%04X)", tmp,message_number);
        g_snprintf(result, ITEM_LABEL_LENGTH, "Unknown (0x%04X)", message_number);
            { &hf_emb_msg_header_t_number,
                {"DMX message number", "emb.dmx.number",
                    FT_UINT16, BASE_CUSTOM, CF_FUNC(print_dmx_message), 0x0,
                    "DX message number (message_number_t)", HFILL}},
edit flag offensive delete link more


Glad it worked out. Wasn't looking forward to opening a new bug if that comment in proto.c was applicable. :-)

Chuckc gravatar imageChuckc ( 2020-06-25 05:19:08 +0000 )edit

It also meant I could customise the output of the internal program block IDs we use - they're stored as a word value but really are only three digit hex numbers.

So instead of just having the default 0x0abc output, I now have something that looks nicer (for my needs):

static void
print_dmx_family(gchar *result, guint16 family_id )
    /* print 00A, 0AB, or ABC */
    const gchar *tmp = NULL;

    tmp = try_val_to_str(family_id, dmxFamily);
    if (tmp)
        g_snprintf(result, ITEM_LABEL_LENGTH, "%s (%03X)", tmp,family_id);
        g_snprintf(result, ITEM_LABEL_LENGTH, "Unknown (%03X)", family_id);

which results in

DMX family: ZS4PRB (SIP access side signalling service) (68C)
brett323 gravatar imagebrett323 ( 2020-06-25 05:41:36 +0000 )edit

I had originally tried calling the val_to_str within the g_snprintf function but this caused Wireshark to crash when it returned a NULL (I'm guessing), something like:

g_snprintf(result, ITEM_LABEL_LENGTH, "%s (0x%04X)", val_to_str(message_number, dmxMessageNumber, "Unknown"), message_number);

Hence why I had to grep around a bit more until I found the example in the Abis dissector, and hence why I've implemented it the way I have.

brett323 gravatar imagebrett323 ( 2020-06-25 06:03:30 +0000 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2020-06-24 06:18:53 +0000

Seen: 37 times

Last updated: Jun 25