2 * Routines for iSCSI dissection
3 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
5 * $Id: packet-iscsi.c,v 1.33 2002/05/16 10:03:31 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
60 static enum_val_t iscsi_protocol_versions[] = {
61 { "Draft 08", ISCSI_PROTOCOL_DRAFT08 },
62 { "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
63 { "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
64 { "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
68 static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT12;
70 static gboolean iscsi_desegment = TRUE;
72 static int demand_good_f_bit = FALSE;
73 static int enable_bogosity_filter = TRUE;
74 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
76 static int enableDataDigests = FALSE;
77 static int enableHeaderDigests = FALSE;
79 static int dataDigestIsCRC32 = TRUE;
80 static int headerDigestIsCRC32 = TRUE;
82 static int dataDigestSize = 4;
83 static int headerDigestSize = 4;
85 static guint iscsi_port = 3260;
87 /* Initialize the protocol and registered fields */
88 static int proto_iscsi = -1;
89 static int hf_iscsi_AHS = -1;
90 static int hf_iscsi_Padding = -1;
91 static int hf_iscsi_ping_data = -1;
92 static int hf_iscsi_immediate_data = -1;
93 static int hf_iscsi_write_data = -1;
94 static int hf_iscsi_read_data = -1;
95 static int hf_iscsi_error_pdu_data = -1;
96 static int hf_iscsi_async_message_data = -1;
97 static int hf_iscsi_vendor_specific_data = -1;
98 static int hf_iscsi_Opcode = -1;
99 static int hf_iscsi_Flags = -1;
100 static int hf_iscsi_HeaderDigest = -1;
101 static int hf_iscsi_HeaderDigest32 = -1;
102 static int hf_iscsi_DataDigest = -1;
103 static int hf_iscsi_DataDigest32 = -1;
105 static int hf_iscsi_X = -1;
107 static int hf_iscsi_I = -1;
108 static int hf_iscsi_SCSICommand_F = -1;
109 static int hf_iscsi_SCSICommand_R = -1;
110 static int hf_iscsi_SCSICommand_W = -1;
111 static int hf_iscsi_SCSICommand_Attr = -1;
112 static int hf_iscsi_SCSICommand_CRN = -1;
113 static int hf_iscsi_SCSICommand_AddCDB = -1;
114 static int hf_iscsi_DataSegmentLength = -1;
115 static int hf_iscsi_TotalAHSLength = -1;
116 static int hf_iscsi_LUN = -1;
117 static int hf_iscsi_InitiatorTaskTag = -1;
118 static int hf_iscsi_ExpectedDataTransferLength = -1;
119 static int hf_iscsi_CmdSN = -1;
120 static int hf_iscsi_ExpStatSN = -1;
121 static int hf_iscsi_StatSN = -1;
122 static int hf_iscsi_ExpCmdSN = -1;
123 static int hf_iscsi_MaxCmdSN = -1;
124 static int hf_iscsi_SCSIResponse_o = -1;
125 static int hf_iscsi_SCSIResponse_u = -1;
126 static int hf_iscsi_SCSIResponse_O = -1;
127 static int hf_iscsi_SCSIResponse_U = -1;
128 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
129 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
130 static int hf_iscsi_SCSIResponse_Response = -1;
131 static int hf_iscsi_SCSIResponse_Status = -1;
132 static int hf_iscsi_SenseLength = -1;
133 static int hf_iscsi_SCSIData_F = -1;
134 static int hf_iscsi_SCSIData_A = -1;
135 static int hf_iscsi_SCSIData_S = -1;
136 static int hf_iscsi_SCSIData_O = -1;
137 static int hf_iscsi_SCSIData_U = -1;
138 static int hf_iscsi_TargetTransferTag = -1;
139 static int hf_iscsi_DataSN = -1;
140 static int hf_iscsi_BufferOffset = -1;
141 static int hf_iscsi_SCSIData_ResidualCount = -1;
142 static int hf_iscsi_VersionMin = -1;
143 static int hf_iscsi_VersionMax = -1;
144 static int hf_iscsi_VersionActive = -1;
145 static int hf_iscsi_CID = -1;
146 static int hf_iscsi_ISID8 = -1;
147 static int hf_iscsi_ISID = -1;
148 /* #if defined(DRAFT09) */
149 static int hf_iscsi_ISID_Type = -1;
150 static int hf_iscsi_ISID_NamingAuthority = -1;
151 static int hf_iscsi_ISID_Qualifier = -1;
152 /* #elif !defined(DRAFT08) */
153 static int hf_iscsi_ISID_t = -1;
154 static int hf_iscsi_ISID_a = -1;
155 static int hf_iscsi_ISID_b = -1;
156 static int hf_iscsi_ISID_c = -1;
157 static int hf_iscsi_ISID_d = -1;
159 static int hf_iscsi_TSID = -1;
160 static int hf_iscsi_TSIH = -1;
161 static int hf_iscsi_InitStatSN = -1;
162 static int hf_iscsi_InitCmdSN = -1;
164 static int hf_iscsi_Login_X = -1;
166 static int hf_iscsi_Login_T = -1;
167 static int hf_iscsi_Login_CSG = -1;
168 static int hf_iscsi_Login_NSG = -1;
169 static int hf_iscsi_Login_Status = -1;
170 static int hf_iscsi_KeyValue = -1;
171 static int hf_iscsi_Text_F = -1;
172 static int hf_iscsi_ExpDataSN = -1;
173 static int hf_iscsi_R2TSN = -1;
174 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
175 static int hf_iscsi_RefCmdSN = -1;
176 static int hf_iscsi_TaskManagementFunction_Function = -1;
177 static int hf_iscsi_TaskManagementFunction_Response = -1;
178 static int hf_iscsi_Logout_Reason = -1;
179 static int hf_iscsi_Logout_Response = -1;
180 static int hf_iscsi_Time2Wait = -1;
181 static int hf_iscsi_Time2Retain = -1;
182 static int hf_iscsi_DesiredDataLength = -1;
183 static int hf_iscsi_AsyncEvent = -1;
184 static int hf_iscsi_EventVendorCode = -1;
185 static int hf_iscsi_Parameter1 = -1;
186 static int hf_iscsi_Parameter2 = -1;
187 static int hf_iscsi_Parameter3 = -1;
188 static int hf_iscsi_Reject_Reason = -1;
189 static int hf_iscsi_snack_type = -1;
190 static int hf_iscsi_BegRun = -1;
191 static int hf_iscsi_RunLength = -1;
193 /* Initialize the subtree pointers */
194 static gint ett_iscsi = -1;
195 static gint ett_iscsi_KeyValues = -1;
196 static gint ett_iscsi_CDB = -1;
197 static gint ett_iscsi_Flags = -1;
198 /* #ifndef DRAFT08 */
199 static gint ett_iscsi_ISID = -1;
202 typedef struct _iscsi_conv_key {
207 typedef struct _iscsi_conv_data {
213 static GHashTable *iscsi_req_hash = NULL;
214 static GMemChunk *iscsi_req_keys = NULL;
215 static GMemChunk *iscsi_req_vals = NULL;
216 static guint32 iscsi_init_count = 25;
224 #define OPCODE_MASK 0x3f
226 #define TARGET_OPCODE_BIT 0x20
228 #define ISCSI_OPCODE_NOP_OUT 0x00
229 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
230 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
231 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
232 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
233 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
234 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
235 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
236 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
237 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
238 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
240 #define ISCSI_OPCODE_NOP_IN 0x20
241 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
242 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
243 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
244 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
245 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
246 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
247 #define ISCSI_OPCODE_R2T 0x31
248 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
249 #define ISCSI_OPCODE_REJECT 0x3f
250 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
251 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
252 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
255 #define CSG_MASK (0x03 << CSG_SHIFT)
256 #define NSG_MASK 0x03
258 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
259 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
260 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
262 #define ISCSI_SCSI_DATA_FLAG_S 0x01
263 #define ISCSI_SCSI_DATA_FLAG_U 0x02
264 #define ISCSI_SCSI_DATA_FLAG_O 0x04
265 #define ISCSI_SCSI_DATA_FLAG_A 0x40
266 #define ISCSI_SCSI_DATA_FLAG_F 0x80
268 static const value_string iscsi_opcodes[] = {
269 { ISCSI_OPCODE_NOP_OUT, "NOP Out" },
270 { ISCSI_OPCODE_SCSI_COMMAND, "SCSI Command" },
271 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION, "Task Management Function" },
272 { ISCSI_OPCODE_LOGIN_COMMAND, "Login Command" },
273 { ISCSI_OPCODE_TEXT_COMMAND, "Text Command" },
274 { ISCSI_OPCODE_SCSI_DATA_OUT, "SCSI Data Out" },
275 { ISCSI_OPCODE_LOGOUT_COMMAND, "Logout Command" },
276 { ISCSI_OPCODE_SNACK_REQUEST, "SNACK Request" },
277 { ISCSI_OPCODE_VENDOR_SPECIFIC_I0, "Vendor Specific I0" },
278 { ISCSI_OPCODE_VENDOR_SPECIFIC_I1, "Vendor Specific I1" },
279 { ISCSI_OPCODE_VENDOR_SPECIFIC_I2, "Vendor Specific I2" },
281 { ISCSI_OPCODE_NOP_IN, "NOP In" },
282 { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
283 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
284 { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
285 { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
286 { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
287 { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
288 { ISCSI_OPCODE_R2T, "Ready To Transfer" },
289 { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
290 { ISCSI_OPCODE_REJECT, "Reject"},
291 { ISCSI_OPCODE_VENDOR_SPECIFIC_T0, "Vendor Specific T0" },
292 { ISCSI_OPCODE_VENDOR_SPECIFIC_T1, "Vendor Specific T1" },
293 { ISCSI_OPCODE_VENDOR_SPECIFIC_T2, "Vendor Specific T2" },
298 static const true_false_string iscsi_meaning_X = {
305 static const true_false_string iscsi_meaning_login_X = {
306 "Reinstate failed connection",
311 static const true_false_string iscsi_meaning_I = {
312 "Immediate delivery",
316 static const true_false_string iscsi_meaning_F = {
317 "Final PDU in sequence",
318 "Not final PDU in sequence"
321 static const true_false_string iscsi_meaning_A = {
322 "Acknowledge requested",
323 "Acknowledge not requested"
326 static const true_false_string iscsi_meaning_T = {
327 "Transit to next login stage",
328 "Stay in current login stage"
331 static const true_false_string iscsi_meaning_S = {
332 "Response contains SCSI status",
333 "Response does not contain SCSI status"
336 static const true_false_string iscsi_meaning_R = {
337 "Data will be read from target",
338 "No data will be read from target"
341 static const true_false_string iscsi_meaning_W = {
342 "Data will be written to target",
343 "No data will be written to target"
346 static const true_false_string iscsi_meaning_o = {
347 "Read part of bi-directional command overflowed",
348 "No overflow of read part of bi-directional command",
351 static const true_false_string iscsi_meaning_u = {
352 "Read part of bi-directional command underflowed",
353 "No underflow of read part of bi-directional command",
356 static const true_false_string iscsi_meaning_O = {
357 "Residual overflow occurred",
358 "No residual overflow occurred",
361 static const true_false_string iscsi_meaning_U = {
362 "Residual underflow occurred",
363 "No residual underflow occurred",
366 static const value_string iscsi_scsi_responses[] = {
367 { 0, "Command completed at target" },
368 { 1, "Response does not contain SCSI status"},
372 static const value_string iscsi_scsicommand_taskattrs[] = {
376 {3, "Head of Queue"},
381 static const value_string iscsi_task_management_responses[] = {
382 {0, "Function complete"},
383 {1, "Task not in task set"},
384 {2, "LUN does not exist"},
385 {3, "Task still allegiant"},
386 {4, "Task failover not supported"},
387 {5, "Task management function not supported"},
388 {6, "Authorisation failed"},
389 {255, "Function rejected"},
393 static const value_string iscsi_task_management_functions[] = {
395 {2, "Abort Task Set"},
397 {4, "Clear Task Set"},
398 {5, "Logical Unit Reset"},
399 {6, "Target Warm Reset"},
400 {7, "Target Cold Reset"},
404 static const value_string iscsi_login_status[] = {
406 {0x0101, "Target moved temporarily"},
407 {0x0102, "Target moved permanently"},
408 {0x0200, "Initiator error (miscellaneous error)"},
409 {0x0201, "Athentication failed"},
410 {0x0202, "Authorisation failure"},
411 {0x0203, "Target not found"},
412 {0x0204, "Target removed"},
413 {0x0205, "Unsupported version"},
414 {0x0206, "Too many connections"},
415 {0x0207, "Missing parameter"},
416 {0x0208, "Can't include in session"},
417 {0x0209, "Session type not supported"},
418 {0x020a, "Session does not exist"},
419 {0x020b, "Invalid request during login"},
420 {0x0300, "Target error (miscellaneous error)"},
421 {0x0301, "Service unavailable"},
422 {0x0302, "Out of resources"},
426 static const value_string iscsi_login_stage[] = {
427 {0, "Security negotiation"},
428 {1, "Operational negotiation"},
429 {3, "Full feature phase"},
433 /* #ifndef DRAFT08 */
434 static const value_string iscsi_isid_type[] = {
436 {0x01, "IANA Enterprise Number"},
442 static const value_string iscsi_logout_reasons[] = {
443 {0, "Close session"},
444 {1, "Close connection"},
445 {2, "Remove connection for recovery"},
449 static const value_string iscsi_logout_response[] = {
450 {0, "Connection closed successfully"},
451 {1, "CID not found"},
452 {2, "Connection recovery not supported"},
453 {3, "Cleanup failed for various reasons"},
457 static const value_string iscsi_asyncevents[] = {
458 {0, "A SCSI asynchronous event is reported in the sense data"},
459 {1, "Target requests logout"},
460 {2, "Target will/has dropped connection"},
461 {3, "Target will/has dropped all connections"},
465 static const value_string iscsi_snack_types[] = {
468 /* #ifndef DRAFT08 */
474 static const value_string iscsi_reject_reasons[] = {
476 {0x01, "Full feature phase command before login"},
478 {0x02, "Data (payload) digest error"},
479 {0x03, "Data SNACK reject"},
480 {0x04, "Protocol error"},
481 {0x05, "Command not supported in this session type"},
482 {0x06, "Immediate command reject (too many immediate commands)"},
483 {0x07, "Task in progress"},
484 {0x08, "Invalid SNACK"},
485 {0x09, "Bookmark reject (no bookmark for this initiator task tag)"},
486 {0x0a, "Bookmark reject (can't generate bookmark - out of resources)"},
487 {0x0b, "Negotiation reset"},
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 calculateCRC32(const void *buf, int len, guint32 crc) {
582 guint8 *p = (guint8 *)buf;
584 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
592 iscsi_equal(gconstpointer v, gconstpointer w)
594 iscsi_conv_key_t *v1 = (iscsi_conv_key_t *)v;
595 iscsi_conv_key_t *v2 = (iscsi_conv_key_t *)w;
597 return (v1->conv_idx == v2->conv_idx);
601 iscsi_hash (gconstpointer v)
603 iscsi_conv_key_t *key = (iscsi_conv_key_t *)v;
612 * Protocol initialization
615 iscsi_init_protocol(void)
618 g_mem_chunk_destroy(iscsi_req_keys);
620 g_mem_chunk_destroy(iscsi_req_vals);
622 g_hash_table_destroy(iscsi_req_hash);
624 iscsi_req_hash = g_hash_table_new(iscsi_hash, iscsi_equal);
625 iscsi_req_keys = g_mem_chunk_new("iscsi_req_keys",
626 sizeof(iscsi_conv_key_t),
627 iscsi_init_count * sizeof(iscsi_conv_key_t),
629 iscsi_req_vals = g_mem_chunk_new("iscsi_req_vals",
630 sizeof(iscsi_conv_data_t),
631 iscsi_init_count * sizeof(iscsi_conv_data_t),
636 iscsi_min(int a, int b) {
637 return (a < b)? a : b;
641 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
642 const gint limit = offset + text_len;
643 while(offset < limit) {
644 gint len = tvb_strnlen(tvb, offset, limit - offset);
646 len = limit - offset;
649 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
656 handleHeaderDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
657 int available_bytes = tvb_length_remaining(tvb, offset);
658 if(enableHeaderDigests) {
659 if(headerDigestIsCRC32) {
660 if(available_bytes >= (headerLen + 4)) {
661 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
662 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
664 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
667 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);
670 return offset + headerLen + 4;
672 if(available_bytes >= (headerLen + headerDigestSize)) {
673 proto_tree_add_item(ti, hf_iscsi_HeaderDigest, tvb, offset + headerLen, headerDigestSize, FALSE);
675 return offset + headerLen + headerDigestSize;
677 return offset + headerLen;
681 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
682 int available_bytes = tvb_length_remaining(tvb, offset);
683 if(enableDataDigests) {
684 if(dataDigestIsCRC32) {
685 if(available_bytes >= (dataLen + 4)) {
686 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
687 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
689 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
692 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);
695 return offset + dataLen + 4;
697 if(available_bytes >= (dataLen + dataDigestSize)) {
698 proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
700 return offset + dataLen + dataDigestSize;
702 return offset + dataLen;
706 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
707 if(endOffset > offset) {
708 int dataOffset = offset;
709 int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
711 proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
714 if(offset < endOffset && (offset & 3) != 0) {
715 int padding = 4 - (offset & 3);
716 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
719 if(dataSegmentLen > 0 && offset < endOffset)
720 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
727 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
728 if(endOffset > offset) {
729 int dataOffset = offset;
730 int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
732 proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
733 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
734 offset = addTextKeys(tt, tvb, offset, textLen);
736 if(offset < endOffset && (offset & 3) != 0) {
737 int padding = 4 - (offset & 3);
738 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
741 if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
742 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
747 /* Code to actually dissect the packets */
749 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len) {
751 guint original_offset = offset;
752 proto_tree *ti = NULL;
753 guint8 scsi_status = 0;
754 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
755 guint end_offset = offset + tvb_length_remaining(tvb, offset);
756 guint32 del_usecs = 0;
757 conversation_t *conversation = NULL;
758 iscsi_conv_data_t *cdata = NULL;
759 iscsi_conv_key_t ckey, *req_key;
760 scsi_task_id_t task_key;
761 int paddedDataSegmentLength = data_segment_len;
762 if(paddedDataSegmentLength & 3)
763 paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
765 /* Make entries in Protocol column and Info column on summary display */
766 if (check_col(pinfo->cinfo, COL_PROTOCOL))
767 col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
769 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
770 opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
771 scsi_status = tvb_get_guint8 (tvb, offset+3);
774 if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
775 (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
776 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
777 conversation = find_conversation (&pinfo->src, &pinfo->dst,
778 pinfo->ptype, pinfo->srcport,
781 ckey.conv_idx = conversation->index;
782 ckey.itt = tvb_get_ntohl (tvb, offset+16);
784 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_hash,
787 task_key.conv_id = ckey.conv_idx;
788 task_key.task_id = ckey.itt;
789 pinfo->private_data = &task_key;
791 /* no conversation, meaning we didn't see the request */
792 pinfo->private_data = NULL;
796 del_usecs = (pinfo->fd->abs_secs - cdata->abs_secs)* 1000000 +
797 (pinfo->fd->abs_usecs - cdata->abs_usecs);
800 else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
801 conversation = find_conversation (&pinfo->src, &pinfo->dst,
802 pinfo->ptype, pinfo->srcport,
805 conversation = conversation_new (&pinfo->src, &pinfo->dst,
806 pinfo->ptype, pinfo->srcport,
810 ckey.conv_idx = conversation->index;
811 ckey.itt = tvb_get_ntohl (tvb, offset+16);
813 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_hash,
816 /* Since we never free the memory used by an exchange, this maybe a
817 * case of another request using the same exchange as a previous
820 cdata->abs_usecs = pinfo->fd->abs_usecs;
821 cdata->abs_secs = pinfo->fd->abs_secs;
824 req_key = g_mem_chunk_alloc (iscsi_req_keys);
825 req_key->conv_idx = conversation->index;
826 req_key->itt = tvb_get_ntohl (tvb, offset+16);
828 cdata = g_mem_chunk_alloc (iscsi_req_vals);
829 cdata->abs_usecs = pinfo->fd->abs_usecs;
830 cdata->abs_secs = pinfo->fd->abs_secs;
832 g_hash_table_insert (iscsi_req_hash, req_key, cdata);
835 /* The SCSI protocol uses this as the key to detect a
836 * SCSI-level conversation. */
837 task_key.conv_id = ckey.conv_idx;
838 task_key.task_id = ckey.itt;
839 pinfo->private_data = &task_key;
842 pinfo->private_data = NULL;
845 if (check_col(pinfo->cinfo, COL_INFO)) {
847 if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
849 col_append_str(pinfo->cinfo, COL_INFO, (char *)opcode_str);
851 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
852 (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
853 (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
854 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
855 val_to_str (scsi_status, scsi_status_val, "0x%x"));
857 else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
858 guint16 login_status = tvb_get_ntohs(tvb, offset+36);
859 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
860 val_to_str (login_status, iscsi_login_status, "0x%x"));
862 else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
863 guint16 logoutReason = tvb_get_ntohs(tvb, offset+11);
864 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
865 val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
867 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
868 guint8 tmf = tvb_get_guint8(tvb, offset + 1);
869 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
870 val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
872 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
873 guint8 resp = tvb_get_guint8(tvb, offset + 2);
874 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
875 val_to_str (resp, iscsi_task_management_responses, "0x%x"));
877 else if (opcode == ISCSI_OPCODE_REJECT) {
878 guint8 reason = tvb_get_guint8(tvb, offset + 2);
879 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
880 val_to_str (reason, iscsi_reject_reasons, "0x%x"));
882 else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
883 guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
884 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
885 val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
890 /* In the interest of speed, if "tree" is NULL, don't do any
891 work not necessary to generate protocol tree items. */
894 /* create display subtree for the protocol */
895 tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
896 offset, -1, "iSCSI (%s)",
898 ti = proto_item_add_subtree(tp, ett_iscsi);
900 proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
901 offset + 0, 1, opcode);
902 if((opcode & TARGET_OPCODE_BIT) == 0) {
903 /* initiator -> target */
904 gint b = tvb_get_guint8(tvb, offset + 0);
905 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
906 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
907 opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
908 opcode != ISCSI_OPCODE_SNACK_REQUEST)
909 proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
911 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
912 opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
913 opcode != ISCSI_OPCODE_SNACK_REQUEST)
914 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
917 if(opcode == ISCSI_OPCODE_NOP_OUT) {
919 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
920 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
922 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
923 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
924 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
925 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
926 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
927 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
928 offset = handleHeaderDigest(ti, tvb, offset, 48);
929 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
931 else if(opcode == ISCSI_OPCODE_NOP_IN) {
933 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
934 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
936 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
937 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
938 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
939 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
940 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
941 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
942 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
943 offset = handleHeaderDigest(ti, tvb, offset, 48);
944 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
946 else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
948 guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
950 gint b = tvb_get_guint8(tvb, offset + 1);
951 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
952 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
954 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
955 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
956 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
957 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
959 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
960 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
962 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
963 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
964 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
965 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
966 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
967 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
968 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
971 /* FIXME - disssect AHS? */
972 proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 48, ahsLen, FALSE);
974 offset = handleHeaderDigest(ti, tvb, offset, 48 + ahsLen);
976 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
978 else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
981 if (del_usecs > 1000)
982 proto_tree_add_text (ti, tvb, offset, 0,
983 "Cmd Response Time: %d msecs",
986 proto_tree_add_text (ti, tvb, offset, 0,
987 "Cmd Response Time: %d usecs",
991 gint b = tvb_get_guint8(tvb, offset + 1);
992 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
993 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
995 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
996 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
997 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
998 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
1000 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
1001 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1002 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1003 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1005 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1006 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1007 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1008 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
1010 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1011 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1012 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1013 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1014 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1015 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
1018 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
1019 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
1021 offset = handleHeaderDigest(ti, tvb, offset, 48);
1022 /* do not update offset here because the data segment is
1023 * dissected below */
1024 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1026 else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
1027 /* Task Management Function */
1028 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
1029 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1030 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1031 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1033 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1034 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1035 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1036 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1037 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1038 proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1039 offset = handleHeaderDigest(ti, tvb, offset, 48);
1041 else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1042 /* Task Management Function Response */
1043 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
1044 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1045 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1046 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1048 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1049 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1050 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1052 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1053 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1054 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1055 offset = handleHeaderDigest(ti, tvb, offset, 48);
1057 else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1059 int digestsActive = 0;
1061 gint b = tvb_get_guint8(tvb, offset + 1);
1062 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1063 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1067 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1068 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1071 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1072 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1073 proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1075 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1076 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1078 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1079 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1080 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1081 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1083 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1084 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1085 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1086 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1089 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1090 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1091 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1092 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1093 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1094 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1097 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1098 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1099 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1100 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1101 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1104 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1105 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1108 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1110 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1111 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1112 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1114 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1115 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1117 offset = handleHeaderDigest(ti, tvb, offset, 48);
1120 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1122 else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1123 /* Login Response */
1124 int digestsActive = 0;
1126 gint b = tvb_get_guint8(tvb, offset + 1);
1127 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1128 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1132 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1133 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1136 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1137 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1138 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1141 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1142 proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1143 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1144 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1146 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1147 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1148 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1151 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1152 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1153 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1154 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1155 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1156 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1159 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1160 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1161 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1162 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1163 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1166 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1167 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1170 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1172 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1173 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1174 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1175 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1176 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1178 offset = handleHeaderDigest(ti, tvb, offset, 48);
1181 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1183 else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1186 gint b = tvb_get_guint8(tvb, offset + 1);
1187 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1188 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1190 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1192 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1193 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1195 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1196 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1197 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1199 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1200 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1201 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1202 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1203 offset = handleHeaderDigest(ti, tvb, offset, 48);
1204 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1206 else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1209 gint b = tvb_get_guint8(tvb, offset + 1);
1210 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1211 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1213 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1215 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1216 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1218 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1219 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1220 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1222 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1223 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1224 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1225 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1226 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1227 offset = handleHeaderDigest(ti, tvb, offset, 48);
1228 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1230 else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1231 /* SCSI Data Out (write) */
1233 gint b = tvb_get_guint8(tvb, offset + 1);
1234 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1235 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1237 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1239 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1240 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1242 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1243 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1244 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1245 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1246 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1247 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1248 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1249 offset = handleHeaderDigest(ti, tvb, offset, 48);
1250 /* do not update offset here because the data segment is
1251 * dissected below */
1252 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1254 else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
1255 /* SCSI Data In (read) */
1257 gint b = tvb_get_guint8(tvb, offset + 1);
1258 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1259 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1261 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1262 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1263 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
1265 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1266 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1267 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1269 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1270 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1271 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1273 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1274 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1275 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1277 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1278 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1279 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1282 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1284 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1285 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1286 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1287 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1288 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1289 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1290 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1292 offset = handleHeaderDigest(ti, tvb, offset, 48);
1293 /* do not update offset here because the data segment is
1294 * dissected below */
1295 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1297 else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1298 /* Logout Command */
1299 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1300 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1301 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1303 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1304 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1305 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1307 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1308 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1309 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1310 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
1312 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1313 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1314 offset = handleHeaderDigest(ti, tvb, offset, 48);
1316 else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1317 /* Logout Response */
1318 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1319 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1320 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1321 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1323 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1324 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1325 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1326 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1327 proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1328 proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1329 offset = handleHeaderDigest(ti, tvb, offset, 48);
1331 else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1334 gint b = tvb_get_guint8(tvb, offset + 1);
1336 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1337 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1340 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1342 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1343 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1344 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1345 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1347 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1348 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1349 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1350 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1351 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1352 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1355 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1356 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1357 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1358 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1360 offset = handleHeaderDigest(ti, tvb, offset, 48);
1362 else if(opcode == ISCSI_OPCODE_R2T) {
1364 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1365 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1366 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1367 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1369 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1370 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1371 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1372 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1373 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1374 proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
1375 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1376 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1377 offset = handleHeaderDigest(ti, tvb, offset, 48);
1379 else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1380 /* Asynchronous Message */
1381 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1382 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1384 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1385 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1386 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1387 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1388 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1389 proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1390 proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1391 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1392 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1393 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1394 offset = handleHeaderDigest(ti, tvb, offset, 48);
1395 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
1397 else if(opcode == ISCSI_OPCODE_REJECT) {
1399 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
1400 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1401 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1403 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1404 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1405 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1406 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1407 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1408 offset = handleHeaderDigest(ti, tvb, offset, 48);
1409 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1411 else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
1412 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
1413 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
1414 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
1415 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
1416 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
1417 /* Vendor specific opcodes */
1418 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1419 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1421 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1422 offset = handleHeaderDigest(ti, tvb, offset, 48);
1423 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
1426 proto_item_set_len(ti, offset - original_offset);
1429 if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
1431 ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
1433 dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16);
1435 else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1436 if (scsi_status == 0x2) {
1437 /* A SCSI response with Check Condition contains sense data */
1438 /* offset is setup correctly by the iscsi code for response above */
1439 if((end_offset - offset) >= 2) {
1440 int senseLen = tvb_get_ntohs(tvb, offset);
1442 proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1445 dissect_scsi_snsinfo (tvb, pinfo, tree, offset,
1446 iscsi_min (senseLen,
1447 end_offset-offset));
1451 dissect_scsi_rsp (tvb, pinfo, tree);
1453 if (cdata && tree) {
1454 /* destroy the data structures for this SCSI task */
1456 g_mem_chunk_free (iscsi_req_vals, cdata);
1457 g_hash_table_remove (iscsi_req_hash, &ckey);
1458 pinfo->private_data = NULL;
1462 else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1463 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1464 /* offset is setup correctly by the iscsi code for response above */
1465 dissect_scsi_payload (tvb, pinfo, tree, offset, FALSE,
1466 iscsi_min (data_segment_len, end_offset-offset));
1471 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1472 /* Set up structures needed to add the protocol subtree and manage it */
1473 guint iSCSIPdusDissected = 0;
1475 guint32 available_bytes = tvb_length_remaining(tvb, offset);
1477 if (!proto_is_protocol_enabled(proto_iscsi))
1478 return FALSE; /* iSCSI has been disabled */
1480 /* quick check to see if the packet is long enough to contain the
1481 * minimum amount of information we need */
1482 if (available_bytes < 48 && (!iscsi_desegment || available_bytes < 8)) {
1483 /* no, so give up */
1487 /* process multiple iSCSI PDUs per packet */
1488 while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
1489 const char *opcode_str = NULL;
1490 guint32 data_segment_len;
1491 guint8 opcode = tvb_get_guint8(tvb, offset + 0);
1492 guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
1495 /* mask out any extra bits in the opcode byte */
1496 opcode &= OPCODE_MASK;
1498 opcode_str = match_strval(opcode, iscsi_opcodes);
1499 if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
1500 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1501 opcode == ISCSI_OPCODE_R2T ||
1502 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1503 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1504 opcode == ISCSI_OPCODE_SNACK_REQUEST)
1505 data_segment_len = 0;
1507 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
1509 if(opcode_str == NULL) {
1512 else if(iscsi_port != 0 &&
1513 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
1514 (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
1517 else if(enable_bogosity_filter) {
1518 /* try and distinguish between data and real headers */
1519 if(data_segment_len > bogus_pdu_data_length_threshold) {
1522 else if(demand_good_f_bit &&
1523 !(secondPduByte & 0x80) &&
1524 (opcode == ISCSI_OPCODE_NOP_OUT ||
1525 opcode == ISCSI_OPCODE_NOP_IN ||
1526 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1527 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1528 opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
1529 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1530 opcode == ISCSI_OPCODE_R2T ||
1531 opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
1532 opcode == ISCSI_OPCODE_SNACK_REQUEST ||
1533 opcode == ISCSI_OPCODE_REJECT)) {
1539 return iSCSIPdusDissected > 0;
1542 guint32 pduLen = 48;
1543 int digestsActive = 1;
1545 if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
1546 opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1547 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1548 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
1549 /* digests are not yet turned on */
1558 if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1560 pduLen += tvb_get_guint8(tvb, offset + 4) * 4;
1563 pduLen += data_segment_len;
1564 if((pduLen & 3) != 0)
1565 pduLen += 4 - (pduLen & 3);
1567 if(digestsActive && enableHeaderDigests) {
1568 if(headerDigestIsCRC32)
1571 pduLen += headerDigestSize;
1574 if(digestsActive && data_segment_len > 0 && enableDataDigests) {
1575 if(dataDigestIsCRC32)
1578 pduLen += dataDigestSize;
1582 * Desegmentation check.
1584 if(iscsi_desegment && pinfo->can_desegment) {
1585 if(pduLen > available_bytes) {
1587 * This frame doesn't have all of the data for
1588 * this message, but we can do reassembly on it.
1590 * Tell the TCP dissector where the data for this
1591 * message starts in the data it handed us, and
1592 * how many more bytes we need, and return.
1594 pinfo->desegment_offset = offset;
1595 pinfo->desegment_len = pduLen - available_bytes;
1600 if(check_col(pinfo->cinfo, COL_INFO)) {
1601 if(iSCSIPdusDissected == 0)
1602 col_set_str(pinfo->cinfo, COL_INFO, "");
1604 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1607 dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len);
1608 if(pduLen > available_bytes)
1609 pduLen = available_bytes;
1611 available_bytes -= pduLen;
1612 ++iSCSIPdusDissected;
1616 return iSCSIPdusDissected > 0;
1620 /* Register the protocol with Ethereal */
1623 * this format is require because a script is used to build the C
1624 * function that calls all the protocol registration.
1628 proto_register_iscsi(void)
1631 /* Setup list of header fields See Section 1.6.1 for details*/
1632 static hf_register_info hf[] = {
1634 { "AHS", "iscsi.ahs",
1635 FT_BYTES, BASE_HEX, NULL, 0,
1636 "Additional header segment", HFILL }
1638 { &hf_iscsi_Padding,
1639 { "Padding", "iscsi.padding",
1640 FT_BYTES, BASE_HEX, NULL, 0,
1641 "Padding to 4 byte boundary", HFILL }
1643 { &hf_iscsi_ping_data,
1644 { "PingData", "iscsi.pingdata",
1645 FT_BYTES, BASE_HEX, NULL, 0,
1646 "Ping Data", HFILL }
1648 { &hf_iscsi_immediate_data,
1649 { "ImmediateData", "iscsi.immediatedata",
1650 FT_BYTES, BASE_HEX, NULL, 0,
1651 "Immediate Data", HFILL }
1653 { &hf_iscsi_write_data,
1654 { "WriteData", "iscsi.writedata",
1655 FT_BYTES, BASE_HEX, NULL, 0,
1656 "Write Data", HFILL }
1658 { &hf_iscsi_read_data,
1659 { "ReadData", "iscsi.readdata",
1660 FT_BYTES, BASE_HEX, NULL, 0,
1661 "Read Data", HFILL }
1663 { &hf_iscsi_error_pdu_data,
1664 { "ErrorPDUData", "iscsi.errorpdudata",
1665 FT_BYTES, BASE_HEX, NULL, 0,
1666 "Error PDU Data", HFILL }
1668 { &hf_iscsi_async_message_data,
1669 { "AsyncMessageData", "iscsi.asyncmessagedata",
1670 FT_BYTES, BASE_HEX, NULL, 0,
1671 "Async Message Data", HFILL }
1673 { &hf_iscsi_vendor_specific_data,
1674 { "VendorSpecificData", "iscsi.vendorspecificdata",
1675 FT_BYTES, BASE_HEX, NULL, 0,
1676 "Vendor Specific Data", HFILL }
1678 { &hf_iscsi_HeaderDigest,
1679 { "HeaderDigest", "iscsi.headerdigest",
1680 FT_BYTES, BASE_HEX, NULL, 0,
1681 "Header Digest", HFILL }
1683 { &hf_iscsi_HeaderDigest32,
1684 { "HeaderDigest", "iscsi.headerdigest32",
1685 FT_UINT32, BASE_HEX, NULL, 0,
1686 "Header Digest", HFILL }
1688 { &hf_iscsi_DataDigest,
1689 { "DataDigest", "iscsi.datadigest",
1690 FT_BYTES, BASE_HEX, NULL, 0,
1691 "Data Digest", HFILL }
1693 { &hf_iscsi_DataDigest32,
1694 { "DataDigest", "iscsi.datadigest32",
1695 FT_UINT32, BASE_HEX, NULL, 0,
1696 "Data Digest", HFILL }
1699 { "Opcode", "iscsi.opcode",
1700 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
1703 /* #ifdef DRAFT08 */
1706 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1707 "Command Retry", HFILL }
1712 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
1713 "Immediate delivery", HFILL }
1716 { "Flags", "iscsi.flags",
1717 FT_UINT8, BASE_HEX, NULL, 0,
1718 "Opcode specific flags", HFILL }
1720 { &hf_iscsi_SCSICommand_F,
1721 { "F", "iscsi.scsicommand.F",
1722 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1723 "PDU completes command", HFILL }
1725 { &hf_iscsi_SCSICommand_R,
1726 { "R", "iscsi.scsicommand.R",
1727 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
1728 "Command reads from SCSI target", HFILL }
1730 { &hf_iscsi_SCSICommand_W,
1731 { "W", "iscsi.scsicommand.W",
1732 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
1733 "Command writes to SCSI target", HFILL }
1735 { &hf_iscsi_SCSICommand_Attr,
1736 { "Attr", "iscsi.scsicommand.attr",
1737 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
1738 "SCSI task attributes", HFILL }
1740 { &hf_iscsi_SCSICommand_CRN,
1741 { "CRN", "iscsi.scsicommand.crn",
1742 FT_UINT8, BASE_HEX, NULL, 0,
1743 "SCSI command reference number", HFILL }
1745 { &hf_iscsi_SCSICommand_AddCDB,
1746 { "AddCDB", "iscsi.scsicommand.addcdb",
1747 FT_UINT8, BASE_HEX, NULL, 0,
1748 "Additional CDB length (in 4 byte units)", HFILL }
1750 { &hf_iscsi_DataSegmentLength,
1751 { "DataSegmentLength", "iscsi.datasegmentlength",
1752 FT_UINT32, BASE_HEX, NULL, 0,
1753 "Data segment length (bytes)", HFILL }
1755 { &hf_iscsi_TotalAHSLength,
1756 { "TotalAHSLength", "iscsi.totalahslength",
1757 FT_UINT8, BASE_HEX, NULL, 0,
1758 "Total additional header segment length (4 byte words)", HFILL }
1761 { "LUN", "iscsi.lun",
1762 FT_BYTES, BASE_HEX, NULL, 0,
1763 "Logical Unit Number", HFILL }
1765 { &hf_iscsi_InitiatorTaskTag,
1766 { "InitiatorTaskTag", "iscsi.initiatortasktag",
1767 FT_UINT32, BASE_HEX, NULL, 0,
1768 "Initiator's task tag", HFILL }
1770 { &hf_iscsi_ExpectedDataTransferLength,
1771 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
1772 FT_UINT32, BASE_HEX, NULL, 0,
1773 "Expected length of data transfer", HFILL }
1776 { "CmdSN", "iscsi.cmdsn",
1777 FT_UINT32, BASE_HEX, NULL, 0,
1778 "Sequence number for this command (0 == immediate)", HFILL }
1780 { &hf_iscsi_ExpStatSN,
1781 { "ExpStatSN", "iscsi.expstatsn",
1782 FT_UINT32, BASE_HEX, NULL, 0,
1783 "Next expected status sequence number", HFILL }
1785 { &hf_iscsi_SCSIResponse_ResidualCount,
1786 { "ResidualCount", "iscsi.scsiresponse.residualcount",
1787 FT_UINT32, BASE_HEX, NULL, 0,
1788 "Residual count", HFILL }
1791 { "StatSN", "iscsi.statsn",
1792 FT_UINT32, BASE_HEX, NULL, 0,
1793 "Status sequence number", HFILL }
1795 { &hf_iscsi_ExpCmdSN,
1796 { "ExpCmdSN", "iscsi.expcmdsn",
1797 FT_UINT32, BASE_HEX, NULL, 0,
1798 "Next expected command sequence number", HFILL }
1800 { &hf_iscsi_MaxCmdSN,
1801 { "MaxCmdSN", "iscsi.maxcmdsn",
1802 FT_UINT32, BASE_HEX, NULL, 0,
1803 "Maximum acceptable command sequence number", HFILL }
1805 { &hf_iscsi_SCSIResponse_o,
1806 { "o", "iscsi.scsiresponse.o",
1807 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
1808 "Bi-directional read residual overflow", HFILL }
1810 { &hf_iscsi_SCSIResponse_u,
1811 { "u", "iscsi.scsiresponse.u",
1812 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
1813 "Bi-directional read residual underflow", HFILL }
1815 { &hf_iscsi_SCSIResponse_O,
1816 { "O", "iscsi.scsiresponse.O",
1817 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
1818 "Residual overflow", HFILL }
1820 { &hf_iscsi_SCSIResponse_U,
1821 { "U", "iscsi.scsiresponse.U",
1822 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
1823 "Residual underflow", HFILL }
1825 { &hf_iscsi_SCSIResponse_Status,
1826 { "Status", "iscsi.scsiresponse.status",
1827 FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
1828 "SCSI command status value", HFILL }
1830 { &hf_iscsi_SCSIResponse_Response,
1831 { "Response", "iscsi.scsiresponse.response",
1832 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
1833 "SCSI command response value", HFILL }
1835 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
1836 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
1837 FT_UINT32, BASE_HEX, NULL, 0,
1838 "Bi-directional read residual count", HFILL }
1840 { &hf_iscsi_SenseLength,
1841 { "SenseLength", "iscsi.scsiresponse.senselength",
1842 FT_UINT16, BASE_HEX, NULL, 0,
1843 "Sense data length", HFILL }
1845 { &hf_iscsi_SCSIData_F,
1846 { "F", "iscsi.scsidata.F",
1847 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
1848 "Final PDU", HFILL }
1850 { &hf_iscsi_SCSIData_A,
1851 { "A", "iscsi.scsidata.A",
1852 FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
1853 "Acknowledge Requested", HFILL }
1855 { &hf_iscsi_SCSIData_S,
1856 { "S", "iscsi.scsidata.S",
1857 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
1858 "PDU Contains SCSI command status", HFILL }
1860 { &hf_iscsi_SCSIData_U,
1861 { "U", "iscsi.scsidata.U",
1862 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
1863 "Residual underflow", HFILL }
1865 { &hf_iscsi_SCSIData_O,
1866 { "O", "iscsi.scsidata.O",
1867 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
1868 "Residual overflow", HFILL }
1870 { &hf_iscsi_TargetTransferTag,
1871 { "TargetTransferTag", "iscsi.targettransfertag",
1872 FT_UINT32, BASE_HEX, NULL, 0,
1873 "Target transfer tag", HFILL }
1875 { &hf_iscsi_BufferOffset,
1876 { "BufferOffset", "iscsi.bufferOffset",
1877 FT_UINT32, BASE_HEX, NULL, 0,
1878 "Buffer offset", HFILL }
1880 { &hf_iscsi_SCSIData_ResidualCount,
1881 { "ResidualCount", "iscsi.scsidata.readresidualcount",
1882 FT_UINT32, BASE_HEX, NULL, 0,
1883 "Residual count", HFILL }
1886 { "DataSN", "iscsi.datasn",
1887 FT_UINT32, BASE_HEX, NULL, 0,
1888 "Data sequence number", HFILL }
1890 { &hf_iscsi_VersionMax,
1891 { "VersionMax", "iscsi.versionmax",
1892 FT_UINT8, BASE_HEX, NULL, 0,
1893 "Maximum supported protocol version", HFILL }
1895 { &hf_iscsi_VersionMin,
1896 { "VersionMin", "iscsi.versionmin",
1897 FT_UINT8, BASE_HEX, NULL, 0,
1898 "Minimum supported protocol version", HFILL }
1900 { &hf_iscsi_VersionActive,
1901 { "VersionActive", "iscsi.versionactive",
1902 FT_UINT8, BASE_HEX, NULL, 0,
1903 "Negotiated protocol version", HFILL }
1906 { "CID", "iscsi.cid",
1907 FT_UINT16, BASE_HEX, NULL, 0,
1908 "Connection identifier", HFILL }
1910 /* #ifdef DRAFT08 */
1912 { "ISID", "iscsi.isid",
1913 FT_UINT16, BASE_HEX, NULL, 0,
1914 "Initiator part of session identifier", HFILL }
1918 { "ISID", "iscsi.isid",
1919 FT_BYTES, BASE_HEX, NULL, 0,
1920 "Initiator part of session identifier", HFILL }
1922 /* #ifdef DRAFT09 */
1923 { &hf_iscsi_ISID_Type,
1924 { "ISID_Type", "iscsi.isid.type",
1925 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
1926 "Initiator part of session identifier - type", HFILL }
1928 { &hf_iscsi_ISID_NamingAuthority,
1929 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
1930 FT_UINT24, BASE_HEX, NULL, 0,
1931 "Initiator part of session identifier - naming authority", HFILL }
1933 { &hf_iscsi_ISID_Qualifier,
1934 { "ISID_Qualifier", "iscsi.isid.qualifier",
1935 FT_UINT8, BASE_HEX, NULL, 0,
1936 "Initiator part of session identifier - qualifier", HFILL }
1940 { "ISID_t", "iscsi.isid.t",
1941 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
1942 "Initiator part of session identifier - t", HFILL }
1945 { "ISID_a", "iscsi.isid.a",
1946 FT_UINT8, BASE_HEX, NULL, 0x3f,
1947 "Initiator part of session identifier - a", HFILL }
1950 { "ISID_b", "iscsi.isid.b",
1951 FT_UINT16, BASE_HEX, NULL, 0,
1952 "Initiator part of session identifier - b", HFILL }
1955 { "ISID_c", "iscsi.isid.c",
1956 FT_UINT8, BASE_HEX, NULL, 0,
1957 "Initiator part of session identifier - c", HFILL }
1960 { "ISID_d", "iscsi.isid.d",
1961 FT_UINT16, BASE_HEX, NULL, 0,
1962 "Initiator part of session identifier - d", HFILL }
1967 { "TSID", "iscsi.tsid",
1968 FT_UINT16, BASE_HEX, NULL, 0,
1969 "Target part of session identifier", HFILL }
1972 { "TSIH", "iscsi.tsih",
1973 FT_UINT16, BASE_HEX, NULL, 0,
1974 "Target session identifying handle", HFILL }
1976 { &hf_iscsi_InitStatSN,
1977 { "InitStatSN", "iscsi.initstatsn",
1978 FT_UINT32, BASE_HEX, NULL, 0,
1979 "Initial status sequence number", HFILL }
1981 { &hf_iscsi_InitCmdSN,
1982 { "InitCmdSN", "iscsi.initcmdsn",
1983 FT_UINT32, BASE_HEX, NULL, 0,
1984 "Initial command sequence number", HFILL }
1986 { &hf_iscsi_Login_T,
1987 { "T", "iscsi.login.T",
1988 FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
1989 "Transit to next login stage", HFILL }
1991 /* #ifdef DRAFT09 */
1992 { &hf_iscsi_Login_X,
1993 { "X", "iscsi.login.X",
1994 FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
1995 "Restart Connection", HFILL }
1998 { &hf_iscsi_Login_CSG,
1999 { "CSG", "iscsi.login.csg",
2000 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
2001 "Current stage", HFILL }
2003 { &hf_iscsi_Login_NSG,
2004 { "NSG", "iscsi.login.nsg",
2005 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
2006 "Next stage", HFILL }
2008 { &hf_iscsi_Login_Status,
2009 { "Status", "iscsi.login.status",
2010 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
2011 "Status class and detail", HFILL }
2013 { &hf_iscsi_KeyValue,
2014 { "KeyValue", "iscsi.keyvalue",
2015 FT_STRING, 0, NULL, 0,
2016 "Key/value pair", HFILL }
2019 { "F", "iscsi.text.F",
2020 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2021 "Final PDU in text sequence", HFILL }
2023 { &hf_iscsi_ExpDataSN,
2024 { "ExpDataSN", "iscsi.expdatasn",
2025 FT_UINT32, BASE_HEX, NULL, 0,
2026 "Next expected data sequence number", HFILL }
2029 { "R2TSN", "iscsi.r2tsn",
2030 FT_UINT32, BASE_HEX, NULL, 0,
2031 "R2T PDU Number", HFILL }
2033 { &hf_iscsi_TaskManagementFunction_Response,
2034 { "Response", "iscsi.taskmanfun.response",
2035 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
2038 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
2039 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
2040 FT_UINT32, BASE_HEX, NULL, 0,
2041 "Referenced task tag", HFILL }
2043 { &hf_iscsi_RefCmdSN,
2044 { "RefCmdSN", "iscsi.refcmdsn",
2045 FT_UINT32, BASE_HEX, NULL, 0,
2046 "Command sequence number for command to be aborted", HFILL }
2048 { &hf_iscsi_TaskManagementFunction_Function,
2049 { "Function", "iscsi.taskmanfun.function",
2050 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
2051 "Requested task function", HFILL }
2053 { &hf_iscsi_Logout_Reason,
2054 { "Reason", "iscsi.logout.reason",
2055 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0,
2056 "Reason for logout", HFILL }
2058 { &hf_iscsi_Logout_Response,
2059 { "Response", "iscsi.logout.response",
2060 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
2061 "Logout response", HFILL }
2063 { &hf_iscsi_Time2Wait,
2064 { "Time2Wait", "iscsi.time2wait",
2065 FT_UINT16, BASE_HEX, NULL, 0,
2066 "Time2Wait", HFILL }
2068 { &hf_iscsi_Time2Retain,
2069 { "Time2Retain", "iscsi.time2retain",
2070 FT_UINT16, BASE_HEX, NULL, 0,
2071 "Time2Retain", HFILL }
2073 { &hf_iscsi_DesiredDataLength,
2074 { "DesiredDataLength", "iscsi.desireddatalength",
2075 FT_UINT32, BASE_HEX, NULL, 0,
2076 "Desired data length (bytes)", HFILL }
2078 { &hf_iscsi_AsyncEvent,
2079 { "AsyncEvent", "iscsi.asyncevent",
2080 FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2081 "Async event type", HFILL }
2083 { &hf_iscsi_EventVendorCode,
2084 { "EventVendorCode", "iscsi.eventvendorcode",
2085 FT_UINT8, BASE_HEX, NULL, 0,
2086 "Event vendor code", HFILL }
2088 { &hf_iscsi_Parameter1,
2089 { "Parameter1", "iscsi.parameter1",
2090 FT_UINT16, BASE_HEX, NULL, 0,
2091 "Parameter 1", HFILL }
2093 { &hf_iscsi_Parameter2,
2094 { "Parameter2", "iscsi.parameter2",
2095 FT_UINT16, BASE_HEX, NULL, 0,
2096 "Parameter 2", HFILL }
2098 { &hf_iscsi_Parameter3,
2099 { "Parameter3", "iscsi.parameter3",
2100 FT_UINT16, BASE_HEX, NULL, 0,
2101 "Parameter 3", HFILL }
2103 { &hf_iscsi_Reject_Reason,
2104 { "Reason", "iscsi.reject.reason",
2105 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2106 "Reason for command rejection", HFILL }
2108 { &hf_iscsi_snack_type,
2109 { "S", "iscsi.snack.type",
2110 FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2111 "Type of SNACK requested", HFILL }
2114 { "BegRun", "iscsi.snack.begrun",
2115 FT_UINT32, BASE_HEX, NULL, 0,
2116 "First missed DataSN or StatSN", HFILL }
2118 { &hf_iscsi_RunLength,
2119 { "RunLength", "iscsi.snack.runlength",
2120 FT_UINT32, BASE_HEX, NULL, 0,
2121 "Number of additional missing status PDUs in this run", HFILL }
2125 /* Setup protocol subtree array */
2126 static gint *ett[] = {
2128 &ett_iscsi_KeyValues,
2131 /* #ifndef DRAFT08 */
2136 /* Register the protocol name and description */
2137 proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2139 /* Required function calls to register the header fields and
2141 proto_register_field_array(proto_iscsi, hf, array_length(hf));
2142 proto_register_subtree_array(ett, array_length(ett));
2143 register_init_routine (&iscsi_init_protocol);
2146 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2148 prefs_register_enum_preference(iscsi_module,
2151 "The iSCSI protocol version",
2152 &iscsi_protocol_version,
2153 iscsi_protocol_versions,
2156 prefs_register_bool_preference(iscsi_module,
2157 "desegment_iscsi_messages",
2158 "Desegment iSCSI messages",
2159 "When enabled, iSCSI messages that span multiple TCP segments are desegmented",
2162 prefs_register_bool_preference(iscsi_module,
2164 "Enable bogus pdu filter",
2165 "When enabled, packets that appear bogus are ignored",
2166 &enable_bogosity_filter);
2168 prefs_register_bool_preference(iscsi_module,
2169 "demand_good_f_bit",
2170 "Ignore packets with bad F bit",
2171 "Ignore packets that haven't set the F bit when they should have",
2172 &demand_good_f_bit);
2174 prefs_register_uint_preference(iscsi_module,
2175 "bogus_pdu_max_data_len",
2176 "Bogus pdu max data length threshold",
2177 "Treat packets whose data segment length is greater than this value as bogus",
2179 &bogus_pdu_data_length_threshold);
2181 prefs_register_uint_preference(iscsi_module,
2184 "Port number of iSCSI target",
2188 prefs_register_bool_preference(iscsi_module,
2189 "enable_header_digests",
2190 "Enable header digests",
2191 "When enabled, pdus are assumed to contain a header digest",
2192 &enableHeaderDigests);
2193 prefs_register_bool_preference(iscsi_module,
2194 "enable_data_digests",
2195 "Enable data digests",
2196 "When enabled, pdus are assumed to contain a data digest",
2197 &enableDataDigests);
2199 prefs_register_bool_preference(iscsi_module,
2200 "header_digest_is_crc32c",
2201 "Header digest is CRC32C",
2202 "When enabled, header digests are assumed to be CRC32C",
2203 &headerDigestIsCRC32);
2204 prefs_register_bool_preference(iscsi_module,
2205 "data_digest_is_crc32c",
2206 "Data digest is CRC32C",
2207 "When enabled, data digests are assumed to be CRC32C",
2208 &dataDigestIsCRC32);
2210 prefs_register_uint_preference(iscsi_module,
2211 "header_digest_size",
2212 "Header digest size",
2213 "The size of a header digest (bytes)",
2216 prefs_register_uint_preference(iscsi_module,
2219 "The size of a data digest (bytes)",
2223 /* Preference supported in older versions.
2224 Register them as obsolete. */
2225 prefs_register_obsolete_preference(iscsi_module,
2226 "version_03_compatible");
2227 prefs_register_obsolete_preference(iscsi_module,
2228 "bogus_pdu_max_digest_padding");
2234 * If this dissector uses sub-dissector registration add a
2235 * registration routine.
2239 * This format is required because a script is used to find these
2240 * routines and create the code that calls these routines.
2243 proto_reg_handoff_iscsi(void)
2245 heur_dissector_add("tcp", dissect_iscsi, proto_iscsi);