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