1/* 2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 3 * By downloading, copying, installing or using the software you agree 4 * to this license. If you do not agree to this license, do not 5 * download, install, copy or use the software. 6 * 7 * Intel License Agreement 8 * 9 * Copyright (c) 2000, Intel Corporation 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * -Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * -Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the 22 * distribution. 23 * 24 * -The name of Intel Corporation may not be used to endorse or 25 * promote products derived from this software without specific prior 26 * written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL 32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 37 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 38 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 */ 41#include "config.h" 42 43#ifdef HAVE_STDLIB_H 44#include <stdlib.h> 45#endif 46 47#ifdef HAVE_NETINET_IN_H 48#include <netinet/in.h> 49#endif 50 51#ifdef HAVE_SYS_UIO_H 52#include <sys/uio.h> 53#endif 54 55#ifdef HAVE_STRING_H 56#include <string.h> 57#endif 58 59#ifdef HAVE_INTTYPES_H 60#include <inttypes.h> 61#endif 62 63#include "iscsiprotocol.h" 64#include "iscsiutil.h" 65#include <compat.h> 66 67 68/* 69 * Task Command 70 */ 71 72int 73iscsi_task_cmd_encap(uint8_t *header, iscsi_task_cmd_t * cmd) 74{ 75 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 76 iscsi_trace(TRACE_ISCSI_ARGS, "Function: %u\n", cmd->function); 77 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 78 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 79 iscsi_trace(TRACE_ISCSI_ARGS, "Ref Tag: %#x\n", cmd->ref_tag); 80 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 81 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 82 iscsi_trace(TRACE_ISCSI_ARGS, "RefCmdSN: %u\n", cmd->RefCmdSN); 83 iscsi_trace(TRACE_ISCSI_ARGS, "ExpDataSN: %u\n", cmd->ExpDataSN); 84 85 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 86 87 header[0] |= ISCSI_TASK_CMD; /* Opcode */ 88 if (cmd->immediate) { 89 header[0] |= 0x40; /* Immediate bit */ 90 } 91 header[1] = cmd->function & 0x80; /* Function */ 92 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->lun); /* LUN */ 93 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Tag */ 94 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(cmd->ref_tag); /* Reference Tag */ 95 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->CmdSN); /* CmdSN */ 96 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpStatSN); /* ExpStatSN */ 97 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(cmd->RefCmdSN); /* RefCmdSN */ 98 *((uint32_t *) (void *) (header + 36)) = ISCSI_HTONL(cmd->ExpDataSN); /* ExpDataSN */ 99 100 return 0; 101} 102 103int 104iscsi_task_cmd_decap(uint8_t *header, iscsi_task_cmd_t * cmd) 105{ 106 const char *errmsg; 107 uint8_t zeros[16]; 108 109 if (ISCSI_OPCODE(header) != ISCSI_TASK_CMD) { 110 iscsi_err(__FILE__, __LINE__, "Opcode"); 111 return 1; 112 } 113 cmd->immediate = ((header[0] & 0x40) == 0x40); 114 cmd->function = header[1] & 0x80; 115 cmd->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); 116 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); 117 cmd->ref_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); 118 cmd->CmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); 119 cmd->ExpStatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); 120 cmd->RefCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); 121 cmd->ExpDataSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 36))); 122 123 errmsg = NULL; 124 (void) memset(zeros, 0x0, sizeof(zeros)); 125 if ((header[1] & 0x80) != 0x80) { 126 errmsg = "Byte 1 bit 0"; 127 } else if (header[2] != 0) { 128 errmsg = "Byte 2"; 129 } else if (header[3] != 0) { 130 errmsg = "Byte 3"; 131 } else if (memcmp(header + 4, zeros, 4) != 0) { 132 errmsg = "Bytes 4-7"; 133 } else if (memcmp(header + 40, zeros, 8) != 0) { 134 errmsg = "Bytes 40-47"; 135 } 136 if (errmsg) { 137 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 138 NO_CLEANUP; 139 return 1; 140 } 141 142 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 143 iscsi_trace(TRACE_ISCSI_ARGS, "Function: %u\n", cmd->function); 144 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 145 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 146 iscsi_trace(TRACE_ISCSI_ARGS, "Ref Tag: %#x\n", cmd->ref_tag); 147 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 148 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 149 iscsi_trace(TRACE_ISCSI_ARGS, "RefCmdSN: %u\n", cmd->RefCmdSN); 150 iscsi_trace(TRACE_ISCSI_ARGS, "ExpDataSN: %u\n", cmd->ExpDataSN); 151 return 0; 152} 153 154/* 155 * Task Response 156 */ 157 158int 159iscsi_task_rsp_encap(uint8_t *header, iscsi_task_rsp_t * rsp) 160{ 161 uint32_t length; 162 163 iscsi_trace(TRACE_ISCSI_ARGS, "Response: %u\n", rsp->response); 164 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", rsp->length); 165 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", rsp->tag); 166 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 167 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 168 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 169 170 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 171 172 header[0] |= ISCSI_TASK_RSP; /* Opcode */ 173 header[1] |= 0x80; /* Byte 1 bit 0 */ 174 header[2] = rsp->response; /* Response */ 175 length = (rsp->length & 0x00ffffff); /* Length */ 176 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(length); 177 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(rsp->tag); 178 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(rsp->StatSN); 179 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(rsp->ExpCmdSN); 180 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(rsp->MaxCmdSN); 181 return 0; 182} 183 184int 185iscsi_task_rsp_decap(uint8_t *header, iscsi_task_rsp_t * rsp) 186{ 187 const char *errmsg; 188 uint8_t zeros[16]; 189 190 if (ISCSI_OPCODE(header) != ISCSI_TASK_RSP) { 191 iscsi_err(__FILE__, __LINE__, "Opcode"); 192 return 1; 193 } 194 rsp->response = header[2]; 195 rsp->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); 196 rsp->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); 197 rsp->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); 198 rsp->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); 199 errmsg = NULL; 200 (void) memset(zeros, 0x0, sizeof(zeros)); 201 if ((header[0] & 0x00) != 0x00) { 202 errmsg = "Byte 0 bits 0-1"; 203 } else if ((header[1] & 0x80) != 0x80) { 204 errmsg = "Byte 1 bit 0"; 205 } else if (header[3] != 0) { 206 errmsg = "Byte 3"; 207 } else if (memcmp(header + 4, zeros, 12) != 0) { 208 errmsg = "Bytes 4-15"; 209 } else if (memcmp(header + 20, zeros, 4) != 0) { 210 errmsg = "Bytes 20-23"; 211 } else if (memcmp(header + 36, zeros, 12) != 0) { 212 errmsg = "Bytes 36-47"; 213 } 214 if (errmsg) { 215 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 216 NO_CLEANUP; 217 return 1; 218 } 219 iscsi_trace(TRACE_ISCSI_ARGS, "Response: %u\n", rsp->response); 220 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", rsp->tag); 221 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 222 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 223 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 224 return 0; 225} 226 227/* 228 * NOP-Out 229 */ 230 231int 232iscsi_nop_out_encap(uint8_t *header, iscsi_nop_out_args_t * cmd) 233{ 234 235 uint32_t length; 236 237 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 238 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 239 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 240 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 241 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 242 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 243 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 244 245 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 246 247 header[0] = ISCSI_NOP_OUT; /* Opcode */ 248 if (cmd->immediate) { 249 header[0] |= 0x40; /* Immediate bit */ 250 } 251 header[1] |= 0x80; /* Byte 1 bit 0 and Reserved */ 252 length = (cmd->length & 0x00ffffff); /* Length */ 253 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(length); /* Length */ 254 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->lun); /* LUN */ 255 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Tag */ 256 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(cmd->transfer_tag); /* Target Transfer Tag */ 257 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->CmdSN); /* CmdSN */ 258 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpStatSN); /* ExpStatSN */ 259 260 return 0; 261} 262 263int 264iscsi_nop_out_decap(uint8_t *header, iscsi_nop_out_args_t * cmd) 265{ 266 const char *errmsg; 267 uint8_t zeros[16]; 268 269 if (ISCSI_OPCODE(header) != ISCSI_NOP_OUT) { 270 iscsi_err(__FILE__, __LINE__, "Opcode"); 271 return 1; 272 } 273 cmd->immediate = ((header[0] & 0x40) == 0x40); /* Immediate bit */ 274 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 275 cmd->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 276 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Tag */ 277 cmd->transfer_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); /* Target Tranfer Tag */ 278 cmd->CmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* CmdSN */ 279 cmd->ExpStatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpStatSN */ 280 281 errmsg = NULL; 282 (void) memset(zeros, 0x0, sizeof(zeros)); 283 if (header[1] != 0x80) { 284 errmsg = "Byte 1"; 285 } else if (memcmp(header + 2, zeros, 3) != 0) { 286 errmsg = "Bytes 2-4"; 287 } else if (memcmp(header + 32, zeros, 16) != 0) { 288 errmsg = "Bytes 32-47"; 289 } 290 if (errmsg) { 291 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 292 NO_CLEANUP; 293 return 1; 294 } 295 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 296 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 297 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 298 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 299 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 300 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 301 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 302 return 0; 303} 304 305/* 306 * NOP-In 307 */ 308 309int 310iscsi_nop_in_encap(uint8_t *header, iscsi_nop_in_args_t * cmd) 311{ 312 uint32_t length; 313 314 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 315 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 316 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 317 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 318 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", cmd->StatSN); 319 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", cmd->ExpCmdSN); 320 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", cmd->MaxCmdSN); 321 322 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 323 324 header[0] = 0x00 | ISCSI_NOP_IN; /* Opcode */ 325 header[1] |= 0x80; /* Reserved */ 326 length = (cmd->length & 0x00ffffff); /* Length */ 327 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(length); /* Length */ 328 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->lun); /* LUN */ 329 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Tag */ 330 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(cmd->transfer_tag); /* Target Transfer Tag */ 331 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->StatSN); /* StatSN */ 332 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpCmdSN); /* ExpCmdSN */ 333 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(cmd->MaxCmdSN); /* MaxCmdSN */ 334 335 return 0; 336} 337 338int 339iscsi_nop_in_decap(uint8_t *header, iscsi_nop_in_args_t * cmd) 340{ 341 const char *errmsg; 342 uint8_t zeros[16]; 343 344 if (ISCSI_OPCODE(header) != ISCSI_NOP_IN) { 345 iscsi_err(__FILE__, __LINE__, "Opcode"); 346 return 1; 347 } 348 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 349 cmd->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 350 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Tag */ 351 cmd->transfer_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); /* Target Transfer Tag */ 352 cmd->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* StatSN */ 353 cmd->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpCmdSN */ 354 cmd->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); /* MaxCmdSN */ 355 356 errmsg = NULL; 357 (void) memset(zeros, 0x0, sizeof(zeros)); 358 if ((header[0] & 0xc0) != 0x00) { 359 errmsg = "Byte 0, bits 0-1"; 360 } else if (header[1] != 0x80) { 361 errmsg = "Byte 1"; 362 } else if (memcmp(header + 2, zeros, 3) != 0) { 363 errmsg = "Bytes 2-4"; 364 } else if (memcmp(header + 36, zeros, 12) != 0) { 365 errmsg = "Bytes 36-47"; 366 } 367 if (errmsg) { 368 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 369 NO_CLEANUP; 370 return 1; 371 } 372 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 373 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 374 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 375 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 376 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", cmd->StatSN); 377 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", cmd->ExpCmdSN); 378 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", cmd->MaxCmdSN); 379 return 0; 380} 381 382/* 383 * Text Command 384 */ 385 386int 387iscsi_text_cmd_encap(uint8_t *header, iscsi_text_cmd_args_t * cmd) 388{ 389 uint32_t length; 390 391 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 392 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %d\n", cmd->final); 393 iscsi_trace(TRACE_ISCSI_ARGS, "Continue: %d\n", cmd->cont); 394 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 395 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 396 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 397 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 398 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 399 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 400 401 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 402 403 header[0] |= ISCSI_TEXT_CMD; /* Opcode */ 404 if (cmd->immediate) { 405 header[0] |= 0x40; /* Immediate bit */ 406 } 407 if (cmd->final) { 408 header[1] |= 0x80; /* Final bit */ 409 } 410 if (cmd->cont) { 411 header[1] |= 0x40; /* Continue bit */ 412 } 413 length = (cmd->length & 0x00ffffff); /* Length */ 414 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(length); /* Length */ 415 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->lun); /* LUN */ 416 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Tag */ 417 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(cmd->transfer_tag); /* Transfer Tag */ 418 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->CmdSN); /* CmdSN */ 419 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpStatSN); /* ExpStatSN */ 420 421 return 0; 422} 423 424int 425iscsi_text_cmd_decap(uint8_t *header, iscsi_text_cmd_args_t * cmd) 426{ 427 const char *errmsg; 428 uint8_t zeros[16]; 429 430 if (ISCSI_OPCODE(header) != ISCSI_TEXT_CMD) { 431 iscsi_err(__FILE__, __LINE__, "Opcode"); 432 return 1; 433 } 434 cmd->immediate = ((header[0] & 0x40) == 0x40); /* Immediate bit */ 435 cmd->final = ((header[1] & 0x80) == 0x80); /* Final bit */ 436 cmd->cont = ((header[1] & 0x40) == 0x40); /* Continue bit */ 437 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 438 cmd->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 439 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Tag */ 440 cmd->transfer_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); /* Transfer Tag */ 441 cmd->CmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* CmdSN */ 442 cmd->ExpStatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpStatSN */ 443 444 errmsg = NULL; 445 (void) memset(zeros, 0x0, sizeof(zeros)); 446 if ((header[1] & 0x00) != 0x00) { 447 errmsg = "Byte 1, bits 2-7"; 448 } else if (memcmp(header + 2, zeros, 3) != 0) { 449 errmsg = "Bytes 2-4"; 450 } else if (memcmp(header + 8, zeros, 8) != 0) { 451 errmsg = "Bytes 8-15"; 452 } else if (memcmp(header + 32, zeros, 16) != 0) { 453 errmsg = "Bytes 32-47"; 454 } 455 if (errmsg) { 456 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 457 NO_CLEANUP; 458 return 1; 459 } 460 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 461 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %d\n", cmd->final); 462 iscsi_trace(TRACE_ISCSI_ARGS, "Continue: %d\n", cmd->cont); 463 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 464 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 465 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 466 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 467 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 468 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 469 470 return 0; 471} 472 473/* 474 * Text Response 475 */ 476 477int 478iscsi_text_rsp_encap(uint8_t *header, iscsi_text_rsp_args_t * rsp) 479{ 480 uint32_t length; 481 482 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %d\n", rsp->final); 483 iscsi_trace(TRACE_ISCSI_ARGS, "Continue: %d\n", rsp->cont); 484 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", rsp->length); 485 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", rsp->lun); 486 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", rsp->tag); 487 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", rsp->transfer_tag); 488 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 489 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 490 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 491 492 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 493 header[0] |= 0x00 | ISCSI_TEXT_RSP; /* Opcode */ 494 if (rsp->final) { 495 header[1] |= 0x80; /* Final bit */ 496 } 497 if (rsp->cont) { 498 header[1] |= 0x40; /* Continue */ 499 } 500 length = (rsp->length & 0x00ffffff); /* Length */ 501 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(length); /* Length */ 502 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(rsp->lun); /* LUN */ 503 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(rsp->tag); /* Tag */ 504 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(rsp->transfer_tag); /* Transfer Tag */ 505 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(rsp->StatSN); /* StatSN */ 506 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(rsp->ExpCmdSN); /* ExpCmdSN */ 507 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(rsp->MaxCmdSN); /* MaxCmdSN */ 508 509 return 0; 510} 511 512int 513iscsi_text_rsp_decap(uint8_t *header, iscsi_text_rsp_args_t * rsp) 514{ 515 const char *errmsg; 516 uint8_t zeros[16]; 517 518 if (ISCSI_OPCODE(header) != ISCSI_TEXT_RSP) { 519 iscsi_err(__FILE__, __LINE__, "Opcode"); 520 return 1; 521 } 522 rsp->final = ((header[1] & 0x80) == 0x80); /* Final bit */ 523 rsp->cont = ((header[1] & 0x40) == 0x40); /* Continue bit */ 524 rsp->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 525 rsp->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 526 rsp->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Tag */ 527 rsp->transfer_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); /* Transfer Tag */ 528 rsp->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* StatSN */ 529 rsp->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpCmdSN */ 530 rsp->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); /* MaxCmdSN */ 531 532 errmsg = NULL; 533 (void) memset(zeros, 0x0, sizeof(zeros)); 534 if ((header[1] & 0x3f) != 0x00) { 535 errmsg = "Byte 1, bits 2-7"; 536 } else if (memcmp(header + 2, zeros, 3) != 0) { 537 errmsg = "Bytes 2-4"; 538 } else if (memcmp(header + 8, zeros, 8) != 0) { 539 errmsg = "Bytes 8-15"; 540 } else if (memcmp(header + 36, zeros, 12) != 0) { 541 errmsg = "Bytes 36-47"; 542 } 543 if (errmsg) { 544 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 545 NO_CLEANUP; 546 return 1; 547 } 548 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %d\n", rsp->final); 549 iscsi_trace(TRACE_ISCSI_ARGS, "Continue: %d\n", rsp->cont); 550 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", rsp->length); 551 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", rsp->lun); 552 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", rsp->tag); 553 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", rsp->transfer_tag); 554 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 555 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 556 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 557 558 return 0; 559} 560 561/* 562 * Login Command 563 */ 564 565int 566iscsi_login_cmd_encap(uint8_t *header, iscsi_login_cmd_args_t * cmd) 567{ 568 uint32_t length; 569 570 iscsi_trace(TRACE_ISCSI_ARGS, "Transit: %d\n", cmd->transit); 571 iscsi_trace(TRACE_ISCSI_ARGS, "Continue: %d\n", cmd->cont); 572 iscsi_trace(TRACE_ISCSI_ARGS, "CSG: %u\n", cmd->csg); 573 iscsi_trace(TRACE_ISCSI_ARGS, "NSG: %u\n", cmd->nsg); 574 iscsi_trace(TRACE_ISCSI_ARGS, "Version_min: %u\n", cmd->version_min); 575 iscsi_trace(TRACE_ISCSI_ARGS, "Version_max: %u\n", cmd->version_max); 576 iscsi_trace(TRACE_ISCSI_ARGS, "TotalAHSLength: %u\n", cmd->AHSlength); 577 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", cmd->length); 578 iscsi_trace(TRACE_ISCSI_ARGS, "ISID: %" PRIu64 "\n", cmd->isid); 579 iscsi_trace(TRACE_ISCSI_ARGS, "TSIH: %hu\n", cmd->tsih); 580 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->tag); 581 iscsi_trace(TRACE_ISCSI_ARGS, "CID: %hu\n", cmd->cid); 582 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 583 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 584 585 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 586 587 header[0] |= 0x40 | ISCSI_LOGIN_CMD; /* Opcode */ 588 if (cmd->transit) { 589 header[1] |= 0x80; /* Transit */ 590 } 591 if (cmd->cont) { 592 header[1] |= 0x40; /* Continue */ 593 } 594 header[1] |= ((cmd->csg) << 2) & 0x0c; /* CSG */ 595 header[1] |= (cmd->nsg) & 0x03; /* NSG */ 596 header[2] = cmd->version_max; /* Version-Max */ 597 header[3] = cmd->version_min; /* Version-Min */ 598 header[4] = cmd->AHSlength; /* TotalAHSLength */ 599 length = (cmd->length & 0x00ffffff); /* Length */ 600 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(length); /* Length */ 601 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->isid << 16); /* ISID */ 602 *((uint16_t *) (void *) (header + 14)) = ISCSI_HTONS(cmd->tsih); /* TSIH */ 603 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Task Tag */ 604 *((uint16_t *) (void *) (header + 20)) = ISCSI_HTONS(cmd->cid); /* CID */ 605 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->CmdSN); /* CmdSN */ 606 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpStatSN); /* ExpStatSN */ 607 608 return 0; 609} 610 611int 612iscsi_login_cmd_decap(uint8_t *header, iscsi_login_cmd_args_t * cmd) 613{ 614 const char *errmsg; 615 uint8_t zeros[16]; 616 617 if (ISCSI_OPCODE(header) != ISCSI_LOGIN_CMD) { 618 iscsi_err(__FILE__, __LINE__, "Opcode"); 619 return 1; 620 } 621 cmd->transit = (header[1] & 0x80) ? 1 : 0; /* Transit */ 622 cmd->cont = (header[1] & 0x40) ? 1 : 0; /* Continue */ 623 cmd->csg = (header[1] & 0x0cU) >> 2; /* CSG */ 624 cmd->nsg = header[1] & 0x03; /* NSG */ 625 cmd->version_max = header[2]; /* Version-Max */ 626 cmd->version_min = header[3]; /* Version-Min */ 627 cmd->AHSlength = header[4]; /* TotalAHSLength */ 628 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 629 cmd->isid = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))) >> 16; /* ISID */ 630 cmd->tsih = ISCSI_NTOHS(*((uint16_t *) (void *) (header + 14))); /* TSIH */ 631 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Task Tag */ 632 cmd->cid = ISCSI_NTOHS(*((uint16_t *) (void *) (header + 20))); /* CID */ 633 cmd->CmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* CmdSN */ 634 cmd->ExpStatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpStatSN */ 635 636 iscsi_trace(TRACE_ISCSI_ARGS, "Transit: %d\n", cmd->transit); 637 iscsi_trace(TRACE_ISCSI_ARGS, "Continue: %d\n", cmd->cont); 638 iscsi_trace(TRACE_ISCSI_ARGS, "CSG: %u\n", cmd->csg); 639 iscsi_trace(TRACE_ISCSI_ARGS, "NSG: %u\n", cmd->nsg); 640 iscsi_trace(TRACE_ISCSI_ARGS, "Version_min: %u\n", cmd->version_min); 641 iscsi_trace(TRACE_ISCSI_ARGS, "Version_max: %u\n", cmd->version_max); 642 iscsi_trace(TRACE_ISCSI_ARGS, "TotalAHSLength: %u\n", cmd->AHSlength); 643 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", cmd->length); 644 iscsi_trace(TRACE_ISCSI_ARGS, "ISID: %" PRIu64 "\n", cmd->isid); 645 iscsi_trace(TRACE_ISCSI_ARGS, "TSIH: %hu\n", cmd->tsih); 646 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->tag); 647 iscsi_trace(TRACE_ISCSI_ARGS, "CID: %hu\n", cmd->cid); 648 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 649 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 650 651 errmsg = NULL; 652 (void) memset(zeros, 0x0, sizeof(zeros)); 653 if (((header[1] & 0x30U) >> 4U) != 0x0) { 654 errmsg = "Byte 1, bits 2-3"; 655 } else if (memcmp(header + 22, zeros, 2) != 0) { 656 errmsg = "Bytes 22-23"; 657 } else if (memcmp(header + 32, zeros, 16) != 0) { 658 errmsg = "Bytes 32-47"; 659 } 660 if (errmsg) { 661 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 662 NO_CLEANUP; 663 return 1; 664 } 665 if (cmd->transit) { 666 if (cmd->nsg <= cmd->csg) { 667 return -1; 668 } 669 if ((cmd->nsg != 0) && (cmd->nsg != 1) && (cmd->nsg != 3)) { 670 return -1; 671 } 672 } 673 return 0; 674} 675 676/* 677 * Login Response 678 */ 679 680int 681iscsi_login_rsp_encap(uint8_t *header, iscsi_login_rsp_args_t * rsp) 682{ 683 684 iscsi_trace(TRACE_ISCSI_ARGS, "Transit: %d\n", rsp->transit); 685 iscsi_trace(TRACE_ISCSI_ARGS, "Continue: %d\n", rsp->cont); 686 iscsi_trace(TRACE_ISCSI_ARGS, "CSG: %u\n", rsp->csg); 687 iscsi_trace(TRACE_ISCSI_ARGS, "NSG: %u\n", rsp->nsg); 688 iscsi_trace(TRACE_ISCSI_ARGS, "Version_max: %u\n", rsp->version_max); 689 iscsi_trace(TRACE_ISCSI_ARGS, "Version_active: %u\n", rsp->version_active); 690 iscsi_trace(TRACE_ISCSI_ARGS, "TotalAHSLength: %u\n", rsp->AHSlength); 691 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", rsp->length); 692 iscsi_trace(TRACE_ISCSI_ARGS, "ISID: %" PRIu64 "\n", rsp->isid); 693 iscsi_trace(TRACE_ISCSI_ARGS, "TSIH: %u\n", rsp->tsih); 694 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", rsp->tag); 695 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 696 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 697 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 698 iscsi_trace(TRACE_ISCSI_ARGS, "Status-Class: %u\n", rsp->status_class); 699 iscsi_trace(TRACE_ISCSI_ARGS, "Status-Detail: %u\n", rsp->status_detail); 700 701 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 702 703 header[0] |= 0x00 | ISCSI_LOGIN_RSP; /* Opcode */ 704 if (rsp->transit) { 705 header[1] |= 0x80; /* Transit */ 706 } 707 if (rsp->cont) { 708 header[1] |= 0x40; /* Continue */ 709 } 710 header[1] |= ((rsp->csg) << 2) & 0x0c; /* CSG */ 711 if (rsp->transit) { 712 header[1] |= (rsp->nsg) & 0x03; /* NSG */ 713 } 714 header[2] = rsp->version_max; /* Version-max */ 715 header[3] = rsp->version_active; /* Version-active */ 716 header[4] = rsp->AHSlength; /* TotalAHSLength */ 717 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(rsp->length); /* Length */ 718 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(rsp->isid << 16); /* ISID */ 719 *((uint16_t *) (void *) (header + 14)) = ISCSI_HTONS(rsp->tsih); /* TSIH */ 720 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(rsp->tag); /* Tag */ 721 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(rsp->StatSN); /* StatRn */ 722 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(rsp->ExpCmdSN); /* ExpCmdSN */ 723 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(rsp->MaxCmdSN); /* MaxCmdSN */ 724 header[36] = rsp->status_class; /* Status-Class */ 725 header[37] = rsp->status_detail; /* Status-Detail */ 726 727 return 0; 728} 729 730int 731iscsi_login_rsp_decap(uint8_t *header, iscsi_login_rsp_args_t * rsp) 732{ 733 const char *errmsg; 734 uint8_t zeros[8]; 735 736 if (ISCSI_OPCODE(header) != ISCSI_LOGIN_RSP) { 737 iscsi_err(__FILE__, __LINE__, "Opcode"); 738 return 1; 739 } 740 rsp->transit = (header[1] & 0x80U) >> 7; /* Transit */ 741 rsp->cont = (header[1] & 0x40U) >> 6; /* Continue */ 742 rsp->csg = (header[1] & 0x0cU) >> 2; /* CSG */ 743 rsp->nsg = header[1] & 0x03; /* NSG */ 744 rsp->version_max = header[2]; /* Version-max */ 745 rsp->version_active = header[3]; /* Version-active */ 746 rsp->AHSlength = header[4]; /* TotalAHSLength */ 747 rsp->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 748 rsp->isid = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))) >> 16; /* ISID */ 749 rsp->tsih = ISCSI_NTOHS(*((uint16_t *) (void *) (header + 14))); /* TSIH */ 750 751 rsp->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Tag */ 752 rsp->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* StatSN */ 753 rsp->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpCmdSN */ 754 rsp->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); /* MaxCmdSN */ 755 rsp->status_class = header[36]; /* Status-Class */ 756 rsp->status_detail = header[37]; /* Status-Detail */ 757 758 iscsi_trace(TRACE_ISCSI_ARGS, "Transit: %d\n", rsp->transit); 759 iscsi_trace(TRACE_ISCSI_ARGS, "Continue: %d\n", rsp->cont); 760 iscsi_trace(TRACE_ISCSI_ARGS, "CSG: %u\n", rsp->csg); 761 iscsi_trace(TRACE_ISCSI_ARGS, "NSG: %u\n", rsp->nsg); 762 763 iscsi_trace(TRACE_ISCSI_ARGS, "Version_max: %u\n", rsp->version_max); 764 iscsi_trace(TRACE_ISCSI_ARGS, "Version_active: %u\n", rsp->version_active); 765 iscsi_trace(TRACE_ISCSI_ARGS, "TotalAHSLength: %u\n", rsp->AHSlength); 766 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", rsp->length); 767 iscsi_trace(TRACE_ISCSI_ARGS, "ISID: %" PRIu64 "\n", rsp->isid); 768 iscsi_trace(TRACE_ISCSI_ARGS, "TSIH: %u\n", rsp->tsih); 769 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", rsp->tag); 770 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 771 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 772 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 773 iscsi_trace(TRACE_ISCSI_ARGS, "Status-Class: %u\n", rsp->status_class); 774 iscsi_trace(TRACE_ISCSI_ARGS, "Status-Detail: %u\n", rsp->status_detail); 775 errmsg = NULL; 776 (void) memset(zeros, 0x0, sizeof(zeros)); 777 if (((header[1] & 0x30U) >> 4U) != 0x0) { 778 errmsg = "Byte 1, bits 2-3"; 779 } else if (memcmp(header + 20, zeros, 4) != 0) { 780 errmsg = "Bytes 20-23"; 781 } else if (memcmp(header + 38, zeros, 2) != 0) { 782 errmsg = "Bytes 38-39"; 783 } else if (memcmp(header + 40, zeros, 8) != 0) { 784 errmsg = "Bytes 40-47"; 785 } 786 if (errmsg) { 787 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 788 NO_CLEANUP; 789 return 1; 790 } 791 return 0; 792} 793 794/* 795 * Logout Command 796 */ 797 798int 799iscsi_logout_cmd_encap(uint8_t *header, iscsi_logout_cmd_args_t * cmd) 800{ 801 802 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 803 iscsi_trace(TRACE_ISCSI_ARGS, "Reason: %u\n", cmd->reason); 804 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->tag); 805 iscsi_trace(TRACE_ISCSI_ARGS, "CID: %hu\n", cmd->cid); 806 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 807 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 808 809 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 810 811 header[0] = ISCSI_LOGOUT_CMD; /* Opcode */ 812 if (cmd->immediate) { 813 header[0] |= 0x40; /* Immediate */ 814 } 815 header[1] = cmd->reason | 0x80; /* Reason */ 816 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Tag */ 817 *((uint16_t *) (void *) (header + 20)) = ISCSI_HTONS(cmd->cid); /* CID */ 818 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->CmdSN); /* CmdSN */ 819 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpStatSN); /* ExpStatSN */ 820 821 return 0; 822} 823 824int 825iscsi_logout_cmd_decap(uint8_t *header, iscsi_logout_cmd_args_t * cmd) 826{ 827 const char *errmsg; 828 uint8_t zeros[16]; 829 830 if (ISCSI_OPCODE(header) != ISCSI_LOGOUT_CMD) { 831 iscsi_err(__FILE__, __LINE__, "Opcode"); 832 return 1; 833 } 834 cmd->immediate = (header[0] & 0x40) ? 1 : 0; /* Immediate */ 835 cmd->reason = header[1] & 0x7f; /* Reason */ 836 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Tag */ 837 cmd->cid = ISCSI_NTOHS(*((uint16_t *) (void *) (header + 20))); /* CID */ 838 cmd->CmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* CmdSN */ 839 cmd->ExpStatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpStatSN */ 840 841 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 842 iscsi_trace(TRACE_ISCSI_ARGS, "Reason: %u\n", cmd->reason); 843 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->tag); 844 845 iscsi_trace(TRACE_ISCSI_ARGS, "CID: %hu\n", cmd->cid); 846 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 847 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 848 errmsg = NULL; 849 (void) memset(zeros, 0x0, sizeof(zeros)); 850 if ((unsigned)(header[0]) >> 0x7U != 0) { 851 errmsg = "Byte 0, bit 0"; 852 } else if ((unsigned)(header[1]) >> 7U != 1) { 853 errmsg = "Byte 1, bit 0"; 854 } else if (header[2] != 0) { 855 errmsg = "Byte 2"; 856 } else if (header[3] != 0) { 857 errmsg = "Byte 3"; 858 } else if (memcmp(header + 4, zeros, 12) != 0) { 859 errmsg = "Bytes 4-7"; 860 } else if (memcmp(header + 22, zeros, 2) != 0) { 861 errmsg = "Bytes 22-23"; 862 } else if (memcmp(header + 32, zeros, 16) != 0) { 863 errmsg = "Bytes 32-47"; 864 } 865 if (errmsg) { 866 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 867 NO_CLEANUP; 868 return 1; 869 } 870 return 0; 871} 872 873/* 874 * Logout Response 875 */ 876 877int 878iscsi_logout_rsp_encap(uint8_t *header, iscsi_logout_rsp_args_t * rsp) 879{ 880 881 iscsi_trace(TRACE_ISCSI_ARGS, "Response: %u\n", rsp->response); 882 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", rsp->length); 883 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", rsp->tag); 884 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 885 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 886 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 887 888 iscsi_trace(TRACE_ISCSI_ARGS, "Time2Wait: %hu\n", rsp->Time2Wait); 889 iscsi_trace(TRACE_ISCSI_ARGS, "Time2Retain: %hu\n", rsp->Time2Retain); 890 891 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 892 893 header[0] |= 0x00 | ISCSI_LOGOUT_RSP; /* Opcode */ 894 header[1] |= 0x80; /* Reserved */ 895 header[2] = rsp->response; /* Response */ 896 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(rsp->length); /* Length */ 897 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(rsp->tag); /* Tag */ 898 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(rsp->StatSN); /* StatSN */ 899 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(rsp->ExpCmdSN); /* ExpCmdSN */ 900 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(rsp->MaxCmdSN); /* MaxCmdSN */ 901 *((uint16_t *) (void *) (header + 40)) = ISCSI_HTONS(rsp->Time2Wait); /* Time2Wait */ 902 *((uint16_t *) (void *) (header + 42)) = ISCSI_HTONS(rsp->Time2Retain); /* Time2Retain */ 903 904 return 0; 905} 906 907int 908iscsi_logout_rsp_decap(uint8_t *header, iscsi_logout_rsp_args_t * rsp) 909{ 910 const char *errmsg; 911 uint8_t zeros[16]; 912 913 if (ISCSI_OPCODE(header) != ISCSI_LOGOUT_RSP) { 914 iscsi_err(__FILE__, __LINE__, "Opcode"); 915 return 1; 916 } 917 rsp->response = header[2]; /* Response */ 918 rsp->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 919 rsp->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Tag */ 920 rsp->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* StatSN */ 921 rsp->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpCmdSN */ 922 rsp->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); /* MaxCmdSN */ 923 rsp->Time2Wait = ISCSI_NTOHS(*((uint16_t *) (void *) (header + 40))); /* Time2Wait */ 924 rsp->Time2Retain = ISCSI_NTOHS(*((uint16_t *) (void *) (header + 42))); /* Time2Retain */ 925 926 errmsg = NULL; 927 (void) memset(zeros, 0x0, sizeof(zeros)); 928 if ((header[0] & 0x20) != 0x20) { 929 errmsg = "Byte 0, bits 0-1"; 930 } else if ((header[1] & 0x80) != 0x80) { 931 errmsg = "Byte 1, bit 0"; 932 } else if (header[3] != 0) { 933 errmsg = "Byte 3"; 934 } else if (memcmp(header + 4, zeros, 12) != 0) { 935 errmsg = "Bytes 4-15"; 936 } else if (memcmp(header + 20, zeros, 4) != 0) { 937 errmsg = "Bytes 20-23"; 938 } else if (memcmp(header + 36, zeros, 4) != 0) { 939 errmsg = "Bytes 36-39"; 940 } else if (memcmp(header + 44, zeros, 4) != 0) { 941 errmsg = "Bytes 44-47"; 942 } 943 if (errmsg) { 944 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 945 NO_CLEANUP; 946 return 1; 947 } 948 iscsi_trace(TRACE_ISCSI_ARGS, "Response: %u\n", rsp->response); 949 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", rsp->length); 950 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", rsp->tag); 951 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 952 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 953 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 954 iscsi_trace(TRACE_ISCSI_ARGS, "Time2Wait: %hu\n", rsp->Time2Wait); 955 iscsi_trace(TRACE_ISCSI_ARGS, "Time2Retain: %hu\n", rsp->Time2Retain); 956 957 return 0; 958} 959 960/* 961 * SCSI Command 962 */ 963 964int 965iscsi_scsi_cmd_encap(uint8_t *header, iscsi_scsi_cmd_args_t * cmd) 966{ 967 968 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 969 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %d\n", cmd->final); 970 iscsi_trace(TRACE_ISCSI_ARGS, "Input: %d\n", cmd->input); 971 iscsi_trace(TRACE_ISCSI_ARGS, "Output: %d\n", cmd->output); 972 iscsi_trace(TRACE_ISCSI_ARGS, "ATTR: %d\n", cmd->attr); 973 iscsi_trace(TRACE_ISCSI_ARGS, "TotalAHSLength: %u\n", cmd->ahs_len); 974 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", cmd->length); 975 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 976 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->tag); 977 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Length: %u\n", cmd->trans_len); 978 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 979 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 980 iscsi_trace(TRACE_ISCSI_ARGS, "CDB: %#x\n", cmd->cdb[0]); 981 982 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 983 984 header[0] |= ISCSI_SCSI_CMD; /* Opcode */ 985 if (cmd->immediate) { 986 header[0] |= 0x40; /* Immediate */ 987 } 988 if (cmd->final) { 989 header[1] |= 0x80; /* Final */ 990 } 991 if (cmd->input) { 992 header[1] |= 0x40; /* Input bit */ 993 } 994 if (cmd->output) { 995 header[1] |= 0x20; /* Output bit */ 996 } 997 header[1] |= cmd->attr & 0x07; /* ATTR */ 998 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(cmd->length); /* DataSegmentLength */ 999 header[4] = cmd->ahs_len; /* TotalAHSLength */ 1000 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->lun); /* LUN */ 1001 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Task Tag */ 1002 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(cmd->trans_len); /* Expected Transfer 1003 * Length */ 1004 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->CmdSN); /* CmdSN */ 1005 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpStatSN); /* ExpStatSN */ 1006 memcpy(header + 32, cmd->cdb, 16); /* CDB */ 1007 1008 return 0; 1009} 1010 1011int 1012iscsi_scsi_cmd_decap(uint8_t *header, iscsi_scsi_cmd_args_t * cmd) 1013{ 1014 const char *errmsg; 1015 1016 if (ISCSI_OPCODE(header) != ISCSI_SCSI_CMD) { 1017 iscsi_err(__FILE__, __LINE__, "Opcode"); 1018 return 1; 1019 } 1020 cmd->immediate = (header[0] & 0x40) ? 1 : 0; /* Immediate */ 1021 cmd->final = (header[1] & 0x80) ? 1 : 0; /* Final */ 1022 cmd->input = (header[1] & 0x40) ? 1 : 0; /* Input */ 1023 cmd->output = (header[1] & 0x20) ? 1 : 0; /* Output */ 1024 cmd->attr = header[1] & 0x07; /* ATTR */ 1025 cmd->ahs_len = header[4]; 1026 header[4] = 0x00; 1027 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* DataSegmentLength */ 1028 cmd->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 1029 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Task Tag */ 1030 cmd->trans_len = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); /* Expected Transfer 1031 * Length */ 1032 cmd->CmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* CmdSN */ 1033 cmd->ExpStatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpStatSN */ 1034 cmd->cdb = header + 32; /* CDB */ 1035 1036 errmsg = NULL; 1037 if ((header[1] & 0x18) != 0x0) { 1038 errmsg = "Byte 1, bits 3-4"; 1039 } else if (header[2] != 0) { 1040 errmsg = "Byte 2"; 1041 } else if (header[3] != 0) { 1042 errmsg = "Byte 3"; 1043 } 1044 if (errmsg) { 1045 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 1046 NO_CLEANUP; 1047 return 1; 1048 } 1049 iscsi_trace(TRACE_ISCSI_ARGS, "Immediate: %d\n", cmd->immediate); 1050 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %d\n", cmd->final); 1051 iscsi_trace(TRACE_ISCSI_ARGS, "Input: %d\n", cmd->input); 1052 iscsi_trace(TRACE_ISCSI_ARGS, "Output: %d\n", cmd->output); 1053 iscsi_trace(TRACE_ISCSI_ARGS, "ATTR: %d\n", cmd->attr); 1054 iscsi_trace(TRACE_ISCSI_ARGS, "TotalAHSLength: %u\n", cmd->ahs_len); 1055 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", cmd->length); 1056 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 1057 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->tag); 1058 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Length: %u\n", cmd->trans_len); 1059 iscsi_trace(TRACE_ISCSI_ARGS, "CmdSN: %u\n", cmd->CmdSN); 1060 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 1061 iscsi_trace(TRACE_ISCSI_ARGS, "CDB: %#x\n", cmd->cdb[0]); 1062 1063 return 0; 1064} 1065 1066/* 1067 * SCSI Response 1068 */ 1069 1070int 1071iscsi_scsi_rsp_encap(uint8_t *header, iscsi_scsi_rsp_t * rsp) 1072{ 1073 1074 iscsi_trace(TRACE_ISCSI_ARGS, "Bidi Overflow: %d\n", rsp->bidi_overflow); 1075 iscsi_trace(TRACE_ISCSI_ARGS, "Bidi Underflow: %d\n", rsp->bidi_underflow); 1076 iscsi_trace(TRACE_ISCSI_ARGS, "Overflow: %d\n", rsp->overflow); 1077 iscsi_trace(TRACE_ISCSI_ARGS, "Underflow: %d\n", rsp->underflow); 1078 iscsi_trace(TRACE_ISCSI_ARGS, "iSCSI Response: %u\n", rsp->response); 1079 iscsi_trace(TRACE_ISCSI_ARGS, "SCSI Status: %u\n", rsp->status); 1080 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", rsp->length); 1081 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", rsp->tag); 1082 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 1083 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 1084 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 1085 iscsi_trace(TRACE_ISCSI_ARGS, "ExpDataSN: %u\n", rsp->ExpDataSN); 1086 iscsi_trace(TRACE_ISCSI_ARGS, "Bidi Residual Count: %u\n", rsp->bidi_res_cnt); 1087 iscsi_trace(TRACE_ISCSI_ARGS, "Residual Count: %u\n", rsp->basic_res_cnt); 1088 1089 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 1090 1091 header[0] |= 0x00 | ISCSI_SCSI_RSP; /* Opcode */ 1092 header[1] |= 0x80; /* Byte 1 bit 7 */ 1093 if (rsp->bidi_overflow) { 1094 header[1] |= 0x10; /* Bidi overflow */ 1095 } 1096 if (rsp->bidi_underflow) { 1097 header[1] |= 0x08; /* Bidi underflow */ 1098 } 1099 if (rsp->overflow) { 1100 header[1] |= 0x04; /* Overflow */ 1101 } 1102 if (rsp->underflow) { 1103 header[1] |= 0x02; /* Underflow */ 1104 } 1105 header[2] = rsp->response; /* iSCSI Response */ 1106 header[3] = rsp->status;/* SCSI Status */ 1107 header[4] = rsp->ahs_len; /* TotalAHSLength */ 1108 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(rsp->length); /* DataSegmentLength */ 1109 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(rsp->tag); /* Task Tag */ 1110 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(rsp->StatSN); /* StatSN */ 1111 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(rsp->ExpCmdSN); /* ExpCmdSN */ 1112 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(rsp->MaxCmdSN); /* MaxCmdSN */ 1113 *((uint32_t *) (void *) (header + 36)) = ISCSI_HTONL(rsp->ExpDataSN); /* ExpDataSN */ 1114 *((uint32_t *) (void *) (header + 40)) = ISCSI_HTONL(rsp->bidi_res_cnt); /* Bidi Residual Count */ 1115 *((uint32_t *) (void *) (header + 44)) = ISCSI_HTONL(rsp->basic_res_cnt); /* Residual Count */ 1116 1117 return 0; 1118} 1119 1120int 1121iscsi_scsi_rsp_decap(uint8_t *header, iscsi_scsi_rsp_t * rsp) 1122{ 1123 const char *errmsg; 1124 1125 if (ISCSI_OPCODE(header) != ISCSI_SCSI_RSP) { 1126 iscsi_err(__FILE__, __LINE__, "Opcode"); 1127 return 1; 1128 } 1129 rsp->bidi_overflow = (header[1] & 0x10) ? 1 : 0; /* Bidi overflow */ 1130 rsp->bidi_underflow = (header[1] & 0x08) ? 1 : 0; /* Bidi underflow */ 1131 rsp->overflow = (header[1] & 0x04) ? 1 : 0; /* Overflow */ 1132 rsp->underflow = (header[1] & 0x02) ? 1 : 0; /* Underflow */ 1133 1134 rsp->response = header[2]; /* iSCSI Response */ 1135 rsp->status = header[3];/* SCSI Status */ 1136 rsp->ahs_len = header[4]; /* TotalAHSLength */ 1137 rsp->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* DataSegmentLength */ 1138 rsp->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Task Tag */ 1139 rsp->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* StatSN */ 1140 rsp->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpCmdSN */ 1141 rsp->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); /* MaxCmdSN */ 1142 rsp->ExpDataSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 36))); /* ExpDataSN */ 1143 rsp->bidi_res_cnt = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 40))); /* Bidi Residual Count */ 1144 rsp->basic_res_cnt = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 44))); /* Residual Count */ 1145 1146 errmsg = NULL; 1147 if ((header[0] & 0xc0) != 0x0) { 1148 errmsg = "Byte 0, bits 0-1"; 1149 } else if ((header[1] & 0x80) != 0x80) { 1150 errmsg = "Byte 1, bit 0"; 1151 } else if (rsp->bidi_res_cnt != 0) { 1152 errmsg = "bidi_res_cnt"; 1153 } else if (rsp->bidi_overflow != 0) { 1154 errmsg = "bidi_overflow"; 1155 } else if (rsp->bidi_underflow != 0) { 1156 errmsg = "bidi_underflow"; 1157 } else if (rsp->overflow != 0) { 1158 errmsg = "overflow"; 1159 } 1160 if (errmsg) { 1161 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 1162 NO_CLEANUP; 1163 return 1; 1164 } 1165 iscsi_trace(TRACE_ISCSI_ARGS, "Bidi Overflow: %d\n", rsp->bidi_overflow); 1166 iscsi_trace(TRACE_ISCSI_ARGS, "Bidi Underflow: %d\n", rsp->bidi_underflow); 1167 iscsi_trace(TRACE_ISCSI_ARGS, "Overflow: %d\n", rsp->overflow); 1168 iscsi_trace(TRACE_ISCSI_ARGS, "Underflow: %d\n", rsp->underflow); 1169 iscsi_trace(TRACE_ISCSI_ARGS, "iSCSI Response: %u\n", rsp->response); 1170 iscsi_trace(TRACE_ISCSI_ARGS, "SCSI Status: %u\n", rsp->status); 1171 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", rsp->length); 1172 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", rsp->tag); 1173 iscsi_trace(TRACE_ISCSI_ARGS, "Residual Count: %u\n", rsp->basic_res_cnt); 1174 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", rsp->StatSN); 1175 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", rsp->ExpCmdSN); 1176 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", rsp->MaxCmdSN); 1177 iscsi_trace(TRACE_ISCSI_ARGS, "ExpDataSN: %u\n", rsp->ExpDataSN); 1178 iscsi_trace(TRACE_ISCSI_ARGS, "Bidi Residual Count: %u\n", rsp->bidi_res_cnt); 1179 1180 return 0; 1181} 1182 1183 1184/* 1185 * Ready To Transfer 1186 */ 1187 1188int 1189iscsi_r2t_encap(uint8_t *header, iscsi_r2t_t * cmd) 1190{ 1191 uint32_t length; 1192 1193 iscsi_trace(TRACE_ISCSI_ARGS, "TotalAHSLength: %u\n", cmd->AHSlength); 1194 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 1195 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 1196 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 1197 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", cmd->StatSN); 1198 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", cmd->ExpCmdSN); 1199 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", cmd->MaxCmdSN); 1200 iscsi_trace(TRACE_ISCSI_ARGS, "R2TSN: %u\n", cmd->R2TSN); 1201 iscsi_trace(TRACE_ISCSI_ARGS, "Offset: %u\n", cmd->offset); 1202 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 1203 1204 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 1205 1206 header[0] |= 0x00 | ISCSI_R2T; /* Opcode */ 1207 header[1] |= 0x80; 1208 length = (cmd->AHSlength & 0x00ffffff); /* AHSLength */ 1209 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(length); /* AHSLength */ 1210 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->lun); /* LUN */ 1211 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Tag */ 1212 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(cmd->transfer_tag); /* Transfer Tag */ 1213 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->StatSN); /* StatSN */ 1214 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpCmdSN); /* ExpCmdSN */ 1215 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(cmd->MaxCmdSN); /* MaxCmdSN */ 1216 *((uint32_t *) (void *) (header + 36)) = ISCSI_HTONL(cmd->R2TSN); /* R2TSN */ 1217 *((uint32_t *) (void *) (header + 40)) = ISCSI_HTONL(cmd->offset); /* Buffer Offset */ 1218 *((uint32_t *) (void *) (header + 44)) = ISCSI_HTONL(cmd->length); /* Transfer Length */ 1219 1220 return 0; 1221} 1222 1223int 1224iscsi_r2t_decap(uint8_t *header, iscsi_r2t_t * cmd) 1225{ 1226 const char *errmsg; 1227 uint8_t zeros[12]; 1228 1229 if (ISCSI_OPCODE(header) != ISCSI_R2T) { 1230 iscsi_err(__FILE__, __LINE__, "Opcode"); 1231 return 1; 1232 } 1233 cmd->AHSlength = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* TotalAHSLength */ 1234 cmd->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 1235 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); 1236 cmd->transfer_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); 1237 cmd->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); 1238 cmd->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); 1239 cmd->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); 1240 cmd->R2TSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 36))); 1241 cmd->offset = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 40))); 1242 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 44))); 1243 1244 errmsg = NULL; 1245 (void) memset(zeros, 0x0, sizeof(zeros)); 1246 if ((header[1] & 0x7f) != 0x0) { 1247 errmsg = "Byte 1, bits 1-7"; 1248 } else if (header[2] != 0) { 1249 errmsg = "Byte 2"; 1250 } else if (header[3] != 0) { 1251 errmsg = "Byte 3"; 1252 } else if (memcmp(header + 4, zeros, 12) != 0) { 1253 errmsg = "Bytes 4-15"; 1254 } 1255 if (errmsg) { 1256 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 1257 NO_CLEANUP; 1258 return 1; 1259 } 1260 iscsi_trace(TRACE_ISCSI_ARGS, "AHSLength: %u\n", cmd->AHSlength); 1261 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 1262 iscsi_trace(TRACE_ISCSI_ARGS, "Tag: %#x\n", cmd->tag); 1263 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 1264 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", cmd->StatSN); 1265 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", cmd->ExpCmdSN); 1266 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", cmd->MaxCmdSN); 1267 iscsi_trace(TRACE_ISCSI_ARGS, "R2TSN: %u\n", cmd->R2TSN); 1268 iscsi_trace(TRACE_ISCSI_ARGS, "Offset: %u\n", cmd->offset); 1269 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 1270 return 0; 1271} 1272 1273/* 1274 * SCSI Write Data 1275 */ 1276 1277int 1278iscsi_write_data_encap(uint8_t *header, iscsi_write_data_t * cmd) 1279{ 1280 1281 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %u\n", cmd->final); 1282 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", cmd->length); 1283 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 1284 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->tag); 1285 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 1286 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 1287 iscsi_trace(TRACE_ISCSI_ARGS, "DataSN: %u\n", cmd->DataSN); 1288 iscsi_trace(TRACE_ISCSI_ARGS, "Buffer Offset: %u\n", cmd->offset); 1289 1290 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 1291 header[0] = 0x00 | ISCSI_WRITE_DATA; /* Opcode */ 1292 if (cmd->final) { 1293 header[1] |= 0x80; /* Final */ 1294 } 1295 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(cmd->length); /* Length */ 1296 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->lun); /* LUN */ 1297 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->tag); /* Tag */ 1298 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(cmd->transfer_tag); /* Transfer Tag */ 1299 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpStatSN); /* ExpStatSN */ 1300 *((uint32_t *) (void *) (header + 36)) = ISCSI_HTONL(cmd->DataSN); /* DataSN */ 1301 *((uint32_t *) (void *) (header + 40)) = ISCSI_HTONL(cmd->offset); /* Buffer Offset */ 1302 1303 return 0; 1304} 1305 1306int 1307iscsi_write_data_decap(uint8_t *header, iscsi_write_data_t * cmd) 1308{ 1309 const char *errmsg; 1310 uint8_t zeros[16]; 1311 1312 if (ISCSI_OPCODE(header) != ISCSI_WRITE_DATA) { 1313 iscsi_err(__FILE__, __LINE__, "Opcode"); 1314 return 1; 1315 } 1316 cmd->final = (header[1] & 0x80) ? 1 : 0; /* Final */ 1317 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 1318 cmd->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 1319 cmd->tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Tag */ 1320 cmd->transfer_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); /* Transfer Tag */ 1321 cmd->ExpStatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpStatSN */ 1322 cmd->DataSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 36))); /* DataSN */ 1323 cmd->offset = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 40))); /* Buffer Offset */ 1324 1325 errmsg = NULL; 1326 (void) memset(zeros, 0x0, sizeof(zeros)); 1327 if ((header[1] & 0x7f) != 0x0) { 1328 errmsg = "Byte 1, bits 1-7"; 1329 } else if (header[2] != 0) { 1330 errmsg = "Byte 2"; 1331 } else if (header[3] != 0) { 1332 errmsg = "Byte 3"; 1333 } else if (header[4] != 0) { 1334 errmsg = "Byte 4"; 1335 } else if (memcmp(header + 24, zeros, 4) != 0) { 1336 errmsg = "Bytes 24-27"; 1337 } else if (memcmp(header + 32, zeros, 4) != 0) { 1338 errmsg = "Bytes 32-35"; 1339 } else if (memcmp(header + 44, zeros, 4) != 0) { 1340 errmsg = "Bytes 44-47"; 1341 } 1342 if (errmsg) { 1343 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 1344 NO_CLEANUP; 1345 return 1; 1346 } 1347 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %u\n", cmd->final); 1348 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", cmd->length); 1349 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 1350 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->tag); 1351 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 1352 iscsi_trace(TRACE_ISCSI_ARGS, "ExpStatSN: %u\n", cmd->ExpStatSN); 1353 iscsi_trace(TRACE_ISCSI_ARGS, "DataSN: %u\n", cmd->DataSN); 1354 iscsi_trace(TRACE_ISCSI_ARGS, "Buffer Offset: %u\n", cmd->offset); 1355 1356 return 0; 1357} 1358 1359/* 1360 * SCSI Read Data 1361 */ 1362 1363int 1364iscsi_read_data_encap(uint8_t *header, iscsi_read_data_t * cmd) 1365{ 1366 1367 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %d\n", cmd->final); 1368 iscsi_trace(TRACE_ISCSI_ARGS, "Acknowledge: %d\n", cmd->ack); 1369 iscsi_trace(TRACE_ISCSI_ARGS, "Overflow: %d\n", cmd->overflow); 1370 iscsi_trace(TRACE_ISCSI_ARGS, "Underflow: %d\n", cmd->underflow); 1371 iscsi_trace(TRACE_ISCSI_ARGS, "S_bit: %d\n", cmd->S_bit); 1372 iscsi_trace(TRACE_ISCSI_ARGS, "Status: %u\n", cmd->status); 1373 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", cmd->length); 1374 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", cmd->lun); 1375 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->task_tag); 1376 iscsi_trace(TRACE_ISCSI_ARGS, "Transfer Tag: %#x\n", cmd->transfer_tag); 1377 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", cmd->StatSN); 1378 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", cmd->ExpCmdSN); 1379 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", cmd->MaxCmdSN); 1380 iscsi_trace(TRACE_ISCSI_ARGS, "DataSN: %u\n", cmd->DataSN); 1381 iscsi_trace(TRACE_ISCSI_ARGS, "Buffer Offset %u\n", cmd->offset); 1382 iscsi_trace(TRACE_ISCSI_ARGS, "Residual Count: %u\n", cmd->res_count); 1383 1384 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 1385 1386 header[0] = 0x00 | ISCSI_READ_DATA; /* Opcode */ 1387 if (cmd->final) { 1388 header[1] |= 0x80; /* Final */ 1389 } 1390 if (cmd->ack) { 1391 header[1] |= 0x40; /* ACK */ 1392 } 1393 if (cmd->overflow) { 1394 header[1] |= 0x04; /* Overflow */ 1395 } 1396 if (cmd->underflow) { 1397 header[1] |= 0x02; /* Underflow */ 1398 } 1399 if (cmd->S_bit) { 1400 header[1] |= 0x01; /* S Bit */ 1401 } 1402 if (cmd->S_bit) { 1403 header[3] = cmd->status; /* Status */ 1404 } 1405 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(cmd->length); /* Length */ 1406 *((uint64_t *) (void *) (header + 8)) = ISCSI_HTONLL(cmd->lun); /* LUN */ 1407 *((uint32_t *) (void *) (header + 16)) = ISCSI_HTONL(cmd->task_tag); /* Task Tag */ 1408 *((uint32_t *) (void *) (header + 20)) = ISCSI_HTONL(cmd->transfer_tag); /* Transfer Tag */ 1409 if (cmd->S_bit) { 1410 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->StatSN); /* StatSN */ 1411 } 1412 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpCmdSN); /* ExpCmdSN */ 1413 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(cmd->MaxCmdSN); /* MaxCmdSN */ 1414 *((uint32_t *) (void *) (header + 36)) = ISCSI_HTONL(cmd->DataSN); /* DataSN */ 1415 *((uint32_t *) (void *) (header + 40)) = ISCSI_HTONL(cmd->offset); /* Buffer Offset */ 1416 if (cmd->S_bit) { 1417 *((uint32_t *) (void *) (header + 44)) = ISCSI_HTONL(cmd->res_count); /* Residual Count */ 1418 } 1419 1420 return 0; 1421} 1422 1423int 1424iscsi_read_data_decap(uint8_t *header, iscsi_read_data_t * cmd) 1425{ 1426 const char *errmsg; 1427 uint8_t zeros[16]; 1428 1429 if (ISCSI_OPCODE(header) != ISCSI_READ_DATA) { 1430 iscsi_err(__FILE__, __LINE__, "Opcode"); 1431 return 1; 1432 } 1433 cmd->final = (header[1] & 0x80) ? 1 : 0; /* Final */ 1434 cmd->ack = (header[1] & 0x40) ? 1 : 0; /* Acknowledge */ 1435 cmd->overflow = (header[1] & 0x04) ? 1 : 0; /* Overflow */ 1436 cmd->underflow = (header[1] & 0x02) ? 1 : 0; /* Underflow */ 1437 cmd->S_bit = (header[1] & 0x01) ? 1 : 0; /* S Bit */ 1438 cmd->status = header[3];/* Status */ 1439 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 1440 cmd->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 1441 cmd->task_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 16))); /* Task Tag */ 1442 cmd->transfer_tag = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 20))); /* Transfer Tag */ 1443 cmd->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* StatSN */ 1444 cmd->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpCmdSN */ 1445 cmd->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); /* MaxCmdSN */ 1446 cmd->DataSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 36))); /* DataSN */ 1447 cmd->offset = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 40))); /* Buffer Offset */ 1448 cmd->res_count = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 44))); /* Residual Count */ 1449 errmsg = NULL; 1450 (void) memset(zeros, 0x0, sizeof(zeros)); 1451 if ((header[0] & 0xc0) != 0x0) { 1452 errmsg = "Byte 0, bits 0-1"; 1453 } else if ((header[1] & 0x38) != 0x0) { 1454 errmsg = "Byte 1, bits 2-4"; 1455 } else if (header[2] != 0) { 1456 errmsg = "Byte 2"; 1457 } else if (header[4] != 0) { 1458 errmsg = "Byte 4"; 1459 } else if (memcmp(header + 8, zeros, 8) != 0) { 1460 errmsg = "Bytes 8-15"; 1461 } else if (!cmd->underflow && memcmp(header + 44, zeros, 4) != 0) { 1462 errmsg = "Bytes 44-47"; 1463 } 1464 if (errmsg) { 1465 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 1466 NO_CLEANUP; 1467 return 1; 1468 } 1469 iscsi_trace(TRACE_ISCSI_ARGS, "Final: %d\n", cmd->final); 1470 iscsi_trace(TRACE_ISCSI_ARGS, "Acknowledge: %d\n", cmd->ack); 1471 iscsi_trace(TRACE_ISCSI_ARGS, "Overflow: %d\n", cmd->overflow); 1472 iscsi_trace(TRACE_ISCSI_ARGS, "Underflow: %d\n", cmd->underflow); 1473 iscsi_trace(TRACE_ISCSI_ARGS, "S_bit: %d\n", cmd->S_bit); 1474 iscsi_trace(TRACE_ISCSI_ARGS, "Status: %u\n", cmd->status); 1475 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", cmd->length); 1476 iscsi_trace(TRACE_ISCSI_ARGS, "Task Tag: %#x\n", cmd->task_tag); 1477 iscsi_trace(TRACE_ISCSI_ARGS, "Residual Count: %u\n", cmd->res_count); 1478 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", cmd->StatSN); 1479 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", cmd->ExpCmdSN); 1480 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", cmd->MaxCmdSN); 1481 iscsi_trace(TRACE_ISCSI_ARGS, "DataSN: %u\n", cmd->DataSN); 1482 iscsi_trace(TRACE_ISCSI_ARGS, "Buffer Offset %u\n", cmd->offset); 1483 return 0; 1484} 1485 1486/* 1487 * Reject 1488 */ 1489 1490int 1491iscsi_reject_encap(uint8_t *header, iscsi_reject_t * cmd) 1492{ 1493 1494 iscsi_trace(TRACE_ISCSI_ARGS, "Reason: %u\n", cmd->reason); 1495 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 1496 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", cmd->StatSN); 1497 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", cmd->ExpCmdSN); 1498 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", cmd->MaxCmdSN); 1499 iscsi_trace(TRACE_ISCSI_ARGS, "DataSN: %u\n", cmd->DataSN); 1500 1501 (void) memset(header, 0x0, ISCSI_HEADER_LEN); 1502 1503 header[0] |= 0x00 | ISCSI_REJECT; /* Opcode */ 1504 header[1] |= 0x80; 1505 header[2] = cmd->reason;/* Reason */ 1506 *((uint32_t *) (void *) (header + 4)) = ISCSI_HTONL(cmd->length); /* Length */ 1507 *((uint32_t *) (void *) (header + 24)) = ISCSI_HTONL(cmd->StatSN); /* StatSN */ 1508 *((uint32_t *) (void *) (header + 28)) = ISCSI_HTONL(cmd->ExpCmdSN); /* ExpCmdSN */ 1509 *((uint32_t *) (void *) (header + 32)) = ISCSI_HTONL(cmd->MaxCmdSN); /* MaxCmdSN */ 1510 *((uint32_t *) (void *) (header + 36)) = ISCSI_HTONL(cmd->DataSN); /* DataSN */ 1511 1512 return 0; 1513} 1514 1515int 1516iscsi_reject_decap(uint8_t *header, iscsi_reject_t * cmd) 1517{ 1518 const char *errmsg; 1519 uint8_t zeros[8]; 1520 1521 if (ISCSI_OPCODE(header) != ISCSI_REJECT) { 1522 iscsi_err(__FILE__, __LINE__, "Opcode"); 1523 return 1; 1524 } 1525 cmd->reason = header[2];/* Reason */ 1526 cmd->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 1527 cmd->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* StatSN */ 1528 cmd->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpCmdSN */ 1529 cmd->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); /* MaxCmdSN */ 1530 cmd->DataSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 36))); /* DataSN */ 1531 1532 errmsg = NULL; 1533 (void) memset(zeros, 0x0, sizeof(zeros)); 1534 if ((header[0] & 0xc0) != 0x0) { 1535 errmsg = "Byte 0, bits 0-1"; 1536 } else if ((header[1] & 0x7f) != 0x0) { 1537 errmsg = "Byte 1, bits 0-7"; 1538 } else if (header[3] != 0) { 1539 errmsg = "Byte 3"; 1540 } else if (header[4] != 0) { 1541 errmsg = "Byte 4"; 1542 } else if (memcmp(header + 8, zeros, 8) != 0) { 1543 errmsg = "Bytes 8-15"; 1544 } else if (memcmp(header + 20, zeros, 4) != 0) { 1545 errmsg = "Bytes 20-23"; 1546 } else if (memcmp(header + 40, zeros, 8) != 0) { 1547 errmsg = "Bytes 40-47"; 1548 } 1549 if (errmsg) { 1550 iscsi_err(__FILE__, __LINE__, "%s", errmsg); 1551 NO_CLEANUP; 1552 return 1; 1553 } 1554 iscsi_trace(TRACE_ISCSI_ARGS, "Reason: %u\n", cmd->reason); 1555 iscsi_trace(TRACE_ISCSI_ARGS, "Length: %u\n", cmd->length); 1556 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", cmd->StatSN); 1557 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", cmd->ExpCmdSN); 1558 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", cmd->MaxCmdSN); 1559 iscsi_trace(TRACE_ISCSI_ARGS, "DataSN: %u\n", cmd->DataSN); 1560 return 0; 1561} 1562 1563int 1564iscsi_amsg_decap(uint8_t *header, iscsi_async_msg_t * msg) 1565{ 1566 1567 if (ISCSI_OPCODE(header) != ISCSI_ASYNC) { 1568 iscsi_err(__FILE__, __LINE__, "Opcode"); 1569 return 1; 1570 } 1571 msg->AHSlength = header[4]; /* TotalAHSLength */ 1572 msg->length = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 4))); /* Length */ 1573 msg->lun = ISCSI_NTOHLL(*((uint64_t *) (void *) (header + 8))); /* LUN */ 1574 msg->StatSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 24))); /* StatSN */ 1575 msg->ExpCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 28))); /* ExpCmdSN */ 1576 msg->MaxCmdSN = ISCSI_NTOHL(*((uint32_t *) (void *) (header + 32))); /* MaxCmdSN */ 1577 msg->AsyncEvent = header[36]; /* Async Event */ 1578 msg->AsyncVCode = header[37]; /* Async Vendor Code */ 1579 1580 iscsi_trace(TRACE_ISCSI_ARGS, "TotalAHSLength: %u\n", msg->AHSlength); 1581 iscsi_trace(TRACE_ISCSI_ARGS, "DataSegmentLength: %u\n", msg->length); 1582 iscsi_trace(TRACE_ISCSI_ARGS, "LUN: %" PRIu64 "\n", msg->lun); 1583 iscsi_trace(TRACE_ISCSI_ARGS, "StatSN: %u\n", msg->StatSN); 1584 iscsi_trace(TRACE_ISCSI_ARGS, "ExpCmdSN: %u\n", msg->ExpCmdSN); 1585 iscsi_trace(TRACE_ISCSI_ARGS, "MaxCmdSN: %u\n", msg->MaxCmdSN); 1586 iscsi_trace(TRACE_ISCSI_ARGS, "AsyncEvent: %u\n", msg->AsyncEvent); 1587 iscsi_trace(TRACE_ISCSI_ARGS, "AsyncVCode: %u\n", msg->AsyncVCode); 1588 1589 return 0; 1590} 1591