Include files from the "epan" directory and subdirectories thereof with
[obnox/wireshark/wip.git] / packet-scsi.c
1 /* packet-scsi.c
2  * Routines for decoding SCSI CDBs and responses
3  * Author: Dinesh G Dutt (ddutt@cisco.com)
4  *
5  * $Id: packet-scsi.c,v 1.3 2002/01/21 07:36:41 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 2002 Gerald Combs
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 /*
27  * Some Notes on using the SCSI Decoder:
28  *
29  * The SCSI decoder has been built right now that it is invoked directly by the
30  * SCSI transport layers as compared to the standard mechanism of being invoked
31  * via a dissector chain. There are multiple reasons for this:
32  * - The SCSI CDB is typically embedded inside the transport alongwith other
33  *   header fields that have nothing to do with SCSI. So, it is required to be
34  *   invoked on a embedded subset of the packet.
35  * - Originally, Ethereal couldn't do filtering on protocol trees that were not
36  *   on the top level.
37  *
38  * There are four main routines that are provided:
39  * o dissect_scsi_cdb - invoked on receiving a SCSI Command
40  *   void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *, guint,
41  *   guint); 
42  * o dissect_scsi_payload - invoked to decode SCSI responses
43  *   void dissect_scsi_payload (tvbuff_t *, packet_info *, proto_tree *, guint,
44  *                              gboolean, guint32);
45  *   The final parameter is the length of the response field that is negotiated
46  *   as part of the SCSI transport layer. If this is not tracked by the
47  *   transport, it can be set to 0.
48  * o dissect_scsi_rsp - invoked to destroy the data structures associated with a
49  *                      SCSI task.
50  *   void dissect_scsi_rsp (tvbuff_t *, packet_info *, proto_tree *);
51  * o dissect_scsi_snsinfo - invoked to decode the sense data provided in case of
52  *                          an error.
53  *   void dissect_scsi_snsinfo (tvbuff_t *, packet_info *, proto_tree *, guint,
54  *   guint);
55  *
56  * In addition to this, the other requirement made from the transport is to
57  * provide a unique way to determine a SCSI task. In Fibre channel networks,
58  * this is the exchange ID pair alongwith the source/destination addresses; in
59  * iSCSI it is the initiator task tag along with the src/dst address and port
60  * numbers. This is to be provided to the SCSI decoder via the private_data
61  * field in the packet_info data structure. The private_data field is treated
62  * as a 32-bit field to uniquely identify a SCSI task. 
63  *
64  * This decoder attempts to track the type of SCSI device based on the response
65  * to the Inquiry command. If the trace does not contain an Inquiry command,
66  * the decoding of the commands is done as per a user preference. Currently,
67  * only SBC (disks) and SSC (tapes) are the alternatives offered. The basic
68  * SCSI command set (SPC-2/3) is decoded for all SCSI devices. If there is a
69  * mixture of devices in the trace, some with Inquiry response and some
70  * without, the user preference is used only for those devices whose type the
71  * decoder has not been able to determine. 
72  *
73  */
74 #ifdef HAVE_CONFIG_H
75 # include "config.h"
76 #endif
77
78 #ifdef HAVE_SYS_TYPES_H
79 # include <sys/types.h>
80 #endif
81
82 #include <glib.h>
83 #include <string.h>
84 #include <epan/strutil.h>
85 #include <epan/conversation.h>
86 #include "prefs.h"
87 #include "packet-scsi.h"
88
89 static int proto_scsi                    = -1;
90 static int hf_scsi_spcopcode             = -1;
91 static int hf_scsi_sbcopcode             = -1;
92 static int hf_scsi_control               = -1;
93 static int hf_scsi_inquiry_flags         = -1;
94 static int hf_scsi_inquiry_evpd_page     = -1;
95 static int hf_scsi_inquiry_cmdt_page     = -1;
96 static int hf_scsi_alloclen              = -1;
97 static int hf_scsi_logsel_flags          = -1;
98 static int hf_scsi_log_pc                = -1;
99 static int hf_scsi_paramlen              = -1;
100 static int hf_scsi_logsns_flags          = -1;
101 static int hf_scsi_logsns_pagecode       = -1;
102 static int hf_scsi_paramlen16            = -1;
103 static int hf_scsi_modesel_flags         = -1;
104 static int hf_scsi_alloclen16            = -1;
105 static int hf_scsi_modesns_pc            = -1;
106 static int hf_scsi_modesns_pagecode      = -1;
107 static int hf_scsi_modesns_flags         = -1;
108 static int hf_scsi_persresvin_svcaction  = -1;
109 static int hf_scsi_persresvout_svcaction = -1;
110 static int hf_scsi_persresv_scope        = -1;
111 static int hf_scsi_persresv_type         = -1;
112 static int hf_scsi_release_flags         = -1;
113 static int hf_scsi_release_thirdpartyid  = -1;
114 static int hf_scsi_alloclen32            = -1;
115 static int hf_scsi_formatunit_flags      = -1;
116 static int hf_scsi_formatunit_interleave = -1;
117 static int hf_scsi_formatunit_vendor     = -1;
118 static int hf_scsi_rdwr6_lba             = -1;
119 static int hf_scsi_rdwr6_xferlen         = -1;
120 static int hf_scsi_rdwr10_lba            = -1;
121 static int hf_scsi_read_flags            = -1;
122 static int hf_scsi_rdwr12_xferlen        = -1;
123 static int hf_scsi_rdwr16_lba            = -1;
124 static int hf_scsi_readcapacity_flags    = -1;
125 static int hf_scsi_readcapacity_lba      = -1;
126 static int hf_scsi_readcapacity_pmi      = -1;
127 static int hf_scsi_rdwr10_xferlen        = -1;
128 static int hf_scsi_readdefdata_flags     = -1;
129 static int hf_scsi_cdb_defectfmt         = -1;
130 static int hf_scsi_reassignblks_flags    = -1;
131 static int hf_scsi_inq_devtype           = -1;
132 static int hf_scsi_inq_version           = -1;
133 static int hf_scsi_rluns_lun             = -1;
134 static int hf_scsi_rluns_multilun        = -1;
135 static int hf_scsi_modesns_errrep        = -1;
136 static int hf_scsi_modesns_tst           = -1;
137 static int hf_scsi_modesns_qmod          = -1;
138 static int hf_scsi_modesns_qerr          = -1;
139 static int hf_scsi_modesns_rac           = -1;
140 static int hf_scsi_modesns_tas           = -1;
141 static int hf_scsi_protocol              = -1;
142 static int hf_scsi_sns_errtype           = -1;
143 static int hf_scsi_snskey                = -1;
144 static int hf_scsi_snsinfo               = -1;
145 static int hf_scsi_addlsnslen            = -1;
146 static int hf_scsi_asc                   = -1;
147 static int hf_scsi_ascascq               = -1;
148 static int hf_scsi_ascq                  = -1;
149 static int hf_scsi_fru                   = -1;
150 static int hf_scsi_sksv                  = -1;
151 static int hf_scsi_inq_normaca           = -1;
152 static int hf_scsi_persresv_key          = -1;
153 static int hf_scsi_persresv_scopeaddr    = -1;
154 static int hf_scsi_sscopcode             = -1;
155
156
157 static gint ett_scsi         = -1;
158 static gint ett_scsi_page    = -1;
159 static gint scsi_def_devtype = SCSI_DEV_SBC;
160
161 /* The next two structures are used to track SCSI req/rsp */ 
162 typedef struct _scsi_task_key {
163     guint32 conv_idx;
164 } scsi_task_key_t;
165
166 typedef struct _scsi_task_data {
167     guint32 opcode;
168     scsi_device_type devtype;
169     guint8 flags;               /* used by SCSI Inquiry */
170 } scsi_task_data_t;
171
172 /* The next two data structures are used to track SCSI device type */
173 typedef struct _scsi_devtype_key {
174     address devid;
175 } scsi_devtype_key_t;
176
177 typedef struct _scsi_devtype_data {
178     scsi_device_type devtype;
179 } scsi_devtype_data_t;
180
181 static GHashTable *scsi_req_hash = NULL;
182 static GMemChunk *scsi_req_keys = NULL;
183 static GMemChunk *scsi_req_vals = NULL;
184 static guint32 scsi_init_count = 25;
185
186 static GHashTable *scsidev_req_hash = NULL;
187 static GMemChunk *scsidev_req_keys = NULL;
188 static GMemChunk *scsidev_req_vals = NULL;
189 static guint32 scsidev_init_count = 25;
190
191 static dissector_handle_t data_handle;
192
193 /*
194  * Hash Functions
195  */
196 static gint
197 scsi_equal(gconstpointer v, gconstpointer w)
198 {
199   scsi_task_key_t *v1 = (scsi_task_key_t *)v;
200   scsi_task_key_t *v2 = (scsi_task_key_t *)w;
201
202   return (v1->conv_idx == v2->conv_idx);
203 }
204
205 static guint
206 scsi_hash (gconstpointer v)
207 {
208         scsi_task_key_t *key = (scsi_task_key_t *)v;
209         guint val;
210
211         val = key->conv_idx;
212
213         return val;
214 }
215
216 static gint
217 scsidev_equal (gconstpointer v, gconstpointer w)
218 {
219     scsi_devtype_key_t *k1 = (scsi_devtype_key_t *)v;
220     scsi_devtype_key_t *k2 = (scsi_devtype_key_t *)w;
221
222     if (ADDRESSES_EQUAL (&k1->devid, &k2->devid))
223         return 1;
224     else
225         return 0;
226 }
227
228 static guint
229 scsidev_hash (gconstpointer v)
230 {
231     scsi_devtype_key_t *key = (scsi_devtype_key_t *)v;
232     guint val;
233     int i;
234
235     val = 0;
236     for (i = 0; i < key->devid.len; i++)
237         val += key->devid.data[i];
238     val += key->devid.type;
239
240     return val;
241 }
242
243 static scsi_task_data_t *
244 scsi_new_task (packet_info *pinfo)
245 {
246     scsi_task_data_t *cdata = NULL;
247     scsi_task_key_t ckey, *req_key;
248     conversation_t *conversation;
249     
250     if ((pinfo != NULL) && (pinfo->private_data)) {
251         ckey.conv_idx = (guint32)pinfo->private_data;
252
253         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
254                                                          &ckey);
255         if (!cdata) {
256             req_key = g_mem_chunk_alloc (scsi_req_keys);
257             req_key->conv_idx = (guint32 )pinfo->private_data;
258             
259             cdata = g_mem_chunk_alloc (scsi_req_vals);
260             
261             g_hash_table_insert (scsi_req_hash, req_key, cdata);
262         }
263     }
264     return (cdata);
265 }
266
267 static scsi_task_data_t *
268 scsi_find_task (packet_info *pinfo)
269 {
270     scsi_task_data_t *cdata = NULL;
271     scsi_task_key_t ckey, *req_key;
272     conversation_t *conversation;
273
274     if ((pinfo != NULL) && (pinfo->private_data)) {
275         ckey.conv_idx = (guint32)pinfo->private_data;
276
277         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
278                                                          &ckey);
279     }
280     return (cdata);
281 }
282
283 static void
284 scsi_end_task (packet_info *pinfo)
285 {
286     scsi_task_data_t *cdata = NULL;
287     scsi_task_key_t ckey, *req_key;
288     conversation_t *conversation;
289
290     if ((pinfo != NULL) && (pinfo->private_data)) {
291         ckey.conv_idx = (guint32)pinfo->private_data;
292         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
293                                                          &ckey);
294         if (cdata) {
295             g_mem_chunk_free (scsi_req_vals, cdata);
296             g_hash_table_remove (scsi_req_hash, &ckey);
297         }
298     }
299 }
300
301 /*
302  * Protocol initialization
303  */
304 static void
305 scsi_init_protocol(void)
306 {
307         if (scsi_req_keys)
308             g_mem_chunk_destroy(scsi_req_keys);
309         if (scsi_req_vals)
310             g_mem_chunk_destroy(scsi_req_vals);
311         if (scsidev_req_keys)
312             g_mem_chunk_destroy (scsidev_req_keys);
313         if (scsidev_req_vals)
314             g_mem_chunk_destroy (scsidev_req_vals);
315         if (scsi_req_hash)
316             g_hash_table_destroy(scsi_req_hash);
317         if (scsidev_req_hash)
318             g_hash_table_destroy (scsidev_req_hash);
319
320         scsi_req_hash = g_hash_table_new(scsi_hash, scsi_equal);
321         scsi_req_keys = g_mem_chunk_new("scsi_req_keys",
322                                         sizeof(scsi_task_key_t),
323                                         scsi_init_count *
324                                         sizeof(scsi_task_key_t),
325                                         G_ALLOC_AND_FREE);
326         scsi_req_vals = g_mem_chunk_new("scsi_req_vals",
327                                         sizeof(scsi_task_data_t),
328                                         scsi_init_count *
329                                         sizeof(scsi_task_data_t),
330                                         G_ALLOC_AND_FREE);
331         scsidev_req_hash = g_hash_table_new (scsidev_hash, scsidev_equal);
332         scsidev_req_keys = g_mem_chunk_new("scsidev_req_keys",
333                                            sizeof(scsi_devtype_key_t),
334                                            scsidev_init_count *
335                                            sizeof(scsi_devtype_key_t),
336                                            G_ALLOC_AND_FREE);
337         scsidev_req_vals = g_mem_chunk_new("scsidev_req_vals",
338                                            sizeof(scsi_devtype_data_t),
339                                            scsidev_init_count *
340                                            sizeof(scsi_devtype_data_t),
341                                            G_ALLOC_AND_FREE);
342 }
343
344 static void
345 dissect_scsi_evpd (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
346                    guint offset, guint tot_len)
347 {
348     proto_tree *evpd_tree;
349     proto_item *ti;
350     guint pcode, plen, i, idlen;
351     guint8 flags;
352     char str[32];
353
354     if (tree) {
355         pcode = tvb_get_guint8 (tvb, offset+1);
356         plen = tvb_get_guint8 (tvb, offset+3);
357         ti = proto_tree_add_text (tree, tvb, offset, plen+4, "Page Code: %s",
358                                   val_to_str (pcode, scsi_evpd_pagecode_val,
359                                               "Unknown (0x%08x)"));
360         evpd_tree = proto_item_add_subtree (ti, ett_scsi_page);
361         
362         proto_tree_add_text (evpd_tree, tvb, offset, 1,
363                              "Peripheral Qualifier: 0x%x",
364                              (tvb_get_guint8 (tvb, offset) & 0xF0)>>4);
365         proto_tree_add_item (evpd_tree, hf_scsi_inq_devtype, tvb, offset,
366                              1, 0);
367         proto_tree_add_text (evpd_tree, tvb, offset+1, 1,
368                              "Page Code: %s",
369                              val_to_str (pcode, scsi_evpd_pagecode_val,
370                                          "Unknown (0x%02x)"));
371         proto_tree_add_text (evpd_tree, tvb, offset+3, 1,
372                              "Page Length: %u", plen);
373         offset += 4;
374         switch (pcode) {
375         case SCSI_EVPD_SUPPPG:
376             for (i = 0; i < plen; i++) {
377                 proto_tree_add_text (evpd_tree, tvb, offset+i, 1,
378                                      "Supported Page: %s",
379                                      val_to_str (tvb_get_guint8 (tvb, offset+i),
380                                                  scsi_evpd_pagecode_val,
381                                                  "Unknown (0x%02x)"));
382             }
383             break;
384         case SCSI_EVPD_DEVID:
385             while (plen > 0) {
386                 flags = tvb_get_guint8 (tvb, offset);
387                 proto_tree_add_text (evpd_tree, tvb, offset, 1,
388                                      "Code Set: %s",
389                                      val_to_str (plen & 0x0F,
390                                                  scsi_devid_codeset_val,
391                                                  "Unknown (0x%02x)"));
392                 flags = tvb_get_guint8 (tvb, offset+1);
393                 proto_tree_add_text (evpd_tree, tvb, offset+1, 1,
394                                      "Association: %s",
395                                      val_to_str ((flags & 0x30) >> 4,
396                                                  scsi_devid_assoc_val,
397                                                  "Unknown (0x%02x)"));
398                 proto_tree_add_text (evpd_tree, tvb, offset+1, 1,
399                                      "Identifier Type: %s", 
400                                      val_to_str ((flags & 0x0F),
401                                                  scsi_devid_idtype_val, 
402                                                  "Unknown (0x%02x)"));
403                 idlen = tvb_get_guint8 (tvb, offset+3);
404                 proto_tree_add_text (evpd_tree, tvb, offset+3, 1,
405                                      "Identifier Length: %u", idlen);
406                 proto_tree_add_text (evpd_tree, tvb, offset+4, idlen,
407                                          "Identifier: %s",
408                                          tvb_bytes_to_str (tvb, offset+4,
409                                                            idlen));
410                 plen -= idlen;
411                 offset += idlen;
412             }
413             break;
414         case SCSI_EVPD_DEVSERNUM:
415             str[0] = '\0';
416             tvb_get_nstringz0 (tvb, offset, plen, str);
417             proto_tree_add_text (evpd_tree, tvb, offset, plen,
418                                  "Product Serial Number: %s", str);
419             break;
420         }
421     }
422 }
423
424 static void
425 dissect_scsi_cmddt (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
426                     guint offset, guint tot_len)
427 {
428     proto_tree *cmdt_tree;
429     proto_item *ti;
430     guint opcode, plen, i;
431     guint8 flags;
432
433     if (tree) {
434         plen = tvb_get_guint8 (tvb, offset+5);
435         ti = proto_tree_add_text (tree, tvb, offset, plen, "Command Data");
436         cmdt_tree = proto_item_add_subtree (ti, ett_scsi_page);
437
438         proto_tree_add_text (cmdt_tree, tvb, offset, 1,
439                              "Peripheral Qualifier: 0x%x",
440                              (tvb_get_guint8 (tvb, offset) & 0xF0)>>4);
441         proto_tree_add_item (cmdt_tree, hf_scsi_inq_devtype, tvb, offset,
442                              1, 0);
443         proto_tree_add_text (cmdt_tree, tvb, offset+1, 1, "Support: %s",
444                              match_strval (tvb_get_guint8 (tvb, offset+1) & 0x7,
445                                            scsi_cmdt_supp_val));
446         proto_tree_add_text (cmdt_tree, tvb, offset+2, 1, "Version: %s",
447                              val_to_str (tvb_get_guint8 (tvb, offset+2),
448                                          scsi_verdesc_val,
449                                          "Unknown (0x%02x)"));
450         proto_tree_add_text (cmdt_tree, tvb, offset+5, 1, "CDB Size: %u",
451                              plen);
452     }
453 }
454
455 void
456 dissect_scsi_inquiry (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
457                       guint offset, gboolean isreq, gboolean iscdb,
458                       guint32 payload_len, scsi_task_data_t *cdata)
459 {
460     guint8 flags, i;
461     gchar str[32];
462     guint tot_len, pcode, plen, replen;
463     conversation_t *conversation;
464     scsi_device_type dev = 0;
465     scsi_devtype_data_t *devdata = NULL;
466     scsi_devtype_key_t dkey, *req_key;
467
468     if (!tree)
469         return;
470     
471     if (isreq && iscdb) {
472         flags = tvb_get_guint8 (tvb, offset);
473         if (cdata != NULL) {
474             cdata->flags = flags;
475         }
476         
477         proto_tree_add_uint_format (tree, hf_scsi_inquiry_flags, tvb, offset, 1,
478                                     flags, "CMDT = %u, EVPD = %u",
479                                     flags & 0x2, flags & 0x1);
480         if (flags & 0x1) {
481             proto_tree_add_item (tree, hf_scsi_inquiry_evpd_page, tvb, offset+1,
482                                  1, 0);
483         }
484         else if (flags & 0x2) {
485             proto_tree_add_item (tree, hf_scsi_inquiry_cmdt_page, tvb, offset+1,
486                                  1, 0);
487         }
488
489         proto_tree_add_uint (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
490         flags = tvb_get_guint8 (tvb, offset+4);
491         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
492                                     flags,
493                                     "Vendor Unique = %u, NACA = %u, Link = %u",
494                                     flags & 0xC0, flags & 0x4, flags & 0x1);
495     }
496     else if (!isreq) {
497         if (cdata && (cdata->flags & 0x1)) {
498             dissect_scsi_evpd (tvb, pinfo, tree, offset, payload_len);
499             return;
500         }
501         else if (cdata && (cdata->flags & 0x2)) {
502             dissect_scsi_cmddt (tvb, pinfo, tree, offset, payload_len);
503             return;
504         }
505
506         /* Add device type to list of known devices & their types */
507         COPY_ADDRESS (&(dkey.devid), &(pinfo->src));
508         devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
509                                                               &dkey);
510         if (!devdata) {
511             req_key = g_mem_chunk_alloc (scsidev_req_keys);
512             COPY_ADDRESS (&(req_key->devid), &(pinfo->src));
513
514             devdata = g_mem_chunk_alloc (scsidev_req_vals);
515             devdata->devtype = tvb_get_guint8 (tvb, offset) & 0x10;
516
517             g_hash_table_insert (scsidev_req_hash, req_key, devdata);
518         }
519         
520         proto_tree_add_text (tree, tvb, offset, 1, "Peripheral Qualifier: 0x%x",
521                              (tvb_get_guint8 (tvb, offset) & 0xF0)>>4);
522         proto_tree_add_item (tree, hf_scsi_inq_devtype, tvb, offset, 1, 0);
523         proto_tree_add_item (tree, hf_scsi_inq_version, tvb, offset+2, 1, 0);
524
525         flags = tvb_get_guint8 (tvb, offset+3);
526         proto_tree_add_item_hidden (tree, hf_scsi_inq_normaca, tvb,
527                                     offset+3, 1, 0);
528         proto_tree_add_text (tree, tvb, offset+3, 1, "NormACA: %u, HiSup: %u",
529                              ((flags & 0x20) >> 5), ((flags & 0x10) >> 4));
530         tot_len = tvb_get_guint8 (tvb, offset+4);
531         proto_tree_add_text (tree, tvb, offset+4, 1, "Additional Length: %u",
532                              tot_len);
533         flags = tvb_get_guint8 (tvb, offset+6);
534         proto_tree_add_text (tree, tvb, offset+6, 1,
535                              "BQue: %u, SES: %u, MultiP: %u, Addr16: %u",
536                              ((flags & 0x80) >> 7), (flags & 0x40) >> 6,
537                              (flags & 10) >> 4, (flags & 0x01));
538         flags = tvb_get_guint8 (tvb, offset+7);
539         proto_tree_add_text (tree, tvb, offset+7, 1,
540                              "RelAdr: %u, Linked: %u, CmdQue: %u",
541                              (flags & 0x80) >> 7, (flags & 0x08) >> 3,
542                              (flags & 0x02) >> 1);
543         tvb_get_nstringz0 (tvb, offset+8, 8, str);
544         proto_tree_add_text (tree, tvb, offset+8, 8, "Vendor Id: %s", str);
545         tvb_get_nstringz0 (tvb, offset+16, 16, str);
546         proto_tree_add_text (tree, tvb, offset+16, 16, "Product ID: %s", str);
547         tvb_get_nstringz0 (tvb, offset+32, 4, str);
548         proto_tree_add_text (tree, tvb, offset+32, 4, "Product Revision: %s",
549                              str);
550         
551         offset += 58;
552         if ((tot_len > 58) && tvb_bytes_exist (tvb, offset, 16)) {
553             for (i = 0; i < 8; i++) {
554                 proto_tree_add_text (tree, tvb, offset, 2,
555                                      "Vendor Descriptor %u: %s",
556                                      i,
557                                      val_to_str (tvb_get_ntohs (tvb, offset),
558                                                  scsi_verdesc_val,
559                                                  "Unknown (0x%04x)"));
560                 offset += 2;
561             }
562         }
563     }
564 }
565
566 static void
567 dissect_scsi_extcopy (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
568                       guint offset, gboolean isreq, gboolean iscdb)
569 {
570     
571 }
572
573 static void
574 dissect_scsi_logselect (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
575                         guint offset, gboolean isreq, gboolean iscdb)
576 {
577     guint8 flags;
578     
579     if (!tree)
580         return;
581     
582     if (isreq && iscdb) {
583         flags = tvb_get_guint8 (tvb, offset);
584         
585         proto_tree_add_uint_format (tree, hf_scsi_logsel_flags, tvb, offset, 1,
586                                     flags, "PCR = %u, SP = %u", flags & 0x2,
587                                     flags & 0x1);
588         proto_tree_add_uint_format (tree, hf_scsi_log_pc, tvb, offset+1, 1,
589                                     tvb_get_guint8 (tvb, offset+1),
590                                     "PC: 0x%x", flags & 0xC0);
591         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
592
593         flags = tvb_get_guint8 (tvb, offset+8);
594         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
595                                     flags,
596                                     "Vendor Unique = %u, NACA = %u, Link = %u",
597                                     flags & 0xC0, flags & 0x4, flags & 0x1);
598     }
599     else {
600     }
601 }
602
603 static void
604 dissect_scsi_logsense (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
605                        guint offset, gboolean isreq, gboolean iscdb)
606 {
607     guint8 flags;
608     
609     if (!tree)
610         return;
611     
612     if (isreq && iscdb) {
613         flags = tvb_get_guint8 (tvb, offset);
614         
615         proto_tree_add_uint_format (tree, hf_scsi_logsns_flags, tvb, offset, 1,
616                                     flags, "PPC = %u, SP = %u", flags & 0x2,
617                                     flags & 0x1);
618         proto_tree_add_uint_format (tree, hf_scsi_log_pc, tvb, offset+1, 1,
619                                     tvb_get_guint8 (tvb, offset+1),
620                                     "PC: 0x%x", flags & 0xC0);
621         proto_tree_add_item (tree, hf_scsi_logsns_pagecode, tvb, offset+1,
622                              1, 0);
623         proto_tree_add_text (tree, tvb, offset+4, 2, "Parameter Pointer: 0x%04x",
624                              tvb_get_ntohs (tvb, offset+4));
625         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
626
627         flags = tvb_get_guint8 (tvb, offset+8);
628         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
629                                     flags,
630                                     "Vendor Unique = %u, NACA = %u, Link = %u",
631                                     flags & 0xC0, flags & 0x4, flags & 0x1);
632     }
633     else {
634     }
635 }
636
637 static guint8
638 dissect_scsi_modepage (tvbuff_t *tvb, packet_info *pinfo, proto_tree *scsi_tree,
639                        guint offset)
640 {
641     guint8 pcode, plen, flags, proto;
642     proto_tree *tree;
643     proto_item *ti;
644
645     pcode = tvb_get_guint8 (tvb, offset);
646     plen = tvb_get_guint8 (tvb, offset+1);
647
648     ti = proto_tree_add_text (scsi_tree, tvb, offset, plen+2, "%s Mode Page",
649                               val_to_str (pcode & 0x3F, scsi_modesns_page_val,
650                                           "Unknown (0x%08x)"));
651     tree = proto_item_add_subtree (ti, ett_scsi_page);
652     proto_tree_add_text (tree, tvb, offset, 1, "PS: %u", (pcode & 0x80) >> 8);
653                          
654     proto_tree_add_item (tree, hf_scsi_modesns_pagecode, tvb, offset, 1, 0);
655     proto_tree_add_text (tree, tvb, offset+1, 1, "Page Length: %u",
656                          plen);
657
658     if (!tvb_bytes_exist (tvb, offset, plen)) {
659         return (plen + 2);
660     }
661     
662     pcode &= 0x3F;
663     switch (pcode) {
664     case SCSI_MODEPAGE_CTL:
665         flags = tvb_get_guint8 (tvb, offset+2);
666         proto_tree_add_item (tree, hf_scsi_modesns_tst, tvb, offset+2, 1, 0);
667         proto_tree_add_text (tree, tvb, offset+2, 1,
668                              "Global Logging Target Save Disable: %u, Report Log Exception Condition: %u",
669                              (flags & 0x2) >> 1, (flags & 0x1));
670         flags = tvb_get_guint8 (tvb, offset+3);
671         proto_tree_add_item (tree, hf_scsi_modesns_qmod, tvb, offset+3, 1, 0);
672         proto_tree_add_item (tree, hf_scsi_modesns_qerr, tvb, offset+3, 1, 0);
673         proto_tree_add_text (tree, tvb, offset+3, 1, "Disable Queuing: %u",
674                              flags & 0x1);
675         flags = tvb_get_guint8 (tvb, offset+4);
676         proto_tree_add_item (tree, hf_scsi_modesns_rac, tvb, offset+4, 1, 0);
677         proto_tree_add_item (tree, hf_scsi_modesns_tas, tvb, offset+4, 1, 0);
678         proto_tree_add_text (tree, tvb, offset+4, 1,
679                              "SWP: %u, RAERP: %u, UAAERP: %u, EAERP: %u",
680                              (flags & 0x8) >> 3, (flags & 0x4) >> 2,
681                              (flags & 0x2) >> 2, (flags & 0x1));
682         proto_tree_add_text (tree, tvb, offset+5, 1, "Autoload Mode: 0x%x",
683                              tvb_get_guint8 (tvb, offset+5) & 0x7);
684         proto_tree_add_text (tree, tvb, offset+6, 2,
685                              "Ready AER Holdoff Period: %u ms",
686                              tvb_get_ntohs (tvb, offset+6));
687         proto_tree_add_text (tree, tvb, offset+8, 2,
688                              "Busy Timeout Period: %u ms",
689                              tvb_get_ntohs (tvb, offset+8)*100);
690         proto_tree_add_text (tree, tvb, offset+10, 2,
691                              "Extended Self-Test Completion Time: %u",
692                              tvb_get_ntohs (tvb, offset+10));
693         break;
694     case SCSI_MODEPAGE_DISCON:
695         proto_tree_add_text (tree, tvb, offset+2, 1, "Buffer Full Ratio: %u",
696                              tvb_get_guint8 (tvb, offset+2));
697         proto_tree_add_text (tree, tvb, offset+3, 1, "Buffer Empty Ratio: %u",
698                              tvb_get_guint8 (tvb, offset+3));
699         proto_tree_add_text (tree, tvb, offset+4, 2, "Bus Inactivity Limit: %u",
700                              tvb_get_ntohs (tvb, offset+4));
701         proto_tree_add_text (tree, tvb, offset+6, 2, "Disconnect Time Limit: %u",
702                              tvb_get_ntohs (tvb, offset+6));
703         proto_tree_add_text (tree, tvb, offset+8, 2, "Connect Time Limit: %u",
704                              tvb_get_ntohs (tvb, offset+8));
705         proto_tree_add_text (tree, tvb, offset+10, 2,
706                              "Maximum Burst Size: %u bytes",
707                              tvb_get_ntohs (tvb, offset+10)*512);
708         flags = tvb_get_guint8 (tvb, offset+12);
709         proto_tree_add_text (tree, tvb, offset+12, 1,
710                              "EMDP: %u, FAA: %u, FAB: %u, FAC: %u",
711                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
712                              (flags & 0x20) >> 5, (flags & 0x10) >> 4);
713         proto_tree_add_text (tree, tvb, offset+14, 2,
714                              "First Burst Size: %u bytes",
715                              tvb_get_ntohs (tvb, offset+14)*512);
716         break;
717     case SCSI_MODEPAGE_INFOEXCP:
718         flags = tvb_get_guint8 (tvb, offset+2);
719         proto_tree_add_text (tree, tvb, offset+2, 1,
720                              "Perf: %u, EBF: %u, EWasc: %u, DExcpt: %u, Test: %u, LogErr: %u",
721                              (flags & 0x80) >> 7, (flags & 0x20) >> 5,
722                              (flags & 0x10) >> 4, (flags & 0x08) >> 3,
723                              (flags & 0x04) >> 2, (flags & 0x01));
724         if (!((flags & 0x10) >> 4) && ((flags & 0x08) >> 3)) {
725             proto_tree_add_item_hidden (tree, hf_scsi_modesns_errrep, tvb,
726                                         offset+3, 1, 0);
727         }
728         else {
729             proto_tree_add_item (tree, hf_scsi_modesns_errrep, tvb, offset+3, 1, 0);
730         }
731         proto_tree_add_text (tree, tvb, offset+4, 4, "Interval Timer: %u",
732                              tvb_get_ntohl (tvb, offset+4));
733         proto_tree_add_text (tree, tvb, offset+8, 4, "Report Count: %u",
734                              tvb_get_ntohl (tvb, offset+8));
735         break;
736     case SCSI_MODEPAGE_PWR:
737         flags = tvb_get_guint8 (tvb, offset+3);
738         proto_tree_add_text (tree, tvb, offset+3, 1, "Idle: %u, Standby: %u",
739                              (flags & 0x2) >> 1, (flags & 0x1));
740         proto_tree_add_text (tree, tvb, offset+4, 2,
741                              "Idle Condition Timer: %u ms",
742                              tvb_get_ntohs (tvb, offset+4) * 100);
743         proto_tree_add_text (tree, tvb, offset+6, 2,
744                              "Standby Condition Timer: %u ms",
745                              tvb_get_ntohs (tvb, offset+6) * 100);
746         break;
747     case SCSI_MODEPAGE_LUN:
748         break;
749     case SCSI_MODEPAGE_PORT:
750         proto = tvb_get_guint8 (tvb, offset+2) & 0x0F;
751         proto_tree_add_item (tree, hf_scsi_protocol, tvb, offset+2, 1, 0);
752         if (proto == SCSI_PROTO_FCP) {
753             flags = tvb_get_guint8 (tvb, offset+3);
754             proto_tree_add_text (tree, tvb, offset+3, 1,
755                                  "DTFD: %u, PLPB: %u, DDIS: %u, DLM: %u, RHA: %u, ALWI: %u, DTIPE: %u, DTOLI:%u",
756                                  (flags & 0x80) >> 7, (flags & 0x40) >> 6,
757                                  (flags & 0x20) >> 5, (flags & 0x10) >> 4,
758                                  (flags & 0x08) >> 3, (flags & 0x04) >> 2,
759                                  (flags & 0x02) >> 1, (flags & 0x1));
760             proto_tree_add_text (tree, tvb, offset+6, 1, "RR_TOV Units: %s",
761                                  val_to_str (tvb_get_guint8 (tvb, offset+6) & 0x7,
762                                              scsi_fcp_rrtov_val,
763                                              "Unknown (0x%02x)"));
764             proto_tree_add_text (tree, tvb, offset+7, 1, "RR_TOV: %u",
765                                  tvb_get_guint8 (tvb, offset+7));
766         }
767         else if (proto == SCSI_PROTO_iSCSI) {
768         }
769         else {
770         }
771         break;
772     case SCSI_MODEPAGE_FMTDEV:
773         proto_tree_add_text (tree, tvb, offset+2, 2, "Tracks Per Zone: %u",
774                              tvb_get_ntohs (tvb, offset+2));
775         proto_tree_add_text (tree, tvb, offset+4, 2,
776                              "Alternate Sectors Per Zone: %u",
777                              tvb_get_ntohs (tvb, offset+4));
778         proto_tree_add_text (tree, tvb, offset+6, 2,
779                              "Alternate Tracks Per Zone: %u",
780                              tvb_get_ntohs (tvb, offset+6));
781         proto_tree_add_text (tree, tvb, offset+8, 2,
782                              "Alternate Tracks Per LU: %u",
783                              tvb_get_ntohs (tvb, offset+8));
784         proto_tree_add_text (tree, tvb, offset+10, 2, "Sectors Per Track: %u",
785                              tvb_get_ntohs (tvb, offset+10));
786         proto_tree_add_text (tree, tvb, offset+12, 2,
787                              "Data Bytes Per Physical Sector: %u",
788                              tvb_get_ntohs (tvb, offset+12));
789         proto_tree_add_text (tree, tvb, offset+14, 2, "Interleave: %u",
790                              tvb_get_ntohs (tvb, offset+14));
791         proto_tree_add_text (tree, tvb, offset+16, 2, "Track Skew Factor: %u",
792                              tvb_get_ntohs (tvb, offset+16));
793         proto_tree_add_text (tree, tvb, offset+18, 2,
794                              "Cylinder Skew Factor: %u",
795                              tvb_get_ntohs (tvb, offset+18));
796         flags = tvb_get_guint8 (tvb, offset+20);
797         proto_tree_add_text (tree, tvb, offset+20, 1,
798                              "SSEC: %u, HSEC: %u, RMB: %u, SURF: %u",
799                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
800                              (flags & 0x20) >> 5, (flags & 0x10) >> 4);
801         break;
802     case SCSI_MODEPAGE_RDWRERR:
803         flags = tvb_get_guint8 (tvb, offset+2);
804         proto_tree_add_text (tree, tvb, offset+2, 1,
805                              "AWRE: %u, ARRE: %u, TB: %u, RC: %u, EER: %u, PER: %u, DTE: %u, DCR: %u",
806                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
807                              (flags & 0x20) >> 5, (flags & 0x10) >> 4,
808                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
809                              (flags & 0x02) >> 1, (flags & 0x01));
810         proto_tree_add_text (tree, tvb, offset+3, 1, "Read Retry Count: %u",
811                              tvb_get_guint8 (tvb, offset+3));
812         proto_tree_add_text (tree, tvb, offset+4, 1, "Correction Span: %u",
813                              tvb_get_guint8 (tvb, offset+4));
814         proto_tree_add_text (tree, tvb, offset+5, 1, "Head Offset Count: %u",
815                              tvb_get_guint8 (tvb, offset+5));
816         proto_tree_add_text (tree, tvb, offset+6, 1,
817                              "Data Strobe Offset Count: %u",
818                              tvb_get_guint8 (tvb, offset+6));
819         proto_tree_add_text (tree, tvb, offset+8, 1, "Write Retry Count: %u",
820                              tvb_get_guint8 (tvb, offset+8));
821         proto_tree_add_text (tree, tvb, offset+10, 2,
822                              "Recovery Time Limit: %u ms",
823                              tvb_get_ntohs (tvb, offset+10));
824         break;
825     case SCSI_MODEPAGE_DISKGEOM:
826         proto_tree_add_text (tree, tvb, offset+2, 3, "Number of Cylinders: %u",
827                              tvb_get_ntoh24 (tvb, offset+2));
828         proto_tree_add_text (tree, tvb, offset+5, 1, "Number of Heads: %u",
829                              tvb_get_guint8 (tvb, offset+5));
830         proto_tree_add_text (tree, tvb, offset+6, 3,
831                              "Starting Cyl Pre-compensation: %u",
832                              tvb_get_ntoh24 (tvb, offset+6));
833         proto_tree_add_text (tree, tvb, offset+9, 3,
834                              "Starting Cyl-reduced Write Current: %u",
835                              tvb_get_ntoh24 (tvb, offset+9));
836         proto_tree_add_text (tree, tvb, offset+12, 2, "Device Step Rate: %u",
837                              tvb_get_ntohs (tvb, offset+12));
838         proto_tree_add_text (tree, tvb, offset+14, 3, "Landing Zone Cyl: %u",
839                              tvb_get_ntoh24 (tvb, offset+14));
840         proto_tree_add_text (tree, tvb, offset+18, 1, "Rotational Offset: %u",
841                              tvb_get_guint8 (tvb, offset+18));
842         proto_tree_add_text (tree, tvb, offset+20, 2,
843                              "Medium Rotation Rate: %u",
844                              tvb_get_ntohs (tvb, offset+20));
845         break;
846     case SCSI_MODEPAGE_FLEXDISK:
847         break;
848     case SCSI_MODEPAGE_VERERR:
849         break;
850     case SCSI_MODEPAGE_CACHE:
851         flags = tvb_get_guint8 (tvb, offset+2);
852         proto_tree_add_text (tree, tvb, offset+2, 1,
853                              "IC: %u, ABPF: %u, CAP %u, Disc: %u, Size: %u, WCE: %u, MF: %u, RCD: %u",
854                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
855                              (flags & 0x20) >> 5, (flags & 0x10) >> 4,
856                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
857                              (flags & 0x02) >> 1, (flags & 0x01));
858         flags = tvb_get_guint8 (tvb, offset+3);
859         proto_tree_add_text (tree, tvb, offset+3, 1,
860                              "Demand Read Retention Priority: %u, Write Retention Priority: %u",
861                              (flags & 0xF0) >> 4, (flags & 0x0F));
862         proto_tree_add_text (tree, tvb, offset+4, 2,
863                              "Disable Pre-fetch Xfer Len: %u",
864                              tvb_get_ntohs (tvb, offset+4));
865         proto_tree_add_text (tree, tvb, offset+6, 2, "Minimum Pre-Fetch: %u",
866                              tvb_get_ntohs (tvb, offset+6));
867         proto_tree_add_text (tree, tvb, offset+8, 2, "Maximum Pre-Fetch: %u",
868                              tvb_get_ntohs (tvb, offset+8));
869         proto_tree_add_text (tree, tvb, offset+10, 2,
870                              "Maximum Pre-Fetch Ceiling: %u",
871                              tvb_get_ntohs (tvb, offset+10));
872         flags = tvb_get_guint8 (tvb, offset+12);
873         proto_tree_add_text (tree, tvb, offset+12, 1,
874                              "FSW: %u, LBCSS: %u, DRA: %u, Vendor Specific: %u",
875                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
876                              (flags & 0x20) >> 5, (flags & 0x1F) >> 4);
877         proto_tree_add_text (tree, tvb, offset+13, 1,
878                              "Number of Cache Segments: %u",
879                              tvb_get_guint8 (tvb, offset+13));
880         proto_tree_add_text (tree, tvb, offset+14, 2, "Cache Segment Size: %u",
881                              tvb_get_ntohs (tvb, offset+14));
882         proto_tree_add_text (tree, tvb, offset+17, 3,
883                              "Non-Cache Segment Size: %u",
884                              tvb_get_ntoh24 (tvb, offset+17));
885         break;
886     case SCSI_MODEPAGE_PERDEV:
887         break;
888     case SCSI_MODEPAGE_MEDTYPE:
889         break;
890     case SCSI_MODEPAGE_NOTPART:
891         break;
892     case SCSI_MODEPAGE_XORCTL:
893         break;
894     default:
895         proto_tree_add_text (tree, tvb, offset, plen,
896                              "Unknown Page");
897         break;
898     }
899     return (plen+2);
900 }
901
902 static void
903 dissect_scsi_modeselect6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
904                           guint offset, gboolean isreq, gboolean iscdb,
905                           guint payload_len)
906 {
907     guint8 flags, pcode;
908     guint tot_len, desclen, plen;
909     
910     if (!tree)
911         return;
912     
913     if (isreq && iscdb) {
914         flags = tvb_get_guint8 (tvb, offset);
915         
916         proto_tree_add_uint_format (tree, hf_scsi_modesel_flags, tvb, offset, 1,
917                                     flags, "PF = %u, SP = %u", flags & 0x10,
918                                     flags & 0x1);
919         proto_tree_add_item (tree, hf_scsi_paramlen, tvb, offset+3, 1, 0);
920
921         flags = tvb_get_guint8 (tvb, offset+4);
922         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
923                                     flags,
924                                     "Vendor Unique = %u, NACA = %u, Link = %u",
925                                     flags & 0xC0, flags & 0x4, flags & 0x1);
926     }
927     else {
928         /* Mode Parameter has the following format:
929          * Mode Parameter Header
930          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
931          *      Blk Desc Len
932          * Block Descriptor (s)
933          *    - Number of blocks, density code, block length
934          * Page (s)
935          *    - Page code, Page length, Page Parameters
936          */
937         tot_len = tvb_get_guint8 (tvb, offset);
938         proto_tree_add_text (tree, tvb, offset, 1, "Mode Data Length: %u",
939                              tot_len);
940         proto_tree_add_text (tree, tvb, offset+1, 1, "Medium Type: 0x%02x",
941                              tvb_get_guint8 (tvb, offset+1));
942         proto_tree_add_text (tree, tvb, offset+2, 1,
943                              "Device-Specific Parameter: 0x%02x",
944                              tvb_get_guint8 (tvb, offset+2));
945         desclen = tvb_get_guint8 (tvb, offset+3);
946         proto_tree_add_text (tree, tvb, offset+3, 1,
947                              "Block Descriptor Length: %u", desclen);
948         offset = 4;
949         tot_len -= 3;           /* tot_len does not include the len field */
950         if (desclen) {
951             proto_tree_add_text (tree, tvb, offset, 4, "No. of Blocks: %u",
952                                  tvb_get_ntohl (tvb, offset));
953             proto_tree_add_text (tree, tvb, offset+4, 1, "Density Code: 0x%02x",
954                                  tvb_get_guint8 (tvb, offset+4));
955             proto_tree_add_text (tree, tvb, offset+5, 3, "Block Length: %u",
956                                  tvb_get_ntoh24 (tvb, offset+5));
957             offset += 8;        /* increment the offset by 8 */
958             tot_len -= 8;       /* subtract by the block desc len */
959         }
960         /* offset points to the start of the mode page */
961         while ((tot_len > offset) && tvb_bytes_exist (tvb, offset, 2)) {
962             plen = dissect_scsi_modepage (tvb, pinfo, tree, offset);
963             offset += plen;
964         }
965     }
966 }
967
968 static void
969 dissect_scsi_modeselect10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
970                            guint offset, gboolean isreq, gboolean iscdb,
971                            guint payload_len)
972 {
973     guint8 flags, pcode;
974     gboolean longlba;
975     guint tot_len, desclen, plen;
976     
977     if (!tree)
978         return;
979     
980     if (isreq && iscdb) {
981         flags = tvb_get_guint8 (tvb, offset);
982         
983         proto_tree_add_uint_format (tree, hf_scsi_modesel_flags, tvb, offset, 1,
984                                     flags, "PF = %u, SP = %u", flags & 0x10,
985                                     flags & 0x1);
986         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
987
988         flags = tvb_get_guint8 (tvb, offset+8);
989         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
990                                     flags,
991                                     "Vendor Unique = %u, NACA = %u, Link = %u",
992                                     flags & 0xC0, flags & 0x4, flags & 0x1);
993     }
994     else {
995         /* Mode Parameter has the following format:
996          * Mode Parameter Header
997          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
998          *      Blk Desc Len
999          * Block Descriptor (s)
1000          *    - Number of blocks, density code, block length
1001          * Page (s)
1002          *    - Page code, Page length, Page Parameters
1003          */
1004         tot_len = tvb_get_ntohs (tvb, offset);
1005         proto_tree_add_text (tree, tvb, offset, 2, "Mode Data Length: %u",
1006                              tot_len);
1007         proto_tree_add_text (tree, tvb, offset+2, 1, "Medium Type: 0x%02x",
1008                              tvb_get_guint8 (tvb, offset+2));
1009         proto_tree_add_text (tree, tvb, offset+3, 1,
1010                              "Device-Specific Parameter: 0x%02x",
1011                              tvb_get_guint8 (tvb, offset+3));
1012         longlba = tvb_get_guint8 (tvb, offset+4) & 0x1;
1013         proto_tree_add_text (tree, tvb, offset+4, 1, "LongLBA: %u", longlba);
1014         desclen = tvb_get_guint8 (tvb, offset+6);
1015         proto_tree_add_text (tree, tvb, offset+6, 1,
1016                              "Block Descriptor Length: %u", desclen);
1017         offset = 8;
1018         tot_len -= 6;           /* tot_len does not include the len field */
1019         if (desclen) {
1020             proto_tree_add_text (tree, tvb, offset, 8, "No. of Blocks: %s",
1021                                  bytes_to_str (tvb_get_ptr (tvb, offset, 8),
1022                                                8));
1023             proto_tree_add_text (tree, tvb, offset+8, 1, "Density Code: 0x%02x",
1024                                  tvb_get_guint8 (tvb, offset+4));
1025             proto_tree_add_text (tree, tvb, offset+12, 4, "Block Length: %u",
1026                                  tvb_get_ntohl (tvb, offset+12));
1027             offset += 16;        /* increment the offset by 8 */
1028             tot_len -= 16;       /* subtract by the block desc len */
1029         }
1030         /* offset points to the start of the mode page */
1031         while ((tot_len > offset) && tvb_bytes_exist (tvb, offset, 2)) {
1032             offset += dissect_scsi_modepage (tvb, pinfo, tree, offset);
1033         }
1034     }
1035 }
1036
1037 static void
1038 dissect_scsi_modesense6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1039                          guint offset, gboolean isreq, gboolean iscdb,
1040                          guint payload_len)
1041 {
1042     guint8 flags, pcode;
1043     guint tot_len, desclen, plen;
1044     
1045     if (!tree)
1046         return;
1047     
1048     if (isreq && iscdb) {
1049         flags = tvb_get_guint8 (tvb, offset);
1050         
1051         proto_tree_add_uint_format (tree, hf_scsi_modesns_flags, tvb, offset, 1,
1052                                     flags, "DBD = %u", flags & 0x8);
1053         proto_tree_add_item (tree, hf_scsi_modesns_pc, tvb, offset+1, 1, 0);
1054         proto_tree_add_item (tree, hf_scsi_modesns_pagecode, tvb, offset+1, 1,
1055                              0);
1056         proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
1057
1058         flags = tvb_get_guint8 (tvb, offset+4);
1059         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1060                                     flags,
1061                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1062                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1063     }
1064     else {
1065         /* Mode sense response has the following format:
1066          * Mode Parameter Header
1067          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
1068          *      Blk Desc Len
1069          * Block Descriptor (s)
1070          *    - Number of blocks, density code, block length
1071          * Page (s)
1072          *    - Page code, Page length, Page Parameters
1073          */
1074         tot_len = tvb_get_guint8 (tvb, offset);
1075         proto_tree_add_text (tree, tvb, offset, 1, "Mode Data Length: %u",
1076                              tot_len);
1077         proto_tree_add_text (tree, tvb, offset+1, 1, "Medium Type: 0x%02x",
1078                              tvb_get_guint8 (tvb, offset+1));
1079         proto_tree_add_text (tree, tvb, offset+2, 1,
1080                              "Device-Specific Parameter: 0x%02x",
1081                              tvb_get_guint8 (tvb, offset+2));
1082         desclen = tvb_get_guint8 (tvb, offset+3);
1083         proto_tree_add_text (tree, tvb, offset+3, 1,
1084                              "Block Descriptor Length: %u", desclen);
1085         offset = 4;
1086         /* The actual payload is the min of the length in the response & the
1087          * space allocated by the initiator as specified in the request.
1088          */
1089         if (payload_len && (tot_len > payload_len))
1090             tot_len = payload_len;
1091         if (desclen) {
1092             proto_tree_add_text (tree, tvb, offset, 4, "No. of Blocks: %u",
1093                                  tvb_get_ntohl (tvb, offset));
1094             proto_tree_add_text (tree, tvb, offset+4, 1, "Density Code: 0x%02x",
1095                                  tvb_get_guint8 (tvb, offset+4));
1096             proto_tree_add_text (tree, tvb, offset+5, 3, "Block Length: %u",
1097                                  tvb_get_ntoh24 (tvb, offset+5));
1098             offset += 8;        /* increment the offset by 8 */
1099         }
1100         /* offset points to the start of the mode page */
1101         while ((tot_len > offset) && tvb_bytes_exist (tvb, offset, 2)) {
1102             plen = dissect_scsi_modepage (tvb, pinfo, tree, offset);
1103             offset += plen;
1104         }
1105     }
1106 }
1107
1108 static void
1109 dissect_scsi_modesense10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1110                           guint offset, gboolean isreq, gboolean iscdb,
1111                           guint payload_len)
1112 {
1113     guint8 flags, pcode;
1114     gboolean longlba;
1115     guint tot_len, desclen, plen;
1116  
1117     if (!tree)
1118         return;
1119     
1120     if (isreq && iscdb) {
1121         flags = tvb_get_guint8 (tvb, offset);
1122         
1123         proto_tree_add_uint_format (tree, hf_scsi_modesns_flags, tvb, offset, 1,
1124                                     flags, "LLBAA = %u, DBD = %u", flags & 0x10,
1125                                     flags & 0x8);
1126         proto_tree_add_item (tree, hf_scsi_modesns_pc, tvb, offset+1, 1, 0);
1127         proto_tree_add_item (tree, hf_scsi_modesns_pagecode, tvb, offset+1, 1,
1128                              0);
1129         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
1130
1131         flags = tvb_get_guint8 (tvb, offset+8);
1132         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1133                                     flags,
1134                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1135                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1136     }
1137     else {
1138         /* Mode sense response has the following format:
1139          * Mode Parameter Header
1140          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
1141          *      Blk Desc Len
1142          * Block Descriptor (s)
1143          *    - Number of blocks, density code, block length
1144          * Page (s)
1145          *    - Page code, Page length, Page Parameters
1146          */
1147         tot_len = tvb_get_ntohs (tvb, offset);
1148         proto_tree_add_text (tree, tvb, offset, 2, "Mode Data Length: %u",
1149                              tot_len);
1150         proto_tree_add_text (tree, tvb, offset+2, 1, "Medium Type: 0x%02x",
1151                              tvb_get_guint8 (tvb, offset+2));
1152         proto_tree_add_text (tree, tvb, offset+3, 1,
1153                              "Device-Specific Parameter: 0x%02x",
1154                              tvb_get_guint8 (tvb, offset+3));
1155         longlba = tvb_get_guint8 (tvb, offset+4) & 0x1;
1156         proto_tree_add_text (tree, tvb, offset+4, 1, "LongLBA: %u", longlba);
1157         desclen = tvb_get_guint8 (tvb, offset+6);
1158         proto_tree_add_text (tree, tvb, offset+6, 1,
1159                              "Block Descriptor Length: %u", desclen);
1160         offset = 8;
1161         tot_len -= 6;           /* tot_len does not include the len field */
1162         if (desclen) {
1163             proto_tree_add_text (tree, tvb, offset, 8, "No. of Blocks: %s",
1164                                  bytes_to_str (tvb_get_ptr (tvb, offset, 8),
1165                                                8));
1166             proto_tree_add_text (tree, tvb, offset+8, 1, "Density Code: 0x%02x",
1167                                  tvb_get_guint8 (tvb, offset+4));
1168             proto_tree_add_text (tree, tvb, offset+12, 4, "Block Length: %u",
1169                                  tvb_get_ntohl (tvb, offset+12));
1170             offset += 16;        /* increment the offset by 8 */
1171             tot_len -= 16;       /* subtract by the block desc len */
1172         }
1173         /* offset points to the start of the mode page */
1174         while ((tot_len > offset) && tvb_bytes_exist (tvb, offset, 2)) {
1175             offset += dissect_scsi_modepage (tvb, pinfo, tree, offset);
1176         }
1177     }
1178 }
1179
1180 static void
1181 dissect_scsi_persresvin (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1182                          guint offset, gboolean isreq, gboolean iscdb,
1183                          scsi_task_data_t *cdata, guint payload_len)
1184 {
1185     guint8 flags;
1186     int numrec, i;
1187     guint len;
1188
1189     if (!tree)
1190         return;
1191     
1192     if (isreq && iscdb) {
1193         proto_tree_add_item (tree, hf_scsi_persresvin_svcaction, tvb, offset+1,
1194                              1, 0);
1195         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
1196
1197         flags = tvb_get_guint8 (tvb, offset+8);
1198         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1199                                     flags,
1200                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1201                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1202         /* We store the service action since we want to interpret the data */
1203         cdata->flags = tvb_get_guint8 (tvb, offset+1);
1204     }
1205     else {
1206         if (cdata) {
1207             flags = cdata->flags;
1208         }
1209         else {
1210             flags = 0xFF;
1211         }
1212         proto_tree_add_text (tree, tvb, offset, 4, "Generation Number: 0x%08x",
1213                              tvb_get_ntohl (tvb, offset));
1214         len = tvb_get_ntohl (tvb, offset+4);
1215         proto_tree_add_text (tree, tvb, offset, 4, "Additional Length: %u",
1216                              len);
1217         len = (payload_len > len) ? len : payload_len;
1218         
1219         if ((flags & 0x1F) == SCSI_SPC2_RESVIN_SVCA_RDKEYS) {
1220             /* XXX - what if len is < 8?  That may be illegal, but
1221                that doesn't make it impossible.... */
1222             numrec = (len - 8)/8;
1223             offset += 8;
1224             
1225             for (i = 0; i < numrec; i++) {
1226                 proto_tree_add_item (tree, hf_scsi_persresv_key, tvb, offset,
1227                                      8, 0);
1228                 offset -= 8;
1229             }
1230         }
1231         else if ((flags & 0x1F) == SCSI_SPC2_RESVIN_SVCA_RDRESV) {
1232             proto_tree_add_item (tree, hf_scsi_persresv_key, tvb, offset+8,
1233                                  8, 0);
1234             proto_tree_add_item (tree, hf_scsi_persresv_scopeaddr, tvb,
1235                                  offset+8, 4, 0);
1236             proto_tree_add_item (tree, hf_scsi_persresv_scope, tvb, offset+13,
1237                                  1, 0);
1238             proto_tree_add_item (tree, hf_scsi_persresv_type, tvb, offset+13,
1239                                  1, 0);
1240         }
1241     }
1242 }
1243
1244 static void
1245 dissect_scsi_persresvout (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1246                           guint offset, gboolean isreq, gboolean iscdb,
1247                           scsi_task_data_t *cdata, guint payload_len)
1248 {
1249     guint8 flags;
1250
1251     if (!tree)
1252         return;
1253     
1254     if (isreq && iscdb) {
1255         proto_tree_add_item (tree, hf_scsi_persresvin_svcaction, tvb, offset,
1256                              1, 0);
1257         proto_tree_add_item (tree, hf_scsi_persresv_scope, tvb, offset+1, 1, 0);
1258         proto_tree_add_item (tree, hf_scsi_persresv_type, tvb, offset+1, 1, 0);
1259         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
1260
1261         flags = tvb_get_guint8 (tvb, offset+8);
1262         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1263                                     flags,
1264                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1265                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1266     }
1267     else {
1268     }
1269 }
1270
1271 static void
1272 dissect_scsi_release6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1273                        guint offset, gboolean isreq, gboolean iscdb)
1274 {
1275     guint8 flags;
1276
1277     if (!tree)
1278         return;
1279     
1280     if (isreq && iscdb) {
1281         flags = tvb_get_guint8 (tvb, offset+4);
1282         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1283                                     flags,
1284                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1285                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1286     }
1287 }
1288
1289 static void
1290 dissect_scsi_release10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1291                         guint offset, gboolean isreq, gboolean iscdb)
1292 {
1293     guint8 flags;
1294
1295     if (!tree)
1296         return;
1297     
1298     if (isreq && iscdb) {
1299         flags = tvb_get_guint8 (tvb, offset);
1300
1301         proto_tree_add_uint_format (tree, hf_scsi_release_flags, tvb, offset, 1,
1302                                     flags,
1303                                     "Flags: 3rd Party ID = %u, LongID = %u",
1304                                     flags & 0x10, flags & 0x2);
1305         if ((flags & 0x12) == 0x10) {
1306             proto_tree_add_item (tree, hf_scsi_release_thirdpartyid, tvb,
1307                                  offset+2, 1, 0);
1308         }
1309         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
1310
1311         flags = tvb_get_guint8 (tvb, offset+8);
1312         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1313                                     flags,
1314                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1315                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1316     }
1317 }
1318
1319 static void
1320 dissect_scsi_reportdeviceid (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1321                              guint offset, gboolean isreq, gboolean iscdb)
1322 {
1323     
1324 }
1325
1326 static void
1327 dissect_scsi_reportluns (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1328                          guint offset, gboolean isreq, gboolean iscdb)
1329 {
1330     guint8 flags;
1331     guint numelem, i;
1332
1333     if (!tree)
1334         return;
1335     
1336     if (isreq && iscdb) {
1337         proto_tree_add_item (tree, hf_scsi_alloclen32, tvb, offset+5, 4, 0);
1338
1339         flags = tvb_get_guint8 (tvb, offset+10);
1340         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
1341                                     flags,
1342                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1343                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1344     }
1345     else if (!isreq) {
1346         numelem = tvb_get_ntohl (tvb, offset);
1347         proto_tree_add_text (tree, tvb, offset, 4, "LUN List Length: %u",
1348                              numelem);
1349         offset += 8;
1350         for (i = 0; i < numelem/8; i++) {
1351             if (!tvb_get_guint8 (tvb, offset))
1352                 proto_tree_add_item (tree, hf_scsi_rluns_lun, tvb, offset+1, 1,
1353                                      0);
1354             else
1355                 proto_tree_add_item (tree, hf_scsi_rluns_multilun, tvb, offset,
1356                                      8, 0);
1357             offset += 8;
1358         }
1359     }
1360 }
1361
1362 static void
1363 dissect_scsi_reqsense (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1364                        guint offset, gboolean isreq, gboolean iscdb)
1365 {
1366     guint8 flags;
1367
1368     if (!tree)
1369         return;
1370     
1371     if (isreq && iscdb) {
1372         proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
1373
1374         flags = tvb_get_guint8 (tvb, offset+4);
1375         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1376                                     flags,
1377                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1378                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1379     }
1380 }
1381
1382 static void
1383 dissect_scsi_reserve6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1384                        guint offset, gboolean isreq, gboolean iscdb)
1385 {
1386     guint8 flags;
1387
1388     if (!tree)
1389         return;
1390     
1391     if (isreq && iscdb) {
1392         flags = tvb_get_guint8 (tvb, offset+4);
1393         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1394                                     flags,
1395                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1396                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1397     }
1398 }
1399
1400 static void
1401 dissect_scsi_reserve10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1402                         guint offset, gboolean isreq, gboolean iscdb)
1403 {
1404     guint8 flags;
1405
1406     if (!tree)
1407         return;
1408     
1409     if (isreq && iscdb) {
1410         flags = tvb_get_guint8 (tvb, offset);
1411
1412         proto_tree_add_uint_format (tree, hf_scsi_release_flags, tvb, offset, 1,
1413                                     flags,
1414                                     "Flags: 3rd Party ID = %u, LongID = %u",
1415                                     flags & 0x10, flags & 0x2);
1416         if ((flags & 0x12) == 0x10) {
1417             proto_tree_add_item (tree, hf_scsi_release_thirdpartyid, tvb,
1418                                  offset+2, 1, 0);
1419         }
1420         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
1421
1422         flags = tvb_get_guint8 (tvb, offset+8);
1423         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1424                                     flags,
1425                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1426                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1427     }
1428 }
1429
1430 static void
1431 dissect_scsi_testunitrdy (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1432                           guint offset, gboolean isreq, gboolean iscdb)
1433 {
1434     guint8 flags;
1435
1436     if (!tree)
1437         return;
1438     
1439     if (isreq && iscdb) {
1440         flags = tvb_get_guint8 (tvb, offset+4);
1441         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1442                                     flags,
1443                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1444                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1445     }
1446 }
1447
1448 static void
1449 dissect_scsi_formatunit (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1450                          guint offset, gboolean isreq, gboolean iscdb)
1451 {
1452     guint8 flags;
1453
1454     if (!tree)
1455         return;
1456     
1457     if (isreq && iscdb) {
1458         flags = tvb_get_guint8 (tvb, offset);
1459         proto_tree_add_uint_format (tree, hf_scsi_formatunit_flags, tvb, offset,
1460                                     1, flags,
1461                                     "Flags: Longlist = %u, FMTDATA = %u, CMPLIST = %u",
1462                                     flags & 0x20, flags & 0x8, flags & 0x4);
1463         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
1464         proto_tree_add_item (tree, hf_scsi_formatunit_vendor, tvb, offset+1,
1465                              1, 0);
1466         proto_tree_add_item (tree, hf_scsi_formatunit_interleave, tvb, offset+2,
1467                              2, 0);
1468         flags = tvb_get_guint8 (tvb, offset+4);
1469         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1470                                     flags,
1471                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1472                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1473     }
1474 }
1475
1476 static void
1477 dissect_scsi_rdwr6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1478                     guint offset, gboolean isreq, gboolean iscdb)
1479 {
1480     guint8 flags;
1481
1482     if (isreq) {
1483         if (check_col (pinfo->cinfo, COL_INFO))
1484             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%06x, Len: %u)",
1485                              tvb_get_ntoh24 (tvb, offset),
1486                              tvb_get_guint8 (tvb, offset+3));
1487     }
1488     
1489     if (tree && isreq && iscdb) {
1490         proto_tree_add_item (tree, hf_scsi_rdwr6_lba, tvb, offset, 3, 0);
1491         proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+3, 1, 0);
1492         flags = tvb_get_guint8 (tvb, offset+4);
1493         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1494                                     flags,
1495                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1496                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1497     }
1498 }
1499
1500 static void
1501 dissect_scsi_rdwr10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1502                      guint offset, gboolean isreq, gboolean iscdb)
1503 {
1504     guint8 flags;
1505
1506     if (isreq) {
1507         if (check_col (pinfo->cinfo, COL_INFO))
1508             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%08x, Len: %u)",
1509                              tvb_get_ntohl (tvb, offset+1),
1510                              tvb_get_ntohs (tvb, offset+6));
1511     }
1512
1513     if (tree && isreq && iscdb) {
1514         flags = tvb_get_guint8 (tvb, offset);
1515
1516         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
1517                                     flags,
1518                                     "DPO = %u, FUA = %u, RelAddr = %u",
1519                                     flags & 0x10, flags & 0x8, flags & 0x1);
1520         proto_tree_add_item (tree, hf_scsi_rdwr10_lba, tvb, offset+1, 4, 0);
1521         proto_tree_add_item (tree, hf_scsi_rdwr10_xferlen, tvb, offset+6, 2, 0);
1522         flags = tvb_get_guint8 (tvb, offset+8);
1523         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1524                                     flags,
1525                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1526                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1527     }
1528 }
1529
1530 static void
1531 dissect_scsi_rdwr12 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1532                      guint offset, gboolean isreq, gboolean iscdb)
1533 {
1534     guint8 flags;
1535
1536     if (isreq) {
1537         if (check_col (pinfo->cinfo, COL_INFO))
1538             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%08x, Len: %u)",
1539                              tvb_get_ntohl (tvb, offset+1),
1540                              tvb_get_ntohl (tvb, offset+5));
1541     }
1542
1543     if (tree && isreq && iscdb) {
1544         flags = tvb_get_guint8 (tvb, offset);
1545
1546         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
1547                                     flags,
1548                                     "DPO = %u, FUA = %u, RelAddr = %u",
1549                                     flags & 0x10, flags & 0x8, flags & 0x1);
1550         proto_tree_add_item (tree, hf_scsi_rdwr10_lba, tvb, offset+1, 4, 0);
1551         proto_tree_add_item (tree, hf_scsi_rdwr12_xferlen, tvb, offset+5, 4, 0);
1552         flags = tvb_get_guint8 (tvb, offset+10);
1553         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
1554                                     flags,
1555                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1556                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1557     }
1558 }
1559
1560 static void
1561 dissect_scsi_rdwr16 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1562                      guint offset, gboolean isreq, gboolean iscdb)
1563 {
1564     guint8 flags;
1565
1566     if (tree && isreq && iscdb) {
1567         flags = tvb_get_guint8 (tvb, offset);
1568
1569         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
1570                                     flags,
1571                                     "DPO = %u, FUA = %u, RelAddr = %u",
1572                                     flags & 0x10, flags & 0x8, flags & 0x1);
1573         proto_tree_add_item (tree, hf_scsi_rdwr16_lba, tvb, offset+1, 8, 0);
1574         proto_tree_add_item (tree, hf_scsi_rdwr12_xferlen, tvb, offset+9, 4, 0);
1575         flags = tvb_get_guint8 (tvb, offset+14);
1576         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+14, 1,
1577                                     flags,
1578                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1579                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1580     }
1581 }
1582
1583 static void
1584 dissect_scsi_readcapacity (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1585                            guint offset, gboolean isreq, gboolean iscdb)
1586 {
1587     guint8 flags;
1588     guint len;
1589
1590     if (!tree)
1591         return;
1592     
1593     if (isreq && iscdb) {
1594         flags = tvb_get_guint8 (tvb, offset);
1595
1596         proto_tree_add_uint_format (tree, hf_scsi_readcapacity_flags, tvb,
1597                                     offset, 1, flags,
1598                                     "LongLBA = %u, RelAddr = %u", 
1599                                     flags & 0x2, flags & 0x1);
1600         proto_tree_add_item (tree, hf_scsi_readcapacity_lba, tvb, offset+1,
1601                              4, 0);
1602         proto_tree_add_item (tree, hf_scsi_readcapacity_pmi, tvb, offset+7,
1603                              1, 0);
1604
1605         flags = tvb_get_guint8 (tvb, offset+8);
1606         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1607                                     flags,
1608                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1609                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1610     }
1611     else if (!iscdb) {
1612         len = tvb_get_ntohl (tvb, offset);
1613         proto_tree_add_text (tree, tvb, offset, 4, "LBA: %u (%u MB)",
1614                              len, len/(1024*1024));
1615         proto_tree_add_text (tree, tvb, offset+4, 4, "Block Length: %u bytes",
1616                              tvb_get_ntohl (tvb, offset+4));
1617     }
1618 }
1619
1620 static void
1621 dissect_scsi_readdefdata10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1622                             guint offset, gboolean isreq, gboolean iscdb)
1623 {
1624     guint8 flags;
1625
1626     if (!tree)
1627         return;
1628     
1629     if (isreq && iscdb) {
1630         flags = tvb_get_guint8 (tvb, offset);
1631
1632         proto_tree_add_uint_format (tree, hf_scsi_readdefdata_flags, tvb,
1633                                     offset, 1, flags, "PLIST = %u, GLIST = %u",
1634                                     flags & 0x10, flags & 0x8);
1635         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
1636         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
1637         flags = tvb_get_guint8 (tvb, offset+8);
1638         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1639                                     flags,
1640                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1641                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1642     }
1643 }
1644
1645 static void
1646 dissect_scsi_readdefdata12 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1647                             guint offset, gboolean isreq, gboolean iscdb)
1648 {
1649     guint8 flags;
1650
1651     if (!tree)
1652         return;
1653     
1654     if (isreq && iscdb) {
1655         flags = tvb_get_guint8 (tvb, offset);
1656
1657         proto_tree_add_uint_format (tree, hf_scsi_readdefdata_flags, tvb,
1658                                     offset, 1, flags, "PLIST = %u, GLIST = %u",
1659                                     flags & 0x10, flags & 0x8);
1660         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
1661         proto_tree_add_item (tree, hf_scsi_alloclen32, tvb, offset+5, 4, 0);
1662         flags = tvb_get_guint8 (tvb, offset+10);
1663         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
1664                                     flags,
1665                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1666                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1667     }
1668 }
1669
1670 static void
1671 dissect_scsi_reassignblks (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1672                            guint offset, gboolean isreq, gboolean iscdb)
1673 {
1674     guint8 flags;
1675
1676     if (!tree)
1677         return;
1678     
1679     if (isreq && iscdb) {
1680         flags = tvb_get_guint8 (tvb, offset);
1681
1682         proto_tree_add_uint_format (tree, hf_scsi_reassignblks_flags, tvb,
1683                                     offset, 1, flags,
1684                                     "LongLBA = %u, LongList = %u",
1685                                     flags & 0x2, flags & 0x1);
1686         flags = tvb_get_guint8 (tvb, offset+4);
1687         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1688                                     flags,
1689                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1690                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1691     }
1692 }
1693
1694 void
1695 dissect_scsi_rsp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1696 {
1697     /* Nothing to do here, just blow up the data structures for this SCSI
1698      * transaction
1699     if (tree)
1700         scsi_end_task (pinfo);
1701      */
1702 }
1703
1704 void
1705 dissect_scsi_snsinfo (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1706                       guint offset, guint snslen)
1707 {
1708     guint8 flags;
1709     proto_item *ti;
1710     proto_tree *sns_tree;
1711     scsi_device_type dev = 0;
1712     scsi_devtype_key_t dkey;
1713     scsi_devtype_data_t *devdata;
1714
1715     scsi_end_task (pinfo);
1716     
1717     if (tree) {
1718         ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
1719                                              snslen, "SCSI: SNS Info");
1720         sns_tree = proto_item_add_subtree (ti, ett_scsi);
1721
1722         flags = tvb_get_guint8 (tvb, offset);
1723         proto_tree_add_text (sns_tree, tvb, offset, 1, "Valid: %u",
1724                              (flags & 0x80) >> 7);
1725         proto_tree_add_item (sns_tree, hf_scsi_sns_errtype, tvb, offset, 1, 0);
1726         flags = tvb_get_guint8 (tvb, offset+2);
1727         proto_tree_add_text (sns_tree, tvb, offset+2, 1,
1728                              "Filemark: %u, EOM: %u, ILI: %u",
1729                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1730                              (flags & 0x20) >> 5);
1731         proto_tree_add_item (sns_tree, hf_scsi_snskey, tvb, offset+2, 1, 0);
1732         proto_tree_add_item (sns_tree, hf_scsi_snsinfo, tvb, offset+3, 4, 0);
1733         proto_tree_add_item (sns_tree, hf_scsi_addlsnslen, tvb, offset+7, 1, 0);
1734         proto_tree_add_text (sns_tree, tvb, offset+8, 4,
1735                              "Command-Specific Information: %s",
1736                              tvb_bytes_to_str (tvb, offset+8, 4));
1737         proto_tree_add_item (sns_tree, hf_scsi_ascascq, tvb, offset+12, 2, 0);
1738         proto_tree_add_item_hidden (sns_tree, hf_scsi_asc, tvb, offset+12, 1, 0);
1739         proto_tree_add_item_hidden (sns_tree, hf_scsi_ascq, tvb, offset+13,
1740                                     1, 0);
1741         proto_tree_add_item (sns_tree, hf_scsi_fru, tvb, offset+14, 1, 0);
1742         proto_tree_add_item (sns_tree, hf_scsi_sksv, tvb, offset+15, 1, 0);
1743         proto_tree_add_text (sns_tree, tvb, offset+15, 3,
1744                              "Sense Key Specific: %s",
1745                              tvb_bytes_to_str (tvb, offset+15, 3));
1746     }
1747 }
1748
1749 void
1750 dissect_scsi_cdb (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1751                   guint start, guint cdblen)
1752 {
1753     int offset = start;
1754     proto_item *ti;
1755     proto_tree *scsi_tree = NULL;
1756     guint8 opcode;
1757     scsi_cmnd_type cmd = 0;     /* 0 is undefined type */
1758     scsi_device_type devtype = 0;
1759     gchar *valstr;
1760     conversation_t *conversation;
1761     scsi_task_data_t *cdata;
1762     scsi_task_key_t ckey, *req_key;
1763     scsi_devtype_key_t dkey;
1764     scsi_devtype_data_t *devdata;
1765     
1766     opcode = tvb_get_guint8 (tvb, offset);
1767
1768     /* Identify target if possible */
1769     COPY_ADDRESS (&(dkey.devid), &pinfo->dst);
1770
1771     devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
1772                                                           &dkey);
1773     if (devdata != NULL) {
1774         devtype = devdata->devtype;
1775     }
1776     else {
1777         devtype = (scsi_device_type)scsi_def_devtype;
1778     }
1779
1780     if ((valstr = match_strval (opcode, scsi_spc2_val)) == NULL) {
1781         if (devtype == SCSI_DEV_SBC) {
1782             valstr = match_strval (opcode, scsi_sbc2_val);
1783             cmd = SCSI_CMND_SBC2;
1784         }
1785         else {
1786             /* Right now, the only choices are SBC or SSC. If we ever expand
1787              * this to decode other device types, this piece of code needs to
1788              * be modified.
1789              */
1790             valstr = match_strval (opcode, scsi_ssc2_val);
1791             cmd = SCSI_CMND_SSC2;
1792         }
1793     }
1794     else {
1795         cmd = SCSI_CMND_SPC2;
1796     }
1797     
1798     if (valstr != NULL) {
1799         if (check_col (pinfo->cinfo, COL_INFO)) {
1800             col_add_fstr (pinfo->cinfo, COL_INFO, "SCSI: %s", valstr);
1801         }
1802     }
1803     else {
1804         if (check_col (pinfo->cinfo, COL_INFO)) {
1805             col_add_fstr (pinfo->cinfo, COL_INFO, "SCSI Command: 0x%02x", opcode);
1806         }
1807     }
1808
1809     cdata = scsi_new_task (pinfo);
1810
1811     if (cdata) {
1812         cdata->opcode = opcode;
1813         cdata->devtype = cmd;
1814     }
1815     
1816     if (tree) {
1817         ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, start,
1818                                              cdblen, "SCSI CDB");
1819         scsi_tree = proto_item_add_subtree (ti, ett_scsi);
1820
1821         if (valstr != NULL) {
1822             if (cmd == SCSI_CMND_SPC2) {
1823                 proto_tree_add_uint_format (scsi_tree, hf_scsi_spcopcode, tvb,
1824                                             offset, 1,
1825                                             tvb_get_guint8 (tvb, offset),
1826                                             "Opcode: %s (0x%02x)", valstr,
1827                                             opcode);
1828             }
1829             else if (cmd == SCSI_CMND_SBC2) {
1830                 proto_tree_add_uint_format (scsi_tree, hf_scsi_sbcopcode, tvb,
1831                                             offset, 1,
1832                                             tvb_get_guint8 (tvb, offset),
1833                                             "Opcode: %s (0x%02x)", valstr,
1834                                             opcode);
1835             }
1836             else {
1837                  proto_tree_add_uint_format (scsi_tree, hf_scsi_sscopcode, tvb,
1838                                              offset, 1,
1839                                              tvb_get_guint8 (tvb, offset),
1840                                              "Opcode: %s (0x%02x)", valstr,
1841                                              opcode);
1842             }
1843         }
1844         else {
1845             proto_tree_add_item (scsi_tree, hf_scsi_sbcopcode, tvb, offset, 1, 0);
1846         }
1847     }
1848         
1849     if (cmd == SCSI_CMND_SPC2) {
1850         switch (opcode) {
1851         case SCSI_SPC2_INQUIRY:
1852             dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset+1, TRUE,
1853                                   TRUE, 0, cdata);
1854             break;
1855
1856         case SCSI_SPC2_EXTCOPY:
1857             dissect_scsi_extcopy (tvb, pinfo, scsi_tree, offset+1, TRUE,
1858                                   TRUE);
1859             break;
1860
1861         case SCSI_SPC2_LOGSELECT:
1862             dissect_scsi_logselect (tvb, pinfo, scsi_tree, offset+1, TRUE,
1863                                     TRUE);
1864             break;
1865
1866         case SCSI_SPC2_LOGSENSE:
1867             dissect_scsi_logsense (tvb, pinfo, scsi_tree, offset+1, TRUE,
1868                                    TRUE);
1869             break;
1870
1871         case SCSI_SPC2_MODESELECT6:
1872             dissect_scsi_modeselect6 (tvb, pinfo, scsi_tree, offset+1,
1873                                       TRUE, TRUE, 0);
1874             break;
1875
1876         case SCSI_SPC2_MODESELECT10:
1877             dissect_scsi_modeselect10 (tvb, pinfo, scsi_tree, offset+1,
1878                                        TRUE, TRUE, 0);
1879             break;
1880
1881         case SCSI_SPC2_MODESENSE6:
1882             dissect_scsi_modesense6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1883                                      TRUE, 0);
1884             break;
1885
1886         case SCSI_SPC2_MODESENSE10:
1887             dissect_scsi_modesense10 (tvb, pinfo, scsi_tree, offset+1,
1888                                       TRUE, TRUE, 0);
1889             break;
1890
1891         case SCSI_SPC2_PERSRESVIN:
1892             dissect_scsi_persresvin (tvb, pinfo, scsi_tree, offset+1, TRUE,
1893                                      TRUE, cdata, 0);
1894             break;
1895
1896         case SCSI_SPC2_PERSRESVOUT:
1897             dissect_scsi_persresvout (tvb, pinfo, scsi_tree, offset+1,
1898                                       TRUE, TRUE, cdata, 0);
1899             break;
1900
1901         case SCSI_SPC2_RELEASE6:
1902             dissect_scsi_release6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1903                                    TRUE);
1904             break;
1905
1906         case SCSI_SPC2_RELEASE10:
1907             dissect_scsi_release10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1908                                     TRUE);
1909             break;
1910
1911         case SCSI_SPC2_REPORTDEVICEID:
1912             dissect_scsi_reportdeviceid (tvb, pinfo, scsi_tree, offset+1,
1913                                          TRUE, TRUE);
1914             break;
1915
1916         case SCSI_SPC2_REPORTLUNS:
1917             dissect_scsi_reportluns (tvb, pinfo, scsi_tree, offset+1, TRUE,
1918                                      TRUE);
1919             break;
1920
1921         case SCSI_SPC2_REQSENSE:
1922             dissect_scsi_reqsense (tvb, pinfo, scsi_tree, offset+1, TRUE,
1923                                    TRUE);
1924             break;
1925
1926         case SCSI_SPC2_RESERVE6:
1927             dissect_scsi_reserve6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1928                                    TRUE);
1929             break;
1930
1931         case SCSI_SPC2_RESERVE10:
1932             dissect_scsi_reserve10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1933                                     TRUE);
1934             break;
1935
1936         case SCSI_SPC2_TESTUNITRDY:
1937             dissect_scsi_testunitrdy (tvb, pinfo, scsi_tree, offset+1,
1938                                       TRUE, TRUE);
1939             break;
1940
1941         default:
1942             call_dissector (data_handle, tvb, pinfo, scsi_tree);
1943             break;
1944         }
1945     }
1946     else if (cmd == SCSI_CMND_SBC2) {
1947         switch (opcode) {
1948
1949         case SCSI_SBC2_FORMATUNIT:
1950             dissect_scsi_formatunit (tvb, pinfo, scsi_tree, offset+1, TRUE,
1951                                      TRUE);
1952             break;
1953
1954         case SCSI_SBC2_READ6:
1955             dissect_scsi_rdwr6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1956                                 TRUE);
1957             break;
1958
1959         case SCSI_SBC2_READ10:
1960             dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1961                                  TRUE);
1962             break;
1963
1964         case SCSI_SBC2_READ12:
1965             dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1966                                  TRUE);
1967             break;
1968
1969         case SCSI_SBC2_READ16:
1970             dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1971                                  TRUE);
1972             break;
1973
1974         case SCSI_SBC2_READCAPACITY:
1975             dissect_scsi_readcapacity (tvb, pinfo, scsi_tree, offset+1,
1976                                        TRUE, TRUE);
1977             break;
1978
1979         case SCSI_SBC2_READDEFDATA10:
1980             dissect_scsi_readdefdata10 (tvb, pinfo, scsi_tree, offset+1,
1981                                         TRUE, TRUE);
1982             break;
1983
1984         case SCSI_SBC2_READDEFDATA12:
1985             dissect_scsi_readdefdata12 (tvb, pinfo, scsi_tree, offset+1,
1986                                         TRUE, TRUE);
1987             break;
1988
1989         case SCSI_SBC2_REASSIGNBLKS:
1990             dissect_scsi_reassignblks (tvb, pinfo, scsi_tree, offset+1,
1991                                        TRUE, TRUE);
1992             break;
1993
1994         case SCSI_SBC2_WRITE6:
1995             dissect_scsi_rdwr6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
1996                                 TRUE);
1997             break;
1998
1999         case SCSI_SBC2_WRITE10:
2000             dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2001                                  TRUE);
2002             break;
2003
2004         case SCSI_SBC2_WRITE12:
2005             dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2006                                  TRUE);
2007             break;
2008
2009         case SCSI_SBC2_WRITE16:
2010             dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2011                                  TRUE);
2012             break;
2013
2014         default:
2015             call_dissector (data_handle, tvb, pinfo, scsi_tree);
2016             break;
2017         }
2018     }
2019     else if (cmd == SCSI_CMND_SSC2) {
2020         call_dissector (data_handle, tvb, pinfo, scsi_tree);
2021     }
2022 }
2023
2024 static void
2025 dissect_scsi (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2026 {
2027 }
2028
2029 void
2030 dissect_scsi_payload (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2031                       guint offset, gboolean isreq, guint32 payload_len)
2032 {
2033     proto_item *ti;
2034     proto_tree *scsi_tree;
2035     guint8 opcode = 0xFF;
2036     scsi_cmnd_type cmd = 0;     /* 0 is undefined type */
2037     gchar *valstr;
2038     scsi_device_type dev = 0;
2039     scsi_task_data_t *cdata = NULL;
2040     scsi_devtype_key_t dkey;
2041     scsi_devtype_data_t *devdata;
2042     
2043     cdata = scsi_find_task (pinfo);
2044     
2045     if (!cdata) {
2046         /* we have no record of this exchange and so we can't dissect the
2047          * payload
2048          */
2049         return;
2050     }
2051
2052     opcode = cdata->opcode;
2053     cmd = cdata->devtype;
2054     
2055     if (tree) {
2056         if (cmd == SCSI_CMND_SPC2) {
2057             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
2058                                                  payload_len,
2059                                                  "SCSI Payload (%s %s)",
2060                                                  val_to_str (opcode,
2061                                                              scsi_spc2_val,
2062                                                              "0x%02x"),
2063                                                  isreq ? "Request" : "Response");
2064         }
2065         else if (cmd == SCSI_CMND_SBC2) {
2066             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
2067                                                  payload_len,
2068                                                  "SCSI Payload (%s %s)",
2069                                                  val_to_str (opcode,
2070                                                              scsi_sbc2_val,
2071                                                              "0x%02x"),
2072                                                  isreq ? "Request" : "Response");
2073         }
2074         else {
2075             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
2076                                                  payload_len,
2077                                                  "SCSI Payload (0x%02x %s)",
2078                                                  opcode,
2079                                                  isreq ? "Request" : "Response");
2080         }
2081
2082         scsi_tree = proto_item_add_subtree (ti, ett_scsi);
2083
2084         if (cmd == SCSI_CMND_SPC2) {
2085             switch (opcode) {
2086             case SCSI_SPC2_INQUIRY:
2087                 dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset, isreq,
2088                                       FALSE, payload_len, cdata);
2089                 break;
2090
2091             case SCSI_SPC2_EXTCOPY:
2092                 dissect_scsi_extcopy (tvb, pinfo, scsi_tree, offset, isreq,
2093                                       FALSE);
2094                 break;
2095
2096             case SCSI_SPC2_LOGSELECT:
2097                 dissect_scsi_logselect (tvb, pinfo, scsi_tree, offset, isreq,
2098                                         FALSE);
2099                 break;
2100
2101             case SCSI_SPC2_LOGSENSE:
2102                 dissect_scsi_logsense (tvb, pinfo, scsi_tree, offset, isreq,
2103                                        FALSE);
2104                 break;
2105
2106             case SCSI_SPC2_MODESELECT6:
2107                 dissect_scsi_modeselect6 (tvb, pinfo, scsi_tree, offset,
2108                                           isreq, FALSE, payload_len);
2109                 break;
2110
2111             case SCSI_SPC2_MODESELECT10:
2112                 dissect_scsi_modeselect10 (tvb, pinfo, scsi_tree, offset,
2113                                            isreq, FALSE, payload_len);
2114                 break;
2115
2116             case SCSI_SPC2_MODESENSE6:
2117                 dissect_scsi_modesense6 (tvb, pinfo, scsi_tree, offset, isreq,
2118                                          FALSE, payload_len);
2119                 break;
2120
2121             case SCSI_SPC2_MODESENSE10:
2122                 dissect_scsi_modesense10 (tvb, pinfo, scsi_tree, offset,
2123                                           isreq, FALSE, payload_len);
2124                 break;
2125
2126             case SCSI_SPC2_PERSRESVIN:
2127                 dissect_scsi_persresvin (tvb, pinfo, scsi_tree, offset, isreq,
2128                                          FALSE, cdata, payload_len);
2129                 break;
2130
2131             case SCSI_SPC2_PERSRESVOUT:
2132                 dissect_scsi_persresvout (tvb, pinfo, scsi_tree, offset,
2133                                           isreq, FALSE, cdata, payload_len);
2134                 break;
2135
2136             case SCSI_SPC2_RELEASE6:
2137                 dissect_scsi_release6 (tvb, pinfo, scsi_tree, offset, isreq,
2138                                        FALSE);
2139                 break;
2140
2141             case SCSI_SPC2_RELEASE10:
2142                 dissect_scsi_release10 (tvb, pinfo, scsi_tree, offset, isreq,
2143                                         FALSE);
2144                 break;
2145
2146             case SCSI_SPC2_REPORTDEVICEID:
2147                 dissect_scsi_reportdeviceid (tvb, pinfo, scsi_tree, offset,
2148                                              isreq, FALSE);
2149                 break;
2150
2151             case SCSI_SPC2_REPORTLUNS:
2152                 dissect_scsi_reportluns (tvb, pinfo, scsi_tree, offset, isreq,
2153                                          FALSE);
2154                 break;
2155
2156             case SCSI_SPC2_REQSENSE:
2157                 dissect_scsi_reqsense (tvb, pinfo, scsi_tree, offset, isreq,
2158                                        FALSE);
2159                 break;
2160
2161             case SCSI_SPC2_RESERVE6:
2162                 dissect_scsi_reserve6 (tvb, pinfo, scsi_tree, offset, isreq,
2163                                        FALSE);
2164                 break;
2165
2166             case SCSI_SPC2_RESERVE10:
2167                 dissect_scsi_reserve10 (tvb, pinfo, scsi_tree, offset, isreq,
2168                                         FALSE);
2169                 break;
2170
2171             case SCSI_SPC2_TESTUNITRDY:
2172                 dissect_scsi_testunitrdy (tvb, pinfo, scsi_tree, offset,
2173                                           isreq, FALSE);
2174                 break;
2175
2176             default:
2177                 call_dissector (data_handle, tvb, pinfo, scsi_tree);
2178                 break;
2179             }
2180         }
2181         else if (cmd == SCSI_CMND_SBC2) {
2182             switch (opcode) {
2183
2184             case SCSI_SBC2_FORMATUNIT:
2185                 dissect_scsi_formatunit (tvb, pinfo, scsi_tree, offset, isreq,
2186                                          FALSE);
2187                 break;
2188
2189             case SCSI_SBC2_READ6:
2190                 dissect_scsi_rdwr6 (tvb, pinfo, scsi_tree, offset, isreq,
2191                                     FALSE);
2192                 break;
2193
2194             case SCSI_SBC2_READ10:
2195                 dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset, isreq,
2196                                      FALSE);
2197                 break;
2198
2199             case SCSI_SBC2_READ12:
2200                 dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset, isreq,
2201                                      FALSE);
2202                 break;
2203
2204             case SCSI_SBC2_READ16:
2205                 dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset, isreq,
2206                                      FALSE);
2207                 break;
2208
2209             case SCSI_SBC2_READCAPACITY:
2210                 dissect_scsi_readcapacity (tvb, pinfo, scsi_tree, offset,
2211                                            isreq, FALSE);
2212                 break;
2213
2214             case SCSI_SBC2_READDEFDATA10:
2215                 dissect_scsi_readdefdata10 (tvb, pinfo, scsi_tree, offset,
2216                                             isreq, FALSE);
2217                 break;
2218
2219             case SCSI_SBC2_READDEFDATA12:
2220                 dissect_scsi_readdefdata12 (tvb, pinfo, scsi_tree, offset,
2221                                             isreq, FALSE);
2222                 break;
2223
2224             case SCSI_SBC2_REASSIGNBLKS:
2225                 dissect_scsi_reassignblks (tvb, pinfo, scsi_tree, offset,
2226                                            isreq, FALSE);
2227                 break;
2228
2229             case SCSI_SBC2_WRITE6:
2230                 dissect_scsi_rdwr6 (tvb, pinfo, scsi_tree, offset, isreq,
2231                                     FALSE);
2232                 break;
2233
2234             case SCSI_SBC2_WRITE10:
2235                 dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset, isreq,
2236                                      FALSE);
2237                 break;
2238
2239             case SCSI_SBC2_WRITE12:
2240                 dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset, isreq,
2241                                      FALSE);
2242                 break;
2243
2244             case SCSI_SBC2_WRITE16:
2245                 dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset, isreq,
2246                                      FALSE);
2247                 break;
2248
2249             default:
2250                 call_dissector (data_handle, tvb, pinfo, scsi_tree);
2251                 break;
2252             }
2253         }
2254         else {
2255             call_dissector (data_handle, tvb, pinfo, scsi_tree);
2256         }
2257     }
2258 }
2259
2260 void
2261 proto_register_scsi (void)
2262 {
2263     /* Setup list of header fields  See Section 1.6.1 for details*/
2264     static hf_register_info hf[] = {
2265         { &hf_scsi_spcopcode,
2266           {"SPC-2 Opcode", "scsi.spc.opcode", FT_UINT8, BASE_HEX,
2267            VALS (scsi_spc2_val), 0x0, "", HFILL}},
2268         { &hf_scsi_sbcopcode,
2269           {"SBC-2 Opcode", "scsi.sbc.opcode", FT_UINT8, BASE_HEX,
2270            VALS (scsi_sbc2_val), 0x0, "", HFILL}},
2271         { &hf_scsi_sscopcode,
2272           {"SSC-2 Opcode", "scsi.ssc.opcode", FT_UINT8, BASE_HEX,
2273            VALS (scsi_ssc2_val), 0x0, "", HFILL}},
2274         { &hf_scsi_control,
2275           {"Control", "scsi.cdb.control", FT_UINT8, BASE_HEX, NULL, 0x0, "",
2276            HFILL}},
2277         { &hf_scsi_inquiry_flags,
2278           {"Flags", "scsi.inquiry.flags", FT_UINT8, BASE_BIN, NULL, 0x0, "",
2279            HFILL}},
2280         { &hf_scsi_inquiry_evpd_page,
2281           {"EVPD Page Code", "scsi.inquiry.evpd.pagecode", FT_UINT8, BASE_HEX,
2282            VALS (scsi_evpd_pagecode_val), 0x0, "", HFILL}},
2283         { &hf_scsi_inquiry_cmdt_page,
2284           {"CMDT Page Code", "scsi.inquiry.cmdt.pagecode", FT_UINT8, BASE_HEX,
2285            NULL, 0x0, "", HFILL}},
2286         { &hf_scsi_alloclen,
2287           {"Allocation Length", "scsi.cdb.alloclen", FT_UINT8, BASE_DEC, NULL,
2288            0x0, "", HFILL}},
2289         { &hf_scsi_logsel_flags,
2290           {"Flags", "scsi.logsel.flags", FT_UINT8, BASE_BIN, NULL, 0x0, "",
2291            HFILL}},
2292         { &hf_scsi_log_pc,
2293           {"Page Control", "scsi.log.pc", FT_UINT8, BASE_BIN,
2294            VALS (scsi_logsel_pc_val), 0xC0, "", HFILL}},
2295         { &hf_scsi_paramlen,
2296           {"Parameter Length", "scsi.cdb.paramlen", FT_UINT8, BASE_DEC, NULL,
2297            0x0, "", HFILL}},
2298         { &hf_scsi_logsns_flags,
2299           {"Flags", "scsi.logsns.flags", FT_UINT16, BASE_BIN, NULL, 0x0, "",
2300            HFILL}},
2301         { &hf_scsi_logsns_pagecode,
2302           {"Page Code", "scsi.logsns.pagecode", FT_UINT8, BASE_HEX,
2303            VALS (scsi_logsns_page_val), 0x3F0, "", HFILL}},
2304         { &hf_scsi_paramlen16,
2305           {"Parameter Length", "scsi.cdb.paramlen16", FT_UINT16, BASE_DEC, NULL,
2306            0x0, "", HFILL}},
2307         { &hf_scsi_modesel_flags,
2308           {"Mode Sense/Select Flags", "scsi.cdb.mode.flags", FT_UINT8, BASE_BIN,
2309            NULL, 0x0, "", HFILL}},
2310         { &hf_scsi_alloclen16,
2311           {"Allocation Length", "scsi.cdb.alloclen16", FT_UINT16, BASE_DEC,
2312            NULL, 0x0, "", HFILL}},
2313         { &hf_scsi_modesns_pc,
2314           {"Page Control", "scsi.mode.pc", FT_UINT8, BASE_BIN,
2315            VALS (scsi_modesns_pc_val), 0xC0, "", HFILL}},
2316         { &hf_scsi_modesns_pagecode,
2317           {"Page Code", "scsi.mode.pagecode", FT_UINT8, BASE_HEX,
2318            VALS (scsi_modesns_page_val), 0x3F, "", HFILL}},
2319         { &hf_scsi_modesns_flags,
2320           {"Flags", "scsi.mode.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
2321            HFILL}},
2322         { &hf_scsi_persresvin_svcaction,
2323           {"Service Action", "scsi.persresvin.svcaction", FT_UINT8, BASE_HEX,
2324            VALS (scsi_persresvin_svcaction_val), 0x0F, "", HFILL}},
2325         { &hf_scsi_persresvout_svcaction,
2326           {"Service Action", "scsi.persresvout.svcaction", FT_UINT8, BASE_HEX,
2327            VALS (scsi_persresvout_svcaction_val), 0x0F, "", HFILL}},
2328         { &hf_scsi_persresv_scope,
2329           {"Reservation Scope", "scsi.persresv.scope", FT_UINT8, BASE_HEX,
2330            VALS (scsi_persresv_scope_val), 0xF0, "", HFILL}},
2331         { &hf_scsi_persresv_type,
2332           {"Reservation Type", "scsi.persresv.type", FT_UINT8, BASE_HEX,
2333            VALS (scsi_persresv_type_val), 0x0F, "", HFILL}},
2334         { &hf_scsi_release_flags,
2335           {"Release Flags", "scsi.release.flags", FT_UINT8, BASE_BIN, NULL,
2336            0x0, "", HFILL}},
2337         { &hf_scsi_release_thirdpartyid,
2338           {"Third-Party ID", "scsi.release.thirdpartyid", FT_BYTES, BASE_HEX,
2339            NULL, 0x0, "", HFILL}},
2340         { &hf_scsi_alloclen32,
2341           {"Allocation Length", "scsi.cdb.alloclen32", FT_UINT32, BASE_DEC,
2342            NULL, 0x0, "", HFILL}},
2343         { &hf_scsi_formatunit_flags,
2344           {"Flags", "scsi.formatunit.flags", FT_UINT8, BASE_BIN, NULL, 0xF8,
2345            "", HFILL}},
2346         { &hf_scsi_cdb_defectfmt,
2347           {"Defect List Format", "scsi.cdb.defectfmt", FT_UINT8, BASE_BIN,
2348            NULL, 0x7, "", HFILL}},
2349         { &hf_scsi_formatunit_interleave,
2350           {"Interleave", "scsi.formatunit.interleave", FT_UINT16, BASE_HEX,
2351            NULL, 0x0, "", HFILL}},
2352         { &hf_scsi_formatunit_vendor,
2353           {"Vendor Unique", "scsi.formatunit.vendor", FT_UINT8, BASE_HEX, NULL,
2354            0x0, "", HFILL}},
2355         { &hf_scsi_rdwr6_lba,
2356           {"Logical Block Address (LBA)", "scsi.rdwr6.lba", FT_UINT24, BASE_DEC,
2357            NULL, 0x0FFFFF, "", HFILL}},
2358         { &hf_scsi_rdwr6_xferlen,
2359           {"Transfer Length", "scsi.rdwr6.xferlen", FT_UINT8, BASE_DEC, NULL, 0x0,
2360            "", HFILL}},
2361         { &hf_scsi_rdwr10_lba,
2362           {"Logical Block Address (LBA)", "scsi.rdwr10.lba", FT_UINT32, BASE_DEC,
2363            NULL, 0x0, "", HFILL}},
2364         { &hf_scsi_rdwr10_xferlen,
2365           {"Transfer Length", "scsi.rdwr10.xferlen", FT_UINT16, BASE_DEC, NULL,
2366            0x0, "", HFILL}},
2367         { &hf_scsi_read_flags,
2368           {"Flags", "scsi.read.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
2369            HFILL}},
2370         { &hf_scsi_rdwr12_xferlen,
2371           {"Transfer Length", "scsi.rdwr12.xferlen", FT_UINT32, BASE_DEC, NULL,
2372            0x0, "", HFILL}},
2373         { &hf_scsi_rdwr16_lba,
2374           {"Logical Block Address (LBA)", "scsi.rdwr16.lba", FT_BYTES, BASE_DEC,
2375            NULL, 0x0, "", HFILL}},
2376         { &hf_scsi_readcapacity_flags,
2377           {"Flags", "scsi.readcapacity.flags", FT_UINT8, BASE_BIN, NULL, 0x0,
2378            "", HFILL}},
2379         { &hf_scsi_readcapacity_lba,
2380           {"Logical Block Address", "scsi.readcapacity.lba", FT_UINT32, BASE_DEC,
2381            NULL, 0x0, "", HFILL}},
2382         { &hf_scsi_readcapacity_pmi,
2383           {"PMI", "scsi.readcapacity.pmi", FT_UINT8, BASE_BIN, NULL, 0x1, "",
2384            HFILL}},
2385         { &hf_scsi_readdefdata_flags,
2386           {"Flags", "scsi.readdefdata.flags", FT_UINT8, BASE_BIN, NULL, 0x0, "",
2387            HFILL}},
2388         { &hf_scsi_reassignblks_flags,
2389           {"Flags", "scsi.reassignblks.flags", FT_UINT8, BASE_BIN, NULL, 0x0, "",
2390            HFILL}},
2391         { &hf_scsi_inq_devtype,
2392           {"Device Type", "scsi.inquiry.devtype", FT_UINT8, BASE_HEX,
2393            VALS (scsi_devtype_val), 0x0F, "", HFILL}},
2394         { & hf_scsi_inq_version,
2395           {"Version", "scsi.inquiry.version", FT_UINT8, BASE_HEX,
2396            VALS (scsi_inquiry_vers_val), 0x0, "", HFILL}},
2397         { &hf_scsi_inq_normaca,
2398           {"NormACA", "scsi.inquiry.normaca", FT_UINT8, BASE_HEX, NULL, 0x20,
2399            "", HFILL}},
2400         { &hf_scsi_rluns_lun,
2401           {"LUN", "scsi.reportluns.lun", FT_UINT8, BASE_DEC, NULL, 0x0, "",
2402            HFILL}},
2403         { &hf_scsi_rluns_multilun,
2404           {"Multi-level LUN", "scsi.reportluns.mlun", FT_BYTES, BASE_HEX, NULL,
2405            0x0, "", HFILL}},
2406         { &hf_scsi_modesns_errrep,
2407           {"MRIE", "scsi.mode.mrie", FT_UINT8, BASE_HEX,
2408            VALS (scsi_modesns_mrie_val), 0x0F, "", HFILL}},
2409         { &hf_scsi_modesns_tst,
2410           {"Task Set Type", "scsi.mode.tst", FT_UINT8, BASE_BIN,
2411            VALS (scsi_modesns_tst_val), 0xE0, "", HFILL}},
2412         { &hf_scsi_modesns_qmod,
2413           {"Queue Algorithm Modifier", "scsi.mode.qmod", FT_UINT8, BASE_HEX,
2414            VALS (scsi_modesns_qmod_val), 0xF0, "", HFILL}},
2415         { &hf_scsi_modesns_qerr,
2416           {"Queue Error Management", "scsi.mode.qerr", FT_BOOLEAN, BASE_HEX,
2417            TFS (&scsi_modesns_qerr_val), 0x2, "", HFILL}},
2418         { &hf_scsi_modesns_tas,
2419           {"Task Aborted Status", "scsi.mode.tac", FT_BOOLEAN, BASE_HEX,
2420            TFS (&scsi_modesns_tas_val), 0x80, "", HFILL}},
2421         { &hf_scsi_modesns_rac,
2422           {"Report a Check", "ssci.mode.rac", FT_BOOLEAN, BASE_HEX,
2423            TFS (&scsi_modesns_rac_val), 0x40, "", HFILL}},
2424         { &hf_scsi_protocol,
2425           {"Protocol", "scsi.proto", FT_UINT8, BASE_DEC, VALS (scsi_proto_val),
2426            0x0F, "", HFILL}},
2427         { &hf_scsi_sns_errtype,
2428           {"SNS Error Type", "scsi.sns.errtype", FT_UINT8, BASE_HEX,
2429            VALS (scsi_sns_errtype_val), 0x7F, "", HFILL}},
2430         { &hf_scsi_snskey,
2431           {"Sense Key", "scsi.sns.key", FT_UINT8, BASE_HEX,
2432            VALS (scsi_sensekey_val), 0x0F, "", HFILL}},
2433         { &hf_scsi_snsinfo,
2434           {"Sense Info", "scsi.sns.info", FT_UINT32, BASE_HEX, NULL, 0x0, "",
2435            HFILL}},
2436         { &hf_scsi_addlsnslen,
2437           {"Additional Sense Length", "scsi.sns.addlen", FT_UINT8, BASE_DEC,
2438            NULL, 0x0, "", HFILL}},
2439         { &hf_scsi_asc,
2440           {"Additional Sense Code", "scsi.sns.asc", FT_UINT8, BASE_HEX, NULL,
2441            0x0, "", HFILL}},
2442         { &hf_scsi_ascq,
2443           {"Additional Sense Code Qualifier", "scsi.sns.ascq", FT_UINT8,
2444            BASE_HEX, NULL, 0x0, "", HFILL}},
2445         { &hf_scsi_ascascq,
2446           {"Additional Sense Code+Qualifier", "scsi.sns.ascascq", FT_UINT16,
2447            BASE_HEX, VALS (scsi_asc_val), 0x0, "", HFILL}},
2448         { &hf_scsi_fru,
2449           {"Field Replaceable Unit Code", "scsi.sns.fru", FT_UINT8, BASE_HEX,
2450            NULL, 0x0, "", HFILL}},
2451         { &hf_scsi_sksv,
2452           {"SKSV", "scsi.sns.sksv", FT_BOOLEAN, BASE_HEX, NULL, 0x80, "",
2453            HFILL}},
2454         { &hf_scsi_persresv_key,
2455           {"Reservation Key", "scsi.spc2.resv.key", FT_BYTES, BASE_HEX, NULL,
2456            0x0, "", HFILL}},
2457         { &hf_scsi_persresv_scopeaddr,
2458           {"Scope Address", "scsi.spc2.resv.scopeaddr", FT_BYTES, BASE_HEX, NULL,
2459            0x0, "", HFILL}},
2460     };
2461
2462     /* Setup protocol subtree array */
2463     static gint *ett[] = {
2464         &ett_scsi,
2465         &ett_scsi_page,
2466     };
2467     module_t *scsi_module;
2468     
2469     /* Register the protocol name and description */
2470     proto_scsi = proto_register_protocol("SCSI", "SCSI", "scsi");
2471
2472     /* Required function calls to register the header fields and subtrees used */
2473     proto_register_field_array(proto_scsi, hf, array_length(hf));
2474     proto_register_subtree_array(ett, array_length(ett));
2475     register_init_routine (&scsi_init_protocol);
2476     register_dissector ("SCSI", dissect_scsi, proto_scsi);
2477     data_handle = find_dissector ("data");
2478
2479     /* add preferences to decode SCSI message */
2480     scsi_module = prefs_register_protocol (proto_scsi, NULL);
2481     prefs_register_enum_preference (scsi_module, "decode_scsi_messages_as",
2482                                     "Decode SCSI Messages As",
2483                                     "When Target Cannot Be Identified, Decode SCSI Messages As",
2484                                     &scsi_def_devtype, scsi_devtype_options, TRUE);
2485 }