scsi: unusual scsi protocols can request multiple AHS fields for iscsi so decode...
authorsahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 8 Oct 2006 04:13:18 +0000 (04:13 +0000)
committersahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 8 Oct 2006 04:13:18 +0000 (04:13 +0000)
scsi-osd   add dissection of  LIST data pdus  and  CREATE cdb

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@19449 f5534014-38df-0310-8fa8-9805f1628bb7

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

index 081a184e46c44cf35ba9c722882461a67f701692..8e747cc2fd88aadcf74ff014f9670935f5cf4bee 100644 (file)
@@ -101,7 +101,9 @@ static int hf_iscsi_response_frame = -1;
 static int hf_iscsi_AHS = -1;
 static int hf_iscsi_AHS_length = -1;
 static int hf_iscsi_AHS_type = -1;
-static int hf_iscsi_AHS_specific = -1;
+static int hf_iscsi_AHS_blob = -1;
+static int hf_iscsi_AHS_read_data_length = -1;
+static int hf_iscsi_AHS_extended_cdb = -1;
 static int hf_iscsi_Padding = -1;
 static int hf_iscsi_ping_data = -1;
 static int hf_iscsi_immediate_data = -1;
@@ -753,8 +755,8 @@ dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
     guint immediate_data_length=0;
     guint immediate_data_offset=0;
     itl_nexus_t *itl=NULL;
-    guint16 ahs_length=0;
-    guint8 ahs_type=0;
+    guint ahs_cdb_length=0;
+    guint ahs_cdb_offset=0;
 
     if(paddedDataSegmentLength & 3)
        paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
@@ -975,17 +977,51 @@ dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
            proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
            proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
            proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
-           {
-               if(ahsLen > 0) {
-                   ahs_length=tvb_get_ntohs(tvb, offset+48);
-                   proto_tree_add_item(ti, hf_iscsi_AHS_length, tvb, offset + 48, 2, FALSE);
-                   ahs_type=tvb_get_guint8(tvb, offset+50);
-                   proto_tree_add_item(ti, hf_iscsi_AHS_type, tvb, offset + 50, 1, FALSE);
-                   proto_tree_add_item(ti, hf_iscsi_AHS_specific, tvb, offset + 51, 1, FALSE);
-                   proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 52, ahsLen-4, FALSE);
+           if(ahsLen > 0) {
+               int ahs_offset=offset+48;
+               guint16 ahs_length=0;
+               guint8 ahs_type=0;
+
+               while(ahs_offset<(offset+48+ahsLen)){
+
+                   ahs_length=tvb_get_ntohs(tvb, ahs_offset);
+                   proto_tree_add_item(ti, hf_iscsi_AHS_length, tvb, ahs_offset, 2, FALSE);
+                   ahs_offset+=2;
+
+                   ahs_type=tvb_get_guint8(tvb, ahs_offset);
+                   proto_tree_add_item(ti, hf_iscsi_AHS_type, tvb, ahs_offset, 1, FALSE);
+                   ahs_offset++;
+               
+                   switch(ahs_type){
+                   case 0x01: /* extended CDB */
+                       /* additional cdb */
+                       ahs_cdb_offset=ahs_offset+1;
+                       ahs_cdb_length=ahs_length-1;
+                       proto_tree_add_item(ti, hf_iscsi_AHS_extended_cdb, tvb, ahs_cdb_offset, ahs_cdb_length, FALSE);
+                       ahs_offset+=ahs_length;
+                       break;
+                   case 0x02: /* bidirectional read data length */
+                       /* skip reserved byte */
+                       ahs_offset++;
+                       /* read data length */
+                       proto_tree_add_item(ti, hf_iscsi_AHS_read_data_length, tvb, ahs_offset, 4, FALSE);
+                       ahs_offset+=4;
+                       break;
+                   default:
+                       proto_tree_add_item(ti, hf_iscsi_AHS_blob, tvb, ahs_offset, ahs_length, FALSE);
+                       ahs_offset+=ahs_length;
+                   }
+
+                   /* strip off padding bytes */
+                   if(ahs_offset&0x0003){
+                       ahs_offset=(ahs_offset+3)&0xfffc;
+                   }
+
                }
-               offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48 + ahsLen);
+
            }
+           offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48 + ahsLen);
+           
             immediate_data_offset=offset;
            offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
            immediate_data_length=offset-immediate_data_offset;
@@ -1511,21 +1547,21 @@ dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
        tvb_len=tvb_length_remaining(tvb, cdb_offset);
        tvb_rlen=tvb_reported_length_remaining(tvb, cdb_offset);
        scsi_opcode=tvb_get_guint8(tvb, cdb_offset);
-       if(ahs_type==1 && ahs_length && ahs_length<1024){
+       if(ahs_cdb_length && ahs_cdb_length<1024){
                char *cdb_buf;
 
                /* We have a variable length CDB where bytes >16 is transported
                 * in the AHS.
                 */
-               cdb_buf=ep_alloc(16+ahs_length-1);
+               cdb_buf=ep_alloc(16+ahs_cdb_length);
                /* the 16 first bytes of the cdb */
                tvb_memcpy(tvb, cdb_buf, cdb_offset, 16);
-               /* hte remainder of the cdb from the ahs */
-               tvb_memcpy(tvb, cdb_buf+16, cdb_offset+20, ahs_length-1);
+               /* the remainder of the cdb from the ahs */
+               tvb_memcpy(tvb, cdb_buf+16, ahs_cdb_offset, ahs_cdb_length);
 
                cdb_tvb = tvb_new_real_data(cdb_buf,
-                                         ahs_length+16-1,
-                                         ahs_length+16-1);
+                                         ahs_cdb_length+16,
+                                         ahs_cdb_length+16);
 
                tvb_set_child_real_data_tvbuff(tvb, cdb_tvb);
 
@@ -2419,15 +2455,25 @@ proto_register_iscsi(void)
            FT_UINT16, BASE_DEC, NULL, 0,
            "Length of Additional header segment", HFILL }
        },
+       { &hf_iscsi_AHS_read_data_length,
+         { "Bidirectional Read Data Length", "iscsi.ahs.bidir.length",
+           FT_UINT32, BASE_DEC, NULL, 0,
+           "", HFILL }
+       },
        { &hf_iscsi_AHS_type,
          { "AHS Type", "iscsi.ahs.type",
            FT_UINT8, BASE_DEC, VALS(ahs_type_vals), 0,
            "Type of Additional header segment", HFILL }
        },
-       { &hf_iscsi_AHS_specific,
-         { "AHS Specific", "iscsi.ahs",
-           FT_UINT8, BASE_HEX, NULL, 0,
-           "Specific qualifier of Additional header segment", HFILL }
+       { &hf_iscsi_AHS_extended_cdb,
+         { "AHS Extended CDB", "iscsi.ahs.extended_cdb",
+           FT_BYTES, BASE_HEX, NULL, 0,
+           "", HFILL }
+       },
+       { &hf_iscsi_AHS_blob,
+         { "Unknown AHS blob", "iscsi.ahs.unknown_blob",
+           FT_BYTES, BASE_HEX, NULL, 0,
+           "", HFILL }
        },
        { &hf_iscsi_Padding,
          { "Padding", "iscsi.padding",
index 0b6ba26327dd02d56fdf96a4e2a0d35ade02905d..74ea55822b6a55506067acdfcb4d8dc8a955d8f7 100644 (file)
@@ -78,6 +78,13 @@ static int hf_scsi_osd_partition_id  = -1;
 static int hf_scsi_osd_list_identifier = -1;
 static int hf_scsi_osd_allocation_length= -1;
 static int hf_scsi_osd_initial_object_id= -1;
+static int hf_scsi_osd_additional_length= -1;
+static int hf_scsi_osd_continuation_object_id= -1;
+static int hf_scsi_osd_list_flags_lstchg= -1;
+static int hf_scsi_osd_list_flags_root= -1;
+static int hf_scsi_osd_user_object_id= -1;
+static int hf_scsi_osd_requested_user_object_id        = -1;
+static int hf_scsi_osd_number_of_user_objects  = -1;
 
 static gint ett_osd_option             = -1;
 
@@ -362,7 +369,7 @@ dissect_osd_requested_partition_id(tvbuff_t *tvb, int offset, proto_tree *tree)
 static void
 dissect_osd_partition_id(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       /* request partition id */
+       /* partition id */
        proto_tree_add_item(tree, hf_scsi_osd_partition_id, tvb, offset, 8, 0);
        offset+=8;
 }
@@ -459,6 +466,40 @@ dissect_osd_initial_object_id(tvbuff_t *tvb, int offset, proto_tree *tree)
        offset+=8;
 }
 
+static void
+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, 0);
+       offset+=8;
+}
+
+
+static void
+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, 0);
+       offset+=8;
+}
+
+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 a partition and are USER OBJECTs"
+};
+
+static void
+dissect_osd_user_object_id(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       /* user object id */
+       proto_tree_add_item(tree, hf_scsi_osd_user_object_id, tvb, offset, 8, 0);
+       offset+=8;
+}
+
 static void
 dissect_osd_list(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
                         guint offset, gboolean isreq, gboolean iscdb,
@@ -521,8 +562,123 @@ dissect_osd_list(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
 
        /* dissecting the DATA IN */
        if(!isreq && !iscdb){
+               guint64 additional_length;
+               gboolean is_root;
+
                /* dissection of the LIST DATA-IN */
-/* qqq to be added ... */
+               /* additional length */
+               additional_length=tvb_get_ntoh64(tvb, offset);
+               dissect_osd_additional_length(tvb, offset, tree);
+               offset+=8;
+
+               /* continuation object id */
+               dissect_osd_continuation_object_id(tvb, offset, tree);
+               offset+=8;
+
+               /* list identifier */
+               dissect_osd_list_identifier(tvb, offset, tree);
+               offset+=4;
+
+               /* 3 reserved bytes */
+               offset+=3;
+
+               /* LSTCHG and ROOT flags */
+               proto_tree_add_item(tree, hf_scsi_osd_list_flags_lstchg, tvb, offset, 1, 0);
+               proto_tree_add_item(tree, hf_scsi_osd_list_flags_root, tvb, offset, 1, 0);
+               is_root=tvb_get_guint8(tvb, offset)&0x01;
+               offset++;
+
+
+               /* list of user object ids or partition ids */
+               while(additional_length > (offset-8)){
+                       if(is_root){
+                               dissect_osd_partition_id(tvb, offset, tree);
+                       } else {
+                               dissect_osd_user_object_id(tvb, offset, tree);
+                       }
+                       offset+=8;
+               }
+       }
+       
+}
+
+static void
+dissect_osd_requested_user_object_id(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       /* request user object id */
+       proto_tree_add_item(tree, hf_scsi_osd_requested_user_object_id, tvb, offset, 8, 0);
+       offset+=8;
+}
+
+static void
+dissect_osd_number_of_user_objects(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+       /* number_of_user_objects */
+       proto_tree_add_item(tree, hf_scsi_osd_number_of_user_objects, tvb, offset, 2, 0);
+       offset+=2;
+}
+
+static void
+dissect_osd_create(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+                        guint offset, gboolean isreq, gboolean iscdb,
+                        guint payload_len _U_, scsi_task_data_t *cdata _U_)
+{
+       /* dissecting the CDB   dissection starts at byte 10 of the CDB */
+       if(isreq && iscdb){
+               /* options byte */
+               dissect_osd_option(tvb, offset, tree);
+               offset++;
+
+               /* getset attributes byte */
+               dissect_osd_getsetattrib(tvb, offset, tree, cdata);
+               offset++;
+
+               /* timestamps control */
+               dissect_osd_timestamps_control(tvb, offset, tree);
+               offset++;
+
+               /* 3 reserved bytes */
+               offset+=3;
+
+               /* partiton id */
+               dissect_osd_partition_id(tvb, offset, tree);
+               offset+=8;
+
+               /* requested user_object id */
+               dissect_osd_requested_user_object_id(tvb, offset, tree);
+               offset+=8;
+
+               /* 4 reserved bytes */
+               offset+=4;
+
+               /* number of user objects */
+               dissect_osd_number_of_user_objects(tvb, offset, tree);
+               offset+=2;
+
+               /* 14 reserved bytes */
+               offset+=14;
+
+               /* attribute parameters */
+               dissect_osd_attribute_parameters(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){
+               /* no data out for create */
+       }
+
+       /* dissecting the DATA IN */
+       if(!isreq && !iscdb){
+               /* no data in for create */
        }
        
 }
@@ -530,10 +686,12 @@ dissect_osd_list(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
 
 /* OSD Service Actions */
 #define OSD_FORMAT_OSD         0x8801
+#define OSD_CREATE             0x8802
 #define OSD_LIST               0x8803
 #define OSD_CREATE_PARTITION   0x880b
 static const value_string scsi_osd_svcaction_vals[] = {
     {OSD_FORMAT_OSD,           "Format OSD"},
+    {OSD_CREATE,               "Create"},
     {OSD_LIST,                 "List"},
     {OSD_CREATE_PARTITION,     "Create Partition"},
     {0, NULL},
@@ -546,6 +704,7 @@ typedef struct _scsi_osd_svcaction_t {
 } 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_CREATE_PARTITION,     dissect_osd_create_partition},
     {0, NULL},
@@ -1042,6 +1201,27 @@ proto_register_scsi_osd(void)
         { &hf_scsi_osd_initial_object_id,
           {"Initial Object Id", "scsi.osd.initial_object_id", FT_BYTES, BASE_HEX,
            NULL, 0, "", HFILL}},
+       { &hf_scsi_osd_additional_length,
+          {"Additional Length", "scsi.osd.additional_length", FT_UINT64, BASE_DEC,
+           NULL, 0, "", HFILL}},
+        { &hf_scsi_osd_continuation_object_id,
+          {"Continuation Object Id", "scsi.osd.continuation_object_id", FT_BYTES, BASE_HEX,
+           NULL, 0, "", HFILL}},
+        { &hf_scsi_osd_user_object_id,
+          {"User Object Id", "scsi.osd.user_object_id", FT_BYTES, BASE_HEX,
+           NULL, 0, "", HFILL}},
+        { &hf_scsi_osd_list_flags_lstchg,
+          {"LSTCHG", "scsi.osd.list.lstchg", FT_BOOLEAN, 8,
+           TFS(&list_lstchg_tfs), 0x02, "", HFILL}},
+        { &hf_scsi_osd_list_flags_root,
+          {"ROOT", "scsi.osd.list.root", FT_BOOLEAN, 8,
+           TFS(&list_root_tfs), 0x01, "", HFILL}},
+        { &hf_scsi_osd_requested_user_object_id,
+          {"Requested User Object Id", "scsi.osd.requested_user_object_id", FT_BYTES, BASE_HEX,
+           NULL, 0, "", HFILL}},
+       { &hf_scsi_osd_number_of_user_objects,
+          {"Number Of User Objects", "scsi.osd.number_of_user_objects", FT_UINT16, BASE_DEC,
+           NULL, 0, "", HFILL}},
        };
 
        /* Setup protocol subtree array */