Home | History | Annotate | Line # | Download | only in lib
      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 
     72 int
     73 iscsi_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 
    103 int
    104 iscsi_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 
    158 int
    159 iscsi_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 
    184 int
    185 iscsi_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 
    231 int
    232 iscsi_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 
    263 int
    264 iscsi_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 
    309 int
    310 iscsi_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 
    338 int
    339 iscsi_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 
    386 int
    387 iscsi_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 
    424 int
    425 iscsi_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 
    477 int
    478 iscsi_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 
    512 int
    513 iscsi_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 
    565 int
    566 iscsi_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 
    611 int
    612 iscsi_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 
    680 int
    681 iscsi_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 
    730 int
    731 iscsi_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 
    798 int
    799 iscsi_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 
    824 int
    825 iscsi_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 
    877 int
    878 iscsi_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 
    907 int
    908 iscsi_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 
    964 int
    965 iscsi_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 
   1011 int
   1012 iscsi_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 
   1070 int
   1071 iscsi_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 
   1120 int
   1121 iscsi_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 
   1188 int
   1189 iscsi_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 
   1223 int
   1224 iscsi_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 
   1277 int
   1278 iscsi_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 
   1306 int
   1307 iscsi_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 
   1363 int
   1364 iscsi_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 
   1423 int
   1424 iscsi_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 
   1490 int
   1491 iscsi_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 
   1515 int
   1516 iscsi_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 
   1563 int
   1564 iscsi_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