aboutsummaryrefslogtreecommitdiffstats
path: root/epan/proto.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2016-09-18 18:48:50 -0700
committerGuy Harris <guy@alum.mit.edu>2016-09-19 02:51:13 +0000
commitd7fe514fc05e95e3a99fd211768de5abdc3f6486 (patch)
tree68b3e2a24ee11c7dd223089bc9a21ac9ccae302b /epan/proto.c
parent630b64613567c268b2b08966707c81d3ec8661a5 (diff)
Improve support for single-character fields and filter expressions.
Add an FT_CHAR type, which is like FT_UINT8 except that the value is displayed as a C-style character constant. Allow use of C-style character constants in filter expressions; they can be used in comparisons with all integral types, and in "contains" operators. Use that type for some fields that appear (based on the way they're displayed, or on the use of C-style character constants in their value_string tables) to be 1-byte characters rather than 8-bit numbers. Change-Id: I39a9f0dda0bd7f4fa02a9ca8373216206f4d7135 Reviewed-on: https://code.wireshark.org/review/17787 Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'epan/proto.c')
-rw-r--r--epan/proto.c404
1 files changed, 389 insertions, 15 deletions
diff --git a/epan/proto.c b/epan/proto.c
index 42689a36ac..fd673faf05 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -178,17 +178,22 @@ static void label_mark_truncated(char *label_str, gsize name_pos);
#define LABEL_MARK_TRUNCATED_START(label_str) label_mark_truncated(label_str, 0)
static void fill_label_boolean(field_info *fi, gchar *label_str);
+static void fill_label_bitfield_char(field_info *fi, gchar *label_str);
static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
static void fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed);
+static void fill_label_char(field_info *fi, gchar *label_str);
static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
+static const char *hfinfo_char_value_format_display(int display, char buf[7], guint32 value);
static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
static const char *hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value);
+static const char *hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
static const char *hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
static const char *hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
+static const char *hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
static const char *hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
@@ -1889,6 +1894,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
get_uint64_value(tree, tvb, start, length, encoding));
break;
+ case FT_CHAR:
/* XXX - make these just FT_UINT? */
case FT_UINT8:
case FT_UINT16:
@@ -2344,6 +2350,7 @@ proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
switch (hfinfo->type){
+ case FT_CHAR:
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
@@ -2364,6 +2371,7 @@ proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
REPORT_DISSECTOR_BUG("wrong 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(tree, tvb, start, length, encoding);
if (retval)
@@ -3924,7 +3932,7 @@ proto_tree_set_double(field_info *fi, double value)
fvalue_set_floating(&fi->value, value);
}
-/* Add FT_UINT{8,16,24,32} to a proto_tree */
+/* 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)
@@ -3937,6 +3945,7 @@ proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
switch (hfinfo->type) {
+ case FT_CHAR:
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
@@ -4598,6 +4607,7 @@ get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
break;
case FT_BOOLEAN:
+ case FT_CHAR:
/* XXX - make these just FT_UINT? */
case FT_UINT8:
case FT_UINT16:
@@ -5022,6 +5032,44 @@ proto_custom_set(proto_tree* tree, GSList *field_ids, gint occurrence,
number64 ? "1" : "0", size-offset_e);
break;
+ case FT_CHAR:
+ hf_str_val = NULL;
+ number = fvalue_get_uinteger(&finfo->value);
+
+ if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
+ gchar tmp[ITEM_LABEL_LENGTH];
+ custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
+
+ DISSECTOR_ASSERT(fmtfunc);
+ fmtfunc(tmp, number);
+
+ offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
+
+ } else if (hfinfo->strings) {
+ number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
+
+ if (!number_out)
+ number_out = hfinfo_char_value_format_display(BASE_HEX, number_buf, number);
+
+ offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
+
+ } else {
+ number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
+
+ offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
+ }
+
+ if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
+ g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
+ } else {
+ number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
+
+ g_strlcpy(expr+offset_e, number_out, size-offset_e);
+ }
+
+ offset_e = (int)strlen(expr);
+ break;
+
/* XXX - make these just FT_NUMBER? */
case FT_INT8:
case FT_INT16:
@@ -5240,6 +5288,7 @@ proto_custom_set(proto_tree* tree, GSList *field_ids, gint occurrence,
switch (hfinfo->type) {
case FT_BOOLEAN:
+ case FT_CHAR:
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
@@ -6412,6 +6461,7 @@ tmp_fld_check_assert(header_field_info *hfinfo)
* true_false_strings or a protocol_t struct
*/
if (hfinfo->strings != NULL && !(
+ (hfinfo->type == FT_CHAR) ||
(hfinfo->type == FT_UINT8) ||
(hfinfo->type == FT_UINT16) ||
(hfinfo->type == FT_UINT24) ||
@@ -6446,6 +6496,7 @@ tmp_fld_check_assert(header_field_info *hfinfo)
!(hfinfo->display & BASE_RANGE_STRING) &&
!((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
(
+ (hfinfo->type == FT_CHAR) ||
(hfinfo->type == FT_UINT8) ||
(hfinfo->type == FT_UINT16) ||
(hfinfo->type == FT_UINT24) ||
@@ -6491,6 +6542,38 @@ tmp_fld_check_assert(header_field_info *hfinfo)
switch (hfinfo->type) {
+ case FT_CHAR:
+ /* Require the char type to have BASE_HEX, BASE_OCT,
+ * BASE_CUSTOM, or BASE_NONE as its base.
+ *
+ * If the display value is BASE_NONE and there is a
+ * strings conversion then the dissector writer is
+ * telling us that the field's numerical value is
+ * meaningless; we'll avoid showing the value to the
+ * user.
+ */
+ switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
+ case BASE_HEX:
+ case BASE_OCT:
+ case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
+ break;
+ case BASE_NONE:
+ if (hfinfo->strings == NULL)
+ g_error("Field '%s' (%s) is an integral value (%s)"
+ " but is being displayed as BASE_NONE but"
+ " without a strings conversion",
+ hfinfo->name, hfinfo->abbrev,
+ ftype_name(hfinfo->type));
+ break;
+ default:
+ tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
+ g_error("Field '%s' (%s) is a character value (%s)"
+ " but is being displayed as %s\n",
+ hfinfo->name, hfinfo->abbrev,
+ ftype_name(hfinfo->type), tmp_str);
+ wmem_free(NULL, tmp_str);
+ }
+ break;
case FT_INT8:
case FT_INT16:
case FT_INT24:
@@ -6716,6 +6799,7 @@ _ftype_common(enum ftenum type)
case FT_INT32:
return FT_INT32;
+ case FT_CHAR:
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
@@ -7097,6 +7181,14 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
}
break;
+ case FT_CHAR:
+ if (hfinfo->bitmask) {
+ fill_label_bitfield_char(fi, label_str);
+ } else {
+ fill_label_char(fi, label_str);
+ }
+ break;
+
/* Four types of integers to take care of:
* Bitfield, with val_string
* Bitfield, w/o val_string
@@ -7427,6 +7519,60 @@ hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const
return (str) ? str : unknown_str;
}
+/* Fills data for bitfield chars with val_strings */
+static void
+fill_label_bitfield_char(field_info *fi, gchar *label_str)
+{
+ char *p;
+ int bitfield_byte_length, bitwidth;
+ guint32 unshifted_value;
+ guint32 value;
+
+ char buf[32];
+ const char *out;
+
+ header_field_info *hfinfo = fi->hfinfo;
+
+ /* Figure out the bit width */
+ bitwidth = hfinfo_container_bitwidth(hfinfo);
+
+ /* Un-shift bits */
+ value = fvalue_get_uinteger(&fi->value);
+
+ unshifted_value = value;
+ if (hfinfo->bitmask) {
+ unshifted_value <<= hfinfo_bitshift(hfinfo);
+ }
+
+ /* Create the bitfield first */
+ p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
+ bitfield_byte_length = (int) (p - label_str);
+
+ /* Fill in the textual info using stored (shifted) value */
+ if (hfinfo->display == BASE_CUSTOM) {
+ gchar tmp[ITEM_LABEL_LENGTH];
+ const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
+
+ DISSECTOR_ASSERT(fmtfunc);
+ fmtfunc(tmp, value);
+ label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
+ }
+ else if (hfinfo->strings) {
+ const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
+
+ out = hfinfo_char_vals_format(hfinfo, buf, value);
+ if (out == NULL) /* BASE_NONE so don't put integer in descr */
+ label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
+ else
+ label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
+ }
+ else {
+ out = hfinfo_char_value_format(hfinfo, buf, value);
+
+ label_fill(label_str, bitfield_byte_length, hfinfo, out);
+ }
+}
+
/* Fills data for bitfield ints with val_strings */
static void
fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
@@ -7541,6 +7687,39 @@ fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed)
}
static void
+fill_label_char(field_info *fi, gchar *label_str)
+{
+ header_field_info *hfinfo = fi->hfinfo;
+ guint32 value;
+
+ char buf[32];
+ const char *out;
+
+ value = fvalue_get_uinteger(&fi->value);
+
+ /* Fill in the textual info */
+ if (hfinfo->display == BASE_CUSTOM) {
+ gchar tmp[ITEM_LABEL_LENGTH];
+ const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
+
+ DISSECTOR_ASSERT(fmtfunc);
+ fmtfunc(tmp, value);
+ label_fill(label_str, 0, hfinfo, tmp);
+ }
+ else if (hfinfo->strings) {
+ const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
+
+ out = hfinfo_char_vals_format(hfinfo, buf, value);
+ label_fill_descr(label_str, 0, hfinfo, val_str, out);
+ }
+ else {
+ out = hfinfo_char_value_format(hfinfo, buf, value);
+
+ label_fill(label_str, 0, hfinfo, out);
+ }
+}
+
+static void
fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
{
header_field_info *hfinfo = fi->hfinfo;
@@ -7563,7 +7742,12 @@ fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
fmtfunc(tmp, value);
label_fill(label_str, 0, hfinfo, tmp);
}
- else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) { /* Add fill_label_framenum? */
+ else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
+ /*
+ * It makes no sense to have a value-string table for a
+ * frame-number field - they're just integers giving
+ * the ordinal frame number.
+ */
const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
out = hfinfo_number_vals_format(hfinfo, buf, value);
@@ -7648,6 +7832,7 @@ hfinfo_type_bitwidth(enum ftenum type)
int bitwidth = 0;
switch (type) {
+ case FT_CHAR:
case FT_UINT8:
case FT_INT8:
bitwidth = 8;
@@ -7722,6 +7907,94 @@ hfinfo_hex_digits(const header_field_info *hfinfo)
}
static const char *
+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' };
+
+ *ptr = '\0';
+ *(--ptr) = '\'';
+ /* Properly format value */
+ if (g_ascii_isprint(value)) {
+ /*
+ * Printable, so just show the character, and, if it needs
+ * to be escaped, escape it.
+ */
+ *(--ptr) = value;
+ if (value == '\\' || value == '\'')
+ *(--ptr) = '\\';
+ } else {
+ /*
+ * Non-printable; show it as an escape sequence.
+ */
+ switch (value) {
+
+ case '\0':
+ /*
+ * Show a NUL with only one digit.
+ */
+ *(--ptr) = '0';
+ break;
+
+ case '\a':
+ *(--ptr) = 'a';
+ break;
+
+ case '\b':
+ *(--ptr) = 'b';
+ break;
+
+ case '\f':
+ *(--ptr) = 'f';
+ break;
+
+ case '\n':
+ *(--ptr) = 'n';
+ break;
+
+ case '\r':
+ *(--ptr) = 'r';
+ break;
+
+ case '\t':
+ *(--ptr) = 't';
+ break;
+
+ case '\v':
+ *(--ptr) = 'v';
+ break;
+
+ default:
+ switch (display & FIELD_DISPLAY_E_MASK) {
+
+ case BASE_OCT:
+ *(--ptr) = (value & 0x7) + '0';
+ value >>= 3;
+ *(--ptr) = (value & 0x7) + '0';
+ value >>= 3;
+ *(--ptr) = (value & 0x7) + '0';
+ break;
+
+ case BASE_HEX:
+ *(--ptr) = hex_digits[value & 0x0F];
+ value >>= 4;
+ *(--ptr) = hex_digits[value & 0x0F];
+ *(--ptr) = 'x';
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+ }
+ *(--ptr) = '\\';
+ }
+ *(--ptr) = '\'';
+ return ptr;
+}
+
+static const char *
hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
{
char *ptr = &buf[31];
@@ -7840,6 +8113,15 @@ hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[64], guin
}
static const char *
+hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
+{
+ /* Get the underlying BASE_ value */
+ int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
+
+ return hfinfo_char_value_format_display(display, buf, value);
+}
+
+static const char *
hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
{
/* Get the underlying BASE_ value */
@@ -7906,6 +8188,15 @@ hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[64], gui
}
static const char *
+hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
+{
+ /* Get the underlying BASE_ value */
+ int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
+
+ return hfinfo_char_value_format_display(display, buf, value);
+}
+
+static const char *
hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
{
/* Get the underlying BASE_ value */
@@ -8304,7 +8595,8 @@ proto_registrar_dump_values(void)
if (hfinfo->strings != NULL) {
if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
- (hfinfo->type == FT_UINT8 ||
+ (hfinfo->type == FT_CHAR ||
+ hfinfo->type == FT_UINT8 ||
hfinfo->type == FT_UINT16 ||
hfinfo->type == FT_UINT24 ||
hfinfo->type == FT_UINT32 ||
@@ -8354,17 +8646,39 @@ proto_registrar_dump_values(void)
vi = 0;
while (vals[vi].strptr) {
/* Print in the proper base */
- if (hfinfo->display == BASE_HEX) {
- ws_debug_printf("V\t%s\t0x%x\t%s\n",
- hfinfo->abbrev,
- vals[vi].value,
- vals[vi].strptr);
- }
- else {
- ws_debug_printf("V\t%s\t%u\t%s\n",
- hfinfo->abbrev,
- vals[vi].value,
- vals[vi].strptr);
+ if (hfinfo->type == FT_CHAR) {
+ if (g_ascii_isprint(vals[vi].value)) {
+ ws_debug_printf("V\t%s\t'%c'\t%s\n",
+ hfinfo->abbrev,
+ vals[vi].value,
+ vals[vi].strptr);
+ } else {
+ if (hfinfo->display == BASE_HEX) {
+ ws_debug_printf("V\t%s\t'\\x%02x'\t%s\n",
+ hfinfo->abbrev,
+ vals[vi].value,
+ vals[vi].strptr);
+ }
+ else {
+ ws_debug_printf("V\t%s\t'\\%03o'\t%s\n",
+ hfinfo->abbrev,
+ vals[vi].value,
+ vals[vi].strptr);
+ }
+ }
+ } else {
+ if (hfinfo->display == BASE_HEX) {
+ ws_debug_printf("V\t%s\t0x%x\t%s\n",
+ hfinfo->abbrev,
+ vals[vi].value,
+ vals[vi].strptr);
+ }
+ else {
+ ws_debug_printf("V\t%s\t%u\t%s\n",
+ hfinfo->abbrev,
+ vals[vi].value,
+ vals[vi].strptr);
+ }
}
vi++;
}
@@ -8537,7 +8851,8 @@ proto_registrar_dump_fields(void)
enum_name = ftype_name(hfinfo->type);
base_name = "";
- if (hfinfo->type == FT_UINT8 ||
+ if (hfinfo->type == FT_CHAR ||
+ hfinfo->type == FT_UINT8 ||
hfinfo->type == FT_UINT16 ||
hfinfo->type == FT_UINT24 ||
hfinfo->type == FT_UINT32 ||
@@ -8651,6 +8966,7 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
break;
+ case FT_CHAR:
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
@@ -8690,6 +9006,21 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
*/
switch (hfinfo->type) {
+ case FT_CHAR:
+ if (filter != NULL) {
+ guint32 number;
+
+ char buf [48];
+ const char *out;
+
+ number = fvalue_get_uinteger(&finfo->value);
+
+ out = hfinfo_char_value_format(hfinfo, buf, number);
+
+ *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
+ }
+ break;
+
case FT_INT8:
case FT_INT16:
case FT_INT24:
@@ -8919,6 +9250,7 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
}
switch (hf->type) {
+ case FT_CHAR:
case FT_INT8:
case FT_UINT8:
case FT_INT16:
@@ -8956,6 +9288,37 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
switch (hf->type) {
+ case FT_CHAR:
+ if (hf->display == BASE_CUSTOM) {
+ gchar lbl[ITEM_LABEL_LENGTH];
+ const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
+
+ DISSECTOR_ASSERT(fmtfunc);
+ fmtfunc(lbl, (guint32) tmpval);
+ proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
+ hf->name, lbl);
+ first = FALSE;
+ }
+ else if (hf->strings) {
+ proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
+ hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
+ first = FALSE;
+ }
+ else if (!(flags & BMT_NO_INT)) {
+ char buf[32];
+ const char *out;
+
+ if (!first) {
+ proto_item_append_text(item, ", ");
+ }
+
+ out = hfinfo_char_value_format(hf, buf, (guint32) tmpval);
+ proto_item_append_text(item, "%s: %s", hf->name, out);
+ first = FALSE;
+ }
+
+ break;
+
case FT_INT8:
case FT_UINT8:
case FT_INT16:
@@ -9402,6 +9765,11 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
(guint64)value ? tfstring->true_string : tfstring->false_string);
break;
+ case FT_CHAR:
+ pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
+ fill_label_char(PITEM_FINFO(pi), lbl_str);
+ break;
+
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
@@ -9572,6 +9940,11 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbu
(guint64)value ? tfstring->true_string : tfstring->false_string);
break;
+ case FT_CHAR:
+ pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
+ fill_label_char(PITEM_FINFO(pi), lbl_str);
+ break;
+
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
@@ -9712,6 +10085,7 @@ _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
"%s: %s", str, value_str);
break;
+ case FT_CHAR:
case FT_UINT8:
case FT_UINT16:
case FT_UINT24: