Wed Oct 8 14:58:57 2008 UTC ()
memset to zero the entire nop_in structure.  Fixes PR#39688 by
Henning Petersen.  Thanks!


(oster)
diff -r1.23 -r1.24 src/dist/iscsi/src/target.c

cvs diff -r1.23 -r1.24 src/dist/iscsi/src/Attic/target.c (switch to unified diff)

--- src/dist/iscsi/src/Attic/target.c 2008/02/07 19:09:02 1.23
+++ src/dist/iscsi/src/Attic/target.c 2008/10/08 14:58:57 1.24
@@ -1,1551 +1,1551 @@ @@ -1,1551 +1,1551 @@
1/* 1/*
2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or 2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
3 * using the software you agree to this license. If you do not agree to this license, do not download, install, 3 * using the software you agree to this license. If you do not agree to this license, do not download, install,
4 * copy or use the software. 4 * copy or use the software.
5 * 5 *
6 * Intel License Agreement 6 * Intel License Agreement
7 * 7 *
8 * Copyright (c) 2000, Intel Corporation 8 * Copyright (c) 2000, Intel Corporation
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that 11 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
12 * the following conditions are met: 12 * the following conditions are met:
13 * 13 *
14 * -Redistributions of source code must retain the above copyright notice, this list of conditions and the 14 * -Redistributions of source code must retain the above copyright notice, this list of conditions and the
15 * following disclaimer. 15 * following disclaimer.
16 * 16 *
17 * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 17 * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
18 * following disclaimer in the documentation and/or other materials provided with the distribution. 18 * following disclaimer in the documentation and/or other materials provided with the distribution.
19 * 19 *
20 * -The name of Intel Corporation may not be used to endorse or promote products derived from this software 20 * -The name of Intel Corporation may not be used to endorse or promote products derived from this software
21 * without specific prior written permission. 21 * without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32#include "config.h" 32#include "config.h"
33 33
34#include <sys/types.h> 34#include <sys/types.h>
35#include <sys/param.h> 35#include <sys/param.h>
36 36
37#include <stdlib.h> 37#include <stdlib.h>
38 38
39#ifdef HAVE_NETINET_TCP_H 39#ifdef HAVE_NETINET_TCP_H
40#include <netinet/tcp.h> 40#include <netinet/tcp.h>
41#endif 41#endif
42 42
43#ifdef HAVE_SYS_UIO_H 43#ifdef HAVE_SYS_UIO_H
44#include <sys/uio.h> 44#include <sys/uio.h>
45#endif 45#endif
46 46
47#ifdef HAVE_SYS_SOCKET_H 47#ifdef HAVE_SYS_SOCKET_H
48#include <sys/socket.h> 48#include <sys/socket.h>
49#endif 49#endif
50 50
51#ifdef HAVE_NETINET_IN_H 51#ifdef HAVE_NETINET_IN_H
52#include <netinet/in.h> 52#include <netinet/in.h>
53#endif 53#endif
54 54
55#ifdef HAVE_STRING_H 55#ifdef HAVE_STRING_H
56#include <string.h> 56#include <string.h>
57#endif 57#endif
58 58
59#ifdef HAVE_SIGNAL_H 59#ifdef HAVE_SIGNAL_H
60#include <signal.h> 60#include <signal.h>
61#endif 61#endif
62 62
63#ifdef HAVE_SYSLOG_H 63#ifdef HAVE_SYSLOG_H
64#include <syslog.h> 64#include <syslog.h>
65#endif 65#endif
66 66
67#ifdef HAVE_ERRNO_H 67#ifdef HAVE_ERRNO_H
68#include <errno.h> 68#include <errno.h>
69#endif 69#endif
70 70
71#ifdef HAVE_NETDB_H 71#ifdef HAVE_NETDB_H
72#include <netdb.h> 72#include <netdb.h>
73#endif 73#endif
74 74
75#ifdef HAVE_ARPA_INET_H 75#ifdef HAVE_ARPA_INET_H
76#include <arpa/inet.h> 76#include <arpa/inet.h>
77#endif 77#endif
78 78
79#ifdef HAVE_INTTYPES_H 79#ifdef HAVE_INTTYPES_H
80#include <inttypes.h> 80#include <inttypes.h>
81#endif 81#endif
82  82
83 83
84#include "iscsi.h" 84#include "iscsi.h"
85#include "target.h" 85#include "target.h"
86#include "device.h" 86#include "device.h"
87#include "iscsi-md5.h" 87#include "iscsi-md5.h"
88#include "parameters.h" 88#include "parameters.h"
89 89
90enum { 90enum {
91 TARGET_SHUT_DOWN = 0, 91 TARGET_SHUT_DOWN = 0,
92 TARGET_INITIALIZING = 1, 92 TARGET_INITIALIZING = 1,
93 TARGET_INITIALIZED = 2, 93 TARGET_INITIALIZED = 2,
94 TARGET_SHUTTING_DOWN = 3 94 TARGET_SHUTTING_DOWN = 3
95}; 95};
96 96
97/*********** 97/***********
98 * Private * 98 * Private *
99 ***********/ 99 ***********/
100 100
101static target_session_t *g_session; 101static target_session_t *g_session;
102static iscsi_queue_t g_session_q; 102static iscsi_queue_t g_session_q;
103static iscsi_mutex_t g_session_q_mutex; 103static iscsi_mutex_t g_session_q_mutex;
104 104
105/********************* 105/*********************
106 * Private Functions * 106 * Private Functions *
107 *********************/ 107 *********************/
108 108
109static char * 109static char *
110get_iqn(target_session_t *sess, int t, char *buf, size_t size) 110get_iqn(target_session_t *sess, int t, char *buf, size_t size)
111{ 111{
112 if (sess->globals->tv->v[t].iqn != NULL) { 112 if (sess->globals->tv->v[t].iqn != NULL) {
113 (void) strlcpy(buf, sess->globals->tv->v[t].iqn, size); 113 (void) strlcpy(buf, sess->globals->tv->v[t].iqn, size);
114 return buf; 114 return buf;
115 } 115 }
116 (void) snprintf(buf, size, "%s:%s", sess->globals->targetname, 116 (void) snprintf(buf, size, "%s:%s", sess->globals->targetname,
117 sess->globals->tv->v[t].target); 117 sess->globals->tv->v[t].target);
118 return buf; 118 return buf;
119} 119}
120 120
121static int  121static int
122reject_t(target_session_t * sess, uint8_t *header, uint8_t reason) 122reject_t(target_session_t * sess, uint8_t *header, uint8_t reason)
123{ 123{
124 iscsi_reject_t reject; 124 iscsi_reject_t reject;
125 uint8_t rsp_header[ISCSI_HEADER_LEN]; 125 uint8_t rsp_header[ISCSI_HEADER_LEN];
126 126
127 iscsi_trace_error(__FILE__, __LINE__, "reject %x\n", reason); 127 iscsi_trace_error(__FILE__, __LINE__, "reject %x\n", reason);
128 reject.reason = reason; 128 reject.reason = reason;
129 reject.length = ISCSI_HEADER_LEN; 129 reject.length = ISCSI_HEADER_LEN;
130 reject.StatSN = ++(sess->StatSN); 130 reject.StatSN = ++(sess->StatSN);
131 reject.ExpCmdSN = sess->ExpCmdSN; 131 reject.ExpCmdSN = sess->ExpCmdSN;
132 reject.MaxCmdSN = sess->MaxCmdSN; 132 reject.MaxCmdSN = sess->MaxCmdSN;
133 reject.DataSN = 0; /* SNACK not yet implemented */ 133 reject.DataSN = 0; /* SNACK not yet implemented */
134 134
135 if (iscsi_reject_encap(rsp_header, &reject) != 0) { 135 if (iscsi_reject_encap(rsp_header, &reject) != 0) {
136 iscsi_trace_error(__FILE__, __LINE__, "iscsi_reject_encap() failed\n"); 136 iscsi_trace_error(__FILE__, __LINE__, "iscsi_reject_encap() failed\n");
137 return -1; 137 return -1;
138 } 138 }
139 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN, 139 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN,
140 header, ISCSI_HEADER_LEN, 0) != 2 * ISCSI_HEADER_LEN) { 140 header, ISCSI_HEADER_LEN, 0) != 2 * ISCSI_HEADER_LEN) {
141 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 141 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
142 return -1; 142 return -1;
143 } 143 }
144 return 0; 144 return 0;
145} 145}
146 146
147static int  147static int
148scsi_command_t(target_session_t *sess, uint8_t *header) 148scsi_command_t(target_session_t *sess, uint8_t *header)
149{ 149{
150 target_cmd_t cmd; 150 target_cmd_t cmd;
151 iscsi_scsi_cmd_args_t scsi_cmd; 151 iscsi_scsi_cmd_args_t scsi_cmd;
152 iscsi_scsi_rsp_t scsi_rsp; 152 iscsi_scsi_rsp_t scsi_rsp;
153 iscsi_read_data_t data; 153 iscsi_read_data_t data;
154 uint8_t rsp_header[ISCSI_HEADER_LEN]; 154 uint8_t rsp_header[ISCSI_HEADER_LEN];
155 uint32_t DataSN = 0; 155 uint32_t DataSN = 0;
156 156
157 (void) memset(&scsi_cmd, 0x0, sizeof(scsi_cmd)); 157 (void) memset(&scsi_cmd, 0x0, sizeof(scsi_cmd));
158 if (iscsi_scsi_cmd_decap(header, &scsi_cmd) != 0) { 158 if (iscsi_scsi_cmd_decap(header, &scsi_cmd) != 0) {
159 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_cmd_decap() failed\n"); 159 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_cmd_decap() failed\n");
160 return -1; 160 return -1;
161 } 161 }
162 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: SCSI Command (CmdSN %u, op %#x)\n", sess->id, scsi_cmd.CmdSN, scsi_cmd.cdb[0]); 162 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: SCSI Command (CmdSN %u, op %#x)\n", sess->id, scsi_cmd.CmdSN, scsi_cmd.cdb[0]);
163 163
164 /* For Non-immediate commands, the CmdSN should be between ExpCmdSN */ 164 /* For Non-immediate commands, the CmdSN should be between ExpCmdSN */
165 /* and MaxCmdSN, inclusive of both. Otherwise, ignore the command */ 165 /* and MaxCmdSN, inclusive of both. Otherwise, ignore the command */
166 if ((!scsi_cmd.immediate) && 166 if ((!scsi_cmd.immediate) &&
167 ((scsi_cmd.CmdSN < sess->ExpCmdSN) || (scsi_cmd.CmdSN > sess->MaxCmdSN))) { 167 ((scsi_cmd.CmdSN < sess->ExpCmdSN) || (scsi_cmd.CmdSN > sess->MaxCmdSN))) {
168 iscsi_trace_error(__FILE__, __LINE__, "CmdSN(%d) of SCSI Command not valid, ExpCmdSN(%d) MaxCmdSN(%d). Ignoring the command\n", scsi_cmd.CmdSN, sess->ExpCmdSN, sess->MaxCmdSN); 168 iscsi_trace_error(__FILE__, __LINE__, "CmdSN(%d) of SCSI Command not valid, ExpCmdSN(%d) MaxCmdSN(%d). Ignoring the command\n", scsi_cmd.CmdSN, sess->ExpCmdSN, sess->MaxCmdSN);
169 return 0; 169 return 0;
170 } 170 }
171 /* Arg check. */ 171 /* Arg check. */
172 scsi_cmd.attr = 0; /* Temp fix FIXME */ 172 scsi_cmd.attr = 0; /* Temp fix FIXME */
173 /* 173 /*
174 * RETURN_NOT_EQUAL("ATTR (FIX ME)", scsi_cmd.attr, 0, NO_CLEANUP, 174 * RETURN_NOT_EQUAL("ATTR (FIX ME)", scsi_cmd.attr, 0, NO_CLEANUP,
175 * -1); 175 * -1);
176 */ 176 */
177 177
178 /* Check Numbering */ 178 /* Check Numbering */
179 179
180 if (scsi_cmd.CmdSN != sess->ExpCmdSN) { 180 if (scsi_cmd.CmdSN != sess->ExpCmdSN) {
181 iscsi_trace_warning(__FILE__, __LINE__, "Expected CmdSN %d, got %d. (ignoring and resetting expectations)\n", 181 iscsi_trace_warning(__FILE__, __LINE__, "Expected CmdSN %d, got %d. (ignoring and resetting expectations)\n",
182 sess->ExpCmdSN, scsi_cmd.CmdSN); 182 sess->ExpCmdSN, scsi_cmd.CmdSN);
183 sess->ExpCmdSN = scsi_cmd.CmdSN; 183 sess->ExpCmdSN = scsi_cmd.CmdSN;
184 } 184 }
185 /* Check Transfer Lengths */ 185 /* Check Transfer Lengths */
186 if (sess->sess_params.first_burst_length 186 if (sess->sess_params.first_burst_length
187 && (scsi_cmd.length > sess->sess_params.first_burst_length)) { 187 && (scsi_cmd.length > sess->sess_params.first_burst_length)) {
188 iscsi_trace_error(__FILE__, __LINE__, "scsi_cmd.length (%u) > FirstBurstLength (%u)\n", 188 iscsi_trace_error(__FILE__, __LINE__, "scsi_cmd.length (%u) > FirstBurstLength (%u)\n",
189 scsi_cmd.length, sess->sess_params.first_burst_length); 189 scsi_cmd.length, sess->sess_params.first_burst_length);
190 scsi_cmd.status = 0x02; 190 scsi_cmd.status = 0x02;
191 scsi_cmd.length = 0; 191 scsi_cmd.length = 0;
192 goto response; 192 goto response;
193 } 193 }
194 if (sess->sess_params.max_data_seg_length 194 if (sess->sess_params.max_data_seg_length
195 && (scsi_cmd.length > sess->sess_params.max_data_seg_length)) { 195 && (scsi_cmd.length > sess->sess_params.max_data_seg_length)) {
196 iscsi_trace_error(__FILE__, __LINE__, "scsi_cmd.length (%u) > MaxRecvDataSegmentLength (%u)\n", 196 iscsi_trace_error(__FILE__, __LINE__, "scsi_cmd.length (%u) > MaxRecvDataSegmentLength (%u)\n",
197 scsi_cmd.length, sess->sess_params.max_data_seg_length); 197 scsi_cmd.length, sess->sess_params.max_data_seg_length);
198 return -1; 198 return -1;
199 } 199 }
200 200
201#if 0 201#if 0
202 /* commented out in original Intel reference code */ 202 /* commented out in original Intel reference code */
203 if (scsi_cmd.final && scsi_cmd.output) { 203 if (scsi_cmd.final && scsi_cmd.output) {
204 RETURN_NOT_EQUAL("Length", scsi_cmd.length, scsi_cmd.trans_len, NO_CLEANUP, -1); 204 RETURN_NOT_EQUAL("Length", scsi_cmd.length, scsi_cmd.trans_len, NO_CLEANUP, -1);
205 } 205 }
206#endif 206#endif
207 207
208 /* Read AHS. Need to optimize/clean this. */ 208 /* Read AHS. Need to optimize/clean this. */
209 /* We should not be calling malloc(). */ 209 /* We should not be calling malloc(). */
210 /* We need to check for properly formated AHS segments. */ 210 /* We need to check for properly formated AHS segments. */
211 211
212 if (scsi_cmd.ahs_len) { 212 if (scsi_cmd.ahs_len) {
213 uint32_t ahs_len; 213 uint32_t ahs_len;
214 uint8_t *ahs_ptr; 214 uint8_t *ahs_ptr;
215 uint8_t ahs_type; 215 uint8_t ahs_type;
216 216
217 scsi_cmd.ahs = NULL; 217 scsi_cmd.ahs = NULL;
218 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes AHS\n", scsi_cmd.ahs_len); 218 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes AHS\n", scsi_cmd.ahs_len);
219 if ((scsi_cmd.ahs = iscsi_malloc_atomic((unsigned)scsi_cmd.ahs_len)) == NULL) { 219 if ((scsi_cmd.ahs = iscsi_malloc_atomic((unsigned)scsi_cmd.ahs_len)) == NULL) {
220 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 220 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
221 return -1; 221 return -1;
222 } 222 }
223#define AHS_CLEANUP do { \ 223#define AHS_CLEANUP do { \
224 if (scsi_cmd.ahs != NULL) { \ 224 if (scsi_cmd.ahs != NULL) { \
225 iscsi_free_atomic(scsi_cmd.ahs); \ 225 iscsi_free_atomic(scsi_cmd.ahs); \
226 } \ 226 } \
227} while (/* CONSTCOND */ 0) 227} while (/* CONSTCOND */ 0)
228 if (iscsi_sock_msg(sess->sock, 0, (unsigned)scsi_cmd.ahs_len, scsi_cmd.ahs, 0) != scsi_cmd.ahs_len) { 228 if (iscsi_sock_msg(sess->sock, 0, (unsigned)scsi_cmd.ahs_len, scsi_cmd.ahs, 0) != scsi_cmd.ahs_len) {
229 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 229 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
230 AHS_CLEANUP; 230 AHS_CLEANUP;
231 return -1; 231 return -1;
232 } 232 }
233 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "read %d bytes AHS\n", scsi_cmd.ahs_len); 233 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "read %d bytes AHS\n", scsi_cmd.ahs_len);
234 for (ahs_ptr = scsi_cmd.ahs; ahs_ptr < (scsi_cmd.ahs + scsi_cmd.ahs_len - 1) ; ahs_ptr += ahs_len) { 234 for (ahs_ptr = scsi_cmd.ahs; ahs_ptr < (scsi_cmd.ahs + scsi_cmd.ahs_len - 1) ; ahs_ptr += ahs_len) {
235 ahs_len = ISCSI_NTOHS(*((uint16_t *) (void *)ahs_ptr)); 235 ahs_len = ISCSI_NTOHS(*((uint16_t *) (void *)ahs_ptr));
236 RETURN_EQUAL("AHS Length", ahs_len, 0, AHS_CLEANUP, -1); 236 RETURN_EQUAL("AHS Length", ahs_len, 0, AHS_CLEANUP, -1);
237 switch (ahs_type = *(ahs_ptr + 2)) { 237 switch (ahs_type = *(ahs_ptr + 2)) {
238 case ISCSI_AHS_EXTENDED_CDB: 238 case ISCSI_AHS_EXTENDED_CDB:
239 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Got ExtendedCDB AHS (%u bytes extra CDB)\n", ahs_len - 1); 239 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Got ExtendedCDB AHS (%u bytes extra CDB)\n", ahs_len - 1);
240 scsi_cmd.ext_cdb = ahs_ptr + 4; 240 scsi_cmd.ext_cdb = ahs_ptr + 4;
241 break; 241 break;
242 case ISCSI_AHS_BIDI_READ: 242 case ISCSI_AHS_BIDI_READ:
243 scsi_cmd.bidi_trans_len = ISCSI_NTOHL(*((uint32_t *) (void *) (ahs_ptr + 4))); 243 scsi_cmd.bidi_trans_len = ISCSI_NTOHL(*((uint32_t *) (void *) (ahs_ptr + 4)));
244 *((uint32_t *) (void *) (ahs_ptr + 4)) = scsi_cmd.bidi_trans_len; 244 *((uint32_t *) (void *) (ahs_ptr + 4)) = scsi_cmd.bidi_trans_len;
245 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Got Bidirectional Read AHS (expected read length %u)\n", scsi_cmd.bidi_trans_len); 245 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Got Bidirectional Read AHS (expected read length %u)\n", scsi_cmd.bidi_trans_len);
246 break; 246 break;
247 default: 247 default:
248 iscsi_trace_error(__FILE__, __LINE__, "unknown AHS type %x\n", ahs_type); 248 iscsi_trace_error(__FILE__, __LINE__, "unknown AHS type %x\n", ahs_type);
249 AHS_CLEANUP; 249 AHS_CLEANUP;
250 return -1; 250 return -1;
251 } 251 }
252 } 252 }
253 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "done parsing %d bytes AHS\n", scsi_cmd.ahs_len); 253 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "done parsing %d bytes AHS\n", scsi_cmd.ahs_len);
254 } else { 254 } else {
255 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no AHS to read\n"); 255 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "no AHS to read\n");
256 scsi_cmd.ahs = NULL; 256 scsi_cmd.ahs = NULL;
257 } 257 }
258 258
259 sess->ExpCmdSN++; 259 sess->ExpCmdSN++;
260 sess->MaxCmdSN++; 260 sess->MaxCmdSN++;
261 261
262 /* Execute cdb. device_command() will set scsi_cmd.input if */ 262 /* Execute cdb. device_command() will set scsi_cmd.input if */
263 /* there is input data and set the length of the input */ 263 /* there is input data and set the length of the input */
264 /* to either scsi_cmd.trans_len or scsi_cmd.bidi_trans_len, depending */ 264 /* to either scsi_cmd.trans_len or scsi_cmd.bidi_trans_len, depending */
265 /* on whether scsi_cmd.output was set. */ 265 /* on whether scsi_cmd.output was set. */
266 266
267 if (scsi_cmd.input) { 267 if (scsi_cmd.input) {
268 scsi_cmd.send_data = sess->buff; 268 scsi_cmd.send_data = sess->buff;
269 } 269 }
270 scsi_cmd.input = 0; 270 scsi_cmd.input = 0;
271 cmd.scsi_cmd = &scsi_cmd; 271 cmd.scsi_cmd = &scsi_cmd;
272 cmd.callback = NULL; 272 cmd.callback = NULL;
273 if (device_command(sess, &cmd) != 0) { 273 if (device_command(sess, &cmd) != 0) {
274 iscsi_trace_error(__FILE__, __LINE__, "device_command() failed\n"); 274 iscsi_trace_error(__FILE__, __LINE__, "device_command() failed\n");
275 AHS_CLEANUP; 275 AHS_CLEANUP;
276 return -1; 276 return -1;
277 } 277 }
278 /* Send any input data */ 278 /* Send any input data */
279 279
280 scsi_cmd.bytes_sent = 0; 280 scsi_cmd.bytes_sent = 0;
281 if (!scsi_cmd.status && scsi_cmd.input) { 281 if (!scsi_cmd.status && scsi_cmd.input) {
282 struct iovec sg_singleton; 282 struct iovec sg_singleton;
283 struct iovec *sg, *sg_orig, *sg_new = NULL; 283 struct iovec *sg, *sg_orig, *sg_new = NULL;
284 int sg_len_orig, sg_len; 284 int sg_len_orig, sg_len;
285 uint32_t offset, trans_len; 285 uint32_t offset, trans_len;
286 int fragment_flag = 0; 286 int fragment_flag = 0;
287 int offset_inc; 287 int offset_inc;
288#define SG_CLEANUP do { \ 288#define SG_CLEANUP do { \
289 if (fragment_flag) { \ 289 if (fragment_flag) { \
290 iscsi_free_atomic(sg_new); \ 290 iscsi_free_atomic(sg_new); \
291 } \ 291 } \
292} while (/* CONSTCOND */ 0) 292} while (/* CONSTCOND */ 0)
293 if (scsi_cmd.output) { 293 if (scsi_cmd.output) {
294 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %u bytes bi-directional input data\n", scsi_cmd.bidi_trans_len); 294 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %u bytes bi-directional input data\n", scsi_cmd.bidi_trans_len);
295 trans_len = scsi_cmd.bidi_trans_len; 295 trans_len = scsi_cmd.bidi_trans_len;
296 } else { 296 } else {
297 trans_len = scsi_cmd.trans_len; 297 trans_len = scsi_cmd.trans_len;
298 } 298 }
299 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %d bytes input data as separate PDUs\n", trans_len); 299 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %d bytes input data as separate PDUs\n", trans_len);
300 300
301 if (scsi_cmd.send_sg_len) { 301 if (scsi_cmd.send_sg_len) {
302 sg_orig = (struct iovec *) (void *) scsi_cmd.send_data; 302 sg_orig = (struct iovec *) (void *) scsi_cmd.send_data;
303 sg_len_orig = scsi_cmd.send_sg_len; 303 sg_len_orig = scsi_cmd.send_sg_len;
304 } else { 304 } else {
305 sg_len_orig = 1; 305 sg_len_orig = 1;
306 sg_singleton.iov_base = scsi_cmd.send_data; 306 sg_singleton.iov_base = scsi_cmd.send_data;
307 sg_singleton.iov_len = trans_len; 307 sg_singleton.iov_len = trans_len;
308 sg_orig = &sg_singleton; 308 sg_orig = &sg_singleton;
309 } 309 }
310 sg = sg_orig; 310 sg = sg_orig;
311 sg_len = sg_len_orig; 311 sg_len = sg_len_orig;
312 312
313 offset_inc = (sess->sess_params.max_data_seg_length) ? sess->sess_params.max_data_seg_length : trans_len; 313 offset_inc = (sess->sess_params.max_data_seg_length) ? sess->sess_params.max_data_seg_length : trans_len;
314 314
315 for (offset = 0; offset < trans_len; offset += offset_inc) { 315 for (offset = 0; offset < trans_len; offset += offset_inc) {
316 (void) memset(&data, 0x0, sizeof(data)); 316 (void) memset(&data, 0x0, sizeof(data));
317 317
318 data.length = (sess->sess_params.max_data_seg_length) ? MIN(trans_len - offset, sess->sess_params.max_data_seg_length) : trans_len - offset; 318 data.length = (sess->sess_params.max_data_seg_length) ? MIN(trans_len - offset, sess->sess_params.max_data_seg_length) : trans_len - offset;
319 if (data.length != trans_len) { 319 if (data.length != trans_len) {
320 if (!fragment_flag) { 320 if (!fragment_flag) {
321 if ((sg_new = iscsi_malloc_atomic(sizeof(struct iovec) * sg_len_orig)) == NULL) { 321 if ((sg_new = iscsi_malloc_atomic(sizeof(struct iovec) * sg_len_orig)) == NULL) {
322 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 322 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
323 AHS_CLEANUP; 323 AHS_CLEANUP;
324 return -1; 324 return -1;
325 } 325 }
326 fragment_flag++; 326 fragment_flag++;
327 } 327 }
328 sg = sg_new; 328 sg = sg_new;
329 sg_len = sg_len_orig; 329 sg_len = sg_len_orig;
330 (void) memcpy(sg, sg_orig, sizeof(struct iovec) * sg_len_orig); 330 (void) memcpy(sg, sg_orig, sizeof(struct iovec) * sg_len_orig);
331 if (modify_iov(&sg, &sg_len, offset, data.length) != 0) { 331 if (modify_iov(&sg, &sg_len, offset, data.length) != 0) {
332 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n"); 332 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n");
333 SG_CLEANUP; 333 SG_CLEANUP;
334 AHS_CLEANUP; 334 AHS_CLEANUP;
335 return -1; 335 return -1;
336 } 336 }
337 } 337 }
338 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending read data PDU (offset %u, len %u)\n", offset, data.length); 338 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending read data PDU (offset %u, len %u)\n", offset, data.length);
339 if (offset + data.length == trans_len) { 339 if (offset + data.length == trans_len) {
340 data.final = 1; 340 data.final = 1;
341 341
342 if (sess->UsePhaseCollapsedRead) { 342 if (sess->UsePhaseCollapsedRead) {
343 data.status = 1; 343 data.status = 1;
344 data.status = scsi_cmd.status; 344 data.status = scsi_cmd.status;
345 data.StatSN = ++(sess->StatSN); 345 data.StatSN = ++(sess->StatSN);
346 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "status %#x collapsed into last data PDU\n", data.status); 346 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "status %#x collapsed into last data PDU\n", data.status);
347 } else { 347 } else {
348 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "NOT collapsing status with last data PDU\n"); 348 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "NOT collapsing status with last data PDU\n");
349 } 349 }
350 } else if (offset + data.length > trans_len) { 350 } else if (offset + data.length > trans_len) {
351 iscsi_trace_error(__FILE__, __LINE__, "offset+data.length > trans_len??\n"); 351 iscsi_trace_error(__FILE__, __LINE__, "offset+data.length > trans_len??\n");
352 SG_CLEANUP; 352 SG_CLEANUP;
353 AHS_CLEANUP; 353 AHS_CLEANUP;
354 return -1; 354 return -1;
355 } 355 }
356 data.task_tag = scsi_cmd.tag; 356 data.task_tag = scsi_cmd.tag;
357 data.ExpCmdSN = sess->ExpCmdSN; 357 data.ExpCmdSN = sess->ExpCmdSN;
358 data.MaxCmdSN = sess->MaxCmdSN; 358 data.MaxCmdSN = sess->MaxCmdSN;
359 data.DataSN = DataSN++; 359 data.DataSN = DataSN++;
360 data.offset = offset; 360 data.offset = offset;
361 if (iscsi_read_data_encap(rsp_header, &data) != 0) { 361 if (iscsi_read_data_encap(rsp_header, &data) != 0) {
362 iscsi_trace_error(__FILE__, __LINE__, "iscsi_read_data_encap() failed\n"); 362 iscsi_trace_error(__FILE__, __LINE__, "iscsi_read_data_encap() failed\n");
363 SG_CLEANUP; 363 SG_CLEANUP;
364 AHS_CLEANUP; 364 AHS_CLEANUP;
365 return -1; 365 return -1;
366 } 366 }
367 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN, sg, data.length, sg_len) 367 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN, sg, data.length, sg_len)
368 != ISCSI_HEADER_LEN + data.length) { 368 != ISCSI_HEADER_LEN + data.length) {
369 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 369 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
370 SG_CLEANUP; 370 SG_CLEANUP;
371 AHS_CLEANUP; 371 AHS_CLEANUP;
372 return -1; 372 return -1;
373 } 373 }
374 scsi_cmd.bytes_sent += data.length; 374 scsi_cmd.bytes_sent += data.length;
375 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent read data PDU ok (offset %u, len %u)\n", data.offset, data.length); 375 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent read data PDU ok (offset %u, len %u)\n", data.offset, data.length);
376 } 376 }
377 SG_CLEANUP; 377 SG_CLEANUP;
378 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully sent %d bytes read data\n", trans_len); 378 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully sent %d bytes read data\n", trans_len);
379 } 379 }
380 /* 380 /*
381 * Send a response PDU if 381 * Send a response PDU if
382 * 382 *
383 * 1) we're not using phase collapsed input (and status was good) 383 * 1) we're not using phase collapsed input (and status was good)
384 * 2) we are using phase collapsed input, but there was no input data (e.g., TEST UNIT READY) 384 * 2) we are using phase collapsed input, but there was no input data (e.g., TEST UNIT READY)
385 * 3) command had non-zero status and possible sense data 385 * 3) command had non-zero status and possible sense data
386 */ 386 */
387response: 387response:
388 if (!sess->UsePhaseCollapsedRead || !scsi_cmd.length || scsi_cmd.status) { 388 if (!sess->UsePhaseCollapsedRead || !scsi_cmd.length || scsi_cmd.status) {
389 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending SCSI response PDU\n"); 389 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending SCSI response PDU\n");
390 (void) memset(&scsi_rsp, 0x0, sizeof(scsi_rsp)); 390 (void) memset(&scsi_rsp, 0x0, sizeof(scsi_rsp));
391 scsi_rsp.length = scsi_cmd.status ? scsi_cmd.length : 0; 391 scsi_rsp.length = scsi_cmd.status ? scsi_cmd.length : 0;
392 scsi_rsp.tag = scsi_cmd.tag; 392 scsi_rsp.tag = scsi_cmd.tag;
393 /* If r2t send, then the StatSN is already incremented */ 393 /* If r2t send, then the StatSN is already incremented */
394 if (sess->StatSN < scsi_cmd.ExpStatSN) { 394 if (sess->StatSN < scsi_cmd.ExpStatSN) {
395 ++sess->StatSN; 395 ++sess->StatSN;
396 } 396 }
397 scsi_rsp.StatSN = sess->StatSN; 397 scsi_rsp.StatSN = sess->StatSN;
398 scsi_rsp.ExpCmdSN = sess->ExpCmdSN; 398 scsi_rsp.ExpCmdSN = sess->ExpCmdSN;
399 scsi_rsp.MaxCmdSN = sess->MaxCmdSN; 399 scsi_rsp.MaxCmdSN = sess->MaxCmdSN;
400 scsi_rsp.ExpDataSN = (!scsi_cmd.status && scsi_cmd.input) ? DataSN : 0; 400 scsi_rsp.ExpDataSN = (!scsi_cmd.status && scsi_cmd.input) ? DataSN : 0;
401 scsi_rsp.response = 0x00; /* iSCSI response */ 401 scsi_rsp.response = 0x00; /* iSCSI response */
402 scsi_rsp.status = scsi_cmd.status; /* SCSI status */ 402 scsi_rsp.status = scsi_cmd.status; /* SCSI status */
403 if (iscsi_scsi_rsp_encap(rsp_header, &scsi_rsp) != 0) { 403 if (iscsi_scsi_rsp_encap(rsp_header, &scsi_rsp) != 0) {
404 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_rsp_encap() failed\n"); 404 iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_rsp_encap() failed\n");
405 AHS_CLEANUP; 405 AHS_CLEANUP;
406 return -1; 406 return -1;
407 } 407 }
408 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN, 408 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN,
409 scsi_cmd.send_data, scsi_rsp.length, scsi_cmd.send_sg_len) 409 scsi_cmd.send_data, scsi_rsp.length, scsi_cmd.send_sg_len)
410 != ISCSI_HEADER_LEN + scsi_rsp.length) { 410 != ISCSI_HEADER_LEN + scsi_rsp.length) {
411 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 411 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
412 AHS_CLEANUP; 412 AHS_CLEANUP;
413 return -1; 413 return -1;
414 } 414 }
415 /* Make sure all data was transferred */ 415 /* Make sure all data was transferred */
416 416
417 if (scsi_cmd.output) { 417 if (scsi_cmd.output) {
418 RETURN_NOT_EQUAL("scsi_cmd.bytes_recv", scsi_cmd.bytes_recv, scsi_cmd.trans_len, AHS_CLEANUP, -1); 418 RETURN_NOT_EQUAL("scsi_cmd.bytes_recv", scsi_cmd.bytes_recv, scsi_cmd.trans_len, AHS_CLEANUP, -1);
419 if (scsi_cmd.input) { 419 if (scsi_cmd.input) {
420 RETURN_NOT_EQUAL("scsi_cmd.bytes_sent", scsi_cmd.bytes_sent, scsi_cmd.bidi_trans_len, AHS_CLEANUP, -1); 420 RETURN_NOT_EQUAL("scsi_cmd.bytes_sent", scsi_cmd.bytes_sent, scsi_cmd.bidi_trans_len, AHS_CLEANUP, -1);
421 } 421 }
422 } else { 422 } else {
423 if (scsi_cmd.input) { 423 if (scsi_cmd.input) {
424 RETURN_NOT_EQUAL("scsi_cmd.bytes_sent", scsi_cmd.bytes_sent, scsi_cmd.trans_len, AHS_CLEANUP, -1); 424 RETURN_NOT_EQUAL("scsi_cmd.bytes_sent", scsi_cmd.bytes_sent, scsi_cmd.trans_len, AHS_CLEANUP, -1);
425 } 425 }
426 } 426 }
427 } 427 }
428 /* Device callback after command has completed */ 428 /* Device callback after command has completed */
429 429
430 if (cmd.callback) { 430 if (cmd.callback) {
431 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "issuing device callback\n"); 431 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "issuing device callback\n");
432 if ((*cmd.callback)(cmd.callback_arg) != 0) { 432 if ((*cmd.callback)(cmd.callback_arg) != 0) {
433 iscsi_trace_error(__FILE__, __LINE__, "device callback failed\n"); 433 iscsi_trace_error(__FILE__, __LINE__, "device callback failed\n");
434 AHS_CLEANUP; 434 AHS_CLEANUP;
435 return -1; 435 return -1;
436 } 436 }
437 } 437 }
438 AHS_CLEANUP; 438 AHS_CLEANUP;
439 return 0; 439 return 0;
440} 440}
441 441
442static int  442static int
443task_command_t(target_session_t * sess, uint8_t *header) 443task_command_t(target_session_t * sess, uint8_t *header)
444{ 444{
445 iscsi_task_cmd_t cmd; 445 iscsi_task_cmd_t cmd;
446 iscsi_task_rsp_t rsp; 446 iscsi_task_rsp_t rsp;
447 uint8_t rsp_header[ISCSI_HEADER_LEN]; 447 uint8_t rsp_header[ISCSI_HEADER_LEN];
448 448
449 /* Get & check args */ 449 /* Get & check args */
450 450
451 if (iscsi_task_cmd_decap(header, &cmd) != 0) { 451 if (iscsi_task_cmd_decap(header, &cmd) != 0) {
452 iscsi_trace_error(__FILE__, __LINE__, "iscsi_task_cmd_decap() failed\n"); 452 iscsi_trace_error(__FILE__, __LINE__, "iscsi_task_cmd_decap() failed\n");
453 return -1; 453 return -1;
454 } 454 }
455 if (cmd.CmdSN != sess->ExpCmdSN) { 455 if (cmd.CmdSN != sess->ExpCmdSN) {
456 iscsi_trace_warning(__FILE__, __LINE__, "Expected CmdSN %d, got %d. (ignoring and resetting expectations)\n", 456 iscsi_trace_warning(__FILE__, __LINE__, "Expected CmdSN %d, got %d. (ignoring and resetting expectations)\n",
457 cmd.CmdSN, sess->ExpCmdSN); 457 cmd.CmdSN, sess->ExpCmdSN);
458 sess->ExpCmdSN = cmd.CmdSN; 458 sess->ExpCmdSN = cmd.CmdSN;
459 } 459 }
460 sess->MaxCmdSN++; 460 sess->MaxCmdSN++;
461 461
462 (void) memset(&rsp, 0x0, sizeof(rsp)); 462 (void) memset(&rsp, 0x0, sizeof(rsp));
463 rsp.response = ISCSI_TASK_RSP_FUNCTION_COMPLETE; 463 rsp.response = ISCSI_TASK_RSP_FUNCTION_COMPLETE;
464 464
465 switch (cmd.function) { 465 switch (cmd.function) {
466 case ISCSI_TASK_CMD_ABORT_TASK: 466 case ISCSI_TASK_CMD_ABORT_TASK:
467 printf("ISCSI_TASK_CMD_ABORT_TASK\n"); 467 printf("ISCSI_TASK_CMD_ABORT_TASK\n");
468 break; 468 break;
469 case ISCSI_TASK_CMD_ABORT_TASK_SET: 469 case ISCSI_TASK_CMD_ABORT_TASK_SET:
470 printf("ISCSI_TASK_CMD_ABORT_TASK_SET\n"); 470 printf("ISCSI_TASK_CMD_ABORT_TASK_SET\n");
471 break; 471 break;
472 case ISCSI_TASK_CMD_CLEAR_ACA: 472 case ISCSI_TASK_CMD_CLEAR_ACA:
473 printf("ISCSI_TASK_CMD_CLEAR_ACA\n"); 473 printf("ISCSI_TASK_CMD_CLEAR_ACA\n");
474 break; 474 break;
475 case ISCSI_TASK_CMD_CLEAR_TASK_SET: 475 case ISCSI_TASK_CMD_CLEAR_TASK_SET:
476 printf("ISCSI_TASK_CMD_CLEAR_TASK_SET\n"); 476 printf("ISCSI_TASK_CMD_CLEAR_TASK_SET\n");
477 break; 477 break;
478 case ISCSI_TASK_CMD_LOGICAL_UNIT_RESET: 478 case ISCSI_TASK_CMD_LOGICAL_UNIT_RESET:
479 printf("ISCSI_TASK_CMD_LOGICAL_UNIT_RESET\n"); 479 printf("ISCSI_TASK_CMD_LOGICAL_UNIT_RESET\n");
480 break; 480 break;
481 case ISCSI_TASK_CMD_TARGET_WARM_RESET: 481 case ISCSI_TASK_CMD_TARGET_WARM_RESET:
482 printf("ISCSI_TASK_CMD_TARGET_WARM_RESET\n"); 482 printf("ISCSI_TASK_CMD_TARGET_WARM_RESET\n");
483 break; 483 break;
484 case ISCSI_TASK_CMD_TARGET_COLD_RESET: 484 case ISCSI_TASK_CMD_TARGET_COLD_RESET:
485 printf("ISCSI_TASK_CMD_TARGET_COLD_RESET\n"); 485 printf("ISCSI_TASK_CMD_TARGET_COLD_RESET\n");
486 break; 486 break;
487 case ISCSI_TASK_CMD_TARGET_REASSIGN: 487 case ISCSI_TASK_CMD_TARGET_REASSIGN:
488 printf("ISCSI_TASK_CMD_TARGET_REASSIGN\n"); 488 printf("ISCSI_TASK_CMD_TARGET_REASSIGN\n");
489 break; 489 break;
490 default: 490 default:
491 iscsi_trace_error(__FILE__, __LINE__, "Unknown task function %d\n", cmd.function); 491 iscsi_trace_error(__FILE__, __LINE__, "Unknown task function %d\n", cmd.function);
492 rsp.response = ISCSI_TASK_RSP_REJECTED; 492 rsp.response = ISCSI_TASK_RSP_REJECTED;
493 } 493 }
494 494
495 rsp.tag = cmd.tag; 495 rsp.tag = cmd.tag;
496 rsp.StatSN = ++(sess->StatSN); 496 rsp.StatSN = ++(sess->StatSN);
497 rsp.ExpCmdSN = sess->ExpCmdSN; 497 rsp.ExpCmdSN = sess->ExpCmdSN;
498 rsp.MaxCmdSN = sess->MaxCmdSN; 498 rsp.MaxCmdSN = sess->MaxCmdSN;
499 499
500 if (iscsi_task_rsp_encap(rsp_header, &rsp) != 0) { 500 if (iscsi_task_rsp_encap(rsp_header, &rsp) != 0) {
501 iscsi_trace_error(__FILE__, __LINE__, "iscsi_task_cmd_decap() failed\n"); 501 iscsi_trace_error(__FILE__, __LINE__, "iscsi_task_cmd_decap() failed\n");
502 return -1; 502 return -1;
503 } 503 }
504 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, rsp_header, 0) != ISCSI_HEADER_LEN) { 504 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, rsp_header, 0) != ISCSI_HEADER_LEN) {
505 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 505 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
506 return -1; 506 return -1;
507 507
508 } 508 }
509 return 0; 509 return 0;
510} 510}
511 511
512static int  512static int
513nop_out_t(target_session_t * sess, uint8_t *header) 513nop_out_t(target_session_t * sess, uint8_t *header)
514{ 514{
515 iscsi_nop_out_args_t nop_out; 515 iscsi_nop_out_args_t nop_out;
516 char *ping_data = NULL; 516 char *ping_data = NULL;
517 517
518 if (iscsi_nop_out_decap(header, &nop_out) != 0) { 518 if (iscsi_nop_out_decap(header, &nop_out) != 0) {
519 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_out_decap() failed\n"); 519 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_out_decap() failed\n");
520 return -1; 520 return -1;
521 } 521 }
522 if (nop_out.CmdSN != sess->ExpCmdSN) { 522 if (nop_out.CmdSN != sess->ExpCmdSN) {
523 iscsi_trace_warning(__FILE__, __LINE__, "Expected CmdSN %d, got %d. (ignoring and resetting expectations)\n", 523 iscsi_trace_warning(__FILE__, __LINE__, "Expected CmdSN %d, got %d. (ignoring and resetting expectations)\n",
524 nop_out.CmdSN, sess->ExpCmdSN); 524 nop_out.CmdSN, sess->ExpCmdSN);
525 sess->ExpCmdSN = nop_out.CmdSN; 525 sess->ExpCmdSN = nop_out.CmdSN;
526 } 526 }
527 /* TODO Clarify whether we need to update the CmdSN */ 527 /* TODO Clarify whether we need to update the CmdSN */
528 /* sess->ExpCmdSN++; */ 528 /* sess->ExpCmdSN++; */
529 /* sess->MaxCmdSN++; */ 529 /* sess->MaxCmdSN++; */
530 530
531 if (nop_out.length) { 531 if (nop_out.length) {
532 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes ping data\n", nop_out.length); 532 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes ping data\n", nop_out.length);
533 if ((ping_data = iscsi_malloc(nop_out.length)) == NULL) { 533 if ((ping_data = iscsi_malloc(nop_out.length)) == NULL) {
534 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 534 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
535 return -1; 535 return -1;
536 } 536 }
537 if (iscsi_sock_msg(sess->sock, 0, nop_out.length, ping_data, 0) != nop_out.length) { 537 if (iscsi_sock_msg(sess->sock, 0, nop_out.length, ping_data, 0) != nop_out.length) {
538 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 538 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
539 if (ping_data) { 539 if (ping_data) {
540 iscsi_free(ping_data); 540 iscsi_free(ping_data);
541 } 541 }
542 return -1; 542 return -1;
543 } 543 }
544 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully read %d bytes ping data:\n", nop_out.length); 544 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully read %d bytes ping data:\n", nop_out.length);
545 iscsi_print_buffer(ping_data, nop_out.length); 545 iscsi_print_buffer(ping_data, nop_out.length);
546 } 546 }
547 if (nop_out.tag != 0xffffffff) { 547 if (nop_out.tag != 0xffffffff) {
548 iscsi_nop_in_args_t nop_in; 548 iscsi_nop_in_args_t nop_in;
549 uint8_t rsp_header[ISCSI_HEADER_LEN]; 549 uint8_t rsp_header[ISCSI_HEADER_LEN];
550 550
551 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %d bytes ping response\n", nop_out.length); 551 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending %d bytes ping response\n", nop_out.length);
552 (void) memset(&nop_in, 0x0, sizeof(&nop_in)); 552 (void) memset(&nop_in, 0x0, sizeof(nop_in));
553 nop_in.length = nop_out.length; 553 nop_in.length = nop_out.length;
554 nop_in.lun = nop_out.lun; 554 nop_in.lun = nop_out.lun;
555 nop_in.tag = nop_out.tag; 555 nop_in.tag = nop_out.tag;
556 nop_in.transfer_tag = 0xffffffff; 556 nop_in.transfer_tag = 0xffffffff;
557 nop_in.StatSN = ++(sess->StatSN); 557 nop_in.StatSN = ++(sess->StatSN);
558 nop_in.ExpCmdSN = sess->ExpCmdSN; 558 nop_in.ExpCmdSN = sess->ExpCmdSN;
559 nop_in.MaxCmdSN = sess->MaxCmdSN; 559 nop_in.MaxCmdSN = sess->MaxCmdSN;
560 560
561 if (iscsi_nop_in_encap(rsp_header, &nop_in) != 0) { 561 if (iscsi_nop_in_encap(rsp_header, &nop_in) != 0) {
562 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_in_encap() failed\n"); 562 iscsi_trace_error(__FILE__, __LINE__, "iscsi_nop_in_encap() failed\n");
563 if (ping_data) { 563 if (ping_data) {
564 iscsi_free(ping_data); 564 iscsi_free(ping_data);
565 } 565 }
566 return -1; 566 return -1;
567 } 567 }
568 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN, 568 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN,
569 ping_data, nop_in.length, 0) != ISCSI_HEADER_LEN + nop_in.length) { 569 ping_data, nop_in.length, 0) != ISCSI_HEADER_LEN + nop_in.length) {
570 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 570 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
571 if (ping_data) { 571 if (ping_data) {
572 iscsi_free(ping_data); 572 iscsi_free(ping_data);
573 } 573 }
574 return -1; 574 return -1;
575 } 575 }
576 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully sent %d bytes ping response\n", nop_out.length); 576 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully sent %d bytes ping response\n", nop_out.length);
577 } 577 }
578 if (ping_data) { 578 if (ping_data) {
579 iscsi_free(ping_data); 579 iscsi_free(ping_data);
580 } 580 }
581 return 0; 581 return 0;
582} 582}
583 583
584/* 584/*
585 * text_command_t 585 * text_command_t
586 */ 586 */
587 587
588static int  588static int
589text_command_t(target_session_t * sess, uint8_t *header) 589text_command_t(target_session_t * sess, uint8_t *header)
590{ 590{
591 iscsi_text_cmd_args_t text_cmd; 591 iscsi_text_cmd_args_t text_cmd;
592 iscsi_text_rsp_args_t text_rsp; 592 iscsi_text_rsp_args_t text_rsp;
593 uint8_t rsp_header[ISCSI_HEADER_LEN]; 593 uint8_t rsp_header[ISCSI_HEADER_LEN];
594 char *text_in = NULL; 594 char *text_in = NULL;
595 char *text_out = NULL; 595 char *text_out = NULL;
596 unsigned len_in; 596 unsigned len_in;
597 char buf[BUFSIZ]; 597 char buf[BUFSIZ];
598 int len_out = 0; 598 int len_out = 0;
599 int i; 599 int i;
600 600
601#define TC_CLEANUP do { \ 601#define TC_CLEANUP do { \
602 if (text_in != NULL) { \ 602 if (text_in != NULL) { \
603 iscsi_free_atomic(text_in); \ 603 iscsi_free_atomic(text_in); \
604 } \ 604 } \
605 if (text_out != NULL) { \ 605 if (text_out != NULL) { \
606 iscsi_free_atomic(text_out); \ 606 iscsi_free_atomic(text_out); \
607 } \ 607 } \
608} while (/* CONSTCOND */ 0) 608} while (/* CONSTCOND */ 0)
609#define TC_ERROR { \ 609#define TC_ERROR { \
610 TC_CLEANUP; \ 610 TC_CLEANUP; \
611 return -1; \ 611 return -1; \
612} 612}
613 /* Get text args */ 613 /* Get text args */
614 614
615 if (iscsi_text_cmd_decap(header, &text_cmd) != 0) { 615 if (iscsi_text_cmd_decap(header, &text_cmd) != 0) {
616 iscsi_trace_error(__FILE__, __LINE__, "iscsi_text_cmd_decap() failed\n"); 616 iscsi_trace_error(__FILE__, __LINE__, "iscsi_text_cmd_decap() failed\n");
617 return -1; 617 return -1;
618 } 618 }
619 /* Check args & update numbering */ 619 /* Check args & update numbering */
620 RETURN_NOT_EQUAL("Continue", text_cmd.cont, 0, NO_CLEANUP, -1); 620 RETURN_NOT_EQUAL("Continue", text_cmd.cont, 0, NO_CLEANUP, -1);
621 RETURN_NOT_EQUAL("CmdSN", text_cmd.CmdSN, sess->ExpCmdSN, NO_CLEANUP, -1); 621 RETURN_NOT_EQUAL("CmdSN", text_cmd.CmdSN, sess->ExpCmdSN, NO_CLEANUP, -1);
622 622
623 sess->ExpCmdSN++; 623 sess->ExpCmdSN++;
624 sess->MaxCmdSN++; 624 sess->MaxCmdSN++;
625 625
626 if ((text_out = iscsi_malloc_atomic(2048)) == NULL) { 626 if ((text_out = iscsi_malloc_atomic(2048)) == NULL) {
627 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 627 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
628 return -1; 628 return -1;
629 } 629 }
630 /* Read text parameters */ 630 /* Read text parameters */
631 631
632 if ((len_in = text_cmd.length) != 0) { 632 if ((len_in = text_cmd.length) != 0) {
633 iscsi_parameter_t *ptr; 633 iscsi_parameter_t *ptr;
634 634
635 if ((text_in = iscsi_malloc_atomic(len_in + 1)) == NULL) { 635 if ((text_in = iscsi_malloc_atomic(len_in + 1)) == NULL) {
636 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 636 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
637 TC_CLEANUP; 637 TC_CLEANUP;
638 return -1; 638 return -1;
639 } 639 }
640 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes text parameters\n", len_in); 640 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes text parameters\n", len_in);
641 if (iscsi_sock_msg(sess->sock, 0, len_in, text_in, 0) != len_in) { 641 if (iscsi_sock_msg(sess->sock, 0, len_in, text_in, 0) != len_in) {
642 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 642 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
643 TC_CLEANUP; 643 TC_CLEANUP;
644 return -1; 644 return -1;
645 } 645 }
646 text_in[len_in] = 0x0; 646 text_in[len_in] = 0x0;
647 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text_in, (int) len_in, text_out, (int *)(void *)&len_out, 2048, 0, TC_ERROR); 647 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text_in, (int) len_in, text_out, (int *)(void *)&len_out, 2048, 0, TC_ERROR);
648 648
649 /* 649 /*
650 * Handle exceptional cases not covered by parameters.c 650 * Handle exceptional cases not covered by parameters.c
651 * (e.g., SendTargets) 651 * (e.g., SendTargets)
652 */ 652 */
653 653
654 if ((ptr = param_get(sess->params, "SendTargets")) == NULL) { 654 if ((ptr = param_get(sess->params, "SendTargets")) == NULL) {
655 iscsi_trace_error(__FILE__, __LINE__, "param_get() failed\n"); 655 iscsi_trace_error(__FILE__, __LINE__, "param_get() failed\n");
656 TC_CLEANUP; 656 TC_CLEANUP;
657 return -1; 657 return -1;
658 } 658 }
659 if (ptr->rx_offer) { 659 if (ptr->rx_offer) {
660 if (ptr->offer_rx && strcmp(ptr->offer_rx, "All") == 0 && !param_equiv(sess->params, "SessionType", "Discovery")) { 660 if (ptr->offer_rx && strcmp(ptr->offer_rx, "All") == 0 && !param_equiv(sess->params, "SessionType", "Discovery")) {
661 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Rejecting SendTargets=All in a non Discovery session\n"); 661 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Rejecting SendTargets=All in a non Discovery session\n");
662 PARAM_TEXT_ADD(sess->params, "SendTargets", "Reject", text_out, &len_out, 2048, 0, TC_ERROR); 662 PARAM_TEXT_ADD(sess->params, "SendTargets", "Reject", text_out, &len_out, 2048, 0, TC_ERROR);
663 } else { 663 } else {
664 for (i = 0 ; i < sess->globals->tv->c ; i++) { 664 for (i = 0 ; i < sess->globals->tv->c ; i++) {
665 if (sess->address_family == ISCSI_IPv6 || 665 if (sess->address_family == ISCSI_IPv6 ||
666 (sess->address_family == ISCSI_IPv4 && allow_netmask(sess->globals->tv->v[i].mask, sess->initiator))) { 666 (sess->address_family == ISCSI_IPv4 && allow_netmask(sess->globals->tv->v[i].mask, sess->initiator))) {
667 (void) get_iqn(sess, i, buf, sizeof(buf)); 667 (void) get_iqn(sess, i, buf, sizeof(buf));
668 PARAM_TEXT_ADD(sess->params, "TargetName", buf, text_out, &len_out, 2048, 0, TC_ERROR); 668 PARAM_TEXT_ADD(sess->params, "TargetName", buf, text_out, &len_out, 2048, 0, TC_ERROR);
669 PARAM_TEXT_ADD(sess->params, "TargetAddress", sess->globals->targetaddress, text_out, &len_out, 2048, 0, TC_ERROR); 669 PARAM_TEXT_ADD(sess->params, "TargetAddress", sess->globals->targetaddress, text_out, &len_out, 2048, 0, TC_ERROR);
670 } else { 670 } else {
671#ifdef HAVE_SYSLOG_H 671#ifdef HAVE_SYSLOG_H
672 syslog(LOG_INFO, "WARNING: attempt to discover targets from %s (not allowed by %s) has been rejected", sess->initiator, sess->globals->tv->v[0].mask); 672 syslog(LOG_INFO, "WARNING: attempt to discover targets from %s (not allowed by %s) has been rejected", sess->initiator, sess->globals->tv->v[0].mask);
673#endif 673#endif
674 } 674 }
675 } 675 }
676 } 676 }
677 ptr->rx_offer = 0; 677 ptr->rx_offer = 0;
678 } 678 }
679 /* Parse outgoing offer */ 679 /* Parse outgoing offer */
680 680
681 if (len_out) { 681 if (len_out) {
682 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text_out, len_out, NULL, NULL, 2048, 1, TC_ERROR); 682 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text_out, len_out, NULL, NULL, 2048, 1, TC_ERROR);
683 } 683 }
684 } 684 }
685 if (sess->IsFullFeature) { 685 if (sess->IsFullFeature) {
686 set_session_parameters(sess->params, &sess->sess_params); 686 set_session_parameters(sess->params, &sess->sess_params);
687 } 687 }
688 /* Send response */ 688 /* Send response */
689 689
690 text_rsp.final = text_cmd.final; 690 text_rsp.final = text_cmd.final;
691 text_rsp.cont = 0; 691 text_rsp.cont = 0;
692 text_rsp.length = len_out; 692 text_rsp.length = len_out;
693 text_rsp.lun = text_cmd.lun; 693 text_rsp.lun = text_cmd.lun;
694 text_rsp.tag = text_cmd.tag; 694 text_rsp.tag = text_cmd.tag;
695 text_rsp.transfer_tag = (text_rsp.final) ? 0xffffffff : 0x1234; 695 text_rsp.transfer_tag = (text_rsp.final) ? 0xffffffff : 0x1234;
696 text_rsp.StatSN = ++(sess->StatSN); 696 text_rsp.StatSN = ++(sess->StatSN);
697 text_rsp.ExpCmdSN = sess->ExpCmdSN; 697 text_rsp.ExpCmdSN = sess->ExpCmdSN;
698 text_rsp.MaxCmdSN = sess->MaxCmdSN; 698 text_rsp.MaxCmdSN = sess->MaxCmdSN;
699 if (iscsi_text_rsp_encap(rsp_header, &text_rsp) != 0) { 699 if (iscsi_text_rsp_encap(rsp_header, &text_rsp) != 0) {
700 iscsi_trace_error(__FILE__, __LINE__, "iscsi_text_rsp_encap() failed\n"); 700 iscsi_trace_error(__FILE__, __LINE__, "iscsi_text_rsp_encap() failed\n");
701 TC_CLEANUP; 701 TC_CLEANUP;
702 return -1; 702 return -1;
703 } 703 }
704 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, rsp_header, 0) != ISCSI_HEADER_LEN) { 704 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, rsp_header, 0) != ISCSI_HEADER_LEN) {
705 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 705 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
706 TC_CLEANUP; 706 TC_CLEANUP;
707 return -1; 707 return -1;
708 } 708 }
709 if (len_out) { 709 if (len_out) {
710 if (iscsi_sock_msg(sess->sock, 1, (unsigned) len_out, text_out, 0) != len_out) { 710 if (iscsi_sock_msg(sess->sock, 1, (unsigned) len_out, text_out, 0) != len_out) {
711 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 711 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
712 TC_CLEANUP; 712 TC_CLEANUP;
713 return -1; 713 return -1;
714 } 714 }
715 } 715 }
716 TC_CLEANUP; 716 TC_CLEANUP;
717 return 0; 717 return 0;
718} 718}
719 719
720/* given a target's iqn, find the relevant target that we're exporting */ 720/* given a target's iqn, find the relevant target that we're exporting */
721int 721int
722find_target_iqn(target_session_t *sess) 722find_target_iqn(target_session_t *sess)
723{ 723{
724 char buf[BUFSIZ]; 724 char buf[BUFSIZ];
725 int i; 725 int i;
726 726
727 for (i = 0 ; i < sess->globals->tv->c ; i++) { 727 for (i = 0 ; i < sess->globals->tv->c ; i++) {
728 if (param_equiv(sess->params, "TargetName", 728 if (param_equiv(sess->params, "TargetName",
729 get_iqn(sess, i, buf, sizeof(buf)))) { 729 get_iqn(sess, i, buf, sizeof(buf)))) {
730 return sess->d = i; 730 return sess->d = i;
731 } 731 }
732 } 732 }
733 return -1; 733 return -1;
734} 734}
735 735
736/* given a tsih, find the relevant target that we're exporting */ 736/* given a tsih, find the relevant target that we're exporting */
737int 737int
738find_target_tsih(globals_t *globals, int tsih) 738find_target_tsih(globals_t *globals, int tsih)
739{ 739{
740 int i; 740 int i;
741 741
742 for (i = 0 ; i < globals->tv->c ; i++) { 742 for (i = 0 ; i < globals->tv->c ; i++) {
743 if (globals->tv->v[i].tsih == tsih) { 743 if (globals->tv->v[i].tsih == tsih) {
744 return i; 744 return i;
745 } 745 }
746 } 746 }
747 return -1; 747 return -1;
748} 748}
749 749
750/* 750/*
751 * login_command_t() handles login requests and replies. 751 * login_command_t() handles login requests and replies.
752 */ 752 */
753 753
754static int  754static int
755login_command_t(target_session_t * sess, uint8_t *header) 755login_command_t(target_session_t * sess, uint8_t *header)
756{ 756{
757 iscsi_login_cmd_args_t cmd; 757 iscsi_login_cmd_args_t cmd;
758 iscsi_login_rsp_args_t rsp; 758 iscsi_login_rsp_args_t rsp;
759 uint8_t rsp_header[ISCSI_HEADER_LEN]; 759 uint8_t rsp_header[ISCSI_HEADER_LEN];
760 char *text_in = NULL; 760 char *text_in = NULL;
761 char *text_out = NULL; 761 char *text_out = NULL;
762 char logbuf[BUFSIZ]; 762 char logbuf[BUFSIZ];
763 int len_in = 0; 763 int len_in = 0;
764 int len_out = 0; 764 int len_out = 0;
765 int status = 0; 765 int status = 0;
766 int i; 766 int i;
767 767
768 /* Initialize response */ 768 /* Initialize response */
769 769
770#define LC_CLEANUP do { \ 770#define LC_CLEANUP do { \
771 if (text_in != NULL) { \ 771 if (text_in != NULL) { \
772 iscsi_free_atomic(text_in); \ 772 iscsi_free_atomic(text_in); \
773 } \ 773 } \
774 if (text_out != NULL) { \ 774 if (text_out != NULL) { \
775 iscsi_free_atomic(text_out); \ 775 iscsi_free_atomic(text_out); \
776 } \ 776 } \
777} while (/* CONSTCOND */ 0) 777} while (/* CONSTCOND */ 0)
778#define LC_ERROR { \ 778#define LC_ERROR { \
779 TC_CLEANUP; \ 779 TC_CLEANUP; \
780 return -1; \ 780 return -1; \
781} 781}
782 782
783 (void) memset(&rsp, 0x0, sizeof(rsp)); 783 (void) memset(&rsp, 0x0, sizeof(rsp));
784 rsp.status_class = ISCSI_LOGIN_STATUS_INITIATOR_ERROR; 784 rsp.status_class = ISCSI_LOGIN_STATUS_INITIATOR_ERROR;
785 785
786 /* Get login args & check preconditions */ 786 /* Get login args & check preconditions */
787 787
788 if (iscsi_login_cmd_decap(header, &cmd) != 0) { 788 if (iscsi_login_cmd_decap(header, &cmd) != 0) {
789 iscsi_trace_error(__FILE__, __LINE__, "iscsi_login_cmd_decap() failed\n"); 789 iscsi_trace_error(__FILE__, __LINE__, "iscsi_login_cmd_decap() failed\n");
790 goto response; 790 goto response;
791 } 791 }
792 if (sess->IsLoggedIn) { 792 if (sess->IsLoggedIn) {
793 iscsi_trace_error(__FILE__, __LINE__, "duplicate login attempt on sess %d\n", sess->id); 793 iscsi_trace_error(__FILE__, __LINE__, "duplicate login attempt on sess %d\n", sess->id);
794 goto response; 794 goto response;
795 } 795 }
796 if ((cmd.cont != 0) && (cmd.transit != 0)) { 796 if ((cmd.cont != 0) && (cmd.transit != 0)) {
797 iscsi_trace_error(__FILE__, __LINE__, "Bad cmd.continue. Expected 0.\n"); 797 iscsi_trace_error(__FILE__, __LINE__, "Bad cmd.continue. Expected 0.\n");
798 goto response; 798 goto response;
799 } else if ((cmd.version_max < ISCSI_VERSION) || (cmd.version_min > ISCSI_VERSION)) { 799 } else if ((cmd.version_max < ISCSI_VERSION) || (cmd.version_min > ISCSI_VERSION)) {
800 iscsi_trace_error(__FILE__, __LINE__, "Target iscsi version (%u) not supported by initiator [Max Ver (%u) and Min Ver (%u)]\n", ISCSI_VERSION, cmd.version_max, cmd.version_min); 800 iscsi_trace_error(__FILE__, __LINE__, "Target iscsi version (%u) not supported by initiator [Max Ver (%u) and Min Ver (%u)]\n", ISCSI_VERSION, cmd.version_max, cmd.version_min);
801 rsp.status_class = ISCSI_LOGIN_STATUS_INITIATOR_ERROR; 801 rsp.status_class = ISCSI_LOGIN_STATUS_INITIATOR_ERROR;
802 rsp.status_detail = ISCSI_LOGIN_DETAIL_VERSION_NOT_SUPPORTED; 802 rsp.status_detail = ISCSI_LOGIN_DETAIL_VERSION_NOT_SUPPORTED;
803 rsp.version_max = ISCSI_VERSION; 803 rsp.version_max = ISCSI_VERSION;
804 rsp.version_active = ISCSI_VERSION; 804 rsp.version_active = ISCSI_VERSION;
805 goto response; 805 goto response;
806 } else if (cmd.tsih != 0) { 806 } else if (cmd.tsih != 0) {
807 iscsi_trace_error(__FILE__, __LINE__, "Bad cmd.tsih (%u). Expected 0.\n", cmd.tsih); 807 iscsi_trace_error(__FILE__, __LINE__, "Bad cmd.tsih (%u). Expected 0.\n", cmd.tsih);
808 goto response; 808 goto response;
809 } 809 }
810 /* Parse text parameters and build response */ 810 /* Parse text parameters and build response */
811 811
812 if ((text_out = iscsi_malloc_atomic(2048)) == NULL) { 812 if ((text_out = iscsi_malloc_atomic(2048)) == NULL) {
813 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 813 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
814 return -1; 814 return -1;
815 } 815 }
816 if ((len_in = cmd.length) != 0) { 816 if ((len_in = cmd.length) != 0) {
817 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes text data\n", len_in); 817 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading %d bytes text data\n", len_in);
818 if ((text_in = iscsi_malloc_atomic((unsigned)(len_in + 1))) == NULL) { 818 if ((text_in = iscsi_malloc_atomic((unsigned)(len_in + 1))) == NULL) {
819 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 819 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
820 LC_CLEANUP; 820 LC_CLEANUP;
821 return -1; 821 return -1;
822 } 822 }
823 if (iscsi_sock_msg(sess->sock, 0, (unsigned) len_in, text_in, 0) != len_in) { 823 if (iscsi_sock_msg(sess->sock, 0, (unsigned) len_in, text_in, 0) != len_in) {
824 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 824 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
825 LC_CLEANUP; 825 LC_CLEANUP;
826 return -1; 826 return -1;
827 } 827 }
828 text_in[len_in] = 0x0; 828 text_in[len_in] = 0x0;
829 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully read %d bytes text data\n", len_in); 829 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully read %d bytes text data\n", len_in);
830 830
831 /* 831 /*
832 * Parse incoming parameters (text_out will contain the 832 * Parse incoming parameters (text_out will contain the
833 * response we need 833 * response we need
834 */ 834 */
835 835
836 /* to send back to the initiator */ 836 /* to send back to the initiator */
837 837
838 838
839 if ((status = param_text_parse(sess->params, &sess->sess_params.cred, text_in, len_in, text_out, &len_out, 2048, 0)) != 0) { 839 if ((status = param_text_parse(sess->params, &sess->sess_params.cred, text_in, len_in, text_out, &len_out, 2048, 0)) != 0) {
840 switch (status) { 840 switch (status) {
841 case ISCSI_PARAM_STATUS_FAILED: 841 case ISCSI_PARAM_STATUS_FAILED:
842 rsp.status_detail = ISCSI_LOGIN_DETAIL_SUCCESS; 842 rsp.status_detail = ISCSI_LOGIN_DETAIL_SUCCESS;
843 break; 843 break;
844 case ISCSI_PARAM_STATUS_AUTH_FAILED: 844 case ISCSI_PARAM_STATUS_AUTH_FAILED:
845 rsp.status_detail = ISCSI_LOGIN_DETAIL_INIT_AUTH_FAILURE; 845 rsp.status_detail = ISCSI_LOGIN_DETAIL_INIT_AUTH_FAILURE;
846 break; 846 break;
847 default: 847 default:
848 /* 848 /*
849 * We will need to set the detail field based on more detailed error 849 * We will need to set the detail field based on more detailed error
850 * cases. Will need to fix this if compliciance test break 850 * cases. Will need to fix this if compliciance test break
851 * (status_detail field). 851 * (status_detail field).
852 */ 852 */
853 break; 853 break;
854 } 854 }
855 goto response; 855 goto response;
856 } 856 }
857 /* Parse the outgoing offer */ 857 /* Parse the outgoing offer */
858 if (!sess->LoginStarted) { 858 if (!sess->LoginStarted) {
859 PARAM_TEXT_ADD(sess->params, "TargetPortalGroupTag", "1", text_out, &len_out, 2048, 0, LC_ERROR); 859 PARAM_TEXT_ADD(sess->params, "TargetPortalGroupTag", "1", text_out, &len_out, 2048, 0, LC_ERROR);
860 } 860 }
861 if (len_out) { 861 if (len_out) {
862 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text_out, len_out, NULL, NULL, 2048, 1, LC_ERROR; 862 PARAM_TEXT_PARSE(sess->params, &sess->sess_params.cred, text_out, len_out, NULL, NULL, 2048, 1, LC_ERROR;
863 ); 863 );
864 } 864 }
865 } 865 }
866 if (!sess->LoginStarted) { 866 if (!sess->LoginStarted) {
867 sess->LoginStarted = 1; 867 sess->LoginStarted = 1;
868 } 868 }
869 /* 869 /*
870 * For now, we accept what ever the initiators' current and next 870 * For now, we accept what ever the initiators' current and next
871 * states are. And le are always 871 * states are. And le are always
872 */ 872 */
873 /* ready to transitition to that state. */ 873 /* ready to transitition to that state. */
874 874
875 rsp.csg = cmd.csg; 875 rsp.csg = cmd.csg;
876 rsp.nsg = cmd.nsg; 876 rsp.nsg = cmd.nsg;
877 rsp.transit = cmd.transit; 877 rsp.transit = cmd.transit;
878 878
879 if (cmd.csg == ISCSI_LOGIN_STAGE_SECURITY) { 879 if (cmd.csg == ISCSI_LOGIN_STAGE_SECURITY) {
880 if (param_equiv(sess->params, "AuthResult", "No")) { 880 if (param_equiv(sess->params, "AuthResult", "No")) {
881 rsp.transit = 0; 881 rsp.transit = 0;
882 } else if (param_equiv(sess->params, "AuthResult", "Fail")) { 882 } else if (param_equiv(sess->params, "AuthResult", "Fail")) {
883 rsp.status_class = rsp.status_detail = ISCSI_LOGIN_DETAIL_INIT_AUTH_FAILURE; 883 rsp.status_class = rsp.status_detail = ISCSI_LOGIN_DETAIL_INIT_AUTH_FAILURE;
884 goto response; 884 goto response;
885 } 885 }
886 } 886 }
887 if (cmd.transit && cmd.nsg == ISCSI_LOGIN_STAGE_FULL_FEATURE) { 887 if (cmd.transit && cmd.nsg == ISCSI_LOGIN_STAGE_FULL_FEATURE) {
888 888
889 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "transitioning to ISCSI_LOGIN_STAGE_FULL_FEATURE\n"); 889 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "transitioning to ISCSI_LOGIN_STAGE_FULL_FEATURE\n");
890 890
891 /* Check post conditions */ 891 /* Check post conditions */
892 892
893 if (param_equiv(sess->params, "InitiatorName", "")) { 893 if (param_equiv(sess->params, "InitiatorName", "")) {
894 iscsi_trace_error(__FILE__, __LINE__, "InitiatorName not specified\n"); 894 iscsi_trace_error(__FILE__, __LINE__, "InitiatorName not specified\n");
895 goto response; 895 goto response;
896 } 896 }
897 if (param_equiv(sess->params, "SessionType", "Normal")) { 897 if (param_equiv(sess->params, "SessionType", "Normal")) {
898 if (param_equiv(sess->params, "TargetName", "")) { 898 if (param_equiv(sess->params, "TargetName", "")) {
899 iscsi_trace_error(__FILE__, __LINE__, "TargetName not specified\n"); 899 iscsi_trace_error(__FILE__, __LINE__, "TargetName not specified\n");
900 goto response; 900 goto response;
901 } 901 }
902 if ((i = find_target_iqn(sess)) < 0) {  902 if ((i = find_target_iqn(sess)) < 0) {
903 iscsi_trace_error(__FILE__, __LINE__, "Bad TargetName \"%s\"\n", param_val(sess->params, "TargetName")); 903 iscsi_trace_error(__FILE__, __LINE__, "Bad TargetName \"%s\"\n", param_val(sess->params, "TargetName"));
904 goto response; 904 goto response;
905 } 905 }
906 if (cmd.tsih != 0 && find_target_tsih(sess->globals, cmd.tsih) != i) { 906 if (cmd.tsih != 0 && find_target_tsih(sess->globals, cmd.tsih) != i) {
907 iscsi_trace_error(__FILE__, __LINE__, "target tsih expected %d, cmd.tsih %d, i %d\n", sess->globals->tv->v[i].tsih, cmd.tsih, i); 907 iscsi_trace_error(__FILE__, __LINE__, "target tsih expected %d, cmd.tsih %d, i %d\n", sess->globals->tv->v[i].tsih, cmd.tsih, i);
908 } 908 }
909 sess->d = i; 909 sess->d = i;
910 } else if ((i = find_target_tsih(sess->globals, cmd.tsih)) < 0) { 910 } else if ((i = find_target_tsih(sess->globals, cmd.tsih)) < 0) {
911 iscsi_trace_error(__FILE__, __LINE__, "Abnormal SessionType cmd.tsih %d not found\n", cmd.tsih); 911 iscsi_trace_error(__FILE__, __LINE__, "Abnormal SessionType cmd.tsih %d not found\n", cmd.tsih);
912 i = sess->d; 912 i = sess->d;
913 } 913 }
914 if (param_equiv(sess->params, "SessionType", "")) { 914 if (param_equiv(sess->params, "SessionType", "")) {
915 iscsi_trace_error(__FILE__, __LINE__, "SessionType not specified\n"); 915 iscsi_trace_error(__FILE__, __LINE__, "SessionType not specified\n");
916 goto response; 916 goto response;
917 } 917 }
918 sess->ExpCmdSN = sess->MaxCmdSN = cmd.CmdSN; 918 sess->ExpCmdSN = sess->MaxCmdSN = cmd.CmdSN;
919 sess->cid = cmd.cid; 919 sess->cid = cmd.cid;
920 sess->isid = cmd.isid; 920 sess->isid = cmd.isid;
921 921
922 sess->globals->tv->v[i].tsih = sess->tsih = ++sess->globals->last_tsih; 922 sess->globals->tv->v[i].tsih = sess->tsih = ++sess->globals->last_tsih;
923 sess->IsFullFeature = 1; 923 sess->IsFullFeature = 1;
924 924
925 sess->IsLoggedIn = 1; 925 sess->IsLoggedIn = 1;
926 if (!param_equiv(sess->params, "SessionType", "Discovery")) { 926 if (!param_equiv(sess->params, "SessionType", "Discovery")) {
927 (void) strlcpy(param_val(sess->params, "MaxConnections"), "1", 2); 927 (void) strlcpy(param_val(sess->params, "MaxConnections"), "1", 2);
928 } 928 }
929 set_session_parameters(sess->params, &sess->sess_params); 929 set_session_parameters(sess->params, &sess->sess_params);
930 } else { 930 } else {
931 if ((i = find_target_tsih(sess->globals, cmd.tsih)) < 0) { 931 if ((i = find_target_tsih(sess->globals, cmd.tsih)) < 0) {
932 iscsi_trace_error(__FILE__, __LINE__, "cmd.tsih %d not found\n", cmd.tsih); 932 iscsi_trace_error(__FILE__, __LINE__, "cmd.tsih %d not found\n", cmd.tsih);
933 } 933 }
934 } 934 }
935 935
936 /* No errors */ 936 /* No errors */
937 937
938 rsp.status_class = rsp.status_detail = ISCSI_LOGIN_DETAIL_SUCCESS; 938 rsp.status_class = rsp.status_detail = ISCSI_LOGIN_DETAIL_SUCCESS;
939 rsp.length = len_out; 939 rsp.length = len_out;
940 940
941 /* Send login response */ 941 /* Send login response */
942 942
943response: 943response:
944 sess->ExpCmdSN = sess->MaxCmdSN = cmd.CmdSN; 944 sess->ExpCmdSN = sess->MaxCmdSN = cmd.CmdSN;
945 rsp.isid = cmd.isid; 945 rsp.isid = cmd.isid;
946 rsp.StatSN = cmd.ExpStatSN; /* debug */ 946 rsp.StatSN = cmd.ExpStatSN; /* debug */
947 rsp.tag = cmd.tag; 947 rsp.tag = cmd.tag;
948 rsp.cont = cmd.cont; 948 rsp.cont = cmd.cont;
949 rsp.ExpCmdSN = sess->ExpCmdSN; 949 rsp.ExpCmdSN = sess->ExpCmdSN;
950 rsp.MaxCmdSN = sess->MaxCmdSN; 950 rsp.MaxCmdSN = sess->MaxCmdSN;
951 if (!rsp.status_class) { 951 if (!rsp.status_class) {
952 if (rsp.transit && (rsp.nsg == ISCSI_LOGIN_STAGE_FULL_FEATURE)) { 952 if (rsp.transit && (rsp.nsg == ISCSI_LOGIN_STAGE_FULL_FEATURE)) {
953 rsp.version_max = ISCSI_VERSION; 953 rsp.version_max = ISCSI_VERSION;
954 rsp.version_active = ISCSI_VERSION; 954 rsp.version_active = ISCSI_VERSION;
955 rsp.StatSN = ++(sess->StatSN); 955 rsp.StatSN = ++(sess->StatSN);
956 rsp.tsih = sess->tsih; 956 rsp.tsih = sess->tsih;
957 } 957 }
958 } 958 }
959 if (iscsi_login_rsp_encap(rsp_header, &rsp) != 0) { 959 if (iscsi_login_rsp_encap(rsp_header, &rsp) != 0) {
960 iscsi_trace_error(__FILE__, __LINE__, "iscsi_login_rsp_encap() failed\n"); 960 iscsi_trace_error(__FILE__, __LINE__, "iscsi_login_rsp_encap() failed\n");
961 LC_CLEANUP; 961 LC_CLEANUP;
962 return -1; 962 return -1;
963 } 963 }
964 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending login response\n"); 964 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending login response\n");
965 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN, 965 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, ISCSI_HEADER_LEN,
966 text_out, rsp.length, 0) != ISCSI_HEADER_LEN + rsp.length) { 966 text_out, rsp.length, 0) != ISCSI_HEADER_LEN + rsp.length) {
967 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 967 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
968 LC_CLEANUP; 968 LC_CLEANUP;
969 return -1; 969 return -1;
970 } 970 }
971 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent login response ok\n"); 971 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent login response ok\n");
972 if (rsp.status_class != 0) { 972 if (rsp.status_class != 0) {
973 LC_CLEANUP; 973 LC_CLEANUP;
974 return -1; 974 return -1;
975 } 975 }
976 if (cmd.transit && cmd.nsg == ISCSI_LOGIN_STAGE_FULL_FEATURE) { 976 if (cmd.transit && cmd.nsg == ISCSI_LOGIN_STAGE_FULL_FEATURE) {
977 977
978 /* log information to stdout */ 978 /* log information to stdout */
979 (void) snprintf(logbuf, sizeof(logbuf), 979 (void) snprintf(logbuf, sizeof(logbuf),
980 "> iSCSI %s login successful from %s on %s disk %d, ISID %" PRIu64 ", TSIH %u", 980 "> iSCSI %s login successful from %s on %s disk %d, ISID %" PRIu64 ", TSIH %u",
981 param_val(sess->params, "SessionType"), 981 param_val(sess->params, "SessionType"),
982 param_val(sess->params, "InitiatorName"), 982 param_val(sess->params, "InitiatorName"),
983 sess->initiator, 983 sess->initiator,
984 sess->d, 984 sess->d,
985 sess->isid, 985 sess->isid,
986 sess->tsih); 986 sess->tsih);
987 printf("%s\n", logbuf); 987 printf("%s\n", logbuf);
988#ifdef HAVE_SYSLOG_H 988#ifdef HAVE_SYSLOG_H
989 /* log information to syslog */ 989 /* log information to syslog */
990 syslog(LOG_INFO, "%s", logbuf); 990 syslog(LOG_INFO, "%s", logbuf);
991#endif 991#endif
992 992
993 /* Buffer for data xfers to/from the scsi device */ 993 /* Buffer for data xfers to/from the scsi device */
994 if (!param_equiv(sess->params, "MaxRecvDataSegmentLength", "0")) { 994 if (!param_equiv(sess->params, "MaxRecvDataSegmentLength", "0")) {
995 if ((sess->buff = iscsi_malloc((unsigned)(param_atoi(sess->params, "MaxRecvDataSegmentLength")))) == NULL) { 995 if ((sess->buff = iscsi_malloc((unsigned)(param_atoi(sess->params, "MaxRecvDataSegmentLength")))) == NULL) {
996 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n"); 996 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
997 LC_CLEANUP; 997 LC_CLEANUP;
998 return -1; 998 return -1;
999 } 999 }
1000 } else { 1000 } else {
1001 iscsi_trace_error(__FILE__, __LINE__, "MaxRecvDataSegmentLength of 0 not supported\n"); 1001 iscsi_trace_error(__FILE__, __LINE__, "MaxRecvDataSegmentLength of 0 not supported\n");
1002 LC_CLEANUP; 1002 LC_CLEANUP;
1003 return -1; 1003 return -1;
1004 } 1004 }
1005 } 1005 }
1006 LC_CLEANUP; 1006 LC_CLEANUP;
1007 return 0; 1007 return 0;
1008} 1008}
1009 1009
1010static int  1010static int
1011logout_command_t(target_session_t * sess, uint8_t *header) 1011logout_command_t(target_session_t * sess, uint8_t *header)
1012{ 1012{
1013 iscsi_logout_cmd_args_t cmd; 1013 iscsi_logout_cmd_args_t cmd;
1014 iscsi_logout_rsp_args_t rsp; 1014 iscsi_logout_rsp_args_t rsp;
1015 uint8_t rsp_header[ISCSI_HEADER_LEN]; 1015 uint8_t rsp_header[ISCSI_HEADER_LEN];
1016 char logbuf[BUFSIZ]; 1016 char logbuf[BUFSIZ];
1017 int i; 1017 int i;
1018 1018
1019 (void) memset(&rsp, 0x0, sizeof(rsp)); 1019 (void) memset(&rsp, 0x0, sizeof(rsp));
1020 if (iscsi_logout_cmd_decap(header, &cmd) != 0) { 1020 if (iscsi_logout_cmd_decap(header, &cmd) != 0) {
1021 iscsi_trace_error(__FILE__, __LINE__, "iscsi_logout_cmd_decap() failed\n"); 1021 iscsi_trace_error(__FILE__, __LINE__, "iscsi_logout_cmd_decap() failed\n");
1022 return -1; 1022 return -1;
1023 } 1023 }
1024 sess->StatSN = cmd.ExpStatSN; 1024 sess->StatSN = cmd.ExpStatSN;
1025 if ((cmd.reason == ISCSI_LOGOUT_CLOSE_RECOVERY) && (param_equiv(sess->params, "ErrorRecoveryLevel", "0"))) { 1025 if ((cmd.reason == ISCSI_LOGOUT_CLOSE_RECOVERY) && (param_equiv(sess->params, "ErrorRecoveryLevel", "0"))) {
1026 rsp.response = ISCSI_LOGOUT_STATUS_NO_RECOVERY; 1026 rsp.response = ISCSI_LOGOUT_STATUS_NO_RECOVERY;
1027 } 1027 }
1028 RETURN_NOT_EQUAL("CmdSN", cmd.CmdSN, sess->ExpCmdSN, NO_CLEANUP, -1); 1028 RETURN_NOT_EQUAL("CmdSN", cmd.CmdSN, sess->ExpCmdSN, NO_CLEANUP, -1);
1029 RETURN_NOT_EQUAL("ExpStatSN", cmd.ExpStatSN, sess->StatSN, NO_CLEANUP, -1); 1029 RETURN_NOT_EQUAL("ExpStatSN", cmd.ExpStatSN, sess->StatSN, NO_CLEANUP, -1);
1030 1030
1031 rsp.tag = cmd.tag; 1031 rsp.tag = cmd.tag;
1032 rsp.StatSN = sess->StatSN; 1032 rsp.StatSN = sess->StatSN;
1033 rsp.ExpCmdSN = ++sess->ExpCmdSN; 1033 rsp.ExpCmdSN = ++sess->ExpCmdSN;
1034 rsp.MaxCmdSN = sess->MaxCmdSN; 1034 rsp.MaxCmdSN = sess->MaxCmdSN;
1035 if (iscsi_logout_rsp_encap(rsp_header, &rsp) != 0) { 1035 if (iscsi_logout_rsp_encap(rsp_header, &rsp) != 0) {
1036 iscsi_trace_error(__FILE__, __LINE__, "iscsi_logout_rsp_encap() failed\n"); 1036 iscsi_trace_error(__FILE__, __LINE__, "iscsi_logout_rsp_encap() failed\n");
1037 return -1; 1037 return -1;
1038 } 1038 }
1039 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, rsp_header, 0) != ISCSI_HEADER_LEN) { 1039 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, rsp_header, 0) != ISCSI_HEADER_LEN) {
1040 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 1040 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
1041 return -1; 1041 return -1;
1042 } 1042 }
1043 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent logout response OK\n"); 1043 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent logout response OK\n");
1044 1044
1045 /* log information to stdout */ 1045 /* log information to stdout */
1046 (void) snprintf(logbuf, sizeof(logbuf),  1046 (void) snprintf(logbuf, sizeof(logbuf),
1047 "< iSCSI %s logout successful from %s on %s disk %d, ISID %" PRIu64 ", TSIH %u", 1047 "< iSCSI %s logout successful from %s on %s disk %d, ISID %" PRIu64 ", TSIH %u",
1048 param_val(sess->params, "SessionType"), 1048 param_val(sess->params, "SessionType"),
1049 param_val(sess->params, "InitiatorName"), 1049 param_val(sess->params, "InitiatorName"),
1050 sess->initiator, 1050 sess->initiator,
1051 sess->d, 1051 sess->d,
1052 sess->isid, 1052 sess->isid,
1053 sess->tsih); 1053 sess->tsih);
1054 printf("%s\n", logbuf); 1054 printf("%s\n", logbuf);
1055#ifdef HAVE_SYSLOG 1055#ifdef HAVE_SYSLOG
1056 /* log information to syslog */ 1056 /* log information to syslog */
1057 syslog(LOG_INFO, "%s", logbuf); 1057 syslog(LOG_INFO, "%s", logbuf);
1058#endif 1058#endif
1059 1059
1060 sess->IsLoggedIn = 0; 1060 sess->IsLoggedIn = 0;
1061 1061
1062 if (sess->sess_params.cred.user) { 1062 if (sess->sess_params.cred.user) {
1063 free(sess->sess_params.cred.user); 1063 free(sess->sess_params.cred.user);
1064 sess->sess_params.cred.user = NULL; 1064 sess->sess_params.cred.user = NULL;
1065 } 1065 }
1066 1066
1067 if ((i = find_target_tsih(sess->globals, sess->tsih)) < 0) { 1067 if ((i = find_target_tsih(sess->globals, sess->tsih)) < 0) {
1068 iscsi_trace_error(__FILE__, __LINE__, "logout sess->tsih %d not found\n", sess->tsih); 1068 iscsi_trace_error(__FILE__, __LINE__, "logout sess->tsih %d not found\n", sess->tsih);
1069 } else { 1069 } else {
1070 sess->globals->tv->v[i].tsih = 0; 1070 sess->globals->tv->v[i].tsih = 0;
1071 } 1071 }
1072 sess->tsih = 0; 1072 sess->tsih = 0;
1073 1073
1074 return 0; 1074 return 0;
1075} 1075}
1076 1076
1077static int  1077static int
1078verify_cmd_t(target_session_t * sess, uint8_t *header) 1078verify_cmd_t(target_session_t * sess, uint8_t *header)
1079{ 1079{
1080 int op = ISCSI_OPCODE(header); 1080 int op = ISCSI_OPCODE(header);
1081 1081
1082 if ((!sess->LoginStarted) && (op != ISCSI_LOGIN_CMD)) { 1082 if ((!sess->LoginStarted) && (op != ISCSI_LOGIN_CMD)) {
1083 /* Terminate the connection */ 1083 /* Terminate the connection */
1084 iscsi_trace_error(__FILE__, __LINE__, "session %d: iSCSI op %#x attempted before LOGIN PHASE\n", 1084 iscsi_trace_error(__FILE__, __LINE__, "session %d: iSCSI op %#x attempted before LOGIN PHASE\n",
1085 sess->id, op); 1085 sess->id, op);
1086 return -1; 1086 return -1;
1087 } 1087 }
1088 if (!sess->IsFullFeature && ((op != ISCSI_LOGIN_CMD) && (op != ISCSI_LOGOUT_CMD))) { 1088 if (!sess->IsFullFeature && ((op != ISCSI_LOGIN_CMD) && (op != ISCSI_LOGOUT_CMD))) {
1089 iscsi_login_rsp_args_t rsp; 1089 iscsi_login_rsp_args_t rsp;
1090 uint8_t rsp_header[ISCSI_HEADER_LEN]; 1090 uint8_t rsp_header[ISCSI_HEADER_LEN];
1091 iscsi_trace_error(__FILE__, __LINE__, "session %d: iSCSI op %#x attempted before FULL FEATURE\n", 1091 iscsi_trace_error(__FILE__, __LINE__, "session %d: iSCSI op %#x attempted before FULL FEATURE\n",
1092 sess->id, op); 1092 sess->id, op);
1093 /* Create Login Reject response */ 1093 /* Create Login Reject response */
1094 (void) memset(&rsp, 0x0, sizeof(rsp)); 1094 (void) memset(&rsp, 0x0, sizeof(rsp));
1095 rsp.status_class = ISCSI_LOGIN_STATUS_INITIATOR_ERROR; 1095 rsp.status_class = ISCSI_LOGIN_STATUS_INITIATOR_ERROR;
1096 rsp.status_detail = ISCSI_LOGIN_DETAIL_NOT_LOGGED_IN; 1096 rsp.status_detail = ISCSI_LOGIN_DETAIL_NOT_LOGGED_IN;
1097 rsp.version_max = ISCSI_VERSION; 1097 rsp.version_max = ISCSI_VERSION;
1098 rsp.version_active = ISCSI_VERSION; 1098 rsp.version_active = ISCSI_VERSION;
1099 1099
1100 if (iscsi_login_rsp_encap(rsp_header, &rsp) != 0) { 1100 if (iscsi_login_rsp_encap(rsp_header, &rsp) != 0) {
1101 iscsi_trace_error(__FILE__, __LINE__, "iscsi_login_rsp_encap() failed\n"); 1101 iscsi_trace_error(__FILE__, __LINE__, "iscsi_login_rsp_encap() failed\n");
1102 return -1; 1102 return -1;
1103 } 1103 }
1104 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending login response\n"); 1104 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending login response\n");
1105 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header, 1105 if (iscsi_sock_send_header_and_data(sess->sock, rsp_header,
1106 ISCSI_HEADER_LEN, NULL, 0, 0) != ISCSI_HEADER_LEN + 1106 ISCSI_HEADER_LEN, NULL, 0, 0) != ISCSI_HEADER_LEN +
1107 rsp.length) { 1107 rsp.length) {
1108 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n"); 1108 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_send_header_and_data() failed\n");
1109 return -1; 1109 return -1;
1110 } 1110 }
1111 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent login response ok\n"); 1111 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent login response ok\n");
1112 return -1; 1112 return -1;
1113 } 1113 }
1114 return 0; 1114 return 0;
1115} 1115}
1116 1116
1117/* 1117/*
1118 * this function looks at the opcode in the received header for the session, 1118 * this function looks at the opcode in the received header for the session,
1119 * and does a switch on the opcode to call the required function. 1119 * and does a switch on the opcode to call the required function.
1120 */ 1120 */
1121static int  1121static int
1122execute_t(target_session_t *sess, uint8_t *header) 1122execute_t(target_session_t *sess, uint8_t *header)
1123{ 1123{
1124 int op = ISCSI_OPCODE(header); 1124 int op = ISCSI_OPCODE(header);
1125 1125
1126 if (verify_cmd_t(sess, header) != 0) { 1126 if (verify_cmd_t(sess, header) != 0) {
1127 return -1; 1127 return -1;
1128 } 1128 }
1129 switch (op) { 1129 switch (op) {
1130 case ISCSI_TASK_CMD: 1130 case ISCSI_TASK_CMD:
1131 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: Task Command\n", sess->id); 1131 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: Task Command\n", sess->id);
1132 if (task_command_t(sess, header) != 0) { 1132 if (task_command_t(sess, header) != 0) {
1133 iscsi_trace_error(__FILE__, __LINE__, "task_command_t() failed\n"); 1133 iscsi_trace_error(__FILE__, __LINE__, "task_command_t() failed\n");
1134 return -1; 1134 return -1;
1135 } 1135 }
1136 break; 1136 break;
1137 1137
1138 case ISCSI_NOP_OUT: 1138 case ISCSI_NOP_OUT:
1139 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: NOP-Out\n", sess->id); 1139 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: NOP-Out\n", sess->id);
1140 if (nop_out_t(sess, header) != 0) { 1140 if (nop_out_t(sess, header) != 0) {
1141 iscsi_trace_error(__FILE__, __LINE__, "nop_out_t() failed\n"); 1141 iscsi_trace_error(__FILE__, __LINE__, "nop_out_t() failed\n");
1142 return -1; 1142 return -1;
1143 } 1143 }
1144 break; 1144 break;
1145 1145
1146 case ISCSI_LOGIN_CMD: 1146 case ISCSI_LOGIN_CMD:
1147 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: Login Command\n", sess->id); 1147 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: Login Command\n", sess->id);
1148 if (login_command_t(sess, header) != 0) { 1148 if (login_command_t(sess, header) != 0) {
1149 iscsi_trace_error(__FILE__, __LINE__, "login_command_t() failed\n"); 1149 iscsi_trace_error(__FILE__, __LINE__, "login_command_t() failed\n");
1150 return -1; 1150 return -1;
1151 } 1151 }
1152 break; 1152 break;
1153 1153
1154 case ISCSI_TEXT_CMD: 1154 case ISCSI_TEXT_CMD:
1155 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: Text Command\n", sess->id); 1155 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: Text Command\n", sess->id);
1156 if (text_command_t(sess, header) != 0) { 1156 if (text_command_t(sess, header) != 0) {
1157 iscsi_trace_error(__FILE__, __LINE__, "text_command_t() failed\n"); 1157 iscsi_trace_error(__FILE__, __LINE__, "text_command_t() failed\n");
1158 return -1; 1158 return -1;
1159 } 1159 }
1160 break; 1160 break;
1161 1161
1162 case ISCSI_LOGOUT_CMD: 1162 case ISCSI_LOGOUT_CMD:
1163 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: Logout Command\n", sess->id); 1163 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: Logout Command\n", sess->id);
1164 if (logout_command_t(sess, header) != 0) { 1164 if (logout_command_t(sess, header) != 0) {
1165 iscsi_trace_error(__FILE__, __LINE__, "logout_command_t() failed\n"); 1165 iscsi_trace_error(__FILE__, __LINE__, "logout_command_t() failed\n");
1166 return -1; 1166 return -1;
1167 } 1167 }
1168 break; 1168 break;
1169 1169
1170 case ISCSI_SCSI_CMD: 1170 case ISCSI_SCSI_CMD:
1171 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: SCSI Command\n", sess->id); 1171 iscsi_trace(TRACE_ISCSI_CMD, __FILE__, __LINE__, "session %d: SCSI Command\n", sess->id);
1172 if (scsi_command_t(sess, header) != 0) { 1172 if (scsi_command_t(sess, header) != 0) {
1173 iscsi_trace_error(__FILE__, __LINE__, "scsi_command_t() failed\n"); 1173 iscsi_trace_error(__FILE__, __LINE__, "scsi_command_t() failed\n");
1174 return -1; 1174 return -1;
1175 } 1175 }
1176 break; 1176 break;
1177 1177
1178 default: 1178 default:
1179 iscsi_trace_error(__FILE__, __LINE__, "Unknown Opcode %#x\n", ISCSI_OPCODE(header)); 1179 iscsi_trace_error(__FILE__, __LINE__, "Unknown Opcode %#x\n", ISCSI_OPCODE(header));
1180 if (reject_t(sess, header, 0x04) != 0) { 1180 if (reject_t(sess, header, 0x04) != 0) {
1181 iscsi_trace_error(__FILE__, __LINE__, "reject_t() failed\n"); 1181 iscsi_trace_error(__FILE__, __LINE__, "reject_t() failed\n");
1182 return -1; 1182 return -1;
1183 } 1183 }
1184 break; 1184 break;
1185 } 1185 }
1186 return 0; 1186 return 0;
1187} 1187}
1188 1188
1189/* 1189/*
1190 * Currently one thread per session, used for both Rx and Tx. 1190 * Currently one thread per session, used for both Rx and Tx.
1191 */ 1191 */
1192 1192
1193static int  1193static int
1194worker_proc_t(void *arg) 1194worker_proc_t(void *arg)
1195{ 1195{
1196 target_session_t *sess = (target_session_t *) arg; 1196 target_session_t *sess = (target_session_t *) arg;
1197 uint8_t header[ISCSI_HEADER_LEN]; 1197 uint8_t header[ISCSI_HEADER_LEN];
1198 iscsi_parameter_t **l = &sess->params; 1198 iscsi_parameter_t **l = &sess->params;
1199 1199
1200 ISCSI_THREAD_START("worker_thread"); 1200 ISCSI_THREAD_START("worker_thread");
1201 sess->worker.pid = ISCSI_GETPID; 1201 sess->worker.pid = ISCSI_GETPID;
1202 sess->worker.state |= ISCSI_WORKER_STATE_STARTED; 1202 sess->worker.state |= ISCSI_WORKER_STATE_STARTED;
1203 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: started\n", sess->id); 1203 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: started\n", sess->id);
1204 1204
1205 /* 1205 /*
1206 * ISCSI_PARAM_TYPE_LIST format: <type> <key> <dflt> <valid list values> 1206 * ISCSI_PARAM_TYPE_LIST format: <type> <key> <dflt> <valid list values>
1207 * ISCSI_PARAM_TYPE_BINARY format: <type> <key> <dflt> <valid binary values> 1207 * ISCSI_PARAM_TYPE_BINARY format: <type> <key> <dflt> <valid binary values>
1208 * ISCSI_PARAM_TYPE_NUMERICAL format: <type> <key> <dflt> <max> 1208 * ISCSI_PARAM_TYPE_NUMERICAL format: <type> <key> <dflt> <max>
1209 * ISCSI_PARAM_TYPE_DECLARATIVE format: <type> <key> <dflt> "" 1209 * ISCSI_PARAM_TYPE_DECLARATIVE format: <type> <key> <dflt> ""
1210 */ 1210 */
1211 1211
1212 sess->params = NULL; 1212 sess->params = NULL;
1213 l = &sess->params; 1213 l = &sess->params;
1214 1214
1215 /* CHAP Parameters */ 1215 /* CHAP Parameters */
1216 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "AuthMethod", "CHAP", "CHAP,None", return -1); 1216 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "AuthMethod", "CHAP", "CHAP,None", return -1);
1217 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "CHAP_A", "None", "5", return -1); 1217 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "CHAP_A", "None", "5", return -1);
1218 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_N", "", "", return -1); 1218 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_N", "", "", return -1);
1219 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_R", "", "", return -1); 1219 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_R", "", "", return -1);
1220 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_I", "", "", return -1); 1220 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_I", "", "", return -1);
1221 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_C", "", "", return -1); 1221 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "CHAP_C", "", "", return -1);
1222 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetPortalGroupTag", "1", "1", return -1); 1222 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetPortalGroupTag", "1", "1", return -1);
1223 /* CHAP Parameters */ 1223 /* CHAP Parameters */
1224 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "HeaderDigest", "None", "None", return -1); 1224 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "HeaderDigest", "None", "None", return -1);
1225 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "DataDigest", "None", "None", return -1); 1225 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "DataDigest", "None", "None", return -1);
1226 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "MaxConnections", "1", "1", return -1); 1226 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "MaxConnections", "1", "1", return -1);
1227 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "SendTargets", "", "", return -1); 1227 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "SendTargets", "", "", return -1);
1228 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetName", "", "", return -1); 1228 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetName", "", "", return -1);
1229 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "InitiatorName", "", "", return -1); 1229 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "InitiatorName", "", "", return -1);
1230 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetAlias", "", "", return -1); 1230 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetAlias", "", "", return -1);
1231 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "InitiatorAlias", "", "", return -1); 1231 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "InitiatorAlias", "", "", return -1);
1232 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetAddress", "", "", return -1); 1232 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "TargetAddress", "", "", return -1);
1233 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "InitialR2T", "Yes", "Yes,No", return -1); 1233 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "InitialR2T", "Yes", "Yes,No", return -1);
1234 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_AND, "OFMarker", "No", "Yes,No", return -1); 1234 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_AND, "OFMarker", "No", "Yes,No", return -1);
1235 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_AND, "IFMarker", "No", "Yes,No", return -1); 1235 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_AND, "IFMarker", "No", "Yes,No", return -1);
1236 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "OFMarkInt", "1", "65536", return -1); 1236 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "OFMarkInt", "1", "65536", return -1);
1237 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "IFMarkInt", "1", "65536", return -1); 1237 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "IFMarkInt", "1", "65536", return -1);
1238 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_AND, "ImmediateData", "Yes", "Yes,No", return -1); 1238 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_AND, "ImmediateData", "Yes", "Yes,No", return -1);
1239 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "MaxRecvDataSegmentLength", "8192", "16777215", return -1); 1239 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "MaxRecvDataSegmentLength", "8192", "16777215", return -1);
1240 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "MaxBurstLength", "262144", "16777215", return -1); 1240 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "MaxBurstLength", "262144", "16777215", return -1);
1241 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "FirstBurstLength", "65536", "16777215", return -1); 1241 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL_Z, "FirstBurstLength", "65536", "16777215", return -1);
1242 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "DefaultTime2Wait", "2", "2", return -1); 1242 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "DefaultTime2Wait", "2", "2", return -1);
1243 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "DefaultTime2Retain", "20", "20", return -1); 1243 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "DefaultTime2Retain", "20", "20", return -1);
1244 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "MaxOutstandingR2T", "1", "1", return -1); 1244 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "MaxOutstandingR2T", "1", "1", return -1);
1245 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "DataPDUInOrder", "Yes", "Yes,No", return -1); 1245 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "DataPDUInOrder", "Yes", "Yes,No", return -1);
1246 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "DataSequenceInOrder", "Yes", "Yes,No", return -1); 1246 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_BINARY_OR, "DataSequenceInOrder", "Yes", "Yes,No", return -1);
1247 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "ErrorRecoveryLevel", "0", "0", return -1); 1247 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_NUMERICAL, "ErrorRecoveryLevel", "0", "0", return -1);
1248 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "SessionType", "Normal", "Normal,Discovery", return -1); 1248 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_DECLARATIVE, "SessionType", "Normal", "Normal,Discovery", return -1);
1249 /* 1249 /*
1250 * Auth Result is not in specs, we use this key to pass 1250 * Auth Result is not in specs, we use this key to pass
1251 * authentication result 1251 * authentication result
1252 */ 1252 */
1253 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "AuthResult", "No", "Yes,No,Fail", return -1); 1253 PARAM_LIST_ADD(l, ISCSI_PARAM_TYPE_LIST, "AuthResult", "No", "Yes,No,Fail", return -1);
1254 1254
1255 /* Set remaining session parameters */ 1255 /* Set remaining session parameters */
1256 1256
1257 sess->UsePhaseCollapsedRead = ISCSI_USE_PHASE_COLLAPSED_READ_DFLT; 1257 sess->UsePhaseCollapsedRead = ISCSI_USE_PHASE_COLLAPSED_READ_DFLT;
1258 1258
1259 /* Loop for commands */ 1259 /* Loop for commands */
1260 1260
1261 while (sess->globals->state != TARGET_SHUT_DOWN) { 1261 while (sess->globals->state != TARGET_SHUT_DOWN) {
1262 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: reading header\n", sess->id); 1262 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: reading header\n", sess->id);
1263 if (iscsi_sock_msg(sess->sock, 0, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) { 1263 if (iscsi_sock_msg(sess->sock, 0, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) {
1264 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: iscsi_sock_msg() failed\n", sess->id); 1264 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: iscsi_sock_msg() failed\n", sess->id);
1265 break; 1265 break;
1266 } 1266 }
1267 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: iscsi op %#x\n", sess->id, ISCSI_OPCODE(header)); 1267 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: iscsi op %#x\n", sess->id, ISCSI_OPCODE(header));
1268 if (execute_t(sess, header) != 0) { 1268 if (execute_t(sess, header) != 0) {
1269 iscsi_trace_error(__FILE__, __LINE__, "execute_t() failed\n"); 1269 iscsi_trace_error(__FILE__, __LINE__, "execute_t() failed\n");
1270 break; 1270 break;
1271 } 1271 }
1272 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: iscsi op %#x complete\n", sess->id, ISCSI_OPCODE(header)); 1272 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: iscsi op %#x complete\n", sess->id, ISCSI_OPCODE(header));
1273 if (ISCSI_OPCODE(header) == ISCSI_LOGOUT_CMD) { 1273 if (ISCSI_OPCODE(header) == ISCSI_LOGOUT_CMD) {
1274 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: logout received, ending session\n", sess->id); 1274 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: logout received, ending session\n", sess->id);
1275 break; 1275 break;
1276 } 1276 }
1277 } 1277 }
1278 1278
1279 /* Clean up */ 1279 /* Clean up */
1280 1280
1281 iscsi_free(sess->buff); 1281 iscsi_free(sess->buff);
1282 if (param_list_destroy(sess->params) != 0) { 1282 if (param_list_destroy(sess->params) != 0) {
1283 iscsi_trace_error(__FILE__, __LINE__, "param_list_destroy() failed\n"); 1283 iscsi_trace_error(__FILE__, __LINE__, "param_list_destroy() failed\n");
1284 return -1; 1284 return -1;
1285 } 1285 }
1286 /* Terminate connection */ 1286 /* Terminate connection */
1287 1287
1288 if (iscsi_sock_close(sess->sock) != 0) { 1288 if (iscsi_sock_close(sess->sock) != 0) {
1289 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_close() failed\n"); 1289 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_close() failed\n");
1290 } 1290 }
1291 /* Make session available */ 1291 /* Make session available */
1292 1292
1293 ISCSI_LOCK(&g_session_q_mutex, return -1); 1293 ISCSI_LOCK(&g_session_q_mutex, return -1);
1294 (void) memset(sess, 0x0, sizeof(*sess)); 1294 (void) memset(sess, 0x0, sizeof(*sess));
1295 if (iscsi_queue_insert(&g_session_q, sess) != 0) { 1295 if (iscsi_queue_insert(&g_session_q, sess) != 0) {
1296 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 1296 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
1297 return -1; 1297 return -1;
1298 } 1298 }
1299 ISCSI_UNLOCK(&g_session_q_mutex, return -1); 1299 ISCSI_UNLOCK(&g_session_q_mutex, return -1);
1300 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: ended\n", sess->id); 1300 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "session %d: ended\n", sess->id);
1301 1301
1302 return 0; 1302 return 0;
1303} 1303}
1304 1304
1305static int  1305static int
1306read_data_pdu(target_session_t * sess, 1306read_data_pdu(target_session_t * sess,
1307 iscsi_write_data_t * data, 1307 iscsi_write_data_t * data,
1308 iscsi_scsi_cmd_args_t * args) 1308 iscsi_scsi_cmd_args_t * args)
1309{ 1309{
1310 uint8_t header[ISCSI_HEADER_LEN]; 1310 uint8_t header[ISCSI_HEADER_LEN];
1311 int ret_val = -1; 1311 int ret_val = -1;
1312 1312
1313 if (iscsi_sock_msg(sess->sock, 0, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) { 1313 if (iscsi_sock_msg(sess->sock, 0, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) {
1314 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 1314 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
1315 return -1; 1315 return -1;
1316 } 1316 }
1317 if ((ret_val = iscsi_write_data_decap(header, data)) != 0) { 1317 if ((ret_val = iscsi_write_data_decap(header, data)) != 0) {
1318 iscsi_trace_error(__FILE__, __LINE__, "iscsi_write_data_decap() failed\n"); 1318 iscsi_trace_error(__FILE__, __LINE__, "iscsi_write_data_decap() failed\n");
1319 return ret_val; 1319 return ret_val;
1320 } 1320 }
1321 /* Check args */ 1321 /* Check args */
1322 if (sess->sess_params.max_data_seg_length) { 1322 if (sess->sess_params.max_data_seg_length) {
1323 if (data->length > sess->sess_params.max_data_seg_length) { 1323 if (data->length > sess->sess_params.max_data_seg_length) {
1324 args->status = 0x02; 1324 args->status = 0x02;
1325 return -1; 1325 return -1;
1326 } 1326 }
1327 } 1327 }
1328 if ((args->bytes_recv + data->length) > args->trans_len) { 1328 if ((args->bytes_recv + data->length) > args->trans_len) {
1329 args->status = 0x02; 1329 args->status = 0x02;
1330 return -1; 1330 return -1;
1331 } 1331 }
1332 if (data->tag != args->tag) { 1332 if (data->tag != args->tag) {
1333 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Data ITT (%d) does not match with command ITT (%d)\n", data->tag, args->tag); 1333 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Data ITT (%d) does not match with command ITT (%d)\n", data->tag, args->tag);
1334 if (data->final) { 1334 if (data->final) {
1335 args->status = 0x02; 1335 args->status = 0x02;
1336 return -1; 1336 return -1;
1337 } else { 1337 } else {
1338 /* Send a reject PDU */ 1338 /* Send a reject PDU */
1339 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Sending Reject PDU\n"); 1339 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Sending Reject PDU\n");
1340 if (reject_t(sess, header, 0x09) != 0) { /* Invalid PDU Field */ 1340 if (reject_t(sess, header, 0x09) != 0) { /* Invalid PDU Field */
1341 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Sending Reject PDU failed\n"); 1341 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Sending Reject PDU failed\n");
1342 return 1; 1342 return 1;
1343 } 1343 }
1344 } 1344 }
1345 } 1345 }
1346 return 0; 1346 return 0;
1347} 1347}
1348 1348
1349int  1349int
1350target_transfer_data(target_session_t * sess, iscsi_scsi_cmd_args_t * args, struct iovec * sg, int sg_len) 1350target_transfer_data(target_session_t * sess, iscsi_scsi_cmd_args_t * args, struct iovec * sg, int sg_len)
1351{ 1351{
1352 iscsi_write_data_t data; 1352 iscsi_write_data_t data;
1353 struct iovec *iov, *iov_ptr = NULL; 1353 struct iovec *iov, *iov_ptr = NULL;
1354 int iov_len; 1354 int iov_len;
1355 1355
1356#define TTD_CLEANUP do { \ 1356#define TTD_CLEANUP do { \
1357 if (iov_ptr != NULL) { \ 1357 if (iov_ptr != NULL) { \
1358 iscsi_free_atomic(iov_ptr); \ 1358 iscsi_free_atomic(iov_ptr); \
1359 } \ 1359 } \
1360} while (/* CONSTCOND */ 0) 1360} while (/* CONSTCOND */ 0)
1361 1361
1362 args->bytes_recv = 0; 1362 args->bytes_recv = 0;
1363 if ((!sess->sess_params.immediate_data) && args->length) { 1363 if ((!sess->sess_params.immediate_data) && args->length) {
1364 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Cannot accept any Immediate data\n"); 1364 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Cannot accept any Immediate data\n");
1365 args->status = 0x02; 1365 args->status = 0x02;
1366 return -1; 1366 return -1;
1367 } 1367 }
1368 /* Make a copy of the iovec */ 1368 /* Make a copy of the iovec */
1369 1369
1370 if ((iov_ptr = iscsi_malloc_atomic(sizeof(struct iovec) * sg_len)) == NULL) { 1370 if ((iov_ptr = iscsi_malloc_atomic(sizeof(struct iovec) * sg_len)) == NULL) {
1371 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n"); 1371 iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
1372 return -1; 1372 return -1;
1373 } 1373 }
1374 iov = iov_ptr; 1374 iov = iov_ptr;
1375 (void) memcpy(iov, sg, sizeof(struct iovec) * sg_len); 1375 (void) memcpy(iov, sg, sizeof(struct iovec) * sg_len);
1376 iov_len = sg_len; 1376 iov_len = sg_len;
1377 1377
1378 /* 1378 /*
1379 * Read any immediate data. 1379 * Read any immediate data.
1380 */ 1380 */
1381 1381
1382 if (sess->sess_params.immediate_data && args->length) { 1382 if (sess->sess_params.immediate_data && args->length) {
1383 if (sess->sess_params.max_data_seg_length) { 1383 if (sess->sess_params.max_data_seg_length) {
1384 RETURN_GREATER("args->length", args->length, sess->sess_params.max_data_seg_length, TTD_CLEANUP, -1); 1384 RETURN_GREATER("args->length", args->length, sess->sess_params.max_data_seg_length, TTD_CLEANUP, -1);
1385 } 1385 }
1386 /* Modify iov to include just immediate data */ 1386 /* Modify iov to include just immediate data */
1387 1387
1388 if (modify_iov(&iov, &iov_len, 0, args->length) != 0) { 1388 if (modify_iov(&iov, &iov_len, 0, args->length) != 0) {
1389 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n"); 1389 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n");
1390 TTD_CLEANUP; 1390 TTD_CLEANUP;
1391 return -1; 1391 return -1;
1392 } 1392 }
1393 iscsi_trace(TRACE_SCSI_DATA, __FILE__, __LINE__, "reading %d bytes immediate write data\n", args->length); 1393 iscsi_trace(TRACE_SCSI_DATA, __FILE__, __LINE__, "reading %d bytes immediate write data\n", args->length);
1394 if (iscsi_sock_msg(sess->sock, 0, args->length, iov, iov_len) != args->length) { 1394 if (iscsi_sock_msg(sess->sock, 0, args->length, iov, iov_len) != args->length) {
1395 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 1395 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
1396 TTD_CLEANUP; 1396 TTD_CLEANUP;
1397 return -1; 1397 return -1;
1398 } 1398 }
1399 iscsi_trace(TRACE_SCSI_DATA, __FILE__, __LINE__, "successfully read %d bytes immediate write data\n", args->length); 1399 iscsi_trace(TRACE_SCSI_DATA, __FILE__, __LINE__, "successfully read %d bytes immediate write data\n", args->length);
1400 args->bytes_recv += args->length; 1400 args->bytes_recv += args->length;
1401 } 1401 }
1402 /* 1402 /*
1403 * Read iSCSI data PDUs 1403 * Read iSCSI data PDUs
1404 */ 1404 */
1405 1405
1406 if (args->bytes_recv < args->trans_len) { 1406 if (args->bytes_recv < args->trans_len) {
1407 int r2t_flag = 0; 1407 int r2t_flag = 0;
1408 int read_status = 0; 1408 int read_status = 0;
1409 iscsi_r2t_t r2t; 1409 iscsi_r2t_t r2t;
1410 int desired_xfer_len = MIN(sess->sess_params.first_burst_length, 1410 int desired_xfer_len = MIN(sess->sess_params.first_burst_length,
1411 args->trans_len) - args->bytes_recv; 1411 args->trans_len) - args->bytes_recv;
1412 1412
1413 (void) memset(&r2t, 0x0, sizeof(r2t)); 1413 (void) memset(&r2t, 0x0, sizeof(r2t));
1414 do { 1414 do {
1415 1415
1416 /* 1416 /*
1417 * Send R2T if we're either operating in solicted 1417 * Send R2T if we're either operating in solicted
1418 * mode or we're operating in unsolicted 1418 * mode or we're operating in unsolicted
1419 */ 1419 */
1420 /* mode and have reached the first burst */ 1420 /* mode and have reached the first burst */
1421 if (!r2t_flag && (sess->sess_params.initial_r2t || 1421 if (!r2t_flag && (sess->sess_params.initial_r2t ||
1422 (sess->sess_params.first_burst_length && 1422 (sess->sess_params.first_burst_length &&
1423 (args->bytes_recv >= sess->sess_params.first_burst_length)))) { 1423 (args->bytes_recv >= sess->sess_params.first_burst_length)))) {
1424 uint8_t header[ISCSI_HEADER_LEN]; 1424 uint8_t header[ISCSI_HEADER_LEN];
1425 1425
1426 desired_xfer_len = MIN((args->trans_len - args->bytes_recv), 1426 desired_xfer_len = MIN((args->trans_len - args->bytes_recv),
1427 sess->sess_params.max_burst_length); 1427 sess->sess_params.max_burst_length);
1428 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending R2T for %u bytes data\n", desired_xfer_len); 1428 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending R2T for %u bytes data\n", desired_xfer_len);
1429 r2t.tag = args->tag; 1429 r2t.tag = args->tag;
1430 1430
1431 r2t.transfer_tag = 0x1234; 1431 r2t.transfer_tag = 0x1234;
1432 1432
1433 r2t.ExpCmdSN = sess->ExpCmdSN; 1433 r2t.ExpCmdSN = sess->ExpCmdSN;
1434 r2t.MaxCmdSN = sess->MaxCmdSN; 1434 r2t.MaxCmdSN = sess->MaxCmdSN;
1435 r2t.StatSN = ++(sess->StatSN); 1435 r2t.StatSN = ++(sess->StatSN);
1436 r2t.length = desired_xfer_len; 1436 r2t.length = desired_xfer_len;
1437 r2t.offset = args->bytes_recv; 1437 r2t.offset = args->bytes_recv;
1438 if (iscsi_r2t_encap(header, &r2t) != 0) { 1438 if (iscsi_r2t_encap(header, &r2t) != 0) {
1439 iscsi_trace_error(__FILE__, __LINE__, "r2t_encap() failed\n"); 1439 iscsi_trace_error(__FILE__, __LINE__, "r2t_encap() failed\n");
1440 TTD_CLEANUP; 1440 TTD_CLEANUP;
1441 return -1; 1441 return -1;
1442 } 1442 }
1443 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending R2T tag %u transfer tag %u len %u offset %u\n", 1443 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending R2T tag %u transfer tag %u len %u offset %u\n",
1444 r2t.tag, r2t.transfer_tag, r2t.length, r2t.offset); 1444 r2t.tag, r2t.transfer_tag, r2t.length, r2t.offset);
1445 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) { 1445 if (iscsi_sock_msg(sess->sock, 1, ISCSI_HEADER_LEN, header, 0) != ISCSI_HEADER_LEN) {
1446 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 1446 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
1447 TTD_CLEANUP; 1447 TTD_CLEANUP;
1448 return -1; 1448 return -1;
1449 } 1449 }
1450 r2t_flag = 1; 1450 r2t_flag = 1;
1451 r2t.R2TSN += 1; 1451 r2t.R2TSN += 1;
1452 } 1452 }
1453 /* Read iSCSI data PDU */ 1453 /* Read iSCSI data PDU */
1454 1454
1455 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading data pdu\n"); 1455 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "reading data pdu\n");
1456 if ((read_status = read_data_pdu(sess, &data, args)) != 0) { 1456 if ((read_status = read_data_pdu(sess, &data, args)) != 0) {
1457 if (read_status == 1) { 1457 if (read_status == 1) {
1458 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Unknown PDU received and ignored. Expecting Data PDU\n"); 1458 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "Unknown PDU received and ignored. Expecting Data PDU\n");
1459 continue; 1459 continue;
1460 } else { 1460 } else {
1461 iscsi_trace_error(__FILE__, __LINE__, "read_data_pdu() failed\n"); 1461 iscsi_trace_error(__FILE__, __LINE__, "read_data_pdu() failed\n");
1462 args->status = 0x02; 1462 args->status = 0x02;
1463 TTD_CLEANUP; 1463 TTD_CLEANUP;
1464 return -1; 1464 return -1;
1465 } 1465 }
1466 } 1466 }
1467 WARN_NOT_EQUAL("ExpStatSN", data.ExpStatSN, sess->StatSN); 1467 WARN_NOT_EQUAL("ExpStatSN", data.ExpStatSN, sess->StatSN);
1468 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "read data pdu OK (offset %u, length %u)\n", data.offset, data.length); 1468 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "read data pdu OK (offset %u, length %u)\n", data.offset, data.length);
1469 1469
1470 /* Modify iov with offset and length. */ 1470 /* Modify iov with offset and length. */
1471 1471
1472 iov = iov_ptr; 1472 iov = iov_ptr;
1473 (void) memcpy(iov, sg, sizeof(struct iovec) * sg_len); 1473 (void) memcpy(iov, sg, sizeof(struct iovec) * sg_len);
1474 iov_len = sg_len; 1474 iov_len = sg_len;
1475 if (modify_iov(&iov, &iov_len, data.offset, data.length) != 0) { 1475 if (modify_iov(&iov, &iov_len, data.offset, data.length) != 0) {
1476 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n"); 1476 iscsi_trace_error(__FILE__, __LINE__, "modify_iov() failed\n");
1477 TTD_CLEANUP; 1477 TTD_CLEANUP;
1478 return -1; 1478 return -1;
1479 } 1479 }
1480 /* Scatter into destination buffers */ 1480 /* Scatter into destination buffers */
1481 1481
1482 if (iscsi_sock_msg(sess->sock, 0, data.length, iov, iov_len) != data.length) { 1482 if (iscsi_sock_msg(sess->sock, 0, data.length, iov, iov_len) != data.length) {
1483 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n"); 1483 iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_msg() failed\n");
1484 TTD_CLEANUP; 1484 TTD_CLEANUP;
1485 return -1; 1485 return -1;
1486 } 1486 }
1487 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully scattered %u bytes\n", data.length); 1487 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully scattered %u bytes\n", data.length);
1488 args->bytes_recv += data.length; 1488 args->bytes_recv += data.length;
1489 desired_xfer_len -= data.length; 1489 desired_xfer_len -= data.length;
1490 if ((!r2t_flag) && (args->bytes_recv > sess->sess_params.first_burst_length)) { 1490 if ((!r2t_flag) && (args->bytes_recv > sess->sess_params.first_burst_length)) {
1491 iscsi_trace_error(__FILE__, __LINE__, "Received unsolicited data (%d) more than first_burst_length (%d)\n", args->bytes_recv, sess->sess_params.first_burst_length); 1491 iscsi_trace_error(__FILE__, __LINE__, "Received unsolicited data (%d) more than first_burst_length (%d)\n", args->bytes_recv, sess->sess_params.first_burst_length);
1492 args->status = 0x02; 1492 args->status = 0x02;
1493 TTD_CLEANUP; 1493 TTD_CLEANUP;
1494 return -1; 1494 return -1;
1495 } 1495 }
1496 if ((desired_xfer_len != 0) && data.final) { 1496 if ((desired_xfer_len != 0) && data.final) {
1497 iscsi_trace_error(__FILE__, __LINE__, "Expecting more data (%d) from initiator for this sequence\n", desired_xfer_len); 1497 iscsi_trace_error(__FILE__, __LINE__, "Expecting more data (%d) from initiator for this sequence\n", desired_xfer_len);
1498 args->status = 0x02; 1498 args->status = 0x02;
1499 TTD_CLEANUP; 1499 TTD_CLEANUP;
1500 return -1; 1500 return -1;
1501 } 1501 }
1502 if ((desired_xfer_len == 0) && !data.final) { 1502 if ((desired_xfer_len == 0) && !data.final) {
1503 iscsi_trace_error(__FILE__, __LINE__, "Final bit not set on the last data PDU of this sequence\n"); 1503 iscsi_trace_error(__FILE__, __LINE__, "Final bit not set on the last data PDU of this sequence\n");
1504 args->status = 0x02; 1504 args->status = 0x02;
1505 TTD_CLEANUP; 1505 TTD_CLEANUP;
1506 return -1; 1506 return -1;
1507 } 1507 }
1508 if ((desired_xfer_len == 0) && (args->bytes_recv < args->trans_len)) { 1508 if ((desired_xfer_len == 0) && (args->bytes_recv < args->trans_len)) {
1509 r2t_flag = 0; 1509 r2t_flag = 0;
1510 } 1510 }
1511 } while (args->bytes_recv < args->trans_len); 1511 } while (args->bytes_recv < args->trans_len);
1512 RETURN_NOT_EQUAL("Final bit", data.final, 1, TTD_CLEANUP, -1); 1512 RETURN_NOT_EQUAL("Final bit", data.final, 1, TTD_CLEANUP, -1);
1513 } else { 1513 } else {
1514 RETURN_NOT_EQUAL("Final bit", args->final, 1, TTD_CLEANUP, -1); 1514 RETURN_NOT_EQUAL("Final bit", args->final, 1, TTD_CLEANUP, -1);
1515 } 1515 }
1516 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully transferred %u bytes write data\n", args->trans_len); 1516 iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "successfully transferred %u bytes write data\n", args->trans_len);
1517 TTD_CLEANUP; 1517 TTD_CLEANUP;
1518 return 0; 1518 return 0;
1519} 1519}
1520 1520
1521 1521
1522 1522
1523 1523
1524/******************** 1524/********************
1525 * Public Functions * 1525 * Public Functions *
1526 ********************/ 1526 ********************/
1527 1527
1528int  1528int
1529target_init(globals_t *gp, targv_t *tv, char *TargetName) 1529target_init(globals_t *gp, targv_t *tv, char *TargetName)
1530{ 1530{
1531 int i; 1531 int i;
1532 1532
1533 NEWARRAY(target_session_t, g_session, gp->max_sessions, "target_init", return -1); 1533 NEWARRAY(target_session_t, g_session, gp->max_sessions, "target_init", return -1);
1534 (void) strlcpy(gp->targetname, TargetName, sizeof(gp->targetname)); 1534 (void) strlcpy(gp->targetname, TargetName, sizeof(gp->targetname));
1535 if (gp->state == TARGET_INITIALIZING || gp->state == TARGET_INITIALIZED) { 1535 if (gp->state == TARGET_INITIALIZING || gp->state == TARGET_INITIALIZED) {
1536 iscsi_trace_error(__FILE__, __LINE__, "duplicate target initialization attempted\n"); 1536 iscsi_trace_error(__FILE__, __LINE__, "duplicate target initialization attempted\n");
1537 return -1; 1537 return -1;
1538 } 1538 }
1539 gp->state = TARGET_INITIALIZING; 1539 gp->state = TARGET_INITIALIZING;
1540 if (iscsi_queue_init(&g_session_q, gp->max_sessions) != 0) { 1540 if (iscsi_queue_init(&g_session_q, gp->max_sessions) != 0) {
1541 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n"); 1541 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_init() failed\n");
1542 return -1; 1542 return -1;
1543 } 1543 }
1544 gp->tv = tv; 1544 gp->tv = tv;
1545 for (i = 0; i < gp->max_sessions; i++) { 1545 for (i = 0; i < gp->max_sessions; i++) {
1546 g_session[i].id = i; 1546 g_session[i].id = i;
1547 if (iscsi_queue_insert(&g_session_q, &g_session[i]) != 0) { 1547 if (iscsi_queue_insert(&g_session_q, &g_session[i]) != 0) {
1548 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n"); 1548 iscsi_trace_error(__FILE__, __LINE__, "iscsi_queue_insert() failed\n");
1549 return -1; 1549 return -1;
1550 } 1550 }
1551 } 1551 }