/* 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 * Copyright 2002 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include "packet-scsi.h" #include "packet-scsi-osd.h" void proto_register_scsi_osd(void); static int proto_scsi_osd; int hf_scsi_osd_opcode; static int hf_scsi_osd_add_cdblen; static int hf_scsi_osd_svcaction; static int hf_scsi_osd_option; static int hf_scsi_osd_option_dpo; static int hf_scsi_osd_option_fua; static int hf_scsi_osd_getsetattrib; static int hf_scsi_osd_timestamps_control; static int hf_scsi_osd_formatted_capacity; static int hf_scsi_osd_get_attributes_page; static int hf_scsi_osd_get_attributes_allocation_length; static int hf_scsi_osd_get_attributes_list_length; static int hf_scsi_osd_get_attributes_list_offset; static int hf_scsi_osd_retrieved_attributes_offset; static int hf_scsi_osd_set_attributes_page; static int hf_scsi_osd_set_attribute_length; static int hf_scsi_osd_set_attribute_number; static int hf_scsi_osd_set_attributes_offset; static int hf_scsi_osd_set_attributes_list_length; static int hf_scsi_osd_set_attributes_list_offset; static int hf_scsi_osd_capability_format; static int hf_scsi_osd_key_version; static int hf_scsi_osd_icva; static int hf_scsi_osd_security_method; static int hf_scsi_osd_capability_expiration_time; static int hf_scsi_osd_audit; static int hf_scsi_osd_capability_discriminator; static int hf_scsi_osd_object_created_time; static int hf_scsi_osd_object_type; static int hf_scsi_osd_permissions; static int hf_scsi_osd_permissions_read; static int hf_scsi_osd_permissions_write; static int hf_scsi_osd_permissions_get_attr; static int hf_scsi_osd_permissions_set_attr; static int hf_scsi_osd_permissions_create; static int hf_scsi_osd_permissions_remove; static int hf_scsi_osd_permissions_obj_mgmt; static int hf_scsi_osd_permissions_append; static int hf_scsi_osd_permissions_dev_mgmt; static int hf_scsi_osd_permissions_global; static int hf_scsi_osd_permissions_pol_sec; static int hf_scsi_osd_object_descriptor_type; static int hf_scsi_osd_object_descriptor; static int hf_scsi_osd_ricv; static int hf_scsi_osd_request_nonce; static int hf_scsi_osd_diicvo; static int hf_scsi_osd_doicvo; static int hf_scsi_osd_requested_partition_id; static int hf_scsi_osd_sortorder; static int hf_scsi_osd_partition_id; static int hf_scsi_osd_list_identifier; static int hf_scsi_osd_allocation_length; static int hf_scsi_osd_length; static int hf_scsi_osd_starting_byte_address; static int hf_scsi_osd_initial_object_id; static int hf_scsi_osd_additional_length; static int hf_scsi_osd_continuation_object_id; static int hf_scsi_osd_list_flags_lstchg; static int hf_scsi_osd_list_flags_root; static int hf_scsi_osd_list_collection_flags_coltn; static int hf_scsi_osd_user_object_id; static int hf_scsi_osd_requested_user_object_id; static int hf_scsi_osd_number_of_user_objects; static int hf_scsi_osd_key_to_set; static int hf_scsi_osd_set_key_version; static int hf_scsi_osd_key_identifier; static int hf_scsi_osd_seed; static int hf_scsi_osd_collection_fcr; static int hf_scsi_osd_collection_object_id; static int hf_scsi_osd_requested_collection_object_id; static int hf_scsi_osd_partition_created_in; static int hf_scsi_osd_partition_removed_in; static int hf_scsi_osd_flush_scope; static int hf_scsi_osd_flush_collection_scope; static int hf_scsi_osd_flush_partition_scope; static int hf_scsi_osd_flush_osd_scope; static int hf_scsi_osd_attributes_list_type; static int hf_scsi_osd_attributes_list_length; static int hf_scsi_osd_attributes_page; static int hf_scsi_osd_attribute_number; static int hf_scsi_osd_attribute_length; static int hf_scsi_osd_attrval_user_object_logical_length; static int hf_scsi_osd_attrval_object_type; static int hf_scsi_osd_attrval_partition_id; static int hf_scsi_osd_attrval_object_id; static int hf_scsi_osd2_query_type; static int hf_scsi_osd2_query_entry_length; static int hf_scsi_osd2_query_attributes_page; static int hf_scsi_osd2_query_attribute_number; static int hf_scsi_osd2_query_minimum_attribute_value_length; static int hf_scsi_osd2_query_maximum_attribute_value_length; /* Fields that are defined in OSD-2 are prefixed with hf_scsi_osd2_ */ static int hf_scsi_osd2_attributes_list_length; static int hf_scsi_osd2_set_attribute_value; static int hf_scsi_osd2_isolation; static int hf_scsi_osd2_immed_tr; static int hf_scsi_osd2_list_attr; static int hf_scsi_osd2_object_descriptor_format; static int hf_scsi_osd2_matches_collection_object_id; static int hf_scsi_osd2_source_collection_object_id; static int hf_scsi_osd2_cdb_continuation_length; static int hf_scsi_osd2_cdb_continuation_format; static int hf_scsi_osd2_continued_service_action; static int hf_scsi_osd2_cdb_continuation_descriptor_type; static int hf_scsi_osd2_cdb_continuation_descriptor_pad_length; static int hf_scsi_osd2_cdb_continuation_descriptor_length; static int hf_scsi_osd2_remove_scope; static int ett_osd_option; static int ett_osd_partition; static int ett_osd_attribute_parameters; static int ett_osd_capability; static int ett_osd_permission_bitmask; static int ett_osd_security_parameters; static int ett_osd_get_attributes; static int ett_osd_set_attributes; static int ett_osd_multi_object; static int ett_osd_attribute; static int ett_osd2_query_criteria_entry; static expert_field ei_osd_attr_unknown; static expert_field ei_osd2_invalid_offset; static expert_field ei_osd2_invalid_object_descriptor_format; static expert_field ei_osd_unknown_attributes_list_type; static expert_field ei_osd2_cdb_continuation_format_unknown; static expert_field ei_osd2_continued_service_action_mismatch; static expert_field ei_osd2_cdb_continuation_descriptor_type_unknown; static expert_field ei_osd2_cdb_continuation_descriptor_length_invalid; static expert_field ei_osd2_cdb_continuation_length_invalid; static expert_field ei_osd_attr_length_invalid; static expert_field ei_osd2_query_values_equal; #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, unsigned offset, bool isreq, bool iscdb, uint32_t 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 { uint16_t svcaction; uint8_t gsatype; union { struct { /* gsatype: attribute list */ uint32_t get_list_length; uint32_t get_list_offset; uint32_t get_list_allocation_length; uint32_t retrieved_list_offset; uint32_t set_list_length; uint32_t set_list_offset; } al; } u; uint32_t continuation_length; bool 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, bool is_created, bool 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 { uint32_t 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(uint32_t page, uint32_t 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 uint32_t dissect_osd_attribute_list_entry(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, proto_item *item, uint32_t offset, scsi_osd_lun_info_t *lun_info, bool osd2) { uint16_t attribute_length; uint32_t 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, bool osd2) { uint8_t type; uint32_t length; uint32_t page, number; int start_offset = offset; proto_item *item, *list_type_item; const attribute_page_numbers_t *apn; /* list type */ type = tvb_get_uint8(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 ( (uint32_t)(offset-start_offset)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; uint8_t option; option = tvb_get_uint8(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_uint8(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, uint32_t *raw_value_ptr, bool osd2) { /* dissects an OSD offset value, add proto item and updates *raw_value_ptr */ uint32_t 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); uint32_t mantissa = (value&0x0FFFFFFF); if (exponent&0x8) { exponent = -(((~exponent)&7)+1); if (exponent <=- 6 && mantissa != 0xFFFFFFF) { proto_item *item; item = proto_tree_add_uint(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) { uint8_t gsatype = 0; proto_tree *tree; scsi_osd_extra_data_t *extra_data = NULL; bool 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) { uint8_t 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) { uint8_t 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, uint32_t offset, proto_tree *tree, scsi_task_data_t *cdata) { scsi_osd_extra_data_t *extra_data; uint32_t 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, uint32_t offset, proto_tree *tree, uint32_t length) { uint32_t 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 (offsetname); } /* 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; iitlq && 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_uint8(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 (offsetcontinuation_length) { uint16_t type; uint32_t 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_uint8(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; uint16_t 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; uint8_t 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_uint8(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, unsigned offset, bool isreq, bool iscdb, unsigned 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, bool is_created, bool is_removed) { proto_item *item = NULL; uint32_t 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, unsigned offset, bool isreq, bool iscdb, unsigned payload_len _U_, scsi_task_data_t *cdata _U_, scsi_osd_conv_info_t *conv_info _U_, scsi_osd_lun_info_t *lun_info) { bool 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 partition 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) { uint64_t alloc_len = tvb_get_ntoh64(tvb, offset); if (alloc_len>INT64_C(0xFFFFFFFF)) { alloc_len = INT64_C(0xFFFFFFFF); } cdata->itlq->alloc_len = (uint32_t)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, unsigned offset, bool isreq, bool iscdb, unsigned payload_len _U_, scsi_task_data_t *cdata _U_, scsi_osd_conv_info_t *conv_info _U_, scsi_osd_lun_info_t *lun_info) { unsigned svcaction = ((scsi_osd_extra_data_t *)cdata->itlq->extra_data)->svcaction; bool list_collection = (svcaction == 0x8817) || (svcaction == 0x8897); bool 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; /* partition 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) { uint64_t additional_length; uint64_t allocation_length; uint64_t remaining_length; bool is_root_or_coltn; uint8_t 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>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_uint8(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)) { uint32_t 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+16itlq->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; /* partition 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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* partition 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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* 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_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, unsigned offset, bool isreq, bool iscdb, unsigned payload_len _U_, scsi_task_data_t *cdata _U_, scsi_osd_conv_info_t *conv_info _U_, scsi_osd_lun_info_t *lun_info) { bool 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; /* 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; /* 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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* 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_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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* partition 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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* 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_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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* 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; /* 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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* 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_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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* partition 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, unsigned offset, bool isreq, bool iscdb, unsigned 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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* partition 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, unsigned offset, bool isreq, bool iscdb, unsigned payload_len _U_, scsi_task_data_t *cdata _U_, scsi_osd_conv_info_t *conv_info _U_, scsi_osd_lun_info_t *lun_info) { bool 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; /* 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_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, unsigned offset, bool isreq, bool iscdb, unsigned 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; /* 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_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, unsigned offset, bool isreq, bool iscdb, unsigned payload_len _U_, scsi_task_data_t *cdata _U_, scsi_osd_conv_info_t *conv_info _U_, scsi_osd_lun_info_t *lun_info) { bool 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; /* 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_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, unsigned offset, bool isreq, bool iscdb, unsigned 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, unsigned offset, bool isreq, bool iscdb, unsigned 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) { uint64_t additional_length; uint64_t allocation_length; uint64_t remaining_length; uint8_t 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>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 { uint16_t 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(uint16_t 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, unsigned offset, bool isreq, bool iscdb, unsigned payload_len, scsi_task_data_t *cdata) { uint16_t 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); const 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 int *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: */