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