xref: /netbsd-src/external/bsd/iscsi/dist/src/lib/protocol.c (revision 3305a62508675f3dcf4d084928709cf55fc1986d)
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
iscsi_task_cmd_encap(uint8_t * header,iscsi_task_cmd_t * cmd)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
iscsi_task_cmd_decap(uint8_t * header,iscsi_task_cmd_t * cmd)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
iscsi_task_rsp_encap(uint8_t * header,iscsi_task_rsp_t * rsp)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
iscsi_task_rsp_decap(uint8_t * header,iscsi_task_rsp_t * rsp)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
iscsi_nop_out_encap(uint8_t * header,iscsi_nop_out_args_t * cmd)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
iscsi_nop_out_decap(uint8_t * header,iscsi_nop_out_args_t * cmd)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
iscsi_nop_in_encap(uint8_t * header,iscsi_nop_in_args_t * cmd)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
iscsi_nop_in_decap(uint8_t * header,iscsi_nop_in_args_t * cmd)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
iscsi_text_cmd_encap(uint8_t * header,iscsi_text_cmd_args_t * cmd)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
iscsi_text_cmd_decap(uint8_t * header,iscsi_text_cmd_args_t * cmd)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
iscsi_text_rsp_encap(uint8_t * header,iscsi_text_rsp_args_t * rsp)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
iscsi_text_rsp_decap(uint8_t * header,iscsi_text_rsp_args_t * rsp)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
iscsi_login_cmd_encap(uint8_t * header,iscsi_login_cmd_args_t * cmd)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
iscsi_login_cmd_decap(uint8_t * header,iscsi_login_cmd_args_t * cmd)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
iscsi_login_rsp_encap(uint8_t * header,iscsi_login_rsp_args_t * rsp)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
iscsi_login_rsp_decap(uint8_t * header,iscsi_login_rsp_args_t * rsp)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
iscsi_logout_cmd_encap(uint8_t * header,iscsi_logout_cmd_args_t * cmd)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
iscsi_logout_cmd_decap(uint8_t * header,iscsi_logout_cmd_args_t * cmd)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
iscsi_logout_rsp_encap(uint8_t * header,iscsi_logout_rsp_args_t * rsp)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
iscsi_logout_rsp_decap(uint8_t * header,iscsi_logout_rsp_args_t * rsp)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
iscsi_scsi_cmd_encap(uint8_t * header,iscsi_scsi_cmd_args_t * cmd)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
iscsi_scsi_cmd_decap(uint8_t * header,iscsi_scsi_cmd_args_t * cmd)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
iscsi_scsi_rsp_encap(uint8_t * header,iscsi_scsi_rsp_t * rsp)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
iscsi_scsi_rsp_decap(uint8_t * header,iscsi_scsi_rsp_t * rsp)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
iscsi_r2t_encap(uint8_t * header,iscsi_r2t_t * cmd)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
iscsi_r2t_decap(uint8_t * header,iscsi_r2t_t * cmd)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
iscsi_write_data_encap(uint8_t * header,iscsi_write_data_t * cmd)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
iscsi_write_data_decap(uint8_t * header,iscsi_write_data_t * cmd)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
iscsi_read_data_encap(uint8_t * header,iscsi_read_data_t * cmd)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
iscsi_read_data_decap(uint8_t * header,iscsi_read_data_t * cmd)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
iscsi_reject_encap(uint8_t * header,iscsi_reject_t * cmd)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
iscsi_reject_decap(uint8_t * header,iscsi_reject_t * cmd)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
iscsi_amsg_decap(uint8_t * header,iscsi_async_msg_t * msg)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