aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors
diff options
context:
space:
mode:
authorMartin Kaiser <wireshark@kaiser.cx>2015-02-05 22:37:54 +0100
committerMartin Kaiser <wireshark@kaiser.cx>2015-02-07 18:19:40 +0000
commit540347850fce692b8789220344b0a8978dd82e62 (patch)
treeb99c2df94cddc8a829eb04058e923e0fdd742527 /epan/dissectors
parenta09765955c29eb5b7b912b96704fded1c898e4e6 (diff)
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>
Diffstat (limited to 'epan/dissectors')
-rw-r--r--epan/dissectors/packet-usb.c75
1 files changed, 47 insertions, 28 deletions
diff --git a/epan/dissectors/packet-usb.c b/epan/dissectors/packet-usb.c
index 52d0585c0f..7d17902b4e 100644
--- a/epan/dissectors/packet-usb.c
+++ b/epan/dissectors/packet-usb.c
@@ -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;
}