Make expert items used in "low level" proto functions filterable (and ensure they are called even with a NULL tree). I don't really like the Type Length Mismatch "protocol", but it doesn't seem that much different than the exception "protocols".

svn path=/trunk/; revision=52341
This commit is contained in:
Michael Mann 2013-10-03 01:54:02 +00:00
parent b9eecb6f28
commit a891f3e70b
4 changed files with 79 additions and 45 deletions

View File

@ -348,6 +348,7 @@ static gint ett_video_standards = -1;
static gint ett_control_capabilities = -1;
static expert_field ei_usb_vid_subtype_unknown = EI_INIT;
static expert_field ei_usb_vid_bitmask_len = EI_INIT;
/* Lookup tables */
static const value_string vc_ep_descriptor_subtypes[] = {
@ -690,7 +691,7 @@ dissect_bmControl(proto_tree *tree, tvbuff_t *tvb, int offset,
if (bm_size > 0)
{
proto_tree_add_bitmask_len(tree, tvb, offset, bm_size, hf_usb_vid_bmControl,
ett_subtree, bm_items, ENC_LITTLE_ENDIAN);
ett_subtree, bm_items, &ei_usb_vid_bitmask_len, ENC_LITTLE_ENDIAN);
offset += bm_size;
}
@ -1120,7 +1121,7 @@ dissect_usb_video_streaming_input_header(proto_tree *tree, tvbuff_t *tvb, int of
for (i=0; i<num_formats; ++i)
{
proto_tree_add_bitmask_len(tree, tvb, offset, bm_size, hf_usb_vid_bmControl,
ett_streaming_controls, control_bits,
ett_streaming_controls, control_bits, &ei_usb_vid_bitmask_len,
ENC_LITTLE_ENDIAN);
offset += bm_size;
}
@ -1350,23 +1351,19 @@ static int
dissect_usb_video_streaming_interface_descriptor(proto_tree *parent_tree, tvbuff_t *tvb,
guint8 descriptor_len)
{
proto_item *item = NULL;
proto_tree *tree = NULL;
proto_item *item;
proto_tree *tree;
int offset = 0;
const gchar* subtype_str;
guint8 subtype;
subtype = tvb_get_guint8(tvb, offset+2);
if (parent_tree)
{
const gchar* subtype_str;
subtype_str = val_to_str_ext(subtype, &vs_if_descriptor_subtypes_ext, "Unknown (0x%x)");
item = proto_tree_add_text(parent_tree, tvb, offset, descriptor_len,
"VIDEO STREAMING INTERFACE DESCRIPTOR [%s]",
subtype_str);
tree = proto_item_add_subtree(item, ett_descriptor_video_streaming);
}
subtype_str = val_to_str_ext(subtype, &vs_if_descriptor_subtypes_ext, "Unknown (0x%x)");
item = proto_tree_add_text(parent_tree, tvb, offset, descriptor_len,
"VIDEO STREAMING INTERFACE DESCRIPTOR [%s]",
subtype_str);
tree = proto_item_add_subtree(item, ett_descriptor_video_streaming);
dissect_usb_descriptor_header(tree, tvb, offset, &vid_descriptor_type_vals_ext);
proto_tree_add_item(tree, hf_usb_vid_streaming_ifdesc_subtype, tvb, offset+2, 1, ENC_NA);
@ -3227,6 +3224,7 @@ proto_register_usb_vid(void)
static ei_register_info ei[] = {
{ &ei_usb_vid_subtype_unknown, { "usbvideo.subtype.unknown", PI_UNDECODED, PI_WARN, "Unknown VC subtype", EXPFILL }},
{ &ei_usb_vid_bitmask_len, { "usbvideo.bitmask_len_error", PI_UNDECODED, PI_WARN, "Only least-significant bytes decoded", EXPFILL }},
};
expert_module_t* expert_usb_vid;

View File

@ -188,7 +188,7 @@ proto_tree_add_expert(proto_tree *tree, packet_info *pinfo, expert_field* eiinde
Add an expert info tree to a protocol item, using registered expert info item,
but with a formatted message.
This function is intended to replace places where
proto_tree_add_text or proto_tree_add_none_format + expert_add_info_format_text
proto_tree_add_text or proto_tree_add_none_format + expert_add_info_format
would be used.
@param tree Current protocol item (or NULL)
@param pinfo Packet info of the currently processed packet. May be NULL if tree is supplied

View File

@ -221,11 +221,12 @@ static void
proto_tree_set_eui64(field_info *fi, const guint64 value);
static void
proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
static gboolean
proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
const int len, const gint ett, const gint **fields,
const guint encoding, const int flags,
gboolean first);
/* Handle type length mismatch (now filterable) expert info */
static int proto_type_length_mismatch = -1;
static expert_field ei_type_length_mismatch_error = EI_INIT;
static expert_field ei_type_length_mismatch_warn = EI_INIT;
static void register_type_length_mismatch(void);
static int proto_register_field_init(header_field_info *hfinfo, const int parent);
@ -348,6 +349,7 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
/* Register the pseudo-protocols used for exceptions. */
register_show_exception();
register_type_length_mismatch();
/* Have each built-in dissector register its protocols, fields,
dissector tables, and dissectors to be called through a
@ -1045,15 +1047,25 @@ proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
/* We could probably get away with changing is_error to a minimum length value. */
static void
report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
tree_data_t *tree_data = NULL;
field_info *fi_save = NULL;
if (tree) {
tree_data_t *tree_data = PTREE_DATA(tree);
field_info *fi_save = tree_data->fi_tmp;
tree_data = PTREE_DATA(tree);
fi_save = tree_data->fi_tmp;
/* Keep the current item from getting freed by proto_tree_new_item. */
tree_data->fi_tmp = NULL;
}
expert_add_info_format_internal(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
if (is_error) {
expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
} else {
expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
}
if (tree) {
tree_data->fi_tmp = fi_save;
}
@ -4997,6 +5009,26 @@ tmp_fld_check_assert(header_field_info *hfinfo)
}
}
static void
register_type_length_mismatch(void)
{
static ei_register_info ei[] = {
{ &ei_type_length_mismatch_error, { "type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
{ &ei_type_length_mismatch_warn, { "type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
};
expert_module_t* expert_type_length_mismatch;
proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "type_length");
expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
/* "Type Length Mismatch" isn't really a protocol, it's an error indication;
disabling them makes no sense. */
proto_set_cant_toggle(proto_type_length_mismatch);
}
#define PROTO_PRE_ALLOC_HF_FIELDS_MEM (120000+PRE_ALLOC_EXPERT_FIELDS_MEM)
static int
proto_register_field_init(header_field_info *hfinfo, const int parent)
@ -6908,44 +6940,45 @@ proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
proto_item *
proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
const guint offset, const guint len, const int hf_hdr,
const gint ett, const int **fields,
const gint ett, const int **fields, struct expert_field* exp,
const guint encoding)
{
proto_item *item = NULL;
header_field_info *hf;
guint decodable_len;
guint decodable_offset;
guint32 decodable_value;
hf = proto_registrar_get_nth(hf_hdr);
DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
decodable_offset = offset;
decodable_len = MIN(len, (guint) ftype_length(hf->type));
/* If we are ftype_length-limited,
* make sure we decode as many LSBs as possible.
*/
if (encoding == ENC_BIG_ENDIAN) {
decodable_offset += (len - decodable_len);
}
if (parent_tree) {
guint decodable_len;
guint decodable_offset;
guint32 decodable_value;
decodable_offset = offset;
decodable_len = MIN(len, (guint) ftype_length(hf->type));
/* If we are ftype_length-limited,
* make sure we decode as many LSBs as possible.
*/
if (encoding == ENC_BIG_ENDIAN) {
decodable_offset += (len - decodable_len);
}
decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
decodable_len, encoding);
/* The root item covers all the bytes even if we can't decode them all */
item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
decodable_value);
}
if (decodable_len < len) {
/* Dissector likely requires updating for new protocol revision */
expert_add_info_format_internal(NULL, item, PI_UNDECODED, PI_WARN,
"Only least-significant %d of %d bytes decoded",
decodable_len, len);
}
if (decodable_len < len) {
/* Dissector likely requires updating for new protocol revision */
expert_add_info_format(NULL, item, exp,
"Only least-significant %d of %d bytes decoded",
decodable_len, len);
}
if (item) {
proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
}

View File

@ -76,6 +76,7 @@ WS_DLL_PUBLIC int hf_text_only;
#define ITEM_LABEL_LENGTH 240
struct _value_string;
struct expert_field;
/** Make a const value_string[] look like a _value_string pointer, used to set header_field_info.strings */
#define VALS(x) (const struct _value_string*)(x)
@ -1936,11 +1937,13 @@ proto_tree_add_bitmask(proto_tree *tree, tvbuff_t *tvb, const guint offset,
FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
FT_integer fields that have a value_string attached will have the
matched string displayed on the expansion line.
@param exp expert info field used when decodable_len < len. This also means this function
should be called even when tree == NULL
@param encoding big or little endian byte representation (ENC_BIG_ENDIAN/ENC_LITTLE_ENDIAN)
@return the newly created item */
WS_DLL_PUBLIC proto_item *
proto_tree_add_bitmask_len(proto_tree *tree, tvbuff_t *tvb, const guint offset, const guint len,
const int hf_hdr, const gint ett, const int **fields, const guint encoding);
const int hf_hdr, const gint ett, const int **fields, struct expert_field* exp, const guint encoding);
/** Add a text with a subtree of bitfields.
@param tree the tree to append this item to