Wireshark  4.3.0
The Wireshark network protocol analyzer
packet-scsi.h
1 /* packet-scsi.h
2  * Author: Dinesh G Dutt (ddutt@cisco.com)
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 2002 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
11 #ifndef __PACKET_SCSI_H_
12 #define __PACKET_SCSI_H_
13 
14 #include <epan/exceptions.h>
15 #include <epan/srt_table.h>
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif /* __cplusplus */
20 
21 /* Structure containing itl nexus data :
22  * The itlq nexus is a structure containing data specific
23  * for a initiator target lun combination.
24  */
25 typedef struct _itl_nexus_t {
26 #define SCSI_CMDSET_DEFAULT 0x80
27 #define SCSI_CMDSET_MASK 0x7f
28  guint8 cmdset; /* This is a bitfield.
29  * The MSB (0x80) represents whether
30  * 0: the commandset is known from a INQ PDU
31  * 1: is using the "default" from preferences.
32  * The lower 7 bits represent the commandset used
33  * for decoding commands on this itl nexus.
34  * The field is initialized to 0xff == unknown.
35  */
37 } itl_nexus_t;
38 
39 /* Structure containing itlq nexus data :
40  * The itlq nexus is a structure containing data specific
41  * for a initiator target lun queue/commandid combination.
42  */
43 typedef struct _itlq_nexus_t {
44  guint32 first_exchange_frame;
45  guint32 last_exchange_frame;
46  guint16 lun; /* initialized to 0xffff == unknown */
47  guint16 scsi_opcode; /* initialized to 0xffff == unknown */
48  guint16 flags;
49 
50 #define SCSI_DATA_READ 0x0001
51 #define SCSI_DATA_WRITE 0x0002
52  guint16 task_flags; /* Flags set by the transport for this
53  * scsi task.
54  *
55  * If there is no data being transferred both flags
56  * are 0 and both data lengths below are undefined.
57  *
58  * If one of the flags are set the amount of
59  * data being transferred is held in data_length
60  * and bidir_data_length is undefined.
61  *
62  * If both flags are set (a bidirectional transfer)
63  * data_length specifies the amount of DATA-OUT and
64  * bidir_data_length specifies the amount of DATA-IN
65  */
66  guint32 data_length;
67  guint32 bidir_data_length;
68 
69  guint32 alloc_len; /* we need to track alloc_len between the CDB and
70  * the DATA pdus for some opcodes.
71  */
72  nstime_t fc_time;
73  nstime_t r2t_time;
74 
75  void *extra_data; /* extra data that is task specific */
76 } itlq_nexus_t;
77 
78 
79 #define SCSI_PDU_TYPE_CDB 1
80 #define SCSI_PDU_TYPE_DATA 2
81 #define SCSI_PDU_TYPE_RSP 4
82 #define SCSI_PDU_TYPE_SNS 5
83 typedef struct _scsi_task_data {
84  int type;
85  itlq_nexus_t *itlq;
86  itl_nexus_t *itl;
88 
89 
90 /* list of commands for each commandset */
91 typedef void (*scsi_dissector_t)(tvbuff_t *tvb, packet_info *pinfo,
92  proto_tree *tree, guint offset,
93  gboolean isreq, gboolean iscdb,
94  guint32 payload_len, scsi_task_data_t *cdata);
95 
96 typedef struct _scsi_cdb_table_t {
97  scsi_dissector_t func;
99 
100 
101 /* SPC Commands */
102 #define SCSI_SPC_ACCESS_CONTROL_IN 0x86
103 #define SCSI_SPC_ACCESS_CONTROL_OUT 0x87
104 #define SCSI_SPC_CHANGE_DEFINITION 0x40
105 #define SCSI_SPC_COMPARE 0x39
106 #define SCSI_SPC_COPY 0x18
107 #define SCSI_SPC_COPY_AND_VERIFY 0x3A
108 #define SCSI_SPC_INQUIRY 0x12
109 #define SCSI_SPC_EXTCOPY 0x83
110 #define SCSI_SPC_RECVCOPY 0x84
111 #define SCSI_SPC_LOGSELECT 0x4C
112 #define SCSI_SPC_LOGSENSE 0x4D
113 #define SCSI_SPC_MODESELECT6 0x15
114 #define SCSI_SPC_MODESELECT10 0x55
115 #define SCSI_SPC_MODESENSE6 0x1A
116 #define SCSI_SPC_MODESENSE10 0x5A
117 #define SCSI_SPC_PERSRESVIN 0x5E
118 #define SCSI_SPC_PERSRESVOUT 0x5F
119 #define SCSI_SPC_PREVMEDREMOVAL 0x1E
120 #define SCSI_SPC_READBUFFER 0x3C
121 #define SCSI_SPC_RCVDIAGRESULTS 0x1C
122 #define SCSI_SPC_RELEASE6 0x17
123 #define SCSI_SPC_RELEASE10 0x57
124 #define SCSI_SPC_MGMT_PROTOCOL_IN 0xA3
125 #define SCSI_SPC_REPORTLUNS 0xA0
126 #define SCSI_SPC_REQSENSE 0x03
127 #define SCSI_SPC_RESERVE6 0x16
128 #define SCSI_SPC_RESERVE10 0x56
129 #define SCSI_SPC_SENDDIAG 0x1D
130 #define SCSI_SPC_SETDEVICEID 0xA4
131 #define SCSI_SPC_TESTUNITRDY 0x00
132 #define SCSI_SPC_WRITEBUFFER 0x3B
133 #define SCSI_SPC_VARLENCDB 0x7F
134 
135 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);
136 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_);
137 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_);
138 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_);
139 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);
140 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);
141 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);
142 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);
143 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);
144 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_);
145 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_);
146 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_);
147 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_);
148 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_);
149 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_);
150 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_);
151 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_);
152 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_);
153 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_);
154 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_);
155 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_);
156 void dissect_spc_recvcopy (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 
158 
159 
160 
161 
162 
163 extern const value_string scsi_status_val[];
164 
165 /*
166  * SCSI Device Types.
167  *
168  * These can be supplied to the dissection routines if the caller happens
169  * to know the device type (e.g., NDMP assumes that a "jukebox" is a
170  * media changer, SCSI_DEV_SMC, and a "tape" is a sequential access device,
171  * SCSI_DEV_SSC).
172  *
173  * If the caller doesn't know the device type, it supplies SCSI_DEV_UNKNOWN.
174  */
175 #define SCSI_DEV_UNKNOWN -1
176 #define SCSI_DEV_SBC 0x0
177 #define SCSI_DEV_SSC 0x1
178 #define SCSI_DEV_PRNT 0x2
179 #define SCSI_DEV_PROC 0x3
180 #define SCSI_DEV_WORM 0x4
181 #define SCSI_DEV_CDROM 0x5
182 #define SCSI_DEV_SCAN 0x6
183 #define SCSI_DEV_OPTMEM 0x7
184 #define SCSI_DEV_SMC 0x8
185 #define SCSI_DEV_COMM 0x9
186 #define SCSI_DEV_RAID 0xC
187 #define SCSI_DEV_SES 0xD
188 #define SCSI_DEV_RBC 0xE
189 #define SCSI_DEV_OCRW 0xF
190 #define SCSI_DEV_OSD 0x11
191 #define SCSI_DEV_ADC 0x12
192 #define SCSI_DEV_NOLUN 0x1F
193 
194 #define SCSI_DEV_BITS 0x1F /* the lower 5 bits indicate device type */
195 #define SCSI_MS_PCODE_BITS 0x3F /* Page code bits in Mode Sense */
196 
197 /* Function Decls; functions invoked by SAM-2 transport protocols such as
198  * FCP/iSCSI
199  */
200 void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *,
201  gint, itlq_nexus_t *, itl_nexus_t *);
202 void dissect_scsi_rsp (tvbuff_t *, packet_info *, proto_tree *, itlq_nexus_t *, itl_nexus_t *, guint8);
203 void dissect_scsi_payload (tvbuff_t *, packet_info *, proto_tree *,
204  gboolean, itlq_nexus_t *, itl_nexus_t *,
205  guint32 relative_offset);
206 void dissect_scsi_snsinfo (tvbuff_t *, packet_info *, proto_tree *, guint, guint, itlq_nexus_t *, itl_nexus_t *);
207 
208 void dissect_scsi_lun(proto_tree *, tvbuff_t *, guint);
209 
210 extern int * const cdb_control_fields[6];
211 extern gint ett_scsi_control;
212 extern int hf_scsi_control;
213 extern int hf_scsi_alloclen16;
214 
215 /* service actions */
216 #define SHORT_FORM_BLOCK_ID 0x00
217 #define SHORT_FORM_VENDOR_SPECIFIC 0x01
218 #define LONG_FORM 0x06
219 #define EXTENDED_FORM 0x08
220 #define SERVICE_READ_CAPACITY16 0x10
221 #define SERVICE_READ_LONG16 0x11
222 #define SERVICE_WRITE_LONG16 0x11
223 #define SERVICE_GET_LBA_STATUS 0x12
224 #define SERVICE_REPORT_REFERRALS 0x13
225 
226 extern const value_string service_action_vals[];
227 extern const value_string scsi_devid_codeset_val[];
228 extern const value_string scsi_devid_idtype_val[];
229 extern value_string_ext scsi_asc_val_ext;
230 
231 /* 0xA3 MGMT PROTOCOL IN service actions */
232 #define MPI_MANAGEMENT_PROTOCOL_IN 0x10
233 #define MPI_REPORT_SUPPORTED_OPERATION_CODES 0x0C
234 
235 /* These two defines are used to handle cases where data coming back from
236  * the device is truncated due to a too short allocation_length specified
237  * in the command CDB.
238  * This is semi-common in SCSI and it would be wrong to mark these packets
239  * as [malformed packets].
240  * These macros will reset the reported length to what the data pdu specified
241  * and if a ContainedBoundsError or ReportedBoundsError is generated we will
242  * instead throw ScsiBoundsError
243  *
244  * Please see dissect_spc_inquiry() for an example how to use these
245  * macros.
246  *
247  * Note that try_tvb & try_offset are initialized to be used in the code
248  * bounded by TRY_SCSI_ALLOC_LEN and END_TRY_SCSI_CDB_ALLOC_LEN
249  */
250 
251 #define TRY_SCSI_CDB_ALLOC_LEN(length_arg) \
252  { \
253  tvbuff_t *try_tvb; \
254  volatile guint try_offset; \
255  guint32 try_end_data_offset=0; \
256  \
257  try_tvb=tvb_new_subset_length(tvb_a, offset_a, length_arg); \
258  try_offset=0; \
259  TRY {
260 
261 #define END_TRY_SCSI_CDB_ALLOC_LEN \
262  if(try_end_data_offset){ \
263  /* just verify we can read all the bytes we were\
264  * supposed to. \
265  */ \
266  tvb_get_guint8(try_tvb,try_end_data_offset); \
267  } \
268  } /* TRY */ \
269  CATCH(BoundsError) { \
270  /* this was a short packet */ \
271  RETHROW; \
272  } \
273  CATCH(ContainedBoundsError) { \
274  /* We probably tried to dissect beyond the end \
275  * of the alloc len reported in the data \
276  * pdu. This is not an error so don't flag it \
277  * as one \
278  * it is the alloc_len in the CDB that is the \
279  * important one \
280  */ \
281  } \
282  CATCH(ReportedBoundsError) { \
283  /* this packet was not really short but limited \
284  * due to a short SCSI allocation length \
285  */ \
286  THROW(ScsiBoundsError); \
287  } \
288  ENDTRY; \
289  }
290 
291 /* If the data pdu contains an alloc_len as well, this macro can be set
292  * to registe this offset for the TRY section above.
293  * At the end of the TRY section we will, if set, verify that the data
294  * pdu contained all bytes that was specified in the data alloc len.
295  *
296  * This macro does currently not do anything but we might enhance it in
297  * the future. There is no harm in teaching the dissector about how long
298  * the data pdu is supposed to be according to alloc_len in the data pdu
299  */
300 #define SET_SCSI_DATA_END(offset_arg) \
301  try_end_data_offset=offset_arg;
302 
303 
304 WS_DLL_PUBLIC guint scsistat_param(register_srt_t* srt, const char* opt_arg, char** err);
305 
306 #ifdef __cplusplus
307 }
308 #endif /* __cplusplus */
309 
310 #endif
311 
312 /*
313  * Editor modelines - https://www.wireshark.org/tools/modelines.html
314  *
315  * Local variables:
316  * c-basic-offset: 8
317  * tab-width: 8
318  * indent-tabs-mode: t
319  * End:
320  *
321  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
322  * :indentSize=8:tabSize=8:noTabs=false:
323  */
Definition: packet-scsi.h:25
Definition: packet-scsi.h:43
Definition: packet_info.h:44
Definition: proto.h:904
Definition: packet-scsi.h:96
Definition: packet-scsi.h:83
Definition: value_string.h:170
Definition: value_string.h:26
Definition: conversation.h:220
Definition: nstime.h:26
Definition: srt_table.c:20
Definition: tvbuff-int.h:35