aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors
diff options
context:
space:
mode:
authorRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>2006-10-18 11:24:03 +0000
committerRonnie Sahlberg <ronnie_sahlberg@ozemail.com.au>2006-10-18 11:24:03 +0000
commit232e884ca140fd4146f1b96b4cfc6c3a5ae80c94 (patch)
tree28bea8f6e89dd0af8966621d9b7f390ad2cfc2c3 /epan/dissectors
parent6a75fbab650e4e4e2f125f06a4fd5a2ca0bfcc3e (diff)
new dissector : usb mass storage
this is a wrapper protocol to store SCSI frames inside usb bulk data transfers the dissector is far from complete but does track ITL and ITLQ structures and will also call the SCSI dissector to dissect the SCSI CDB. what is still missing is handling of data in/out and scsi responses at least it will now display the SCSI CDB and dissect it. woohoo svn path=/trunk/; revision=19589
Diffstat (limited to 'epan/dissectors')
-rw-r--r--epan/dissectors/Makefile.common1
-rw-r--r--epan/dissectors/packet-usb-masstorage.c223
-rw-r--r--epan/dissectors/packet-usb.c11
-rw-r--r--epan/dissectors/packet-usb.h9
4 files changed, 236 insertions, 8 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 85f77e9235..1dc736c9d6 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -661,6 +661,7 @@ DISSECTOR_SRC = \
packet-udp.c \
packet-ulp.c \
packet-usb.c \
+ packet-usb-masstorage.c \
packet-umts_fp.c \
packet-umts_rrc.c \
packet-umts_rrc_ies.c \
diff --git a/epan/dissectors/packet-usb-masstorage.c b/epan/dissectors/packet-usb-masstorage.c
new file mode 100644
index 0000000000..a02a79550c
--- /dev/null
+++ b/epan/dissectors/packet-usb-masstorage.c
@@ -0,0 +1,223 @@
+/* packet-usb-masstorage.c
+ *
+ * $Id$
+ *
+ * usb mass storage dissector
+ * Ronnie Sahlberg 2006
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/emem.h>
+#include <epan/conversation.h>
+#include <string.h>
+#include "packet-usb.h"
+#include "packet-scsi.h"
+
+/* protocols and header fields */
+static int proto_usb_ms = -1;
+static int hf_usb_ms_dCBWSignature = -1;
+static int hf_usb_ms_dCBWTag = -1;
+static int hf_usb_ms_dCBWDataTransferLength = -1;
+static int hf_usb_ms_dCBWFlags = -1;
+static int hf_usb_ms_dCBWLUN = -1;
+static int hf_usb_ms_dCBWCBLength = -1;
+
+static gint ett_usb_ms = -1;
+
+
+/* there is one such structure for each masstorage conversation */
+typedef struct _usb_ms_conv_info_t {
+ emem_tree_t *itl; /* indexed by LUN */
+ emem_tree_t *itlq; /* pinfo->fd->num */
+} usb_ms_conv_info_t;
+
+static void
+dissect_usb_ms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ usb_conv_info_t *usb_conv_info;
+ usb_ms_conv_info_t *usb_ms_conv_info;
+ proto_tree *tree=NULL;
+ guint32 signature;
+ int offset=0;
+ gboolean is_request;
+ itl_nexus_t *itl;
+ itlq_nexus_t *itlq;
+
+ usb_conv_info=pinfo->usb_conv_info;
+ /* verify that we do have a usb_ms_conv_info */
+ usb_ms_conv_info=usb_conv_info->masstorage;
+ if(!usb_ms_conv_info){
+ usb_ms_conv_info=se_alloc(sizeof(usb_ms_conv_info_t));
+ usb_ms_conv_info->itl=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "USB ITL");
+ usb_ms_conv_info->itlq=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "USB ITLQ");
+ usb_conv_info->masstorage=usb_ms_conv_info;
+ }
+
+
+ is_request=(pinfo->srcport==NO_ENDPOINT);
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBMS");
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+
+ if(parent_tree){
+ proto_item *ti = NULL;
+ ti = proto_tree_add_protocol_format(parent_tree, proto_usb_ms, tvb, 0, -1, "USB Mass Storage");
+
+ tree = proto_item_add_subtree(ti, ett_usb_ms);
+ }
+
+ signature=tvb_get_letohl(tvb, offset);
+ /* is this a CDB ? */
+ if(is_request&&(signature==0x43425355)&&(tvb_length(tvb)==31)){
+ tvbuff_t *cdb_tvb;
+ int cdbrlen, cdblen;
+ guint8 lun, flags;
+ guint32 datalen;
+
+ /* dCBWSignature */
+ proto_tree_add_item(tree, hf_usb_ms_dCBWSignature, tvb, offset, 4, TRUE);
+ offset+=4;
+
+ /* dCBWTag */
+ proto_tree_add_item(tree, hf_usb_ms_dCBWTag, tvb, offset, 4, TRUE);
+ offset+=4;
+
+ /* dCBWDataTransferLength */
+ proto_tree_add_item(tree, hf_usb_ms_dCBWDataTransferLength, tvb, offset, 4, TRUE);
+ datalen=tvb_get_letohl(tvb, offset);
+ offset+=4;
+
+ /* dCBWFlags */
+ proto_tree_add_item(tree, hf_usb_ms_dCBWFlags, tvb, offset, 1, TRUE);
+ flags=tvb_get_guint8(tvb, offset);
+ offset+=1;
+
+ /* dCBWLUN */
+ proto_tree_add_item(tree, hf_usb_ms_dCBWLUN, tvb, offset, 1, TRUE);
+ lun=tvb_get_guint8(tvb, offset)&0x0f;
+ offset+=1;
+
+ /* make sure we have a ITL structure for this LUN */
+ itl=(itl_nexus_t *)se_tree_lookup32(usb_ms_conv_info->itl, lun);
+ if(!itl){
+ itl=se_alloc(sizeof(itl_nexus_t));
+ itl->cmdset=0xff;
+ itl->conversation=NULL;
+ se_tree_insert32(usb_ms_conv_info->itl, lun, itl);
+ }
+
+ /* make sure we have an ITLQ structure for this LUN/transaction */
+ itlq=(itlq_nexus_t *)se_tree_lookup32(usb_ms_conv_info->itlq, pinfo->fd->num);
+ if(!itlq){
+ itlq=se_alloc(sizeof(itlq_nexus_t));
+ itlq->lun=lun;
+ itlq->scsi_opcode=0xffff;
+ itlq->task_flags=0;
+ if(datalen){
+ if(flags&0x80){
+ itlq->task_flags|=SCSI_DATA_READ;
+ } else {
+ itlq->task_flags|=SCSI_DATA_WRITE;
+ }
+ }
+ itlq->data_length=datalen;
+ itlq->bidir_data_length=0;
+ itlq->fc_time=pinfo->fd->abs_ts;
+ itlq->first_exchange_frame=pinfo->fd->num;
+ itlq->last_exchange_frame=0;
+ itlq->flags=0;
+ itlq->alloc_len=0;
+ itlq->extra_data=NULL;
+ se_tree_insert32(usb_ms_conv_info->itlq, pinfo->fd->num, itlq);
+ }
+
+ /* dCBWCBLength */
+ proto_tree_add_item(tree, hf_usb_ms_dCBWCBLength, tvb, offset, 1, TRUE);
+ cdbrlen=tvb_get_guint8(tvb, offset)&0x1f;
+ offset+=1;
+
+ cdblen=cdbrlen;
+ if(cdblen>tvb_length_remaining(tvb, offset)){
+ cdblen=tvb_length_remaining(tvb, offset);
+ }
+ if(cdblen){
+ cdb_tvb=tvb_new_subset(tvb, offset, cdblen, cdbrlen);
+ dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, itlq, itl);
+ }
+ }
+}
+
+void
+proto_register_usb_ms(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_usb_ms_dCBWSignature,
+ { "Signature", "usbms.dCBWSignature", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_usb_ms_dCBWTag,
+ { "Tag", "usbms.dCBWTag", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_usb_ms_dCBWDataTransferLength,
+ { "DataTransferLength", "usbms.dCBWDataTransferLength", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_usb_ms_dCBWFlags,
+ { "Flags", "usbms.dCBWFlags", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_usb_ms_dCBWLUN,
+ { "LUN", "usbms.dCBWLUN", FT_UINT8, BASE_HEX,
+ NULL, 0x0f, "", HFILL }},
+
+ { &hf_usb_ms_dCBWCBLength,
+ { "CDB Length", "usbms.dCBWCBLength", FT_UINT8, BASE_HEX,
+ NULL, 0x1f, "", HFILL }},
+
+ };
+
+ static gint *usb_ms_subtrees[] = {
+ &ett_usb_ms,
+ };
+
+
+ proto_usb_ms = proto_register_protocol("USB Mass Storage", "USBMS", "usbms");
+ proto_register_field_array(proto_usb_ms, hf, array_length(hf));
+ proto_register_subtree_array(usb_ms_subtrees, array_length(usb_ms_subtrees));
+
+ register_dissector("usbms", dissect_usb_ms, proto_usb_ms);
+}
+
+void
+proto_reg_handoff_usb_ms(void)
+{
+ dissector_handle_t usb_ms_handle;
+ usb_ms_handle = create_dissector_handle(dissect_usb_ms, proto_usb_ms);
+
+ dissector_add("usb.bulk", IF_CLASS_MASSTORAGE, usb_ms_handle);
+}
diff --git a/epan/dissectors/packet-usb.c b/epan/dissectors/packet-usb.c
index f46ca3e453..52e9d68e84 100644
--- a/epan/dissectors/packet-usb.c
+++ b/epan/dissectors/packet-usb.c
@@ -102,14 +102,6 @@ static gint ett_descriptor_device = -1;
static dissector_table_t usb_bulk_dissector_table;
-/* This is the endpoint number user for "no endpoint" or the fake endpoint
- * for the host side since we need two endpoints to manage conversations
- * properly.
- */
-#define NO_ENDPOINT 0xffff
-
-
-
typedef enum {
URB_CONTROL_INPUT,
URB_CONTROL_OUTPUT,
@@ -196,6 +188,7 @@ get_usb_conv_info(conversation_t *conversation)
usb_conv_info = se_alloc(sizeof(usb_conv_info_t));
usb_conv_info->class=IF_CLASS_UNKNOWN;
usb_conv_info->transactions=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "usb transactions");
+ usb_conv_info->masstorage=NULL;
conversation_add_proto_data(conversation, proto_usb, usb_conv_info);
}
@@ -456,6 +449,7 @@ dissect_usb_interface_descriptor(packet_info *pinfo, proto_tree *parent_tree, tv
usb_trans_info->interface_info=se_alloc(sizeof(usb_conv_info_t));
usb_trans_info->interface_info->class=tvb_get_guint8(tvb, offset);
usb_trans_info->interface_info->transactions=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "usb transactions");
+ usb_trans_info->interface_info->masstorage=NULL;
}
offset++;
@@ -878,6 +872,7 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent)
usb_conv_info = se_alloc(sizeof(usb_conv_info_t));
usb_conv_info->class=IF_CLASS_UNKNOWN;
usb_conv_info->transactions=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "usb transactions");
+ usb_conv_info->masstorage=NULL;
conversation_add_proto_data(conversation, proto_usb, usb_conv_info);
}
diff --git a/epan/dissectors/packet-usb.h b/epan/dissectors/packet-usb.h
index c0004df45d..972a1fcb95 100644
--- a/epan/dissectors/packet-usb.h
+++ b/epan/dissectors/packet-usb.h
@@ -28,6 +28,7 @@
typedef struct _usb_conv_info_t {
guint16 class; /* class for this conversation */
emem_tree_t *transactions;
+ void *masstorage; /* mass storage data */
} usb_conv_info_t;
/* there is one such structure for each request/response */
@@ -53,6 +54,14 @@ typedef struct _usb_trans_info_t {
usb_conv_info_t *interface_info;
} usb_trans_info_t;
+
+/* This is the endpoint number user for "no endpoint" or the fake endpoint
+ * for the host side since we need two endpoints to manage conversations
+ * properly.
+ */
+#define NO_ENDPOINT 0xffff
+
+
#define IF_CLASS_UNKNOWN 0xffff
#define IF_CLASS_MASSTORAGE 0x08