whitespace fixes; mostly: remove trailing blanks
[metze/wireshark/wip.git] / epan / dissectors / packet-scsi.h
1 /* packet-scsi.h
2  * Author: Dinesh G Dutt (ddutt@cisco.com)
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 2002 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifndef __PACKET_SCSI_H_
26 #define __PACKET_SCSI_H_
27
28 #include "ws_symbol_export.h"
29
30 /* Structure containing itl nexus data :
31  * The itlq nexus is a structure containing data specific
32  * for a initiator target lun combination.
33  */
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.
44                             */
45     conversation_t *conversation;
46 } itl_nexus_t;
47
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.
51  */
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 */
57     guint16 flags;
58
59 #define SCSI_DATA_READ  0x0001
60 #define SCSI_DATA_WRITE 0x0002
61     guint16 task_flags; /* Flags set by the transport for this
62                          * scsi task.
63                          *
64                          * If there is no data being transferred both flags
65                          * are 0 and both data lengths below are undefined.
66                          *
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.
70                          *
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
74                          */
75     guint32 data_length;
76     guint32 bidir_data_length;
77
78     guint32 alloc_len;  /* we need to track alloc_len between the CDB and
79                          * the DATA pdus for some opcodes.
80                          */
81     nstime_t fc_time;
82
83
84     void *extra_data;     /* extra data that that is task specific */
85 } itlq_nexus_t;
86
87
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 {
93     int type;
94     itlq_nexus_t *itlq;
95     itl_nexus_t *itl;
96 } scsi_task_data_t;
97
98
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);
104
105 typedef struct _scsi_cdb_table_t {
106         scsi_dissector_t        func;
107 } scsi_cdb_table_t;
108
109
110 /* SPC Commands */
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
143
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_);
165
166
167
168
169
170 extern const value_string scsi_status_val[];
171
172 /*
173  * SCSI Device Types.
174  *
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,
178  * SCSI_DEV_SSC).
179  *
180  * If the caller doesn't know the device type, it supplies SCSI_DEV_UNKNOWN.
181  */
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
200
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 */
203
204 /* Function Decls; functions invoked by SAM-2 transport protocols such as
205  * FCP/iSCSI
206  */
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 *);
214
215 void dissect_scsi_lun(proto_tree *, tvbuff_t *, guint);
216
217 WS_DLL_PUBLIC const value_string scsi_mmc_vals[];
218
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;
223
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
232
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;
237
238 /* 0xA3 MGMT PROTOCOL IN service actions */
239 #define MPI_MANAGEMENT_PROTOCOL_IN           0x10
240 #define MPI_REPORT_SUPPORTED_OPERATION_CODES 0x0C
241
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
249  * ScsiBoundsError
250  *
251  * Please see dissect_spc_inquiry() for an example how to use these
252  * macros.
253  */
254 #define TRY_SCSI_CDB_ALLOC_LEN(pinfo, tvb, offset, length)              \
255     {                                                                   \
256         volatile gboolean short_packet;                                 \
257         tvbuff_t *new_tvb;                                              \
258         guint32 end_data_offset=0;                                      \
259                                                                         \
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);\
262         tvb=new_tvb;                                                    \
263         offset=0;                                                       \
264         TRY {
265
266 #define END_TRY_SCSI_CDB_ALLOC_LEN                                      \
267                     if(end_data_offset){                                \
268                         /* just verify we can read all the bytes we were\
269                          * supposed to.                                 \
270                          */                                             \
271                         tvb_get_guint8(tvb,end_data_offset);            \
272                 }                                                       \
273             } /* TRY */                                                 \
274         CATCH(BoundsError) {                                            \
275                 if(short_packet){                                       \
276                         /* this was a short packet */                   \
277                         RETHROW;                                        \
278                 } else {                                                \
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 \
282                          * one                                          \
283                          * it is the alloc_len in the CDB that is the   \
284                          * important one                                \
285                          */                                             \
286                 }                                                       \
287             }                                                           \
288         CATCH(ReportedBoundsError) {                                    \
289                 if(short_packet){                                       \
290                         /* this was a short packet */                   \
291                         RETHROW;                                        \
292                 } else {                                                \
293                         /* this packet was not really short but limited \
294                          * due to a short SCSI allocation length        \
295                          */                                             \
296                         THROW(ScsiBoundsError);                         \
297                 }                                                       \
298             }                                                           \
299         ENDTRY;                                                         \
300     }
301
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.
306  *
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
310  */
311 #define SET_SCSI_DATA_END(offset)                                       \
312         end_data_offset=offset;
313
314
315 #endif