2 * Routines for iSCSI dissection
3 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
5 * $Id: packet-iscsi.c,v 1.46 2003/06/21 10:16:18 sahlberg Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/packet.h>
38 #include <epan/conversation.h>
39 #include "packet-scsi.h"
40 #include "epan/nstime.h"
42 /* the absolute values of these constants don't matter as long as
43 * latter revisions of the protocol are assigned a larger number */
44 #define ISCSI_PROTOCOL_DRAFT08 1
45 #define ISCSI_PROTOCOL_DRAFT09 2
46 #define ISCSI_PROTOCOL_DRAFT11 3
47 #define ISCSI_PROTOCOL_DRAFT12 4
48 #define ISCSI_PROTOCOL_DRAFT13 5
50 static enum_val_t iscsi_protocol_versions[] = {
51 { "Draft 08", ISCSI_PROTOCOL_DRAFT08 },
52 { "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
53 { "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
54 { "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
55 { "Draft 13", ISCSI_PROTOCOL_DRAFT13 },
59 static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT13;
61 static gboolean iscsi_desegment = TRUE;
63 static int demand_good_f_bit = FALSE;
64 static int enable_bogosity_filter = TRUE;
65 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
67 static int enableDataDigests = FALSE;
68 static int enableHeaderDigests = FALSE;
70 static int dataDigestIsCRC32 = TRUE;
71 static int headerDigestIsCRC32 = TRUE;
73 static int dataDigestSize = 4;
74 static int headerDigestSize = 4;
76 static guint iscsi_port = 3260;
78 /* Initialize the protocol and registered fields */
79 static int proto_iscsi = -1;
80 static int hf_iscsi_time = -1;
81 static int hf_iscsi_request_frame = -1;
82 static int hf_iscsi_data_in_frame = -1;
83 static int hf_iscsi_data_out_frame = -1;
84 static int hf_iscsi_response_frame = -1;
85 static int hf_iscsi_AHS = -1;
86 static int hf_iscsi_Padding = -1;
87 static int hf_iscsi_ping_data = -1;
88 static int hf_iscsi_immediate_data = -1;
89 static int hf_iscsi_write_data = -1;
90 static int hf_iscsi_read_data = -1;
91 static int hf_iscsi_error_pdu_data = -1;
92 static int hf_iscsi_async_message_data = -1;
93 static int hf_iscsi_vendor_specific_data = -1;
94 static int hf_iscsi_Opcode = -1;
95 static int hf_iscsi_Flags = -1;
96 static int hf_iscsi_HeaderDigest = -1;
97 static int hf_iscsi_HeaderDigest32 = -1;
98 static int hf_iscsi_DataDigest = -1;
99 static int hf_iscsi_DataDigest32 = -1;
101 static int hf_iscsi_X = -1;
103 static int hf_iscsi_I = -1;
104 static int hf_iscsi_SCSICommand_F = -1;
105 static int hf_iscsi_SCSICommand_R = -1;
106 static int hf_iscsi_SCSICommand_W = -1;
107 static int hf_iscsi_SCSICommand_Attr = -1;
108 static int hf_iscsi_SCSICommand_CRN = -1;
109 static int hf_iscsi_SCSICommand_AddCDB = -1;
110 static int hf_iscsi_DataSegmentLength = -1;
111 static int hf_iscsi_TotalAHSLength = -1;
112 static int hf_iscsi_LUN = -1;
113 static int hf_iscsi_InitiatorTaskTag = -1;
114 static int hf_iscsi_ExpectedDataTransferLength = -1;
115 static int hf_iscsi_CmdSN = -1;
116 static int hf_iscsi_ExpStatSN = -1;
117 static int hf_iscsi_StatSN = -1;
118 static int hf_iscsi_ExpCmdSN = -1;
119 static int hf_iscsi_MaxCmdSN = -1;
120 static int hf_iscsi_SCSIResponse_o = -1;
121 static int hf_iscsi_SCSIResponse_u = -1;
122 static int hf_iscsi_SCSIResponse_O = -1;
123 static int hf_iscsi_SCSIResponse_U = -1;
124 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
125 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
126 static int hf_iscsi_SCSIResponse_Response = -1;
127 static int hf_iscsi_SCSIResponse_Status = -1;
128 static int hf_iscsi_SenseLength = -1;
129 static int hf_iscsi_SCSIData_F = -1;
130 static int hf_iscsi_SCSIData_A = -1;
131 static int hf_iscsi_SCSIData_S = -1;
132 static int hf_iscsi_SCSIData_O = -1;
133 static int hf_iscsi_SCSIData_U = -1;
134 static int hf_iscsi_TargetTransferTag = -1;
135 static int hf_iscsi_DataSN = -1;
136 static int hf_iscsi_BufferOffset = -1;
137 static int hf_iscsi_SCSIData_ResidualCount = -1;
138 static int hf_iscsi_VersionMin = -1;
139 static int hf_iscsi_VersionMax = -1;
140 static int hf_iscsi_VersionActive = -1;
141 static int hf_iscsi_CID = -1;
142 static int hf_iscsi_ISID8 = -1;
143 static int hf_iscsi_ISID = -1;
144 /* #if defined(DRAFT09) */
145 static int hf_iscsi_ISID_Type = -1;
146 static int hf_iscsi_ISID_NamingAuthority = -1;
147 static int hf_iscsi_ISID_Qualifier = -1;
148 /* #elif !defined(DRAFT08) */
149 static int hf_iscsi_ISID_t = -1;
150 static int hf_iscsi_ISID_a = -1;
151 static int hf_iscsi_ISID_b = -1;
152 static int hf_iscsi_ISID_c = -1;
153 static int hf_iscsi_ISID_d = -1;
155 static int hf_iscsi_TSID = -1;
156 static int hf_iscsi_TSIH = -1;
157 static int hf_iscsi_InitStatSN = -1;
158 static int hf_iscsi_InitCmdSN = -1;
160 static int hf_iscsi_Login_X = -1;
162 static int hf_iscsi_Login_C = -1;
163 static int hf_iscsi_Login_T = -1;
164 static int hf_iscsi_Login_CSG = -1;
165 static int hf_iscsi_Login_NSG = -1;
166 static int hf_iscsi_Login_Status = -1;
167 static int hf_iscsi_KeyValue = -1;
168 static int hf_iscsi_Text_C = -1;
169 static int hf_iscsi_Text_F = -1;
170 static int hf_iscsi_ExpDataSN = -1;
171 static int hf_iscsi_R2TSN = -1;
172 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
173 static int hf_iscsi_RefCmdSN = -1;
174 static int hf_iscsi_TaskManagementFunction_Function = -1;
175 static int hf_iscsi_TaskManagementFunction_Response = -1;
176 static int hf_iscsi_Logout_Reason = -1;
177 static int hf_iscsi_Logout_Response = -1;
178 static int hf_iscsi_Time2Wait = -1;
179 static int hf_iscsi_Time2Retain = -1;
180 static int hf_iscsi_DesiredDataLength = -1;
181 static int hf_iscsi_AsyncEvent = -1;
182 static int hf_iscsi_EventVendorCode = -1;
183 static int hf_iscsi_Parameter1 = -1;
184 static int hf_iscsi_Parameter2 = -1;
185 static int hf_iscsi_Parameter3 = -1;
186 static int hf_iscsi_Reject_Reason = -1;
187 static int hf_iscsi_snack_type = -1;
188 static int hf_iscsi_BegRun = -1;
189 static int hf_iscsi_RunLength = -1;
191 /* Initialize the subtree pointers */
192 static gint ett_iscsi = -1;
193 static gint ett_iscsi_KeyValues = -1;
194 static gint ett_iscsi_CDB = -1;
195 static gint ett_iscsi_Flags = -1;
196 /* #ifndef DRAFT08 */
197 static gint ett_iscsi_ISID = -1;
207 #define OPCODE_MASK 0x3f
209 #define TARGET_OPCODE_BIT 0x20
211 #define ISCSI_OPCODE_NOP_OUT 0x00
212 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
213 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
214 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
215 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
216 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
217 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
218 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
219 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
220 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
221 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
223 #define ISCSI_OPCODE_NOP_IN 0x20
224 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
225 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
226 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
227 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
228 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
229 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
230 #define ISCSI_OPCODE_R2T 0x31
231 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
232 #define ISCSI_OPCODE_REJECT 0x3f
233 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
234 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
235 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
238 #define CSG_MASK (0x03 << CSG_SHIFT)
239 #define NSG_MASK 0x03
241 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
242 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
243 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
245 #define ISCSI_SCSI_DATA_FLAG_S 0x01
246 #define ISCSI_SCSI_DATA_FLAG_U 0x02
247 #define ISCSI_SCSI_DATA_FLAG_O 0x04
248 #define ISCSI_SCSI_DATA_FLAG_A 0x40
249 #define ISCSI_SCSI_DATA_FLAG_F 0x80
251 static const value_string iscsi_opcodes[] = {
252 { ISCSI_OPCODE_NOP_OUT, "NOP Out" },
253 { ISCSI_OPCODE_SCSI_COMMAND, "SCSI Command" },
254 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION, "Task Management Function" },
255 { ISCSI_OPCODE_LOGIN_COMMAND, "Login Command" },
256 { ISCSI_OPCODE_TEXT_COMMAND, "Text Command" },
257 { ISCSI_OPCODE_SCSI_DATA_OUT, "SCSI Data Out" },
258 { ISCSI_OPCODE_LOGOUT_COMMAND, "Logout Command" },
259 { ISCSI_OPCODE_SNACK_REQUEST, "SNACK Request" },
260 { ISCSI_OPCODE_VENDOR_SPECIFIC_I0, "Vendor Specific I0" },
261 { ISCSI_OPCODE_VENDOR_SPECIFIC_I1, "Vendor Specific I1" },
262 { ISCSI_OPCODE_VENDOR_SPECIFIC_I2, "Vendor Specific I2" },
264 { ISCSI_OPCODE_NOP_IN, "NOP In" },
265 { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
266 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
267 { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
268 { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
269 { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
270 { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
271 { ISCSI_OPCODE_R2T, "Ready To Transfer" },
272 { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
273 { ISCSI_OPCODE_REJECT, "Reject"},
274 { ISCSI_OPCODE_VENDOR_SPECIFIC_T0, "Vendor Specific T0" },
275 { ISCSI_OPCODE_VENDOR_SPECIFIC_T1, "Vendor Specific T1" },
276 { ISCSI_OPCODE_VENDOR_SPECIFIC_T2, "Vendor Specific T2" },
281 static const true_false_string iscsi_meaning_X = {
288 static const true_false_string iscsi_meaning_login_X = {
289 "Reinstate failed connection",
294 static const true_false_string iscsi_meaning_I = {
295 "Immediate delivery",
299 static const true_false_string iscsi_meaning_F = {
300 "Final PDU in sequence",
301 "Not final PDU in sequence"
304 static const true_false_string iscsi_meaning_A = {
305 "Acknowledge requested",
306 "Acknowledge not requested"
309 static const true_false_string iscsi_meaning_T = {
310 "Transit to next login stage",
311 "Stay in current login stage"
314 static const true_false_string iscsi_meaning_C = {
315 "Text is incomplete",
319 static const true_false_string iscsi_meaning_S = {
320 "Response contains SCSI status",
321 "Response does not contain SCSI status"
324 static const true_false_string iscsi_meaning_R = {
325 "Data will be read from target",
326 "No data will be read from target"
329 static const true_false_string iscsi_meaning_W = {
330 "Data will be written to target",
331 "No data will be written to target"
334 static const true_false_string iscsi_meaning_o = {
335 "Read part of bi-directional command overflowed",
336 "No overflow of read part of bi-directional command",
339 static const true_false_string iscsi_meaning_u = {
340 "Read part of bi-directional command underflowed",
341 "No underflow of read part of bi-directional command",
344 static const true_false_string iscsi_meaning_O = {
345 "Residual overflow occurred",
346 "No residual overflow occurred",
349 static const true_false_string iscsi_meaning_U = {
350 "Residual underflow occurred",
351 "No residual underflow occurred",
354 static const value_string iscsi_scsi_responses[] = {
355 { 0, "Command completed at target" },
356 { 1, "Response does not contain SCSI status"},
360 static const value_string iscsi_scsicommand_taskattrs[] = {
364 {3, "Head of Queue"},
369 static const value_string iscsi_task_management_responses[] = {
370 {0, "Function complete"},
371 {1, "Task not in task set"},
372 {2, "LUN does not exist"},
373 {3, "Task still allegiant"},
374 {4, "Task failover not supported"},
375 {5, "Task management function not supported"},
376 {6, "Authorisation failed"},
377 {255, "Function rejected"},
381 static const value_string iscsi_task_management_functions[] = {
383 {2, "Abort Task Set"},
385 {4, "Clear Task Set"},
386 {5, "Logical Unit Reset"},
387 {6, "Target Warm Reset"},
388 {7, "Target Cold Reset"},
392 static const value_string iscsi_login_status[] = {
394 {0x0101, "Target moved temporarily"},
395 {0x0102, "Target moved permanently"},
396 {0x0200, "Initiator error (miscellaneous error)"},
397 {0x0201, "Authentication failed"},
398 {0x0202, "Authorisation failure"},
399 {0x0203, "Target not found"},
400 {0x0204, "Target removed"},
401 {0x0205, "Unsupported version"},
402 {0x0206, "Too many connections"},
403 {0x0207, "Missing parameter"},
404 {0x0208, "Can't include in session"},
405 {0x0209, "Session type not supported"},
406 {0x020a, "Session does not exist"},
407 {0x020b, "Invalid request during login"},
408 {0x0300, "Target error (miscellaneous error)"},
409 {0x0301, "Service unavailable"},
410 {0x0302, "Out of resources"},
414 static const value_string iscsi_login_stage[] = {
415 {0, "Security negotiation"},
416 {1, "Operational negotiation"},
417 {3, "Full feature phase"},
421 /* #ifndef DRAFT08 */
422 static const value_string iscsi_isid_type[] = {
424 {0x01, "IANA Enterprise Number"},
430 static const value_string iscsi_logout_reasons[] = {
431 {0, "Close session"},
432 {1, "Close connection"},
433 {2, "Remove connection for recovery"},
437 static const value_string iscsi_logout_response[] = {
438 {0, "Connection closed successfully"},
439 {1, "CID not found"},
440 {2, "Connection recovery not supported"},
441 {3, "Cleanup failed for various reasons"},
445 static const value_string iscsi_asyncevents[] = {
446 {0, "A SCSI asynchronous event is reported in the sense data"},
447 {1, "Target requests logout"},
448 {2, "Target will/has dropped connection"},
449 {3, "Target will/has dropped all connections"},
450 {4, "Target requests parameter negotiation"},
454 static const value_string iscsi_snack_types[] = {
457 /* #ifndef DRAFT08 */
464 static const value_string iscsi_reject_reasons[] = {
466 {0x01, "Full feature phase command before login"},
468 {0x02, "Data (payload) digest error"},
469 {0x03, "Data SNACK reject"},
470 {0x04, "Protocol error"},
471 {0x05, "Command not supported in this session type"},
472 {0x06, "Immediate command reject (too many immediate commands)"},
473 {0x07, "Task in progress"},
474 {0x08, "Invalid Data Ack"},
475 {0x09, "Invalid PDU field"},
476 {0x0a, "Long operation reject"},
477 {0x0b, "Negotiation reset"},
478 {0x0c, "Waiting for logout"},
482 /*****************************************************************/
484 /* CRC LOOKUP TABLE */
485 /* ================ */
486 /* The following CRC lookup table was generated automagically */
487 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
488 /* Program V1.0 using the following model parameters: */
490 /* Width : 4 bytes. */
491 /* Poly : 0x1EDC6F41L */
492 /* Reverse : TRUE. */
494 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
495 /* see the document titled "A Painless Guide to CRC Error */
496 /* Detection Algorithms" by Ross Williams */
497 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
498 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
500 /*****************************************************************/
502 static guint32 crc32Table[256] = {
503 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
504 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
505 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
506 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
507 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
508 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
509 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
510 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
511 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
512 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
513 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
514 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
515 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
516 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
517 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
518 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
519 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
520 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
521 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
522 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
523 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
524 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
525 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
526 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
527 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
528 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
529 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
530 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
531 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
532 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
533 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
534 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
535 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
536 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
537 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
538 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
539 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
540 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
541 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
542 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
543 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
544 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
545 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
546 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
547 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
548 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
549 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
550 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
551 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
552 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
553 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
554 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
555 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
556 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
557 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
558 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
559 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
560 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
561 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
562 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
563 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
564 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
565 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
566 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
569 #define CRC32C_PRELOAD 0xffffffff
572 * Byte swap fix contributed by Dave Wysochanski <davidw@netapp.com>
574 #define CRC32C_SWAP(crc32c_value) \
575 (((crc32c_value & 0xff000000) >> 24) | \
576 ((crc32c_value & 0x00ff0000) >> 8) | \
577 ((crc32c_value & 0x0000ff00) << 8) | \
578 ((crc32c_value & 0x000000ff) << 24))
581 calculateCRC32(const void *buf, int len, guint32 crc) {
582 const guint8 *p = (const guint8 *)buf;
583 crc = CRC32C_SWAP(crc);
585 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
586 return CRC32C_SWAP(crc);
593 /* structure and functions to keep track of
594 * COMMAND/DATA_IN/DATA_OUT/RESPONSE matching
596 typedef struct _iscsi_conv_data {
599 guint32 request_frame;
600 guint32 data_in_frame;
601 guint32 data_out_frame;
602 guint32 response_frame;
606 static GHashTable *iscsi_req_unmatched = NULL;
607 static GHashTable *iscsi_req_matched = NULL;
608 static GMemChunk *iscsi_req_vals = NULL;
609 static guint32 iscsi_init_count = 200;
612 iscsi_equal_unmatched(gconstpointer v, gconstpointer w)
614 const iscsi_conv_data_t *v1 = (const iscsi_conv_data_t *)v;
615 const iscsi_conv_data_t *v2 = (const iscsi_conv_data_t *)w;
617 return (v1->conv_idx == v2->conv_idx)&&(v1->itt == v2->itt);
621 iscsi_hash_unmatched (gconstpointer v)
623 const iscsi_conv_data_t *key = (const iscsi_conv_data_t *)v;
626 val = key->conv_idx + key->itt;
632 iscsi_equal_matched(gconstpointer v, gconstpointer w)
634 const iscsi_conv_data_t *v1 = (const iscsi_conv_data_t *)v;
635 const iscsi_conv_data_t *v2 = (const iscsi_conv_data_t *)w;
639 if (v1->request_frame && (v1->request_frame==v2->request_frame))
641 if (v1->data_in_frame && (v1->data_in_frame==v2->data_in_frame))
643 if (v1->data_out_frame && (v1->data_out_frame==v2->data_out_frame))
645 if (v1->response_frame && (v1->response_frame==v2->response_frame))
648 return check_frame&&(v1->conv_idx == v2->conv_idx)&&(v1->itt == v2->itt);
652 iscsi_hash_matched (gconstpointer v)
654 const iscsi_conv_data_t *key = (const iscsi_conv_data_t *)v;
657 val = key->conv_idx + key->itt;
668 * Protocol initialization
671 iscsi_init_protocol(void)
674 g_mem_chunk_destroy(iscsi_req_vals);
675 if (iscsi_req_unmatched)
676 g_hash_table_destroy(iscsi_req_unmatched);
677 if (iscsi_req_matched)
678 g_hash_table_destroy(iscsi_req_matched);
680 iscsi_req_unmatched = g_hash_table_new(iscsi_hash_unmatched, iscsi_equal_unmatched);
681 iscsi_req_matched = g_hash_table_new(iscsi_hash_matched, iscsi_equal_matched);
682 iscsi_req_vals = g_mem_chunk_new("iscsi_req_vals",
683 sizeof(iscsi_conv_data_t),
684 iscsi_init_count * sizeof(iscsi_conv_data_t),
689 iscsi_min(int a, int b) {
690 return (a < b)? a : b;
694 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
695 const gint limit = offset + text_len;
696 while(offset < limit) {
697 gint len = tvb_strnlen(tvb, offset, limit - offset);
699 len = limit - offset;
702 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
709 handleHeaderDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
710 int available_bytes = tvb_length_remaining(tvb, offset);
711 if(enableHeaderDigests) {
712 if(headerDigestIsCRC32) {
713 if(available_bytes >= (headerLen + 4)) {
714 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
715 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
717 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
720 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);
723 return offset + headerLen + 4;
725 if(available_bytes >= (headerLen + headerDigestSize)) {
726 proto_tree_add_item(ti, hf_iscsi_HeaderDigest, tvb, offset + headerLen, headerDigestSize, FALSE);
728 return offset + headerLen + headerDigestSize;
730 return offset + headerLen;
734 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
735 int available_bytes = tvb_length_remaining(tvb, offset);
736 if(enableDataDigests) {
737 if(dataDigestIsCRC32) {
738 if(available_bytes >= (dataLen + 4)) {
739 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
740 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
742 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
745 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);
748 return offset + dataLen + 4;
750 if(available_bytes >= (dataLen + dataDigestSize)) {
751 proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
753 return offset + dataLen + dataDigestSize;
755 return offset + dataLen;
759 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
760 if(endOffset > offset) {
761 int dataOffset = offset;
762 int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
764 proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
767 if(offset < endOffset && (offset & 3) != 0) {
768 int padding = 4 - (offset & 3);
769 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
772 if(dataSegmentLen > 0 && offset < endOffset)
773 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
780 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
781 if(endOffset > offset) {
782 int dataOffset = offset;
783 int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
785 proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
786 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
787 offset = addTextKeys(tt, tvb, offset, textLen);
789 if(offset < endOffset && (offset & 3) != 0) {
790 int padding = 4 - (offset & 3);
791 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
794 if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
795 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
800 /* Code to actually dissect the packets */
802 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len) {
804 guint original_offset = offset;
805 proto_tree *ti = NULL;
806 guint8 scsi_status = 0;
807 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
808 guint end_offset = offset + tvb_length_remaining(tvb, offset);
809 conversation_t *conversation = NULL;
810 iscsi_conv_data_t *cdata = NULL;
811 scsi_task_id_t task_key;
812 int paddedDataSegmentLength = data_segment_len;
813 if(paddedDataSegmentLength & 3)
814 paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
816 /* Make entries in Protocol column and Info column on summary display */
817 if (check_col(pinfo->cinfo, COL_PROTOCOL))
818 col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
820 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
821 opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
822 scsi_status = tvb_get_guint8 (tvb, offset+3);
825 if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
826 (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
827 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
828 conversation = find_conversation (&pinfo->src, &pinfo->dst,
829 pinfo->ptype, pinfo->srcport,
832 if (!pinfo->fd->flags.visited){
833 iscsi_conv_data_t ckey;
834 ckey.conv_idx = conversation->index;
835 ckey.itt = tvb_get_ntohl (tvb, offset+16);
837 /* first time we see this packet. check if we can find the request */
838 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_unmatched, &ckey);
840 if (cdata->data_in_frame+cdata->data_out_frame+cdata->response_frame==0){
841 /* this is the first response to the request, add it to the matched table */
842 g_hash_table_insert (iscsi_req_matched, cdata, cdata);
845 case ISCSI_OPCODE_SCSI_RESPONSE:
846 cdata->response_frame=pinfo->fd->num;
848 case ISCSI_OPCODE_SCSI_DATA_IN:
849 cdata->data_in_frame=pinfo->fd->num;
851 case ISCSI_OPCODE_SCSI_DATA_OUT:
852 cdata->data_out_frame=pinfo->fd->num;
857 iscsi_conv_data_t ckey;
858 ckey.conv_idx = conversation->index;
859 ckey.itt = tvb_get_ntohl (tvb, offset+16);
860 ckey.request_frame=0;
861 ckey.data_in_frame=0;
862 ckey.data_out_frame=0;
863 ckey.response_frame=0;
865 case ISCSI_OPCODE_SCSI_RESPONSE:
866 ckey.response_frame=pinfo->fd->num;
868 case ISCSI_OPCODE_SCSI_DATA_IN:
869 ckey.data_in_frame=pinfo->fd->num;
871 case ISCSI_OPCODE_SCSI_DATA_OUT:
872 ckey.data_out_frame=pinfo->fd->num;
876 /* we have seen this one before, pick it up from the matched table */
877 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_matched, &ckey);
881 task_key.conv_id = cdata->conv_idx;
882 task_key.task_id = cdata->itt;
883 pinfo->private_data = &task_key;
885 pinfo->private_data = NULL;
888 /* no conversation, meaning we didn't see the request */
889 pinfo->private_data = NULL;
892 } else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
893 conversation = find_conversation (&pinfo->src, &pinfo->dst,
894 pinfo->ptype, pinfo->srcport,
897 conversation = conversation_new (&pinfo->src, &pinfo->dst,
898 pinfo->ptype, pinfo->srcport,
902 if (!pinfo->fd->flags.visited){
903 iscsi_conv_data_t ckey;
905 /* first time we see this packet. */
906 /*check if we have seen this request before and delete it in that case */
907 ckey.conv_idx = conversation->index;
908 ckey.itt = tvb_get_ntohl (tvb, offset+16);
909 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_unmatched, &ckey);
911 g_hash_table_remove(iscsi_req_unmatched, &ckey);
914 /* add this new transaction to teh unmatched table */
915 cdata = g_mem_chunk_alloc (iscsi_req_vals);
916 cdata->conv_idx = conversation->index;
917 cdata->itt = tvb_get_ntohl (tvb, offset+16);
918 cdata->request_frame=pinfo->fd->num;
919 cdata->data_in_frame=0;
920 cdata->data_out_frame=0;
921 cdata->response_frame=0;
922 cdata->req_time.nsecs = pinfo->fd->abs_usecs*1000;
923 cdata->req_time.secs = pinfo->fd->abs_secs;
925 g_hash_table_insert (iscsi_req_unmatched, cdata, cdata);
927 iscsi_conv_data_t ckey;
928 ckey.conv_idx = conversation->index;
929 ckey.itt = tvb_get_ntohl (tvb, offset+16);
930 ckey.request_frame=pinfo->fd->num;
931 ckey.data_in_frame=0;
932 ckey.data_out_frame=0;
933 ckey.response_frame=0;
935 /* we have seen this one before, pick it up from the matched table */
936 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_matched, &ckey);
941 /* The SCSI protocol uses this as the key to detect a
942 * SCSI-level conversation. */
943 task_key.conv_id = cdata->conv_idx;
944 task_key.task_id = cdata->itt;
945 pinfo->private_data = &task_key;
947 pinfo->private_data=NULL;
951 pinfo->private_data = NULL;
954 if (check_col(pinfo->cinfo, COL_INFO)) {
956 if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
958 col_append_str(pinfo->cinfo, COL_INFO, opcode_str);
960 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
961 (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
962 (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
963 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
964 val_to_str (scsi_status, scsi_status_val, "0x%x"));
966 else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
967 guint16 login_status = tvb_get_ntohs(tvb, offset+36);
968 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
969 val_to_str (login_status, iscsi_login_status, "0x%x"));
971 else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
973 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
974 logoutReason = tvb_get_guint8(tvb, offset+11);
975 } else if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
976 logoutReason = tvb_get_guint8(tvb, offset+1) & 0x7f;
979 logoutReason = tvb_get_guint8(tvb, offset+23);
981 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
982 val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
984 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
985 guint8 tmf = tvb_get_guint8(tvb, offset + 1);
986 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
987 val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
989 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
990 guint8 resp = tvb_get_guint8(tvb, offset + 2);
991 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
992 val_to_str (resp, iscsi_task_management_responses, "0x%x"));
994 else if (opcode == ISCSI_OPCODE_REJECT) {
995 guint8 reason = tvb_get_guint8(tvb, offset + 2);
996 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
997 val_to_str (reason, iscsi_reject_reasons, "0x%x"));
999 else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1000 guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
1001 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
1002 val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
1007 /* In the interest of speed, if "tree" is NULL, don't do any
1008 work not necessary to generate protocol tree items. */
1011 /* create display subtree for the protocol */
1012 tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
1013 offset, -1, "iSCSI (%s)",
1015 ti = proto_item_add_subtree(tp, ett_iscsi);
1017 proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
1018 offset + 0, 1, opcode);
1019 if((opcode & TARGET_OPCODE_BIT) == 0) {
1020 /* initiator -> target */
1021 gint b = tvb_get_guint8(tvb, offset + 0);
1022 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1023 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
1024 opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
1025 opcode != ISCSI_OPCODE_SNACK_REQUEST)
1026 proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
1028 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
1029 opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
1030 opcode != ISCSI_OPCODE_SNACK_REQUEST)
1031 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
1034 /* handle request/response matching */
1037 case ISCSI_OPCODE_SCSI_RESPONSE:
1038 if (cdata->request_frame){
1039 nstime_t delta_time;
1040 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
1041 delta_time.secs = pinfo->fd->abs_secs - cdata->req_time.secs;
1042 delta_time.nsecs = pinfo->fd->abs_usecs*1000 - cdata->req_time.nsecs;
1043 if (delta_time.nsecs<0){
1044 delta_time.nsecs+=1000000000;
1047 proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1050 if (cdata->data_in_frame)
1051 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1052 if (cdata->data_out_frame)
1053 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1055 case ISCSI_OPCODE_SCSI_DATA_IN:
1056 if (cdata->request_frame)
1057 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
1058 if (cdata->data_out_frame)
1059 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1060 if (cdata->response_frame)
1061 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
1063 case ISCSI_OPCODE_SCSI_DATA_OUT:
1064 if (cdata->request_frame)
1065 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
1066 if (cdata->data_in_frame)
1067 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1068 if (cdata->response_frame)
1069 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
1071 case ISCSI_OPCODE_SCSI_COMMAND:
1072 if (cdata->data_in_frame)
1073 proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1074 if (cdata->data_out_frame)
1075 proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1076 if (cdata->response_frame)
1077 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
1082 if(opcode == ISCSI_OPCODE_NOP_OUT) {
1084 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1085 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1087 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1088 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1089 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1090 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1091 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1092 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1093 offset = handleHeaderDigest(ti, tvb, offset, 48);
1094 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
1095 } else if(opcode == ISCSI_OPCODE_NOP_IN) {
1097 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1098 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1100 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1101 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1102 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1103 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1104 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1105 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1106 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1107 offset = handleHeaderDigest(ti, tvb, offset, 48);
1108 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
1109 } else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1111 guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
1113 gint b = tvb_get_guint8(tvb, offset + 1);
1114 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1115 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1117 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
1118 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
1119 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
1120 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
1122 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1123 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
1125 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1126 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1127 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1128 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1129 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
1130 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1131 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1134 /* FIXME - disssect AHS? */
1135 proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 48, ahsLen, FALSE);
1137 offset = handleHeaderDigest(ti, tvb, offset, 48 + ahsLen);
1139 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
1140 } else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1143 gint b = tvb_get_guint8(tvb, offset + 1);
1144 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1145 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1147 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
1148 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
1149 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
1150 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
1152 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
1153 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1154 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1155 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1157 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1158 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1159 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1160 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
1162 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1163 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1164 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1165 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1166 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1167 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
1170 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
1171 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
1173 offset = handleHeaderDigest(ti, tvb, offset, 48);
1174 /* do not update offset here because the data segment is
1175 * dissected below */
1176 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1177 } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
1178 /* Task Management Function */
1179 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
1180 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1181 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1182 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1184 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1185 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1186 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1187 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1188 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1189 proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1190 offset = handleHeaderDigest(ti, tvb, offset, 48);
1191 } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1192 /* Task Management Function Response */
1193 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
1194 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1195 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1196 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1198 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1199 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1200 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1202 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1203 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1204 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1205 offset = handleHeaderDigest(ti, tvb, offset, 48);
1206 } else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1208 int digestsActive = 0;
1210 gint b = tvb_get_guint8(tvb, offset + 1);
1211 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1212 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1216 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1217 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1220 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1221 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1222 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1224 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1225 proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1227 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1228 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1230 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1231 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1232 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1233 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1235 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1236 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1237 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1238 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1241 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1242 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1243 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1244 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1245 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1246 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1249 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1250 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1251 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1252 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1253 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1256 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1257 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1260 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1262 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1263 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1264 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1266 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1267 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1269 offset = handleHeaderDigest(ti, tvb, offset, 48);
1272 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1273 } else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1274 /* Login Response */
1275 int digestsActive = 0;
1277 gint b = tvb_get_guint8(tvb, offset + 1);
1278 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1279 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1283 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1284 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1287 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1288 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1289 proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1291 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1292 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1295 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1296 proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1297 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1298 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1300 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1301 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1302 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1305 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1306 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1307 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1308 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1309 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1310 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1313 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1314 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1315 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1316 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1317 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1320 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1321 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1324 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1326 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1327 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1328 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1329 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1330 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1332 offset = handleHeaderDigest(ti, tvb, offset, 48);
1335 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1336 } else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1339 gint b = tvb_get_guint8(tvb, offset + 1);
1340 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1341 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1343 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1344 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1345 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1348 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1349 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 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1353 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1355 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1356 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1357 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1358 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1359 offset = handleHeaderDigest(ti, tvb, offset, 48);
1360 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1361 } else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1364 gint b = tvb_get_guint8(tvb, offset + 1);
1365 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1366 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1368 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1369 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1370 proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1373 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1374 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1376 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1377 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1378 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1380 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1381 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1382 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1383 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1384 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1385 offset = handleHeaderDigest(ti, tvb, offset, 48);
1386 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1387 } else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1388 /* SCSI Data Out (write) */
1390 gint b = tvb_get_guint8(tvb, offset + 1);
1391 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1392 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1394 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1396 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1397 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1399 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1400 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1401 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1402 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1403 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1404 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1405 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1406 offset = handleHeaderDigest(ti, tvb, offset, 48);
1407 /* do not update offset here because the data segment is
1408 * dissected below */
1409 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1410 } else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
1411 /* SCSI Data In (read) */
1413 gint b = tvb_get_guint8(tvb, offset + 1);
1414 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1415 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1417 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1418 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1419 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
1421 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1422 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1423 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1425 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1426 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1427 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1429 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1430 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1431 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1433 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1434 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1435 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1438 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1440 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1441 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1442 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1443 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1444 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1445 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1446 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1448 offset = handleHeaderDigest(ti, tvb, offset, 48);
1449 /* do not update offset here because the data segment is
1450 * dissected below */
1451 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1452 } else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1453 /* Logout Command */
1454 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1455 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 1, 1, FALSE);
1457 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1458 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1459 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1461 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1462 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1463 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1465 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1466 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1467 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1468 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT13) {
1469 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
1472 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1473 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1474 offset = handleHeaderDigest(ti, tvb, offset, 48);
1475 } else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1476 /* Logout Response */
1477 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1478 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1479 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1480 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1482 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1483 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1484 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1485 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1486 proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1487 proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1488 offset = handleHeaderDigest(ti, tvb, offset, 48);
1489 } else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1492 gint b = tvb_get_guint8(tvb, offset + 1);
1494 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1495 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1498 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1500 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1501 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1502 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1503 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1505 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1506 if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1507 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1508 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1509 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1510 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1513 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1514 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1515 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1516 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1518 offset = handleHeaderDigest(ti, tvb, offset, 48);
1519 } else if(opcode == ISCSI_OPCODE_R2T) {
1521 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1522 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1523 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1524 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1526 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1527 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
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_R2TSN, tvb, offset + 36, 4, FALSE);
1532 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1533 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1534 offset = handleHeaderDigest(ti, tvb, offset, 48);
1535 } else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1536 /* Asynchronous Message */
1537 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1538 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1540 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1541 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1542 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1543 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1544 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1545 proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1546 proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1547 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1548 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1549 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1550 offset = handleHeaderDigest(ti, tvb, offset, 48);
1551 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
1552 } else if(opcode == ISCSI_OPCODE_REJECT) {
1554 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
1555 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1556 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1558 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1559 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1560 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1561 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1562 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1563 offset = handleHeaderDigest(ti, tvb, offset, 48);
1564 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1565 } else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
1566 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
1567 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
1568 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
1569 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
1570 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
1571 /* Vendor specific opcodes */
1572 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1573 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1575 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1576 offset = handleHeaderDigest(ti, tvb, offset, 48);
1577 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
1580 proto_item_set_len(ti, offset - original_offset);
1582 if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
1584 ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
1586 dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16, SCSI_DEV_UNKNOWN);
1588 else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1589 if (scsi_status == 0x2) {
1590 /* A SCSI response with Check Condition contains sense data */
1591 /* offset is setup correctly by the iscsi code for response above */
1592 if((end_offset - offset) >= 2) {
1593 int senseLen = tvb_get_ntohs(tvb, offset);
1595 proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1598 dissect_scsi_snsinfo (tvb, pinfo, tree, offset,
1599 iscsi_min (senseLen,
1600 end_offset-offset));
1604 dissect_scsi_rsp (tvb, pinfo, tree);
1607 else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1608 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1609 /* offset is setup correctly by the iscsi code for response above */
1610 dissect_scsi_payload (tvb, pinfo, tree, offset, FALSE,
1611 iscsi_min (data_segment_len, end_offset-offset));
1616 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_port) {
1617 /* Set up structures needed to add the protocol subtree and manage it */
1618 guint iSCSIPdusDissected = 0;
1620 guint32 available_bytes = tvb_length_remaining(tvb, offset);
1622 if (!proto_is_protocol_enabled(proto_iscsi))
1623 return FALSE; /* iSCSI has been disabled */
1625 /* quick check to see if the packet is long enough to contain the
1626 * minimum amount of information we need */
1627 if (available_bytes < 48 && (!iscsi_desegment || available_bytes < 8)) {
1628 /* no, so give up */
1632 /* process multiple iSCSI PDUs per packet */
1633 while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
1634 const char *opcode_str = NULL;
1635 guint32 data_segment_len;
1636 guint8 opcode = tvb_get_guint8(tvb, offset + 0);
1637 guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
1640 /* mask out any extra bits in the opcode byte */
1641 opcode &= OPCODE_MASK;
1643 opcode_str = match_strval(opcode, iscsi_opcodes);
1644 if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
1645 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1646 opcode == ISCSI_OPCODE_R2T ||
1647 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1648 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1649 opcode == ISCSI_OPCODE_SNACK_REQUEST)
1650 data_segment_len = 0;
1652 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
1654 if(opcode_str == NULL) {
1657 else if(check_port && iscsi_port != 0 &&
1658 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
1659 (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
1662 else if(enable_bogosity_filter) {
1663 /* try and distinguish between data and real headers */
1664 if(data_segment_len > bogus_pdu_data_length_threshold) {
1667 else if(demand_good_f_bit &&
1668 !(secondPduByte & 0x80) &&
1669 (opcode == ISCSI_OPCODE_NOP_OUT ||
1670 opcode == ISCSI_OPCODE_NOP_IN ||
1671 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1672 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1673 opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
1674 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1675 opcode == ISCSI_OPCODE_R2T ||
1676 opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
1677 opcode == ISCSI_OPCODE_SNACK_REQUEST ||
1678 opcode == ISCSI_OPCODE_REJECT)) {
1680 } else if(opcode==ISCSI_OPCODE_NOP_OUT) {
1681 /* TransferTag for NOP-Out should either be -1 or
1682 the tag value we want for a response.
1683 Assume 0 means we are just inside a big all zero
1686 if(tvb_get_ntohl(tvb, offset+20)==0){
1693 return iSCSIPdusDissected > 0;
1696 guint32 pduLen = 48;
1697 int digestsActive = 1;
1699 if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
1700 opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1701 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1702 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
1703 /* digests are not yet turned on */
1712 if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1714 pduLen += tvb_get_guint8(tvb, offset + 4) * 4;
1717 pduLen += data_segment_len;
1718 if((pduLen & 3) != 0)
1719 pduLen += 4 - (pduLen & 3);
1721 if(digestsActive && enableHeaderDigests) {
1722 if(headerDigestIsCRC32)
1725 pduLen += headerDigestSize;
1728 if(digestsActive && data_segment_len > 0 && enableDataDigests) {
1729 if(dataDigestIsCRC32)
1732 pduLen += dataDigestSize;
1736 * Desegmentation check.
1738 if(iscsi_desegment && pinfo->can_desegment) {
1739 if(pduLen > available_bytes) {
1741 * This frame doesn't have all of the data for
1742 * this message, but we can do reassembly on it.
1744 * Tell the TCP dissector where the data for this
1745 * message starts in the data it handed us, and
1746 * how many more bytes we need, and return.
1748 pinfo->desegment_offset = offset;
1749 pinfo->desegment_len = pduLen - available_bytes;
1754 /* This is to help TCP keep track of PDU boundaries
1755 and allows it to find PDUs that are not aligned to
1756 the start of a TCP segments.
1757 Since it also allows TCP to know what is in the middle
1758 of a large PDU, it reduces the probability of a segment
1759 in the middle of a large PDU transfer being misdissected as
1762 if(!pinfo->fd->flags.visited){
1763 if(pduLen>(guint32)tvb_reported_length_remaining(tvb, offset)){
1764 pinfo->want_pdu_tracking=2;
1765 pinfo->bytes_until_next_pdu=pduLen-tvb_reported_length_remaining(tvb, offset);
1769 if(check_col(pinfo->cinfo, COL_INFO)) {
1770 if(iSCSIPdusDissected == 0)
1771 col_set_str(pinfo->cinfo, COL_INFO, "");
1773 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1776 dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len);
1777 if(pduLen > available_bytes)
1778 pduLen = available_bytes;
1780 available_bytes -= pduLen;
1781 ++iSCSIPdusDissected;
1785 return iSCSIPdusDissected > 0;
1788 /* This is called for those sessions where we have explicitely said
1789 this to be iSCSI using "Decode As..."
1790 In this case we will not check the port number for sanity and just
1791 do as the user said.
1794 dissect_iscsi_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1795 dissect_iscsi(tvb, pinfo, tree, FALSE);
1798 /* This is called through the heuristic handler.
1799 In this case we also want to check that the port matches the preference
1800 setting for iSCSI in order to reduce the number of
1804 dissect_iscsi_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1805 return dissect_iscsi(tvb, pinfo, tree, TRUE);
1809 /* Register the protocol with Ethereal */
1812 * this format is require because a script is used to build the C
1813 * function that calls all the protocol registration.
1817 proto_register_iscsi(void)
1820 /* Setup list of header fields See Section 1.6.1 for details*/
1821 static hf_register_info hf[] = {
1822 { &hf_iscsi_request_frame,
1823 { "Request in", "iscsi.request_frame",
1824 FT_FRAMENUM, BASE_NONE, NULL, 0,
1825 "The request to this transaction is in this frame", HFILL }},
1828 { "Time from request", "iscsi.time",
1829 FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
1830 "Time between the Command and the Response", HFILL }},
1832 { &hf_iscsi_data_in_frame,
1833 { "Data In in", "iscsi.data_in_frame",
1834 FT_FRAMENUM, BASE_NONE, NULL, 0,
1835 "The Data In for this transaction is in this frame", HFILL }},
1837 { &hf_iscsi_data_out_frame,
1838 { "Data Out in", "iscsi.data_out_frame",
1839 FT_FRAMENUM, BASE_NONE, NULL, 0,
1840 "The Data Out for this transaction is in this frame", HFILL }},
1842 { &hf_iscsi_response_frame,
1843 { "Response in", "iscsi.response_frame",
1844 FT_FRAMENUM, BASE_NONE, NULL, 0,
1845 "The response to this transaction is in this frame", HFILL }},
1848 { "AHS", "iscsi.ahs",
1849 FT_BYTES, BASE_HEX, NULL, 0,
1850 "Additional header segment", HFILL }
1852 { &hf_iscsi_Padding,
1853 { "Padding", "iscsi.padding",
1854 FT_BYTES, BASE_HEX, NULL, 0,
1855 "Padding to 4 byte boundary", HFILL }
1857 { &hf_iscsi_ping_data,
1858 { "PingData", "iscsi.pingdata",
1859 FT_BYTES, BASE_HEX, NULL, 0,
1860 "Ping Data", HFILL }
1862 { &hf_iscsi_immediate_data,
1863 { "ImmediateData", "iscsi.immediatedata",
1864 FT_BYTES, BASE_HEX, NULL, 0,
1865 "Immediate Data", HFILL }
1867 { &hf_iscsi_write_data,
1868 { "WriteData", "iscsi.writedata",
1869 FT_BYTES, BASE_HEX, NULL, 0,
1870 "Write Data", HFILL }
1872 { &hf_iscsi_read_data,
1873 { "ReadData", "iscsi.readdata",
1874 FT_BYTES, BASE_HEX, NULL, 0,
1875 "Read Data", HFILL }
1877 { &hf_iscsi_error_pdu_data,
1878 { "ErrorPDUData", "iscsi.errorpdudata",
1879 FT_BYTES, BASE_HEX, NULL, 0,
1880 "Error PDU Data", HFILL }
1882 { &hf_iscsi_async_message_data,
1883 { "AsyncMessageData", "iscsi.asyncmessagedata",
1884 FT_BYTES, BASE_HEX, NULL, 0,
1885 "Async Message Data", HFILL }
1887 { &hf_iscsi_vendor_specific_data,
1888 { "VendorSpecificData", "iscsi.vendorspecificdata",
1889 FT_BYTES, BASE_HEX, NULL, 0,
1890 "Vendor Specific Data", HFILL }
1892 { &hf_iscsi_HeaderDigest,
1893 { "HeaderDigest", "iscsi.headerdigest",
1894 FT_BYTES, BASE_HEX, NULL, 0,
1895 "Header Digest", HFILL }
1897 { &hf_iscsi_HeaderDigest32,
1898 { "HeaderDigest", "iscsi.headerdigest32",
1899 FT_UINT32, BASE_HEX, NULL, 0,
1900 "Header Digest", HFILL }
1902 { &hf_iscsi_DataDigest,
1903 { "DataDigest", "iscsi.datadigest",
1904 FT_BYTES, BASE_HEX, NULL, 0,
1905 "Data Digest", HFILL }
1907 { &hf_iscsi_DataDigest32,
1908 { "DataDigest", "iscsi.datadigest32",
1909 FT_UINT32, BASE_HEX, NULL, 0,
1910 "Data Digest", HFILL }
1913 { "Opcode", "iscsi.opcode",
1914 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
1917 /* #ifdef DRAFT08 */
1920 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1921 "Command Retry", HFILL }
1926 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
1927 "Immediate delivery", HFILL }
1930 { "Flags", "iscsi.flags",
1931 FT_UINT8, BASE_HEX, NULL, 0,
1932 "Opcode specific flags", HFILL }
1934 { &hf_iscsi_SCSICommand_F,
1935 { "F", "iscsi.scsicommand.F",
1936 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1937 "PDU completes command", HFILL }
1939 { &hf_iscsi_SCSICommand_R,
1940 { "R", "iscsi.scsicommand.R",
1941 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
1942 "Command reads from SCSI target", HFILL }
1944 { &hf_iscsi_SCSICommand_W,
1945 { "W", "iscsi.scsicommand.W",
1946 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
1947 "Command writes to SCSI target", HFILL }
1949 { &hf_iscsi_SCSICommand_Attr,
1950 { "Attr", "iscsi.scsicommand.attr",
1951 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
1952 "SCSI task attributes", HFILL }
1954 { &hf_iscsi_SCSICommand_CRN,
1955 { "CRN", "iscsi.scsicommand.crn",
1956 FT_UINT8, BASE_HEX, NULL, 0,
1957 "SCSI command reference number", HFILL }
1959 { &hf_iscsi_SCSICommand_AddCDB,
1960 { "AddCDB", "iscsi.scsicommand.addcdb",
1961 FT_UINT8, BASE_HEX, NULL, 0,
1962 "Additional CDB length (in 4 byte units)", HFILL }
1964 { &hf_iscsi_DataSegmentLength,
1965 { "DataSegmentLength", "iscsi.datasegmentlength",
1966 FT_UINT32, BASE_HEX, NULL, 0,
1967 "Data segment length (bytes)", HFILL }
1969 { &hf_iscsi_TotalAHSLength,
1970 { "TotalAHSLength", "iscsi.totalahslength",
1971 FT_UINT8, BASE_HEX, NULL, 0,
1972 "Total additional header segment length (4 byte words)", HFILL }
1975 { "LUN", "iscsi.lun",
1976 FT_BYTES, BASE_HEX, NULL, 0,
1977 "Logical Unit Number", HFILL }
1979 { &hf_iscsi_InitiatorTaskTag,
1980 { "InitiatorTaskTag", "iscsi.initiatortasktag",
1981 FT_UINT32, BASE_HEX, NULL, 0,
1982 "Initiator's task tag", HFILL }
1984 { &hf_iscsi_ExpectedDataTransferLength,
1985 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
1986 FT_UINT32, BASE_HEX, NULL, 0,
1987 "Expected length of data transfer", HFILL }
1990 { "CmdSN", "iscsi.cmdsn",
1991 FT_UINT32, BASE_HEX, NULL, 0,
1992 "Sequence number for this command", HFILL }
1994 { &hf_iscsi_ExpStatSN,
1995 { "ExpStatSN", "iscsi.expstatsn",
1996 FT_UINT32, BASE_HEX, NULL, 0,
1997 "Next expected status sequence number", HFILL }
1999 { &hf_iscsi_SCSIResponse_ResidualCount,
2000 { "ResidualCount", "iscsi.scsiresponse.residualcount",
2001 FT_UINT32, BASE_HEX, NULL, 0,
2002 "Residual count", HFILL }
2005 { "StatSN", "iscsi.statsn",
2006 FT_UINT32, BASE_HEX, NULL, 0,
2007 "Status sequence number", HFILL }
2009 { &hf_iscsi_ExpCmdSN,
2010 { "ExpCmdSN", "iscsi.expcmdsn",
2011 FT_UINT32, BASE_HEX, NULL, 0,
2012 "Next expected command sequence number", HFILL }
2014 { &hf_iscsi_MaxCmdSN,
2015 { "MaxCmdSN", "iscsi.maxcmdsn",
2016 FT_UINT32, BASE_HEX, NULL, 0,
2017 "Maximum acceptable command sequence number", HFILL }
2019 { &hf_iscsi_SCSIResponse_o,
2020 { "o", "iscsi.scsiresponse.o",
2021 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
2022 "Bi-directional read residual overflow", HFILL }
2024 { &hf_iscsi_SCSIResponse_u,
2025 { "u", "iscsi.scsiresponse.u",
2026 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
2027 "Bi-directional read residual underflow", HFILL }
2029 { &hf_iscsi_SCSIResponse_O,
2030 { "O", "iscsi.scsiresponse.O",
2031 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
2032 "Residual overflow", HFILL }
2034 { &hf_iscsi_SCSIResponse_U,
2035 { "U", "iscsi.scsiresponse.U",
2036 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
2037 "Residual underflow", HFILL }
2039 { &hf_iscsi_SCSIResponse_Status,
2040 { "Status", "iscsi.scsiresponse.status",
2041 FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
2042 "SCSI command status value", HFILL }
2044 { &hf_iscsi_SCSIResponse_Response,
2045 { "Response", "iscsi.scsiresponse.response",
2046 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
2047 "SCSI command response value", HFILL }
2049 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
2050 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
2051 FT_UINT32, BASE_HEX, NULL, 0,
2052 "Bi-directional read residual count", HFILL }
2054 { &hf_iscsi_SenseLength,
2055 { "SenseLength", "iscsi.scsiresponse.senselength",
2056 FT_UINT16, BASE_HEX, NULL, 0,
2057 "Sense data length", HFILL }
2059 { &hf_iscsi_SCSIData_F,
2060 { "F", "iscsi.scsidata.F",
2061 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
2062 "Final PDU", HFILL }
2064 { &hf_iscsi_SCSIData_A,
2065 { "A", "iscsi.scsidata.A",
2066 FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
2067 "Acknowledge Requested", HFILL }
2069 { &hf_iscsi_SCSIData_S,
2070 { "S", "iscsi.scsidata.S",
2071 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
2072 "PDU Contains SCSI command status", HFILL }
2074 { &hf_iscsi_SCSIData_U,
2075 { "U", "iscsi.scsidata.U",
2076 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
2077 "Residual underflow", HFILL }
2079 { &hf_iscsi_SCSIData_O,
2080 { "O", "iscsi.scsidata.O",
2081 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
2082 "Residual overflow", HFILL }
2084 { &hf_iscsi_TargetTransferTag,
2085 { "TargetTransferTag", "iscsi.targettransfertag",
2086 FT_UINT32, BASE_HEX, NULL, 0,
2087 "Target transfer tag", HFILL }
2089 { &hf_iscsi_BufferOffset,
2090 { "BufferOffset", "iscsi.bufferOffset",
2091 FT_UINT32, BASE_HEX, NULL, 0,
2092 "Buffer offset", HFILL }
2094 { &hf_iscsi_SCSIData_ResidualCount,
2095 { "ResidualCount", "iscsi.scsidata.readresidualcount",
2096 FT_UINT32, BASE_HEX, NULL, 0,
2097 "Residual count", HFILL }
2100 { "DataSN", "iscsi.datasn",
2101 FT_UINT32, BASE_HEX, NULL, 0,
2102 "Data sequence number", HFILL }
2104 { &hf_iscsi_VersionMax,
2105 { "VersionMax", "iscsi.versionmax",
2106 FT_UINT8, BASE_HEX, NULL, 0,
2107 "Maximum supported protocol version", HFILL }
2109 { &hf_iscsi_VersionMin,
2110 { "VersionMin", "iscsi.versionmin",
2111 FT_UINT8, BASE_HEX, NULL, 0,
2112 "Minimum supported protocol version", HFILL }
2114 { &hf_iscsi_VersionActive,
2115 { "VersionActive", "iscsi.versionactive",
2116 FT_UINT8, BASE_HEX, NULL, 0,
2117 "Negotiated protocol version", HFILL }
2120 { "CID", "iscsi.cid",
2121 FT_UINT16, BASE_HEX, NULL, 0,
2122 "Connection identifier", HFILL }
2124 /* #ifdef DRAFT08 */
2126 { "ISID", "iscsi.isid",
2127 FT_UINT16, BASE_HEX, NULL, 0,
2128 "Initiator part of session identifier", HFILL }
2132 { "ISID", "iscsi.isid",
2133 FT_BYTES, BASE_HEX, NULL, 0,
2134 "Initiator part of session identifier", HFILL }
2136 /* #ifdef DRAFT09 */
2137 { &hf_iscsi_ISID_Type,
2138 { "ISID_Type", "iscsi.isid.type",
2139 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
2140 "Initiator part of session identifier - type", HFILL }
2142 { &hf_iscsi_ISID_NamingAuthority,
2143 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
2144 FT_UINT24, BASE_HEX, NULL, 0,
2145 "Initiator part of session identifier - naming authority", HFILL }
2147 { &hf_iscsi_ISID_Qualifier,
2148 { "ISID_Qualifier", "iscsi.isid.qualifier",
2149 FT_UINT8, BASE_HEX, NULL, 0,
2150 "Initiator part of session identifier - qualifier", HFILL }
2154 { "ISID_t", "iscsi.isid.t",
2155 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
2156 "Initiator part of session identifier - t", HFILL }
2159 { "ISID_a", "iscsi.isid.a",
2160 FT_UINT8, BASE_HEX, NULL, 0x3f,
2161 "Initiator part of session identifier - a", HFILL }
2164 { "ISID_b", "iscsi.isid.b",
2165 FT_UINT16, BASE_HEX, NULL, 0,
2166 "Initiator part of session identifier - b", HFILL }
2169 { "ISID_c", "iscsi.isid.c",
2170 FT_UINT8, BASE_HEX, NULL, 0,
2171 "Initiator part of session identifier - c", HFILL }
2174 { "ISID_d", "iscsi.isid.d",
2175 FT_UINT16, BASE_HEX, NULL, 0,
2176 "Initiator part of session identifier - d", HFILL }
2181 { "TSID", "iscsi.tsid",
2182 FT_UINT16, BASE_HEX, NULL, 0,
2183 "Target part of session identifier", HFILL }
2186 { "TSIH", "iscsi.tsih",
2187 FT_UINT16, BASE_HEX, NULL, 0,
2188 "Target session identifying handle", HFILL }
2190 { &hf_iscsi_InitStatSN,
2191 { "InitStatSN", "iscsi.initstatsn",
2192 FT_UINT32, BASE_HEX, NULL, 0,
2193 "Initial status sequence number", HFILL }
2195 { &hf_iscsi_InitCmdSN,
2196 { "InitCmdSN", "iscsi.initcmdsn",
2197 FT_UINT32, BASE_HEX, NULL, 0,
2198 "Initial command sequence number", HFILL }
2200 { &hf_iscsi_Login_T,
2201 { "T", "iscsi.login.T",
2202 FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
2203 "Transit to next login stage", HFILL }
2205 { &hf_iscsi_Login_C,
2206 { "C", "iscsi.login.C",
2207 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2208 "Text incomplete", HFILL }
2210 /* #ifdef DRAFT09 */
2211 { &hf_iscsi_Login_X,
2212 { "X", "iscsi.login.X",
2213 FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
2214 "Restart Connection", HFILL }
2217 { &hf_iscsi_Login_CSG,
2218 { "CSG", "iscsi.login.csg",
2219 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
2220 "Current stage", HFILL }
2222 { &hf_iscsi_Login_NSG,
2223 { "NSG", "iscsi.login.nsg",
2224 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
2225 "Next stage", HFILL }
2227 { &hf_iscsi_Login_Status,
2228 { "Status", "iscsi.login.status",
2229 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
2230 "Status class and detail", HFILL }
2232 { &hf_iscsi_KeyValue,
2233 { "KeyValue", "iscsi.keyvalue",
2234 FT_STRING, 0, NULL, 0,
2235 "Key/value pair", HFILL }
2238 { "F", "iscsi.text.F",
2239 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2240 "Final PDU in text sequence", HFILL }
2243 { "C", "iscsi.text.C",
2244 FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2245 "Text incomplete", HFILL }
2247 { &hf_iscsi_ExpDataSN,
2248 { "ExpDataSN", "iscsi.expdatasn",
2249 FT_UINT32, BASE_HEX, NULL, 0,
2250 "Next expected data sequence number", HFILL }
2253 { "R2TSN", "iscsi.r2tsn",
2254 FT_UINT32, BASE_HEX, NULL, 0,
2255 "R2T PDU Number", HFILL }
2257 { &hf_iscsi_TaskManagementFunction_Response,
2258 { "Response", "iscsi.taskmanfun.response",
2259 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
2262 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
2263 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
2264 FT_UINT32, BASE_HEX, NULL, 0,
2265 "Referenced task tag", HFILL }
2267 { &hf_iscsi_RefCmdSN,
2268 { "RefCmdSN", "iscsi.refcmdsn",
2269 FT_UINT32, BASE_HEX, NULL, 0,
2270 "Command sequence number for command to be aborted", HFILL }
2272 { &hf_iscsi_TaskManagementFunction_Function,
2273 { "Function", "iscsi.taskmanfun.function",
2274 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
2275 "Requested task function", HFILL }
2277 { &hf_iscsi_Logout_Reason,
2278 { "Reason", "iscsi.logout.reason",
2279 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0x7F,
2280 "Reason for logout", HFILL }
2282 { &hf_iscsi_Logout_Response,
2283 { "Response", "iscsi.logout.response",
2284 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
2285 "Logout response", HFILL }
2287 { &hf_iscsi_Time2Wait,
2288 { "Time2Wait", "iscsi.time2wait",
2289 FT_UINT16, BASE_HEX, NULL, 0,
2290 "Time2Wait", HFILL }
2292 { &hf_iscsi_Time2Retain,
2293 { "Time2Retain", "iscsi.time2retain",
2294 FT_UINT16, BASE_HEX, NULL, 0,
2295 "Time2Retain", HFILL }
2297 { &hf_iscsi_DesiredDataLength,
2298 { "DesiredDataLength", "iscsi.desireddatalength",
2299 FT_UINT32, BASE_HEX, NULL, 0,
2300 "Desired data length (bytes)", HFILL }
2302 { &hf_iscsi_AsyncEvent,
2303 { "AsyncEvent", "iscsi.asyncevent",
2304 FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2305 "Async event type", HFILL }
2307 { &hf_iscsi_EventVendorCode,
2308 { "EventVendorCode", "iscsi.eventvendorcode",
2309 FT_UINT8, BASE_HEX, NULL, 0,
2310 "Event vendor code", HFILL }
2312 { &hf_iscsi_Parameter1,
2313 { "Parameter1", "iscsi.parameter1",
2314 FT_UINT16, BASE_HEX, NULL, 0,
2315 "Parameter 1", HFILL }
2317 { &hf_iscsi_Parameter2,
2318 { "Parameter2", "iscsi.parameter2",
2319 FT_UINT16, BASE_HEX, NULL, 0,
2320 "Parameter 2", HFILL }
2322 { &hf_iscsi_Parameter3,
2323 { "Parameter3", "iscsi.parameter3",
2324 FT_UINT16, BASE_HEX, NULL, 0,
2325 "Parameter 3", HFILL }
2327 { &hf_iscsi_Reject_Reason,
2328 { "Reason", "iscsi.reject.reason",
2329 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2330 "Reason for command rejection", HFILL }
2332 { &hf_iscsi_snack_type,
2333 { "S", "iscsi.snack.type",
2334 FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2335 "Type of SNACK requested", HFILL }
2338 { "BegRun", "iscsi.snack.begrun",
2339 FT_UINT32, BASE_HEX, NULL, 0,
2340 "First missed DataSN or StatSN", HFILL }
2342 { &hf_iscsi_RunLength,
2343 { "RunLength", "iscsi.snack.runlength",
2344 FT_UINT32, BASE_HEX, NULL, 0,
2345 "Number of additional missing status PDUs in this run", HFILL }
2349 /* Setup protocol subtree array */
2350 static gint *ett[] = {
2352 &ett_iscsi_KeyValues,
2355 /* #ifndef DRAFT08 */
2360 /* Register the protocol name and description */
2361 proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2363 /* Required function calls to register the header fields and
2365 proto_register_field_array(proto_iscsi, hf, array_length(hf));
2366 proto_register_subtree_array(ett, array_length(ett));
2367 register_init_routine (&iscsi_init_protocol);
2370 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2372 prefs_register_enum_preference(iscsi_module,
2375 "The iSCSI protocol version",
2376 &iscsi_protocol_version,
2377 iscsi_protocol_versions,
2380 prefs_register_bool_preference(iscsi_module,
2381 "desegment_iscsi_messages",
2382 "Desegment iSCSI messages",
2383 "When enabled, iSCSI messages that span multiple TCP segments are desegmented",
2386 prefs_register_bool_preference(iscsi_module,
2388 "Enable bogus pdu filter",
2389 "When enabled, packets that appear bogus are ignored",
2390 &enable_bogosity_filter);
2392 prefs_register_bool_preference(iscsi_module,
2393 "demand_good_f_bit",
2394 "Ignore packets with bad F bit",
2395 "Ignore packets that haven't set the F bit when they should have",
2396 &demand_good_f_bit);
2398 prefs_register_uint_preference(iscsi_module,
2399 "bogus_pdu_max_data_len",
2400 "Bogus pdu max data length threshold",
2401 "Treat packets whose data segment length is greater than this value as bogus",
2403 &bogus_pdu_data_length_threshold);
2406 prefs_register_uint_preference(iscsi_module,
2409 "Port number of iSCSI target",
2413 prefs_register_bool_preference(iscsi_module,
2414 "enable_header_digests",
2415 "Enable header digests",
2416 "When enabled, pdus are assumed to contain a header digest",
2417 &enableHeaderDigests);
2418 prefs_register_bool_preference(iscsi_module,
2419 "enable_data_digests",
2420 "Enable data digests",
2421 "When enabled, pdus are assumed to contain a data digest",
2422 &enableDataDigests);
2424 prefs_register_bool_preference(iscsi_module,
2425 "header_digest_is_crc32c",
2426 "Header digest is CRC32C",
2427 "When enabled, header digests are assumed to be CRC32C",
2428 &headerDigestIsCRC32);
2429 prefs_register_bool_preference(iscsi_module,
2430 "data_digest_is_crc32c",
2431 "Data digest is CRC32C",
2432 "When enabled, data digests are assumed to be CRC32C",
2433 &dataDigestIsCRC32);
2435 prefs_register_uint_preference(iscsi_module,
2436 "header_digest_size",
2437 "Header digest size",
2438 "The size of a header digest (bytes)",
2441 prefs_register_uint_preference(iscsi_module,
2444 "The size of a data digest (bytes)",
2448 /* Preference supported in older versions.
2449 Register them as obsolete. */
2450 prefs_register_obsolete_preference(iscsi_module,
2451 "version_03_compatible");
2452 prefs_register_obsolete_preference(iscsi_module,
2453 "bogus_pdu_max_digest_padding");
2459 * If this dissector uses sub-dissector registration add a
2460 * registration routine.
2464 * This format is required because a script is used to find these
2465 * routines and create the code that calls these routines.
2468 proto_reg_handoff_iscsi(void)
2470 dissector_handle_t iscsi_handle;
2472 heur_dissector_add("tcp", dissect_iscsi_heur, proto_iscsi);
2474 iscsi_handle = create_dissector_handle(dissect_iscsi_handle, proto_iscsi);
2475 dissector_add_handle("tcp.port", iscsi_handle);