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