2 * Routines for iSCSI dissection
3 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
5 * Conforms to the protocol described in: draft-ietf-ips-iscsi-11.txt
6 * Optionally, may be compiled for compatibility with
7 * draft-ietf-ips-iscsi-09.txt by defining DRAFT09
8 * draft-ietf-ips-iscsi-08.txt by defining DRAFT08
10 * $Id: packet-iscsi.c,v 1.30 2002/04/29 08:20:08 guy Exp $
12 * Ethereal - Network traffic analyzer
13 * By Gerald Combs <gerald@ethereal.com>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 * Until the iSCSI standard reaches non-draft status, support for
33 * selected legacy versions of the draft standard can be enabled using
34 * #define DRAFTdd where dd can, currently, be either 08 or 09
45 #ifdef HAVE_SYS_TYPES_H
46 # include <sys/types.h>
49 #ifdef HAVE_NETINET_IN_H
50 # include <netinet/in.h>
55 #ifdef NEED_SNPRINTF_H
56 # include "snprintf.h"
59 #include <epan/packet.h>
61 #include <epan/conversation.h>
62 #include "packet-scsi.h"
64 static gboolean iscsi_desegment = TRUE;
66 static int demand_good_f_bit = FALSE;
67 static int enable_bogosity_filter = TRUE;
68 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
70 static int enableDataDigests = FALSE;
71 static int enableHeaderDigests = FALSE;
73 static int dataDigestIsCRC32 = TRUE;
74 static int headerDigestIsCRC32 = TRUE;
76 static int dataDigestSize = 4;
77 static int headerDigestSize = 4;
79 static guint iscsi_port = 3260;
81 /* Initialize the protocol and registered fields */
82 static int proto_iscsi = -1;
83 static int hf_iscsi_AHS = -1;
84 static int hf_iscsi_Padding = -1;
85 static int hf_iscsi_ping_data = -1;
86 static int hf_iscsi_immediate_data = -1;
87 static int hf_iscsi_write_data = -1;
88 static int hf_iscsi_read_data = -1;
89 static int hf_iscsi_error_pdu_data = -1;
90 static int hf_iscsi_Opcode = -1;
91 static int hf_iscsi_Flags = -1;
92 static int hf_iscsi_HeaderDigest = -1;
93 static int hf_iscsi_HeaderDigest32 = -1;
94 static int hf_iscsi_DataDigest = -1;
95 static int hf_iscsi_DataDigest32 = -1;
97 static int hf_iscsi_X = -1;
99 static int hf_iscsi_I = -1;
100 static int hf_iscsi_SCSICommand_F = -1;
101 static int hf_iscsi_SCSICommand_R = -1;
102 static int hf_iscsi_SCSICommand_W = -1;
103 static int hf_iscsi_SCSICommand_Attr = -1;
104 static int hf_iscsi_SCSICommand_CRN = -1;
105 static int hf_iscsi_SCSICommand_AddCDB = -1;
106 static int hf_iscsi_DataSegmentLength = -1;
107 static int hf_iscsi_TotalAHSLength = -1;
108 static int hf_iscsi_LUN = -1;
109 static int hf_iscsi_InitiatorTaskTag = -1;
110 static int hf_iscsi_ExpectedDataTransferLength = -1;
111 static int hf_iscsi_CmdSN = -1;
112 static int hf_iscsi_ExpStatSN = -1;
113 static int hf_iscsi_StatSN = -1;
114 static int hf_iscsi_ExpCmdSN = -1;
115 static int hf_iscsi_MaxCmdSN = -1;
116 static int hf_iscsi_SCSIResponse_o = -1;
117 static int hf_iscsi_SCSIResponse_u = -1;
118 static int hf_iscsi_SCSIResponse_O = -1;
119 static int hf_iscsi_SCSIResponse_U = -1;
120 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
121 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
122 static int hf_iscsi_SCSIResponse_Response = -1;
123 static int hf_iscsi_SCSIResponse_Status = -1;
124 static int hf_iscsi_SenseLength = -1;
125 static int hf_iscsi_SCSIData_F = -1;
126 static int hf_iscsi_SCSIData_S = -1;
127 static int hf_iscsi_SCSIData_O = -1;
128 static int hf_iscsi_SCSIData_U = -1;
129 static int hf_iscsi_TargetTransferTag = -1;
130 static int hf_iscsi_DataSN = -1;
131 static int hf_iscsi_BufferOffset = -1;
132 static int hf_iscsi_SCSIData_ResidualCount = -1;
133 static int hf_iscsi_VersionMin = -1;
134 static int hf_iscsi_VersionMax = -1;
135 static int hf_iscsi_VersionActive = -1;
136 static int hf_iscsi_CID = -1;
137 static int hf_iscsi_ISID = -1;
139 static int hf_iscsi_ISID_Type = -1;
140 static int hf_iscsi_ISID_NamingAuthority = -1;
141 static int hf_iscsi_ISID_Qualifier = -1;
142 #elif !defined(DRAFT08)
143 static int hf_iscsi_ISID_t = -1;
144 static int hf_iscsi_ISID_a = -1;
145 static int hf_iscsi_ISID_b = -1;
146 static int hf_iscsi_ISID_c = -1;
147 static int hf_iscsi_ISID_d = -1;
149 static int hf_iscsi_TSID = -1;
150 static int hf_iscsi_InitStatSN = -1;
151 static int hf_iscsi_InitCmdSN = -1;
153 static int hf_iscsi_Login_X = -1;
155 static int hf_iscsi_Login_T = -1;
156 static int hf_iscsi_Login_CSG = -1;
157 static int hf_iscsi_Login_NSG = -1;
158 #ifdef ISCSI_UNUSED_HANDLES
159 static int hf_iscsi_Login_Stage = -1;
161 static int hf_iscsi_Login_Status = -1;
162 static int hf_iscsi_KeyValue = -1;
163 static int hf_iscsi_Text_F = -1;
164 static int hf_iscsi_ExpDataSN = -1;
165 static int hf_iscsi_R2TSN = -1;
166 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
167 static int hf_iscsi_RefCmdSN = -1;
168 static int hf_iscsi_TaskManagementFunction_Function = -1;
169 static int hf_iscsi_TaskManagementFunction_Response = -1;
170 static int hf_iscsi_Logout_Reason = -1;
171 static int hf_iscsi_Logout_Response = -1;
172 static int hf_iscsi_Time2Wait = -1;
173 static int hf_iscsi_Time2Retain = -1;
174 static int hf_iscsi_DesiredDataLength = -1;
175 static int hf_iscsi_AsyncEvent = -1;
176 static int hf_iscsi_EventVendorCode = -1;
177 static int hf_iscsi_Parameter1 = -1;
178 static int hf_iscsi_Parameter2 = -1;
179 static int hf_iscsi_Parameter3 = -1;
180 static int hf_iscsi_Reject_Reason = -1;
181 static int hf_iscsi_snack_type = -1;
182 static int hf_iscsi_BegRun = -1;
183 static int hf_iscsi_RunLength = -1;
185 /* Initialize the subtree pointers */
186 static gint ett_iscsi = -1;
187 static gint ett_iscsi_KeyValues = -1;
188 static gint ett_iscsi_CDB = -1;
189 static gint ett_iscsi_Flags = -1;
191 static gint ett_iscsi_ISID = -1;
194 typedef struct _iscsi_conv_key {
199 typedef struct _iscsi_conv_data {
205 static GHashTable *iscsi_req_hash = NULL;
206 static GMemChunk *iscsi_req_keys = NULL;
207 static GMemChunk *iscsi_req_vals = NULL;
208 static guint32 iscsi_init_count = 25;
215 #define OPCODE_MASK 0x3f
217 #define TARGET_OPCODE_BIT 0x20
219 #define ISCSI_OPCODE_NOP_OUT 0x00
220 #define ISCSI_OPCODE_SCSI_COMMAND 0x01
221 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
222 #define ISCSI_OPCODE_LOGIN_COMMAND 0x03
223 #define ISCSI_OPCODE_TEXT_COMMAND 0x04
224 #define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
225 #define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
226 #define ISCSI_OPCODE_SNACK_REQUEST 0x10
228 #define ISCSI_OPCODE_NOP_IN 0x20
229 #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
230 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
231 #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
232 #define ISCSI_OPCODE_TEXT_RESPONSE 0x24
233 #define ISCSI_OPCODE_SCSI_DATA_IN 0x25
234 #define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
235 #define ISCSI_OPCODE_R2T 0x31
236 #define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
237 #define ISCSI_OPCODE_REJECT 0x3f
240 #define CSG_MASK (0x03 << CSG_SHIFT)
241 #define NSG_MASK 0x03
243 #define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
244 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
245 #define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
247 #define ISCSI_SCSI_DATA_FLAG_S 0x01
248 #define ISCSI_SCSI_DATA_FLAG_U 0x02
249 #define ISCSI_SCSI_DATA_FLAG_O 0x04
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" },
262 { ISCSI_OPCODE_NOP_IN, "NOP In" },
263 { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
264 { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
265 { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
266 { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
267 { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
268 { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
269 { ISCSI_OPCODE_R2T, "Ready To Transfer" },
270 { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
271 { ISCSI_OPCODE_REJECT, "Reject"},
276 static const true_false_string iscsi_meaning_X = {
283 static const true_false_string iscsi_meaning_login_X = {
284 "Reinstate failed connection",
289 static const true_false_string iscsi_meaning_I = {
290 "Immediate delivery",
294 static const true_false_string iscsi_meaning_F = {
295 "Final PDU in sequence",
296 "Not final PDU in sequence"
299 static const true_false_string iscsi_meaning_T = {
300 "Transit to next login stage",
301 "Stay in current login stage"
304 static const true_false_string iscsi_meaning_S = {
305 "Response contains SCSI status",
306 "Response does not contain SCSI status"
309 static const true_false_string iscsi_meaning_R = {
310 "Data will be read from target",
311 "No data will be read from target"
314 static const true_false_string iscsi_meaning_W = {
315 "Data will be written to target",
316 "No data will be written to target"
319 static const true_false_string iscsi_meaning_o = {
320 "Read part of bi-directional command overflowed",
321 "No overflow of read part of bi-directional command",
324 static const true_false_string iscsi_meaning_u = {
325 "Read part of bi-directional command underflowed",
326 "No underflow of read part of bi-directional command",
329 static const true_false_string iscsi_meaning_O = {
330 "Residual overflow occurred",
331 "No residual overflow occurred",
334 static const true_false_string iscsi_meaning_U = {
335 "Residual underflow occurred",
336 "No residual underflow occurred",
339 static const value_string iscsi_scsi_responses[] = {
340 { 0, "Command completed at target" },
341 { 1, "Response does not contain SCSI status"},
345 static const value_string iscsi_scsicommand_taskattrs[] = {
349 {3, "Head of Queue"},
354 static const value_string iscsi_task_management_responses[] = {
355 {0, "Function complete"},
356 {1, "Task not in task set"},
357 {2, "LUN does not exist"},
358 {3, "Task still allegiant"},
359 {4, "Task failover not supported"},
360 {5, "Task management function not supported"},
361 {6, "Authorisation failed"},
362 {255, "Function rejected"},
366 static const value_string iscsi_task_management_functions[] = {
368 {2, "Abort Task Set"},
370 {4, "Clear Task Set"},
371 {5, "Logical Unit Reset"},
372 {6, "Target Warm Reset"},
373 {7, "Target Cold Reset"},
377 static const value_string iscsi_login_status[] = {
379 {0x0101, "Target moved temporarily"},
380 {0x0102, "Target moved permanently"},
381 {0x0200, "Initiator error (miscellaneous error)"},
382 {0x0201, "Athentication failed"},
383 {0x0202, "Authorisation failure"},
384 {0x0203, "Target not found"},
385 {0x0204, "Target removed"},
386 {0x0205, "Unsupported version"},
387 {0x0206, "Too many connections"},
388 {0x0207, "Missing parameter"},
389 {0x0208, "Can't include in session"},
390 {0x0209, "Session type not supported"},
391 {0x020a, "Session does not exist"},
392 {0x020b, "Invalid request during login"},
393 {0x0300, "Target error (miscellaneous error)"},
394 {0x0301, "Service unavailable"},
395 {0x0302, "Out of resources"},
399 static const value_string iscsi_login_stage[] = {
400 {0, "Security negotiation"},
401 {1, "Operational negotiation"},
402 {3, "Full feature phase"},
407 static const value_string iscsi_isid_type[] = {
409 {0x01, "IANA Enterprise Number"},
415 static const value_string iscsi_logout_reasons[] = {
416 {0, "Close session"},
417 {1, "Close connection"},
418 {2, "Remove connection for recovery"},
422 static const value_string iscsi_logout_response[] = {
423 {0, "Connection closed successfully"},
424 {1, "CID not found"},
425 {2, "Connection recovery not supported"},
426 {3, "Cleanup failed for various reasons"},
430 static const value_string iscsi_asyncevents[] = {
431 {0, "A SCSI asynchronous event is reported in the sense data"},
432 {1, "Target requests logout"},
433 {2, "Target will/has dropped connection"},
434 {3, "Target will/has dropped all connections"},
438 static const value_string iscsi_snack_types[] = {
447 static const value_string iscsi_reject_reasons[] = {
449 {0x01, "Full feature phase command before login"},
451 {0x02, "Data (payload) digest error"},
452 {0x03, "Data SNACK reject"},
453 {0x04, "Protocol error"},
454 {0x05, "Command not supported in this session type"},
455 {0x06, "Immediate command reject (too many immediate commands)"},
456 {0x07, "Task in progress"},
457 {0x08, "Invalid SNACK"},
458 {0x09, "Bookmark reject (no bookmark for this initiator task tag)"},
459 {0x0a, "Bookmark reject (can't generate bookmark - out of resources)"},
460 {0x0b, "Negotiation reset"},
464 /*****************************************************************/
466 /* CRC LOOKUP TABLE */
467 /* ================ */
468 /* The following CRC lookup table was generated automagically */
469 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
470 /* Program V1.0 using the following model parameters: */
472 /* Width : 4 bytes. */
473 /* Poly : 0x1EDC6F41L */
474 /* Reverse : TRUE. */
476 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
477 /* see the document titled "A Painless Guide to CRC Error */
478 /* Detection Algorithms" by Ross Williams */
479 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
480 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
482 /*****************************************************************/
484 static guint32 crc32Table[256] = {
485 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
486 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
487 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
488 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
489 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
490 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
491 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
492 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
493 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
494 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
495 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
496 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
497 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
498 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
499 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
500 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
501 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
502 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
503 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
504 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
505 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
506 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
507 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
508 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
509 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
510 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
511 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
512 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
513 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
514 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
515 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
516 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
517 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
518 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
519 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
520 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
521 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
522 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
523 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
524 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
525 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
526 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
527 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
528 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
529 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
530 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
531 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
532 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
533 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
534 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
535 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
536 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
537 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
538 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
539 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
540 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
541 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
542 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
543 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
544 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
545 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
546 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
547 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
548 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
551 #define CRC32C_PRELOAD 0xffffffff
554 calculateCRC32(const void *buf, int len, guint32 crc) {
555 guint8 *p = (guint8 *)buf;
557 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
565 iscsi_equal(gconstpointer v, gconstpointer w)
567 iscsi_conv_key_t *v1 = (iscsi_conv_key_t *)v;
568 iscsi_conv_key_t *v2 = (iscsi_conv_key_t *)w;
570 return (v1->conv_idx == v2->conv_idx);
574 iscsi_hash (gconstpointer v)
576 iscsi_conv_key_t *key = (iscsi_conv_key_t *)v;
585 * Protocol initialization
588 iscsi_init_protocol(void)
591 g_mem_chunk_destroy(iscsi_req_keys);
593 g_mem_chunk_destroy(iscsi_req_vals);
595 g_hash_table_destroy(iscsi_req_hash);
597 iscsi_req_hash = g_hash_table_new(iscsi_hash, iscsi_equal);
598 iscsi_req_keys = g_mem_chunk_new("iscsi_req_keys",
599 sizeof(iscsi_conv_key_t),
600 iscsi_init_count * sizeof(iscsi_conv_key_t),
602 iscsi_req_vals = g_mem_chunk_new("iscsi_req_vals",
603 sizeof(iscsi_conv_data_t),
604 iscsi_init_count * sizeof(iscsi_conv_data_t),
609 iscsi_min(int a, int b) {
610 return (a < b)? a : b;
614 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
615 const gint limit = offset + text_len;
616 while(offset < limit) {
617 gint len = tvb_strnlen(tvb, offset, limit - offset);
619 len = limit - offset;
622 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
629 handleHeaderDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
630 int available_bytes = tvb_length_remaining(tvb, offset);
631 if(enableHeaderDigests) {
632 if(headerDigestIsCRC32) {
633 if(available_bytes >= (headerLen + 4)) {
634 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
635 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
637 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
640 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);
643 return offset + headerLen + 4;
645 if(available_bytes >= (headerLen + headerDigestSize)) {
646 proto_tree_add_item(ti, hf_iscsi_HeaderDigest, tvb, offset + headerLen, headerDigestSize, FALSE);
648 return offset + headerLen + headerDigestSize;
650 return offset + headerLen;
654 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
655 int available_bytes = tvb_length_remaining(tvb, offset);
656 if(enableDataDigests) {
657 if(dataDigestIsCRC32) {
658 if(available_bytes >= (dataLen + 4)) {
659 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
660 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
662 proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
665 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);
668 return offset + dataLen + 4;
670 if(available_bytes >= (dataLen + dataDigestSize)) {
671 proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
673 return offset + dataLen + dataDigestSize;
675 return offset + dataLen;
679 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
680 if(endOffset > offset) {
681 int dataOffset = offset;
682 int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
684 proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
687 if(offset < endOffset && (offset & 3) != 0) {
688 int padding = 4 - (offset & 3);
689 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
692 if(dataSegmentLen > 0 && offset < endOffset)
693 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
700 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
701 if(endOffset > offset) {
702 int dataOffset = offset;
703 int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
705 proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
706 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
707 offset = addTextKeys(tt, tvb, offset, textLen);
709 if(offset < endOffset && (offset & 3) != 0) {
710 int padding = 4 - (offset & 3);
711 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
714 if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
715 offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
720 /* Code to actually dissect the packets */
722 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len) {
724 guint original_offset = offset;
725 proto_tree *ti = NULL;
726 guint8 scsi_status = 0;
727 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
728 guint end_offset = offset + tvb_length_remaining(tvb, offset);
729 guint32 del_usecs = 0;
730 conversation_t *conversation = NULL;
731 iscsi_conv_data_t *cdata = NULL;
732 iscsi_conv_key_t ckey, *req_key;
733 scsi_task_id_t task_key;
734 int paddedDataSegmentLength = data_segment_len;
735 if(paddedDataSegmentLength & 3)
736 paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
738 /* Make entries in Protocol column and Info column on summary display */
739 if (check_col(pinfo->cinfo, COL_PROTOCOL))
740 col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
742 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
743 opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
744 scsi_status = tvb_get_guint8 (tvb, offset+3);
747 if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
748 (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
749 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
750 conversation = find_conversation (&pinfo->src, &pinfo->dst,
751 pinfo->ptype, pinfo->srcport,
754 ckey.conv_idx = conversation->index;
755 ckey.itt = tvb_get_ntohl (tvb, offset+16);
757 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_hash,
760 task_key.conv_id = ckey.conv_idx;
761 task_key.task_id = ckey.itt;
762 pinfo->private_data = &task_key;
764 /* no conversation, meaning we didn't see the request */
765 pinfo->private_data = NULL;
769 del_usecs = (pinfo->fd->abs_secs - cdata->abs_secs)* 1000000 +
770 (pinfo->fd->abs_usecs - cdata->abs_usecs);
773 else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
774 conversation = find_conversation (&pinfo->src, &pinfo->dst,
775 pinfo->ptype, pinfo->srcport,
778 conversation = conversation_new (&pinfo->src, &pinfo->dst,
779 pinfo->ptype, pinfo->srcport,
783 ckey.conv_idx = conversation->index;
784 ckey.itt = tvb_get_ntohl (tvb, offset+16);
786 cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_hash,
789 /* Since we never free the memory used by an exchange, this maybe a
790 * case of another request using the same exchange as a previous
793 cdata->abs_usecs = pinfo->fd->abs_usecs;
794 cdata->abs_secs = pinfo->fd->abs_secs;
797 req_key = g_mem_chunk_alloc (iscsi_req_keys);
798 req_key->conv_idx = conversation->index;
799 req_key->itt = tvb_get_ntohl (tvb, offset+16);
801 cdata = g_mem_chunk_alloc (iscsi_req_vals);
802 cdata->abs_usecs = pinfo->fd->abs_usecs;
803 cdata->abs_secs = pinfo->fd->abs_secs;
805 g_hash_table_insert (iscsi_req_hash, req_key, cdata);
808 /* The SCSI protocol uses this as the key to detect a
809 * SCSI-level conversation. */
810 task_key.conv_id = ckey.conv_idx;
811 task_key.task_id = ckey.itt;
812 pinfo->private_data = &task_key;
815 pinfo->private_data = NULL;
818 if (check_col(pinfo->cinfo, COL_INFO)) {
820 if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
822 col_append_str(pinfo->cinfo, COL_INFO, (char *)opcode_str);
824 if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
825 (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
826 (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
827 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
828 val_to_str (scsi_status, scsi_status_val, "0x%x"));
830 else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
831 guint16 login_status = tvb_get_ntohs(tvb, offset+36);
832 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
833 val_to_str (login_status, iscsi_login_status, "0x%x"));
835 else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
836 guint16 logoutReason = tvb_get_ntohs(tvb, offset+11);
837 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
838 val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
840 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
841 guint8 tmf = tvb_get_guint8(tvb, offset + 1);
842 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
843 val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
845 else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
846 guint8 resp = tvb_get_guint8(tvb, offset + 2);
847 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
848 val_to_str (resp, iscsi_task_management_responses, "0x%x"));
850 else if (opcode == ISCSI_OPCODE_REJECT) {
851 guint8 reason = tvb_get_guint8(tvb, offset + 2);
852 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
853 val_to_str (reason, iscsi_reject_reasons, "0x%x"));
855 else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
856 guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
857 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
858 val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
863 /* In the interest of speed, if "tree" is NULL, don't do any
864 work not necessary to generate protocol tree items. */
867 /* create display subtree for the protocol */
868 tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
869 offset, -1, "iSCSI (%s)",
871 ti = proto_item_add_subtree(tp, ett_iscsi);
873 proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
874 offset + 0, 1, opcode);
875 if((opcode & TARGET_OPCODE_BIT) == 0) {
876 /* initiator -> target */
877 gint b = tvb_get_guint8(tvb, offset + 0);
879 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
880 opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
881 opcode != ISCSI_OPCODE_SNACK_REQUEST)
882 proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
884 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
885 opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
886 opcode != ISCSI_OPCODE_SNACK_REQUEST)
887 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
890 if(opcode == ISCSI_OPCODE_NOP_OUT) {
892 #if !defined(DRAFT08) && !defined(DRAFT09)
893 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
895 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
896 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
897 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
898 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
899 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
900 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
901 offset = handleHeaderDigest(ti, tvb, offset, 48);
902 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
904 else if(opcode == ISCSI_OPCODE_NOP_IN) {
906 #if !defined(DRAFT08) && !defined(DRAFT09)
907 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
909 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
910 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
911 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
912 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
913 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
914 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
915 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
916 offset = handleHeaderDigest(ti, tvb, offset, 48);
917 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
919 else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
921 guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
923 gint b = tvb_get_guint8(tvb, offset + 1);
924 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
925 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
927 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
928 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
929 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
930 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
932 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
933 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
934 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
935 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
936 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
937 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
938 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
939 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
942 /* FIXME - disssect AHS? */
943 proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 48, ahsLen, FALSE);
945 offset = handleHeaderDigest(ti, tvb, offset, 48 + ahsLen);
947 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
949 else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
952 if (del_usecs > 1000)
953 proto_tree_add_text (ti, tvb, offset, 0,
954 "Cmd Response Time: %d msecs",
957 proto_tree_add_text (ti, tvb, offset, 0,
958 "Cmd Response Time: %d usecs",
962 gint b = tvb_get_guint8(tvb, offset + 1);
963 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
964 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
966 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
967 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
968 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
969 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
971 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
972 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
973 #if !defined(DRAFT08) && !defined(DRAFT09)
974 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
976 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
977 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
978 #if defined(DRAFT08) || defined(DRAFT09)
979 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
981 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
982 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
983 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
984 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
985 #if defined(DRAFT08) || defined(DRAFT09)
986 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
988 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
989 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
991 offset = handleHeaderDigest(ti, tvb, offset, 48);
992 /* do not update offset here because the data segment is
994 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
996 else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
997 /* Task Management Function */
998 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
999 #if !defined(DRAFT08) && !defined(DRAFT09)
1000 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1001 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1003 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1004 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1005 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1006 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1007 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1008 proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1009 offset = handleHeaderDigest(ti, tvb, offset, 48);
1011 else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1012 /* Task Management Function Response */
1013 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
1014 #if !defined(DRAFT08) && !defined(DRAFT09)
1015 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1016 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1018 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1019 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1020 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1021 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1022 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1023 offset = handleHeaderDigest(ti, tvb, offset, 48);
1025 else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1027 int digestsActive = 0;
1029 gint b = tvb_get_guint8(tvb, offset + 1);
1031 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1035 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1036 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1039 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1041 proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1043 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1044 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1046 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1047 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1048 #if !defined(DRAFT08) && !defined(DRAFT09)
1049 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1051 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1053 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1054 proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 12, 2, FALSE);
1057 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1058 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1060 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1061 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1062 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1064 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1065 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1066 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1067 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1068 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1072 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1073 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1075 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1077 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1078 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1080 offset = handleHeaderDigest(ti, tvb, offset, 48);
1083 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1085 else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1086 /* Login Response */
1087 int digestsActive = 0;
1089 gint b = tvb_get_guint8(tvb, offset + 1);
1091 if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1095 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1096 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1099 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1100 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1101 proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1104 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1105 proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1106 #if !defined(DRAFT08) && !defined(DRAFT09)
1107 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1109 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1111 proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 12, 2, FALSE);
1114 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1115 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1117 proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1118 proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1119 proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1121 proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1122 proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1123 proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1124 proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1125 proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1129 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1130 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1131 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1132 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1133 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1134 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1136 offset = handleHeaderDigest(ti, tvb, offset, 48);
1139 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1141 else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1144 gint b = tvb_get_guint8(tvb, offset + 1);
1145 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1146 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1148 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1150 #if !defined(DRAFT08) && !defined(DRAFT09)
1151 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1153 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1154 #if !defined(DRAFT08) && !defined(DRAFT09)
1155 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1157 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1158 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1159 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1160 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1161 offset = handleHeaderDigest(ti, tvb, offset, 48);
1162 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1164 else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1167 gint b = tvb_get_guint8(tvb, offset + 1);
1168 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1169 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1171 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1173 #if !defined(DRAFT08) && !defined(DRAFT09)
1174 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1176 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1177 #if !defined(DRAFT08) && !defined(DRAFT09)
1178 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1180 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1181 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1182 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1183 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1184 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1185 offset = handleHeaderDigest(ti, tvb, offset, 48);
1186 offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1188 else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1189 /* SCSI Data Out (write) */
1191 gint b = tvb_get_guint8(tvb, offset + 1);
1192 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1193 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1195 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1197 #if !defined(DRAFT08) && !defined(DRAFT09)
1198 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1200 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1201 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1202 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1203 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1204 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1205 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1206 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1207 offset = handleHeaderDigest(ti, tvb, offset, 48);
1208 /* do not update offset here because the data segment is
1209 * dissected below */
1210 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1212 else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
1213 /* SCSI Data In (read) */
1215 gint b = tvb_get_guint8(tvb, offset + 1);
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);
1219 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1220 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1221 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1222 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1224 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1225 #if !defined(DRAFT08) && !defined(DRAFT09)
1226 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1228 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1229 #if !defined(DRAFT08) && !defined(DRAFT09)
1230 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1232 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1233 #if defined(DRAFT08) || defined(DRAFT09)
1234 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1236 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1238 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1239 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1240 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1241 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1242 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1243 #if !defined(DRAFT08) && !defined(DRAFT09)
1244 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1246 offset = handleHeaderDigest(ti, tvb, offset, 48);
1247 /* do not update offset here because the data segment is
1248 * dissected below */
1249 handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1251 else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1252 /* Logout Command */
1253 #if !defined(DRAFT08) && !defined(DRAFT09)
1254 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1255 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1258 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1259 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1261 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1263 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1264 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, 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);
1268 offset = handleHeaderDigest(ti, tvb, offset, 48);
1270 else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1271 /* Logout Response */
1272 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1273 #if !defined(DRAFT08) && !defined(DRAFT09)
1274 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1275 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1277 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1278 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1279 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1280 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1281 proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1282 proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1283 offset = handleHeaderDigest(ti, tvb, offset, 48);
1285 else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1288 gint b = tvb_get_guint8(tvb, offset + 1);
1290 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1291 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1294 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1296 #if !defined(DRAFT08) && !defined(DRAFT09)
1297 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1298 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1299 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1301 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1302 #if defined(DRAFT08) || defined(DRAFT09)
1303 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1304 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1305 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1306 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1308 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1309 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1310 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1311 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1313 offset = handleHeaderDigest(ti, tvb, offset, 48);
1315 else if(opcode == ISCSI_OPCODE_R2T) {
1317 #if !defined(DRAFT08) && !defined(DRAFT09)
1318 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1319 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1320 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1322 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1323 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1324 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1325 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1326 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1327 proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
1328 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1329 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1330 offset = handleHeaderDigest(ti, tvb, offset, 48);
1332 else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1333 /* Asynchronous Message */
1334 #if !defined(DRAFT08) && !defined(DRAFT09)
1335 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1337 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1338 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1339 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1340 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1341 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1342 proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1343 proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1344 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1345 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1346 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1347 offset = handleHeaderDigest(ti, tvb, offset, 48);
1349 else if(opcode == ISCSI_OPCODE_REJECT) {
1351 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
1352 #if !defined(DRAFT08) && !defined(DRAFT09)
1353 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1355 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1356 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1357 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1358 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1359 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1360 offset = handleHeaderDigest(ti, tvb, offset, 48);
1361 offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1364 proto_item_set_len(ti, offset - original_offset);
1367 if((opcode & ~(X_BIT | I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND)
1369 if((opcode & ~I_BIT) == ISCSI_OPCODE_SCSI_COMMAND)
1373 dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16);
1375 else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1376 if (scsi_status == 0x2) {
1377 /* A SCSI response with Check Condition contains sense data */
1378 /* offset is setup correctly by the iscsi code for response above */
1379 if((end_offset - offset) >= 2) {
1380 int senseLen = tvb_get_ntohs(tvb, offset);
1382 proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1385 dissect_scsi_snsinfo (tvb, pinfo, tree, offset,
1386 iscsi_min (senseLen,
1387 end_offset-offset));
1391 dissect_scsi_rsp (tvb, pinfo, tree);
1393 if (cdata && tree) {
1394 /* destroy the data structures for this SCSI task */
1396 g_mem_chunk_free (iscsi_req_vals, cdata);
1397 g_hash_table_remove (iscsi_req_hash, &ckey);
1398 pinfo->private_data = NULL;
1402 else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1403 (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1404 /* offset is setup correctly by the iscsi code for response above */
1405 dissect_scsi_payload (tvb, pinfo, tree, offset, FALSE,
1406 iscsi_min (data_segment_len, end_offset-offset));
1411 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1412 /* Set up structures needed to add the protocol subtree and manage it */
1413 guint iSCSIPdusDissected = 0;
1415 guint32 available_bytes = tvb_length_remaining(tvb, offset);
1417 if (!proto_is_protocol_enabled(proto_iscsi))
1418 return FALSE; /* iSCSI has been disabled */
1420 /* quick check to see if the packet is long enough to contain the
1421 * minimum amount of information we need */
1422 if (available_bytes < 48 && (!iscsi_desegment || available_bytes < 8)) {
1423 /* no, so give up */
1427 /* process multiple iSCSI PDUs per packet */
1428 while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
1429 const char *opcode_str = NULL;
1430 guint32 data_segment_len;
1431 guint8 opcode = tvb_get_guint8(tvb, offset + 0);
1432 guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
1435 /* mask out any extra bits in the opcode byte */
1436 opcode &= OPCODE_MASK;
1438 opcode_str = match_strval(opcode, iscsi_opcodes);
1439 if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
1440 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1441 opcode == ISCSI_OPCODE_R2T ||
1442 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1443 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1444 opcode == ISCSI_OPCODE_SNACK_REQUEST)
1445 data_segment_len = 0;
1447 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
1449 if(opcode_str == NULL) {
1452 else if(iscsi_port != 0 &&
1453 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
1454 (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
1457 else if(enable_bogosity_filter) {
1458 /* try and distinguish between data and real headers */
1459 if(data_segment_len > bogus_pdu_data_length_threshold) {
1462 else if(demand_good_f_bit &&
1463 !(secondPduByte & 0x80) &&
1464 (opcode == ISCSI_OPCODE_NOP_OUT ||
1465 opcode == ISCSI_OPCODE_NOP_IN ||
1466 opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
1467 opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
1468 opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
1469 opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
1470 opcode == ISCSI_OPCODE_R2T ||
1471 opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
1472 opcode == ISCSI_OPCODE_SNACK_REQUEST ||
1473 opcode == ISCSI_OPCODE_REJECT)) {
1479 return iSCSIPdusDissected > 0;
1482 guint32 pduLen = 48;
1483 int digestsActive = 1;
1485 if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
1486 opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1488 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
1489 /* digests are not yet turned on */
1497 if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
1499 pduLen += tvb_get_guint8(tvb, offset + 4) * 4;
1502 pduLen += data_segment_len;
1503 if((pduLen & 3) != 0)
1504 pduLen += 4 - (pduLen & 3);
1506 if(digestsActive && enableHeaderDigests) {
1507 if(headerDigestIsCRC32)
1510 pduLen += headerDigestSize;
1513 if(digestsActive && data_segment_len > 0 && enableDataDigests) {
1514 if(dataDigestIsCRC32)
1517 pduLen += dataDigestSize;
1521 * Desegmentation check.
1523 if(iscsi_desegment && pinfo->can_desegment) {
1524 if(pduLen > available_bytes) {
1526 * This frame doesn't have all of the data for
1527 * this message, but we can do reassembly on it.
1529 * Tell the TCP dissector where the data for this
1530 * message starts in the data it handed us, and
1531 * how many more bytes we need, and return.
1533 pinfo->desegment_offset = offset;
1534 pinfo->desegment_len = pduLen - available_bytes;
1539 if(check_col(pinfo->cinfo, COL_INFO)) {
1540 if(iSCSIPdusDissected == 0)
1541 col_set_str(pinfo->cinfo, COL_INFO, "");
1543 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1546 dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len);
1547 if(pduLen > available_bytes)
1548 pduLen = available_bytes;
1550 available_bytes -= pduLen;
1551 ++iSCSIPdusDissected;
1555 return iSCSIPdusDissected > 0;
1559 /* Register the protocol with Ethereal */
1562 * this format is require because a script is used to build the C
1563 * function that calls all the protocol registration.
1567 proto_register_iscsi(void)
1570 /* Setup list of header fields See Section 1.6.1 for details*/
1571 static hf_register_info hf[] = {
1573 { "AHS", "iscsi.ahs",
1574 FT_BYTES, BASE_HEX, NULL, 0,
1575 "Additional header segment", HFILL }
1577 { &hf_iscsi_Padding,
1578 { "Padding", "iscsi.padding",
1579 FT_BYTES, BASE_HEX, NULL, 0,
1580 "Padding to 4 byte boundary", HFILL }
1582 { &hf_iscsi_ping_data,
1583 { "PingData", "iscsi.pingdata",
1584 FT_BYTES, BASE_HEX, NULL, 0,
1585 "Ping Data", HFILL }
1587 { &hf_iscsi_immediate_data,
1588 { "ImmediateData", "iscsi.immediatedata",
1589 FT_BYTES, BASE_HEX, NULL, 0,
1590 "Immediate Data", HFILL }
1592 { &hf_iscsi_write_data,
1593 { "WriteData", "iscsi.writedata",
1594 FT_BYTES, BASE_HEX, NULL, 0,
1595 "Write Data", HFILL }
1597 { &hf_iscsi_read_data,
1598 { "ReadData", "iscsi.readdata",
1599 FT_BYTES, BASE_HEX, NULL, 0,
1600 "Read Data", HFILL }
1602 { &hf_iscsi_error_pdu_data,
1603 { "ErrorPDUData", "iscsi.errorpdudata",
1604 FT_BYTES, BASE_HEX, NULL, 0,
1605 "Error PDU Data", HFILL }
1607 { &hf_iscsi_HeaderDigest,
1608 { "HeaderDigest", "iscsi.headerdigest",
1609 FT_BYTES, BASE_HEX, NULL, 0,
1610 "Header Digest", HFILL }
1612 { &hf_iscsi_HeaderDigest32,
1613 { "HeaderDigest", "iscsi.headerdigest32",
1614 FT_UINT32, BASE_HEX, NULL, 0,
1615 "Header Digest", HFILL }
1617 { &hf_iscsi_DataDigest,
1618 { "DataDigest", "iscsi.datadigest",
1619 FT_BYTES, BASE_HEX, NULL, 0,
1620 "Data Digest", HFILL }
1622 { &hf_iscsi_DataDigest32,
1623 { "DataDigest", "iscsi.datadigest32",
1624 FT_UINT32, BASE_HEX, NULL, 0,
1625 "Data Digest", HFILL }
1628 { "Opcode", "iscsi.opcode",
1629 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
1635 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1636 "Command Retry", HFILL }
1641 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
1642 "Immediate delivery", HFILL }
1645 { "Flags", "iscsi.flags",
1646 FT_UINT8, BASE_HEX, NULL, 0,
1647 "Opcode specific flags", HFILL }
1649 { &hf_iscsi_SCSICommand_F,
1650 { "F", "iscsi.scsicommand.F",
1651 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1652 "PDU completes command", HFILL }
1654 { &hf_iscsi_SCSICommand_R,
1655 { "R", "iscsi.scsicommand.R",
1656 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
1657 "Command reads from SCSI target", HFILL }
1659 { &hf_iscsi_SCSICommand_W,
1660 { "W", "iscsi.scsicommand.W",
1661 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
1662 "Command writes to SCSI target", HFILL }
1664 { &hf_iscsi_SCSICommand_Attr,
1665 { "Attr", "iscsi.scsicommand.attr",
1666 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
1667 "SCSI task attributes", HFILL }
1669 { &hf_iscsi_SCSICommand_CRN,
1670 { "CRN", "iscsi.scsicommand.crn",
1671 FT_UINT8, BASE_HEX, NULL, 0,
1672 "SCSI command reference number", HFILL }
1674 { &hf_iscsi_SCSICommand_AddCDB,
1675 { "AddCDB", "iscsi.scsicommand.addcdb",
1676 FT_UINT8, BASE_HEX, NULL, 0,
1677 "Additional CDB length (in 4 byte units)", HFILL }
1679 { &hf_iscsi_DataSegmentLength,
1680 { "DataSegmentLength", "iscsi.datasegmentlength",
1681 FT_UINT32, BASE_HEX, NULL, 0,
1682 "Data segment length (bytes)", HFILL }
1684 { &hf_iscsi_TotalAHSLength,
1685 { "TotalAHSLength", "iscsi.totalahslength",
1686 FT_UINT8, BASE_HEX, NULL, 0,
1687 "Total additional header segment length (4 byte words)", HFILL }
1690 { "LUN", "iscsi.lun",
1691 FT_BYTES, BASE_HEX, NULL, 0,
1692 "Logical Unit Number", HFILL }
1694 { &hf_iscsi_InitiatorTaskTag,
1695 { "InitiatorTaskTag", "iscsi.initiatortasktag",
1696 FT_UINT32, BASE_HEX, NULL, 0,
1697 "Initiator's task tag", HFILL }
1699 { &hf_iscsi_ExpectedDataTransferLength,
1700 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
1701 FT_UINT32, BASE_HEX, NULL, 0,
1702 "Expected length of data transfer", HFILL }
1705 { "CmdSN", "iscsi.cmdsn",
1706 FT_UINT32, BASE_HEX, NULL, 0,
1707 "Sequence number for this command (0 == immediate)", HFILL }
1709 { &hf_iscsi_ExpStatSN,
1710 { "ExpStatSN", "iscsi.expstatsn",
1711 FT_UINT32, BASE_HEX, NULL, 0,
1712 "Next expected status sequence number", HFILL }
1714 { &hf_iscsi_SCSIResponse_ResidualCount,
1715 { "ResidualCount", "iscsi.scsiresponse.residualcount",
1716 FT_UINT32, BASE_HEX, NULL, 0,
1717 "Residual count", HFILL }
1720 { "StatSN", "iscsi.statsn",
1721 FT_UINT32, BASE_HEX, NULL, 0,
1722 "Status sequence number", HFILL }
1724 { &hf_iscsi_ExpCmdSN,
1725 { "ExpCmdSN", "iscsi.expcmdsn",
1726 FT_UINT32, BASE_HEX, NULL, 0,
1727 "Next expected command sequence number", HFILL }
1729 { &hf_iscsi_MaxCmdSN,
1730 { "MaxCmdSN", "iscsi.maxcmdsn",
1731 FT_UINT32, BASE_HEX, NULL, 0,
1732 "Maximum acceptable command sequence number", HFILL }
1734 { &hf_iscsi_SCSIResponse_o,
1735 { "o", "iscsi.scsiresponse.o",
1736 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
1737 "Bi-directional read residual overflow", HFILL }
1739 { &hf_iscsi_SCSIResponse_u,
1740 { "u", "iscsi.scsiresponse.u",
1741 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
1742 "Bi-directional read residual underflow", HFILL }
1744 { &hf_iscsi_SCSIResponse_O,
1745 { "O", "iscsi.scsiresponse.O",
1746 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
1747 "Residual overflow", HFILL }
1749 { &hf_iscsi_SCSIResponse_U,
1750 { "U", "iscsi.scsiresponse.U",
1751 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
1752 "Residual underflow", HFILL }
1754 { &hf_iscsi_SCSIResponse_Status,
1755 { "Status", "iscsi.scsiresponse.status",
1756 FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
1757 "SCSI command status value", HFILL }
1759 { &hf_iscsi_SCSIResponse_Response,
1760 { "Response", "iscsi.scsiresponse.response",
1761 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
1762 "SCSI command response value", HFILL }
1764 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
1765 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
1766 FT_UINT32, BASE_HEX, NULL, 0,
1767 "Bi-directional read residual count", HFILL }
1769 { &hf_iscsi_SenseLength,
1770 { "SenseLength", "iscsi.scsiresponse.senselength",
1771 FT_UINT16, BASE_HEX, NULL, 0,
1772 "Sense data length", HFILL }
1774 { &hf_iscsi_SCSIData_F,
1775 { "F", "iscsi.scsidata.F",
1776 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
1777 "Final PDU", HFILL }
1779 { &hf_iscsi_SCSIData_S,
1780 { "S", "iscsi.scsidata.S",
1781 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
1782 "PDU Contains SCSI command status", HFILL }
1784 { &hf_iscsi_SCSIData_U,
1785 { "U", "iscsi.scsidata.U",
1786 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
1787 "Residual underflow", HFILL }
1789 { &hf_iscsi_SCSIData_O,
1790 { "O", "iscsi.scsidata.O",
1791 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
1792 "Residual overflow", HFILL }
1794 { &hf_iscsi_TargetTransferTag,
1795 { "TargetTransferTag", "iscsi.targettransfertag",
1796 FT_UINT32, BASE_HEX, NULL, 0,
1797 "Target transfer tag", HFILL }
1799 { &hf_iscsi_BufferOffset,
1800 { "BufferOffset", "iscsi.bufferOffset",
1801 FT_UINT32, BASE_HEX, NULL, 0,
1802 "Buffer offset", HFILL }
1804 { &hf_iscsi_SCSIData_ResidualCount,
1805 { "ResidualCount", "iscsi.scsidata.readresidualcount",
1806 FT_UINT32, BASE_HEX, NULL, 0,
1807 "Residual count", HFILL }
1810 { "DataSN", "iscsi.datasn",
1811 FT_UINT32, BASE_HEX, NULL, 0,
1812 "Data sequence number", HFILL }
1814 { &hf_iscsi_VersionMax,
1815 { "VersionMax", "iscsi.versionmax",
1816 FT_UINT8, BASE_HEX, NULL, 0,
1817 "Maximum supported protocol version", HFILL }
1819 { &hf_iscsi_VersionMin,
1820 { "VersionMin", "iscsi.versionmin",
1821 FT_UINT8, BASE_HEX, NULL, 0,
1822 "Minimum supported protocol version", HFILL }
1824 { &hf_iscsi_VersionActive,
1825 { "VersionActive", "iscsi.versionactive",
1826 FT_UINT8, BASE_HEX, NULL, 0,
1827 "Negotiated protocol version", HFILL }
1830 { "CID", "iscsi.cid",
1831 FT_UINT16, BASE_HEX, NULL, 0,
1832 "Connection identifier", HFILL }
1836 { "ISID", "iscsi.isid",
1837 FT_UINT16, BASE_HEX, NULL, 0,
1838 "Initiator part of session identifier", HFILL }
1842 { "ISID", "iscsi.isid",
1843 FT_BYTES, BASE_HEX, NULL, 0,
1844 "Initiator part of session identifier", HFILL }
1847 { &hf_iscsi_ISID_Type,
1848 { "ISID_Type", "iscsi.isid.type",
1849 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
1850 "Initiator part of session identifier - type", HFILL }
1852 { &hf_iscsi_ISID_NamingAuthority,
1853 { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
1854 FT_UINT24, BASE_HEX, NULL, 0,
1855 "Initiator part of session identifier - naming authority", HFILL }
1857 { &hf_iscsi_ISID_Qualifier,
1858 { "ISID_Qualifier", "iscsi.isid.qualifier",
1859 FT_UINT8, BASE_HEX, NULL, 0,
1860 "Initiator part of session identifier - qualifier", HFILL }
1864 { "ISID_t", "iscsi.isid.t",
1865 FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
1866 "Initiator part of session identifier - t", HFILL }
1869 { "ISID_a", "iscsi.isid.a",
1870 FT_UINT8, BASE_HEX, NULL, 0x3f,
1871 "Initiator part of session identifier - a", HFILL }
1874 { "ISID_b", "iscsi.isid.b",
1875 FT_UINT16, BASE_HEX, NULL, 0,
1876 "Initiator part of session identifier - b", HFILL }
1879 { "ISID_c", "iscsi.isid.c",
1880 FT_UINT8, BASE_HEX, NULL, 0,
1881 "Initiator part of session identifier - c", HFILL }
1884 { "ISID_d", "iscsi.isid.d",
1885 FT_UINT16, BASE_HEX, NULL, 0,
1886 "Initiator part of session identifier - d", HFILL }
1891 { "TSID", "iscsi.tsid",
1892 FT_UINT16, BASE_HEX, NULL, 0,
1893 "Target part of session identifier", HFILL }
1895 { &hf_iscsi_InitStatSN,
1896 { "InitStatSN", "iscsi.initstatsn",
1897 FT_UINT32, BASE_HEX, NULL, 0,
1898 "Initial status sequence number", HFILL }
1900 { &hf_iscsi_InitCmdSN,
1901 { "InitCmdSN", "iscsi.initcmdsn",
1902 FT_UINT32, BASE_HEX, NULL, 0,
1903 "Initial command sequence number", HFILL }
1905 { &hf_iscsi_Login_T,
1906 { "T", "iscsi.login.T",
1907 FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
1908 "Transit to next login stage", HFILL }
1911 { &hf_iscsi_Login_X,
1912 { "X", "iscsi.login.X",
1913 FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
1914 "Restart Connection", HFILL }
1917 { &hf_iscsi_Login_CSG,
1918 { "CSG", "iscsi.login.csg",
1919 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
1920 "Current stage", HFILL }
1922 { &hf_iscsi_Login_NSG,
1923 { "NSG", "iscsi.login.nsg",
1924 FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
1925 "Next stage", HFILL }
1927 { &hf_iscsi_Login_Status,
1928 { "Status", "iscsi.login.status",
1929 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
1930 "Status class and detail", HFILL }
1932 { &hf_iscsi_KeyValue,
1933 { "KeyValue", "iscsi.keyvalue",
1934 FT_STRING, 0, NULL, 0,
1935 "Key/value pair", HFILL }
1938 { "F", "iscsi.text.F",
1939 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1940 "Final PDU in text sequence", HFILL }
1942 { &hf_iscsi_ExpDataSN,
1943 { "ExpDataSN", "iscsi.expdatasn",
1944 FT_UINT32, BASE_HEX, NULL, 0,
1945 "Next expected data sequence number", HFILL }
1948 { "R2TSN", "iscsi.r2tsn",
1949 FT_UINT32, BASE_HEX, NULL, 0,
1950 "R2T PDU Number", HFILL }
1952 { &hf_iscsi_TaskManagementFunction_Response,
1953 { "Response", "iscsi.taskmanfun.response",
1954 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
1957 { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
1958 { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
1959 FT_UINT32, BASE_HEX, NULL, 0,
1960 "Referenced task tag", HFILL }
1962 { &hf_iscsi_RefCmdSN,
1963 { "RefCmdSN", "iscsi.refcmdsn",
1964 FT_UINT32, BASE_HEX, NULL, 0,
1965 "Command sequence number for command to be aborted", HFILL }
1967 { &hf_iscsi_TaskManagementFunction_Function,
1968 { "Function", "iscsi.taskmanfun.function",
1969 FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
1970 "Requested task function", HFILL }
1972 { &hf_iscsi_Logout_Reason,
1973 { "Reason", "iscsi.logout.reason",
1974 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0,
1975 "Reason for logout", HFILL }
1977 { &hf_iscsi_Logout_Response,
1978 { "Response", "iscsi.logout.response",
1979 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
1980 "Logout response", HFILL }
1982 { &hf_iscsi_Time2Wait,
1983 { "Time2Wait", "iscsi.time2wait",
1984 FT_UINT16, BASE_HEX, NULL, 0,
1985 "Time2Wait", HFILL }
1987 { &hf_iscsi_Time2Retain,
1988 { "Time2Retain", "iscsi.time2retain",
1989 FT_UINT16, BASE_HEX, NULL, 0,
1990 "Time2Retain", HFILL }
1992 { &hf_iscsi_DesiredDataLength,
1993 { "DesiredDataLength", "iscsi.desireddatalength",
1994 FT_UINT32, BASE_HEX, NULL, 0,
1995 "Desired data length (bytes)", HFILL }
1997 { &hf_iscsi_AsyncEvent,
1998 { "AsyncEvent", "iscsi.asyncevent",
1999 FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2000 "Async event type", HFILL }
2002 { &hf_iscsi_EventVendorCode,
2003 { "EventVendorCode", "iscsi.eventvendorcode",
2004 FT_UINT8, BASE_HEX, NULL, 0,
2005 "Event vendor code", HFILL }
2007 { &hf_iscsi_Parameter1,
2008 { "Parameter1", "iscsi.parameter1",
2009 FT_UINT16, BASE_HEX, NULL, 0,
2010 "Parameter 1", HFILL }
2012 { &hf_iscsi_Parameter2,
2013 { "Parameter2", "iscsi.parameter2",
2014 FT_UINT16, BASE_HEX, NULL, 0,
2015 "Parameter 2", HFILL }
2017 { &hf_iscsi_Parameter3,
2018 { "Parameter3", "iscsi.parameter3",
2019 FT_UINT16, BASE_HEX, NULL, 0,
2020 "Parameter 3", HFILL }
2022 { &hf_iscsi_Reject_Reason,
2023 { "Reason", "iscsi.reject.reason",
2024 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2025 "Reason for command rejection", HFILL }
2027 { &hf_iscsi_snack_type,
2028 { "S", "iscsi.snack.type",
2029 FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2030 "Type of SNACK requested", HFILL }
2033 { "BegRun", "iscsi.snack.begrun",
2034 FT_UINT32, BASE_HEX, NULL, 0,
2035 "First missed DataSN or StatSN", HFILL }
2037 { &hf_iscsi_RunLength,
2038 { "RunLength", "iscsi.snack.runlength",
2039 FT_UINT32, BASE_HEX, NULL, 0,
2040 "Number of additional missing status PDUs in this run", HFILL }
2044 /* Setup protocol subtree array */
2045 static gint *ett[] = {
2047 &ett_iscsi_KeyValues,
2055 /* Register the protocol name and description */
2056 proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2058 /* Required function calls to register the header fields and
2060 proto_register_field_array(proto_iscsi, hf, array_length(hf));
2061 proto_register_subtree_array(ett, array_length(ett));
2062 register_init_routine (&iscsi_init_protocol);
2065 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2067 prefs_register_bool_preference(iscsi_module,
2068 "desegment_iscsi_messages",
2069 "Desegment iSCSI messages",
2070 "When enabled, iSCSI messages that span multiple TCP segments are desegmented",
2073 prefs_register_bool_preference(iscsi_module,
2075 "Enable bogus pdu filter",
2076 "When enabled, packets that appear bogus are ignored",
2077 &enable_bogosity_filter);
2079 prefs_register_bool_preference(iscsi_module,
2080 "demand_good_f_bit",
2081 "Ignore packets with bad F bit",
2082 "Ignore packets that haven't set the F bit when they should have",
2083 &demand_good_f_bit);
2085 prefs_register_uint_preference(iscsi_module,
2086 "bogus_pdu_max_data_len",
2087 "Bogus pdu max data length threshold",
2088 "Treat packets whose data segment length is greater than this value as bogus",
2090 &bogus_pdu_data_length_threshold);
2092 prefs_register_uint_preference(iscsi_module,
2095 "Port number of iSCSI target",
2099 prefs_register_bool_preference(iscsi_module,
2100 "enable_header_digests",
2101 "Enable header digests",
2102 "When enabled, pdus are assumed to contain a header digest",
2103 &enableHeaderDigests);
2104 prefs_register_bool_preference(iscsi_module,
2105 "enable_data_digests",
2106 "Enable data digests",
2107 "When enabled, pdus are assumed to contain a data digest",
2108 &enableDataDigests);
2110 prefs_register_bool_preference(iscsi_module,
2111 "header_digest_is_crc32c",
2112 "Header digest is CRC32C",
2113 "When enabled, header digests are assumed to be CRC32C",
2114 &headerDigestIsCRC32);
2115 prefs_register_bool_preference(iscsi_module,
2116 "data_digest_is_crc32c",
2117 "Data digest is CRC32C",
2118 "When enabled, data digests are assumed to be CRC32C",
2119 &dataDigestIsCRC32);
2121 prefs_register_uint_preference(iscsi_module,
2122 "header_digest_size",
2123 "Header digest size",
2124 "The size of a header digest (bytes)",
2127 prefs_register_uint_preference(iscsi_module,
2130 "The size of a data digest (bytes)",
2134 /* Preference supported in older versions.
2135 Register them as obsolete. */
2136 prefs_register_obsolete_preference(iscsi_module,
2137 "version_03_compatible");
2138 prefs_register_obsolete_preference(iscsi_module,
2139 "bogus_pdu_max_digest_padding");
2145 * If this dissector uses sub-dissector registration add a
2146 * registration routine.
2150 * This format is required because a script is used to find these
2151 * routines and create the code that calls these routines.
2154 proto_reg_handoff_iscsi(void)
2156 heur_dissector_add("tcp", dissect_iscsi, proto_iscsi);