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