Have "dissect_scsi_cdb()" take an argument that's a SCSI device type,

for the benefit of dissectors such as the NDMP dissector that can at
least supply a reasonable guess for the device type; more than one type
of device can be opened on the same host over NDMP, so the scheme
currently used by the SCSI dissector to remember device types in INQUIRY
replies won't work.

Have the iSCSI dissector supply SCSI_DEV_UNKNOWN, and have the NDMP
dissector supply SCSI_DEV_SMC for NDMP_SCSI_EXECUTE_CDB (under the
assumption that it's operating on a media changer) and supply
SCSI_DEV_SSC for NDMP_TAPE_EXECUTE_CDB (under the assumption that it's
operating on a tape device).

Fix memory leaks in the SCSI dissector.

Fix the dissectors for the SSC READ(6) and WRITE(6) CDBs to dissect the
transfer length as a 24-bit quantity.

svn path=/trunk/; revision=6035
This commit is contained in:
Guy Harris 2002-08-20 22:33:17 +00:00
parent 7200333d8b
commit 71bfe6806c
4 changed files with 146 additions and 60 deletions

View File

@ -2,7 +2,7 @@
* Routines for iSCSI dissection
* Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
*
* $Id: packet-iscsi.c,v 1.36 2002/08/02 23:35:51 jmayer Exp $
* $Id: packet-iscsi.c,v 1.37 2002/08/20 22:33:16 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -1434,7 +1434,7 @@ dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
~(X_BIT | I_BIT) :
~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
/* SCSI Command */
dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16);
dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16, SCSI_DEV_UNKNOWN);
}
else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
if (scsi_status == 0x2) {

View File

@ -2,7 +2,7 @@
* Routines for NDMP dissection
* 2001 Ronnie Sahlberg (see AUTHORS for email)
*
* $Id: packet-ndmp.c,v 1.21 2002/08/02 23:35:54 jmayer Exp $
* $Id: packet-ndmp.c,v 1.22 2002/08/20 22:33:16 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -421,7 +421,6 @@ static const value_string msg_vals[] = {
{0, NULL}
};
static int
dissect_connect_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
@ -1051,7 +1050,8 @@ dissect_execute_cdb_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
}
static int
dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *parent_tree, gint devtype)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
@ -1072,7 +1072,7 @@ dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tre
offset += 4;
if (cdb_len != 0) {
dissect_scsi_cdb(tvb, pinfo, tree, offset, cdb_len);
dissect_scsi_cdb(tvb, pinfo, tree, offset, cdb_len, devtype);
offset += cdb_len_full;
}
@ -1111,9 +1111,24 @@ dissect_execute_cdb_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto
return offset;
}
/*
* XXX - we assume that NDMP_SCSI_EXECUTE_CDB requests only go to SCSI Media
* Changer devices and NDMP_TAPE_EXECUTE_CDB only go to SCSI Sequential
* Access devices.
*
* If that's not the case, we'll have to use the SCSI dissector's mechanisms
* for saving inquiry data for devices, and use inquiry data when available.
* Unfortunately, that means we need to save the name of the device, and
* use it as a device identifier; as the name isn't available in the
* NDMP_SCSI_EXECUTE_CDB or NDMP_TAPE_EXECUTE_CDB messages, that means
* we need to remember the currently-opened "SCSI" and "TAPE" devices
* from NDMP_SCSI_OPEN and NDMP_TAPE_OPEN, and attach to all frames
* that are the ones that trigger the dissection of NDMP_SCSI_EXECUTE_CDB
* or NDMP_TAPE_EXECUTE_CDB requests pointers to those names.
*/
static int
dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
proto_tree *tree, guint32 seq, gint devtype)
{
conversation_t *conversation;
scsi_task_id_t task_key;
@ -1132,7 +1147,7 @@ dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
}
task_key.conv_id = conversation->index;
task_key.task_id = seq;
pinfo->private_data = &task_key;
pinfo->private_data = &task_key;
/* flags */
offset = dissect_execute_cdb_flags(tvb, offset, pinfo, tree);
@ -1146,7 +1161,7 @@ dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
offset += 4;
/* CDB */
offset = dissect_execute_cdb_cdb(tvb, offset, pinfo, tree);
offset = dissect_execute_cdb_cdb(tvb, offset, pinfo, tree, devtype);
/* dataout */
offset = dissect_execute_cdb_payload(tvb, offset, pinfo, tree,
@ -1155,6 +1170,22 @@ dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
return offset;
}
static int
dissect_execute_cdb_request_mc(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
SCSI_DEV_SMC);
}
static int
dissect_execute_cdb_request_tape(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
SCSI_DEV_SSC);
}
static int
dissect_execute_cdb_sns(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
{
@ -2441,7 +2472,7 @@ static const ndmp_command ndmp_commands[] = {
{NDMP_SCSI_RESET_BUS,
NULL, dissect_error},
{NDMP_SCSI_EXECUTE_CDB,
dissect_execute_cdb_request, dissect_execute_cdb_reply},
dissect_execute_cdb_request_mc, dissect_execute_cdb_reply},
{NDMP_TAPE_OPEN,
dissect_tape_open_request, dissect_error},
{NDMP_TAPE_CLOSE,
@ -2455,7 +2486,7 @@ static const ndmp_command ndmp_commands[] = {
{NDMP_TAPE_READ,
dissect_tape_read_request, dissect_tape_read_reply},
{NDMP_TAPE_EXECUTE_CDB,
dissect_execute_cdb_request, dissect_execute_cdb_reply},
dissect_execute_cdb_request_tape, dissect_execute_cdb_reply},
{NDMP_DATA_GET_STATE,
NULL, dissect_data_get_state_reply},
{NDMP_DATA_START_BACKUP,

View File

@ -2,7 +2,7 @@
* Routines for decoding SCSI CDBs and responses
* Author: Dinesh G Dutt (ddutt@cisco.com)
*
* $Id: packet-scsi.c,v 1.14 2002/08/20 03:21:42 guy Exp $
* $Id: packet-scsi.c,v 1.15 2002/08/20 22:33:16 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -520,23 +520,6 @@ static const value_string scsi_persresv_type_val[] = {
{0, NULL},
};
/* SCSI Device Types */
#define SCSI_DEV_SBC 0x0
#define SCSI_DEV_SSC 0x1
#define SCSI_DEV_PRNT 0x2
#define SCSI_DEV_PROC 0x3
#define SCSI_DEV_WORM 0x4
#define SCSI_DEV_CDROM 0x5
#define SCSI_DEV_SCAN 0x6
#define SCSI_DEV_OPTMEM 0x7
#define SCSI_DEV_SMC 0x8
#define SCSI_DEV_COMM 0x9
#define SCSI_DEV_RAID 0xC
#define SCSI_DEV_SES 0xD
#define SCSI_DEV_RBC 0xE
#define SCSI_DEV_OCRW 0xF
#define SCSI_DEV_OSD 0x11
static const value_string scsi_devtype_val[] = {
{SCSI_DEV_SBC , "Direct Access Device"},
{SCSI_DEV_SSC , "Sequential Access Device"},
@ -1100,7 +1083,21 @@ typedef struct _scsi_task_data {
guint8 flags; /* used by SCSI Inquiry */
} scsi_task_data_t;
/* The next two data structures are used to track SCSI device type */
/*
* The next two data structures are used to track SCSI device type.
*
* XXX - it might not be sufficient to use the address of the server
* to which SCSI CDBs are being sent to identify the device, as
*
* 1) a server might have multiple targets or logical units;
*
* 2) a server might make a different logical unit refer to
* different devices for different clients;
*
* so we should really base this on the connection index for the
* connection and on a device identifier supplied to us by our caller,
* not on a network-layer address.
*/
typedef struct _scsi_devtype_key {
address devid;
} scsi_devtype_key_t;
@ -1229,9 +1226,32 @@ scsi_end_task (packet_info *pinfo)
/*
* Protocol initialization
*/
static void
free_devtype_key_dev_info(gpointer key_arg, gpointer value_arg _U_,
gpointer user_data _U_)
{
scsi_devtype_key_t *key = key_arg;
if (key->devid.data != NULL) {
g_free((gpointer)key->devid.data);
key->devid.data = NULL;
}
}
static void
scsi_init_protocol(void)
{
/*
* First, free up the data for the addresses attached to
* scsi_devtype_key_t structures. Do so before we free
* those structures or destroy the hash table in which
* they're stored.
*/
if (scsidev_req_hash != NULL) {
g_hash_table_foreach(scsidev_req_hash, free_devtype_key_dev_info,
NULL);
}
if (scsi_req_keys)
g_mem_chunk_destroy(scsi_req_keys);
if (scsi_req_vals)
@ -1392,16 +1412,15 @@ dissect_scsi_inquiry (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
if (!isreq && (cdata == NULL || !(cdata->flags & 0x3))) {
/*
* INQUIRY response; add device type to list of known devices &
* their types if not already known.
* INQUIRY response with device type information; add device type
* to list of known devices & their types if not already known.
*
* XXX - this assumes that the source address of the INQUIRY
* reply uniquely identifies the device; that isn't the case, as,
* for example, for iSCSI you could have more than one target
* or LUN at a given IP address, and for NDMP more than one
* device can be opened and closed in the same session.
* We don't use COPY_ADDRESS because "dkey.devid" isn't
* persistent, and therefore it can point to the stuff
* in "pinfo->src". (Were we to use COPY_ADDRESS, we'd
* have to free the address data it allocated before we return.)
*/
COPY_ADDRESS (&(dkey.devid), &(pinfo->src));
dkey.devid = pinfo->src;
devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
&dkey);
if (!devdata) {
@ -2685,7 +2704,7 @@ dissect_scsi_ssc2_read6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree
proto_tree_add_text (tree, tvb, offset, 1,
"SILI: %u, FIXED: %u",
(flags & 0x02) >> 1, flags & 0x01);
proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 1, 0);
proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 3, 0);
flags = tvb_get_guint8 (tvb, offset+4);
proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
flags,
@ -2710,7 +2729,8 @@ dissect_scsi_ssc2_write6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tre
flags = tvb_get_guint8 (tvb, offset);
proto_tree_add_text (tree, tvb, offset, 1,
"FIXED: %u", flags & 0x01);
proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 1, 0);
proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 3,
FALSE);
flags = tvb_get_guint8 (tvb, offset+4);
proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
flags,
@ -2987,7 +3007,7 @@ dissect_scsi_snsinfo (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
void
dissect_scsi_cdb (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint start, guint cdblen)
guint start, guint cdblen, gint devtype_arg)
{
int offset = start;
proto_item *ti;
@ -3002,24 +3022,27 @@ dissect_scsi_cdb (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
opcode = tvb_get_guint8 (tvb, offset);
/*
* Try to look up the device data for this device.
*
* XXX - this assumes that the destination address of the request
* uniquely identifies the device; that isn't the case, as,
* for example, for iSCSI you could have more than one target
* or LUN at a given IP address, and for NDMP more than one
* device can be opened and closed in the same session.
*/
COPY_ADDRESS (&(dkey.devid), &pinfo->dst);
devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
&dkey);
if (devdata != NULL) {
devtype = devdata->devtype;
}
if (devtype_arg != SCSI_DEV_UNKNOWN)
devtype = devtype_arg;
else {
devtype = (scsi_device_type)scsi_def_devtype;
/*
* Try to look up the device data for this device.
*
* We don't use COPY_ADDRESS because "dkey.devid" isn't
* persistent, and therefore it can point to the stuff
* in "pinfo->src". (Were we to use COPY_ADDRESS, we'd
* have to free the address data it allocated before we return.)
*/
dkey.devid = pinfo->dst;
devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
&dkey);
if (devdata != NULL) {
devtype = devdata->devtype;
}
else {
devtype = (scsi_device_type)scsi_def_devtype;
}
}
if ((valstr = match_strval (opcode, scsi_spc2_val)) == NULL) {
@ -3098,6 +3121,10 @@ dissect_scsi_cdb (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
"Opcode: %s (0x%02x)", valstr,
opcode);
}
else {
/* "Can't happen" */
g_assert_not_reached();
}
}
else {
proto_tree_add_item (scsi_tree, hf_scsi_spcopcode, tvb, offset, 1, 0);

View File

@ -1,7 +1,7 @@
/* packet-scsi.h
* Author: Dinesh G Dutt (ddutt@cisco.com)
*
* $Id: packet-scsi.h,v 1.3 2002/02/13 01:17:58 guy Exp $
* $Id: packet-scsi.h,v 1.4 2002/08/20 22:33:17 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -27,10 +27,38 @@
extern const value_string scsi_status_val[];
/*
* SCSI Device Types.
*
* These can be supplied to the dissection routines if the caller happens
* to know the device type (e.g., NDMP assumes that a "jukebox" is a
* media changer, SCSI_DEV_SMC, and a "tape" is a sequential access device,
* SCSI_DEV_SSC).
*
* If the caller doesn't know the device type, it supplies SCSI_DEV_UNKNOWN.
*/
#define SCSI_DEV_UNKNOWN -1
#define SCSI_DEV_SBC 0x0
#define SCSI_DEV_SSC 0x1
#define SCSI_DEV_PRNT 0x2
#define SCSI_DEV_PROC 0x3
#define SCSI_DEV_WORM 0x4
#define SCSI_DEV_CDROM 0x5
#define SCSI_DEV_SCAN 0x6
#define SCSI_DEV_OPTMEM 0x7
#define SCSI_DEV_SMC 0x8
#define SCSI_DEV_COMM 0x9
#define SCSI_DEV_RAID 0xC
#define SCSI_DEV_SES 0xD
#define SCSI_DEV_RBC 0xE
#define SCSI_DEV_OCRW 0xF
#define SCSI_DEV_OSD 0x11
/* Function Decls; functions invoked by SAM-2 transport protocols such as
* FCP/iSCSI
*/
void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *, guint, guint);
void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *, guint, guint,
gint);
void dissect_scsi_rsp (tvbuff_t *, packet_info *, proto_tree *);
void dissect_scsi_payload (tvbuff_t *, packet_info *, proto_tree *, guint,
gboolean, guint32);