forked from osmocom/wireshark
![Guy Harris](/assets/img/avatar_default.png)
That removes most of the uses of the frame number field in the frame_data structure. Change-Id: Ie22e4533e87f8360d7c0a61ca6ffb796cc233f22 Reviewed-on: https://code.wireshark.org/review/13509 Reviewed-by: Guy Harris <guy@alum.mit.edu>
4055 lines
142 KiB
C
4055 lines
142 KiB
C
/* packet-scsi-osd.c
|
|
* Dissector for the SCSI OSD (object based storage) commandset
|
|
*
|
|
* Ronnie sahlberg 2006
|
|
* Joe Breher 2006
|
|
* Javier Godoy 2013 (OSD-2 dissector)
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 2002 Gerald Combs
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <epan/packet.h>
|
|
#include <epan/conversation.h>
|
|
#include <epan/expert.h>
|
|
#include "packet-scsi.h"
|
|
#include "packet-scsi-osd.h"
|
|
|
|
void proto_register_scsi_osd(void);
|
|
|
|
static int proto_scsi_osd = -1;
|
|
int hf_scsi_osd_opcode = -1;
|
|
static int hf_scsi_osd_add_cdblen = -1;
|
|
static int hf_scsi_osd_svcaction = -1;
|
|
static int hf_scsi_osd_option = -1;
|
|
static int hf_scsi_osd_option_dpo = -1;
|
|
static int hf_scsi_osd_option_fua = -1;
|
|
static int hf_scsi_osd_getsetattrib = -1;
|
|
static int hf_scsi_osd_timestamps_control = -1;
|
|
static int hf_scsi_osd_formatted_capacity = -1;
|
|
static int hf_scsi_osd_get_attributes_page = -1;
|
|
static int hf_scsi_osd_get_attributes_allocation_length = -1;
|
|
static int hf_scsi_osd_get_attributes_list_length = -1;
|
|
static int hf_scsi_osd_get_attributes_list_offset = -1;
|
|
static int hf_scsi_osd_retrieved_attributes_offset = -1;
|
|
static int hf_scsi_osd_set_attributes_page = -1;
|
|
static int hf_scsi_osd_set_attribute_length = -1;
|
|
static int hf_scsi_osd_set_attribute_number = -1;
|
|
static int hf_scsi_osd_set_attributes_offset = -1;
|
|
static int hf_scsi_osd_set_attributes_list_length = -1;
|
|
static int hf_scsi_osd_set_attributes_list_offset = -1;
|
|
static int hf_scsi_osd_capability_format = -1;
|
|
static int hf_scsi_osd_key_version = -1;
|
|
static int hf_scsi_osd_icva = -1;
|
|
static int hf_scsi_osd_security_method = -1;
|
|
static int hf_scsi_osd_capability_expiration_time = -1;
|
|
static int hf_scsi_osd_audit = -1;
|
|
static int hf_scsi_osd_capability_discriminator = -1;
|
|
static int hf_scsi_osd_object_created_time = -1;
|
|
static int hf_scsi_osd_object_type = -1;
|
|
static int hf_scsi_osd_permissions = -1;
|
|
static int hf_scsi_osd_permissions_read = -1;
|
|
static int hf_scsi_osd_permissions_write = -1;
|
|
static int hf_scsi_osd_permissions_get_attr = -1;
|
|
static int hf_scsi_osd_permissions_set_attr = -1;
|
|
static int hf_scsi_osd_permissions_create = -1;
|
|
static int hf_scsi_osd_permissions_remove = -1;
|
|
static int hf_scsi_osd_permissions_obj_mgmt = -1;
|
|
static int hf_scsi_osd_permissions_append = -1;
|
|
static int hf_scsi_osd_permissions_dev_mgmt = -1;
|
|
static int hf_scsi_osd_permissions_global = -1;
|
|
static int hf_scsi_osd_permissions_pol_sec = -1;
|
|
static int hf_scsi_osd_object_descriptor_type = -1;
|
|
static int hf_scsi_osd_object_descriptor = -1;
|
|
static int hf_scsi_osd_ricv = -1;
|
|
static int hf_scsi_osd_request_nonce = -1;
|
|
static int hf_scsi_osd_diicvo = -1;
|
|
static int hf_scsi_osd_doicvo = -1;
|
|
static int hf_scsi_osd_requested_partition_id = -1;
|
|
static int hf_scsi_osd_sortorder = -1;
|
|
static int hf_scsi_osd_partition_id = -1;
|
|
static int hf_scsi_osd_list_identifier = -1;
|
|
static int hf_scsi_osd_allocation_length = -1;
|
|
static int hf_scsi_osd_length = -1;
|
|
static int hf_scsi_osd_starting_byte_address = -1;
|
|
static int hf_scsi_osd_initial_object_id = -1;
|
|
static int hf_scsi_osd_additional_length = -1;
|
|
static int hf_scsi_osd_continuation_object_id = -1;
|
|
static int hf_scsi_osd_list_flags_lstchg = -1;
|
|
static int hf_scsi_osd_list_flags_root = -1;
|
|
static int hf_scsi_osd_list_collection_flags_coltn = -1;
|
|
static int hf_scsi_osd_user_object_id = -1;
|
|
static int hf_scsi_osd_requested_user_object_id = -1;
|
|
static int hf_scsi_osd_number_of_user_objects = -1;
|
|
static int hf_scsi_osd_key_to_set = -1;
|
|
static int hf_scsi_osd_set_key_version = -1;
|
|
static int hf_scsi_osd_key_identifier = -1;
|
|
static int hf_scsi_osd_seed = -1;
|
|
static int hf_scsi_osd_collection_fcr = -1;
|
|
static int hf_scsi_osd_collection_object_id = -1;
|
|
static int hf_scsi_osd_requested_collection_object_id = -1;
|
|
static int hf_scsi_osd_partition_created_in = -1;
|
|
static int hf_scsi_osd_partition_removed_in = -1;
|
|
static int hf_scsi_osd_flush_scope = -1;
|
|
static int hf_scsi_osd_flush_collection_scope = -1;
|
|
static int hf_scsi_osd_flush_partition_scope = -1;
|
|
static int hf_scsi_osd_flush_osd_scope = -1;
|
|
static int hf_scsi_osd_attributes_list_type = -1;
|
|
static int hf_scsi_osd_attributes_list_length = -1;
|
|
static int hf_scsi_osd_attributes_page = -1;
|
|
static int hf_scsi_osd_attribute_number = -1;
|
|
static int hf_scsi_osd_attribute_length = -1;
|
|
static int hf_scsi_osd_attrval_user_object_logical_length = -1;
|
|
static int hf_scsi_osd_attrval_object_type = -1;
|
|
static int hf_scsi_osd_attrval_partition_id = -1;
|
|
static int hf_scsi_osd_attrval_object_id = -1;
|
|
static int hf_scsi_osd2_query_type = -1;
|
|
static int hf_scsi_osd2_query_entry_length = -1;
|
|
static int hf_scsi_osd2_query_attributes_page = -1;
|
|
static int hf_scsi_osd2_query_attribute_number = -1;
|
|
static int hf_scsi_osd2_query_minimum_attribute_value_length = -1;
|
|
static int hf_scsi_osd2_query_maximum_attribute_value_length = -1;
|
|
|
|
/* Fields that are defined in OSD-2 are prefixed with hf_scsi_osd2_ */
|
|
static int hf_scsi_osd2_attributes_list_length = -1;
|
|
static int hf_scsi_osd2_set_attribute_value = -1;
|
|
static int hf_scsi_osd2_isolation = -1;
|
|
static int hf_scsi_osd2_immed_tr = -1;
|
|
static int hf_scsi_osd2_list_attr = -1;
|
|
static int hf_scsi_osd2_object_descriptor_format = -1;
|
|
static int hf_scsi_osd2_matches_collection_object_id = -1;
|
|
static int hf_scsi_osd2_source_collection_object_id = -1;
|
|
static int hf_scsi_osd2_cdb_continuation_length = -1;
|
|
static int hf_scsi_osd2_cdb_continuation_format = -1;
|
|
static int hf_scsi_osd2_continued_service_action = -1;
|
|
static int hf_scsi_osd2_cdb_continuation_descriptor_type = -1;
|
|
static int hf_scsi_osd2_cdb_continuation_descriptor_pad_length = -1;
|
|
static int hf_scsi_osd2_cdb_continuation_descriptor_length = -1;
|
|
static int hf_scsi_osd2_remove_scope = -1;
|
|
|
|
static gint ett_osd_option = -1;
|
|
static gint ett_osd_partition = -1;
|
|
static gint ett_osd_attribute_parameters = -1;
|
|
static gint ett_osd_capability = -1;
|
|
static gint ett_osd_permission_bitmask = -1;
|
|
static gint ett_osd_security_parameters = -1;
|
|
static gint ett_osd_get_attributes = -1;
|
|
static gint ett_osd_set_attributes = -1;
|
|
static gint ett_osd_multi_object = -1;
|
|
static gint ett_osd_attribute = -1;
|
|
static gint ett_osd2_query_criteria_entry = -1;
|
|
|
|
static expert_field ei_osd_attr_unknown = EI_INIT;
|
|
static expert_field ei_osd2_invalid_offset = EI_INIT;
|
|
static expert_field ei_osd2_invalid_object_descriptor_format = EI_INIT;
|
|
static expert_field ei_osd_unknown_attributes_list_type = EI_INIT;
|
|
static expert_field ei_osd2_cdb_continuation_format_unknown = EI_INIT;
|
|
static expert_field ei_osd2_continued_service_action_mismatch = EI_INIT;
|
|
static expert_field ei_osd2_cdb_continuation_descriptor_type_unknown = EI_INIT;
|
|
static expert_field ei_osd2_cdb_continuation_descriptor_length_invalid = EI_INIT;
|
|
static expert_field ei_osd2_cdb_continuation_length_invalid = EI_INIT;
|
|
static expert_field ei_osd_attr_length_invalid = EI_INIT;
|
|
static expert_field ei_osd2_query_values_equal= EI_INIT;
|
|
|
|
#define PAGE_NUMBER_OBJECT 0x00000000
|
|
#define PAGE_NUMBER_PARTITION 0x30000000
|
|
#define PAGE_NUMBER_COLLECTION 0x60000000
|
|
#define PAGE_NUMBER_ROOT 0x90000000
|
|
|
|
|
|
/* There will be one such structure create for each conversation ontop of which
|
|
* there is an OSD session
|
|
*/
|
|
typedef struct _scsi_osd_conv_info_t {
|
|
wmem_tree_t *luns;
|
|
} scsi_osd_conv_info_t;
|
|
|
|
/* there will be one such structure created for each lun for each conversation
|
|
* that is handled by the OSD dissector
|
|
*/
|
|
struct _scsi_osd_lun_info_t {
|
|
wmem_tree_t *partitions;
|
|
};
|
|
|
|
typedef void (*scsi_osd_dissector_t)(tvbuff_t *tvb, packet_info *pinfo,
|
|
proto_tree *tree, guint offset,
|
|
gboolean isreq, gboolean iscdb,
|
|
guint32 payload_len, scsi_task_data_t *cdata,
|
|
scsi_osd_conv_info_t *conv_info,
|
|
scsi_osd_lun_info_t *lun_info
|
|
);
|
|
|
|
/* One such structure is created per conversation/lun/partition to
|
|
* keep track of when partitions are created/used/destroyed
|
|
*/
|
|
typedef struct _partition_info_t {
|
|
int created_in;
|
|
int removed_in;
|
|
} partition_info_t;
|
|
|
|
|
|
/* This is a set of extra data specific to OSD that we need to attach to every
|
|
* task.
|
|
*/
|
|
typedef struct _scsi_osd_extra_data_t {
|
|
guint16 svcaction;
|
|
guint8 gsatype;
|
|
union {
|
|
struct { /* gsatype: attribute list */
|
|
guint32 get_list_length;
|
|
guint32 get_list_offset;
|
|
guint32 get_list_allocation_length;
|
|
guint32 retrieved_list_offset;
|
|
guint32 set_list_length;
|
|
guint32 set_list_offset;
|
|
} al;
|
|
} u;
|
|
guint32 continuation_length;
|
|
gboolean osd2;
|
|
} scsi_osd_extra_data_t;
|
|
|
|
static proto_item*
|
|
dissect_osd_user_object_id(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* user object id */
|
|
proto_item *item;
|
|
item = proto_tree_add_item(tree, hf_scsi_osd_user_object_id, tvb, offset, 8, ENC_NA);
|
|
return item;
|
|
}
|
|
|
|
|
|
/*dissects an attribute that is defined as a pair of hf_index, length*/
|
|
static void
|
|
generic_attribute_dissector(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
|
|
scsi_osd_lun_info_t *lun_info _U_, const attribute_page_numbers_t *att)
|
|
{
|
|
proto_tree_add_item(tree, *att->hf_index, tvb, 0, att->expected_length, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
static proto_item *
|
|
dissect_osd_partition_id(packet_info *pinfo, tvbuff_t *tvb, int offset,
|
|
proto_tree *tree, int hf_index,
|
|
scsi_osd_lun_info_t *lun_info, gboolean is_created,
|
|
gboolean is_removed);
|
|
|
|
static void
|
|
partition_id_attribute_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
scsi_osd_lun_info_t *lun_info, const attribute_page_numbers_t *att)
|
|
{
|
|
dissect_osd_partition_id(pinfo, tvb, 0, tree, *att->hf_index, lun_info, FALSE, FALSE);
|
|
}
|
|
|
|
static const attribute_page_numbers_t user_object_info_attributes[] = {
|
|
{0x82, "User object logical length", generic_attribute_dissector, &hf_scsi_osd_attrval_user_object_logical_length, 8},
|
|
{0, NULL, NULL, NULL, 0}
|
|
};
|
|
|
|
static const attribute_page_numbers_t current_command_attributes[] = {
|
|
{0x02, "Object Type", generic_attribute_dissector, &hf_scsi_osd_attrval_object_type, 1},
|
|
{0x03, "Partition ID", partition_id_attribute_dissector, &hf_scsi_osd_attrval_partition_id, 8},
|
|
{0x04, "Collection Object ID or User Object ID", generic_attribute_dissector, &hf_scsi_osd_attrval_object_id, 8},
|
|
{0, NULL, NULL, NULL, 0}
|
|
};
|
|
|
|
typedef struct _attribute_pages_t {
|
|
guint32 page;
|
|
const attribute_page_numbers_t *attributes;
|
|
} attribute_pages_t;
|
|
|
|
static const attribute_pages_t attribute_pages[] = {
|
|
{PAGE_NUMBER_OBJECT+1, user_object_info_attributes},
|
|
{0xFFFFFFFE, current_command_attributes},
|
|
{0, NULL}
|
|
};
|
|
|
|
static const value_string attributes_page_vals[] = {
|
|
{PAGE_NUMBER_OBJECT+0, "User Object Directory"},
|
|
{PAGE_NUMBER_OBJECT+1, "User Object Information"},
|
|
{PAGE_NUMBER_OBJECT+2, "User Object Quotas"},
|
|
{PAGE_NUMBER_OBJECT+3, "User Object Timestamps"},
|
|
{PAGE_NUMBER_OBJECT+4, "User Object Collections"},
|
|
{PAGE_NUMBER_OBJECT+5, "User Object Policy/Security"},
|
|
{PAGE_NUMBER_PARTITION, "Partition Directory"},
|
|
{PAGE_NUMBER_PARTITION+1, "Partition Information"},
|
|
{PAGE_NUMBER_PARTITION+2, "Partition Quotas"},
|
|
{PAGE_NUMBER_PARTITION+3, "Partition Timestamps"},
|
|
{PAGE_NUMBER_PARTITION+5, "Partition Policy/Security"},
|
|
{PAGE_NUMBER_COLLECTION, "Collection Directory"},
|
|
{PAGE_NUMBER_COLLECTION+1, "Collection Information"},
|
|
{PAGE_NUMBER_COLLECTION+2, "Collection Quotas"},
|
|
{PAGE_NUMBER_COLLECTION+4, "Collection Command Tracking"},
|
|
{PAGE_NUMBER_COLLECTION+5, "Collection Policy/Security"},
|
|
{PAGE_NUMBER_ROOT, "Root Directory"},
|
|
{PAGE_NUMBER_ROOT+1, "Root Information"},
|
|
{PAGE_NUMBER_ROOT+2, "Root Quotas"},
|
|
{PAGE_NUMBER_ROOT+3, "Root Timestamps"},
|
|
{PAGE_NUMBER_ROOT+5, "Root Policy/Security"},
|
|
{0xFFFFFFFE, "Current Command"},
|
|
{0xFFFFFFFF, "All attribute pages"},
|
|
{0, NULL}
|
|
};
|
|
value_string_ext attributes_page_vals_ext = VALUE_STRING_EXT_INIT(attributes_page_vals);
|
|
|
|
static const value_string attributes_list_type_vals[] = {
|
|
{0x01, "Retrieve attributes for this OSD object"},
|
|
{0x09, "Retrieve/Set attributes for this OSD object"},
|
|
{0x0f, "Retrieve attributes for a CREATE command"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static const value_string scsi_osd2_isolation_val[] = {
|
|
{0x00, "Default"},
|
|
{0x01, "None"},
|
|
{0x02, "Strict"},
|
|
{0x04, "Range"},
|
|
{0x05, "Functional"},
|
|
{0x07, "Vendor specific"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static const value_string scsi_osd2_object_descriptor_format_val[] = {
|
|
{0x01, "Partition ID"},
|
|
{0x02, "Partition ID followed by attribute parameters"},
|
|
{0x11, "Collection ID"},
|
|
{0x12, "Collection ID followed by attribute parameters"},
|
|
{0x21, "User Object ID"},
|
|
{0x22, "User Object ID followed by attribute parameters"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static const value_string scsi_osd2_remove_scope[] = {
|
|
{0x00, "Fail if there are collections or user objects in the partition"},
|
|
{0x01, "Remove collections and user objects in the partition"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static const value_string scsi_osd2_cdb_continuation_format_val[] = {
|
|
{0x01, "OSD2"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static const value_string scsi_osd2_cdb_continuation_descriptor_type_val[] = {
|
|
{0x0000, "No more continuation descriptors"},
|
|
{0x0001, "Scatter/gather list"},
|
|
{0x0002, "Query list"},
|
|
{0x0100, "User object"},
|
|
{0x0101, "Copy user object source"},
|
|
{0xFFEE, "Extension capabilities"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static const value_string scsi_osd2_query_type_vals[] = {
|
|
{0x00, "Match any query criteria"},
|
|
{0x01, "Match all query criteria"},
|
|
{0, NULL}
|
|
};
|
|
|
|
/* OSD2/3 helper functions */
|
|
|
|
static void
|
|
dissect_osd2_isolation(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* isolation */
|
|
proto_tree_add_item(tree, hf_scsi_osd2_isolation, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
static void
|
|
dissect_osd2_list_attr(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* list_attr */
|
|
proto_tree_add_item(tree, hf_scsi_osd2_list_attr, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
|
|
/* used by dissect_osd_attributes_list, dissect_osd2_attribute_list_entry
|
|
and dissect_scsi_descriptor_snsinfo from packet-scsi.c*/
|
|
const attribute_page_numbers_t *
|
|
osd_lookup_attribute(guint32 page, guint32 number)
|
|
{
|
|
const attribute_pages_t *ap;
|
|
const attribute_page_numbers_t *apn;
|
|
|
|
/* find the proper attributes page */
|
|
apn = NULL;
|
|
for (ap=attribute_pages;ap->attributes;ap++) {
|
|
if (ap->page == page) {
|
|
apn = ap->attributes;
|
|
break;
|
|
}
|
|
}
|
|
if (!apn) return NULL;
|
|
|
|
/* find the specific attribute */
|
|
for (;apn->name;apn++) {
|
|
if (apn->number == number) {
|
|
break;
|
|
}
|
|
}
|
|
if (!apn->name) return NULL;
|
|
|
|
/* found it */
|
|
return apn;
|
|
}
|
|
|
|
/* OSD-1: 7.1.3.3, OSD2 7.1.4.3 list entry format */
|
|
static guint32
|
|
dissect_osd_attribute_list_entry(packet_info *pinfo, tvbuff_t *tvb,
|
|
proto_tree *tree, proto_item *item,
|
|
guint32 offset, scsi_osd_lun_info_t *lun_info,
|
|
gboolean osd2)
|
|
{
|
|
guint16 attribute_length;
|
|
guint32 page, number;
|
|
const attribute_page_numbers_t *apn;
|
|
|
|
/* attributes page */
|
|
page = tvb_get_ntohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_scsi_osd_attributes_page, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* attribute number */
|
|
number = tvb_get_ntohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_scsi_osd_attribute_number, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
if (osd2) {
|
|
/*6 reserved bytes*/
|
|
offset += 6;
|
|
}
|
|
|
|
/* attribute length */
|
|
attribute_length = tvb_get_ntohs(tvb, offset);
|
|
proto_tree_add_item(tree, hf_scsi_osd_attribute_length, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
proto_item_append_text(item, " 0x%08x (%s)", page, val_to_str_ext_const(page, &attributes_page_vals_ext, "Unknown"));
|
|
proto_item_append_text(item, " 0x%08x", number);
|
|
apn= osd_lookup_attribute(page, number);
|
|
|
|
if (!apn) {
|
|
expert_add_info(pinfo, item, &ei_osd_attr_unknown);
|
|
proto_item_append_text(item, " (Unknown)");
|
|
} else {
|
|
proto_item_append_text(item, " (%s)", apn->name);
|
|
|
|
/* attribute value */
|
|
if (attribute_length) {
|
|
if (attribute_length != apn->expected_length) {
|
|
proto_tree_add_expert_format(tree, pinfo, &ei_osd_attr_length_invalid,
|
|
tvb, 0, attribute_length, "%s", apn->name);
|
|
} else {
|
|
tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, attribute_length);
|
|
apn->dissector(next_tvb, pinfo, tree, lun_info, apn);
|
|
}
|
|
}
|
|
}
|
|
|
|
offset += attribute_length;
|
|
if (osd2 && (attribute_length&7)) {
|
|
/* 8-bit padding */
|
|
offset += 8-(attribute_length&7);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
/* OSD1: 7.1.3.1
|
|
OSD2: 7.1.4.1*/
|
|
static void
|
|
dissect_osd_attributes_list(packet_info *pinfo, tvbuff_t *tvb, int offset,
|
|
proto_tree *tree, scsi_osd_lun_info_t *lun_info,
|
|
gboolean osd2)
|
|
{
|
|
guint8 type;
|
|
guint32 length;
|
|
guint32 page, number;
|
|
int start_offset = offset;
|
|
proto_item *item, *list_type_item;
|
|
const attribute_page_numbers_t *apn;
|
|
|
|
/* list type */
|
|
type = tvb_get_guint8(tvb, offset)&0x0f;
|
|
list_type_item = proto_tree_add_item(tree, hf_scsi_osd_attributes_list_type, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* OSD-1: a reserved byte */
|
|
/* OSD-2: 3 reserved bytes */
|
|
offset += (osd2?3:1);
|
|
|
|
/* OSD-1: length (16 bit)
|
|
OSD-2: length (32 bit) */
|
|
if (osd2) {
|
|
length = tvb_get_ntohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_scsi_osd2_attributes_list_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
} else {
|
|
length = tvb_get_ntohs(tvb, offset);
|
|
proto_tree_add_item(tree, hf_scsi_osd_attributes_list_length, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
}
|
|
|
|
/* if type is 1 length will be zero and we have to cycle over
|
|
* all remaining bytes. 7.1.3.1
|
|
*/
|
|
if (!osd2 && type == 1) {
|
|
length = tvb_reported_length_remaining(tvb, offset);
|
|
}
|
|
|
|
length += (osd2?8:4);
|
|
|
|
while ( (guint32)(offset-start_offset)<length ) {
|
|
proto_item *ti;
|
|
proto_tree *tt;
|
|
guint32 attribute_entry_length;
|
|
|
|
switch (type) {
|
|
case 0x01:
|
|
attribute_entry_length = 8;
|
|
break;
|
|
case 0x0f:
|
|
attribute_entry_length = 18+tvb_get_ntohs(tvb, offset+16);
|
|
break;
|
|
case 0x09:
|
|
if (osd2) {
|
|
attribute_entry_length = 16+tvb_get_ntohs(tvb, offset+14);
|
|
} else {
|
|
attribute_entry_length = 10+tvb_get_ntohs(tvb, offset+8);
|
|
}
|
|
break;
|
|
default:
|
|
expert_add_info(pinfo, list_type_item, &ei_osd_unknown_attributes_list_type);
|
|
return;
|
|
}
|
|
|
|
if ((guint32)(offset-start_offset)+attribute_entry_length>length) break;
|
|
tt = proto_tree_add_subtree(tree, tvb, offset, attribute_entry_length, ett_osd_attribute, &ti, "Attribute:");
|
|
|
|
switch (type) {
|
|
case 0x01: /* retrieving attributes 7.1.3.2 */
|
|
/* attributes page */
|
|
page = tvb_get_ntohl(tvb, offset);
|
|
proto_tree_add_item(tt, hf_scsi_osd_attributes_page, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* attribute number */
|
|
number = tvb_get_ntohl(tvb, offset);
|
|
item = proto_tree_add_item(tt, hf_scsi_osd_attribute_number, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
proto_item_append_text(ti, " 0x%08x (%s)", page, val_to_str_ext_const(page, &attributes_page_vals_ext, "Unknown"));
|
|
proto_item_append_text(ti, " 0x%08x", number);
|
|
|
|
/* find the proper attributes page */
|
|
apn = osd_lookup_attribute(page, number);
|
|
if (!apn) {
|
|
proto_item_append_text(ti, " (Unknown)");
|
|
proto_item_append_text(item, " (Unknown)");
|
|
} else {
|
|
proto_item_append_text(ti, " (%s)", apn->name);
|
|
proto_item_append_text(item, " (%s)", apn->name);
|
|
}
|
|
break;
|
|
case 0x0f: /* create attributes 7.1.3.4 */
|
|
/* user object id */
|
|
dissect_osd_user_object_id(tvb, offset, tt);
|
|
offset += 8;
|
|
/* fallthrough to the next case */
|
|
case 0x09: /* retrieved/set attributes OSD-1: 7.1.3.3 OSD-2: 7.1.4.3*/
|
|
offset = dissect_osd_attribute_list_entry(pinfo, tvb, tt, ti, offset, lun_info, osd2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* OSD2 5.2.4 */
|
|
static void
|
|
dissect_osd_option(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
|
|
{
|
|
proto_tree *tree;
|
|
proto_item *it;
|
|
guint8 option;
|
|
|
|
option = tvb_get_guint8(tvb, offset);
|
|
|
|
it = proto_tree_add_item(parent_tree, hf_scsi_osd_option, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
tree = proto_item_add_subtree(it, ett_osd_option);
|
|
|
|
proto_tree_add_item(tree, hf_scsi_osd_option_dpo, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
if (option&0x10) {
|
|
proto_item_append_text(tree, " DPO");
|
|
}
|
|
|
|
proto_tree_add_item(tree, hf_scsi_osd_option_fua, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
if (option&0x08) {
|
|
proto_item_append_text(tree, " FUA");
|
|
}
|
|
}
|
|
|
|
|
|
static const value_string scsi_osd_getsetattrib_vals[] = {
|
|
{1, "Set one attribute using CDB fields (OSD-2)"},
|
|
{2, "Get an attributes page and set an attribute value"},
|
|
{3, "Get and set attributes using a list"},
|
|
{0, NULL},
|
|
};
|
|
|
|
/* OSD2 5.2.2.1 */
|
|
static void
|
|
dissect_osd_getsetattrib(tvbuff_t *tvb, int offset, proto_tree *tree, scsi_task_data_t *cdata)
|
|
{
|
|
if (cdata && cdata->itlq && cdata->itlq->extra_data) {
|
|
scsi_osd_extra_data_t *extra_data = (scsi_osd_extra_data_t *)cdata->itlq->extra_data;
|
|
extra_data->gsatype = (tvb_get_guint8(tvb, offset)>>4)&0x03;
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_getsetattrib, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
static const value_string scsi_osd_timestamps_control_vals[] = {
|
|
{0x00, "Timestamps shall be updated"},
|
|
{0x7f, "Timestamps shall not be updated"},
|
|
{0, NULL},
|
|
};
|
|
|
|
/* OSD2 5.2.8 */
|
|
static void
|
|
dissect_osd_timestamps_control(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
proto_tree_add_item(tree, hf_scsi_osd_timestamps_control, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_formatted_capacity(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
proto_tree_add_item(tree, hf_scsi_osd_formatted_capacity, tvb, offset, 8, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
static void
|
|
dissect_osd_offset(packet_info *pinfo, tvbuff_t *tvb, int offset,
|
|
proto_tree *tree, int field, guint32 *raw_value_ptr,
|
|
gboolean osd2)
|
|
{
|
|
/* dissects an OSD offset value, add proto item and updates *raw_value_ptr */
|
|
guint32 value = *raw_value_ptr;
|
|
|
|
if (value != 0xFFFFFFFF) {
|
|
if (!osd2) {
|
|
/*OSD-1: the exponent is an unsigned value (4.12.5)*/
|
|
value = (value & 0x0fffffff) << ((value>>28) & 0x0f);
|
|
value <<= 8;
|
|
} else {
|
|
/*OSD-2: the exponent is a signed value (4.15.5)*/
|
|
int exponent = (value>>28);
|
|
guint32 mantissa = (value&0x0FFFFFFF);
|
|
|
|
if (exponent&0x8) {
|
|
exponent = -(((~exponent)&7)+1);
|
|
if (exponent <=- 6 && mantissa != 0xFFFFFFF) {
|
|
proto_item *item;
|
|
item = proto_tree_add_item(tree, field, tvb, offset, 4, value);
|
|
expert_add_info(pinfo, item, &ei_osd2_invalid_offset);
|
|
*raw_value_ptr = 0xFFFFFFFF;
|
|
return;
|
|
}
|
|
}
|
|
value = mantissa << (exponent+8);
|
|
}
|
|
}
|
|
proto_tree_add_uint(tree, field, tvb, offset, 4, value);
|
|
*raw_value_ptr = value;
|
|
}
|
|
|
|
static int
|
|
dissect_osd_attribute_parameters(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *parent_tree, scsi_task_data_t *cdata)
|
|
{
|
|
guint8 gsatype = 0;
|
|
proto_tree *tree;
|
|
scsi_osd_extra_data_t *extra_data = NULL;
|
|
gboolean osd2;
|
|
|
|
tree = proto_tree_add_subtree(parent_tree, tvb, offset, 28,
|
|
ett_osd_attribute_parameters, NULL, "Attribute Parameters");
|
|
|
|
if (cdata && cdata->itlq && cdata->itlq->extra_data) {
|
|
extra_data = (scsi_osd_extra_data_t *)cdata->itlq->extra_data;
|
|
gsatype = extra_data->gsatype;
|
|
osd2 = extra_data->osd2;
|
|
} else {
|
|
return offset;
|
|
}
|
|
|
|
switch (gsatype) {
|
|
case 1: /* OSD-2 5.2.6.2 Set one attribute using CDB fields*/
|
|
if (osd2) {
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_attributes_page, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_attribute_number, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_attribute_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd2_set_attribute_value, tvb, offset, 18, ENC_NA);
|
|
offset += 18;
|
|
}
|
|
break;
|
|
case 2: /* 5.2.2.2 attribute page */
|
|
proto_tree_add_item(tree, hf_scsi_osd_get_attributes_page, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd_get_attributes_allocation_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd_retrieved_attributes_offset, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_attributes_page, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_attribute_number, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_attribute_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_attributes_offset, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
break;
|
|
case 3: /* 5.2.2.3 attribute list */
|
|
proto_tree_add_item(tree, hf_scsi_osd_get_attributes_list_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
extra_data->u.al.get_list_length = tvb_get_ntohl(tvb, offset);
|
|
offset += 4;
|
|
|
|
/* 4.12.5 */
|
|
extra_data->u.al.get_list_offset = tvb_get_ntohl(tvb, offset);
|
|
dissect_osd_offset(pinfo, tvb, offset, tree, hf_scsi_osd_get_attributes_list_offset,
|
|
&extra_data->u.al.get_list_offset, osd2);
|
|
if (extra_data->u.al.get_list_offset == 0xFFFFFFFF) {
|
|
extra_data->u.al.get_list_length = 0;
|
|
}
|
|
offset += 4;
|
|
|
|
proto_tree_add_item(tree, hf_scsi_osd_get_attributes_allocation_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
extra_data->u.al.get_list_allocation_length = tvb_get_ntohl(tvb, offset);
|
|
offset += 4;
|
|
|
|
/* 4.12.5 */
|
|
extra_data->u.al.retrieved_list_offset = tvb_get_ntohl(tvb, offset);
|
|
dissect_osd_offset(pinfo, tvb, offset, tree, hf_scsi_osd_retrieved_attributes_offset,
|
|
&extra_data->u.al.retrieved_list_offset, osd2);
|
|
if (extra_data->u.al.retrieved_list_offset == 0xFFFFFFFF) {
|
|
extra_data->u.al.get_list_allocation_length = 0;
|
|
}
|
|
offset += 4;
|
|
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_attributes_list_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
extra_data->u.al.set_list_length = tvb_get_ntohl(tvb, offset);
|
|
offset += 4;
|
|
|
|
extra_data->u.al.set_list_offset = tvb_get_ntohl(tvb, offset);
|
|
dissect_osd_offset(pinfo, tvb, offset, tree, hf_scsi_osd_set_attributes_list_offset,
|
|
&extra_data->u.al.set_list_offset, osd2);
|
|
if (extra_data->u.al.set_list_offset == 0xFFFFFFFF) {
|
|
extra_data->u.al.set_list_length = 0;
|
|
}
|
|
offset += 4;
|
|
|
|
/* 4 reserved bytes */
|
|
offset += 4;
|
|
|
|
break;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_attribute_data_out(packet_info *pinfo, tvbuff_t *tvb, int offset _U_,
|
|
proto_tree *tree, scsi_task_data_t *cdata,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
guint8 gsatype = 0;
|
|
proto_tree *subtree;
|
|
scsi_osd_extra_data_t *extra_data = NULL;
|
|
|
|
if (cdata && cdata->itlq && cdata->itlq->extra_data) {
|
|
extra_data = (scsi_osd_extra_data_t *)cdata->itlq->extra_data;
|
|
gsatype = extra_data->gsatype;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
switch (gsatype) {
|
|
case 2: /* 5.2.2.2 attribute page */
|
|
/*qqq*/
|
|
break;
|
|
case 3: /* 5.2.2.3 attribute list */
|
|
if (extra_data->u.al.get_list_length) {
|
|
subtree = proto_tree_add_subtree(tree, tvb, extra_data->u.al.get_list_offset, extra_data->u.al.get_list_length,
|
|
ett_osd_get_attributes, NULL, "Get Attributes Segment");
|
|
dissect_osd_attributes_list(pinfo, tvb, extra_data->u.al.get_list_offset, subtree, lun_info, extra_data->osd2);
|
|
}
|
|
if (extra_data->u.al.set_list_length) {
|
|
subtree = proto_tree_add_subtree(tree, tvb, extra_data->u.al.set_list_offset, extra_data->u.al.set_list_length,
|
|
ett_osd_get_attributes, NULL, "Set Attributes Segment");
|
|
dissect_osd_attributes_list(pinfo, tvb, extra_data->u.al.set_list_offset, subtree, lun_info, extra_data->osd2);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_attribute_data_in(packet_info *pinfo, tvbuff_t *tvb, int offset _U_, proto_tree *tree, scsi_task_data_t *cdata, scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
guint8 gsatype = 0;
|
|
scsi_osd_extra_data_t *extra_data = NULL;
|
|
|
|
if (cdata && cdata->itlq && cdata->itlq->extra_data) {
|
|
extra_data = (scsi_osd_extra_data_t *)cdata->itlq->extra_data;
|
|
gsatype = extra_data->gsatype;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
switch (gsatype) {
|
|
case 2: /* 5.2.2.2 attribute page */
|
|
/*qqq*/
|
|
break;
|
|
case 3: /* 5.2.2.3 attribute list */
|
|
if (extra_data->u.al.get_list_allocation_length) {
|
|
dissect_osd_attributes_list(pinfo, tvb, extra_data->u.al.retrieved_list_offset, tree, lun_info, extra_data->osd2);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
dissect_osd2_cdb_continuation_length(packet_info *pinfo, tvbuff_t *tvb,
|
|
guint32 offset, proto_tree *tree,
|
|
scsi_task_data_t *cdata)
|
|
{
|
|
scsi_osd_extra_data_t *extra_data;
|
|
guint32 continuation_length;
|
|
proto_item *item;
|
|
|
|
continuation_length = tvb_get_ntohl(tvb, offset);
|
|
item = proto_tree_add_item(tree, hf_scsi_osd2_cdb_continuation_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
if (cdata && cdata->itlq && cdata->itlq->extra_data) {
|
|
extra_data = (scsi_osd_extra_data_t *)cdata->itlq->extra_data;
|
|
extra_data->continuation_length = continuation_length;
|
|
}
|
|
if (continuation_length>0 && continuation_length<40) {
|
|
expert_add_info(pinfo, item, &ei_osd2_cdb_continuation_length_invalid);
|
|
}
|
|
}
|
|
|
|
static void dissect_osd2_query_list_descriptor(packet_info *pinfo, tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint32 length) {
|
|
guint32 end = offset+length;
|
|
|
|
/* query type */
|
|
proto_tree_add_item(tree, hf_scsi_osd2_query_type, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/*query criteria entry*/
|
|
while (offset<end) {
|
|
guint32 page, number;
|
|
guint32 min_value_length, max_value_length;
|
|
guint32 min_value_offset, max_value_offset;
|
|
proto_item *item;
|
|
const attribute_page_numbers_t *apn;
|
|
|
|
/* 2 reserved bytes */
|
|
offset += 2;
|
|
|
|
/* query entry length */
|
|
proto_tree_add_item(tree, hf_scsi_osd2_query_entry_length, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
/* query attributes page */
|
|
page = tvb_get_ntohl(tvb, offset);
|
|
proto_tree_add_item(tree, hf_scsi_osd2_query_attributes_page, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* query attributes number */
|
|
number = tvb_get_ntohl(tvb, offset);
|
|
item = proto_tree_add_item(tree, hf_scsi_osd2_query_attribute_number, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
apn = osd_lookup_attribute(page, number);
|
|
|
|
if (!apn) {
|
|
expert_add_info(pinfo, item, &ei_osd_attr_unknown);
|
|
proto_item_append_text(item, " (Unknown)");
|
|
} else {
|
|
proto_item_append_text(item, " (%s)", apn->name);
|
|
}
|
|
|
|
/* query minimum attribute value length */
|
|
proto_tree_add_item(tree, hf_scsi_osd2_query_minimum_attribute_value_length, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
min_value_length = tvb_get_ntohs(tvb, offset);
|
|
offset += 2;
|
|
|
|
/* query minimum attribute value */
|
|
/* if (apn && min_value_length) {
|
|
call_apn_dissector(tvb, pinfo, tree, lun_info, apn, offset, min_value_length);
|
|
} */
|
|
max_value_offset = offset;
|
|
offset += min_value_length;
|
|
|
|
/* query maximum attribute value length */
|
|
item = proto_tree_add_item(tree, hf_scsi_osd2_query_maximum_attribute_value_length, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
max_value_length = tvb_get_ntohs(tvb, offset);
|
|
offset += 2;
|
|
|
|
/* xxx query maximum attribute value */
|
|
/* if (apn && max_value_length) {
|
|
call_apn_dissector(tvb, pinfo, tree, lun_info, apn, offset, max_value_length);
|
|
} */
|
|
min_value_offset = offset;
|
|
offset += max_value_length;
|
|
|
|
/* test if min and max values are equal */
|
|
if (max_value_length == min_value_length) {
|
|
unsigned int i;
|
|
for (i=0; i<max_value_length; i++) {
|
|
if (tvb_get_guint8(tvb, max_value_offset+i) != tvb_get_guint8(tvb, min_value_offset+i)) return;
|
|
}
|
|
expert_add_info(pinfo, item, &ei_osd2_query_values_equal);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
dissect_osd2_cdb_continuation(packet_info *pinfo, tvbuff_t *tvb, guint32 offset,
|
|
proto_tree *tree, scsi_task_data_t *cdata)
|
|
{
|
|
scsi_osd_extra_data_t *extra_data = NULL;
|
|
proto_item *item;
|
|
guint8 format;
|
|
guint16 sa;
|
|
if (cdata && cdata->itlq && cdata->itlq->extra_data) {
|
|
extra_data = (scsi_osd_extra_data_t *)cdata->itlq->extra_data;
|
|
}
|
|
if (!extra_data || extra_data->continuation_length<40) return;
|
|
|
|
/* cdb continuation format */
|
|
item = proto_tree_add_item(tree, hf_scsi_osd2_cdb_continuation_format, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
format = tvb_get_guint8(tvb, offset);
|
|
if (format != 0x01) {
|
|
expert_add_info(pinfo, item, &ei_osd2_cdb_continuation_format_unknown);
|
|
return;
|
|
}
|
|
offset += 1;
|
|
|
|
/* 1 reserved byte */
|
|
offset += 1;
|
|
|
|
/* continued service action */
|
|
item = proto_tree_add_item(tree, hf_scsi_osd2_continued_service_action, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
sa = tvb_get_ntohs(tvb, offset);
|
|
if (sa != extra_data->svcaction) {
|
|
expert_add_info(pinfo, item, &ei_osd2_continued_service_action_mismatch);
|
|
}
|
|
offset += 2;
|
|
|
|
/*4 reserved bytes and continuation integrity check value (32 bytes, not dissected)*/
|
|
offset += 36;
|
|
|
|
|
|
/* CDB continuation descriptors */
|
|
while (offset<extra_data->continuation_length) {
|
|
guint16 type;
|
|
guint32 length, padlen;
|
|
proto_item *item_type, *item_length;
|
|
|
|
/* descriptor type */
|
|
item_type= proto_tree_add_item(tree, hf_scsi_osd2_cdb_continuation_descriptor_type, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
type = tvb_get_ntohs(tvb, offset);
|
|
offset += 2;
|
|
|
|
/* 1 reserved byte*/
|
|
offset += 1;
|
|
|
|
/* descriptor pad length */
|
|
proto_tree_add_item(tree, hf_scsi_osd2_cdb_continuation_descriptor_pad_length, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
padlen = tvb_get_guint8(tvb, offset)&7;
|
|
offset += 1;
|
|
|
|
/* descriptor length */
|
|
item_length = proto_tree_add_item(tree, hf_scsi_osd2_cdb_continuation_descriptor_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
length = tvb_get_ntohl(tvb, offset);
|
|
offset += 4;
|
|
|
|
switch (type) {
|
|
case 0x0000: break;
|
|
case 0x0001: break;
|
|
case 0x0002: dissect_osd2_query_list_descriptor(pinfo, tvb, offset, tree, length);
|
|
case 0x0100: break;
|
|
case 0x0101: break;
|
|
case 0xFFEE: break;
|
|
default: expert_add_info(pinfo, item_type, &ei_osd2_cdb_continuation_descriptor_type_unknown);
|
|
}
|
|
|
|
if ((length+padlen)%8) {
|
|
expert_add_info(pinfo, item_length, &ei_osd2_cdb_continuation_descriptor_length_invalid);
|
|
return;
|
|
}
|
|
/* check for overflow */
|
|
if (offset + length + padlen > offset) {
|
|
offset += length+padlen;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static const value_string scsi_osd_capability_format_vals[] = {
|
|
{0x00, "No Capability"},
|
|
{0x01, "SCSI OSD Capabilities"},
|
|
{0, NULL},
|
|
};
|
|
static const value_string scsi_osd_object_type_vals[] = {
|
|
{0x01, "ROOT"},
|
|
{0x02, "PARTITION"},
|
|
{0x40, "COLLECTION"},
|
|
{0x80, "USER"},
|
|
{0, NULL},
|
|
};
|
|
static const value_string scsi_osd_object_descriptor_type_vals[] = {
|
|
{0, "NONE: the object descriptor field shall be ignored"},
|
|
{1, "U/C: a single collection or user object"},
|
|
{2, "PAR: a single partition, including partition zero"},
|
|
{0, NULL},
|
|
};
|
|
|
|
|
|
/* OSD 4.9.2.2.1 */
|
|
static void
|
|
dissect_osd_permissions(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
|
|
{
|
|
proto_tree *tree = NULL;
|
|
proto_item *it = NULL;
|
|
guint16 permissions;
|
|
|
|
permissions = tvb_get_ntohs(tvb, offset);
|
|
|
|
if (parent_tree) {
|
|
it = proto_tree_add_item(parent_tree, hf_scsi_osd_permissions, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
tree = proto_item_add_subtree(it, ett_osd_permission_bitmask);
|
|
}
|
|
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_read, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x8000) {
|
|
proto_item_append_text(tree, " READ");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_write, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x4000) {
|
|
proto_item_append_text(tree, " WRITE");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_get_attr, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x2000) {
|
|
proto_item_append_text(tree, " GET_ATTR");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_set_attr, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x1000) {
|
|
proto_item_append_text(tree, " SET_ATTR");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_create, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x0800) {
|
|
proto_item_append_text(tree, " CREATE");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_remove, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x0400) {
|
|
proto_item_append_text(tree, " REMOVE");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_obj_mgmt, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x0200) {
|
|
proto_item_append_text(tree, " OBJ_MGMT");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_append, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x0100) {
|
|
proto_item_append_text(tree, " APPEND");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_dev_mgmt, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x0080) {
|
|
proto_item_append_text(tree, " DEV_MGMT");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_global, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x0040) {
|
|
proto_item_append_text(tree, " GLOBAL");
|
|
}
|
|
proto_tree_add_item(tree, hf_scsi_osd_permissions_pol_sec, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
if (permissions&0x0020) {
|
|
proto_item_append_text(tree, " POL/SEC");
|
|
}
|
|
}
|
|
|
|
/* OSD-1 4.9.2.2
|
|
OSD-2 4.11.2.2 */
|
|
static void
|
|
dissect_osd_capability(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
|
|
{
|
|
proto_tree *tree;
|
|
guint8 format;
|
|
|
|
tree = proto_tree_add_subtree(parent_tree, tvb, offset, 80,
|
|
ett_osd_capability, NULL, "Capability");
|
|
|
|
/* capability format */
|
|
proto_tree_add_item(tree, hf_scsi_osd_capability_format, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
format = tvb_get_guint8(tvb, offset)&0x0F;
|
|
offset += 1;
|
|
|
|
if (format != 1) return;
|
|
|
|
/* key version and icva */
|
|
proto_tree_add_item(tree, hf_scsi_osd_key_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
proto_tree_add_item(tree, hf_scsi_osd_icva, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* security method */
|
|
proto_tree_add_item(tree, hf_scsi_osd_security_method, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* a reserved byte */
|
|
offset += 1;
|
|
|
|
/* capability expiration time */
|
|
proto_tree_add_item(tree, hf_scsi_osd_capability_expiration_time, tvb, offset, 6, ENC_NA);
|
|
offset += 6;
|
|
|
|
/* audit */
|
|
proto_tree_add_item(tree, hf_scsi_osd_audit, tvb, offset, 20, ENC_NA);
|
|
offset += 20;
|
|
|
|
/* capability discriminator */
|
|
proto_tree_add_item(tree, hf_scsi_osd_capability_discriminator, tvb, offset, 12, ENC_NA);
|
|
offset += 12;
|
|
|
|
/* object created time */
|
|
proto_tree_add_item(tree, hf_scsi_osd_object_created_time, tvb, offset, 6, ENC_NA);
|
|
offset += 6;
|
|
|
|
/* object type */
|
|
proto_tree_add_item(tree, hf_scsi_osd_object_type, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* permission bitmask */
|
|
dissect_osd_permissions(tvb, offset, tree);
|
|
offset += 5;
|
|
|
|
/* a reserved byte */
|
|
offset += 1;
|
|
|
|
/* object descriptor type */
|
|
proto_tree_add_item(tree, hf_scsi_osd_object_descriptor_type, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* object descriptor */
|
|
proto_tree_add_item(tree, hf_scsi_osd_object_descriptor, tvb, offset, 24, ENC_NA);
|
|
/*offset += 24;*/
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/* 5.2.6 */
|
|
static int
|
|
dissect_osd_security_parameters(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
|
|
{
|
|
proto_tree *tree;
|
|
|
|
tree = proto_tree_add_subtree(parent_tree, tvb, offset, 40,
|
|
ett_osd_security_parameters, NULL, "Security Parameters");
|
|
|
|
/* request integrity check value */
|
|
proto_tree_add_item(tree, hf_scsi_osd_ricv, tvb, offset, 20, ENC_NA);
|
|
offset += 20;
|
|
|
|
/* request nonce */
|
|
proto_tree_add_item(tree, hf_scsi_osd_request_nonce, tvb, offset, 12, ENC_NA);
|
|
offset += 12;
|
|
|
|
/* data in integrity check value offset */
|
|
proto_tree_add_item(tree, hf_scsi_osd_diicvo, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
/* data out integrity check value offset */
|
|
proto_tree_add_item(tree, hf_scsi_osd_doicvo, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
dissect_osd_format_osd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info _U_)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 23 reserved bytes */
|
|
offset += 23;
|
|
|
|
/* formatted capacity */
|
|
dissect_osd_formatted_capacity(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 8 reserved bytes */
|
|
offset += 8;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for format osd */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for format osd */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static proto_item*
|
|
dissect_osd_partition_id(packet_info *pinfo, tvbuff_t *tvb, int offset,
|
|
proto_tree *tree, int hf_index,
|
|
scsi_osd_lun_info_t *lun_info, gboolean is_created,
|
|
gboolean is_removed)
|
|
{
|
|
proto_item *item = NULL;
|
|
guint32 partition_id[2];
|
|
|
|
/* partition id */
|
|
item = proto_tree_add_item(tree, hf_index, tvb, offset, 8, ENC_BIG_ENDIAN);
|
|
partition_id[0] = tvb_get_ntohl(tvb, offset);
|
|
partition_id[1] = tvb_get_ntohl(tvb, offset+4);
|
|
if (!partition_id[0] && !partition_id[1]) {
|
|
proto_item_append_text(item, " (ROOT partition)");
|
|
} else {
|
|
partition_info_t *part_info;
|
|
wmem_tree_key_t pikey[2];
|
|
proto_tree *partition_tree = NULL;
|
|
|
|
pikey[0].length = 2;
|
|
pikey[0].key = partition_id;
|
|
pikey[1].length = 0;
|
|
part_info = (partition_info_t *)wmem_tree_lookup32_array(lun_info->partitions, &pikey[0]);
|
|
if (!part_info) {
|
|
part_info = wmem_new(wmem_file_scope(), partition_info_t);
|
|
part_info->created_in = 0;
|
|
part_info->removed_in = 0;
|
|
|
|
pikey[0].length = 2;
|
|
pikey[0].key = partition_id;
|
|
pikey[1].length = 0;
|
|
wmem_tree_insert32_array(lun_info->partitions, &pikey[0], part_info);
|
|
}
|
|
if (is_created) {
|
|
part_info->created_in = pinfo->num;
|
|
}
|
|
if (is_removed) {
|
|
part_info->removed_in = pinfo->num;
|
|
}
|
|
if (item) {
|
|
partition_tree = proto_item_add_subtree(item, ett_osd_partition);
|
|
}
|
|
if (part_info->created_in) {
|
|
proto_item *tmp_item;
|
|
tmp_item = proto_tree_add_uint(partition_tree, hf_scsi_osd_partition_created_in, tvb, 0, 0, part_info->created_in);
|
|
PROTO_ITEM_SET_GENERATED(tmp_item);
|
|
}
|
|
if (part_info->removed_in) {
|
|
proto_item *tmp_item;
|
|
tmp_item = proto_tree_add_uint(partition_tree, hf_scsi_osd_partition_removed_in, tvb, 0, 0, part_info->removed_in);
|
|
PROTO_ITEM_SET_GENERATED(tmp_item);
|
|
}
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
dissect_osd_create_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
gboolean osd2 = ((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->svcaction&0x80;
|
|
((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->osd2 = osd2;
|
|
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
if (osd2) dissect_osd2_isolation(tvb, offset, tree);
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* requested partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_requested_partition_id, lun_info, TRUE, FALSE);
|
|
offset += 8;
|
|
|
|
/* 24 reserved bytes */
|
|
offset += 24;
|
|
|
|
if (osd2) {
|
|
dissect_osd2_cdb_continuation_length(pinfo, tvb, offset, tree, cdata);
|
|
} else {
|
|
/* 4 reserved bytes */
|
|
}
|
|
offset += 4;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += osd2?104:80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += osd2?52:40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* CDB continuation */
|
|
dissect_osd2_cdb_continuation(pinfo, tvb, offset, tree, cdata);
|
|
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for create partition */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for create partition */
|
|
}
|
|
|
|
}
|
|
|
|
static const value_string scsi_osd_sort_order_vals[] = {
|
|
{0x00, "Ascending numeric value"},
|
|
{0, NULL},
|
|
};
|
|
static int
|
|
dissect_osd_sortorder(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* sort order */
|
|
proto_tree_add_item(tree, hf_scsi_osd_sortorder, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_osd_list_identifier(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* list identifier */
|
|
proto_tree_add_item(tree, hf_scsi_osd_list_identifier, tvb, offset, 4, ENC_BIG_ENDIAN);
|
|
offset += 4;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
dissect_osd_allocation_length(tvbuff_t *tvb, int offset, proto_tree *tree, scsi_task_data_t *cdata)
|
|
{
|
|
/* allocation length */
|
|
proto_tree_add_item(tree, hf_scsi_osd_allocation_length, tvb, offset, 8, ENC_BIG_ENDIAN);
|
|
|
|
if (cdata) {
|
|
guint64 alloc_len = tvb_get_ntoh64(tvb, offset);
|
|
if (alloc_len>G_GINT64_CONSTANT(0xFFFFFFFF)) {
|
|
alloc_len = G_GINT64_CONSTANT(0xFFFFFFFF);
|
|
}
|
|
cdata->itlq->alloc_len = (guint32)alloc_len;
|
|
}
|
|
}
|
|
|
|
static int
|
|
dissect_osd_initial_object_id(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* initial object id */
|
|
proto_tree_add_item(tree, hf_scsi_osd_initial_object_id, tvb, offset, 8, ENC_NA);
|
|
offset += 8;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_osd_additional_length(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* additional length */
|
|
proto_tree_add_item(tree, hf_scsi_osd_additional_length, tvb, offset, 8, ENC_BIG_ENDIAN);
|
|
offset += 8;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_osd_continuation_object_id(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* continuation object id */
|
|
proto_tree_add_item(tree, hf_scsi_osd_continuation_object_id, tvb, offset, 8, ENC_NA);
|
|
offset += 8;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static const true_false_string list_lstchg_tfs = {
|
|
"List has CHANGED since the first List command",
|
|
"List has NOT changed since first command"
|
|
};
|
|
static const true_false_string list_root_tfs = {
|
|
"Objects are from root and are PARTITION IDs",
|
|
"Objects are from the partition and are USER OBJECTs"
|
|
};
|
|
static const true_false_string list_coltn_tfs = {
|
|
"Objects are from the partition and are COLLECTION IDs",
|
|
"Objects are from the collection and are USER OBJECTs"
|
|
};
|
|
|
|
static proto_item*
|
|
dissect_osd_collection_object_id(tvbuff_t *tvb, int offset, proto_tree *tree, const int hfindex)
|
|
{
|
|
/* collection object id */
|
|
proto_item *item;
|
|
item = proto_tree_add_item(tree, hfindex, tvb, offset, 8, ENC_NA);
|
|
return item;
|
|
}
|
|
|
|
static void
|
|
dissect_osd_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
guint svcaction = ((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->svcaction;
|
|
gboolean list_collection = (svcaction == 0x8817) || (svcaction == 0x8897);
|
|
gboolean osd2 = svcaction&0x80;
|
|
((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->osd2 = osd2;
|
|
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
|
|
if (isreq && iscdb) {
|
|
/*byte 10*/
|
|
if (osd2) dissect_osd2_isolation(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte / sort order */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
if (!list_collection) dissect_osd_sortorder(tvb, offset, tree);
|
|
if (osd2) dissect_osd2_list_attr(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
if (list_collection) {
|
|
/* collection id */
|
|
dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd_collection_object_id);
|
|
} else {
|
|
/* 8 reserved bytes */
|
|
}
|
|
offset += 8;
|
|
|
|
if (osd2) {
|
|
/* allocation length */
|
|
dissect_osd_allocation_length(tvb, offset, tree, cdata);
|
|
offset += 8;
|
|
|
|
/* initial object id */
|
|
dissect_osd_initial_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* list identifier */
|
|
dissect_osd_list_identifier(tvb, offset, tree);
|
|
offset += 4;
|
|
} else {
|
|
/* list identifier */
|
|
dissect_osd_list_identifier(tvb, offset, tree);
|
|
offset += 4;
|
|
|
|
/* allocation length */
|
|
dissect_osd_allocation_length(tvb, offset, tree, cdata);
|
|
offset += 8;
|
|
|
|
/* initial object id */
|
|
dissect_osd_initial_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
}
|
|
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += osd2?104:80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += osd2?52:40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for LIST or LIST COLLECTION */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
|
|
guint64 additional_length;
|
|
guint64 allocation_length;
|
|
guint64 remaining_length;
|
|
gboolean is_root_or_coltn;
|
|
guint8 format = 0;
|
|
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
allocation_length = cdata->itlq->alloc_len;
|
|
remaining_length = tvb_captured_length_remaining(tvb, offset);
|
|
if (remaining_length<allocation_length) allocation_length = remaining_length;
|
|
if (allocation_length<24) return;
|
|
|
|
/* dissection of the LIST or LIST COLLECTION DATA-IN */
|
|
/* additional length */
|
|
additional_length = tvb_get_ntoh64(tvb, offset);
|
|
if (allocation_length<additional_length) additional_length = allocation_length;
|
|
|
|
dissect_osd_additional_length(tvb, offset, tree);
|
|
|
|
offset += 8;
|
|
/* continuation object id */
|
|
dissect_osd_continuation_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
/* list identifier */
|
|
dissect_osd_list_identifier(tvb, offset, tree);
|
|
offset += 4;
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* OSD: LSTCHG and ROOT flags
|
|
OSD2: LSTCHG and OBJECT DESCRIPTOR FORMAT*/
|
|
proto_tree_add_item(tree, hf_scsi_osd_list_flags_lstchg, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
if (osd2) {
|
|
proto_item *item;
|
|
item = proto_tree_add_item(tree, hf_scsi_osd2_object_descriptor_format, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
format = tvb_get_guint8(tvb, offset)>>2;
|
|
if (format == 0x01 || format == 0x02) {
|
|
is_root_or_coltn = TRUE;
|
|
if (list_collection) format = 0;
|
|
} else if (format == 0x11 || format == 0x12) {
|
|
is_root_or_coltn = TRUE;
|
|
if (!list_collection) format = 0;
|
|
} else if (format == 0x21 || format == 0x22) {
|
|
is_root_or_coltn = FALSE;
|
|
} else format = 0;
|
|
if (!format) {
|
|
expert_add_info(pinfo, item, &ei_osd2_invalid_object_descriptor_format);
|
|
return;
|
|
}
|
|
} else {
|
|
if (list_collection) {
|
|
proto_tree_add_item(tree, hf_scsi_osd_list_collection_flags_coltn, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
} else {
|
|
proto_tree_add_item(tree, hf_scsi_osd_list_flags_root, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
is_root_or_coltn = tvb_get_guint8(tvb, offset)&0x01;
|
|
}
|
|
|
|
offset += 1;
|
|
|
|
while (additional_length > (offset-8)) {
|
|
proto_item *ti;
|
|
/* list of 8-byte IDs; the type of ID is given by is_root_or_coltn and list_collection*/
|
|
if (is_root_or_coltn) {
|
|
if (list_collection) {
|
|
ti = dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd_collection_object_id);
|
|
} else {
|
|
ti = dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
}
|
|
} else {
|
|
ti = dissect_osd_user_object_id(tvb, offset, tree);
|
|
}
|
|
offset += 8;
|
|
|
|
/* for OSD-2 if format is 0x02, 0x12 or 0x22: sub-list of attributes*/
|
|
if (osd2 && (format&0x02)) {
|
|
guint32 attr_list_end;
|
|
proto_tree *subtree;
|
|
|
|
if (offset+8>additional_length) break;
|
|
subtree = proto_item_add_subtree(ti, ett_osd_multi_object);
|
|
|
|
/*object type*/
|
|
proto_tree_add_item(subtree, hf_scsi_osd_object_type, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
/* 5 reserved bytes */
|
|
offset += 5;
|
|
/* attribute list length*/
|
|
attr_list_end = offset+2+tvb_get_ntohs(tvb, offset);
|
|
offset += 2;
|
|
if (attr_list_end>additional_length+8) break;
|
|
while (offset+16<attr_list_end) {
|
|
guint32 attribute_length = tvb_get_ntohs(tvb, offset+14);
|
|
proto_item *att_item;
|
|
proto_tree *att_tree = proto_tree_add_subtree(subtree, tvb, offset, 16+attribute_length, ett_osd_attribute, &att_item, "Attribute:");
|
|
offset = dissect_osd_attribute_list_entry(pinfo, tvb, att_tree, att_item, offset, lun_info, TRUE);
|
|
}
|
|
offset = attr_list_end;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static int
|
|
dissect_osd_requested_user_object_id(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* request user object id */
|
|
proto_tree_add_item(tree, hf_scsi_osd_requested_user_object_id, tvb, offset, 8, ENC_NA);
|
|
offset += 8;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_osd_number_of_user_objects(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* number_of_user_objects */
|
|
proto_tree_add_item(tree, hf_scsi_osd_number_of_user_objects, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
dissect_osd_create(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* requested user_object id */
|
|
dissect_osd_requested_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 4 reserved bytes */
|
|
offset += 4;
|
|
|
|
/* number of user objects */
|
|
dissect_osd_number_of_user_objects(tvb, offset, tree);
|
|
offset += 2;
|
|
|
|
/* 14 reserved bytes */
|
|
offset += 14;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for create */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for create */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_remove_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
gboolean osd2 = ((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->svcaction&0x80;
|
|
((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->osd2 = osd2;
|
|
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
if (osd2) dissect_osd2_isolation(tvb, offset, tree);
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
if (osd2) proto_tree_add_item(tree, hf_scsi_osd2_remove_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, TRUE);
|
|
offset += 8;
|
|
|
|
/* 24 reserved bytes */
|
|
offset += 24;
|
|
|
|
if (osd2) {
|
|
dissect_osd2_cdb_continuation_length(pinfo, tvb, offset, tree, cdata);
|
|
} else {
|
|
/* 4 reserved bytes */
|
|
}
|
|
offset += 4;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += osd2?104:80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += osd2?52:40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* CDB continuation */
|
|
dissect_osd2_cdb_continuation(pinfo, tvb, offset, tree, cdata);
|
|
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for remove partition */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for remove partition */
|
|
}
|
|
|
|
}
|
|
|
|
static const value_string key_to_set_vals[] = {
|
|
{1, "Root"},
|
|
{2, "Partition"},
|
|
{3, "Working"},
|
|
{0, NULL},
|
|
};
|
|
static void
|
|
dissect_osd_key_to_set(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
proto_tree_add_item(tree, hf_scsi_osd_key_to_set, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
static void
|
|
dissect_osd_set_key_version(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
proto_tree_add_item(tree, hf_scsi_osd_set_key_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
static void
|
|
dissect_osd_key_identifier(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
proto_tree_add_item(tree, hf_scsi_osd_key_identifier, tvb, offset, 7, ENC_NA);
|
|
}
|
|
|
|
static void
|
|
dissect_osd_seed(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
proto_tree_add_item(tree, hf_scsi_osd_seed, tvb, offset, 20, ENC_NA);
|
|
}
|
|
|
|
static void
|
|
dissect_osd_set_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* a reserved byte */
|
|
offset += 1;
|
|
|
|
/* getset attributes byte and key to set*/
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
dissect_osd_key_to_set(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* key version */
|
|
dissect_osd_set_key_version(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* key identifier */
|
|
dissect_osd_key_identifier(tvb, offset, tree);
|
|
offset += 7;
|
|
|
|
/* seed */
|
|
dissect_osd_seed(tvb, offset, tree);
|
|
offset += 20;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for set key */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for set key */
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
dissect_osd_remove(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* user object id */
|
|
dissect_osd_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 20 reserved bytes */
|
|
offset += 20;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for remove */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for remove */
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
dissect_osd_collection_fcr(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
proto_tree_add_item(tree, hf_scsi_osd_collection_fcr, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
}
|
|
|
|
static void
|
|
dissect_osd_remove_collection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
gboolean osd2 = ((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->svcaction&0x80;
|
|
((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->osd2 = osd2;
|
|
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
dissect_osd_collection_fcr(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* collection object id */
|
|
dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd_collection_object_id);
|
|
offset += 8;
|
|
|
|
/* 16 reserved bytes */
|
|
offset += 16;
|
|
|
|
if (osd2) {
|
|
dissect_osd2_cdb_continuation_length(pinfo, tvb, offset, tree, cdata);
|
|
} else {
|
|
/* 4 reserved bytes */
|
|
}
|
|
offset += 4;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += osd2?104:80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += osd2?52:40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* CDB continuation */
|
|
dissect_osd2_cdb_continuation(pinfo, tvb, offset, tree, cdata);
|
|
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for remove collection */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for remove collection */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_osd_length(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* length */
|
|
proto_tree_add_item(tree, hf_scsi_osd_length, tvb, offset, 8, ENC_BIG_ENDIAN);
|
|
offset += 8;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
dissect_osd_starting_byte_address(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* starting_byte_address */
|
|
proto_tree_add_item(tree, hf_scsi_osd_starting_byte_address, tvb, offset, 8, ENC_BIG_ENDIAN);
|
|
offset += 8;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_write(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte / sort order */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* user object id */
|
|
dissect_osd_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 4 reserved bytes */
|
|
offset += 4;
|
|
|
|
/* length */
|
|
dissect_osd_length(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* starting byte address */
|
|
dissect_osd_starting_byte_address(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* xxx should dissect the data ? */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for WRITE */
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
dissect_osd_create_collection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
dissect_osd_collection_fcr(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* requested collection object id */
|
|
dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd_requested_collection_object_id);
|
|
offset += 8;
|
|
|
|
/* 20 reserved bytes */
|
|
offset += 20;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for create collection */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for create collection */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static const value_string flush_scope_vals[] = {
|
|
{0, "User object data and attributes"},
|
|
{1, "User object attributes only"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static int
|
|
dissect_osd_flush_scope(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* flush scope */
|
|
proto_tree_add_item(tree, hf_scsi_osd_flush_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
dissect_osd_flush(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_flush_scope(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* user object id */
|
|
dissect_osd_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 20 reserved bytes */
|
|
offset += 20;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for flush */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for flush */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static const value_string flush_collection_scope_vals[] = {
|
|
{0, "List of user objects contained in the collection"},
|
|
{1, "Collection attributes only"},
|
|
{2, "List of user objects and collection attributes"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static int
|
|
dissect_osd_flush_collection_scope(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* flush collection scope */
|
|
proto_tree_add_item(tree, hf_scsi_osd_flush_collection_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
dissect_osd_flush_collection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_flush_collection_scope(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
dissect_osd_collection_fcr(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* collection object id */
|
|
dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd_collection_object_id);
|
|
offset += 8;
|
|
|
|
/* 20 reserved bytes */
|
|
offset += 20;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for flush collection */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for flush collection */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_append(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* user object id */
|
|
dissect_osd_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 4 reserved bytes */
|
|
offset += 4;
|
|
|
|
/* length */
|
|
dissect_osd_length(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 8 reserved bytes */
|
|
offset += 8;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* xxx should dissect the data ? */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for append */
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
dissect_osd_create_and_write(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* requested user_object id */
|
|
dissect_osd_requested_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 4 reserved bytes */
|
|
offset += 4;
|
|
|
|
/* length */
|
|
dissect_osd_length(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* starting byte address */
|
|
dissect_osd_starting_byte_address(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* should we dissect the data? */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for create and write*/
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static const value_string flush_osd_scope_vals[] = {
|
|
{0, "List of partitions contained in the OSD logical unit"},
|
|
{1, "Root object attributes only"},
|
|
{2, "Everything"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static int
|
|
dissect_osd_flush_osd_scope(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* flush osd scope */
|
|
proto_tree_add_item(tree, hf_scsi_osd_flush_osd_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
dissect_osd_flush_osd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info _U_)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_flush_osd_scope(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 39 reserved bytes */
|
|
offset += 39;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for flush osd */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for flush osd */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static const value_string flush_partition_scope_vals[] = {
|
|
{0, "List of user objects and collections in the partition"},
|
|
{1, "Partition attributes only"},
|
|
{2, "Everything"},
|
|
{0, NULL}
|
|
};
|
|
|
|
static int
|
|
dissect_osd_flush_partition_scope(tvbuff_t *tvb, int offset, proto_tree *tree)
|
|
{
|
|
/* flush partition scope */
|
|
proto_tree_add_item(tree, hf_scsi_osd_flush_partition_scope, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_flush_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_flush_partition_scope(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* 28 reserved bytes */
|
|
offset += 28;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for flush partition */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for flush partition */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_get_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
gboolean osd2 = ((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->svcaction&0x80;
|
|
((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->osd2 = osd2;
|
|
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* user_object id */
|
|
dissect_osd_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 16 reserved bytes */
|
|
offset += 16;
|
|
|
|
if (osd2) {
|
|
dissect_osd2_cdb_continuation_length(pinfo, tvb, offset, tree, cdata);
|
|
} else {
|
|
/* 4 reserved bytes */
|
|
}
|
|
offset += 4;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += osd2?104:80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += osd2?52:40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for get attributes */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for get attributes */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_read(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte / sort order */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* user object id */
|
|
dissect_osd_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 4 reserved bytes */
|
|
offset += 4;
|
|
|
|
/* length */
|
|
dissect_osd_length(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* starting byte address */
|
|
dissect_osd_starting_byte_address(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for READ */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* xxx should dissect the data ? */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd_set_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
gboolean osd2 = ((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->svcaction&0x80;
|
|
((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->osd2 = osd2;
|
|
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
/* options byte */
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partiton id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* user_object id */
|
|
dissect_osd_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 16 reserved bytes */
|
|
offset += 16;
|
|
|
|
if (osd2) {
|
|
dissect_osd2_cdb_continuation_length(pinfo, tvb, offset, tree, cdata);
|
|
} else {
|
|
/* 4 reserved bytes */
|
|
}
|
|
offset += 4;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += osd2?104:80;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += osd2?52:40;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for set attributes */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for set attributes */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void
|
|
dissect_osd2_create_user_tracking_collection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->osd2 = TRUE;
|
|
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
|
|
/* options byte */
|
|
dissect_osd2_isolation(tvb, offset, tree);
|
|
dissect_osd_option(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* getset attributes byte */
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partition id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* user_object id */
|
|
dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd_requested_collection_object_id);
|
|
offset += 8;
|
|
|
|
/* 8 reserved bytes */
|
|
offset += 8;
|
|
|
|
/* source collection id */
|
|
dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd2_source_collection_object_id);
|
|
offset += 8;
|
|
|
|
/*cdb continuation length*/
|
|
dissect_osd2_cdb_continuation_length(pinfo, tvb, offset, tree, cdata);
|
|
offset += 4;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 104;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 52;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* CDB continuation */
|
|
dissect_osd2_cdb_continuation(pinfo, tvb, offset, tree, cdata);
|
|
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for create user tracking collection */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data in for create user tracking collection */
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
dissect_osd2_query(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len _U_, scsi_task_data_t *cdata _U_,
|
|
scsi_osd_conv_info_t *conv_info _U_,
|
|
scsi_osd_lun_info_t *lun_info)
|
|
{
|
|
((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->osd2 = TRUE;
|
|
|
|
/* dissecting the CDB dissection starts at byte 10 of the CDB */
|
|
if (isreq && iscdb) {
|
|
|
|
/* isolation field */
|
|
dissect_osd2_isolation(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* immed_tr, getset attributes*/
|
|
proto_tree_add_item(tree, hf_scsi_osd2_immed_tr, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
dissect_osd_getsetattrib(tvb, offset, tree, cdata);
|
|
offset += 1;
|
|
|
|
/* timestamps control */
|
|
dissect_osd_timestamps_control(tvb, offset, tree);
|
|
offset += 1;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
|
|
/* partition id */
|
|
dissect_osd_partition_id(pinfo, tvb, offset, tree, hf_scsi_osd_partition_id, lun_info, FALSE, FALSE);
|
|
offset += 8;
|
|
|
|
/* collection_object id */
|
|
dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd_collection_object_id);
|
|
offset += 8;
|
|
|
|
/* allocation_length */
|
|
dissect_osd_allocation_length(tvb, offset, tree, cdata);
|
|
offset += 8;
|
|
|
|
/* matches collection id */
|
|
dissect_osd_collection_object_id(tvb, offset, tree, hf_scsi_osd2_matches_collection_object_id);
|
|
offset += 8;
|
|
|
|
/*cdb continuation length*/
|
|
dissect_osd2_cdb_continuation_length(pinfo, tvb, offset, tree, cdata);
|
|
offset += 4;
|
|
|
|
/* attribute parameters */
|
|
dissect_osd_attribute_parameters(pinfo, tvb, offset, tree, cdata);
|
|
offset += 28;
|
|
|
|
/* capability */
|
|
dissect_osd_capability(tvb, offset, tree);
|
|
offset += 104;
|
|
|
|
/* security parameters */
|
|
dissect_osd_security_parameters(tvb, offset, tree);
|
|
offset += 52;
|
|
}
|
|
|
|
/* dissecting the DATA OUT */
|
|
if (isreq && !iscdb) {
|
|
/* CDB continuation */
|
|
dissect_osd2_cdb_continuation(pinfo, tvb, offset, tree, cdata);
|
|
|
|
/* attribute data out */
|
|
dissect_osd_attribute_data_out(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
/* no data out for query */
|
|
}
|
|
|
|
/* dissecting the DATA IN */
|
|
if (!isreq && !iscdb) {
|
|
guint64 additional_length;
|
|
guint64 allocation_length;
|
|
guint64 remaining_length;
|
|
guint8 format;
|
|
proto_item *item;
|
|
|
|
/* attribute data in */
|
|
dissect_osd_attribute_data_in(pinfo, tvb, offset, tree, cdata, lun_info);
|
|
|
|
allocation_length = cdata->itlq->alloc_len;
|
|
remaining_length = tvb_captured_length_remaining(tvb, offset);
|
|
if (remaining_length<allocation_length) allocation_length = remaining_length;
|
|
if (allocation_length<12) return;
|
|
|
|
/* dissection of the LIST or LIST COLLECTION DATA-IN */
|
|
/* additional length */
|
|
additional_length = tvb_get_ntoh64(tvb, offset);
|
|
if ((guint32)(allocation_length-8)<additional_length) additional_length = (guint32)(allocation_length-8);
|
|
|
|
dissect_osd_additional_length(tvb, offset, tree);
|
|
offset += 8;
|
|
|
|
/* 3 reserved bytes */
|
|
offset += 3;
|
|
item = proto_tree_add_item(tree, hf_scsi_osd2_object_descriptor_format, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
format = tvb_get_guint8(tvb, offset)>>2;
|
|
offset += 1;
|
|
if (format != 0x21) {
|
|
expert_add_info(pinfo, item, &ei_osd2_invalid_object_descriptor_format);
|
|
return;
|
|
}
|
|
|
|
while (additional_length > (offset-4)) {
|
|
dissect_osd_user_object_id(tvb, offset, tree);
|
|
offset += 8;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* OSD Service Actions */
|
|
#define OSD_FORMAT_OSD 0x8801
|
|
#define OSD_CREATE 0x8802
|
|
#define OSD_LIST 0x8803
|
|
#define OSD_READ 0x8805
|
|
#define OSD_WRITE 0x8806
|
|
#define OSD_APPEND 0x8807
|
|
#define OSD_FLUSH 0x8808
|
|
#define OSD_REMOVE 0x880a
|
|
#define OSD_CREATE_PARTITION 0x880b
|
|
#define OSD_REMOVE_PARTITION 0x880c
|
|
#define OSD_GET_ATTRIBUTES 0x880e
|
|
#define OSD_SET_ATTRIBUTES 0x880f
|
|
#define OSD_CREATE_AND_WRITE 0x8812
|
|
#define OSD_CREATE_COLLECTION 0x8815
|
|
#define OSD_REMOVE_COLLECTION 0x8816
|
|
#define OSD_LIST_COLLECTION 0x8817
|
|
#define OSD_SET_KEY 0x8818
|
|
#define OSD_FLUSH_COLLECTION 0x881a
|
|
#define OSD_FLUSH_PARTITION 0x881b
|
|
#define OSD_FLUSH_OSD 0x881c
|
|
|
|
#define OSD_2_CREATE 0x8882
|
|
#define OSD_2_LIST 0x8883
|
|
#define OSD_2_READ 0x8885
|
|
#define OSD_2_WRITE 0x8886
|
|
#define OSD_2_APPEND 0x8887
|
|
#define OSD_2_CLEAR 0x8889
|
|
#define OSD_2_REMOVE 0x888a
|
|
#define OSD_2_CREATE_PARTITION 0x888b
|
|
#define OSD_2_REMOVE_PARTITION 0x888c
|
|
#define OSD_2_GET_ATTRIBUTES 0x888e
|
|
#define OSD_2_SET_ATTRIBUTES 0x888f
|
|
#define OSD_2_CREATE_AND_WRITE 0x8892
|
|
#define OSD_2_COPY_USER_OBJECTS 0x8893
|
|
#define OSD_2_CREATE_USER_TRACKING_COLLECTION 0x8894
|
|
#define OSD_2_REMOVE_COLLECTION 0x8896
|
|
#define OSD_2_LIST_COLLECTION 0x8897
|
|
#define OSD_2_QUERY 0x88a0
|
|
#define OSD_2_REMOVE_MEMBER_OBJECTS 0x88a1
|
|
#define OSD_2_GET_MEMBER_ATTRIBUTES 0x88a2
|
|
#define OSD_2_SET_MEMBER_ATTRIBUTES 0x88a3
|
|
|
|
static const value_string scsi_osd_svcaction_vals[] = {
|
|
{OSD_FORMAT_OSD, "Format OSD"},
|
|
{OSD_CREATE, "Create"},
|
|
{OSD_LIST, "List"},
|
|
{OSD_READ, "Read"},
|
|
{OSD_WRITE, "Write"},
|
|
{OSD_APPEND, "Append"},
|
|
{OSD_FLUSH, "Flush"},
|
|
{OSD_REMOVE, "Remove"},
|
|
{OSD_CREATE_PARTITION, "Create Partition"},
|
|
{OSD_REMOVE_PARTITION, "Remove Partition"},
|
|
{OSD_GET_ATTRIBUTES, "Get Attributes"},
|
|
{OSD_SET_ATTRIBUTES, "Set Attributes"},
|
|
{OSD_CREATE_AND_WRITE, "Create And Write"},
|
|
{OSD_CREATE_COLLECTION, "Create Collection"},
|
|
{OSD_REMOVE_COLLECTION, "Remove Collection"},
|
|
{OSD_LIST_COLLECTION, "List Collection"},
|
|
{OSD_SET_KEY, "Set Key"},
|
|
{OSD_FLUSH_COLLECTION, "Flush Collection"},
|
|
{OSD_FLUSH_PARTITION, "Flush Partition"},
|
|
{OSD_FLUSH_OSD, "Flush OSD"},
|
|
|
|
{OSD_2_CREATE, "Create (OSD-2)"},
|
|
{OSD_2_LIST, "List (OSD-2)"},
|
|
{OSD_2_READ, "Read (OSD-2)"},
|
|
{OSD_2_WRITE, "Write (OSD-2)"},
|
|
{OSD_2_APPEND, "Append (OSD-2)"},
|
|
{OSD_2_CLEAR, "Clear (OSD-2)"},
|
|
{OSD_2_REMOVE, "Remove (OSD-2)"},
|
|
{OSD_2_CREATE_PARTITION, "Create Partition (OSD-2)"},
|
|
{OSD_2_REMOVE_PARTITION, "Remove Partition (OSD-2)"},
|
|
{OSD_2_GET_ATTRIBUTES, "Get Attributes (OSD-2)"},
|
|
{OSD_2_SET_ATTRIBUTES, "Set Attributes (OSD-2)"},
|
|
{OSD_2_CREATE_AND_WRITE, "Create And Write (OSD-2)"},
|
|
{OSD_2_COPY_USER_OBJECTS, "Copy User Objects (OSD-2)"},
|
|
{OSD_2_CREATE_USER_TRACKING_COLLECTION, "Create User Tracking Collection (OSD-2)"},
|
|
{OSD_2_REMOVE_COLLECTION, "Remove Collection (OSD-2)"},
|
|
{OSD_2_LIST_COLLECTION, "List Collection (OSD-2)"},
|
|
{OSD_2_QUERY, "Query (OSD-2)"},
|
|
{OSD_2_REMOVE_MEMBER_OBJECTS, "Remove Member Objects (OSD-2)"},
|
|
{OSD_2_GET_MEMBER_ATTRIBUTES, "Get Member Attributes (OSD-2)"},
|
|
{OSD_2_SET_MEMBER_ATTRIBUTES, "Set Member Attributes (OSD-2)"},
|
|
{0, NULL},
|
|
};
|
|
static value_string_ext scsi_osd_svcaction_vals_ext = VALUE_STRING_EXT_INIT(scsi_osd_svcaction_vals);
|
|
|
|
/* OSD Service Action dissectors */
|
|
typedef struct _scsi_osd_svcaction_t {
|
|
guint16 svcaction;
|
|
scsi_osd_dissector_t dissector;
|
|
} scsi_osd_svcaction_t;
|
|
|
|
static const scsi_osd_svcaction_t scsi_osd_svcaction[] = {
|
|
{OSD_FORMAT_OSD, dissect_osd_format_osd},
|
|
{OSD_CREATE, dissect_osd_create},
|
|
{OSD_LIST, dissect_osd_list},
|
|
{OSD_READ, dissect_osd_read},
|
|
{OSD_WRITE, dissect_osd_write},
|
|
{OSD_APPEND, dissect_osd_append},
|
|
{OSD_FLUSH, dissect_osd_flush},
|
|
{OSD_REMOVE, dissect_osd_remove},
|
|
{OSD_CREATE_PARTITION, dissect_osd_create_partition},
|
|
{OSD_REMOVE_PARTITION, dissect_osd_remove_partition},
|
|
{OSD_GET_ATTRIBUTES, dissect_osd_get_attributes},
|
|
{OSD_SET_ATTRIBUTES, dissect_osd_set_attributes},
|
|
{OSD_CREATE_AND_WRITE, dissect_osd_create_and_write},
|
|
{OSD_CREATE_COLLECTION, dissect_osd_create_collection},
|
|
{OSD_REMOVE_COLLECTION, dissect_osd_remove_collection},
|
|
{OSD_LIST_COLLECTION, dissect_osd_list},
|
|
{OSD_SET_KEY, dissect_osd_set_key},
|
|
{OSD_FLUSH_COLLECTION, dissect_osd_flush_collection},
|
|
{OSD_FLUSH_PARTITION, dissect_osd_flush_partition},
|
|
{OSD_FLUSH_OSD, dissect_osd_flush_osd},
|
|
{OSD_2_LIST, dissect_osd_list},
|
|
{OSD_2_CREATE_PARTITION, dissect_osd_create_partition},
|
|
{OSD_2_CREATE_USER_TRACKING_COLLECTION, dissect_osd2_create_user_tracking_collection},
|
|
{OSD_2_REMOVE_PARTITION, dissect_osd_remove_partition},
|
|
{OSD_2_LIST_COLLECTION, dissect_osd_list},
|
|
{OSD_2_CREATE_USER_TRACKING_COLLECTION, dissect_osd2_create_user_tracking_collection},
|
|
{OSD_2_REMOVE_COLLECTION, dissect_osd_remove_collection},
|
|
{OSD_2_GET_ATTRIBUTES, dissect_osd_get_attributes},
|
|
{OSD_2_SET_ATTRIBUTES, dissect_osd_set_attributes},
|
|
{OSD_2_QUERY, dissect_osd2_query},
|
|
{0, NULL},
|
|
};
|
|
|
|
static scsi_osd_dissector_t
|
|
find_svcaction_dissector(guint16 svcaction)
|
|
{
|
|
const scsi_osd_svcaction_t *sa = scsi_osd_svcaction;
|
|
|
|
while (sa && sa->dissector) {
|
|
if (sa->svcaction == svcaction) {
|
|
return sa->dissector;
|
|
}
|
|
sa++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
dissect_osd_opcode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
guint offset, gboolean isreq, gboolean iscdb,
|
|
guint payload_len, scsi_task_data_t *cdata)
|
|
{
|
|
guint16 svcaction = 0;
|
|
scsi_osd_dissector_t dissector;
|
|
scsi_osd_conv_info_t *conv_info;
|
|
scsi_osd_lun_info_t *lun_info;
|
|
|
|
if (!tree) {
|
|
return;
|
|
}
|
|
|
|
/* We must have an itl an itlq and a conversation */
|
|
if (!cdata || !cdata->itl || !cdata->itl->conversation || !cdata->itlq) {
|
|
return;
|
|
}
|
|
/* make sure we have a conversation info for this */
|
|
conv_info = (scsi_osd_conv_info_t *)conversation_get_proto_data(cdata->itl->conversation, proto_scsi_osd);
|
|
if (!conv_info) {
|
|
conv_info = wmem_new(wmem_file_scope(), scsi_osd_conv_info_t);
|
|
conv_info->luns = wmem_tree_new(wmem_file_scope());
|
|
conversation_add_proto_data(cdata->itl->conversation, proto_scsi_osd, conv_info);
|
|
}
|
|
/* make sure we have a lun_info structure for this */
|
|
lun_info = (scsi_osd_lun_info_t *)wmem_tree_lookup32(conv_info->luns, cdata->itlq->lun);
|
|
if (!lun_info) {
|
|
lun_info = wmem_new(wmem_file_scope(), scsi_osd_lun_info_t);
|
|
lun_info->partitions = wmem_tree_new(wmem_file_scope());
|
|
wmem_tree_insert32(conv_info->luns, cdata->itlq->lun, (void *)lun_info);
|
|
}
|
|
|
|
/* dissecting the CDB */
|
|
if (isreq && iscdb) {
|
|
proto_tree_add_item (tree, hf_scsi_control, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
/* 5 reserved bytes */
|
|
offset += 5;
|
|
|
|
proto_tree_add_item (tree, hf_scsi_osd_add_cdblen, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
offset += 1;
|
|
|
|
svcaction = tvb_get_ntohs(tvb, offset);
|
|
if (cdata && cdata->itlq) {
|
|
/* We must store the service action for this itlq
|
|
* so we can identify what the data contains
|
|
*/
|
|
if ((!pinfo->fd->flags.visited) || (!cdata->itlq->extra_data)) {
|
|
scsi_osd_extra_data_t *extra_data;
|
|
|
|
extra_data = wmem_new0(wmem_file_scope(), scsi_osd_extra_data_t);
|
|
extra_data->svcaction = svcaction;
|
|
cdata->itlq->extra_data = extra_data;
|
|
}
|
|
}
|
|
proto_tree_add_item (tree, hf_scsi_osd_svcaction, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
offset += 2;
|
|
|
|
|
|
col_append_str(pinfo->cinfo, COL_INFO,
|
|
val_to_str_ext_const(svcaction, &scsi_osd_svcaction_vals_ext, "Unknown OSD Service Action"));
|
|
|
|
dissector = find_svcaction_dissector(svcaction);
|
|
if (dissector) {
|
|
(*dissector)(tvb, pinfo, tree, offset, isreq, iscdb, payload_len, cdata, conv_info, lun_info);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* If it was not a CDB, try to find the service action and pass it
|
|
* off to the service action dissector
|
|
*/
|
|
if (cdata && cdata->itlq && cdata->itlq->extra_data) {
|
|
scsi_osd_extra_data_t *extra_data = (scsi_osd_extra_data_t *)cdata->itlq->extra_data;
|
|
svcaction = extra_data->svcaction;
|
|
}
|
|
col_append_str(pinfo->cinfo, COL_INFO,
|
|
val_to_str_ext_const(svcaction, &scsi_osd_svcaction_vals_ext, "Unknown OSD Service Action"));
|
|
if (svcaction) {
|
|
proto_item *it;
|
|
it = proto_tree_add_uint_format_value(tree, hf_scsi_osd_svcaction, tvb, 0, 0, svcaction, "0x%04x", svcaction);
|
|
PROTO_ITEM_SET_GENERATED(it);
|
|
}
|
|
dissector = find_svcaction_dissector(svcaction);
|
|
if (dissector) {
|
|
(*dissector)(tvb, pinfo, tree, offset, isreq, iscdb, payload_len, cdata, conv_info, lun_info);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* OSD Commands */
|
|
static const value_string scsi_osd_vals[] = {
|
|
/* 0x12 */ {SCSI_SPC_INQUIRY, "Inquiry"},
|
|
/* 0x4C */ {SCSI_SPC_LOGSELECT, "Log Select"},
|
|
/* 0x4D */ {SCSI_SPC_LOGSENSE, "Log Sense"},
|
|
/* 0x55 */ {SCSI_SPC_MODESELECT10, "Mode Select(10)"},
|
|
/* 0x5A */ {SCSI_SPC_MODESENSE10, "Mode Sense(10)"},
|
|
/* 0x5E */ {SCSI_SPC_PERSRESVIN, "Persistent Reserve In"},
|
|
/* 0x5F */ {SCSI_SPC_PERSRESVOUT, "Persistent Reserve Out"},
|
|
/* 0x7f */ {SCSI_OSD_OPCODE, "OSD Command" },
|
|
/* 0xA0 */ {SCSI_SPC_REPORTLUNS, "Report LUNs"},
|
|
/* 0xA3 */ {SCSI_SPC_MGMT_PROTOCOL_IN, "Mgmt Protocol In"},
|
|
{0, NULL},
|
|
};
|
|
value_string_ext scsi_osd_vals_ext = VALUE_STRING_EXT_INIT(scsi_osd_vals);
|
|
|
|
scsi_cdb_table_t scsi_osd_table[256] = {
|
|
/*OSD 0x00*/{NULL},
|
|
/*OSD 0x01*/{NULL},
|
|
/*OSD 0x02*/{NULL},
|
|
/*OSD 0x03*/{NULL},
|
|
/*OSD 0x04*/{NULL},
|
|
/*OSD 0x05*/{NULL},
|
|
/*OSD 0x06*/{NULL},
|
|
/*OSD 0x07*/{NULL},
|
|
/*OSD 0x08*/{NULL},
|
|
/*OSD 0x09*/{NULL},
|
|
/*OSD 0x0a*/{NULL},
|
|
/*OSD 0x0b*/{NULL},
|
|
/*OSD 0x0c*/{NULL},
|
|
/*OSD 0x0d*/{NULL},
|
|
/*OSD 0x0e*/{NULL},
|
|
/*OSD 0x0f*/{NULL},
|
|
/*OSD 0x10*/{NULL},
|
|
/*OSD 0x11*/{NULL},
|
|
/*OSD 0x12*/{dissect_spc_inquiry},
|
|
/*OSD 0x13*/{NULL},
|
|
/*OSD 0x14*/{NULL},
|
|
/*OSD 0x15*/{NULL},
|
|
/*OSD 0x16*/{NULL},
|
|
/*OSD 0x17*/{NULL},
|
|
/*OSD 0x18*/{NULL},
|
|
/*OSD 0x19*/{NULL},
|
|
/*OSD 0x1a*/{NULL},
|
|
/*OSD 0x1b*/{NULL},
|
|
/*OSD 0x1c*/{NULL},
|
|
/*OSD 0x1d*/{NULL},
|
|
/*OSD 0x1e*/{NULL},
|
|
/*OSD 0x1f*/{NULL},
|
|
/*OSD 0x20*/{NULL},
|
|
/*OSD 0x21*/{NULL},
|
|
/*OSD 0x22*/{NULL},
|
|
/*OSD 0x23*/{NULL},
|
|
/*OSD 0x24*/{NULL},
|
|
/*OSD 0x25*/{NULL},
|
|
/*OSD 0x26*/{NULL},
|
|
/*OSD 0x27*/{NULL},
|
|
/*OSD 0x28*/{NULL},
|
|
/*OSD 0x29*/{NULL},
|
|
/*OSD 0x2a*/{NULL},
|
|
/*OSD 0x2b*/{NULL},
|
|
/*OSD 0x2c*/{NULL},
|
|
/*OSD 0x2d*/{NULL},
|
|
/*OSD 0x2e*/{NULL},
|
|
/*OSD 0x2f*/{NULL},
|
|
/*OSD 0x30*/{NULL},
|
|
/*OSD 0x31*/{NULL},
|
|
/*OSD 0x32*/{NULL},
|
|
/*OSD 0x33*/{NULL},
|
|
/*OSD 0x34*/{NULL},
|
|
/*OSD 0x35*/{NULL},
|
|
/*OSD 0x36*/{NULL},
|
|
/*OSD 0x37*/{NULL},
|
|
/*OSD 0x38*/{NULL},
|
|
/*OSD 0x39*/{NULL},
|
|
/*OSD 0x3a*/{NULL},
|
|
/*OSD 0x3b*/{NULL},
|
|
/*OSD 0x3c*/{NULL},
|
|
/*OSD 0x3d*/{NULL},
|
|
/*OSD 0x3e*/{NULL},
|
|
/*OSD 0x3f*/{NULL},
|
|
/*OSD 0x40*/{NULL},
|
|
/*OSD 0x41*/{NULL},
|
|
/*OSD 0x42*/{NULL},
|
|
/*OSD 0x43*/{NULL},
|
|
/*OSD 0x44*/{NULL},
|
|
/*OSD 0x45*/{NULL},
|
|
/*OSD 0x46*/{NULL},
|
|
/*OSD 0x47*/{NULL},
|
|
/*OSD 0x48*/{NULL},
|
|
/*OSD 0x49*/{NULL},
|
|
/*OSD 0x4a*/{NULL},
|
|
/*OSD 0x4b*/{NULL},
|
|
/*OSD 0x4c*/{dissect_spc_logselect},
|
|
/*OSD 0x4d*/{dissect_spc_logsense},
|
|
/*OSD 0x4e*/{NULL},
|
|
/*OSD 0x4f*/{NULL},
|
|
/*OSD 0x50*/{NULL},
|
|
/*OSD 0x51*/{NULL},
|
|
/*OSD 0x52*/{NULL},
|
|
/*OSD 0x53*/{NULL},
|
|
/*OSD 0x54*/{NULL},
|
|
/*OSD 0x55*/{dissect_spc_modeselect10},
|
|
/*OSD 0x56*/{NULL},
|
|
/*OSD 0x57*/{NULL},
|
|
/*OSD 0x58*/{NULL},
|
|
/*OSD 0x59*/{NULL},
|
|
/*OSD 0x5a*/{dissect_spc_modesense10},
|
|
/*OSD 0x5b*/{NULL},
|
|
/*OSD 0x5c*/{NULL},
|
|
/*OSD 0x5d*/{NULL},
|
|
/*OSD 0x5e*/{dissect_spc_persistentreservein},
|
|
/*OSD 0x5f*/{dissect_spc_persistentreserveout},
|
|
/*OSD 0x60*/{NULL},
|
|
/*OSD 0x61*/{NULL},
|
|
/*OSD 0x62*/{NULL},
|
|
/*OSD 0x63*/{NULL},
|
|
/*OSD 0x64*/{NULL},
|
|
/*OSD 0x65*/{NULL},
|
|
/*OSD 0x66*/{NULL},
|
|
/*OSD 0x67*/{NULL},
|
|
/*OSD 0x68*/{NULL},
|
|
/*OSD 0x69*/{NULL},
|
|
/*OSD 0x6a*/{NULL},
|
|
/*OSD 0x6b*/{NULL},
|
|
/*OSD 0x6c*/{NULL},
|
|
/*OSD 0x6d*/{NULL},
|
|
/*OSD 0x6e*/{NULL},
|
|
/*OSD 0x6f*/{NULL},
|
|
/*OSD 0x70*/{NULL},
|
|
/*OSD 0x71*/{NULL},
|
|
/*OSD 0x72*/{NULL},
|
|
/*OSD 0x73*/{NULL},
|
|
/*OSD 0x74*/{NULL},
|
|
/*OSD 0x75*/{NULL},
|
|
/*OSD 0x76*/{NULL},
|
|
/*OSD 0x77*/{NULL},
|
|
/*OSD 0x78*/{NULL},
|
|
/*OSD 0x79*/{NULL},
|
|
/*OSD 0x7a*/{NULL},
|
|
/*OSD 0x7b*/{NULL},
|
|
/*OSD 0x7c*/{NULL},
|
|
/*OSD 0x7d*/{NULL},
|
|
/*OSD 0x7e*/{NULL},
|
|
/*OSD 0x7f*/{dissect_osd_opcode},
|
|
/*OSD 0x80*/{NULL},
|
|
/*OSD 0x81*/{NULL},
|
|
/*OSD 0x82*/{NULL},
|
|
/*OSD 0x83*/{NULL},
|
|
/*OSD 0x84*/{NULL},
|
|
/*OSD 0x85*/{NULL},
|
|
/*OSD 0x86*/{NULL},
|
|
/*OSD 0x87*/{NULL},
|
|
/*OSD 0x88*/{NULL},
|
|
/*OSD 0x89*/{NULL},
|
|
/*OSD 0x8a*/{NULL},
|
|
/*OSD 0x8b*/{NULL},
|
|
/*OSD 0x8c*/{NULL},
|
|
/*OSD 0x8d*/{NULL},
|
|
/*OSD 0x8e*/{NULL},
|
|
/*OSD 0x8f*/{NULL},
|
|
/*OSD 0x90*/{NULL},
|
|
/*OSD 0x91*/{NULL},
|
|
/*OSD 0x92*/{NULL},
|
|
/*OSD 0x93*/{NULL},
|
|
/*OSD 0x94*/{NULL},
|
|
/*OSD 0x95*/{NULL},
|
|
/*OSD 0x96*/{NULL},
|
|
/*OSD 0x97*/{NULL},
|
|
/*OSD 0x98*/{NULL},
|
|
/*OSD 0x99*/{NULL},
|
|
/*OSD 0x9a*/{NULL},
|
|
/*OSD 0x9b*/{NULL},
|
|
/*OSD 0x9c*/{NULL},
|
|
/*OSD 0x9d*/{NULL},
|
|
/*OSD 0x9e*/{NULL},
|
|
/*OSD 0x9f*/{NULL},
|
|
/*OSD 0xa0*/{dissect_spc_reportluns},
|
|
/*OSD 0xa1*/{NULL},
|
|
/*OSD 0xa2*/{NULL},
|
|
/*SPC 0xa3*/{dissect_spc_mgmt_protocol_in},
|
|
/*OSD 0xa4*/{NULL},
|
|
/*OSD 0xa5*/{NULL},
|
|
/*OSD 0xa6*/{NULL},
|
|
/*OSD 0xa7*/{NULL},
|
|
/*OSD 0xa8*/{NULL},
|
|
/*OSD 0xa9*/{NULL},
|
|
/*OSD 0xaa*/{NULL},
|
|
/*OSD 0xab*/{NULL},
|
|
/*OSD 0xac*/{NULL},
|
|
/*OSD 0xad*/{NULL},
|
|
/*OSD 0xae*/{NULL},
|
|
/*OSD 0xaf*/{NULL},
|
|
/*OSD 0xb0*/{NULL},
|
|
/*OSD 0xb1*/{NULL},
|
|
/*OSD 0xb2*/{NULL},
|
|
/*OSD 0xb3*/{NULL},
|
|
/*OSD 0xb4*/{NULL},
|
|
/*OSD 0xb5*/{NULL},
|
|
/*OSD 0xb6*/{NULL},
|
|
/*OSD 0xb7*/{NULL},
|
|
/*OSD 0xb8*/{NULL},
|
|
/*OSD 0xb9*/{NULL},
|
|
/*OSD 0xba*/{NULL},
|
|
/*OSD 0xbb*/{NULL},
|
|
/*OSD 0xbc*/{NULL},
|
|
/*OSD 0xbd*/{NULL},
|
|
/*OSD 0xbe*/{NULL},
|
|
/*OSD 0xbf*/{NULL},
|
|
/*OSD 0xc0*/{NULL},
|
|
/*OSD 0xc1*/{NULL},
|
|
/*OSD 0xc2*/{NULL},
|
|
/*OSD 0xc3*/{NULL},
|
|
/*OSD 0xc4*/{NULL},
|
|
/*OSD 0xc5*/{NULL},
|
|
/*OSD 0xc6*/{NULL},
|
|
/*OSD 0xc7*/{NULL},
|
|
/*OSD 0xc8*/{NULL},
|
|
/*OSD 0xc9*/{NULL},
|
|
/*OSD 0xca*/{NULL},
|
|
/*OSD 0xcb*/{NULL},
|
|
/*OSD 0xcc*/{NULL},
|
|
/*OSD 0xcd*/{NULL},
|
|
/*OSD 0xce*/{NULL},
|
|
/*OSD 0xcf*/{NULL},
|
|
/*OSD 0xd0*/{NULL},
|
|
/*OSD 0xd1*/{NULL},
|
|
/*OSD 0xd2*/{NULL},
|
|
/*OSD 0xd3*/{NULL},
|
|
/*OSD 0xd4*/{NULL},
|
|
/*OSD 0xd5*/{NULL},
|
|
/*OSD 0xd6*/{NULL},
|
|
/*OSD 0xd7*/{NULL},
|
|
/*OSD 0xd8*/{NULL},
|
|
/*OSD 0xd9*/{NULL},
|
|
/*OSD 0xda*/{NULL},
|
|
/*OSD 0xdb*/{NULL},
|
|
/*OSD 0xdc*/{NULL},
|
|
/*OSD 0xdd*/{NULL},
|
|
/*OSD 0xde*/{NULL},
|
|
/*OSD 0xdf*/{NULL},
|
|
/*OSD 0xe0*/{NULL},
|
|
/*OSD 0xe1*/{NULL},
|
|
/*OSD 0xe2*/{NULL},
|
|
/*OSD 0xe3*/{NULL},
|
|
/*OSD 0xe4*/{NULL},
|
|
/*OSD 0xe5*/{NULL},
|
|
/*OSD 0xe6*/{NULL},
|
|
/*OSD 0xe7*/{NULL},
|
|
/*OSD 0xe8*/{NULL},
|
|
/*OSD 0xe9*/{NULL},
|
|
/*OSD 0xea*/{NULL},
|
|
/*OSD 0xeb*/{NULL},
|
|
/*OSD 0xec*/{NULL},
|
|
/*OSD 0xed*/{NULL},
|
|
/*OSD 0xee*/{NULL},
|
|
/*OSD 0xef*/{NULL},
|
|
/*OSD 0xf0*/{NULL},
|
|
/*OSD 0xf1*/{NULL},
|
|
/*OSD 0xf2*/{NULL},
|
|
/*OSD 0xf3*/{NULL},
|
|
/*OSD 0xf4*/{NULL},
|
|
/*OSD 0xf5*/{NULL},
|
|
/*OSD 0xf6*/{NULL},
|
|
/*OSD 0xf7*/{NULL},
|
|
/*OSD 0xf8*/{NULL},
|
|
/*OSD 0xf9*/{NULL},
|
|
/*OSD 0xfa*/{NULL},
|
|
/*OSD 0xfb*/{NULL},
|
|
/*OSD 0xfc*/{NULL},
|
|
/*OSD 0xfd*/{NULL},
|
|
/*OSD 0xfe*/{NULL},
|
|
/*OSD 0xff*/{NULL}
|
|
};
|
|
|
|
|
|
|
|
|
|
void
|
|
proto_register_scsi_osd(void)
|
|
{
|
|
expert_module_t *expert_scsi_osd;
|
|
|
|
static hf_register_info hf[] = {
|
|
{ &hf_scsi_osd_opcode,
|
|
{"OSD Opcode", "scsi_osd.opcode", FT_UINT8, BASE_HEX | BASE_EXT_STRING,
|
|
&scsi_osd_vals_ext, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_add_cdblen,
|
|
{"Additional CDB Length", "scsi_osd.addcdblen", FT_UINT8, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_svcaction,
|
|
{"Service Action", "scsi_osd.svcaction", FT_UINT16, BASE_HEX | BASE_EXT_STRING,
|
|
&scsi_osd_svcaction_vals_ext, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_option,
|
|
{"Options Byte", "scsi_osd.option", FT_UINT8, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_option_dpo,
|
|
{"DPO", "scsi_osd.option.dpo", FT_BOOLEAN, 8,
|
|
TFS(&tfs_set_notset), 0x10, NULL, HFILL}},
|
|
{ &hf_scsi_osd_option_fua,
|
|
{"FUA", "scsi_osd.option.fua", FT_BOOLEAN, 8,
|
|
TFS(&tfs_set_notset), 0x08, NULL, HFILL}},
|
|
{ &hf_scsi_osd_getsetattrib,
|
|
{"GET/SET CDBFMT", "scsi_osd.getset", FT_UINT8, BASE_HEX,
|
|
VALS(scsi_osd_getsetattrib_vals), 0x30, NULL, HFILL}},
|
|
{ &hf_scsi_osd_timestamps_control,
|
|
{"Timestamps Control", "scsi_osd.timestamps_control", FT_UINT8, BASE_HEX,
|
|
VALS(scsi_osd_timestamps_control_vals), 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_formatted_capacity,
|
|
{"Formatted Capacity", "scsi_osd.formatted_capacity", FT_UINT64, BASE_DEC,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_get_attributes_page,
|
|
{"Get Attributes Page", "scsi_osd.get_attributes_page", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_get_attributes_list_length,
|
|
{"Get Attributes List Length", "scsi_osd.get_attributes_list_length", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_get_attributes_list_offset,
|
|
{"Get Attributes List Offset", "scsi_osd.get_attributes_list_offset", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_set_attributes_list_length,
|
|
{"Set Attributes List Length", "scsi_osd.set_attributes_list_length", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_set_attributes_list_offset,
|
|
{"Set Attributes List Offset", "scsi_osd.set_attributes_list_offset", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_get_attributes_allocation_length,
|
|
{"Get Attributes Allocation Length", "scsi_osd.get_attributes_allocation_length", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_retrieved_attributes_offset,
|
|
{"Retrieved Attributes Offset", "scsi_osd.retrieved_attributes_offset", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_set_attributes_page,
|
|
{"Set Attributes Page", "scsi_osd.set_attributes_page", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_set_attribute_length,
|
|
{"Set Attribute Length", "scsi_osd.set_attribute_length", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_set_attribute_number,
|
|
{"Set Attribute Number", "scsi_osd.set_attribute_number", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_set_attributes_offset,
|
|
{"Set Attributes Offset", "scsi_osd.set_attributes_offset", FT_UINT32, BASE_HEX,
|
|
NULL, 0x0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_capability_format,
|
|
{"Capability Format", "scsi_osd.capability_format", FT_UINT8, BASE_HEX,
|
|
VALS(scsi_osd_capability_format_vals), 0x0f, NULL, HFILL}},
|
|
{ &hf_scsi_osd_key_version,
|
|
{"Key Version", "scsi_osd.key_version", FT_UINT8, BASE_HEX,
|
|
NULL, 0xf0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_icva,
|
|
{"Integrity Check Value Algorithm", "scsi_osd.icva", FT_UINT8, BASE_HEX,
|
|
NULL, 0x0f, NULL, HFILL}},
|
|
{ &hf_scsi_osd_security_method,
|
|
{"Security Method", "scsi_osd.security_method", FT_UINT8, BASE_HEX,
|
|
NULL, 0x0f, NULL, HFILL}},
|
|
{ &hf_scsi_osd_capability_expiration_time,
|
|
{"Capability Expiration Time", "scsi_osd.capability_expiration_time", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_audit,
|
|
{"Audit", "scsi_osd.audit", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_capability_discriminator,
|
|
{"Capability Discriminator", "scsi_osd.capability_descriminator", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_object_created_time,
|
|
{"Object Created Time", "scsi_osd.object_created_time", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_object_type,
|
|
{"Object Type", "scsi_osd.object_type", FT_UINT8, BASE_HEX,
|
|
VALS(scsi_osd_object_type_vals), 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions,
|
|
{"Permissions", "scsi_osd.permissions", FT_UINT16, BASE_HEX,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_read,
|
|
{"READ", "scsi_osd.permissions.read", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x8000, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_write,
|
|
{"WRITE", "scsi_osd.permissions.write", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x4000, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_get_attr,
|
|
{"GET_ATTR", "scsi_osd.permissions.get_attr", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x2000, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_set_attr,
|
|
{"SET_ATTR", "scsi_osd.permissions.set_attr", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x1000, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_create,
|
|
{"CREATE", "scsi_osd.permissions.create", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x0800, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_remove,
|
|
{"REMOVE", "scsi_osd.permissions.remove", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x0400, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_obj_mgmt,
|
|
{"OBJ_MGMT", "scsi_osd.permissions.obj_mgmt", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x0200, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_append,
|
|
{"APPEND", "scsi_osd.permissions.append", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x0100, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_dev_mgmt,
|
|
{"DEV_MGMT", "scsi_osd.permissions.dev_mgmt", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x0080, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_global,
|
|
{"GLOBAL", "scsi_osd.permissions.global", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x0040, NULL, HFILL}},
|
|
{ &hf_scsi_osd_permissions_pol_sec,
|
|
{"POL/SEC", "scsi_osd.permissions.pol_sec", FT_BOOLEAN, 16,
|
|
TFS(&tfs_set_notset), 0x0020, NULL, HFILL}},
|
|
|
|
{ &hf_scsi_osd_object_descriptor_type,
|
|
{"Object Descriptor Type", "scsi_osd.object_descriptor_type", FT_UINT8, BASE_HEX,
|
|
VALS(scsi_osd_object_descriptor_type_vals), 0xf0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_object_descriptor,
|
|
{"Object Descriptor", "scsi_osd.object_descriptor", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_ricv,
|
|
{"Request Integrity Check value", "scsi_osd.ricv", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_request_nonce,
|
|
{"Request Nonce", "scsi_osd.request_nonce", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_diicvo,
|
|
{"Data-In Integrity Check Value Offset", "scsi_osd.diicvo", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_doicvo,
|
|
{"Data-Out Integrity Check Value Offset", "scsi_osd.doicvo", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_requested_partition_id,
|
|
{"Requested Partition Id", "scsi_osd.requested_partition_id", FT_UINT64, BASE_HEX,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_sortorder,
|
|
{"Sort Order", "scsi_osd.sort_order", FT_UINT8, BASE_DEC,
|
|
VALS(scsi_osd_sort_order_vals), 0x0f, NULL, HFILL}},
|
|
{ &hf_scsi_osd_partition_id,
|
|
{"Partition Id", "scsi_osd.partition_id", FT_UINT64, BASE_HEX,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_list_identifier,
|
|
{"List Identifier", "scsi_osd.list_identifier", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_allocation_length,
|
|
{"Allocation Length", "scsi_osd.allocation_length", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_length,
|
|
{"Length", "scsi_osd.length", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_starting_byte_address,
|
|
{"Starting Byte Address", "scsi_osd.starting_byte_address", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_initial_object_id,
|
|
{"Initial Object Id", "scsi_osd.initial_object_id", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_additional_length,
|
|
{"Additional Length", "scsi_osd.additional_length", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_continuation_object_id,
|
|
{"Continuation Object Id", "scsi_osd.continuation_object_id", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_user_object_id,
|
|
{"User Object Id", "scsi_osd.user_object_id", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_list_flags_lstchg,
|
|
{"LSTCHG", "scsi_osd.list.lstchg", FT_BOOLEAN, 8,
|
|
TFS(&list_lstchg_tfs), 0x02, NULL, HFILL}},
|
|
{ &hf_scsi_osd_list_flags_root,
|
|
{"ROOT", "scsi_osd.list.root", FT_BOOLEAN, 8,
|
|
TFS(&list_root_tfs), 0x01, NULL, HFILL}},
|
|
{ &hf_scsi_osd_list_collection_flags_coltn,
|
|
{"COLTN", "scsi_osd.list_collection.coltn", FT_BOOLEAN, 8,
|
|
TFS(&list_coltn_tfs), 0x01, NULL, HFILL}},
|
|
{ &hf_scsi_osd_requested_user_object_id,
|
|
{"Requested User Object Id", "scsi_osd.requested_user_object_id", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_number_of_user_objects,
|
|
{"Number Of User Objects", "scsi_osd.number_of_user_objects", FT_UINT16, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_key_to_set,
|
|
{"Key to Set", "scsi_osd.key_to_set", FT_UINT8, BASE_DEC,
|
|
VALS(key_to_set_vals), 0x03, NULL, HFILL}},
|
|
{ &hf_scsi_osd_set_key_version,
|
|
{"Key Version", "scsi_osd.set_key_version", FT_UINT8, BASE_DEC,
|
|
NULL, 0x0f, NULL, HFILL}},
|
|
{ &hf_scsi_osd_key_identifier,
|
|
{"Key Identifier", "scsi_osd.key_identifier", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_seed,
|
|
{"Seed", "scsi_osd.seed", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_collection_fcr,
|
|
{"FCR", "scsi_osd.collection.fcr", FT_BOOLEAN, 8,
|
|
TFS(&tfs_set_notset), 0x01, NULL, HFILL}},
|
|
{ &hf_scsi_osd_collection_object_id,
|
|
{"Collection Object Id", "scsi_osd.collection_object_id", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_requested_collection_object_id,
|
|
{"Requested Collection Object Id", "scsi_osd.requested_collection_object_id", FT_BYTES, BASE_NONE,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_partition_created_in,
|
|
{ "Created In", "scsi_osd.partition.created_in", FT_FRAMENUM, BASE_NONE,
|
|
NULL, 0x0, "The frame this partition was created", HFILL }},
|
|
|
|
{ &hf_scsi_osd_partition_removed_in,
|
|
{ "Removed In", "scsi_osd.partition.removed_in", FT_FRAMENUM, BASE_NONE,
|
|
NULL, 0x0, "The frame this partition was removed", HFILL }},
|
|
|
|
{ &hf_scsi_osd_flush_scope,
|
|
{"Flush Scope", "scsi_osd.flush.scope", FT_UINT8, BASE_DEC,
|
|
VALS(flush_scope_vals), 0x03, NULL, HFILL}},
|
|
|
|
{ &hf_scsi_osd_flush_collection_scope,
|
|
{"Flush Collection Scope", "scsi_osd.flush_collection.scope", FT_UINT8, BASE_DEC,
|
|
VALS(flush_collection_scope_vals), 0x03, NULL, HFILL}},
|
|
|
|
{ &hf_scsi_osd_flush_partition_scope,
|
|
{"Flush Partition Scope", "scsi_osd.flush_partition.scope", FT_UINT8, BASE_DEC,
|
|
VALS(flush_partition_scope_vals), 0x03, NULL, HFILL}},
|
|
|
|
{ &hf_scsi_osd_flush_osd_scope,
|
|
{"Flush OSD Scope", "scsi_osd.flush_osd.scope", FT_UINT8, BASE_DEC,
|
|
VALS(flush_osd_scope_vals), 0x03, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attributes_list_type,
|
|
{"Attributes List Type", "scsi_osd.attributes_list.type", FT_UINT8, BASE_HEX,
|
|
VALS(attributes_list_type_vals), 0x0f, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attributes_list_length,
|
|
{"Attributes List Length", "scsi_osd.attributes_list.length", FT_UINT16, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attributes_page,
|
|
{"Attributes Page", "scsi_osd.attributes.page", FT_UINT32, BASE_HEX | BASE_EXT_STRING,
|
|
&attributes_page_vals_ext, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attribute_number,
|
|
{"Attribute Number", "scsi_osd.attribute.number", FT_UINT32, BASE_HEX,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attribute_length,
|
|
{"Attribute Length", "scsi_osd.attribute.length", FT_UINT16, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_attributes_list_length,
|
|
{"Attributes List Length", "scsi_osd2.attributes_list.length", FT_UINT32, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attrval_user_object_logical_length,
|
|
{"User Object Logical Length", "scsi_osd.user_object.logical_length", FT_UINT64, BASE_DEC,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attrval_object_type,
|
|
{"Object Type", "scsi_osd.attr.object_type", FT_UINT8, BASE_HEX, VALS(scsi_osd_object_type_vals), 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attrval_partition_id,
|
|
{"Partition ID", "scsi_osd.attr.partition_id", FT_UINT64, BASE_HEX,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd_attrval_object_id,
|
|
{"Object ID", "scsi_osd.attr.object_id", FT_UINT64, BASE_HEX,
|
|
NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_set_attribute_value,
|
|
{"Set Attributes Value", "scsi_osd.set_attribute_value", FT_BYTES, BASE_NONE, 0, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_isolation,
|
|
{"Isolation", "scsi_osd2.isolation", FT_UINT8, BASE_HEX, VALS(scsi_osd2_isolation_val), 0x0F, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_list_attr,
|
|
{"LIST ATTR flag", "scsi_osd2.list_attr", FT_BOOLEAN, 8, 0, 0x40, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_object_descriptor_format,
|
|
{"Object Descriptor Format", "scsi_osd2.object_descriptor_format", FT_UINT8, BASE_HEX, VALS(scsi_osd2_object_descriptor_format_val), 0xFC, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_immed_tr,
|
|
{"Immed TR", "scsi_osd2.immed_tr", FT_UINT8, BASE_DEC, 0, 0x80, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_remove_scope,
|
|
{"Remove scope", "scsi_osd2.remove_scope", FT_UINT8, BASE_HEX, VALS(scsi_osd2_remove_scope), 0x07, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_source_collection_object_id,
|
|
{"Source Collection Object ID", "scsi_osd2.source_collection_object_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_matches_collection_object_id,
|
|
{"Matches Collection Object ID", "scsi_osd2.matches_collection_object_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_cdb_continuation_length,
|
|
{"CDB Continuation Length", "scsi_osd2.cdb_continuation.length", FT_UINT32, BASE_DEC, 0, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_cdb_continuation_format,
|
|
{"CDB Continuation Format", "scsi_osd2.cdb_continuation.format", FT_UINT8, BASE_HEX, VALS(scsi_osd2_cdb_continuation_format_val), 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_continued_service_action,
|
|
{"Continued Service Action", "scsi_osd2.cdb_continuation.sa", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_cdb_continuation_descriptor_type,
|
|
{"Descriptor Type", "scsi_osd2.cdb_continuation.desc.type", FT_UINT16, BASE_HEX, VALS(scsi_osd2_cdb_continuation_descriptor_type_val), 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_cdb_continuation_descriptor_pad_length,
|
|
{"Descriptor Pad Length", "scsi_osd2.cdb_continuation.desc.padlen", FT_UINT8, BASE_DEC, NULL, 0x7, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_cdb_continuation_descriptor_length,
|
|
{"Descriptor Length", "scsi_osd2.cdb_continuation.desc.length", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_query_type,
|
|
{"Query Type", "scsi_osd2.query.type", FT_UINT8, BASE_HEX, VALS(scsi_osd2_query_type_vals), 0x0f, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_query_entry_length,
|
|
{"Entry Length", "scsi_osd2.query.entry.length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_query_attributes_page,
|
|
{"Attributes Page", "scsi_osd2.query.entry.page", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &attributes_page_vals_ext, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_query_attribute_number,
|
|
{"Attribute Number", "scsi_osd2.query.entry.number", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_query_minimum_attribute_value_length,
|
|
{"Minimum Attribute Value Length", "scsi_osd2.query.entry.min_length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL}},
|
|
{ &hf_scsi_osd2_query_maximum_attribute_value_length,
|
|
{"Maximum Attribute Value Length", "scsi_osd2.query.entry.max_length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL}},
|
|
};
|
|
|
|
/* Setup protocol subtree array */
|
|
static gint *ett[] = {
|
|
&ett_osd_option,
|
|
&ett_osd_partition,
|
|
&ett_osd_attribute_parameters,
|
|
&ett_osd_capability,
|
|
&ett_osd_permission_bitmask,
|
|
&ett_osd_security_parameters,
|
|
&ett_osd_get_attributes,
|
|
&ett_osd_set_attributes,
|
|
&ett_osd_multi_object,
|
|
&ett_osd_attribute,
|
|
&ett_osd2_query_criteria_entry,
|
|
};
|
|
|
|
/* Setup expert info */
|
|
static ei_register_info ei[] = {
|
|
{ &ei_osd_attr_unknown, { "scsi_osd.attr_unknown", PI_UNDECODED, PI_NOTE, "Unknown attribute, cannot decode attribute value", EXPFILL }},
|
|
{ &ei_osd2_invalid_offset, { "scsi_osd2.invalid_offset", PI_UNDECODED, PI_ERROR, "Invalid offset exponent", EXPFILL }},
|
|
{ &ei_osd2_invalid_object_descriptor_format, { "scsi_osd2.object_descriptor_format.invalid", PI_UNDECODED, PI_ERROR, "Invalid list format", EXPFILL }},
|
|
{ &ei_osd_unknown_attributes_list_type, {"scsi_osd.attributes_list.type.invalid", PI_UNDECODED, PI_ERROR, "Unknown attribute list type", EXPFILL }},
|
|
{ &ei_osd2_cdb_continuation_format_unknown, {"scsi_osd2.cdb_continuation.format.unknown", PI_UNDECODED, PI_ERROR, "Unknown CDB Continuation Format", EXPFILL }},
|
|
{ &ei_osd2_continued_service_action_mismatch, {"scsi_osd2.cdb_continuation.sa.mismatch", PI_PROTOCOL, PI_WARN, "CONTINUED SERVICE ACTION and SERVICE ACTION do not match", EXPFILL }},
|
|
{ &ei_osd2_cdb_continuation_descriptor_type_unknown, {"scsi_osd2.cdb_continuation.desc.type.unknown", PI_UNDECODED, PI_WARN, "Unknown descriptor type", EXPFILL }},
|
|
{ &ei_osd2_cdb_continuation_descriptor_length_invalid, {"scsi_osd2.cdb_continuation.desc.length.invalid", PI_PROTOCOL, PI_ERROR, "Invalid descriptor length (not a multiple of 8)", EXPFILL }},
|
|
{ &ei_osd2_cdb_continuation_length_invalid, {"scsi_osd2.cdb_continuation.length.invalid", PI_PROTOCOL, PI_ERROR, "Invalid CDB continuation length", EXPFILL }},
|
|
{ &ei_osd_attr_length_invalid, {"scsi_osd.attribute_length.invalid", PI_PROTOCOL, PI_ERROR, "Invalid Attribute Length", EXPFILL }},
|
|
{ &ei_osd2_query_values_equal, {"scsi_osd2.query.entry.equal", PI_PROTOCOL, PI_NOTE, "The minimum and maximum values are equal", EXPFILL }},
|
|
};
|
|
|
|
/* Register the protocol name and description */
|
|
proto_scsi_osd = proto_register_protocol("SCSI_OSD", "SCSI_OSD", "scsi_osd");
|
|
|
|
/* Required function calls to register the header fields and subtrees used */
|
|
proto_register_field_array(proto_scsi_osd, hf, array_length(hf));
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
/* Register expert info */
|
|
expert_scsi_osd = expert_register_protocol(proto_scsi_osd);
|
|
expert_register_field_array(expert_scsi_osd, ei, array_length(ei));
|
|
}
|
|
|
|
/*
|
|
* Editor modelines
|
|
*
|
|
* Local Variables:
|
|
* c-basic-offset: 4
|
|
* tab-width: 8
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
*/
|