2 * Author: Dinesh G Dutt (ddutt@cisco.com)
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 2002 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #ifndef __PACKET_SCSI_H_
26 #define __PACKET_SCSI_H_
28 #include "ws_symbol_export.h"
30 /* Structure containing itl nexus data :
31 * The itlq nexus is a structure containing data specific
32 * for a initiator target lun combination.
34 typedef struct _itl_nexus_t {
35 #define SCSI_CMDSET_DEFAULT 0x80
36 #define SCSI_CMDSET_MASK 0x7f
37 guint8 cmdset; /* This is a bitfield.
38 * The MSB (0x80) represents whether
39 * 0: the commandset is known from a INQ PDU
40 * 1: is using the "default" from preferences.
41 * The lower 7 bits represent the commandset used
42 * for decoding commands on this itl nexus.
43 * The field is initialized to 0xff == unknown.
45 conversation_t *conversation;
48 /* Structure containing itlq nexus data :
49 * The itlq nexus is a structure containing data specific
50 * for a initiator target lun queue/commandid combination.
52 typedef struct _itlq_nexus_t {
53 guint32 first_exchange_frame;
54 guint32 last_exchange_frame;
55 guint16 lun; /* initialized to 0xffff == unknown */
56 guint16 scsi_opcode; /* initialized to 0xffff == unknown */
59 #define SCSI_DATA_READ 0x0001
60 #define SCSI_DATA_WRITE 0x0002
61 guint16 task_flags; /* Flags set by the transport for this
64 * If there is no data being transferred both flags
65 * are 0 and both data lengths below are undefined.
67 * If one of the flags are set the amount of
68 * data being transferred is held in data_length
69 * and bidir_data_length is undefined.
71 * If both flags are set (a bidirectional transfer)
72 * data_length specifies the amount of DATA-OUT and
73 * bidir_data_length specifies the amount of DATA-IN
76 guint32 bidir_data_length;
78 guint32 alloc_len; /* we need to track alloc_len between the CDB and
79 * the DATA pdus for some opcodes.
84 void *extra_data; /* extra data that that is task specific */
88 #define SCSI_PDU_TYPE_CDB 1
89 #define SCSI_PDU_TYPE_DATA 2
90 #define SCSI_PDU_TYPE_RSP 4
91 #define SCSI_PDU_TYPE_SNS 5
92 typedef struct _scsi_task_data {
99 /* list of commands for each commandset */
100 typedef void (*scsi_dissector_t)(tvbuff_t *tvb, packet_info *pinfo,
101 proto_tree *tree, guint offset,
102 gboolean isreq, gboolean iscdb,
103 guint32 payload_len, scsi_task_data_t *cdata);
105 typedef struct _scsi_cdb_table_t {
106 scsi_dissector_t func;
111 #define SCSI_SPC_ACCESS_CONTROL_IN 0x86
112 #define SCSI_SPC_ACCESS_CONTROL_OUT 0x87
113 #define SCSI_SPC_CHANGE_DEFINITION 0x40
114 #define SCSI_SPC_COMPARE 0x39
115 #define SCSI_SPC_COPY 0x18
116 #define SCSI_SPC_COPY_AND_VERIFY 0x3A
117 #define SCSI_SPC_INQUIRY 0x12
118 #define SCSI_SPC_EXTCOPY 0x83
119 #define SCSI_SPC_LOGSELECT 0x4C
120 #define SCSI_SPC_LOGSENSE 0x4D
121 #define SCSI_SPC_MODESELECT6 0x15
122 #define SCSI_SPC_MODESELECT10 0x55
123 #define SCSI_SPC_MODESENSE6 0x1A
124 #define SCSI_SPC_MODESENSE10 0x5A
125 #define SCSI_SPC_PERSRESVIN 0x5E
126 #define SCSI_SPC_PERSRESVOUT 0x5F
127 #define SCSI_SPC_PREVMEDREMOVAL 0x1E
128 #define SCSI_SPC_READBUFFER 0x3C
129 #define SCSI_SPC_RCVCOPYRESULTS 0x84
130 #define SCSI_SPC_RCVDIAGRESULTS 0x1C
131 #define SCSI_SPC_RELEASE6 0x17
132 #define SCSI_SPC_RELEASE10 0x57
133 #define SCSI_SPC_MGMT_PROTOCOL_IN 0xA3
134 #define SCSI_SPC_REPORTLUNS 0xA0
135 #define SCSI_SPC_REQSENSE 0x03
136 #define SCSI_SPC_RESERVE6 0x16
137 #define SCSI_SPC_RESERVE10 0x56
138 #define SCSI_SPC_SENDDIAG 0x1D
139 #define SCSI_SPC_SETDEVICEID 0xA4
140 #define SCSI_SPC_TESTUNITRDY 0x00
141 #define SCSI_SPC_WRITEBUFFER 0x3B
142 #define SCSI_SPC_VARLENCDB 0x7F
144 void dissect_spc_inquiry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint32 payload_len, scsi_task_data_t *cdata);
145 void dissect_spc_logselect(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
146 void dissect_spc_logsense(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
147 void dissect_spc_mgmt_protocol_in(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
148 void dissect_spc_modeselect6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len, scsi_task_data_t *cdata);
149 void dissect_spc_modesense6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len, scsi_task_data_t *cdata);
150 void dissect_spc_modeselect10(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len, scsi_task_data_t *cdata);
151 void dissect_spc_modesense10(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len, scsi_task_data_t *cdata);
152 void dissect_spc_persistentreservein(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len, scsi_task_data_t *cdata);
153 void dissect_spc_persistentreserveout(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
154 void dissect_spc_reportluns(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
155 void dissect_spc_testunitready (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
156 void dissect_spc_requestsense (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
157 void dissect_spc_preventallowmediaremoval (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
158 void dissect_spc_writebuffer (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb _U_, guint payload_len _U_, scsi_task_data_t *cdata _U_);
159 void dissect_spc_reserve6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
160 void dissect_spc_release6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
161 void dissect_spc_reserve10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
162 void dissect_spc_release10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
163 void dissect_spc_senddiagnostic (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
164 void dissect_spc_extcopy (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset, gboolean isreq, gboolean iscdb, guint payload_len _U_, scsi_task_data_t *cdata _U_);
170 extern const value_string scsi_status_val[];
175 * These can be supplied to the dissection routines if the caller happens
176 * to know the device type (e.g., NDMP assumes that a "jukebox" is a
177 * media changer, SCSI_DEV_SMC, and a "tape" is a sequential access device,
180 * If the caller doesn't know the device type, it supplies SCSI_DEV_UNKNOWN.
182 #define SCSI_DEV_UNKNOWN -1
183 #define SCSI_DEV_SBC 0x0
184 #define SCSI_DEV_SSC 0x1
185 #define SCSI_DEV_PRNT 0x2
186 #define SCSI_DEV_PROC 0x3
187 #define SCSI_DEV_WORM 0x4
188 #define SCSI_DEV_CDROM 0x5
189 #define SCSI_DEV_SCAN 0x6
190 #define SCSI_DEV_OPTMEM 0x7
191 #define SCSI_DEV_SMC 0x8
192 #define SCSI_DEV_COMM 0x9
193 #define SCSI_DEV_RAID 0xC
194 #define SCSI_DEV_SES 0xD
195 #define SCSI_DEV_RBC 0xE
196 #define SCSI_DEV_OCRW 0xF
197 #define SCSI_DEV_OSD 0x11
198 #define SCSI_DEV_ADC 0x12
199 #define SCSI_DEV_NOLUN 0x1F
201 #define SCSI_DEV_BITS 0x1F /* the lower 5 bits indicate device type */
202 #define SCSI_MS_PCODE_BITS 0x3F /* Page code bits in Mode Sense */
204 /* Function Decls; functions invoked by SAM-2 transport protocols such as
207 void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *,
208 gint, itlq_nexus_t *, itl_nexus_t *);
209 void dissect_scsi_rsp (tvbuff_t *, packet_info *, proto_tree *, itlq_nexus_t *, itl_nexus_t *, guint8);
210 void dissect_scsi_payload (tvbuff_t *, packet_info *, proto_tree *,
211 gboolean, itlq_nexus_t *, itl_nexus_t *,
212 guint32 relative_offset);
213 void dissect_scsi_snsinfo (tvbuff_t *, packet_info *, proto_tree *, guint, guint, itlq_nexus_t *, itl_nexus_t *);
215 void dissect_scsi_lun(proto_tree *, tvbuff_t *, guint);
217 WS_DLL_PUBLIC const value_string scsi_mmc_vals[];
219 extern const int *cdb_control_fields[6];
220 extern gint ett_scsi_control;
221 extern int hf_scsi_control;
222 extern int hf_scsi_alloclen16;
224 /* service actions */
225 #define SHORT_FORM_BLOCK_ID 0x00
226 #define SHORT_FORM_VENDOR_SPECIFIC 0x01
227 #define LONG_FORM 0x06
228 #define EXTENDED_FORM 0x08
229 #define SERVICE_READ_CAPACITY16 0x10
230 #define SERVICE_READ_LONG16 0x11
231 #define SERVICE_GET_LBA_STATUS 0x12
233 extern const value_string service_action_vals[];
234 extern const value_string scsi_devid_codeset_val[];
235 extern const value_string scsi_devid_idtype_val[];
236 extern value_string_ext scsi_asc_val_ext;
238 /* 0xA3 MGMT PROTOCOL IN service actions */
239 #define MPI_MANAGEMENT_PROTOCOL_IN 0x10
240 #define MPI_REPORT_SUPPORTED_OPERATION_CODES 0x0C
242 /* These two defines are used to handle cases where data coming back from
243 * the device is truncated due to a too short allocation_length specified
244 * in the command CDB.
245 * This is semi-common in SCSI and it would be wrong to mark these packets
246 * as [malformed packets].
247 * These macros will reset the reported length to what the data pdu specified
248 * and if a ReportedBoundsError is generated we will instead throw
251 * Please see dissect_spc_inquiry() for an example how to use these
254 #define TRY_SCSI_CDB_ALLOC_LEN(pinfo, tvb, offset, length) \
256 volatile gboolean short_packet; \
258 guint32 end_data_offset=0; \
260 short_packet=pinfo->fd->cap_len<pinfo->fd->pkt_len; \
261 new_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);\
266 #define END_TRY_SCSI_CDB_ALLOC_LEN \
267 if(end_data_offset){ \
268 /* just verify we can read all the bytes we were\
271 tvb_get_guint8(tvb,end_data_offset); \
274 CATCH(BoundsError) { \
276 /* this was a short packet */ \
279 /* We probably tried to dissect beyond the end \
280 * of the alloc len reported in the data \
281 * pdu. This is not an error so dont flag it as \
283 * it is the alloc_len in the CDB that is the \
288 CATCH(ReportedBoundsError) { \
290 /* this was a short packet */ \
293 /* this packet was not really short but limited \
294 * due to a short SCSI allocation length \
296 THROW(ScsiBoundsError); \
302 /* If the data pdu contains an alloc_len as well, this macro can be set
303 * to registe this offset for the TRY section above.
304 * At the end of the TRY section we will, if set, verify that the data
305 * pdu contained all bytes that was specified in the data alloc len.
307 * This macro does currently not do anything but we might enhance it in
308 * the future. There is no harm in teaching the dissector about how long
309 * the data pdu is supposed to be according to alloc_len in the data pdu
311 #define SET_SCSI_DATA_END(offset) \
312 end_data_offset=offset;