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