refactor the dissection of USB setup requests

pass the data only to one subsequent dissection function
either we have a standard request or a non-standard request that can be
handled by a class dissector (we used to do both at the same time,
this makes the output difficult to read)

Change-Id: Ia46239b2b9e121c9ca165cc56d0b271345d7962e
Reviewed-on: https://code.wireshark.org/review/7005
Reviewed-by: Martin Kaiser <wireshark@kaiser.cx>
Tested-by: Martin Kaiser <wireshark@kaiser.cx>
This commit is contained in:
Martin Kaiser 2015-02-05 22:37:54 +01:00
parent a09765955c
commit 540347850f
1 changed files with 47 additions and 28 deletions

View File

@ -2956,10 +2956,10 @@ dissect_usb_setup_request(packet_info *pinfo, proto_tree *tree,
usb_header_t header_type)
{
gint req_type;
gint ret;
proto_tree *parent, *setup_tree;
tvbuff_t *setup_tvb;
usb_trans_info_t *usb_trans_info, trans_info;
tvbuff_t *next_tvb, *data_tvb;
tvbuff_t *next_tvb, *data_tvb = NULL;
/* we should do the NULL check in all non-static functions */
if (usb_conv_info)
@ -2970,52 +2970,71 @@ dissect_usb_setup_request(packet_info *pinfo, proto_tree *tree,
parent = proto_tree_get_parent_tree(tree);
setup_tree = proto_tree_add_subtree(parent, tvb, offset, 8, usb_setup_hdr, NULL, "URB setup");
setup_tvb = tvb_new_subset_length(tvb, offset, 8);
req_type = USB_TYPE(tvb_get_guint8(tvb, offset));
usb_trans_info->setup.requesttype = tvb_get_guint8(tvb, offset);
if (usb_conv_info)
usb_conv_info->setup_requesttype = tvb_get_guint8(tvb, offset);
offset = dissect_usb_bmrequesttype(setup_tree, tvb, offset);
usb_trans_info->setup.request = tvb_get_guint8(tvb, offset);
usb_trans_info->setup.wValue = tvb_get_letohs(tvb, offset+1);
usb_trans_info->setup.wIndex = tvb_get_letohs(tvb, offset+3);
usb_trans_info->setup.wLength = tvb_get_letohs(tvb, offset+5);
if (usb_conv_info) {
usb_conv_info->setup_requesttype = tvb_get_guint8(tvb, offset);
if (req_type != RQT_SETUP_TYPE_CLASS)
usb_tap_queue_packet(pinfo, urb_type, usb_conv_info);
}
if (is_usb_standard_setup_request(usb_trans_info)) {
offset = dissect_usb_standard_setup_request(pinfo, setup_tree, tvb, offset,
usb_conv_info, usb_trans_info);
}
else {
proto_tree_add_item(setup_tree, hf_usb_request_unknown_class, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset += 1;
offset = dissect_usb_setup_generic(pinfo, setup_tree, tvb, offset, usb_conv_info);
}
offset = dissect_usb_bmrequesttype(setup_tree, tvb, offset);
/* as we're going through the data, we build a next_tvb that
contains the the setup packet without the request type
and request-specific data
all subsequent dissection routines work on this tvb */
next_tvb = tvb_new_composite();
tvb_composite_append(next_tvb, tvb_new_subset(tvb, offset, 7, 7));
usb_trans_info->setup.request = tvb_get_guint8(tvb, offset);
offset++;
usb_trans_info->setup.wValue = tvb_get_letohs(tvb, offset);
offset += 2;
usb_trans_info->setup.wIndex = tvb_get_letohs(tvb, offset);
offset += 2;
usb_trans_info->setup.wLength = tvb_get_letohs(tvb, offset);
offset += 2;
if (header_type == USB_HEADER_LINUX_64_BYTES) {
offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree);
}
next_tvb = tvb_new_composite();
tvb_composite_append(next_tvb, tvb_new_subset_remaining(setup_tvb, 1));
if (tvb_captured_length_remaining(tvb, offset) > 0) {
proto_tree_add_item(setup_tree, hf_usb_data_fragment, tvb, offset, -1, ENC_NA);
data_tvb = tvb_new_subset_remaining(tvb, offset);
tvb_composite_append(next_tvb, data_tvb);
offset += tvb_captured_length(data_tvb);
add_new_data_source(pinfo, next_tvb, "Linux USB Control");
}
tvb_composite_finalize(next_tvb);
offset += try_dissect_next_protocol(parent, next_tvb, pinfo, usb_conv_info, urb_type);
/* at this point, offset contains the number of bytes that we
dissected */
if (is_usb_standard_setup_request(usb_trans_info)) {
/* there's no point in checking the return value as there's no
fallback for standard setup requests */
dissect_usb_standard_setup_request(pinfo, setup_tree,
next_tvb, 0, usb_conv_info, usb_trans_info);
}
else {
/* no standard request - pass it on to class-specific dissectors */
ret = try_dissect_next_protocol(
setup_tree, next_tvb, pinfo, usb_conv_info, urb_type);
if (ret <= 0) {
/* no class-specific dissector could handle it,
dissect it as generic setup request */
proto_tree_add_item(setup_tree, hf_usb_request_unknown_class,
next_tvb, 0, 1, ENC_LITTLE_ENDIAN);
dissect_usb_setup_generic(pinfo, setup_tree,
next_tvb, 1, usb_conv_info);
}
}
if (data_tvb)
proto_tree_add_item(setup_tree, hf_usb_data_fragment, data_tvb, 0, -1, ENC_NA);
return offset;
}