2 * Routines for iSCSI dissection
3 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
5 * $Id: packet-iscsi.c,v 1.43 2003/01/28 23:56:39 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/packet.h>
38 #include <epan/conversation.h>
39 #include "packet-scsi.h"
41 /* the absolute values of these constants don't matter as long as
42 * latter revisions of the protocol are assigned a larger number */
43 #define ISCSI_PROTOCOL_DRAFT08 1
44 #define ISCSI_PROTOCOL_DRAFT09 2
45 #define ISCSI_PROTOCOL_DRAFT11 3
46 #define ISCSI_PROTOCOL_DRAFT12 4
47 #define ISCSI_PROTOCOL_DRAFT13 5
49 static enum_val_t iscsi_protocol_versions[] = {
50 { "Draft 08", ISCSI_PROTOCOL_DRAFT08 },
51 { "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
52 { "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
53 { "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
54 { "Draft 13", ISCSI_PROTOCOL_DRAFT13 },
58 static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT13;
60 static gboolean iscsi_desegment = TRUE;
62 static int demand_good_f_bit = FALSE;
63 static int enable_bogosity_filter = TRUE;
64 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
66 static int enableDataDigests = FALSE;
67 static int enableHeaderDigests = FALSE;
69 static int dataDigestIsCRC32 = TRUE;
70 static int headerDigestIsCRC32 = TRUE;
72 static int dataDigestSize = 4;
73 static int headerDigestSize = 4;
75 static guint iscsi_port = 3260;
77 /* Initialize the protocol and registered fields */
78 static int proto_iscsi = -1;
79 static int hf_iscsi_AHS = -1;
80 static int hf_iscsi_Padding = -1;
81 static int hf_iscsi_ping_data = -1;
82 static int hf_iscsi_immediate_data = -1;
83 static int hf_iscsi_write_data = -1;
84 static int hf_iscsi_read_data = -1;
85 static int hf_iscsi_error_pdu_data = -1;
86 static int hf_iscsi_async_message_data = -1;
87 static int hf_iscsi_vendor_specific_data = -1;
88 static int hf_iscsi_Opcode = -1;
89 static int hf_iscsi_Flags = -1;
90 static int hf_iscsi_HeaderDigest = -1;
91 static int hf_iscsi_HeaderDigest32 = -1;
92 static int hf_iscsi_DataDigest = -1;
93 static int hf_iscsi_DataDigest32 = -1;
95 static int hf_iscsi_X = -1;
97 static int hf_iscsi_I = -1;
98 static int hf_iscsi_SCSICommand_F = -1;
99 static int hf_iscsi_SCSICommand_R = -1;
100 static int hf_iscsi_SCSICommand_W = -1;
101 static int hf_iscsi_SCSICommand_Attr = -1;
102 static int hf_iscsi_SCSICommand_CRN = -1;
103 static int hf_iscsi_SCSICommand_AddCDB = -1;
104 static int hf_iscsi_DataSegmentLength = -1;
105 static int hf_iscsi_TotalAHSLength = -1;
106 static int hf_iscsi_LUN = -1;
107 static int hf_iscsi_InitiatorTaskTag = -1;
108 static int hf_iscsi_ExpectedDataTransferLength = -1;
109 static int hf_iscsi_CmdSN = -1;
110 static int hf_iscsi_ExpStatSN = -1;
111 static int hf_iscsi_StatSN = -1;
112 static int hf_iscsi_ExpCmdSN = -1;
113 static int hf_iscsi_MaxCmdSN = -1;
114 static int hf_iscsi_SCSIResponse_o = -1;
115 static int hf_iscsi_SCSIResponse_u = -1;
116 static int hf_iscsi_SCSIResponse_O = -1;
117 static int hf_iscsi_SCSIResponse_U = -1;
118 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
119 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
120 static int hf_iscsi_SCSIResponse_Response = -1;
121 static int hf_iscsi_SCSIResponse_Status = -1;
122 static int hf_iscsi_SenseLength = -1;
123 static int hf_iscsi_SCSIData_F = -1;
124 static int hf_iscsi_SCSIData_A = -1;
125 static int hf_iscsi_SCSIData_S = -1;
126 static int hf_iscsi_SCSIData_O = -1;
127 static int hf_iscsi_SCSIData_U = -1;
128 static int hf_iscsi_TargetTransferTag = -1;
129 static int hf_iscsi_DataSN = -1;
130 static int hf_iscsi_BufferOffset = -1;
131 static int hf_iscsi_SCSIData_ResidualCount = -1;
132 static int hf_iscsi_VersionMin = -1;
133 static int hf_iscsi_VersionMax = -1;
134 static int hf_iscsi_VersionActive = -1;
135 static int hf_iscsi_CID = -1;
136 static int hf_iscsi_ISID8 = -1;
137 static int hf_iscsi_ISID = -1;
138 /* #if defined(DRAFT09) */
139 static int hf_iscsi_ISID_Type = -1;
140 static int hf_iscsi_ISID_NamingAuthority = -1;
141 static int hf_iscsi_ISID_Qualifier = -1;
142 /* #elif !defined(DRAFT08) */
143 static int hf_iscsi_ISID_t = -1;
144 static int hf_iscsi_ISID_a = -1;
145 static int hf_iscsi_ISID_b = -1;
146 static int hf_iscsi_ISID_c = -1;
147 static int hf_iscsi_ISID_d = -1;
149 static int hf_iscsi_TSID = -1;
150 static int hf_iscsi_TSIH = -1;
151 static int hf_iscsi_InitStatSN = -1;
152 static int hf_iscsi_InitCmdSN = -1;
154 static int hf_iscsi_Login_X = -1;
156 static int hf_iscsi_Login_C = -1;
157 static int hf_iscsi_Login_T = -1;
158 static int hf_iscsi_Login_CSG = -1;
159 static int hf_iscsi_Login_NSG = -1;
160 static int hf_iscsi_Login_Status = -1;
161 static int hf_iscsi_KeyValue = -1;
162 static int hf_iscsi_Text_C = -1;
163 static int hf_iscsi_Text_F = -1;
164 static int hf_iscsi_ExpDataSN = -1;
165 static int hf_iscsi_R2TSN = -1;
166 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
167 static int hf_iscsi_RefCmdSN = -1;
168 static int hf_iscsi_TaskManagementFunction_Function = -1;
169 static int hf_iscsi_TaskManagementFunction_Response = -1;
170 static int hf_iscsi_Logout_Reason = -1;
171 static int hf_iscsi_Logout_Response = -1;
172 static int hf_iscsi_Time2Wait = -1;
173 static int hf_iscsi_Time2Retain = -1;
174 static int hf_iscsi_DesiredDataLength = -1;
175 static int hf_iscsi_AsyncEvent = -1;
176 static int hf_iscsi_EventVendorCode = -1;
177 static int hf_iscsi_Parameter1 = -1;
178 static int hf_iscsi_Parameter2 = -1;
179 static int hf_iscsi_Parameter3 = -1;
180 static int hf_iscsi_Reject_Reason = -1;
181 static int hf_iscsi_snack_type = -1;
182 static int hf_iscsi_BegRun = -1;
183 static int hf_iscsi_RunLength = -1;
185 /* Initialize the subtree pointers */
186 static gint ett_iscsi = -1;
187 static gint ett_iscsi_KeyValues = -1;
188 static gint ett_iscsi_CDB = -1;
189 static gint ett_iscsi_Flags = -1;
190 /* #ifndef DRAFT08 */
191 static gint ett_iscsi_ISID = -1;
194 typedef struct _iscsi_conv_key {
199 typedef struct _iscsi_conv_data {
205 static GHashTable *iscsi_req_hash = NULL;
206 static GMemChunk *iscsi_req_keys = NULL;
207 static GMemChunk *iscsi_req_vals = NULL;
208 static guint32 iscsi_init_count = 25;
216 #define OPCODE_MASK 0x3f
218 #define TARGET_OPCODE_BIT 0x20
220 #define ISCSI_OPCODE_NOP_OUT 0x00
221 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
222 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
223 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
224 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
225 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
226 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
227 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
228 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
229 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
230 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
232 #define ISCSI_OPCODE_NOP_IN 0x20
233 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
234 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
235 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
236 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
237 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
238 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
239 #define ISCSI_OPCODE_R2T 0x31
240 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
241 #define ISCSI_OPCODE_REJECT 0x3f
242 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
243 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
244 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
247 #define CSG_MASK (0x03 << CSG_SHIFT)
248 #define NSG_MASK 0x03
250 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
251 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
252 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
254 #define ISCSI_SCSI_DATA_FLAG_S 0x01
255 #define ISCSI_SCSI_DATA_FLAG_U 0x02
256 #define ISCSI_SCSI_DATA_FLAG_O 0x04
257 #define ISCSI_SCSI_DATA_FLAG_A 0x40
258 #define ISCSI_SCSI_DATA_FLAG_F 0x80
260 static const value_string iscsi_opcodes[] = {
261 { ISCSI_OPCODE_NOP_OUT, "NOP Out" },
262 { ISCSI_OPCODE_SCSI_COMMAND, "SCSI Command" },
263 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION, "Task Management Function" },
264 { ISCSI_OPCODE_LOGIN_COMMAND, "Login Command" },
265 { ISCSI_OPCODE_TEXT_COMMAND, "Text Command" },
266 { ISCSI_OPCODE_SCSI_DATA_OUT, "SCSI Data Out" },
267 { ISCSI_OPCODE_LOGOUT_COMMAND, "Logout Command" },
268 { ISCSI_OPCODE_SNACK_REQUEST, "SNACK Request" },
269 { ISCSI_OPCODE_VENDOR_SPECIFIC_I0, "Vendor Specific I0" },
270 { ISCSI_OPCODE_VENDOR_SPECIFIC_I1, "Vendor Specific I1" },
271 { ISCSI_OPCODE_VENDOR_SPECIFIC_I2, "Vendor Specific I2" },
273 { ISCSI_OPCODE_NOP_IN, "NOP In" },
274 { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
275 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
276 { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
277 { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
278 { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
279 { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
280 { ISCSI_OPCODE_R2T, "Ready To Transfer" },
281 { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
282 { ISCSI_OPCODE_REJECT, "Reject"},
283 { ISCSI_OPCODE_VENDOR_SPECIFIC_T0, "Vendor Specific T0" },
284 { ISCSI_OPCODE_VENDOR_SPECIFIC_T1, "Vendor Specific T1" },
285 { ISCSI_OPCODE_VENDOR_SPECIFIC_T2, "Vendor Specific T2" },
290 static const true_false_string iscsi_meaning_X = {
297 static const true_false_string iscsi_meaning_login_X = {
298 "Reinstate failed connection",
303 static const true_false_string iscsi_meaning_I = {
304 "Immediate delivery",
308 static const true_false_string iscsi_meaning_F = {
309 "Final PDU in sequence",
310 "Not final PDU in sequence"
313 static const true_false_string iscsi_meaning_A = {
314 "Acknowledge requested",
315 "Acknowledge not requested"
318 static const true_false_string iscsi_meaning_T = {
319 "Transit to next login stage",
320 "Stay in current login stage"
323 static const true_false_string iscsi_meaning_C = {
324 "Text is incomplete",
328 static const true_false_string iscsi_meaning_S = {
329 "Response contains SCSI status",
330 "Response does not contain SCSI status"
333 static const true_false_string iscsi_meaning_R = {
334 "Data will be read from target",
335 "No data will be read from target"
338 static const true_false_string iscsi_meaning_W = {
339 "Data will be written to target",
340 "No data will be written to target"
343 static const true_false_string iscsi_meaning_o = {
344 "Read part of bi-directional command overflowed",
345 "No overflow of read part of bi-directional command",
348 static const true_false_string iscsi_meaning_u = {
349 "Read part of bi-directional command underflowed",
350 "No underflow of read part of bi-directional command",
353 static const true_false_string iscsi_meaning_O = {
354 "Residual overflow occurred",
355 "No residual overflow occurred",
358 static const true_false_string iscsi_meaning_U = {
359 "Residual underflow occurred",
360 "No residual underflow occurred",
363 static const value_string iscsi_scsi_responses[] = {
364 { 0, "Command completed at target" },
365 { 1, "Response does not contain SCSI status"},
369 static const value_string iscsi_scsicommand_taskattrs[] = {
373 {3, "Head of Queue"},
378 static const value_string iscsi_task_management_responses[] = {
379 {0, "Function complete"},
380 {1, "Task not in task set"},
381 {2, "LUN does not exist"},
382 {3, "Task still allegiant"},
383 {4, "Task failover not supported"},
384 {5, "Task management function not supported"},
385 {6, "Authorisation failed"},
386 {255, "Function rejected"},
390 static const value_string iscsi_task_management_functions[] = {
392 {2, "Abort Task Set"},
394 {4, "Clear Task Set"},
395 {5, "Logical Unit Reset"},
396 {6, "Target Warm Reset"},
397 {7, "Target Cold Reset"},
401 static const value_string iscsi_login_status[] = {
403 {0x0101, "Target moved temporarily"},
404 {0x0102, "Target moved permanently"},
405 {0x0200, "Initiator error (miscellaneous error)"},
406 {0x0201, "Authentication failed"},
407 {0x0202, "Authorisation failure"},
408 {0x0203, "Target not found"},
409 {0x0204, "Target removed"},
410 {0x0205, "Unsupported version"},
411 {0x0206, "Too many connections"},
412 {0x0207, "Missing parameter"},
413 {0x0208, "Can't include in session"},
414 {0x0209, "Session type not supported"},
415 {0x020a, "Session does not exist"},
416 {0x020b, "Invalid request during login"},
417 {0x0300, "Target error (miscellaneous error)"},
418 {0x0301, "Service unavailable"},
419 {0x0302, "Out of resources"},
423 static const value_string iscsi_login_stage[] = {
424 {0, "Security negotiation"},
425 {1, "Operational negotiation"},
426 {3, "Full feature phase"},
430 /* #ifndef DRAFT08 */
431 static const value_string iscsi_isid_type[] = {
433 {0x01, "IANA Enterprise Number"},
439 static const value_string iscsi_logout_reasons[] = {
440 {0, "Close session"},
441 {1, "Close connection"},
442 {2, "Remove connection for recovery"},
446 static const value_string iscsi_logout_response[] = {
447 {0, "Connection closed successfully"},
448 {1, "CID not found"},
449 {2, "Connection recovery not supported"},
450 {3, "Cleanup failed for various reasons"},
454 static const value_string iscsi_asyncevents[] = {
455 {0, "A SCSI asynchronous event is reported in the sense data"},
456 {1, "Target requests logout"},
457 {2, "Target will/has dropped connection"},
458 {3, "Target will/has dropped all connections"},
459 {4, "Target requests parameter negotiation"},
463 static const value_string iscsi_snack_types[] = {
466 /* #ifndef DRAFT08 */
473 static const value_string iscsi_reject_reasons[] = {
475 {0x01, "Full feature phase command before login"},
477 {0x02, "Data (payload) digest error"},
478 {0x03, "Data SNACK reject"},
479 {0x04, "Protocol error"},
480 {0x05, "Command not supported in this session type"},
481 {0x06, "Immediate command reject (too many immediate commands)"},
482 {0x07, "Task in progress"},
483 {0x08, "Invalid Data Ack"},
484 {0x09, "Invalid PDU field"},
485 {0x0a, "Long operation reject"},
486 {0x0b, "Negotiation reset"},
487 {0x0c, "Waiting for logout"},
491 /*****************************************************************/
493 /* CRC LOOKUP TABLE */
494 /* ================ */
495 /* The following CRC lookup table was generated automagically */
496 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
497 /* Program V1.0 using the following model parameters: */
499 /* Width : 4 bytes. */
500 /* Poly : 0x1EDC6F41L */
501 /* Reverse : TRUE. */
503 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
504 /* see the document titled "A Painless Guide to CRC Error */
505 /* Detection Algorithms" by Ross Williams */
506 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
507 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
509 /*****************************************************************/
511 static guint32 crc32Table[256] = {
512 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
513 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
514 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
515 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
516 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
517 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
518 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
519 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
520 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
521 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
522 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
523 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
524 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
525 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
526 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
527 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
528 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
529 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
530 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
531 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
532 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
533 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
534 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
535 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
536 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
537 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
538 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
539 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
540 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
541 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
542 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
543 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
544 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
545 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
546 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
547 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
548 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
549 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
550 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
551 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
552 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
553 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
554 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
555 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
556 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
557 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
558 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
559 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
560 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
561 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
562 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
563 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
564 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
565 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
566 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
567 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
568 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
569 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
570 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
571 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
572 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
573 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
574 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
575 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
578 #define CRC32C_PRELOAD 0xffffffff
581 * Byte swap fix contributed by Dave Wysochanski <davidw@netapp.com>
583 #define CRC32C_SWAP(crc32c_value) \
584 (((crc32c_value & 0xff000000) >> 24) | \
585 ((crc32c_value & 0x00ff0000) >> 8) | \
586 ((crc32c_value & 0x0000ff00) << 8) | \
587 ((crc32c_value & 0x000000ff) << 24))
590 calculateCRC32(const void *buf, int len, guint32 crc) {
591 const guint8 *p = (const guint8 *)buf;
592 crc = CRC32C_SWAP(crc);
594 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
595 return CRC32C_SWAP(crc);
602 iscsi_equal(gconstpointer v, gconstpointer w)
604 const iscsi_conv_key_t *v1 = (const iscsi_conv_key_t *)v;
605 const iscsi_conv_key_t *v2 = (const iscsi_conv_key_t *)w;
607 return (v1->conv_idx == v2->conv_idx);
611 iscsi_hash (gconstpointer v)
613 const iscsi_conv_key_t *key = (const iscsi_conv_key_t *)v;
622 * Protocol initialization
625 iscsi_init_protocol(void)
628 g_mem_chunk_destroy(iscsi_req_keys);
630 g_mem_chunk_destroy(iscsi_req_vals);
632 g_hash_table_destroy(iscsi_req_hash);
634 iscsi_req_hash = g_hash_table_new(iscsi_hash, iscsi_equal);
635 iscsi_req_keys = g_mem_chunk_new("iscsi_req_keys",
636 sizeof(iscsi_conv_key_t),
637 iscsi_init_count * sizeof(iscsi_conv_key_t),
639 iscsi_req_vals = g_mem_chunk_new("iscsi_req_vals",
640 sizeof(iscsi_conv_data_t),
641 iscsi_init_count * sizeof(iscsi_conv_data_t),
646 iscsi_min(int a, int b) {
647 return (a < b)? a : b;
651 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
652 const gint limit = offset + text_len;
653 while(offset < limit) {
654 gint len = tvb_strnlen(tvb, offset, limit - offset);
656 len = limit - offset;
659 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
666 handleHeaderDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
667 int available_bytes = tvb_length_remaining(tvb, offset);
668 if(enableHeaderDigests) {
669 if(headerDigestIsCRC32) {
670 if(available_bytes >= (headerLen + 4)) {
671 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
672 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
674 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
677 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);
680 return offset + headerLen + 4;
682 if(available_bytes >= (headerLen + headerDigestSize)) {
683 proto_tree_add_item(ti, hf_iscsi_HeaderDigest, tvb, offset + headerLen, headerDigestSize, FALSE);
685 return offset + headerLen + headerDigestSize;
687 return offset + headerLen;
691 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
692 int available_bytes = tvb_length_remaining(tvb, offset);
693 if(enableDataDigests) {
694 if(dataDigestIsCRC32) {
695 if(available_bytes >= (dataLen + 4)) {
696 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
697 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
699 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
702 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);
705 return offset + dataLen + 4;
707 if(available_bytes >= (dataLen + dataDigestSize)) {
708 proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
710 return offset + dataLen + dataDigestSize;
712 return offset + dataLen;
716 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
717 if(endOffset > offset) {
718 int dataOffset = offset;
719 int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
721 proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
724 if(offset < endOffset && (offset & 3) != 0) {
725 int padding = 4 - (offset & 3);
726 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
729 if(dataSegmentLen > 0 && offset < endOffset)
730 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
737 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
738 if(endOffset > offset) {
739 int dataOffset = offset;
740 int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
742 proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
743 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
744 offset = addTextKeys(tt, tvb, offset, textLen);
746 if(offset < endOffset && (offset & 3) != 0) {
747 int padding = 4 - (offset & 3);
748 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
751 if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
752 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
757 /* Code to actually dissect the packets */
759 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len) {
761 guint original_offset = offset;
762 proto_tree *ti = NULL;
763 guint8 scsi_status = 0;
764 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
765 guint end_offset = offset + tvb_length_remaining(tvb, offset);
766 guint32 del_usecs = 0;
767 conversation_t *conversation = NULL;
768 iscsi_conv_data_t *cdata = NULL;
769 iscsi_conv_key_t ckey, *req_key;
770 scsi_task_id_t task_key;
771 int paddedDataSegmentLength = data_segment_len;
772 if(paddedDataSegmentLength & 3)
773 paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
775 /* Make entries in Protocol column and Info column on summary display */
776 if (check_col(pinfo->cinfo, COL_PROTOCOL))
777 col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
779 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
780 opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
781 scsi_status = tvb_get_guint8 (tvb, offset+3);
784 if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
785 (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
786 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
787 conversation = find_conversation (&pinfo->src, &pinfo->dst,
788 pinfo->ptype, pinfo->srcport,
791 ckey.conv_idx = conversation->index;
792 ckey.itt = tvb_get_ntohl (tvb, offset+16);
794 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_hash,
797 task_key.conv_id = ckey.conv_idx;
798 task_key.task_id = ckey.itt;
799 pinfo->private_data = &task_key;
801 /* no conversation, meaning we didn't see the request */
802 pinfo->private_data = NULL;
806 del_usecs = (pinfo->fd->abs_secs - cdata->abs_secs)* 1000000 +
807 (pinfo->fd->abs_usecs - cdata->abs_usecs);
810 else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
811 conversation = find_conversation (&pinfo->src, &pinfo->dst,
812 pinfo->ptype, pinfo->srcport,
815 conversation = conversation_new (&pinfo->src, &pinfo->dst,
816 pinfo->ptype, pinfo->srcport,
820 ckey.conv_idx = conversation->index;
821 ckey.itt = tvb_get_ntohl (tvb, offset+16);
823 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_hash,
826 /* Since we never free the memory used by an exchange, this maybe a
827 * case of another request using the same exchange as a previous
830 cdata->abs_usecs = pinfo->fd->abs_usecs;
831 cdata->abs_secs = pinfo->fd->abs_secs;
834 req_key = g_mem_chunk_alloc (iscsi_req_keys);
835 req_key->conv_idx = conversation->index;
836 req_key->itt = tvb_get_ntohl (tvb, offset+16);
838 cdata = g_mem_chunk_alloc (iscsi_req_vals);
839 cdata->abs_usecs = pinfo->fd->abs_usecs;
840 cdata->abs_secs = pinfo->fd->abs_secs;
842 g_hash_table_insert (iscsi_req_hash, req_key, cdata);
845 /* The SCSI protocol uses this as the key to detect a
846 * SCSI-level conversation. */
847 task_key.conv_id = ckey.conv_idx;
848 task_key.task_id = ckey.itt;
849 pinfo->private_data = &task_key;
852 pinfo->private_data = NULL;
855 if (check_col(pinfo->cinfo, COL_INFO)) {
857 if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
859 col_append_str(pinfo->cinfo, COL_INFO, opcode_str);
861 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
862 (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
863 (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
864 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
865 val_to_str (scsi_status, scsi_status_val, "0x%x"));
867 else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
868 guint16 login_status = tvb_get_ntohs(tvb, offset+36);
869 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
870 val_to_str (login_status, iscsi_login_status, "0x%x"));
872 else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
874 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
875 logoutReason = tvb_get_guint8(tvb, offset+11);
876 } else if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
877 logoutReason = tvb_get_guint8(tvb, offset+1) & 0x7f;
880 logoutReason = tvb_get_guint8(tvb, offset+23);
882 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
883 val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
885 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
886 guint8 tmf = tvb_get_guint8(tvb, offset + 1);
887 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
888 val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
890 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
891 guint8 resp = tvb_get_guint8(tvb, offset + 2);
892 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
893 val_to_str (resp, iscsi_task_management_responses, "0x%x"));
895 else if (opcode == ISCSI_OPCODE_REJECT) {
896 guint8 reason = tvb_get_guint8(tvb, offset + 2);
897 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
898 val_to_str (reason, iscsi_reject_reasons, "0x%x"));
900 else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
901 guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
902 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
903 val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
908 /* In the interest of speed, if "tree" is NULL, don't do any
909 work not necessary to generate protocol tree items. */
912 /* create display subtree for the protocol */
913 tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
914 offset, -1, "iSCSI (%s)",
916 ti = proto_item_add_subtree(tp, ett_iscsi);
918 proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
919 offset + 0, 1, opcode);
920 if((opcode & TARGET_OPCODE_BIT) == 0) {
921 /* initiator -> target */
922 gint b = tvb_get_guint8(tvb, offset + 0);
923 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
924 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
925 opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
926 opcode != ISCSI_OPCODE_SNACK_REQUEST)
927 proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
929 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
930 opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
931 opcode != ISCSI_OPCODE_SNACK_REQUEST)
932 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
935 if(opcode == ISCSI_OPCODE_NOP_OUT) {
937 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
938 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
940 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
941 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
942 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
943 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
944 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
945 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
946 offset = handleHeaderDigest(ti, tvb, offset, 48);
947 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
949 else if(opcode == ISCSI_OPCODE_NOP_IN) {
951 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
952 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
954 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
955 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
956 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
957 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
958 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
959 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
960 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
961 offset = handleHeaderDigest(ti, tvb, offset, 48);
962 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
964 else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
966 guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
968 gint b = tvb_get_guint8(tvb, offset + 1);
969 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
970 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
972 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
973 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
974 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
975 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
977 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
978 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
980 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
981 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
982 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
983 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
984 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
985 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
986 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
989 /* FIXME - disssect AHS? */
990 proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 48, ahsLen, FALSE);
992 offset = handleHeaderDigest(ti, tvb, offset, 48 + ahsLen);
994 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
996 else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
999 if (del_usecs > 1000)
1000 proto_tree_add_text (ti, tvb, offset, 0,
1001 "Cmd Response Time: %d msecs",
1004 proto_tree_add_text (ti, tvb, offset, 0,
1005 "Cmd Response Time: %d usecs",
1009 gint b = tvb_get_guint8(tvb, offset + 1);
1010 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1011 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1013 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
1014 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
1015 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
1016 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
1018 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
1019 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1020 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1021 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1023 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1024 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1025 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1026 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
1028 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1029 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1030 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1031 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1032 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1033 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
1036 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
1037 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
1039 offset = handleHeaderDigest(ti, tvb, offset, 48);
1040 /* do not update offset here because the data segment is
1041 * dissected below */
1042 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1044 else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
1045 /* Task Management Function */
1046 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
1047 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1048 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1049 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1051 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1052 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1053 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1054 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1055 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1056 proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1057 offset = handleHeaderDigest(ti, tvb, offset, 48);
1059 else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1060 /* Task Management Function Response */
1061 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
1062 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1063 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1064 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1066 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1067 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1068 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1070 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1071 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1072 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1073 offset = handleHeaderDigest(ti, tvb, offset, 48);
1075 else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1077 int digestsActive = 0;
1079 gint b = tvb_get_guint8(tvb, offset + 1);
1080 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1081 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1085 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1086 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1089 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1090 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1091 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1093 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1094 proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1096 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1097 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1099 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1100 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1101 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1102 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1104 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1105 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1106 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1107 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1110 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1111 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1112 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1113 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1114 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1115 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1118 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1119 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1120 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1121 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1122 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1125 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1126 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1129 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1131 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1132 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1133 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1135 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1136 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1138 offset = handleHeaderDigest(ti, tvb, offset, 48);
1141 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1143 else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1144 /* Login Response */
1145 int digestsActive = 0;
1147 gint b = tvb_get_guint8(tvb, offset + 1);
1148 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1149 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1153 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1154 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1157 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1158 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1159 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1161 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1162 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1165 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1166 proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1167 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1168 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1170 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1171 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1172 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1175 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1176 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1177 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1178 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1179 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1180 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1183 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1184 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1185 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1186 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1187 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1190 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1191 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1194 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1196 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1197 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1198 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1199 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1200 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1202 offset = handleHeaderDigest(ti, tvb, offset, 48);
1205 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1207 else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1210 gint b = tvb_get_guint8(tvb, offset + 1);
1211 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1212 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1214 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1215 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1216 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1219 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1220 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1222 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1223 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1224 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1226 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1227 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1228 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1229 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1230 offset = handleHeaderDigest(ti, tvb, offset, 48);
1231 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1233 else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1236 gint b = tvb_get_guint8(tvb, offset + 1);
1237 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1238 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1240 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1241 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1242 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1245 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1246 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1248 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1249 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1250 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1252 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1253 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1254 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1255 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1256 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1257 offset = handleHeaderDigest(ti, tvb, offset, 48);
1258 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1260 else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1261 /* SCSI Data Out (write) */
1263 gint b = tvb_get_guint8(tvb, offset + 1);
1264 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1265 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1267 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1269 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1270 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1272 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1273 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1274 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1275 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1276 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1277 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1278 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1279 offset = handleHeaderDigest(ti, tvb, offset, 48);
1280 /* do not update offset here because the data segment is
1281 * dissected below */
1282 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1284 else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
1285 /* SCSI Data In (read) */
1287 gint b = tvb_get_guint8(tvb, offset + 1);
1288 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1289 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1291 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1292 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1293 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
1295 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1296 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1297 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1299 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1300 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1301 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1303 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1304 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1305 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1307 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1308 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1309 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1312 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1314 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1315 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1316 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1317 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1318 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1319 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1320 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1322 offset = handleHeaderDigest(ti, tvb, offset, 48);
1323 /* do not update offset here because the data segment is
1324 * dissected below */
1325 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1327 else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1328 /* Logout Command */
1329 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1330 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 1, 1, FALSE);
1332 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1333 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1334 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1336 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1337 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1338 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1340 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1341 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1342 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1343 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT13) {
1344 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
1347 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1348 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1349 offset = handleHeaderDigest(ti, tvb, offset, 48);
1351 else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1352 /* Logout Response */
1353 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1354 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1355 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1356 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1358 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1359 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1360 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1361 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1362 proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1363 proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1364 offset = handleHeaderDigest(ti, tvb, offset, 48);
1366 else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1369 gint b = tvb_get_guint8(tvb, offset + 1);
1371 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1372 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1375 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1377 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1378 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1379 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1380 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1382 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1383 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1384 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1385 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1386 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1387 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1390 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1391 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1392 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1393 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1395 offset = handleHeaderDigest(ti, tvb, offset, 48);
1397 else if(opcode == ISCSI_OPCODE_R2T) {
1399 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1400 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1401 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1402 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1404 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1405 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1406 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1407 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1408 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1409 proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
1410 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1411 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1412 offset = handleHeaderDigest(ti, tvb, offset, 48);
1414 else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1415 /* Asynchronous Message */
1416 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1417 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1419 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1420 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1421 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1422 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1423 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1424 proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1425 proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1426 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1427 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1428 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1429 offset = handleHeaderDigest(ti, tvb, offset, 48);
1430 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
1432 else if(opcode == ISCSI_OPCODE_REJECT) {
1434 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
1435 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1436 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1438 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1439 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1440 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1441 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1442 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1443 offset = handleHeaderDigest(ti, tvb, offset, 48);
1444 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1446 else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
1447 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
1448 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
1449 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
1450 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
1451 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
1452 /* Vendor specific opcodes */
1453 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1454 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1456 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1457 offset = handleHeaderDigest(ti, tvb, offset, 48);
1458 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
1461 proto_item_set_len(ti, offset - original_offset);
1464 if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
1466 ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
1468 dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16, SCSI_DEV_UNKNOWN);
1470 else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1471 if (scsi_status == 0x2) {
1472 /* A SCSI response with Check Condition contains sense data */
1473 /* offset is setup correctly by the iscsi code for response above */
1474 if((end_offset - offset) >= 2) {
1475 int senseLen = tvb_get_ntohs(tvb, offset);
1477 proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1480 dissect_scsi_snsinfo (tvb, pinfo, tree, offset,
1481 iscsi_min (senseLen,
1482 end_offset-offset));
1486 dissect_scsi_rsp (tvb, pinfo, tree);
1488 if (cdata && tree) {
1489 /* destroy the data structures for this SCSI task */
1491 g_mem_chunk_free (iscsi_req_vals, cdata);
1492 g_hash_table_remove (iscsi_req_hash, &ckey);
1493 pinfo->private_data = NULL;
1497 else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1498 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1499 /* offset is setup correctly by the iscsi code for response above */
1500 dissect_scsi_payload (tvb, pinfo, tree, offset, FALSE,
1501 iscsi_min (data_segment_len, end_offset-offset));
1506 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1507 /* Set up structures needed to add the protocol subtree and manage it */
1508 guint iSCSIPdusDissected = 0;
1510 guint32 available_bytes = tvb_length_remaining(tvb, offset);
1512 if (!proto_is_protocol_enabled(proto_iscsi))
1513 return FALSE; /* iSCSI has been disabled */
1515 /* quick check to see if the packet is long enough to contain the
1516 * minimum amount of information we need */
1517 if (available_bytes < 48 && (!iscsi_desegment || available_bytes < 8)) {
1518 /* no, so give up */
1522 /* process multiple iSCSI PDUs per packet */
1523 while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
1524 const char *opcode_str = NULL;
1525 guint32 data_segment_len;
1526 guint8 opcode = tvb_get_guint8(tvb, offset + 0);
1527 guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
1530 /* mask out any extra bits in the opcode byte */
1531 opcode &= OPCODE_MASK;
1533 opcode_str = match_strval(opcode, iscsi_opcodes);
1534 if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
1535 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1536 opcode == ISCSI_OPCODE_R2T ||
1537 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1538 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1539 opcode == ISCSI_OPCODE_SNACK_REQUEST)
1540 data_segment_len = 0;
1542 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
1544 if(opcode_str == NULL) {
1547 else if(iscsi_port != 0 &&
1548 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
1549 (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
1552 else if(enable_bogosity_filter) {
1553 /* try and distinguish between data and real headers */
1554 if(data_segment_len > bogus_pdu_data_length_threshold) {
1557 else if(demand_good_f_bit &&
1558 !(secondPduByte & 0x80) &&
1559 (opcode == ISCSI_OPCODE_NOP_OUT ||
1560 opcode == ISCSI_OPCODE_NOP_IN ||
1561 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1562 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1563 opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
1564 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1565 opcode == ISCSI_OPCODE_R2T ||
1566 opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
1567 opcode == ISCSI_OPCODE_SNACK_REQUEST ||
1568 opcode == ISCSI_OPCODE_REJECT)) {
1574 return iSCSIPdusDissected > 0;
1577 guint32 pduLen = 48;
1578 int digestsActive = 1;
1580 if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
1581 opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1582 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1583 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
1584 /* digests are not yet turned on */
1593 if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1595 pduLen += tvb_get_guint8(tvb, offset + 4) * 4;
1598 pduLen += data_segment_len;
1599 if((pduLen & 3) != 0)
1600 pduLen += 4 - (pduLen & 3);
1602 if(digestsActive && enableHeaderDigests) {
1603 if(headerDigestIsCRC32)
1606 pduLen += headerDigestSize;
1609 if(digestsActive && data_segment_len > 0 && enableDataDigests) {
1610 if(dataDigestIsCRC32)
1613 pduLen += dataDigestSize;
1617 * Desegmentation check.
1619 if(iscsi_desegment && pinfo->can_desegment) {
1620 if(pduLen > available_bytes) {
1622 * This frame doesn't have all of the data for
1623 * this message, but we can do reassembly on it.
1625 * Tell the TCP dissector where the data for this
1626 * message starts in the data it handed us, and
1627 * how many more bytes we need, and return.
1629 pinfo->desegment_offset = offset;
1630 pinfo->desegment_len = pduLen - available_bytes;
1635 if(check_col(pinfo->cinfo, COL_INFO)) {
1636 if(iSCSIPdusDissected == 0)
1637 col_set_str(pinfo->cinfo, COL_INFO, "");
1639 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1642 dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len);
1643 if(pduLen > available_bytes)
1644 pduLen = available_bytes;
1646 available_bytes -= pduLen;
1647 ++iSCSIPdusDissected;
1651 return iSCSIPdusDissected > 0;
1655 /* Register the protocol with Ethereal */
1658 * this format is require because a script is used to build the C
1659 * function that calls all the protocol registration.
1663 proto_register_iscsi(void)
1666 /* Setup list of header fields See Section 1.6.1 for details*/
1667 static hf_register_info hf[] = {
1669 { "AHS", "iscsi.ahs",
1670 FT_BYTES, BASE_HEX, NULL, 0,
1671 "Additional header segment", HFILL }
1673 { &hf_iscsi_Padding,
1674 { "Padding", "iscsi.padding",
1675 FT_BYTES, BASE_HEX, NULL, 0,
1676 "Padding to 4 byte boundary", HFILL }
1678 { &hf_iscsi_ping_data,
1679 { "PingData", "iscsi.pingdata",
1680 FT_BYTES, BASE_HEX, NULL, 0,
1681 "Ping Data", HFILL }
1683 { &hf_iscsi_immediate_data,
1684 { "ImmediateData", "iscsi.immediatedata",
1685 FT_BYTES, BASE_HEX, NULL, 0,
1686 "Immediate Data", HFILL }
1688 { &hf_iscsi_write_data,
1689 { "WriteData", "iscsi.writedata",
1690 FT_BYTES, BASE_HEX, NULL, 0,
1691 "Write Data", HFILL }
1693 { &hf_iscsi_read_data,
1694 { "ReadData", "iscsi.readdata",
1695 FT_BYTES, BASE_HEX, NULL, 0,
1696 "Read Data", HFILL }
1698 { &hf_iscsi_error_pdu_data,
1699 { "ErrorPDUData", "iscsi.errorpdudata",
1700 FT_BYTES, BASE_HEX, NULL, 0,
1701 "Error PDU Data", HFILL }
1703 { &hf_iscsi_async_message_data,
1704 { "AsyncMessageData", "iscsi.asyncmessagedata",
1705 FT_BYTES, BASE_HEX, NULL, 0,
1706 "Async Message Data", HFILL }
1708 { &hf_iscsi_vendor_specific_data,
1709 { "VendorSpecificData", "iscsi.vendorspecificdata",
1710 FT_BYTES, BASE_HEX, NULL, 0,
1711 "Vendor Specific Data", HFILL }
1713 { &hf_iscsi_HeaderDigest,
1714 { "HeaderDigest", "iscsi.headerdigest",
1715 FT_BYTES, BASE_HEX, NULL, 0,
1716 "Header Digest", HFILL }
1718 { &hf_iscsi_HeaderDigest32,
1719 { "HeaderDigest", "iscsi.headerdigest32",
1720 FT_UINT32, BASE_HEX, NULL, 0,
1721 "Header Digest", HFILL }
1723 { &hf_iscsi_DataDigest,
1724 { "DataDigest", "iscsi.datadigest",
1725 FT_BYTES, BASE_HEX, NULL, 0,
1726 "Data Digest", HFILL }
1728 { &hf_iscsi_DataDigest32,
1729 { "DataDigest", "iscsi.datadigest32",
1730 FT_UINT32, BASE_HEX, NULL, 0,
1731 "Data Digest", HFILL }
1734 { "Opcode", "iscsi.opcode",
1735 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
1738 /* #ifdef DRAFT08 */
1741 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1742 "Command Retry", HFILL }
1747 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
1748 "Immediate delivery", HFILL }
1751 { "Flags", "iscsi.flags",
1752 FT_UINT8, BASE_HEX, NULL, 0,
1753 "Opcode specific flags", HFILL }
1755 { &hf_iscsi_SCSICommand_F,
1756 { "F", "iscsi.scsicommand.F",
1757 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1758 "PDU completes command", HFILL }
1760 { &hf_iscsi_SCSICommand_R,
1761 { "R", "iscsi.scsicommand.R",
1762 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
1763 "Command reads from SCSI target", HFILL }
1765 { &hf_iscsi_SCSICommand_W,
1766 { "W", "iscsi.scsicommand.W",
1767 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
1768 "Command writes to SCSI target", HFILL }
1770 { &hf_iscsi_SCSICommand_Attr,
1771 { "Attr", "iscsi.scsicommand.attr",
1772 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
1773 "SCSI task attributes", HFILL }
1775 { &hf_iscsi_SCSICommand_CRN,
1776 { "CRN", "iscsi.scsicommand.crn",
1777 FT_UINT8, BASE_HEX, NULL, 0,
1778 "SCSI command reference number", HFILL }
1780 { &hf_iscsi_SCSICommand_AddCDB,
1781 { "AddCDB", "iscsi.scsicommand.addcdb",
1782 FT_UINT8, BASE_HEX, NULL, 0,
1783 "Additional CDB length (in 4 byte units)", HFILL }
1785 { &hf_iscsi_DataSegmentLength,
1786 { "DataSegmentLength", "iscsi.datasegmentlength",
1787 FT_UINT32, BASE_HEX, NULL, 0,
1788 "Data segment length (bytes)", HFILL }
1790 { &hf_iscsi_TotalAHSLength,
1791 { "TotalAHSLength", "iscsi.totalahslength",
1792 FT_UINT8, BASE_HEX, NULL, 0,
1793 "Total additional header segment length (4 byte words)", HFILL }
1796 { "LUN", "iscsi.lun",
1797 FT_BYTES, BASE_HEX, NULL, 0,
1798 "Logical Unit Number", HFILL }
1800 { &hf_iscsi_InitiatorTaskTag,
1801 { "InitiatorTaskTag", "iscsi.initiatortasktag",
1802 FT_UINT32, BASE_HEX, NULL, 0,
1803 "Initiator's task tag", HFILL }
1805 { &hf_iscsi_ExpectedDataTransferLength,
1806 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
1807 FT_UINT32, BASE_HEX, NULL, 0,
1808 "Expected length of data transfer", HFILL }
1811 { "CmdSN", "iscsi.cmdsn",
1812 FT_UINT32, BASE_HEX, NULL, 0,
1813 "Sequence number for this command", HFILL }
1815 { &hf_iscsi_ExpStatSN,
1816 { "ExpStatSN", "iscsi.expstatsn",
1817 FT_UINT32, BASE_HEX, NULL, 0,
1818 "Next expected status sequence number", HFILL }
1820 { &hf_iscsi_SCSIResponse_ResidualCount,
1821 { "ResidualCount", "iscsi.scsiresponse.residualcount",
1822 FT_UINT32, BASE_HEX, NULL, 0,
1823 "Residual count", HFILL }
1826 { "StatSN", "iscsi.statsn",
1827 FT_UINT32, BASE_HEX, NULL, 0,
1828 "Status sequence number", HFILL }
1830 { &hf_iscsi_ExpCmdSN,
1831 { "ExpCmdSN", "iscsi.expcmdsn",
1832 FT_UINT32, BASE_HEX, NULL, 0,
1833 "Next expected command sequence number", HFILL }
1835 { &hf_iscsi_MaxCmdSN,
1836 { "MaxCmdSN", "iscsi.maxcmdsn",
1837 FT_UINT32, BASE_HEX, NULL, 0,
1838 "Maximum acceptable command sequence number", HFILL }
1840 { &hf_iscsi_SCSIResponse_o,
1841 { "o", "iscsi.scsiresponse.o",
1842 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
1843 "Bi-directional read residual overflow", HFILL }
1845 { &hf_iscsi_SCSIResponse_u,
1846 { "u", "iscsi.scsiresponse.u",
1847 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
1848 "Bi-directional read residual underflow", HFILL }
1850 { &hf_iscsi_SCSIResponse_O,
1851 { "O", "iscsi.scsiresponse.O",
1852 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
1853 "Residual overflow", HFILL }
1855 { &hf_iscsi_SCSIResponse_U,
1856 { "U", "iscsi.scsiresponse.U",
1857 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
1858 "Residual underflow", HFILL }
1860 { &hf_iscsi_SCSIResponse_Status,
1861 { "Status", "iscsi.scsiresponse.status",
1862 FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
1863 "SCSI command status value", HFILL }
1865 { &hf_iscsi_SCSIResponse_Response,
1866 { "Response", "iscsi.scsiresponse.response",
1867 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
1868 "SCSI command response value", HFILL }
1870 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
1871 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
1872 FT_UINT32, BASE_HEX, NULL, 0,
1873 "Bi-directional read residual count", HFILL }
1875 { &hf_iscsi_SenseLength,
1876 { "SenseLength", "iscsi.scsiresponse.senselength",
1877 FT_UINT16, BASE_HEX, NULL, 0,
1878 "Sense data length", HFILL }
1880 { &hf_iscsi_SCSIData_F,
1881 { "F", "iscsi.scsidata.F",
1882 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
1883 "Final PDU", HFILL }
1885 { &hf_iscsi_SCSIData_A,
1886 { "A", "iscsi.scsidata.A",
1887 FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
1888 "Acknowledge Requested", HFILL }
1890 { &hf_iscsi_SCSIData_S,
1891 { "S", "iscsi.scsidata.S",
1892 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
1893 "PDU Contains SCSI command status", HFILL }
1895 { &hf_iscsi_SCSIData_U,
1896 { "U", "iscsi.scsidata.U",
1897 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
1898 "Residual underflow", HFILL }
1900 { &hf_iscsi_SCSIData_O,
1901 { "O", "iscsi.scsidata.O",
1902 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
1903 "Residual overflow", HFILL }
1905 { &hf_iscsi_TargetTransferTag,
1906 { "TargetTransferTag", "iscsi.targettransfertag",
1907 FT_UINT32, BASE_HEX, NULL, 0,
1908 "Target transfer tag", HFILL }
1910 { &hf_iscsi_BufferOffset,
1911 { "BufferOffset", "iscsi.bufferOffset",
1912 FT_UINT32, BASE_HEX, NULL, 0,
1913 "Buffer offset", HFILL }
1915 { &hf_iscsi_SCSIData_ResidualCount,
1916 { "ResidualCount", "iscsi.scsidata.readresidualcount",
1917 FT_UINT32, BASE_HEX, NULL, 0,
1918 "Residual count", HFILL }
1921 { "DataSN", "iscsi.datasn",
1922 FT_UINT32, BASE_HEX, NULL, 0,
1923 "Data sequence number", HFILL }
1925 { &hf_iscsi_VersionMax,
1926 { "VersionMax", "iscsi.versionmax",
1927 FT_UINT8, BASE_HEX, NULL, 0,
1928 "Maximum supported protocol version", HFILL }
1930 { &hf_iscsi_VersionMin,
1931 { "VersionMin", "iscsi.versionmin",
1932 FT_UINT8, BASE_HEX, NULL, 0,
1933 "Minimum supported protocol version", HFILL }
1935 { &hf_iscsi_VersionActive,
1936 { "VersionActive", "iscsi.versionactive",
1937 FT_UINT8, BASE_HEX, NULL, 0,
1938 "Negotiated protocol version", HFILL }
1941 { "CID", "iscsi.cid",
1942 FT_UINT16, BASE_HEX, NULL, 0,
1943 "Connection identifier", HFILL }
1945 /* #ifdef DRAFT08 */
1947 { "ISID", "iscsi.isid",
1948 FT_UINT16, BASE_HEX, NULL, 0,
1949 "Initiator part of session identifier", HFILL }
1953 { "ISID", "iscsi.isid",
1954 FT_BYTES, BASE_HEX, NULL, 0,
1955 "Initiator part of session identifier", HFILL }
1957 /* #ifdef DRAFT09 */
1958 { &hf_iscsi_ISID_Type,
1959 { "ISID_Type", "iscsi.isid.type",
1960 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
1961 "Initiator part of session identifier - type", HFILL }
1963 { &hf_iscsi_ISID_NamingAuthority,
1964 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
1965 FT_UINT24, BASE_HEX, NULL, 0,
1966 "Initiator part of session identifier - naming authority", HFILL }
1968 { &hf_iscsi_ISID_Qualifier,
1969 { "ISID_Qualifier", "iscsi.isid.qualifier",
1970 FT_UINT8, BASE_HEX, NULL, 0,
1971 "Initiator part of session identifier - qualifier", HFILL }
1975 { "ISID_t", "iscsi.isid.t",
1976 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
1977 "Initiator part of session identifier - t", HFILL }
1980 { "ISID_a", "iscsi.isid.a",
1981 FT_UINT8, BASE_HEX, NULL, 0x3f,
1982 "Initiator part of session identifier - a", HFILL }
1985 { "ISID_b", "iscsi.isid.b",
1986 FT_UINT16, BASE_HEX, NULL, 0,
1987 "Initiator part of session identifier - b", HFILL }
1990 { "ISID_c", "iscsi.isid.c",
1991 FT_UINT8, BASE_HEX, NULL, 0,
1992 "Initiator part of session identifier - c", HFILL }
1995 { "ISID_d", "iscsi.isid.d",
1996 FT_UINT16, BASE_HEX, NULL, 0,
1997 "Initiator part of session identifier - d", HFILL }
2002 { "TSID", "iscsi.tsid",
2003 FT_UINT16, BASE_HEX, NULL, 0,
2004 "Target part of session identifier", HFILL }
2007 { "TSIH", "iscsi.tsih",
2008 FT_UINT16, BASE_HEX, NULL, 0,
2009 "Target session identifying handle", HFILL }
2011 { &hf_iscsi_InitStatSN,
2012 { "InitStatSN", "iscsi.initstatsn",
2013 FT_UINT32, BASE_HEX, NULL, 0,
2014 "Initial status sequence number", HFILL }
2016 { &hf_iscsi_InitCmdSN,
2017 { "InitCmdSN", "iscsi.initcmdsn",
2018 FT_UINT32, BASE_HEX, NULL, 0,
2019 "Initial command sequence number", HFILL }
2021 { &hf_iscsi_Login_T,
2022 { "T", "iscsi.login.T",
2023 FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
2024 "Transit to next login stage", HFILL }
2026 { &hf_iscsi_Login_C,
2027 { "C", "iscsi.login.C",
2028 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2029 "Text incomplete", HFILL }
2031 /* #ifdef DRAFT09 */
2032 { &hf_iscsi_Login_X,
2033 { "X", "iscsi.login.X",
2034 FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
2035 "Restart Connection", HFILL }
2038 { &hf_iscsi_Login_CSG,
2039 { "CSG", "iscsi.login.csg",
2040 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
2041 "Current stage", HFILL }
2043 { &hf_iscsi_Login_NSG,
2044 { "NSG", "iscsi.login.nsg",
2045 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
2046 "Next stage", HFILL }
2048 { &hf_iscsi_Login_Status,
2049 { "Status", "iscsi.login.status",
2050 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
2051 "Status class and detail", HFILL }
2053 { &hf_iscsi_KeyValue,
2054 { "KeyValue", "iscsi.keyvalue",
2055 FT_STRING, 0, NULL, 0,
2056 "Key/value pair", HFILL }
2059 { "F", "iscsi.text.F",
2060 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2061 "Final PDU in text sequence", HFILL }
2064 { "C", "iscsi.text.C",
2065 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2066 "Text incomplete", HFILL }
2068 { &hf_iscsi_ExpDataSN,
2069 { "ExpDataSN", "iscsi.expdatasn",
2070 FT_UINT32, BASE_HEX, NULL, 0,
2071 "Next expected data sequence number", HFILL }
2074 { "R2TSN", "iscsi.r2tsn",
2075 FT_UINT32, BASE_HEX, NULL, 0,
2076 "R2T PDU Number", HFILL }
2078 { &hf_iscsi_TaskManagementFunction_Response,
2079 { "Response", "iscsi.taskmanfun.response",
2080 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
2083 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
2084 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
2085 FT_UINT32, BASE_HEX, NULL, 0,
2086 "Referenced task tag", HFILL }
2088 { &hf_iscsi_RefCmdSN,
2089 { "RefCmdSN", "iscsi.refcmdsn",
2090 FT_UINT32, BASE_HEX, NULL, 0,
2091 "Command sequence number for command to be aborted", HFILL }
2093 { &hf_iscsi_TaskManagementFunction_Function,
2094 { "Function", "iscsi.taskmanfun.function",
2095 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
2096 "Requested task function", HFILL }
2098 { &hf_iscsi_Logout_Reason,
2099 { "Reason", "iscsi.logout.reason",
2100 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0x7F,
2101 "Reason for logout", HFILL }
2103 { &hf_iscsi_Logout_Response,
2104 { "Response", "iscsi.logout.response",
2105 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
2106 "Logout response", HFILL }
2108 { &hf_iscsi_Time2Wait,
2109 { "Time2Wait", "iscsi.time2wait",
2110 FT_UINT16, BASE_HEX, NULL, 0,
2111 "Time2Wait", HFILL }
2113 { &hf_iscsi_Time2Retain,
2114 { "Time2Retain", "iscsi.time2retain",
2115 FT_UINT16, BASE_HEX, NULL, 0,
2116 "Time2Retain", HFILL }
2118 { &hf_iscsi_DesiredDataLength,
2119 { "DesiredDataLength", "iscsi.desireddatalength",
2120 FT_UINT32, BASE_HEX, NULL, 0,
2121 "Desired data length (bytes)", HFILL }
2123 { &hf_iscsi_AsyncEvent,
2124 { "AsyncEvent", "iscsi.asyncevent",
2125 FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2126 "Async event type", HFILL }
2128 { &hf_iscsi_EventVendorCode,
2129 { "EventVendorCode", "iscsi.eventvendorcode",
2130 FT_UINT8, BASE_HEX, NULL, 0,
2131 "Event vendor code", HFILL }
2133 { &hf_iscsi_Parameter1,
2134 { "Parameter1", "iscsi.parameter1",
2135 FT_UINT16, BASE_HEX, NULL, 0,
2136 "Parameter 1", HFILL }
2138 { &hf_iscsi_Parameter2,
2139 { "Parameter2", "iscsi.parameter2",
2140 FT_UINT16, BASE_HEX, NULL, 0,
2141 "Parameter 2", HFILL }
2143 { &hf_iscsi_Parameter3,
2144 { "Parameter3", "iscsi.parameter3",
2145 FT_UINT16, BASE_HEX, NULL, 0,
2146 "Parameter 3", HFILL }
2148 { &hf_iscsi_Reject_Reason,
2149 { "Reason", "iscsi.reject.reason",
2150 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2151 "Reason for command rejection", HFILL }
2153 { &hf_iscsi_snack_type,
2154 { "S", "iscsi.snack.type",
2155 FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2156 "Type of SNACK requested", HFILL }
2159 { "BegRun", "iscsi.snack.begrun",
2160 FT_UINT32, BASE_HEX, NULL, 0,
2161 "First missed DataSN or StatSN", HFILL }
2163 { &hf_iscsi_RunLength,
2164 { "RunLength", "iscsi.snack.runlength",
2165 FT_UINT32, BASE_HEX, NULL, 0,
2166 "Number of additional missing status PDUs in this run", HFILL }
2170 /* Setup protocol subtree array */
2171 static gint *ett[] = {
2173 &ett_iscsi_KeyValues,
2176 /* #ifndef DRAFT08 */
2181 /* Register the protocol name and description */
2182 proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2184 /* Required function calls to register the header fields and
2186 proto_register_field_array(proto_iscsi, hf, array_length(hf));
2187 proto_register_subtree_array(ett, array_length(ett));
2188 register_init_routine (&iscsi_init_protocol);
2191 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2193 prefs_register_enum_preference(iscsi_module,
2196 "The iSCSI protocol version",
2197 &iscsi_protocol_version,
2198 iscsi_protocol_versions,
2201 prefs_register_bool_preference(iscsi_module,
2202 "desegment_iscsi_messages",
2203 "Desegment iSCSI messages",
2204 "When enabled, iSCSI messages that span multiple TCP segments are desegmented",
2207 prefs_register_bool_preference(iscsi_module,
2209 "Enable bogus pdu filter",
2210 "When enabled, packets that appear bogus are ignored",
2211 &enable_bogosity_filter);
2213 prefs_register_bool_preference(iscsi_module,
2214 "demand_good_f_bit",
2215 "Ignore packets with bad F bit",
2216 "Ignore packets that haven't set the F bit when they should have",
2217 &demand_good_f_bit);
2219 prefs_register_uint_preference(iscsi_module,
2220 "bogus_pdu_max_data_len",
2221 "Bogus pdu max data length threshold",
2222 "Treat packets whose data segment length is greater than this value as bogus",
2224 &bogus_pdu_data_length_threshold);
2226 prefs_register_uint_preference(iscsi_module,
2229 "Port number of iSCSI target",
2233 prefs_register_bool_preference(iscsi_module,
2234 "enable_header_digests",
2235 "Enable header digests",
2236 "When enabled, pdus are assumed to contain a header digest",
2237 &enableHeaderDigests);
2238 prefs_register_bool_preference(iscsi_module,
2239 "enable_data_digests",
2240 "Enable data digests",
2241 "When enabled, pdus are assumed to contain a data digest",
2242 &enableDataDigests);
2244 prefs_register_bool_preference(iscsi_module,
2245 "header_digest_is_crc32c",
2246 "Header digest is CRC32C",
2247 "When enabled, header digests are assumed to be CRC32C",
2248 &headerDigestIsCRC32);
2249 prefs_register_bool_preference(iscsi_module,
2250 "data_digest_is_crc32c",
2251 "Data digest is CRC32C",
2252 "When enabled, data digests are assumed to be CRC32C",
2253 &dataDigestIsCRC32);
2255 prefs_register_uint_preference(iscsi_module,
2256 "header_digest_size",
2257 "Header digest size",
2258 "The size of a header digest (bytes)",
2261 prefs_register_uint_preference(iscsi_module,
2264 "The size of a data digest (bytes)",
2268 /* Preference supported in older versions.
2269 Register them as obsolete. */
2270 prefs_register_obsolete_preference(iscsi_module,
2271 "version_03_compatible");
2272 prefs_register_obsolete_preference(iscsi_module,
2273 "bogus_pdu_max_digest_padding");
2279 * If this dissector uses sub-dissector registration add a
2280 * registration routine.
2284 * This format is required because a script is used to find these
2285 * routines and create the code that calls these routines.
2288 proto_reg_handoff_iscsi(void)
2290 heur_dissector_add("tcp", dissect_iscsi, proto_iscsi);