wireshark/epan/dissectors/packet-scsi-osd.c

4043 lines
141 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
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#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 */
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->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_DEC_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_DEC_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_DEC_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_DEC_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_discriminator", 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:
*/