1 /* TODO for the cases where one just can not autodetect whether header digest
2 is used or not we might need a new preference
10 * Routines for iSCSI dissection
11 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
12 * 2004 Request/Response matching and Service Response Time: ronnie sahlberg
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * SPDX-License-Identifier: GPL-2.0-or-later
23 #include <epan/packet.h>
24 #include <epan/prefs.h>
25 #include <epan/conversation.h>
26 #include <epan/expert.h>
28 #include "packet-scsi.h"
29 #include <epan/crc32-tvb.h>
30 #include <wsutil/crc32.h>
31 #include <wsutil/inet_addr.h>
32 #include <wsutil/strtoi.h>
33 #include <wsutil/array.h>
34 #include <wsutil/ws_roundup.h>
36 void proto_register_iscsi(void);
37 void proto_reg_handoff_iscsi(void);
39 /* the absolute values of these constants don't matter as long as
40 * latter revisions of the protocol are assigned a larger number */
41 #define ISCSI_PROTOCOL_DRAFT08 1
42 #define ISCSI_PROTOCOL_DRAFT09 2
43 #define ISCSI_PROTOCOL_DRAFT11 3
44 #define ISCSI_PROTOCOL_DRAFT12 4
45 #define ISCSI_PROTOCOL_DRAFT13 5
47 static const enum_val_t iscsi_protocol_versions
[] = {
48 { "draft-08", "Draft 08", ISCSI_PROTOCOL_DRAFT08
},
49 { "draft-09", "Draft 09", ISCSI_PROTOCOL_DRAFT09
},
50 { "draft-11", "Draft 11", ISCSI_PROTOCOL_DRAFT11
},
51 { "draft-12", "Draft 12", ISCSI_PROTOCOL_DRAFT12
},
52 { "draft-13", "Draft 13", ISCSI_PROTOCOL_DRAFT13
},
56 static const value_string ahs_type_vals
[] = {
58 {2, "Expected Bidirection Read Data Length"},
62 static dissector_handle_t iscsi_handle
;
64 static int iscsi_protocol_version
= ISCSI_PROTOCOL_DRAFT13
;
66 static bool iscsi_desegment
= true;
68 static bool demand_good_f_bit
;
69 static bool enable_bogosity_filter
= true;
70 static uint32_t bogus_pdu_data_length_threshold
= 256 * 1024;
72 #define TCP_PORT_ISCSI_RANGE "3260"
74 static range_t
*global_iscsi_port_range
;
75 static unsigned iscsi_system_port
= 860;
77 /* Initialize the protocol and registered fields */
78 static int proto_iscsi
;
79 static int hf_iscsi_time
;
80 static int hf_iscsi_r2t_time
;
81 static int hf_iscsi_request_frame
;
82 static int hf_iscsi_r2t_frame
;
83 static int hf_iscsi_data_in_frame
;
84 static int hf_iscsi_data_out_frame
;
85 static int hf_iscsi_response_frame
;
86 static int hf_iscsi_AHS_length
;
87 static int hf_iscsi_AHS_type
;
88 static int hf_iscsi_AHS_blob
;
89 static int hf_iscsi_AHS_read_data_length
;
90 static int hf_iscsi_AHS_extended_cdb
;
91 static int hf_iscsi_Padding
;
92 static int hf_iscsi_ping_data
;
93 static int hf_iscsi_immediate_data
;
94 static int hf_iscsi_async_event_data
;
95 static int hf_iscsi_vendor_specific_data
;
96 static int hf_iscsi_Opcode
;
97 static int hf_iscsi_Flags
;
98 static int hf_iscsi_HeaderDigest32
;
99 static int hf_iscsi_DataDigest32
;
101 static int hf_iscsi_X
;
103 static int hf_iscsi_I
;
104 static int hf_iscsi_SCSICommand_F
;
105 static int hf_iscsi_SCSICommand_R
;
106 static int hf_iscsi_SCSICommand_W
;
107 static int hf_iscsi_SCSICommand_Attr
;
108 static int hf_iscsi_SCSICommand_CRN
;
109 static int hf_iscsi_DataSegmentLength
;
110 static int hf_iscsi_TotalAHSLength
;
111 static int hf_iscsi_InitiatorTaskTag
;
112 static int hf_iscsi_ExpectedDataTransferLength
;
113 static int hf_iscsi_CmdSN
;
114 static int hf_iscsi_ExpStatSN
;
115 static int hf_iscsi_StatSN
;
116 static int hf_iscsi_ExpCmdSN
;
117 static int hf_iscsi_MaxCmdSN
;
118 static int hf_iscsi_SCSIResponse_o
;
119 static int hf_iscsi_SCSIResponse_u
;
120 static int hf_iscsi_SCSIResponse_O
;
121 static int hf_iscsi_SCSIResponse_U
;
122 static int hf_iscsi_SCSIResponse_BidiReadResidualCount
;
123 static int hf_iscsi_SCSIResponse_ResidualCount
;
124 static int hf_iscsi_SCSIResponse_Response
;
125 static int hf_iscsi_SCSIResponse_Status
;
126 static int hf_iscsi_SenseLength
;
127 static int hf_iscsi_SCSIData_F
;
128 static int hf_iscsi_SCSIData_A
;
129 static int hf_iscsi_SCSIData_S
;
130 static int hf_iscsi_SCSIData_O
;
131 static int hf_iscsi_SCSIData_U
;
132 static int hf_iscsi_TargetTransferTag
;
133 static int hf_iscsi_DataSN
;
134 static int hf_iscsi_BufferOffset
;
135 static int hf_iscsi_SCSIData_ResidualCount
;
136 static int hf_iscsi_VersionMin
;
137 static int hf_iscsi_VersionMax
;
138 static int hf_iscsi_VersionActive
;
139 static int hf_iscsi_CID
;
140 static int hf_iscsi_ISID8
;
141 static int hf_iscsi_ISID
;
142 /* #if defined(DRAFT09) */
143 static int hf_iscsi_ISID_Type
;
144 static int hf_iscsi_ISID_NamingAuthority
;
145 static int hf_iscsi_ISID_Qualifier
;
146 /* #elif !defined(DRAFT08) */
147 static int hf_iscsi_ISID_t
;
148 static int hf_iscsi_ISID_a
;
149 static int hf_iscsi_ISID_b
;
150 static int hf_iscsi_ISID_c
;
151 static int hf_iscsi_ISID_d
;
153 static int hf_iscsi_TSID
;
154 static int hf_iscsi_TSIH
;
156 static int hf_iscsi_Login_X
;
158 static int hf_iscsi_Login_C
;
159 static int hf_iscsi_Login_T
;
160 static int hf_iscsi_Login_CSG
;
161 static int hf_iscsi_Login_NSG
;
162 static int hf_iscsi_Login_Status
;
163 static int hf_iscsi_KeyValue
;
164 static int hf_iscsi_Text_C
;
165 static int hf_iscsi_Text_F
;
166 static int hf_iscsi_ExpDataSN
;
167 static int hf_iscsi_R2TSN
;
168 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag
;
169 static int hf_iscsi_RefCmdSN
;
170 static int hf_iscsi_TaskManagementFunction_Function
;
171 static int hf_iscsi_TaskManagementFunction_Response
;
172 static int hf_iscsi_Logout_Reason
;
173 static int hf_iscsi_Logout_Response
;
174 static int hf_iscsi_Time2Wait
;
175 static int hf_iscsi_Time2Retain
;
176 static int hf_iscsi_DesiredDataLength
;
177 static int hf_iscsi_AsyncEvent
;
178 static int hf_iscsi_EventVendorCode
;
179 static int hf_iscsi_Parameter1
;
180 static int hf_iscsi_Parameter2
;
181 static int hf_iscsi_Parameter3
;
182 static int hf_iscsi_Reject_Reason
;
183 static int hf_iscsi_snack_type
;
184 static int hf_iscsi_BegRun
;
185 static int hf_iscsi_RunLength
;
187 /* Initialize the subtree pointers */
188 static int ett_iscsi
;
189 static int ett_iscsi_KeyValues
;
190 static int ett_iscsi_CDB
;
191 static int ett_iscsi_Flags
;
192 static int ett_iscsi_RejectHeader
;
193 static int ett_iscsi_lun
;
194 /* #ifndef DRAFT08 */
195 static int ett_iscsi_ISID
;
198 static expert_field ei_iscsi_keyvalue_invalid
;
199 static expert_field ei_iscsi_opcode_invalid
;
206 /* this structure contains session wide state for a specific tcp conversation */
207 typedef struct _iscsi_session_t
{
208 enum iscsi_digest header_digest
;
209 enum iscsi_digest data_digest
;
210 wmem_tree_t
*itlq
; /* indexed by ITT */
211 wmem_map_t
*itl
; /* indexed by LUN */
222 #define OPCODE_MASK 0x3f
224 #define TARGET_OPCODE_BIT 0x20
226 #define ISCSI_OPCODE_NOP_OUT 0x00
227 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
228 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
229 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
230 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
231 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
232 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
233 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
234 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
235 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
236 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
238 #define ISCSI_OPCODE_NOP_IN 0x20
239 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
240 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
241 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
242 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
243 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
244 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
245 #define ISCSI_OPCODE_R2T 0x31
246 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
247 #define ISCSI_OPCODE_REJECT 0x3f
248 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
249 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
250 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
253 #define CSG_MASK (0x03 << CSG_SHIFT)
254 #define NSG_MASK 0x03
256 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
257 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
258 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
260 #define ISCSI_SCSI_DATA_FLAG_S 0x01
261 #define ISCSI_SCSI_DATA_FLAG_U 0x02
262 #define ISCSI_SCSI_DATA_FLAG_O 0x04
263 #define ISCSI_SCSI_DATA_FLAG_A 0x40
264 #define ISCSI_SCSI_DATA_FLAG_F 0x80
266 static const value_string iscsi_opcodes
[] = {
267 { ISCSI_OPCODE_NOP_OUT
, "NOP Out" },
268 { ISCSI_OPCODE_SCSI_COMMAND
, "SCSI Command" },
269 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION
, "Task Management Function" },
270 { ISCSI_OPCODE_LOGIN_COMMAND
, "Login Command" },
271 { ISCSI_OPCODE_TEXT_COMMAND
, "Text Command" },
272 { ISCSI_OPCODE_SCSI_DATA_OUT
, "SCSI Data Out" },
273 { ISCSI_OPCODE_LOGOUT_COMMAND
, "Logout Command" },
274 { ISCSI_OPCODE_SNACK_REQUEST
, "SNACK Request" },
275 { ISCSI_OPCODE_VENDOR_SPECIFIC_I0
, "Vendor Specific I0" },
276 { ISCSI_OPCODE_VENDOR_SPECIFIC_I1
, "Vendor Specific I1" },
277 { ISCSI_OPCODE_VENDOR_SPECIFIC_I2
, "Vendor Specific I2" },
279 { ISCSI_OPCODE_NOP_IN
, "NOP In" },
280 { ISCSI_OPCODE_SCSI_RESPONSE
, "SCSI Response" },
281 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE
, "Task Management Function Response" },
282 { ISCSI_OPCODE_LOGIN_RESPONSE
, "Login Response" },
283 { ISCSI_OPCODE_TEXT_RESPONSE
, "Text Response" },
284 { ISCSI_OPCODE_SCSI_DATA_IN
, "SCSI Data In" },
285 { ISCSI_OPCODE_LOGOUT_RESPONSE
, "Logout Response" },
286 { ISCSI_OPCODE_R2T
, "Ready To Transfer" },
287 { ISCSI_OPCODE_ASYNC_MESSAGE
, "Asynchronous Message" },
288 { ISCSI_OPCODE_REJECT
, "Reject"},
289 { ISCSI_OPCODE_VENDOR_SPECIFIC_T0
, "Vendor Specific T0" },
290 { ISCSI_OPCODE_VENDOR_SPECIFIC_T1
, "Vendor Specific T1" },
291 { ISCSI_OPCODE_VENDOR_SPECIFIC_T2
, "Vendor Specific T2" },
296 static const true_false_string iscsi_meaning_X
= {
303 static const true_false_string iscsi_meaning_login_X
= {
304 "Reinstate failed connection",
309 static const true_false_string iscsi_meaning_I
= {
310 "Immediate delivery",
314 static const true_false_string iscsi_meaning_F
= {
315 "Final PDU in sequence",
316 "Not final PDU in sequence"
319 static const true_false_string iscsi_meaning_A
= {
320 "Acknowledge requested",
321 "Acknowledge not requested"
324 static const true_false_string iscsi_meaning_T
= {
325 "Transit to next login stage",
326 "Stay in current login stage"
329 static const true_false_string iscsi_meaning_C
= {
330 "Text is incomplete",
334 static const true_false_string iscsi_meaning_S
= {
335 "Response contains SCSI status",
336 "Response does not contain SCSI status"
339 static const true_false_string iscsi_meaning_R
= {
340 "Data will be read from target",
341 "No data will be read from target"
344 static const true_false_string iscsi_meaning_W
= {
345 "Data will be written to target",
346 "No data will be written to target"
349 static const true_false_string iscsi_meaning_o
= {
350 "Read part of bi-directional command overflowed",
351 "No overflow of read part of bi-directional command",
354 static const true_false_string iscsi_meaning_u
= {
355 "Read part of bi-directional command underflowed",
356 "No underflow of read part of bi-directional command",
359 static const true_false_string iscsi_meaning_O
= {
360 "Residual overflow occurred",
361 "No residual overflow occurred",
364 static const true_false_string iscsi_meaning_U
= {
365 "Residual underflow occurred",
366 "No residual underflow occurred",
369 static const value_string iscsi_scsi_responses
[] = {
370 { 0, "Command completed at target" },
371 { 1, "Response does not contain SCSI status"},
375 static const value_string iscsi_scsicommand_taskattrs
[] = {
379 {3, "Head of Queue"},
384 static const value_string iscsi_task_management_responses
[] = {
385 {0, "Function complete"},
386 {1, "Task not in task set"},
387 {2, "LUN does not exist"},
388 {3, "Task still allegiant"},
389 {4, "Task failover not supported"},
390 {5, "Task management function not supported"},
391 {6, "Authorisation failed"},
392 {255, "Function rejected"},
396 static const value_string iscsi_task_management_functions
[] = {
398 {2, "Abort Task Set"},
400 {4, "Clear Task Set"},
401 {5, "Logical Unit Reset"},
402 {6, "Target Warm Reset"},
403 {7, "Target Cold Reset"},
404 {8, "Target Reassign"},
408 static const value_string iscsi_login_status
[] = {
410 {0x0101, "Target moved temporarily"},
411 {0x0102, "Target moved permanently"},
412 {0x0200, "Initiator error (miscellaneous error)"},
413 {0x0201, "Authentication failed"},
414 {0x0202, "Authorisation failure"},
415 {0x0203, "Target not found"},
416 {0x0204, "Target removed"},
417 {0x0205, "Unsupported version"},
418 {0x0206, "Too many connections"},
419 {0x0207, "Missing parameter"},
420 {0x0208, "Can't include in session"},
421 {0x0209, "Session type not supported"},
422 {0x020a, "Session does not exist"},
423 {0x020b, "Invalid request during login"},
424 {0x0300, "Target error (miscellaneous error)"},
425 {0x0301, "Service unavailable"},
426 {0x0302, "Out of resources"},
430 static const value_string iscsi_login_stage
[] = {
431 {0, "Security negotiation"},
432 {1, "Operational negotiation"},
433 {3, "Full feature phase"},
437 /* #ifndef DRAFT08 */
438 static const value_string iscsi_isid_type
[] = {
440 {0x01, "IANA Enterprise Number"},
446 static const value_string iscsi_logout_reasons
[] = {
447 {0, "Close session"},
448 {1, "Close connection"},
449 {2, "Remove connection for recovery"},
453 static const value_string iscsi_logout_response
[] = {
454 {0, "Connection closed successfully"},
455 {1, "CID not found"},
456 {2, "Connection recovery not supported"},
457 {3, "Cleanup failed for various reasons"},
461 static const value_string iscsi_asyncevents
[] = {
462 {0, "A SCSI asynchronous event is reported in the sense data"},
463 {1, "Target requests logout"},
464 {2, "Target will/has dropped connection"},
465 {3, "Target will/has dropped all connections"},
466 {4, "Target requests parameter negotiation"},
470 static const value_string iscsi_snack_types
[] = {
473 /* #ifndef DRAFT08 */
480 static const value_string iscsi_reject_reasons
[] = {
482 {0x01, "Full feature phase command before login"},
484 {0x02, "Data (payload) digest error"},
485 {0x03, "Data SNACK reject"},
486 {0x04, "Protocol error"},
487 {0x05, "Command not supported in this session type"},
488 {0x06, "Immediate command reject (too many immediate commands)"},
489 {0x07, "Task in progress"},
490 {0x08, "Invalid Data Ack"},
491 {0x09, "Invalid PDU field"},
492 {0x0a, "Long operation reject"},
493 {0x0b, "Negotiation reset"},
494 {0x0c, "Waiting for logout"},
498 /* structure and functions to keep track of
499 * COMMAND/DATA_IN/DATA_OUT/RESPONSE matching
501 typedef struct _iscsi_conv_data
{
502 uint32_t data_in_frame
;
503 uint32_t data_out_frame
;
509 /* TargetAddress describes a iscsi port, possibly using a non-standard port
510 so we can use this to set up a conversation dissector to that port.
512 TargetAddress is of the form :
513 TargetAddress=domainname[:port][,portal-group-tag]
515 where domainname is either a dns-name, an ipv4 address is dotted-decimal
516 form or a bracketed ipv6 address.
517 so treat this as signalling, parse the value and register iscis as a conversation
518 dissector for the address/port that TargetAddress points to.
519 (it starts to be common to use redirectors to point to non-3260 ports)
521 static address null_address
= ADDRESS_INIT_NONE
;
524 iscsi_dissect_TargetAddress(packet_info
*pinfo
, tvbuff_t
* tvb
, proto_tree
*tree
, unsigned offset
)
526 address addr
= ADDRESS_INIT_NONE
;
530 char *ip_str
, *port_str
;
532 colon_offset
= tvb_find_uint8(tvb
, offset
, -1, ':');
533 if (colon_offset
== -1) {
534 /* RFC 7143 13.8 TargetAddress "If the TCP port is not specified,
535 * it is assumed to be the IANA-assigned default port for iSCSI",
536 * so nothing to do here.
541 /* We found a colon, so there's at least one byte and this won't fail. */
542 if (tvb_get_uint8(tvb
, offset
) == '[') {
544 /* could be an ipv6 address */
545 end_offset
= tvb_find_uint8(tvb
, offset
, -1, ']');
546 if (end_offset
== -1) {
550 /* look for the colon before the port, if any */
551 colon_offset
= tvb_find_uint8(tvb
, end_offset
, -1, ':');
552 if (colon_offset
== -1) {
556 ws_in6_addr
*ip6_addr
= wmem_new(pinfo
->pool
, ws_in6_addr
);
557 ip_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, end_offset
- offset
, ENC_ASCII
);
558 if (ws_inet_pton6(ip_str
, ip6_addr
)) {
559 /* looks like a ipv6 address */
560 set_address(&addr
, AT_IPv6
, sizeof(ws_in6_addr
), ip6_addr
);
564 /* This is either a ipv4 address or a dns name */
565 ip_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, colon_offset
- offset
, ENC_ASCII
);
566 ws_in4_addr
*ip4_addr
= wmem_new(pinfo
->pool
, ws_in4_addr
);
567 if (ws_inet_pton4(ip_str
, ip4_addr
)) {
568 /* looks like a ipv4 address */
569 set_address(&addr
, AT_IPv4
, 4, ip4_addr
);
571 /* else a DNS host name; we could, theoretically, try to use
572 * name resolution information in the capture to lookup the address.
576 /* Extract the port */
577 end_offset
= tvb_find_uint8(tvb
, colon_offset
, -1, ',');
579 if (end_offset
== -1) {
580 port_len
= tvb_reported_length_remaining(tvb
, colon_offset
+ 1);
582 port_len
= end_offset
- (colon_offset
+ 1);
584 port_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, colon_offset
+ 1, port_len
, ENC_ASCII
);
585 if (!ws_strtou16(port_str
, NULL
, &port
)) {
586 proto_tree_add_expert_format(tree
, pinfo
, &ei_iscsi_keyvalue_invalid
,
587 tvb
, colon_offset
+ 1, port_len
, "Invalid port: %s", port_str
);
591 /* attach a conversation dissector to this address/port tuple */
592 if (!addresses_equal(&addr
, &null_address
) && !pinfo
->fd
->visited
) {
593 conversation_t
*conv
;
595 conv
= conversation_new(pinfo
->num
, &addr
, &null_address
, CONVERSATION_TCP
, port
, 0, NO_ADDR2
|NO_PORT2
);
599 conversation_set_dissector(conv
, iscsi_handle
);
605 addTextKeys(packet_info
*pinfo
, proto_tree
*tt
, tvbuff_t
*tvb
, int offset
, uint32_t text_len
) {
606 const int limit
= offset
+ text_len
;
607 tvbuff_t
*keyvalue_tvb
;
608 int len
, value_offset
;
610 while(offset
< limit
) {
611 /* RFC 7143 6.1 Text Format: "Every key=value pair, including the
612 * last or only pair in a LTDS, MUST be followed by one null (0x00)
615 proto_tree_add_item_ret_length(tt
, hf_iscsi_KeyValue
, tvb
, offset
, -1, ENC_ASCII
, &len
);
616 keyvalue_tvb
= tvb_new_subset_length(tvb
, offset
, len
);
617 value_offset
= tvb_find_uint8(keyvalue_tvb
, 0, len
, '=');
618 if (value_offset
== -1) {
623 if (tvb_strneql(keyvalue_tvb
, 0, "TargetAddress=", strlen("TargetAddress=")) == 0) {
624 iscsi_dissect_TargetAddress(pinfo
, keyvalue_tvb
, tt
, value_offset
);
633 handleHeaderDigest(iscsi_session_t
*iscsi_session
, proto_item
*ti
, tvbuff_t
*tvb
, unsigned offset
, int headerLen
) {
634 int available_bytes
= tvb_captured_length_remaining(tvb
, offset
);
636 switch(iscsi_session
->header_digest
){
637 case ISCSI_DIGEST_CRC32
:
638 if(available_bytes
>= (headerLen
+ 4)) {
639 uint32_t crc
= ~crc32c_tvb_offset_calculate(tvb
, offset
, headerLen
, CRC32C_PRELOAD
);
640 uint32_t sent
= tvb_get_ntohl(tvb
, offset
+ headerLen
);
642 proto_tree_add_uint_format_value(ti
, hf_iscsi_HeaderDigest32
, tvb
, offset
+ headerLen
, 4, sent
, "0x%08x (Good CRC32)", sent
);
644 proto_tree_add_uint_format_value(ti
, hf_iscsi_HeaderDigest32
, tvb
, offset
+ headerLen
, 4, sent
, "0x%08x (Bad CRC32, should be 0x%08x)", sent
, crc
);
647 return offset
+ headerLen
+ 4;
651 return offset
+ headerLen
;
655 handleDataDigest(iscsi_session_t
*iscsi_session
, proto_item
*ti
, tvbuff_t
*tvb
, unsigned offset
, int dataLen
) {
656 int available_bytes
= tvb_captured_length_remaining(tvb
, offset
);
659 switch (iscsi_session
->data_digest
){
660 case ISCSI_DIGEST_CRC32
:
661 if(available_bytes
>= (dataLen
+ 4)) {
662 uint32_t crc
= ~crc32c_tvb_offset_calculate(tvb
, offset
, dataLen
, CRC32C_PRELOAD
);
663 uint32_t sent
= tvb_get_ntohl(tvb
, offset
+ dataLen
);
665 proto_tree_add_uint_format_value(ti
, hf_iscsi_DataDigest32
, tvb
, offset
+ dataLen
, 4, sent
, "0x%08x (Good CRC32)", sent
);
668 proto_tree_add_uint_format_value(ti
, hf_iscsi_DataDigest32
, tvb
, offset
+ dataLen
, 4, sent
, "0x%08x (Bad CRC32, should be 0x%08x)", sent
, crc
);
671 return offset
+ dataLen
+ 4;
676 return offset
+ dataLen
;
680 handleDataSegment(iscsi_session_t
*iscsi_session
, proto_item
*ti
, tvbuff_t
*tvb
, unsigned offset
, unsigned dataSegmentLen
, unsigned endOffset
, int hf_id
) {
681 if(endOffset
> offset
) {
682 int dataOffset
= offset
;
683 int dataLen
= MIN(dataSegmentLen
, endOffset
- offset
);
685 proto_tree_add_item(ti
, hf_id
, tvb
, offset
, dataLen
, ENC_NA
);
688 if(offset
< endOffset
&& (offset
& 3) != 0) {
689 int padding
= 4 - (offset
& 3);
690 proto_tree_add_item(ti
, hf_iscsi_Padding
, tvb
, offset
, padding
, ENC_NA
);
693 if(dataSegmentLen
> 0 && offset
< endOffset
)
694 offset
= handleDataDigest(iscsi_session
, ti
, tvb
, dataOffset
, offset
- dataOffset
);
701 handleDataSegmentAsTextKeys(iscsi_session_t
*iscsi_session
, packet_info
*pinfo
, proto_item
*ti
, tvbuff_t
*tvb
, unsigned offset
, unsigned dataSegmentLen
, unsigned endOffset
, int digestsActive
) {
702 if(endOffset
> offset
) {
703 int dataOffset
= offset
;
704 int textLen
= MIN(dataSegmentLen
, endOffset
- offset
);
706 proto_tree
*tt
= proto_tree_add_subtree(ti
, tvb
, offset
, textLen
,
707 ett_iscsi_KeyValues
, NULL
, "Key/Value Pairs");
708 offset
= addTextKeys(pinfo
, tt
, tvb
, offset
, textLen
);
710 if(offset
< endOffset
&& (offset
& 3) != 0) {
711 int padding
= 4 - (offset
& 3);
712 proto_tree_add_item(ti
, hf_iscsi_Padding
, tvb
, offset
, padding
, ENC_NA
);
715 if(digestsActive
&& dataSegmentLen
> 0 && offset
< endOffset
)
716 offset
= handleDataDigest(iscsi_session
, ti
, tvb
, dataOffset
, offset
- dataOffset
);
721 /* Code to actually dissect the packets */
723 // NOLINTNEXTLINE(misc-no-recursion)
724 dissect_iscsi_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, unsigned offset
, uint8_t opcode
, uint32_t data_segment_len
, iscsi_session_t
*iscsi_session
, conversation_t
*conversation
) {
726 unsigned original_offset
= offset
;
727 proto_tree
*ti
= NULL
, *opcode_item
= NULL
, *itm
= NULL
;
728 uint8_t scsi_status
= 0;
731 unsigned cdb_offset
= offset
+ 32; /* offset of CDB from start of PDU */
732 unsigned end_offset
= offset
+ tvb_captured_length_remaining(tvb
, offset
);
733 iscsi_conv_data_t
*cdata
= NULL
;
734 int paddedDataSegmentLength
= data_segment_len
;
736 unsigned immediate_data_length
=0;
737 unsigned immediate_data_offset
=0;
738 itl_nexus_t
*itl
=NULL
;
739 unsigned ahs_cdb_length
=0;
740 unsigned ahs_cdb_offset
=0;
741 uint32_t data_offset
=0;
742 wmem_tree_key_t key
[3];
744 const char* opcode_str
= val_to_str_const(opcode
, iscsi_opcodes
, "Unknown");
746 if(paddedDataSegmentLength
& 3)
747 paddedDataSegmentLength
+= 4 - (paddedDataSegmentLength
& 3);
748 /* Make entries in Protocol column and Info column on summary display */
749 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "iSCSI");
751 itt
= tvb_get_ntohl(tvb
, offset
+16);
755 key
[1].key
= &pinfo
->num
;
759 if (!PINFO_FD_VISITED(pinfo
)) {
760 if (opcode
== ISCSI_OPCODE_SCSI_COMMAND
) {
761 cdata
= wmem_new(wmem_file_scope(), iscsi_conv_data_t
);
762 cdata
->itlq
.lun
= 0xffff;
763 cdata
->itlq
.scsi_opcode
= 0xffff;
764 cdata
->itlq
.task_flags
= 0;
765 cdata
->itlq
.data_length
= 0;
766 cdata
->itlq
.bidir_data_length
= 0;
767 cdata
->itlq
.fc_time
= pinfo
->abs_ts
;
768 cdata
->itlq
.r2t_time
= pinfo
->abs_ts
;
769 cdata
->itlq
.first_exchange_frame
= 0;
770 cdata
->itlq
.last_exchange_frame
= 0;
771 cdata
->itlq
.flags
= 0;
772 cdata
->itlq
.alloc_len
= 0;
773 cdata
->itlq
.extra_data
= NULL
;
774 cdata
->r2t_frame
= 0;
775 cdata
->data_in_frame
= 0;
776 cdata
->data_out_frame
= 0;
778 wmem_tree_insert32_array(iscsi_session
->itlq
, key
, (void *)cdata
);
780 cdata
= (iscsi_conv_data_t
*)wmem_tree_lookup32_array_le(iscsi_session
->itlq
, key
);
781 if (cdata
&& (cdata
->itt
!= itt
)) {
786 cdata
= (iscsi_conv_data_t
*)wmem_tree_lookup32_array_le(iscsi_session
->itlq
, key
);
787 if (cdata
&& (cdata
->itt
!= itt
)) {
793 /* Create a fake temporary structure */
794 cdata
= wmem_new(pinfo
->pool
, iscsi_conv_data_t
);
795 cdata
->itlq
.lun
= 0xffff;
796 cdata
->itlq
.scsi_opcode
= 0xffff;
797 cdata
->itlq
.task_flags
= 0;
798 cdata
->itlq
.data_length
= 0;
799 cdata
->itlq
.bidir_data_length
= 0;
800 cdata
->itlq
.fc_time
= pinfo
->abs_ts
;
801 cdata
->itlq
.first_exchange_frame
= 0;
802 cdata
->itlq
.last_exchange_frame
= 0;
803 cdata
->itlq
.flags
= 0;
804 cdata
->itlq
.alloc_len
= 0;
805 cdata
->itlq
.extra_data
= NULL
;
806 cdata
->data_in_frame
= 0;
807 cdata
->data_out_frame
= 0;
808 cdata
->r2t_frame
= 0;
812 if (opcode
== ISCSI_OPCODE_SCSI_RESPONSE
||
813 opcode
== ISCSI_OPCODE_SCSI_DATA_IN
) {
814 scsi_status
= tvb_get_uint8 (tvb
, offset
+3);
817 if ((opcode
== ISCSI_OPCODE_SCSI_RESPONSE
) ||
818 (opcode
== ISCSI_OPCODE_SCSI_DATA_IN
) ||
819 (opcode
== ISCSI_OPCODE_SCSI_DATA_OUT
) ||
820 (opcode
== ISCSI_OPCODE_R2T
)) {
821 /* first time we see this packet. check if we can find the request */
823 case ISCSI_OPCODE_SCSI_RESPONSE
:
824 cdata
->itlq
.last_exchange_frame
=pinfo
->num
;
826 case ISCSI_OPCODE_R2T
:
827 cdata
->r2t_frame
=pinfo
->num
;
829 case ISCSI_OPCODE_SCSI_DATA_IN
:
830 /* a bit ugly but we need to check the S bit here */
831 if(tvb_get_uint8(tvb
, offset
+1)&ISCSI_SCSI_DATA_FLAG_S
){
832 cdata
->itlq
.last_exchange_frame
=pinfo
->num
;
834 cdata
->data_in_frame
=pinfo
->num
;
836 case ISCSI_OPCODE_SCSI_DATA_OUT
:
837 cdata
->data_out_frame
=pinfo
->num
;
841 } else if (opcode
== ISCSI_OPCODE_SCSI_COMMAND
) {
842 /*we need the LUN value for some of the commands so we can pass it
843 across to the SCSI dissector.
844 Not correct but simple and probably accurate enough :
845 If bit 6 of first bit is 0 then just take second byte as the LUN
846 If bit 6 of first bit is 1, then take 6 bits from first byte
847 and all of second byte and pretend it is the lun value
848 people that care can add host specific dissection of vsa later.
850 We need to keep track of this on a per transaction basis since
851 for error recoverylevel 0 and when the A bit is clear in a
852 Data-In PDU, there will not be a LUN field in the iscsi layer.
854 if(tvb_get_uint8(tvb
, offset
+8)&0x40){
855 /* volume set addressing */
856 lun
=tvb_get_uint8(tvb
,offset
+8)&0x3f;
858 lun
|=tvb_get_uint8(tvb
,offset
+9);
860 lun
=tvb_get_uint8(tvb
,offset
+9);
864 cdata
->itlq
.first_exchange_frame
=pinfo
->num
;
866 itl
=(itl_nexus_t
*)wmem_map_lookup(iscsi_session
->itl
, GUINT_TO_POINTER((unsigned long)lun
));
868 itl
=wmem_new(wmem_file_scope(), itl_nexus_t
);
870 itl
->conversation
=conversation
;
871 wmem_map_insert(iscsi_session
->itl
, GUINT_TO_POINTER((unsigned long)lun
), itl
);
877 itl
=(itl_nexus_t
*)wmem_map_lookup(iscsi_session
->itl
, GUINT_TO_POINTER((unsigned long)cdata
->itlq
.lun
));
882 if (opcode
!= ISCSI_OPCODE_SCSI_COMMAND
) {
884 col_append_str(pinfo
->cinfo
, COL_INFO
, opcode_str
);
886 if (opcode
== ISCSI_OPCODE_SCSI_RESPONSE
||
887 (opcode
== ISCSI_OPCODE_SCSI_DATA_IN
&&
888 (tvb_get_uint8(tvb
, offset
+ 1) & ISCSI_SCSI_DATA_FLAG_S
))) {
889 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (%s) ",
890 val_to_str (scsi_status
, scsi_status_val
, "0x%x"));
892 else if (opcode
== ISCSI_OPCODE_LOGIN_RESPONSE
) {
893 uint16_t login_status
= tvb_get_ntohs(tvb
, offset
+36);
894 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (%s) ",
895 val_to_str (login_status
, iscsi_login_status
, "0x%x"));
897 else if (opcode
== ISCSI_OPCODE_LOGOUT_COMMAND
) {
898 uint8_t logoutReason
;
899 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
900 logoutReason
= tvb_get_uint8(tvb
, offset
+11);
901 } else if(iscsi_protocol_version
>= ISCSI_PROTOCOL_DRAFT13
) {
902 logoutReason
= tvb_get_uint8(tvb
, offset
+1) & 0x7f;
905 logoutReason
= tvb_get_uint8(tvb
, offset
+23);
907 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (%s) ",
908 val_to_str (logoutReason
, iscsi_logout_reasons
, "0x%x"));
910 else if (opcode
== ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION
) {
911 uint8_t tmf
= tvb_get_uint8(tvb
, offset
+ 1) & 0x7f;
912 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (%s) ",
913 val_to_str (tmf
, iscsi_task_management_functions
, "0x%x"));
915 else if (opcode
== ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE
) {
916 uint8_t resp
= tvb_get_uint8(tvb
, offset
+ 2);
917 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (%s) ",
918 val_to_str (resp
, iscsi_task_management_responses
, "0x%x"));
920 else if (opcode
== ISCSI_OPCODE_REJECT
) {
921 uint8_t reason
= tvb_get_uint8(tvb
, offset
+ 2);
922 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (%s) ",
923 val_to_str (reason
, iscsi_reject_reasons
, "0x%x"));
925 else if (opcode
== ISCSI_OPCODE_ASYNC_MESSAGE
) {
926 uint8_t asyncEvent
= tvb_get_uint8(tvb
, offset
+ 36);
927 col_append_fstr (pinfo
->cinfo
, COL_INFO
, " (%s) ",
928 val_to_str (asyncEvent
, iscsi_asyncevents
, "0x%x"));
932 /* In the interest of speed, if "tree" is NULL, don't do any
933 work not necessary to generate protocol tree items. */
936 /* create display subtree for the protocol */
937 tp
= proto_tree_add_protocol_format(tree
, proto_iscsi
, tvb
,
938 offset
, -1, "iSCSI (%s) ",
940 ti
= proto_item_add_subtree(tp
, ett_iscsi
);
942 opcode_item
= proto_tree_add_item(ti
, hf_iscsi_Opcode
, tvb
,
943 offset
+ 0, 1, ENC_NA
);
944 if (!try_val_to_str(opcode
, iscsi_opcodes
)) {
945 expert_add_info(pinfo
, opcode_item
, &ei_iscsi_opcode_invalid
);
947 if((opcode
& TARGET_OPCODE_BIT
) == 0) {
948 /* initiator -> target */
949 int b
= tvb_get_uint8(tvb
, offset
+ 0);
950 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
951 if(opcode
!= ISCSI_OPCODE_SCSI_DATA_OUT
&&
952 opcode
!= ISCSI_OPCODE_LOGOUT_COMMAND
&&
953 opcode
!= ISCSI_OPCODE_SNACK_REQUEST
)
954 proto_tree_add_boolean(ti
, hf_iscsi_X
, tvb
, offset
+ 0, 1, b
);
956 if(opcode
!= ISCSI_OPCODE_SCSI_DATA_OUT
&&
957 opcode
!= ISCSI_OPCODE_LOGIN_COMMAND
&&
958 opcode
!= ISCSI_OPCODE_SNACK_REQUEST
)
959 proto_tree_add_boolean(ti
, hf_iscsi_I
, tvb
, offset
+ 0, 1, b
);
962 if(opcode
== ISCSI_OPCODE_NOP_OUT
) {
964 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
965 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
967 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
968 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
969 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
970 proto_tree_add_item(ti
, hf_iscsi_TargetTransferTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
971 proto_tree_add_item(ti
, hf_iscsi_CmdSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
972 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
973 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
974 offset
= handleDataSegment(iscsi_session
, ti
, tvb
, offset
, data_segment_len
, end_offset
, hf_iscsi_ping_data
);
975 } else if(opcode
== ISCSI_OPCODE_NOP_IN
) {
977 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
978 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
980 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
981 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
982 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
983 proto_tree_add_item(ti
, hf_iscsi_TargetTransferTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
984 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
985 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
986 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
987 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
988 offset
= handleDataSegment(iscsi_session
, ti
, tvb
, offset
, data_segment_len
, end_offset
, hf_iscsi_ping_data
);
989 } else if(opcode
== ISCSI_OPCODE_SCSI_COMMAND
) {
991 uint32_t ahsLen
= tvb_get_uint8(tvb
, offset
+ 4) * 4;
993 int b
= tvb_get_uint8(tvb
, offset
+ 1);
994 static int * const flags
[] = {
995 &hf_iscsi_SCSICommand_F
,
996 &hf_iscsi_SCSICommand_R
,
997 &hf_iscsi_SCSICommand_W
,
998 &hf_iscsi_SCSICommand_Attr
,
1002 proto_tree_add_bitmask(tree
, tvb
, offset
+ 1, hf_iscsi_Flags
, ett_iscsi_Flags
, flags
, ENC_NA
);
1005 cdata
->itlq
.task_flags
|=SCSI_DATA_READ
;
1008 cdata
->itlq
.task_flags
|=SCSI_DATA_WRITE
;
1011 if(iscsi_protocol_version
< ISCSI_PROTOCOL_DRAFT12
) {
1012 proto_tree_add_item(ti
, hf_iscsi_SCSICommand_CRN
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
1014 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1015 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1016 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1017 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1018 proto_tree_add_item(ti
, hf_iscsi_ExpectedDataTransferLength
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1019 cdata
->itlq
.data_length
=tvb_get_ntohl(tvb
, offset
+20);
1020 proto_tree_add_item(ti
, hf_iscsi_CmdSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1021 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1023 unsigned ahs_offset
=offset
+48;
1024 uint16_t ahs_length
=0;
1027 while(ahs_offset
<(offset
+48+ahsLen
)){
1029 ahs_length
=tvb_get_ntohs(tvb
, ahs_offset
);
1030 proto_tree_add_item(ti
, hf_iscsi_AHS_length
, tvb
, ahs_offset
, 2, ENC_BIG_ENDIAN
);
1033 ahs_type
=tvb_get_uint8(tvb
, ahs_offset
);
1034 proto_tree_add_item(ti
, hf_iscsi_AHS_type
, tvb
, ahs_offset
, 1, ENC_BIG_ENDIAN
);
1038 case 0x01: /* extended CDB */
1039 /* additional cdb */
1040 ahs_cdb_offset
=ahs_offset
+1;
1041 ahs_cdb_length
=ahs_length
-1;
1042 proto_tree_add_item(ti
, hf_iscsi_AHS_extended_cdb
, tvb
, ahs_cdb_offset
, ahs_cdb_length
, ENC_NA
);
1043 ahs_offset
+=ahs_length
;
1045 case 0x02: /* bidirectional read data length */
1046 /* skip reserved byte */
1048 /* read data length */
1049 proto_tree_add_item(ti
, hf_iscsi_AHS_read_data_length
, tvb
, ahs_offset
, 4, ENC_BIG_ENDIAN
);
1050 cdata
->itlq
.bidir_data_length
=tvb_get_ntohl(tvb
, ahs_offset
);
1054 proto_tree_add_item(ti
, hf_iscsi_AHS_blob
, tvb
, ahs_offset
, ahs_length
, ENC_NA
);
1055 ahs_offset
+=ahs_length
;
1058 /* strip off padding bytes */
1060 ahs_offset
=WS_ROUNDUP_4(ahs_offset
);
1066 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48 + ahsLen
);
1068 immediate_data_offset
=offset
;
1069 offset
= handleDataSegment(iscsi_session
, ti
, tvb
, offset
, data_segment_len
, end_offset
, hf_iscsi_immediate_data
);
1070 immediate_data_length
=offset
-immediate_data_offset
;
1071 } else if(opcode
== ISCSI_OPCODE_SCSI_RESPONSE
) {
1073 static int * const flags
[] = {
1074 &hf_iscsi_SCSIResponse_o
,
1075 &hf_iscsi_SCSIResponse_u
,
1076 &hf_iscsi_SCSIResponse_O
,
1077 &hf_iscsi_SCSIResponse_U
,
1081 proto_tree_add_bitmask(tree
, tvb
, offset
+ 1, hf_iscsi_Flags
, ett_iscsi_Flags
, flags
, ENC_NA
);
1082 proto_tree_add_item(ti
, hf_iscsi_SCSIResponse_Response
, tvb
, offset
+ 2, 1, ENC_BIG_ENDIAN
);
1083 proto_tree_add_item(ti
, hf_iscsi_SCSIResponse_Status
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
1084 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1085 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1087 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1088 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1089 if(iscsi_protocol_version
<= ISCSI_PROTOCOL_DRAFT09
) {
1090 proto_tree_add_item(ti
, hf_iscsi_SCSIResponse_ResidualCount
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1092 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1093 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1094 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1095 proto_tree_add_item(ti
, hf_iscsi_ExpDataSN
, tvb
, offset
+ 36, 4, ENC_BIG_ENDIAN
);
1096 if(iscsi_protocol_version
<= ISCSI_PROTOCOL_DRAFT09
) {
1097 proto_tree_add_item(ti
, hf_iscsi_SCSIResponse_BidiReadResidualCount
, tvb
, offset
+ 44, 4, ENC_BIG_ENDIAN
);
1100 proto_tree_add_item(ti
, hf_iscsi_SCSIResponse_BidiReadResidualCount
, tvb
, offset
+ 40, 4, ENC_BIG_ENDIAN
);
1101 proto_tree_add_item(ti
, hf_iscsi_SCSIResponse_ResidualCount
, tvb
, offset
+ 44, 4, ENC_BIG_ENDIAN
);
1103 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1104 /* do not update offset here because the data segment is
1105 * dissected below */
1106 handleDataDigest(iscsi_session
, ti
, tvb
, offset
, paddedDataSegmentLength
);
1107 } else if(opcode
== ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION
) {
1108 /* Task Management Function */
1109 proto_tree_add_item(ti
, hf_iscsi_TaskManagementFunction_Function
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
1110 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1111 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1112 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1114 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1115 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1116 proto_tree_add_item(ti
, hf_iscsi_TaskManagementFunction_ReferencedTaskTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1117 proto_tree_add_item(ti
, hf_iscsi_CmdSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1118 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1119 proto_tree_add_item(ti
, hf_iscsi_RefCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1120 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1121 } else if(opcode
== ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE
) {
1122 /* Task Management Function Response */
1123 proto_tree_add_item(ti
, hf_iscsi_TaskManagementFunction_Response
, tvb
, offset
+ 2, 1, ENC_BIG_ENDIAN
);
1124 if(iscsi_protocol_version
<= ISCSI_PROTOCOL_DRAFT09
) {
1125 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1126 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1128 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1129 if(iscsi_protocol_version
< ISCSI_PROTOCOL_DRAFT12
) {
1130 proto_tree_add_item(ti
, hf_iscsi_TaskManagementFunction_ReferencedTaskTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1132 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1133 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1134 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1135 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1136 } else if(opcode
== ISCSI_OPCODE_LOGIN_COMMAND
) {
1138 int digestsActive
= 0;
1140 int b
= tvb_get_uint8(tvb
, offset
+ 1);
1141 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
1142 if((b
& CSG_MASK
) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION
)
1146 proto_item
*tf
= proto_tree_add_uint(ti
, hf_iscsi_Flags
, tvb
, offset
+ 1, 1, b
);
1147 proto_tree
*tt
= proto_item_add_subtree(tf
, ett_iscsi_Flags
);
1150 proto_tree_add_boolean(ti
, hf_iscsi_Login_T
, tvb
, offset
+ 1, 1, b
);
1151 if(iscsi_protocol_version
>= ISCSI_PROTOCOL_DRAFT13
) {
1152 proto_tree_add_boolean(ti
, hf_iscsi_Login_C
, tvb
, offset
+ 1, 1, b
);
1154 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
1155 proto_tree_add_boolean(ti
, hf_iscsi_Login_X
, tvb
, offset
+ 1, 1, b
);
1157 proto_tree_add_item(ti
, hf_iscsi_Login_CSG
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
1159 /* NSG is undefined unless T is set */
1161 proto_tree_add_item(ti
, hf_iscsi_Login_NSG
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
1164 proto_tree_add_item(ti
, hf_iscsi_VersionMax
, tvb
, offset
+ 2, 1, ENC_BIG_ENDIAN
);
1165 proto_tree_add_item(ti
, hf_iscsi_VersionMin
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
1166 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1167 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1169 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1170 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
1171 proto_tree_add_item(ti
, hf_iscsi_CID
, tvb
, offset
+ 8, 2, ENC_BIG_ENDIAN
);
1172 proto_tree_add_item(ti
, hf_iscsi_ISID8
, tvb
, offset
+ 12, 2, ENC_BIG_ENDIAN
);
1175 proto_item
*tf
= proto_tree_add_item(ti
, hf_iscsi_ISID
, tvb
, offset
+ 8, 6, ENC_NA
);
1176 proto_tree
*tt
= proto_item_add_subtree(tf
, ett_iscsi_ISID
);
1177 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT09
) {
1178 proto_tree_add_item(tt
, hf_iscsi_ISID_Type
, tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
1179 proto_tree_add_item(tt
, hf_iscsi_ISID_NamingAuthority
, tvb
, offset
+ 9, 3, ENC_BIG_ENDIAN
);
1180 proto_tree_add_item(tt
, hf_iscsi_ISID_Qualifier
, tvb
, offset
+ 12, 2, ENC_BIG_ENDIAN
);
1183 proto_tree_add_item(tt
, hf_iscsi_ISID_t
, tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
1184 proto_tree_add_item(tt
, hf_iscsi_ISID_a
, tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
1185 proto_tree_add_item(tt
, hf_iscsi_ISID_b
, tvb
, offset
+ 9, 2, ENC_BIG_ENDIAN
);
1186 proto_tree_add_item(tt
, hf_iscsi_ISID_c
, tvb
, offset
+ 11, 1, ENC_BIG_ENDIAN
);
1187 proto_tree_add_item(tt
, hf_iscsi_ISID_d
, tvb
, offset
+ 12, 2, ENC_BIG_ENDIAN
);
1190 if(iscsi_protocol_version
< ISCSI_PROTOCOL_DRAFT12
) {
1191 proto_tree_add_item(ti
, hf_iscsi_TSID
, tvb
, offset
+ 14, 2, ENC_BIG_ENDIAN
);
1194 proto_tree_add_item(ti
, hf_iscsi_TSIH
, tvb
, offset
+ 14, 2, ENC_BIG_ENDIAN
);
1196 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1197 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT08
) {
1198 proto_tree_add_item(ti
, hf_iscsi_CID
, tvb
, offset
+ 20, 2, ENC_BIG_ENDIAN
);
1200 proto_tree_add_item(ti
, hf_iscsi_CmdSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1201 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1203 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1207 offset
= handleDataSegmentAsTextKeys(iscsi_session
, pinfo
, ti
, tvb
, offset
, data_segment_len
, end_offset
, digestsActive
);
1208 } else if(opcode
== ISCSI_OPCODE_LOGIN_RESPONSE
) {
1209 /* Login Response */
1210 int digestsActive
= 0;
1212 int b
= tvb_get_uint8(tvb
, offset
+ 1);
1213 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
1214 if((b
& CSG_MASK
) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION
)
1218 proto_item
*tf
= proto_tree_add_uint(ti
, hf_iscsi_Flags
, tvb
, offset
+ 1, 1, b
);
1219 proto_tree
*tt
= proto_item_add_subtree(tf
, ett_iscsi_Flags
);
1222 proto_tree_add_boolean(ti
, hf_iscsi_Login_T
, tvb
, offset
+ 1, 1, b
);
1223 if(iscsi_protocol_version
>= ISCSI_PROTOCOL_DRAFT13
) {
1224 proto_tree_add_boolean(ti
, hf_iscsi_Login_C
, tvb
, offset
+ 1, 1, b
);
1226 proto_tree_add_item(ti
, hf_iscsi_Login_CSG
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
1227 /* NSG is undefined unless T is set */
1229 proto_tree_add_item(ti
, hf_iscsi_Login_NSG
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
1233 proto_tree_add_item(ti
, hf_iscsi_VersionMax
, tvb
, offset
+ 2, 1, ENC_BIG_ENDIAN
);
1234 proto_tree_add_item(ti
, hf_iscsi_VersionActive
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
1235 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1236 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1238 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1239 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
1240 proto_tree_add_item(ti
, hf_iscsi_ISID8
, tvb
, offset
+ 12, 2, ENC_BIG_ENDIAN
);
1243 proto_item
*tf
= proto_tree_add_item(ti
, hf_iscsi_ISID
, tvb
, offset
+ 8, 6, ENC_NA
);
1244 proto_tree
*tt
= proto_item_add_subtree(tf
, ett_iscsi_ISID
);
1245 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT09
) {
1246 proto_tree_add_item(tt
, hf_iscsi_ISID_Type
, tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
1247 proto_tree_add_item(tt
, hf_iscsi_ISID_NamingAuthority
, tvb
, offset
+ 9, 3, ENC_BIG_ENDIAN
);
1248 proto_tree_add_item(tt
, hf_iscsi_ISID_Qualifier
, tvb
, offset
+ 12, 2, ENC_BIG_ENDIAN
);
1251 proto_tree_add_item(tt
, hf_iscsi_ISID_t
, tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
1252 proto_tree_add_item(tt
, hf_iscsi_ISID_a
, tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
1253 proto_tree_add_item(tt
, hf_iscsi_ISID_b
, tvb
, offset
+ 9, 2, ENC_BIG_ENDIAN
);
1254 proto_tree_add_item(tt
, hf_iscsi_ISID_c
, tvb
, offset
+ 11, 1, ENC_BIG_ENDIAN
);
1255 proto_tree_add_item(tt
, hf_iscsi_ISID_d
, tvb
, offset
+ 12, 2, ENC_BIG_ENDIAN
);
1258 if(iscsi_protocol_version
< ISCSI_PROTOCOL_DRAFT12
) {
1259 proto_tree_add_item(ti
, hf_iscsi_TSID
, tvb
, offset
+ 14, 2, ENC_BIG_ENDIAN
);
1262 proto_tree_add_item(ti
, hf_iscsi_TSIH
, tvb
, offset
+ 14, 2, ENC_BIG_ENDIAN
);
1264 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1265 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1266 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1267 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1268 proto_tree_add_item(ti
, hf_iscsi_Login_Status
, tvb
, offset
+ 36, 2, ENC_BIG_ENDIAN
);
1270 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1274 offset
= handleDataSegmentAsTextKeys(iscsi_session
, pinfo
, ti
, tvb
, offset
, data_segment_len
, end_offset
, digestsActive
);
1275 } else if(opcode
== ISCSI_OPCODE_TEXT_COMMAND
) {
1278 int b
= tvb_get_uint8(tvb
, offset
+ 1);
1279 proto_item
*tf
= proto_tree_add_uint(ti
, hf_iscsi_Flags
, tvb
, offset
+ 1, 1, b
);
1280 proto_tree
*tt
= proto_item_add_subtree(tf
, ett_iscsi_Flags
);
1282 proto_tree_add_boolean(tt
, hf_iscsi_Text_F
, tvb
, offset
+ 1, 1, b
);
1283 if(iscsi_protocol_version
>= ISCSI_PROTOCOL_DRAFT13
) {
1284 proto_tree_add_boolean(tt
, hf_iscsi_Text_C
, tvb
, offset
+ 1, 1, b
);
1287 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1288 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1290 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1291 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1292 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1294 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1295 proto_tree_add_item(ti
, hf_iscsi_TargetTransferTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1296 proto_tree_add_item(ti
, hf_iscsi_CmdSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1297 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1298 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1299 offset
= handleDataSegmentAsTextKeys(iscsi_session
, pinfo
, ti
, tvb
, offset
, data_segment_len
, end_offset
, true);
1300 } else if(opcode
== ISCSI_OPCODE_TEXT_RESPONSE
) {
1303 int b
= tvb_get_uint8(tvb
, offset
+ 1);
1304 proto_item
*tf
= proto_tree_add_uint(ti
, hf_iscsi_Flags
, tvb
, offset
+ 1, 1, b
);
1305 proto_tree
*tt
= proto_item_add_subtree(tf
, ett_iscsi_Flags
);
1307 proto_tree_add_boolean(tt
, hf_iscsi_Text_F
, tvb
, offset
+ 1, 1, b
);
1308 if(iscsi_protocol_version
>= ISCSI_PROTOCOL_DRAFT13
) {
1309 proto_tree_add_boolean(tt
, hf_iscsi_Text_C
, tvb
, offset
+ 1, 1, b
);
1312 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1313 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1315 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1316 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1317 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1319 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1320 proto_tree_add_item(ti
, hf_iscsi_TargetTransferTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1321 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1322 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1323 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1324 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1325 offset
= handleDataSegmentAsTextKeys(iscsi_session
, pinfo
, ti
, tvb
, offset
, data_segment_len
, end_offset
, true);
1326 } else if(opcode
== ISCSI_OPCODE_SCSI_DATA_OUT
) {
1327 /* SCSI Data Out (write) */
1328 static int * const flags
[] = {
1329 &hf_iscsi_SCSIData_F
,
1333 proto_tree_add_bitmask(tree
, tvb
, offset
+ 1, hf_iscsi_Flags
, ett_iscsi_Flags
, flags
, ENC_NA
);
1335 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1336 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1338 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1339 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1340 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1341 proto_tree_add_item(ti
, hf_iscsi_TargetTransferTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1342 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1343 proto_tree_add_item(ti
, hf_iscsi_DataSN
, tvb
, offset
+ 36, 4, ENC_BIG_ENDIAN
);
1344 proto_tree_add_item(ti
, hf_iscsi_BufferOffset
, tvb
, offset
+ 40, 4, ENC_BIG_ENDIAN
);
1345 data_offset
=tvb_get_ntohl(tvb
, offset
+40);
1347 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1348 /* do not update offset here because the data segment is
1349 * dissected below */
1350 handleDataDigest(iscsi_session
, ti
, tvb
, offset
, paddedDataSegmentLength
);
1351 } else if(opcode
== ISCSI_OPCODE_SCSI_DATA_IN
) {
1352 /* SCSI Data In (read) */
1354 static int * const scsi_data_in
[] = {
1355 &hf_iscsi_SCSIData_F
,
1356 &hf_iscsi_SCSIData_O
,
1357 &hf_iscsi_SCSIData_U
,
1358 &hf_iscsi_SCSIData_S
,
1362 static int * const scsi_data_in_draft08
[] = {
1363 &hf_iscsi_SCSIData_F
,
1364 &hf_iscsi_SCSIData_A
,
1365 &hf_iscsi_SCSIData_O
,
1366 &hf_iscsi_SCSIData_U
,
1367 &hf_iscsi_SCSIData_S
,
1372 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT08
) {
1373 proto_tree_add_bitmask_with_flags(ti
, tvb
, offset
+1, hf_iscsi_Flags
,
1374 ett_iscsi_Flags
, scsi_data_in_draft08
, ENC_NA
, BMT_NO_APPEND
);
1376 proto_tree_add_bitmask_with_flags(ti
, tvb
, offset
+1, hf_iscsi_Flags
,
1377 ett_iscsi_Flags
, scsi_data_in
, ENC_NA
, BMT_NO_APPEND
);
1380 b
= tvb_get_uint8(tvb
, offset
+ 1);
1381 if(b
&ISCSI_SCSI_DATA_FLAG_S
){
1385 if(b
&ISCSI_SCSI_DATA_FLAG_A
){
1391 proto_tree_add_item(ti
, hf_iscsi_SCSIResponse_Status
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
1393 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1394 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1396 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1397 cdata
->itlq
.data_length
=tvb_get_ntoh24(tvb
, offset
+ 5);
1398 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1400 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1403 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1404 if(iscsi_protocol_version
<= ISCSI_PROTOCOL_DRAFT09
) {
1405 proto_tree_add_item(ti
, hf_iscsi_SCSIData_ResidualCount
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1409 proto_tree_add_item(ti
, hf_iscsi_TargetTransferTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1412 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1413 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1414 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1415 proto_tree_add_item(ti
, hf_iscsi_DataSN
, tvb
, offset
+ 36, 4, ENC_BIG_ENDIAN
);
1416 proto_tree_add_item(ti
, hf_iscsi_BufferOffset
, tvb
, offset
+ 40, 4, ENC_BIG_ENDIAN
);
1417 data_offset
=tvb_get_ntohl(tvb
, offset
+40);
1419 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1420 proto_tree_add_item(ti
, hf_iscsi_SCSIData_ResidualCount
, tvb
, offset
+ 44, 4, ENC_BIG_ENDIAN
);
1422 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1423 /* do not update offset here because the data segment is
1424 * dissected below */
1425 handleDataDigest(iscsi_session
, ti
, tvb
, offset
, paddedDataSegmentLength
);
1426 } else if(opcode
== ISCSI_OPCODE_LOGOUT_COMMAND
) {
1427 /* Logout Command */
1428 if(iscsi_protocol_version
>= ISCSI_PROTOCOL_DRAFT13
) {
1429 proto_tree_add_item(ti
, hf_iscsi_Logout_Reason
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
1431 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1432 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1433 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1435 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
1436 proto_tree_add_item(ti
, hf_iscsi_CID
, tvb
, offset
+ 8, 2, ENC_BIG_ENDIAN
);
1437 proto_tree_add_item(ti
, hf_iscsi_Logout_Reason
, tvb
, offset
+ 11, 1, ENC_BIG_ENDIAN
);
1439 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1440 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT08
) {
1441 proto_tree_add_item(ti
, hf_iscsi_CID
, tvb
, offset
+ 20, 2, ENC_BIG_ENDIAN
);
1442 if(iscsi_protocol_version
< ISCSI_PROTOCOL_DRAFT13
) {
1443 proto_tree_add_item(ti
, hf_iscsi_Logout_Reason
, tvb
, offset
+ 23, 1, ENC_BIG_ENDIAN
);
1446 proto_tree_add_item(ti
, hf_iscsi_CmdSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1447 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1448 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1449 } else if(opcode
== ISCSI_OPCODE_LOGOUT_RESPONSE
) {
1450 /* Logout Response */
1451 proto_tree_add_item(ti
, hf_iscsi_Logout_Response
, tvb
, offset
+ 2, 1, ENC_BIG_ENDIAN
);
1452 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1453 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1454 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1456 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1457 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1458 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1459 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1460 proto_tree_add_item(ti
, hf_iscsi_Time2Wait
, tvb
, offset
+ 40, 2, ENC_BIG_ENDIAN
);
1461 proto_tree_add_item(ti
, hf_iscsi_Time2Retain
, tvb
, offset
+ 42, 2, ENC_BIG_ENDIAN
);
1462 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1463 } else if(opcode
== ISCSI_OPCODE_SNACK_REQUEST
) {
1467 int b
= tvb_get_uint8(tvb
, offset
+ 1);
1468 proto_item
*tf
= proto_tree_add_uint(ti
, hf_iscsi_Flags
, tvb
, offset
+ 1, 1, b
);
1469 proto_tree
*tt
= proto_item_add_subtree(tf
, ett_iscsi_Flags
);
1472 proto_tree_add_item(ti
, hf_iscsi_snack_type
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
1474 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1475 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1476 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1477 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1479 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1480 if(iscsi_protocol_version
<= ISCSI_PROTOCOL_DRAFT09
) {
1481 proto_tree_add_item(ti
, hf_iscsi_BegRun
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1482 proto_tree_add_item(ti
, hf_iscsi_RunLength
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1483 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1484 proto_tree_add_item(ti
, hf_iscsi_ExpDataSN
, tvb
, offset
+ 36, 4, ENC_BIG_ENDIAN
);
1487 proto_tree_add_item(ti
, hf_iscsi_TargetTransferTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1488 proto_tree_add_item(ti
, hf_iscsi_ExpStatSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1489 proto_tree_add_item(ti
, hf_iscsi_BegRun
, tvb
, offset
+ 40, 4, ENC_BIG_ENDIAN
);
1490 proto_tree_add_item(ti
, hf_iscsi_RunLength
, tvb
, offset
+ 44, 4, ENC_BIG_ENDIAN
);
1492 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1493 } else if(opcode
== ISCSI_OPCODE_R2T
) {
1495 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1496 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1497 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1498 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1500 proto_tree_add_item(ti
, hf_iscsi_InitiatorTaskTag
, tvb
, offset
+ 16, 4, ENC_BIG_ENDIAN
);
1501 proto_tree_add_item(ti
, hf_iscsi_TargetTransferTag
, tvb
, offset
+ 20, 4, ENC_BIG_ENDIAN
);
1502 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1503 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1504 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1505 proto_tree_add_item(ti
, hf_iscsi_R2TSN
, tvb
, offset
+ 36, 4, ENC_BIG_ENDIAN
);
1506 proto_tree_add_item(ti
, hf_iscsi_BufferOffset
, tvb
, offset
+ 40, 4, ENC_BIG_ENDIAN
);
1507 proto_tree_add_item(ti
, hf_iscsi_DesiredDataLength
, tvb
, offset
+ 44, 4, ENC_BIG_ENDIAN
);
1508 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1509 } else if(opcode
== ISCSI_OPCODE_ASYNC_MESSAGE
) {
1512 /* Asynchronous Message */
1513 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1514 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1516 dsl
=tvb_get_ntoh24(tvb
, offset
+5);
1517 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1518 dissect_scsi_lun(ti
, tvb
, offset
+ 8);
1519 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1520 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1521 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1522 proto_tree_add_item(ti
, hf_iscsi_AsyncEvent
, tvb
, offset
+ 36, 1, ENC_BIG_ENDIAN
);
1523 proto_tree_add_item(ti
, hf_iscsi_EventVendorCode
, tvb
, offset
+ 37, 1, ENC_BIG_ENDIAN
);
1524 proto_tree_add_item(ti
, hf_iscsi_Parameter1
, tvb
, offset
+ 38, 2, ENC_BIG_ENDIAN
);
1525 proto_tree_add_item(ti
, hf_iscsi_Parameter2
, tvb
, offset
+ 40, 2, ENC_BIG_ENDIAN
);
1526 proto_tree_add_item(ti
, hf_iscsi_Parameter3
, tvb
, offset
+ 42, 2, ENC_BIG_ENDIAN
);
1527 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1529 /* If we have a datasegment this contains scsi sense info followed
1530 * by iscsi event data. (rfc3720 10.9.4)
1533 snsl
=tvb_get_ntohs(tvb
, offset
);
1537 int tvb_len
, tvb_rlen
;
1539 tvb_len
=tvb_captured_length_remaining(tvb
, offset
);
1542 tvb_rlen
=tvb_reported_length_remaining(tvb
, offset
);
1545 data_tvb
=tvb_new_subset_length_caplen(tvb
, offset
, tvb_len
, tvb_rlen
);
1546 dissect_scsi_snsinfo (data_tvb
, pinfo
, tree
, 0,
1552 if((end_offset
-offset
)>0){
1553 proto_tree_add_item(ti
, hf_iscsi_async_event_data
, tvb
, offset
, end_offset
-offset
, ENC_NA
);
1557 } else if(opcode
== ISCSI_OPCODE_REJECT
) {
1559 uint8_t next_opcode
;
1562 proto_tree_add_item(ti
, hf_iscsi_Reject_Reason
, tvb
, offset
+ 2, 1, ENC_BIG_ENDIAN
);
1563 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1564 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1566 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1567 proto_tree_add_item(ti
, hf_iscsi_StatSN
, tvb
, offset
+ 24, 4, ENC_BIG_ENDIAN
);
1568 proto_tree_add_item(ti
, hf_iscsi_ExpCmdSN
, tvb
, offset
+ 28, 4, ENC_BIG_ENDIAN
);
1569 proto_tree_add_item(ti
, hf_iscsi_MaxCmdSN
, tvb
, offset
+ 32, 4, ENC_BIG_ENDIAN
);
1570 proto_tree_add_item(ti
, hf_iscsi_DataSN
, tvb
, offset
+ 36, 4, ENC_BIG_ENDIAN
);
1571 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1573 next_opcode
= tvb_get_uint8(tvb
, offset
) & OPCODE_MASK
;
1575 tt
= proto_tree_add_subtree(ti
, tvb
, offset
, -1, ett_iscsi_RejectHeader
, NULL
, "Rejected Header");
1577 increment_dissection_depth(pinfo
);
1578 dissect_iscsi_pdu(tvb
, pinfo
, tt
, offset
, next_opcode
, 0, iscsi_session
, conversation
);
1579 decrement_dissection_depth(pinfo
);
1580 } else if(opcode
== ISCSI_OPCODE_VENDOR_SPECIFIC_I0
||
1581 opcode
== ISCSI_OPCODE_VENDOR_SPECIFIC_I1
||
1582 opcode
== ISCSI_OPCODE_VENDOR_SPECIFIC_I2
||
1583 opcode
== ISCSI_OPCODE_VENDOR_SPECIFIC_T0
||
1584 opcode
== ISCSI_OPCODE_VENDOR_SPECIFIC_T1
||
1585 opcode
== ISCSI_OPCODE_VENDOR_SPECIFIC_T2
) {
1586 /* Vendor specific opcodes */
1587 if(iscsi_protocol_version
> ISCSI_PROTOCOL_DRAFT09
) {
1588 proto_tree_add_item(ti
, hf_iscsi_TotalAHSLength
, tvb
, offset
+ 4, 1, ENC_BIG_ENDIAN
);
1590 proto_tree_add_item(ti
, hf_iscsi_DataSegmentLength
, tvb
, offset
+ 5, 3, ENC_BIG_ENDIAN
);
1591 offset
= handleHeaderDigest(iscsi_session
, ti
, tvb
, offset
, 48);
1592 offset
= handleDataSegment(iscsi_session
, ti
, tvb
, offset
, data_segment_len
, end_offset
, hf_iscsi_vendor_specific_data
);
1597 /* handle request/response matching */
1599 case ISCSI_OPCODE_SCSI_RESPONSE
:
1600 if (cdata
->itlq
.first_exchange_frame
){
1601 nstime_t delta_time
;
1602 itm
= proto_tree_add_uint(ti
, hf_iscsi_request_frame
, tvb
, 0, 0, cdata
->itlq
.first_exchange_frame
);
1603 proto_item_set_generated(itm
);
1604 nstime_delta(&delta_time
, &pinfo
->abs_ts
, &cdata
->itlq
.fc_time
);
1605 itm
= proto_tree_add_time(ti
, hf_iscsi_time
, tvb
, 0, 0, &delta_time
);
1606 proto_item_set_generated(itm
);
1608 if (cdata
->r2t_frame
) {
1609 itm
= proto_tree_add_uint(ti
, hf_iscsi_r2t_frame
, tvb
, 0, 0, cdata
->r2t_frame
);
1610 proto_item_set_generated(itm
);
1612 if (cdata
->data_in_frame
) {
1613 itm
= proto_tree_add_uint(ti
, hf_iscsi_data_in_frame
, tvb
, 0, 0, cdata
->data_in_frame
);
1614 proto_item_set_generated(itm
);
1616 if (cdata
->data_out_frame
) {
1617 itm
= proto_tree_add_uint(ti
, hf_iscsi_data_out_frame
, tvb
, 0, 0, cdata
->data_out_frame
);
1618 proto_item_set_generated(itm
);
1622 case ISCSI_OPCODE_R2T
:
1623 if (cdata
->itlq
.first_exchange_frame
) {
1624 itm
= proto_tree_add_uint(ti
, hf_iscsi_request_frame
, tvb
, 0, 0, cdata
->itlq
.first_exchange_frame
);
1625 proto_item_set_generated(itm
);
1627 if (cdata
->itlq
.first_exchange_frame
&& (cdata
->itlq
.first_exchange_frame
< pinfo
->num
)) {
1628 nstime_t delta_time
;
1629 nstime_delta(&delta_time
, &pinfo
->abs_ts
, &cdata
->itlq
.r2t_time
);
1630 itm
= proto_tree_add_time(ti
, hf_iscsi_r2t_time
, tvb
, 0, 0, &delta_time
);
1631 proto_item_set_generated(itm
);
1633 if (cdata
->data_out_frame
) {
1634 itm
= proto_tree_add_uint(ti
, hf_iscsi_data_out_frame
, tvb
, 0, 0, cdata
->data_out_frame
);
1635 proto_item_set_generated(itm
);
1637 if (cdata
->itlq
.last_exchange_frame
) {
1638 itm
= proto_tree_add_uint(ti
, hf_iscsi_response_frame
, tvb
, 0, 0, cdata
->itlq
.last_exchange_frame
);
1639 proto_item_set_generated(itm
);
1642 if (cdata
->itlq
.lun
== 0xffff)
1643 col_append_str (pinfo
->cinfo
, COL_INFO
,
1644 " <missing request> "
1647 col_append_fstr (pinfo
->cinfo
, COL_INFO
,
1648 " LUN: 0x0%x, OK to write %u bytes (%u blocks) ",
1650 cdata
->itlq
.data_length
,
1651 cdata
->itlq
.data_length
>=512 ? cdata
->itlq
.data_length
/512 : 0
1654 case ISCSI_OPCODE_SCSI_DATA_IN
:
1655 /* if we have phase collaps then we might have the
1656 response embedded in the last DataIn segment */
1658 if (cdata
->itlq
.first_exchange_frame
) {
1659 itm
= proto_tree_add_uint(ti
, hf_iscsi_response_frame
, tvb
, 0, 0, cdata
->itlq
.last_exchange_frame
);
1660 proto_item_set_generated(itm
);
1663 if (cdata
->itlq
.first_exchange_frame
){
1664 nstime_t delta_time
;
1665 itm
= proto_tree_add_uint(ti
, hf_iscsi_request_frame
, tvb
, 0, 0, cdata
->itlq
.first_exchange_frame
);
1666 proto_item_set_generated(itm
);
1667 nstime_delta(&delta_time
, &pinfo
->abs_ts
, &cdata
->itlq
.fc_time
);
1668 itm
= proto_tree_add_time(ti
, hf_iscsi_time
, tvb
, 0, 0, &delta_time
);
1669 proto_item_set_generated(itm
);
1672 if (cdata
->data_out_frame
) {
1673 itm
= proto_tree_add_uint(ti
, hf_iscsi_data_out_frame
, tvb
, 0, 0, cdata
->data_out_frame
);
1674 proto_item_set_generated(itm
);
1677 col_set_fence(pinfo
->cinfo
, COL_INFO
);
1678 col_append_fstr (pinfo
->cinfo
, COL_INFO
,
1679 " LUN: %u, read %u bytes (%u blocks) ",
1682 data_segment_len
>=512 ? data_segment_len
/512 : 0
1685 case ISCSI_OPCODE_SCSI_DATA_OUT
:
1686 if (cdata
->itlq
.first_exchange_frame
) {
1687 itm
= proto_tree_add_uint(ti
, hf_iscsi_request_frame
, tvb
, 0, 0, cdata
->itlq
.first_exchange_frame
);
1688 proto_item_set_generated(itm
);
1690 if (cdata
->r2t_frame
) {
1691 itm
= proto_tree_add_uint(ti
, hf_iscsi_r2t_frame
, tvb
, 0, 0, cdata
->r2t_frame
);
1692 proto_item_set_generated(itm
);
1694 if (cdata
->data_in_frame
) {
1695 itm
= proto_tree_add_uint(ti
, hf_iscsi_data_in_frame
, tvb
, 0, 0, cdata
->data_in_frame
);
1696 proto_item_set_generated(itm
);
1698 if (cdata
->itlq
.last_exchange_frame
) {
1699 itm
= proto_tree_add_uint(ti
, hf_iscsi_response_frame
, tvb
, 0, 0, cdata
->itlq
.last_exchange_frame
);
1700 proto_item_set_generated(itm
);
1703 col_set_fence(pinfo
->cinfo
, COL_INFO
);
1704 col_append_fstr (pinfo
->cinfo
, COL_INFO
,
1705 " LUN: 0x0%x, wrote %u bytes (%u blocks) ",
1708 data_segment_len
>=512 ? data_segment_len
/512 : 0
1711 case ISCSI_OPCODE_SCSI_COMMAND
:
1712 if (cdata
->r2t_frame
) {
1713 itm
= proto_tree_add_uint(ti
, hf_iscsi_r2t_frame
, tvb
, 0, 0, cdata
->r2t_frame
);
1714 proto_item_set_generated(itm
);
1716 if (cdata
->data_in_frame
) {
1717 itm
= proto_tree_add_uint(ti
, hf_iscsi_data_in_frame
, tvb
, 0, 0, cdata
->data_in_frame
);
1718 proto_item_set_generated(itm
);
1720 if (cdata
->data_out_frame
) {
1721 itm
= proto_tree_add_uint(ti
, hf_iscsi_data_out_frame
, tvb
, 0, 0, cdata
->data_out_frame
);
1722 proto_item_set_generated(itm
);
1724 if (cdata
->itlq
.last_exchange_frame
) {
1725 itm
= proto_tree_add_uint(ti
, hf_iscsi_response_frame
, tvb
, 0, 0, cdata
->itlq
.last_exchange_frame
);
1726 proto_item_set_generated(itm
);
1733 proto_item_set_len(ti
, offset
- original_offset
);
1735 if((opcode
& ((iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
)?
1737 ~I_BIT
)) == ISCSI_OPCODE_SCSI_COMMAND
) {
1738 tvbuff_t
*cdb_tvb
, *data_tvb
;
1739 int tvb_len
, tvb_rlen
;
1742 tvb_len
=tvb_captured_length_remaining(tvb
, cdb_offset
);
1743 tvb_rlen
=tvb_reported_length_remaining(tvb
, cdb_offset
);
1744 if(ahs_cdb_length
&& ahs_cdb_length
<1024){
1747 /* We have a variable length CDB where bytes >16 is transported
1750 cdb_buf
=(uint8_t *)wmem_alloc(pinfo
->pool
, 16+ahs_cdb_length
);
1751 /* the 16 first bytes of the cdb */
1752 tvb_memcpy(tvb
, cdb_buf
, cdb_offset
, 16);
1753 /* the remainder of the cdb from the ahs */
1754 tvb_memcpy(tvb
, cdb_buf
+16, ahs_cdb_offset
, ahs_cdb_length
);
1756 cdb_tvb
= tvb_new_child_real_data(tvb
, cdb_buf
,
1760 add_new_data_source(pinfo
, cdb_tvb
, "CDB+AHS");
1768 cdb_tvb
=tvb_new_subset_length_caplen(tvb
, cdb_offset
, tvb_len
, tvb_rlen
);
1770 dissect_scsi_cdb(cdb_tvb
, pinfo
, tree
, SCSI_DEV_UNKNOWN
, &cdata
->itlq
, itl
);
1771 /* we don't want the immediate below to overwrite our CDB info */
1772 col_set_fence(pinfo
->cinfo
, COL_INFO
);
1774 /* where there any ImmediateData ? */
1775 if(immediate_data_length
){
1776 /* Immediate Data TVB */
1777 tvb_len
=tvb_captured_length_remaining(tvb
, immediate_data_offset
);
1778 if(tvb_len
>(int)immediate_data_length
)
1779 tvb_len
=immediate_data_length
;
1780 tvb_rlen
=tvb_reported_length_remaining(tvb
, immediate_data_offset
);
1781 if(tvb_rlen
>(int)immediate_data_length
)
1782 tvb_rlen
=immediate_data_length
;
1783 data_tvb
=tvb_new_subset_length_caplen(tvb
, immediate_data_offset
, tvb_len
, tvb_rlen
);
1784 dissect_scsi_payload (data_tvb
, pinfo
, tree
,
1790 else if (opcode
== ISCSI_OPCODE_SCSI_RESPONSE
) {
1791 if (scsi_status
== 0x2) {
1792 /* A SCSI response with Check Condition contains sense data */
1793 /* offset is setup correctly by the iscsi code for response above */
1794 if((end_offset
- offset
) >= 2) {
1795 int senseLen
= tvb_get_ntohs(tvb
, offset
);
1797 proto_tree_add_item(ti
, hf_iscsi_SenseLength
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1801 int tvb_len
, tvb_rlen
;
1803 tvb_len
=tvb_captured_length_remaining(tvb
, offset
);
1804 if(tvb_len
>senseLen
)
1806 tvb_rlen
=tvb_reported_length_remaining(tvb
, offset
);
1807 if(tvb_rlen
>senseLen
)
1809 data_tvb
=tvb_new_subset_length_caplen(tvb
, offset
, tvb_len
, tvb_rlen
);
1810 dissect_scsi_snsinfo (data_tvb
, pinfo
, tree
, 0,
1817 dissect_scsi_rsp(tvb
, pinfo
, tree
, &cdata
->itlq
, itl
, scsi_status
);
1820 else if ((opcode
== ISCSI_OPCODE_SCSI_DATA_IN
) ||
1821 (opcode
== ISCSI_OPCODE_SCSI_DATA_OUT
)) {
1823 int tvb_len
, tvb_rlen
;
1825 /* offset is setup correctly by the iscsi code for response above */
1826 tvb_len
=tvb_captured_length_remaining(tvb
, offset
);
1827 if(tvb_len
>(int)data_segment_len
)
1828 tvb_len
=data_segment_len
;
1829 tvb_rlen
=tvb_reported_length_remaining(tvb
, offset
);
1830 if(tvb_rlen
>(int)data_segment_len
)
1831 tvb_rlen
=data_segment_len
;
1832 data_tvb
=tvb_new_subset_length_caplen(tvb
, offset
, tvb_len
, tvb_rlen
);
1833 dissect_scsi_payload (data_tvb
, pinfo
, tree
,
1834 (opcode
==ISCSI_OPCODE_SCSI_DATA_OUT
),
1840 dissect_scsi_rsp(tvb
, pinfo
, tree
, &cdata
->itlq
, itl
, scsi_status
);
1845 dissect_iscsi(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, bool check_port
) {
1846 /* Set up structures needed to add the protocol subtree and manage it */
1847 unsigned offset
= 0;
1848 uint32_t available_bytes
= tvb_captured_length(tvb
);
1849 int digestsActive
= 1;
1850 conversation_t
*conversation
= NULL
;
1851 iscsi_session_t
*iscsi_session
=NULL
;
1852 uint8_t opcode
, tmpbyte
;
1854 if (available_bytes
< 48) {
1855 /* heuristic already rejected the packet if size < 48,
1856 assume it's an iscsi packet with a segmented header */
1857 pinfo
->desegment_offset
= offset
;
1858 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
1862 opcode
= tvb_get_uint8(tvb
, offset
+ 0);
1863 opcode
&= OPCODE_MASK
;
1865 /* heuristics to verify that the packet looks sane. the heuristics
1866 * are based on the RFC version of iscsi.
1867 * (we should retire support for older iscsi versions in wireshark)
1870 /* opcode must be any of the ones from the standard
1871 * also check the header that it looks "sane"
1872 * all reserved or undefined bits in iscsi must be set to zero.
1875 case ISCSI_OPCODE_NOP_IN
:
1876 /* top two bits of byte 0 must be 0 */
1877 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
1880 /* byte 1 must be 0x80 */
1881 if(tvb_get_uint8(tvb
, offset
+1)!=0x80){
1884 /* bytes 2 and 3 must be 0 */
1885 if(tvb_get_uint8(tvb
, offset
+2)||tvb_get_uint8(tvb
, offset
+3)){
1889 case ISCSI_OPCODE_NOP_OUT
:
1890 /* top bit of byte 0 must be 0 */
1891 if(tvb_get_uint8(tvb
, offset
+0)&0x80){
1894 /* byte 1 must be 0x80 */
1895 if(tvb_get_uint8(tvb
, offset
+1)!=0x80){
1898 /* bytes 2 and 3 must be 0 */
1899 if(tvb_get_uint8(tvb
, offset
+2)||tvb_get_uint8(tvb
, offset
+3)){
1902 /* assume ITT and TTT must always be non NULL (ok they can be NULL
1903 * from time to time but it usually means we are in the middle
1904 * of a zeroed datablock).
1906 if(!tvb_get_letohl(tvb
,offset
+16) || !tvb_get_letohl(tvb
,offset
+20)){
1909 /* all reserved bytes between 32 - 47 must be null */
1910 if(tvb_get_letohl(tvb
,offset
+32)
1911 || tvb_get_letohl(tvb
,offset
+36)
1912 || tvb_get_letohl(tvb
,offset
+40)
1913 || tvb_get_letohl(tvb
,offset
+44)){
1917 case ISCSI_OPCODE_LOGIN_COMMAND
:
1918 /* top two bits in byte 0 must be 0x40 */
1919 if((tvb_get_uint8(tvb
, offset
+0)&0xc0)!=0x40){
1923 /* both the T and C bits can not be set
1924 * and the two reserved bits in byte 1 must be 0
1926 tmpbyte
=tvb_get_uint8(tvb
, offset
+1);
1927 switch(tmpbyte
&0xf0){
1935 /* CSG and NSG must not be 2 */
1936 if(((tmpbyte
& 0x03) == 0x02)
1937 || ((tmpbyte
& 0x0c) == 0x08)) {
1940 /* if T bit is set NSG must not be 0 */
1942 if(!(tmpbyte
&0x03)){
1946 /* should we test that datasegmentlen is non zero? */
1948 case ISCSI_OPCODE_LOGIN_RESPONSE
:
1949 /* top two bits in byte 0 must be 0 */
1950 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
1954 /* both the T and C bits can not be set
1955 * and the two reserved bits in byte 1 must be 0
1957 tmpbyte
=tvb_get_uint8(tvb
, offset
+1);
1958 switch(tmpbyte
&0xf0){
1966 /* CSG and NSG must not be 2 */
1967 if(((tmpbyte
& 0x03) == 0x02)
1968 || ((tmpbyte
& 0x0c) == 0x08)) {
1971 /* if T bit is set NSG must not be 0 */
1973 if(!(tmpbyte
&0x03)){
1977 /* the 32bit words at offsets 20, 40, 44 must be zero */
1978 if(tvb_get_letohl(tvb
,offset
+20)
1979 || tvb_get_letohl(tvb
,offset
+40)
1980 || tvb_get_letohl(tvb
,offset
+44)){
1983 /* the two bytes at offset 38 must be zero */
1984 if(tvb_get_letohs(tvb
,offset
+38)){
1987 /* should we test that datasegmentlen is non zero unless we just
1988 * entered full featured phase?
1991 case ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION
:
1992 /* top bit in byte 0 must be 0 */
1993 if(tvb_get_uint8(tvb
, offset
+0)&0x80){
1996 /* top bit in byte 1 must be set */
1997 tmpbyte
=tvb_get_uint8(tvb
, offset
+1);
1998 if(!(tmpbyte
&0x80)){
2001 /* Function must be known */
2002 if(!try_val_to_str(tmpbyte
&0x7f, iscsi_task_management_functions
)){
2005 /* bytes 2,3 must be null */
2006 if(tvb_get_letohs(tvb
,offset
+2)){
2009 /* ahs and dsl must be null */
2010 if(tvb_get_letohl(tvb
,offset
+4)){
2014 case ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE
:
2015 /* top two bits in byte 0 must be 0 */
2016 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2019 /* byte 1 must be 0x80 */
2020 if(tvb_get_uint8(tvb
, offset
+1)!=0x80){
2023 /* response must be 0-6 or 255 */
2024 tmpbyte
=tvb_get_uint8(tvb
,offset
+2);
2025 if(tmpbyte
>6 && tmpbyte
<255){
2028 /* byte 3 must be 0 */
2029 if(tvb_get_uint8(tvb
,offset
+3)){
2032 /* ahs and dsl as well as the 32bit words at offsets 8, 12, 20, 36
2033 * 40, 44 must all be 0
2035 if(tvb_get_letohl(tvb
,offset
+4)
2036 || tvb_get_letohl(tvb
,offset
+8)
2037 || tvb_get_letohl(tvb
,offset
+12)
2038 || tvb_get_letohl(tvb
,offset
+20)
2039 || tvb_get_letohl(tvb
,offset
+36)
2040 || tvb_get_letohl(tvb
,offset
+40)
2041 || tvb_get_letohl(tvb
,offset
+44)){
2045 case ISCSI_OPCODE_LOGOUT_COMMAND
:
2046 /* top bit in byte 0 must be 0 */
2047 if(tvb_get_uint8(tvb
, offset
+0)&0x80){
2050 /* top bit in byte 1 must be set */
2051 tmpbyte
=tvb_get_uint8(tvb
, offset
+1);
2052 if(!(tmpbyte
&0x80)){
2055 /* Reason code must be known */
2056 if(!try_val_to_str(tmpbyte
&0x7f, iscsi_logout_reasons
)){
2059 /* bytes 2,3 must be null */
2060 if(tvb_get_letohs(tvb
,offset
+2)){
2063 /* ahs and dsl as well as the 32bit words at offsets 8, 12, 32, 36
2064 * 40, 44 must all be 0
2066 if(tvb_get_letohl(tvb
,offset
+4)
2067 || tvb_get_letohl(tvb
,offset
+8)
2068 || tvb_get_letohl(tvb
,offset
+12)
2069 || tvb_get_letohl(tvb
,offset
+32)
2070 || tvb_get_letohl(tvb
,offset
+36)
2071 || tvb_get_letohl(tvb
,offset
+40)
2072 || tvb_get_letohl(tvb
,offset
+44)){
2076 case ISCSI_OPCODE_SNACK_REQUEST
:
2077 /* top two bits in byte 0 must be 0 */
2078 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2081 /* top 4 bits in byte 1 must be 0x80 */
2082 tmpbyte
=tvb_get_uint8(tvb
, offset
+1);
2083 if((tmpbyte
&0xf0)!=0x80){
2086 /* type must be known */
2087 if(!try_val_to_str(tmpbyte
&0x0f, iscsi_snack_types
)){
2090 /* for status/snack and datack itt must be 0xffffffff
2091 * for rdata/snack ttt must not be 0 or 0xffffffff
2093 switch(tmpbyte
&0x0f){
2096 if(tvb_get_letohl(tvb
,offset
+16)!=0xffffffff){
2101 if(tvb_get_letohl(tvb
,offset
+20)==0xffffffff){
2104 if(tvb_get_letohl(tvb
,offset
+20)==0){
2109 /* bytes 2,3 must be null */
2110 if(tvb_get_letohs(tvb
,offset
+2)){
2113 /* the 32bit words at offsets 24, 32, 36
2116 if(tvb_get_letohl(tvb
,offset
+24)
2117 || tvb_get_letohl(tvb
,offset
+32)
2118 || tvb_get_letohl(tvb
,offset
+36)){
2123 case ISCSI_OPCODE_R2T
:
2124 /* top two bits in byte 0 must be 0 */
2125 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2128 /* byte 1 must be 0x80 */
2129 if(tvb_get_uint8(tvb
, offset
+1)!=0x80){
2132 /* bytes 2,3 must be null */
2133 if(tvb_get_letohs(tvb
,offset
+2)){
2136 /* ahs and dsl must be null */
2137 if(tvb_get_letohl(tvb
,offset
+4)){
2140 /* desired data transfer length must not be null */
2141 if(!tvb_get_letohl(tvb
,offset
+44)){
2145 case ISCSI_OPCODE_REJECT
:
2146 /* top two bits in byte 0 must be 0 */
2147 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2150 /* byte 1 must be 0x80 */
2151 if(tvb_get_uint8(tvb
, offset
+1)!=0x80){
2154 /* reason must be known */
2155 if(!try_val_to_str(tvb_get_uint8(tvb
,offset
+2), iscsi_reject_reasons
)){
2158 /* byte 3 must be 0 */
2159 if(tvb_get_uint8(tvb
, offset
+3)){
2162 /* the 32bit words at offsets 8, 12, 20, 40, 44
2165 if(tvb_get_letohl(tvb
,offset
+8)
2166 || tvb_get_letohl(tvb
,offset
+12)
2167 || tvb_get_letohl(tvb
,offset
+20)
2168 || tvb_get_letohl(tvb
,offset
+40)
2169 || tvb_get_letohl(tvb
,offset
+44)){
2172 /* the 32bit word at 16 must be 0xffffffff */
2173 if(tvb_get_letohl(tvb
,offset
+16)!=0xffffffff){
2177 case ISCSI_OPCODE_TEXT_COMMAND
:
2178 /* top bit in byte 0 must be 0 */
2179 if(tvb_get_uint8(tvb
, offset
+0)&0x80){
2182 /* one of the F and C bits must be set but not both
2183 * low 6 bits in byte 1 must be 0
2185 switch(tvb_get_uint8(tvb
,offset
+1)){
2192 /* bytes 2,3 must be null */
2193 if(tvb_get_letohs(tvb
,offset
+2)){
2196 /* the 32bit words at offsets 32, 36, 40, 44
2199 if(tvb_get_letohl(tvb
,offset
+32)
2200 || tvb_get_letohl(tvb
,offset
+36)
2201 || tvb_get_letohl(tvb
,offset
+40)
2202 || tvb_get_letohl(tvb
,offset
+44)){
2206 case ISCSI_OPCODE_TEXT_RESPONSE
:
2207 /* top two bits in byte 0 must be 0 */
2208 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2211 /* one of the F and C bits must be set but not both
2212 * low 6 bits in byte 1 must be 0
2214 switch(tvb_get_uint8(tvb
,offset
+1)){
2221 /* bytes 2,3 must be null */
2222 if(tvb_get_letohs(tvb
,offset
+2)){
2225 /* the 32bit words at offsets 36, 40, 44
2228 if(tvb_get_letohl(tvb
,offset
+36)
2229 || tvb_get_letohl(tvb
,offset
+40)
2230 || tvb_get_letohl(tvb
,offset
+44)){
2234 case ISCSI_OPCODE_SCSI_COMMAND
:
2235 /* top bit in byte 0 must be 0 */
2236 if(tvb_get_uint8(tvb
, offset
+0)&0x80){
2239 /* reserved bits in byte 1 must be 0 */
2240 if(tvb_get_uint8(tvb
, offset
+1)&0x18){
2243 /* bytes 2,3 must be null */
2244 if(tvb_get_letohs(tvb
,offset
+2)){
2247 /* if expected data transfer length is set, W and/or R have to be set */
2248 if(tvb_get_ntohl(tvb
,offset
+20)){
2249 if(!(tvb_get_uint8(tvb
, offset
+1)&0x60)){
2254 case ISCSI_OPCODE_SCSI_RESPONSE
:
2255 /* top two bits in byte 0 must be 0 */
2256 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2259 /* top bit in byte 1 must be 1 */
2260 tmpbyte
=tvb_get_uint8(tvb
,offset
+1);
2261 if(!(tmpbyte
&0x80)){
2264 /* the reserved bits in byte 1 must be 0 */
2268 /* status must be known */
2269 if(!try_val_to_str(tvb_get_uint8(tvb
,offset
+3), scsi_status_val
)){
2272 /* the 32bit words at offsets 8, 12
2275 if(tvb_get_letohl(tvb
,offset
+8)
2276 || tvb_get_letohl(tvb
,offset
+12)){
2280 case ISCSI_OPCODE_ASYNC_MESSAGE
:
2281 /* top two bits in byte 0 must be 0 */
2282 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2285 /* byte 1 must be 0x80 */
2286 if(tvb_get_uint8(tvb
, offset
+1)!=0x80){
2289 /* bytes 2,3 must be null */
2290 if(tvb_get_letohs(tvb
,offset
+2)){
2293 /* the 32bit words at offsets 20, 44
2296 if(tvb_get_letohl(tvb
,offset
+20)
2297 || tvb_get_letohl(tvb
,offset
+44)){
2300 /* the 32bit word at 16 must be 0xffffffff */
2301 if(tvb_get_letohl(tvb
,offset
+16)!=0xffffffff){
2305 case ISCSI_OPCODE_LOGOUT_RESPONSE
:
2306 /* top two bits in byte 0 must be 0 */
2307 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2310 /* byte 1 must be 0x80 */
2311 if(tvb_get_uint8(tvb
, offset
+1)!=0x80){
2314 /* response must be known */
2315 if(!try_val_to_str(tvb_get_uint8(tvb
,offset
+2), iscsi_logout_response
)){
2318 /* byte 3 must be 0 */
2319 if(tvb_get_uint8(tvb
,offset
+3)){
2322 /* ahs and dsl as well as the 32bit words at offsets 8, 12, 20, 36
2325 if(tvb_get_letohl(tvb
,offset
+4)
2326 || tvb_get_letohl(tvb
,offset
+8)
2327 || tvb_get_letohl(tvb
,offset
+12)
2328 || tvb_get_letohl(tvb
,offset
+20)
2329 || tvb_get_letohl(tvb
,offset
+36)
2330 || tvb_get_letohl(tvb
,offset
+44)){
2334 case ISCSI_OPCODE_SCSI_DATA_OUT
:
2335 /* top two bits in byte 0 must be 0 */
2336 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2339 /* low 7 bits in byte 1 must be 0 */
2340 if(tvb_get_uint8(tvb
,offset
+1)&0x7f){
2343 /* bytes 2,3 must be null */
2344 if(tvb_get_letohs(tvb
,offset
+2)){
2347 /* the 32bit words at offsets 24, 32, 44
2350 if(tvb_get_letohl(tvb
,offset
+24)
2351 || tvb_get_letohl(tvb
,offset
+32)
2352 || tvb_get_letohl(tvb
,offset
+44)){
2356 case ISCSI_OPCODE_SCSI_DATA_IN
:
2357 /* top two bits in byte 0 must be 0 */
2358 if(tvb_get_uint8(tvb
, offset
+0)&0xc0){
2361 /* reserved bits in byte 1 must be 0 */
2362 if(tvb_get_uint8(tvb
,offset
+1)&0x38){
2365 /* byte 2 must be reserved */
2366 if(tvb_get_uint8(tvb
,offset
+2)){
2370 case ISCSI_OPCODE_VENDOR_SPECIFIC_I0
:
2371 case ISCSI_OPCODE_VENDOR_SPECIFIC_I1
:
2372 case ISCSI_OPCODE_VENDOR_SPECIFIC_I2
:
2373 case ISCSI_OPCODE_VENDOR_SPECIFIC_T0
:
2374 case ISCSI_OPCODE_VENDOR_SPECIFIC_T1
:
2375 case ISCSI_OPCODE_VENDOR_SPECIFIC_T2
:
2379 } /* end of heuristics check */
2382 /* process multiple iSCSI PDUs per packet */
2383 while(available_bytes
>= 48 || (iscsi_desegment
&& available_bytes
>= 8)) {
2384 uint32_t data_segment_len
;
2385 uint32_t pduLen
= 48;
2386 uint8_t secondPduByte
= tvb_get_uint8(tvb
, offset
+ 1);
2387 bool badPdu
= false;
2389 uint32_t data_segment_offset
, data_segment_len_padded
;
2391 /* mask out any extra bits in the opcode byte */
2392 opcode
= tvb_get_uint8(tvb
, offset
+ 0);
2393 opcode
&= OPCODE_MASK
;
2395 if(opcode
== ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION
||
2396 opcode
== ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE
||
2397 opcode
== ISCSI_OPCODE_R2T
||
2398 opcode
== ISCSI_OPCODE_LOGOUT_COMMAND
||
2399 opcode
== ISCSI_OPCODE_LOGOUT_RESPONSE
||
2400 opcode
== ISCSI_OPCODE_SNACK_REQUEST
)
2401 data_segment_len
= 0;
2403 data_segment_len
= tvb_get_ntohl(tvb
, offset
+ 4) & 0x00ffffff;
2405 if (!try_val_to_str(opcode
, iscsi_opcodes
)) {
2410 if(!badPdu
&& check_port
) {
2412 if ((opcode
& TARGET_OPCODE_BIT
) && value_is_in_range(global_iscsi_port_range
, pinfo
->srcport
)) {
2415 if (!(opcode
& TARGET_OPCODE_BIT
) && value_is_in_range(global_iscsi_port_range
, pinfo
->destport
)) {
2418 if ((opcode
& TARGET_OPCODE_BIT
) && pinfo
->srcport
== iscsi_system_port
) {
2421 if (!(opcode
& TARGET_OPCODE_BIT
) && pinfo
->destport
== iscsi_system_port
) {
2426 if(!badPdu
&& enable_bogosity_filter
) {
2427 /* try and distinguish between data and real headers */
2428 if(data_segment_len
> bogus_pdu_data_length_threshold
) {
2431 else if(demand_good_f_bit
&&
2432 !(secondPduByte
& 0x80) &&
2433 (opcode
== ISCSI_OPCODE_NOP_OUT
||
2434 opcode
== ISCSI_OPCODE_NOP_IN
||
2435 opcode
== ISCSI_OPCODE_LOGOUT_COMMAND
||
2436 opcode
== ISCSI_OPCODE_LOGOUT_RESPONSE
||
2437 opcode
== ISCSI_OPCODE_SCSI_RESPONSE
||
2438 opcode
== ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE
||
2439 opcode
== ISCSI_OPCODE_R2T
||
2440 opcode
== ISCSI_OPCODE_ASYNC_MESSAGE
||
2441 opcode
== ISCSI_OPCODE_SNACK_REQUEST
||
2442 opcode
== ISCSI_OPCODE_REJECT
)) {
2444 } else if(opcode
==ISCSI_OPCODE_NOP_OUT
) {
2445 /* TransferTag for NOP-Out should either be -1 or
2446 the tag value we want for a response.
2447 Assume 0 means we are just inside a big all zero
2450 if(tvb_get_ntohl(tvb
, offset
+20)==0){
2460 if(opcode
== ISCSI_OPCODE_LOGIN_COMMAND
||
2461 opcode
== ISCSI_OPCODE_LOGIN_RESPONSE
) {
2462 if(iscsi_protocol_version
== ISCSI_PROTOCOL_DRAFT08
) {
2463 if((secondPduByte
& CSG_MASK
) < ISCSI_CSG_OPERATIONAL_NEGOTIATION
) {
2464 /* digests are not yet turned on */
2472 if(opcode
== ISCSI_OPCODE_SCSI_COMMAND
) {
2474 ahsLen
= tvb_get_uint8(tvb
, offset
+ 4);
2475 pduLen
+= ahsLen
* 4;
2478 data_segment_offset
= pduLen
;
2479 data_segment_len_padded
= data_segment_len
;
2480 if((data_segment_len_padded
& 3) != 0)
2481 data_segment_len_padded
+= 4 - (data_segment_len_padded
& 3);
2482 pduLen
+= data_segment_len_padded
;
2485 /* make sure we have a conversation for this session */
2486 conversation
= find_or_create_conversation(pinfo
);
2488 iscsi_session
=(iscsi_session_t
*)conversation_get_proto_data(conversation
, proto_iscsi
);
2490 iscsi_session
= wmem_new(wmem_file_scope(), iscsi_session_t
);
2491 iscsi_session
->header_digest
= ISCSI_DIGEST_AUTO
;
2492 iscsi_session
->data_digest
= ISCSI_DIGEST_AUTO
;
2493 iscsi_session
->itlq
= wmem_tree_new(wmem_file_scope());
2494 iscsi_session
->itl
= wmem_map_new(wmem_file_scope(), g_direct_hash
, g_direct_equal
);
2495 conversation_add_proto_data(conversation
, proto_iscsi
, iscsi_session
);
2497 /* DataOut PDUs are often mistaken by DCERPC heuristics to be
2498 * that protocol. Now that we know this is iscsi, set a
2499 * dissector for this conversation to block other heuristic
2502 conversation_set_dissector(conversation
, iscsi_handle
);
2504 /* try to autodetect if header digest is used or not */
2505 if (digestsActive
&& (available_bytes
>= (uint32_t) (48+4+ahsLen
*4)) &&
2506 (iscsi_session
->header_digest
== ISCSI_DIGEST_AUTO
)) {
2508 /* we have enough data to test if HeaderDigest is enabled */
2509 crc
= ~crc32c_tvb_offset_calculate(tvb
, offset
, 48+ahsLen
*4, CRC32C_PRELOAD
);
2510 if(crc
==tvb_get_ntohl(tvb
,48+ahsLen
*4)){
2511 iscsi_session
->header_digest
= ISCSI_DIGEST_CRC32
;
2513 iscsi_session
->header_digest
= ISCSI_DIGEST_NONE
;
2518 /* Add header digest length to pdulen */
2520 switch(iscsi_session
->header_digest
){
2521 case ISCSI_DIGEST_CRC32
:
2523 data_segment_offset
+= 4;
2525 case ISCSI_DIGEST_NONE
:
2527 case ISCSI_DIGEST_AUTO
:
2528 /* oops we don't yet know what digest is used */
2529 /* here we should use some default */
2532 DISSECTOR_ASSERT_NOT_REACHED();
2536 /* try to autodetect whether data digest is used */
2537 if (digestsActive
&&
2538 (available_bytes
>= data_segment_offset
+ data_segment_len_padded
+ 4) &&
2539 (iscsi_session
->data_digest
== ISCSI_DIGEST_AUTO
)) {
2541 /* we have enough data to test if DataDigest is enabled */
2542 crc
= ~crc32c_tvb_offset_calculate(tvb
, data_segment_offset
, data_segment_len_padded
, CRC32C_PRELOAD
);
2543 if (crc
== tvb_get_ntohl(tvb
, data_segment_offset
+ data_segment_len_padded
)) {
2544 iscsi_session
->data_digest
= ISCSI_DIGEST_CRC32
;
2546 iscsi_session
->data_digest
= ISCSI_DIGEST_NONE
;
2550 /* Add data digest length to pdulen */
2551 if (digestsActive
&& data_segment_len
> 0) {
2552 switch (iscsi_session
->data_digest
) {
2553 case ISCSI_DIGEST_CRC32
:
2556 case ISCSI_DIGEST_NONE
:
2558 case ISCSI_DIGEST_AUTO
:
2559 /* unknown digest, perhaps a new field was introduced? */
2562 DISSECTOR_ASSERT_NOT_REACHED();
2567 * Desegmentation check.
2569 if(iscsi_desegment
&& pinfo
->can_desegment
) {
2570 if(pduLen
> available_bytes
) {
2572 * This frame doesn't have all of the data for
2573 * this message, but we can do reassembly on it.
2575 * Tell the TCP dissector where the data for this
2576 * message starts in the data it handed us, and
2577 * how many more bytes we need, and return.
2579 pinfo
->desegment_offset
= offset
;
2580 pinfo
->desegment_len
= pduLen
- available_bytes
;
2585 /* This is to help TCP keep track of PDU boundaries
2586 and allows it to find PDUs that are not aligned to
2587 the start of a TCP segments.
2588 Since it also allows TCP to know what is in the middle
2589 of a large PDU, it reduces the probability of a segment
2590 in the middle of a large PDU transfer being misdissected as
2593 if(!pinfo
->fd
->visited
){
2594 if(pduLen
>(uint32_t)tvb_reported_length_remaining(tvb
, offset
)){
2595 pinfo
->want_pdu_tracking
=2;
2596 pinfo
->bytes_until_next_pdu
=pduLen
-tvb_reported_length_remaining(tvb
, offset
);
2601 col_clear(pinfo
->cinfo
, COL_INFO
);
2603 col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
2605 dissect_iscsi_pdu(tvb
, pinfo
, tree
, offset
, opcode
, data_segment_len
, iscsi_session
, conversation
);
2606 if(pduLen
> available_bytes
)
2607 pduLen
= available_bytes
;
2609 available_bytes
-= pduLen
;
2615 /* This is called for those sessions where we have explicitly said
2616 this to be iSCSI using "Decode As..."
2617 In this case we will not check the port number for sanity and just
2618 do as the user said.
2619 We still check that the PDU header looks sane though.
2622 dissect_iscsi_handle(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
2623 return dissect_iscsi(tvb
, pinfo
, tree
, false);
2626 /* This is called through the heuristic handler.
2627 In this case we also want to check that the port matches the preference
2628 setting for iSCSI in order to reduce the number of
2632 dissect_iscsi_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
2633 uint32_t available_bytes
= tvb_captured_length(tvb
);
2635 /* quick check to see if the packet is long enough to contain the
2636 * minimum amount of information we need */
2637 if (available_bytes
< 48 ){
2638 /* no, so give up */
2642 return dissect_iscsi(tvb
, pinfo
, tree
, true) != 0;
2646 /* Register the protocol with Wireshark */
2649 * this format is require because a script is used to build the C
2650 * function that calls all the protocol registration.
2654 proto_register_iscsi(void)
2656 module_t
*iscsi_module
;
2657 expert_module_t
* expert_iscsi
;
2659 /* Setup list of header fields See Section 1.6.1 for details*/
2660 static hf_register_info hf
[] = {
2661 { &hf_iscsi_request_frame
,
2662 { "Request in", "iscsi.request_frame",
2663 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0,
2664 "Frame number of the request", HFILL
}},
2667 { "Time from request", "iscsi.time",
2668 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0,
2669 "Time between the Command and the Response", HFILL
}},
2671 { &hf_iscsi_r2t_frame
,
2672 { "Ready To Transfer", "iscsi.r2t_frame",
2673 FT_FRAMENUM
, BASE_NONE
, NULL
, 0,
2674 "Frame number of the R2T", HFILL
}},
2676 { &hf_iscsi_r2t_time
,
2677 { "Time from request to R2T", "iscsi.r2t_time",
2678 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0,
2679 "Time from the client's request to the server's R2T", HFILL
}},
2681 { &hf_iscsi_data_in_frame
,
2682 { "Data In in", "iscsi.data_in_frame",
2683 FT_FRAMENUM
, BASE_NONE
, NULL
, 0,
2684 "Frame number of the final Data In (could be multiple)", HFILL
}},
2686 { &hf_iscsi_data_out_frame
,
2687 { "Final Data Out in", "iscsi.data_out_frame",
2688 FT_FRAMENUM
, BASE_NONE
, NULL
, 0,
2689 "Frame number of the final Data Out (could be multiple)", HFILL
}},
2691 { &hf_iscsi_response_frame
,
2692 { "Response in", "iscsi.response_frame",
2693 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0,
2694 "Frame number of the response", HFILL
}},
2695 { &hf_iscsi_AHS_length
,
2696 { "AHS Length", "iscsi.ahs.length",
2697 FT_UINT16
, BASE_DEC
, NULL
, 0,
2698 "Length of Additional header segment", HFILL
}
2700 { &hf_iscsi_AHS_read_data_length
,
2701 { "Bidirectional Read Data Length", "iscsi.ahs.bidir.length",
2702 FT_UINT32
, BASE_DEC
, NULL
, 0,
2705 { &hf_iscsi_AHS_type
,
2706 { "AHS Type", "iscsi.ahs.type",
2707 FT_UINT8
, BASE_DEC
, VALS(ahs_type_vals
), 0,
2708 "Type of Additional header segment", HFILL
}
2710 { &hf_iscsi_AHS_extended_cdb
,
2711 { "AHS Extended CDB", "iscsi.ahs.extended_cdb",
2712 FT_BYTES
, BASE_NONE
, NULL
, 0,
2715 { &hf_iscsi_AHS_blob
,
2716 { "Unknown AHS blob", "iscsi.ahs.unknown_blob",
2717 FT_BYTES
, BASE_NONE
, NULL
, 0,
2720 { &hf_iscsi_Padding
,
2721 { "Padding", "iscsi.padding",
2722 FT_BYTES
, BASE_NONE
, NULL
, 0,
2723 "Padding to 4 byte boundary", HFILL
}
2725 { &hf_iscsi_ping_data
,
2726 { "PingData", "iscsi.pingdata",
2727 FT_BYTES
, BASE_NONE
, NULL
, 0,
2728 "Ping Data", HFILL
}
2730 { &hf_iscsi_immediate_data
,
2731 { "ImmediateData", "iscsi.immediatedata",
2732 FT_BYTES
, BASE_NONE
, NULL
, 0,
2733 "Immediate Data", HFILL
}
2735 { &hf_iscsi_async_event_data
,
2736 { "AsyncEventData", "iscsi.asynceventdata",
2737 FT_BYTES
, BASE_NONE
, NULL
, 0,
2738 "Async Event Data", HFILL
}
2740 { &hf_iscsi_vendor_specific_data
,
2741 { "VendorSpecificData", "iscsi.vendorspecificdata",
2742 FT_BYTES
, BASE_NONE
, NULL
, 0,
2743 "Vendor Specific Data", HFILL
}
2745 { &hf_iscsi_HeaderDigest32
,
2746 { "HeaderDigest", "iscsi.headerdigest32",
2747 FT_UINT32
, BASE_HEX
, NULL
, 0,
2748 "Header Digest", HFILL
}
2750 { &hf_iscsi_DataDigest32
,
2751 { "DataDigest", "iscsi.datadigest32",
2752 FT_UINT32
, BASE_HEX
, NULL
, 0,
2753 "Data Digest", HFILL
}
2756 { "Opcode", "iscsi.opcode",
2757 FT_UINT8
, BASE_HEX
, VALS(iscsi_opcodes
), OPCODE_MASK
,
2760 /* #ifdef DRAFT08 */
2763 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_X
), 0x80,
2764 "Command Retry", HFILL
}
2769 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_I
), 0x40,
2770 "Immediate delivery", HFILL
}
2773 { "Flags", "iscsi.flags",
2774 FT_UINT8
, BASE_HEX
, NULL
, 0,
2775 "Opcode specific flags", HFILL
}
2777 { &hf_iscsi_SCSICommand_F
,
2778 { "F", "iscsi.scsicommand.F",
2779 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_F
), 0x80,
2780 "PDU completes command", HFILL
}
2782 { &hf_iscsi_SCSICommand_R
,
2783 { "R", "iscsi.scsicommand.R",
2784 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_R
), 0x40,
2785 "Command reads from SCSI target", HFILL
}
2787 { &hf_iscsi_SCSICommand_W
,
2788 { "W", "iscsi.scsicommand.W",
2789 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_W
), 0x20,
2790 "Command writes to SCSI target", HFILL
}
2792 { &hf_iscsi_SCSICommand_Attr
,
2793 { "Attr", "iscsi.scsicommand.attr",
2794 FT_UINT8
, BASE_HEX
, VALS(iscsi_scsicommand_taskattrs
), 0x07,
2795 "SCSI task attributes", HFILL
}
2797 { &hf_iscsi_SCSICommand_CRN
,
2798 { "CRN", "iscsi.scsicommand.crn",
2799 FT_UINT8
, BASE_HEX
, NULL
, 0,
2800 "SCSI command reference number", HFILL
}
2802 { &hf_iscsi_DataSegmentLength
,
2803 { "DataSegmentLength", "iscsi.datasegmentlength",
2804 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2805 "Data segment length (bytes)", HFILL
}
2807 { &hf_iscsi_TotalAHSLength
,
2808 { "TotalAHSLength", "iscsi.totalahslength",
2809 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0,
2810 "Total additional header segment length (4 byte words)", HFILL
}
2812 { &hf_iscsi_InitiatorTaskTag
,
2813 { "InitiatorTaskTag", "iscsi.initiatortasktag",
2814 FT_UINT32
, BASE_HEX
, NULL
, 0,
2815 "Initiator's task tag", HFILL
}
2817 { &hf_iscsi_ExpectedDataTransferLength
,
2818 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
2819 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2820 "Expected length of data transfer", HFILL
}
2823 { "CmdSN", "iscsi.cmdsn",
2824 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2825 "Sequence number for this command", HFILL
}
2827 { &hf_iscsi_ExpStatSN
,
2828 { "ExpStatSN", "iscsi.expstatsn",
2829 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2830 "Next expected status sequence number", HFILL
}
2832 { &hf_iscsi_SCSIResponse_ResidualCount
,
2833 { "ResidualCount", "iscsi.scsiresponse.residualcount",
2834 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2835 "Residual count", HFILL
}
2838 { "StatSN", "iscsi.statsn",
2839 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2840 "Status sequence number", HFILL
}
2842 { &hf_iscsi_ExpCmdSN
,
2843 { "ExpCmdSN", "iscsi.expcmdsn",
2844 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2845 "Next expected command sequence number", HFILL
}
2847 { &hf_iscsi_MaxCmdSN
,
2848 { "MaxCmdSN", "iscsi.maxcmdsn",
2849 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2850 "Maximum acceptable command sequence number", HFILL
}
2852 { &hf_iscsi_SCSIResponse_o
,
2853 { "o", "iscsi.scsiresponse.o",
2854 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_o
), 0x10,
2855 "Bi-directional read residual overflow", HFILL
}
2857 { &hf_iscsi_SCSIResponse_u
,
2858 { "u", "iscsi.scsiresponse.u",
2859 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_u
), 0x08,
2860 "Bi-directional read residual underflow", HFILL
}
2862 { &hf_iscsi_SCSIResponse_O
,
2863 { "O", "iscsi.scsiresponse.O",
2864 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_O
), 0x04,
2865 "Residual overflow", HFILL
}
2867 { &hf_iscsi_SCSIResponse_U
,
2868 { "U", "iscsi.scsiresponse.U",
2869 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_U
), 0x02,
2870 "Residual underflow", HFILL
}
2872 { &hf_iscsi_SCSIResponse_Status
,
2873 { "Status", "iscsi.scsiresponse.status",
2874 FT_UINT8
, BASE_HEX
, VALS(scsi_status_val
), 0,
2875 "SCSI command status value", HFILL
}
2877 { &hf_iscsi_SCSIResponse_Response
,
2878 { "Response", "iscsi.scsiresponse.response",
2879 FT_UINT8
, BASE_HEX
, VALS(iscsi_scsi_responses
), 0,
2880 "SCSI command response value", HFILL
}
2882 { &hf_iscsi_SCSIResponse_BidiReadResidualCount
,
2883 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
2884 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2885 "Bi-directional read residual count", HFILL
}
2887 { &hf_iscsi_SenseLength
,
2888 { "SenseLength", "iscsi.scsiresponse.senselength",
2889 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0,
2890 "Sense data length", HFILL
}
2892 { &hf_iscsi_SCSIData_F
,
2893 { "F", "iscsi.scsidata.F",
2894 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_F
), ISCSI_SCSI_DATA_FLAG_F
,
2895 "Final PDU", HFILL
}
2897 { &hf_iscsi_SCSIData_A
,
2898 { "A", "iscsi.scsidata.A",
2899 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_A
), ISCSI_SCSI_DATA_FLAG_A
,
2900 "Acknowledge Requested", HFILL
}
2902 { &hf_iscsi_SCSIData_S
,
2903 { "S", "iscsi.scsidata.S",
2904 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_S
), ISCSI_SCSI_DATA_FLAG_S
,
2905 "PDU Contains SCSI command status", HFILL
}
2907 { &hf_iscsi_SCSIData_U
,
2908 { "U", "iscsi.scsidata.U",
2909 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_U
), ISCSI_SCSI_DATA_FLAG_U
,
2910 "Residual underflow", HFILL
}
2912 { &hf_iscsi_SCSIData_O
,
2913 { "O", "iscsi.scsidata.O",
2914 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_O
), ISCSI_SCSI_DATA_FLAG_O
,
2915 "Residual overflow", HFILL
}
2917 { &hf_iscsi_TargetTransferTag
,
2918 { "TargetTransferTag", "iscsi.targettransfertag",
2919 FT_UINT32
, BASE_HEX
, NULL
, 0,
2920 "Target transfer tag", HFILL
}
2922 { &hf_iscsi_BufferOffset
,
2923 { "BufferOffset", "iscsi.bufferOffset",
2924 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2925 "Buffer offset", HFILL
}
2927 { &hf_iscsi_SCSIData_ResidualCount
,
2928 { "ResidualCount", "iscsi.scsidata.readresidualcount",
2929 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2930 "Residual count", HFILL
}
2933 { "DataSN", "iscsi.datasn",
2934 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
2935 "Data sequence number", HFILL
}
2937 { &hf_iscsi_VersionMax
,
2938 { "VersionMax", "iscsi.versionmax",
2939 FT_UINT8
, BASE_HEX
, NULL
, 0,
2940 "Maximum supported protocol version", HFILL
}
2942 { &hf_iscsi_VersionMin
,
2943 { "VersionMin", "iscsi.versionmin",
2944 FT_UINT8
, BASE_HEX
, NULL
, 0,
2945 "Minimum supported protocol version", HFILL
}
2947 { &hf_iscsi_VersionActive
,
2948 { "VersionActive", "iscsi.versionactive",
2949 FT_UINT8
, BASE_HEX
, NULL
, 0,
2950 "Negotiated protocol version", HFILL
}
2953 { "CID", "iscsi.cid",
2954 FT_UINT16
, BASE_HEX
, NULL
, 0,
2955 "Connection identifier", HFILL
}
2957 /* #ifdef DRAFT08 */
2959 { "ISID", "iscsi.isid8",
2960 FT_UINT16
, BASE_HEX
, NULL
, 0,
2961 "Initiator part of session identifier", HFILL
}
2965 { "ISID", "iscsi.isid",
2966 FT_BYTES
, BASE_NONE
, NULL
, 0,
2967 "Initiator part of session identifier", HFILL
}
2969 /* #ifdef DRAFT09 */
2970 { &hf_iscsi_ISID_Type
,
2971 { "ISID_Type", "iscsi.isid.type",
2972 FT_UINT8
, BASE_HEX
, VALS(iscsi_isid_type
), 0,
2973 "Initiator part of session identifier - type", HFILL
}
2975 { &hf_iscsi_ISID_NamingAuthority
,
2976 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
2977 FT_UINT24
, BASE_HEX
, NULL
, 0,
2978 "Initiator part of session identifier - naming authority", HFILL
}
2980 { &hf_iscsi_ISID_Qualifier
,
2981 { "ISID_Qualifier", "iscsi.isid.qualifier",
2982 FT_UINT16
, BASE_HEX
, NULL
, 0,
2983 "Initiator part of session identifier - qualifier", HFILL
}
2987 { "ISID_t", "iscsi.isid.t",
2988 FT_UINT8
, BASE_HEX
, VALS(iscsi_isid_type
), 0xc0,
2989 "Initiator part of session identifier - t", HFILL
}
2992 { "ISID_a", "iscsi.isid.a",
2993 FT_UINT8
, BASE_HEX
, NULL
, 0x3f,
2994 "Initiator part of session identifier - a", HFILL
}
2997 { "ISID_b", "iscsi.isid.b",
2998 FT_UINT16
, BASE_HEX
, NULL
, 0,
2999 "Initiator part of session identifier - b", HFILL
}
3002 { "ISID_c", "iscsi.isid.c",
3003 FT_UINT8
, BASE_HEX
, NULL
, 0,
3004 "Initiator part of session identifier - c", HFILL
}
3007 { "ISID_d", "iscsi.isid.d",
3008 FT_UINT16
, BASE_HEX
, NULL
, 0,
3009 "Initiator part of session identifier - d", HFILL
}
3014 { "TSID", "iscsi.tsid",
3015 FT_UINT16
, BASE_HEX
, NULL
, 0,
3016 "Target part of session identifier", HFILL
}
3019 { "TSIH", "iscsi.tsih",
3020 FT_UINT16
, BASE_HEX
, NULL
, 0,
3021 "Target session identifying handle", HFILL
}
3023 { &hf_iscsi_Login_T
,
3024 { "T", "iscsi.login.T",
3025 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_T
), 0x80,
3026 "Transit to next login stage", HFILL
}
3028 { &hf_iscsi_Login_C
,
3029 { "C", "iscsi.login.C",
3030 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_C
), 0x40,
3031 "Text incomplete", HFILL
}
3033 /* #ifdef DRAFT09 */
3034 { &hf_iscsi_Login_X
,
3035 { "X", "iscsi.login.X",
3036 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_login_X
), 0x40,
3037 "Restart Connection", HFILL
}
3040 { &hf_iscsi_Login_CSG
,
3041 { "CSG", "iscsi.login.csg",
3042 FT_UINT8
, BASE_HEX
, VALS(iscsi_login_stage
), CSG_MASK
,
3043 "Current stage", HFILL
}
3045 { &hf_iscsi_Login_NSG
,
3046 { "NSG", "iscsi.login.nsg",
3047 FT_UINT8
, BASE_HEX
, VALS(iscsi_login_stage
), NSG_MASK
,
3048 "Next stage", HFILL
}
3050 { &hf_iscsi_Login_Status
,
3051 { "Status", "iscsi.login.status",
3052 FT_UINT16
, BASE_HEX
, VALS(iscsi_login_status
), 0,
3053 "Status class and detail", HFILL
}
3055 { &hf_iscsi_KeyValue
,
3056 { "KeyValue", "iscsi.keyvalue",
3057 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
3058 "Key/value pair", HFILL
}
3061 { "F", "iscsi.text.F",
3062 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_F
), 0x80,
3063 "Final PDU in text sequence", HFILL
}
3066 { "C", "iscsi.text.C",
3067 FT_BOOLEAN
, 8, TFS(&iscsi_meaning_C
), 0x40,
3068 "Text incomplete", HFILL
}
3070 { &hf_iscsi_ExpDataSN
,
3071 { "ExpDataSN", "iscsi.expdatasn",
3072 FT_UINT32
, BASE_HEX
, NULL
, 0,
3073 "Next expected data sequence number", HFILL
}
3076 { "R2TSN", "iscsi.r2tsn",
3077 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
3078 "R2T PDU Number", HFILL
}
3080 { &hf_iscsi_TaskManagementFunction_Response
,
3081 { "Response", "iscsi.taskmanfun.response",
3082 FT_UINT8
, BASE_HEX
, VALS(iscsi_task_management_responses
), 0,
3085 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag
,
3086 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
3087 FT_UINT32
, BASE_HEX
, NULL
, 0,
3088 "Referenced task tag", HFILL
}
3090 { &hf_iscsi_RefCmdSN
,
3091 { "RefCmdSN", "iscsi.refcmdsn",
3092 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
3093 "Command sequence number for command to be aborted", HFILL
}
3095 { &hf_iscsi_TaskManagementFunction_Function
,
3096 { "Function", "iscsi.taskmanfun.function",
3097 FT_UINT8
, BASE_HEX
, VALS(iscsi_task_management_functions
), 0x7F,
3098 "Requested task function", HFILL
}
3100 { &hf_iscsi_Logout_Reason
,
3101 { "Reason", "iscsi.logout.reason",
3102 FT_UINT8
, BASE_HEX
, VALS(iscsi_logout_reasons
), 0x7F,
3103 "Reason for logout", HFILL
}
3105 { &hf_iscsi_Logout_Response
,
3106 { "Response", "iscsi.logout.response",
3107 FT_UINT8
, BASE_HEX
, VALS(iscsi_logout_response
), 0,
3108 "Logout response", HFILL
}
3110 { &hf_iscsi_Time2Wait
,
3111 { "Time2Wait", "iscsi.time2wait",
3112 FT_UINT16
, BASE_HEX
, NULL
, 0,
3115 { &hf_iscsi_Time2Retain
,
3116 { "Time2Retain", "iscsi.time2retain",
3117 FT_UINT16
, BASE_HEX
, NULL
, 0,
3120 { &hf_iscsi_DesiredDataLength
,
3121 { "DesiredDataLength", "iscsi.desireddatalength",
3122 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
3123 "Desired data length (bytes)", HFILL
}
3125 { &hf_iscsi_AsyncEvent
,
3126 { "AsyncEvent", "iscsi.asyncevent",
3127 FT_UINT8
, BASE_HEX
, VALS(iscsi_asyncevents
), 0,
3128 "Async event type", HFILL
}
3130 { &hf_iscsi_EventVendorCode
,
3131 { "EventVendorCode", "iscsi.eventvendorcode",
3132 FT_UINT8
, BASE_HEX
, NULL
, 0,
3133 "Event vendor code", HFILL
}
3135 { &hf_iscsi_Parameter1
,
3136 { "Parameter1", "iscsi.parameter1",
3137 FT_UINT16
, BASE_HEX
, NULL
, 0,
3138 "Parameter 1", HFILL
}
3140 { &hf_iscsi_Parameter2
,
3141 { "Parameter2", "iscsi.parameter2",
3142 FT_UINT16
, BASE_HEX
, NULL
, 0,
3143 "Parameter 2", HFILL
}
3145 { &hf_iscsi_Parameter3
,
3146 { "Parameter3", "iscsi.parameter3",
3147 FT_UINT16
, BASE_HEX
, NULL
, 0,
3148 "Parameter 3", HFILL
}
3150 { &hf_iscsi_Reject_Reason
,
3151 { "Reason", "iscsi.reject.reason",
3152 FT_UINT8
, BASE_HEX
, VALS(iscsi_reject_reasons
), 0,
3153 "Reason for command rejection", HFILL
}
3155 { &hf_iscsi_snack_type
,
3156 { "S", "iscsi.snack.type",
3157 FT_UINT8
, BASE_DEC
, VALS(iscsi_snack_types
), 0x0f,
3158 "Type of SNACK requested", HFILL
}
3161 { "BegRun", "iscsi.snack.begrun",
3162 FT_UINT32
, BASE_HEX
, NULL
, 0,
3163 "First missed DataSN or StatSN", HFILL
}
3165 { &hf_iscsi_RunLength
,
3166 { "RunLength", "iscsi.snack.runlength",
3167 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0,
3168 "Number of additional missing status PDUs in this run", HFILL
}
3172 /* Setup protocol subtree array */
3173 static int *ett
[] = {
3175 &ett_iscsi_KeyValues
,
3178 &ett_iscsi_RejectHeader
,
3180 /* #ifndef DRAFT08 */
3185 static ei_register_info ei
[] = {
3186 { &ei_iscsi_keyvalue_invalid
, { "iscsi.keyvalue.invalid", PI_MALFORMED
, PI_ERROR
,
3187 "Invalid key/value pair", EXPFILL
}},
3188 { &ei_iscsi_opcode_invalid
, { "iscsi.opcode.invalid", PI_MALFORMED
, PI_ERROR
,
3189 "Invalid opcode", EXPFILL
}},
3192 /* Register the protocol name and description */
3193 proto_iscsi
= proto_register_protocol("iSCSI", "iSCSI", "iscsi");
3194 iscsi_handle
= register_dissector("iscsi", dissect_iscsi_handle
, proto_iscsi
);
3196 /* Required function calls to register the header fields and
3198 proto_register_field_array(proto_iscsi
, hf
, array_length(hf
));
3199 proto_register_subtree_array(ett
, array_length(ett
));
3201 iscsi_module
= prefs_register_protocol(proto_iscsi
, NULL
);
3203 prefs_register_enum_preference(iscsi_module
,
3206 "The iSCSI protocol version",
3207 &iscsi_protocol_version
,
3208 iscsi_protocol_versions
,
3211 prefs_register_bool_preference(iscsi_module
,
3212 "desegment_iscsi_messages",
3213 "Reassemble iSCSI messages spanning multiple TCP segments",
3214 "Whether the iSCSI dissector should reassemble messages spanning multiple TCP segments."
3215 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3218 prefs_register_bool_preference(iscsi_module
,
3220 "Enable bogus pdu filter",
3221 "When enabled, packets that appear bogus are ignored",
3222 &enable_bogosity_filter
);
3224 prefs_register_bool_preference(iscsi_module
,
3225 "demand_good_f_bit",
3226 "Ignore packets with bad F bit",
3227 "Ignore packets that haven't set the F bit when they should have",
3228 &demand_good_f_bit
);
3230 prefs_register_uint_preference(iscsi_module
,
3231 "bogus_pdu_max_data_len",
3232 "Bogus pdu max data length threshold",
3233 "Treat packets whose data segment length is greater than this value as bogus",
3235 &bogus_pdu_data_length_threshold
);
3237 range_convert_str(wmem_epan_scope(), &global_iscsi_port_range
, TCP_PORT_ISCSI_RANGE
, MAX_TCP_PORT
);
3238 prefs_register_range_preference(iscsi_module
,
3240 "Target Ports Range",
3241 "Range of iSCSI target ports"
3242 "(default " TCP_PORT_ISCSI_RANGE
")",
3243 &global_iscsi_port_range
, MAX_TCP_PORT
);
3245 prefs_register_uint_preference(iscsi_module
,
3246 "target_system_port",
3247 "Target system port",
3248 "System port number of iSCSI target",
3250 &iscsi_system_port
);
3252 /* Preference supported in older versions.
3253 Register them as obsolete. */
3254 prefs_register_obsolete_preference(iscsi_module
,
3255 "version_03_compatible");
3256 prefs_register_obsolete_preference(iscsi_module
,
3257 "bogus_pdu_max_digest_padding");
3258 prefs_register_obsolete_preference(iscsi_module
,
3259 "header_digest_is_crc32c");
3260 prefs_register_obsolete_preference(iscsi_module
,
3261 "header_digest_size");
3262 prefs_register_obsolete_preference(iscsi_module
,
3263 "enable_header_digests");
3264 prefs_register_obsolete_preference(iscsi_module
,
3265 "data_digest_is_crc32c");
3266 prefs_register_obsolete_preference(iscsi_module
,
3267 "data_digest_size");
3268 prefs_register_obsolete_preference(iscsi_module
,
3269 "enable_data_digests");
3271 expert_iscsi
= expert_register_protocol(proto_iscsi
);
3272 expert_register_field_array(expert_iscsi
, ei
, array_length(ei
));
3277 * If this dissector uses sub-dissector registration add a
3278 * registration routine.
3282 * This format is required because a script is used to find these
3283 * routines and create the code that calls these routines.
3286 proto_reg_handoff_iscsi(void)
3288 heur_dissector_add("tcp", dissect_iscsi_heur
, "iSCSI over TCP", "iscsi_tcp", proto_iscsi
, HEURISTIC_ENABLE
);
3290 dissector_add_for_decode_as_with_preference("tcp.port", iscsi_handle
);
3294 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3299 * indent-tabs-mode: nil
3302 * vi: set shiftwidth=4 tabstop=8 expandtab:
3303 * :indentSize=4:tabSize=8:noTabs=true: