081a184e46c44cf35ba9c722882461a67f701692
[obnox/wireshark/wip.git] / epan / dissectors / packet-iscsi.c
1 /* TODO for the cases where one just can not autodetect whether header digest 
2    is used or not we might need a new preference 
3    HeaderDigest : 
4        Automatic (default)
5        None
6        CRC32
7 */
8  
9 /* packet-iscsi.c
10  * Routines for iSCSI dissection
11  * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
12  *  2004 Request/Response matching and Service Response Time: ronnie sahlberg
13  *
14  * $Id$
15  *
16  * Wireshark - Network traffic analyzer
17  * By Gerald Combs <gerald@wireshark.org>
18  * Copyright 1998 Gerald Combs
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include <glib.h>
44
45 #include <epan/packet.h>
46 #include <epan/prefs.h>
47 #include <epan/conversation.h>
48 #include "packet-fc.h"
49 #include "packet-scsi.h"
50 #include "epan/nstime.h"
51 #include <epan/emem.h>
52
53 /* the absolute values of these constants don't matter as long as
54  * latter revisions of the protocol are assigned a larger number */
55 #define ISCSI_PROTOCOL_DRAFT08 1
56 #define ISCSI_PROTOCOL_DRAFT09 2
57 #define ISCSI_PROTOCOL_DRAFT11 3
58 #define ISCSI_PROTOCOL_DRAFT12 4
59 #define ISCSI_PROTOCOL_DRAFT13 5
60
61 static enum_val_t iscsi_protocol_versions[] = {
62     { "draft-08", "Draft 08", ISCSI_PROTOCOL_DRAFT08 },
63     { "draft-09", "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
64     { "draft-11", "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
65     { "draft-12", "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
66     { "draft-13", "Draft 13", ISCSI_PROTOCOL_DRAFT13 },
67     { NULL, NULL, 0 }
68 };
69
70 static const value_string ahs_type_vals[] = {
71     {1, "Extended CDB"},
72     {2, "Expected Bidirection Read Data Length"},
73     {0, NULL}
74 };
75
76 static dissector_handle_t iscsi_handle=NULL;
77
78 static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT13;
79
80 static gboolean iscsi_desegment = TRUE;
81
82 static int demand_good_f_bit = FALSE;
83 static int enable_bogosity_filter = TRUE;
84 static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
85
86 static int enableDataDigests = FALSE;
87
88 static int dataDigestIsCRC32 = TRUE;
89
90 static guint dataDigestSize = 4;
91
92 static guint iscsi_port = 3260;
93
94 /* Initialize the protocol and registered fields */
95 static int proto_iscsi = -1;
96 static int hf_iscsi_time = -1;
97 static int hf_iscsi_request_frame = -1;
98 static int hf_iscsi_data_in_frame = -1;
99 static int hf_iscsi_data_out_frame = -1;
100 static int hf_iscsi_response_frame = -1;
101 static int hf_iscsi_AHS = -1;
102 static int hf_iscsi_AHS_length = -1;
103 static int hf_iscsi_AHS_type = -1;
104 static int hf_iscsi_AHS_specific = -1;
105 static int hf_iscsi_Padding = -1;
106 static int hf_iscsi_ping_data = -1;
107 static int hf_iscsi_immediate_data = -1;
108 static int hf_iscsi_write_data = -1;
109 static int hf_iscsi_read_data = -1;
110 static int hf_iscsi_error_pdu_data = -1;
111 static int hf_iscsi_async_message_data = -1;
112 static int hf_iscsi_vendor_specific_data = -1;
113 static int hf_iscsi_Opcode = -1;
114 static int hf_iscsi_Flags = -1;
115 static int hf_iscsi_HeaderDigest32 = -1;
116 static int hf_iscsi_DataDigest = -1;
117 static int hf_iscsi_DataDigest32 = -1;
118 /* #ifdef DRAFT08 */
119 static int hf_iscsi_X = -1;
120 /* #endif */
121 static int hf_iscsi_I = -1;
122 static int hf_iscsi_SCSICommand_F = -1;
123 static int hf_iscsi_SCSICommand_R = -1;
124 static int hf_iscsi_SCSICommand_W = -1;
125 static int hf_iscsi_SCSICommand_Attr = -1;
126 static int hf_iscsi_SCSICommand_CRN = -1;
127 static int hf_iscsi_SCSICommand_AddCDB = -1;
128 static int hf_iscsi_DataSegmentLength = -1;
129 static int hf_iscsi_TotalAHSLength = -1;
130 static int hf_iscsi_LUN = -1;
131 static int hf_iscsi_InitiatorTaskTag = -1;
132 static int hf_iscsi_ExpectedDataTransferLength = -1;
133 static int hf_iscsi_CmdSN = -1;
134 static int hf_iscsi_ExpStatSN = -1;
135 static int hf_iscsi_StatSN = -1;
136 static int hf_iscsi_ExpCmdSN = -1;
137 static int hf_iscsi_MaxCmdSN = -1;
138 static int hf_iscsi_SCSIResponse_o = -1;
139 static int hf_iscsi_SCSIResponse_u = -1;
140 static int hf_iscsi_SCSIResponse_O = -1;
141 static int hf_iscsi_SCSIResponse_U = -1;
142 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
143 static int hf_iscsi_SCSIResponse_ResidualCount = -1;
144 static int hf_iscsi_SCSIResponse_Response = -1;
145 static int hf_iscsi_SCSIResponse_Status = -1;
146 static int hf_iscsi_SenseLength = -1;
147 static int hf_iscsi_SCSIData_F = -1;
148 static int hf_iscsi_SCSIData_A = -1;
149 static int hf_iscsi_SCSIData_S = -1;
150 static int hf_iscsi_SCSIData_O = -1;
151 static int hf_iscsi_SCSIData_U = -1;
152 static int hf_iscsi_TargetTransferTag = -1;
153 static int hf_iscsi_DataSN = -1;
154 static int hf_iscsi_BufferOffset = -1;
155 static int hf_iscsi_SCSIData_ResidualCount = -1;
156 static int hf_iscsi_VersionMin = -1;
157 static int hf_iscsi_VersionMax = -1;
158 static int hf_iscsi_VersionActive = -1;
159 static int hf_iscsi_CID = -1;
160 static int hf_iscsi_ISID8 = -1;
161 static int hf_iscsi_ISID = -1;
162 /* #if defined(DRAFT09) */
163 static int hf_iscsi_ISID_Type = -1;
164 static int hf_iscsi_ISID_NamingAuthority = -1;
165 static int hf_iscsi_ISID_Qualifier = -1;
166 /* #elif !defined(DRAFT08) */
167 static int hf_iscsi_ISID_t = -1;
168 static int hf_iscsi_ISID_a = -1;
169 static int hf_iscsi_ISID_b = -1;
170 static int hf_iscsi_ISID_c = -1;
171 static int hf_iscsi_ISID_d = -1;
172 /* #endif */
173 static int hf_iscsi_TSID = -1;
174 static int hf_iscsi_TSIH = -1;
175 static int hf_iscsi_InitStatSN = -1;
176 static int hf_iscsi_InitCmdSN = -1;
177 /* #ifdef DRAFT09 */
178 static int hf_iscsi_Login_X = -1;
179 /* #endif */
180 static int hf_iscsi_Login_C = -1;
181 static int hf_iscsi_Login_T = -1;
182 static int hf_iscsi_Login_CSG = -1;
183 static int hf_iscsi_Login_NSG = -1;
184 static int hf_iscsi_Login_Status = -1;
185 static int hf_iscsi_KeyValue = -1;
186 static int hf_iscsi_Text_C = -1;
187 static int hf_iscsi_Text_F = -1;
188 static int hf_iscsi_ExpDataSN = -1;
189 static int hf_iscsi_R2TSN = -1;
190 static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
191 static int hf_iscsi_RefCmdSN = -1;
192 static int hf_iscsi_TaskManagementFunction_Function = -1;
193 static int hf_iscsi_TaskManagementFunction_Response = -1;
194 static int hf_iscsi_Logout_Reason = -1;
195 static int hf_iscsi_Logout_Response = -1;
196 static int hf_iscsi_Time2Wait = -1;
197 static int hf_iscsi_Time2Retain = -1;
198 static int hf_iscsi_DesiredDataLength = -1;
199 static int hf_iscsi_AsyncEvent = -1;
200 static int hf_iscsi_EventVendorCode = -1;
201 static int hf_iscsi_Parameter1 = -1;
202 static int hf_iscsi_Parameter2 = -1;
203 static int hf_iscsi_Parameter3 = -1;
204 static int hf_iscsi_Reject_Reason = -1;
205 static int hf_iscsi_snack_type = -1;
206 static int hf_iscsi_BegRun = -1;
207 static int hf_iscsi_RunLength = -1;
208
209 /* Initialize the subtree pointers */
210 static gint ett_iscsi = -1;
211 static gint ett_iscsi_KeyValues = -1;
212 static gint ett_iscsi_CDB = -1;
213 static gint ett_iscsi_Flags = -1;
214 /* #ifndef DRAFT08 */
215 static gint ett_iscsi_ISID = -1;
216 /* #endif */
217
218 #define ISCSI_HEADER_DIGEST_AUTO        0
219 #define ISCSI_HEADER_DIGEST_NONE        1
220 #define ISCSI_HEADER_DIGEST_CRC32       2
221 /* this structure contains session wide state for a specific tcp conversation */
222 typedef struct _iscsi_session_t {
223         guint32 header_digest;
224         emem_tree_t *itlq;      /* indexed by ITT */
225         emem_tree_t *itl;               /* indexed by LUN */
226 } iscsi_session_t;
227
228
229
230 /* #ifdef DRAFT08 */
231 #define X_BIT 0x80
232 /* #endif */
233
234 #define I_BIT 0x40
235
236 #define OPCODE_MASK 0x3f
237
238 #define TARGET_OPCODE_BIT 0x20
239
240 #define ISCSI_OPCODE_NOP_OUT                  0x00
241 #define ISCSI_OPCODE_SCSI_COMMAND             0x01
242 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
243 #define ISCSI_OPCODE_LOGIN_COMMAND            0x03
244 #define ISCSI_OPCODE_TEXT_COMMAND             0x04
245 #define ISCSI_OPCODE_SCSI_DATA_OUT            0x05
246 #define ISCSI_OPCODE_LOGOUT_COMMAND           0x06
247 #define ISCSI_OPCODE_SNACK_REQUEST            0x10
248 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I0       0x1c
249 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I1       0x1d
250 #define ISCSI_OPCODE_VENDOR_SPECIFIC_I2       0x1e
251
252 #define ISCSI_OPCODE_NOP_IN                            0x20
253 #define ISCSI_OPCODE_SCSI_RESPONSE                     0x21
254 #define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
255 #define ISCSI_OPCODE_LOGIN_RESPONSE                    0x23
256 #define ISCSI_OPCODE_TEXT_RESPONSE                     0x24
257 #define ISCSI_OPCODE_SCSI_DATA_IN                      0x25
258 #define ISCSI_OPCODE_LOGOUT_RESPONSE                   0x26
259 #define ISCSI_OPCODE_R2T                               0x31
260 #define ISCSI_OPCODE_ASYNC_MESSAGE                     0x32
261 #define ISCSI_OPCODE_REJECT                            0x3f
262 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T0                0x3c
263 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T1                0x3d
264 #define ISCSI_OPCODE_VENDOR_SPECIFIC_T2                0x3e
265
266 #define CSG_SHIFT 2
267 #define CSG_MASK  (0x03 << CSG_SHIFT)
268 #define NSG_MASK  0x03
269
270 #define ISCSI_CSG_SECURITY_NEGOTIATION    (0 << CSG_SHIFT)
271 #define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
272 #define ISCSI_CSG_FULL_FEATURE_PHASE      (3 << CSG_SHIFT)
273
274 #define ISCSI_SCSI_DATA_FLAG_S 0x01
275 #define ISCSI_SCSI_DATA_FLAG_U 0x02
276 #define ISCSI_SCSI_DATA_FLAG_O 0x04
277 #define ISCSI_SCSI_DATA_FLAG_A 0x40
278 #define ISCSI_SCSI_DATA_FLAG_F 0x80
279
280 static const value_string iscsi_opcodes[] = {
281   { ISCSI_OPCODE_NOP_OUT,                           "NOP Out" },
282   { ISCSI_OPCODE_SCSI_COMMAND,                      "SCSI Command" },
283   { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION,          "Task Management Function" },
284   { ISCSI_OPCODE_LOGIN_COMMAND,                     "Login Command" },
285   { ISCSI_OPCODE_TEXT_COMMAND,                      "Text Command" },
286   { ISCSI_OPCODE_SCSI_DATA_OUT,                     "SCSI Data Out" },
287   { ISCSI_OPCODE_LOGOUT_COMMAND,                    "Logout Command" },
288   { ISCSI_OPCODE_SNACK_REQUEST,                     "SNACK Request" },
289   { ISCSI_OPCODE_VENDOR_SPECIFIC_I0,                "Vendor Specific I0" },
290   { ISCSI_OPCODE_VENDOR_SPECIFIC_I1,                "Vendor Specific I1" },
291   { ISCSI_OPCODE_VENDOR_SPECIFIC_I2,                "Vendor Specific I2" },
292
293   { ISCSI_OPCODE_NOP_IN,                            "NOP In" },
294   { ISCSI_OPCODE_SCSI_RESPONSE,                     "SCSI Response" },
295   { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
296   { ISCSI_OPCODE_LOGIN_RESPONSE,                    "Login Response" },
297   { ISCSI_OPCODE_TEXT_RESPONSE,                     "Text Response" },
298   { ISCSI_OPCODE_SCSI_DATA_IN,                      "SCSI Data In" },
299   { ISCSI_OPCODE_LOGOUT_RESPONSE,                   "Logout Response" },
300   { ISCSI_OPCODE_R2T,                               "Ready To Transfer" },
301   { ISCSI_OPCODE_ASYNC_MESSAGE,                     "Asynchronous Message" },
302   { ISCSI_OPCODE_REJECT,                            "Reject"},
303   { ISCSI_OPCODE_VENDOR_SPECIFIC_T0,                "Vendor Specific T0" },
304   { ISCSI_OPCODE_VENDOR_SPECIFIC_T1,                "Vendor Specific T1" },
305   { ISCSI_OPCODE_VENDOR_SPECIFIC_T2,                "Vendor Specific T2" },
306   {0, NULL},
307 };
308
309 /* #ifdef DRAFT08 */
310 static const true_false_string iscsi_meaning_X = {
311     "Retry",
312     "Not retry"
313 };
314 /* #endif */
315
316 /* #ifdef DRAFT09 */
317 static const true_false_string iscsi_meaning_login_X = {
318     "Reinstate failed connection",
319     "New connection"
320 };
321 /* #endif */
322
323 static const true_false_string iscsi_meaning_I = {
324     "Immediate delivery",
325     "Queued delivery"
326 };
327
328 static const true_false_string iscsi_meaning_F = {
329     "Final PDU in sequence",
330     "Not final PDU in sequence"
331 };
332
333 static const true_false_string iscsi_meaning_A = {
334     "Acknowledge requested",
335     "Acknowledge not requested"
336 };
337
338 static const true_false_string iscsi_meaning_T = {
339     "Transit to next login stage",
340     "Stay in current login stage"
341 };
342
343 static const true_false_string iscsi_meaning_C = {
344     "Text is incomplete",
345     "Text is complete"
346 };
347
348 static const true_false_string iscsi_meaning_S = {
349     "Response contains SCSI status",
350     "Response does not contain SCSI status"
351 };
352
353 static const true_false_string iscsi_meaning_R = {
354     "Data will be read from target",
355     "No data will be read from target"
356 };
357
358 static const true_false_string iscsi_meaning_W = {
359     "Data will be written to target",
360     "No data will be written to target"
361 };
362
363 static const true_false_string iscsi_meaning_o = {
364     "Read part of bi-directional command overflowed",
365     "No overflow of read part of bi-directional command",
366 };
367
368 static const true_false_string iscsi_meaning_u = {
369     "Read part of bi-directional command underflowed",
370     "No underflow of read part of bi-directional command",
371 };
372
373 static const true_false_string iscsi_meaning_O = {
374     "Residual overflow occurred",
375     "No residual overflow occurred",
376 };
377
378 static const true_false_string iscsi_meaning_U = {
379     "Residual underflow occurred",
380     "No residual underflow occurred",
381 };
382
383 static const value_string iscsi_scsi_responses[] = {
384     { 0, "Command completed at target" },
385     { 1, "Response does not contain SCSI status"},
386     { 0, NULL }
387 };
388
389 static const value_string iscsi_scsicommand_taskattrs[] = {
390     {0, "Untagged"},
391     {1, "Simple"},
392     {2, "Ordered"},
393     {3, "Head of Queue"},
394     {4, "ACA"},
395     {0, NULL},
396 };
397
398 static const value_string iscsi_task_management_responses[] = {
399     {0, "Function complete"},
400     {1, "Task not in task set"},
401     {2, "LUN does not exist"},
402     {3, "Task still allegiant"},
403     {4, "Task failover not supported"},
404     {5, "Task management function not supported"},
405     {6, "Authorisation failed"},
406     {255, "Function rejected"},
407     {0, NULL},
408 };
409
410 static const value_string iscsi_task_management_functions[] = {
411     {1, "Abort Task"},
412     {2, "Abort Task Set"},
413     {3, "Clear ACA"},
414     {4, "Clear Task Set"},
415     {5, "Logical Unit Reset"},
416     {6, "Target Warm Reset"},
417     {7, "Target Cold Reset"},
418     {8, "Target Reassign"},
419     {0, NULL},
420 };
421
422 static const value_string iscsi_login_status[] = {
423     {0x0000, "Success"},
424     {0x0101, "Target moved temporarily"},
425     {0x0102, "Target moved permanently"},
426     {0x0200, "Initiator error (miscellaneous error)"},
427     {0x0201, "Authentication failed"},
428     {0x0202, "Authorisation failure"},
429     {0x0203, "Target not found"},
430     {0x0204, "Target removed"},
431     {0x0205, "Unsupported version"},
432     {0x0206, "Too many connections"},
433     {0x0207, "Missing parameter"},
434     {0x0208, "Can't include in session"},
435     {0x0209, "Session type not supported"},
436     {0x020a, "Session does not exist"},
437     {0x020b, "Invalid request during login"},
438     {0x0300, "Target error (miscellaneous error)"},
439     {0x0301, "Service unavailable"},
440     {0x0302, "Out of resources"},
441     {0, NULL},
442 };
443
444 static const value_string iscsi_login_stage[] = {
445     {0, "Security negotiation"},
446     {1, "Operational negotiation"},
447     {3, "Full feature phase"},
448     {0, NULL},
449 };
450
451 /* #ifndef DRAFT08 */
452 static const value_string iscsi_isid_type[] = {
453     {0x00, "IEEE OUI"},
454     {0x01, "IANA Enterprise Number"},
455     {0x02, "Random"},
456     {0, NULL},
457 };
458 /* #endif */
459
460 static const value_string iscsi_logout_reasons[] = {
461     {0, "Close session"},
462     {1, "Close connection"},
463     {2, "Remove connection for recovery"},
464     {0, NULL},
465 };
466
467 static const value_string iscsi_logout_response[] = {
468     {0, "Connection closed successfully"},
469     {1, "CID not found"},
470     {2, "Connection recovery not supported"},
471     {3, "Cleanup failed for various reasons"},
472     {0, NULL},
473 };
474
475 static const value_string iscsi_asyncevents[] = {
476     {0, "A SCSI asynchronous event is reported in the sense data"},
477     {1, "Target requests logout"},
478     {2, "Target will/has dropped connection"},
479     {3, "Target will/has dropped all connections"},
480     {4, "Target requests parameter negotiation"},
481     {0, NULL},
482 };
483
484 static const value_string iscsi_snack_types[] = {
485     {0, "Data/R2T"},
486     {1, "Status"},
487 /* #ifndef DRAFT08 */
488     {2, "Data ACK"},
489 /* #endif */
490     {3, "R-Data"},
491     {0, NULL}
492 };
493
494 static const value_string iscsi_reject_reasons[] = {
495 /* #ifdef DRAFT08 */
496     {0x01, "Full feature phase command before login"},
497 /* #endif */
498     {0x02, "Data (payload) digest error"},
499     {0x03, "Data SNACK reject"},
500     {0x04, "Protocol error"},
501     {0x05, "Command not supported in this session type"},
502     {0x06, "Immediate command reject (too many immediate commands)"},
503     {0x07, "Task in progress"},
504     {0x08, "Invalid Data Ack"},
505     {0x09, "Invalid PDU field"},
506     {0x0a, "Long operation reject"},
507     {0x0b, "Negotiation reset"},
508     {0x0c, "Waiting for logout"},
509     {0, NULL},
510 };
511
512 /*****************************************************************/
513 /*                                                               */
514 /* CRC LOOKUP TABLE                                              */
515 /* ================                                              */
516 /* The following CRC lookup table was generated automagically    */
517 /* by the Rocksoft^tm Model CRC Algorithm Table Generation       */
518 /* Program V1.0 using the following model parameters:            */
519 /*                                                               */
520 /*    Width   : 4 bytes.                                         */
521 /*    Poly    : 0x1EDC6F41L                                      */
522 /*    Reverse : TRUE.                                            */
523 /*                                                               */
524 /* For more information on the Rocksoft^tm Model CRC Algorithm,  */
525 /* see the document titled "A Painless Guide to CRC Error        */
526 /* Detection Algorithms" by Ross Williams                        */
527 /* (ross@guest.adelaide.edu.au.). This document is likely to be  */
528 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft".        */
529 /*                                                               */
530 /*****************************************************************/
531
532 static guint32 crc32Table[256] = {
533     0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
534     0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
535     0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
536     0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
537     0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
538     0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
539     0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
540     0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
541     0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
542     0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
543     0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
544     0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
545     0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
546     0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
547     0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
548     0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
549     0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
550     0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
551     0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
552     0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
553     0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
554     0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
555     0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
556     0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
557     0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
558     0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
559     0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
560     0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
561     0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
562     0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
563     0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
564     0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
565     0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
566     0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
567     0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
568     0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
569     0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
570     0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
571     0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
572     0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
573     0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
574     0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
575     0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
576     0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
577     0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
578     0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
579     0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
580     0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
581     0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
582     0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
583     0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
584     0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
585     0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
586     0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
587     0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
588     0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
589     0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
590     0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
591     0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
592     0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
593     0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
594     0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
595     0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
596     0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
597 };
598
599 #define CRC32C_PRELOAD 0xffffffff
600
601 /* 
602  * Byte swap fix contributed by Dave Wysochanski <davidw@netapp.com>
603  */
604 #define CRC32C_SWAP(crc32c_value) \
605                 (((crc32c_value & 0xff000000) >> 24) | \
606                 ((crc32c_value & 0x00ff0000) >>  8) | \
607                 ((crc32c_value & 0x0000ff00) <<  8) | \
608                 ((crc32c_value & 0x000000ff) << 24))
609
610 static guint32
611 calculateCRC32(const void *buf, int len, guint32 crc) {
612     const guint8 *p = (const guint8 *)buf;
613     crc = CRC32C_SWAP(crc);
614     while(len-- > 0)
615         crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
616     return CRC32C_SWAP(crc);
617 }
618
619
620
621
622
623 /* structure and functions to keep track of 
624  * COMMAND/DATA_IN/DATA_OUT/RESPONSE matching 
625  */
626 typedef struct _iscsi_conv_data {
627     guint32 data_in_frame;
628     guint32 data_out_frame;
629     itlq_nexus_t itlq;
630 } iscsi_conv_data_t;
631
632 static int
633 iscsi_min(int a, int b) {
634     return (a < b)? a : b;
635 }
636
637 static gint
638 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
639     const gint limit = offset + text_len;
640     while(offset < limit) {
641         gint len = tvb_strnlen(tvb, offset, limit - offset);
642         if(len == -1)
643             len = limit - offset;
644         else
645             len = len + 1;
646         proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
647         offset += len;
648     }
649     return offset;
650 }
651
652 static gint
653 handleHeaderDigest(iscsi_session_t *iscsi_session, proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
654     int available_bytes = tvb_length_remaining(tvb, offset);
655
656     switch(iscsi_session->header_digest){
657     case ISCSI_HEADER_DIGEST_CRC32:
658         if(available_bytes >= (headerLen + 4)) {
659             guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
660             guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
661             if(crc == sent) {
662                 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
663             } else {
664                 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);
665             }
666         }
667         return offset + headerLen + 4;
668         break;
669     }
670     return offset + headerLen;
671 }
672
673 static gint
674 handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
675     int available_bytes = tvb_length_remaining(tvb, offset);
676     if(enableDataDigests) {
677         if(dataDigestIsCRC32) {
678             if(available_bytes >= (dataLen + 4)) {
679                 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
680                 guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
681                 if(crc == sent) {
682                     proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
683                 }
684                 else {
685                     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);
686                 }
687             }
688             return offset + dataLen + 4;
689         }
690         if((unsigned)available_bytes >= (dataLen + dataDigestSize)) {
691             proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
692         }
693         return offset + dataLen + dataDigestSize;
694     }
695     return offset + dataLen;
696 }
697
698 static int
699 handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
700     if(endOffset > offset) {
701         int dataOffset = offset;
702         int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
703         if(dataLen > 0) {
704             proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
705             offset += dataLen;
706         }
707         if(offset < endOffset && (offset & 3) != 0) {
708             int padding = 4 - (offset & 3);
709             proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
710             offset += padding;
711         }
712         if(dataSegmentLen > 0 && offset < endOffset)
713             offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
714     }
715
716     return offset;
717 }
718
719 static int
720 handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
721     if(endOffset > offset) {
722         int dataOffset = offset;
723         int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
724         if(textLen > 0) {
725             proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
726             proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
727             offset = addTextKeys(tt, tvb, offset, textLen);
728         }
729         if(offset < endOffset && (offset & 3) != 0) {
730             int padding = 4 - (offset & 3);
731             proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
732             offset += padding;
733         }
734         if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
735             offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
736     }
737     return offset;
738 }
739
740 /* Code to actually dissect the packets */
741 static void
742 dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len, iscsi_session_t *iscsi_session) {
743
744     guint original_offset = offset;
745     proto_tree *ti = NULL;
746     guint8 scsi_status = 0;
747     gboolean S_bit=FALSE;
748     guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
749     guint end_offset = offset + tvb_length_remaining(tvb, offset);
750     iscsi_conv_data_t *cdata = NULL;
751     int paddedDataSegmentLength = data_segment_len;
752     guint16 lun=0xffff;
753     guint immediate_data_length=0;
754     guint immediate_data_offset=0;
755     itl_nexus_t *itl=NULL;
756     guint16 ahs_length=0;
757     guint8 ahs_type=0;
758
759     if(paddedDataSegmentLength & 3)
760         paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
761
762     /* Make entries in Protocol column and Info column on summary display */
763     if (check_col(pinfo->cinfo, COL_PROTOCOL))
764         col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
765
766     /* XXX we need a way to handle replayed iscsi itt here */
767     cdata=(iscsi_conv_data_t *)se_tree_lookup32(iscsi_session->itlq, tvb_get_ntohl(tvb, offset+16));
768     if(!cdata){
769         cdata = se_alloc (sizeof(iscsi_conv_data_t));
770         cdata->itlq.lun=0xffff;
771         cdata->itlq.scsi_opcode=0xffff;
772         cdata->itlq.fc_time = pinfo->fd->abs_ts;
773         cdata->itlq.first_exchange_frame=0;
774         cdata->itlq.last_exchange_frame=0;
775         cdata->itlq.flags=0;
776         cdata->itlq.alloc_len=0;
777         cdata->itlq.extra_data=NULL;
778         cdata->data_in_frame=0;
779         cdata->data_out_frame=0;
780
781         se_tree_insert32(iscsi_session->itlq, tvb_get_ntohl(tvb, offset+16), cdata);
782     }
783
784     if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
785         opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
786         scsi_status = tvb_get_guint8 (tvb, offset+3);
787     }
788
789     if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
790         (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
791         (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
792         /* first time we see this packet. check if we can find the request */
793         switch(opcode){
794         case ISCSI_OPCODE_SCSI_RESPONSE:
795             cdata->itlq.last_exchange_frame=pinfo->fd->num;
796             break;
797         case ISCSI_OPCODE_SCSI_DATA_IN:
798             /* a bit ugly but we need to check the S bit here */
799             if(tvb_get_guint8(tvb, offset+1)&ISCSI_SCSI_DATA_FLAG_S){
800                 cdata->itlq.last_exchange_frame=pinfo->fd->num;
801             }
802             cdata->data_in_frame=pinfo->fd->num;
803             break;
804         case ISCSI_OPCODE_SCSI_DATA_OUT:
805             cdata->data_out_frame=pinfo->fd->num;
806             break;
807         }
808
809     } else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
810         /*we need the LUN value for some of the commands so we can pass it
811           across to the SCSI dissector.
812           Not correct but simple  and probably accurate enough :
813           If bit 6 of first bit is 0   then just take second byte as the LUN
814           If bit 6 of first bit is 1, then take 6 bits from first byte
815           and all of second byte and pretend it is the lun value
816           people that care can add host specific dissection of vsa later.
817
818           We need to keep track of this on a per transaction basis since
819           for error recoverylevel 0 and when the A bit is clear in a 
820           Data-In PDU, there will not be a LUN field in teh iscsi layer.
821         */
822         if(tvb_get_guint8(tvb, offset+8)&0x40){
823           /* volume set addressing */
824           lun=tvb_get_guint8(tvb,offset+8)&0x3f;
825           lun<<=8;
826           lun|=tvb_get_guint8(tvb,offset+9);
827         } else {
828           lun=tvb_get_guint8(tvb,offset+9);
829         }
830
831         cdata->itlq.lun=lun;
832         cdata->itlq.first_exchange_frame=pinfo->fd->num;
833
834         itl=(itl_nexus_t *)se_tree_lookup32(iscsi_session->itl, lun);
835         if(!itl){
836             itl=se_alloc(sizeof(itl_nexus_t));
837             itl->cmdset=0xff;
838             se_tree_insert32(iscsi_session->itl, lun, itl);
839         }
840
841     }
842
843     if(!itl){
844         itl=(itl_nexus_t *)se_tree_lookup32(iscsi_session->itl, cdata->itlq.lun);
845     }
846
847
848     if (check_col(pinfo->cinfo, COL_INFO)) {
849
850         if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
851
852             col_append_str(pinfo->cinfo, COL_INFO, opcode_str);
853
854             if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
855                 (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
856                  (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
857                 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
858                                  val_to_str (scsi_status, scsi_status_val, "0x%x"));
859             }
860             else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
861                 guint16 login_status = tvb_get_ntohs(tvb, offset+36);
862                 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
863                                  val_to_str (login_status, iscsi_login_status, "0x%x"));
864             }
865             else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
866                 guint8 logoutReason;
867                 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
868                     logoutReason = tvb_get_guint8(tvb, offset+11);
869                 } else if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
870                     logoutReason = tvb_get_guint8(tvb, offset+1) & 0x7f;
871                 }
872                 else {
873                     logoutReason = tvb_get_guint8(tvb, offset+23);
874                 }
875                 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
876                                  val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
877             }
878             else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
879                 guint8 tmf = tvb_get_guint8(tvb, offset + 1);
880                 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
881                                  val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
882             }
883             else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
884                 guint8 resp = tvb_get_guint8(tvb, offset + 2);
885                 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
886                                  val_to_str (resp, iscsi_task_management_responses, "0x%x"));
887             }
888             else if (opcode == ISCSI_OPCODE_REJECT) {
889                 guint8 reason = tvb_get_guint8(tvb, offset + 2);
890                 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
891                                  val_to_str (reason, iscsi_reject_reasons, "0x%x"));
892             }
893             else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
894                 guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
895                 col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
896                                  val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
897             }
898         }
899     }
900
901     /* In the interest of speed, if "tree" is NULL, don't do any
902        work not necessary to generate protocol tree items. */
903     if (tree) {
904         proto_item *tp;
905         /* create display subtree for the protocol */
906         tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
907                                             offset, -1, "iSCSI (%s)",
908                                             opcode_str);
909         ti = proto_item_add_subtree(tp, ett_iscsi);
910     }
911     proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
912                             offset + 0, 1, opcode);
913     if((opcode & TARGET_OPCODE_BIT) == 0) {
914             /* initiator -> target */
915             gint b = tvb_get_guint8(tvb, offset + 0);
916         if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
917                 if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
918                    opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
919                    opcode != ISCSI_OPCODE_SNACK_REQUEST)
920                     proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
921         }
922             if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
923                opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
924                opcode != ISCSI_OPCODE_SNACK_REQUEST)
925                 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
926     }
927
928     if(opcode == ISCSI_OPCODE_NOP_OUT) {
929             /* NOP Out */
930             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
931                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
932             }
933             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
934             proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
935             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
936             proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
937             proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
938             proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
939             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
940             offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
941     } else if(opcode == ISCSI_OPCODE_NOP_IN) {
942             /* NOP In */
943             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
944                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
945             }
946             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
947             proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
948             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
949             proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
950             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
951             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
952             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
953             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
954             offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
955     } else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
956             /* SCSI Command */
957             guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
958             {
959                 gint b = tvb_get_guint8(tvb, offset + 1);
960                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
961                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
962
963                 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
964                 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
965                 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
966                 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
967             }
968             if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
969                 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
970             }
971             proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
972             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
973             proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
974             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
975             proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
976             proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
977             proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
978             {
979                 if(ahsLen > 0) {
980                     ahs_length=tvb_get_ntohs(tvb, offset+48);
981                     proto_tree_add_item(ti, hf_iscsi_AHS_length, tvb, offset + 48, 2, FALSE);
982                     ahs_type=tvb_get_guint8(tvb, offset+50);
983                     proto_tree_add_item(ti, hf_iscsi_AHS_type, tvb, offset + 50, 1, FALSE);
984                     proto_tree_add_item(ti, hf_iscsi_AHS_specific, tvb, offset + 51, 1, FALSE);
985                     proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 52, ahsLen-4, FALSE);
986                 }
987                 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48 + ahsLen);
988             }
989             immediate_data_offset=offset;
990             offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
991             immediate_data_length=offset-immediate_data_offset;
992     } else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
993             /* SCSI Response */
994             {
995                 gint b = tvb_get_guint8(tvb, offset + 1);
996                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
997                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
998
999                 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
1000                 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
1001                 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
1002                 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
1003             }
1004             proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
1005             proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1006             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1007                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1008             }
1009             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1010             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1011             if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1012                 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
1013             }
1014             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1015             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1016             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1017             proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1018             if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1019                 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
1020             }
1021             else {
1022                 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
1023                 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
1024             }
1025             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1026             /* do not update offset here because the data segment is
1027              * dissected below */
1028             handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1029     } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
1030             /* Task Management Function */
1031             proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
1032             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1033                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1034                 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1035             }
1036             proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1037             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1038             proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1039             proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1040             proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1041             proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
1042             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1043     } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
1044             /* Task Management Function Response */
1045             proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
1046             if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1047                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1048                 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1049             }
1050             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1051             if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1052                 proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1053             }
1054             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1055             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1056             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1057             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1058     } else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
1059             /* Login Command */
1060             int digestsActive = 0;
1061             {
1062                 gint b = tvb_get_guint8(tvb, offset + 1);
1063                 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1064                     if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1065                         digestsActive = 1;
1066                 }
1067 #if 0
1068                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1069                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1070 #endif
1071
1072                 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1073                 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1074                     proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1075                 }
1076                 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1077                     proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
1078                 }
1079                 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1080
1081                 /* NSG is undefined unless T is set */
1082                 if(b&0x80){
1083                         proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1084                 }
1085             }
1086             proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1087             proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1088             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1089                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1090             }
1091             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1092             if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1093                 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1094                 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1095             }
1096             else {
1097                 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1098                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1099                 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1100                     proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1101                     proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1102                     proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1103                 }
1104                 else {
1105                     proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1106                     proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1107                     proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1108                     proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1109                     proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1110                 }
1111             }
1112             if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1113                 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1114             }
1115             else {
1116                 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1117             }
1118             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1119             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1120                 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1121             }
1122             proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1123             proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1124             if(digestsActive){
1125                 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1126             } else {
1127                 offset += 48;
1128             }
1129             offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1130     } else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
1131             /* Login Response */
1132             int digestsActive = 0;
1133             {
1134                 gint b = tvb_get_guint8(tvb, offset + 1);
1135                 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1136                     if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
1137                         digestsActive = 1;
1138                 }
1139 #if 0
1140                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1141                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1142 #endif
1143
1144                 proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
1145                 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1146                     proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
1147                 }
1148                 proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
1149                 /* NSG is undefined unless T is set */
1150                 if(b&0x80){
1151                         proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
1152                 }
1153             }
1154
1155             proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1156             proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
1157             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1158                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1159             }
1160             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1161             if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1162                 proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
1163             }
1164             else {
1165                 proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
1166                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
1167                 if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
1168                     proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
1169                     proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
1170                     proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
1171                 }
1172                 else {
1173                     proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
1174                     proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
1175                     proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
1176                     proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
1177                     proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
1178                 }
1179             }
1180             if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
1181                 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1182             }
1183             else {
1184                 proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
1185             }
1186             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1187             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1188             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1189             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1190             proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
1191             if(digestsActive){
1192                 offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1193             } else {
1194                 offset += 48;
1195             }
1196             offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
1197     } else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
1198             /* Text Command */
1199             {
1200                 gint b = tvb_get_guint8(tvb, offset + 1);
1201                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1202                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1203
1204                 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1205                 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1206                     proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1207                 }
1208             }
1209             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1210                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1211             }
1212             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1213             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1214                 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1215             }
1216             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1217             proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1218             proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1219             proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1220             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1221             offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1222     } else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
1223             /* Text Response */
1224             {
1225                 gint b = tvb_get_guint8(tvb, offset + 1);
1226                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1227                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1228
1229                 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1230                 if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1231                     proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
1232                 }
1233             }
1234             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1235                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1236             }
1237             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1238             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1239                 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1240             }
1241             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1242             proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1243             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1244             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1245             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1246             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1247             offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
1248     } else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
1249             /* SCSI Data Out (write) */
1250             {
1251                 gint b = tvb_get_guint8(tvb, offset + 1);
1252                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1253                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1254
1255                 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1256             }
1257             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1258                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1259             }
1260             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1261             proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1262             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1263             proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1264             proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1265             proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1266             proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1267             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1268             /* do not update offset here because the data segment is
1269              * dissected below */
1270             handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1271     } else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
1272             /* SCSI Data In (read) */
1273             {
1274                 gint b = tvb_get_guint8(tvb, offset + 1);
1275                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1276                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1277
1278                 if(b&ISCSI_SCSI_DATA_FLAG_S){
1279                    S_bit=TRUE;
1280                 }
1281                 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1282                 if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1283                     proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
1284                 }
1285                 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1286                 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1287                 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1288             }
1289             if(S_bit){
1290                 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
1291             }
1292             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1293                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1294             }
1295             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1296             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1297                 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1298             }
1299             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1300             if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1301                 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
1302             }
1303             else {
1304                 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1305             }
1306             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1307             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1308             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1309             proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1310             proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1311             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1312                 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1313             }
1314             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1315             /* do not update offset here because the data segment is
1316              * dissected below */
1317             handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
1318     } else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
1319             /* Logout Command */
1320             if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
1321                 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 1, 1, FALSE);
1322             }
1323             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1324                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1325                 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1326             }
1327             if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
1328                 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1329                 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1330             }
1331             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1332             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
1333                 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
1334                 if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT13) {
1335                     proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
1336                 }
1337             }
1338             proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1339             proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1340             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1341     } else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
1342             /* Logout Response */
1343             proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
1344             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1345                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1346                 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1347             }
1348             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1349             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1350             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1351             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1352             proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
1353             proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
1354             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1355     } else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
1356             /* SNACK Request */
1357             {
1358                 gint b = tvb_get_guint8(tvb, offset + 1);
1359 #if 0
1360                 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1361                 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1362 #endif
1363
1364                 proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
1365             }
1366             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1367                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1368                 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1369                 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1370             }
1371             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1372             if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
1373                 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1374                 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1375                 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1376                 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
1377             }
1378             else {
1379                 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1380                 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1381                 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
1382                 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
1383             }
1384             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1385     } else if(opcode == ISCSI_OPCODE_R2T) {
1386             /* R2T */
1387             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1388                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1389                 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1390                 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1391             }
1392             proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1393             proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1394             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1395             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1396             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1397             proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
1398             proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1399             proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1400             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1401     } else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
1402             /* Asynchronous Message */
1403             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1404                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1405             }
1406             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1407             proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1408             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1409             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1410             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1411             proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
1412             proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
1413             proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1414             proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1415             proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1416             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1417             offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
1418     } else if(opcode == ISCSI_OPCODE_REJECT) {
1419             /* Reject */
1420             proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
1421             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1422                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1423             }
1424             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1425             proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1426             proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1427             proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1428             proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1429             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1430             offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
1431     } else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
1432                 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
1433                 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
1434                 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
1435                 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
1436                 opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
1437             /* Vendor specific opcodes */
1438             if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
1439                 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
1440             }
1441             proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1442             offset = handleHeaderDigest(iscsi_session, ti, tvb, offset, 48);
1443             offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
1444     }
1445
1446
1447
1448     /* handle request/response matching */
1449     switch(opcode){
1450     case ISCSI_OPCODE_SCSI_RESPONSE:
1451         if (cdata->itlq.first_exchange_frame){
1452             nstime_t delta_time;
1453             proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1454             nstime_delta(&delta_time, &pinfo->fd->abs_ts, &cdata->itlq.fc_time);
1455             proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1456         }
1457         if (cdata->data_in_frame)
1458             proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1459         if (cdata->data_out_frame)
1460             proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1461         break;
1462     case ISCSI_OPCODE_SCSI_DATA_IN:
1463         /* if we have phase collaps then we might have the
1464            response embedded in the last DataIn segment */
1465         if(!S_bit){
1466             if (cdata->itlq.first_exchange_frame)
1467                 proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1468             if (cdata->itlq.last_exchange_frame)
1469                 proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1470         } else {
1471             if (cdata->itlq.first_exchange_frame){
1472                  nstime_t delta_time;
1473                  proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1474                  nstime_delta(&delta_time, &pinfo->fd->abs_ts, &cdata->itlq.fc_time);
1475                  proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
1476             }
1477         }
1478         if (cdata->data_out_frame)
1479             proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1480         break;
1481     case ISCSI_OPCODE_SCSI_DATA_OUT:
1482         if (cdata->itlq.first_exchange_frame)
1483             proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->itlq.first_exchange_frame);
1484         if (cdata->data_in_frame)
1485             proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1486         if (cdata->itlq.last_exchange_frame)
1487             proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1488         break;
1489     case ISCSI_OPCODE_SCSI_COMMAND:
1490         if (cdata->data_in_frame)
1491             proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
1492         if (cdata->data_out_frame)
1493             proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
1494         if (cdata->itlq.last_exchange_frame)
1495             proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->itlq.last_exchange_frame);
1496         break;
1497     }
1498
1499
1500
1501     proto_item_set_len(ti, offset - original_offset);
1502
1503     if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
1504                   ~(X_BIT | I_BIT) :
1505                   ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
1506         tvbuff_t *cdb_tvb, *data_tvb;
1507         int tvb_len, tvb_rlen;
1508         guint8 scsi_opcode;
1509
1510         /* SCSI Command */
1511         tvb_len=tvb_length_remaining(tvb, cdb_offset);
1512         tvb_rlen=tvb_reported_length_remaining(tvb, cdb_offset);
1513         scsi_opcode=tvb_get_guint8(tvb, cdb_offset);
1514         if(ahs_type==1 && ahs_length && ahs_length<1024){
1515                 char *cdb_buf;
1516
1517                 /* We have a variable length CDB where bytes >16 is transported
1518                  * in the AHS.
1519                  */
1520                 cdb_buf=ep_alloc(16+ahs_length-1);
1521                 /* the 16 first bytes of the cdb */
1522                 tvb_memcpy(tvb, cdb_buf, cdb_offset, 16);
1523                 /* hte remainder of the cdb from the ahs */
1524                 tvb_memcpy(tvb, cdb_buf+16, cdb_offset+20, ahs_length-1);
1525
1526                 cdb_tvb = tvb_new_real_data(cdb_buf,
1527                                           ahs_length+16-1,
1528                                           ahs_length+16-1);
1529
1530                 tvb_set_child_real_data_tvbuff(tvb, cdb_tvb);
1531
1532                 add_new_data_source(pinfo, cdb_tvb, "CDB+AHS");
1533         } else {
1534                 if(tvb_len>16){
1535                     tvb_len=16;
1536                 }
1537                 if(tvb_rlen>16){
1538                     tvb_rlen=16;
1539                 }
1540                 cdb_tvb=tvb_new_subset(tvb, cdb_offset, tvb_len, tvb_rlen);
1541         }
1542         dissect_scsi_cdb(cdb_tvb, pinfo, tree, SCSI_DEV_UNKNOWN, &cdata->itlq, itl);
1543         /* we dont want the immediata below to overwrite our CDB info */
1544         if (check_col(pinfo->cinfo, COL_INFO)) {
1545             col_set_fence(pinfo->cinfo, COL_INFO);
1546         }
1547         /* where there any ImmediateData ? */
1548         if(immediate_data_length){
1549             /* Immediate Data TVB */
1550             tvb_len=tvb_length_remaining(tvb, immediate_data_offset);
1551             if(tvb_len>(int)immediate_data_length)
1552                 tvb_len=immediate_data_length;
1553             tvb_rlen=tvb_reported_length_remaining(tvb, immediate_data_offset);
1554             if(tvb_rlen>(int)immediate_data_length)
1555                 tvb_rlen=immediate_data_length;
1556             data_tvb=tvb_new_subset(tvb, immediate_data_offset, tvb_len, tvb_rlen);
1557             dissect_scsi_payload (data_tvb, pinfo, tree,
1558                                   TRUE,
1559                                   &cdata->itlq, itl);
1560         }
1561     }
1562     else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
1563         if (scsi_status == 0x2) {
1564             /* A SCSI response with Check Condition contains sense data */
1565             /* offset is setup correctly by the iscsi code for response above */
1566             if((end_offset - offset) >= 2) {
1567                 int senseLen = tvb_get_ntohs(tvb, offset);
1568                 if(ti != NULL)
1569                     proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
1570                 offset += 2;
1571                 if(senseLen > 0){
1572                     tvbuff_t *data_tvb;
1573                     int tvb_len, tvb_rlen;
1574
1575                     tvb_len=tvb_length_remaining(tvb, offset);
1576                     if(tvb_len>senseLen)
1577                         tvb_len=senseLen;
1578                     tvb_rlen=tvb_reported_length_remaining(tvb, offset);
1579                     if(tvb_rlen>senseLen)
1580                         tvb_rlen=senseLen;
1581                     data_tvb=tvb_new_subset(tvb, offset, tvb_len, tvb_rlen);
1582                     dissect_scsi_snsinfo (data_tvb, pinfo, tree, 0,
1583                                           tvb_len,
1584                                           &cdata->itlq, itl);
1585                 }
1586             }
1587         }
1588         else {
1589             dissect_scsi_rsp(tvb, pinfo, tree, &cdata->itlq, itl, scsi_status);
1590         }
1591     }
1592     else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
1593              (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
1594         tvbuff_t *data_tvb;
1595         int tvb_len, tvb_rlen;
1596
1597         /* offset is setup correctly by the iscsi code for response above */
1598         tvb_len=tvb_length_remaining(tvb, offset);
1599         if(tvb_len>(int)data_segment_len)
1600             tvb_len=data_segment_len;
1601         tvb_rlen=tvb_reported_length_remaining(tvb, offset);
1602         if(tvb_rlen>(int)data_segment_len)
1603             tvb_rlen=data_segment_len;
1604         data_tvb=tvb_new_subset(tvb, offset, tvb_len, tvb_rlen);
1605         dissect_scsi_payload (data_tvb, pinfo, tree,
1606                               (opcode==ISCSI_OPCODE_SCSI_DATA_OUT),
1607                               &cdata->itlq, itl);
1608     }
1609
1610     if(S_bit){
1611         dissect_scsi_rsp(tvb, pinfo, tree, &cdata->itlq, itl, scsi_status);
1612     }
1613 }
1614
1615 static gboolean
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;
1619     guint offset = 0;
1620     guint32 available_bytes = tvb_length_remaining(tvb, offset);
1621     int digestsActive = 1;
1622     conversation_t *conversation = NULL;
1623     iscsi_session_t *iscsi_session=NULL;
1624     guint8 opcode, tmpbyte;
1625
1626     /* quick check to see if the packet is long enough to contain the
1627      * minimum amount of information we need */
1628     if (available_bytes < 48 ){
1629         /* no, so give up */
1630         return FALSE;
1631     }
1632
1633     opcode = tvb_get_guint8(tvb, offset + 0);
1634     opcode &= OPCODE_MASK;
1635
1636     /* heuristics to verify that the packet looks sane.   the heuristics
1637      * are based on the RFC version of iscsi.
1638      * (we should retire support for older iscsi versions in wireshark)
1639      *      -- ronnie s
1640      */
1641     /* opcode must be any of the ones from the standard
1642      * also check the header that it looks "sane"
1643      * all reserved or undefined bits in iscsi must be set to zero.
1644      */
1645     switch(opcode){
1646     case ISCSI_OPCODE_NOP_IN:
1647         /* top two bits of byte 0 must be 0 */
1648         if(tvb_get_guint8(tvb, offset+0)&0xc0){
1649             return FALSE;
1650         }
1651         /* byte 1 must be 0x80 */
1652         if(tvb_get_guint8(tvb, offset+1)!=0x80){
1653             return FALSE;
1654         }
1655         /* bytes 2 and 3 must be 0 */
1656         if(tvb_get_guint8(tvb, offset+2)||tvb_get_guint8(tvb, offset+3)){
1657             return FALSE;
1658         }
1659         break;
1660     case ISCSI_OPCODE_NOP_OUT:
1661         /* top bit of byte 0 must be 0 */
1662         if(tvb_get_guint8(tvb, offset+0)&0x80){
1663             return FALSE;
1664         }
1665         /* byte 1 must be 0x80 */
1666         if(tvb_get_guint8(tvb, offset+1)!=0x80){
1667             return FALSE;
1668         }
1669         /* bytes 2 and 3 must be 0 */
1670         if(tvb_get_guint8(tvb, offset+2)||tvb_get_guint8(tvb, offset+3)){
1671             return FALSE;
1672         }
1673         /* assume ITT and TTT must always be non NULL (ok they can be NULL
1674          * from time to time but it usually means we are in the middle
1675          * of a zeroed datablock).
1676          */
1677         if(!tvb_get_letohl(tvb,offset+16) || !tvb_get_letohl(tvb,offset+20)){
1678             return FALSE;
1679         }
1680         /* all reserved bytes between 32 - 47 must be null */
1681         if(tvb_get_letohl(tvb,offset+32)
1682         || tvb_get_letohl(tvb,offset+36)
1683         || tvb_get_letohl(tvb,offset+40)
1684         || tvb_get_letohl(tvb,offset+44)){
1685             return FALSE;
1686         }
1687         break;
1688     case ISCSI_OPCODE_LOGIN_COMMAND:
1689         /* top two bits in byte 0 must be 0x40 */
1690         if((tvb_get_guint8(tvb, offset+0)&0xc0)!=0x40){
1691
1692             return FALSE;
1693         }
1694         /* exactly one of the T and C bits must be set
1695          * and the two reserved bits in byte 1 must be 0
1696          */
1697         tmpbyte=tvb_get_guint8(tvb, offset+1);
1698         switch(tmpbyte&0xf0){
1699         case 0x80:
1700         case 0x40:
1701             break;
1702         default:
1703             return FALSE;
1704         }
1705         /* CSG and NSG must not be 2 */
1706         if(((tmpbyte&0x03)==0x02)
1707         || ((tmpbyte&0xc0)==0x08)){
1708             return FALSE;
1709         }
1710         /* if T bit is set NSG must not be 0 */
1711         if(tmpbyte&0x80){
1712             if(!(tmpbyte&0x03)){
1713                 return FALSE;
1714             }
1715         }
1716         /* should we test that datasegmentlen is non zero? */
1717         break;
1718     case ISCSI_OPCODE_LOGIN_RESPONSE:
1719         /* top two bits in byte 0 must be 0 */
1720         if(tvb_get_guint8(tvb, offset+0)&0xc0){
1721
1722             return FALSE;
1723         }
1724         /* both the T and C bits can not be set
1725          * and the two reserved bits in byte 1 must be 0
1726          */
1727         tmpbyte=tvb_get_guint8(tvb, offset+1);
1728         switch(tmpbyte&0xf0){
1729         case 0x80:
1730         case 0x40:
1731         case 0x00:
1732             break;
1733         default:
1734             return FALSE;
1735         }
1736         /* CSG and NSG must not be 2 */
1737         if(((tmpbyte&0x03)==0x02)
1738         || ((tmpbyte&0xc0)==0x08)){
1739             return FALSE;
1740         }
1741         /* if T bit is set NSG must not be 0 */
1742         if(tmpbyte&0x80){
1743             if(!(tmpbyte&0x03)){
1744                 return FALSE;
1745             }
1746         }
1747         /* the 32bit words at offsets 20, 40, 44 must be zero */
1748         if(tvb_get_letohl(tvb,offset+20)
1749         || tvb_get_letohl(tvb,offset+40)
1750         || tvb_get_letohl(tvb,offset+44)){
1751             return FALSE;
1752         }
1753         /* the two bytes at offset 38 must be zero */
1754         if(tvb_get_letohs(tvb,offset+38)){
1755             return FALSE;
1756         }
1757         /* should we test that datasegmentlen is non zero unless we just
1758          * entered full featured phase? 
1759          */
1760         break;
1761     case ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION:
1762         /* top bit in byte 0 must be 0 */
1763         if(tvb_get_guint8(tvb, offset+0)&0x80){
1764             return FALSE;
1765         }
1766         /* top bit in byte 1 must be set */
1767         tmpbyte=tvb_get_guint8(tvb, offset+1);
1768         if(!(tmpbyte&0x80)){
1769             return FALSE;
1770         }
1771         /* Function must be known */
1772         if(!match_strval(tmpbyte&0x7f, iscsi_task_management_functions)){
1773             return FALSE;
1774         }
1775         /* bytes 2,3 must be null */
1776         if(tvb_get_letohs(tvb,offset+2)){
1777             return FALSE;
1778         }
1779         /* ahs and dsl must be null */
1780         if(tvb_get_letohl(tvb,offset+4)){
1781             return FALSE;
1782         }
1783         break;
1784     case ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE:
1785         /* top two bits in byte 0 must be 0 */
1786         if(tvb_get_guint8(tvb, offset+0)&0xc0){
1787             return FALSE;
1788         }
1789         /* byte 1 must be 0x80 */
1790         if(tvb_get_guint8(tvb, offset+1)!=0x80){
1791             return FALSE;
1792         }
1793         /* response must be 0-6 or 255 */
1794         tmpbyte=tvb_get_guint8(tvb,offset+2);
1795         if(tmpbyte>6 && tmpbyte<255){
1796             return FALSE;
1797         }
1798         /* byte 3 must be 0 */
1799         if(tvb_get_guint8(tvb,offset+3)){
1800             return FALSE;
1801         }
1802         /* ahs and dsl  as well as the 32bit words at offsets 8, 12, 20, 36
1803          * 40, 44 must all be 0
1804          */
1805         if(tvb_get_letohl(tvb,offset+4)
1806         || tvb_get_letohl(tvb,offset+8)
1807         || tvb_get_letohl(tvb,offset+12)
1808         || tvb_get_letohl(tvb,offset+20)
1809         || tvb_get_letohl(tvb,offset+36)
1810         || tvb_get_letohl(tvb,offset+40)
1811         || tvb_get_letohl(tvb,offset+44)){
1812             return FALSE;
1813         }
1814         break;
1815     case ISCSI_OPCODE_LOGOUT_COMMAND:
1816         /* top bit in byte 0 must be 0 */
1817         if(tvb_get_guint8(tvb, offset+0)&0x80){
1818             return FALSE;
1819         }
1820         /* top bit in byte 1 must be set */
1821         tmpbyte=tvb_get_guint8(tvb, offset+1);
1822         if(!(tmpbyte&0x80)){
1823             return FALSE;
1824         }
1825         /* Reason code must be known */
1826         if(!match_strval(tmpbyte&0x7f, iscsi_logout_reasons)){
1827             return FALSE;
1828         }
1829         /* bytes 2,3 must be null */
1830         if(tvb_get_letohs(tvb,offset+2)){
1831             return FALSE;
1832         }
1833         /* ahs and dsl  as well as the 32bit words at offsets 8, 12, 32, 36
1834          * 40, 44 must all be 0
1835          */
1836         if(tvb_get_letohl(tvb,offset+4)
1837         || tvb_get_letohl(tvb,offset+8)
1838         || tvb_get_letohl(tvb,offset+12)
1839         || tvb_get_letohl(tvb,offset+32)
1840         || tvb_get_letohl(tvb,offset+36)
1841         || tvb_get_letohl(tvb,offset+40)
1842         || tvb_get_letohl(tvb,offset+44)){
1843             return FALSE;
1844         }
1845         break;
1846     case ISCSI_OPCODE_SNACK_REQUEST:
1847         /* top two bits in byte 0 must be 0 */
1848         if(tvb_get_guint8(tvb, offset+0)&0xc0){
1849             return FALSE;
1850         }
1851         /* top 4 bits in byte 1 must be 0x80 */
1852         tmpbyte=tvb_get_guint8(tvb, offset+1);
1853         if((tmpbyte&0xf0)!=0x80){
1854             return FALSE;
1855         }
1856         /* type must be known */
1857         if(!match_strval(tmpbyte&0x0f, iscsi_snack_types)){
1858             return FALSE;
1859         }
1860         /* for status/snack and datack itt must be 0xffffffff
1861          * for rdata/snack ttt must not be 0 or 0xffffffff
1862          */
1863         switch(tmpbyte&0x0f){
1864         case 1:
1865         case 2:
1866             if(tvb_get_letohl(tvb,offset+16)!=0xffffffff){
1867                 return FALSE;
1868             }
1869             break;
1870         case 3:
1871             if(tvb_get_letohl(tvb,offset+20)==0xffffffff){
1872                 return FALSE;
1873             }
1874             if(tvb_get_letohl(tvb,offset+20)==0){
1875                 return FALSE;
1876             }
1877             break;
1878         }
1879         /* bytes 2,3 must be null */
1880         if(tvb_get_letohs(tvb,offset+2)){
1881             return FALSE;
1882         }
1883         /* the 32bit words at offsets 24, 32, 36
1884          * must all be 0
1885          */
1886         if(tvb_get_letohl(tvb,offset+24)
1887         || tvb_get_letohl(tvb,offset+32)
1888         || tvb_get_letohl(tvb,offset+36)){
1889             return FALSE;
1890         }
1891
1892         break;
1893     case ISCSI_OPCODE_R2T:
1894         /* top two bits in byte 0 must be 0 */
1895         if(tvb_get_guint8(tvb, offset+0)&0xc0){
1896             return FALSE;
1897         }
1898         /* byte 1 must be 0x80 */
1899         if(tvb_get_guint8(tvb, offset+1)!=0x80){
1900             return FALSE;
1901         }
1902         /* bytes 2,3 must be null */
1903         if(tvb_get_letohs(tvb,offset+2)){
1904             return FALSE;
1905         }
1906         /* ahs and dsl must be null */
1907         if(tvb_get_letohl(tvb,offset+4)){
1908             return FALSE;
1909         }
1910         /* desired data transfer length must not be null */
1911         if(!tvb_get_letohl(tvb,offset+44)){
1912             return FALSE;
1913         }
1914         break;
1915     case ISCSI_OPCODE_REJECT:
1916         /* top two bits in byte 0 must be 0 */
1917         if(tvb_get_guint8(tvb, offset+0)&0xc0){
1918             return FALSE;
1919         }
1920         /* byte 1 must be 0x80 */
1921         if(tvb_get_guint8(tvb, offset+1)!=0x80){
1922             return FALSE;
1923         }
1924         /* reason must be known */
1925         if(!match_strval(tvb_get_guint8(tvb,offset+2), iscsi_reject_reasons)){
1926             return FALSE;
1927         }
1928         /* byte 3 must be 0 */
1929         if(tvb_get_guint8(tvb, offset+3)){
1930             return FALSE;
1931         }
1932         /* the 32bit words at offsets 8, 12, 20, 40, 44
1933          * must all be 0
1934          */
1935         if(tvb_get_letohl(tvb,offset+8)
1936         || tvb_get_letohl(tvb,offset+12)
1937         || tvb_get_letohl(tvb,offset+20)
1938         || tvb_get_letohl(tvb,offset+40)
1939         || tvb_get_letohl(tvb,offset+44)){
1940             return FALSE;
1941         }
1942         /* the 32bit word at 16 must be 0xffffffff */
1943         if(tvb_get_letohl(tvb,offset+16)!=0xffffffff){
1944             return FALSE;
1945         }
1946         break;
1947     case ISCSI_OPCODE_TEXT_COMMAND:
1948         /* top bit in byte 0 must be 0 */
1949         if(tvb_get_guint8(tvb, offset+0)&0x80){
1950             return FALSE;
1951         }
1952         /* one of the F and C bits must be set but not both
1953          * low 6 bits in byte 1 must be 0 
1954          */
1955         switch(tvb_get_guint8(tvb,offset+1)){
1956         case 0x80:
1957         case 0x40:
1958             break;
1959         default:
1960             return FALSE;
1961         }
1962         /* bytes 2,3 must be null */
1963         if(tvb_get_letohs(tvb,offset+2)){
1964             return FALSE;
1965         }
1966         /* the 32bit words at offsets 32, 36, 40, 44
1967          * must all be 0
1968          */
1969         if(tvb_get_letohl(tvb,offset+32)
1970         || tvb_get_letohl(tvb,offset+36)
1971         || tvb_get_letohl(tvb,offset+40)
1972         || tvb_get_letohl(tvb,offset+44)){
1973             return FALSE;
1974         }
1975         break;
1976     case ISCSI_OPCODE_TEXT_RESPONSE:
1977         /* top two bits in byte 0 must be 0 */
1978         if(tvb_get_guint8(tvb, offset+0)&0xc0){
1979             return FALSE;
1980         }
1981         /* one of the F and C bits must be set but not both
1982          * low 6 bits in byte 1 must be 0 
1983          */
1984         switch(tvb_get_guint8(tvb,offset+1)){
1985         case 0x80:
1986         case 0x40:
1987             break;
1988         default:
1989             return FALSE;
1990         }
1991         /* bytes 2,3 must be null */
1992         if(tvb_get_letohs(tvb,offset+2)){
1993             return FALSE;
1994         }
1995         /* the 32bit words at offsets 36, 40, 44
1996          * must all be 0
1997          */
1998         if(tvb_get_letohl(tvb,offset+36)
1999         || tvb_get_letohl(tvb,offset+40)
2000         || tvb_get_letohl(tvb,offset+44)){
2001             return FALSE;
2002         }
2003         break;
2004     case ISCSI_OPCODE_SCSI_COMMAND:
2005         /* top bit in byte 0 must be 0 */
2006         if(tvb_get_guint8(tvb, offset+0)&0x80){
2007             return FALSE;
2008         }
2009         /* reserved bits in byte 1 must be 0 */
2010         if(tvb_get_guint8(tvb, offset+1)&0x18){
2011             return FALSE;
2012         }
2013         /* bytes 2,3 must be null */
2014         if(tvb_get_letohs(tvb,offset+2)){
2015             return FALSE;
2016         }
2017         /* expected data transfer length is never >16MByte ? */
2018         if(tvb_get_guint8(tvb,offset+20)){
2019             return FALSE;
2020         }
2021         break;
2022     case ISCSI_OPCODE_SCSI_RESPONSE:
2023         /* top two bits in byte 0 must be 0 */
2024         if(tvb_get_guint8(tvb, offset+0)&0xc0){
2025             return FALSE;
2026         }
2027         /* top bit in byte 1 must be 1 */
2028         tmpbyte=tvb_get_guint8(tvb,offset+1);
2029         if(!(tmpbyte&0x80)){
2030             return FALSE;
2031         }
2032         /* the reserved bits in byte 1 must be 0 */
2033         if(tmpbyte&0x61){
2034             return FALSE;
2035         }
2036         /* status must be known */
2037         if(!match_strval(tvb_get_guint8(tvb,offset+3), scsi_status_val)){
2038             return FALSE;
2039         }
2040         /* the 32bit words at offsets 8, 12
2041          * must all be 0
2042          */
2043         if(tvb_get_letohl(tvb,offset+8)
2044         || tvb_get_letohl(tvb,offset+12)){
2045             return FALSE;
2046         }
2047         break;
2048     case ISCSI_OPCODE_ASYNC_MESSAGE:
2049         /* top two bits in byte 0 must be 0 */
2050         if(tvb_get_guint8(tvb, offset+0)&0xc0){
2051             return FALSE;
2052         }
2053         /* byte 1 must be 0x80 */
2054         if(tvb_get_guint8(tvb, offset+1)!=0x80){
2055             return FALSE;
2056         }
2057         /* bytes 2,3 must be null */
2058         if(tvb_get_letohs(tvb,offset+2)){
2059             return FALSE;
2060         }
2061         /* the 32bit words at offsets 20, 44
2062          * must all be 0
2063          */
2064         if(tvb_get_letohl(tvb,offset+20)
2065         || tvb_get_letohl(tvb,offset+44)){
2066             return FALSE;
2067         }
2068         /* the 32bit word at 16 must be 0xffffffff */
2069         if(tvb_get_letohl(tvb,offset+16)!=0xffffffff){
2070             return FALSE;
2071         }
2072         break;
2073     case ISCSI_OPCODE_LOGOUT_RESPONSE:
2074         /* top two bits in byte 0 must be 0 */
2075         if(tvb_get_guint8(tvb, offset+0)&0xc0){
2076             return FALSE;
2077         }
2078         /* byte 1 must be 0x80 */
2079         if(tvb_get_guint8(tvb, offset+1)!=0x80){
2080             return FALSE;
2081         }
2082         /* response must be known */
2083         if(!match_strval(tvb_get_guint8(tvb,offset+2), iscsi_logout_response)){
2084             return FALSE;
2085         }
2086         /* byte 3 must be 0 */
2087         if(tvb_get_guint8(tvb,offset+3)){
2088             return FALSE;
2089         }
2090         /* ahs and dsl  as well as the 32bit words at offsets 8, 12, 20, 36
2091          * 44 must all be 0
2092          */
2093         if(tvb_get_letohl(tvb,offset+4)
2094         || tvb_get_letohl(tvb,offset+8)
2095         || tvb_get_letohl(tvb,offset+12)
2096         || tvb_get_letohl(tvb,offset+20)
2097         || tvb_get_letohl(tvb,offset+36)
2098         || tvb_get_letohl(tvb,offset+44)){
2099             return FALSE;
2100         }
2101         break;
2102     case ISCSI_OPCODE_SCSI_DATA_OUT:
2103         /* top two bits in byte 0 must be 0 */
2104         if(tvb_get_guint8(tvb, offset+0)&0xc0){
2105             return FALSE;
2106         }
2107         /* low 7 bits in byte 1 must be 0 */
2108         if(tvb_get_guint8(tvb,offset+1)&0x7f){
2109             return FALSE;
2110         }
2111         /* bytes 2,3 must be null */
2112         if(tvb_get_letohs(tvb,offset+2)){
2113             return FALSE;
2114         }
2115         /* the 32bit words at offsets 24, 32, 44
2116          * must all be 0
2117          */
2118         if(tvb_get_letohl(tvb,offset+24)
2119         || tvb_get_letohl(tvb,offset+32)
2120         || tvb_get_letohl(tvb,offset+44)){
2121             return FALSE;
2122         }
2123         break;
2124     case ISCSI_OPCODE_SCSI_DATA_IN:
2125         /* top two bits in byte 0 must be 0 */
2126         if(tvb_get_guint8(tvb, offset+0)&0xc0){
2127             return FALSE;
2128         }
2129         /* reserved bits in byte 1 must be 0 */
2130         if(tvb_get_guint8(tvb,offset+1)&0x38){
2131             return FALSE;
2132         }
2133         /* byte 2 must be reserved */
2134         if(tvb_get_guint8(tvb,offset+2)){
2135             return FALSE;
2136         }
2137         break;
2138     case ISCSI_OPCODE_VENDOR_SPECIFIC_I0:
2139     case ISCSI_OPCODE_VENDOR_SPECIFIC_I1:
2140     case ISCSI_OPCODE_VENDOR_SPECIFIC_I2:
2141     case ISCSI_OPCODE_VENDOR_SPECIFIC_T0:
2142     case ISCSI_OPCODE_VENDOR_SPECIFIC_T1:
2143     case ISCSI_OPCODE_VENDOR_SPECIFIC_T2:
2144         break;
2145     default:
2146         return FALSE;
2147     }
2148
2149
2150     /* process multiple iSCSI PDUs per packet */
2151     while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
2152         const char *opcode_str = NULL;
2153         guint32 data_segment_len;
2154         guint32 pduLen = 48;
2155         guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
2156         int badPdu = FALSE;
2157         guint8 ahsLen=0;
2158
2159         /* mask out any extra bits in the opcode byte */
2160         opcode = tvb_get_guint8(tvb, offset + 0);
2161         opcode &= OPCODE_MASK;
2162
2163         opcode_str = match_strval(opcode, iscsi_opcodes);
2164         if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
2165            opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
2166            opcode == ISCSI_OPCODE_R2T ||
2167            opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
2168            opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
2169            opcode == ISCSI_OPCODE_SNACK_REQUEST)
2170             data_segment_len = 0;
2171         else
2172             data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
2173
2174         if(opcode_str == NULL) {
2175             badPdu = TRUE;
2176         }
2177         else if(check_port && iscsi_port != 0 &&
2178                 (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
2179                  (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
2180             badPdu = TRUE;
2181         }
2182         else if(enable_bogosity_filter) {
2183             /* try and distinguish between data and real headers */
2184             if(data_segment_len > bogus_pdu_data_length_threshold) {
2185                 badPdu = TRUE;
2186             }
2187             else if(demand_good_f_bit &&
2188                     !(secondPduByte & 0x80) &&
2189                     (opcode == ISCSI_OPCODE_NOP_OUT ||
2190                      opcode == ISCSI_OPCODE_NOP_IN ||
2191                      opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
2192                      opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
2193                      opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
2194                      opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
2195                      opcode == ISCSI_OPCODE_R2T ||
2196                      opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
2197                      opcode == ISCSI_OPCODE_SNACK_REQUEST ||
2198                      opcode == ISCSI_OPCODE_REJECT)) {
2199                 badPdu = TRUE;
2200             } else if(opcode==ISCSI_OPCODE_NOP_OUT) {
2201                 /* TransferTag for NOP-Out should either be -1 or
2202                    the tag value we want for a response. 
2203                    Assume 0 means we are just inside a big all zero
2204                    datablock.
2205                 */
2206                 if(tvb_get_ntohl(tvb, offset+20)==0){
2207                     badPdu = TRUE;
2208                 }
2209             }
2210         }
2211
2212         if(badPdu) {
2213             return iSCSIPdusDissected > 0;
2214         }
2215
2216         if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
2217             opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
2218             if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
2219                 if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
2220                     /* digests are not yet turned on */
2221                     digestsActive = 0;
2222                 }
2223             } else {
2224                 digestsActive = 0;
2225             }
2226         }
2227
2228         if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
2229             /* ahsLen */
2230             ahsLen = tvb_get_guint8(tvb, offset + 4);
2231             pduLen += ahsLen * 4;
2232         }
2233
2234         pduLen += data_segment_len;
2235         if((pduLen & 3) != 0)
2236             pduLen += 4 - (pduLen & 3);
2237
2238
2239         if(digestsActive && data_segment_len > 0 && enableDataDigests) {
2240             if(dataDigestIsCRC32)
2241                 pduLen += 4;
2242             else
2243                 pduLen += dataDigestSize;
2244         }
2245
2246         /* make sure we have a conversation for this session */
2247         conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
2248                                           pinfo->ptype, pinfo->srcport,
2249                                           pinfo->destport, 0);
2250         if (!conversation) {
2251             conversation = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst,
2252                                              pinfo->ptype, pinfo->srcport,
2253                                              pinfo->destport, 0);
2254         }
2255         iscsi_session=conversation_get_proto_data(conversation, proto_iscsi);
2256         if(!iscsi_session){
2257             iscsi_session=se_alloc(sizeof(iscsi_session_t));
2258             iscsi_session->header_digest=ISCSI_HEADER_DIGEST_AUTO;
2259             iscsi_session->itlq=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "iSCSI ITLQ");
2260             iscsi_session->itl=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "iSCSI ITL");
2261             conversation_add_proto_data(conversation, proto_iscsi, iscsi_session);
2262
2263             /* DataOut PDUs are often mistaken by DCERPC heuristics to be
2264              * that protocol. Now that we know this is iscsi, set a 
2265              * dissector for this conversation to block other heuristic
2266              * dissectors. 
2267              */
2268             conversation_set_dissector(conversation, iscsi_handle);
2269         }
2270         /* try to autodetect if header digest is used or not */
2271         if(digestsActive && (available_bytes>=(48+4+ahsLen*4)) && (iscsi_session->header_digest==ISCSI_HEADER_DIGEST_AUTO) ){
2272             guint32 crc;
2273                 /* we have enough data to test if HeaderDigest is enabled */
2274             crc= ~calculateCRC32(tvb_get_ptr(tvb, offset, 48+ahsLen*4), 48+ahsLen*4, CRC32C_PRELOAD);
2275             if(crc==tvb_get_ntohl(tvb,48+ahsLen*4)){
2276                 iscsi_session->header_digest=ISCSI_HEADER_DIGEST_CRC32;
2277             } else {
2278                 iscsi_session->header_digest=ISCSI_HEADER_DIGEST_NONE;
2279             }
2280         }
2281
2282
2283         /* Add header digest length to pdulen */
2284         if(digestsActive){
2285                 switch(iscsi_session->header_digest){
2286                 case ISCSI_HEADER_DIGEST_CRC32:
2287                         pduLen += 4;
2288                         break;
2289                 case ISCSI_HEADER_DIGEST_NONE:
2290                         break;
2291                 case ISCSI_HEADER_DIGEST_AUTO:
2292                         /* oops we didnt know what digest is used yet */
2293                         /* here we should use some default */
2294                         break;
2295                 default:
2296                         DISSECTOR_ASSERT_NOT_REACHED();
2297                 }
2298         }
2299
2300         /*
2301          * Desegmentation check.
2302          */
2303         if(iscsi_desegment && pinfo->can_desegment) {
2304             if(pduLen > available_bytes) {
2305                 /*
2306                  * This frame doesn't have all of the data for
2307                  * this message, but we can do reassembly on it.
2308                  *
2309                  * Tell the TCP dissector where the data for this
2310                  * message starts in the data it handed us, and
2311                  * how many more bytes we need, and return.
2312                  */
2313                 pinfo->desegment_offset = offset;
2314                 pinfo->desegment_len = pduLen - available_bytes;
2315                 return TRUE;
2316             }
2317         }
2318
2319         /* This is to help TCP keep track of PDU boundaries
2320            and allows it to find PDUs that are not aligned to 
2321            the start of a TCP segments.
2322            Since it also allows TCP to know what is in the middle
2323            of a large PDU, it reduces the probability of a segment
2324            in the middle of a large PDU transfer being misdissected as
2325            a PDU.
2326         */
2327         if(!pinfo->fd->flags.visited){
2328             if(pduLen>(guint32)tvb_reported_length_remaining(tvb, offset)){
2329                 pinfo->want_pdu_tracking=2;
2330                 pinfo->bytes_until_next_pdu=pduLen-tvb_reported_length_remaining(tvb, offset);
2331             }
2332         }
2333
2334         if(check_col(pinfo->cinfo, COL_INFO)) {
2335             if(iSCSIPdusDissected == 0)
2336                 col_set_str(pinfo->cinfo, COL_INFO, "");
2337             else
2338                 col_append_str(pinfo->cinfo, COL_INFO, ", ");
2339         }
2340
2341         dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len, iscsi_session);
2342         if(pduLen > available_bytes)
2343             pduLen = available_bytes;
2344         offset += pduLen;
2345         available_bytes -= pduLen;
2346         ++iSCSIPdusDissected;
2347     }
2348
2349     return iSCSIPdusDissected > 0;
2350 }
2351
2352 /* This is called for those sessions where we have explicitely said
2353    this to be iSCSI using "Decode As..."
2354    In this case we will not check the port number for sanity and just
2355    do as the user said.
2356    We still check that the PDU header looks sane though.
2357 */
2358 static int
2359 dissect_iscsi_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2360     return dissect_iscsi(tvb, pinfo, tree, FALSE);
2361 }
2362
2363 /* This is called through the heuristic handler.
2364    In this case we also want to check that the port matches the preference
2365    setting for iSCSI in order to reduce the number of
2366    false positives.
2367 */
2368 static gboolean
2369 dissect_iscsi_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2370     return dissect_iscsi(tvb, pinfo, tree, TRUE);
2371 }
2372
2373
2374 /* Register the protocol with Wireshark */
2375
2376 /*
2377  * this format is require because a script is used to build the C
2378  * function that calls all the protocol registration.
2379 */
2380
2381 void
2382 proto_register_iscsi(void)
2383 {
2384
2385     /* Setup list of header fields  See Section 1.6.1 for details*/
2386     static hf_register_info hf[] = {
2387         { &hf_iscsi_request_frame,
2388           { "Request in", "iscsi.request_frame",
2389             FT_FRAMENUM, BASE_NONE, NULL, 0,
2390             "The request to this transaction is in this frame", HFILL }},
2391
2392         { &hf_iscsi_time,
2393           { "Time from request", "iscsi.time",
2394             FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
2395             "Time between the Command and the Response", HFILL }},
2396
2397         { &hf_iscsi_data_in_frame,
2398           { "Data In in", "iscsi.data_in_frame",
2399             FT_FRAMENUM, BASE_NONE, NULL, 0,
2400             "The Data In for this transaction is in this frame", HFILL }},
2401
2402         { &hf_iscsi_data_out_frame,
2403           { "Data Out in", "iscsi.data_out_frame",
2404             FT_FRAMENUM, BASE_NONE, NULL, 0,
2405             "The Data Out for this transaction is in this frame", HFILL }},
2406
2407         { &hf_iscsi_response_frame,
2408           { "Response in", "iscsi.response_frame",
2409             FT_FRAMENUM, BASE_NONE, NULL, 0,
2410             "The response to this transaction is in this frame", HFILL }},
2411
2412         { &hf_iscsi_AHS,
2413           { "AHS", "iscsi.ahs",
2414             FT_BYTES, BASE_HEX, NULL, 0,
2415             "Additional header segment", HFILL }
2416         },
2417         { &hf_iscsi_AHS_length,
2418           { "AHS Length", "iscsi.ahs.length",
2419             FT_UINT16, BASE_DEC, NULL, 0,
2420             "Length of Additional header segment", HFILL }
2421         },
2422         { &hf_iscsi_AHS_type,
2423           { "AHS Type", "iscsi.ahs.type",
2424             FT_UINT8, BASE_DEC, VALS(ahs_type_vals), 0,
2425             "Type of Additional header segment", HFILL }
2426         },
2427         { &hf_iscsi_AHS_specific,
2428           { "AHS Specific", "iscsi.ahs",
2429             FT_UINT8, BASE_HEX, NULL, 0,
2430             "Specific qualifier of Additional header segment", HFILL }
2431         },
2432         { &hf_iscsi_Padding,
2433           { "Padding", "iscsi.padding",
2434             FT_BYTES, BASE_HEX, NULL, 0,
2435             "Padding to 4 byte boundary", HFILL }
2436         },
2437         { &hf_iscsi_ping_data,
2438           { "PingData", "iscsi.pingdata",
2439             FT_BYTES, BASE_HEX, NULL, 0,
2440             "Ping Data", HFILL }
2441         },
2442         { &hf_iscsi_immediate_data,
2443           { "ImmediateData", "iscsi.immediatedata",
2444             FT_BYTES, BASE_HEX, NULL, 0,
2445             "Immediate Data", HFILL }
2446         },
2447         { &hf_iscsi_write_data,
2448           { "WriteData", "iscsi.writedata",
2449             FT_BYTES, BASE_HEX, NULL, 0,
2450             "Write Data", HFILL }
2451         },
2452         { &hf_iscsi_read_data,
2453           { "ReadData", "iscsi.readdata",
2454             FT_BYTES, BASE_HEX, NULL, 0,
2455             "Read Data", HFILL }
2456         },
2457         { &hf_iscsi_error_pdu_data,
2458           { "ErrorPDUData", "iscsi.errorpdudata",
2459             FT_BYTES, BASE_HEX, NULL, 0,
2460             "Error PDU Data", HFILL }
2461         },
2462         { &hf_iscsi_async_message_data,
2463           { "AsyncMessageData", "iscsi.asyncmessagedata",
2464             FT_BYTES, BASE_HEX, NULL, 0,
2465             "Async Message Data", HFILL }
2466         },
2467         { &hf_iscsi_vendor_specific_data,
2468           { "VendorSpecificData", "iscsi.vendorspecificdata",
2469             FT_BYTES, BASE_HEX, NULL, 0,
2470             "Vendor Specific Data", HFILL }
2471         },
2472         { &hf_iscsi_HeaderDigest32,
2473           { "HeaderDigest", "iscsi.headerdigest32",
2474             FT_UINT32, BASE_HEX, NULL, 0,
2475             "Header Digest", HFILL }
2476         },
2477         { &hf_iscsi_DataDigest,
2478           { "DataDigest", "iscsi.datadigest",
2479             FT_BYTES, BASE_HEX, NULL, 0,
2480             "Data Digest", HFILL }
2481         },
2482         { &hf_iscsi_DataDigest32,
2483           { "DataDigest", "iscsi.datadigest32",
2484             FT_UINT32, BASE_HEX, NULL, 0,
2485             "Data Digest", HFILL }
2486         },
2487         { &hf_iscsi_Opcode,
2488           { "Opcode", "iscsi.opcode",
2489             FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
2490             "Opcode", HFILL }
2491         },
2492 /* #ifdef DRAFT08 */
2493         { &hf_iscsi_X,
2494           { "X", "iscsi.X",
2495             FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
2496             "Command Retry", HFILL }
2497         },
2498 /* #endif */
2499         { &hf_iscsi_I,
2500           { "I", "iscsi.I",
2501             FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
2502             "Immediate delivery", HFILL }
2503         },
2504         { &hf_iscsi_Flags,
2505           { "Flags", "iscsi.flags",
2506             FT_UINT8, BASE_HEX, NULL, 0,
2507             "Opcode specific flags", HFILL }
2508         },
2509         { &hf_iscsi_SCSICommand_F,
2510           { "F", "iscsi.scsicommand.F",
2511             FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2512             "PDU completes command", HFILL }
2513         },
2514         { &hf_iscsi_SCSICommand_R,
2515           { "R", "iscsi.scsicommand.R",
2516             FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
2517             "Command reads from SCSI target", HFILL }
2518         },
2519         { &hf_iscsi_SCSICommand_W,
2520           { "W", "iscsi.scsicommand.W",
2521             FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
2522             "Command writes to SCSI target", HFILL }
2523         },
2524         { &hf_iscsi_SCSICommand_Attr,
2525           { "Attr", "iscsi.scsicommand.attr",
2526             FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
2527             "SCSI task attributes", HFILL }
2528         },
2529         { &hf_iscsi_SCSICommand_CRN,
2530           { "CRN", "iscsi.scsicommand.crn",
2531             FT_UINT8, BASE_HEX, NULL, 0,
2532             "SCSI command reference number", HFILL }
2533         },
2534         { &hf_iscsi_SCSICommand_AddCDB,
2535           { "AddCDB", "iscsi.scsicommand.addcdb",
2536             FT_UINT8, BASE_HEX, NULL, 0,
2537             "Additional CDB length (in 4 byte units)", HFILL }
2538         },
2539         { &hf_iscsi_DataSegmentLength,
2540           { "DataSegmentLength", "iscsi.datasegmentlength",
2541             FT_UINT32, BASE_HEX, NULL, 0,
2542             "Data segment length (bytes)", HFILL }
2543         },
2544         { &hf_iscsi_TotalAHSLength,
2545           { "TotalAHSLength", "iscsi.totalahslength",
2546             FT_UINT8, BASE_HEX, NULL, 0,
2547             "Total additional header segment length (4 byte words)", HFILL }
2548         },
2549         { &hf_iscsi_LUN,
2550           { "LUN", "iscsi.lun",
2551             FT_BYTES, BASE_HEX, NULL, 0,
2552             "Logical Unit Number", HFILL }
2553         },
2554         { &hf_iscsi_InitiatorTaskTag,
2555           { "InitiatorTaskTag", "iscsi.initiatortasktag",
2556             FT_UINT32, BASE_HEX, NULL, 0,
2557             "Initiator's task tag", HFILL }
2558         },
2559         { &hf_iscsi_ExpectedDataTransferLength,
2560           { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
2561             FT_UINT32, BASE_HEX, NULL, 0,
2562             "Expected length of data transfer", HFILL }
2563         },
2564         { &hf_iscsi_CmdSN,
2565           { "CmdSN", "iscsi.cmdsn",
2566             FT_UINT32, BASE_HEX, NULL, 0,
2567             "Sequence number for this command", HFILL }
2568         },
2569         { &hf_iscsi_ExpStatSN,
2570           { "ExpStatSN", "iscsi.expstatsn",
2571             FT_UINT32, BASE_HEX, NULL, 0,
2572             "Next expected status sequence number", HFILL }
2573         },
2574         { &hf_iscsi_SCSIResponse_ResidualCount,
2575           { "ResidualCount", "iscsi.scsiresponse.residualcount",
2576             FT_UINT32, BASE_HEX, NULL, 0,
2577             "Residual count", HFILL }
2578         },
2579         { &hf_iscsi_StatSN,
2580           { "StatSN", "iscsi.statsn",
2581             FT_UINT32, BASE_HEX, NULL, 0,
2582             "Status sequence number", HFILL }
2583         },
2584         { &hf_iscsi_ExpCmdSN,
2585           { "ExpCmdSN", "iscsi.expcmdsn",
2586             FT_UINT32, BASE_HEX, NULL, 0,
2587             "Next expected command sequence number", HFILL }
2588         },
2589         { &hf_iscsi_MaxCmdSN,
2590           { "MaxCmdSN", "iscsi.maxcmdsn",
2591             FT_UINT32, BASE_HEX, NULL, 0,
2592             "Maximum acceptable command sequence number", HFILL }
2593         },
2594         { &hf_iscsi_SCSIResponse_o,
2595           { "o", "iscsi.scsiresponse.o",
2596             FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
2597             "Bi-directional read residual overflow", HFILL }
2598         },
2599         { &hf_iscsi_SCSIResponse_u,
2600           { "u", "iscsi.scsiresponse.u",
2601             FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
2602             "Bi-directional read residual underflow", HFILL }
2603         },
2604         { &hf_iscsi_SCSIResponse_O,
2605           { "O", "iscsi.scsiresponse.O",
2606             FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
2607             "Residual overflow", HFILL }
2608         },
2609         { &hf_iscsi_SCSIResponse_U,
2610           { "U", "iscsi.scsiresponse.U",
2611             FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
2612             "Residual underflow", HFILL }
2613         },
2614         { &hf_iscsi_SCSIResponse_Status,
2615           { "Status", "iscsi.scsiresponse.status",
2616             FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
2617             "SCSI command status value", HFILL }
2618         },
2619         { &hf_iscsi_SCSIResponse_Response,
2620           { "Response", "iscsi.scsiresponse.response",
2621             FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
2622             "SCSI command response value", HFILL }
2623         },
2624         { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
2625           { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
2626             FT_UINT32, BASE_HEX, NULL, 0,
2627             "Bi-directional read residual count", HFILL }
2628         },
2629         { &hf_iscsi_SenseLength,
2630           { "SenseLength", "iscsi.scsiresponse.senselength",
2631             FT_UINT16, BASE_HEX, NULL, 0,
2632             "Sense data length", HFILL }
2633         },
2634         { &hf_iscsi_SCSIData_F,
2635           { "F", "iscsi.scsidata.F",
2636             FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
2637             "Final PDU", HFILL }
2638         },
2639         { &hf_iscsi_SCSIData_A,
2640           { "A", "iscsi.scsidata.A",
2641             FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
2642             "Acknowledge Requested", HFILL }
2643         },
2644         { &hf_iscsi_SCSIData_S,
2645           { "S", "iscsi.scsidata.S",
2646             FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
2647             "PDU Contains SCSI command status", HFILL }
2648         },
2649         { &hf_iscsi_SCSIData_U,
2650           { "U", "iscsi.scsidata.U",
2651             FT_BOOLEAN, 8,  TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
2652             "Residual underflow", HFILL }
2653         },
2654         { &hf_iscsi_SCSIData_O,
2655           { "O", "iscsi.scsidata.O",
2656             FT_BOOLEAN, 8,  TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
2657             "Residual overflow", HFILL }
2658         },
2659         { &hf_iscsi_TargetTransferTag,
2660           { "TargetTransferTag", "iscsi.targettransfertag",
2661             FT_UINT32, BASE_HEX, NULL, 0,
2662             "Target transfer tag", HFILL }
2663         },
2664         { &hf_iscsi_BufferOffset,
2665           { "BufferOffset", "iscsi.bufferOffset",
2666             FT_UINT32, BASE_HEX, NULL, 0,
2667             "Buffer offset", HFILL }
2668         },
2669         { &hf_iscsi_SCSIData_ResidualCount,
2670           { "ResidualCount", "iscsi.scsidata.readresidualcount",
2671             FT_UINT32, BASE_HEX, NULL, 0,
2672             "Residual count", HFILL }
2673         },
2674         { &hf_iscsi_DataSN,
2675           { "DataSN", "iscsi.datasn",
2676             FT_UINT32, BASE_HEX, NULL, 0,
2677             "Data sequence number", HFILL }
2678         },
2679         { &hf_iscsi_VersionMax,
2680           { "VersionMax", "iscsi.versionmax",
2681             FT_UINT8, BASE_HEX, NULL, 0,
2682             "Maximum supported protocol version", HFILL }
2683         },
2684         { &hf_iscsi_VersionMin,
2685           { "VersionMin", "iscsi.versionmin",
2686             FT_UINT8, BASE_HEX, NULL, 0,
2687             "Minimum supported protocol version", HFILL }
2688         },
2689         { &hf_iscsi_VersionActive,
2690           { "VersionActive", "iscsi.versionactive",
2691             FT_UINT8, BASE_HEX, NULL, 0,
2692             "Negotiated protocol version", HFILL }
2693         },
2694         { &hf_iscsi_CID,
2695           { "CID", "iscsi.cid",
2696             FT_UINT16, BASE_HEX, NULL, 0,
2697             "Connection identifier", HFILL }
2698         },
2699 /* #ifdef DRAFT08 */
2700         { &hf_iscsi_ISID8,
2701           { "ISID", "iscsi.isid",
2702             FT_UINT16, BASE_HEX, NULL, 0,
2703             "Initiator part of session identifier", HFILL }
2704         },
2705 /* #else */
2706         { &hf_iscsi_ISID,
2707           { "ISID", "iscsi.isid",
2708             FT_BYTES, BASE_HEX, NULL, 0,
2709             "Initiator part of session identifier", HFILL }
2710         },
2711 /* #ifdef DRAFT09 */
2712         { &hf_iscsi_ISID_Type,
2713           { "ISID_Type", "iscsi.isid.type",
2714             FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
2715             "Initiator part of session identifier - type", HFILL }
2716         },
2717         { &hf_iscsi_ISID_NamingAuthority,
2718           { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
2719             FT_UINT24, BASE_HEX, NULL, 0,
2720             "Initiator part of session identifier - naming authority", HFILL }
2721         },
2722         { &hf_iscsi_ISID_Qualifier,
2723           { "ISID_Qualifier", "iscsi.isid.qualifier",
2724             FT_UINT8, BASE_HEX, NULL, 0,
2725             "Initiator part of session identifier - qualifier", HFILL }
2726         },
2727 /* #else */
2728         { &hf_iscsi_ISID_t,
2729           { "ISID_t", "iscsi.isid.t",
2730             FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
2731             "Initiator part of session identifier - t", HFILL }
2732         },
2733         { &hf_iscsi_ISID_a,
2734           { "ISID_a", "iscsi.isid.a",
2735             FT_UINT8, BASE_HEX, NULL, 0x3f,
2736             "Initiator part of session identifier - a", HFILL }
2737         },
2738         { &hf_iscsi_ISID_b,
2739           { "ISID_b", "iscsi.isid.b",
2740             FT_UINT16, BASE_HEX, NULL, 0,
2741             "Initiator part of session identifier - b", HFILL }
2742         },
2743         { &hf_iscsi_ISID_c,
2744           { "ISID_c", "iscsi.isid.c",
2745             FT_UINT8, BASE_HEX, NULL, 0,
2746             "Initiator part of session identifier - c", HFILL }
2747         },
2748         { &hf_iscsi_ISID_d,
2749           { "ISID_d", "iscsi.isid.d",
2750             FT_UINT16, BASE_HEX, NULL, 0,
2751             "Initiator part of session identifier - d", HFILL }
2752         },
2753 /* #endif */
2754 /* #endif */
2755         { &hf_iscsi_TSID,
2756           { "TSID", "iscsi.tsid",
2757             FT_UINT16, BASE_HEX, NULL, 0,
2758             "Target part of session identifier", HFILL }
2759         },
2760         { &hf_iscsi_TSIH,
2761           { "TSIH", "iscsi.tsih",
2762             FT_UINT16, BASE_HEX, NULL, 0,
2763             "Target session identifying handle", HFILL }
2764         },
2765         { &hf_iscsi_InitStatSN,
2766           { "InitStatSN", "iscsi.initstatsn",
2767             FT_UINT32, BASE_HEX, NULL, 0,
2768             "Initial status sequence number", HFILL }
2769         },
2770         { &hf_iscsi_InitCmdSN,
2771           { "InitCmdSN", "iscsi.initcmdsn",
2772             FT_UINT32, BASE_HEX, NULL, 0,
2773             "Initial command sequence number", HFILL }
2774         },
2775         { &hf_iscsi_Login_T,
2776           { "T", "iscsi.login.T",
2777             FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
2778             "Transit to next login stage",  HFILL }
2779         },
2780         { &hf_iscsi_Login_C,
2781           { "C", "iscsi.login.C",
2782             FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2783             "Text incomplete",  HFILL }
2784         },
2785 /* #ifdef DRAFT09 */
2786         { &hf_iscsi_Login_X,
2787           { "X", "iscsi.login.X",
2788             FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
2789             "Restart Connection",  HFILL }
2790         },
2791 /* #endif */
2792         { &hf_iscsi_Login_CSG,
2793           { "CSG", "iscsi.login.csg",
2794             FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
2795             "Current stage",  HFILL }
2796         },
2797         { &hf_iscsi_Login_NSG,
2798           { "NSG", "iscsi.login.nsg",
2799             FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
2800             "Next stage",  HFILL }
2801         },
2802         { &hf_iscsi_Login_Status,
2803           { "Status", "iscsi.login.status",
2804             FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
2805             "Status class and detail", HFILL }
2806         },
2807         { &hf_iscsi_KeyValue,
2808           { "KeyValue", "iscsi.keyvalue",
2809             FT_STRING, 0, NULL, 0,
2810             "Key/value pair", HFILL }
2811         },
2812         { &hf_iscsi_Text_F,
2813           { "F", "iscsi.text.F",
2814             FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
2815             "Final PDU in text sequence", HFILL }
2816         },
2817         { &hf_iscsi_Text_C,
2818           { "C", "iscsi.text.C",
2819             FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
2820             "Text incomplete", HFILL }
2821         },
2822         { &hf_iscsi_ExpDataSN,
2823           { "ExpDataSN", "iscsi.expdatasn",
2824             FT_UINT32, BASE_HEX, NULL, 0,
2825             "Next expected data sequence number", HFILL }
2826         },
2827         { &hf_iscsi_R2TSN,
2828           { "R2TSN", "iscsi.r2tsn",
2829             FT_UINT32, BASE_HEX, NULL, 0,
2830             "R2T PDU Number", HFILL }
2831         },
2832         { &hf_iscsi_TaskManagementFunction_Response,
2833           { "Response", "iscsi.taskmanfun.response",
2834             FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
2835             "Response", HFILL }
2836         },
2837         { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
2838           { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
2839             FT_UINT32, BASE_HEX, NULL, 0,
2840             "Referenced task tag", HFILL }
2841         },
2842         { &hf_iscsi_RefCmdSN,
2843           { "RefCmdSN", "iscsi.refcmdsn",
2844             FT_UINT32, BASE_HEX, NULL, 0,
2845             "Command sequence number for command to be aborted", HFILL }
2846         },
2847         { &hf_iscsi_TaskManagementFunction_Function,
2848           { "Function", "iscsi.taskmanfun.function",
2849             FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
2850             "Requested task function", HFILL }
2851         },
2852         { &hf_iscsi_Logout_Reason,
2853           { "Reason", "iscsi.logout.reason",
2854             FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0x7F,
2855             "Reason for logout", HFILL }
2856         },
2857         { &hf_iscsi_Logout_Response,
2858           { "Response", "iscsi.logout.response",
2859             FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
2860             "Logout response", HFILL }
2861         },
2862         { &hf_iscsi_Time2Wait,
2863           { "Time2Wait", "iscsi.time2wait",
2864             FT_UINT16, BASE_HEX, NULL, 0,
2865             "Time2Wait", HFILL }
2866         },
2867         { &hf_iscsi_Time2Retain,
2868           { "Time2Retain", "iscsi.time2retain",
2869             FT_UINT16, BASE_HEX, NULL, 0,
2870             "Time2Retain", HFILL }
2871         },
2872         { &hf_iscsi_DesiredDataLength,
2873           { "DesiredDataLength", "iscsi.desireddatalength",
2874             FT_UINT32, BASE_HEX, NULL, 0,
2875             "Desired data length (bytes)", HFILL }
2876         },
2877         { &hf_iscsi_AsyncEvent,
2878           { "AsyncEvent", "iscsi.asyncevent",
2879             FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
2880             "Async event type", HFILL }
2881         },
2882         { &hf_iscsi_EventVendorCode,
2883           { "EventVendorCode", "iscsi.eventvendorcode",
2884             FT_UINT8, BASE_HEX, NULL, 0,
2885             "Event vendor code", HFILL }
2886         },
2887         { &hf_iscsi_Parameter1,
2888           { "Parameter1", "iscsi.parameter1",
2889             FT_UINT16, BASE_HEX, NULL, 0,
2890             "Parameter 1", HFILL }
2891         },
2892         { &hf_iscsi_Parameter2,
2893           { "Parameter2", "iscsi.parameter2",
2894             FT_UINT16, BASE_HEX, NULL, 0,
2895             "Parameter 2", HFILL }
2896         },
2897         { &hf_iscsi_Parameter3,
2898           { "Parameter3", "iscsi.parameter3",
2899             FT_UINT16, BASE_HEX, NULL, 0,
2900             "Parameter 3", HFILL }
2901         },
2902         { &hf_iscsi_Reject_Reason,
2903           { "Reason", "iscsi.reject.reason",
2904             FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
2905             "Reason for command rejection", HFILL }
2906         },
2907         { &hf_iscsi_snack_type,
2908           { "S", "iscsi.snack.type",
2909             FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
2910             "Type of SNACK requested", HFILL }
2911         },
2912         { &hf_iscsi_BegRun,
2913           { "BegRun", "iscsi.snack.begrun",
2914             FT_UINT32, BASE_HEX, NULL, 0,
2915             "First missed DataSN or StatSN", HFILL }
2916         },
2917         { &hf_iscsi_RunLength,
2918           { "RunLength", "iscsi.snack.runlength",
2919             FT_UINT32, BASE_HEX, NULL, 0,
2920             "Number of additional missing status PDUs in this run", HFILL }
2921         },
2922     };
2923
2924     /* Setup protocol subtree array */
2925     static gint *ett[] = {
2926         &ett_iscsi,
2927         &ett_iscsi_KeyValues,
2928         &ett_iscsi_CDB,
2929         &ett_iscsi_Flags,
2930 /* #ifndef DRAFT08 */
2931         &ett_iscsi_ISID,
2932 /* #endif */
2933     };
2934
2935     /* Register the protocol name and description */
2936     proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
2937
2938     /* Required function calls to register the header fields and
2939      * subtrees used */
2940     proto_register_field_array(proto_iscsi, hf, array_length(hf));
2941     proto_register_subtree_array(ett, array_length(ett));
2942
2943     {
2944         module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
2945
2946         prefs_register_enum_preference(iscsi_module,
2947                                        "protocol_version",
2948                                        "Protocol version",
2949                                        "The iSCSI protocol version",
2950                                        &iscsi_protocol_version,
2951                                        iscsi_protocol_versions,
2952                                        FALSE);
2953
2954         prefs_register_bool_preference(iscsi_module,
2955                                        "desegment_iscsi_messages",
2956                                        "Reassemble iSCSI messages\nspanning multiple TCP segments",
2957                                        "Whether the iSCSI dissector should reassemble messages spanning multiple TCP segments."
2958                                        " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2959                                        &iscsi_desegment);
2960
2961         prefs_register_bool_preference(iscsi_module,
2962                                        "bogus_pdu_filter",
2963                                        "Enable bogus pdu filter",
2964                                        "When enabled, packets that appear bogus are ignored",
2965                                        &enable_bogosity_filter);
2966
2967         prefs_register_bool_preference(iscsi_module,
2968                                        "demand_good_f_bit",
2969                                        "Ignore packets with bad F bit",
2970                                        "Ignore packets that haven't set the F bit when they should have",
2971                                        &demand_good_f_bit);
2972
2973         prefs_register_uint_preference(iscsi_module,
2974                                        "bogus_pdu_max_data_len",
2975                                        "Bogus pdu max data length threshold",
2976                                        "Treat packets whose data segment length is greater than this value as bogus",
2977                                        10,
2978                                        &bogus_pdu_data_length_threshold);
2979
2980
2981         prefs_register_uint_preference(iscsi_module,
2982                                        "target_port",
2983                                        "Target port",
2984                                        "Port number of iSCSI target",
2985                                        10,
2986                                        &iscsi_port);
2987
2988         prefs_register_bool_preference(iscsi_module,
2989                                        "enable_data_digests",
2990                                        "Enable data digests",
2991                                        "When enabled, pdus are assumed to contain a data digest",
2992                                        &enableDataDigests);
2993
2994         prefs_register_bool_preference(iscsi_module,
2995                                        "data_digest_is_crc32c",
2996                                        "Data digest is CRC32C",
2997                                        "When enabled, data digests are assumed to be CRC32C",
2998                                        &dataDigestIsCRC32);
2999
3000         prefs_register_uint_preference(iscsi_module,
3001                                        "data_digest_size",
3002                                        "Data digest size",
3003                                        "The size of a data digest (bytes)",
3004                                        10,
3005                                        &dataDigestSize);
3006
3007         /* Preference supported in older versions.
3008            Register them as obsolete. */
3009         prefs_register_obsolete_preference(iscsi_module,
3010                                        "version_03_compatible");
3011         prefs_register_obsolete_preference(iscsi_module,
3012                                        "bogus_pdu_max_digest_padding");
3013         prefs_register_obsolete_preference(iscsi_module,
3014                                        "header_digest_is_crc32c");
3015         prefs_register_obsolete_preference(iscsi_module,
3016                                        "header_digest_size");
3017         prefs_register_obsolete_preference(iscsi_module,
3018                                        "enable_header_digests");
3019     }
3020 }
3021
3022
3023 /*
3024  * If this dissector uses sub-dissector registration add a
3025  * registration routine.
3026  */
3027
3028 /*
3029  * This format is required because a script is used to find these
3030  * routines and create the code that calls these routines.
3031  */
3032 void
3033 proto_reg_handoff_iscsi(void)
3034 {
3035     heur_dissector_add("tcp", dissect_iscsi_heur, proto_iscsi);
3036
3037     iscsi_handle = new_create_dissector_handle(dissect_iscsi_handle, proto_iscsi);
3038     dissector_add_handle("tcp.port", iscsi_handle);
3039 }