aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2010-04-21 20:51:22 +0000
committerGuy Harris <guy@alum.mit.edu>2010-04-21 20:51:22 +0000
commit21a210b77763224e0ac15611842cf7203d07fa08 (patch)
tree8bcb5aa12a0e02936ac8737faf20ddbae72d0998 /epan
parentc1729024c520afc5c8824abc04b3a3cc9eacb716 (diff)
From Chris Maynard:
Support PPP-over-USB. Don't remove the USB pseudo-header from the packet data for Linux USB packets, just byte-swap it if necessary and have the USB dissector fetch the pseudo-header from the raw packet data. Update USB language ID values. svn path=/trunk/; revision=32534
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/packet-ppp.c53
-rw-r--r--epan/dissectors/packet-usb.c451
-rw-r--r--epan/dissectors/packet-usb.h1
3 files changed, 333 insertions, 172 deletions
diff --git a/epan/dissectors/packet-ppp.c b/epan/dissectors/packet-ppp.c
index b16c26fb19..91519a0e3e 100644
--- a/epan/dissectors/packet-ppp.c
+++ b/epan/dissectors/packet-ppp.c
@@ -46,8 +46,9 @@
#include <epan/crc16.h>
#include <epan/crc32.h>
#include <epan/ipproto.h>
+#include "packet-usb.h"
-#define ppp_min(a, b) ((a<b) ? a : b)
+#define ppp_min(a, b) (((a)<(b)) ? (a) : (b))
static int proto_ppp = -1;
static int hf_ppp_direction = -1;
@@ -3255,7 +3256,7 @@ dissect_lcp_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
/*
- * RFC 1661.
+ * RFC's 1661, 2153 and 1570.
*/
static void
dissect_lcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
@@ -4336,6 +4337,50 @@ dissect_ppp_raw_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
} /* end while */
}
+/*
+ * At least for the PPP/USB captures I've seen, the data either starts with
+ * 0x7eff03 or 0x7eff7d23 or 0xff03, so this function performs that heuristic
+ * matching first before calling dissect_ppp_raw_hdlc(). Otherwise, if we call
+ * it directly for USB captures, some captures like the following will not be
+ * dissected correctly:
+ * http://wiki.wireshark.org/SampleCaptures#head-886e340c31ca977f321c921f81cbec4c21bb7738
+ *
+ * NOTE: I don't know if these heuristics are sufficient. Time will tell ...
+ */
+static void
+dissect_ppp_usb( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ /* In some cases, the 0x03 normally in byte 3 is escaped so we must look for
+ * the 2 byte sequence of 0x7d23 instead of 0x03. The 0x23 is generated by
+ * 0x20^0x03 per section 4.2 of: http://tools.ietf.org/html/rfc1662.html. */
+ const guchar buf1[3] = {0x7e, 0xff, 0x03};
+ const guchar buf2[4] = {0x7e, 0xff, 0x7d, 0x23};
+ tvbuff_t *next_tvb;
+
+ if ((tvb_memeql(tvb, 0, buf2, sizeof(buf2)) == 0) ||
+ (tvb_memeql(tvb, 0, buf1, sizeof(buf1)) == 0)) {
+ dissect_ppp_raw_hdlc(tvb, pinfo, tree);
+ }
+ else {
+ /* See if it's missing the 0x7e framing character */
+ if (tvb_memeql(tvb, 0, &buf1[1], 2) == 0) {
+ /* Yup ... what TODO? Should we try faking it by sticking 0x7e in
+ * front? Or try telling dissect_ppp_raw_hdlc() NOT to look for the
+ * 0x7e frame deliminator? Or is this a bug in libpcap (used 1.1.0)?
+ * Or a bug in the Linux kernel (tested with 2.6.24.4) Or a bug in
+ * usbmon? Or is the data we're looking at really just part of the
+ * payload and not control data? Well, at least in my case it's
+ * definitely not, but not sure if this is always the case. Is this
+ * issue applicable only to PPP/USB or PPP/XYZ, in which case a more
+ * general solution should be found?
+ */
+ /* For now, just try skipping the framing I guess??? */
+ next_tvb = tvb_new_subset_remaining(tvb, 2);
+ dissect_ppp(next_tvb, pinfo, tree);
+ }
+ }
+}
+
void
proto_register_ppp_raw_hdlc(void)
{
@@ -4351,10 +4396,14 @@ void
proto_reg_handoff_ppp_raw_hdlc(void)
{
dissector_handle_t ppp_raw_hdlc_handle;
+ dissector_handle_t ppp_usb_handle;
ppp_raw_hdlc_handle = create_dissector_handle(dissect_ppp_raw_hdlc, proto_ppp);
dissector_add("gre.proto", ETHERTYPE_CDMA2000_A10_UBS, ppp_raw_hdlc_handle);
dissector_add("gre.proto", ETHERTYPE_3GPP2, ppp_raw_hdlc_handle);
+
+ ppp_usb_handle = create_dissector_handle(dissect_ppp_usb, proto_ppp);
+ dissector_add("usb.bulk", IF_CLASS_UNKNOWN, ppp_usb_handle);
}
/*
diff --git a/epan/dissectors/packet-usb.c b/epan/dissectors/packet-usb.c
index ace2635c08..9a1b2c1388 100644
--- a/epan/dissectors/packet-usb.c
+++ b/epan/dissectors/packet-usb.c
@@ -5,6 +5,9 @@
* USB basic dissector
* By Paolo Abeni <paolo.abeni@email.it>
* Ronnie Sahlberg 2006
+ * Chris Maynard 2010 <chris[dot]maynard[at]gtech[dot]com>
+ *
+ * http://www.usb.org/developers/docs/usb_20_122909-2.zip
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,6 +29,7 @@
# include "config.h"
#endif
+#include <isprint.h>
#include <glib.h>
#include <epan/packet.h>
#include <epan/etypes.h>
@@ -49,6 +53,8 @@ static int hf_usb_device_address = -1;
static int hf_usb_bus_id = -1;
static int hf_usb_setup_flag = -1;
static int hf_usb_data_flag = -1;
+static int hf_usb_urb_ts_sec = -1;
+static int hf_usb_urb_ts_usec = -1;
static int hf_usb_urb_status = -1;
static int hf_usb_urb_len = -1;
static int hf_usb_data_len = -1;
@@ -131,9 +137,157 @@ static int usb_tap = -1;
static dissector_table_t usb_bulk_dissector_table;
static dissector_table_t usb_control_dissector_table;
+/* http://www.usb.org/developers/docs/USB_LANGIDs.pdf */
static const value_string usb_langid_vals[] = {
- {0x0000, "no language specified"},
- {0x0409, "English (United States)"},
+ {0x0000, "no language specified"},
+ {0x0436, "Afrikaans"},
+ {0x041c, "Albanian"},
+ {0x0401, "Arabic (Saudi Arabia)"},
+ {0x0801, "Arabic (Iraq)"},
+ {0x0c01, "Arabic (Egypt)"},
+ {0x1001, "Arabic (Libya)"},
+ {0x1401, "Arabic (Algeria)"},
+ {0x1801, "Arabic (Morocco)"},
+ {0x1c01, "Arabic (Tunisia)"},
+ {0x2001, "Arabic (Oman)"},
+ {0x2401, "Arabic (Yemen)"},
+ {0x2801, "Arabic (Syria)"},
+ {0x2c01, "Arabic (Jordan)"},
+ {0x3001, "Arabic (Lebanon)"},
+ {0x3401, "Arabic (Kuwait)"},
+ {0x3801, "Arabic (U.A.E.)"},
+ {0x3c01, "Arabic (Bahrain)"},
+ {0x4001, "Arabic (Qatar)"},
+ {0x042b, "Armenian"},
+ {0x044d, "Assamese"},
+ {0x042c, "Azeri (Latin)"},
+ {0x082c, "Azeri (Cyrillic)"},
+ {0x042d, "Basque"},
+ {0x0423, "Belarussian"},
+ {0x0445, "Bengali"},
+ {0x0402, "Bulgarian"},
+ {0x0455, "Burmese"},
+ {0x0403, "Catalan"},
+ {0x0404, "Chinese (Taiwan)"},
+ {0x0804, "Chinese (PRC)"},
+ {0x0c04, "Chinese (Hong Kong SAR, PRC)"},
+ {0x1004, "Chinese (Singapore)"},
+ {0x1404, "Chinese (Macau SAR)"},
+ {0x041a, "Croatian"},
+ {0x0405, "Czech"},
+ {0x0406, "Danish"},
+ {0x0413, "Dutch (Netherlands)"},
+ {0x0813, "Dutch (Belgium)"},
+ {0x0409, "English (United States)"},
+ {0x0809, "English (United Kingdom)"},
+ {0x0c09, "English (Australian)"},
+ {0x1009, "English (Canadian)"},
+ {0x1409, "English (New Zealand)"},
+ {0x1809, "English (Ireland)"},
+ {0x1c09, "English (South Africa)"},
+ {0x2009, "English (Jamaica)"},
+ {0x2409, "English (Caribbean)"},
+ {0x2809, "English (Belize)"},
+ {0x2c09, "English (Trinidad)"},
+ {0x3009, "English (Zimbabwe)"},
+ {0x3409, "English (Philippines)"},
+ {0x0425, "Estonian"},
+ {0x0438, "Faeroese"},
+ {0x0429, "Farsi"},
+ {0x040b, "Finnish"},
+ {0x040c, "French (Standard)"},
+ {0x080c, "French (Belgian)"},
+ {0x0c0c, "French (Canadian)"},
+ {0x100c, "French (Switzerland)"},
+ {0x140c, "French (Luxembourg)"},
+ {0x180c, "French (Monaco)"},
+ {0x0437, "Georgian"},
+ {0x0407, "German (Standard)"},
+ {0x0807, "German (Switzerland)"},
+ {0x0c07, "German (Austria)"},
+ {0x1007, "German (Luxembourg)"},
+ {0x1407, "German (Liechtenstein)"},
+ {0x0408, "Greek"},
+ {0x0447, "Gujarati"},
+ {0x040d, "Hebrew"},
+ {0x0439, "Hindi"},
+ {0x040e, "Hungarian"},
+ {0x040f, "Icelandic"},
+ {0x0421, "Indonesian"},
+ {0x0410, "Italian (Standard)"},
+ {0x0810, "Italian (Switzerland)"},
+ {0x0411, "Japanese"},
+ {0x044b, "Kannada"},
+ {0x0860, "Kashmiri (India)"},
+ {0x043f, "Kazakh"},
+ {0x0457, "Konkani"},
+ {0x0412, "Korean"},
+ {0x0812, "Korean (Johab)"},
+ {0x0426, "Latvian"},
+ {0x0427, "Lithuanian"},
+ {0x0827, "Lithuanian (Classic)"},
+ {0x042f, "Macedonian"},
+ {0x043e, "Malay (Malaysian)"},
+ {0x083e, "Malay (Brunei Darussalam)"},
+ {0x044c, "Malayalam"},
+ {0x0458, "Manipuri"},
+ {0x044e, "Marathi"},
+ {0x0861, "Nepali (India)"},
+ {0x0414, "Norwegian (Bokmal)"},
+ {0x0814, "Norwegian (Nynorsk)"},
+ {0x0448, "Oriya"},
+ {0x0415, "Polish"},
+ {0x0416, "Portuguese (Brazil)"},
+ {0x0816, "Portuguese (Standard)"},
+ {0x0446, "Punjabi"},
+ {0x0418, "Romanian"},
+ {0x0419, "Russian"},
+ {0x044f, "Sanskrit"},
+ {0x0c1a, "Serbian (Cyrillic)"},
+ {0x081a, "Serbian (Latin)"},
+ {0x0459, "Sindhi"},
+ {0x041b, "Slovak"},
+ {0x0424, "Slovenian"},
+ {0x040a, "Spanish (Traditional Sort)"},
+ {0x080a, "Spanish (Mexican)"},
+ {0x0c0a, "Spanish (Modern Sort)"},
+ {0x100a, "Spanish (Guatemala)"},
+ {0x140a, "Spanish (Costa Rica)"},
+ {0x180a, "Spanish (Panama)"},
+ {0x1c0a, "Spanish (Dominican Republic)"},
+ {0x200a, "Spanish (Venezuela)"},
+ {0x240a, "Spanish (Colombia)"},
+ {0x280a, "Spanish (Peru)"},
+ {0x2c0a, "Spanish (Argentina)"},
+ {0x300a, "Spanish (Ecuador)"},
+ {0x340a, "Spanish (Chile)"},
+ {0x380a, "Spanish (Uruguay)"},
+ {0x3c0a, "Spanish (Paraguay)"},
+ {0x400a, "Spanish (Bolivia)"},
+ {0x440a, "Spanish (El Salvador)"},
+ {0x480a, "Spanish (Honduras)"},
+ {0x4c0a, "Spanish (Nicaragua)"},
+ {0x500a, "Spanish (Puerto Rico)"},
+ {0x0430, "Sutu"},
+ {0x0441, "Swahili (Kenya)"},
+ {0x041d, "Swedish"},
+ {0x081d, "Swedish (Finland)"},
+ {0x0449, "Tamil"},
+ {0x0444, "Tatar (Tatarstan)"},
+ {0x044a, "Telugu"},
+ {0x041e, "Thai"},
+ {0x041f, "Turkish"},
+ {0x0422, "Ukrainian"},
+ {0x0420, "Urdu (Pakistan)"},
+ {0x0820, "Urdu (India)"},
+ {0x0443, "Uzbek (Latin)"},
+ {0x0843, "Uzbek (Cyrillic)"},
+ {0x042a, "Vietnamese"},
+ {0x04ff, "HID (Usage Data Descriptor)"},
+ {0xf0ff, "HID (Vendor Defined 1)"},
+ {0xf4ff, "HID (Vendor Defined 2)"},
+ {0xf8ff, "HID (Vendor Defined 3)"},
+ {0xfcff, "HID (Vendor Defined 4)"},
{0, NULL}
};
@@ -979,7 +1133,7 @@ dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvb
/* bmAttributes */
if (tree) {
ep_attrib_item=proto_tree_add_item(tree, hf_usb_bmAttributes, tvb, offset, 1, TRUE);
- ep_attrib_tree=proto_item_add_subtree(ep_attrib_item, ett_endpoint_bmAttributes);
+ ep_attrib_tree=proto_item_add_subtree(ep_attrib_item, ett_endpoint_bmAttributes);
}
proto_tree_add_item(ep_attrib_tree, hf_usb_bEndpointAttributeTransfer, tvb, offset, 1, TRUE);
/* isochronous only */
@@ -1192,6 +1346,8 @@ static int
dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info, usb_conv_info_t *usb_conv_info)
{
proto_item *item=NULL;
+ guint32 data_len;
+
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
val_to_str(usb_trans_info->u.get_descriptor.type, descriptor_type_vals, "Unknown type %u"));
@@ -1225,8 +1381,9 @@ dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree,
/* XXX dissect the descriptor coming back from the device */
item=proto_tree_add_text(tree, tvb, offset, -1, "GET DESCRIPTOR data (unknown descriptor type)");
tree=proto_item_add_subtree(item, ett_descriptor_device);
- proto_tree_add_item(tree, hf_usb_data, tvb, offset, pinfo->pseudo_header->linux_usb.data_len, FALSE);
- offset += pinfo->pseudo_header->linux_usb.data_len;
+ tvb_memcpy(tvb, (guint8 *)&data_len, offset, 4);
+ proto_tree_add_uint(tree, hf_usb_data, tvb, offset, 4, data_len);
+ offset += data_len;
break;
}
@@ -1537,8 +1694,8 @@ static const value_string setup_request_names_vals[] = {
static const true_false_string tfs_bmrequesttype_direction = {
- "Device-to-host",
- "Host-to-device"
+ "Device-to-host",
+ "Host-to-device"
};
static const value_string bmrequesttype_type_vals[] = {
@@ -1560,106 +1717,94 @@ static int
dissect_usb_bmrequesttype(proto_tree *parent_tree, tvbuff_t *tvb, int offset,
int *type)
{
- proto_item *item=NULL;
- proto_tree *tree=NULL;
- guint8 bmRequestType;
-
- if(parent_tree){
- item=proto_tree_add_item(parent_tree, hf_usb_bmRequestType, tvb, offset, 1, TRUE);
- tree = proto_item_add_subtree(item, ett_usb_setup_bmrequesttype);
- }
-
- bmRequestType = tvb_get_guint8(tvb, offset);
- *type = (bmRequestType & USB_TYPE_MASK) >>5;
- proto_tree_add_item(tree, hf_usb_bmRequestType_direction, tvb, offset, 1, TRUE);
- proto_tree_add_item(tree, hf_usb_bmRequestType_type, tvb, offset, 1, TRUE);
- proto_tree_add_item(tree, hf_usb_bmRequestType_recipient, tvb, offset, 1, TRUE);
-
- offset++;
- return offset;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_usb_bmRequestType, tvb, offset, 1, TRUE);
+ tree = proto_item_add_subtree(item, ett_usb_setup_bmrequesttype);
+ }
+
+ *type = USB_TYPE(tvb_get_guint8(tvb, offset));
+ proto_tree_add_item(tree, hf_usb_bmRequestType_direction, tvb, offset, 1, TRUE);
+ proto_tree_add_item(tree, hf_usb_bmRequestType_type, tvb, offset, 1, TRUE);
+ proto_tree_add_item(tree, hf_usb_bmRequestType_recipient, tvb, offset, 1, TRUE);
+
+ return ++offset;
}
+/* Adds the Linux USB pseudo header fields to the tree.
+ * NOTE: The multi-byte fields in this header (and only this header) are in
+ * host-endian format so we can't use proto_tree_add_item() nor the
+ * tvb_get_xyz() routines and is the reason for the tvb_memcpy() and
+ * proto_tree_add_uint[64]() pairs below. */
static void
dissect_linux_usb_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
guint8 transfer_type;
const gchar* val_str;
+ guint8 type, flag;
+ guint16 val16;
+ guint32 val32;
+ guint64 val64;
- proto_tree_add_uint64(tree, hf_usb_urb_id, tvb, 0, 0,
- pinfo->pseudo_header->linux_usb.id);
+ tvb_memcpy(tvb, (guint8 *)&val64, 0, 8);
+ proto_tree_add_uint64(tree, hf_usb_urb_id, tvb, 0, 8, val64);
/* show the event type of this URB as string and as a character */
- val_str = val_to_str(pinfo->pseudo_header->linux_usb.event_type,
- usb_urb_type_vals, "Unknown %d");
- proto_tree_add_string_format_value(tree, hf_usb_urb_type, tvb, 0, 0,
- &(pinfo->pseudo_header->linux_usb.event_type),
- "%s ('%c')", val_str,
- pinfo->pseudo_header->linux_usb.event_type);
-
- transfer_type = pinfo->pseudo_header->linux_usb.transfer_type;
- proto_tree_add_uint(tree, hf_usb_transfer_type, tvb, 0, 0, transfer_type);
+ type = tvb_get_guint8(tvb, 8);
+ val_str = val_to_str(type, usb_urb_type_vals, "Unknown %d");
+ proto_tree_add_string_format_value(tree, hf_usb_urb_type, tvb, 8, 1,
+ &type, "%s ('%c')", val_str, isprint(type) ? type : '.');
+
+ proto_tree_add_item(tree, hf_usb_transfer_type, tvb, 9, 1, FALSE);
if (check_col(pinfo->cinfo, COL_INFO)) {
+ transfer_type = tvb_get_guint8(tvb, 9);
col_append_str(pinfo->cinfo, COL_INFO,
val_to_str(transfer_type, usb_transfer_type_vals, "Unknown type %x"));
}
- proto_tree_add_uint(tree, hf_usb_endpoint_number, tvb, 0, 0,
- pinfo->pseudo_header->linux_usb.endpoint_number);
+ proto_tree_add_item(tree, hf_usb_endpoint_number, tvb, 10, 1, FALSE);
+ proto_tree_add_item(tree, hf_usb_device_address, tvb, 11, 1, FALSE);
- proto_tree_add_uint(tree, hf_usb_device_address, tvb, 0, 0,
- pinfo->pseudo_header->linux_usb.device_address);
-
- proto_tree_add_uint(tree, hf_usb_bus_id, tvb, 0, 0,
- pinfo->pseudo_header->linux_usb.bus_id);
+ tvb_memcpy(tvb, (guint8 *)&val16, 12, 2);
+ proto_tree_add_uint(tree, hf_usb_bus_id, tvb, 12, 2, val16);
/* Right after the pseudo header we always have
- * sizeof(struct usb_device_setup_hdr)=8 bytes. The content of these
- * bytes have only meaning in case setup_flag == 0.
+ * sizeof(struct usb_device_setup_hdr) bytes. The content of these
+ * bytes only have meaning in case setup_flag == 0.
*/
- if (pinfo->pseudo_header->linux_usb.setup_flag == 0) {
- proto_tree_add_string_format_value(tree, hf_usb_setup_flag, tvb,
- 0, 0,
- &(pinfo->pseudo_header->linux_usb.setup_flag),
- "present (%d)",
- pinfo->pseudo_header->linux_usb.setup_flag);
+ flag = tvb_get_guint8(tvb, 14);
+ if (flag == 0) {
+ proto_tree_add_string(tree, hf_usb_setup_flag, tvb, 14, 1, "relevant (0)");
} else {
proto_tree_add_string_format_value(tree, hf_usb_setup_flag, tvb,
- 0, 0,
- &(pinfo->pseudo_header->linux_usb.setup_flag),
- "not present ('%c')",
- pinfo->pseudo_header->linux_usb.setup_flag);
+ 14, 1, &flag, "not relevant ('%c')", isprint(flag) ? flag: '.');
}
- if (pinfo->pseudo_header->linux_usb.data_flag == 0) {
- proto_tree_add_string_format_value(tree, hf_usb_data_flag, tvb,
- 0, 0,
- &(pinfo->pseudo_header->linux_usb.data_flag),
- "present (%d)",
- pinfo->pseudo_header->linux_usb.data_flag);
+ flag = tvb_get_guint8(tvb, 15);
+ if (flag == 0) {
+ proto_tree_add_string(tree, hf_usb_data_flag, tvb, 15, 1, "present (0)");
} else {
proto_tree_add_string_format_value(tree, hf_usb_data_flag, tvb,
- 0, 0,
- &(pinfo->pseudo_header->linux_usb.data_flag),
- "not present ('%c')",
- pinfo->pseudo_header->linux_usb.data_flag);
+ 15, 1, &flag, "not present ('%c')", isprint(flag) ? flag : '.');
}
- /* Timestamp was already processed by libpcap,
- * skip it for now:
- * pinfo->pseudo_header->linux_usb.ts_sec
- * pinfo->pseudo_header->linux_usb.ts_usec
- */
-
- proto_tree_add_int(tree, hf_usb_urb_status, tvb, 0, 0,
- pinfo->pseudo_header->linux_usb.status);
+ tvb_memcpy(tvb, (guint8 *)&val64, 16, 8);
+ proto_tree_add_uint64(tree, hf_usb_urb_ts_sec, tvb, 16, 8, val64);
+
+ tvb_memcpy(tvb, (guint8 *)&val32, 24, 4);
+ proto_tree_add_uint(tree, hf_usb_urb_ts_usec, tvb, 24, 4, val32);
- proto_tree_add_uint(tree, hf_usb_urb_len, tvb, 0, 0,
- pinfo->pseudo_header->linux_usb.urb_len);
+ tvb_memcpy(tvb, (guint8 *)&val32, 28, 4);
+ proto_tree_add_int(tree, hf_usb_urb_status, tvb, 28, 4, val32);
- proto_tree_add_uint(tree, hf_usb_data_len, tvb, 0, 0,
- pinfo->pseudo_header->linux_usb.data_len);
+ tvb_memcpy(tvb, (guint8 *)&val32, 32, 4);
+ proto_tree_add_uint(tree, hf_usb_urb_len, tvb, 32, 4, val32);
+ tvb_memcpy(tvb, (guint8 *)&val32, 36, 4);
+ proto_tree_add_uint(tree, hf_usb_data_len, tvb, 36, 4, val32);
}
static void
@@ -1684,21 +1829,18 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
/* add usb hdr*/
if (parent) {
proto_item *ti = NULL;
- ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0, sizeof(struct usb_device_setup_hdr), "USB URB");
-
+ ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0,
+ sizeof(struct linux_usb_phdr) + sizeof(struct usb_device_setup_hdr), "USB URB");
tree = proto_item_add_subtree(ti, usb_hdr);
}
- dissect_linux_usb_pseudo_header(tvb, pinfo, tree);
-
- type = pinfo->pseudo_header->linux_usb.transfer_type;
-
- endpoint = pinfo->pseudo_header->linux_usb.endpoint_number & (~URB_TRANSFER_IN);
-
- tmp_addr = pinfo->pseudo_header->linux_usb.device_address;
- setup_flag = pinfo->pseudo_header->linux_usb.setup_flag;
-
- is_request = (pinfo->pseudo_header->linux_usb.event_type == URB_SUBMIT) ? TRUE : FALSE;
+ dissect_linux_usb_pseudo_header(tvb, pinfo, tree);
+ is_request = (tvb_get_guint8(tvb, 8) == URB_SUBMIT) ? TRUE : FALSE;
+ type = tvb_get_guint8(tvb, 9);
+ endpoint = tvb_get_guint8(tvb, 10) & (~URB_TRANSFER_IN);
+ tmp_addr = tvb_get_guint8(tvb, 11);
+ setup_flag = tvb_get_guint8(tvb, 14);
+ offset += sizeof(struct linux_usb_phdr); /* skip pseudo header */
/* Set up addresses and ports. */
if (is_request) {
@@ -1775,7 +1917,7 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
}
tap_data=ep_alloc(sizeof(usb_tap_data_t));
- tap_data->urb_type=(guint8)pinfo->pseudo_header->linux_usb.event_type;
+ tap_data->urb_type=tvb_get_guint8(tvb, 8);
tap_data->transfer_type=(guint8)type;
tap_data->conv_info=usb_conv_info;
tap_data->trans_info=usb_trans_info;
@@ -1790,22 +1932,16 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
item=proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, 0, 0, usb_conv_info->interfaceClass);
PROTO_ITEM_SET_GENERATED(item);
- /* Skip setup header - it's never present */
- offset += 8;
+ /* Skip setup header - it's not applicable */
+ offset += sizeof(struct usb_device_setup_hdr);
/*
* If this is padded (as is the case if the capture is done in
* memory-mapped mode), skip the padding; it's padded to a multiple
- * of 64 bits *after* the pseudo-header and setup header. The
- * pseudo-header is 40 bytes, and the setup header is 8 bytes,
- * so that's 16 bytes of padding to 64 bytes. (The pseudo-header
- * was removed from the packet data by Wiretap, so the offset
- * is relative to the beginning of the setup header, not relative
- * to the beginning of the raw packet data, so we can't just
- * round it up to a multiple of 64.)
+ * of 64 bits *after* the pseudo-header and setup header.
*/
if (padded)
- offset += 16;
+ offset += (64 - ((sizeof(struct linux_usb_phdr) + sizeof(struct usb_device_setup_hdr)) % 64)) % 64;
if(tvb_reported_length_remaining(tvb, offset)){
tvbuff_t *next_tvb;
@@ -1836,7 +1972,7 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
/* this is a request */
- /* Dissect the setup header - it's present */
+ /* Dissect the setup header - it's applicable */
ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(struct usb_device_setup_hdr), "URB setup");
setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
@@ -1857,7 +1993,7 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
* dissector
*/
proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE);
- offset += 1;
+ offset++;
if (check_col(pinfo->cinfo, COL_INFO)) {
col_add_fstr(pinfo->cinfo, COL_INFO, "%s Request",
@@ -1887,18 +2023,10 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
* If this is padded (as is the case if the capture
* is done in memory-mapped mode), skip the padding;
* it's padded to a multiple of 64 bits *after* the
- * pseudo-header and setup header. The pseudo-header
- * is 40 bytes, and the setup header is 8 bytes, so
- * that's 16 bytes of padding to 64 bytes. (The
- * pseudo-header was removed from the packet data by
- * Wiretap, so the offset is relative to the beginning
- * of the setup header, not relative to the beginning
- * of the raw packet data, so we can't just round it up
- * to a multiple of 64.)
+ * pseudo-header and setup header.
*/
if (padded)
- offset += 16;
-
+ offset += (64 - ((sizeof(struct linux_usb_phdr) + sizeof(struct usb_device_setup_hdr)) % 64)) % 64;
break;
case RQT_SETUP_TYPE_CLASS:
@@ -1909,7 +2037,7 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
}
/* Else no class dissector, just display generic fields */
proto_tree_add_item(setup_tree, hf_usb_request_unknown_class, tvb, offset, 1, TRUE);
- offset += 1;
+ offset++;
proto_tree_add_item(setup_tree, hf_usb_value, tvb, offset, 2, TRUE);
offset += 2;
proto_tree_add_item(setup_tree, hf_usb_index, tvb, offset, 2, TRUE);
@@ -1917,9 +2045,10 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
proto_tree_add_item(setup_tree, hf_usb_length, tvb, offset, 2, TRUE);
offset += 2;
break;
+
default:
proto_tree_add_item(setup_tree, hf_usb_request_unknown_class, tvb, offset, 1, TRUE);
- offset += 1;
+ offset++;
proto_tree_add_item(setup_tree, hf_usb_value, tvb, offset, 2, TRUE);
offset += 2;
proto_tree_add_item(setup_tree, hf_usb_index, tvb, offset, 2, TRUE);
@@ -1928,46 +2057,33 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
offset += 2;
}
} else {
- /* Skip setup header - it's not present */
-
- offset += 8;
+ /* Skip setup header - it's not applicable */
+ offset += sizeof(struct usb_device_setup_hdr);
/*
* If this is padded (as is the case if the capture is done
* in memory-mapped mode), skip the padding; it's padded to
* a multiple of 64 bits *after* the pseudo-header and setup
- * header. The pseudo-header is 40 bytes, and the setup
- * header is 8 bytes, so that's 16 bytes of padding to 64
- * bytes. (The pseudo-header was removed from the packet
- * data by Wiretap, so the offset is relative to the beginning
- * of the setup header, not relative to the beginning of the
- * raw packet data, so we can't just round it up to a multiple
- * of 64.)
+ * header.
*/
if (padded)
- offset += 16;
+ offset += (64 - ((sizeof(struct linux_usb_phdr) + sizeof(struct usb_device_setup_hdr)) % 64)) % 64;
}
} else {
tvbuff_t *next_tvb;
/* this is a response */
- /* Skip setup header - it's never present for responses */
- offset += 8;
+ /* Skip setup header - it's never applicable for responses */
+ offset += sizeof(struct usb_device_setup_hdr);
/*
* If this is padded (as is the case if the capture is done in
* memory-mapped mode), skip the padding; it's padded to a multiple
- * of 64 bits *after* the pseudo-header and setup header. The
- * pseudo-header is 40 bytes, and the setup header is 8 bytes,
- * so that's 16 bytes of padding to 64 bytes. (The pseudo-header
- * was removed from the packet data by Wiretap, so the offset
- * is relative to the beginning of the setup header, not relative
- * to the beginning of the raw packet data, so we can't just
- * round it up to a multiple of 64.)
+ * of 64 bits *after* the pseudo-header and setup header.
*/
if (padded)
- offset += 16;
+ offset += (64 - ((sizeof(struct linux_usb_phdr) + sizeof(struct usb_device_setup_hdr)) % 64)) % 64;
if(usb_trans_info){
/* Try to find a class specific dissector */
@@ -1976,7 +2092,7 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
return;
}
- type_2 = (usb_trans_info->requesttype & USB_TYPE_MASK) >>5;
+ type_2 = USB_TYPE(usb_trans_info->requesttype);
switch (type_2) {
case RQT_SETUP_TYPE_STANDARD:
@@ -2028,22 +2144,16 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
if (setup_flag == 0) {
proto_item *ti = NULL;
proto_tree *setup_tree = NULL;
- guint8 requesttype, request;
int type_2;
- /* Dissect the setup header - it's present */
+ /* Dissect the setup header - it's applicable */
ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(struct usb_device_setup_hdr), "URB setup");
setup_tree = proto_item_add_subtree(ti, usb_setup_hdr);
-
- requesttype=tvb_get_guint8(tvb, offset);
offset=dissect_usb_bmrequesttype(setup_tree, tvb, offset, &type_2);
-
- request=tvb_get_guint8(tvb, offset);
proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE);
- offset += 1;
-
+ offset++;
proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, TRUE);
offset += 2;
proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, TRUE);
@@ -2051,25 +2161,17 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent,
proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, TRUE);
offset += 2;
} else {
- /* Skip setup header - it's not present */
-
- offset += 8;
+ /* Skip setup header - it's not applicable */
+ offset += sizeof(struct usb_device_setup_hdr);
}
/*
* If this is padded (as is the case if the capture is done in
* memory-mapped mode), skip the padding; it's padded to a multiple
- * of 64 bits *after* the pseudo-header and setup header. The
- * pseudo-header is 40 bytes, and the setup header is 8 bytes,
- * so that's 16 bytes of padding to 64 bytes. (The pseudo-header
- * was removed from the packet data by Wiretap, so the offset
- * is relative to the beginning of the setup header, not relative
- * to the beginning of the raw packet data, so we can't just
- * round it up to a multiple of 64.)
+ * of 64 bits *after* the pseudo-header and setup header.
*/
if (padded)
- offset += 16;
-
+ offset += (64 - ((sizeof(struct linux_usb_phdr) + sizeof(struct usb_device_setup_hdr)) % 64)) % 64;
break;
}
@@ -2128,13 +2230,23 @@ proto_register_usb(void)
{ &hf_usb_setup_flag,
{ "Device setup request", "usb.setup_flag", FT_STRING, BASE_NONE,
NULL, 0x0,
- "USB device setup request is present (0) or not", HFILL }},
+ "USB device setup request is relevant (0) or not", HFILL }},
{ &hf_usb_data_flag,
{ "Data", "usb.data_flag", FT_STRING, BASE_NONE,
NULL, 0x0,
"USB data is present (0) or not", HFILL }},
+ { &hf_usb_urb_ts_sec,
+ { "URB sec", "usb.urb_ts_sec", FT_UINT64, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_usb_urb_ts_usec,
+ { "URB usec", "usb.urb_ts_usec", FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL }},
+
{ &hf_usb_urb_status,
{ "URB status", "usb.urb_status", FT_INT32, BASE_DEC,
VALS(usb_urb_status_vals), 0x0,
@@ -2185,19 +2297,19 @@ proto_register_usb(void)
{ &hf_usb_wFeatureSelector,
{ "wFeatureSelector", "usb.setup.wFeatureSelector", FT_UINT16, BASE_DEC,
- VALS(usb_feature_selector_vals), 0x0, NULL, HFILL }},
+ VALS(usb_feature_selector_vals), 0x0, NULL, HFILL }},
{ &hf_usb_wInterface,
{ "wInterface", "usb.setup.wInterface", FT_UINT16, BASE_DEC,
- NULL, 0x0, NULL, HFILL }},
+ NULL, 0x0, NULL, HFILL }},
{ &hf_usb_wStatus,
{ "wStatus", "usb.setup.wStatus", FT_UINT16, BASE_HEX,
- NULL, 0x0, NULL, HFILL }},
+ NULL, 0x0, NULL, HFILL }},
{ &hf_usb_wFrameNumber,
{ "wFrameNumber", "usb.setup.wFrameNumber", FT_UINT16, BASE_DEC,
- NULL, 0x0, NULL, HFILL }},
+ NULL, 0x0, NULL, HFILL }},
/* --------------------------------- */
{ &hf_usb_data,
@@ -2394,18 +2506,17 @@ proto_register_usb(void)
{ "Direction", "usb.bEndpointAddress.direction", FT_BOOLEAN, 8,
TFS(&tfs_endpoint_direction), 0x80, NULL, HFILL }},
- { &hf_usb_request_in,
- { "Request in", "usb.request_in", FT_FRAMENUM, BASE_NONE,
- NULL, 0, "The request to this packet is in this packet", HFILL }},
-
- { &hf_usb_time,
- { "Time from request", "usb.time", FT_RELATIVE_TIME, BASE_NONE,
- NULL, 0, "Time between Request and Response for USB cmds", HFILL }},
+ { &hf_usb_request_in,
+ { "Request in", "usb.request_in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "The request to this packet is in this packet", HFILL }},
- { &hf_usb_response_in,
- { "Response in", "usb.response_in", FT_FRAMENUM, BASE_NONE,
- NULL, 0, "The response to this packet is in this packet", HFILL }},
+ { &hf_usb_time,
+ { "Time from request", "usb.time", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Time between Request and Response for USB cmds", HFILL }},
+ { &hf_usb_response_in,
+ { "Response in", "usb.response_in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "The response to this packet is in this packet", HFILL }},
};
static gint *usb_subtrees[] = {
diff --git a/epan/dissectors/packet-usb.h b/epan/dissectors/packet-usb.h
index 1afadd4947..441ca0195a 100644
--- a/epan/dissectors/packet-usb.h
+++ b/epan/dissectors/packet-usb.h
@@ -106,6 +106,7 @@ typedef struct _usb_tap_data_t {
#define USB_DIR_IN 0x80 /* to host */
#define USB_TYPE_MASK (0x03 << 5)
+#define USB_TYPE(type) (((type) & USB_TYPE_MASK) >> 5)
#define RQT_SETUP_TYPE_STANDARD 0
#define RQT_SETUP_TYPE_CLASS 1
#define RQT_SETUP_TYPE_VENDOR 2