2 * Routines for iSCSI dissection
3 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
5 * $Id: packet-iscsi.c,v 1.34 2002/06/24 07:57:50 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.
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
48 #include <epan/packet.h>
50 #include <epan/conversation.h>
51 #include "packet-scsi.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", ISCSI_PROTOCOL_DRAFT08 },
63 { "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
64 { "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
65 { "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
66 { "Draft 13", ISCSI_PROTOCOL_DRAFT13 },
70 static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT13;
72 static gboolean iscsi_desegment = TRUE;
74 static int demand_good_f_bit = FALSE;
75 static int enable_bogosity_filter = TRUE;
76 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
78 static int enableDataDigests = FALSE;
79 static int enableHeaderDigests = FALSE;
81 static int dataDigestIsCRC32 = TRUE;
82 static int headerDigestIsCRC32 = TRUE;
84 static int dataDigestSize = 4;
85 static int headerDigestSize = 4;
87 static guint iscsi_port = 3260;
89 /* Initialize the protocol and registered fields */
90 static int proto_iscsi = -1;
91 static int hf_iscsi_AHS = -1;
92 static int hf_iscsi_Padding = -1;
93 static int hf_iscsi_ping_data = -1;
94 static int hf_iscsi_immediate_data = -1;
95 static int hf_iscsi_write_data = -1;
96 static int hf_iscsi_read_data = -1;
97 static int hf_iscsi_error_pdu_data = -1;
98 static int hf_iscsi_async_message_data = -1;
99 static int hf_iscsi_vendor_specific_data = -1;
100 static int hf_iscsi_Opcode = -1;
101 static int hf_iscsi_Flags = -1;
102 static int hf_iscsi_HeaderDigest = -1;
103 static int hf_iscsi_HeaderDigest32 = -1;
104 static int hf_iscsi_DataDigest = -1;
105 static int hf_iscsi_DataDigest32 = -1;
107 static int hf_iscsi_X = -1;
109 static int hf_iscsi_I = -1;
110 static int hf_iscsi_SCSICommand_F = -1;
111 static int hf_iscsi_SCSICommand_R = -1;
112 static int hf_iscsi_SCSICommand_W = -1;
113 static int hf_iscsi_SCSICommand_Attr = -1;
114 static int hf_iscsi_SCSICommand_CRN = -1;
115 static int hf_iscsi_SCSICommand_AddCDB = -1;
116 static int hf_iscsi_DataSegmentLength = -1;
117 static int hf_iscsi_TotalAHSLength = -1;
118 static int hf_iscsi_LUN = -1;
119 static int hf_iscsi_InitiatorTaskTag = -1;
120 static int hf_iscsi_ExpectedDataTransferLength = -1;
121 static int hf_iscsi_CmdSN = -1;
122 static int hf_iscsi_ExpStatSN = -1;
123 static int hf_iscsi_StatSN = -1;
124 static int hf_iscsi_ExpCmdSN = -1;
125 static int hf_iscsi_MaxCmdSN = -1;
126 static int hf_iscsi_SCSIResponse_o = -1;
127 static int hf_iscsi_SCSIResponse_u = -1;
128 static int hf_iscsi_SCSIResponse_O = -1;
129 static int hf_iscsi_SCSIResponse_U = -1;
130 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
131 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
132 static int hf_iscsi_SCSIResponse_Response = -1;
133 static int hf_iscsi_SCSIResponse_Status = -1;
134 static int hf_iscsi_SenseLength = -1;
135 static int hf_iscsi_SCSIData_F = -1;
136 static int hf_iscsi_SCSIData_A = -1;
137 static int hf_iscsi_SCSIData_S = -1;
138 static int hf_iscsi_SCSIData_O = -1;
139 static int hf_iscsi_SCSIData_U = -1;
140 static int hf_iscsi_TargetTransferTag = -1;
141 static int hf_iscsi_DataSN = -1;
142 static int hf_iscsi_BufferOffset = -1;
143 static int hf_iscsi_SCSIData_ResidualCount = -1;
144 static int hf_iscsi_VersionMin = -1;
145 static int hf_iscsi_VersionMax = -1;
146 static int hf_iscsi_VersionActive = -1;
147 static int hf_iscsi_CID = -1;
148 static int hf_iscsi_ISID8 = -1;
149 static int hf_iscsi_ISID = -1;
150 /* #if defined(DRAFT09) */
151 static int hf_iscsi_ISID_Type = -1;
152 static int hf_iscsi_ISID_NamingAuthority = -1;
153 static int hf_iscsi_ISID_Qualifier = -1;
154 /* #elif !defined(DRAFT08) */
155 static int hf_iscsi_ISID_t = -1;
156 static int hf_iscsi_ISID_a = -1;
157 static int hf_iscsi_ISID_b = -1;
158 static int hf_iscsi_ISID_c = -1;
159 static int hf_iscsi_ISID_d = -1;
161 static int hf_iscsi_TSID = -1;
162 static int hf_iscsi_TSIH = -1;
163 static int hf_iscsi_InitStatSN = -1;
164 static int hf_iscsi_InitCmdSN = -1;
166 static int hf_iscsi_Login_X = -1;
168 static int hf_iscsi_Login_T = -1;
169 static int hf_iscsi_Login_CSG = -1;
170 static int hf_iscsi_Login_NSG = -1;
171 static int hf_iscsi_Login_Status = -1;
172 static int hf_iscsi_KeyValue = -1;
173 static int hf_iscsi_Text_F = -1;
174 static int hf_iscsi_ExpDataSN = -1;
175 static int hf_iscsi_R2TSN = -1;
176 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
177 static int hf_iscsi_RefCmdSN = -1;
178 static int hf_iscsi_TaskManagementFunction_Function = -1;
179 static int hf_iscsi_TaskManagementFunction_Response = -1;
180 static int hf_iscsi_Logout_Reason = -1;
181 static int hf_iscsi_Logout_Response = -1;
182 static int hf_iscsi_Time2Wait = -1;
183 static int hf_iscsi_Time2Retain = -1;
184 static int hf_iscsi_DesiredDataLength = -1;
185 static int hf_iscsi_AsyncEvent = -1;
186 static int hf_iscsi_EventVendorCode = -1;
187 static int hf_iscsi_Parameter1 = -1;
188 static int hf_iscsi_Parameter2 = -1;
189 static int hf_iscsi_Parameter3 = -1;
190 static int hf_iscsi_Reject_Reason = -1;
191 static int hf_iscsi_snack_type = -1;
192 static int hf_iscsi_BegRun = -1;
193 static int hf_iscsi_RunLength = -1;
195 /* Initialize the subtree pointers */
196 static gint ett_iscsi = -1;
197 static gint ett_iscsi_KeyValues = -1;
198 static gint ett_iscsi_CDB = -1;
199 static gint ett_iscsi_Flags = -1;
200 /* #ifndef DRAFT08 */
201 static gint ett_iscsi_ISID = -1;
204 typedef struct _iscsi_conv_key {
209 typedef struct _iscsi_conv_data {
215 static GHashTable *iscsi_req_hash = NULL;
216 static GMemChunk *iscsi_req_keys = NULL;
217 static GMemChunk *iscsi_req_vals = NULL;
218 static guint32 iscsi_init_count = 25;
226 #define OPCODE_MASK 0x3f
228 #define TARGET_OPCODE_BIT 0x20
230 #define ISCSI_OPCODE_NOP_OUT 0x00
231 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
232 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
233 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
234 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
235 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
236 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
237 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
238 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
239 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
240 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
242 #define ISCSI_OPCODE_NOP_IN 0x20
243 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
244 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
245 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
246 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
247 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
248 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
249 #define ISCSI_OPCODE_R2T 0x31
250 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
251 #define ISCSI_OPCODE_REJECT 0x3f
252 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
253 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
254 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
257 #define CSG_MASK (0x03 << CSG_SHIFT)
258 #define NSG_MASK 0x03
260 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
261 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
262 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
264 #define ISCSI_SCSI_DATA_FLAG_S 0x01
265 #define ISCSI_SCSI_DATA_FLAG_U 0x02
266 #define ISCSI_SCSI_DATA_FLAG_O 0x04
267 #define ISCSI_SCSI_DATA_FLAG_A 0x40
268 #define ISCSI_SCSI_DATA_FLAG_F 0x80
270 static const value_string iscsi_opcodes[] = {
271 { ISCSI_OPCODE_NOP_OUT, "NOP Out" },
272 { ISCSI_OPCODE_SCSI_COMMAND, "SCSI Command" },
273 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION, "Task Management Function" },
274 { ISCSI_OPCODE_LOGIN_COMMAND, "Login Command" },
275 { ISCSI_OPCODE_TEXT_COMMAND, "Text Command" },
276 { ISCSI_OPCODE_SCSI_DATA_OUT, "SCSI Data Out" },
277 { ISCSI_OPCODE_LOGOUT_COMMAND, "Logout Command" },
278 { ISCSI_OPCODE_SNACK_REQUEST, "SNACK Request" },
279 { ISCSI_OPCODE_VENDOR_SPECIFIC_I0, "Vendor Specific I0" },
280 { ISCSI_OPCODE_VENDOR_SPECIFIC_I1, "Vendor Specific I1" },
281 { ISCSI_OPCODE_VENDOR_SPECIFIC_I2, "Vendor Specific I2" },
283 { ISCSI_OPCODE_NOP_IN, "NOP In" },
284 { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
285 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
286 { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
287 { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
288 { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
289 { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
290 { ISCSI_OPCODE_R2T, "Ready To Transfer" },
291 { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
292 { ISCSI_OPCODE_REJECT, "Reject"},
293 { ISCSI_OPCODE_VENDOR_SPECIFIC_T0, "Vendor Specific T0" },
294 { ISCSI_OPCODE_VENDOR_SPECIFIC_T1, "Vendor Specific T1" },
295 { ISCSI_OPCODE_VENDOR_SPECIFIC_T2, "Vendor Specific T2" },
300 static const true_false_string iscsi_meaning_X = {
307 static const true_false_string iscsi_meaning_login_X = {
308 "Reinstate failed connection",
313 static const true_false_string iscsi_meaning_I = {
314 "Immediate delivery",
318 static const true_false_string iscsi_meaning_F = {
319 "Final PDU in sequence",
320 "Not final PDU in sequence"
323 static const true_false_string iscsi_meaning_A = {
324 "Acknowledge requested",
325 "Acknowledge not requested"
328 static const true_false_string iscsi_meaning_T = {
329 "Transit to next login stage",
330 "Stay in current login stage"
333 static const true_false_string iscsi_meaning_S = {
334 "Response contains SCSI status",
335 "Response does not contain SCSI status"
338 static const true_false_string iscsi_meaning_R = {
339 "Data will be read from target",
340 "No data will be read from target"
343 static const true_false_string iscsi_meaning_W = {
344 "Data will be written to target",
345 "No data will be written to target"
348 static const true_false_string iscsi_meaning_o = {
349 "Read part of bi-directional command overflowed",
350 "No overflow of read part of bi-directional command",
353 static const true_false_string iscsi_meaning_u = {
354 "Read part of bi-directional command underflowed",
355 "No underflow of read part of bi-directional command",
358 static const true_false_string iscsi_meaning_O = {
359 "Residual overflow occurred",
360 "No residual overflow occurred",
363 static const true_false_string iscsi_meaning_U = {
364 "Residual underflow occurred",
365 "No residual underflow occurred",
368 static const value_string iscsi_scsi_responses[] = {
369 { 0, "Command completed at target" },
370 { 1, "Response does not contain SCSI status"},
374 static const value_string iscsi_scsicommand_taskattrs[] = {
378 {3, "Head of Queue"},
383 static const value_string iscsi_task_management_responses[] = {
384 {0, "Function complete"},
385 {1, "Task not in task set"},
386 {2, "LUN does not exist"},
387 {3, "Task still allegiant"},
388 {4, "Task failover not supported"},
389 {5, "Task management function not supported"},
390 {6, "Authorisation failed"},
391 {255, "Function rejected"},
395 static const value_string iscsi_task_management_functions[] = {
397 {2, "Abort Task Set"},
399 {4, "Clear Task Set"},
400 {5, "Logical Unit Reset"},
401 {6, "Target Warm Reset"},
402 {7, "Target Cold Reset"},
406 static const value_string iscsi_login_status[] = {
408 {0x0101, "Target moved temporarily"},
409 {0x0102, "Target moved permanently"},
410 {0x0200, "Initiator error (miscellaneous error)"},
411 {0x0201, "Athentication failed"},
412 {0x0202, "Authorisation failure"},
413 {0x0203, "Target not found"},
414 {0x0204, "Target removed"},
415 {0x0205, "Unsupported version"},
416 {0x0206, "Too many connections"},
417 {0x0207, "Missing parameter"},
418 {0x0208, "Can't include in session"},
419 {0x0209, "Session type not supported"},
420 {0x020a, "Session does not exist"},
421 {0x020b, "Invalid request during login"},
422 {0x0300, "Target error (miscellaneous error)"},
423 {0x0301, "Service unavailable"},
424 {0x0302, "Out of resources"},
428 static const value_string iscsi_login_stage[] = {
429 {0, "Security negotiation"},
430 {1, "Operational negotiation"},
431 {3, "Full feature phase"},
435 /* #ifndef DRAFT08 */
436 static const value_string iscsi_isid_type[] = {
438 {0x01, "IANA Enterprise Number"},
444 static const value_string iscsi_logout_reasons[] = {
445 {0, "Close session"},
446 {1, "Close connection"},
447 {2, "Remove connection for recovery"},
451 static const value_string iscsi_logout_response[] = {
452 {0, "Connection closed successfully"},
453 {1, "CID not found"},
454 {2, "Connection recovery not supported"},
455 {3, "Cleanup failed for various reasons"},
459 static const value_string iscsi_asyncevents[] = {
460 {0, "A SCSI asynchronous event is reported in the sense data"},
461 {1, "Target requests logout"},
462 {2, "Target will/has dropped connection"},
463 {3, "Target will/has dropped all connections"},
464 {4, "Target requests parameter negotiation"},
468 static const value_string iscsi_snack_types[] = {
471 /* #ifndef DRAFT08 */
477 static const value_string iscsi_reject_reasons[] = {
479 {0x01, "Full feature phase command before login"},
481 {0x02, "Data (payload) digest error"},
482 {0x03, "Data SNACK reject"},
483 {0x04, "Protocol error"},
484 {0x05, "Command not supported in this session type"},
485 {0x06, "Immediate command reject (too many immediate commands)"},
486 {0x07, "Task in progress"},
487 {0x08, "Invalid SNACK"},
488 {0x09, "Bookmark reject (no bookmark for this initiator task tag)"},
489 {0x0a, "Bookmark reject (can't generate bookmark - out of resources)"},
490 {0x0b, "Negotiation reset"},
494 /*****************************************************************/
496 /* CRC LOOKUP TABLE */
497 /* ================ */
498 /* The following CRC lookup table was generated automagically */
499 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
500 /* Program V1.0 using the following model parameters: */
502 /* Width : 4 bytes. */
503 /* Poly : 0x1EDC6F41L */
504 /* Reverse : TRUE. */
506 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
507 /* see the document titled "A Painless Guide to CRC Error */
508 /* Detection Algorithms" by Ross Williams */
509 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
510 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
512 /*****************************************************************/
514 static guint32 crc32Table[256] = {
515 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
516 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
517 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
518 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
519 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
520 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
521 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
522 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
523 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
524 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
525 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
526 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
527 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
528 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
529 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
530 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
531 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
532 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
533 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
534 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
535 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
536 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
537 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
538 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
539 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
540 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
541 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
542 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
543 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
544 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
545 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
546 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
547 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
548 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
549 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
550 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
551 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
552 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
553 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
554 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
555 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
556 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
557 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
558 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
559 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
560 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
561 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
562 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
563 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
564 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
565 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
566 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
567 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
568 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
569 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
570 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
571 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
572 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
573 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
574 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
575 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
576 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
577 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
578 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
581 #define CRC32C_PRELOAD 0xffffffff
584 calculateCRC32(const void *buf, int len, guint32 crc) {
585 guint8 *p = (guint8 *)buf;
587 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
595 iscsi_equal(gconstpointer v, gconstpointer w)
597 iscsi_conv_key_t *v1 = (iscsi_conv_key_t *)v;
598 iscsi_conv_key_t *v2 = (iscsi_conv_key_t *)w;
600 return (v1->conv_idx == v2->conv_idx);
604 iscsi_hash (gconstpointer v)
606 iscsi_conv_key_t *key = (iscsi_conv_key_t *)v;
615 * Protocol initialization
618 iscsi_init_protocol(void)
621 g_mem_chunk_destroy(iscsi_req_keys);
623 g_mem_chunk_destroy(iscsi_req_vals);
625 g_hash_table_destroy(iscsi_req_hash);
627 iscsi_req_hash = g_hash_table_new(iscsi_hash, iscsi_equal);
628 iscsi_req_keys = g_mem_chunk_new("iscsi_req_keys",
629 sizeof(iscsi_conv_key_t),
630 iscsi_init_count * sizeof(iscsi_conv_key_t),
632 iscsi_req_vals = g_mem_chunk_new("iscsi_req_vals",
633 sizeof(iscsi_conv_data_t),
634 iscsi_init_count * sizeof(iscsi_conv_data_t),
639 iscsi_min(int a, int b) {
640 return (a < b)? a : b;
644 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
645 const gint limit = offset + text_len;
646 while(offset < limit) {
647 gint len = tvb_strnlen(tvb, offset, limit - offset);
649 len = limit - offset;
652 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
659 handleHeaderDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
660 int available_bytes = tvb_length_remaining(tvb, offset);
661 if(enableHeaderDigests) {
662 if(headerDigestIsCRC32) {
663 if(available_bytes >= (headerLen + 4)) {
664 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
665 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
667 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
670 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);
673 return offset + headerLen + 4;
675 if(available_bytes >= (headerLen + headerDigestSize)) {
676 proto_tree_add_item(ti, hf_iscsi_HeaderDigest, tvb, offset + headerLen, headerDigestSize, FALSE);
678 return offset + headerLen + headerDigestSize;
680 return offset + headerLen;
684 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
685 int available_bytes = tvb_length_remaining(tvb, offset);
686 if(enableDataDigests) {
687 if(dataDigestIsCRC32) {
688 if(available_bytes >= (dataLen + 4)) {
689 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
690 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
692 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
695 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);
698 return offset + dataLen + 4;
700 if(available_bytes >= (dataLen + dataDigestSize)) {
701 proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
703 return offset + dataLen + dataDigestSize;
705 return offset + dataLen;
709 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
710 if(endOffset > offset) {
711 int dataOffset = offset;
712 int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
714 proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
717 if(offset < endOffset && (offset & 3) != 0) {
718 int padding = 4 - (offset & 3);
719 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
722 if(dataSegmentLen > 0 && offset < endOffset)
723 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
730 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
731 if(endOffset > offset) {
732 int dataOffset = offset;
733 int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
735 proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
736 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
737 offset = addTextKeys(tt, tvb, offset, textLen);
739 if(offset < endOffset && (offset & 3) != 0) {
740 int padding = 4 - (offset & 3);
741 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
744 if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
745 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
750 /* Code to actually dissect the packets */
752 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len) {
754 guint original_offset = offset;
755 proto_tree *ti = NULL;
756 guint8 scsi_status = 0;
757 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
758 guint end_offset = offset + tvb_length_remaining(tvb, offset);
759 guint32 del_usecs = 0;
760 conversation_t *conversation = NULL;
761 iscsi_conv_data_t *cdata = NULL;
762 iscsi_conv_key_t ckey, *req_key;
763 scsi_task_id_t task_key;
764 int paddedDataSegmentLength = data_segment_len;
765 if(paddedDataSegmentLength & 3)
766 paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
768 /* Make entries in Protocol column and Info column on summary display */
769 if (check_col(pinfo->cinfo, COL_PROTOCOL))
770 col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
772 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
773 opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
774 scsi_status = tvb_get_guint8 (tvb, offset+3);
777 if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
778 (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
779 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
780 conversation = find_conversation (&pinfo->src, &pinfo->dst,
781 pinfo->ptype, pinfo->srcport,
784 ckey.conv_idx = conversation->index;
785 ckey.itt = tvb_get_ntohl (tvb, offset+16);
787 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_hash,
790 task_key.conv_id = ckey.conv_idx;
791 task_key.task_id = ckey.itt;
792 pinfo->private_data = &task_key;
794 /* no conversation, meaning we didn't see the request */
795 pinfo->private_data = NULL;
799 del_usecs = (pinfo->fd->abs_secs - cdata->abs_secs)* 1000000 +
800 (pinfo->fd->abs_usecs - cdata->abs_usecs);
803 else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
804 conversation = find_conversation (&pinfo->src, &pinfo->dst,
805 pinfo->ptype, pinfo->srcport,
808 conversation = conversation_new (&pinfo->src, &pinfo->dst,
809 pinfo->ptype, pinfo->srcport,
813 ckey.conv_idx = conversation->index;
814 ckey.itt = tvb_get_ntohl (tvb, offset+16);
816 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_hash,
819 /* Since we never free the memory used by an exchange, this maybe a
820 * case of another request using the same exchange as a previous
823 cdata->abs_usecs = pinfo->fd->abs_usecs;
824 cdata->abs_secs = pinfo->fd->abs_secs;
827 req_key = g_mem_chunk_alloc (iscsi_req_keys);
828 req_key->conv_idx = conversation->index;
829 req_key->itt = tvb_get_ntohl (tvb, offset+16);
831 cdata = g_mem_chunk_alloc (iscsi_req_vals);
832 cdata->abs_usecs = pinfo->fd->abs_usecs;
833 cdata->abs_secs = pinfo->fd->abs_secs;
835 g_hash_table_insert (iscsi_req_hash, req_key, cdata);
838 /* The SCSI protocol uses this as the key to detect a
839 * SCSI-level conversation. */
840 task_key.conv_id = ckey.conv_idx;
841 task_key.task_id = ckey.itt;
842 pinfo->private_data = &task_key;
845 pinfo->private_data = NULL;
848 if (check_col(pinfo->cinfo, COL_INFO)) {
850 if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
852 col_append_str(pinfo->cinfo, COL_INFO, (char *)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) {
866 guint16 logoutReason;
867 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
868 logoutReason = tvb_get_ntohs(tvb, offset+11);
869 } else if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
870 logoutReason = tvb_get_ntohs(tvb, offset+1) & 0x7f;
873 logoutReason = tvb_get_ntohs(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(ti, tvb, offset, 48);
940 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
942 else if(opcode == ISCSI_OPCODE_NOP_IN) {
944 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
945 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
947 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
948 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
949 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
950 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
951 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
952 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
953 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
954 offset = handleHeaderDigest(ti, tvb, offset, 48);
955 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
957 else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
959 guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
961 gint b = tvb_get_guint8(tvb, offset + 1);
962 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
963 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
965 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
966 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
967 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
968 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
970 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
971 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
973 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
974 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
975 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
976 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
977 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
978 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
979 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
982 /* FIXME - disssect AHS? */
983 proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 48, ahsLen, FALSE);
985 offset = handleHeaderDigest(ti, tvb, offset, 48 + ahsLen);
987 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
989 else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
992 if (del_usecs > 1000)
993 proto_tree_add_text (ti, tvb, offset, 0,
994 "Cmd Response Time: %d msecs",
997 proto_tree_add_text (ti, tvb, offset, 0,
998 "Cmd Response Time: %d usecs",
1002 gint b = tvb_get_guint8(tvb, offset + 1);
1003 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1004 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1006 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
1007 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
1008 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
1009 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
1011 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
1012 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1013 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1014 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1016 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1017 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1018 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1019 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
1021 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1022 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1023 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1024 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1025 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1026 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
1029 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
1030 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
1032 offset = handleHeaderDigest(ti, tvb, offset, 48);
1033 /* do not update offset here because the data segment is
1034 * dissected below */
1035 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1037 else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
1038 /* Task Management Function */
1039 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
1040 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1041 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1042 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1044 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1045 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1046 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1047 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1048 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1049 proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1050 offset = handleHeaderDigest(ti, tvb, offset, 48);
1052 else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1053 /* Task Management Function Response */
1054 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
1055 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1056 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1057 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1059 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1060 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1061 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1063 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1064 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1065 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1066 offset = handleHeaderDigest(ti, tvb, offset, 48);
1068 else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1070 int digestsActive = 0;
1072 gint b = tvb_get_guint8(tvb, offset + 1);
1073 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1074 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1078 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1079 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1082 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1083 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1084 proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1086 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1087 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1089 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1090 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1091 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1092 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1094 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1095 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1096 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1097 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1100 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1101 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1102 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1103 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1104 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1105 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1108 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1109 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1110 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1111 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1112 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1115 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1116 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1119 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1121 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1122 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1123 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1125 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1126 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1128 offset = handleHeaderDigest(ti, tvb, offset, 48);
1131 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1133 else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1134 /* Login Response */
1135 int digestsActive = 0;
1137 gint b = tvb_get_guint8(tvb, offset + 1);
1138 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1139 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1143 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1144 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1147 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1148 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1149 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1152 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1153 proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1154 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1155 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1157 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1158 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1159 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1162 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1163 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1164 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1165 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1166 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1167 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1170 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1171 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1172 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1173 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1174 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1177 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1178 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1181 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1183 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1184 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1185 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1186 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1187 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1189 offset = handleHeaderDigest(ti, tvb, offset, 48);
1192 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1194 else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1197 gint b = tvb_get_guint8(tvb, offset + 1);
1198 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1199 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1201 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1203 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1204 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1206 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1207 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1208 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1210 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1211 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1212 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1213 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1214 offset = handleHeaderDigest(ti, tvb, offset, 48);
1215 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1217 else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1220 gint b = tvb_get_guint8(tvb, offset + 1);
1221 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1222 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1224 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1226 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1227 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1229 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1230 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1231 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1233 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1234 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1235 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1236 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1237 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1238 offset = handleHeaderDigest(ti, tvb, offset, 48);
1239 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1241 else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1242 /* SCSI Data Out (write) */
1244 gint b = tvb_get_guint8(tvb, offset + 1);
1245 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1246 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1248 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1250 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1251 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1253 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1254 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1255 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1256 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1257 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1258 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1259 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1260 offset = handleHeaderDigest(ti, tvb, offset, 48);
1261 /* do not update offset here because the data segment is
1262 * dissected below */
1263 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1265 else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
1266 /* SCSI Data In (read) */
1268 gint b = tvb_get_guint8(tvb, offset + 1);
1269 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1270 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1272 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1273 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1274 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
1276 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1277 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1278 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1280 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1281 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1282 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1284 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1285 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1286 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1288 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1289 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1290 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1293 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1295 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1296 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1297 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1298 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1299 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1300 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1301 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1303 offset = handleHeaderDigest(ti, tvb, offset, 48);
1304 /* do not update offset here because the data segment is
1305 * dissected below */
1306 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1308 else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1309 /* Logout Command */
1310 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1311 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 1, 1, FALSE);
1313 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1314 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1315 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1317 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1318 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1319 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1321 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1322 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1323 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1324 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT13) {
1325 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
1328 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1329 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1330 offset = handleHeaderDigest(ti, tvb, offset, 48);
1332 else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1333 /* Logout Response */
1334 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1335 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1336 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1337 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1339 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1340 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1341 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1342 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1343 proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1344 proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1345 offset = handleHeaderDigest(ti, tvb, offset, 48);
1347 else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1350 gint b = tvb_get_guint8(tvb, offset + 1);
1352 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1353 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1356 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1358 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1359 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1360 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1361 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1363 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1364 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1365 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1366 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1367 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1368 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1371 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1372 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1373 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1374 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1376 offset = handleHeaderDigest(ti, tvb, offset, 48);
1378 else if(opcode == ISCSI_OPCODE_R2T) {
1380 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1381 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1382 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1383 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1385 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1386 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1387 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1388 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1389 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1390 proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
1391 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1392 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1393 offset = handleHeaderDigest(ti, tvb, offset, 48);
1395 else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1396 /* Asynchronous Message */
1397 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1398 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1400 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1401 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1402 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1403 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1404 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1405 proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1406 proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1407 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1408 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1409 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1410 offset = handleHeaderDigest(ti, tvb, offset, 48);
1411 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
1413 else if(opcode == ISCSI_OPCODE_REJECT) {
1415 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
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_StatSN, tvb, offset + 24, 4, FALSE);
1421 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1422 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1423 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1424 offset = handleHeaderDigest(ti, tvb, offset, 48);
1425 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1427 else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
1428 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
1429 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
1430 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
1431 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
1432 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
1433 /* Vendor specific opcodes */
1434 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1435 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1437 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1438 offset = handleHeaderDigest(ti, tvb, offset, 48);
1439 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
1442 proto_item_set_len(ti, offset - original_offset);
1445 if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
1447 ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
1449 dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16);
1451 else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1452 if (scsi_status == 0x2) {
1453 /* A SCSI response with Check Condition contains sense data */
1454 /* offset is setup correctly by the iscsi code for response above */
1455 if((end_offset - offset) >= 2) {
1456 int senseLen = tvb_get_ntohs(tvb, offset);
1458 proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1461 dissect_scsi_snsinfo (tvb, pinfo, tree, offset,
1462 iscsi_min (senseLen,
1463 end_offset-offset));
1467 dissect_scsi_rsp (tvb, pinfo, tree);
1469 if (cdata && tree) {
1470 /* destroy the data structures for this SCSI task */
1472 g_mem_chunk_free (iscsi_req_vals, cdata);
1473 g_hash_table_remove (iscsi_req_hash, &ckey);
1474 pinfo->private_data = NULL;
1478 else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1479 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1480 /* offset is setup correctly by the iscsi code for response above */
1481 dissect_scsi_payload (tvb, pinfo, tree, offset, FALSE,
1482 iscsi_min (data_segment_len, end_offset-offset));
1487 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1488 /* Set up structures needed to add the protocol subtree and manage it */
1489 guint iSCSIPdusDissected = 0;
1491 guint32 available_bytes = tvb_length_remaining(tvb, offset);
1493 if (!proto_is_protocol_enabled(proto_iscsi))
1494 return FALSE; /* iSCSI has been disabled */
1496 /* quick check to see if the packet is long enough to contain the
1497 * minimum amount of information we need */
1498 if (available_bytes < 48 && (!iscsi_desegment || available_bytes < 8)) {
1499 /* no, so give up */
1503 /* process multiple iSCSI PDUs per packet */
1504 while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
1505 const char *opcode_str = NULL;
1506 guint32 data_segment_len;
1507 guint8 opcode = tvb_get_guint8(tvb, offset + 0);
1508 guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
1511 /* mask out any extra bits in the opcode byte */
1512 opcode &= OPCODE_MASK;
1514 opcode_str = match_strval(opcode, iscsi_opcodes);
1515 if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
1516 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1517 opcode == ISCSI_OPCODE_R2T ||
1518 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1519 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1520 opcode == ISCSI_OPCODE_SNACK_REQUEST)
1521 data_segment_len = 0;
1523 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
1525 if(opcode_str == NULL) {
1528 else if(iscsi_port != 0 &&
1529 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
1530 (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
1533 else if(enable_bogosity_filter) {
1534 /* try and distinguish between data and real headers */
1535 if(data_segment_len > bogus_pdu_data_length_threshold) {
1538 else if(demand_good_f_bit &&
1539 !(secondPduByte & 0x80) &&
1540 (opcode == ISCSI_OPCODE_NOP_OUT ||
1541 opcode == ISCSI_OPCODE_NOP_IN ||
1542 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1543 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1544 opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
1545 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1546 opcode == ISCSI_OPCODE_R2T ||
1547 opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
1548 opcode == ISCSI_OPCODE_SNACK_REQUEST ||
1549 opcode == ISCSI_OPCODE_REJECT)) {
1555 return iSCSIPdusDissected > 0;
1558 guint32 pduLen = 48;
1559 int digestsActive = 1;
1561 if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
1562 opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1563 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1564 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
1565 /* digests are not yet turned on */
1574 if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1576 pduLen += tvb_get_guint8(tvb, offset + 4) * 4;
1579 pduLen += data_segment_len;
1580 if((pduLen & 3) != 0)
1581 pduLen += 4 - (pduLen & 3);
1583 if(digestsActive && enableHeaderDigests) {
1584 if(headerDigestIsCRC32)
1587 pduLen += headerDigestSize;
1590 if(digestsActive && data_segment_len > 0 && enableDataDigests) {
1591 if(dataDigestIsCRC32)
1594 pduLen += dataDigestSize;
1598 * Desegmentation check.
1600 if(iscsi_desegment && pinfo->can_desegment) {
1601 if(pduLen > available_bytes) {
1603 * This frame doesn't have all of the data for
1604 * this message, but we can do reassembly on it.
1606 * Tell the TCP dissector where the data for this
1607 * message starts in the data it handed us, and
1608 * how many more bytes we need, and return.
1610 pinfo->desegment_offset = offset;
1611 pinfo->desegment_len = pduLen - available_bytes;
1616 if(check_col(pinfo->cinfo, COL_INFO)) {
1617 if(iSCSIPdusDissected == 0)
1618 col_set_str(pinfo->cinfo, COL_INFO, "");
1620 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1623 dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len);
1624 if(pduLen > available_bytes)
1625 pduLen = available_bytes;
1627 available_bytes -= pduLen;
1628 ++iSCSIPdusDissected;
1632 return iSCSIPdusDissected > 0;
1636 /* Register the protocol with Ethereal */
1639 * this format is require because a script is used to build the C
1640 * function that calls all the protocol registration.
1644 proto_register_iscsi(void)
1647 /* Setup list of header fields See Section 1.6.1 for details*/
1648 static hf_register_info hf[] = {
1650 { "AHS", "iscsi.ahs",
1651 FT_BYTES, BASE_HEX, NULL, 0,
1652 "Additional header segment", HFILL }
1654 { &hf_iscsi_Padding,
1655 { "Padding", "iscsi.padding",
1656 FT_BYTES, BASE_HEX, NULL, 0,
1657 "Padding to 4 byte boundary", HFILL }
1659 { &hf_iscsi_ping_data,
1660 { "PingData", "iscsi.pingdata",
1661 FT_BYTES, BASE_HEX, NULL, 0,
1662 "Ping Data", HFILL }
1664 { &hf_iscsi_immediate_data,
1665 { "ImmediateData", "iscsi.immediatedata",
1666 FT_BYTES, BASE_HEX, NULL, 0,
1667 "Immediate Data", HFILL }
1669 { &hf_iscsi_write_data,
1670 { "WriteData", "iscsi.writedata",
1671 FT_BYTES, BASE_HEX, NULL, 0,
1672 "Write Data", HFILL }
1674 { &hf_iscsi_read_data,
1675 { "ReadData", "iscsi.readdata",
1676 FT_BYTES, BASE_HEX, NULL, 0,
1677 "Read Data", HFILL }
1679 { &hf_iscsi_error_pdu_data,
1680 { "ErrorPDUData", "iscsi.errorpdudata",
1681 FT_BYTES, BASE_HEX, NULL, 0,
1682 "Error PDU Data", HFILL }
1684 { &hf_iscsi_async_message_data,
1685 { "AsyncMessageData", "iscsi.asyncmessagedata",
1686 FT_BYTES, BASE_HEX, NULL, 0,
1687 "Async Message Data", HFILL }
1689 { &hf_iscsi_vendor_specific_data,
1690 { "VendorSpecificData", "iscsi.vendorspecificdata",
1691 FT_BYTES, BASE_HEX, NULL, 0,
1692 "Vendor Specific Data", HFILL }
1694 { &hf_iscsi_HeaderDigest,
1695 { "HeaderDigest", "iscsi.headerdigest",
1696 FT_BYTES, BASE_HEX, NULL, 0,
1697 "Header Digest", HFILL }
1699 { &hf_iscsi_HeaderDigest32,
1700 { "HeaderDigest", "iscsi.headerdigest32",
1701 FT_UINT32, BASE_HEX, NULL, 0,
1702 "Header Digest", HFILL }
1704 { &hf_iscsi_DataDigest,
1705 { "DataDigest", "iscsi.datadigest",
1706 FT_BYTES, BASE_HEX, NULL, 0,
1707 "Data Digest", HFILL }
1709 { &hf_iscsi_DataDigest32,
1710 { "DataDigest", "iscsi.datadigest32",
1711 FT_UINT32, BASE_HEX, NULL, 0,
1712 "Data Digest", HFILL }
1715 { "Opcode", "iscsi.opcode",
1716 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
1719 /* #ifdef DRAFT08 */
1722 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1723 "Command Retry", HFILL }
1728 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
1729 "Immediate delivery", HFILL }
1732 { "Flags", "iscsi.flags",
1733 FT_UINT8, BASE_HEX, NULL, 0,
1734 "Opcode specific flags", HFILL }
1736 { &hf_iscsi_SCSICommand_F,
1737 { "F", "iscsi.scsicommand.F",
1738 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1739 "PDU completes command", HFILL }
1741 { &hf_iscsi_SCSICommand_R,
1742 { "R", "iscsi.scsicommand.R",
1743 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
1744 "Command reads from SCSI target", HFILL }
1746 { &hf_iscsi_SCSICommand_W,
1747 { "W", "iscsi.scsicommand.W",
1748 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
1749 "Command writes to SCSI target", HFILL }
1751 { &hf_iscsi_SCSICommand_Attr,
1752 { "Attr", "iscsi.scsicommand.attr",
1753 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
1754 "SCSI task attributes", HFILL }
1756 { &hf_iscsi_SCSICommand_CRN,
1757 { "CRN", "iscsi.scsicommand.crn",
1758 FT_UINT8, BASE_HEX, NULL, 0,
1759 "SCSI command reference number", HFILL }
1761 { &hf_iscsi_SCSICommand_AddCDB,
1762 { "AddCDB", "iscsi.scsicommand.addcdb",
1763 FT_UINT8, BASE_HEX, NULL, 0,
1764 "Additional CDB length (in 4 byte units)", HFILL }
1766 { &hf_iscsi_DataSegmentLength,
1767 { "DataSegmentLength", "iscsi.datasegmentlength",
1768 FT_UINT32, BASE_HEX, NULL, 0,
1769 "Data segment length (bytes)", HFILL }
1771 { &hf_iscsi_TotalAHSLength,
1772 { "TotalAHSLength", "iscsi.totalahslength",
1773 FT_UINT8, BASE_HEX, NULL, 0,
1774 "Total additional header segment length (4 byte words)", HFILL }
1777 { "LUN", "iscsi.lun",
1778 FT_BYTES, BASE_HEX, NULL, 0,
1779 "Logical Unit Number", HFILL }
1781 { &hf_iscsi_InitiatorTaskTag,
1782 { "InitiatorTaskTag", "iscsi.initiatortasktag",
1783 FT_UINT32, BASE_HEX, NULL, 0,
1784 "Initiator's task tag", HFILL }
1786 { &hf_iscsi_ExpectedDataTransferLength,
1787 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
1788 FT_UINT32, BASE_HEX, NULL, 0,
1789 "Expected length of data transfer", HFILL }
1792 { "CmdSN", "iscsi.cmdsn",
1793 FT_UINT32, BASE_HEX, NULL, 0,
1794 "Sequence number for this command (0 == immediate)", HFILL }
1796 { &hf_iscsi_ExpStatSN,
1797 { "ExpStatSN", "iscsi.expstatsn",
1798 FT_UINT32, BASE_HEX, NULL, 0,
1799 "Next expected status sequence number", HFILL }
1801 { &hf_iscsi_SCSIResponse_ResidualCount,
1802 { "ResidualCount", "iscsi.scsiresponse.residualcount",
1803 FT_UINT32, BASE_HEX, NULL, 0,
1804 "Residual count", HFILL }
1807 { "StatSN", "iscsi.statsn",
1808 FT_UINT32, BASE_HEX, NULL, 0,
1809 "Status sequence number", HFILL }
1811 { &hf_iscsi_ExpCmdSN,
1812 { "ExpCmdSN", "iscsi.expcmdsn",
1813 FT_UINT32, BASE_HEX, NULL, 0,
1814 "Next expected command sequence number", HFILL }
1816 { &hf_iscsi_MaxCmdSN,
1817 { "MaxCmdSN", "iscsi.maxcmdsn",
1818 FT_UINT32, BASE_HEX, NULL, 0,
1819 "Maximum acceptable command sequence number", HFILL }
1821 { &hf_iscsi_SCSIResponse_o,
1822 { "o", "iscsi.scsiresponse.o",
1823 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
1824 "Bi-directional read residual overflow", HFILL }
1826 { &hf_iscsi_SCSIResponse_u,
1827 { "u", "iscsi.scsiresponse.u",
1828 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
1829 "Bi-directional read residual underflow", HFILL }
1831 { &hf_iscsi_SCSIResponse_O,
1832 { "O", "iscsi.scsiresponse.O",
1833 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
1834 "Residual overflow", HFILL }
1836 { &hf_iscsi_SCSIResponse_U,
1837 { "U", "iscsi.scsiresponse.U",
1838 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
1839 "Residual underflow", HFILL }
1841 { &hf_iscsi_SCSIResponse_Status,
1842 { "Status", "iscsi.scsiresponse.status",
1843 FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
1844 "SCSI command status value", HFILL }
1846 { &hf_iscsi_SCSIResponse_Response,
1847 { "Response", "iscsi.scsiresponse.response",
1848 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
1849 "SCSI command response value", HFILL }
1851 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
1852 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
1853 FT_UINT32, BASE_HEX, NULL, 0,
1854 "Bi-directional read residual count", HFILL }
1856 { &hf_iscsi_SenseLength,
1857 { "SenseLength", "iscsi.scsiresponse.senselength",
1858 FT_UINT16, BASE_HEX, NULL, 0,
1859 "Sense data length", HFILL }
1861 { &hf_iscsi_SCSIData_F,
1862 { "F", "iscsi.scsidata.F",
1863 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
1864 "Final PDU", HFILL }
1866 { &hf_iscsi_SCSIData_A,
1867 { "A", "iscsi.scsidata.A",
1868 FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
1869 "Acknowledge Requested", HFILL }
1871 { &hf_iscsi_SCSIData_S,
1872 { "S", "iscsi.scsidata.S",
1873 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
1874 "PDU Contains SCSI command status", HFILL }
1876 { &hf_iscsi_SCSIData_U,
1877 { "U", "iscsi.scsidata.U",
1878 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
1879 "Residual underflow", HFILL }
1881 { &hf_iscsi_SCSIData_O,
1882 { "O", "iscsi.scsidata.O",
1883 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
1884 "Residual overflow", HFILL }
1886 { &hf_iscsi_TargetTransferTag,
1887 { "TargetTransferTag", "iscsi.targettransfertag",
1888 FT_UINT32, BASE_HEX, NULL, 0,
1889 "Target transfer tag", HFILL }
1891 { &hf_iscsi_BufferOffset,
1892 { "BufferOffset", "iscsi.bufferOffset",
1893 FT_UINT32, BASE_HEX, NULL, 0,
1894 "Buffer offset", HFILL }
1896 { &hf_iscsi_SCSIData_ResidualCount,
1897 { "ResidualCount", "iscsi.scsidata.readresidualcount",
1898 FT_UINT32, BASE_HEX, NULL, 0,
1899 "Residual count", HFILL }
1902 { "DataSN", "iscsi.datasn",
1903 FT_UINT32, BASE_HEX, NULL, 0,
1904 "Data sequence number", HFILL }
1906 { &hf_iscsi_VersionMax,
1907 { "VersionMax", "iscsi.versionmax",
1908 FT_UINT8, BASE_HEX, NULL, 0,
1909 "Maximum supported protocol version", HFILL }
1911 { &hf_iscsi_VersionMin,
1912 { "VersionMin", "iscsi.versionmin",
1913 FT_UINT8, BASE_HEX, NULL, 0,
1914 "Minimum supported protocol version", HFILL }
1916 { &hf_iscsi_VersionActive,
1917 { "VersionActive", "iscsi.versionactive",
1918 FT_UINT8, BASE_HEX, NULL, 0,
1919 "Negotiated protocol version", HFILL }
1922 { "CID", "iscsi.cid",
1923 FT_UINT16, BASE_HEX, NULL, 0,
1924 "Connection identifier", HFILL }
1926 /* #ifdef DRAFT08 */
1928 { "ISID", "iscsi.isid",
1929 FT_UINT16, BASE_HEX, NULL, 0,
1930 "Initiator part of session identifier", HFILL }
1934 { "ISID", "iscsi.isid",
1935 FT_BYTES, BASE_HEX, NULL, 0,
1936 "Initiator part of session identifier", HFILL }
1938 /* #ifdef DRAFT09 */
1939 { &hf_iscsi_ISID_Type,
1940 { "ISID_Type", "iscsi.isid.type",
1941 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
1942 "Initiator part of session identifier - type", HFILL }
1944 { &hf_iscsi_ISID_NamingAuthority,
1945 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
1946 FT_UINT24, BASE_HEX, NULL, 0,
1947 "Initiator part of session identifier - naming authority", HFILL }
1949 { &hf_iscsi_ISID_Qualifier,
1950 { "ISID_Qualifier", "iscsi.isid.qualifier",
1951 FT_UINT8, BASE_HEX, NULL, 0,
1952 "Initiator part of session identifier - qualifier", HFILL }
1956 { "ISID_t", "iscsi.isid.t",
1957 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
1958 "Initiator part of session identifier - t", HFILL }
1961 { "ISID_a", "iscsi.isid.a",
1962 FT_UINT8, BASE_HEX, NULL, 0x3f,
1963 "Initiator part of session identifier - a", HFILL }
1966 { "ISID_b", "iscsi.isid.b",
1967 FT_UINT16, BASE_HEX, NULL, 0,
1968 "Initiator part of session identifier - b", HFILL }
1971 { "ISID_c", "iscsi.isid.c",
1972 FT_UINT8, BASE_HEX, NULL, 0,
1973 "Initiator part of session identifier - c", HFILL }
1976 { "ISID_d", "iscsi.isid.d",
1977 FT_UINT16, BASE_HEX, NULL, 0,
1978 "Initiator part of session identifier - d", HFILL }
1983 { "TSID", "iscsi.tsid",
1984 FT_UINT16, BASE_HEX, NULL, 0,
1985 "Target part of session identifier", HFILL }
1988 { "TSIH", "iscsi.tsih",
1989 FT_UINT16, BASE_HEX, NULL, 0,
1990 "Target session identifying handle", HFILL }
1992 { &hf_iscsi_InitStatSN,
1993 { "InitStatSN", "iscsi.initstatsn",
1994 FT_UINT32, BASE_HEX, NULL, 0,
1995 "Initial status sequence number", HFILL }
1997 { &hf_iscsi_InitCmdSN,
1998 { "InitCmdSN", "iscsi.initcmdsn",
1999 FT_UINT32, BASE_HEX, NULL, 0,
2000 "Initial command sequence number", HFILL }
2002 { &hf_iscsi_Login_T,
2003 { "T", "iscsi.login.T",
2004 FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
2005 "Transit to next login stage", HFILL }
2007 /* #ifdef DRAFT09 */
2008 { &hf_iscsi_Login_X,
2009 { "X", "iscsi.login.X",
2010 FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
2011 "Restart Connection", HFILL }
2014 { &hf_iscsi_Login_CSG,
2015 { "CSG", "iscsi.login.csg",
2016 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
2017 "Current stage", HFILL }
2019 { &hf_iscsi_Login_NSG,
2020 { "NSG", "iscsi.login.nsg",
2021 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
2022 "Next stage", HFILL }
2024 { &hf_iscsi_Login_Status,
2025 { "Status", "iscsi.login.status",
2026 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
2027 "Status class and detail", HFILL }
2029 { &hf_iscsi_KeyValue,
2030 { "KeyValue", "iscsi.keyvalue",
2031 FT_STRING, 0, NULL, 0,
2032 "Key/value pair", HFILL }
2035 { "F", "iscsi.text.F",
2036 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2037 "Final PDU in text sequence", HFILL }
2039 { &hf_iscsi_ExpDataSN,
2040 { "ExpDataSN", "iscsi.expdatasn",
2041 FT_UINT32, BASE_HEX, NULL, 0,
2042 "Next expected data sequence number", HFILL }
2045 { "R2TSN", "iscsi.r2tsn",
2046 FT_UINT32, BASE_HEX, NULL, 0,
2047 "R2T PDU Number", HFILL }
2049 { &hf_iscsi_TaskManagementFunction_Response,
2050 { "Response", "iscsi.taskmanfun.response",
2051 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
2054 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
2055 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
2056 FT_UINT32, BASE_HEX, NULL, 0,
2057 "Referenced task tag", HFILL }
2059 { &hf_iscsi_RefCmdSN,
2060 { "RefCmdSN", "iscsi.refcmdsn",
2061 FT_UINT32, BASE_HEX, NULL, 0,
2062 "Command sequence number for command to be aborted", HFILL }
2064 { &hf_iscsi_TaskManagementFunction_Function,
2065 { "Function", "iscsi.taskmanfun.function",
2066 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
2067 "Requested task function", HFILL }
2069 { &hf_iscsi_Logout_Reason,
2070 { "Reason", "iscsi.logout.reason",
2071 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0x7F,
2072 "Reason for logout", HFILL }
2074 { &hf_iscsi_Logout_Response,
2075 { "Response", "iscsi.logout.response",
2076 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
2077 "Logout response", HFILL }
2079 { &hf_iscsi_Time2Wait,
2080 { "Time2Wait", "iscsi.time2wait",
2081 FT_UINT16, BASE_HEX, NULL, 0,
2082 "Time2Wait", HFILL }
2084 { &hf_iscsi_Time2Retain,
2085 { "Time2Retain", "iscsi.time2retain",
2086 FT_UINT16, BASE_HEX, NULL, 0,
2087 "Time2Retain", HFILL }
2089 { &hf_iscsi_DesiredDataLength,
2090 { "DesiredDataLength", "iscsi.desireddatalength",
2091 FT_UINT32, BASE_HEX, NULL, 0,
2092 "Desired data length (bytes)", HFILL }
2094 { &hf_iscsi_AsyncEvent,
2095 { "AsyncEvent", "iscsi.asyncevent",
2096 FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2097 "Async event type", HFILL }
2099 { &hf_iscsi_EventVendorCode,
2100 { "EventVendorCode", "iscsi.eventvendorcode",
2101 FT_UINT8, BASE_HEX, NULL, 0,
2102 "Event vendor code", HFILL }
2104 { &hf_iscsi_Parameter1,
2105 { "Parameter1", "iscsi.parameter1",
2106 FT_UINT16, BASE_HEX, NULL, 0,
2107 "Parameter 1", HFILL }
2109 { &hf_iscsi_Parameter2,
2110 { "Parameter2", "iscsi.parameter2",
2111 FT_UINT16, BASE_HEX, NULL, 0,
2112 "Parameter 2", HFILL }
2114 { &hf_iscsi_Parameter3,
2115 { "Parameter3", "iscsi.parameter3",
2116 FT_UINT16, BASE_HEX, NULL, 0,
2117 "Parameter 3", HFILL }
2119 { &hf_iscsi_Reject_Reason,
2120 { "Reason", "iscsi.reject.reason",
2121 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2122 "Reason for command rejection", HFILL }
2124 { &hf_iscsi_snack_type,
2125 { "S", "iscsi.snack.type",
2126 FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2127 "Type of SNACK requested", HFILL }
2130 { "BegRun", "iscsi.snack.begrun",
2131 FT_UINT32, BASE_HEX, NULL, 0,
2132 "First missed DataSN or StatSN", HFILL }
2134 { &hf_iscsi_RunLength,
2135 { "RunLength", "iscsi.snack.runlength",
2136 FT_UINT32, BASE_HEX, NULL, 0,
2137 "Number of additional missing status PDUs in this run", HFILL }
2141 /* Setup protocol subtree array */
2142 static gint *ett[] = {
2144 &ett_iscsi_KeyValues,
2147 /* #ifndef DRAFT08 */
2152 /* Register the protocol name and description */
2153 proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2155 /* Required function calls to register the header fields and
2157 proto_register_field_array(proto_iscsi, hf, array_length(hf));
2158 proto_register_subtree_array(ett, array_length(ett));
2159 register_init_routine (&iscsi_init_protocol);
2162 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2164 prefs_register_enum_preference(iscsi_module,
2167 "The iSCSI protocol version",
2168 &iscsi_protocol_version,
2169 iscsi_protocol_versions,
2172 prefs_register_bool_preference(iscsi_module,
2173 "desegment_iscsi_messages",
2174 "Desegment iSCSI messages",
2175 "When enabled, iSCSI messages that span multiple TCP segments are desegmented",
2178 prefs_register_bool_preference(iscsi_module,
2180 "Enable bogus pdu filter",
2181 "When enabled, packets that appear bogus are ignored",
2182 &enable_bogosity_filter);
2184 prefs_register_bool_preference(iscsi_module,
2185 "demand_good_f_bit",
2186 "Ignore packets with bad F bit",
2187 "Ignore packets that haven't set the F bit when they should have",
2188 &demand_good_f_bit);
2190 prefs_register_uint_preference(iscsi_module,
2191 "bogus_pdu_max_data_len",
2192 "Bogus pdu max data length threshold",
2193 "Treat packets whose data segment length is greater than this value as bogus",
2195 &bogus_pdu_data_length_threshold);
2197 prefs_register_uint_preference(iscsi_module,
2200 "Port number of iSCSI target",
2204 prefs_register_bool_preference(iscsi_module,
2205 "enable_header_digests",
2206 "Enable header digests",
2207 "When enabled, pdus are assumed to contain a header digest",
2208 &enableHeaderDigests);
2209 prefs_register_bool_preference(iscsi_module,
2210 "enable_data_digests",
2211 "Enable data digests",
2212 "When enabled, pdus are assumed to contain a data digest",
2213 &enableDataDigests);
2215 prefs_register_bool_preference(iscsi_module,
2216 "header_digest_is_crc32c",
2217 "Header digest is CRC32C",
2218 "When enabled, header digests are assumed to be CRC32C",
2219 &headerDigestIsCRC32);
2220 prefs_register_bool_preference(iscsi_module,
2221 "data_digest_is_crc32c",
2222 "Data digest is CRC32C",
2223 "When enabled, data digests are assumed to be CRC32C",
2224 &dataDigestIsCRC32);
2226 prefs_register_uint_preference(iscsi_module,
2227 "header_digest_size",
2228 "Header digest size",
2229 "The size of a header digest (bytes)",
2232 prefs_register_uint_preference(iscsi_module,
2235 "The size of a data digest (bytes)",
2239 /* Preference supported in older versions.
2240 Register them as obsolete. */
2241 prefs_register_obsolete_preference(iscsi_module,
2242 "version_03_compatible");
2243 prefs_register_obsolete_preference(iscsi_module,
2244 "bogus_pdu_max_digest_padding");
2250 * If this dissector uses sub-dissector registration add a
2251 * registration routine.
2255 * This format is required because a script is used to find these
2256 * routines and create the code that calls these routines.
2259 proto_reg_handoff_iscsi(void)
2261 heur_dissector_add("tcp", dissect_iscsi, proto_iscsi);