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