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