2 * Routines for iSCSI dissection
3 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
4 * 2004 Request/Response matching and Service Response Time: ronnie sahlberg
6 * $Id: packet-iscsi.c,v 1.49 2004/02/18 09:10:02 sahlberg Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/packet.h>
39 #include <epan/conversation.h>
40 #include "packet-scsi.h"
41 #include "epan/nstime.h"
43 /* the absolute values of these constants don't matter as long as
44 * latter revisions of the protocol are assigned a larger number */
45 #define ISCSI_PROTOCOL_DRAFT08 1
46 #define ISCSI_PROTOCOL_DRAFT09 2
47 #define ISCSI_PROTOCOL_DRAFT11 3
48 #define ISCSI_PROTOCOL_DRAFT12 4
49 #define ISCSI_PROTOCOL_DRAFT13 5
51 static enum_val_t iscsi_protocol_versions[] = {
52 { "Draft 08", ISCSI_PROTOCOL_DRAFT08 },
53 { "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
54 { "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
55 { "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
56 { "Draft 13", ISCSI_PROTOCOL_DRAFT13 },
60 static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT13;
62 static gboolean iscsi_desegment = TRUE;
64 static int demand_good_f_bit = FALSE;
65 static int enable_bogosity_filter = TRUE;
66 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
68 static int enableDataDigests = FALSE;
69 static int enableHeaderDigests = FALSE;
71 static int dataDigestIsCRC32 = TRUE;
72 static int headerDigestIsCRC32 = TRUE;
74 static int dataDigestSize = 4;
75 static int headerDigestSize = 4;
77 static guint iscsi_port = 3260;
79 /* Initialize the protocol and registered fields */
80 static int proto_iscsi = -1;
81 static int hf_iscsi_time = -1;
82 static int hf_iscsi_request_frame = -1;
83 static int hf_iscsi_data_in_frame = -1;
84 static int hf_iscsi_data_out_frame = -1;
85 static int hf_iscsi_response_frame = -1;
86 static int hf_iscsi_AHS = -1;
87 static int hf_iscsi_Padding = -1;
88 static int hf_iscsi_ping_data = -1;
89 static int hf_iscsi_immediate_data = -1;
90 static int hf_iscsi_write_data = -1;
91 static int hf_iscsi_read_data = -1;
92 static int hf_iscsi_error_pdu_data = -1;
93 static int hf_iscsi_async_message_data = -1;
94 static int hf_iscsi_vendor_specific_data = -1;
95 static int hf_iscsi_Opcode = -1;
96 static int hf_iscsi_Flags = -1;
97 static int hf_iscsi_HeaderDigest = -1;
98 static int hf_iscsi_HeaderDigest32 = -1;
99 static int hf_iscsi_DataDigest = -1;
100 static int hf_iscsi_DataDigest32 = -1;
102 static int hf_iscsi_X = -1;
104 static int hf_iscsi_I = -1;
105 static int hf_iscsi_SCSICommand_F = -1;
106 static int hf_iscsi_SCSICommand_R = -1;
107 static int hf_iscsi_SCSICommand_W = -1;
108 static int hf_iscsi_SCSICommand_Attr = -1;
109 static int hf_iscsi_SCSICommand_CRN = -1;
110 static int hf_iscsi_SCSICommand_AddCDB = -1;
111 static int hf_iscsi_DataSegmentLength = -1;
112 static int hf_iscsi_TotalAHSLength = -1;
113 static int hf_iscsi_LUN = -1;
114 static int hf_iscsi_InitiatorTaskTag = -1;
115 static int hf_iscsi_ExpectedDataTransferLength = -1;
116 static int hf_iscsi_CmdSN = -1;
117 static int hf_iscsi_ExpStatSN = -1;
118 static int hf_iscsi_StatSN = -1;
119 static int hf_iscsi_ExpCmdSN = -1;
120 static int hf_iscsi_MaxCmdSN = -1;
121 static int hf_iscsi_SCSIResponse_o = -1;
122 static int hf_iscsi_SCSIResponse_u = -1;
123 static int hf_iscsi_SCSIResponse_O = -1;
124 static int hf_iscsi_SCSIResponse_U = -1;
125 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
126 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
127 static int hf_iscsi_SCSIResponse_Response = -1;
128 static int hf_iscsi_SCSIResponse_Status = -1;
129 static int hf_iscsi_SenseLength = -1;
130 static int hf_iscsi_SCSIData_F = -1;
131 static int hf_iscsi_SCSIData_A = -1;
132 static int hf_iscsi_SCSIData_S = -1;
133 static int hf_iscsi_SCSIData_O = -1;
134 static int hf_iscsi_SCSIData_U = -1;
135 static int hf_iscsi_TargetTransferTag = -1;
136 static int hf_iscsi_DataSN = -1;
137 static int hf_iscsi_BufferOffset = -1;
138 static int hf_iscsi_SCSIData_ResidualCount = -1;
139 static int hf_iscsi_VersionMin = -1;
140 static int hf_iscsi_VersionMax = -1;
141 static int hf_iscsi_VersionActive = -1;
142 static int hf_iscsi_CID = -1;
143 static int hf_iscsi_ISID8 = -1;
144 static int hf_iscsi_ISID = -1;
145 /* #if defined(DRAFT09) */
146 static int hf_iscsi_ISID_Type = -1;
147 static int hf_iscsi_ISID_NamingAuthority = -1;
148 static int hf_iscsi_ISID_Qualifier = -1;
149 /* #elif !defined(DRAFT08) */
150 static int hf_iscsi_ISID_t = -1;
151 static int hf_iscsi_ISID_a = -1;
152 static int hf_iscsi_ISID_b = -1;
153 static int hf_iscsi_ISID_c = -1;
154 static int hf_iscsi_ISID_d = -1;
156 static int hf_iscsi_TSID = -1;
157 static int hf_iscsi_TSIH = -1;
158 static int hf_iscsi_InitStatSN = -1;
159 static int hf_iscsi_InitCmdSN = -1;
161 static int hf_iscsi_Login_X = -1;
163 static int hf_iscsi_Login_C = -1;
164 static int hf_iscsi_Login_T = -1;
165 static int hf_iscsi_Login_CSG = -1;
166 static int hf_iscsi_Login_NSG = -1;
167 static int hf_iscsi_Login_Status = -1;
168 static int hf_iscsi_KeyValue = -1;
169 static int hf_iscsi_Text_C = -1;
170 static int hf_iscsi_Text_F = -1;
171 static int hf_iscsi_ExpDataSN = -1;
172 static int hf_iscsi_R2TSN = -1;
173 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
174 static int hf_iscsi_RefCmdSN = -1;
175 static int hf_iscsi_TaskManagementFunction_Function = -1;
176 static int hf_iscsi_TaskManagementFunction_Response = -1;
177 static int hf_iscsi_Logout_Reason = -1;
178 static int hf_iscsi_Logout_Response = -1;
179 static int hf_iscsi_Time2Wait = -1;
180 static int hf_iscsi_Time2Retain = -1;
181 static int hf_iscsi_DesiredDataLength = -1;
182 static int hf_iscsi_AsyncEvent = -1;
183 static int hf_iscsi_EventVendorCode = -1;
184 static int hf_iscsi_Parameter1 = -1;
185 static int hf_iscsi_Parameter2 = -1;
186 static int hf_iscsi_Parameter3 = -1;
187 static int hf_iscsi_Reject_Reason = -1;
188 static int hf_iscsi_snack_type = -1;
189 static int hf_iscsi_BegRun = -1;
190 static int hf_iscsi_RunLength = -1;
192 /* Initialize the subtree pointers */
193 static gint ett_iscsi = -1;
194 static gint ett_iscsi_KeyValues = -1;
195 static gint ett_iscsi_CDB = -1;
196 static gint ett_iscsi_Flags = -1;
197 /* #ifndef DRAFT08 */
198 static gint ett_iscsi_ISID = -1;
208 #define OPCODE_MASK 0x3f
210 #define TARGET_OPCODE_BIT 0x20
212 #define ISCSI_OPCODE_NOP_OUT 0x00
213 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
214 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
215 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
216 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
217 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
218 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
219 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
220 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
221 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
222 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
224 #define ISCSI_OPCODE_NOP_IN 0x20
225 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
226 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
227 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
228 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
229 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
230 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
231 #define ISCSI_OPCODE_R2T 0x31
232 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
233 #define ISCSI_OPCODE_REJECT 0x3f
234 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
235 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
236 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
239 #define CSG_MASK (0x03 << CSG_SHIFT)
240 #define NSG_MASK 0x03
242 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
243 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
244 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
246 #define ISCSI_SCSI_DATA_FLAG_S 0x01
247 #define ISCSI_SCSI_DATA_FLAG_U 0x02
248 #define ISCSI_SCSI_DATA_FLAG_O 0x04
249 #define ISCSI_SCSI_DATA_FLAG_A 0x40
250 #define ISCSI_SCSI_DATA_FLAG_F 0x80
252 static const value_string iscsi_opcodes[] = {
253 { ISCSI_OPCODE_NOP_OUT, "NOP Out" },
254 { ISCSI_OPCODE_SCSI_COMMAND, "SCSI Command" },
255 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION, "Task Management Function" },
256 { ISCSI_OPCODE_LOGIN_COMMAND, "Login Command" },
257 { ISCSI_OPCODE_TEXT_COMMAND, "Text Command" },
258 { ISCSI_OPCODE_SCSI_DATA_OUT, "SCSI Data Out" },
259 { ISCSI_OPCODE_LOGOUT_COMMAND, "Logout Command" },
260 { ISCSI_OPCODE_SNACK_REQUEST, "SNACK Request" },
261 { ISCSI_OPCODE_VENDOR_SPECIFIC_I0, "Vendor Specific I0" },
262 { ISCSI_OPCODE_VENDOR_SPECIFIC_I1, "Vendor Specific I1" },
263 { ISCSI_OPCODE_VENDOR_SPECIFIC_I2, "Vendor Specific I2" },
265 { ISCSI_OPCODE_NOP_IN, "NOP In" },
266 { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
267 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
268 { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
269 { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
270 { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
271 { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
272 { ISCSI_OPCODE_R2T, "Ready To Transfer" },
273 { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
274 { ISCSI_OPCODE_REJECT, "Reject"},
275 { ISCSI_OPCODE_VENDOR_SPECIFIC_T0, "Vendor Specific T0" },
276 { ISCSI_OPCODE_VENDOR_SPECIFIC_T1, "Vendor Specific T1" },
277 { ISCSI_OPCODE_VENDOR_SPECIFIC_T2, "Vendor Specific T2" },
282 static const true_false_string iscsi_meaning_X = {
289 static const true_false_string iscsi_meaning_login_X = {
290 "Reinstate failed connection",
295 static const true_false_string iscsi_meaning_I = {
296 "Immediate delivery",
300 static const true_false_string iscsi_meaning_F = {
301 "Final PDU in sequence",
302 "Not final PDU in sequence"
305 static const true_false_string iscsi_meaning_A = {
306 "Acknowledge requested",
307 "Acknowledge not requested"
310 static const true_false_string iscsi_meaning_T = {
311 "Transit to next login stage",
312 "Stay in current login stage"
315 static const true_false_string iscsi_meaning_C = {
316 "Text is incomplete",
320 static const true_false_string iscsi_meaning_S = {
321 "Response contains SCSI status",
322 "Response does not contain SCSI status"
325 static const true_false_string iscsi_meaning_R = {
326 "Data will be read from target",
327 "No data will be read from target"
330 static const true_false_string iscsi_meaning_W = {
331 "Data will be written to target",
332 "No data will be written to target"
335 static const true_false_string iscsi_meaning_o = {
336 "Read part of bi-directional command overflowed",
337 "No overflow of read part of bi-directional command",
340 static const true_false_string iscsi_meaning_u = {
341 "Read part of bi-directional command underflowed",
342 "No underflow of read part of bi-directional command",
345 static const true_false_string iscsi_meaning_O = {
346 "Residual overflow occurred",
347 "No residual overflow occurred",
350 static const true_false_string iscsi_meaning_U = {
351 "Residual underflow occurred",
352 "No residual underflow occurred",
355 static const value_string iscsi_scsi_responses[] = {
356 { 0, "Command completed at target" },
357 { 1, "Response does not contain SCSI status"},
361 static const value_string iscsi_scsicommand_taskattrs[] = {
365 {3, "Head of Queue"},
370 static const value_string iscsi_task_management_responses[] = {
371 {0, "Function complete"},
372 {1, "Task not in task set"},
373 {2, "LUN does not exist"},
374 {3, "Task still allegiant"},
375 {4, "Task failover not supported"},
376 {5, "Task management function not supported"},
377 {6, "Authorisation failed"},
378 {255, "Function rejected"},
382 static const value_string iscsi_task_management_functions[] = {
384 {2, "Abort Task Set"},
386 {4, "Clear Task Set"},
387 {5, "Logical Unit Reset"},
388 {6, "Target Warm Reset"},
389 {7, "Target Cold Reset"},
393 static const value_string iscsi_login_status[] = {
395 {0x0101, "Target moved temporarily"},
396 {0x0102, "Target moved permanently"},
397 {0x0200, "Initiator error (miscellaneous error)"},
398 {0x0201, "Authentication failed"},
399 {0x0202, "Authorisation failure"},
400 {0x0203, "Target not found"},
401 {0x0204, "Target removed"},
402 {0x0205, "Unsupported version"},
403 {0x0206, "Too many connections"},
404 {0x0207, "Missing parameter"},
405 {0x0208, "Can't include in session"},
406 {0x0209, "Session type not supported"},
407 {0x020a, "Session does not exist"},
408 {0x020b, "Invalid request during login"},
409 {0x0300, "Target error (miscellaneous error)"},
410 {0x0301, "Service unavailable"},
411 {0x0302, "Out of resources"},
415 static const value_string iscsi_login_stage[] = {
416 {0, "Security negotiation"},
417 {1, "Operational negotiation"},
418 {3, "Full feature phase"},
422 /* #ifndef DRAFT08 */
423 static const value_string iscsi_isid_type[] = {
425 {0x01, "IANA Enterprise Number"},
431 static const value_string iscsi_logout_reasons[] = {
432 {0, "Close session"},
433 {1, "Close connection"},
434 {2, "Remove connection for recovery"},
438 static const value_string iscsi_logout_response[] = {
439 {0, "Connection closed successfully"},
440 {1, "CID not found"},
441 {2, "Connection recovery not supported"},
442 {3, "Cleanup failed for various reasons"},
446 static const value_string iscsi_asyncevents[] = {
447 {0, "A SCSI asynchronous event is reported in the sense data"},
448 {1, "Target requests logout"},
449 {2, "Target will/has dropped connection"},
450 {3, "Target will/has dropped all connections"},
451 {4, "Target requests parameter negotiation"},
455 static const value_string iscsi_snack_types[] = {
458 /* #ifndef DRAFT08 */
465 static const value_string iscsi_reject_reasons[] = {
467 {0x01, "Full feature phase command before login"},
469 {0x02, "Data (payload) digest error"},
470 {0x03, "Data SNACK reject"},
471 {0x04, "Protocol error"},
472 {0x05, "Command not supported in this session type"},
473 {0x06, "Immediate command reject (too many immediate commands)"},
474 {0x07, "Task in progress"},
475 {0x08, "Invalid Data Ack"},
476 {0x09, "Invalid PDU field"},
477 {0x0a, "Long operation reject"},
478 {0x0b, "Negotiation reset"},
479 {0x0c, "Waiting for logout"},
483 /*****************************************************************/
485 /* CRC LOOKUP TABLE */
486 /* ================ */
487 /* The following CRC lookup table was generated automagically */
488 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
489 /* Program V1.0 using the following model parameters: */
491 /* Width : 4 bytes. */
492 /* Poly : 0x1EDC6F41L */
493 /* Reverse : TRUE. */
495 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
496 /* see the document titled "A Painless Guide to CRC Error */
497 /* Detection Algorithms" by Ross Williams */
498 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
499 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
501 /*****************************************************************/
503 static guint32 crc32Table[256] = {
504 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
505 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
506 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
507 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
508 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
509 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
510 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
511 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
512 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
513 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
514 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
515 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
516 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
517 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
518 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
519 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
520 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
521 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
522 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
523 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
524 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
525 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
526 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
527 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
528 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
529 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
530 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
531 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
532 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
533 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
534 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
535 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
536 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
537 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
538 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
539 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
540 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
541 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
542 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
543 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
544 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
545 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
546 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
547 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
548 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
549 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
550 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
551 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
552 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
553 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
554 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
555 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
556 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
557 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
558 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
559 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
560 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
561 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
562 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
563 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
564 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
565 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
566 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
567 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
570 #define CRC32C_PRELOAD 0xffffffff
573 * Byte swap fix contributed by Dave Wysochanski <davidw@netapp.com>
575 #define CRC32C_SWAP(crc32c_value) \
576 (((crc32c_value & 0xff000000) >> 24) | \
577 ((crc32c_value & 0x00ff0000) >> 8) | \
578 ((crc32c_value & 0x0000ff00) << 8) | \
579 ((crc32c_value & 0x000000ff) << 24))
582 calculateCRC32(const void *buf, int len, guint32 crc) {
583 const guint8 *p = (const guint8 *)buf;
584 crc = CRC32C_SWAP(crc);
586 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
587 return CRC32C_SWAP(crc);
594 /* structure and functions to keep track of
595 * COMMAND/DATA_IN/DATA_OUT/RESPONSE matching
597 typedef struct _iscsi_conv_data {
600 guint32 request_frame;
601 guint32 data_in_frame;
602 guint32 data_out_frame;
603 guint32 response_frame;
607 static GHashTable *iscsi_req_unmatched = NULL;
608 static GHashTable *iscsi_req_matched = NULL;
609 static GMemChunk *iscsi_req_vals = NULL;
610 static guint32 iscsi_init_count = 200;
613 iscsi_equal_unmatched(gconstpointer v, gconstpointer w)
615 const iscsi_conv_data_t *v1 = (const iscsi_conv_data_t *)v;
616 const iscsi_conv_data_t *v2 = (const iscsi_conv_data_t *)w;
618 return (v1->conv_idx == v2->conv_idx)&&(v1->itt == v2->itt);
622 iscsi_hash_unmatched (gconstpointer v)
624 const iscsi_conv_data_t *key = (const iscsi_conv_data_t *)v;
627 val = key->conv_idx + key->itt;
633 iscsi_equal_matched(gconstpointer v, gconstpointer w)
635 const iscsi_conv_data_t *v1 = (const iscsi_conv_data_t *)v;
636 const iscsi_conv_data_t *v2 = (const iscsi_conv_data_t *)w;
640 if (v1->request_frame && (v1->request_frame==v2->request_frame))
642 if (v1->data_in_frame && (v1->data_in_frame==v2->data_in_frame))
644 if (v1->data_out_frame && (v1->data_out_frame==v2->data_out_frame))
646 if (v1->response_frame && (v1->response_frame==v2->response_frame))
649 return check_frame&&(v1->conv_idx == v2->conv_idx)&&(v1->itt == v2->itt);
653 iscsi_hash_matched (gconstpointer v)
655 const iscsi_conv_data_t *key = (const iscsi_conv_data_t *)v;
658 val = key->conv_idx + key->itt;
669 * Protocol initialization
672 iscsi_init_protocol(void)
675 g_mem_chunk_destroy(iscsi_req_vals);
676 if (iscsi_req_unmatched)
677 g_hash_table_destroy(iscsi_req_unmatched);
678 if (iscsi_req_matched)
679 g_hash_table_destroy(iscsi_req_matched);
681 iscsi_req_unmatched = g_hash_table_new(iscsi_hash_unmatched, iscsi_equal_unmatched);
682 iscsi_req_matched = g_hash_table_new(iscsi_hash_matched, iscsi_equal_matched);
683 iscsi_req_vals = g_mem_chunk_new("iscsi_req_vals",
684 sizeof(iscsi_conv_data_t),
685 iscsi_init_count * sizeof(iscsi_conv_data_t),
690 iscsi_min(int a, int b) {
691 return (a < b)? a : b;
695 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
696 const gint limit = offset + text_len;
697 while(offset < limit) {
698 gint len = tvb_strnlen(tvb, offset, limit - offset);
700 len = limit - offset;
703 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
710 handleHeaderDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
711 int available_bytes = tvb_length_remaining(tvb, offset);
712 if(enableHeaderDigests) {
713 if(headerDigestIsCRC32) {
714 if(available_bytes >= (headerLen + 4)) {
715 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
716 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
718 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
721 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);
724 return offset + headerLen + 4;
726 if(available_bytes >= (headerLen + headerDigestSize)) {
727 proto_tree_add_item(ti, hf_iscsi_HeaderDigest, tvb, offset + headerLen, headerDigestSize, FALSE);
729 return offset + headerLen + headerDigestSize;
731 return offset + headerLen;
735 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
736 int available_bytes = tvb_length_remaining(tvb, offset);
737 if(enableDataDigests) {
738 if(dataDigestIsCRC32) {
739 if(available_bytes >= (dataLen + 4)) {
740 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
741 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
743 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
746 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);
749 return offset + dataLen + 4;
751 if(available_bytes >= (dataLen + dataDigestSize)) {
752 proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
754 return offset + dataLen + dataDigestSize;
756 return offset + dataLen;
760 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
761 if(endOffset > offset) {
762 int dataOffset = offset;
763 int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
765 proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
768 if(offset < endOffset && (offset & 3) != 0) {
769 int padding = 4 - (offset & 3);
770 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
773 if(dataSegmentLen > 0 && offset < endOffset)
774 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
781 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
782 if(endOffset > offset) {
783 int dataOffset = offset;
784 int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
786 proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
787 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
788 offset = addTextKeys(tt, tvb, offset, textLen);
790 if(offset < endOffset && (offset & 3) != 0) {
791 int padding = 4 - (offset & 3);
792 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
795 if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
796 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
801 /* Code to actually dissect the packets */
803 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len) {
805 guint original_offset = offset;
806 proto_tree *ti = NULL;
807 guint8 scsi_status = 0;
808 gboolean S_bit=FALSE;
809 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
810 guint end_offset = offset + tvb_length_remaining(tvb, offset);
811 conversation_t *conversation = NULL;
812 iscsi_conv_data_t *cdata = NULL;
813 scsi_task_id_t task_key;
814 int paddedDataSegmentLength = data_segment_len;
815 if(paddedDataSegmentLength & 3)
816 paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
818 /* Make entries in Protocol column and Info column on summary display */
819 if (check_col(pinfo->cinfo, COL_PROTOCOL))
820 col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
822 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
823 opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
824 scsi_status = tvb_get_guint8 (tvb, offset+3);
827 if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
828 (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
829 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
830 conversation = find_conversation (&pinfo->src, &pinfo->dst,
831 pinfo->ptype, pinfo->srcport,
834 if (!pinfo->fd->flags.visited){
835 iscsi_conv_data_t ckey;
836 ckey.conv_idx = conversation->index;
837 ckey.itt = tvb_get_ntohl (tvb, offset+16);
839 /* first time we see this packet. check if we can find the request */
840 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_unmatched, &ckey);
842 if (cdata->data_in_frame+cdata->data_out_frame+cdata->response_frame==0){
843 /* this is the first response to the request, add it to the matched table */
844 g_hash_table_insert (iscsi_req_matched, cdata, cdata);
847 case ISCSI_OPCODE_SCSI_RESPONSE:
848 cdata->response_frame=pinfo->fd->num;
850 case ISCSI_OPCODE_SCSI_DATA_IN:
851 /* a bit ugly but we need to check the S bit here */
852 if(tvb_get_guint8(tvb, offset+1)&ISCSI_SCSI_DATA_FLAG_S){
853 cdata->response_frame=pinfo->fd->num;
855 cdata->data_in_frame=pinfo->fd->num;
857 case ISCSI_OPCODE_SCSI_DATA_OUT:
858 cdata->data_out_frame=pinfo->fd->num;
863 iscsi_conv_data_t ckey;
864 ckey.conv_idx = conversation->index;
865 ckey.itt = tvb_get_ntohl (tvb, offset+16);
866 ckey.request_frame=0;
867 ckey.data_in_frame=0;
868 ckey.data_out_frame=0;
869 ckey.response_frame=0;
871 case ISCSI_OPCODE_SCSI_RESPONSE:
872 ckey.response_frame=pinfo->fd->num;
874 case ISCSI_OPCODE_SCSI_DATA_IN:
875 ckey.data_in_frame=pinfo->fd->num;
877 case ISCSI_OPCODE_SCSI_DATA_OUT:
878 ckey.data_out_frame=pinfo->fd->num;
882 /* we have seen this one before, pick it up from the matched table */
883 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_matched, &ckey);
887 task_key.conv_id = cdata->conv_idx;
888 task_key.task_id = cdata->itt;
889 pinfo->private_data = &task_key;
891 pinfo->private_data = NULL;
894 /* no conversation, meaning we didn't see the request */
895 pinfo->private_data = NULL;
898 } else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
899 conversation = find_conversation (&pinfo->src, &pinfo->dst,
900 pinfo->ptype, pinfo->srcport,
903 conversation = conversation_new (&pinfo->src, &pinfo->dst,
904 pinfo->ptype, pinfo->srcport,
908 if (!pinfo->fd->flags.visited){
909 iscsi_conv_data_t ckey;
911 /* first time we see this packet. */
912 /*check if we have seen this request before and delete it in that case */
913 ckey.conv_idx = conversation->index;
914 ckey.itt = tvb_get_ntohl (tvb, offset+16);
915 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_unmatched, &ckey);
917 g_hash_table_remove(iscsi_req_unmatched, &ckey);
920 /* add this new transaction to the unmatched table */
921 cdata = g_mem_chunk_alloc (iscsi_req_vals);
922 cdata->conv_idx = conversation->index;
923 cdata->itt = tvb_get_ntohl (tvb, offset+16);
924 cdata->request_frame=pinfo->fd->num;
925 cdata->data_in_frame=0;
926 cdata->data_out_frame=0;
927 cdata->response_frame=0;
928 cdata->req_time.nsecs = pinfo->fd->abs_usecs*1000;
929 cdata->req_time.secs = pinfo->fd->abs_secs;
931 g_hash_table_insert (iscsi_req_unmatched, cdata, cdata);
933 iscsi_conv_data_t ckey;
934 ckey.conv_idx = conversation->index;
935 ckey.itt = tvb_get_ntohl (tvb, offset+16);
936 ckey.request_frame=pinfo->fd->num;
937 ckey.data_in_frame=0;
938 ckey.data_out_frame=0;
939 ckey.response_frame=0;
941 /* we have seen this one before, pick it up from the matched table */
942 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_matched, &ckey);
947 /* The SCSI protocol uses this as the key to detect a
948 * SCSI-level conversation. */
949 task_key.conv_id = cdata->conv_idx;
950 task_key.task_id = cdata->itt;
951 pinfo->private_data = &task_key;
953 pinfo->private_data=NULL;
957 pinfo->private_data = NULL;
960 if (check_col(pinfo->cinfo, COL_INFO)) {
962 if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
964 col_append_str(pinfo->cinfo, COL_INFO, opcode_str);
966 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
967 (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
968 (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
969 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
970 val_to_str (scsi_status, scsi_status_val, "0x%x"));
972 else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
973 guint16 login_status = tvb_get_ntohs(tvb, offset+36);
974 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
975 val_to_str (login_status, iscsi_login_status, "0x%x"));
977 else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
979 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
980 logoutReason = tvb_get_guint8(tvb, offset+11);
981 } else if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
982 logoutReason = tvb_get_guint8(tvb, offset+1) & 0x7f;
985 logoutReason = tvb_get_guint8(tvb, offset+23);
987 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
988 val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
990 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
991 guint8 tmf = tvb_get_guint8(tvb, offset + 1);
992 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
993 val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
995 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
996 guint8 resp = tvb_get_guint8(tvb, offset + 2);
997 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
998 val_to_str (resp, iscsi_task_management_responses, "0x%x"));
1000 else if (opcode == ISCSI_OPCODE_REJECT) {
1001 guint8 reason = tvb_get_guint8(tvb, offset + 2);
1002 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
1003 val_to_str (reason, iscsi_reject_reasons, "0x%x"));
1005 else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1006 guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
1007 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
1008 val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
1013 /* In the interest of speed, if "tree" is NULL, don't do any
1014 work not necessary to generate protocol tree items. */
1017 /* create display subtree for the protocol */
1018 tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
1019 offset, -1, "iSCSI (%s)",
1021 ti = proto_item_add_subtree(tp, ett_iscsi);
1023 proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
1024 offset + 0, 1, opcode);
1025 if((opcode & TARGET_OPCODE_BIT) == 0) {
1026 /* initiator -> target */
1027 gint b = tvb_get_guint8(tvb, offset + 0);
1028 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1029 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
1030 opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
1031 opcode != ISCSI_OPCODE_SNACK_REQUEST)
1032 proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
1034 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
1035 opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
1036 opcode != ISCSI_OPCODE_SNACK_REQUEST)
1037 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
1041 if(opcode == ISCSI_OPCODE_NOP_OUT) {
1043 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1044 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);
1047 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1048 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1049 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1050 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1051 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1052 offset = handleHeaderDigest(ti, tvb, offset, 48);
1053 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
1054 } else if(opcode == ISCSI_OPCODE_NOP_IN) {
1056 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1057 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1059 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1060 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1061 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1062 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1063 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1064 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1065 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1066 offset = handleHeaderDigest(ti, tvb, offset, 48);
1067 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
1068 } else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1070 guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
1072 gint b = tvb_get_guint8(tvb, offset + 1);
1073 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1074 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1076 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
1077 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
1078 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
1079 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
1081 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1082 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
1084 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1085 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1086 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1087 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1088 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
1089 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1090 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1093 /* FIXME - disssect AHS? */
1094 proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 48, ahsLen, FALSE);
1096 offset = handleHeaderDigest(ti, tvb, offset, 48 + ahsLen);
1098 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
1099 } else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1102 gint b = tvb_get_guint8(tvb, offset + 1);
1103 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1104 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1106 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
1107 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
1108 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
1109 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
1111 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
1112 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1113 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1114 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1116 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1117 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1118 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1119 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
1121 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1122 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1123 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1124 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1125 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1126 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
1129 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
1130 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
1132 offset = handleHeaderDigest(ti, tvb, offset, 48);
1133 /* do not update offset here because the data segment is
1134 * dissected below */
1135 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1136 } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
1137 /* Task Management Function */
1138 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
1139 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1140 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1141 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1143 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1144 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1145 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1146 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1147 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1148 proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1149 offset = handleHeaderDigest(ti, tvb, offset, 48);
1150 } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1151 /* Task Management Function Response */
1152 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
1153 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1154 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1155 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1157 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1158 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1159 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1161 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1162 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1163 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1164 offset = handleHeaderDigest(ti, tvb, offset, 48);
1165 } else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1167 int digestsActive = 0;
1169 gint b = tvb_get_guint8(tvb, offset + 1);
1170 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1171 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1175 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1176 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1179 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1180 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1181 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1183 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1184 proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1186 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1188 /* NSG is undefined unless T is set */
1190 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1193 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1194 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1195 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1196 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1198 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1199 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1200 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1201 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1204 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1205 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1206 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1207 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1208 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1209 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1212 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1213 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1214 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1215 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1216 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1219 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1220 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1223 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1225 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1226 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1227 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1229 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1230 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1232 offset = handleHeaderDigest(ti, tvb, offset, 48);
1235 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1236 } else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1237 /* Login Response */
1238 int digestsActive = 0;
1240 gint b = tvb_get_guint8(tvb, offset + 1);
1241 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1242 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1246 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1247 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1250 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1251 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1252 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1254 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1255 /* NSG is undefined unless T is set */
1257 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1261 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1262 proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1263 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1264 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1266 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1267 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1268 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1271 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1272 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1273 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1274 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1275 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1276 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1279 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1280 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1281 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1282 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1283 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1286 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1287 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1290 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1292 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1293 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1294 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1295 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1296 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1298 offset = handleHeaderDigest(ti, tvb, offset, 48);
1301 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1302 } else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1305 gint b = tvb_get_guint8(tvb, offset + 1);
1306 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1307 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1309 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1310 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1311 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1314 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1315 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1317 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1318 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1319 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1321 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1322 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1323 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1324 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1325 offset = handleHeaderDigest(ti, tvb, offset, 48);
1326 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1327 } else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1330 gint b = tvb_get_guint8(tvb, offset + 1);
1331 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1332 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1334 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1335 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1336 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1339 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1340 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1342 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1343 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1344 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1346 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1347 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1348 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1349 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1350 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1351 offset = handleHeaderDigest(ti, tvb, offset, 48);
1352 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1353 } else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1354 /* SCSI Data Out (write) */
1356 gint b = tvb_get_guint8(tvb, offset + 1);
1357 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1358 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1360 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1362 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1363 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1365 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1366 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1367 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1368 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1369 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1370 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1371 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1372 offset = handleHeaderDigest(ti, tvb, offset, 48);
1373 /* do not update offset here because the data segment is
1374 * dissected below */
1375 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1376 } else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
1377 /* SCSI Data In (read) */
1379 gint b = tvb_get_guint8(tvb, offset + 1);
1380 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1381 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1383 if(b&ISCSI_SCSI_DATA_FLAG_S){
1386 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1387 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1388 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
1390 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1391 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1392 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1394 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1395 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1396 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1398 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1399 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1400 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1402 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1403 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1404 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1407 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1409 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1410 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1411 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1412 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1413 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1414 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1415 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1417 offset = handleHeaderDigest(ti, tvb, offset, 48);
1418 /* do not update offset here because the data segment is
1419 * dissected below */
1420 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1421 } else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1422 /* Logout Command */
1423 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1424 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 1, 1, FALSE);
1426 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1427 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1428 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1430 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1431 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1432 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1434 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1435 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1436 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1437 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT13) {
1438 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
1441 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1442 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1443 offset = handleHeaderDigest(ti, tvb, offset, 48);
1444 } else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1445 /* Logout Response */
1446 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1447 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1448 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1449 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1451 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1452 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1453 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1454 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1455 proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1456 proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1457 offset = handleHeaderDigest(ti, tvb, offset, 48);
1458 } else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1461 gint b = tvb_get_guint8(tvb, offset + 1);
1463 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1464 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1467 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1469 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1470 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1471 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1472 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1474 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1475 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1476 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1477 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1478 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1479 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1482 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1483 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1484 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1485 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1487 offset = handleHeaderDigest(ti, tvb, offset, 48);
1488 } else if(opcode == ISCSI_OPCODE_R2T) {
1490 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1491 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1492 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1493 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1495 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1496 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1497 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1498 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1499 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1500 proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
1501 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1502 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1503 offset = handleHeaderDigest(ti, tvb, offset, 48);
1504 } else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1505 /* Asynchronous Message */
1506 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1507 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1509 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1510 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1511 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1512 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1513 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1514 proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1515 proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1516 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1517 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1518 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1519 offset = handleHeaderDigest(ti, tvb, offset, 48);
1520 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
1521 } else if(opcode == ISCSI_OPCODE_REJECT) {
1523 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
1524 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1525 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1527 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1528 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1529 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1530 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1531 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1532 offset = handleHeaderDigest(ti, tvb, offset, 48);
1533 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1534 } else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
1535 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
1536 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
1537 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
1538 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
1539 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
1540 /* Vendor specific opcodes */
1541 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1542 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1544 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1545 offset = handleHeaderDigest(ti, tvb, offset, 48);
1546 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
1551 /* handle request/response matching */
1554 case ISCSI_OPCODE_SCSI_RESPONSE:
1555 if (cdata->request_frame){
1556 nstime_t delta_time;
1557 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
1558 delta_time.secs = pinfo->fd->abs_secs - cdata->req_time.secs;
1559 delta_time.nsecs = pinfo->fd->abs_usecs*1000 - cdata->req_time.nsecs;
1560 if (delta_time.nsecs<0){
1561 delta_time.nsecs+=1000000000;
1564 proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1567 if (cdata->data_in_frame)
1568 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1569 if (cdata->data_out_frame)
1570 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1572 case ISCSI_OPCODE_SCSI_DATA_IN:
1573 /* if we have phase collaps then we might have the
1574 response embedded in the last DataIn segment */
1576 if (cdata->request_frame)
1577 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
1578 if (cdata->response_frame)
1579 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
1581 if (cdata->request_frame){
1582 nstime_t delta_time;
1583 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
1584 delta_time.secs = pinfo->fd->abs_secs - cdata->req_time.secs;
1585 delta_time.nsecs = pinfo->fd->abs_usecs*1000 - cdata->req_time.nsecs;
1586 if (delta_time.nsecs<0){
1587 delta_time.nsecs+=1000000000;
1590 proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1594 if (cdata->data_out_frame)
1595 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1597 case ISCSI_OPCODE_SCSI_DATA_OUT:
1598 if (cdata->request_frame)
1599 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
1600 if (cdata->data_in_frame)
1601 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1602 if (cdata->response_frame)
1603 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
1605 case ISCSI_OPCODE_SCSI_COMMAND:
1606 if (cdata->data_in_frame)
1607 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1608 if (cdata->data_out_frame)
1609 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1610 if (cdata->response_frame)
1611 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
1618 proto_item_set_len(ti, offset - original_offset);
1620 if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
1622 ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
1624 dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16, SCSI_DEV_UNKNOWN);
1626 else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1627 if (scsi_status == 0x2) {
1628 /* A SCSI response with Check Condition contains sense data */
1629 /* offset is setup correctly by the iscsi code for response above */
1630 if((end_offset - offset) >= 2) {
1631 int senseLen = tvb_get_ntohs(tvb, offset);
1633 proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1636 dissect_scsi_snsinfo (tvb, pinfo, tree, offset,
1637 iscsi_min (senseLen,
1638 end_offset-offset));
1642 dissect_scsi_rsp (tvb, pinfo, tree);
1645 else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1646 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1647 /* offset is setup correctly by the iscsi code for response above */
1648 dissect_scsi_payload (tvb, pinfo, tree, offset, FALSE,
1649 iscsi_min (data_segment_len, end_offset-offset));
1654 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_port) {
1655 /* Set up structures needed to add the protocol subtree and manage it */
1656 guint iSCSIPdusDissected = 0;
1658 guint32 available_bytes = tvb_length_remaining(tvb, offset);
1660 /* quick check to see if the packet is long enough to contain the
1661 * minimum amount of information we need */
1662 if (available_bytes < 48 && (!iscsi_desegment || available_bytes < 8)) {
1663 /* no, so give up */
1667 /* process multiple iSCSI PDUs per packet */
1668 while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
1669 const char *opcode_str = NULL;
1670 guint32 data_segment_len;
1671 guint8 opcode = tvb_get_guint8(tvb, offset + 0);
1672 guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
1675 /* mask out any extra bits in the opcode byte */
1676 opcode &= OPCODE_MASK;
1678 opcode_str = match_strval(opcode, iscsi_opcodes);
1679 if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
1680 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1681 opcode == ISCSI_OPCODE_R2T ||
1682 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1683 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1684 opcode == ISCSI_OPCODE_SNACK_REQUEST)
1685 data_segment_len = 0;
1687 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
1689 if(opcode_str == NULL) {
1692 else if(check_port && iscsi_port != 0 &&
1693 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
1694 (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
1697 else if(enable_bogosity_filter) {
1698 /* try and distinguish between data and real headers */
1699 if(data_segment_len > bogus_pdu_data_length_threshold) {
1702 else if(demand_good_f_bit &&
1703 !(secondPduByte & 0x80) &&
1704 (opcode == ISCSI_OPCODE_NOP_OUT ||
1705 opcode == ISCSI_OPCODE_NOP_IN ||
1706 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1707 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1708 opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
1709 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1710 opcode == ISCSI_OPCODE_R2T ||
1711 opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
1712 opcode == ISCSI_OPCODE_SNACK_REQUEST ||
1713 opcode == ISCSI_OPCODE_REJECT)) {
1715 } else if(opcode==ISCSI_OPCODE_NOP_OUT) {
1716 /* TransferTag for NOP-Out should either be -1 or
1717 the tag value we want for a response.
1718 Assume 0 means we are just inside a big all zero
1721 if(tvb_get_ntohl(tvb, offset+20)==0){
1728 return iSCSIPdusDissected > 0;
1731 guint32 pduLen = 48;
1732 int digestsActive = 1;
1734 if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
1735 opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1736 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1737 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
1738 /* digests are not yet turned on */
1747 if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1749 pduLen += tvb_get_guint8(tvb, offset + 4) * 4;
1752 pduLen += data_segment_len;
1753 if((pduLen & 3) != 0)
1754 pduLen += 4 - (pduLen & 3);
1756 if(digestsActive && enableHeaderDigests) {
1757 if(headerDigestIsCRC32)
1760 pduLen += headerDigestSize;
1763 if(digestsActive && data_segment_len > 0 && enableDataDigests) {
1764 if(dataDigestIsCRC32)
1767 pduLen += dataDigestSize;
1771 * Desegmentation check.
1773 if(iscsi_desegment && pinfo->can_desegment) {
1774 if(pduLen > available_bytes) {
1776 * This frame doesn't have all of the data for
1777 * this message, but we can do reassembly on it.
1779 * Tell the TCP dissector where the data for this
1780 * message starts in the data it handed us, and
1781 * how many more bytes we need, and return.
1783 pinfo->desegment_offset = offset;
1784 pinfo->desegment_len = pduLen - available_bytes;
1789 /* This is to help TCP keep track of PDU boundaries
1790 and allows it to find PDUs that are not aligned to
1791 the start of a TCP segments.
1792 Since it also allows TCP to know what is in the middle
1793 of a large PDU, it reduces the probability of a segment
1794 in the middle of a large PDU transfer being misdissected as
1797 if(!pinfo->fd->flags.visited){
1798 if(pduLen>(guint32)tvb_reported_length_remaining(tvb, offset)){
1799 pinfo->want_pdu_tracking=2;
1800 pinfo->bytes_until_next_pdu=pduLen-tvb_reported_length_remaining(tvb, offset);
1804 if(check_col(pinfo->cinfo, COL_INFO)) {
1805 if(iSCSIPdusDissected == 0)
1806 col_set_str(pinfo->cinfo, COL_INFO, "");
1808 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1811 dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len);
1812 if(pduLen > available_bytes)
1813 pduLen = available_bytes;
1815 available_bytes -= pduLen;
1816 ++iSCSIPdusDissected;
1820 return iSCSIPdusDissected > 0;
1823 /* This is called for those sessions where we have explicitely said
1824 this to be iSCSI using "Decode As..."
1825 In this case we will not check the port number for sanity and just
1826 do as the user said.
1829 dissect_iscsi_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1830 dissect_iscsi(tvb, pinfo, tree, FALSE);
1833 /* This is called through the heuristic handler.
1834 In this case we also want to check that the port matches the preference
1835 setting for iSCSI in order to reduce the number of
1839 dissect_iscsi_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1840 return dissect_iscsi(tvb, pinfo, tree, TRUE);
1844 /* Register the protocol with Ethereal */
1847 * this format is require because a script is used to build the C
1848 * function that calls all the protocol registration.
1852 proto_register_iscsi(void)
1855 /* Setup list of header fields See Section 1.6.1 for details*/
1856 static hf_register_info hf[] = {
1857 { &hf_iscsi_request_frame,
1858 { "Request in", "iscsi.request_frame",
1859 FT_FRAMENUM, BASE_NONE, NULL, 0,
1860 "The request to this transaction is in this frame", HFILL }},
1863 { "Time from request", "iscsi.time",
1864 FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
1865 "Time between the Command and the Response", HFILL }},
1867 { &hf_iscsi_data_in_frame,
1868 { "Data In in", "iscsi.data_in_frame",
1869 FT_FRAMENUM, BASE_NONE, NULL, 0,
1870 "The Data In for this transaction is in this frame", HFILL }},
1872 { &hf_iscsi_data_out_frame,
1873 { "Data Out in", "iscsi.data_out_frame",
1874 FT_FRAMENUM, BASE_NONE, NULL, 0,
1875 "The Data Out for this transaction is in this frame", HFILL }},
1877 { &hf_iscsi_response_frame,
1878 { "Response in", "iscsi.response_frame",
1879 FT_FRAMENUM, BASE_NONE, NULL, 0,
1880 "The response to this transaction is in this frame", HFILL }},
1883 { "AHS", "iscsi.ahs",
1884 FT_BYTES, BASE_HEX, NULL, 0,
1885 "Additional header segment", HFILL }
1887 { &hf_iscsi_Padding,
1888 { "Padding", "iscsi.padding",
1889 FT_BYTES, BASE_HEX, NULL, 0,
1890 "Padding to 4 byte boundary", HFILL }
1892 { &hf_iscsi_ping_data,
1893 { "PingData", "iscsi.pingdata",
1894 FT_BYTES, BASE_HEX, NULL, 0,
1895 "Ping Data", HFILL }
1897 { &hf_iscsi_immediate_data,
1898 { "ImmediateData", "iscsi.immediatedata",
1899 FT_BYTES, BASE_HEX, NULL, 0,
1900 "Immediate Data", HFILL }
1902 { &hf_iscsi_write_data,
1903 { "WriteData", "iscsi.writedata",
1904 FT_BYTES, BASE_HEX, NULL, 0,
1905 "Write Data", HFILL }
1907 { &hf_iscsi_read_data,
1908 { "ReadData", "iscsi.readdata",
1909 FT_BYTES, BASE_HEX, NULL, 0,
1910 "Read Data", HFILL }
1912 { &hf_iscsi_error_pdu_data,
1913 { "ErrorPDUData", "iscsi.errorpdudata",
1914 FT_BYTES, BASE_HEX, NULL, 0,
1915 "Error PDU Data", HFILL }
1917 { &hf_iscsi_async_message_data,
1918 { "AsyncMessageData", "iscsi.asyncmessagedata",
1919 FT_BYTES, BASE_HEX, NULL, 0,
1920 "Async Message Data", HFILL }
1922 { &hf_iscsi_vendor_specific_data,
1923 { "VendorSpecificData", "iscsi.vendorspecificdata",
1924 FT_BYTES, BASE_HEX, NULL, 0,
1925 "Vendor Specific Data", HFILL }
1927 { &hf_iscsi_HeaderDigest,
1928 { "HeaderDigest", "iscsi.headerdigest",
1929 FT_BYTES, BASE_HEX, NULL, 0,
1930 "Header Digest", HFILL }
1932 { &hf_iscsi_HeaderDigest32,
1933 { "HeaderDigest", "iscsi.headerdigest32",
1934 FT_UINT32, BASE_HEX, NULL, 0,
1935 "Header Digest", HFILL }
1937 { &hf_iscsi_DataDigest,
1938 { "DataDigest", "iscsi.datadigest",
1939 FT_BYTES, BASE_HEX, NULL, 0,
1940 "Data Digest", HFILL }
1942 { &hf_iscsi_DataDigest32,
1943 { "DataDigest", "iscsi.datadigest32",
1944 FT_UINT32, BASE_HEX, NULL, 0,
1945 "Data Digest", HFILL }
1948 { "Opcode", "iscsi.opcode",
1949 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
1952 /* #ifdef DRAFT08 */
1955 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1956 "Command Retry", HFILL }
1961 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
1962 "Immediate delivery", HFILL }
1965 { "Flags", "iscsi.flags",
1966 FT_UINT8, BASE_HEX, NULL, 0,
1967 "Opcode specific flags", HFILL }
1969 { &hf_iscsi_SCSICommand_F,
1970 { "F", "iscsi.scsicommand.F",
1971 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1972 "PDU completes command", HFILL }
1974 { &hf_iscsi_SCSICommand_R,
1975 { "R", "iscsi.scsicommand.R",
1976 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
1977 "Command reads from SCSI target", HFILL }
1979 { &hf_iscsi_SCSICommand_W,
1980 { "W", "iscsi.scsicommand.W",
1981 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
1982 "Command writes to SCSI target", HFILL }
1984 { &hf_iscsi_SCSICommand_Attr,
1985 { "Attr", "iscsi.scsicommand.attr",
1986 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
1987 "SCSI task attributes", HFILL }
1989 { &hf_iscsi_SCSICommand_CRN,
1990 { "CRN", "iscsi.scsicommand.crn",
1991 FT_UINT8, BASE_HEX, NULL, 0,
1992 "SCSI command reference number", HFILL }
1994 { &hf_iscsi_SCSICommand_AddCDB,
1995 { "AddCDB", "iscsi.scsicommand.addcdb",
1996 FT_UINT8, BASE_HEX, NULL, 0,
1997 "Additional CDB length (in 4 byte units)", HFILL }
1999 { &hf_iscsi_DataSegmentLength,
2000 { "DataSegmentLength", "iscsi.datasegmentlength",
2001 FT_UINT32, BASE_HEX, NULL, 0,
2002 "Data segment length (bytes)", HFILL }
2004 { &hf_iscsi_TotalAHSLength,
2005 { "TotalAHSLength", "iscsi.totalahslength",
2006 FT_UINT8, BASE_HEX, NULL, 0,
2007 "Total additional header segment length (4 byte words)", HFILL }
2010 { "LUN", "iscsi.lun",
2011 FT_BYTES, BASE_HEX, NULL, 0,
2012 "Logical Unit Number", HFILL }
2014 { &hf_iscsi_InitiatorTaskTag,
2015 { "InitiatorTaskTag", "iscsi.initiatortasktag",
2016 FT_UINT32, BASE_HEX, NULL, 0,
2017 "Initiator's task tag", HFILL }
2019 { &hf_iscsi_ExpectedDataTransferLength,
2020 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
2021 FT_UINT32, BASE_HEX, NULL, 0,
2022 "Expected length of data transfer", HFILL }
2025 { "CmdSN", "iscsi.cmdsn",
2026 FT_UINT32, BASE_HEX, NULL, 0,
2027 "Sequence number for this command", HFILL }
2029 { &hf_iscsi_ExpStatSN,
2030 { "ExpStatSN", "iscsi.expstatsn",
2031 FT_UINT32, BASE_HEX, NULL, 0,
2032 "Next expected status sequence number", HFILL }
2034 { &hf_iscsi_SCSIResponse_ResidualCount,
2035 { "ResidualCount", "iscsi.scsiresponse.residualcount",
2036 FT_UINT32, BASE_HEX, NULL, 0,
2037 "Residual count", HFILL }
2040 { "StatSN", "iscsi.statsn",
2041 FT_UINT32, BASE_HEX, NULL, 0,
2042 "Status sequence number", HFILL }
2044 { &hf_iscsi_ExpCmdSN,
2045 { "ExpCmdSN", "iscsi.expcmdsn",
2046 FT_UINT32, BASE_HEX, NULL, 0,
2047 "Next expected command sequence number", HFILL }
2049 { &hf_iscsi_MaxCmdSN,
2050 { "MaxCmdSN", "iscsi.maxcmdsn",
2051 FT_UINT32, BASE_HEX, NULL, 0,
2052 "Maximum acceptable command sequence number", HFILL }
2054 { &hf_iscsi_SCSIResponse_o,
2055 { "o", "iscsi.scsiresponse.o",
2056 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
2057 "Bi-directional read residual overflow", HFILL }
2059 { &hf_iscsi_SCSIResponse_u,
2060 { "u", "iscsi.scsiresponse.u",
2061 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
2062 "Bi-directional read residual underflow", HFILL }
2064 { &hf_iscsi_SCSIResponse_O,
2065 { "O", "iscsi.scsiresponse.O",
2066 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
2067 "Residual overflow", HFILL }
2069 { &hf_iscsi_SCSIResponse_U,
2070 { "U", "iscsi.scsiresponse.U",
2071 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
2072 "Residual underflow", HFILL }
2074 { &hf_iscsi_SCSIResponse_Status,
2075 { "Status", "iscsi.scsiresponse.status",
2076 FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
2077 "SCSI command status value", HFILL }
2079 { &hf_iscsi_SCSIResponse_Response,
2080 { "Response", "iscsi.scsiresponse.response",
2081 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
2082 "SCSI command response value", HFILL }
2084 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
2085 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
2086 FT_UINT32, BASE_HEX, NULL, 0,
2087 "Bi-directional read residual count", HFILL }
2089 { &hf_iscsi_SenseLength,
2090 { "SenseLength", "iscsi.scsiresponse.senselength",
2091 FT_UINT16, BASE_HEX, NULL, 0,
2092 "Sense data length", HFILL }
2094 { &hf_iscsi_SCSIData_F,
2095 { "F", "iscsi.scsidata.F",
2096 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
2097 "Final PDU", HFILL }
2099 { &hf_iscsi_SCSIData_A,
2100 { "A", "iscsi.scsidata.A",
2101 FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
2102 "Acknowledge Requested", HFILL }
2104 { &hf_iscsi_SCSIData_S,
2105 { "S", "iscsi.scsidata.S",
2106 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
2107 "PDU Contains SCSI command status", HFILL }
2109 { &hf_iscsi_SCSIData_U,
2110 { "U", "iscsi.scsidata.U",
2111 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
2112 "Residual underflow", HFILL }
2114 { &hf_iscsi_SCSIData_O,
2115 { "O", "iscsi.scsidata.O",
2116 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
2117 "Residual overflow", HFILL }
2119 { &hf_iscsi_TargetTransferTag,
2120 { "TargetTransferTag", "iscsi.targettransfertag",
2121 FT_UINT32, BASE_HEX, NULL, 0,
2122 "Target transfer tag", HFILL }
2124 { &hf_iscsi_BufferOffset,
2125 { "BufferOffset", "iscsi.bufferOffset",
2126 FT_UINT32, BASE_HEX, NULL, 0,
2127 "Buffer offset", HFILL }
2129 { &hf_iscsi_SCSIData_ResidualCount,
2130 { "ResidualCount", "iscsi.scsidata.readresidualcount",
2131 FT_UINT32, BASE_HEX, NULL, 0,
2132 "Residual count", HFILL }
2135 { "DataSN", "iscsi.datasn",
2136 FT_UINT32, BASE_HEX, NULL, 0,
2137 "Data sequence number", HFILL }
2139 { &hf_iscsi_VersionMax,
2140 { "VersionMax", "iscsi.versionmax",
2141 FT_UINT8, BASE_HEX, NULL, 0,
2142 "Maximum supported protocol version", HFILL }
2144 { &hf_iscsi_VersionMin,
2145 { "VersionMin", "iscsi.versionmin",
2146 FT_UINT8, BASE_HEX, NULL, 0,
2147 "Minimum supported protocol version", HFILL }
2149 { &hf_iscsi_VersionActive,
2150 { "VersionActive", "iscsi.versionactive",
2151 FT_UINT8, BASE_HEX, NULL, 0,
2152 "Negotiated protocol version", HFILL }
2155 { "CID", "iscsi.cid",
2156 FT_UINT16, BASE_HEX, NULL, 0,
2157 "Connection identifier", HFILL }
2159 /* #ifdef DRAFT08 */
2161 { "ISID", "iscsi.isid",
2162 FT_UINT16, BASE_HEX, NULL, 0,
2163 "Initiator part of session identifier", HFILL }
2167 { "ISID", "iscsi.isid",
2168 FT_BYTES, BASE_HEX, NULL, 0,
2169 "Initiator part of session identifier", HFILL }
2171 /* #ifdef DRAFT09 */
2172 { &hf_iscsi_ISID_Type,
2173 { "ISID_Type", "iscsi.isid.type",
2174 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
2175 "Initiator part of session identifier - type", HFILL }
2177 { &hf_iscsi_ISID_NamingAuthority,
2178 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
2179 FT_UINT24, BASE_HEX, NULL, 0,
2180 "Initiator part of session identifier - naming authority", HFILL }
2182 { &hf_iscsi_ISID_Qualifier,
2183 { "ISID_Qualifier", "iscsi.isid.qualifier",
2184 FT_UINT8, BASE_HEX, NULL, 0,
2185 "Initiator part of session identifier - qualifier", HFILL }
2189 { "ISID_t", "iscsi.isid.t",
2190 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
2191 "Initiator part of session identifier - t", HFILL }
2194 { "ISID_a", "iscsi.isid.a",
2195 FT_UINT8, BASE_HEX, NULL, 0x3f,
2196 "Initiator part of session identifier - a", HFILL }
2199 { "ISID_b", "iscsi.isid.b",
2200 FT_UINT16, BASE_HEX, NULL, 0,
2201 "Initiator part of session identifier - b", HFILL }
2204 { "ISID_c", "iscsi.isid.c",
2205 FT_UINT8, BASE_HEX, NULL, 0,
2206 "Initiator part of session identifier - c", HFILL }
2209 { "ISID_d", "iscsi.isid.d",
2210 FT_UINT16, BASE_HEX, NULL, 0,
2211 "Initiator part of session identifier - d", HFILL }
2216 { "TSID", "iscsi.tsid",
2217 FT_UINT16, BASE_HEX, NULL, 0,
2218 "Target part of session identifier", HFILL }
2221 { "TSIH", "iscsi.tsih",
2222 FT_UINT16, BASE_HEX, NULL, 0,
2223 "Target session identifying handle", HFILL }
2225 { &hf_iscsi_InitStatSN,
2226 { "InitStatSN", "iscsi.initstatsn",
2227 FT_UINT32, BASE_HEX, NULL, 0,
2228 "Initial status sequence number", HFILL }
2230 { &hf_iscsi_InitCmdSN,
2231 { "InitCmdSN", "iscsi.initcmdsn",
2232 FT_UINT32, BASE_HEX, NULL, 0,
2233 "Initial command sequence number", HFILL }
2235 { &hf_iscsi_Login_T,
2236 { "T", "iscsi.login.T",
2237 FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
2238 "Transit to next login stage", HFILL }
2240 { &hf_iscsi_Login_C,
2241 { "C", "iscsi.login.C",
2242 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2243 "Text incomplete", HFILL }
2245 /* #ifdef DRAFT09 */
2246 { &hf_iscsi_Login_X,
2247 { "X", "iscsi.login.X",
2248 FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
2249 "Restart Connection", HFILL }
2252 { &hf_iscsi_Login_CSG,
2253 { "CSG", "iscsi.login.csg",
2254 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
2255 "Current stage", HFILL }
2257 { &hf_iscsi_Login_NSG,
2258 { "NSG", "iscsi.login.nsg",
2259 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
2260 "Next stage", HFILL }
2262 { &hf_iscsi_Login_Status,
2263 { "Status", "iscsi.login.status",
2264 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
2265 "Status class and detail", HFILL }
2267 { &hf_iscsi_KeyValue,
2268 { "KeyValue", "iscsi.keyvalue",
2269 FT_STRING, 0, NULL, 0,
2270 "Key/value pair", HFILL }
2273 { "F", "iscsi.text.F",
2274 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2275 "Final PDU in text sequence", HFILL }
2278 { "C", "iscsi.text.C",
2279 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2280 "Text incomplete", HFILL }
2282 { &hf_iscsi_ExpDataSN,
2283 { "ExpDataSN", "iscsi.expdatasn",
2284 FT_UINT32, BASE_HEX, NULL, 0,
2285 "Next expected data sequence number", HFILL }
2288 { "R2TSN", "iscsi.r2tsn",
2289 FT_UINT32, BASE_HEX, NULL, 0,
2290 "R2T PDU Number", HFILL }
2292 { &hf_iscsi_TaskManagementFunction_Response,
2293 { "Response", "iscsi.taskmanfun.response",
2294 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
2297 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
2298 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
2299 FT_UINT32, BASE_HEX, NULL, 0,
2300 "Referenced task tag", HFILL }
2302 { &hf_iscsi_RefCmdSN,
2303 { "RefCmdSN", "iscsi.refcmdsn",
2304 FT_UINT32, BASE_HEX, NULL, 0,
2305 "Command sequence number for command to be aborted", HFILL }
2307 { &hf_iscsi_TaskManagementFunction_Function,
2308 { "Function", "iscsi.taskmanfun.function",
2309 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
2310 "Requested task function", HFILL }
2312 { &hf_iscsi_Logout_Reason,
2313 { "Reason", "iscsi.logout.reason",
2314 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0x7F,
2315 "Reason for logout", HFILL }
2317 { &hf_iscsi_Logout_Response,
2318 { "Response", "iscsi.logout.response",
2319 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
2320 "Logout response", HFILL }
2322 { &hf_iscsi_Time2Wait,
2323 { "Time2Wait", "iscsi.time2wait",
2324 FT_UINT16, BASE_HEX, NULL, 0,
2325 "Time2Wait", HFILL }
2327 { &hf_iscsi_Time2Retain,
2328 { "Time2Retain", "iscsi.time2retain",
2329 FT_UINT16, BASE_HEX, NULL, 0,
2330 "Time2Retain", HFILL }
2332 { &hf_iscsi_DesiredDataLength,
2333 { "DesiredDataLength", "iscsi.desireddatalength",
2334 FT_UINT32, BASE_HEX, NULL, 0,
2335 "Desired data length (bytes)", HFILL }
2337 { &hf_iscsi_AsyncEvent,
2338 { "AsyncEvent", "iscsi.asyncevent",
2339 FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2340 "Async event type", HFILL }
2342 { &hf_iscsi_EventVendorCode,
2343 { "EventVendorCode", "iscsi.eventvendorcode",
2344 FT_UINT8, BASE_HEX, NULL, 0,
2345 "Event vendor code", HFILL }
2347 { &hf_iscsi_Parameter1,
2348 { "Parameter1", "iscsi.parameter1",
2349 FT_UINT16, BASE_HEX, NULL, 0,
2350 "Parameter 1", HFILL }
2352 { &hf_iscsi_Parameter2,
2353 { "Parameter2", "iscsi.parameter2",
2354 FT_UINT16, BASE_HEX, NULL, 0,
2355 "Parameter 2", HFILL }
2357 { &hf_iscsi_Parameter3,
2358 { "Parameter3", "iscsi.parameter3",
2359 FT_UINT16, BASE_HEX, NULL, 0,
2360 "Parameter 3", HFILL }
2362 { &hf_iscsi_Reject_Reason,
2363 { "Reason", "iscsi.reject.reason",
2364 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2365 "Reason for command rejection", HFILL }
2367 { &hf_iscsi_snack_type,
2368 { "S", "iscsi.snack.type",
2369 FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2370 "Type of SNACK requested", HFILL }
2373 { "BegRun", "iscsi.snack.begrun",
2374 FT_UINT32, BASE_HEX, NULL, 0,
2375 "First missed DataSN or StatSN", HFILL }
2377 { &hf_iscsi_RunLength,
2378 { "RunLength", "iscsi.snack.runlength",
2379 FT_UINT32, BASE_HEX, NULL, 0,
2380 "Number of additional missing status PDUs in this run", HFILL }
2384 /* Setup protocol subtree array */
2385 static gint *ett[] = {
2387 &ett_iscsi_KeyValues,
2390 /* #ifndef DRAFT08 */
2395 /* Register the protocol name and description */
2396 proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2398 /* Required function calls to register the header fields and
2400 proto_register_field_array(proto_iscsi, hf, array_length(hf));
2401 proto_register_subtree_array(ett, array_length(ett));
2402 register_init_routine (&iscsi_init_protocol);
2405 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2407 prefs_register_enum_preference(iscsi_module,
2410 "The iSCSI protocol version",
2411 &iscsi_protocol_version,
2412 iscsi_protocol_versions,
2415 prefs_register_bool_preference(iscsi_module,
2416 "desegment_iscsi_messages",
2417 "Desegment iSCSI messages",
2418 "When enabled, iSCSI messages that span multiple TCP segments are desegmented",
2421 prefs_register_bool_preference(iscsi_module,
2423 "Enable bogus pdu filter",
2424 "When enabled, packets that appear bogus are ignored",
2425 &enable_bogosity_filter);
2427 prefs_register_bool_preference(iscsi_module,
2428 "demand_good_f_bit",
2429 "Ignore packets with bad F bit",
2430 "Ignore packets that haven't set the F bit when they should have",
2431 &demand_good_f_bit);
2433 prefs_register_uint_preference(iscsi_module,
2434 "bogus_pdu_max_data_len",
2435 "Bogus pdu max data length threshold",
2436 "Treat packets whose data segment length is greater than this value as bogus",
2438 &bogus_pdu_data_length_threshold);
2441 prefs_register_uint_preference(iscsi_module,
2444 "Port number of iSCSI target",
2448 prefs_register_bool_preference(iscsi_module,
2449 "enable_header_digests",
2450 "Enable header digests",
2451 "When enabled, pdus are assumed to contain a header digest",
2452 &enableHeaderDigests);
2453 prefs_register_bool_preference(iscsi_module,
2454 "enable_data_digests",
2455 "Enable data digests",
2456 "When enabled, pdus are assumed to contain a data digest",
2457 &enableDataDigests);
2459 prefs_register_bool_preference(iscsi_module,
2460 "header_digest_is_crc32c",
2461 "Header digest is CRC32C",
2462 "When enabled, header digests are assumed to be CRC32C",
2463 &headerDigestIsCRC32);
2464 prefs_register_bool_preference(iscsi_module,
2465 "data_digest_is_crc32c",
2466 "Data digest is CRC32C",
2467 "When enabled, data digests are assumed to be CRC32C",
2468 &dataDigestIsCRC32);
2470 prefs_register_uint_preference(iscsi_module,
2471 "header_digest_size",
2472 "Header digest size",
2473 "The size of a header digest (bytes)",
2476 prefs_register_uint_preference(iscsi_module,
2479 "The size of a data digest (bytes)",
2483 /* Preference supported in older versions.
2484 Register them as obsolete. */
2485 prefs_register_obsolete_preference(iscsi_module,
2486 "version_03_compatible");
2487 prefs_register_obsolete_preference(iscsi_module,
2488 "bogus_pdu_max_digest_padding");
2494 * If this dissector uses sub-dissector registration add a
2495 * registration routine.
2499 * This format is required because a script is used to find these
2500 * routines and create the code that calls these routines.
2503 proto_reg_handoff_iscsi(void)
2505 dissector_handle_t iscsi_handle;
2507 heur_dissector_add("tcp", dissect_iscsi_heur, proto_iscsi);
2509 iscsi_handle = create_dissector_handle(dissect_iscsi_handle, proto_iscsi);
2510 dissector_add_handle("tcp.port", iscsi_handle);