Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I've been given a template that uses an FT_ prefix instead of the g prefix - for example, it uses FT_Boolean and FT_UINT8 instead for the previous types.

They're not prefixes for the same kind of types.

The g prefix is for GLib types; those are typedefs in C, for use in C code.

The FT_ prefix is for Wireshark named field types. Those are data types for data within packets; some might happen to be similar to GLib (or C99) types, but that's more of a case of "those are concepts that go beyond either C or network packets" than a case of "the types are equivalents".

For example, a gboolean is 32 bits on all the platforms that GLib supports (unless it's used as the type of a C bitfield), but an FT_BOOLEAN field could be anywhere from 1 to 8 bytes.

Assume I have a 40 bit header, foo, with the following fields:

bit<2> version
bit<1> bypass
bit<1> command_flag
.... (skipping until the end of 32 bits for concision)
bit<8> sequuence_number

So I'm assuming that means that, from the uppermost bits to the lowermost bits, you have:

  • a 2-bit version number field;
  • a 1-bit bypass flag;
  • a 1-bit command flag;
  • 28 bits worth of other flags;
  • an 8-bit sequence number.

That sounds like a 32-bit word of bitfields, followed by an 8-bit field containing the sequence number.

What you can do, in that case, is to make the bitfields be bitfields; that's somewhat like C bitfields, except that the bits to which they correspond are specified by bit masks, and the bits to which they correspond are directly specified (unlike C bitfields, which may be big-endian or little-endian within the word; that's up to the compiler and the ABI of the particular platform for which the compile is being done).

You'd do that with something along the lines of:

static hf_register_info hf[] = {
    { &hf_foo_version_number,
        { "Version number", "foo.version_number",
        FT_UINT32, // This is an integer within a 32-bit quantity
        BASE_DEC,  // Display it in decimal
        NULL,
        0xC0000000, // Upper 2 bits of the 32-bit quantity
        NULL, HFILL }
    },
    { &hf_foo_version_number,
        { "Bypass", "foo.bypass",
        FT_BOOLEAN, // This is a Boolean
        32, // it's within a 32-bit quantity
        NULL,
        0x20000000, // The next bit down from the previous field
        NULL, HFILL }
    },
    { &hf_foo_command_flag,
        { "Command flag", "foo.command_flag",
        FT_BOOLEAN, // This is a Boolean
        32, // it's within a 32-bit quantity
        NULL,
        0x10000000, // The next bit down from the previous field
        NULL, HFILL }
    },

... (other fields here)

    { &hf_foo_sequence_number,
        { "Sequence number", "foo.sequence_number",
        FT_UINT8, // This is an 8-bit integer field
        BASE_DEC, // Display it in decimal
        NULL,
        0x0, // This is not a bitfield, it's the entire octet
        NULL, HFILL }
    },

... (additional protocol fields)

};

You could just add the bitfields with proto_tree_add_item(), with the offset being the offset of the first octet of the 32-bit word containing the fields and with the length being 4 (4 octets, 32 bits), or you could build an array of pointers to the hf_ values for the fields within the 32-bit word and make one call to one of the proto_tree_add_bitmask functions to add all of them - see the doc/README.dissector file.

What is the correct type to use here for dissecting this quantity? It's a two bit field, so boolean is too small and guint8 and/or FT_UINT8 are too large. I don't know what type to use there, which is where the label for this particular question comes from.

The correct types are FT_BOOLEAN for Booleans and FT_UINTn for the non-Booleans; n should be the length of the octet-aligned field in which the bitfields are contained.

The lengths are specified elsewhere; see below.

I've been given a template that uses an FT_ prefix instead of the g prefix - for example, it uses FT_Boolean and FT_UINT8 instead for the previous types.

...

What is the difference between FT_ and g versions of a type, if any? For example, what is the difference between "gboolean" and "FT_BOOLEAN" as a type?

They're not prefixes for the same kind of types.

The g prefix is for GLib types; those are typedefs in C, for use in C code.

The FT_ prefix is for Wireshark named field types. Those are data types for data within packets; some might happen to be similar to GLib (or C99) types, but that's more of a case of "those are concepts that go beyond either C or network packets" than a case of "the types are equivalents".

For example, a gboolean is 32 bits on all the platforms that GLib supports (unless it's used as the type of a C bitfield), but an FT_BOOLEAN field could be anywhere from 1 to 8 bytes.

I don't see FT mentioned at all in README.developer.

See section 1.2 "Explanation of needed substitutions in code skeleton." and section 1.5 "Constructing the protocol tree."; in the latter, look in the subsection "type (FIELDTYPE)".

BASE_DEC is how this value should be printed in Wireshark.

Yes, except that, for FT_BOOLEAN, it's a "special case" for Boolean bitfields, giving the length of the octet-aligned field in which the bitfield appears; see below.

The next four options are VALS(), ???, NULL, and HFILL. VALS() is allowing me to pass in the array that has a mapping from values read to semantic meanings for wireshark to display.

VALS() can actually be different things for different field types. VALS() is used for mappings from integral values to strings giving a semantic description (think of it as being for enumerated data types).

For Boolean values (FT_BOOLEAN), TFS() is used, instead; it stands for "true/false string", and what's wrapped in TFS() is a pointer to a struct true_false_string, which is a structure containing two character string pointers, one for the string to be used if the field is "true" (non-zero), and one for the string to be used if the field is "false" (zero).

There are some additional ones, such as VALS64() for 64-bit fields and 64-bit numerical values, and RVALS(), to specify the meanings of certain ranges of value.

?? seems to be...a mask? a size? a predefined value? It seems to be different things in different places in the code, so I'm lost there.

For fields that aren't bitfields within an octet-aligned field, it's unused, and normally set to 0x0.

For fields that are bitfields within an octet-aligned field, it's a bitmask indicating which bits in that octet-aligned field contain this field. See below for an example.

I have no idea what NULL is for.

It's for a "blurb" that gives a more complete description of the field than the label. It's optional; if it's null, the label is assumed to be a "good enough" description, so that's what's used. If you want a long description that shows up on the status line if you click on the field, but that's too long for the packet detail display, put it there; otherwise, just leave it as null.

I also have no idea what HFILL is for.

Not all fields of a header_field_info are for the dissector developer to fill in; some are used internally by Wireshark. For compilers that can produce warnings about a structure not all of whose fields have been filled in, Wireshark builds with those warnings enabled; the "h"eader field structure is "fill"ed in by HFILL with values for those fields, to squelch those warnings.

Assume I have a 40 bit header, foo, with the following fields:

bit<2> version
bit<1> bypass
bit<1> command_flag
.... (skipping until the end of 32 bits for concision)
bit<8> sequuence_number

So I'm assuming that means that, from the uppermost bits to the lowermost bits, you have:

  • a 2-bit version number field;
  • a 1-bit bypass flag;
  • a 1-bit command flag;
  • 28 bits worth of other flags;
  • an 8-bit sequence number.

That sounds like a 32-bit word of bitfields, followed by an 8-bit field containing the sequence number.

What you can do, in that case, is to make the bitfields be bitfields; that's somewhat like C bitfields, except that the bits to which they correspond are specified by bit masks, and the bits to which they correspond are directly specified (unlike C bitfields, which may be big-endian or little-endian within the word; that's up to the compiler and the ABI of the particular platform for which the compile is being done).

You'd do that with something along the lines of:

static hf_register_info hf[] = {
    { &hf_foo_version_number,
        { "Version number", "foo.version_number",
        FT_UINT32, // This is an integer within a 32-bit quantity
        BASE_DEC,  // Display it in decimal
        NULL,
        0xC0000000, // Upper 2 bits of the 32-bit quantity
        NULL, HFILL }
    },
    { &hf_foo_version_number,
        { "Bypass", "foo.bypass",
        FT_BOOLEAN, // This is a Boolean
        32, // it's within a 32-bit quantity
        NULL,
        0x20000000, // The next bit down from the previous field
        NULL, HFILL }
    },
    { &hf_foo_command_flag,
        { "Command flag", "foo.command_flag",
        FT_BOOLEAN, // This is a Boolean
        32, // it's within a 32-bit quantity
        NULL,
        0x10000000, // The next bit down from the previous field
        NULL, HFILL }
    },

... (other fields here)

    { &hf_foo_sequence_number,
        { "Sequence number", "foo.sequence_number",
        FT_UINT8, // This is an 8-bit integer field
        BASE_DEC, // Display it in decimal
        NULL,
        0x0, // This is not a bitfield, it's the entire octet
        NULL, HFILL }
    },

... (additional protocol fields)

};

You could just add the bitfields with proto_tree_add_item(), with the offset being the offset of the first octet of the 32-bit word containing the fields and with the length being 4 (4 octets, 32 bits), or you could build an array of pointers to the hf_ values for the fields within the 32-bit word and make one call to one of the proto_tree_add_bitmask functions to add all of them - see the doc/README.dissector file.

What is the correct type to use here for dissecting this quantity? It's a two bit field, so boolean is too small and guint8 and/or FT_UINT8 are too large. I don't know what type to use there, which is where the label for this particular question comes from.

The correct types are FT_BOOLEAN for Booleans and FT_UINTn for the non-Booleans; n should be the length of the octet-aligned field in which the bitfields are contained.

The lengths are specified elsewhere; see below.

I've been given a template that uses an FT_ prefix instead of the g prefix - for example, it uses FT_Boolean and FT_UINT8 instead for the previous types.

...

What is the difference between FT_ and g versions of a type, if any? For example, what is the difference between "gboolean" and "FT_BOOLEAN" as a type?

They're not prefixes for the same kind of types.

The g prefix is for GLib types; those are typedefs in C, for use in C code.

The FT_ prefix is for Wireshark named field types. Those are data types for data within packets; some might happen to be similar to GLib (or C99) types, but that's more of a case of "those are concepts that go beyond either C or network packets" than a case of "the types are equivalents".

For example, a gboolean is 32 bits on all the platforms that GLib supports (unless it's used as the type of a C bitfield), but an FT_BOOLEAN field could be anywhere from 1 to 8 bytes.

I don't see FT mentioned at all in README.developer.

See section 1.2 "Explanation of needed substitutions in code skeleton." and section 1.5 "Constructing the protocol tree."; in the latter, look in the subsection "type (FIELDTYPE)".

BASE_DEC is how this value should be printed in Wireshark.

Yes, except that, for FT_BOOLEAN, it's a "special case" for Boolean bitfields, giving the length of the octet-aligned field in which the bitfield appears; see below.

The next four options are VALS(), ???, NULL, and HFILL. VALS() is allowing me to pass in the array that has a mapping from values read to semantic meanings for wireshark to display.

VALS() can actually be different things for different field types. VALS() is used for mappings from integral values to strings giving a semantic description (think of it as being for enumerated data types).

For Boolean values (FT_BOOLEAN), TFS() is used, instead; it stands for "true/false string", and what's wrapped in TFS() is a pointer to a struct true_false_string, which is a structure containing two character string pointers, one for the string to be used if the field is "true" (non-zero), and one for the string to be used if the field is "false" (zero).

There are some additional ones, such as VALS64() for 64-bit fields and 64-bit numerical values, and RVALS(), to specify the meanings of certain ranges of value.

?? seems to be...a mask? a size? a predefined value? It seems to be different things in different places in the code, so I'm lost there.

For fields that aren't bitfields within an octet-aligned field, it's unused, and normally set to 0x0.

For fields that are bitfields within an octet-aligned field, it's a bitmask indicating which bits in that octet-aligned field contain this field. See below for an example.

I have no idea what NULL is for.

It's for a "blurb" that gives a more complete description of the field than the label. It's optional; if it's null, the label is assumed to be a "good enough" description, so that's what's used. If you want a long description that shows up on the status line if you click on the field, but that's too long for the packet detail display, put it there; otherwise, just leave it as null.

I also have no idea what HFILL is for.

Not all fields of a header_field_info are for the dissector developer to fill in; some are used internally by Wireshark. For compilers that can produce warnings about a structure not all of whose fields have been filled in, Wireshark builds with those warnings enabled; the "h"eader field structure is "fill"ed in by HFILL with values for those fields, to squelch those warnings.

Assume I have a 40 bit header, foo, with the following fields:

bit<2> version
bit<1> bypass
bit<1> command_flag
.... (skipping until the end of 32 bits for concision)
bit<8> sequuence_number

So I'm assuming that means that, from the uppermost bits to the lowermost bits, you have:

  • a 2-bit version number field;
  • a 1-bit bypass flag;
  • a 1-bit command flag;
  • 28 bits worth of other flags;
  • an 8-bit sequence number.

That sounds like a 32-bit word of bitfields, followed by an 8-bit field containing the sequence number.

What you can do, in that case, is to make the bitfields be bitfields; that's somewhat like C bitfields, except that the bits to which they correspond are specified by bit masks, and the bits to which they correspond are directly specified (unlike C bitfields, which may be big-endian or little-endian within the word; that's up to the compiler and the ABI of the particular platform for which the compile is being done).

You'd do that with something along the lines of:

static hf_register_info hf[] = {
    { &hf_foo_version_number,
        { "Version number", "foo.version_number",
        FT_UINT32, // This is an integer within a 32-bit quantity
        BASE_DEC,  // Display it in decimal
        NULL,
        0xC0000000, // Upper 2 bits of the 32-bit quantity
        NULL, HFILL }
    },
    { &hf_foo_version_number,
&hf_foo_bypass_flag,
        { "Bypass", "foo.bypass",
        FT_BOOLEAN, // This is a Boolean
        32, // it's within a 32-bit quantity
        NULL,
        0x20000000, // The next bit down from the previous field
        NULL, HFILL }
    },
    { &hf_foo_command_flag,
        { "Command flag", "foo.command_flag",
        FT_BOOLEAN, // This is a Boolean
        32, // it's within a 32-bit quantity
        NULL,
        0x10000000, // The next bit down from the previous field
        NULL, HFILL }
    },

... (other fields here)

    { &hf_foo_sequence_number,
        { "Sequence number", "foo.sequence_number",
        FT_UINT8, // This is an 8-bit integer field
        BASE_DEC, // Display it in decimal
        NULL,
        0x0, // This is not a bitfield, it's the entire octet
        NULL, HFILL }
    },

... (additional protocol fields)

};

You could just add the bitfields with proto_tree_add_item(), with the offset being the offset of the first octet of the 32-bit word containing the fields and with the length being 4 (4 octets, 32 bits), or you could build an array of pointers to the hf_ values for the fields within the 32-bit word and make one call to one of the proto_tree_add_bitmask functions to add all of them - see the doc/README.dissector file.

What is the correct type to use here for dissecting this quantity? It's a two bit field, so boolean is too small and guint8 and/or FT_UINT8 are too large. I don't know what type to use there, which is where the label for this particular question comes from.

The correct types are FT_BOOLEAN for Booleans and FT_UINTn for the non-Booleans; n should be the length of the octet-aligned field in which the bitfields are contained.

The lengths are specified elsewhere; see below.

I've been given a template that uses an FT_ prefix instead of the g prefix - for example, it uses FT_Boolean and FT_UINT8 instead for the previous types.

...

What is the difference between FT_ and g versions of a type, if any? For example, what is the difference between "gboolean" and "FT_BOOLEAN" as a type?

They're not prefixes for the same kind of types.

The g prefix is for GLib types; those are typedefs in C, for use in C code.

The FT_ prefix is for Wireshark named field types. Those are data types for data within packets; some might happen to be similar to GLib (or C99) types, but that's more of a case of "those are concepts that go beyond either C or network packets" than a case of "the types are equivalents".

For example, a gboolean is 32 bits on all the platforms that GLib supports (unless it's used as the type of a C bitfield), but an FT_BOOLEAN field could be anywhere from 1 to 8 bytes.

I don't see FT mentioned at all in README.developer.

See section 1.2 "Explanation of needed substitutions in code skeleton." and section 1.5 "Constructing the protocol tree."; in the latter, look in the subsection "type (FIELDTYPE)".

BASE_DEC is how this value should be printed in Wireshark.

Yes, except that, for FT_BOOLEAN, it's a "special case" for Boolean bitfields, giving the length of the octet-aligned field in which the bitfield appears; see below.

The next four options are VALS(), ???, NULL, and HFILL. VALS() is allowing me to pass in the array that has a mapping from values read to semantic meanings for wireshark to display.

VALS() can actually be different things for different field types. VALS() is used for mappings from integral values to strings giving a semantic description (think of it as being for enumerated data types).

For Boolean values (FT_BOOLEAN), TFS() is used, instead; it stands for "true/false string", and what's wrapped in TFS() is a pointer to a struct true_false_string, which is a structure containing two character string pointers, one for the string to be used if the field is "true" (non-zero), and one for the string to be used if the field is "false" (zero).

There are some additional ones, such as VALS64() for 64-bit fields and 64-bit numerical values, and RVALS(), to specify the meanings of certain ranges of value.

?? seems to be...a mask? a size? a predefined value? It seems to be different things in different places in the code, so I'm lost there.

For fields that aren't bitfields within an octet-aligned field, it's unused, and normally set to 0x0.

For fields that are bitfields within an octet-aligned field, it's a bitmask indicating which bits in that octet-aligned field contain this field. See below for an example.

I have no idea what NULL is for.

It's for a "blurb" that gives a more complete description of the field than the label. It's optional; if it's null, the label is assumed to be a "good enough" description, so that's what's used. If you want a long description that shows up on the status line if you click on the field, but that's too long for the packet detail display, put it there; otherwise, just leave it as null.

I also have no idea what HFILL is for.

Not all fields of a header_field_info are for the dissector developer to fill in; some are used internally by Wireshark. For compilers that can produce warnings about a structure not all of whose fields have been filled in, Wireshark builds with those warnings enabled; the "h"eader field structure is "fill"ed in by HFILL with values for those fields, to squelch those warnings.

Assume I have a 40 bit header, foo, with the following fields:

bit<2> version
bit<1> bypass
bit<1> command_flag
.... (skipping until the end of 32 bits for concision)
bit<8> sequuence_number

So I'm assuming that means that, from the uppermost bits to the lowermost bits, you have:

  • a 2-bit version number field;
  • a 1-bit bypass flag;
  • a 1-bit command flag;
  • 28 bits worth of other flags;
  • an 8-bit sequence number.

That sounds like a 32-bit word of bitfields, followed by an 8-bit field containing the sequence number.

What you can do, in that case, is to make the bitfields be bitfields; that's somewhat like C bitfields, except that the bits to which they correspond are specified by bit masks, and the bits to which they correspond are directly specified (unlike C bitfields, which may be big-endian or little-endian within the word; that's up to the compiler and the ABI of the particular platform for which the compile is being done).

You'd do that with something along the lines of:

static hf_register_info hf[] = {
    { &hf_foo_version_number,
        { "Version number", "foo.version_number",
        FT_UINT32, // This is an integer within a 32-bit quantity
        BASE_DEC,  // Display it in decimal
        NULL,
        0xC0000000, // Upper 2 bits of the 32-bit quantity
        NULL, HFILL }
    },
    { &hf_foo_bypass_flag,
        { "Bypass", "foo.bypass",
        FT_BOOLEAN, // This is a Boolean
        32, // it's within a 32-bit quantity
        NULL,
        0x20000000, // The next bit down from the previous field
        NULL, HFILL }
    },
    { &hf_foo_command_flag,
        { "Command flag", "foo.command_flag",
        FT_BOOLEAN, // This is a Boolean
        32, // it's within a 32-bit quantity
        NULL,
        0x10000000, // The next bit down from the previous field
        NULL, HFILL }
    },

... (other fields here)

    { &hf_foo_sequence_number,
        { "Sequence number", "foo.sequence_number",
        FT_UINT8, // This is an 8-bit integer field
        BASE_DEC, // Display it in decimal
        NULL,
        0x0, // This is not a bitfield, it's the entire octet
        NULL, HFILL }
    },

... (additional protocol fields)

};

You could just add the bitfields with proto_tree_add_item(), with the offset being the offset of the first octet of the 32-bit word containing the fields and with the length being 4 (4 octets, 32 bits), or you could build an array of pointers to the hf_ values for the fields within the 32-bit word and make one call to one of the proto_tree_add_bitmask functions to add all of them - see the doc/README.dissector file.

And, as for your example:

static hf_register_info hf[] = {
    { &hf_foo_version,
      { "Version",         "foo.version",
        FT_UINT32, BASE_DEC,
        NULL, 0x03,
        NULL, HFILL }
      }
};

That should be

static hf_register_info hf[] = {
    { &hf_foo_version,
      { "Version",         "foo.version",
        FT_UINT32, BASE_DEC,
        NULL, 0x03,
        NULL, HFILL }
    },

because there should be only one hf array, with multiple fields in it.

Also, 0x03 is valid if the version is in the low-order 2 bits of the 32-bit field. You might want to write it as 0x00000003 to make it clearer that the field is 32 bits.

static hf_register_info hf[] = {
    { &hf_foo_version,
      { "Bypass",         "foo.bypass",
        FT_UINT32, BASE_DEC,
        NULL, 0x07,
        NULL, HFILL }
    }
};

That should be

    { &hf_foo_bypass,
      { "Bypass",         "foo.bypass",
        FT_UINT32, BASE_DEC,
        NULL, 0x04,
        NULL, HFILL }
     }

if you want it to be a number that's 0 or 1, rather than a Boolean value, because 1) it should be the next element in the hf array, 2) it should have a separate hf_ variable, and 3) 0x07 means it's in the bottom 3 bits, so it overlaps the version number field - presumably you want it to be in the first bit above that field. Again, you might want to show it as 0x00000004, to make it clearer that it's in a 32-bit field.

If you want it to be a Boolean, then, as per my example, it should be

    { &hf_foo_bypass,
      { "Bypass",         "foo.bypass",
        FT_BOOLEAN, 32,
        NULL, 0x04,
        NULL, HFILL }
    }

If it's the last field in the entire dissector, put the }; terminator for the array after it. If it's not the last field, put a comma after the last closing }, and add more fields.