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
16 * Wireshark - Network traffic analyzer
17 * By Gerald Combs <gerald@wireshark.org>
18 * Copyright 1998 Gerald Combs
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
45 #include <epan/packet.h>
46 #include <epan/prefs.h>
47 #include <epan/conversation.h>
48 #include "packet-fc.h"
49 #include "packet-scsi.h"
50 #include "epan/nstime.h"
51 #include <epan/emem.h>
53 /* the absolute values of these constants don't matter as long as
54 * latter revisions of the protocol are assigned a larger number */
55 #define ISCSI_PROTOCOL_DRAFT08 1
56 #define ISCSI_PROTOCOL_DRAFT09 2
57 #define ISCSI_PROTOCOL_DRAFT11 3
58 #define ISCSI_PROTOCOL_DRAFT12 4
59 #define ISCSI_PROTOCOL_DRAFT13 5
61 static enum_val_t iscsi_protocol_versions[] = {
62 { "draft-08", "Draft 08", ISCSI_PROTOCOL_DRAFT08 },
63 { "draft-09", "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
64 { "draft-11", "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
65 { "draft-12", "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
66 { "draft-13", "Draft 13", ISCSI_PROTOCOL_DRAFT13 },
70 static const value_string ahs_type_vals[] = {
72 {2, "Expected Bidirection Read Data Length"},
76 static dissector_handle_t iscsi_handle=NULL;
78 static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT13;
80 static gboolean iscsi_desegment = TRUE;
82 static int demand_good_f_bit = FALSE;
83 static int enable_bogosity_filter = TRUE;
84 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
86 static int enableDataDigests = FALSE;
88 static int dataDigestIsCRC32 = TRUE;
90 static guint dataDigestSize = 4;
92 static guint iscsi_port = 3260;
94 /* Initialize the protocol and registered fields */
95 static int proto_iscsi = -1;
96 static int hf_iscsi_time = -1;
97 static int hf_iscsi_request_frame = -1;
98 static int hf_iscsi_data_in_frame = -1;
99 static int hf_iscsi_data_out_frame = -1;
100 static int hf_iscsi_response_frame = -1;
101 static int hf_iscsi_AHS = -1;
102 static int hf_iscsi_AHS_length = -1;
103 static int hf_iscsi_AHS_type = -1;
104 static int hf_iscsi_AHS_specific = -1;
105 static int hf_iscsi_Padding = -1;
106 static int hf_iscsi_ping_data = -1;
107 static int hf_iscsi_immediate_data = -1;
108 static int hf_iscsi_write_data = -1;
109 static int hf_iscsi_read_data = -1;
110 static int hf_iscsi_error_pdu_data = -1;
111 static int hf_iscsi_async_message_data = -1;
112 static int hf_iscsi_vendor_specific_data = -1;
113 static int hf_iscsi_Opcode = -1;
114 static int hf_iscsi_Flags = -1;
115 static int hf_iscsi_HeaderDigest32 = -1;
116 static int hf_iscsi_DataDigest = -1;
117 static int hf_iscsi_DataDigest32 = -1;
119 static int hf_iscsi_X = -1;
121 static int hf_iscsi_I = -1;
122 static int hf_iscsi_SCSICommand_F = -1;
123 static int hf_iscsi_SCSICommand_R = -1;
124 static int hf_iscsi_SCSICommand_W = -1;
125 static int hf_iscsi_SCSICommand_Attr = -1;
126 static int hf_iscsi_SCSICommand_CRN = -1;
127 static int hf_iscsi_SCSICommand_AddCDB = -1;
128 static int hf_iscsi_DataSegmentLength = -1;
129 static int hf_iscsi_TotalAHSLength = -1;
130 static int hf_iscsi_LUN = -1;
131 static int hf_iscsi_InitiatorTaskTag = -1;
132 static int hf_iscsi_ExpectedDataTransferLength = -1;
133 static int hf_iscsi_CmdSN = -1;
134 static int hf_iscsi_ExpStatSN = -1;
135 static int hf_iscsi_StatSN = -1;
136 static int hf_iscsi_ExpCmdSN = -1;
137 static int hf_iscsi_MaxCmdSN = -1;
138 static int hf_iscsi_SCSIResponse_o = -1;
139 static int hf_iscsi_SCSIResponse_u = -1;
140 static int hf_iscsi_SCSIResponse_O = -1;
141 static int hf_iscsi_SCSIResponse_U = -1;
142 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
143 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
144 static int hf_iscsi_SCSIResponse_Response = -1;
145 static int hf_iscsi_SCSIResponse_Status = -1;
146 static int hf_iscsi_SenseLength = -1;
147 static int hf_iscsi_SCSIData_F = -1;
148 static int hf_iscsi_SCSIData_A = -1;
149 static int hf_iscsi_SCSIData_S = -1;
150 static int hf_iscsi_SCSIData_O = -1;
151 static int hf_iscsi_SCSIData_U = -1;
152 static int hf_iscsi_TargetTransferTag = -1;
153 static int hf_iscsi_DataSN = -1;
154 static int hf_iscsi_BufferOffset = -1;
155 static int hf_iscsi_SCSIData_ResidualCount = -1;
156 static int hf_iscsi_VersionMin = -1;
157 static int hf_iscsi_VersionMax = -1;
158 static int hf_iscsi_VersionActive = -1;
159 static int hf_iscsi_CID = -1;
160 static int hf_iscsi_ISID8 = -1;
161 static int hf_iscsi_ISID = -1;
162 /* #if defined(DRAFT09) */
163 static int hf_iscsi_ISID_Type = -1;
164 static int hf_iscsi_ISID_NamingAuthority = -1;
165 static int hf_iscsi_ISID_Qualifier = -1;
166 /* #elif !defined(DRAFT08) */
167 static int hf_iscsi_ISID_t = -1;
168 static int hf_iscsi_ISID_a = -1;
169 static int hf_iscsi_ISID_b = -1;
170 static int hf_iscsi_ISID_c = -1;
171 static int hf_iscsi_ISID_d = -1;
173 static int hf_iscsi_TSID = -1;
174 static int hf_iscsi_TSIH = -1;
175 static int hf_iscsi_InitStatSN = -1;
176 static int hf_iscsi_InitCmdSN = -1;
178 static int hf_iscsi_Login_X = -1;
180 static int hf_iscsi_Login_C = -1;
181 static int hf_iscsi_Login_T = -1;
182 static int hf_iscsi_Login_CSG = -1;
183 static int hf_iscsi_Login_NSG = -1;
184 static int hf_iscsi_Login_Status = -1;
185 static int hf_iscsi_KeyValue = -1;
186 static int hf_iscsi_Text_C = -1;
187 static int hf_iscsi_Text_F = -1;
188 static int hf_iscsi_ExpDataSN = -1;
189 static int hf_iscsi_R2TSN = -1;
190 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
191 static int hf_iscsi_RefCmdSN = -1;
192 static int hf_iscsi_TaskManagementFunction_Function = -1;
193 static int hf_iscsi_TaskManagementFunction_Response = -1;
194 static int hf_iscsi_Logout_Reason = -1;
195 static int hf_iscsi_Logout_Response = -1;
196 static int hf_iscsi_Time2Wait = -1;
197 static int hf_iscsi_Time2Retain = -1;
198 static int hf_iscsi_DesiredDataLength = -1;
199 static int hf_iscsi_AsyncEvent = -1;
200 static int hf_iscsi_EventVendorCode = -1;
201 static int hf_iscsi_Parameter1 = -1;
202 static int hf_iscsi_Parameter2 = -1;
203 static int hf_iscsi_Parameter3 = -1;
204 static int hf_iscsi_Reject_Reason = -1;
205 static int hf_iscsi_snack_type = -1;
206 static int hf_iscsi_BegRun = -1;
207 static int hf_iscsi_RunLength = -1;
209 /* Initialize the subtree pointers */
210 static gint ett_iscsi = -1;
211 static gint ett_iscsi_KeyValues = -1;
212 static gint ett_iscsi_CDB = -1;
213 static gint ett_iscsi_Flags = -1;
214 /* #ifndef DRAFT08 */
215 static gint ett_iscsi_ISID = -1;
218 #define ISCSI_HEADER_DIGEST_AUTO 0
219 #define ISCSI_HEADER_DIGEST_NONE 1
220 #define ISCSI_HEADER_DIGEST_CRC32 2
221 /* this structure contains session wide state for a specific tcp conversation */
222 typedef struct _iscsi_session_t {
223 guint32 header_digest;
224 emem_tree_t *itlq; /* indexed by ITT */
225 emem_tree_t *itl; /* indexed by LUN */
236 #define OPCODE_MASK 0x3f
238 #define TARGET_OPCODE_BIT 0x20
240 #define ISCSI_OPCODE_NOP_OUT 0x00
241 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
242 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
243 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
244 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
245 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
246 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
247 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
248 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
249 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
250 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
252 #define ISCSI_OPCODE_NOP_IN 0x20
253 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
254 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
255 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
256 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
257 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
258 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
259 #define ISCSI_OPCODE_R2T 0x31
260 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
261 #define ISCSI_OPCODE_REJECT 0x3f
262 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
263 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
264 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
267 #define CSG_MASK (0x03 << CSG_SHIFT)
268 #define NSG_MASK 0x03
270 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
271 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
272 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
274 #define ISCSI_SCSI_DATA_FLAG_S 0x01
275 #define ISCSI_SCSI_DATA_FLAG_U 0x02
276 #define ISCSI_SCSI_DATA_FLAG_O 0x04
277 #define ISCSI_SCSI_DATA_FLAG_A 0x40
278 #define ISCSI_SCSI_DATA_FLAG_F 0x80
280 static const value_string iscsi_opcodes[] = {
281 { ISCSI_OPCODE_NOP_OUT, "NOP Out" },
282 { ISCSI_OPCODE_SCSI_COMMAND, "SCSI Command" },
283 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION, "Task Management Function" },
284 { ISCSI_OPCODE_LOGIN_COMMAND, "Login Command" },
285 { ISCSI_OPCODE_TEXT_COMMAND, "Text Command" },
286 { ISCSI_OPCODE_SCSI_DATA_OUT, "SCSI Data Out" },
287 { ISCSI_OPCODE_LOGOUT_COMMAND, "Logout Command" },
288 { ISCSI_OPCODE_SNACK_REQUEST, "SNACK Request" },
289 { ISCSI_OPCODE_VENDOR_SPECIFIC_I0, "Vendor Specific I0" },
290 { ISCSI_OPCODE_VENDOR_SPECIFIC_I1, "Vendor Specific I1" },
291 { ISCSI_OPCODE_VENDOR_SPECIFIC_I2, "Vendor Specific I2" },
293 { ISCSI_OPCODE_NOP_IN, "NOP In" },
294 { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
295 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
296 { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
297 { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
298 { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
299 { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
300 { ISCSI_OPCODE_R2T, "Ready To Transfer" },
301 { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
302 { ISCSI_OPCODE_REJECT, "Reject"},
303 { ISCSI_OPCODE_VENDOR_SPECIFIC_T0, "Vendor Specific T0" },
304 { ISCSI_OPCODE_VENDOR_SPECIFIC_T1, "Vendor Specific T1" },
305 { ISCSI_OPCODE_VENDOR_SPECIFIC_T2, "Vendor Specific T2" },
310 static const true_false_string iscsi_meaning_X = {
317 static const true_false_string iscsi_meaning_login_X = {
318 "Reinstate failed connection",
323 static const true_false_string iscsi_meaning_I = {
324 "Immediate delivery",
328 static const true_false_string iscsi_meaning_F = {
329 "Final PDU in sequence",
330 "Not final PDU in sequence"
333 static const true_false_string iscsi_meaning_A = {
334 "Acknowledge requested",
335 "Acknowledge not requested"
338 static const true_false_string iscsi_meaning_T = {
339 "Transit to next login stage",
340 "Stay in current login stage"
343 static const true_false_string iscsi_meaning_C = {
344 "Text is incomplete",
348 static const true_false_string iscsi_meaning_S = {
349 "Response contains SCSI status",
350 "Response does not contain SCSI status"
353 static const true_false_string iscsi_meaning_R = {
354 "Data will be read from target",
355 "No data will be read from target"
358 static const true_false_string iscsi_meaning_W = {
359 "Data will be written to target",
360 "No data will be written to target"
363 static const true_false_string iscsi_meaning_o = {
364 "Read part of bi-directional command overflowed",
365 "No overflow of read part of bi-directional command",
368 static const true_false_string iscsi_meaning_u = {
369 "Read part of bi-directional command underflowed",
370 "No underflow of read part of bi-directional command",
373 static const true_false_string iscsi_meaning_O = {
374 "Residual overflow occurred",
375 "No residual overflow occurred",
378 static const true_false_string iscsi_meaning_U = {
379 "Residual underflow occurred",
380 "No residual underflow occurred",
383 static const value_string iscsi_scsi_responses[] = {
384 { 0, "Command completed at target" },
385 { 1, "Response does not contain SCSI status"},
389 static const value_string iscsi_scsicommand_taskattrs[] = {
393 {3, "Head of Queue"},
398 static const value_string iscsi_task_management_responses[] = {
399 {0, "Function complete"},
400 {1, "Task not in task set"},
401 {2, "LUN does not exist"},
402 {3, "Task still allegiant"},
403 {4, "Task failover not supported"},
404 {5, "Task management function not supported"},
405 {6, "Authorisation failed"},
406 {255, "Function rejected"},
410 static const value_string iscsi_task_management_functions[] = {
412 {2, "Abort Task Set"},
414 {4, "Clear Task Set"},
415 {5, "Logical Unit Reset"},
416 {6, "Target Warm Reset"},
417 {7, "Target Cold Reset"},
418 {8, "Target Reassign"},
422 static const value_string iscsi_login_status[] = {
424 {0x0101, "Target moved temporarily"},
425 {0x0102, "Target moved permanently"},
426 {0x0200, "Initiator error (miscellaneous error)"},
427 {0x0201, "Authentication failed"},
428 {0x0202, "Authorisation failure"},
429 {0x0203, "Target not found"},
430 {0x0204, "Target removed"},
431 {0x0205, "Unsupported version"},
432 {0x0206, "Too many connections"},
433 {0x0207, "Missing parameter"},
434 {0x0208, "Can't include in session"},
435 {0x0209, "Session type not supported"},
436 {0x020a, "Session does not exist"},
437 {0x020b, "Invalid request during login"},
438 {0x0300, "Target error (miscellaneous error)"},
439 {0x0301, "Service unavailable"},
440 {0x0302, "Out of resources"},
444 static const value_string iscsi_login_stage[] = {
445 {0, "Security negotiation"},
446 {1, "Operational negotiation"},
447 {3, "Full feature phase"},
451 /* #ifndef DRAFT08 */
452 static const value_string iscsi_isid_type[] = {
454 {0x01, "IANA Enterprise Number"},
460 static const value_string iscsi_logout_reasons[] = {
461 {0, "Close session"},
462 {1, "Close connection"},
463 {2, "Remove connection for recovery"},
467 static const value_string iscsi_logout_response[] = {
468 {0, "Connection closed successfully"},
469 {1, "CID not found"},
470 {2, "Connection recovery not supported"},
471 {3, "Cleanup failed for various reasons"},
475 static const value_string iscsi_asyncevents[] = {
476 {0, "A SCSI asynchronous event is reported in the sense data"},
477 {1, "Target requests logout"},
478 {2, "Target will/has dropped connection"},
479 {3, "Target will/has dropped all connections"},
480 {4, "Target requests parameter negotiation"},
484 static const value_string iscsi_snack_types[] = {
487 /* #ifndef DRAFT08 */
494 static const value_string iscsi_reject_reasons[] = {
496 {0x01, "Full feature phase command before login"},
498 {0x02, "Data (payload) digest error"},
499 {0x03, "Data SNACK reject"},
500 {0x04, "Protocol error"},
501 {0x05, "Command not supported in this session type"},
502 {0x06, "Immediate command reject (too many immediate commands)"},
503 {0x07, "Task in progress"},
504 {0x08, "Invalid Data Ack"},
505 {0x09, "Invalid PDU field"},
506 {0x0a, "Long operation reject"},
507 {0x0b, "Negotiation reset"},
508 {0x0c, "Waiting for logout"},
512 /*****************************************************************/
514 /* CRC LOOKUP TABLE */
515 /* ================ */
516 /* The following CRC lookup table was generated automagically */
517 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
518 /* Program V1.0 using the following model parameters: */
520 /* Width : 4 bytes. */
521 /* Poly : 0x1EDC6F41L */
522 /* Reverse : TRUE. */
524 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
525 /* see the document titled "A Painless Guide to CRC Error */
526 /* Detection Algorithms" by Ross Williams */
527 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
528 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
530 /*****************************************************************/
532 static guint32 crc32Table[256] = {
533 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
534 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
535 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
536 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
537 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
538 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
539 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
540 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
541 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
542 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
543 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
544 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
545 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
546 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
547 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
548 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
549 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
550 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
551 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
552 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
553 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
554 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
555 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
556 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
557 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
558 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
559 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
560 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
561 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
562 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
563 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
564 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
565 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
566 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
567 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
568 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
569 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
570 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
571 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
572 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
573 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
574 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
575 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
576 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
577 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
578 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
579 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
580 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
581 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
582 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
583 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
584 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
585 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
586 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
587 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
588 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
589 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
590 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
591 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
592 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
593 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
594 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
595 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
596 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
599 #define CRC32C_PRELOAD 0xffffffff
602 * Byte swap fix contributed by Dave Wysochanski <davidw@netapp.com>
604 #define CRC32C_SWAP(crc32c_value) \
605 (((crc32c_value & 0xff000000) >> 24) | \
606 ((crc32c_value & 0x00ff0000) >> 8) | \
607 ((crc32c_value & 0x0000ff00) << 8) | \
608 ((crc32c_value & 0x000000ff) << 24))
611 calculateCRC32(const void *buf, int len, guint32 crc) {
612 const guint8 *p = (const guint8 *)buf;
613 crc = CRC32C_SWAP(crc);
615 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
616 return CRC32C_SWAP(crc);
623 /* structure and functions to keep track of
624 * COMMAND/DATA_IN/DATA_OUT/RESPONSE matching
626 typedef struct _iscsi_conv_data {
627 guint32 data_in_frame;
628 guint32 data_out_frame;
633 iscsi_min(int a, int b) {
634 return (a < b)? a : b;
638 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
639 const gint limit = offset + text_len;
640 while(offset < limit) {
641 gint len = tvb_strnlen(tvb, offset, limit - offset);
643 len = limit - offset;
646 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
653 handleHeaderDigest(iscsi_session_t *iscsi_session, proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
654 int available_bytes = tvb_length_remaining(tvb, offset);
656 switch(iscsi_session->header_digest){
657 case ISCSI_HEADER_DIGEST_CRC32:
658 if(available_bytes >= (headerLen + 4)) {
659 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
660 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
662 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
664 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Bad CRC32, should be 0x%08x)", sent, crc);
667 return offset + headerLen + 4;
670 return offset + headerLen;
674 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
675 int available_bytes = tvb_length_remaining(tvb, offset);
676 if(enableDataDigests) {
677 if(dataDigestIsCRC32) {
678 if(available_bytes >= (dataLen + 4)) {
679 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
680 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
682 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
685 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Bad CRC32, should be 0x%08x)", sent, crc);
688 return offset + dataLen + 4;
690 if((unsigned)available_bytes >= (dataLen + dataDigestSize)) {
691 proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
693 return offset + dataLen + dataDigestSize;
695 return offset + dataLen;
699 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
700 if(endOffset > offset) {
701 int dataOffset = offset;
702 int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
704 proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
707 if(offset < endOffset && (offset & 3) != 0) {
708 int padding = 4 - (offset & 3);
709 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
712 if(dataSegmentLen > 0 && offset < endOffset)
713 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
720 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
721 if(endOffset > offset) {
722 int dataOffset = offset;
723 int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
725 proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
726 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
727 offset = addTextKeys(tt, tvb, offset, textLen);
729 if(offset < endOffset && (offset & 3) != 0) {
730 int padding = 4 - (offset & 3);
731 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
734 if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
735 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
740 /* Code to actually dissect the packets */
742 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len, iscsi_session_t *iscsi_session) {
744 guint original_offset = offset;
745 proto_tree *ti = NULL;
746 guint8 scsi_status = 0;
747 gboolean S_bit=FALSE;
748 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
749 guint end_offset = offset + tvb_length_remaining(tvb, offset);
750 iscsi_conv_data_t *cdata = NULL;
751 int paddedDataSegmentLength = data_segment_len;
753 guint immediate_data_length=0;
754 guint immediate_data_offset=0;
755 itl_nexus_t *itl=NULL;
756 guint16 ahs_length=0;
759 if(paddedDataSegmentLength & 3)
760 paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
762 /* Make entries in Protocol column and Info column on summary display */
763 if (check_col(pinfo->cinfo, COL_PROTOCOL))
764 col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
766 /* XXX we need a way to handle replayed iscsi itt here */
767 cdata=(iscsi_conv_data_t *)se_tree_lookup32(iscsi_session->itlq, tvb_get_ntohl(tvb, offset+16));
769 cdata = se_alloc (sizeof(iscsi_conv_data_t));
770 cdata->itlq.lun=0xffff;
771 cdata->itlq.scsi_opcode=0xffff;
772 cdata->itlq.fc_time = pinfo->fd->abs_ts;
773 cdata->itlq.first_exchange_frame=0;
774 cdata->itlq.last_exchange_frame=0;
776 cdata->itlq.alloc_len=0;
777 cdata->itlq.extra_data=NULL;
778 cdata->data_in_frame=0;
779 cdata->data_out_frame=0;
781 se_tree_insert32(iscsi_session->itlq, tvb_get_ntohl(tvb, offset+16), cdata);
784 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
785 opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
786 scsi_status = tvb_get_guint8 (tvb, offset+3);
789 if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
790 (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
791 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
792 /* first time we see this packet. check if we can find the request */
794 case ISCSI_OPCODE_SCSI_RESPONSE:
795 cdata->itlq.last_exchange_frame=pinfo->fd->num;
797 case ISCSI_OPCODE_SCSI_DATA_IN:
798 /* a bit ugly but we need to check the S bit here */
799 if(tvb_get_guint8(tvb, offset+1)&ISCSI_SCSI_DATA_FLAG_S){
800 cdata->itlq.last_exchange_frame=pinfo->fd->num;
802 cdata->data_in_frame=pinfo->fd->num;
804 case ISCSI_OPCODE_SCSI_DATA_OUT:
805 cdata->data_out_frame=pinfo->fd->num;
809 } else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
810 /*we need the LUN value for some of the commands so we can pass it
811 across to the SCSI dissector.
812 Not correct but simple and probably accurate enough :
813 If bit 6 of first bit is 0 then just take second byte as the LUN
814 If bit 6 of first bit is 1, then take 6 bits from first byte
815 and all of second byte and pretend it is the lun value
816 people that care can add host specific dissection of vsa later.
818 We need to keep track of this on a per transaction basis since
819 for error recoverylevel 0 and when the A bit is clear in a
820 Data-In PDU, there will not be a LUN field in teh iscsi layer.
822 if(tvb_get_guint8(tvb, offset+8)&0x40){
823 /* volume set addressing */
824 lun=tvb_get_guint8(tvb,offset+8)&0x3f;
826 lun|=tvb_get_guint8(tvb,offset+9);
828 lun=tvb_get_guint8(tvb,offset+9);
832 cdata->itlq.first_exchange_frame=pinfo->fd->num;
834 itl=(itl_nexus_t *)se_tree_lookup32(iscsi_session->itl, lun);
836 itl=se_alloc(sizeof(itl_nexus_t));
838 se_tree_insert32(iscsi_session->itl, lun, itl);
844 itl=(itl_nexus_t *)se_tree_lookup32(iscsi_session->itl, cdata->itlq.lun);
848 if (check_col(pinfo->cinfo, COL_INFO)) {
850 if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
852 col_append_str(pinfo->cinfo, COL_INFO, opcode_str);
854 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
855 (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
856 (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
857 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
858 val_to_str (scsi_status, scsi_status_val, "0x%x"));
860 else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
861 guint16 login_status = tvb_get_ntohs(tvb, offset+36);
862 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
863 val_to_str (login_status, iscsi_login_status, "0x%x"));
865 else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
867 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
868 logoutReason = tvb_get_guint8(tvb, offset+11);
869 } else if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
870 logoutReason = tvb_get_guint8(tvb, offset+1) & 0x7f;
873 logoutReason = tvb_get_guint8(tvb, offset+23);
875 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
876 val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
878 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
879 guint8 tmf = tvb_get_guint8(tvb, offset + 1);
880 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
881 val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
883 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
884 guint8 resp = tvb_get_guint8(tvb, offset + 2);
885 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
886 val_to_str (resp, iscsi_task_management_responses, "0x%x"));
888 else if (opcode == ISCSI_OPCODE_REJECT) {
889 guint8 reason = tvb_get_guint8(tvb, offset + 2);
890 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
891 val_to_str (reason, iscsi_reject_reasons, "0x%x"));
893 else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
894 guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
895 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
896 val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
901 /* In the interest of speed, if "tree" is NULL, don't do any
902 work not necessary to generate protocol tree items. */
905 /* create display subtree for the protocol */
906 tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
907 offset, -1, "iSCSI (%s)",
909 ti = proto_item_add_subtree(tp, ett_iscsi);
911 proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
912 offset + 0, 1, opcode);
913 if((opcode & TARGET_OPCODE_BIT) == 0) {
914 /* initiator -> target */
915 gint b = tvb_get_guint8(tvb, offset + 0);
916 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
917 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
918 opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
919 opcode != ISCSI_OPCODE_SNACK_REQUEST)
920 proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
922 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
923 opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
924 opcode != ISCSI_OPCODE_SNACK_REQUEST)
925 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
928 if(opcode == ISCSI_OPCODE_NOP_OUT) {
930 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
931 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
933 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
934 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
935 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
936 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
937 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
938 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
939 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
940 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
941 } else if(opcode == ISCSI_OPCODE_NOP_IN) {
943 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
944 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
946 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
947 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
948 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
949 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
950 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
951 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
952 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
953 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
954 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
955 } else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
957 guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
959 gint b = tvb_get_guint8(tvb, offset + 1);
960 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
961 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
963 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
964 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
965 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
966 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
968 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
969 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
971 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
972 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
973 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
974 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
975 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
976 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
977 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
980 ahs_length=tvb_get_ntohs(tvb, offset+48);
981 proto_tree_add_item(ti, hf_iscsi_AHS_length, tvb, offset + 48, 2, FALSE);
982 ahs_type=tvb_get_guint8(tvb, offset+50);
983 proto_tree_add_item(ti, hf_iscsi_AHS_type, tvb, offset + 50, 1, FALSE);
984 proto_tree_add_item(ti, hf_iscsi_AHS_specific, tvb, offset + 51, 1, FALSE);
985 proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 52, ahsLen-4, FALSE);
987 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48 + ahsLen);
989 immediate_data_offset=offset;
990 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
991 immediate_data_length=offset-immediate_data_offset;
992 } else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
995 gint b = tvb_get_guint8(tvb, offset + 1);
996 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
997 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
999 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
1000 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
1001 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
1002 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
1004 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
1005 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1006 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1007 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1009 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1010 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1011 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1012 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
1014 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1015 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1016 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1017 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1018 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1019 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
1022 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
1023 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
1025 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1026 /* do not update offset here because the data segment is
1027 * dissected below */
1028 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1029 } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
1030 /* Task Management Function */
1031 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
1032 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1033 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1034 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1036 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1037 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1038 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1039 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1040 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1041 proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1042 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1043 } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1044 /* Task Management Function Response */
1045 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
1046 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1047 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1048 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1050 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1051 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1052 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1054 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1055 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1056 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1057 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1058 } else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1060 int digestsActive = 0;
1062 gint b = tvb_get_guint8(tvb, offset + 1);
1063 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1064 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1068 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1069 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1072 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1073 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1074 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1076 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1077 proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1079 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1081 /* NSG is undefined unless T is set */
1083 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1086 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1087 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1088 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1089 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1091 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1092 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1093 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1094 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1097 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1098 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1099 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1100 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1101 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1102 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1105 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1106 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1107 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1108 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1109 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1112 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1113 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1116 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1118 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1119 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1120 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1122 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1123 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1125 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1129 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1130 } else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1131 /* Login Response */
1132 int digestsActive = 0;
1134 gint b = tvb_get_guint8(tvb, offset + 1);
1135 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1136 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1140 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1141 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1144 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1145 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1146 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1148 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1149 /* NSG is undefined unless T is set */
1151 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1155 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1156 proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1157 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1158 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1160 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1161 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1162 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1165 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1166 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1167 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1168 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1169 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1170 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1173 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1174 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1175 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1176 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1177 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1180 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1181 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1184 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1186 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1187 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1188 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1189 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1190 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1192 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1196 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1197 } else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1200 gint b = tvb_get_guint8(tvb, offset + 1);
1201 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1202 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1204 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1205 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1206 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1209 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1210 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1212 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1213 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1214 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1216 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1217 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1218 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1219 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1220 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1221 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1222 } else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1225 gint b = tvb_get_guint8(tvb, offset + 1);
1226 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1227 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1229 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1230 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1231 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1234 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1235 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1237 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1238 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1239 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1241 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1242 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1243 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1244 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1245 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1246 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1247 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1248 } else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1249 /* SCSI Data Out (write) */
1251 gint b = tvb_get_guint8(tvb, offset + 1);
1252 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1253 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1255 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1257 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1258 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1260 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1261 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1262 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1263 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1264 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1265 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1266 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1267 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1268 /* do not update offset here because the data segment is
1269 * dissected below */
1270 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1271 } else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
1272 /* SCSI Data In (read) */
1274 gint b = tvb_get_guint8(tvb, offset + 1);
1275 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1276 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1278 if(b&ISCSI_SCSI_DATA_FLAG_S){
1281 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1282 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1283 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
1285 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1286 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1287 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1290 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1292 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1293 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1295 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1296 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1297 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1299 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1300 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1301 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1304 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1306 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1307 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1308 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1309 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1310 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1311 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1312 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1314 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1315 /* do not update offset here because the data segment is
1316 * dissected below */
1317 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1318 } else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1319 /* Logout Command */
1320 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1321 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 1, 1, FALSE);
1323 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1324 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1325 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1327 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1328 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1329 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1331 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1332 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1333 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1334 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT13) {
1335 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
1338 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1339 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1340 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1341 } else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1342 /* Logout Response */
1343 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1344 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1345 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1346 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1348 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1349 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1350 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1351 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1352 proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1353 proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1354 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1355 } else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1358 gint b = tvb_get_guint8(tvb, offset + 1);
1360 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1361 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1364 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1366 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1367 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1368 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1369 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1371 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1372 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1373 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1374 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1375 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1376 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1379 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1380 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1381 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1382 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1384 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1385 } else if(opcode == ISCSI_OPCODE_R2T) {
1387 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1388 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1389 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1390 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1392 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1393 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1394 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1395 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1396 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1397 proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
1398 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1399 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1400 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1401 } else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1402 /* Asynchronous Message */
1403 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1404 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1406 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1407 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1408 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1409 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1410 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1411 proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1412 proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1413 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1414 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1415 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1416 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1417 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
1418 } else if(opcode == ISCSI_OPCODE_REJECT) {
1420 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
1421 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1422 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1424 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1425 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1426 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1427 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1428 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1429 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1430 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1431 } else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
1432 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
1433 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
1434 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
1435 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
1436 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
1437 /* Vendor specific opcodes */
1438 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1439 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1441 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1442 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1443 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
1448 /* handle request/response matching */
1450 case ISCSI_OPCODE_SCSI_RESPONSE:
1451 if (cdata->itlq.first_exchange_frame){
1452 nstime_t delta_time;
1453 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1454 nstime_delta(&delta_time, &pinfo->fd->abs_ts, &cdata->itlq.fc_time);
1455 proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1457 if (cdata->data_in_frame)
1458 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1459 if (cdata->data_out_frame)
1460 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1462 case ISCSI_OPCODE_SCSI_DATA_IN:
1463 /* if we have phase collaps then we might have the
1464 response embedded in the last DataIn segment */
1466 if (cdata->itlq.first_exchange_frame)
1467 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1468 if (cdata->itlq.last_exchange_frame)
1469 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1471 if (cdata->itlq.first_exchange_frame){
1472 nstime_t delta_time;
1473 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1474 nstime_delta(&delta_time, &pinfo->fd->abs_ts, &cdata->itlq.fc_time);
1475 proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1478 if (cdata->data_out_frame)
1479 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1481 case ISCSI_OPCODE_SCSI_DATA_OUT:
1482 if (cdata->itlq.first_exchange_frame)
1483 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1484 if (cdata->data_in_frame)
1485 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1486 if (cdata->itlq.last_exchange_frame)
1487 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1489 case ISCSI_OPCODE_SCSI_COMMAND:
1490 if (cdata->data_in_frame)
1491 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1492 if (cdata->data_out_frame)
1493 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1494 if (cdata->itlq.last_exchange_frame)
1495 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1501 proto_item_set_len(ti, offset - original_offset);
1503 if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
1505 ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
1506 tvbuff_t *cdb_tvb, *data_tvb;
1507 int tvb_len, tvb_rlen;
1511 tvb_len=tvb_length_remaining(tvb, cdb_offset);
1512 tvb_rlen=tvb_reported_length_remaining(tvb, cdb_offset);
1513 scsi_opcode=tvb_get_guint8(tvb, cdb_offset);
1514 if(ahs_type==1 && ahs_length && ahs_length<1024){
1517 /* We have a variable length CDB where bytes >16 is transported
1520 cdb_buf=ep_alloc(16+ahs_length-1);
1521 /* the 16 first bytes of the cdb */
1522 tvb_memcpy(tvb, cdb_buf, cdb_offset, 16);
1523 /* hte remainder of the cdb from the ahs */
1524 tvb_memcpy(tvb, cdb_buf+16, cdb_offset+20, ahs_length-1);
1526 cdb_tvb = tvb_new_real_data(cdb_buf,
1530 tvb_set_child_real_data_tvbuff(tvb, cdb_tvb);
1532 add_new_data_source(pinfo, cdb_tvb, "CDB+AHS");
1540 cdb_tvb=tvb_new_subset(tvb, cdb_offset, tvb_len, tvb_rlen);
1542 dissect_scsi_cdb(cdb_tvb, pinfo, tree, SCSI_DEV_UNKNOWN, &cdata->itlq, itl);
1543 /* we dont want the immediata below to overwrite our CDB info */
1544 if (check_col(pinfo->cinfo, COL_INFO)) {
1545 col_set_fence(pinfo->cinfo, COL_INFO);
1547 /* where there any ImmediateData ? */
1548 if(immediate_data_length){
1549 /* Immediate Data TVB */
1550 tvb_len=tvb_length_remaining(tvb, immediate_data_offset);
1551 if(tvb_len>(int)immediate_data_length)
1552 tvb_len=immediate_data_length;
1553 tvb_rlen=tvb_reported_length_remaining(tvb, immediate_data_offset);
1554 if(tvb_rlen>(int)immediate_data_length)
1555 tvb_rlen=immediate_data_length;
1556 data_tvb=tvb_new_subset(tvb, immediate_data_offset, tvb_len, tvb_rlen);
1557 dissect_scsi_payload (data_tvb, pinfo, tree,
1562 else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1563 if (scsi_status == 0x2) {
1564 /* A SCSI response with Check Condition contains sense data */
1565 /* offset is setup correctly by the iscsi code for response above */
1566 if((end_offset - offset) >= 2) {
1567 int senseLen = tvb_get_ntohs(tvb, offset);
1569 proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1573 int tvb_len, tvb_rlen;
1575 tvb_len=tvb_length_remaining(tvb, offset);
1576 if(tvb_len>senseLen)
1578 tvb_rlen=tvb_reported_length_remaining(tvb, offset);
1579 if(tvb_rlen>senseLen)
1581 data_tvb=tvb_new_subset(tvb, offset, tvb_len, tvb_rlen);
1582 dissect_scsi_snsinfo (data_tvb, pinfo, tree, 0,
1589 dissect_scsi_rsp(tvb, pinfo, tree, &cdata->itlq, itl, scsi_status);
1592 else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1593 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1595 int tvb_len, tvb_rlen;
1597 /* offset is setup correctly by the iscsi code for response above */
1598 tvb_len=tvb_length_remaining(tvb, offset);
1599 if(tvb_len>(int)data_segment_len)
1600 tvb_len=data_segment_len;
1601 tvb_rlen=tvb_reported_length_remaining(tvb, offset);
1602 if(tvb_rlen>(int)data_segment_len)
1603 tvb_rlen=data_segment_len;
1604 data_tvb=tvb_new_subset(tvb, offset, tvb_len, tvb_rlen);
1605 dissect_scsi_payload (data_tvb, pinfo, tree,
1606 (opcode==ISCSI_OPCODE_SCSI_DATA_OUT),
1611 dissect_scsi_rsp(tvb, pinfo, tree, &cdata->itlq, itl, scsi_status);
1616 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_port) {
1617 /* Set up structures needed to add the protocol subtree and manage it */
1618 guint iSCSIPdusDissected = 0;
1620 guint32 available_bytes = tvb_length_remaining(tvb, offset);
1621 int digestsActive = 1;
1622 conversation_t *conversation = NULL;
1623 iscsi_session_t *iscsi_session=NULL;
1624 guint8 opcode, tmpbyte;
1626 /* quick check to see if the packet is long enough to contain the
1627 * minimum amount of information we need */
1628 if (available_bytes < 48 ){
1629 /* no, so give up */
1633 opcode = tvb_get_guint8(tvb, offset + 0);
1634 opcode &= OPCODE_MASK;
1636 /* heuristics to verify that the packet looks sane. the heuristics
1637 * are based on the RFC version of iscsi.
1638 * (we should retire support for older iscsi versions in wireshark)
1641 /* opcode must be any of the ones from the standard
1642 * also check the header that it looks "sane"
1643 * all reserved or undefined bits in iscsi must be set to zero.
1646 case ISCSI_OPCODE_NOP_IN:
1647 /* top two bits of byte 0 must be 0 */
1648 if(tvb_get_guint8(tvb, offset+0)&0xc0){
1651 /* byte 1 must be 0x80 */
1652 if(tvb_get_guint8(tvb, offset+1)!=0x80){
1655 /* bytes 2 and 3 must be 0 */
1656 if(tvb_get_guint8(tvb, offset+2)||tvb_get_guint8(tvb, offset+3)){
1660 case ISCSI_OPCODE_NOP_OUT:
1661 /* top bit of byte 0 must be 0 */
1662 if(tvb_get_guint8(tvb, offset+0)&0x80){
1665 /* byte 1 must be 0x80 */
1666 if(tvb_get_guint8(tvb, offset+1)!=0x80){
1669 /* bytes 2 and 3 must be 0 */
1670 if(tvb_get_guint8(tvb, offset+2)||tvb_get_guint8(tvb, offset+3)){
1673 /* assume ITT and TTT must always be non NULL (ok they can be NULL
1674 * from time to time but it usually means we are in the middle
1675 * of a zeroed datablock).
1677 if(!tvb_get_letohl(tvb,offset+16) || !tvb_get_letohl(tvb,offset+20)){
1680 /* all reserved bytes between 32 - 47 must be null */
1681 if(tvb_get_letohl(tvb,offset+32)
1682 || tvb_get_letohl(tvb,offset+36)
1683 || tvb_get_letohl(tvb,offset+40)
1684 || tvb_get_letohl(tvb,offset+44)){
1688 case ISCSI_OPCODE_LOGIN_COMMAND:
1689 /* top two bits in byte 0 must be 0x40 */
1690 if((tvb_get_guint8(tvb, offset+0)&0xc0)!=0x40){
1694 /* exactly one of the T and C bits must be set
1695 * and the two reserved bits in byte 1 must be 0
1697 tmpbyte=tvb_get_guint8(tvb, offset+1);
1698 switch(tmpbyte&0xf0){
1705 /* CSG and NSG must not be 2 */
1706 if(((tmpbyte&0x03)==0x02)
1707 || ((tmpbyte&0xc0)==0x08)){
1710 /* if T bit is set NSG must not be 0 */
1712 if(!(tmpbyte&0x03)){
1716 /* should we test that datasegmentlen is non zero? */
1718 case ISCSI_OPCODE_LOGIN_RESPONSE:
1719 /* top two bits in byte 0 must be 0 */
1720 if(tvb_get_guint8(tvb, offset+0)&0xc0){
1724 /* both the T and C bits can not be set
1725 * and the two reserved bits in byte 1 must be 0
1727 tmpbyte=tvb_get_guint8(tvb, offset+1);
1728 switch(tmpbyte&0xf0){
1736 /* CSG and NSG must not be 2 */
1737 if(((tmpbyte&0x03)==0x02)
1738 || ((tmpbyte&0xc0)==0x08)){
1741 /* if T bit is set NSG must not be 0 */
1743 if(!(tmpbyte&0x03)){
1747 /* the 32bit words at offsets 20, 40, 44 must be zero */
1748 if(tvb_get_letohl(tvb,offset+20)
1749 || tvb_get_letohl(tvb,offset+40)
1750 || tvb_get_letohl(tvb,offset+44)){
1753 /* the two bytes at offset 38 must be zero */
1754 if(tvb_get_letohs(tvb,offset+38)){
1757 /* should we test that datasegmentlen is non zero unless we just
1758 * entered full featured phase?
1761 case ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION:
1762 /* top bit in byte 0 must be 0 */
1763 if(tvb_get_guint8(tvb, offset+0)&0x80){
1766 /* top bit in byte 1 must be set */
1767 tmpbyte=tvb_get_guint8(tvb, offset+1);
1768 if(!(tmpbyte&0x80)){
1771 /* Function must be known */
1772 if(!match_strval(tmpbyte&0x7f, iscsi_task_management_functions)){
1775 /* bytes 2,3 must be null */
1776 if(tvb_get_letohs(tvb,offset+2)){
1779 /* ahs and dsl must be null */
1780 if(tvb_get_letohl(tvb,offset+4)){
1784 case ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE:
1785 /* top two bits in byte 0 must be 0 */
1786 if(tvb_get_guint8(tvb, offset+0)&0xc0){
1789 /* byte 1 must be 0x80 */
1790 if(tvb_get_guint8(tvb, offset+1)!=0x80){
1793 /* response must be 0-6 or 255 */
1794 tmpbyte=tvb_get_guint8(tvb,offset+2);
1795 if(tmpbyte>6 && tmpbyte<255){
1798 /* byte 3 must be 0 */
1799 if(tvb_get_guint8(tvb,offset+3)){
1802 /* ahs and dsl as well as the 32bit words at offsets 8, 12, 20, 36
1803 * 40, 44 must all be 0
1805 if(tvb_get_letohl(tvb,offset+4)
1806 || tvb_get_letohl(tvb,offset+8)
1807 || tvb_get_letohl(tvb,offset+12)
1808 || tvb_get_letohl(tvb,offset+20)
1809 || tvb_get_letohl(tvb,offset+36)
1810 || tvb_get_letohl(tvb,offset+40)
1811 || tvb_get_letohl(tvb,offset+44)){
1815 case ISCSI_OPCODE_LOGOUT_COMMAND:
1816 /* top bit in byte 0 must be 0 */
1817 if(tvb_get_guint8(tvb, offset+0)&0x80){
1820 /* top bit in byte 1 must be set */
1821 tmpbyte=tvb_get_guint8(tvb, offset+1);
1822 if(!(tmpbyte&0x80)){
1825 /* Reason code must be known */
1826 if(!match_strval(tmpbyte&0x7f, iscsi_logout_reasons)){
1829 /* bytes 2,3 must be null */
1830 if(tvb_get_letohs(tvb,offset+2)){
1833 /* ahs and dsl as well as the 32bit words at offsets 8, 12, 32, 36
1834 * 40, 44 must all be 0
1836 if(tvb_get_letohl(tvb,offset+4)
1837 || tvb_get_letohl(tvb,offset+8)
1838 || tvb_get_letohl(tvb,offset+12)
1839 || tvb_get_letohl(tvb,offset+32)
1840 || tvb_get_letohl(tvb,offset+36)
1841 || tvb_get_letohl(tvb,offset+40)
1842 || tvb_get_letohl(tvb,offset+44)){
1846 case ISCSI_OPCODE_SNACK_REQUEST:
1847 /* top two bits in byte 0 must be 0 */
1848 if(tvb_get_guint8(tvb, offset+0)&0xc0){
1851 /* top 4 bits in byte 1 must be 0x80 */
1852 tmpbyte=tvb_get_guint8(tvb, offset+1);
1853 if((tmpbyte&0xf0)!=0x80){
1856 /* type must be known */
1857 if(!match_strval(tmpbyte&0x0f, iscsi_snack_types)){
1860 /* for status/snack and datack itt must be 0xffffffff
1861 * for rdata/snack ttt must not be 0 or 0xffffffff
1863 switch(tmpbyte&0x0f){
1866 if(tvb_get_letohl(tvb,offset+16)!=0xffffffff){
1871 if(tvb_get_letohl(tvb,offset+20)==0xffffffff){
1874 if(tvb_get_letohl(tvb,offset+20)==0){
1879 /* bytes 2,3 must be null */
1880 if(tvb_get_letohs(tvb,offset+2)){
1883 /* the 32bit words at offsets 24, 32, 36
1886 if(tvb_get_letohl(tvb,offset+24)
1887 || tvb_get_letohl(tvb,offset+32)
1888 || tvb_get_letohl(tvb,offset+36)){
1893 case ISCSI_OPCODE_R2T:
1894 /* top two bits in byte 0 must be 0 */
1895 if(tvb_get_guint8(tvb, offset+0)&0xc0){
1898 /* byte 1 must be 0x80 */
1899 if(tvb_get_guint8(tvb, offset+1)!=0x80){
1902 /* bytes 2,3 must be null */
1903 if(tvb_get_letohs(tvb,offset+2)){
1906 /* ahs and dsl must be null */
1907 if(tvb_get_letohl(tvb,offset+4)){
1910 /* desired data transfer length must not be null */
1911 if(!tvb_get_letohl(tvb,offset+44)){
1915 case ISCSI_OPCODE_REJECT:
1916 /* top two bits in byte 0 must be 0 */
1917 if(tvb_get_guint8(tvb, offset+0)&0xc0){
1920 /* byte 1 must be 0x80 */
1921 if(tvb_get_guint8(tvb, offset+1)!=0x80){
1924 /* reason must be known */
1925 if(!match_strval(tvb_get_guint8(tvb,offset+2), iscsi_reject_reasons)){
1928 /* byte 3 must be 0 */
1929 if(tvb_get_guint8(tvb, offset+3)){
1932 /* the 32bit words at offsets 8, 12, 20, 40, 44
1935 if(tvb_get_letohl(tvb,offset+8)
1936 || tvb_get_letohl(tvb,offset+12)
1937 || tvb_get_letohl(tvb,offset+20)
1938 || tvb_get_letohl(tvb,offset+40)
1939 || tvb_get_letohl(tvb,offset+44)){
1942 /* the 32bit word at 16 must be 0xffffffff */
1943 if(tvb_get_letohl(tvb,offset+16)!=0xffffffff){
1947 case ISCSI_OPCODE_TEXT_COMMAND:
1948 /* top bit in byte 0 must be 0 */
1949 if(tvb_get_guint8(tvb, offset+0)&0x80){
1952 /* one of the F and C bits must be set but not both
1953 * low 6 bits in byte 1 must be 0
1955 switch(tvb_get_guint8(tvb,offset+1)){
1962 /* bytes 2,3 must be null */
1963 if(tvb_get_letohs(tvb,offset+2)){
1966 /* the 32bit words at offsets 32, 36, 40, 44
1969 if(tvb_get_letohl(tvb,offset+32)
1970 || tvb_get_letohl(tvb,offset+36)
1971 || tvb_get_letohl(tvb,offset+40)
1972 || tvb_get_letohl(tvb,offset+44)){
1976 case ISCSI_OPCODE_TEXT_RESPONSE:
1977 /* top two bits in byte 0 must be 0 */
1978 if(tvb_get_guint8(tvb, offset+0)&0xc0){
1981 /* one of the F and C bits must be set but not both
1982 * low 6 bits in byte 1 must be 0
1984 switch(tvb_get_guint8(tvb,offset+1)){
1991 /* bytes 2,3 must be null */
1992 if(tvb_get_letohs(tvb,offset+2)){
1995 /* the 32bit words at offsets 36, 40, 44
1998 if(tvb_get_letohl(tvb,offset+36)
1999 || tvb_get_letohl(tvb,offset+40)
2000 || tvb_get_letohl(tvb,offset+44)){
2004 case ISCSI_OPCODE_SCSI_COMMAND:
2005 /* top bit in byte 0 must be 0 */
2006 if(tvb_get_guint8(tvb, offset+0)&0x80){
2009 /* reserved bits in byte 1 must be 0 */
2010 if(tvb_get_guint8(tvb, offset+1)&0x18){
2013 /* bytes 2,3 must be null */
2014 if(tvb_get_letohs(tvb,offset+2)){
2017 /* expected data transfer length is never >16MByte ? */
2018 if(tvb_get_guint8(tvb,offset+20)){
2022 case ISCSI_OPCODE_SCSI_RESPONSE:
2023 /* top two bits in byte 0 must be 0 */
2024 if(tvb_get_guint8(tvb, offset+0)&0xc0){
2027 /* top bit in byte 1 must be 1 */
2028 tmpbyte=tvb_get_guint8(tvb,offset+1);
2029 if(!(tmpbyte&0x80)){
2032 /* the reserved bits in byte 1 must be 0 */
2036 /* status must be known */
2037 if(!match_strval(tvb_get_guint8(tvb,offset+3), scsi_status_val)){
2040 /* the 32bit words at offsets 8, 12
2043 if(tvb_get_letohl(tvb,offset+8)
2044 || tvb_get_letohl(tvb,offset+12)){
2048 case ISCSI_OPCODE_ASYNC_MESSAGE:
2049 /* top two bits in byte 0 must be 0 */
2050 if(tvb_get_guint8(tvb, offset+0)&0xc0){
2053 /* byte 1 must be 0x80 */
2054 if(tvb_get_guint8(tvb, offset+1)!=0x80){
2057 /* bytes 2,3 must be null */
2058 if(tvb_get_letohs(tvb,offset+2)){
2061 /* the 32bit words at offsets 20, 44
2064 if(tvb_get_letohl(tvb,offset+20)
2065 || tvb_get_letohl(tvb,offset+44)){
2068 /* the 32bit word at 16 must be 0xffffffff */
2069 if(tvb_get_letohl(tvb,offset+16)!=0xffffffff){
2073 case ISCSI_OPCODE_LOGOUT_RESPONSE:
2074 /* top two bits in byte 0 must be 0 */
2075 if(tvb_get_guint8(tvb, offset+0)&0xc0){
2078 /* byte 1 must be 0x80 */
2079 if(tvb_get_guint8(tvb, offset+1)!=0x80){
2082 /* response must be known */
2083 if(!match_strval(tvb_get_guint8(tvb,offset+2), iscsi_logout_response)){
2086 /* byte 3 must be 0 */
2087 if(tvb_get_guint8(tvb,offset+3)){
2090 /* ahs and dsl as well as the 32bit words at offsets 8, 12, 20, 36
2093 if(tvb_get_letohl(tvb,offset+4)
2094 || tvb_get_letohl(tvb,offset+8)
2095 || tvb_get_letohl(tvb,offset+12)
2096 || tvb_get_letohl(tvb,offset+20)
2097 || tvb_get_letohl(tvb,offset+36)
2098 || tvb_get_letohl(tvb,offset+44)){
2102 case ISCSI_OPCODE_SCSI_DATA_OUT:
2103 /* top two bits in byte 0 must be 0 */
2104 if(tvb_get_guint8(tvb, offset+0)&0xc0){
2107 /* low 7 bits in byte 1 must be 0 */
2108 if(tvb_get_guint8(tvb,offset+1)&0x7f){
2111 /* bytes 2,3 must be null */
2112 if(tvb_get_letohs(tvb,offset+2)){
2115 /* the 32bit words at offsets 24, 32, 44
2118 if(tvb_get_letohl(tvb,offset+24)
2119 || tvb_get_letohl(tvb,offset+32)
2120 || tvb_get_letohl(tvb,offset+44)){
2124 case ISCSI_OPCODE_SCSI_DATA_IN:
2125 /* top two bits in byte 0 must be 0 */
2126 if(tvb_get_guint8(tvb, offset+0)&0xc0){
2129 /* reserved bits in byte 1 must be 0 */
2130 if(tvb_get_guint8(tvb,offset+1)&0x38){
2133 /* byte 2 must be reserved */
2134 if(tvb_get_guint8(tvb,offset+2)){
2138 case ISCSI_OPCODE_VENDOR_SPECIFIC_I0:
2139 case ISCSI_OPCODE_VENDOR_SPECIFIC_I1:
2140 case ISCSI_OPCODE_VENDOR_SPECIFIC_I2:
2141 case ISCSI_OPCODE_VENDOR_SPECIFIC_T0:
2142 case ISCSI_OPCODE_VENDOR_SPECIFIC_T1:
2143 case ISCSI_OPCODE_VENDOR_SPECIFIC_T2:
2150 /* process multiple iSCSI PDUs per packet */
2151 while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
2152 const char *opcode_str = NULL;
2153 guint32 data_segment_len;
2154 guint32 pduLen = 48;
2155 guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
2159 /* mask out any extra bits in the opcode byte */
2160 opcode = tvb_get_guint8(tvb, offset + 0);
2161 opcode &= OPCODE_MASK;
2163 opcode_str = match_strval(opcode, iscsi_opcodes);
2164 if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
2165 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
2166 opcode == ISCSI_OPCODE_R2T ||
2167 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
2168 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
2169 opcode == ISCSI_OPCODE_SNACK_REQUEST)
2170 data_segment_len = 0;
2172 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
2174 if(opcode_str == NULL) {
2177 else if(check_port && iscsi_port != 0 &&
2178 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
2179 (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
2182 else if(enable_bogosity_filter) {
2183 /* try and distinguish between data and real headers */
2184 if(data_segment_len > bogus_pdu_data_length_threshold) {
2187 else if(demand_good_f_bit &&
2188 !(secondPduByte & 0x80) &&
2189 (opcode == ISCSI_OPCODE_NOP_OUT ||
2190 opcode == ISCSI_OPCODE_NOP_IN ||
2191 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
2192 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
2193 opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
2194 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
2195 opcode == ISCSI_OPCODE_R2T ||
2196 opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
2197 opcode == ISCSI_OPCODE_SNACK_REQUEST ||
2198 opcode == ISCSI_OPCODE_REJECT)) {
2200 } else if(opcode==ISCSI_OPCODE_NOP_OUT) {
2201 /* TransferTag for NOP-Out should either be -1 or
2202 the tag value we want for a response.
2203 Assume 0 means we are just inside a big all zero
2206 if(tvb_get_ntohl(tvb, offset+20)==0){
2213 return iSCSIPdusDissected > 0;
2216 if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
2217 opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
2218 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
2219 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
2220 /* digests are not yet turned on */
2228 if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
2230 ahsLen = tvb_get_guint8(tvb, offset + 4);
2231 pduLen += ahsLen * 4;
2234 pduLen += data_segment_len;
2235 if((pduLen & 3) != 0)
2236 pduLen += 4 - (pduLen & 3);
2239 if(digestsActive && data_segment_len > 0 && enableDataDigests) {
2240 if(dataDigestIsCRC32)
2243 pduLen += dataDigestSize;
2246 /* make sure we have a conversation for this session */
2247 conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
2248 pinfo->ptype, pinfo->srcport,
2249 pinfo->destport, 0);
2250 if (!conversation) {
2251 conversation = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst,
2252 pinfo->ptype, pinfo->srcport,
2253 pinfo->destport, 0);
2255 iscsi_session=conversation_get_proto_data(conversation, proto_iscsi);
2257 iscsi_session=se_alloc(sizeof(iscsi_session_t));
2258 iscsi_session->header_digest=ISCSI_HEADER_DIGEST_AUTO;
2259 iscsi_session->itlq=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "iSCSI ITLQ");
2260 iscsi_session->itl=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "iSCSI ITL");
2261 conversation_add_proto_data(conversation, proto_iscsi, iscsi_session);
2263 /* DataOut PDUs are often mistaken by DCERPC heuristics to be
2264 * that protocol. Now that we know this is iscsi, set a
2265 * dissector for this conversation to block other heuristic
2268 conversation_set_dissector(conversation, iscsi_handle);
2270 /* try to autodetect if header digest is used or not */
2271 if(digestsActive && (available_bytes>=(48+4+ahsLen*4)) && (iscsi_session->header_digest==ISCSI_HEADER_DIGEST_AUTO) ){
2273 /* we have enough data to test if HeaderDigest is enabled */
2274 crc= ~calculateCRC32(tvb_get_ptr(tvb, offset, 48+ahsLen*4), 48+ahsLen*4, CRC32C_PRELOAD);
2275 if(crc==tvb_get_ntohl(tvb,48+ahsLen*4)){
2276 iscsi_session->header_digest=ISCSI_HEADER_DIGEST_CRC32;
2278 iscsi_session->header_digest=ISCSI_HEADER_DIGEST_NONE;
2283 /* Add header digest length to pdulen */
2285 switch(iscsi_session->header_digest){
2286 case ISCSI_HEADER_DIGEST_CRC32:
2289 case ISCSI_HEADER_DIGEST_NONE:
2291 case ISCSI_HEADER_DIGEST_AUTO:
2292 /* oops we didnt know what digest is used yet */
2293 /* here we should use some default */
2296 DISSECTOR_ASSERT_NOT_REACHED();
2301 * Desegmentation check.
2303 if(iscsi_desegment && pinfo->can_desegment) {
2304 if(pduLen > available_bytes) {
2306 * This frame doesn't have all of the data for
2307 * this message, but we can do reassembly on it.
2309 * Tell the TCP dissector where the data for this
2310 * message starts in the data it handed us, and
2311 * how many more bytes we need, and return.
2313 pinfo->desegment_offset = offset;
2314 pinfo->desegment_len = pduLen - available_bytes;
2319 /* This is to help TCP keep track of PDU boundaries
2320 and allows it to find PDUs that are not aligned to
2321 the start of a TCP segments.
2322 Since it also allows TCP to know what is in the middle
2323 of a large PDU, it reduces the probability of a segment
2324 in the middle of a large PDU transfer being misdissected as
2327 if(!pinfo->fd->flags.visited){
2328 if(pduLen>(guint32)tvb_reported_length_remaining(tvb, offset)){
2329 pinfo->want_pdu_tracking=2;
2330 pinfo->bytes_until_next_pdu=pduLen-tvb_reported_length_remaining(tvb, offset);
2334 if(check_col(pinfo->cinfo, COL_INFO)) {
2335 if(iSCSIPdusDissected == 0)
2336 col_set_str(pinfo->cinfo, COL_INFO, "");
2338 col_append_str(pinfo->cinfo, COL_INFO, ", ");
2341 dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len, iscsi_session);
2342 if(pduLen > available_bytes)
2343 pduLen = available_bytes;
2345 available_bytes -= pduLen;
2346 ++iSCSIPdusDissected;
2349 return iSCSIPdusDissected > 0;
2352 /* This is called for those sessions where we have explicitely said
2353 this to be iSCSI using "Decode As..."
2354 In this case we will not check the port number for sanity and just
2355 do as the user said.
2356 We still check that the PDU header looks sane though.
2359 dissect_iscsi_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2360 return dissect_iscsi(tvb, pinfo, tree, FALSE);
2363 /* This is called through the heuristic handler.
2364 In this case we also want to check that the port matches the preference
2365 setting for iSCSI in order to reduce the number of
2369 dissect_iscsi_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2370 return dissect_iscsi(tvb, pinfo, tree, TRUE);
2374 /* Register the protocol with Wireshark */
2377 * this format is require because a script is used to build the C
2378 * function that calls all the protocol registration.
2382 proto_register_iscsi(void)
2385 /* Setup list of header fields See Section 1.6.1 for details*/
2386 static hf_register_info hf[] = {
2387 { &hf_iscsi_request_frame,
2388 { "Request in", "iscsi.request_frame",
2389 FT_FRAMENUM, BASE_NONE, NULL, 0,
2390 "The request to this transaction is in this frame", HFILL }},
2393 { "Time from request", "iscsi.time",
2394 FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
2395 "Time between the Command and the Response", HFILL }},
2397 { &hf_iscsi_data_in_frame,
2398 { "Data In in", "iscsi.data_in_frame",
2399 FT_FRAMENUM, BASE_NONE, NULL, 0,
2400 "The Data In for this transaction is in this frame", HFILL }},
2402 { &hf_iscsi_data_out_frame,
2403 { "Data Out in", "iscsi.data_out_frame",
2404 FT_FRAMENUM, BASE_NONE, NULL, 0,
2405 "The Data Out for this transaction is in this frame", HFILL }},
2407 { &hf_iscsi_response_frame,
2408 { "Response in", "iscsi.response_frame",
2409 FT_FRAMENUM, BASE_NONE, NULL, 0,
2410 "The response to this transaction is in this frame", HFILL }},
2413 { "AHS", "iscsi.ahs",
2414 FT_BYTES, BASE_HEX, NULL, 0,
2415 "Additional header segment", HFILL }
2417 { &hf_iscsi_AHS_length,
2418 { "AHS Length", "iscsi.ahs.length",
2419 FT_UINT16, BASE_DEC, NULL, 0,
2420 "Length of Additional header segment", HFILL }
2422 { &hf_iscsi_AHS_type,
2423 { "AHS Type", "iscsi.ahs.type",
2424 FT_UINT8, BASE_DEC, VALS(ahs_type_vals), 0,
2425 "Type of Additional header segment", HFILL }
2427 { &hf_iscsi_AHS_specific,
2428 { "AHS Specific", "iscsi.ahs",
2429 FT_UINT8, BASE_HEX, NULL, 0,
2430 "Specific qualifier of Additional header segment", HFILL }
2432 { &hf_iscsi_Padding,
2433 { "Padding", "iscsi.padding",
2434 FT_BYTES, BASE_HEX, NULL, 0,
2435 "Padding to 4 byte boundary", HFILL }
2437 { &hf_iscsi_ping_data,
2438 { "PingData", "iscsi.pingdata",
2439 FT_BYTES, BASE_HEX, NULL, 0,
2440 "Ping Data", HFILL }
2442 { &hf_iscsi_immediate_data,
2443 { "ImmediateData", "iscsi.immediatedata",
2444 FT_BYTES, BASE_HEX, NULL, 0,
2445 "Immediate Data", HFILL }
2447 { &hf_iscsi_write_data,
2448 { "WriteData", "iscsi.writedata",
2449 FT_BYTES, BASE_HEX, NULL, 0,
2450 "Write Data", HFILL }
2452 { &hf_iscsi_read_data,
2453 { "ReadData", "iscsi.readdata",
2454 FT_BYTES, BASE_HEX, NULL, 0,
2455 "Read Data", HFILL }
2457 { &hf_iscsi_error_pdu_data,
2458 { "ErrorPDUData", "iscsi.errorpdudata",
2459 FT_BYTES, BASE_HEX, NULL, 0,
2460 "Error PDU Data", HFILL }
2462 { &hf_iscsi_async_message_data,
2463 { "AsyncMessageData", "iscsi.asyncmessagedata",
2464 FT_BYTES, BASE_HEX, NULL, 0,
2465 "Async Message Data", HFILL }
2467 { &hf_iscsi_vendor_specific_data,
2468 { "VendorSpecificData", "iscsi.vendorspecificdata",
2469 FT_BYTES, BASE_HEX, NULL, 0,
2470 "Vendor Specific Data", HFILL }
2472 { &hf_iscsi_HeaderDigest32,
2473 { "HeaderDigest", "iscsi.headerdigest32",
2474 FT_UINT32, BASE_HEX, NULL, 0,
2475 "Header Digest", HFILL }
2477 { &hf_iscsi_DataDigest,
2478 { "DataDigest", "iscsi.datadigest",
2479 FT_BYTES, BASE_HEX, NULL, 0,
2480 "Data Digest", HFILL }
2482 { &hf_iscsi_DataDigest32,
2483 { "DataDigest", "iscsi.datadigest32",
2484 FT_UINT32, BASE_HEX, NULL, 0,
2485 "Data Digest", HFILL }
2488 { "Opcode", "iscsi.opcode",
2489 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
2492 /* #ifdef DRAFT08 */
2495 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
2496 "Command Retry", HFILL }
2501 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
2502 "Immediate delivery", HFILL }
2505 { "Flags", "iscsi.flags",
2506 FT_UINT8, BASE_HEX, NULL, 0,
2507 "Opcode specific flags", HFILL }
2509 { &hf_iscsi_SCSICommand_F,
2510 { "F", "iscsi.scsicommand.F",
2511 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2512 "PDU completes command", HFILL }
2514 { &hf_iscsi_SCSICommand_R,
2515 { "R", "iscsi.scsicommand.R",
2516 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
2517 "Command reads from SCSI target", HFILL }
2519 { &hf_iscsi_SCSICommand_W,
2520 { "W", "iscsi.scsicommand.W",
2521 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
2522 "Command writes to SCSI target", HFILL }
2524 { &hf_iscsi_SCSICommand_Attr,
2525 { "Attr", "iscsi.scsicommand.attr",
2526 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
2527 "SCSI task attributes", HFILL }
2529 { &hf_iscsi_SCSICommand_CRN,
2530 { "CRN", "iscsi.scsicommand.crn",
2531 FT_UINT8, BASE_HEX, NULL, 0,
2532 "SCSI command reference number", HFILL }
2534 { &hf_iscsi_SCSICommand_AddCDB,
2535 { "AddCDB", "iscsi.scsicommand.addcdb",
2536 FT_UINT8, BASE_HEX, NULL, 0,
2537 "Additional CDB length (in 4 byte units)", HFILL }
2539 { &hf_iscsi_DataSegmentLength,
2540 { "DataSegmentLength", "iscsi.datasegmentlength",
2541 FT_UINT32, BASE_HEX, NULL, 0,
2542 "Data segment length (bytes)", HFILL }
2544 { &hf_iscsi_TotalAHSLength,
2545 { "TotalAHSLength", "iscsi.totalahslength",
2546 FT_UINT8, BASE_HEX, NULL, 0,
2547 "Total additional header segment length (4 byte words)", HFILL }
2550 { "LUN", "iscsi.lun",
2551 FT_BYTES, BASE_HEX, NULL, 0,
2552 "Logical Unit Number", HFILL }
2554 { &hf_iscsi_InitiatorTaskTag,
2555 { "InitiatorTaskTag", "iscsi.initiatortasktag",
2556 FT_UINT32, BASE_HEX, NULL, 0,
2557 "Initiator's task tag", HFILL }
2559 { &hf_iscsi_ExpectedDataTransferLength,
2560 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
2561 FT_UINT32, BASE_HEX, NULL, 0,
2562 "Expected length of data transfer", HFILL }
2565 { "CmdSN", "iscsi.cmdsn",
2566 FT_UINT32, BASE_HEX, NULL, 0,
2567 "Sequence number for this command", HFILL }
2569 { &hf_iscsi_ExpStatSN,
2570 { "ExpStatSN", "iscsi.expstatsn",
2571 FT_UINT32, BASE_HEX, NULL, 0,
2572 "Next expected status sequence number", HFILL }
2574 { &hf_iscsi_SCSIResponse_ResidualCount,
2575 { "ResidualCount", "iscsi.scsiresponse.residualcount",
2576 FT_UINT32, BASE_HEX, NULL, 0,
2577 "Residual count", HFILL }
2580 { "StatSN", "iscsi.statsn",
2581 FT_UINT32, BASE_HEX, NULL, 0,
2582 "Status sequence number", HFILL }
2584 { &hf_iscsi_ExpCmdSN,
2585 { "ExpCmdSN", "iscsi.expcmdsn",
2586 FT_UINT32, BASE_HEX, NULL, 0,
2587 "Next expected command sequence number", HFILL }
2589 { &hf_iscsi_MaxCmdSN,
2590 { "MaxCmdSN", "iscsi.maxcmdsn",
2591 FT_UINT32, BASE_HEX, NULL, 0,
2592 "Maximum acceptable command sequence number", HFILL }
2594 { &hf_iscsi_SCSIResponse_o,
2595 { "o", "iscsi.scsiresponse.o",
2596 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
2597 "Bi-directional read residual overflow", HFILL }
2599 { &hf_iscsi_SCSIResponse_u,
2600 { "u", "iscsi.scsiresponse.u",
2601 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
2602 "Bi-directional read residual underflow", HFILL }
2604 { &hf_iscsi_SCSIResponse_O,
2605 { "O", "iscsi.scsiresponse.O",
2606 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
2607 "Residual overflow", HFILL }
2609 { &hf_iscsi_SCSIResponse_U,
2610 { "U", "iscsi.scsiresponse.U",
2611 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
2612 "Residual underflow", HFILL }
2614 { &hf_iscsi_SCSIResponse_Status,
2615 { "Status", "iscsi.scsiresponse.status",
2616 FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
2617 "SCSI command status value", HFILL }
2619 { &hf_iscsi_SCSIResponse_Response,
2620 { "Response", "iscsi.scsiresponse.response",
2621 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
2622 "SCSI command response value", HFILL }
2624 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
2625 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
2626 FT_UINT32, BASE_HEX, NULL, 0,
2627 "Bi-directional read residual count", HFILL }
2629 { &hf_iscsi_SenseLength,
2630 { "SenseLength", "iscsi.scsiresponse.senselength",
2631 FT_UINT16, BASE_HEX, NULL, 0,
2632 "Sense data length", HFILL }
2634 { &hf_iscsi_SCSIData_F,
2635 { "F", "iscsi.scsidata.F",
2636 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
2637 "Final PDU", HFILL }
2639 { &hf_iscsi_SCSIData_A,
2640 { "A", "iscsi.scsidata.A",
2641 FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
2642 "Acknowledge Requested", HFILL }
2644 { &hf_iscsi_SCSIData_S,
2645 { "S", "iscsi.scsidata.S",
2646 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
2647 "PDU Contains SCSI command status", HFILL }
2649 { &hf_iscsi_SCSIData_U,
2650 { "U", "iscsi.scsidata.U",
2651 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
2652 "Residual underflow", HFILL }
2654 { &hf_iscsi_SCSIData_O,
2655 { "O", "iscsi.scsidata.O",
2656 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
2657 "Residual overflow", HFILL }
2659 { &hf_iscsi_TargetTransferTag,
2660 { "TargetTransferTag", "iscsi.targettransfertag",
2661 FT_UINT32, BASE_HEX, NULL, 0,
2662 "Target transfer tag", HFILL }
2664 { &hf_iscsi_BufferOffset,
2665 { "BufferOffset", "iscsi.bufferOffset",
2666 FT_UINT32, BASE_HEX, NULL, 0,
2667 "Buffer offset", HFILL }
2669 { &hf_iscsi_SCSIData_ResidualCount,
2670 { "ResidualCount", "iscsi.scsidata.readresidualcount",
2671 FT_UINT32, BASE_HEX, NULL, 0,
2672 "Residual count", HFILL }
2675 { "DataSN", "iscsi.datasn",
2676 FT_UINT32, BASE_HEX, NULL, 0,
2677 "Data sequence number", HFILL }
2679 { &hf_iscsi_VersionMax,
2680 { "VersionMax", "iscsi.versionmax",
2681 FT_UINT8, BASE_HEX, NULL, 0,
2682 "Maximum supported protocol version", HFILL }
2684 { &hf_iscsi_VersionMin,
2685 { "VersionMin", "iscsi.versionmin",
2686 FT_UINT8, BASE_HEX, NULL, 0,
2687 "Minimum supported protocol version", HFILL }
2689 { &hf_iscsi_VersionActive,
2690 { "VersionActive", "iscsi.versionactive",
2691 FT_UINT8, BASE_HEX, NULL, 0,
2692 "Negotiated protocol version", HFILL }
2695 { "CID", "iscsi.cid",
2696 FT_UINT16, BASE_HEX, NULL, 0,
2697 "Connection identifier", HFILL }
2699 /* #ifdef DRAFT08 */
2701 { "ISID", "iscsi.isid",
2702 FT_UINT16, BASE_HEX, NULL, 0,
2703 "Initiator part of session identifier", HFILL }
2707 { "ISID", "iscsi.isid",
2708 FT_BYTES, BASE_HEX, NULL, 0,
2709 "Initiator part of session identifier", HFILL }
2711 /* #ifdef DRAFT09 */
2712 { &hf_iscsi_ISID_Type,
2713 { "ISID_Type", "iscsi.isid.type",
2714 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
2715 "Initiator part of session identifier - type", HFILL }
2717 { &hf_iscsi_ISID_NamingAuthority,
2718 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
2719 FT_UINT24, BASE_HEX, NULL, 0,
2720 "Initiator part of session identifier - naming authority", HFILL }
2722 { &hf_iscsi_ISID_Qualifier,
2723 { "ISID_Qualifier", "iscsi.isid.qualifier",
2724 FT_UINT8, BASE_HEX, NULL, 0,
2725 "Initiator part of session identifier - qualifier", HFILL }
2729 { "ISID_t", "iscsi.isid.t",
2730 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
2731 "Initiator part of session identifier - t", HFILL }
2734 { "ISID_a", "iscsi.isid.a",
2735 FT_UINT8, BASE_HEX, NULL, 0x3f,
2736 "Initiator part of session identifier - a", HFILL }
2739 { "ISID_b", "iscsi.isid.b",
2740 FT_UINT16, BASE_HEX, NULL, 0,
2741 "Initiator part of session identifier - b", HFILL }
2744 { "ISID_c", "iscsi.isid.c",
2745 FT_UINT8, BASE_HEX, NULL, 0,
2746 "Initiator part of session identifier - c", HFILL }
2749 { "ISID_d", "iscsi.isid.d",
2750 FT_UINT16, BASE_HEX, NULL, 0,
2751 "Initiator part of session identifier - d", HFILL }
2756 { "TSID", "iscsi.tsid",
2757 FT_UINT16, BASE_HEX, NULL, 0,
2758 "Target part of session identifier", HFILL }
2761 { "TSIH", "iscsi.tsih",
2762 FT_UINT16, BASE_HEX, NULL, 0,
2763 "Target session identifying handle", HFILL }
2765 { &hf_iscsi_InitStatSN,
2766 { "InitStatSN", "iscsi.initstatsn",
2767 FT_UINT32, BASE_HEX, NULL, 0,
2768 "Initial status sequence number", HFILL }
2770 { &hf_iscsi_InitCmdSN,
2771 { "InitCmdSN", "iscsi.initcmdsn",
2772 FT_UINT32, BASE_HEX, NULL, 0,
2773 "Initial command sequence number", HFILL }
2775 { &hf_iscsi_Login_T,
2776 { "T", "iscsi.login.T",
2777 FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
2778 "Transit to next login stage", HFILL }
2780 { &hf_iscsi_Login_C,
2781 { "C", "iscsi.login.C",
2782 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2783 "Text incomplete", HFILL }
2785 /* #ifdef DRAFT09 */
2786 { &hf_iscsi_Login_X,
2787 { "X", "iscsi.login.X",
2788 FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
2789 "Restart Connection", HFILL }
2792 { &hf_iscsi_Login_CSG,
2793 { "CSG", "iscsi.login.csg",
2794 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
2795 "Current stage", HFILL }
2797 { &hf_iscsi_Login_NSG,
2798 { "NSG", "iscsi.login.nsg",
2799 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
2800 "Next stage", HFILL }
2802 { &hf_iscsi_Login_Status,
2803 { "Status", "iscsi.login.status",
2804 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
2805 "Status class and detail", HFILL }
2807 { &hf_iscsi_KeyValue,
2808 { "KeyValue", "iscsi.keyvalue",
2809 FT_STRING, 0, NULL, 0,
2810 "Key/value pair", HFILL }
2813 { "F", "iscsi.text.F",
2814 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2815 "Final PDU in text sequence", HFILL }
2818 { "C", "iscsi.text.C",
2819 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2820 "Text incomplete", HFILL }
2822 { &hf_iscsi_ExpDataSN,
2823 { "ExpDataSN", "iscsi.expdatasn",
2824 FT_UINT32, BASE_HEX, NULL, 0,
2825 "Next expected data sequence number", HFILL }
2828 { "R2TSN", "iscsi.r2tsn",
2829 FT_UINT32, BASE_HEX, NULL, 0,
2830 "R2T PDU Number", HFILL }
2832 { &hf_iscsi_TaskManagementFunction_Response,
2833 { "Response", "iscsi.taskmanfun.response",
2834 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
2837 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
2838 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
2839 FT_UINT32, BASE_HEX, NULL, 0,
2840 "Referenced task tag", HFILL }
2842 { &hf_iscsi_RefCmdSN,
2843 { "RefCmdSN", "iscsi.refcmdsn",
2844 FT_UINT32, BASE_HEX, NULL, 0,
2845 "Command sequence number for command to be aborted", HFILL }
2847 { &hf_iscsi_TaskManagementFunction_Function,
2848 { "Function", "iscsi.taskmanfun.function",
2849 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
2850 "Requested task function", HFILL }
2852 { &hf_iscsi_Logout_Reason,
2853 { "Reason", "iscsi.logout.reason",
2854 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0x7F,
2855 "Reason for logout", HFILL }
2857 { &hf_iscsi_Logout_Response,
2858 { "Response", "iscsi.logout.response",
2859 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
2860 "Logout response", HFILL }
2862 { &hf_iscsi_Time2Wait,
2863 { "Time2Wait", "iscsi.time2wait",
2864 FT_UINT16, BASE_HEX, NULL, 0,
2865 "Time2Wait", HFILL }
2867 { &hf_iscsi_Time2Retain,
2868 { "Time2Retain", "iscsi.time2retain",
2869 FT_UINT16, BASE_HEX, NULL, 0,
2870 "Time2Retain", HFILL }
2872 { &hf_iscsi_DesiredDataLength,
2873 { "DesiredDataLength", "iscsi.desireddatalength",
2874 FT_UINT32, BASE_HEX, NULL, 0,
2875 "Desired data length (bytes)", HFILL }
2877 { &hf_iscsi_AsyncEvent,
2878 { "AsyncEvent", "iscsi.asyncevent",
2879 FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2880 "Async event type", HFILL }
2882 { &hf_iscsi_EventVendorCode,
2883 { "EventVendorCode", "iscsi.eventvendorcode",
2884 FT_UINT8, BASE_HEX, NULL, 0,
2885 "Event vendor code", HFILL }
2887 { &hf_iscsi_Parameter1,
2888 { "Parameter1", "iscsi.parameter1",
2889 FT_UINT16, BASE_HEX, NULL, 0,
2890 "Parameter 1", HFILL }
2892 { &hf_iscsi_Parameter2,
2893 { "Parameter2", "iscsi.parameter2",
2894 FT_UINT16, BASE_HEX, NULL, 0,
2895 "Parameter 2", HFILL }
2897 { &hf_iscsi_Parameter3,
2898 { "Parameter3", "iscsi.parameter3",
2899 FT_UINT16, BASE_HEX, NULL, 0,
2900 "Parameter 3", HFILL }
2902 { &hf_iscsi_Reject_Reason,
2903 { "Reason", "iscsi.reject.reason",
2904 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2905 "Reason for command rejection", HFILL }
2907 { &hf_iscsi_snack_type,
2908 { "S", "iscsi.snack.type",
2909 FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2910 "Type of SNACK requested", HFILL }
2913 { "BegRun", "iscsi.snack.begrun",
2914 FT_UINT32, BASE_HEX, NULL, 0,
2915 "First missed DataSN or StatSN", HFILL }
2917 { &hf_iscsi_RunLength,
2918 { "RunLength", "iscsi.snack.runlength",
2919 FT_UINT32, BASE_HEX, NULL, 0,
2920 "Number of additional missing status PDUs in this run", HFILL }
2924 /* Setup protocol subtree array */
2925 static gint *ett[] = {
2927 &ett_iscsi_KeyValues,
2930 /* #ifndef DRAFT08 */
2935 /* Register the protocol name and description */
2936 proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2938 /* Required function calls to register the header fields and
2940 proto_register_field_array(proto_iscsi, hf, array_length(hf));
2941 proto_register_subtree_array(ett, array_length(ett));
2944 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2946 prefs_register_enum_preference(iscsi_module,
2949 "The iSCSI protocol version",
2950 &iscsi_protocol_version,
2951 iscsi_protocol_versions,
2954 prefs_register_bool_preference(iscsi_module,
2955 "desegment_iscsi_messages",
2956 "Reassemble iSCSI messages\nspanning multiple TCP segments",
2957 "Whether the iSCSI dissector should reassemble messages spanning multiple TCP segments."
2958 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2961 prefs_register_bool_preference(iscsi_module,
2963 "Enable bogus pdu filter",
2964 "When enabled, packets that appear bogus are ignored",
2965 &enable_bogosity_filter);
2967 prefs_register_bool_preference(iscsi_module,
2968 "demand_good_f_bit",
2969 "Ignore packets with bad F bit",
2970 "Ignore packets that haven't set the F bit when they should have",
2971 &demand_good_f_bit);
2973 prefs_register_uint_preference(iscsi_module,
2974 "bogus_pdu_max_data_len",
2975 "Bogus pdu max data length threshold",
2976 "Treat packets whose data segment length is greater than this value as bogus",
2978 &bogus_pdu_data_length_threshold);
2981 prefs_register_uint_preference(iscsi_module,
2984 "Port number of iSCSI target",
2988 prefs_register_bool_preference(iscsi_module,
2989 "enable_data_digests",
2990 "Enable data digests",
2991 "When enabled, pdus are assumed to contain a data digest",
2992 &enableDataDigests);
2994 prefs_register_bool_preference(iscsi_module,
2995 "data_digest_is_crc32c",
2996 "Data digest is CRC32C",
2997 "When enabled, data digests are assumed to be CRC32C",
2998 &dataDigestIsCRC32);
3000 prefs_register_uint_preference(iscsi_module,
3003 "The size of a data digest (bytes)",
3007 /* Preference supported in older versions.
3008 Register them as obsolete. */
3009 prefs_register_obsolete_preference(iscsi_module,
3010 "version_03_compatible");
3011 prefs_register_obsolete_preference(iscsi_module,
3012 "bogus_pdu_max_digest_padding");
3013 prefs_register_obsolete_preference(iscsi_module,
3014 "header_digest_is_crc32c");
3015 prefs_register_obsolete_preference(iscsi_module,
3016 "header_digest_size");
3017 prefs_register_obsolete_preference(iscsi_module,
3018 "enable_header_digests");
3024 * If this dissector uses sub-dissector registration add a
3025 * registration routine.
3029 * This format is required because a script is used to find these
3030 * routines and create the code that calls these routines.
3033 proto_reg_handoff_iscsi(void)
3035 heur_dissector_add("tcp", dissect_iscsi_heur, proto_iscsi);
3037 iscsi_handle = new_create_dissector_handle(dissect_iscsi_handle, proto_iscsi);
3038 dissector_add_handle("tcp.port", iscsi_handle);