HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-scsi.h
blob2dbd714e0b1ae43cd8a3b65dab1ecb633e5979ad
1 /* packet-scsi.h
2 * Author: Dinesh G Dutt (ddutt@cisco.com)
4 * $Id$
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 #include <epan/exceptions.h>
32 /* Structure containing itl nexus data :
33 * The itlq nexus is a structure containing data specific
34 * for a initiator target lun combination.
36 typedef struct _itl_nexus_t {
37 #define SCSI_CMDSET_DEFAULT 0x80
38 #define SCSI_CMDSET_MASK 0x7f
39 guint8 cmdset; /* This is a bitfield.
40 * The MSB (0x80) represents whether
41 * 0: the commandset is known from a INQ PDU
42 * 1: is using the "default" from preferences.
43 * The lower 7 bits represent the commandset used
44 * for decoding commands on this itl nexus.
45 * The field is initialized to 0xff == unknown.
47 conversation_t *conversation;
48 } itl_nexus_t;
50 /* Structure containing itlq nexus data :
51 * The itlq nexus is a structure containing data specific
52 * for a initiator target lun queue/commandid combination.
54 typedef struct _itlq_nexus_t {
55 guint32 first_exchange_frame;
56 guint32 last_exchange_frame;
57 guint16 lun; /* initialized to 0xffff == unknown */
58 guint16 scsi_opcode; /* initialized to 0xffff == unknown */
59 guint16 flags;
61 #define SCSI_DATA_READ 0x0001
62 #define SCSI_DATA_WRITE 0x0002
63 guint16 task_flags; /* Flags set by the transport for this
64 * scsi task.
66 * If there is no data being transferred both flags
67 * are 0 and both data lengths below are undefined.
69 * If one of the flags are set the amount of
70 * data being transferred is held in data_length
71 * and bidir_data_length is undefined.
73 * If both flags are set (a bidirectional transfer)
74 * data_length specifies the amount of DATA-OUT and
75 * bidir_data_length specifies the amount of DATA-IN
77 guint32 data_length;
78 guint32 bidir_data_length;
80 guint32 alloc_len; /* we need to track alloc_len between the CDB and
81 * the DATA pdus for some opcodes.
83 nstime_t fc_time;
86 void *extra_data; /* extra data that that is task specific */
87 } itlq_nexus_t;
90 #define SCSI_PDU_TYPE_CDB 1
91 #define SCSI_PDU_TYPE_DATA 2
92 #define SCSI_PDU_TYPE_RSP 4
93 #define SCSI_PDU_TYPE_SNS 5
94 typedef struct _scsi_task_data {
95 int type;
96 itlq_nexus_t *itlq;
97 itl_nexus_t *itl;
98 } scsi_task_data_t;
101 /* list of commands for each commandset */
102 typedef void (*scsi_dissector_t)(tvbuff_t *tvb, packet_info *pinfo,
103 proto_tree *tree, guint offset,
104 gboolean isreq, gboolean iscdb,
105 guint32 payload_len, scsi_task_data_t *cdata);
107 typedef struct _scsi_cdb_table_t {
108 scsi_dissector_t func;
109 } scsi_cdb_table_t;
112 /* SPC Commands */
113 #define SCSI_SPC_ACCESS_CONTROL_IN 0x86
114 #define SCSI_SPC_ACCESS_CONTROL_OUT 0x87
115 #define SCSI_SPC_CHANGE_DEFINITION 0x40
116 #define SCSI_SPC_COMPARE 0x39
117 #define SCSI_SPC_COPY 0x18
118 #define SCSI_SPC_COPY_AND_VERIFY 0x3A
119 #define SCSI_SPC_INQUIRY 0x12
120 #define SCSI_SPC_EXTCOPY 0x83
121 #define SCSI_SPC_LOGSELECT 0x4C
122 #define SCSI_SPC_LOGSENSE 0x4D
123 #define SCSI_SPC_MODESELECT6 0x15
124 #define SCSI_SPC_MODESELECT10 0x55
125 #define SCSI_SPC_MODESENSE6 0x1A
126 #define SCSI_SPC_MODESENSE10 0x5A
127 #define SCSI_SPC_PERSRESVIN 0x5E
128 #define SCSI_SPC_PERSRESVOUT 0x5F
129 #define SCSI_SPC_PREVMEDREMOVAL 0x1E
130 #define SCSI_SPC_READBUFFER 0x3C
131 #define SCSI_SPC_RCVCOPYRESULTS 0x84
132 #define SCSI_SPC_RCVDIAGRESULTS 0x1C
133 #define SCSI_SPC_RELEASE6 0x17
134 #define SCSI_SPC_RELEASE10 0x57
135 #define SCSI_SPC_MGMT_PROTOCOL_IN 0xA3
136 #define SCSI_SPC_REPORTLUNS 0xA0
137 #define SCSI_SPC_REQSENSE 0x03
138 #define SCSI_SPC_RESERVE6 0x16
139 #define SCSI_SPC_RESERVE10 0x56
140 #define SCSI_SPC_SENDDIAG 0x1D
141 #define SCSI_SPC_SETDEVICEID 0xA4
142 #define SCSI_SPC_TESTUNITRDY 0x00
143 #define SCSI_SPC_WRITEBUFFER 0x3B
144 #define SCSI_SPC_VARLENCDB 0x7F
146 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);
147 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_);
148 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_);
149 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_);
150 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);
151 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);
152 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);
153 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);
154 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);
155 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_);
156 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_);
157 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_);
158 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_);
159 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_);
160 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_);
161 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_);
162 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_);
163 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_);
164 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_);
165 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_);
166 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_);
172 extern const value_string scsi_status_val[];
175 * SCSI Device Types.
177 * These can be supplied to the dissection routines if the caller happens
178 * to know the device type (e.g., NDMP assumes that a "jukebox" is a
179 * media changer, SCSI_DEV_SMC, and a "tape" is a sequential access device,
180 * SCSI_DEV_SSC).
182 * If the caller doesn't know the device type, it supplies SCSI_DEV_UNKNOWN.
184 #define SCSI_DEV_UNKNOWN -1
185 #define SCSI_DEV_SBC 0x0
186 #define SCSI_DEV_SSC 0x1
187 #define SCSI_DEV_PRNT 0x2
188 #define SCSI_DEV_PROC 0x3
189 #define SCSI_DEV_WORM 0x4
190 #define SCSI_DEV_CDROM 0x5
191 #define SCSI_DEV_SCAN 0x6
192 #define SCSI_DEV_OPTMEM 0x7
193 #define SCSI_DEV_SMC 0x8
194 #define SCSI_DEV_COMM 0x9
195 #define SCSI_DEV_RAID 0xC
196 #define SCSI_DEV_SES 0xD
197 #define SCSI_DEV_RBC 0xE
198 #define SCSI_DEV_OCRW 0xF
199 #define SCSI_DEV_OSD 0x11
200 #define SCSI_DEV_ADC 0x12
201 #define SCSI_DEV_NOLUN 0x1F
203 #define SCSI_DEV_BITS 0x1F /* the lower 5 bits indicate device type */
204 #define SCSI_MS_PCODE_BITS 0x3F /* Page code bits in Mode Sense */
206 /* Function Decls; functions invoked by SAM-2 transport protocols such as
207 * FCP/iSCSI
209 void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *,
210 gint, itlq_nexus_t *, itl_nexus_t *);
211 void dissect_scsi_rsp (tvbuff_t *, packet_info *, proto_tree *, itlq_nexus_t *, itl_nexus_t *, guint8);
212 void dissect_scsi_payload (tvbuff_t *, packet_info *, proto_tree *,
213 gboolean, itlq_nexus_t *, itl_nexus_t *,
214 guint32 relative_offset);
215 void dissect_scsi_snsinfo (tvbuff_t *, packet_info *, proto_tree *, guint, guint, itlq_nexus_t *, itl_nexus_t *);
217 void dissect_scsi_lun(proto_tree *, tvbuff_t *, guint);
219 WS_DLL_PUBLIC const value_string scsi_mmc_vals[];
221 extern const int *cdb_control_fields[6];
222 extern gint ett_scsi_control;
223 extern int hf_scsi_control;
224 extern int hf_scsi_alloclen16;
226 /* service actions */
227 #define SHORT_FORM_BLOCK_ID 0x00
228 #define SHORT_FORM_VENDOR_SPECIFIC 0x01
229 #define LONG_FORM 0x06
230 #define EXTENDED_FORM 0x08
231 #define SERVICE_READ_CAPACITY16 0x10
232 #define SERVICE_READ_LONG16 0x11
233 #define SERVICE_GET_LBA_STATUS 0x12
235 extern const value_string service_action_vals[];
236 extern const value_string scsi_devid_codeset_val[];
237 extern const value_string scsi_devid_idtype_val[];
238 extern value_string_ext scsi_asc_val_ext;
240 /* 0xA3 MGMT PROTOCOL IN service actions */
241 #define MPI_MANAGEMENT_PROTOCOL_IN 0x10
242 #define MPI_REPORT_SUPPORTED_OPERATION_CODES 0x0C
244 /* These two defines are used to handle cases where data coming back from
245 * the device is truncated due to a too short allocation_length specified
246 * in the command CDB.
247 * This is semi-common in SCSI and it would be wrong to mark these packets
248 * as [malformed packets].
249 * These macros will reset the reported length to what the data pdu specified
250 * and if a ReportedBoundsError is generated we will instead throw
251 * ScsiBoundsError
253 * Please see dissect_spc_inquiry() for an example how to use these
254 * macros.
256 #define TRY_SCSI_CDB_ALLOC_LEN(pinfo, tvb, offset, length) \
258 volatile gboolean short_packet; \
259 tvbuff_t *new_tvb; \
260 guint32 end_data_offset=0; \
262 short_packet=pinfo->fd->cap_len<pinfo->fd->pkt_len; \
263 new_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);\
264 tvb=new_tvb; \
265 offset=0; \
266 TRY {
268 #define END_TRY_SCSI_CDB_ALLOC_LEN \
269 if(end_data_offset){ \
270 /* just verify we can read all the bytes we were\
271 * supposed to. \
272 */ \
273 tvb_get_guint8(tvb,end_data_offset); \
275 } /* TRY */ \
276 CATCH(BoundsError) { \
277 if(short_packet){ \
278 /* this was a short packet */ \
279 RETHROW; \
280 } else { \
281 /* We probably tried to dissect beyond the end \
282 * of the alloc len reported in the data \
283 * pdu. This is not an error so dont flag it as \
284 * one \
285 * it is the alloc_len in the CDB that is the \
286 * important one \
287 */ \
290 CATCH(ReportedBoundsError) { \
291 if(short_packet){ \
292 /* this was a short packet */ \
293 RETHROW; \
294 } else { \
295 /* this packet was not really short but limited \
296 * due to a short SCSI allocation length \
297 */ \
298 THROW(ScsiBoundsError); \
301 ENDTRY; \
304 /* If the data pdu contains an alloc_len as well, this macro can be set
305 * to registe this offset for the TRY section above.
306 * At the end of the TRY section we will, if set, verify that the data
307 * pdu contained all bytes that was specified in the data alloc len.
309 * This macro does currently not do anything but we might enhance it in
310 * the future. There is no harm in teaching the dissector about how long
311 * the data pdu is supposed to be according to alloc_len in the data pdu
313 #define SET_SCSI_DATA_END(offset) \
314 end_data_offset=offset;
317 #endif