1/* 2 * Copyright 2010, Andreas F��rber <andreas.faerber@web.de> 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5#ifndef ISCSI_CMDS_H 6#define ISCSI_CMDS_H 7 8 9#include <ByteOrder.h> 10 11 12// TODO Add Little Endian support by introducing more macros 13#if __BYTE_ORDER != __BIG_ENDIAN 14#error Only Big Endian systems supported yet. 15#endif 16 17 18// iSCSI Basic Header Segment (BHS) (RFC 3720 10.2.1) 19 20#define ISCSI_BHS_BYTE0 \ 21 bool reserved : 1; \ 22 bool immediateDelivery : 1; \ 23 uint8 opcode : 6; 24 25// TODO This macro is LE-incompatible 26#define ISCSI_BHS_START \ 27 ISCSI_BHS_BYTE0 \ 28 bool final : 1; 29 30#define ISCSI_BHS_LENGTHS \ 31 uint8 totalAHSLength; \ 32 uint32 dataSegmentLength : 24; 33 34#define ISCSI_BHS_TASK_TAG \ 35 uint32 initiatorTaskTag; 36 37#define ISCSI_BHS_TAGS \ 38 ISCSI_BHS_TASK_TAG \ 39 uint32 targetTransferTag; 40 41struct iscsi_basic_header_segment { 42 ISCSI_BHS_START 43 uint32 opcodeSpecific : 23; 44 ISCSI_BHS_LENGTHS 45 uint64 lun; 46 ISCSI_BHS_TASK_TAG 47 uint8 opcodeSpecific2[28]; 48} _PACKED; 49 50// initiator opcodes 51#define ISCSI_OPCODE_NOP_OUT 0x00 52#define ISCSI_OPCODE_SCSI_COMMAND 0x01 53#define ISCSI_OPCODE_LOGIN_REQUEST 0x03 54#define ISCSI_OPCODE_TEXT_REQUEST 0x04 55#define ISCSI_OPCODE_LOGOUT_REQUEST 0x06 56// target opcodes 57#define ISCSI_OPCODE_NOP_IN 0x20 58#define ISCSI_OPCODE_SCSI_RESPONSE 0x21 59#define ISCSI_OPCODE_LOGIN_RESPONSE 0x23 60#define ISCSI_OPCODE_TEXT_RESPONSE 0x24 61#define ISCSI_OPCODE_SCSI_DATA_IN 0x25 62#define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26 63 64// SCSI Command (RFC 3720 10.3) 65struct iscsi_scsi_command { 66 iscsi_scsi_command() 67 : 68 reserved(0), 69 opcode(ISCSI_OPCODE_SCSI_COMMAND), 70 reserved2(0), 71 reserved3(0) 72 { 73 } 74 ISCSI_BHS_START 75 bool r : 1; 76 bool w : 1; 77 uint8 reserved2 : 2; 78 uint8 attr : 3; 79 uint16 reserved3; 80 ISCSI_BHS_LENGTHS 81 uint64 lun; 82 ISCSI_BHS_TASK_TAG 83 uint32 expectedDataTransferLength; 84 uint32 cmdSN; 85 uint32 expStatSN; 86 uint8 cdb[16]; 87} _PACKED; 88 89// SCSI Response (RFC 3720 10.4) 90struct iscsi_scsi_response { 91 ISCSI_BHS_START 92 uint8 reserved2 : 2; 93 bool o : 1; 94 bool u : 1; 95 bool O : 1; 96 bool U : 1; 97 bool reserved3 : 1; 98 uint8 response; 99 uint8 status; 100 ISCSI_BHS_LENGTHS 101 uint32 reserved4[2]; 102 ISCSI_BHS_TASK_TAG 103 uint32 snackTag; 104 uint32 statSN; 105 uint32 expCmdSN; 106 uint32 maxCmdSN; 107 uint32 expDataSN; 108 uint32 bidirectionalReadResidualCount; 109 uint32 residualCount; 110} _PACKED; 111 112// SCSI Data-In (RFC 3270 10.7) 113struct iscsi_scsi_data_in { 114 ISCSI_BHS_START 115 bool acknowledge : 1; 116 uint8 reserved2 : 3; 117 bool O : 1; 118 bool U : 1; 119 bool S : 1; 120 uint8 reserved3; 121 uint8 status; 122 ISCSI_BHS_LENGTHS 123 uint64 lun; 124 ISCSI_BHS_TAGS 125 uint32 statSN; 126 uint32 expCmdSN; 127 uint32 maxCmdSN; 128 uint32 dataSN; 129 uint32 bufferOffset; 130 uint32 residualCount; 131} _PACKED; 132 133// Text Request (RFC 3720 10.10) 134struct iscsi_text_request { 135 iscsi_text_request() 136 : 137 reserved(0), 138 opcode(ISCSI_OPCODE_TEXT_REQUEST), 139 reserved2(2) 140 { 141 reserved3[0] = 0; 142 reserved3[1] = 0; 143 reserved3[2] = 0; 144 reserved3[3] = 0; 145 } 146 ISCSI_BHS_START 147 bool c : 1; // continue 148 uint32 reserved2 : 22; 149 ISCSI_BHS_LENGTHS 150 uint64 lun; 151 ISCSI_BHS_TAGS 152 uint32 cmdSN; 153 uint32 expStatSN; 154 uint32 reserved3[4]; 155} _PACKED; 156 157// Text Response (RFC 3720 10.11) 158struct iscsi_text_response { 159 ISCSI_BHS_START 160 bool c : 1; // continue 161 uint32 reserved2 : 22; 162 ISCSI_BHS_LENGTHS 163 uint64 lun; 164 ISCSI_BHS_TAGS 165 uint32 statSN; 166 uint32 expCmdSN; 167 uint32 maxCmdSN; 168 uint32 reserved3[3]; 169} _PACKED; 170 171struct iscsi_isid { 172 uint8 t : 2; 173 uint8 a : 6; 174 uint16 b; 175 uint8 c; 176 uint16 d; 177} _PACKED; 178 179// Login Request (RFC 3720 10.12) 180struct iscsi_login_request { 181 iscsi_login_request() 182 : 183 reserved(false), 184 immediateDelivery(1), 185 opcode(ISCSI_OPCODE_LOGIN_REQUEST), 186 reserved2(0), 187 reserved3(0) 188 { 189 memset(reserved4, 0, sizeof(reserved4)); 190 } 191 192 ISCSI_BHS_BYTE0 193 bool transit : 1; 194 bool c : 1; // continue 195 uint8 reserved2 : 2; 196 uint8 currentStage : 2; 197 uint8 nextStage : 2; 198 uint8 versionMax; 199 uint8 versionMin; 200 ISCSI_BHS_LENGTHS 201 iscsi_isid isid; 202 uint16 tsih; 203 ISCSI_BHS_TASK_TAG 204 uint16 cid; 205 uint16 reserved3; 206 uint32 cmdSN; 207 uint32 expStatSN; 208 uint32 reserved4[4]; 209} _PACKED; 210 211#define ISCSI_SESSION_STAGE_SECURITY_NEGOTIATION 0 212#define ISCSI_SESSION_STAGE_LOGIN_OPERATIONAL_NEGOTIATION 1 213#define ISCSI_SESSION_STAGE_FULL_FEATURE_PHASE 3 214 215#define ISCSI_VERSION 0x00 216 217#define ISCSI_ISID_OUI 0 218#define ISCSI_ISID_EN 1 219#define ISCSI_ISID_RANDOM 2 220 221// Login Response (RFC 3720 10.13) 222struct iscsi_login_response { 223 ISCSI_BHS_BYTE0 224 bool transit : 1; 225 bool c : 1; // continue 226 uint8 reserved2 : 2; 227 uint8 currentStage : 2; 228 uint8 nextStage : 2; 229 uint8 versionMax; 230 uint8 versionActive; 231 ISCSI_BHS_LENGTHS 232 iscsi_isid isid; 233 uint16 tsih; 234 ISCSI_BHS_TASK_TAG 235 uint32 reserved3; 236 uint32 statSN; 237 uint32 expCmdSN; 238 uint32 maxCmdSN; 239 uint8 statusClass; 240 uint8 statusDetail; 241 uint16 reserved4; 242 uint32 reserved5[2]; 243} _PACKED; 244 245// Logout Request (RFC 3720 10.14) 246struct iscsi_logout_request { 247 iscsi_logout_request() 248 : 249 reserved(0), 250 opcode(ISCSI_OPCODE_LOGOUT_REQUEST), 251 final(true), 252 reserved2(0), 253 reserved4(0) 254 { 255 reserved3[0] = 0; 256 reserved3[1] = 0; 257 reserved5[0] = 0; 258 reserved5[1] = 0; 259 reserved5[2] = 0; 260 reserved5[3] = 0; 261 } 262 ISCSI_BHS_START 263 uint8 reasonCode : 7; 264 uint16 reserved2; 265 ISCSI_BHS_LENGTHS 266 uint32 reserved3[2]; 267 ISCSI_BHS_TASK_TAG 268 uint16 cid; 269 uint16 reserved4; 270 uint32 cmdSN; 271 uint32 expStatSN; 272 uint32 reserved5[4]; 273} _PACKED; 274 275#define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0 276#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION 1 277#define ISCSI_LOGOUT_REASON_REMOVE_CONNECTION 2 278 279// Logout Response (RFC 3720 10.15) 280struct iscsi_logout_response { 281 ISCSI_BHS_START 282 uint8 reserved2 : 7; 283 uint8 response; 284 uint8 reserved3; 285 ISCSI_BHS_LENGTHS 286 uint32 reserved4[2]; 287 ISCSI_BHS_TASK_TAG 288 uint32 reserved5; 289 uint32 statSN; 290 uint32 expCmdSN; 291 uint32 maxCmdSN; 292 uint32 reserved6; 293 uint16 time2Wait; 294 uint16 time2Remain; 295 uint32 reserved7; 296} _PACKED; 297 298// NOP-Out (RFC 3270, 10.18) 299struct iscsi_nop_out { 300 iscsi_nop_out() 301 : 302 reserved(0), 303 opcode(ISCSI_OPCODE_NOP_OUT), 304 final(true), 305 reserved2(0) 306 { 307 reserved3[0] = 0; 308 reserved3[1] = 0; 309 reserved3[2] = 0; 310 reserved3[3] = 0; 311 } 312 ISCSI_BHS_START 313 uint32 reserved2 : 23; 314 ISCSI_BHS_LENGTHS 315 uint64 lun; 316 ISCSI_BHS_TAGS 317 uint32 cmdSN; 318 uint32 expStatSN; 319 uint32 reserved3[4]; 320} _PACKED; 321 322// NOP-In (RFC 3270, 10.19) 323struct iscsi_nop_in { 324 ISCSI_BHS_START 325 uint32 reserved2 : 23; 326 ISCSI_BHS_LENGTHS 327 uint64 lun; 328 ISCSI_BHS_TAGS 329 uint32 statSN; 330 uint32 expCmdSN; 331 uint32 maxCmdSN; 332 uint32 reserved3[3]; 333} _PACKED; 334 335 336#endif 337