2 * Routines for iSCSI dissection
3 * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
5 * Conforms to the protocol described in: draft-ietf-ips-iscsi-06.txt
6 * but uses the 07 opcodes (as used at the July 2001 UNH plugfest)
8 * Optionally, supports the protocol described in: draft-ietf-ips-iscsi-03.txt
10 * $Id: packet-iscsi.c,v 1.10 2001/07/22 20:02:23 guy Exp $
12 * Ethereal - Network traffic analyzer
13 * By Gerald Combs <gerald@ethereal.com>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
43 #ifdef HAVE_NETINET_IN_H
44 # include <netinet/in.h>
49 #ifdef NEED_SNPRINTF_H
50 # include "snprintf.h"
56 /*#define USE_06_OPCODES*/
58 static int enable_03_mode = FALSE;
59 static int enable_bogosity_filter = TRUE;
60 static guint32 bogus_pdu_data_length_threshold = 1024 * 1024;
61 static guint32 bogus_pdu_max_digest_padding = 20;
63 static int enable_force_header_digest_crc32 = FALSE;
65 /* Initialize the protocol and registered fields */
66 static int proto_iscsi = -1;
67 static int hf_iscsi_Padding = -1;
68 static int hf_iscsi_Payload = -1;
69 static int hf_iscsi_Opcode = -1;
70 static int hf_iscsi_Opcode_03 = -1;
71 static int hf_iscsi_Flags = -1;
72 static int hf_iscsi_HeaderDigest32 = -1;
73 static int hf_iscsi_X = -1;
74 static int hf_iscsi_I = -1;
75 static int hf_iscsi_SCSICommand_X03 = -1;
76 static int hf_iscsi_SCSICommand_F = -1;
77 static int hf_iscsi_SCSICommand_R = -1;
78 static int hf_iscsi_SCSICommand_W = -1;
79 static int hf_iscsi_SCSICommand_Attr = -1;
80 static int hf_iscsi_SCSICommand_CRN = -1;
81 static int hf_iscsi_SCSICommand_AddCDB = -1;
82 static int hf_iscsi_Length03 = -1;
83 static int hf_iscsi_DataSegmentLength = -1;
84 static int hf_iscsi_TotalAHSLength = -1;
85 static int hf_iscsi_LUN = -1;
86 static int hf_iscsi_InitiatorTaskTag = -1;
87 static int hf_iscsi_ExpectedDataTransferLength = -1;
88 static int hf_iscsi_CmdSN = -1;
89 static int hf_iscsi_ExpStatSN = -1;
90 static int hf_iscsi_SCSICommand_CDB = -1;
91 static int hf_iscsi_SCSICommand_CDB0 = -1;
92 static int hf_iscsi_StatSN = -1;
93 static int hf_iscsi_ExpCmdSN = -1;
94 static int hf_iscsi_MaxCmdSN = -1;
95 static int hf_iscsi_SCSIResponse_o03 = -1;
96 static int hf_iscsi_SCSIResponse_u03 = -1;
97 static int hf_iscsi_SCSIResponse_O03 = -1;
98 static int hf_iscsi_SCSIResponse_U03 = -1;
99 static int hf_iscsi_SCSIResponse_o = -1;
100 static int hf_iscsi_SCSIResponse_u = -1;
101 static int hf_iscsi_SCSIResponse_O = -1;
102 static int hf_iscsi_SCSIResponse_U = -1;
103 static int hf_iscsi_SCSIResponse_S = -1;
104 static int hf_iscsi_CommandStatus03 = -1;
105 static int hf_iscsi_StatusResponse_is_status = -1;
106 static int hf_iscsi_StatusResponse_is_response = -1;
107 static int hf_iscsi_SCSIResponse_SenseLength = -1;
108 static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
109 static int hf_iscsi_SCSIResponse_BasicResidualCount = -1;
110 static int hf_iscsi_SCSIData_F = -1;
111 static int hf_iscsi_SCSIData_P03 = -1;
112 static int hf_iscsi_SCSIData_S03 = -1;
113 static int hf_iscsi_SCSIData_O03 = -1;
114 static int hf_iscsi_SCSIData_U03 = -1;
115 static int hf_iscsi_SCSIData_S = -1;
116 static int hf_iscsi_SCSIData_O = -1;
117 static int hf_iscsi_SCSIData_U = -1;
118 static int hf_iscsi_TargetTransferTag = -1;
119 static int hf_iscsi_DataSN = -1;
120 static int hf_iscsi_BufferOffset = -1;
121 static int hf_iscsi_SCSIData_ResidualCount = -1;
122 static int hf_iscsi_VersionMin = -1;
123 static int hf_iscsi_VersionMax = -1;
124 static int hf_iscsi_CID = -1;
125 static int hf_iscsi_ISID = -1;
126 static int hf_iscsi_TSID = -1;
127 static int hf_iscsi_InitStatSN = -1;
128 static int hf_iscsi_InitCmdSN = -1;
129 static int hf_iscsi_Login_F = -1;
130 static int hf_iscsi_Login_Status03 = -1;
131 static int hf_iscsi_Login_Status = -1;
132 static int hf_iscsi_KeyValue = -1;
133 static int hf_iscsi_Text_F = -1;
134 static int hf_iscsi_NOP_P = -1;
135 static int hf_iscsi_ExpDataSN = -1;
136 static int hf_iscsi_R2TExpDataSN = -1;
137 static int hf_iscsi_SCSITask_ReferencedTaskTag = -1;
138 static int hf_iscsi_SCSITask_Function = -1;
139 static int hf_iscsi_SCSITask_Response = -1;
140 static int hf_iscsi_Logout_Reason03 = -1;
141 static int hf_iscsi_Logout_Reason = -1;
142 static int hf_iscsi_Logout_Response = -1;
143 static int hf_iscsi_DesiredDataLength = -1;
144 static int hf_iscsi_SCSIEvent = -1;
145 static int hf_iscsi_iSCSIEvent = -1;
146 static int hf_iscsi_SCSIEvent03 = -1;
147 static int hf_iscsi_iSCSIEvent03 = -1;
148 static int hf_iscsi_Parameter1 = -1;
149 static int hf_iscsi_Parameter2 = -1;
150 static int hf_iscsi_Parameter3 = -1;
151 static int hf_iscsi_Reject_Reason = -1;
152 static int hf_iscsi_Reject_FirstBadByte = -1;
153 static int hf_iscsi_Reject_Reason03 = -1;
154 static int hf_iscsi_SNACK_S = -1;
155 static int hf_iscsi_AddRuns = -1;
156 static int hf_iscsi_BegRun = -1;
157 static int hf_iscsi_RunLength = -1;
158 static int hf_iscsi_AdditionalRuns = -1;
160 /* Initialize the subtree pointers */
161 static gint ett_iscsi_KeyValues = -1;
162 static gint ett_iscsi_CDB = -1;
163 static gint ett_iscsi_Flags = -1;
165 static const value_string iscsi_opcodes[] = {
166 #ifdef USE_06_OPCODES
168 {0x40, "NOP Out (Immediate)"},
169 {0x80, "NOP Out (Retry)"},
171 {0x01, "SCSI Command"},
172 {0x41, "SCSI Command (Immediate)"},
173 {0x81, "SCSI Command (Retry)"},
175 {0x02, "SCSI Task Management Command"},
176 {0x42, "SCSI Task Management Command (Immediate)"},
177 {0x82, "SCSI Task Management Command (Retry)"},
179 {0x03, "Login Command"},
180 {0x83, "Login Command (Retry)"},
182 {0x04, "Text Command"},
183 {0x44, "Text Command (Immediate)"},
184 {0x84, "Text Command (Retry)"},
186 {0x05, "SCSI Write Data"},
188 {0x06, "Logout Command"},
189 {0x46, "Logout Command (Immediate)"},
191 {0x10, "SNACK Request (Missing Immediate bit)"},
192 {0x50, "SNACK Request"},
195 {0xc1, "SCSI Command Response"},
196 {0xc2, "SCSI Task Management Response"},
197 {0xc3, "Login Response"},
198 {0xc4, "Text Response"},
199 {0xc5, "SCSI Read Data"},
200 {0xc6, "Logout Response"},
201 {0xd0, "Ready To Transfer"},
202 {0xd1, "Asynchronous Message"},
206 {0x01, "SCSI Command"},
207 {0x02, "SCSI Task Management Command"},
208 {0x03, "Login Command"},
209 {0x04, "Text Command"},
210 {0x05, "SCSI Write Data"},
211 {0x06, "Logout Command"},
212 {0x10, "SNACK Request"},
215 {0xe1, "SCSI Command Response"},
216 {0xe2, "SCSI Task Management Response"},
217 {0xe3, "Login Response"},
218 {0xe4, "Text Response"},
219 {0xe5, "SCSI Read Data"},
220 {0xe6, "Logout Response"},
221 {0xf1, "Ready To Transfer"},
222 {0xf2, "Asynchronous Message"},
228 static const value_string iscsi_opcodes_03[] = {
230 {0x01, "SCSI Command"},
231 {0x02, "SCSI Task Management Command"},
232 {0x03, "Login Command"},
233 {0x04, "Text Command"},
234 {0x05, "SCSI Write Data"},
235 {0x06, "Logout Command"},
237 {0x81, "SCSI Command Response"},
238 {0x82, "SCSI Task Management Response"},
239 {0x83, "Login Response"},
240 {0x84, "Text Response"},
241 {0x85, "SCSI Read Data"},
242 {0x86, "Logout Response"},
243 {0x90, "Ready To Transfer"},
244 {0x91, "Asynchronous Event"},
249 static const true_false_string iscsi_meaning_X = {
254 static const true_false_string iscsi_meaning_I = {
255 "Immediate delivery",
259 static const true_false_string iscsi_meaning_F = {
260 "Final PDU in sequence",
261 "Not final PDU in sequence"
264 static const true_false_string iscsi_meaning_P = {
269 static const true_false_string iscsi_meaning_S = {
270 "Response contains SCSI status",
271 "Response does not contain SCSI status"
274 static const true_false_string iscsi_meaning_R = {
275 "Data will be read from target",
276 "No data will be read from target"
279 static const true_false_string iscsi_meaning_W = {
280 "Data will be written to target",
281 "No data will be written to target"
284 static const true_false_string iscsi_meaning_o = {
285 "Read part of bi-directional command overflowed",
286 "No overflow of read part of bi-directional command",
289 static const true_false_string iscsi_meaning_u = {
290 "Read part of bi-directional command underflowed",
291 "No underflow of read part of bi-directional command",
294 static const true_false_string iscsi_meaning_O = {
295 "Residual overflow occurred",
296 "No residual overflow occurred",
299 static const true_false_string iscsi_meaning_U = {
300 "Residual underflow occurred",
301 "No residual underflow occurred",
304 static const true_false_string iscsi_meaning_scsiresponse_S = {
305 "Status/Response field contains SCSI status",
306 "Status/Response field contains iSCSI response",
309 static const true_false_string iscsi_meaning_SNACK_S = {
314 static const value_string iscsi_scsicommand_taskattrs[] = {
318 {3, "Head of Queue"},
323 static const value_string iscsi_scsi_cdb0[] = {
324 {0x00, "TEST_UNIT_READY"},
325 {0x01, "REZERO_UNIT"},
326 {0x03, "REQUEST_SENSE"},
327 {0x04, "FORMAT_UNIT"},
328 {0x05, "READ_BLOCK_LIMITS"},
329 {0x07, "REASSIGN_BLOCKS"},
333 {0x0f, "READ_REVERSE"},
334 {0x10, "WRITE_FILEMARKS"},
337 {0x14, "RECOVER_BUFFERED_DATA"},
338 {0x15, "MODE_SELECT"},
343 {0x1a, "MODE_SENSE"},
344 {0x1b, "START_STOP"},
345 {0x1c, "RECEIVE_DIAGNOSTIC"},
346 {0x1d, "SEND_DIAGNOSTIC"},
347 {0x1e, "ALLOW_MEDIUM_REMOVAL"},
348 {0x24, "SET_WINDOW"},
349 {0x25, "READ_CAPACITY"},
353 {0x2e, "WRITE_VERIFY"},
355 {0x30, "SEARCH_HIGH"},
356 {0x31, "SEARCH_EQUAL"},
357 {0x32, "SEARCH_LOW"},
358 {0x33, "SET_LIMITS"},
360 {0x34, "READ_POSITION"},
361 {0x35, "SYNCHRONIZE_CACHE"},
362 {0x36, "LOCK_UNLOCK_CACHE"},
363 {0x37, "READ_DEFECT_DATA"},
364 {0x38, "MEDIUM_SCAN"},
366 {0x3a, "COPY_VERIFY"},
367 {0x3b, "WRITE_BUFFER"},
368 {0x3c, "READ_BUFFER"},
369 {0x3d, "UPDATE_BLOCK"},
371 {0x3f, "WRITE_LONG"},
372 {0x40, "CHANGE_DEFINITION"},
373 {0x41, "WRITE_SAME"},
375 {0x4c, "LOG_SELECT"},
377 {0x55, "MODE_SELECT_10"},
378 {0x5a, "MODE_SENSE_10"},
379 {0xa5, "MOVE_MEDIUM"},
382 {0xae, "WRITE_VERIFY_12"},
383 {0xb0, "SEARCH_HIGH_12"},
384 {0xb1, "SEARCH_EQUAL_12"},
385 {0xb2, "SEARCH_LOW_12"},
386 {0xb8, "READ_ELEMENT_STATUS"},
387 {0xb6, "SEND_VOLUME_TAG"},
388 {0xea, "WRITE_LONG_2"},
392 static const value_string iscsi_scsi_statuses[] = {
394 {0x01, "Check condition"},
395 {0x02, "Condition good"},
397 {0x08, "Intermediate good"},
398 {0x0a, "Intermediate c good"},
399 {0x0c, "Reservation conflict"},
400 {0x11, "Command terminated"},
401 {0x14, "Queue full"},
405 static const value_string iscsi_scsi_responses[] = {
406 {0x01, "Target failure"},
407 {0x02, "Delivery subsystem failure"},
408 {0x03, "Unsolicited data rejected"},
409 {0x04, "SNACK rejected"},
413 static const value_string iscsi_task_responses[] = {
414 {0, "Function complete"},
415 {1, "Task not in task set"},
416 {2, "LUN does not exist"},
417 {255, "Function rejected"},
421 static const value_string iscsi_task_functions[] = {
423 {2, "Abort Task Set"},
425 {4, "Clear Task Set"},
426 {5, "Logical Unit Reset"},
427 {6, "Target Warm Reset"},
428 {7, "Target Cold Reset"},
432 static const value_string iscsi_login_status03[] = {
434 {1, "Reject Login - unsupported version"},
435 {2, "Reject Login - failed authentication"},
436 {3, "Reject Login - incompatible parameters"},
440 static const value_string iscsi_login_status[] = {
441 {0x0000, "Success - Accept login"},
442 {0x0001, "Success - Athenticate"},
443 {0x0002, "Success - iSCSI target name required"},
444 {0x0101, "Redirection - Target moved temporarily"},
445 {0x0102, "Redirection - Target moved permanently"},
446 {0x0103, "Redirection - Proxy required"},
447 {0x0201, "Initiator error - Athentication failed"},
448 {0x0202, "Initiator error - Forbidden target"},
449 {0x0203, "Initiator error - Target not found"},
450 {0x0204, "Initiator error - Target removed"},
451 {0x0205, "Initiator error - Target conflict"},
452 {0x0206, "Initiator error - Initiator SID error"},
453 {0x0207, "Initiator error - Missing parameter"},
454 {0x0300, "Target error - Target error"},
455 {0x0301, "Target error - Service unavailable"},
456 {0x0302, "Target error - Unsupported version"},
460 static const value_string iscsi_logout_reasons03[] = {
461 {0, "Remove connection - session is closing"},
462 {1, "Remove connection - for recovery"},
463 {2, "Remove connection - at target's request"},
467 static const value_string iscsi_logout_reasons[] = {
468 {0, "Session is closing"},
469 {1, "Close connections"},
470 {2, "Remove connection for recovery"},
471 {3, "Remove connection at target's request"},
475 static const value_string iscsi_logout_response[] = {
476 {0, "Connection closed successfully"},
477 {1, "Cleanup failed"},
481 static const value_string iscsi_scsievents03[] = {
482 {0, "No SCSI asynchronous event has occurred"},
483 {1, "Error condition encountered after command completion"},
484 {2, "A newly initialised device is available to the initiator"},
485 {3, "All task sets are being reset by another initiator"},
486 {5, "Some other type of unit attention condition has occurred"},
487 {6, "An asynchronous event has occurred"},
491 static const value_string iscsi_iscsievents03[] = {
492 {0, "No iSCSI event has occurred"},
493 {1, "Target is being reset"},
494 {2, "Target requests logout"},
495 {3, "Target will drop connection"},
499 static const value_string iscsi_scsievents[] = {
500 {0, "No SCSI asynchronous event has occurred"},
501 {1, "A SCSI asynchronous event is reported in the sense data"},
505 static const value_string iscsi_iscsievents[] = {
506 {0, "No iSCSI event has occurred"},
507 {1, "Target is being reset"},
508 {2, "Target requests logout"},
509 {3, "Target will/has dropped connection"},
510 {4, "Target will/has dropped all connections"},
514 static const value_string iscsi_reject_reasons03[] = {
516 {2, "Header digest error"},
517 {3, "Payload digest error"},
521 static const value_string iscsi_reject_reasons[] = {
523 {2, "Header digest error"},
524 {3, "Payload digest error"},
525 {4, "Data SNACK reject"},
526 {5, "Command retry reject"},
527 {15, "Full feature phase command before login"},
531 /*****************************************************************/
533 /* CRC LOOKUP TABLE */
534 /* ================ */
535 /* The following CRC lookup table was generated automagically */
536 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
537 /* Program V1.0 using the following model parameters: */
539 /* Width : 4 bytes. */
540 /* Poly : 0x1EDC6F41L */
541 /* Reverse : TRUE. */
543 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
544 /* see the document titled "A Painless Guide to CRC Error */
545 /* Detection Algorithms" by Ross Williams */
546 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
547 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
549 /*****************************************************************/
551 static guint32 crc32Table[256] = {
552 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
553 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
554 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
555 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
556 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
557 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
558 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
559 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
560 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
561 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
562 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
563 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
564 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
565 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
566 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
567 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
568 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
569 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
570 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
571 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
572 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
573 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
574 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
575 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
576 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
577 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
578 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
579 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
580 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
581 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
582 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
583 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
584 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
585 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
586 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
587 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
588 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
589 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
590 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
591 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
592 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
593 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
594 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
595 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
596 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
597 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
598 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
599 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
600 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
601 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
602 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
603 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
604 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
605 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
606 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
607 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
608 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
609 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
610 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
611 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
612 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
613 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
614 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
615 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
618 #define CRC32C_PRELOAD 0xffffffff
621 calculateCRC32(const void *buf, int len, guint32 crc) {
622 guint8 *p = (guint8 *)buf;
624 crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
629 iscsi_min(int a, int b) {
630 return (a < b)? a : b;
634 addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
635 const gint limit = offset + text_len;
636 while(offset < limit) {
637 gint len = tvb_strnlen(tvb, offset, limit - offset);
639 len = limit - offset;
642 proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
649 handleHeaderDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
650 int packet_len = tvb_length_remaining(tvb, offset);
651 if(packet_len >= (headerLen + 4)) {
652 guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
653 guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
654 if(crc == sent || enable_force_header_digest_crc32) {
656 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
660 proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Bad CRC32)", sent);
668 /* Code to actually dissect the packets */
670 dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
672 /* Set up structures needed to add the protocol subtree and manage it */
674 guint32 data_segment_len;
677 guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
678 const char *opcode_str = NULL;
679 char *scsi_command_name = NULL;
680 guint32 packet_len = tvb_length_remaining(tvb, offset);
682 /* quick check to see if the packet is long enough to contain a
683 * whole iSCSI header segment */
684 if (packet_len < 48) {
689 opcode = tvb_get_guint8(tvb, offset + 0);
692 opcode_str = match_strval(opcode, iscsi_opcodes_03);
693 data_segment_len = tvb_get_ntohl(tvb, offset + 4);
696 #ifndef USE_06_OPCODES
697 if((opcode & 0x20) == 0) {
698 /* initiator -> target */
699 /* mask out X and I bits */
703 opcode_str = match_strval(opcode, iscsi_opcodes);
704 data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
707 /* try and distinguish between data and real headers */
708 if(opcode_str == NULL ||
709 (enable_bogosity_filter &&
710 (data_segment_len > bogus_pdu_data_length_threshold ||
711 packet_len > (data_segment_len + 48 + bogus_pdu_max_digest_padding)))) {
715 /* Make entries in Protocol column and Info column on summary display */
716 if (check_col(pinfo->fd, COL_PROTOCOL))
717 col_set_str(pinfo->fd, COL_PROTOCOL, "iSCSI");
719 if (check_col(pinfo->fd, COL_INFO)) {
721 col_add_str(pinfo->fd, COL_INFO, (char *)opcode_str);
723 if((opcode & 0xbf) == 0x01) {
725 guint8 cdb0 = tvb_get_guint8(tvb, cdb_offset);
726 scsi_command_name = match_strval(cdb0, iscsi_scsi_cdb0);
727 if(cdb0 == 0x08 || cdb0 == 0x0a) {
728 /* READ_6 and WRITE_6 */
729 guint lba = tvb_get_ntohl(tvb, cdb_offset) & 0x1fffff;
730 guint len = tvb_get_guint8(tvb, cdb_offset + 4);
731 col_append_fstr(pinfo->fd, COL_INFO, " (%s LBA 0x%06x len 0x%02x)", scsi_command_name, lba, len);
733 else if(cdb0 == 0x28 || cdb0 == 0x2a) {
734 /* READ_10 and WRITE_10 */
735 guint lba = tvb_get_ntohl(tvb, cdb_offset + 2);
736 guint len = tvb_get_ntohs(tvb, cdb_offset + 7);
737 col_append_fstr(pinfo->fd, COL_INFO, " (%s LBA 0x%08x len 0x%04x)", scsi_command_name, lba, len);
739 else if(scsi_command_name != NULL)
740 col_append_fstr(pinfo->fd, COL_INFO, " (%s)", scsi_command_name);
742 else if(enable_03_mode && opcode == 0x81) {
743 /* SCSI Command Response */
744 const char *blurb = match_strval(tvb_get_guint8(tvb, offset + 36), iscsi_scsi_statuses);
746 col_append_fstr(pinfo->fd, COL_INFO, " (%s)", blurb);
748 else if(!enable_03_mode &&
749 #ifdef USE_06_OPCODES
755 /* SCSI Command Response */
756 const char *blurb = NULL;
757 if(tvb_get_guint8(tvb, offset + 1) & 0x01)
758 blurb = match_strval(tvb_get_guint8(tvb, offset + 3), iscsi_scsi_statuses);
760 blurb = match_strval(tvb_get_guint8(tvb, offset + 3), iscsi_scsi_responses);
762 col_append_fstr(pinfo->fd, COL_INFO, " (%s)", blurb);
766 /* In the interest of speed, if "tree" is NULL, don't do any
767 work not necessary to generate protocol tree items. */
770 /* create display subtree for the protocol */
771 ti = proto_tree_add_protocol_format(tree, proto_iscsi, tvb, offset,
772 packet_len, "iSCSI (%s)", (char *)opcode_str);
775 proto_tree_add_uint(ti, hf_iscsi_Opcode_03, tvb,
776 offset + 0, 1, opcode);
779 proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
780 offset + 0, 1, opcode);
781 #ifndef USE_06_OPCODES
782 if((opcode & 0x20) == 0) {
783 /* initiator -> target */
784 gint b = tvb_get_guint8(tvb, offset + 0);
788 proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
791 proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
796 if((enable_03_mode && opcode == 0x00) ||
797 #ifdef USE_06_OPCODES
798 (!enable_03_mode && (opcode == 0x00 ||
802 (!enable_03_mode && opcode == 0x00)
807 gint b = tvb_get_guint8(tvb, offset + 1);
808 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
809 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
810 proto_tree_add_boolean(tt, hf_iscsi_NOP_P, tvb, offset + 1, 1, b);
813 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
816 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
818 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
819 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
820 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
821 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
822 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
824 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 32, 4, FALSE);
826 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
827 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
829 else if((enable_03_mode && opcode == 0x80) ||
830 #ifdef USE_06_OPCODES
831 (!enable_03_mode && opcode == 0xc0)
833 (!enable_03_mode && opcode == 0xe0)
838 gint b = tvb_get_guint8(tvb, offset + 1);
839 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
840 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
841 proto_tree_add_boolean(tt, hf_iscsi_NOP_P, tvb, offset + 1, 1, b);
844 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
847 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
849 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
850 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
851 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
852 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
853 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
854 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
856 else if((enable_03_mode && opcode == 0x01) ||
857 #ifdef USE_06_OPCODES
858 (!enable_03_mode && (opcode == 0x01 ||
862 (!enable_03_mode && opcode == 0x01)
868 gint b = tvb_get_guint8(tvb, offset + 1);
869 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
870 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
872 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_X03, tvb, offset + 1, 1, b);
873 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
874 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
875 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
877 proto_tree_add_item(ti, hf_iscsi_SCSICommand_AddCDB, tvb, offset + 3, 1, FALSE);
878 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
882 gint b = tvb_get_guint8(tvb, offset + 1);
883 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
884 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
886 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
887 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
888 proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
889 proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
891 proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
892 proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
893 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
895 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
896 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
897 proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
898 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
899 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
901 /* dissect a little of the CDB for the most common
903 guint8 cdb0 = tvb_get_guint8(tvb, cdb_offset);
907 cdb_len += tvb_get_guint8(tvb, offset + 3) * 4;
910 /* FIXME - extended CDB */
912 if(scsi_command_name == NULL)
913 scsi_command_name = match_strval(cdb0, iscsi_scsi_cdb0);
914 if(cdb0 == 0x08 || cdb0 == 0x0a) {
915 /* READ_6 and WRITE_6 */
916 guint lba = tvb_get_ntohl(tvb, cdb_offset) & 0x1fffff;
917 guint len = tvb_get_guint8(tvb, cdb_offset + 4);
918 tf = proto_tree_add_uint_format(ti, hf_iscsi_SCSICommand_CDB0, tvb, cdb_offset, cdb_len, cdb0, "CDB: %s LBA 0x%06x len 0x%02x", scsi_command_name, lba, len);
920 else if(cdb0 == 0x28 || cdb0 == 0x2a) {
921 /* READ_10 and WRITE_10 */
922 guint lba = tvb_get_ntohl(tvb, cdb_offset + 2);
923 guint len = tvb_get_ntohs(tvb, cdb_offset + 7);
924 tf = proto_tree_add_uint_format(ti, hf_iscsi_SCSICommand_CDB0, tvb, cdb_offset, cdb_len, cdb0, "CDB: %s LBA 0x%08x len 0x%04x", scsi_command_name, lba, len);
927 tf = proto_tree_add_uint(ti, hf_iscsi_SCSICommand_CDB0, tvb, cdb_offset, cdb_len, cdb0);
929 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_CDB);
930 proto_tree_add_item(tt, hf_iscsi_SCSICommand_CDB, tvb, cdb_offset, cdb_len, FALSE);
932 offset = cdb_offset + cdb_len + handleHeaderDigest(ti, tvb, offset, cdb_offset + cdb_len);
935 else if((enable_03_mode && opcode == 0x81) ||
936 #ifdef USE_06_OPCODES
937 (!enable_03_mode && opcode == 0xc1)
939 (!enable_03_mode && opcode == 0xe1)
945 gint b = tvb_get_guint8(tvb, offset + 1);
946 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
947 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
949 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o03, tvb, offset + 1, 1, b);
950 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u03, tvb, offset + 1, 1, b);
951 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O03, tvb, offset + 1, 1, b);
952 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U03, tvb, offset + 1, 1, b);
954 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
958 gint b = tvb_get_guint8(tvb, offset + 1);
959 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
960 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
962 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
963 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
964 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
965 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
966 proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_S, tvb, offset + 1, 1, b);
968 proto_tree_add_item(ti, hf_iscsi_StatusResponse_is_status, tvb, offset + 3, 1, FALSE);
970 proto_tree_add_item(ti, hf_iscsi_StatusResponse_is_response, tvb, offset + 3, 1, FALSE);
972 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
974 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
975 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BasicResidualCount, tvb, offset + 20, 4, FALSE);
976 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
977 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
978 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
980 proto_tree_add_item(ti, hf_iscsi_CommandStatus03, tvb, offset + 36, 1, FALSE);
981 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_SenseLength, tvb, offset + 40, 2, FALSE);
984 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
985 proto_tree_add_item(ti, hf_iscsi_R2TExpDataSN, tvb, offset + 40, 4, FALSE);
987 proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
988 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
990 else if((enable_03_mode && opcode == 0x02) ||
991 #ifdef USE_06_OPCODES
992 (!enable_03_mode && (opcode == 0x02 ||
996 (!enable_03_mode && opcode == 0x02)
999 /* SCSI Task Command */
1000 proto_tree_add_item(ti, hf_iscsi_SCSITask_Function, tvb, offset + 1, 1, FALSE);
1001 if(enable_03_mode) {
1002 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1004 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1005 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1006 proto_tree_add_item(ti, hf_iscsi_SCSITask_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1007 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1008 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1009 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1011 else if((enable_03_mode && opcode == 0x82) ||
1012 #ifdef USE_06_OPCODES
1013 (!enable_03_mode && opcode == 0xc2)
1015 (!enable_03_mode && opcode == 0xe2)
1018 /* SCSI Task Response */
1019 if(enable_03_mode) {
1020 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1022 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1023 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1024 proto_tree_add_item(ti, hf_iscsi_SCSITask_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
1025 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1026 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1027 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1028 proto_tree_add_item(ti, hf_iscsi_SCSITask_Response, tvb, offset + 36, 1, FALSE);
1029 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1031 else if((enable_03_mode && opcode == 0x03) ||
1032 #ifdef USE_06_OPCODES
1033 (!enable_03_mode && (opcode == 0x03 ||
1036 (!enable_03_mode && opcode == 0x03)
1040 if(!enable_03_mode) {
1041 gint b = tvb_get_guint8(tvb, offset + 1);
1042 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1043 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1045 proto_tree_add_boolean(tt, hf_iscsi_Login_F, tvb, offset + 1, 1, b);
1047 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1048 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1049 if(enable_03_mode) {
1050 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1053 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1055 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1056 proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 12, 2, FALSE);
1057 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1058 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1059 if(enable_03_mode) {
1060 proto_tree_add_item(ti, hf_iscsi_InitCmdSN, tvb, offset + 24, 4, FALSE);
1063 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1064 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1066 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1067 if(packet_len > offset) {
1068 int text_len = iscsi_min(data_segment_len, packet_len - offset);
1069 proto_item *tf = proto_tree_add_text(ti, tvb, offset, text_len, "Key/Value Pairs");
1070 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
1071 offset = addTextKeys(tt, tvb, offset, text_len);
1072 if(offset < packet_len) {
1073 int padding = 4 - (offset & 3);
1074 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
1079 else if((enable_03_mode && opcode == 0x83) ||
1080 #ifdef USE_06_OPCODES
1081 (!enable_03_mode && opcode == 0xc3)
1083 (!enable_03_mode && opcode == 0xe3)
1086 /* Login Response */
1088 gint b = tvb_get_guint8(tvb, offset + 1);
1089 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1090 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1092 proto_tree_add_boolean(tt, hf_iscsi_Login_F, tvb, offset + 1, 1, b);
1094 proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
1095 proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
1096 if(enable_03_mode) {
1097 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1100 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1102 proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 12, 2, FALSE);
1103 proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
1104 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1105 proto_tree_add_item(ti, hf_iscsi_InitStatSN, tvb, offset + 24, 4, FALSE);
1106 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1107 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1108 if(enable_03_mode) {
1109 proto_tree_add_item(ti, hf_iscsi_Login_Status03, tvb, offset + 36, 1, FALSE);
1112 proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 1, FALSE);
1114 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1115 if(packet_len > offset) {
1116 int text_len = iscsi_min(data_segment_len, packet_len - offset);
1117 proto_item *tf = proto_tree_add_text(ti, tvb, offset, text_len, "Key/Value Pairs");
1118 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
1119 offset = addTextKeys(tt, tvb, offset, text_len);
1120 if(offset < packet_len) {
1121 int padding = 4 - (offset & 3);
1122 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
1127 else if((enable_03_mode && opcode == 0x04) ||
1128 #ifdef USE_06_OPCODES
1129 (!enable_03_mode && (opcode == 0x04 ||
1133 (!enable_03_mode && opcode == 0x04)
1137 if(enable_03_mode) {
1138 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1141 gint b = tvb_get_guint8(tvb, offset + 1);
1142 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1143 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1145 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1146 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1148 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1149 proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
1150 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1151 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1152 if(packet_len > offset) {
1153 int text_len = iscsi_min(data_segment_len, packet_len - offset);
1154 proto_item *tf = proto_tree_add_text(ti, tvb, offset, text_len, "Key/Value Pairs");
1155 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
1156 offset = addTextKeys(tt, tvb, offset, text_len);
1157 if(offset < packet_len) {
1158 int padding = 4 - (offset & 3);
1159 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
1164 else if((enable_03_mode && opcode == 0x84) ||
1165 #ifdef USE_06_OPCODES
1166 (!enable_03_mode && (opcode == 0xc4))
1168 (!enable_03_mode && opcode == 0xe4)
1172 if(enable_03_mode) {
1173 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1176 gint b = tvb_get_guint8(tvb, offset + 1);
1177 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1178 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1180 proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
1181 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1183 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1184 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1185 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1186 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1187 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1188 if(packet_len > offset) {
1189 int text_len = iscsi_min(data_segment_len, packet_len - offset);
1190 proto_item *tf = proto_tree_add_text(ti, tvb, offset, text_len, "Key/Value Pairs");
1191 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
1192 offset = addTextKeys(tt, tvb, offset, text_len);
1193 if(offset < packet_len) {
1194 int padding = 4 - (offset & 3);
1195 proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
1200 else if(opcode == 0x05) {
1201 /* SCSI Data (write) */
1203 gint b = tvb_get_guint8(tvb, offset + 1);
1204 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1205 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1207 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1209 if(enable_03_mode) {
1210 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1213 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1215 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1216 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1217 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1218 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1220 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1221 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1222 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1224 else if((enable_03_mode && opcode == 0x85) ||
1225 #ifdef USE_06_OPCODES
1226 (!enable_03_mode && opcode == 0xc5)
1228 (!enable_03_mode && opcode == 0xe5)
1231 /* SCSI Data (read) */
1232 if(enable_03_mode) {
1233 gint b = tvb_get_guint8(tvb, offset + 1);
1234 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1235 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1237 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_P03, tvb, offset + 1, 1, b);
1238 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S03, tvb, offset + 1, 1, b);
1239 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O03, tvb, offset + 1, 1, b);
1240 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U03, tvb, offset + 1, 1, b);
1241 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1244 gint b = tvb_get_guint8(tvb, offset + 1);
1245 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1246 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1248 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
1249 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
1250 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
1251 proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
1252 proto_tree_add_item(ti, hf_iscsi_StatusResponse_is_status, tvb, offset + 3, 1, FALSE);
1253 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1255 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1256 if(enable_03_mode) {
1257 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1259 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1260 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1261 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1262 if(enable_03_mode) {
1263 proto_tree_add_item(ti, hf_iscsi_CommandStatus03, tvb, offset + 36, 1, FALSE);
1266 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1268 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1269 proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
1270 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1272 else if((enable_03_mode && opcode == 0x06) ||
1273 #ifdef USE_06_OPCODES
1274 (!enable_03_mode && (opcode == 0x06 || opcode == 0x46))
1276 (!enable_03_mode && opcode == 0x06)
1279 /* Logout Command */
1280 if(enable_03_mode) {
1281 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1284 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1286 proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
1288 proto_tree_add_item(ti, hf_iscsi_Logout_Reason03, tvb, offset + 11, 1, FALSE);
1290 proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
1291 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1292 if(!enable_03_mode) {
1293 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1295 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1297 else if((enable_03_mode && opcode == 0x86) ||
1298 #ifdef USE_06_OPCODES
1299 (!enable_03_mode && opcode == 0xc6)
1301 (!enable_03_mode && opcode == 0xe6)
1304 /* Logout Response */
1305 if(enable_03_mode) {
1306 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1308 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1309 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1310 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1311 proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 36, 1, FALSE);
1312 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1315 #ifdef USE_06_OPCODES
1316 (!enable_03_mode && (opcode == 0x10 || opcode == 0x50))
1318 (!enable_03_mode && opcode == 0x10)
1324 gint b = tvb_get_guint8(tvb, offset + 1);
1325 proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
1326 proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
1328 proto_tree_add_boolean(tt, hf_iscsi_SNACK_S, tvb, offset + 1, 1, b);
1331 proto_tree_add_item(ti, hf_iscsi_AddRuns, tvb, offset + 3, 1, FALSE);
1332 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1333 proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
1334 proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
1336 proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
1339 proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 28, 4, FALSE);
1341 proto_tree_add_item(ti, hf_iscsi_AdditionalRuns, tvb, offset + 32, 16, FALSE);
1342 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1344 else if((enable_03_mode && opcode == 0x90) ||
1345 #ifdef USE_06_OPCODES
1346 (!enable_03_mode && opcode == 0xd0)
1348 (!enable_03_mode && opcode == 0xf1)
1352 if(enable_03_mode) {
1353 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1355 proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
1356 proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
1357 if(!enable_03_mode) {
1358 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1360 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1361 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1362 if(enable_03_mode) {
1363 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 36, 4, FALSE);
1364 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1367 proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
1368 proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
1369 proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
1371 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1373 else if((enable_03_mode && opcode == 0x91) ||
1374 #ifdef USE_06_OPCODES
1375 (!enable_03_mode && opcode == 0xd1)
1377 (!enable_03_mode && opcode == 0xf2)
1380 /* Asynchronous Message */
1381 if(enable_03_mode) {
1382 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1385 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1387 proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
1388 proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
1389 proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
1390 proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
1391 if(enable_03_mode) {
1392 proto_tree_add_item(ti, hf_iscsi_SCSIEvent03, tvb, offset + 36, 1, FALSE);
1393 proto_tree_add_item(ti, hf_iscsi_iSCSIEvent03, tvb, offset + 37, 1, FALSE);
1396 proto_tree_add_item(ti, hf_iscsi_SCSIEvent, tvb, offset + 36, 1, FALSE);
1397 proto_tree_add_item(ti, hf_iscsi_iSCSIEvent, tvb, offset + 37, 1, FALSE);
1399 proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
1400 proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
1402 proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
1403 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1405 else if((enable_03_mode && opcode == 0xef) ||
1406 #ifdef USE_06_OPCODES
1407 (!enable_03_mode && opcode == 0xef)
1409 (!enable_03_mode && opcode == 0xff)
1413 if(enable_03_mode) {
1414 proto_tree_add_uint(ti, hf_iscsi_Length03, tvb, offset + 4, 4, data_segment_len);
1415 proto_tree_add_item(ti, hf_iscsi_Reject_Reason03, tvb, offset + 36, 1, FALSE);
1418 proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
1419 proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 40, 1, FALSE);
1420 proto_tree_add_item(ti, hf_iscsi_Reject_FirstBadByte, tvb, offset + 42, 1, FALSE);
1422 offset += 48 + handleHeaderDigest(ti, tvb, offset, 48);
1425 if(packet_len > offset)
1426 proto_tree_add_item(ti, hf_iscsi_Payload, tvb, offset, packet_len - offset, FALSE);
1432 /* Register the protocol with Ethereal */
1434 /* this format is require because a script is used to build the C function
1435 that calls all the protocol registration.
1439 proto_register_iscsi(void)
1442 /* Setup list of header fields See Section 1.6.1 for details*/
1443 static hf_register_info hf[] = {
1444 { &hf_iscsi_Padding,
1445 { "Padding", "iscsi.padding",
1446 FT_BYTES, BASE_HEX, NULL, 0,
1447 "Padding to 4 byte boundary", HFILL }
1449 { &hf_iscsi_Payload,
1450 { "Payload", "iscsi.payload",
1451 FT_BYTES, BASE_HEX, NULL, 0,
1454 { &hf_iscsi_HeaderDigest32,
1455 { "HeaderDigest", "iscsi.headerdigest",
1456 FT_UINT32, BASE_HEX, NULL, 0,
1457 "Header Digest", HFILL }
1460 { "Opcode", "iscsi.opcode",
1461 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
1464 { &hf_iscsi_Opcode_03,
1465 { "Opcode", "iscsi.opcode",
1466 FT_UINT8, BASE_HEX, VALS(iscsi_opcodes_03), 0,
1471 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1472 "Command Retry", HFILL }
1476 FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
1477 "Immediate delivery", HFILL }
1480 { "Flags", "iscsi.flags",
1481 FT_UINT8, BASE_HEX, NULL, 0,
1482 "Opcode specific flags", HFILL }
1484 { &hf_iscsi_SCSICommand_X03,
1485 { "X", "iscsi.scsicommand.X",
1486 FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
1487 "Command Retry", HFILL }
1489 { &hf_iscsi_SCSICommand_F,
1490 { "F", "iscsi.scsicommand.F",
1491 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1492 "PDU completes command", HFILL }
1494 { &hf_iscsi_SCSICommand_R,
1495 { "R", "iscsi.scsicommand.R",
1496 FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
1497 "Command reads from SCSI target", HFILL }
1499 { &hf_iscsi_SCSICommand_W,
1500 { "W", "iscsi.scsicommand.W",
1501 FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
1502 "Command writes to SCSI target", HFILL }
1504 { &hf_iscsi_SCSICommand_Attr,
1505 { "Attr", "iscsi.scsicommand.attr",
1506 FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
1507 "SCSI task attributes", HFILL }
1509 { &hf_iscsi_SCSICommand_CRN,
1510 { "CRN", "iscsi.scsicommand.crn",
1511 FT_UINT8, BASE_HEX, NULL, 0,
1512 "SCSI command reference number", HFILL }
1514 { &hf_iscsi_SCSICommand_AddCDB,
1515 { "AddCDB", "iscsi.scsicommand.addcdb",
1516 FT_UINT8, BASE_HEX, NULL, 0,
1517 "Additional CDB length (in 4 byte units)", HFILL }
1519 { &hf_iscsi_Length03,
1520 { "Length", "iscsi.length",
1521 FT_UINT32, BASE_HEX, NULL, 0,
1522 "Data length (bytes)", HFILL }
1524 { &hf_iscsi_DataSegmentLength,
1525 { "DataSegmentLength", "iscsi.datasegmentlength",
1526 FT_UINT32, BASE_HEX, NULL, 0,
1527 "Data segment length (bytes)", HFILL }
1529 { &hf_iscsi_TotalAHSLength,
1530 { "TotalAHSLength", "iscsi.totalahslength",
1531 FT_UINT8, BASE_HEX, NULL, 0,
1532 "Total additional header segment length (4 byte words)", HFILL }
1535 { "LUN", "iscsi.lun",
1536 FT_BYTES, BASE_HEX, NULL, 0,
1537 "Logical Unit Number", HFILL }
1539 { &hf_iscsi_InitiatorTaskTag,
1540 { "InitiatorTaskTag", "iscsi.initiatortasktag",
1541 FT_UINT32, BASE_HEX, NULL, 0,
1542 "Initiator's task tag", HFILL }
1544 { &hf_iscsi_ExpectedDataTransferLength,
1545 { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
1546 FT_UINT32, BASE_HEX, NULL, 0,
1547 "Expected length of data transfer", HFILL }
1550 { "CmdSN", "iscsi.cmdsn",
1551 FT_UINT32, BASE_HEX, NULL, 0,
1552 "Sequence number for this command (0 == immediate)", HFILL }
1554 { &hf_iscsi_ExpStatSN,
1555 { "ExpStatSN", "iscsi.expstatsn",
1556 FT_UINT32, BASE_HEX, NULL, 0,
1557 "Next expected status sequence number", HFILL }
1559 { &hf_iscsi_SCSICommand_CDB,
1560 { "CDB", "iscsi.scsicommand.cdb",
1561 FT_BYTES, BASE_HEX, NULL, 0,
1564 { &hf_iscsi_SCSICommand_CDB0,
1565 { "CDB", "iscsi.scsicommand.cdb0",
1566 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_cdb0), 0,
1567 "SCSI CDB[0]", HFILL }
1569 { &hf_iscsi_SCSIResponse_BasicResidualCount,
1570 { "BasicResidualCount", "iscsi.scsiresponse.basicresidualcount",
1571 FT_UINT32, BASE_HEX, NULL, 0,
1572 "Residual count", HFILL }
1575 { "StatSN", "iscsi.statsn",
1576 FT_UINT32, BASE_HEX, NULL, 0,
1577 "Status sequence number", HFILL }
1579 { &hf_iscsi_ExpCmdSN,
1580 { "ExpCmdSN", "iscsi.expcmdsn",
1581 FT_UINT32, BASE_HEX, NULL, 0,
1582 "Next expected command sequence number", HFILL }
1584 { &hf_iscsi_MaxCmdSN,
1585 { "MaxCmdSN", "iscsi.maxcmdsn",
1586 FT_UINT32, BASE_HEX, NULL, 0,
1587 "Maximum acceptable command sequence number", HFILL }
1589 { &hf_iscsi_SCSIResponse_o03,
1590 { "o", "iscsi.scsiresponse.o",
1591 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x08,
1592 "Bi-directional read residual overflow", HFILL }
1594 { &hf_iscsi_SCSIResponse_u03,
1595 { "u", "iscsi.scsiresponse.u",
1596 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x04,
1597 "Bi-directional read residual underflow", HFILL }
1599 { &hf_iscsi_SCSIResponse_O03,
1600 { "O", "iscsi.scsiresponse.O",
1601 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x02,
1602 "Residual overflow", HFILL }
1604 { &hf_iscsi_SCSIResponse_U03,
1605 { "U", "iscsi.scsiresponse.U",
1606 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x01,
1607 "Residual underflow", HFILL }
1609 { &hf_iscsi_SCSIResponse_o,
1610 { "o", "iscsi.scsiresponse.o",
1611 FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
1612 "Bi-directional read residual overflow", HFILL }
1614 { &hf_iscsi_SCSIResponse_u,
1615 { "u", "iscsi.scsiresponse.u",
1616 FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
1617 "Bi-directional read residual underflow", HFILL }
1619 { &hf_iscsi_SCSIResponse_O,
1620 { "O", "iscsi.scsiresponse.O",
1621 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
1622 "Residual overflow", HFILL }
1624 { &hf_iscsi_SCSIResponse_U,
1625 { "U", "iscsi.scsiresponse.U",
1626 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
1627 "Residual underflow", HFILL }
1629 { &hf_iscsi_SCSIResponse_S,
1630 { "S", "iscsi.scsiresponse.S",
1631 FT_BOOLEAN, 8, TFS(&iscsi_meaning_scsiresponse_S), 0x01,
1632 "Status/Response", HFILL }
1634 { &hf_iscsi_CommandStatus03,
1635 { "CommandStatus", "iscsi.commandstatus",
1636 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_statuses), 0,
1637 "SCSI command status value", HFILL }
1639 { &hf_iscsi_StatusResponse_is_status,
1640 { "Status/Response", "iscsi.scsiresponse.statusresponse",
1641 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_statuses), 0,
1642 "SCSI command status value", HFILL }
1644 { &hf_iscsi_StatusResponse_is_response,
1645 { "Status/Response", "iscsi.scsiresponse.statusresponse",
1646 FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
1647 "iSCSI response value", HFILL }
1649 { &hf_iscsi_SCSIResponse_SenseLength,
1650 { "SenseLength", "iscsi.scsiresponse.senselength",
1651 FT_UINT16, BASE_HEX, NULL, 0,
1652 "SCSI sense data length", HFILL }
1654 { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
1655 { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
1656 FT_UINT32, BASE_HEX, NULL, 0,
1657 "Bi-directional read residual count", HFILL }
1659 { &hf_iscsi_SCSIData_F,
1660 { "F", "iscsi.scsidata.F",
1661 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1662 "Final PDU", HFILL }
1664 { &hf_iscsi_SCSIData_P03,
1665 { "P", "iscsi.scsidata.P",
1666 FT_BOOLEAN, 8, TFS(&iscsi_meaning_P), 0x80,
1667 "Poll requested", HFILL }
1669 { &hf_iscsi_SCSIData_S03,
1670 { "S", "iscsi.scsidata.S",
1671 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), 0x04,
1672 "PDU Contains SCSI command status", HFILL }
1674 { &hf_iscsi_SCSIData_O03,
1675 { "O", "iscsi.scsidata.O",
1676 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x02,
1677 "Residual overflow", HFILL }
1679 { &hf_iscsi_SCSIData_U03,
1680 { "U", "iscsi.scsidata.U",
1681 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x01,
1682 "Residual underflow", HFILL }
1684 { &hf_iscsi_SCSIData_S,
1685 { "S", "iscsi.scsidata.S",
1686 FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), 0x01,
1687 "PDU Contains SCSI command status", HFILL }
1689 { &hf_iscsi_SCSIData_U,
1690 { "U", "iscsi.scsidata.U",
1691 FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
1692 "Residual underflow", HFILL }
1694 { &hf_iscsi_SCSIData_O,
1695 { "O", "iscsi.scsidata.O",
1696 FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
1697 "Residual overflow", HFILL }
1699 { &hf_iscsi_TargetTransferTag,
1700 { "TargetTransferTag", "iscsi.targettransfertag",
1701 FT_UINT32, BASE_HEX, NULL, 0,
1702 "Target transfer tag", HFILL }
1704 { &hf_iscsi_BufferOffset,
1705 { "BufferOffset", "iscsi.bufferOffset",
1706 FT_UINT32, BASE_HEX, NULL, 0,
1707 "Buffer offset", HFILL }
1709 { &hf_iscsi_SCSIData_ResidualCount,
1710 { "ResidualCount", "iscsi.scsidata.readresidualcount",
1711 FT_UINT32, BASE_HEX, NULL, 0,
1712 "Residual count", HFILL }
1715 { "DataSN", "iscsi.datasn",
1716 FT_UINT32, BASE_HEX, NULL, 0,
1717 "Data sequence number", HFILL }
1719 { &hf_iscsi_VersionMax,
1720 { "VersionMax", "iscsi.versionmax",
1721 FT_UINT8, BASE_HEX, NULL, 0,
1722 "Maximum supported protocol version", HFILL }
1724 { &hf_iscsi_VersionMin,
1725 { "VersionMin", "iscsi.versionmin",
1726 FT_UINT8, BASE_HEX, NULL, 0,
1727 "Minimum supported protocol version", HFILL }
1730 { "CID", "iscsi.cid",
1731 FT_UINT16, BASE_HEX, NULL, 0,
1732 "Connection identifier", HFILL }
1735 { "ISID", "iscsi.isid",
1736 FT_UINT16, BASE_HEX, NULL, 0,
1737 "Initiator part of session identifier", HFILL }
1740 { "TSID", "iscsi.tsid",
1741 FT_UINT16, BASE_HEX, NULL, 0,
1742 "Target part of session identifier", HFILL }
1744 { &hf_iscsi_InitStatSN,
1745 { "InitStatSN", "iscsi.initstatsn",
1746 FT_UINT32, BASE_HEX, NULL, 0,
1747 "Initial status sequence number", HFILL }
1749 { &hf_iscsi_InitCmdSN,
1750 { "InitCmdSN", "iscsi.initcmdsn",
1751 FT_UINT32, BASE_HEX, NULL, 0,
1752 "Initial command sequence number", HFILL }
1754 { &hf_iscsi_Login_F,
1755 { "F", "iscsi.login.F",
1756 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1757 "Final PDU in login sequence", HFILL }
1759 { &hf_iscsi_Login_Status03,
1760 { "Status", "iscsi.login.status",
1761 FT_UINT8, BASE_HEX, VALS(iscsi_login_status03), 0,
1764 { &hf_iscsi_Login_Status,
1765 { "Status", "iscsi.login.status",
1766 FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
1767 "Status class and detail", HFILL }
1769 { &hf_iscsi_KeyValue,
1770 { "KeyValue", "iscsi.keyvalue",
1771 FT_STRING, 0, NULL, 0,
1772 "Key/value pair", HFILL }
1775 { "F", "iscsi.text.F",
1776 FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
1777 "Final PDU in text sequence", HFILL }
1780 { "P", "iscsi.nop.P",
1781 FT_BOOLEAN, 8, TFS(&iscsi_meaning_P), 0x80,
1782 "Poll requested", HFILL }
1784 { &hf_iscsi_ExpDataSN,
1785 { "ExpDataSN", "iscsi.expdatasn",
1786 FT_UINT32, BASE_HEX, NULL, 0,
1787 "Next expected data sequence number", HFILL }
1789 { &hf_iscsi_R2TExpDataSN,
1790 { "R2TExpDataSN", "iscsi.r2texpdatasn",
1791 FT_UINT32, BASE_HEX, NULL, 0,
1792 "Next expected R2T data sequence number", HFILL }
1794 { &hf_iscsi_SCSITask_Response,
1795 { "Response", "iscsi.scsitask.response",
1796 FT_UINT8, BASE_HEX, VALS(iscsi_task_responses), 0,
1799 { &hf_iscsi_SCSITask_ReferencedTaskTag,
1800 { "InitiatorTaskTag", "iscsi.scsitask.referencedtasktag",
1801 FT_UINT32, BASE_HEX, NULL, 0,
1802 "Task's initiator task tag", HFILL }
1804 { &hf_iscsi_SCSITask_Function,
1805 { "Function", "iscsi.scsitask.function",
1806 FT_UINT8, BASE_HEX, VALS(iscsi_task_functions), 0x7F,
1807 "Requested task function", HFILL }
1809 { &hf_iscsi_Logout_Reason03,
1810 { "Reason", "iscsi.logout.reason",
1811 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons03), 0,
1812 "Reason for logout", HFILL }
1814 { &hf_iscsi_Logout_Reason,
1815 { "Reason", "iscsi.logout.reason",
1816 FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0,
1817 "Reason for logout", HFILL }
1819 { &hf_iscsi_Logout_Response,
1820 { "Response", "iscsi.logout.response",
1821 FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
1822 "Logout response", HFILL }
1824 { &hf_iscsi_DesiredDataLength,
1825 { "DesiredDataLength", "iscsi.desireddatalength",
1826 FT_UINT32, BASE_HEX, NULL, 0,
1827 "Desired data length (bytes)", HFILL }
1829 { &hf_iscsi_SCSIEvent03,
1830 { "SCSIEvent", "iscsi.scsievent",
1831 FT_UINT8, BASE_HEX, VALS(iscsi_scsievents03), 0,
1832 "SCSI event indicator", HFILL }
1834 { &hf_iscsi_iSCSIEvent03,
1835 { "iSCSIEvent", "iscsi.iscsievent",
1836 FT_UINT8, BASE_HEX, VALS(iscsi_iscsievents03), 0,
1837 "iSCSI event indicator", HFILL }
1839 { &hf_iscsi_SCSIEvent,
1840 { "SCSIEvent", "iscsi.scsievent",
1841 FT_UINT8, BASE_HEX, VALS(iscsi_scsievents), 0,
1842 "SCSI event indicator", HFILL }
1844 { &hf_iscsi_iSCSIEvent,
1845 { "iSCSIEvent", "iscsi.iscsievent",
1846 FT_UINT8, BASE_HEX, VALS(iscsi_iscsievents), 0,
1847 "iSCSI event indicator", HFILL }
1849 { &hf_iscsi_Parameter1,
1850 { "Parameter1", "iscsi.parameter1",
1851 FT_UINT16, BASE_HEX, NULL, 0,
1852 "Parameter 1", HFILL }
1854 { &hf_iscsi_Parameter2,
1855 { "Parameter2", "iscsi.parameter2",
1856 FT_UINT16, BASE_HEX, NULL, 0,
1857 "Parameter 2", HFILL }
1859 { &hf_iscsi_Parameter3,
1860 { "Parameter3", "iscsi.parameter3",
1861 FT_UINT16, BASE_HEX, NULL, 0,
1862 "Parameter 3", HFILL }
1864 { &hf_iscsi_Reject_Reason,
1865 { "Reason", "iscsi.reject.reason",
1866 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
1867 "Reason for command rejection", HFILL }
1869 { &hf_iscsi_Reject_FirstBadByte,
1870 { "FirstBadByte", "iscsi.reject.firstbadbyte",
1871 FT_UINT16, BASE_HEX, NULL, 0,
1872 "Offset of first bad byte in PDU when reason is 'format error'", HFILL }
1874 { &hf_iscsi_Reject_Reason03,
1875 { "Reason", "iscsi.reject.reason",
1876 FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons03), 0,
1877 "Reason for command rejection", HFILL }
1879 { &hf_iscsi_SNACK_S,
1880 { "S", "iscsi.snack.S",
1881 FT_BOOLEAN, 8, TFS(&iscsi_meaning_SNACK_S), 0x01,
1882 "Status not data SNACK requested", HFILL }
1884 { &hf_iscsi_AddRuns,
1885 { "AddRuns", "iscsi.snack.addruns",
1886 FT_UINT8, BASE_HEX, NULL, 0,
1887 "Number of additional runs", HFILL }
1890 { "BegRun", "iscsi.snack.begrun",
1891 FT_UINT32, BASE_HEX, NULL, 0,
1892 "First missed DataSN or StatSN", HFILL }
1894 { &hf_iscsi_RunLength,
1895 { "RunLength", "iscsi.snack.runlength",
1896 FT_UINT32, BASE_HEX, NULL, 0,
1897 "Number of additional missing status PDUs in this run", HFILL }
1899 { &hf_iscsi_AdditionalRuns,
1900 { "AdditionalRuns", "iscsi.snack.additionalruns",
1901 FT_BYTES, BASE_HEX, NULL, 0,
1902 "Additional runs of missing status PDUs", HFILL }
1906 /* Setup protocol subtree array */
1907 static gint *ett[] = {
1908 &ett_iscsi_KeyValues,
1913 /* Register the protocol name and description */
1914 proto_iscsi = proto_register_protocol("iSCSI", "ISCSI", "iscsi");
1916 /* Required function calls to register the header fields and subtrees used */
1917 proto_register_field_array(proto_iscsi, hf, array_length(hf));
1918 proto_register_subtree_array(ett, array_length(ett));
1921 module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
1923 prefs_register_bool_preference(iscsi_module,
1924 "version_03_compatible",
1925 "Enable 03 compatibility mode",
1926 "When enabled, assume packets conform to the legacy 03 version of the iSCSI specification",
1928 prefs_register_bool_preference(iscsi_module,
1930 "Enable bogus pdu filter",
1931 "When enabled, packets that appear bogus are ignored",
1932 &enable_bogosity_filter);
1934 prefs_register_uint_preference(iscsi_module,
1935 "bogus_pdu_max_data_len",
1936 "Bogus pdu max data length threshold",
1937 "Treat packets whose data segment length is greater than this value as bogus",
1939 &bogus_pdu_data_length_threshold);
1940 prefs_register_uint_preference(iscsi_module,
1941 "bogus_pdu_max_digest_padding",
1942 "Bogus pdu max digest padding",
1943 "Treat packets whose apparent total digest size is greater than this value as bogus",
1945 &bogus_pdu_max_digest_padding);
1950 /* If this dissector uses sub-dissector registration add a registration routine.
1951 This format is required because a script is used to find these routines and
1952 create the code that calls these routines.
1955 proto_reg_handoff_iscsi(void)
1957 heur_dissector_add("tcp", dissect_iscsi, proto_iscsi);