xref: /netbsd-src/external/bsd/iscsi/dist/src/lib/protocol.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
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 
71 int
72 iscsi_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 
102 int
103 iscsi_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__, 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 
157 int
158 iscsi_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 
183 int
184 iscsi_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__, 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 
230 int
231 iscsi_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 
262 int
263 iscsi_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__, 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 
308 int
309 iscsi_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 
337 int
338 iscsi_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__, 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 
385 int
386 iscsi_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 
423 int
424 iscsi_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__, 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 
476 int
477 iscsi_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 
511 int
512 iscsi_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__, 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 
564 int
565 iscsi_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 
610 int
611 iscsi_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__, 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 
679 int
680 iscsi_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 
729 int
730 iscsi_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__, errmsg);
787 		NO_CLEANUP;
788 		return 1;
789 	}
790 	return 0;
791 }
792 
793 /*
794  * Logout Command
795  */
796 
797 int
798 iscsi_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 
823 int
824 iscsi_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__, errmsg);
866 		NO_CLEANUP;
867 		return 1;
868 	}
869 	return 0;
870 }
871 
872 /*
873  * Logout Response
874  */
875 
876 int
877 iscsi_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 
906 int
907 iscsi_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__, 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 
963 int
964 iscsi_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 
1010 int
1011 iscsi_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__, 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 
1069 int
1070 iscsi_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 
1119 int
1120 iscsi_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__, 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 
1187 int
1188 iscsi_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 
1222 int
1223 iscsi_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__, 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 
1276 int
1277 iscsi_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 
1305 int
1306 iscsi_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__, 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 
1362 int
1363 iscsi_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 
1422 int
1423 iscsi_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 (memcmp(header + 44, zeros, 4) != 0) {
1461 		errmsg = "Bytes 44-47";
1462 	}
1463 	if (errmsg) {
1464 		iscsi_err(__FILE__, __LINE__, 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 
1489 int
1490 iscsi_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 
1514 int
1515 iscsi_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__, 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 
1562 int
1563 iscsi_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