1 /* TODO for the cases where one just can not autodetect whether header digest
2 is used or not we might need a new preference
10 * Routines for iSCSI dissection
11 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
12 * 2004 Request/Response matching and Service Response Time: ronnie sahlberg
16 * Wireshark - Network traffic analyzer
17 * By Gerald Combs <gerald@wireshark.org>
18 * Copyright 1998 Gerald Combs
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
45 #include <epan/packet.h>
46 #include <epan/prefs.h>
47 #include <epan/conversation.h>
48 #include "packet-fc.h"
49 #include "packet-scsi.h"
50 #include "epan/nstime.h"
51 #include <epan/emem.h>
53 /* the absolute values of these constants don't matter as long as
54 * latter revisions of the protocol are assigned a larger number */
55 #define ISCSI_PROTOCOL_DRAFT08 1
56 #define ISCSI_PROTOCOL_DRAFT09 2
57 #define ISCSI_PROTOCOL_DRAFT11 3
58 #define ISCSI_PROTOCOL_DRAFT12 4
59 #define ISCSI_PROTOCOL_DRAFT13 5
61 static enum_val_t iscsi_protocol_versions[] = {
62 { "draft-08", "Draft 08", ISCSI_PROTOCOL_DRAFT08 },
63 { "draft-09", "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
64 { "draft-11", "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
65 { "draft-12", "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
66 { "draft-13", "Draft 13", ISCSI_PROTOCOL_DRAFT13 },
70 static dissector_handle_t iscsi_handle=NULL;
72 static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT13;
74 static gboolean iscsi_desegment = TRUE;
76 static int demand_good_f_bit = FALSE;
77 static int enable_bogosity_filter = TRUE;
78 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
80 static int enableDataDigests = FALSE;
82 static int dataDigestIsCRC32 = TRUE;
84 static guint dataDigestSize = 4;
86 static guint iscsi_port = 3260;
88 /* Initialize the protocol and registered fields */
89 static int proto_iscsi = -1;
90 static int hf_iscsi_time = -1;
91 static int hf_iscsi_request_frame = -1;
92 static int hf_iscsi_data_in_frame = -1;
93 static int hf_iscsi_data_out_frame = -1;
94 static int hf_iscsi_response_frame = -1;
95 static int hf_iscsi_AHS = -1;
96 static int hf_iscsi_Padding = -1;
97 static int hf_iscsi_ping_data = -1;
98 static int hf_iscsi_immediate_data = -1;
99 static int hf_iscsi_write_data = -1;
100 static int hf_iscsi_read_data = -1;
101 static int hf_iscsi_error_pdu_data = -1;
102 static int hf_iscsi_async_message_data = -1;
103 static int hf_iscsi_vendor_specific_data = -1;
104 static int hf_iscsi_Opcode = -1;
105 static int hf_iscsi_Flags = -1;
106 static int hf_iscsi_HeaderDigest32 = -1;
107 static int hf_iscsi_DataDigest = -1;
108 static int hf_iscsi_DataDigest32 = -1;
110 static int hf_iscsi_X = -1;
112 static int hf_iscsi_I = -1;
113 static int hf_iscsi_SCSICommand_F = -1;
114 static int hf_iscsi_SCSICommand_R = -1;
115 static int hf_iscsi_SCSICommand_W = -1;
116 static int hf_iscsi_SCSICommand_Attr = -1;
117 static int hf_iscsi_SCSICommand_CRN = -1;
118 static int hf_iscsi_SCSICommand_AddCDB = -1;
119 static int hf_iscsi_DataSegmentLength = -1;
120 static int hf_iscsi_TotalAHSLength = -1;
121 static int hf_iscsi_LUN = -1;
122 static int hf_iscsi_InitiatorTaskTag = -1;
123 static int hf_iscsi_ExpectedDataTransferLength = -1;
124 static int hf_iscsi_CmdSN = -1;
125 static int hf_iscsi_ExpStatSN = -1;
126 static int hf_iscsi_StatSN = -1;
127 static int hf_iscsi_ExpCmdSN = -1;
128 static int hf_iscsi_MaxCmdSN = -1;
129 static int hf_iscsi_SCSIResponse_o = -1;
130 static int hf_iscsi_SCSIResponse_u = -1;
131 static int hf_iscsi_SCSIResponse_O = -1;
132 static int hf_iscsi_SCSIResponse_U = -1;
133 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
134 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
135 static int hf_iscsi_SCSIResponse_Response = -1;
136 static int hf_iscsi_SCSIResponse_Status = -1;
137 static int hf_iscsi_SenseLength = -1;
138 static int hf_iscsi_SCSIData_F = -1;
139 static int hf_iscsi_SCSIData_A = -1;
140 static int hf_iscsi_SCSIData_S = -1;
141 static int hf_iscsi_SCSIData_O = -1;
142 static int hf_iscsi_SCSIData_U = -1;
143 static int hf_iscsi_TargetTransferTag = -1;
144 static int hf_iscsi_DataSN = -1;
145 static int hf_iscsi_BufferOffset = -1;
146 static int hf_iscsi_SCSIData_ResidualCount = -1;
147 static int hf_iscsi_VersionMin = -1;
148 static int hf_iscsi_VersionMax = -1;
149 static int hf_iscsi_VersionActive = -1;
150 static int hf_iscsi_CID = -1;
151 static int hf_iscsi_ISID8 = -1;
152 static int hf_iscsi_ISID = -1;
153 /* #if defined(DRAFT09) */
154 static int hf_iscsi_ISID_Type = -1;
155 static int hf_iscsi_ISID_NamingAuthority = -1;
156 static int hf_iscsi_ISID_Qualifier = -1;
157 /* #elif !defined(DRAFT08) */
158 static int hf_iscsi_ISID_t = -1;
159 static int hf_iscsi_ISID_a = -1;
160 static int hf_iscsi_ISID_b = -1;
161 static int hf_iscsi_ISID_c = -1;
162 static int hf_iscsi_ISID_d = -1;
164 static int hf_iscsi_TSID = -1;
165 static int hf_iscsi_TSIH = -1;
166 static int hf_iscsi_InitStatSN = -1;
167 static int hf_iscsi_InitCmdSN = -1;
169 static int hf_iscsi_Login_X = -1;
171 static int hf_iscsi_Login_C = -1;
172 static int hf_iscsi_Login_T = -1;
173 static int hf_iscsi_Login_CSG = -1;
174 static int hf_iscsi_Login_NSG = -1;
175 static int hf_iscsi_Login_Status = -1;
176 static int hf_iscsi_KeyValue = -1;
177 static int hf_iscsi_Text_C = -1;
178 static int hf_iscsi_Text_F = -1;
179 static int hf_iscsi_ExpDataSN = -1;
180 static int hf_iscsi_R2TSN = -1;
181 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
182 static int hf_iscsi_RefCmdSN = -1;
183 static int hf_iscsi_TaskManagementFunction_Function = -1;
184 static int hf_iscsi_TaskManagementFunction_Response = -1;
185 static int hf_iscsi_Logout_Reason = -1;
186 static int hf_iscsi_Logout_Response = -1;
187 static int hf_iscsi_Time2Wait = -1;
188 static int hf_iscsi_Time2Retain = -1;
189 static int hf_iscsi_DesiredDataLength = -1;
190 static int hf_iscsi_AsyncEvent = -1;
191 static int hf_iscsi_EventVendorCode = -1;
192 static int hf_iscsi_Parameter1 = -1;
193 static int hf_iscsi_Parameter2 = -1;
194 static int hf_iscsi_Parameter3 = -1;
195 static int hf_iscsi_Reject_Reason = -1;
196 static int hf_iscsi_snack_type = -1;
197 static int hf_iscsi_BegRun = -1;
198 static int hf_iscsi_RunLength = -1;
200 /* Initialize the subtree pointers */
201 static gint ett_iscsi = -1;
202 static gint ett_iscsi_KeyValues = -1;
203 static gint ett_iscsi_CDB = -1;
204 static gint ett_iscsi_Flags = -1;
205 /* #ifndef DRAFT08 */
206 static gint ett_iscsi_ISID = -1;
209 #define ISCSI_HEADER_DIGEST_AUTO 0
210 #define ISCSI_HEADER_DIGEST_NONE 1
211 #define ISCSI_HEADER_DIGEST_CRC32 2
212 /* this structure contains session wide state for a specific tcp conversation */
213 typedef struct _iscsi_session_t {
214 guint32 header_digest;
215 se_tree_t *itlq; /* indexed by ITT */
216 se_tree_t *itl; /* indexed by LUN */
227 #define OPCODE_MASK 0x3f
229 #define TARGET_OPCODE_BIT 0x20
231 #define ISCSI_OPCODE_NOP_OUT 0x00
232 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
233 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
234 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
235 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
236 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
237 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
238 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
239 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
240 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
241 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
243 #define ISCSI_OPCODE_NOP_IN 0x20
244 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
245 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
246 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
247 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
248 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
249 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
250 #define ISCSI_OPCODE_R2T 0x31
251 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
252 #define ISCSI_OPCODE_REJECT 0x3f
253 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
254 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
255 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
258 #define CSG_MASK (0x03 << CSG_SHIFT)
259 #define NSG_MASK 0x03
261 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
262 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
263 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
265 #define ISCSI_SCSI_DATA_FLAG_S 0x01
266 #define ISCSI_SCSI_DATA_FLAG_U 0x02
267 #define ISCSI_SCSI_DATA_FLAG_O 0x04
268 #define ISCSI_SCSI_DATA_FLAG_A 0x40
269 #define ISCSI_SCSI_DATA_FLAG_F 0x80
271 static const value_string iscsi_opcodes[] = {
272 { ISCSI_OPCODE_NOP_OUT, "NOP Out" },
273 { ISCSI_OPCODE_SCSI_COMMAND, "SCSI Command" },
274 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION, "Task Management Function" },
275 { ISCSI_OPCODE_LOGIN_COMMAND, "Login Command" },
276 { ISCSI_OPCODE_TEXT_COMMAND, "Text Command" },
277 { ISCSI_OPCODE_SCSI_DATA_OUT, "SCSI Data Out" },
278 { ISCSI_OPCODE_LOGOUT_COMMAND, "Logout Command" },
279 { ISCSI_OPCODE_SNACK_REQUEST, "SNACK Request" },
280 { ISCSI_OPCODE_VENDOR_SPECIFIC_I0, "Vendor Specific I0" },
281 { ISCSI_OPCODE_VENDOR_SPECIFIC_I1, "Vendor Specific I1" },
282 { ISCSI_OPCODE_VENDOR_SPECIFIC_I2, "Vendor Specific I2" },
284 { ISCSI_OPCODE_NOP_IN, "NOP In" },
285 { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
286 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
287 { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
288 { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
289 { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
290 { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
291 { ISCSI_OPCODE_R2T, "Ready To Transfer" },
292 { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
293 { ISCSI_OPCODE_REJECT, "Reject"},
294 { ISCSI_OPCODE_VENDOR_SPECIFIC_T0, "Vendor Specific T0" },
295 { ISCSI_OPCODE_VENDOR_SPECIFIC_T1, "Vendor Specific T1" },
296 { ISCSI_OPCODE_VENDOR_SPECIFIC_T2, "Vendor Specific T2" },
301 static const true_false_string iscsi_meaning_X = {
308 static const true_false_string iscsi_meaning_login_X = {
309 "Reinstate failed connection",
314 static const true_false_string iscsi_meaning_I = {
315 "Immediate delivery",
319 static const true_false_string iscsi_meaning_F = {
320 "Final PDU in sequence",
321 "Not final PDU in sequence"
324 static const true_false_string iscsi_meaning_A = {
325 "Acknowledge requested",
326 "Acknowledge not requested"
329 static const true_false_string iscsi_meaning_T = {
330 "Transit to next login stage",
331 "Stay in current login stage"
334 static const true_false_string iscsi_meaning_C = {
335 "Text is incomplete",
339 static const true_false_string iscsi_meaning_S = {
340 "Response contains SCSI status",
341 "Response does not contain SCSI status"
344 static const true_false_string iscsi_meaning_R = {
345 "Data will be read from target",
346 "No data will be read from target"
349 static const true_false_string iscsi_meaning_W = {
350 "Data will be written to target",
351 "No data will be written to target"
354 static const true_false_string iscsi_meaning_o = {
355 "Read part of bi-directional command overflowed",
356 "No overflow of read part of bi-directional command",
359 static const true_false_string iscsi_meaning_u = {
360 "Read part of bi-directional command underflowed",
361 "No underflow of read part of bi-directional command",
364 static const true_false_string iscsi_meaning_O = {
365 "Residual overflow occurred",
366 "No residual overflow occurred",
369 static const true_false_string iscsi_meaning_U = {
370 "Residual underflow occurred",
371 "No residual underflow occurred",
374 static const value_string iscsi_scsi_responses[] = {
375 { 0, "Command completed at target" },
376 { 1, "Response does not contain SCSI status"},
380 static const value_string iscsi_scsicommand_taskattrs[] = {
384 {3, "Head of Queue"},
389 static const value_string iscsi_task_management_responses[] = {
390 {0, "Function complete"},
391 {1, "Task not in task set"},
392 {2, "LUN does not exist"},
393 {3, "Task still allegiant"},
394 {4, "Task failover not supported"},
395 {5, "Task management function not supported"},
396 {6, "Authorisation failed"},
397 {255, "Function rejected"},
401 static const value_string iscsi_task_management_functions[] = {
403 {2, "Abort Task Set"},
405 {4, "Clear Task Set"},
406 {5, "Logical Unit Reset"},
407 {6, "Target Warm Reset"},
408 {7, "Target Cold Reset"},
412 static const value_string iscsi_login_status[] = {
414 {0x0101, "Target moved temporarily"},
415 {0x0102, "Target moved permanently"},
416 {0x0200, "Initiator error (miscellaneous error)"},
417 {0x0201, "Authentication failed"},
418 {0x0202, "Authorisation failure"},
419 {0x0203, "Target not found"},
420 {0x0204, "Target removed"},
421 {0x0205, "Unsupported version"},
422 {0x0206, "Too many connections"},
423 {0x0207, "Missing parameter"},
424 {0x0208, "Can't include in session"},
425 {0x0209, "Session type not supported"},
426 {0x020a, "Session does not exist"},
427 {0x020b, "Invalid request during login"},
428 {0x0300, "Target error (miscellaneous error)"},
429 {0x0301, "Service unavailable"},
430 {0x0302, "Out of resources"},
434 static const value_string iscsi_login_stage[] = {
435 {0, "Security negotiation"},
436 {1, "Operational negotiation"},
437 {3, "Full feature phase"},
441 /* #ifndef DRAFT08 */
442 static const value_string iscsi_isid_type[] = {
444 {0x01, "IANA Enterprise Number"},
450 static const value_string iscsi_logout_reasons[] = {
451 {0, "Close session"},
452 {1, "Close connection"},
453 {2, "Remove connection for recovery"},
457 static const value_string iscsi_logout_response[] = {
458 {0, "Connection closed successfully"},
459 {1, "CID not found"},
460 {2, "Connection recovery not supported"},
461 {3, "Cleanup failed for various reasons"},
465 static const value_string iscsi_asyncevents[] = {
466 {0, "A SCSI asynchronous event is reported in the sense data"},
467 {1, "Target requests logout"},
468 {2, "Target will/has dropped connection"},
469 {3, "Target will/has dropped all connections"},
470 {4, "Target requests parameter negotiation"},
474 static const value_string iscsi_snack_types[] = {
477 /* #ifndef DRAFT08 */
484 static const value_string iscsi_reject_reasons[] = {
486 {0x01, "Full feature phase command before login"},
488 {0x02, "Data (payload) digest error"},
489 {0x03, "Data SNACK reject"},
490 {0x04, "Protocol error"},
491 {0x05, "Command not supported in this session type"},
492 {0x06, "Immediate command reject (too many immediate commands)"},
493 {0x07, "Task in progress"},
494 {0x08, "Invalid Data Ack"},
495 {0x09, "Invalid PDU field"},
496 {0x0a, "Long operation reject"},
497 {0x0b, "Negotiation reset"},
498 {0x0c, "Waiting for logout"},
502 /*****************************************************************/
504 /* CRC LOOKUP TABLE */
505 /* ================ */
506 /* The following CRC lookup table was generated automagically */
507 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
508 /* Program V1.0 using the following model parameters: */
510 /* Width : 4 bytes. */
511 /* Poly : 0x1EDC6F41L */
512 /* Reverse : TRUE. */
514 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
515 /* see the document titled "A Painless Guide to CRC Error */
516 /* Detection Algorithms" by Ross Williams */
517 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
518 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
520 /*****************************************************************/
522 static guint32 crc32Table[256] = {
523 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
524 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
525 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
526 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
527 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
528 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
529 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
530 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
531 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
532 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
533 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
534 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
535 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
536 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
537 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
538 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
539 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
540 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
541 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
542 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
543 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
544 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
545 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
546 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
547 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
548 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
549 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
550 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
551 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
552 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
553 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
554 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
555 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
556 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
557 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
558 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
559 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
560 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
561 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
562 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
563 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
564 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
565 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
566 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
567 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
568 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
569 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
570 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
571 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
572 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
573 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
574 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
575 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
576 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
577 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
578 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
579 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
580 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
581 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
582 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
583 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
584 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
585 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
586 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
589 #define CRC32C_PRELOAD 0xffffffff
592 * Byte swap fix contributed by Dave Wysochanski <davidw@netapp.com>
594 #define CRC32C_SWAP(crc32c_value) \
595 (((crc32c_value & 0xff000000) >> 24) | \
596 ((crc32c_value & 0x00ff0000) >> 8) | \
597 ((crc32c_value & 0x0000ff00) << 8) | \
598 ((crc32c_value & 0x000000ff) << 24))
601 calculateCRC32(const void *buf, int len, guint32 crc) {
602 const guint8 *p = (const guint8 *)buf;
603 crc = CRC32C_SWAP(crc);
605 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
606 return CRC32C_SWAP(crc);
613 /* structure and functions to keep track of
614 * COMMAND/DATA_IN/DATA_OUT/RESPONSE matching
616 typedef struct _iscsi_conv_data {
617 guint32 data_in_frame;
618 guint32 data_out_frame;
623 iscsi_min(int a, int b) {
624 return (a < b)? a : b;
628 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
629 const gint limit = offset + text_len;
630 while(offset < limit) {
631 gint len = tvb_strnlen(tvb, offset, limit - offset);
633 len = limit - offset;
636 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
643 handleHeaderDigest(iscsi_session_t *iscsi_session, proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
644 int available_bytes = tvb_length_remaining(tvb, offset);
646 switch(iscsi_session->header_digest){
647 case ISCSI_HEADER_DIGEST_CRC32:
648 if(available_bytes >= (headerLen + 4)) {
649 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
650 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
652 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
654 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);
657 return offset + headerLen + 4;
660 return offset + headerLen;
664 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
665 int available_bytes = tvb_length_remaining(tvb, offset);
666 if(enableDataDigests) {
667 if(dataDigestIsCRC32) {
668 if(available_bytes >= (dataLen + 4)) {
669 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
670 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
672 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
675 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);
678 return offset + dataLen + 4;
680 if((unsigned)available_bytes >= (dataLen + dataDigestSize)) {
681 proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
683 return offset + dataLen + dataDigestSize;
685 return offset + dataLen;
689 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
690 if(endOffset > offset) {
691 int dataOffset = offset;
692 int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
694 proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
697 if(offset < endOffset && (offset & 3) != 0) {
698 int padding = 4 - (offset & 3);
699 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
702 if(dataSegmentLen > 0 && offset < endOffset)
703 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
710 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
711 if(endOffset > offset) {
712 int dataOffset = offset;
713 int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
715 proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
716 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
717 offset = addTextKeys(tt, tvb, offset, textLen);
719 if(offset < endOffset && (offset & 3) != 0) {
720 int padding = 4 - (offset & 3);
721 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
724 if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
725 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
730 /* Code to actually dissect the packets */
732 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len, iscsi_session_t *iscsi_session) {
734 guint original_offset = offset;
735 proto_tree *ti = NULL;
736 guint8 scsi_status = 0;
737 gboolean S_bit=FALSE;
738 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
739 guint end_offset = offset + tvb_length_remaining(tvb, offset);
740 iscsi_conv_data_t *cdata = NULL;
741 int paddedDataSegmentLength = data_segment_len;
743 guint immediate_data_length=0;
744 guint immediate_data_offset=0;
745 itl_nexus_t *itl=NULL;
747 if(paddedDataSegmentLength & 3)
748 paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
750 /* Make entries in Protocol column and Info column on summary display */
751 if (check_col(pinfo->cinfo, COL_PROTOCOL))
752 col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
754 /* XXX we need a way to handle replayed iscsi itt here */
755 cdata=(iscsi_conv_data_t *)se_tree_lookup32(iscsi_session->itlq, tvb_get_ntohl(tvb, offset+16));
757 cdata = se_alloc (sizeof(iscsi_conv_data_t));
758 cdata->itlq.lun=0xffff;
759 cdata->itlq.scsi_opcode=0xffff;
760 cdata->itlq.fc_time = pinfo->fd->abs_ts;
761 cdata->itlq.first_exchange_frame=0;
762 cdata->itlq.last_exchange_frame=0;
764 cdata->itlq.alloc_len=0;
765 cdata->data_in_frame=0;
766 cdata->data_out_frame=0;
768 se_tree_insert32(iscsi_session->itlq, tvb_get_ntohl(tvb, offset+16), cdata);
771 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
772 opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
773 scsi_status = tvb_get_guint8 (tvb, offset+3);
776 if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
777 (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
778 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
779 /* first time we see this packet. check if we can find the request */
781 case ISCSI_OPCODE_SCSI_RESPONSE:
782 cdata->itlq.last_exchange_frame=pinfo->fd->num;
784 case ISCSI_OPCODE_SCSI_DATA_IN:
785 /* a bit ugly but we need to check the S bit here */
786 if(tvb_get_guint8(tvb, offset+1)&ISCSI_SCSI_DATA_FLAG_S){
787 cdata->itlq.last_exchange_frame=pinfo->fd->num;
789 cdata->data_in_frame=pinfo->fd->num;
791 case ISCSI_OPCODE_SCSI_DATA_OUT:
792 cdata->data_out_frame=pinfo->fd->num;
796 } else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
797 /*we need the LUN value for some of the commands so we can pass it
798 across to the SCSI dissector.
799 Not correct but simple and probably accurate enough :
800 If bit 6 of first bit is 0 then just take second byte as the LUN
801 If bit 6 of first bit is 1, then take 6 bits from first byte
802 and all of second byte and pretend it is the lun value
803 people that care can add host specific dissection of vsa later.
805 We need to keep track of this on a per transaction basis since
806 for error recoverylevel 0 and when the A bit is clear in a
807 Data-In PDU, there will not be a LUN field in teh iscsi layer.
809 if(tvb_get_guint8(tvb, offset+8)&0x40){
810 /* volume set addressing */
811 lun=tvb_get_guint8(tvb,offset+8)&0x3f;
813 lun|=tvb_get_guint8(tvb,offset+9);
815 lun=tvb_get_guint8(tvb,offset+9);
819 cdata->itlq.first_exchange_frame=pinfo->fd->num;
821 itl=(itl_nexus_t *)se_tree_lookup32(iscsi_session->itl, lun);
823 itl=se_alloc(sizeof(itl_nexus_t));
825 se_tree_insert32(iscsi_session->itl, lun, itl);
831 itl=(itl_nexus_t *)se_tree_lookup32(iscsi_session->itl, cdata->itlq.lun);
835 if (check_col(pinfo->cinfo, COL_INFO)) {
837 if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
839 col_append_str(pinfo->cinfo, COL_INFO, opcode_str);
841 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
842 (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
843 (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
844 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
845 val_to_str (scsi_status, scsi_status_val, "0x%x"));
847 else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
848 guint16 login_status = tvb_get_ntohs(tvb, offset+36);
849 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
850 val_to_str (login_status, iscsi_login_status, "0x%x"));
852 else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
854 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
855 logoutReason = tvb_get_guint8(tvb, offset+11);
856 } else if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
857 logoutReason = tvb_get_guint8(tvb, offset+1) & 0x7f;
860 logoutReason = tvb_get_guint8(tvb, offset+23);
862 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
863 val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
865 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
866 guint8 tmf = tvb_get_guint8(tvb, offset + 1);
867 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
868 val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
870 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
871 guint8 resp = tvb_get_guint8(tvb, offset + 2);
872 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
873 val_to_str (resp, iscsi_task_management_responses, "0x%x"));
875 else if (opcode == ISCSI_OPCODE_REJECT) {
876 guint8 reason = tvb_get_guint8(tvb, offset + 2);
877 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
878 val_to_str (reason, iscsi_reject_reasons, "0x%x"));
880 else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
881 guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
882 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
883 val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
888 /* In the interest of speed, if "tree" is NULL, don't do any
889 work not necessary to generate protocol tree items. */
892 /* create display subtree for the protocol */
893 tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
894 offset, -1, "iSCSI (%s)",
896 ti = proto_item_add_subtree(tp, ett_iscsi);
898 proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
899 offset + 0, 1, opcode);
900 if((opcode & TARGET_OPCODE_BIT) == 0) {
901 /* initiator -> target */
902 gint b = tvb_get_guint8(tvb, offset + 0);
903 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
904 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
905 opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
906 opcode != ISCSI_OPCODE_SNACK_REQUEST)
907 proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
909 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
910 opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
911 opcode != ISCSI_OPCODE_SNACK_REQUEST)
912 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
915 if(opcode == ISCSI_OPCODE_NOP_OUT) {
917 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
918 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
920 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
921 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
922 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
923 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
924 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
925 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
926 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
927 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
928 } else if(opcode == ISCSI_OPCODE_NOP_IN) {
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_StatSN, tvb, offset + 24, 4, FALSE);
938 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
939 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
940 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
941 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
942 } else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
944 guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
946 gint b = tvb_get_guint8(tvb, offset + 1);
947 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
948 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
950 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
951 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
952 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
953 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
955 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
956 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
958 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
959 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
960 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
961 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
962 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
963 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
964 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
967 /* FIXME - disssect AHS? */
968 proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 48, ahsLen, FALSE);
970 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48 + ahsLen);
972 immediate_data_offset=offset;
973 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
974 immediate_data_length=offset-immediate_data_offset;
975 } else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
978 gint b = tvb_get_guint8(tvb, offset + 1);
979 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
980 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
982 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
983 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
984 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
985 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
987 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
988 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
989 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
990 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
992 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
993 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
994 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
995 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
997 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
998 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
999 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1000 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1001 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1002 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
1005 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
1006 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
1008 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1009 /* do not update offset here because the data segment is
1010 * dissected below */
1011 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1012 } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
1013 /* Task Management Function */
1014 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
1015 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1016 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1017 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1019 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1020 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1021 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1022 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1023 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1024 proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1025 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1026 } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1027 /* Task Management Function Response */
1028 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 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_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1034 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1035 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1037 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1038 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1039 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1040 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1041 } else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1043 int digestsActive = 0;
1045 gint b = tvb_get_guint8(tvb, offset + 1);
1046 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1047 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1051 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1052 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1055 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1056 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1057 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1059 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1060 proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1062 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1064 /* NSG is undefined unless T is set */
1066 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1069 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1070 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1071 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1072 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1074 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1075 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1076 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1077 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1080 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1081 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1082 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1083 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1084 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1085 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1088 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1089 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1090 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1091 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1092 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1095 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1096 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1099 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1101 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1102 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1103 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1105 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1106 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1108 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1112 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1113 } else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1114 /* Login Response */
1115 int digestsActive = 0;
1117 gint b = tvb_get_guint8(tvb, offset + 1);
1118 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1119 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1123 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1124 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1127 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1128 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1129 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1131 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1132 /* NSG is undefined unless T is set */
1134 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1138 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1139 proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1140 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1141 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1143 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1144 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1145 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1148 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1149 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1150 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1151 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1152 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1153 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1156 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1157 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1158 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1159 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1160 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1163 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1164 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1167 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1169 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1170 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1171 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1172 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1173 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1175 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1179 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1180 } else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1183 gint b = tvb_get_guint8(tvb, offset + 1);
1184 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1185 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1187 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1188 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1189 proto_tree_add_boolean(tt, hf_iscsi_Text_C, 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(iscsi_session, ti, tvb, offset, 48);
1204 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1205 } else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1208 gint b = tvb_get_guint8(tvb, offset + 1);
1209 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1210 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1212 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1213 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1214 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1217 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1218 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1220 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1221 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1222 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1224 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1225 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1226 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1227 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1228 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1229 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1230 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1231 } else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1232 /* SCSI Data Out (write) */
1234 gint b = tvb_get_guint8(tvb, offset + 1);
1235 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1236 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1238 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1240 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1241 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1243 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1244 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1245 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1246 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1247 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1248 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1249 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1250 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1251 /* do not update offset here because the data segment is
1252 * dissected below */
1253 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 if(b&ISCSI_SCSI_DATA_FLAG_S){
1264 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1265 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1266 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
1268 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1269 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1270 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1273 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1275 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1276 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1278 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1279 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1280 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1282 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1283 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1284 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1287 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1289 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1290 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1291 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1292 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1293 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1294 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1295 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1297 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1298 /* do not update offset here because the data segment is
1299 * dissected below */
1300 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1301 } else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1302 /* Logout Command */
1303 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1304 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 1, 1, FALSE);
1306 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1307 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1308 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1310 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1311 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1312 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1314 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1315 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1316 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1317 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT13) {
1318 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
1321 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1322 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1323 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1324 } else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1325 /* Logout Response */
1326 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1327 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1328 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1329 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1331 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1332 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1333 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1334 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1335 proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1336 proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1337 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1338 } else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1341 gint b = tvb_get_guint8(tvb, offset + 1);
1343 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1344 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1347 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1349 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1350 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1351 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1352 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1354 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1355 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1356 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1357 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1358 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1359 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1362 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1363 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1364 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1365 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1367 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1368 } else if(opcode == ISCSI_OPCODE_R2T) {
1370 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1371 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1372 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1373 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1375 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1376 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1377 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1378 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1379 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1380 proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
1381 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1382 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1383 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1384 } else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1385 /* Asynchronous Message */
1386 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1387 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1389 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1390 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1391 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1392 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1393 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1394 proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1395 proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1396 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1397 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1398 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1399 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1400 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
1401 } else if(opcode == ISCSI_OPCODE_REJECT) {
1403 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
1404 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1405 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1407 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1408 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1409 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1410 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1411 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1412 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1413 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1414 } else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
1415 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
1416 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
1417 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
1418 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
1419 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
1420 /* Vendor specific opcodes */
1421 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1422 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1424 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1425 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1426 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
1431 /* handle request/response matching */
1433 case ISCSI_OPCODE_SCSI_RESPONSE:
1434 if (cdata->itlq.first_exchange_frame){
1435 nstime_t delta_time;
1436 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1437 nstime_delta(&delta_time, &pinfo->fd->abs_ts, &cdata->itlq.fc_time);
1438 proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1440 if (cdata->data_in_frame)
1441 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1442 if (cdata->data_out_frame)
1443 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1445 case ISCSI_OPCODE_SCSI_DATA_IN:
1446 /* if we have phase collaps then we might have the
1447 response embedded in the last DataIn segment */
1449 if (cdata->itlq.first_exchange_frame)
1450 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1451 if (cdata->itlq.last_exchange_frame)
1452 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1454 if (cdata->itlq.first_exchange_frame){
1455 nstime_t delta_time;
1456 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1457 nstime_delta(&delta_time, &pinfo->fd->abs_ts, &cdata->itlq.fc_time);
1458 proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1461 if (cdata->data_out_frame)
1462 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1464 case ISCSI_OPCODE_SCSI_DATA_OUT:
1465 if (cdata->itlq.first_exchange_frame)
1466 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1467 if (cdata->data_in_frame)
1468 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1469 if (cdata->itlq.last_exchange_frame)
1470 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1472 case ISCSI_OPCODE_SCSI_COMMAND:
1473 if (cdata->data_in_frame)
1474 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1475 if (cdata->data_out_frame)
1476 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1477 if (cdata->itlq.last_exchange_frame)
1478 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1484 proto_item_set_len(ti, offset - original_offset);
1486 if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
1488 ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
1489 tvbuff_t *cdb_tvb, *data_tvb;
1490 int tvb_len, tvb_rlen;
1493 tvb_len=tvb_length_remaining(tvb, cdb_offset);
1496 tvb_rlen=tvb_reported_length_remaining(tvb, cdb_offset);
1499 cdb_tvb=tvb_new_subset(tvb, cdb_offset, tvb_len, tvb_rlen);
1500 dissect_scsi_cdb(cdb_tvb, pinfo, tree, SCSI_DEV_UNKNOWN, &cdata->itlq, itl);
1501 /* we dont want the immediata below to overwrite our CDB info */
1502 if (check_col(pinfo->cinfo, COL_INFO)) {
1503 col_set_fence(pinfo->cinfo, COL_INFO);
1505 /* where there any ImmediateData ? */
1506 if(immediate_data_length){
1507 /* Immediate Data TVB */
1508 tvb_len=tvb_length_remaining(tvb, immediate_data_offset);
1509 if(tvb_len>(int)immediate_data_length)
1510 tvb_len=immediate_data_length;
1511 tvb_rlen=tvb_reported_length_remaining(tvb, immediate_data_offset);
1512 if(tvb_rlen>(int)immediate_data_length)
1513 tvb_rlen=immediate_data_length;
1514 data_tvb=tvb_new_subset(tvb, immediate_data_offset, tvb_len, tvb_rlen);
1515 dissect_scsi_payload (data_tvb, pinfo, tree,
1520 else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1521 if (scsi_status == 0x2) {
1522 /* A SCSI response with Check Condition contains sense data */
1523 /* offset is setup correctly by the iscsi code for response above */
1524 if((end_offset - offset) >= 2) {
1525 int senseLen = tvb_get_ntohs(tvb, offset);
1527 proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1531 int tvb_len, tvb_rlen;
1533 tvb_len=tvb_length_remaining(tvb, offset);
1534 if(tvb_len>senseLen)
1536 tvb_rlen=tvb_reported_length_remaining(tvb, offset);
1537 if(tvb_rlen>senseLen)
1539 data_tvb=tvb_new_subset(tvb, offset, tvb_len, tvb_rlen);
1540 dissect_scsi_snsinfo (data_tvb, pinfo, tree, 0,
1547 dissect_scsi_rsp(tvb, pinfo, tree, &cdata->itlq, itl, scsi_status);
1550 else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1551 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1553 int tvb_len, tvb_rlen;
1555 /* offset is setup correctly by the iscsi code for response above */
1556 tvb_len=tvb_length_remaining(tvb, offset);
1557 if(tvb_len>(int)data_segment_len)
1558 tvb_len=data_segment_len;
1559 tvb_rlen=tvb_reported_length_remaining(tvb, offset);
1560 if(tvb_rlen>(int)data_segment_len)
1561 tvb_rlen=data_segment_len;
1562 data_tvb=tvb_new_subset(tvb, offset, tvb_len, tvb_rlen);
1563 dissect_scsi_payload (data_tvb, pinfo, tree,
1564 (opcode==ISCSI_OPCODE_SCSI_DATA_OUT),
1569 dissect_scsi_rsp(tvb, pinfo, tree, &cdata->itlq, itl, scsi_status);
1574 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_port) {
1575 /* Set up structures needed to add the protocol subtree and manage it */
1576 guint iSCSIPdusDissected = 0;
1578 guint32 available_bytes = tvb_length_remaining(tvb, offset);
1579 int digestsActive = 1;
1580 conversation_t *conversation = NULL;
1581 iscsi_session_t *iscsi_session=NULL;
1583 /* quick check to see if the packet is long enough to contain the
1584 * minimum amount of information we need */
1585 if (available_bytes < 48 && (!iscsi_desegment || available_bytes < 8)) {
1586 /* no, so give up */
1590 /* process multiple iSCSI PDUs per packet */
1591 while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
1592 const char *opcode_str = NULL;
1593 guint32 data_segment_len;
1594 guint32 pduLen = 48;
1595 guint8 opcode = tvb_get_guint8(tvb, offset + 0);
1596 guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
1599 /* mask out any extra bits in the opcode byte */
1600 opcode &= OPCODE_MASK;
1602 opcode_str = match_strval(opcode, iscsi_opcodes);
1603 if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
1604 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1605 opcode == ISCSI_OPCODE_R2T ||
1606 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1607 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1608 opcode == ISCSI_OPCODE_SNACK_REQUEST)
1609 data_segment_len = 0;
1611 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
1613 if(opcode_str == NULL) {
1616 else if(check_port && iscsi_port != 0 &&
1617 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
1618 (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
1621 else if(enable_bogosity_filter) {
1622 /* try and distinguish between data and real headers */
1623 if(data_segment_len > bogus_pdu_data_length_threshold) {
1626 else if(demand_good_f_bit &&
1627 !(secondPduByte & 0x80) &&
1628 (opcode == ISCSI_OPCODE_NOP_OUT ||
1629 opcode == ISCSI_OPCODE_NOP_IN ||
1630 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1631 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1632 opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
1633 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1634 opcode == ISCSI_OPCODE_R2T ||
1635 opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
1636 opcode == ISCSI_OPCODE_SNACK_REQUEST ||
1637 opcode == ISCSI_OPCODE_REJECT)) {
1639 } else if(opcode==ISCSI_OPCODE_NOP_OUT) {
1640 /* TransferTag for NOP-Out should either be -1 or
1641 the tag value we want for a response.
1642 Assume 0 means we are just inside a big all zero
1645 if(tvb_get_ntohl(tvb, offset+20)==0){
1652 return iSCSIPdusDissected > 0;
1655 if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
1656 opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1657 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1658 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
1659 /* digests are not yet turned on */
1667 if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1669 pduLen += tvb_get_guint8(tvb, offset + 4) * 4;
1672 pduLen += data_segment_len;
1673 if((pduLen & 3) != 0)
1674 pduLen += 4 - (pduLen & 3);
1677 if(digestsActive && data_segment_len > 0 && enableDataDigests) {
1678 if(dataDigestIsCRC32)
1681 pduLen += dataDigestSize;
1684 /* make sure we have a conversation for this session */
1685 conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
1686 pinfo->ptype, pinfo->srcport,
1687 pinfo->destport, 0);
1688 if (!conversation) {
1689 conversation = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst,
1690 pinfo->ptype, pinfo->srcport,
1691 pinfo->destport, 0);
1693 iscsi_session=conversation_get_proto_data(conversation, proto_iscsi);
1695 iscsi_session=se_alloc(sizeof(iscsi_session_t));
1696 iscsi_session->header_digest=ISCSI_HEADER_DIGEST_AUTO;
1697 iscsi_session->itlq=se_tree_create_non_persistent(SE_TREE_TYPE_RED_BLACK, "iSCSI ITLQ");
1698 iscsi_session->itl=se_tree_create_non_persistent(SE_TREE_TYPE_RED_BLACK, "iSCSI ITL");
1699 conversation_add_proto_data(conversation, proto_iscsi, iscsi_session);
1701 /* DataOut PDUs are often mistaken by DCERPC heuristics to be
1702 * that protocol. Now that we know this is iscsi, set a
1703 * dissector for this conversation to block other heuristic
1706 conversation_set_dissector(conversation, iscsi_handle);
1708 /* try to autodetect if header digest is used or not */
1709 if(digestsActive && (available_bytes>=52) && (iscsi_session->header_digest==ISCSI_HEADER_DIGEST_AUTO) ){
1711 /* we have enough data to test if HeaderDigest is enabled */
1712 crc= ~calculateCRC32(tvb_get_ptr(tvb, offset, 48), 48, CRC32C_PRELOAD);
1713 if(crc==tvb_get_ntohl(tvb,48)){
1714 iscsi_session->header_digest=ISCSI_HEADER_DIGEST_CRC32;
1716 iscsi_session->header_digest=ISCSI_HEADER_DIGEST_NONE;
1721 /* Add header digest length to pdulen */
1723 switch(iscsi_session->header_digest){
1724 case ISCSI_HEADER_DIGEST_CRC32:
1727 case ISCSI_HEADER_DIGEST_NONE:
1729 case ISCSI_HEADER_DIGEST_AUTO:
1730 /* oops we didnt know what digest is used yet */
1731 /* here we should use some default */
1734 DISSECTOR_ASSERT_NOT_REACHED();
1739 * Desegmentation check.
1741 if(iscsi_desegment && pinfo->can_desegment) {
1742 if(pduLen > available_bytes) {
1744 * This frame doesn't have all of the data for
1745 * this message, but we can do reassembly on it.
1747 * Tell the TCP dissector where the data for this
1748 * message starts in the data it handed us, and
1749 * how many more bytes we need, and return.
1751 pinfo->desegment_offset = offset;
1752 pinfo->desegment_len = pduLen - available_bytes;
1757 /* This is to help TCP keep track of PDU boundaries
1758 and allows it to find PDUs that are not aligned to
1759 the start of a TCP segments.
1760 Since it also allows TCP to know what is in the middle
1761 of a large PDU, it reduces the probability of a segment
1762 in the middle of a large PDU transfer being misdissected as
1765 if(!pinfo->fd->flags.visited){
1766 if(pduLen>(guint32)tvb_reported_length_remaining(tvb, offset)){
1767 pinfo->want_pdu_tracking=2;
1768 pinfo->bytes_until_next_pdu=pduLen-tvb_reported_length_remaining(tvb, offset);
1772 if(check_col(pinfo->cinfo, COL_INFO)) {
1773 if(iSCSIPdusDissected == 0)
1774 col_set_str(pinfo->cinfo, COL_INFO, "");
1776 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1779 dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len, iscsi_session);
1780 if(pduLen > available_bytes)
1781 pduLen = available_bytes;
1783 available_bytes -= pduLen;
1784 ++iSCSIPdusDissected;
1787 return iSCSIPdusDissected > 0;
1790 /* This is called for those sessions where we have explicitely said
1791 this to be iSCSI using "Decode As..."
1792 In this case we will not check the port number for sanity and just
1793 do as the user said.
1796 dissect_iscsi_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1797 dissect_iscsi(tvb, pinfo, tree, FALSE);
1800 /* This is called through the heuristic handler.
1801 In this case we also want to check that the port matches the preference
1802 setting for iSCSI in order to reduce the number of
1806 dissect_iscsi_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1807 return dissect_iscsi(tvb, pinfo, tree, TRUE);
1811 /* Register the protocol with Wireshark */
1814 * this format is require because a script is used to build the C
1815 * function that calls all the protocol registration.
1819 proto_register_iscsi(void)
1822 /* Setup list of header fields See Section 1.6.1 for details*/
1823 static hf_register_info hf[] = {
1824 { &hf_iscsi_request_frame,
1825 { "Request in", "iscsi.request_frame",
1826 FT_FRAMENUM, BASE_NONE, NULL, 0,
1827 "The request to this transaction is in this frame", HFILL }},
1830 { "Time from request", "iscsi.time",
1831 FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
1832 "Time between the Command and the Response", HFILL }},
1834 { &hf_iscsi_data_in_frame,
1835 { "Data In in", "iscsi.data_in_frame",
1836 FT_FRAMENUM, BASE_NONE, NULL, 0,
1837 "The Data In for this transaction is in this frame", HFILL }},
1839 { &hf_iscsi_data_out_frame,
1840 { "Data Out in", "iscsi.data_out_frame",
1841 FT_FRAMENUM, BASE_NONE, NULL, 0,
1842 "The Data Out for this transaction is in this frame", HFILL }},
1844 { &hf_iscsi_response_frame,
1845 { "Response in", "iscsi.response_frame",
1846 FT_FRAMENUM, BASE_NONE, NULL, 0,
1847 "The response to this transaction is in this frame", HFILL }},
1850 { "AHS", "iscsi.ahs",
1851 FT_BYTES, BASE_HEX, NULL, 0,
1852 "Additional header segment", HFILL }
1854 { &hf_iscsi_Padding,
1855 { "Padding", "iscsi.padding",
1856 FT_BYTES, BASE_HEX, NULL, 0,
1857 "Padding to 4 byte boundary", HFILL }
1859 { &hf_iscsi_ping_data,
1860 { "PingData", "iscsi.pingdata",
1861 FT_BYTES, BASE_HEX, NULL, 0,
1862 "Ping Data", HFILL }
1864 { &hf_iscsi_immediate_data,
1865 { "ImmediateData", "iscsi.immediatedata",
1866 FT_BYTES, BASE_HEX, NULL, 0,
1867 "Immediate Data", HFILL }
1869 { &hf_iscsi_write_data,
1870 { "WriteData", "iscsi.writedata",
1871 FT_BYTES, BASE_HEX, NULL, 0,
1872 "Write Data", HFILL }
1874 { &hf_iscsi_read_data,
1875 { "ReadData", "iscsi.readdata",
1876 FT_BYTES, BASE_HEX, NULL, 0,
1877 "Read Data", HFILL }
1879 { &hf_iscsi_error_pdu_data,
1880 { "ErrorPDUData", "iscsi.errorpdudata",
1881 FT_BYTES, BASE_HEX, NULL, 0,
1882 "Error PDU Data", HFILL }
1884 { &hf_iscsi_async_message_data,
1885 { "AsyncMessageData", "iscsi.asyncmessagedata",
1886 FT_BYTES, BASE_HEX, NULL, 0,
1887 "Async Message Data", HFILL }
1889 { &hf_iscsi_vendor_specific_data,
1890 { "VendorSpecificData", "iscsi.vendorspecificdata",
1891 FT_BYTES, BASE_HEX, NULL, 0,
1892 "Vendor Specific Data", HFILL }
1894 { &hf_iscsi_HeaderDigest32,
1895 { "HeaderDigest", "iscsi.headerdigest32",
1896 FT_UINT32, BASE_HEX, NULL, 0,
1897 "Header Digest", HFILL }
1899 { &hf_iscsi_DataDigest,
1900 { "DataDigest", "iscsi.datadigest",
1901 FT_BYTES, BASE_HEX, NULL, 0,
1902 "Data Digest", HFILL }
1904 { &hf_iscsi_DataDigest32,
1905 { "DataDigest", "iscsi.datadigest32",
1906 FT_UINT32, BASE_HEX, NULL, 0,
1907 "Data Digest", HFILL }
1910 { "Opcode", "iscsi.opcode",
1911 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
1914 /* #ifdef DRAFT08 */
1917 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1918 "Command Retry", HFILL }
1923 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
1924 "Immediate delivery", HFILL }
1927 { "Flags", "iscsi.flags",
1928 FT_UINT8, BASE_HEX, NULL, 0,
1929 "Opcode specific flags", HFILL }
1931 { &hf_iscsi_SCSICommand_F,
1932 { "F", "iscsi.scsicommand.F",
1933 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1934 "PDU completes command", HFILL }
1936 { &hf_iscsi_SCSICommand_R,
1937 { "R", "iscsi.scsicommand.R",
1938 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
1939 "Command reads from SCSI target", HFILL }
1941 { &hf_iscsi_SCSICommand_W,
1942 { "W", "iscsi.scsicommand.W",
1943 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
1944 "Command writes to SCSI target", HFILL }
1946 { &hf_iscsi_SCSICommand_Attr,
1947 { "Attr", "iscsi.scsicommand.attr",
1948 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
1949 "SCSI task attributes", HFILL }
1951 { &hf_iscsi_SCSICommand_CRN,
1952 { "CRN", "iscsi.scsicommand.crn",
1953 FT_UINT8, BASE_HEX, NULL, 0,
1954 "SCSI command reference number", HFILL }
1956 { &hf_iscsi_SCSICommand_AddCDB,
1957 { "AddCDB", "iscsi.scsicommand.addcdb",
1958 FT_UINT8, BASE_HEX, NULL, 0,
1959 "Additional CDB length (in 4 byte units)", HFILL }
1961 { &hf_iscsi_DataSegmentLength,
1962 { "DataSegmentLength", "iscsi.datasegmentlength",
1963 FT_UINT32, BASE_HEX, NULL, 0,
1964 "Data segment length (bytes)", HFILL }
1966 { &hf_iscsi_TotalAHSLength,
1967 { "TotalAHSLength", "iscsi.totalahslength",
1968 FT_UINT8, BASE_HEX, NULL, 0,
1969 "Total additional header segment length (4 byte words)", HFILL }
1972 { "LUN", "iscsi.lun",
1973 FT_BYTES, BASE_HEX, NULL, 0,
1974 "Logical Unit Number", HFILL }
1976 { &hf_iscsi_InitiatorTaskTag,
1977 { "InitiatorTaskTag", "iscsi.initiatortasktag",
1978 FT_UINT32, BASE_HEX, NULL, 0,
1979 "Initiator's task tag", HFILL }
1981 { &hf_iscsi_ExpectedDataTransferLength,
1982 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
1983 FT_UINT32, BASE_HEX, NULL, 0,
1984 "Expected length of data transfer", HFILL }
1987 { "CmdSN", "iscsi.cmdsn",
1988 FT_UINT32, BASE_HEX, NULL, 0,
1989 "Sequence number for this command", HFILL }
1991 { &hf_iscsi_ExpStatSN,
1992 { "ExpStatSN", "iscsi.expstatsn",
1993 FT_UINT32, BASE_HEX, NULL, 0,
1994 "Next expected status sequence number", HFILL }
1996 { &hf_iscsi_SCSIResponse_ResidualCount,
1997 { "ResidualCount", "iscsi.scsiresponse.residualcount",
1998 FT_UINT32, BASE_HEX, NULL, 0,
1999 "Residual count", HFILL }
2002 { "StatSN", "iscsi.statsn",
2003 FT_UINT32, BASE_HEX, NULL, 0,
2004 "Status sequence number", HFILL }
2006 { &hf_iscsi_ExpCmdSN,
2007 { "ExpCmdSN", "iscsi.expcmdsn",
2008 FT_UINT32, BASE_HEX, NULL, 0,
2009 "Next expected command sequence number", HFILL }
2011 { &hf_iscsi_MaxCmdSN,
2012 { "MaxCmdSN", "iscsi.maxcmdsn",
2013 FT_UINT32, BASE_HEX, NULL, 0,
2014 "Maximum acceptable command sequence number", HFILL }
2016 { &hf_iscsi_SCSIResponse_o,
2017 { "o", "iscsi.scsiresponse.o",
2018 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
2019 "Bi-directional read residual overflow", HFILL }
2021 { &hf_iscsi_SCSIResponse_u,
2022 { "u", "iscsi.scsiresponse.u",
2023 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
2024 "Bi-directional read residual underflow", HFILL }
2026 { &hf_iscsi_SCSIResponse_O,
2027 { "O", "iscsi.scsiresponse.O",
2028 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
2029 "Residual overflow", HFILL }
2031 { &hf_iscsi_SCSIResponse_U,
2032 { "U", "iscsi.scsiresponse.U",
2033 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
2034 "Residual underflow", HFILL }
2036 { &hf_iscsi_SCSIResponse_Status,
2037 { "Status", "iscsi.scsiresponse.status",
2038 FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
2039 "SCSI command status value", HFILL }
2041 { &hf_iscsi_SCSIResponse_Response,
2042 { "Response", "iscsi.scsiresponse.response",
2043 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
2044 "SCSI command response value", HFILL }
2046 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
2047 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
2048 FT_UINT32, BASE_HEX, NULL, 0,
2049 "Bi-directional read residual count", HFILL }
2051 { &hf_iscsi_SenseLength,
2052 { "SenseLength", "iscsi.scsiresponse.senselength",
2053 FT_UINT16, BASE_HEX, NULL, 0,
2054 "Sense data length", HFILL }
2056 { &hf_iscsi_SCSIData_F,
2057 { "F", "iscsi.scsidata.F",
2058 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
2059 "Final PDU", HFILL }
2061 { &hf_iscsi_SCSIData_A,
2062 { "A", "iscsi.scsidata.A",
2063 FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
2064 "Acknowledge Requested", HFILL }
2066 { &hf_iscsi_SCSIData_S,
2067 { "S", "iscsi.scsidata.S",
2068 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
2069 "PDU Contains SCSI command status", HFILL }
2071 { &hf_iscsi_SCSIData_U,
2072 { "U", "iscsi.scsidata.U",
2073 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
2074 "Residual underflow", HFILL }
2076 { &hf_iscsi_SCSIData_O,
2077 { "O", "iscsi.scsidata.O",
2078 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
2079 "Residual overflow", HFILL }
2081 { &hf_iscsi_TargetTransferTag,
2082 { "TargetTransferTag", "iscsi.targettransfertag",
2083 FT_UINT32, BASE_HEX, NULL, 0,
2084 "Target transfer tag", HFILL }
2086 { &hf_iscsi_BufferOffset,
2087 { "BufferOffset", "iscsi.bufferOffset",
2088 FT_UINT32, BASE_HEX, NULL, 0,
2089 "Buffer offset", HFILL }
2091 { &hf_iscsi_SCSIData_ResidualCount,
2092 { "ResidualCount", "iscsi.scsidata.readresidualcount",
2093 FT_UINT32, BASE_HEX, NULL, 0,
2094 "Residual count", HFILL }
2097 { "DataSN", "iscsi.datasn",
2098 FT_UINT32, BASE_HEX, NULL, 0,
2099 "Data sequence number", HFILL }
2101 { &hf_iscsi_VersionMax,
2102 { "VersionMax", "iscsi.versionmax",
2103 FT_UINT8, BASE_HEX, NULL, 0,
2104 "Maximum supported protocol version", HFILL }
2106 { &hf_iscsi_VersionMin,
2107 { "VersionMin", "iscsi.versionmin",
2108 FT_UINT8, BASE_HEX, NULL, 0,
2109 "Minimum supported protocol version", HFILL }
2111 { &hf_iscsi_VersionActive,
2112 { "VersionActive", "iscsi.versionactive",
2113 FT_UINT8, BASE_HEX, NULL, 0,
2114 "Negotiated protocol version", HFILL }
2117 { "CID", "iscsi.cid",
2118 FT_UINT16, BASE_HEX, NULL, 0,
2119 "Connection identifier", HFILL }
2121 /* #ifdef DRAFT08 */
2123 { "ISID", "iscsi.isid",
2124 FT_UINT16, BASE_HEX, NULL, 0,
2125 "Initiator part of session identifier", HFILL }
2129 { "ISID", "iscsi.isid",
2130 FT_BYTES, BASE_HEX, NULL, 0,
2131 "Initiator part of session identifier", HFILL }
2133 /* #ifdef DRAFT09 */
2134 { &hf_iscsi_ISID_Type,
2135 { "ISID_Type", "iscsi.isid.type",
2136 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
2137 "Initiator part of session identifier - type", HFILL }
2139 { &hf_iscsi_ISID_NamingAuthority,
2140 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
2141 FT_UINT24, BASE_HEX, NULL, 0,
2142 "Initiator part of session identifier - naming authority", HFILL }
2144 { &hf_iscsi_ISID_Qualifier,
2145 { "ISID_Qualifier", "iscsi.isid.qualifier",
2146 FT_UINT8, BASE_HEX, NULL, 0,
2147 "Initiator part of session identifier - qualifier", HFILL }
2151 { "ISID_t", "iscsi.isid.t",
2152 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
2153 "Initiator part of session identifier - t", HFILL }
2156 { "ISID_a", "iscsi.isid.a",
2157 FT_UINT8, BASE_HEX, NULL, 0x3f,
2158 "Initiator part of session identifier - a", HFILL }
2161 { "ISID_b", "iscsi.isid.b",
2162 FT_UINT16, BASE_HEX, NULL, 0,
2163 "Initiator part of session identifier - b", HFILL }
2166 { "ISID_c", "iscsi.isid.c",
2167 FT_UINT8, BASE_HEX, NULL, 0,
2168 "Initiator part of session identifier - c", HFILL }
2171 { "ISID_d", "iscsi.isid.d",
2172 FT_UINT16, BASE_HEX, NULL, 0,
2173 "Initiator part of session identifier - d", HFILL }
2178 { "TSID", "iscsi.tsid",
2179 FT_UINT16, BASE_HEX, NULL, 0,
2180 "Target part of session identifier", HFILL }
2183 { "TSIH", "iscsi.tsih",
2184 FT_UINT16, BASE_HEX, NULL, 0,
2185 "Target session identifying handle", HFILL }
2187 { &hf_iscsi_InitStatSN,
2188 { "InitStatSN", "iscsi.initstatsn",
2189 FT_UINT32, BASE_HEX, NULL, 0,
2190 "Initial status sequence number", HFILL }
2192 { &hf_iscsi_InitCmdSN,
2193 { "InitCmdSN", "iscsi.initcmdsn",
2194 FT_UINT32, BASE_HEX, NULL, 0,
2195 "Initial command sequence number", HFILL }
2197 { &hf_iscsi_Login_T,
2198 { "T", "iscsi.login.T",
2199 FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
2200 "Transit to next login stage", HFILL }
2202 { &hf_iscsi_Login_C,
2203 { "C", "iscsi.login.C",
2204 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2205 "Text incomplete", HFILL }
2207 /* #ifdef DRAFT09 */
2208 { &hf_iscsi_Login_X,
2209 { "X", "iscsi.login.X",
2210 FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
2211 "Restart Connection", HFILL }
2214 { &hf_iscsi_Login_CSG,
2215 { "CSG", "iscsi.login.csg",
2216 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
2217 "Current stage", HFILL }
2219 { &hf_iscsi_Login_NSG,
2220 { "NSG", "iscsi.login.nsg",
2221 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
2222 "Next stage", HFILL }
2224 { &hf_iscsi_Login_Status,
2225 { "Status", "iscsi.login.status",
2226 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
2227 "Status class and detail", HFILL }
2229 { &hf_iscsi_KeyValue,
2230 { "KeyValue", "iscsi.keyvalue",
2231 FT_STRING, 0, NULL, 0,
2232 "Key/value pair", HFILL }
2235 { "F", "iscsi.text.F",
2236 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2237 "Final PDU in text sequence", HFILL }
2240 { "C", "iscsi.text.C",
2241 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2242 "Text incomplete", HFILL }
2244 { &hf_iscsi_ExpDataSN,
2245 { "ExpDataSN", "iscsi.expdatasn",
2246 FT_UINT32, BASE_HEX, NULL, 0,
2247 "Next expected data sequence number", HFILL }
2250 { "R2TSN", "iscsi.r2tsn",
2251 FT_UINT32, BASE_HEX, NULL, 0,
2252 "R2T PDU Number", HFILL }
2254 { &hf_iscsi_TaskManagementFunction_Response,
2255 { "Response", "iscsi.taskmanfun.response",
2256 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
2259 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
2260 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
2261 FT_UINT32, BASE_HEX, NULL, 0,
2262 "Referenced task tag", HFILL }
2264 { &hf_iscsi_RefCmdSN,
2265 { "RefCmdSN", "iscsi.refcmdsn",
2266 FT_UINT32, BASE_HEX, NULL, 0,
2267 "Command sequence number for command to be aborted", HFILL }
2269 { &hf_iscsi_TaskManagementFunction_Function,
2270 { "Function", "iscsi.taskmanfun.function",
2271 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
2272 "Requested task function", HFILL }
2274 { &hf_iscsi_Logout_Reason,
2275 { "Reason", "iscsi.logout.reason",
2276 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0x7F,
2277 "Reason for logout", HFILL }
2279 { &hf_iscsi_Logout_Response,
2280 { "Response", "iscsi.logout.response",
2281 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
2282 "Logout response", HFILL }
2284 { &hf_iscsi_Time2Wait,
2285 { "Time2Wait", "iscsi.time2wait",
2286 FT_UINT16, BASE_HEX, NULL, 0,
2287 "Time2Wait", HFILL }
2289 { &hf_iscsi_Time2Retain,
2290 { "Time2Retain", "iscsi.time2retain",
2291 FT_UINT16, BASE_HEX, NULL, 0,
2292 "Time2Retain", HFILL }
2294 { &hf_iscsi_DesiredDataLength,
2295 { "DesiredDataLength", "iscsi.desireddatalength",
2296 FT_UINT32, BASE_HEX, NULL, 0,
2297 "Desired data length (bytes)", HFILL }
2299 { &hf_iscsi_AsyncEvent,
2300 { "AsyncEvent", "iscsi.asyncevent",
2301 FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2302 "Async event type", HFILL }
2304 { &hf_iscsi_EventVendorCode,
2305 { "EventVendorCode", "iscsi.eventvendorcode",
2306 FT_UINT8, BASE_HEX, NULL, 0,
2307 "Event vendor code", HFILL }
2309 { &hf_iscsi_Parameter1,
2310 { "Parameter1", "iscsi.parameter1",
2311 FT_UINT16, BASE_HEX, NULL, 0,
2312 "Parameter 1", HFILL }
2314 { &hf_iscsi_Parameter2,
2315 { "Parameter2", "iscsi.parameter2",
2316 FT_UINT16, BASE_HEX, NULL, 0,
2317 "Parameter 2", HFILL }
2319 { &hf_iscsi_Parameter3,
2320 { "Parameter3", "iscsi.parameter3",
2321 FT_UINT16, BASE_HEX, NULL, 0,
2322 "Parameter 3", HFILL }
2324 { &hf_iscsi_Reject_Reason,
2325 { "Reason", "iscsi.reject.reason",
2326 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2327 "Reason for command rejection", HFILL }
2329 { &hf_iscsi_snack_type,
2330 { "S", "iscsi.snack.type",
2331 FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2332 "Type of SNACK requested", HFILL }
2335 { "BegRun", "iscsi.snack.begrun",
2336 FT_UINT32, BASE_HEX, NULL, 0,
2337 "First missed DataSN or StatSN", HFILL }
2339 { &hf_iscsi_RunLength,
2340 { "RunLength", "iscsi.snack.runlength",
2341 FT_UINT32, BASE_HEX, NULL, 0,
2342 "Number of additional missing status PDUs in this run", HFILL }
2346 /* Setup protocol subtree array */
2347 static gint *ett[] = {
2349 &ett_iscsi_KeyValues,
2352 /* #ifndef DRAFT08 */
2357 /* Register the protocol name and description */
2358 proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2360 /* Required function calls to register the header fields and
2362 proto_register_field_array(proto_iscsi, hf, array_length(hf));
2363 proto_register_subtree_array(ett, array_length(ett));
2366 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2368 prefs_register_enum_preference(iscsi_module,
2371 "The iSCSI protocol version",
2372 &iscsi_protocol_version,
2373 iscsi_protocol_versions,
2376 prefs_register_bool_preference(iscsi_module,
2377 "desegment_iscsi_messages",
2378 "Reassemble iSCSI messages\nspanning multiple TCP segments",
2379 "Whether the iSCSI dissector should reassemble messages spanning multiple TCP segments."
2380 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2383 prefs_register_bool_preference(iscsi_module,
2385 "Enable bogus pdu filter",
2386 "When enabled, packets that appear bogus are ignored",
2387 &enable_bogosity_filter);
2389 prefs_register_bool_preference(iscsi_module,
2390 "demand_good_f_bit",
2391 "Ignore packets with bad F bit",
2392 "Ignore packets that haven't set the F bit when they should have",
2393 &demand_good_f_bit);
2395 prefs_register_uint_preference(iscsi_module,
2396 "bogus_pdu_max_data_len",
2397 "Bogus pdu max data length threshold",
2398 "Treat packets whose data segment length is greater than this value as bogus",
2400 &bogus_pdu_data_length_threshold);
2403 prefs_register_uint_preference(iscsi_module,
2406 "Port number of iSCSI target",
2410 prefs_register_bool_preference(iscsi_module,
2411 "enable_data_digests",
2412 "Enable data digests",
2413 "When enabled, pdus are assumed to contain a data digest",
2414 &enableDataDigests);
2416 prefs_register_bool_preference(iscsi_module,
2417 "data_digest_is_crc32c",
2418 "Data digest is CRC32C",
2419 "When enabled, data digests are assumed to be CRC32C",
2420 &dataDigestIsCRC32);
2422 prefs_register_uint_preference(iscsi_module,
2425 "The size of a data digest (bytes)",
2429 /* Preference supported in older versions.
2430 Register them as obsolete. */
2431 prefs_register_obsolete_preference(iscsi_module,
2432 "version_03_compatible");
2433 prefs_register_obsolete_preference(iscsi_module,
2434 "bogus_pdu_max_digest_padding");
2435 prefs_register_obsolete_preference(iscsi_module,
2436 "header_digest_is_crc32c");
2437 prefs_register_obsolete_preference(iscsi_module,
2438 "header_digest_size");
2439 prefs_register_obsolete_preference(iscsi_module,
2440 "enable_header_digests");
2446 * If this dissector uses sub-dissector registration add a
2447 * registration routine.
2451 * This format is required because a script is used to find these
2452 * routines and create the code that calls these routines.
2455 proto_reg_handoff_iscsi(void)
2457 heur_dissector_add("tcp", dissect_iscsi_heur, proto_iscsi);
2459 iscsi_handle = create_dissector_handle(dissect_iscsi_handle, proto_iscsi);
2460 dissector_add_handle("tcp.port", iscsi_handle);