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