xref: /freebsd/sys/cam/ctl/ctl_frontend_iscsi.c (revision a4dc509f723944821bcfcc52005ff87c9a5dee5b)
1 /*-
2  * Copyright (c) 2012 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Edward Tomasz Napierala under sponsorship
6  * from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 /*
33  * CTL frontend for the iSCSI protocol.
34  */
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 #include <sys/param.h>
40 #include <sys/capsicum.h>
41 #include <sys/condvar.h>
42 #include <sys/file.h>
43 #include <sys/kernel.h>
44 #include <sys/kthread.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/module.h>
48 #include <sys/mutex.h>
49 #include <sys/queue.h>
50 #include <sys/sbuf.h>
51 #include <sys/sysctl.h>
52 #include <sys/systm.h>
53 #include <sys/uio.h>
54 #include <sys/unistd.h>
55 #include <vm/uma.h>
56 
57 #include <cam/scsi/scsi_all.h>
58 #include <cam/scsi/scsi_da.h>
59 #include <cam/ctl/ctl_io.h>
60 #include <cam/ctl/ctl.h>
61 #include <cam/ctl/ctl_backend.h>
62 #include <cam/ctl/ctl_error.h>
63 #include <cam/ctl/ctl_frontend.h>
64 #include <cam/ctl/ctl_debug.h>
65 #include <cam/ctl/ctl_ha.h>
66 #include <cam/ctl/ctl_ioctl.h>
67 #include <cam/ctl/ctl_private.h>
68 
69 #include <dev/iscsi/icl.h>
70 #include <dev/iscsi/icl_wrappers.h>
71 #include <dev/iscsi/iscsi_proto.h>
72 #include <cam/ctl/ctl_frontend_iscsi.h>
73 
74 #ifdef ICL_KERNEL_PROXY
75 #include <sys/socketvar.h>
76 #endif
77 
78 #ifdef ICL_KERNEL_PROXY
79 FEATURE(cfiscsi_kernel_proxy, "iSCSI target built with ICL_KERNEL_PROXY");
80 #endif
81 
82 static MALLOC_DEFINE(M_CFISCSI, "cfiscsi", "Memory used for CTL iSCSI frontend");
83 static uma_zone_t cfiscsi_data_wait_zone;
84 
85 SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, iscsi, CTLFLAG_RD, 0,
86     "CAM Target Layer iSCSI Frontend");
87 static int debug = 1;
88 SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN,
89     &debug, 1, "Enable debug messages");
90 static int ping_timeout = 5;
91 SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, ping_timeout, CTLFLAG_RWTUN,
92     &ping_timeout, 5, "Interval between ping (NOP-Out) requests, in seconds");
93 static int login_timeout = 60;
94 SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, login_timeout, CTLFLAG_RWTUN,
95     &login_timeout, 60, "Time to wait for ctld(8) to finish Login Phase, in seconds");
96 static int maxcmdsn_delta = 256;
97 SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, maxcmdsn_delta, CTLFLAG_RWTUN,
98     &maxcmdsn_delta, 256, "Number of commands the initiator can send "
99     "without confirmation");
100 
101 #define	CFISCSI_DEBUG(X, ...)						\
102 	do {								\
103 		if (debug > 1) {					\
104 			printf("%s: " X "\n",				\
105 			    __func__, ## __VA_ARGS__);			\
106 		}							\
107 	} while (0)
108 
109 #define	CFISCSI_WARN(X, ...)						\
110 	do {								\
111 		if (debug > 0) {					\
112 			printf("WARNING: %s: " X "\n",			\
113 			    __func__, ## __VA_ARGS__);			\
114 		}							\
115 	} while (0)
116 
117 #define	CFISCSI_SESSION_DEBUG(S, X, ...)				\
118 	do {								\
119 		if (debug > 1) {					\
120 			printf("%s: %s (%s): " X "\n",			\
121 			    __func__, S->cs_initiator_addr,		\
122 			    S->cs_initiator_name, ## __VA_ARGS__);	\
123 		}							\
124 	} while (0)
125 
126 #define	CFISCSI_SESSION_WARN(S, X, ...)					\
127 	do  {								\
128 		if (debug > 0) {					\
129 			printf("WARNING: %s (%s): " X "\n",		\
130 			    S->cs_initiator_addr,			\
131 			    S->cs_initiator_name, ## __VA_ARGS__);	\
132 		}							\
133 	} while (0)
134 
135 #define CFISCSI_SESSION_LOCK(X)		mtx_lock(&X->cs_lock)
136 #define CFISCSI_SESSION_UNLOCK(X)	mtx_unlock(&X->cs_lock)
137 #define CFISCSI_SESSION_LOCK_ASSERT(X)	mtx_assert(&X->cs_lock, MA_OWNED)
138 
139 #define	CONN_SESSION(X)			((struct cfiscsi_session *)(X)->ic_prv0)
140 #define	PDU_SESSION(X)			CONN_SESSION((X)->ip_conn)
141 #define	PDU_EXPDATASN(X)		(X)->ip_prv0
142 #define	PDU_TOTAL_TRANSFER_LEN(X)	(X)->ip_prv1
143 #define	PDU_R2TSN(X)			(X)->ip_prv2
144 
145 int		cfiscsi_init(void);
146 static void	cfiscsi_online(void *arg);
147 static void	cfiscsi_offline(void *arg);
148 static int	cfiscsi_info(void *arg, struct sbuf *sb);
149 static int	cfiscsi_ioctl(struct cdev *dev,
150 		    u_long cmd, caddr_t addr, int flag, struct thread *td);
151 static void	cfiscsi_datamove(union ctl_io *io);
152 static void	cfiscsi_datamove_in(union ctl_io *io);
153 static void	cfiscsi_datamove_out(union ctl_io *io);
154 static void	cfiscsi_done(union ctl_io *io);
155 static bool	cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request);
156 static void	cfiscsi_pdu_handle_nop_out(struct icl_pdu *request);
157 static void	cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request);
158 static void	cfiscsi_pdu_handle_task_request(struct icl_pdu *request);
159 static void	cfiscsi_pdu_handle_data_out(struct icl_pdu *request);
160 static void	cfiscsi_pdu_handle_logout_request(struct icl_pdu *request);
161 static void	cfiscsi_session_terminate(struct cfiscsi_session *cs);
162 static struct cfiscsi_data_wait	*cfiscsi_data_wait_new(
163 		    struct cfiscsi_session *cs, union ctl_io *io,
164 		    uint32_t initiator_task_tag,
165 		    uint32_t *target_transfer_tagp);
166 static void	cfiscsi_data_wait_free(struct cfiscsi_session *cs,
167 		    struct cfiscsi_data_wait *cdw);
168 static struct cfiscsi_target	*cfiscsi_target_find(struct cfiscsi_softc
169 		    *softc, const char *name, uint16_t tag);
170 static struct cfiscsi_target	*cfiscsi_target_find_or_create(
171     struct cfiscsi_softc *softc, const char *name, const char *alias,
172     uint16_t tag);
173 static void	cfiscsi_target_release(struct cfiscsi_target *ct);
174 static void	cfiscsi_session_delete(struct cfiscsi_session *cs);
175 
176 static struct cfiscsi_softc cfiscsi_softc;
177 
178 static struct ctl_frontend cfiscsi_frontend =
179 {
180 	.name = "iscsi",
181 	.init = cfiscsi_init,
182 	.ioctl = cfiscsi_ioctl,
183 };
184 CTL_FRONTEND_DECLARE(ctlcfiscsi, cfiscsi_frontend);
185 MODULE_DEPEND(ctlcfiscsi, icl, 1, 1, 1);
186 
187 static struct icl_pdu *
188 cfiscsi_pdu_new_response(struct icl_pdu *request, int flags)
189 {
190 
191 	return (icl_pdu_new(request->ip_conn, flags));
192 }
193 
194 static bool
195 cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request)
196 {
197 	const struct iscsi_bhs_scsi_command *bhssc;
198 	struct cfiscsi_session *cs;
199 	uint32_t cmdsn, expstatsn;
200 
201 	cs = PDU_SESSION(request);
202 
203 	/*
204 	 * Every incoming PDU - not just NOP-Out - resets the ping timer.
205 	 * The purpose of the timeout is to reset the connection when it stalls;
206 	 * we don't want this to happen when NOP-In or NOP-Out ends up delayed
207 	 * in some queue.
208 	 *
209 	 * XXX: Locking?
210 	 */
211 	cs->cs_timeout = 0;
212 
213 	/*
214 	 * Data-Out PDUs don't contain CmdSN.
215 	 */
216 	if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
217 	    ISCSI_BHS_OPCODE_SCSI_DATA_OUT)
218 		return (false);
219 
220 	/*
221 	 * We're only using fields common for all the request
222 	 * (initiator -> target) PDUs.
223 	 */
224 	bhssc = (const struct iscsi_bhs_scsi_command *)request->ip_bhs;
225 	cmdsn = ntohl(bhssc->bhssc_cmdsn);
226 	expstatsn = ntohl(bhssc->bhssc_expstatsn);
227 
228 	CFISCSI_SESSION_LOCK(cs);
229 #if 0
230 	if (expstatsn != cs->cs_statsn) {
231 		CFISCSI_SESSION_DEBUG(cs, "received PDU with ExpStatSN %d, "
232 		    "while current StatSN is %d", expstatsn,
233 		    cs->cs_statsn);
234 	}
235 #endif
236 
237 	if ((request->ip_bhs->bhs_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) {
238 		/*
239 		 * The target MUST silently ignore any non-immediate command
240 		 * outside of this range.
241 		 */
242 		if (ISCSI_SNLT(cmdsn, cs->cs_cmdsn) ||
243 		    ISCSI_SNGT(cmdsn, cs->cs_cmdsn + maxcmdsn_delta)) {
244 			CFISCSI_SESSION_UNLOCK(cs);
245 			CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %u, "
246 			    "while expected %u", cmdsn, cs->cs_cmdsn);
247 			return (true);
248 		}
249 
250 		/*
251 		 * We don't support multiple connections now, so any
252 		 * discontinuity in CmdSN means lost PDUs.  Since we don't
253 		 * support PDU retransmission -- terminate the connection.
254 		 */
255 		if (cmdsn != cs->cs_cmdsn) {
256 			CFISCSI_SESSION_UNLOCK(cs);
257 			CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %u, "
258 			    "while expected %u; dropping connection",
259 			    cmdsn, cs->cs_cmdsn);
260 			cfiscsi_session_terminate(cs);
261 			return (true);
262 		}
263 		cs->cs_cmdsn++;
264 	}
265 
266 	CFISCSI_SESSION_UNLOCK(cs);
267 
268 	return (false);
269 }
270 
271 static void
272 cfiscsi_pdu_handle(struct icl_pdu *request)
273 {
274 	struct cfiscsi_session *cs;
275 	bool ignore;
276 
277 	cs = PDU_SESSION(request);
278 
279 	ignore = cfiscsi_pdu_update_cmdsn(request);
280 	if (ignore) {
281 		icl_pdu_free(request);
282 		return;
283 	}
284 
285 	/*
286 	 * Handle the PDU; this includes e.g. receiving the remaining
287 	 * part of PDU and submitting the SCSI command to CTL
288 	 * or queueing a reply.  The handling routine is responsible
289 	 * for freeing the PDU when it's no longer needed.
290 	 */
291 	switch (request->ip_bhs->bhs_opcode &
292 	    ~ISCSI_BHS_OPCODE_IMMEDIATE) {
293 	case ISCSI_BHS_OPCODE_NOP_OUT:
294 		cfiscsi_pdu_handle_nop_out(request);
295 		break;
296 	case ISCSI_BHS_OPCODE_SCSI_COMMAND:
297 		cfiscsi_pdu_handle_scsi_command(request);
298 		break;
299 	case ISCSI_BHS_OPCODE_TASK_REQUEST:
300 		cfiscsi_pdu_handle_task_request(request);
301 		break;
302 	case ISCSI_BHS_OPCODE_SCSI_DATA_OUT:
303 		cfiscsi_pdu_handle_data_out(request);
304 		break;
305 	case ISCSI_BHS_OPCODE_LOGOUT_REQUEST:
306 		cfiscsi_pdu_handle_logout_request(request);
307 		break;
308 	default:
309 		CFISCSI_SESSION_WARN(cs, "received PDU with unsupported "
310 		    "opcode 0x%x; dropping connection",
311 		    request->ip_bhs->bhs_opcode);
312 		icl_pdu_free(request);
313 		cfiscsi_session_terminate(cs);
314 	}
315 
316 }
317 
318 static void
319 cfiscsi_receive_callback(struct icl_pdu *request)
320 {
321 	struct cfiscsi_session *cs;
322 
323 	cs = PDU_SESSION(request);
324 
325 #ifdef ICL_KERNEL_PROXY
326 	if (cs->cs_waiting_for_ctld || cs->cs_login_phase) {
327 		if (cs->cs_login_pdu == NULL)
328 			cs->cs_login_pdu = request;
329 		else
330 			icl_pdu_free(request);
331 		cv_signal(&cs->cs_login_cv);
332 		return;
333 	}
334 #endif
335 
336 	cfiscsi_pdu_handle(request);
337 }
338 
339 static void
340 cfiscsi_error_callback(struct icl_conn *ic)
341 {
342 	struct cfiscsi_session *cs;
343 
344 	cs = CONN_SESSION(ic);
345 
346 	CFISCSI_SESSION_WARN(cs, "connection error; dropping connection");
347 	cfiscsi_session_terminate(cs);
348 }
349 
350 static int
351 cfiscsi_pdu_prepare(struct icl_pdu *response)
352 {
353 	struct cfiscsi_session *cs;
354 	struct iscsi_bhs_scsi_response *bhssr;
355 	bool advance_statsn = true;
356 
357 	cs = PDU_SESSION(response);
358 
359 	CFISCSI_SESSION_LOCK_ASSERT(cs);
360 
361 	/*
362 	 * We're only using fields common for all the response
363 	 * (target -> initiator) PDUs.
364 	 */
365 	bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs;
366 
367 	/*
368 	 * 10.8.3: "The StatSN for this connection is not advanced
369 	 * after this PDU is sent."
370 	 */
371 	if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_R2T)
372 		advance_statsn = false;
373 
374 	/*
375 	 * 10.19.2: "However, when the Initiator Task Tag is set to 0xffffffff,
376 	 * StatSN for the connection is not advanced after this PDU is sent."
377 	 */
378 	if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_NOP_IN &&
379 	    bhssr->bhssr_initiator_task_tag == 0xffffffff)
380 		advance_statsn = false;
381 
382 	/*
383 	 * See the comment below - StatSN is not meaningful and must
384 	 * not be advanced.
385 	 */
386 	if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_SCSI_DATA_IN &&
387 	    (bhssr->bhssr_flags & BHSDI_FLAGS_S) == 0)
388 		advance_statsn = false;
389 
390 	/*
391 	 * 10.7.3: "The fields StatSN, Status, and Residual Count
392 	 * only have meaningful content if the S bit is set to 1."
393 	 */
394 	if (bhssr->bhssr_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN ||
395 	    (bhssr->bhssr_flags & BHSDI_FLAGS_S))
396 		bhssr->bhssr_statsn = htonl(cs->cs_statsn);
397 	bhssr->bhssr_expcmdsn = htonl(cs->cs_cmdsn);
398 	bhssr->bhssr_maxcmdsn = htonl(cs->cs_cmdsn + maxcmdsn_delta);
399 
400 	if (advance_statsn)
401 		cs->cs_statsn++;
402 
403 	return (0);
404 }
405 
406 static void
407 cfiscsi_pdu_queue(struct icl_pdu *response)
408 {
409 	struct cfiscsi_session *cs;
410 
411 	cs = PDU_SESSION(response);
412 
413 	CFISCSI_SESSION_LOCK(cs);
414 	cfiscsi_pdu_prepare(response);
415 	icl_pdu_queue(response);
416 	CFISCSI_SESSION_UNLOCK(cs);
417 }
418 
419 static uint32_t
420 cfiscsi_decode_lun(uint64_t encoded)
421 {
422 	uint8_t lun[8];
423 	uint32_t result;
424 
425 	/*
426 	 * The LUN field in iSCSI PDUs may look like an ordinary 64 bit number,
427 	 * but is in fact an evil, multidimensional structure defined
428 	 * in SCSI Architecture Model 5 (SAM-5), section 4.6.
429 	 */
430 	memcpy(lun, &encoded, sizeof(lun));
431 	switch (lun[0] & 0xC0) {
432 	case 0x00:
433 		if ((lun[0] & 0x3f) != 0 || lun[2] != 0 || lun[3] != 0 ||
434 		    lun[4] != 0 || lun[5] != 0 || lun[6] != 0 || lun[7] != 0) {
435 			CFISCSI_WARN("malformed LUN "
436 			    "(peripheral device addressing method): 0x%jx",
437 			    (uintmax_t)encoded);
438 			result = 0xffffffff;
439 			break;
440 		}
441 		result = lun[1];
442 		break;
443 	case 0x40:
444 		if (lun[2] != 0 || lun[3] != 0 || lun[4] != 0 || lun[5] != 0 ||
445 		    lun[6] != 0 || lun[7] != 0) {
446 			CFISCSI_WARN("malformed LUN "
447 			    "(flat address space addressing method): 0x%jx",
448 			    (uintmax_t)encoded);
449 			result = 0xffffffff;
450 			break;
451 		}
452 		result = ((lun[0] & 0x3f) << 8) + lun[1];
453 		break;
454 	case 0xC0:
455 		if (lun[0] != 0xD2 || lun[4] != 0 || lun[5] != 0 ||
456 		    lun[6] != 0 || lun[7] != 0) {
457 			CFISCSI_WARN("malformed LUN (extended flat "
458 			    "address space addressing method): 0x%jx",
459 			    (uintmax_t)encoded);
460 			result = 0xffffffff;
461 			break;
462 		}
463 		result = (lun[1] << 16) + (lun[2] << 8) + lun[3];
464 		break;
465 	default:
466 		CFISCSI_WARN("unsupported LUN format 0x%jx",
467 		    (uintmax_t)encoded);
468 		result = 0xffffffff;
469 		break;
470 	}
471 
472 	return (result);
473 }
474 
475 static void
476 cfiscsi_pdu_handle_nop_out(struct icl_pdu *request)
477 {
478 	struct cfiscsi_session *cs;
479 	struct iscsi_bhs_nop_out *bhsno;
480 	struct iscsi_bhs_nop_in *bhsni;
481 	struct icl_pdu *response;
482 	void *data = NULL;
483 	size_t datasize;
484 	int error;
485 
486 	cs = PDU_SESSION(request);
487 	bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
488 
489 	if (bhsno->bhsno_initiator_task_tag == 0xffffffff) {
490 		/*
491 		 * Nothing to do, iscsi_pdu_update_statsn() already
492 		 * zeroed the timeout.
493 		 */
494 		icl_pdu_free(request);
495 		return;
496 	}
497 
498 	datasize = icl_pdu_data_segment_length(request);
499 	if (datasize > 0) {
500 		data = malloc(datasize, M_CFISCSI, M_NOWAIT | M_ZERO);
501 		if (data == NULL) {
502 			CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
503 			    "dropping connection");
504 			icl_pdu_free(request);
505 			cfiscsi_session_terminate(cs);
506 			return;
507 		}
508 		icl_pdu_get_data(request, 0, data, datasize);
509 	}
510 
511 	response = cfiscsi_pdu_new_response(request, M_NOWAIT);
512 	if (response == NULL) {
513 		CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
514 		    "droppping connection");
515 		free(data, M_CFISCSI);
516 		icl_pdu_free(request);
517 		cfiscsi_session_terminate(cs);
518 		return;
519 	}
520 	bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs;
521 	bhsni->bhsni_opcode = ISCSI_BHS_OPCODE_NOP_IN;
522 	bhsni->bhsni_flags = 0x80;
523 	bhsni->bhsni_initiator_task_tag = bhsno->bhsno_initiator_task_tag;
524 	bhsni->bhsni_target_transfer_tag = 0xffffffff;
525 	if (datasize > 0) {
526 		error = icl_pdu_append_data(response, data, datasize, M_NOWAIT);
527 		if (error != 0) {
528 			CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
529 			    "dropping connection");
530 			free(data, M_CFISCSI);
531 			icl_pdu_free(request);
532 			icl_pdu_free(response);
533 			cfiscsi_session_terminate(cs);
534 			return;
535 		}
536 		free(data, M_CFISCSI);
537 	}
538 
539 	icl_pdu_free(request);
540 	cfiscsi_pdu_queue(response);
541 }
542 
543 static void
544 cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request)
545 {
546 	struct iscsi_bhs_scsi_command *bhssc;
547 	struct cfiscsi_session *cs;
548 	union ctl_io *io;
549 	int error;
550 
551 	cs = PDU_SESSION(request);
552 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
553 	//CFISCSI_SESSION_DEBUG(cs, "initiator task tag 0x%x",
554 	//    bhssc->bhssc_initiator_task_tag);
555 
556 	if (request->ip_data_len > 0 && cs->cs_immediate_data == false) {
557 		CFISCSI_SESSION_WARN(cs, "unsolicited data with "
558 		    "ImmediateData=No; dropping connection");
559 		icl_pdu_free(request);
560 		cfiscsi_session_terminate(cs);
561 		return;
562 	}
563 	io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref);
564 	ctl_zero_io(io);
565 	io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = request;
566 	io->io_hdr.io_type = CTL_IO_SCSI;
567 	io->io_hdr.nexus.initid = cs->cs_ctl_initid;
568 	io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
569 	io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhssc->bhssc_lun);
570 	io->scsiio.tag_num = bhssc->bhssc_initiator_task_tag;
571 	switch ((bhssc->bhssc_flags & BHSSC_FLAGS_ATTR)) {
572 	case BHSSC_FLAGS_ATTR_UNTAGGED:
573 		io->scsiio.tag_type = CTL_TAG_UNTAGGED;
574 		break;
575 	case BHSSC_FLAGS_ATTR_SIMPLE:
576 		io->scsiio.tag_type = CTL_TAG_SIMPLE;
577 		break;
578 	case BHSSC_FLAGS_ATTR_ORDERED:
579         	io->scsiio.tag_type = CTL_TAG_ORDERED;
580 		break;
581 	case BHSSC_FLAGS_ATTR_HOQ:
582         	io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
583 		break;
584 	case BHSSC_FLAGS_ATTR_ACA:
585 		io->scsiio.tag_type = CTL_TAG_ACA;
586 		break;
587 	default:
588 		io->scsiio.tag_type = CTL_TAG_UNTAGGED;
589 		CFISCSI_SESSION_WARN(cs, "unhandled tag type %d",
590 		    bhssc->bhssc_flags & BHSSC_FLAGS_ATTR);
591 		break;
592 	}
593 	io->scsiio.cdb_len = sizeof(bhssc->bhssc_cdb); /* Which is 16. */
594 	memcpy(io->scsiio.cdb, bhssc->bhssc_cdb, sizeof(bhssc->bhssc_cdb));
595 	refcount_acquire(&cs->cs_outstanding_ctl_pdus);
596 	error = ctl_queue(io);
597 	if (error != CTL_RETVAL_COMPLETE) {
598 		CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d; "
599 		    "dropping connection", error);
600 		ctl_free_io(io);
601 		refcount_release(&cs->cs_outstanding_ctl_pdus);
602 		icl_pdu_free(request);
603 		cfiscsi_session_terminate(cs);
604 	}
605 }
606 
607 static void
608 cfiscsi_pdu_handle_task_request(struct icl_pdu *request)
609 {
610 	struct iscsi_bhs_task_management_request *bhstmr;
611 	struct iscsi_bhs_task_management_response *bhstmr2;
612 	struct icl_pdu *response;
613 	struct cfiscsi_session *cs;
614 	union ctl_io *io;
615 	int error;
616 
617 	cs = PDU_SESSION(request);
618 	bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs;
619 	io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref);
620 	ctl_zero_io(io);
621 	io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = request;
622 	io->io_hdr.io_type = CTL_IO_TASK;
623 	io->io_hdr.nexus.initid = cs->cs_ctl_initid;
624 	io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
625 	io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhstmr->bhstmr_lun);
626 	io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */
627 
628 	switch (bhstmr->bhstmr_function & ~0x80) {
629 	case BHSTMR_FUNCTION_ABORT_TASK:
630 #if 0
631 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_ABORT_TASK");
632 #endif
633 		io->taskio.task_action = CTL_TASK_ABORT_TASK;
634 		io->taskio.tag_num = bhstmr->bhstmr_referenced_task_tag;
635 		break;
636 	case BHSTMR_FUNCTION_ABORT_TASK_SET:
637 #if 0
638 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_ABORT_TASK_SET");
639 #endif
640 		io->taskio.task_action = CTL_TASK_ABORT_TASK_SET;
641 		break;
642 	case BHSTMR_FUNCTION_CLEAR_TASK_SET:
643 #if 0
644 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_CLEAR_TASK_SET");
645 #endif
646 		io->taskio.task_action = CTL_TASK_CLEAR_TASK_SET;
647 		break;
648 	case BHSTMR_FUNCTION_LOGICAL_UNIT_RESET:
649 #if 0
650 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_LOGICAL_UNIT_RESET");
651 #endif
652 		io->taskio.task_action = CTL_TASK_LUN_RESET;
653 		break;
654 	case BHSTMR_FUNCTION_TARGET_WARM_RESET:
655 #if 0
656 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_TARGET_WARM_RESET");
657 #endif
658 		io->taskio.task_action = CTL_TASK_TARGET_RESET;
659 		break;
660 	case BHSTMR_FUNCTION_TARGET_COLD_RESET:
661 #if 0
662 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_TARGET_COLD_RESET");
663 #endif
664 		io->taskio.task_action = CTL_TASK_TARGET_RESET;
665 		break;
666 	case BHSTMR_FUNCTION_QUERY_TASK:
667 #if 0
668 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_TASK");
669 #endif
670 		io->taskio.task_action = CTL_TASK_QUERY_TASK;
671 		io->taskio.tag_num = bhstmr->bhstmr_referenced_task_tag;
672 		break;
673 	case BHSTMR_FUNCTION_QUERY_TASK_SET:
674 #if 0
675 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_TASK_SET");
676 #endif
677 		io->taskio.task_action = CTL_TASK_QUERY_TASK_SET;
678 		break;
679 	case BHSTMR_FUNCTION_I_T_NEXUS_RESET:
680 #if 0
681 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_I_T_NEXUS_RESET");
682 #endif
683 		io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET;
684 		break;
685 	case BHSTMR_FUNCTION_QUERY_ASYNC_EVENT:
686 #if 0
687 		CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_ASYNC_EVENT");
688 #endif
689 		io->taskio.task_action = CTL_TASK_QUERY_ASYNC_EVENT;
690 		break;
691 	default:
692 		CFISCSI_SESSION_DEBUG(cs, "unsupported function 0x%x",
693 		    bhstmr->bhstmr_function & ~0x80);
694 		ctl_free_io(io);
695 
696 		response = cfiscsi_pdu_new_response(request, M_NOWAIT);
697 		if (response == NULL) {
698 			CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
699 			    "dropping connection");
700 			icl_pdu_free(request);
701 			cfiscsi_session_terminate(cs);
702 			return;
703 		}
704 		bhstmr2 = (struct iscsi_bhs_task_management_response *)
705 		    response->ip_bhs;
706 		bhstmr2->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_RESPONSE;
707 		bhstmr2->bhstmr_flags = 0x80;
708 		bhstmr2->bhstmr_response =
709 		    BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED;
710 		bhstmr2->bhstmr_initiator_task_tag =
711 		    bhstmr->bhstmr_initiator_task_tag;
712 		icl_pdu_free(request);
713 		cfiscsi_pdu_queue(response);
714 		return;
715 	}
716 
717 	refcount_acquire(&cs->cs_outstanding_ctl_pdus);
718 	error = ctl_queue(io);
719 	if (error != CTL_RETVAL_COMPLETE) {
720 		CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d; "
721 		    "dropping connection", error);
722 		ctl_free_io(io);
723 		refcount_release(&cs->cs_outstanding_ctl_pdus);
724 		icl_pdu_free(request);
725 		cfiscsi_session_terminate(cs);
726 	}
727 }
728 
729 static bool
730 cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *cdw)
731 {
732 	struct iscsi_bhs_data_out *bhsdo;
733 	struct cfiscsi_session *cs;
734 	struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
735 	size_t copy_len, len, off, buffer_offset;
736 	int ctl_sg_count;
737 	union ctl_io *io;
738 
739 	cs = PDU_SESSION(request);
740 
741 	KASSERT((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
742 	    ISCSI_BHS_OPCODE_SCSI_DATA_OUT ||
743 	    (request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
744 	    ISCSI_BHS_OPCODE_SCSI_COMMAND,
745 	    ("bad opcode 0x%x", request->ip_bhs->bhs_opcode));
746 
747 	/*
748 	 * We're only using fields common for Data-Out and SCSI Command PDUs.
749 	 */
750 	bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs;
751 
752 	io = cdw->cdw_ctl_io;
753 	KASSERT((io->io_hdr.flags & CTL_FLAG_DATA_MASK) != CTL_FLAG_DATA_IN,
754 	    ("CTL_FLAG_DATA_IN"));
755 
756 #if 0
757 	CFISCSI_SESSION_DEBUG(cs, "received %zd bytes out of %d",
758 	    request->ip_data_len, io->scsiio.kern_total_len);
759 #endif
760 
761 	if (io->scsiio.kern_sg_entries > 0) {
762 		ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
763 		ctl_sg_count = io->scsiio.kern_sg_entries;
764 	} else {
765 		ctl_sglist = &ctl_sg_entry;
766 		ctl_sglist->addr = io->scsiio.kern_data_ptr;
767 		ctl_sglist->len = io->scsiio.kern_data_len;
768 		ctl_sg_count = 1;
769 	}
770 
771 	if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
772 	    ISCSI_BHS_OPCODE_SCSI_DATA_OUT)
773 		buffer_offset = ntohl(bhsdo->bhsdo_buffer_offset);
774 	else
775 		buffer_offset = 0;
776 	len = icl_pdu_data_segment_length(request);
777 
778 	/*
779 	 * Make sure the offset, as sent by the initiator, matches the offset
780 	 * we're supposed to be at in the scatter-gather list.
781 	 */
782 	if (buffer_offset >
783 	    io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled ||
784 	    buffer_offset + len <=
785 	    io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled) {
786 		CFISCSI_SESSION_WARN(cs, "received bad buffer offset %zd, "
787 		    "expected %zd; dropping connection", buffer_offset,
788 		    (size_t)io->scsiio.kern_rel_offset +
789 		    (size_t)io->scsiio.ext_data_filled);
790 		ctl_set_data_phase_error(&io->scsiio);
791 		cfiscsi_session_terminate(cs);
792 		return (true);
793 	}
794 
795 	/*
796 	 * This is the offset within the PDU data segment, as opposed
797 	 * to buffer_offset, which is the offset within the task (SCSI
798 	 * command).
799 	 */
800 	off = io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled -
801 	    buffer_offset;
802 
803 	/*
804 	 * Iterate over the scatter/gather segments, filling them with data
805 	 * from the PDU data segment.  Note that this can get called multiple
806 	 * times for one SCSI command; the cdw structure holds state for the
807 	 * scatter/gather list.
808 	 */
809 	for (;;) {
810 		KASSERT(cdw->cdw_sg_index < ctl_sg_count,
811 		    ("cdw->cdw_sg_index >= ctl_sg_count"));
812 		if (cdw->cdw_sg_len == 0) {
813 			cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr;
814 			cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len;
815 		}
816 		KASSERT(off <= len, ("len > off"));
817 		copy_len = len - off;
818 		if (copy_len > cdw->cdw_sg_len)
819 			copy_len = cdw->cdw_sg_len;
820 
821 		icl_pdu_get_data(request, off, cdw->cdw_sg_addr, copy_len);
822 		cdw->cdw_sg_addr += copy_len;
823 		cdw->cdw_sg_len -= copy_len;
824 		off += copy_len;
825 		io->scsiio.ext_data_filled += copy_len;
826 
827 		if (cdw->cdw_sg_len == 0) {
828 			/*
829 			 * End of current segment.
830 			 */
831 			if (cdw->cdw_sg_index == ctl_sg_count - 1) {
832 				/*
833 				 * Last segment in scatter/gather list.
834 				 */
835 				break;
836 			}
837 			cdw->cdw_sg_index++;
838 		}
839 
840 		if (off == len) {
841 			/*
842 			 * End of PDU payload.
843 			 */
844 			break;
845 		}
846 	}
847 
848 	if (len > off) {
849 		/*
850 		 * In case of unsolicited data, it's possible that the buffer
851 		 * provided by CTL is smaller than negotiated FirstBurstLength.
852 		 * Just ignore the superfluous data; will ask for them with R2T
853 		 * on next call to cfiscsi_datamove().
854 		 *
855 		 * This obviously can only happen with SCSI Command PDU.
856 		 */
857 		if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
858 		    ISCSI_BHS_OPCODE_SCSI_COMMAND)
859 			return (true);
860 
861 		CFISCSI_SESSION_WARN(cs, "received too much data: got %zd bytes, "
862 		    "expected %zd; dropping connection",
863 		    icl_pdu_data_segment_length(request), off);
864 		ctl_set_data_phase_error(&io->scsiio);
865 		cfiscsi_session_terminate(cs);
866 		return (true);
867 	}
868 
869 	if (io->scsiio.ext_data_filled == cdw->cdw_r2t_end &&
870 	    (bhsdo->bhsdo_flags & BHSDO_FLAGS_F) == 0) {
871 		CFISCSI_SESSION_WARN(cs, "got the final packet without "
872 		    "the F flag; flags = 0x%x; dropping connection",
873 		    bhsdo->bhsdo_flags);
874 		ctl_set_data_phase_error(&io->scsiio);
875 		cfiscsi_session_terminate(cs);
876 		return (true);
877 	}
878 
879 	if (io->scsiio.ext_data_filled != cdw->cdw_r2t_end &&
880 	    (bhsdo->bhsdo_flags & BHSDO_FLAGS_F) != 0) {
881 		if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
882 		    ISCSI_BHS_OPCODE_SCSI_DATA_OUT) {
883 			CFISCSI_SESSION_WARN(cs, "got the final packet, but the "
884 			    "transmitted size was %zd bytes instead of %d; "
885 			    "dropping connection",
886 			    (size_t)io->scsiio.ext_data_filled,
887 			    cdw->cdw_r2t_end);
888 			ctl_set_data_phase_error(&io->scsiio);
889 			cfiscsi_session_terminate(cs);
890 			return (true);
891 		} else {
892 			/*
893 			 * For SCSI Command PDU, this just means we need to
894 			 * solicit more data by sending R2T.
895 			 */
896 			return (false);
897 		}
898 	}
899 
900 	if (io->scsiio.ext_data_filled == cdw->cdw_r2t_end) {
901 #if 0
902 		CFISCSI_SESSION_DEBUG(cs, "no longer expecting Data-Out with target "
903 		    "transfer tag 0x%x", cdw->cdw_target_transfer_tag);
904 #endif
905 
906 		return (true);
907 	}
908 
909 	return (false);
910 }
911 
912 static void
913 cfiscsi_pdu_handle_data_out(struct icl_pdu *request)
914 {
915 	struct iscsi_bhs_data_out *bhsdo;
916 	struct cfiscsi_session *cs;
917 	struct cfiscsi_data_wait *cdw = NULL;
918 	union ctl_io *io;
919 	bool done;
920 
921 	cs = PDU_SESSION(request);
922 	bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs;
923 
924 	CFISCSI_SESSION_LOCK(cs);
925 	TAILQ_FOREACH(cdw, &cs->cs_waiting_for_data_out, cdw_next) {
926 #if 0
927 		CFISCSI_SESSION_DEBUG(cs, "have ttt 0x%x, itt 0x%x; looking for "
928 		    "ttt 0x%x, itt 0x%x",
929 		    bhsdo->bhsdo_target_transfer_tag,
930 		    bhsdo->bhsdo_initiator_task_tag,
931 		    cdw->cdw_target_transfer_tag, cdw->cdw_initiator_task_tag));
932 #endif
933 		if (bhsdo->bhsdo_target_transfer_tag ==
934 		    cdw->cdw_target_transfer_tag)
935 			break;
936 	}
937 	CFISCSI_SESSION_UNLOCK(cs);
938 	if (cdw == NULL) {
939 		CFISCSI_SESSION_WARN(cs, "data transfer tag 0x%x, initiator task tag "
940 		    "0x%x, not found; dropping connection",
941 		    bhsdo->bhsdo_target_transfer_tag, bhsdo->bhsdo_initiator_task_tag);
942 		icl_pdu_free(request);
943 		cfiscsi_session_terminate(cs);
944 		return;
945 	}
946 
947 	if (cdw->cdw_datasn != ntohl(bhsdo->bhsdo_datasn)) {
948 		CFISCSI_SESSION_WARN(cs, "received Data-Out PDU with "
949 		    "DataSN %u, while expected %u; dropping connection",
950 		    ntohl(bhsdo->bhsdo_datasn), cdw->cdw_datasn);
951 		icl_pdu_free(request);
952 		cfiscsi_session_terminate(cs);
953 		return;
954 	}
955 	cdw->cdw_datasn++;
956 
957 	io = cdw->cdw_ctl_io;
958 	KASSERT((io->io_hdr.flags & CTL_FLAG_DATA_MASK) != CTL_FLAG_DATA_IN,
959 	    ("CTL_FLAG_DATA_IN"));
960 
961 	done = cfiscsi_handle_data_segment(request, cdw);
962 	if (done) {
963 		CFISCSI_SESSION_LOCK(cs);
964 		TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next);
965 		CFISCSI_SESSION_UNLOCK(cs);
966 		done = (io->scsiio.ext_data_filled != cdw->cdw_r2t_end ||
967 		    io->scsiio.ext_data_filled == io->scsiio.kern_data_len);
968 		cfiscsi_data_wait_free(cs, cdw);
969 		io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
970 		if (done)
971 			io->scsiio.be_move_done(io);
972 		else
973 			cfiscsi_datamove_out(io);
974 	}
975 
976 	icl_pdu_free(request);
977 }
978 
979 static void
980 cfiscsi_pdu_handle_logout_request(struct icl_pdu *request)
981 {
982 	struct iscsi_bhs_logout_request *bhslr;
983 	struct iscsi_bhs_logout_response *bhslr2;
984 	struct icl_pdu *response;
985 	struct cfiscsi_session *cs;
986 
987 	cs = PDU_SESSION(request);
988 	bhslr = (struct iscsi_bhs_logout_request *)request->ip_bhs;
989 	switch (bhslr->bhslr_reason & 0x7f) {
990 	case BHSLR_REASON_CLOSE_SESSION:
991 	case BHSLR_REASON_CLOSE_CONNECTION:
992 		response = cfiscsi_pdu_new_response(request, M_NOWAIT);
993 		if (response == NULL) {
994 			CFISCSI_SESSION_DEBUG(cs, "failed to allocate memory");
995 			icl_pdu_free(request);
996 			cfiscsi_session_terminate(cs);
997 			return;
998 		}
999 		bhslr2 = (struct iscsi_bhs_logout_response *)response->ip_bhs;
1000 		bhslr2->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_RESPONSE;
1001 		bhslr2->bhslr_flags = 0x80;
1002 		bhslr2->bhslr_response = BHSLR_RESPONSE_CLOSED_SUCCESSFULLY;
1003 		bhslr2->bhslr_initiator_task_tag =
1004 		    bhslr->bhslr_initiator_task_tag;
1005 		icl_pdu_free(request);
1006 		cfiscsi_pdu_queue(response);
1007 		cfiscsi_session_terminate(cs);
1008 		break;
1009 	case BHSLR_REASON_REMOVE_FOR_RECOVERY:
1010 		response = cfiscsi_pdu_new_response(request, M_NOWAIT);
1011 		if (response == NULL) {
1012 			CFISCSI_SESSION_WARN(cs,
1013 			    "failed to allocate memory; dropping connection");
1014 			icl_pdu_free(request);
1015 			cfiscsi_session_terminate(cs);
1016 			return;
1017 		}
1018 		bhslr2 = (struct iscsi_bhs_logout_response *)response->ip_bhs;
1019 		bhslr2->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_RESPONSE;
1020 		bhslr2->bhslr_flags = 0x80;
1021 		bhslr2->bhslr_response = BHSLR_RESPONSE_RECOVERY_NOT_SUPPORTED;
1022 		bhslr2->bhslr_initiator_task_tag =
1023 		    bhslr->bhslr_initiator_task_tag;
1024 		icl_pdu_free(request);
1025 		cfiscsi_pdu_queue(response);
1026 		break;
1027 	default:
1028 		CFISCSI_SESSION_WARN(cs, "invalid reason 0%x; dropping connection",
1029 		    bhslr->bhslr_reason);
1030 		icl_pdu_free(request);
1031 		cfiscsi_session_terminate(cs);
1032 		break;
1033 	}
1034 }
1035 
1036 static void
1037 cfiscsi_callout(void *context)
1038 {
1039 	struct icl_pdu *cp;
1040 	struct iscsi_bhs_nop_in *bhsni;
1041 	struct cfiscsi_session *cs;
1042 
1043 	cs = context;
1044 
1045 	if (cs->cs_terminating)
1046 		return;
1047 
1048 	callout_schedule(&cs->cs_callout, 1 * hz);
1049 
1050 	atomic_add_int(&cs->cs_timeout, 1);
1051 
1052 #ifdef ICL_KERNEL_PROXY
1053 	if (cs->cs_waiting_for_ctld || cs->cs_login_phase) {
1054 		if (login_timeout > 0 && cs->cs_timeout > login_timeout) {
1055 			CFISCSI_SESSION_WARN(cs, "login timed out after "
1056 			    "%d seconds; dropping connection", cs->cs_timeout);
1057 			cfiscsi_session_terminate(cs);
1058 		}
1059 		return;
1060 	}
1061 #endif
1062 
1063 	if (ping_timeout <= 0) {
1064 		/*
1065 		 * Pings are disabled.  Don't send NOP-In in this case;
1066 		 * user might have disabled pings to work around problems
1067 		 * with certain initiators that can't properly handle
1068 		 * NOP-In, such as iPXE.  Reset the timeout, to avoid
1069 		 * triggering reconnection, should the user decide to
1070 		 * reenable them.
1071 		 */
1072 		cs->cs_timeout = 0;
1073 		return;
1074 	}
1075 
1076 	if (cs->cs_timeout >= ping_timeout) {
1077 		CFISCSI_SESSION_WARN(cs, "no ping reply (NOP-Out) after %d seconds; "
1078 		    "dropping connection",  ping_timeout);
1079 		cfiscsi_session_terminate(cs);
1080 		return;
1081 	}
1082 
1083 	/*
1084 	 * If the ping was reset less than one second ago - which means
1085 	 * that we've received some PDU during the last second - assume
1086 	 * the traffic flows correctly and don't bother sending a NOP-Out.
1087 	 *
1088 	 * (It's 2 - one for one second, and one for incrementing is_timeout
1089 	 * earlier in this routine.)
1090 	 */
1091 	if (cs->cs_timeout < 2)
1092 		return;
1093 
1094 	cp = icl_pdu_new(cs->cs_conn, M_NOWAIT);
1095 	if (cp == NULL) {
1096 		CFISCSI_SESSION_WARN(cs, "failed to allocate memory");
1097 		return;
1098 	}
1099 	bhsni = (struct iscsi_bhs_nop_in *)cp->ip_bhs;
1100 	bhsni->bhsni_opcode = ISCSI_BHS_OPCODE_NOP_IN;
1101 	bhsni->bhsni_flags = 0x80;
1102 	bhsni->bhsni_initiator_task_tag = 0xffffffff;
1103 
1104 	cfiscsi_pdu_queue(cp);
1105 }
1106 
1107 static struct cfiscsi_data_wait *
1108 cfiscsi_data_wait_new(struct cfiscsi_session *cs, union ctl_io *io,
1109     uint32_t initiator_task_tag, uint32_t *target_transfer_tagp)
1110 {
1111 	struct cfiscsi_data_wait *cdw;
1112 	int error;
1113 
1114 	cdw = uma_zalloc(cfiscsi_data_wait_zone, M_NOWAIT | M_ZERO);
1115 	if (cdw == NULL) {
1116 		CFISCSI_SESSION_WARN(cs,
1117 		    "failed to allocate %zd bytes", sizeof(*cdw));
1118 		return (NULL);
1119 	}
1120 
1121 	error = icl_conn_transfer_setup(cs->cs_conn, io, target_transfer_tagp,
1122 	    &cdw->cdw_icl_prv);
1123 	if (error != 0) {
1124 		CFISCSI_SESSION_WARN(cs,
1125 		    "icl_conn_transfer_setup() failed with error %d", error);
1126 		uma_zfree(cfiscsi_data_wait_zone, cdw);
1127 		return (NULL);
1128 	}
1129 
1130 	cdw->cdw_ctl_io = io;
1131 	cdw->cdw_target_transfer_tag = *target_transfer_tagp;
1132 	cdw->cdw_initiator_task_tag = initiator_task_tag;
1133 
1134 	return (cdw);
1135 }
1136 
1137 static void
1138 cfiscsi_data_wait_free(struct cfiscsi_session *cs,
1139     struct cfiscsi_data_wait *cdw)
1140 {
1141 
1142 	icl_conn_transfer_done(cs->cs_conn, cdw->cdw_icl_prv);
1143 	uma_zfree(cfiscsi_data_wait_zone, cdw);
1144 }
1145 
1146 static void
1147 cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
1148 {
1149 	struct cfiscsi_data_wait *cdw;
1150 	union ctl_io *io;
1151 	int error, last, wait;
1152 
1153 	if (cs->cs_target == NULL)
1154 		return;		/* No target yet, so nothing to do. */
1155 	io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref);
1156 	ctl_zero_io(io);
1157 	io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = cs;
1158 	io->io_hdr.io_type = CTL_IO_TASK;
1159 	io->io_hdr.nexus.initid = cs->cs_ctl_initid;
1160 	io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
1161 	io->io_hdr.nexus.targ_lun = 0;
1162 	io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */
1163 	io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET;
1164 	wait = cs->cs_outstanding_ctl_pdus;
1165 	refcount_acquire(&cs->cs_outstanding_ctl_pdus);
1166 	error = ctl_queue(io);
1167 	if (error != CTL_RETVAL_COMPLETE) {
1168 		CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d", error);
1169 		refcount_release(&cs->cs_outstanding_ctl_pdus);
1170 		ctl_free_io(io);
1171 	}
1172 
1173 	CFISCSI_SESSION_LOCK(cs);
1174 	while ((cdw = TAILQ_FIRST(&cs->cs_waiting_for_data_out)) != NULL) {
1175 		TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next);
1176 		CFISCSI_SESSION_UNLOCK(cs);
1177 		/*
1178 		 * Set nonzero port status; this prevents backends from
1179 		 * assuming that the data transfer actually succeeded
1180 		 * and writing uninitialized data to disk.
1181 		 */
1182 		cdw->cdw_ctl_io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
1183 		cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 42;
1184 		cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io);
1185 		cfiscsi_data_wait_free(cs, cdw);
1186 		CFISCSI_SESSION_LOCK(cs);
1187 	}
1188 	CFISCSI_SESSION_UNLOCK(cs);
1189 
1190 	/*
1191 	 * Wait for CTL to terminate all the tasks.
1192 	 */
1193 	if (wait > 0)
1194 		CFISCSI_SESSION_WARN(cs,
1195 		    "waiting for CTL to terminate %d tasks", wait);
1196 	for (;;) {
1197 		refcount_acquire(&cs->cs_outstanding_ctl_pdus);
1198 		last = refcount_release(&cs->cs_outstanding_ctl_pdus);
1199 		if (last != 0)
1200 			break;
1201 		tsleep(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus),
1202 		    0, "cfiscsi_terminate", hz / 100);
1203 	}
1204 	if (wait > 0)
1205 		CFISCSI_SESSION_WARN(cs, "tasks terminated");
1206 }
1207 
1208 static void
1209 cfiscsi_maintenance_thread(void *arg)
1210 {
1211 	struct cfiscsi_session *cs;
1212 
1213 	cs = arg;
1214 
1215 	for (;;) {
1216 		CFISCSI_SESSION_LOCK(cs);
1217 		if (cs->cs_terminating == false)
1218 			cv_wait(&cs->cs_maintenance_cv, &cs->cs_lock);
1219 		CFISCSI_SESSION_UNLOCK(cs);
1220 
1221 		if (cs->cs_terminating) {
1222 
1223 			/*
1224 			 * We used to wait up to 30 seconds to deliver queued
1225 			 * PDUs to the initiator.  We also tried hard to deliver
1226 			 * SCSI Responses for the aborted PDUs.  We don't do
1227 			 * that anymore.  We might need to revisit that.
1228 			 */
1229 			callout_drain(&cs->cs_callout);
1230 			icl_conn_close(cs->cs_conn);
1231 
1232 			/*
1233 			 * At this point ICL receive thread is no longer
1234 			 * running; no new tasks can be queued.
1235 			 */
1236 			cfiscsi_session_terminate_tasks(cs);
1237 			cfiscsi_session_delete(cs);
1238 			kthread_exit();
1239 			return;
1240 		}
1241 		CFISCSI_SESSION_DEBUG(cs, "nothing to do");
1242 	}
1243 }
1244 
1245 static void
1246 cfiscsi_session_terminate(struct cfiscsi_session *cs)
1247 {
1248 
1249 	if (cs->cs_terminating)
1250 		return;
1251 	cs->cs_terminating = true;
1252 	cv_signal(&cs->cs_maintenance_cv);
1253 #ifdef ICL_KERNEL_PROXY
1254 	cv_signal(&cs->cs_login_cv);
1255 #endif
1256 }
1257 
1258 static int
1259 cfiscsi_session_register_initiator(struct cfiscsi_session *cs)
1260 {
1261 	struct cfiscsi_target *ct;
1262 	char *name;
1263 	int i;
1264 
1265 	KASSERT(cs->cs_ctl_initid == -1, ("already registered"));
1266 
1267 	ct = cs->cs_target;
1268 	name = strdup(cs->cs_initiator_id, M_CTL);
1269 	i = ctl_add_initiator(&ct->ct_port, -1, 0, name);
1270 	if (i < 0) {
1271 		CFISCSI_SESSION_WARN(cs, "ctl_add_initiator failed with error %d",
1272 		    i);
1273 		cs->cs_ctl_initid = -1;
1274 		return (1);
1275 	}
1276 	cs->cs_ctl_initid = i;
1277 #if 0
1278 	CFISCSI_SESSION_DEBUG(cs, "added initiator id %d", i);
1279 #endif
1280 
1281 	return (0);
1282 }
1283 
1284 static void
1285 cfiscsi_session_unregister_initiator(struct cfiscsi_session *cs)
1286 {
1287 	int error;
1288 
1289 	if (cs->cs_ctl_initid == -1)
1290 		return;
1291 
1292 	error = ctl_remove_initiator(&cs->cs_target->ct_port, cs->cs_ctl_initid);
1293 	if (error != 0) {
1294 		CFISCSI_SESSION_WARN(cs, "ctl_remove_initiator failed with error %d",
1295 		    error);
1296 	}
1297 	cs->cs_ctl_initid = -1;
1298 }
1299 
1300 static struct cfiscsi_session *
1301 cfiscsi_session_new(struct cfiscsi_softc *softc, const char *offload)
1302 {
1303 	struct cfiscsi_session *cs;
1304 	int error;
1305 
1306 	cs = malloc(sizeof(*cs), M_CFISCSI, M_NOWAIT | M_ZERO);
1307 	if (cs == NULL) {
1308 		CFISCSI_WARN("malloc failed");
1309 		return (NULL);
1310 	}
1311 	cs->cs_ctl_initid = -1;
1312 
1313 	refcount_init(&cs->cs_outstanding_ctl_pdus, 0);
1314 	TAILQ_INIT(&cs->cs_waiting_for_data_out);
1315 	mtx_init(&cs->cs_lock, "cfiscsi_lock", NULL, MTX_DEF);
1316 	cv_init(&cs->cs_maintenance_cv, "cfiscsi_mt");
1317 #ifdef ICL_KERNEL_PROXY
1318 	cv_init(&cs->cs_login_cv, "cfiscsi_login");
1319 #endif
1320 
1321 	cs->cs_conn = icl_new_conn(offload, "cfiscsi", &cs->cs_lock);
1322 	if (cs->cs_conn == NULL) {
1323 		free(cs, M_CFISCSI);
1324 		return (NULL);
1325 	}
1326 	cs->cs_conn->ic_receive = cfiscsi_receive_callback;
1327 	cs->cs_conn->ic_error = cfiscsi_error_callback;
1328 	cs->cs_conn->ic_prv0 = cs;
1329 
1330 	error = kthread_add(cfiscsi_maintenance_thread, cs, NULL, NULL, 0, 0, "cfiscsimt");
1331 	if (error != 0) {
1332 		CFISCSI_SESSION_WARN(cs, "kthread_add(9) failed with error %d", error);
1333 		free(cs, M_CFISCSI);
1334 		return (NULL);
1335 	}
1336 
1337 	mtx_lock(&softc->lock);
1338 	cs->cs_id = ++softc->last_session_id;
1339 	TAILQ_INSERT_TAIL(&softc->sessions, cs, cs_next);
1340 	mtx_unlock(&softc->lock);
1341 
1342 	/*
1343 	 * Start pinging the initiator.
1344 	 */
1345 	callout_init(&cs->cs_callout, 1);
1346 	callout_reset(&cs->cs_callout, 1 * hz, cfiscsi_callout, cs);
1347 
1348 	return (cs);
1349 }
1350 
1351 static void
1352 cfiscsi_session_delete(struct cfiscsi_session *cs)
1353 {
1354 	struct cfiscsi_softc *softc;
1355 
1356 	softc = &cfiscsi_softc;
1357 
1358 	KASSERT(cs->cs_outstanding_ctl_pdus == 0,
1359 	    ("destroying session with outstanding CTL pdus"));
1360 	KASSERT(TAILQ_EMPTY(&cs->cs_waiting_for_data_out),
1361 	    ("destroying session with non-empty queue"));
1362 
1363 	cfiscsi_session_unregister_initiator(cs);
1364 	if (cs->cs_target != NULL)
1365 		cfiscsi_target_release(cs->cs_target);
1366 	icl_conn_close(cs->cs_conn);
1367 	icl_conn_free(cs->cs_conn);
1368 
1369 	mtx_lock(&softc->lock);
1370 	TAILQ_REMOVE(&softc->sessions, cs, cs_next);
1371 	cv_signal(&softc->sessions_cv);
1372 	mtx_unlock(&softc->lock);
1373 
1374 	free(cs, M_CFISCSI);
1375 }
1376 
1377 int
1378 cfiscsi_init(void)
1379 {
1380 	struct cfiscsi_softc *softc;
1381 
1382 	softc = &cfiscsi_softc;
1383 	bzero(softc, sizeof(*softc));
1384 	mtx_init(&softc->lock, "cfiscsi", NULL, MTX_DEF);
1385 
1386 	cv_init(&softc->sessions_cv, "cfiscsi_sessions");
1387 #ifdef ICL_KERNEL_PROXY
1388 	cv_init(&softc->accept_cv, "cfiscsi_accept");
1389 #endif
1390 	TAILQ_INIT(&softc->sessions);
1391 	TAILQ_INIT(&softc->targets);
1392 
1393 	cfiscsi_data_wait_zone = uma_zcreate("cfiscsi_data_wait",
1394 	    sizeof(struct cfiscsi_data_wait), NULL, NULL, NULL, NULL,
1395 	    UMA_ALIGN_PTR, 0);
1396 
1397 	return (0);
1398 }
1399 
1400 #ifdef ICL_KERNEL_PROXY
1401 static void
1402 cfiscsi_accept(struct socket *so, struct sockaddr *sa, int portal_id)
1403 {
1404 	struct cfiscsi_session *cs;
1405 
1406 	cs = cfiscsi_session_new(&cfiscsi_softc, NULL);
1407 	if (cs == NULL) {
1408 		CFISCSI_WARN("failed to create session");
1409 		return;
1410 	}
1411 
1412 	icl_conn_handoff_sock(cs->cs_conn, so);
1413 	cs->cs_initiator_sa = sa;
1414 	cs->cs_portal_id = portal_id;
1415 	cs->cs_waiting_for_ctld = true;
1416 	cv_signal(&cfiscsi_softc.accept_cv);
1417 }
1418 #endif
1419 
1420 static void
1421 cfiscsi_online(void *arg)
1422 {
1423 	struct cfiscsi_softc *softc;
1424 	struct cfiscsi_target *ct;
1425 	int online;
1426 
1427 	ct = (struct cfiscsi_target *)arg;
1428 	softc = ct->ct_softc;
1429 
1430 	mtx_lock(&softc->lock);
1431 	if (ct->ct_online) {
1432 		mtx_unlock(&softc->lock);
1433 		return;
1434 	}
1435 	ct->ct_online = 1;
1436 	online = softc->online++;
1437 	mtx_unlock(&softc->lock);
1438 	if (online > 0)
1439 		return;
1440 
1441 #ifdef ICL_KERNEL_PROXY
1442 	if (softc->listener != NULL)
1443 		icl_listen_free(softc->listener);
1444 	softc->listener = icl_listen_new(cfiscsi_accept);
1445 #endif
1446 }
1447 
1448 static void
1449 cfiscsi_offline(void *arg)
1450 {
1451 	struct cfiscsi_softc *softc;
1452 	struct cfiscsi_target *ct;
1453 	struct cfiscsi_session *cs;
1454 	int online;
1455 
1456 	ct = (struct cfiscsi_target *)arg;
1457 	softc = ct->ct_softc;
1458 
1459 	mtx_lock(&softc->lock);
1460 	if (!ct->ct_online) {
1461 		mtx_unlock(&softc->lock);
1462 		return;
1463 	}
1464 	ct->ct_online = 0;
1465 	online = --softc->online;
1466 
1467 	TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1468 		if (cs->cs_target == ct)
1469 			cfiscsi_session_terminate(cs);
1470 	}
1471 	do {
1472 		TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1473 			if (cs->cs_target == ct)
1474 				break;
1475 		}
1476 		if (cs != NULL)
1477 			cv_wait(&softc->sessions_cv, &softc->lock);
1478 	} while (cs != NULL && ct->ct_online == 0);
1479 	mtx_unlock(&softc->lock);
1480 	if (online > 0)
1481 		return;
1482 
1483 #ifdef ICL_KERNEL_PROXY
1484 	icl_listen_free(softc->listener);
1485 	softc->listener = NULL;
1486 #endif
1487 }
1488 
1489 static int
1490 cfiscsi_info(void *arg, struct sbuf *sb)
1491 {
1492 	struct cfiscsi_target *ct = (struct cfiscsi_target *)arg;
1493 	int retval;
1494 
1495 	retval = sbuf_printf(sb, "\t<cfiscsi_state>%d</cfiscsi_state>\n",
1496 	    ct->ct_state);
1497 	return (retval);
1498 }
1499 
1500 static void
1501 cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
1502 {
1503 	struct cfiscsi_softc *softc;
1504 	struct cfiscsi_session *cs, *cs2;
1505 	struct cfiscsi_target *ct;
1506 	struct ctl_iscsi_handoff_params *cihp;
1507 	int error;
1508 
1509 	cihp = (struct ctl_iscsi_handoff_params *)&(ci->data);
1510 	softc = &cfiscsi_softc;
1511 
1512 	CFISCSI_DEBUG("new connection from %s (%s) to %s",
1513 	    cihp->initiator_name, cihp->initiator_addr,
1514 	    cihp->target_name);
1515 
1516 	ct = cfiscsi_target_find(softc, cihp->target_name,
1517 	    cihp->portal_group_tag);
1518 	if (ct == NULL) {
1519 		ci->status = CTL_ISCSI_ERROR;
1520 		snprintf(ci->error_str, sizeof(ci->error_str),
1521 		    "%s: target not found", __func__);
1522 		return;
1523 	}
1524 
1525 #ifdef ICL_KERNEL_PROXY
1526 	if (cihp->socket > 0 && cihp->connection_id > 0) {
1527 		snprintf(ci->error_str, sizeof(ci->error_str),
1528 		    "both socket and connection_id set");
1529 		ci->status = CTL_ISCSI_ERROR;
1530 		cfiscsi_target_release(ct);
1531 		return;
1532 	}
1533 	if (cihp->socket == 0) {
1534 		mtx_lock(&cfiscsi_softc.lock);
1535 		TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) {
1536 			if (cs->cs_id == cihp->connection_id)
1537 				break;
1538 		}
1539 		if (cs == NULL) {
1540 			mtx_unlock(&cfiscsi_softc.lock);
1541 			snprintf(ci->error_str, sizeof(ci->error_str),
1542 			    "connection not found");
1543 			ci->status = CTL_ISCSI_ERROR;
1544 			cfiscsi_target_release(ct);
1545 			return;
1546 		}
1547 		mtx_unlock(&cfiscsi_softc.lock);
1548 	} else {
1549 #endif
1550 		cs = cfiscsi_session_new(softc, cihp->offload);
1551 		if (cs == NULL) {
1552 			ci->status = CTL_ISCSI_ERROR;
1553 			snprintf(ci->error_str, sizeof(ci->error_str),
1554 			    "%s: cfiscsi_session_new failed", __func__);
1555 			cfiscsi_target_release(ct);
1556 			return;
1557 		}
1558 #ifdef ICL_KERNEL_PROXY
1559 	}
1560 #endif
1561 
1562 	/*
1563 	 * First PDU of Full Feature phase has the same CmdSN as the last
1564 	 * PDU from the Login Phase received from the initiator.  Thus,
1565 	 * the -1 below.
1566 	 */
1567 	cs->cs_cmdsn = cihp->cmdsn;
1568 	cs->cs_statsn = cihp->statsn;
1569 	cs->cs_max_data_segment_length = cihp->max_recv_data_segment_length;
1570 	cs->cs_max_burst_length = cihp->max_burst_length;
1571 	cs->cs_immediate_data = !!cihp->immediate_data;
1572 	if (cihp->header_digest == CTL_ISCSI_DIGEST_CRC32C)
1573 		cs->cs_conn->ic_header_crc32c = true;
1574 	if (cihp->data_digest == CTL_ISCSI_DIGEST_CRC32C)
1575 		cs->cs_conn->ic_data_crc32c = true;
1576 
1577 	strlcpy(cs->cs_initiator_name,
1578 	    cihp->initiator_name, sizeof(cs->cs_initiator_name));
1579 	strlcpy(cs->cs_initiator_addr,
1580 	    cihp->initiator_addr, sizeof(cs->cs_initiator_addr));
1581 	strlcpy(cs->cs_initiator_alias,
1582 	    cihp->initiator_alias, sizeof(cs->cs_initiator_alias));
1583 	memcpy(cs->cs_initiator_isid,
1584 	    cihp->initiator_isid, sizeof(cs->cs_initiator_isid));
1585 	snprintf(cs->cs_initiator_id, sizeof(cs->cs_initiator_id),
1586 	    "%s,i,0x%02x%02x%02x%02x%02x%02x", cs->cs_initiator_name,
1587 	    cihp->initiator_isid[0], cihp->initiator_isid[1],
1588 	    cihp->initiator_isid[2], cihp->initiator_isid[3],
1589 	    cihp->initiator_isid[4], cihp->initiator_isid[5]);
1590 
1591 	mtx_lock(&softc->lock);
1592 	if (ct->ct_online == 0) {
1593 		mtx_unlock(&softc->lock);
1594 		cfiscsi_session_terminate(cs);
1595 		cfiscsi_target_release(ct);
1596 		ci->status = CTL_ISCSI_ERROR;
1597 		snprintf(ci->error_str, sizeof(ci->error_str),
1598 		    "%s: port offline", __func__);
1599 		return;
1600 	}
1601 	cs->cs_target = ct;
1602 	mtx_unlock(&softc->lock);
1603 
1604 	refcount_acquire(&cs->cs_outstanding_ctl_pdus);
1605 restart:
1606 	if (!cs->cs_terminating) {
1607 		mtx_lock(&softc->lock);
1608 		TAILQ_FOREACH(cs2, &softc->sessions, cs_next) {
1609 			if (cs2 != cs && cs2->cs_tasks_aborted == false &&
1610 			    cs->cs_target == cs2->cs_target &&
1611 			    strcmp(cs->cs_initiator_id, cs2->cs_initiator_id) == 0) {
1612 				if (strcmp(cs->cs_initiator_addr,
1613 				    cs2->cs_initiator_addr) != 0) {
1614 					CFISCSI_SESSION_WARN(cs2,
1615 					    "session reinstatement from "
1616 					    "different address %s",
1617 					    cs->cs_initiator_addr);
1618 				} else {
1619 					CFISCSI_SESSION_DEBUG(cs2,
1620 					    "session reinstatement");
1621 				}
1622 				cfiscsi_session_terminate(cs2);
1623 				mtx_unlock(&softc->lock);
1624 				pause("cfiscsi_reinstate", 1);
1625 				goto restart;
1626 			}
1627 		}
1628 		mtx_unlock(&softc->lock);
1629 	}
1630 
1631 	/*
1632 	 * Register initiator with CTL.
1633 	 */
1634 	cfiscsi_session_register_initiator(cs);
1635 
1636 #ifdef ICL_KERNEL_PROXY
1637 	if (cihp->socket > 0) {
1638 #endif
1639 		error = icl_conn_handoff(cs->cs_conn, cihp->socket);
1640 		if (error != 0) {
1641 			cfiscsi_session_terminate(cs);
1642 			refcount_release(&cs->cs_outstanding_ctl_pdus);
1643 			ci->status = CTL_ISCSI_ERROR;
1644 			snprintf(ci->error_str, sizeof(ci->error_str),
1645 			    "%s: icl_conn_handoff failed with error %d",
1646 			    __func__, error);
1647 			return;
1648 		}
1649 #ifdef ICL_KERNEL_PROXY
1650 	}
1651 #endif
1652 
1653 #ifdef ICL_KERNEL_PROXY
1654 	cs->cs_login_phase = false;
1655 
1656 	/*
1657 	 * First PDU of the Full Feature phase has likely already arrived.
1658 	 * We have to pick it up and execute properly.
1659 	 */
1660 	if (cs->cs_login_pdu != NULL) {
1661 		CFISCSI_SESSION_DEBUG(cs, "picking up first PDU");
1662 		cfiscsi_pdu_handle(cs->cs_login_pdu);
1663 		cs->cs_login_pdu = NULL;
1664 	}
1665 #endif
1666 
1667 	refcount_release(&cs->cs_outstanding_ctl_pdus);
1668 	ci->status = CTL_ISCSI_OK;
1669 }
1670 
1671 static void
1672 cfiscsi_ioctl_list(struct ctl_iscsi *ci)
1673 {
1674 	struct ctl_iscsi_list_params *cilp;
1675 	struct cfiscsi_session *cs;
1676 	struct cfiscsi_softc *softc;
1677 	struct sbuf *sb;
1678 	int error;
1679 
1680 	cilp = (struct ctl_iscsi_list_params *)&(ci->data);
1681 	softc = &cfiscsi_softc;
1682 
1683 	sb = sbuf_new(NULL, NULL, cilp->alloc_len, SBUF_FIXEDLEN);
1684 	if (sb == NULL) {
1685 		ci->status = CTL_ISCSI_ERROR;
1686 		snprintf(ci->error_str, sizeof(ci->error_str),
1687 		    "Unable to allocate %d bytes for iSCSI session list",
1688 		    cilp->alloc_len);
1689 		return;
1690 	}
1691 
1692 	sbuf_printf(sb, "<ctlislist>\n");
1693 	mtx_lock(&softc->lock);
1694 	TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1695 #ifdef ICL_KERNEL_PROXY
1696 		if (cs->cs_target == NULL)
1697 			continue;
1698 #endif
1699 		error = sbuf_printf(sb, "<connection id=\"%d\">"
1700 		    "<initiator>%s</initiator>"
1701 		    "<initiator_addr>%s</initiator_addr>"
1702 		    "<initiator_alias>%s</initiator_alias>"
1703 		    "<target>%s</target>"
1704 		    "<target_alias>%s</target_alias>"
1705 		    "<target_portal_group_tag>%u</target_portal_group_tag>"
1706 		    "<header_digest>%s</header_digest>"
1707 		    "<data_digest>%s</data_digest>"
1708 		    "<max_data_segment_length>%zd</max_data_segment_length>"
1709 		    "<immediate_data>%d</immediate_data>"
1710 		    "<iser>%d</iser>"
1711 		    "<offload>%s</offload>"
1712 		    "</connection>\n",
1713 		    cs->cs_id,
1714 		    cs->cs_initiator_name, cs->cs_initiator_addr, cs->cs_initiator_alias,
1715 		    cs->cs_target->ct_name, cs->cs_target->ct_alias,
1716 		    cs->cs_target->ct_tag,
1717 		    cs->cs_conn->ic_header_crc32c ? "CRC32C" : "None",
1718 		    cs->cs_conn->ic_data_crc32c ? "CRC32C" : "None",
1719 		    cs->cs_max_data_segment_length,
1720 		    cs->cs_immediate_data,
1721 		    cs->cs_conn->ic_iser,
1722 		    cs->cs_conn->ic_offload);
1723 		if (error != 0)
1724 			break;
1725 	}
1726 	mtx_unlock(&softc->lock);
1727 	error = sbuf_printf(sb, "</ctlislist>\n");
1728 	if (error != 0) {
1729 		sbuf_delete(sb);
1730 		ci->status = CTL_ISCSI_LIST_NEED_MORE_SPACE;
1731 		snprintf(ci->error_str, sizeof(ci->error_str),
1732 		    "Out of space, %d bytes is too small", cilp->alloc_len);
1733 		return;
1734 	}
1735 	sbuf_finish(sb);
1736 
1737 	error = copyout(sbuf_data(sb), cilp->conn_xml, sbuf_len(sb) + 1);
1738 	cilp->fill_len = sbuf_len(sb) + 1;
1739 	ci->status = CTL_ISCSI_OK;
1740 	sbuf_delete(sb);
1741 }
1742 
1743 static void
1744 cfiscsi_ioctl_logout(struct ctl_iscsi *ci)
1745 {
1746 	struct icl_pdu *response;
1747 	struct iscsi_bhs_asynchronous_message *bhsam;
1748 	struct ctl_iscsi_logout_params *cilp;
1749 	struct cfiscsi_session *cs;
1750 	struct cfiscsi_softc *softc;
1751 	int found = 0;
1752 
1753 	cilp = (struct ctl_iscsi_logout_params *)&(ci->data);
1754 	softc = &cfiscsi_softc;
1755 
1756 	mtx_lock(&softc->lock);
1757 	TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1758 		if (cilp->all == 0 && cs->cs_id != cilp->connection_id &&
1759 		    strcmp(cs->cs_initiator_name, cilp->initiator_name) != 0 &&
1760 		    strcmp(cs->cs_initiator_addr, cilp->initiator_addr) != 0)
1761 			continue;
1762 
1763 		response = icl_pdu_new(cs->cs_conn, M_NOWAIT);
1764 		if (response == NULL) {
1765 			ci->status = CTL_ISCSI_ERROR;
1766 			snprintf(ci->error_str, sizeof(ci->error_str),
1767 			    "Unable to allocate memory");
1768 			mtx_unlock(&softc->lock);
1769 			return;
1770 		}
1771 		bhsam =
1772 		    (struct iscsi_bhs_asynchronous_message *)response->ip_bhs;
1773 		bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE;
1774 		bhsam->bhsam_flags = 0x80;
1775 		bhsam->bhsam_async_event = BHSAM_EVENT_TARGET_REQUESTS_LOGOUT;
1776 		bhsam->bhsam_parameter3 = htons(10);
1777 		cfiscsi_pdu_queue(response);
1778 		found++;
1779 	}
1780 	mtx_unlock(&softc->lock);
1781 
1782 	if (found == 0) {
1783 		ci->status = CTL_ISCSI_SESSION_NOT_FOUND;
1784 		snprintf(ci->error_str, sizeof(ci->error_str),
1785 		    "No matching connections found");
1786 		return;
1787 	}
1788 
1789 	ci->status = CTL_ISCSI_OK;
1790 }
1791 
1792 static void
1793 cfiscsi_ioctl_terminate(struct ctl_iscsi *ci)
1794 {
1795 	struct icl_pdu *response;
1796 	struct iscsi_bhs_asynchronous_message *bhsam;
1797 	struct ctl_iscsi_terminate_params *citp;
1798 	struct cfiscsi_session *cs;
1799 	struct cfiscsi_softc *softc;
1800 	int found = 0;
1801 
1802 	citp = (struct ctl_iscsi_terminate_params *)&(ci->data);
1803 	softc = &cfiscsi_softc;
1804 
1805 	mtx_lock(&softc->lock);
1806 	TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1807 		if (citp->all == 0 && cs->cs_id != citp->connection_id &&
1808 		    strcmp(cs->cs_initiator_name, citp->initiator_name) != 0 &&
1809 		    strcmp(cs->cs_initiator_addr, citp->initiator_addr) != 0)
1810 			continue;
1811 
1812 		response = icl_pdu_new(cs->cs_conn, M_NOWAIT);
1813 		if (response == NULL) {
1814 			/*
1815 			 * Oh well.  Just terminate the connection.
1816 			 */
1817 		} else {
1818 			bhsam = (struct iscsi_bhs_asynchronous_message *)
1819 			    response->ip_bhs;
1820 			bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE;
1821 			bhsam->bhsam_flags = 0x80;
1822 			bhsam->bhsam_0xffffffff = 0xffffffff;
1823 			bhsam->bhsam_async_event =
1824 			    BHSAM_EVENT_TARGET_TERMINATES_SESSION;
1825 			cfiscsi_pdu_queue(response);
1826 		}
1827 		cfiscsi_session_terminate(cs);
1828 		found++;
1829 	}
1830 	mtx_unlock(&softc->lock);
1831 
1832 	if (found == 0) {
1833 		ci->status = CTL_ISCSI_SESSION_NOT_FOUND;
1834 		snprintf(ci->error_str, sizeof(ci->error_str),
1835 		    "No matching connections found");
1836 		return;
1837 	}
1838 
1839 	ci->status = CTL_ISCSI_OK;
1840 }
1841 
1842 static void
1843 cfiscsi_ioctl_limits(struct ctl_iscsi *ci)
1844 {
1845 	struct ctl_iscsi_limits_params *cilp;
1846 	int error;
1847 
1848 	cilp = (struct ctl_iscsi_limits_params *)&(ci->data);
1849 
1850 	error = icl_limits(cilp->offload, &cilp->data_segment_limit);
1851 	if (error != 0) {
1852 		ci->status = CTL_ISCSI_ERROR;
1853 		snprintf(ci->error_str, sizeof(ci->error_str),
1854 			"%s: icl_limits failed with error %d",
1855 			__func__, error);
1856 		return;
1857 	}
1858 
1859 	ci->status = CTL_ISCSI_OK;
1860 }
1861 
1862 #ifdef ICL_KERNEL_PROXY
1863 static void
1864 cfiscsi_ioctl_listen(struct ctl_iscsi *ci)
1865 {
1866 	struct ctl_iscsi_listen_params *cilp;
1867 	struct sockaddr *sa;
1868 	int error;
1869 
1870 	cilp = (struct ctl_iscsi_listen_params *)&(ci->data);
1871 
1872 	if (cfiscsi_softc.listener == NULL) {
1873 		CFISCSI_DEBUG("no listener");
1874 		snprintf(ci->error_str, sizeof(ci->error_str), "no listener");
1875 		ci->status = CTL_ISCSI_ERROR;
1876 		return;
1877 	}
1878 
1879 	error = getsockaddr(&sa, (void *)cilp->addr, cilp->addrlen);
1880 	if (error != 0) {
1881 		CFISCSI_DEBUG("getsockaddr, error %d", error);
1882 		snprintf(ci->error_str, sizeof(ci->error_str), "getsockaddr failed");
1883 		ci->status = CTL_ISCSI_ERROR;
1884 		return;
1885 	}
1886 
1887 	error = icl_listen_add(cfiscsi_softc.listener, cilp->iser, cilp->domain,
1888 	    cilp->socktype, cilp->protocol, sa, cilp->portal_id);
1889 	if (error != 0) {
1890 		free(sa, M_SONAME);
1891 		CFISCSI_DEBUG("icl_listen_add, error %d", error);
1892 		snprintf(ci->error_str, sizeof(ci->error_str),
1893 		    "icl_listen_add failed, error %d", error);
1894 		ci->status = CTL_ISCSI_ERROR;
1895 		return;
1896 	}
1897 
1898 	ci->status = CTL_ISCSI_OK;
1899 }
1900 
1901 static void
1902 cfiscsi_ioctl_accept(struct ctl_iscsi *ci)
1903 {
1904 	struct ctl_iscsi_accept_params *ciap;
1905 	struct cfiscsi_session *cs;
1906 	int error;
1907 
1908 	ciap = (struct ctl_iscsi_accept_params *)&(ci->data);
1909 
1910 	mtx_lock(&cfiscsi_softc.lock);
1911 	for (;;) {
1912 		TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) {
1913 			if (cs->cs_waiting_for_ctld)
1914 				break;
1915 		}
1916 		if (cs != NULL)
1917 			break;
1918 		error = cv_wait_sig(&cfiscsi_softc.accept_cv, &cfiscsi_softc.lock);
1919 		if (error != 0) {
1920 			mtx_unlock(&cfiscsi_softc.lock);
1921 			snprintf(ci->error_str, sizeof(ci->error_str), "interrupted");
1922 			ci->status = CTL_ISCSI_ERROR;
1923 			return;
1924 		}
1925 	}
1926 	mtx_unlock(&cfiscsi_softc.lock);
1927 
1928 	cs->cs_waiting_for_ctld = false;
1929 	cs->cs_login_phase = true;
1930 
1931 	ciap->connection_id = cs->cs_id;
1932 	ciap->portal_id = cs->cs_portal_id;
1933 	ciap->initiator_addrlen = cs->cs_initiator_sa->sa_len;
1934 	error = copyout(cs->cs_initiator_sa, ciap->initiator_addr,
1935 	    cs->cs_initiator_sa->sa_len);
1936 	if (error != 0) {
1937 		snprintf(ci->error_str, sizeof(ci->error_str),
1938 		    "copyout failed with error %d", error);
1939 		ci->status = CTL_ISCSI_ERROR;
1940 		return;
1941 	}
1942 
1943 	ci->status = CTL_ISCSI_OK;
1944 }
1945 
1946 static void
1947 cfiscsi_ioctl_send(struct ctl_iscsi *ci)
1948 {
1949 	struct ctl_iscsi_send_params *cisp;
1950 	struct cfiscsi_session *cs;
1951 	struct icl_pdu *ip;
1952 	size_t datalen;
1953 	void *data;
1954 	int error;
1955 
1956 	cisp = (struct ctl_iscsi_send_params *)&(ci->data);
1957 
1958 	mtx_lock(&cfiscsi_softc.lock);
1959 	TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) {
1960 		if (cs->cs_id == cisp->connection_id)
1961 			break;
1962 	}
1963 	if (cs == NULL) {
1964 		mtx_unlock(&cfiscsi_softc.lock);
1965 		snprintf(ci->error_str, sizeof(ci->error_str), "connection not found");
1966 		ci->status = CTL_ISCSI_ERROR;
1967 		return;
1968 	}
1969 	mtx_unlock(&cfiscsi_softc.lock);
1970 
1971 #if 0
1972 	if (cs->cs_login_phase == false)
1973 		return (EBUSY);
1974 #endif
1975 
1976 	if (cs->cs_terminating) {
1977 		snprintf(ci->error_str, sizeof(ci->error_str), "connection is terminating");
1978 		ci->status = CTL_ISCSI_ERROR;
1979 		return;
1980 	}
1981 
1982 	datalen = cisp->data_segment_len;
1983 	/*
1984 	 * XXX
1985 	 */
1986 	//if (datalen > CFISCSI_MAX_DATA_SEGMENT_LENGTH) {
1987 	if (datalen > 65535) {
1988 		snprintf(ci->error_str, sizeof(ci->error_str), "data segment too big");
1989 		ci->status = CTL_ISCSI_ERROR;
1990 		return;
1991 	}
1992 	if (datalen > 0) {
1993 		data = malloc(datalen, M_CFISCSI, M_WAITOK);
1994 		error = copyin(cisp->data_segment, data, datalen);
1995 		if (error != 0) {
1996 			free(data, M_CFISCSI);
1997 			snprintf(ci->error_str, sizeof(ci->error_str), "copyin error %d", error);
1998 			ci->status = CTL_ISCSI_ERROR;
1999 			return;
2000 		}
2001 	}
2002 
2003 	ip = icl_pdu_new(cs->cs_conn, M_WAITOK);
2004 	memcpy(ip->ip_bhs, cisp->bhs, sizeof(*ip->ip_bhs));
2005 	if (datalen > 0) {
2006 		icl_pdu_append_data(ip, data, datalen, M_WAITOK);
2007 		free(data, M_CFISCSI);
2008 	}
2009 	CFISCSI_SESSION_LOCK(cs);
2010 	icl_pdu_queue(ip);
2011 	CFISCSI_SESSION_UNLOCK(cs);
2012 	ci->status = CTL_ISCSI_OK;
2013 }
2014 
2015 static void
2016 cfiscsi_ioctl_receive(struct ctl_iscsi *ci)
2017 {
2018 	struct ctl_iscsi_receive_params *cirp;
2019 	struct cfiscsi_session *cs;
2020 	struct icl_pdu *ip;
2021 	void *data;
2022 	int error;
2023 
2024 	cirp = (struct ctl_iscsi_receive_params *)&(ci->data);
2025 
2026 	mtx_lock(&cfiscsi_softc.lock);
2027 	TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) {
2028 		if (cs->cs_id == cirp->connection_id)
2029 			break;
2030 	}
2031 	if (cs == NULL) {
2032 		mtx_unlock(&cfiscsi_softc.lock);
2033 		snprintf(ci->error_str, sizeof(ci->error_str),
2034 		    "connection not found");
2035 		ci->status = CTL_ISCSI_ERROR;
2036 		return;
2037 	}
2038 	mtx_unlock(&cfiscsi_softc.lock);
2039 
2040 #if 0
2041 	if (is->is_login_phase == false)
2042 		return (EBUSY);
2043 #endif
2044 
2045 	CFISCSI_SESSION_LOCK(cs);
2046 	while (cs->cs_login_pdu == NULL && cs->cs_terminating == false) {
2047 		error = cv_wait_sig(&cs->cs_login_cv, &cs->cs_lock);
2048 		if (error != 0) {
2049 			CFISCSI_SESSION_UNLOCK(cs);
2050 			snprintf(ci->error_str, sizeof(ci->error_str),
2051 			    "interrupted by signal");
2052 			ci->status = CTL_ISCSI_ERROR;
2053 			return;
2054 		}
2055 	}
2056 
2057 	if (cs->cs_terminating) {
2058 		CFISCSI_SESSION_UNLOCK(cs);
2059 		snprintf(ci->error_str, sizeof(ci->error_str),
2060 		    "connection terminating");
2061 		ci->status = CTL_ISCSI_ERROR;
2062 		return;
2063 	}
2064 	ip = cs->cs_login_pdu;
2065 	cs->cs_login_pdu = NULL;
2066 	CFISCSI_SESSION_UNLOCK(cs);
2067 
2068 	if (ip->ip_data_len > cirp->data_segment_len) {
2069 		icl_pdu_free(ip);
2070 		snprintf(ci->error_str, sizeof(ci->error_str),
2071 		    "data segment too big");
2072 		ci->status = CTL_ISCSI_ERROR;
2073 		return;
2074 	}
2075 
2076 	copyout(ip->ip_bhs, cirp->bhs, sizeof(*ip->ip_bhs));
2077 	if (ip->ip_data_len > 0) {
2078 		data = malloc(ip->ip_data_len, M_CFISCSI, M_WAITOK);
2079 		icl_pdu_get_data(ip, 0, data, ip->ip_data_len);
2080 		copyout(data, cirp->data_segment, ip->ip_data_len);
2081 		free(data, M_CFISCSI);
2082 	}
2083 
2084 	icl_pdu_free(ip);
2085 	ci->status = CTL_ISCSI_OK;
2086 }
2087 
2088 #endif /* !ICL_KERNEL_PROXY */
2089 
2090 static void
2091 cfiscsi_ioctl_port_create(struct ctl_req *req)
2092 {
2093 	struct cfiscsi_target *ct;
2094 	struct ctl_port *port;
2095 	const char *target, *alias, *tags;
2096 	struct scsi_vpd_id_descriptor *desc;
2097 	ctl_options_t opts;
2098 	int retval, len, idlen;
2099 	uint16_t tag;
2100 
2101 	ctl_init_opts(&opts, req->num_args, req->kern_args);
2102 	target = ctl_get_opt(&opts, "cfiscsi_target");
2103 	alias = ctl_get_opt(&opts, "cfiscsi_target_alias");
2104 	tags = ctl_get_opt(&opts, "cfiscsi_portal_group_tag");
2105 	if (target == NULL || tags == NULL) {
2106 		req->status = CTL_LUN_ERROR;
2107 		snprintf(req->error_str, sizeof(req->error_str),
2108 		    "Missing required argument");
2109 		ctl_free_opts(&opts);
2110 		return;
2111 	}
2112 	tag = strtol(tags, (char **)NULL, 10);
2113 	ct = cfiscsi_target_find_or_create(&cfiscsi_softc, target, alias, tag);
2114 	if (ct == NULL) {
2115 		req->status = CTL_LUN_ERROR;
2116 		snprintf(req->error_str, sizeof(req->error_str),
2117 		    "failed to create target \"%s\"", target);
2118 		ctl_free_opts(&opts);
2119 		return;
2120 	}
2121 	if (ct->ct_state == CFISCSI_TARGET_STATE_ACTIVE) {
2122 		req->status = CTL_LUN_ERROR;
2123 		snprintf(req->error_str, sizeof(req->error_str),
2124 		    "target \"%s\" already exists", target);
2125 		cfiscsi_target_release(ct);
2126 		ctl_free_opts(&opts);
2127 		return;
2128 	}
2129 	port = &ct->ct_port;
2130 	// WAT
2131 	if (ct->ct_state == CFISCSI_TARGET_STATE_DYING)
2132 		goto done;
2133 
2134 	port->frontend = &cfiscsi_frontend;
2135 	port->port_type = CTL_PORT_ISCSI;
2136 	/* XXX KDM what should the real number be here? */
2137 	port->num_requested_ctl_io = 4096;
2138 	port->port_name = "iscsi";
2139 	port->physical_port = tag;
2140 	port->virtual_port = ct->ct_target_id;
2141 	port->port_online = cfiscsi_online;
2142 	port->port_offline = cfiscsi_offline;
2143 	port->port_info = cfiscsi_info;
2144 	port->onoff_arg = ct;
2145 	port->fe_datamove = cfiscsi_datamove;
2146 	port->fe_done = cfiscsi_done;
2147 
2148 	/* XXX KDM what should we report here? */
2149 	/* XXX These should probably be fetched from CTL. */
2150 	port->max_targets = 1;
2151 	port->max_target_id = 15;
2152 	port->targ_port = -1;
2153 
2154 	port->options = opts;
2155 	STAILQ_INIT(&opts);
2156 
2157 	/* Generate Port ID. */
2158 	idlen = strlen(target) + strlen(",t,0x0001") + 1;
2159 	idlen = roundup2(idlen, 4);
2160 	len = sizeof(struct scsi_vpd_device_id) + idlen;
2161 	port->port_devid = malloc(sizeof(struct ctl_devid) + len,
2162 	    M_CTL, M_WAITOK | M_ZERO);
2163 	port->port_devid->len = len;
2164 	desc = (struct scsi_vpd_id_descriptor *)port->port_devid->data;
2165 	desc->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8;
2166 	desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
2167 	    SVPD_ID_TYPE_SCSI_NAME;
2168 	desc->length = idlen;
2169 	snprintf(desc->identifier, idlen, "%s,t,0x%4.4x", target, tag);
2170 
2171 	/* Generate Target ID. */
2172 	idlen = strlen(target) + 1;
2173 	idlen = roundup2(idlen, 4);
2174 	len = sizeof(struct scsi_vpd_device_id) + idlen;
2175 	port->target_devid = malloc(sizeof(struct ctl_devid) + len,
2176 	    M_CTL, M_WAITOK | M_ZERO);
2177 	port->target_devid->len = len;
2178 	desc = (struct scsi_vpd_id_descriptor *)port->target_devid->data;
2179 	desc->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8;
2180 	desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_TARGET |
2181 	    SVPD_ID_TYPE_SCSI_NAME;
2182 	desc->length = idlen;
2183 	strlcpy(desc->identifier, target, idlen);
2184 
2185 	retval = ctl_port_register(port);
2186 	if (retval != 0) {
2187 		ctl_free_opts(&port->options);
2188 		cfiscsi_target_release(ct);
2189 		free(port->port_devid, M_CFISCSI);
2190 		free(port->target_devid, M_CFISCSI);
2191 		req->status = CTL_LUN_ERROR;
2192 		snprintf(req->error_str, sizeof(req->error_str),
2193 		    "ctl_port_register() failed with error %d", retval);
2194 		return;
2195 	}
2196 done:
2197 	ct->ct_state = CFISCSI_TARGET_STATE_ACTIVE;
2198 	req->status = CTL_LUN_OK;
2199 	memcpy(req->kern_args[0].kvalue, &port->targ_port,
2200 	    sizeof(port->targ_port)); //XXX
2201 }
2202 
2203 static void
2204 cfiscsi_ioctl_port_remove(struct ctl_req *req)
2205 {
2206 	struct cfiscsi_target *ct;
2207 	const char *target, *tags;
2208 	ctl_options_t opts;
2209 	uint16_t tag;
2210 
2211 	ctl_init_opts(&opts, req->num_args, req->kern_args);
2212 	target = ctl_get_opt(&opts, "cfiscsi_target");
2213 	tags = ctl_get_opt(&opts, "cfiscsi_portal_group_tag");
2214 	if (target == NULL || tags == NULL) {
2215 		ctl_free_opts(&opts);
2216 		req->status = CTL_LUN_ERROR;
2217 		snprintf(req->error_str, sizeof(req->error_str),
2218 		    "Missing required argument");
2219 		return;
2220 	}
2221 	tag = strtol(tags, (char **)NULL, 10);
2222 	ct = cfiscsi_target_find(&cfiscsi_softc, target, tag);
2223 	if (ct == NULL) {
2224 		ctl_free_opts(&opts);
2225 		req->status = CTL_LUN_ERROR;
2226 		snprintf(req->error_str, sizeof(req->error_str),
2227 		    "can't find target \"%s\"", target);
2228 		return;
2229 	}
2230 	if (ct->ct_state != CFISCSI_TARGET_STATE_ACTIVE) {
2231 		ctl_free_opts(&opts);
2232 		req->status = CTL_LUN_ERROR;
2233 		snprintf(req->error_str, sizeof(req->error_str),
2234 		    "target \"%s\" is already dying", target);
2235 		return;
2236 	}
2237 	ctl_free_opts(&opts);
2238 
2239 	ct->ct_state = CFISCSI_TARGET_STATE_DYING;
2240 	ctl_port_offline(&ct->ct_port);
2241 	cfiscsi_target_release(ct);
2242 	cfiscsi_target_release(ct);
2243 	req->status = CTL_LUN_OK;
2244 }
2245 
2246 static int
2247 cfiscsi_ioctl(struct cdev *dev,
2248     u_long cmd, caddr_t addr, int flag, struct thread *td)
2249 {
2250 	struct ctl_iscsi *ci;
2251 	struct ctl_req *req;
2252 
2253 	if (cmd == CTL_PORT_REQ) {
2254 		req = (struct ctl_req *)addr;
2255 		switch (req->reqtype) {
2256 		case CTL_REQ_CREATE:
2257 			cfiscsi_ioctl_port_create(req);
2258 			break;
2259 		case CTL_REQ_REMOVE:
2260 			cfiscsi_ioctl_port_remove(req);
2261 			break;
2262 		default:
2263 			req->status = CTL_LUN_ERROR;
2264 			snprintf(req->error_str, sizeof(req->error_str),
2265 			    "Unsupported request type %d", req->reqtype);
2266 		}
2267 		return (0);
2268 	}
2269 
2270 	if (cmd != CTL_ISCSI)
2271 		return (ENOTTY);
2272 
2273 	ci = (struct ctl_iscsi *)addr;
2274 	switch (ci->type) {
2275 	case CTL_ISCSI_HANDOFF:
2276 		cfiscsi_ioctl_handoff(ci);
2277 		break;
2278 	case CTL_ISCSI_LIST:
2279 		cfiscsi_ioctl_list(ci);
2280 		break;
2281 	case CTL_ISCSI_LOGOUT:
2282 		cfiscsi_ioctl_logout(ci);
2283 		break;
2284 	case CTL_ISCSI_TERMINATE:
2285 		cfiscsi_ioctl_terminate(ci);
2286 		break;
2287 	case CTL_ISCSI_LIMITS:
2288 		cfiscsi_ioctl_limits(ci);
2289 		break;
2290 #ifdef ICL_KERNEL_PROXY
2291 	case CTL_ISCSI_LISTEN:
2292 		cfiscsi_ioctl_listen(ci);
2293 		break;
2294 	case CTL_ISCSI_ACCEPT:
2295 		cfiscsi_ioctl_accept(ci);
2296 		break;
2297 	case CTL_ISCSI_SEND:
2298 		cfiscsi_ioctl_send(ci);
2299 		break;
2300 	case CTL_ISCSI_RECEIVE:
2301 		cfiscsi_ioctl_receive(ci);
2302 		break;
2303 #else
2304 	case CTL_ISCSI_LISTEN:
2305 	case CTL_ISCSI_ACCEPT:
2306 	case CTL_ISCSI_SEND:
2307 	case CTL_ISCSI_RECEIVE:
2308 		ci->status = CTL_ISCSI_ERROR;
2309 		snprintf(ci->error_str, sizeof(ci->error_str),
2310 		    "%s: CTL compiled without ICL_KERNEL_PROXY",
2311 		    __func__);
2312 		break;
2313 #endif /* !ICL_KERNEL_PROXY */
2314 	default:
2315 		ci->status = CTL_ISCSI_ERROR;
2316 		snprintf(ci->error_str, sizeof(ci->error_str),
2317 		    "%s: invalid iSCSI request type %d", __func__, ci->type);
2318 		break;
2319 	}
2320 
2321 	return (0);
2322 }
2323 
2324 static void
2325 cfiscsi_target_hold(struct cfiscsi_target *ct)
2326 {
2327 
2328 	refcount_acquire(&ct->ct_refcount);
2329 }
2330 
2331 static void
2332 cfiscsi_target_release(struct cfiscsi_target *ct)
2333 {
2334 	struct cfiscsi_softc *softc;
2335 
2336 	softc = ct->ct_softc;
2337 	mtx_lock(&softc->lock);
2338 	if (refcount_release(&ct->ct_refcount)) {
2339 		TAILQ_REMOVE(&softc->targets, ct, ct_next);
2340 		mtx_unlock(&softc->lock);
2341 		if (ct->ct_state != CFISCSI_TARGET_STATE_INVALID) {
2342 			ct->ct_state = CFISCSI_TARGET_STATE_INVALID;
2343 			if (ctl_port_deregister(&ct->ct_port) != 0)
2344 				printf("%s: ctl_port_deregister() failed\n",
2345 				    __func__);
2346 		}
2347 		free(ct, M_CFISCSI);
2348 
2349 		return;
2350 	}
2351 	mtx_unlock(&softc->lock);
2352 }
2353 
2354 static struct cfiscsi_target *
2355 cfiscsi_target_find(struct cfiscsi_softc *softc, const char *name, uint16_t tag)
2356 {
2357 	struct cfiscsi_target *ct;
2358 
2359 	mtx_lock(&softc->lock);
2360 	TAILQ_FOREACH(ct, &softc->targets, ct_next) {
2361 		if (ct->ct_tag != tag ||
2362 		    strcmp(name, ct->ct_name) != 0 ||
2363 		    ct->ct_state != CFISCSI_TARGET_STATE_ACTIVE)
2364 			continue;
2365 		cfiscsi_target_hold(ct);
2366 		mtx_unlock(&softc->lock);
2367 		return (ct);
2368 	}
2369 	mtx_unlock(&softc->lock);
2370 
2371 	return (NULL);
2372 }
2373 
2374 static struct cfiscsi_target *
2375 cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name,
2376     const char *alias, uint16_t tag)
2377 {
2378 	struct cfiscsi_target *ct, *newct;
2379 
2380 	if (name[0] == '\0' || strlen(name) >= CTL_ISCSI_NAME_LEN)
2381 		return (NULL);
2382 
2383 	newct = malloc(sizeof(*newct), M_CFISCSI, M_WAITOK | M_ZERO);
2384 
2385 	mtx_lock(&softc->lock);
2386 	TAILQ_FOREACH(ct, &softc->targets, ct_next) {
2387 		if (ct->ct_tag != tag ||
2388 		    strcmp(name, ct->ct_name) != 0 ||
2389 		    ct->ct_state == CFISCSI_TARGET_STATE_INVALID)
2390 			continue;
2391 		cfiscsi_target_hold(ct);
2392 		mtx_unlock(&softc->lock);
2393 		free(newct, M_CFISCSI);
2394 		return (ct);
2395 	}
2396 
2397 	strlcpy(newct->ct_name, name, sizeof(newct->ct_name));
2398 	if (alias != NULL)
2399 		strlcpy(newct->ct_alias, alias, sizeof(newct->ct_alias));
2400 	newct->ct_tag = tag;
2401 	refcount_init(&newct->ct_refcount, 1);
2402 	newct->ct_softc = softc;
2403 	if (TAILQ_EMPTY(&softc->targets))
2404 		softc->last_target_id = 0;
2405 	newct->ct_target_id = ++softc->last_target_id;
2406 	TAILQ_INSERT_TAIL(&softc->targets, newct, ct_next);
2407 	mtx_unlock(&softc->lock);
2408 
2409 	return (newct);
2410 }
2411 
2412 static void
2413 cfiscsi_datamove_in(union ctl_io *io)
2414 {
2415 	struct cfiscsi_session *cs;
2416 	struct icl_pdu *request, *response;
2417 	const struct iscsi_bhs_scsi_command *bhssc;
2418 	struct iscsi_bhs_data_in *bhsdi;
2419 	struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
2420 	size_t len, expected_len, sg_len, buffer_offset;
2421 	const char *sg_addr;
2422 	int ctl_sg_count, error, i;
2423 
2424 	request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
2425 	cs = PDU_SESSION(request);
2426 
2427 	bhssc = (const struct iscsi_bhs_scsi_command *)request->ip_bhs;
2428 	KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
2429 	    ISCSI_BHS_OPCODE_SCSI_COMMAND,
2430 	    ("bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_COMMAND"));
2431 
2432 	if (io->scsiio.kern_sg_entries > 0) {
2433 		ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
2434 		ctl_sg_count = io->scsiio.kern_sg_entries;
2435 	} else {
2436 		ctl_sglist = &ctl_sg_entry;
2437 		ctl_sglist->addr = io->scsiio.kern_data_ptr;
2438 		ctl_sglist->len = io->scsiio.kern_data_len;
2439 		ctl_sg_count = 1;
2440 	}
2441 
2442 	/*
2443 	 * This is the total amount of data to be transferred within the current
2444 	 * SCSI command.  We need to record it so that we can properly report
2445 	 * underflow/underflow.
2446 	 */
2447 	PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len;
2448 
2449 	/*
2450 	 * This is the offset within the current SCSI command; for the first
2451 	 * call to cfiscsi_datamove() it will be 0, and for subsequent ones
2452 	 * it will be the sum of lengths of previous ones.
2453 	 */
2454 	buffer_offset = io->scsiio.kern_rel_offset;
2455 
2456 	/*
2457 	 * This is the transfer length expected by the initiator.  In theory,
2458 	 * it could be different from the correct amount of data from the SCSI
2459 	 * point of view, even if that doesn't make any sense.
2460 	 */
2461 	expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length);
2462 #if 0
2463 	if (expected_len != io->scsiio.kern_total_len) {
2464 		CFISCSI_SESSION_DEBUG(cs, "expected transfer length %zd, "
2465 		    "actual length %zd", expected_len,
2466 		    (size_t)io->scsiio.kern_total_len);
2467 	}
2468 #endif
2469 
2470 	if (buffer_offset >= expected_len) {
2471 #if 0
2472 		CFISCSI_SESSION_DEBUG(cs, "buffer_offset = %zd, "
2473 		    "already sent the expected len", buffer_offset);
2474 #endif
2475 		io->scsiio.be_move_done(io);
2476 		return;
2477 	}
2478 
2479 	i = 0;
2480 	sg_addr = NULL;
2481 	sg_len = 0;
2482 	response = NULL;
2483 	bhsdi = NULL;
2484 	for (;;) {
2485 		if (response == NULL) {
2486 			response = cfiscsi_pdu_new_response(request, M_NOWAIT);
2487 			if (response == NULL) {
2488 				CFISCSI_SESSION_WARN(cs, "failed to "
2489 				    "allocate memory; dropping connection");
2490 				ctl_set_busy(&io->scsiio);
2491 				io->scsiio.be_move_done(io);
2492 				cfiscsi_session_terminate(cs);
2493 				return;
2494 			}
2495 			bhsdi = (struct iscsi_bhs_data_in *)response->ip_bhs;
2496 			bhsdi->bhsdi_opcode = ISCSI_BHS_OPCODE_SCSI_DATA_IN;
2497 			bhsdi->bhsdi_initiator_task_tag =
2498 			    bhssc->bhssc_initiator_task_tag;
2499 			bhsdi->bhsdi_datasn = htonl(PDU_EXPDATASN(request));
2500 			PDU_EXPDATASN(request)++;
2501 			bhsdi->bhsdi_buffer_offset = htonl(buffer_offset);
2502 		}
2503 
2504 		KASSERT(i < ctl_sg_count, ("i >= ctl_sg_count"));
2505 		if (sg_len == 0) {
2506 			sg_addr = ctl_sglist[i].addr;
2507 			sg_len = ctl_sglist[i].len;
2508 			KASSERT(sg_len > 0, ("sg_len <= 0"));
2509 		}
2510 
2511 		len = sg_len;
2512 
2513 		/*
2514 		 * Truncate to maximum data segment length.
2515 		 */
2516 		KASSERT(response->ip_data_len < cs->cs_max_data_segment_length,
2517 		    ("ip_data_len %zd >= max_data_segment_length %zd",
2518 		    response->ip_data_len, cs->cs_max_data_segment_length));
2519 		if (response->ip_data_len + len >
2520 		    cs->cs_max_data_segment_length) {
2521 			len = cs->cs_max_data_segment_length -
2522 			    response->ip_data_len;
2523 			KASSERT(len <= sg_len, ("len %zd > sg_len %zd",
2524 			    len, sg_len));
2525 		}
2526 
2527 		/*
2528 		 * Truncate to expected data transfer length.
2529 		 */
2530 		KASSERT(buffer_offset + response->ip_data_len < expected_len,
2531 		    ("buffer_offset %zd + ip_data_len %zd >= expected_len %zd",
2532 		    buffer_offset, response->ip_data_len, expected_len));
2533 		if (buffer_offset + response->ip_data_len + len > expected_len) {
2534 			CFISCSI_SESSION_DEBUG(cs, "truncating from %zd "
2535 			    "to expected data transfer length %zd",
2536 			    buffer_offset + response->ip_data_len + len, expected_len);
2537 			len = expected_len - (buffer_offset + response->ip_data_len);
2538 			KASSERT(len <= sg_len, ("len %zd > sg_len %zd",
2539 			    len, sg_len));
2540 		}
2541 
2542 		error = icl_pdu_append_data(response, sg_addr, len, M_NOWAIT);
2543 		if (error != 0) {
2544 			CFISCSI_SESSION_WARN(cs, "failed to "
2545 			    "allocate memory; dropping connection");
2546 			icl_pdu_free(response);
2547 			ctl_set_busy(&io->scsiio);
2548 			io->scsiio.be_move_done(io);
2549 			cfiscsi_session_terminate(cs);
2550 			return;
2551 		}
2552 		sg_addr += len;
2553 		sg_len -= len;
2554 
2555 		KASSERT(buffer_offset + response->ip_data_len <= expected_len,
2556 		    ("buffer_offset %zd + ip_data_len %zd > expected_len %zd",
2557 		    buffer_offset, response->ip_data_len, expected_len));
2558 		if (buffer_offset + response->ip_data_len == expected_len) {
2559 			/*
2560 			 * Already have the amount of data the initiator wanted.
2561 			 */
2562 			break;
2563 		}
2564 
2565 		if (sg_len == 0) {
2566 			/*
2567 			 * End of scatter-gather segment;
2568 			 * proceed to the next one...
2569 			 */
2570 			if (i == ctl_sg_count - 1) {
2571 				/*
2572 				 * ... unless this was the last one.
2573 				 */
2574 				break;
2575 			}
2576 			i++;
2577 		}
2578 
2579 		if (response->ip_data_len == cs->cs_max_data_segment_length) {
2580 			/*
2581 			 * Can't stuff more data into the current PDU;
2582 			 * queue it.  Note that's not enough to check
2583 			 * for kern_data_resid == 0 instead; there
2584 			 * may be several Data-In PDUs for the final
2585 			 * call to cfiscsi_datamove(), and we want
2586 			 * to set the F flag only on the last of them.
2587 			 */
2588 			buffer_offset += response->ip_data_len;
2589 			if (buffer_offset == io->scsiio.kern_total_len ||
2590 			    buffer_offset == expected_len) {
2591 				buffer_offset -= response->ip_data_len;
2592 				break;
2593 			}
2594 			cfiscsi_pdu_queue(response);
2595 			response = NULL;
2596 			bhsdi = NULL;
2597 		}
2598 	}
2599 	if (response != NULL) {
2600 		buffer_offset += response->ip_data_len;
2601 		if (buffer_offset == io->scsiio.kern_total_len ||
2602 		    buffer_offset == expected_len) {
2603 			bhsdi->bhsdi_flags |= BHSDI_FLAGS_F;
2604 			if (io->io_hdr.status == CTL_SUCCESS) {
2605 				bhsdi->bhsdi_flags |= BHSDI_FLAGS_S;
2606 				if (PDU_TOTAL_TRANSFER_LEN(request) <
2607 				    ntohl(bhssc->bhssc_expected_data_transfer_length)) {
2608 					bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_UNDERFLOW;
2609 					bhsdi->bhsdi_residual_count =
2610 					    htonl(ntohl(bhssc->bhssc_expected_data_transfer_length) -
2611 					    PDU_TOTAL_TRANSFER_LEN(request));
2612 				} else if (PDU_TOTAL_TRANSFER_LEN(request) >
2613 				    ntohl(bhssc->bhssc_expected_data_transfer_length)) {
2614 					bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_OVERFLOW;
2615 					bhsdi->bhsdi_residual_count =
2616 					    htonl(PDU_TOTAL_TRANSFER_LEN(request) -
2617 					    ntohl(bhssc->bhssc_expected_data_transfer_length));
2618 				}
2619 				bhsdi->bhsdi_status = io->scsiio.scsi_status;
2620 				io->io_hdr.flags |= CTL_FLAG_STATUS_SENT;
2621 			}
2622 		}
2623 		KASSERT(response->ip_data_len > 0, ("sending empty Data-In"));
2624 		cfiscsi_pdu_queue(response);
2625 	}
2626 
2627 	io->scsiio.be_move_done(io);
2628 }
2629 
2630 static void
2631 cfiscsi_datamove_out(union ctl_io *io)
2632 {
2633 	struct cfiscsi_session *cs;
2634 	struct icl_pdu *request, *response;
2635 	const struct iscsi_bhs_scsi_command *bhssc;
2636 	struct iscsi_bhs_r2t *bhsr2t;
2637 	struct cfiscsi_data_wait *cdw;
2638 	struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
2639 	uint32_t expected_len, r2t_off, r2t_len;
2640 	uint32_t target_transfer_tag;
2641 	bool done;
2642 
2643 	request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
2644 	cs = PDU_SESSION(request);
2645 
2646 	bhssc = (const struct iscsi_bhs_scsi_command *)request->ip_bhs;
2647 	KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
2648 	    ISCSI_BHS_OPCODE_SCSI_COMMAND,
2649 	    ("bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_COMMAND"));
2650 
2651 	/*
2652 	 * We need to record it so that we can properly report
2653 	 * underflow/underflow.
2654 	 */
2655 	PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len;
2656 
2657 	/*
2658 	 * Report write underflow as error since CTL and backends don't
2659 	 * really support it, and SCSI does not tell how to do it right.
2660 	 */
2661 	expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length);
2662 	if (io->scsiio.kern_rel_offset + io->scsiio.kern_data_len >
2663 	    expected_len) {
2664 		io->scsiio.io_hdr.port_status = 43;
2665 		io->scsiio.be_move_done(io);
2666 		return;
2667 	}
2668 
2669 	target_transfer_tag =
2670 	    atomic_fetchadd_32(&cs->cs_target_transfer_tag, 1);
2671 	cdw = cfiscsi_data_wait_new(cs, io, bhssc->bhssc_initiator_task_tag,
2672 	    &target_transfer_tag);
2673 	if (cdw == NULL) {
2674 		CFISCSI_SESSION_WARN(cs, "failed to "
2675 		    "allocate memory; dropping connection");
2676 		ctl_set_busy(&io->scsiio);
2677 		io->scsiio.be_move_done(io);
2678 		cfiscsi_session_terminate(cs);
2679 		return;
2680 	}
2681 #if 0
2682 	CFISCSI_SESSION_DEBUG(cs, "expecting Data-Out with initiator "
2683 	    "task tag 0x%x, target transfer tag 0x%x",
2684 	    bhssc->bhssc_initiator_task_tag, target_transfer_tag);
2685 #endif
2686 
2687 	cdw->cdw_ctl_io = io;
2688 	cdw->cdw_target_transfer_tag = target_transfer_tag;
2689 	cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
2690 	cdw->cdw_r2t_end = io->scsiio.kern_data_len;
2691 	cdw->cdw_datasn = 0;
2692 
2693 	/* Set initial data pointer for the CDW respecting ext_data_filled. */
2694 	if (io->scsiio.kern_sg_entries > 0) {
2695 		ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
2696 	} else {
2697 		ctl_sglist = &ctl_sg_entry;
2698 		ctl_sglist->addr = io->scsiio.kern_data_ptr;
2699 		ctl_sglist->len = io->scsiio.kern_data_len;
2700 	}
2701 	cdw->cdw_sg_index = 0;
2702 	cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr;
2703 	cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len;
2704 	r2t_off = io->scsiio.ext_data_filled;
2705 	while (r2t_off > 0) {
2706 		if (r2t_off >= cdw->cdw_sg_len) {
2707 			r2t_off -= cdw->cdw_sg_len;
2708 			cdw->cdw_sg_index++;
2709 			cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr;
2710 			cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len;
2711 			continue;
2712 		}
2713 		cdw->cdw_sg_addr += r2t_off;
2714 		cdw->cdw_sg_len -= r2t_off;
2715 		r2t_off = 0;
2716 	}
2717 
2718 	if (cs->cs_immediate_data &&
2719 	    io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled <
2720 	    icl_pdu_data_segment_length(request)) {
2721 		done = cfiscsi_handle_data_segment(request, cdw);
2722 		if (done) {
2723 			cfiscsi_data_wait_free(cs, cdw);
2724 			io->scsiio.be_move_done(io);
2725 			return;
2726 		}
2727 	}
2728 
2729 	r2t_off = io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled;
2730 	r2t_len = MIN(io->scsiio.kern_data_len - io->scsiio.ext_data_filled,
2731 	    cs->cs_max_burst_length);
2732 	cdw->cdw_r2t_end = io->scsiio.ext_data_filled + r2t_len;
2733 
2734 	CFISCSI_SESSION_LOCK(cs);
2735 	TAILQ_INSERT_TAIL(&cs->cs_waiting_for_data_out, cdw, cdw_next);
2736 	CFISCSI_SESSION_UNLOCK(cs);
2737 
2738 	/*
2739 	 * XXX: We should limit the number of outstanding R2T PDUs
2740 	 * 	per task to MaxOutstandingR2T.
2741 	 */
2742 	response = cfiscsi_pdu_new_response(request, M_NOWAIT);
2743 	if (response == NULL) {
2744 		CFISCSI_SESSION_WARN(cs, "failed to "
2745 		    "allocate memory; dropping connection");
2746 		ctl_set_busy(&io->scsiio);
2747 		io->scsiio.be_move_done(io);
2748 		cfiscsi_session_terminate(cs);
2749 		return;
2750 	}
2751 	io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
2752 	bhsr2t = (struct iscsi_bhs_r2t *)response->ip_bhs;
2753 	bhsr2t->bhsr2t_opcode = ISCSI_BHS_OPCODE_R2T;
2754 	bhsr2t->bhsr2t_flags = 0x80;
2755 	bhsr2t->bhsr2t_lun = bhssc->bhssc_lun;
2756 	bhsr2t->bhsr2t_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
2757 	bhsr2t->bhsr2t_target_transfer_tag = target_transfer_tag;
2758 	/*
2759 	 * XXX: Here we assume that cfiscsi_datamove() won't ever
2760 	 *	be running concurrently on several CPUs for a given
2761 	 *	command.
2762 	 */
2763 	bhsr2t->bhsr2t_r2tsn = htonl(PDU_R2TSN(request));
2764 	PDU_R2TSN(request)++;
2765 	/*
2766 	 * This is the offset within the current SCSI command;
2767 	 * i.e. for the first call of datamove(), it will be 0,
2768 	 * and for subsequent ones it will be the sum of lengths
2769 	 * of previous ones.
2770 	 *
2771 	 * The ext_data_filled is to account for unsolicited
2772 	 * (immediate) data that might have already arrived.
2773 	 */
2774 	bhsr2t->bhsr2t_buffer_offset = htonl(r2t_off);
2775 	/*
2776 	 * This is the total length (sum of S/G lengths) this call
2777 	 * to cfiscsi_datamove() is supposed to handle, limited by
2778 	 * MaxBurstLength.
2779 	 */
2780 	bhsr2t->bhsr2t_desired_data_transfer_length = htonl(r2t_len);
2781 	cfiscsi_pdu_queue(response);
2782 }
2783 
2784 static void
2785 cfiscsi_datamove(union ctl_io *io)
2786 {
2787 
2788 	if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN)
2789 		cfiscsi_datamove_in(io);
2790 	else {
2791 		/* We hadn't received anything during this datamove yet. */
2792 		io->scsiio.ext_data_filled = 0;
2793 		cfiscsi_datamove_out(io);
2794 	}
2795 }
2796 
2797 static void
2798 cfiscsi_scsi_command_done(union ctl_io *io)
2799 {
2800 	struct icl_pdu *request, *response;
2801 	struct iscsi_bhs_scsi_command *bhssc;
2802 	struct iscsi_bhs_scsi_response *bhssr;
2803 #ifdef DIAGNOSTIC
2804 	struct cfiscsi_data_wait *cdw;
2805 #endif
2806 	struct cfiscsi_session *cs;
2807 	uint16_t sense_length;
2808 
2809 	request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
2810 	cs = PDU_SESSION(request);
2811 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
2812 	KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
2813 	    ISCSI_BHS_OPCODE_SCSI_COMMAND,
2814 	    ("replying to wrong opcode 0x%x", bhssc->bhssc_opcode));
2815 
2816 	//CFISCSI_SESSION_DEBUG(cs, "initiator task tag 0x%x",
2817 	//    bhssc->bhssc_initiator_task_tag);
2818 
2819 #ifdef DIAGNOSTIC
2820 	CFISCSI_SESSION_LOCK(cs);
2821 	TAILQ_FOREACH(cdw, &cs->cs_waiting_for_data_out, cdw_next)
2822 		KASSERT(bhssc->bhssc_initiator_task_tag !=
2823 		    cdw->cdw_initiator_task_tag, ("dangling cdw"));
2824 	CFISCSI_SESSION_UNLOCK(cs);
2825 #endif
2826 
2827 	/*
2828 	 * Do not return status for aborted commands.
2829 	 * There are exceptions, but none supported by CTL yet.
2830 	 */
2831 	if (((io->io_hdr.flags & CTL_FLAG_ABORT) &&
2832 	     (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) ||
2833 	    (io->io_hdr.flags & CTL_FLAG_STATUS_SENT)) {
2834 		ctl_free_io(io);
2835 		icl_pdu_free(request);
2836 		return;
2837 	}
2838 
2839 	response = cfiscsi_pdu_new_response(request, M_WAITOK);
2840 	bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs;
2841 	bhssr->bhssr_opcode = ISCSI_BHS_OPCODE_SCSI_RESPONSE;
2842 	bhssr->bhssr_flags = 0x80;
2843 	/*
2844 	 * XXX: We don't deal with bidirectional under/overflows;
2845 	 *	does anything actually support those?
2846 	 */
2847 	if (PDU_TOTAL_TRANSFER_LEN(request) <
2848 	    ntohl(bhssc->bhssc_expected_data_transfer_length)) {
2849 		bhssr->bhssr_flags |= BHSSR_FLAGS_RESIDUAL_UNDERFLOW;
2850 		bhssr->bhssr_residual_count =
2851 		    htonl(ntohl(bhssc->bhssc_expected_data_transfer_length) -
2852 		    PDU_TOTAL_TRANSFER_LEN(request));
2853 		//CFISCSI_SESSION_DEBUG(cs, "underflow; residual count %d",
2854 		//    ntohl(bhssr->bhssr_residual_count));
2855 	} else if (PDU_TOTAL_TRANSFER_LEN(request) >
2856 	    ntohl(bhssc->bhssc_expected_data_transfer_length)) {
2857 		bhssr->bhssr_flags |= BHSSR_FLAGS_RESIDUAL_OVERFLOW;
2858 		bhssr->bhssr_residual_count =
2859 		    htonl(PDU_TOTAL_TRANSFER_LEN(request) -
2860 		    ntohl(bhssc->bhssc_expected_data_transfer_length));
2861 		//CFISCSI_SESSION_DEBUG(cs, "overflow; residual count %d",
2862 		//    ntohl(bhssr->bhssr_residual_count));
2863 	}
2864 	bhssr->bhssr_response = BHSSR_RESPONSE_COMMAND_COMPLETED;
2865 	bhssr->bhssr_status = io->scsiio.scsi_status;
2866 	bhssr->bhssr_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
2867 	bhssr->bhssr_expdatasn = htonl(PDU_EXPDATASN(request));
2868 
2869 	if (io->scsiio.sense_len > 0) {
2870 #if 0
2871 		CFISCSI_SESSION_DEBUG(cs, "returning %d bytes of sense data",
2872 		    io->scsiio.sense_len);
2873 #endif
2874 		sense_length = htons(io->scsiio.sense_len);
2875 		icl_pdu_append_data(response,
2876 		    &sense_length, sizeof(sense_length), M_WAITOK);
2877 		icl_pdu_append_data(response,
2878 		    &io->scsiio.sense_data, io->scsiio.sense_len, M_WAITOK);
2879 	}
2880 
2881 	ctl_free_io(io);
2882 	icl_pdu_free(request);
2883 	cfiscsi_pdu_queue(response);
2884 }
2885 
2886 static void
2887 cfiscsi_task_management_done(union ctl_io *io)
2888 {
2889 	struct icl_pdu *request, *response;
2890 	struct iscsi_bhs_task_management_request *bhstmr;
2891 	struct iscsi_bhs_task_management_response *bhstmr2;
2892 	struct cfiscsi_data_wait *cdw, *tmpcdw;
2893 	struct cfiscsi_session *cs, *tcs;
2894 	struct cfiscsi_softc *softc;
2895 	int cold_reset = 0;
2896 
2897 	request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
2898 	cs = PDU_SESSION(request);
2899 	bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs;
2900 	KASSERT((bhstmr->bhstmr_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
2901 	    ISCSI_BHS_OPCODE_TASK_REQUEST,
2902 	    ("replying to wrong opcode 0x%x", bhstmr->bhstmr_opcode));
2903 
2904 #if 0
2905 	CFISCSI_SESSION_DEBUG(cs, "initiator task tag 0x%x; referenced task tag 0x%x",
2906 	    bhstmr->bhstmr_initiator_task_tag,
2907 	    bhstmr->bhstmr_referenced_task_tag);
2908 #endif
2909 
2910 	if ((bhstmr->bhstmr_function & ~0x80) ==
2911 	    BHSTMR_FUNCTION_ABORT_TASK) {
2912 		/*
2913 		 * Make sure we no longer wait for Data-Out for this command.
2914 		 */
2915 		CFISCSI_SESSION_LOCK(cs);
2916 		TAILQ_FOREACH_SAFE(cdw,
2917 		    &cs->cs_waiting_for_data_out, cdw_next, tmpcdw) {
2918 			if (bhstmr->bhstmr_referenced_task_tag !=
2919 			    cdw->cdw_initiator_task_tag)
2920 				continue;
2921 
2922 #if 0
2923 			CFISCSI_SESSION_DEBUG(cs, "removing csw for initiator task "
2924 			    "tag 0x%x", bhstmr->bhstmr_initiator_task_tag);
2925 #endif
2926 			TAILQ_REMOVE(&cs->cs_waiting_for_data_out,
2927 			    cdw, cdw_next);
2928 			io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
2929 			cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 43;
2930 			cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io);
2931 			cfiscsi_data_wait_free(cs, cdw);
2932 		}
2933 		CFISCSI_SESSION_UNLOCK(cs);
2934 	}
2935 	if ((bhstmr->bhstmr_function & ~0x80) ==
2936 	    BHSTMR_FUNCTION_TARGET_COLD_RESET &&
2937 	    io->io_hdr.status == CTL_SUCCESS)
2938 		cold_reset = 1;
2939 
2940 	response = cfiscsi_pdu_new_response(request, M_WAITOK);
2941 	bhstmr2 = (struct iscsi_bhs_task_management_response *)
2942 	    response->ip_bhs;
2943 	bhstmr2->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_RESPONSE;
2944 	bhstmr2->bhstmr_flags = 0x80;
2945 	switch (io->taskio.task_status) {
2946 	case CTL_TASK_FUNCTION_COMPLETE:
2947 		bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_COMPLETE;
2948 		break;
2949 	case CTL_TASK_FUNCTION_SUCCEEDED:
2950 		bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_SUCCEEDED;
2951 		break;
2952 	case CTL_TASK_LUN_DOES_NOT_EXIST:
2953 		bhstmr2->bhstmr_response = BHSTMR_RESPONSE_LUN_DOES_NOT_EXIST;
2954 		break;
2955 	case CTL_TASK_FUNCTION_NOT_SUPPORTED:
2956 	default:
2957 		bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED;
2958 		break;
2959 	}
2960 	memcpy(bhstmr2->bhstmr_additional_reponse_information,
2961 	    io->taskio.task_resp, sizeof(io->taskio.task_resp));
2962 	bhstmr2->bhstmr_initiator_task_tag = bhstmr->bhstmr_initiator_task_tag;
2963 
2964 	ctl_free_io(io);
2965 	icl_pdu_free(request);
2966 	cfiscsi_pdu_queue(response);
2967 
2968 	if (cold_reset) {
2969 		softc = cs->cs_target->ct_softc;
2970 		mtx_lock(&softc->lock);
2971 		TAILQ_FOREACH(tcs, &softc->sessions, cs_next) {
2972 			if (tcs->cs_target == cs->cs_target)
2973 				cfiscsi_session_terminate(tcs);
2974 		}
2975 		mtx_unlock(&softc->lock);
2976 	}
2977 }
2978 
2979 static void
2980 cfiscsi_done(union ctl_io *io)
2981 {
2982 	struct icl_pdu *request;
2983 	struct cfiscsi_session *cs;
2984 
2985 	KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE),
2986 		("invalid CTL status %#x", io->io_hdr.status));
2987 
2988 	if (io->io_hdr.io_type == CTL_IO_TASK &&
2989 	    io->taskio.task_action == CTL_TASK_I_T_NEXUS_RESET) {
2990 		/*
2991 		 * Implicit task termination has just completed; nothing to do.
2992 		 */
2993 		cs = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
2994 		cs->cs_tasks_aborted = true;
2995 		refcount_release(&cs->cs_outstanding_ctl_pdus);
2996 		wakeup(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus));
2997 		ctl_free_io(io);
2998 		return;
2999 	}
3000 
3001 	request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
3002 	cs = PDU_SESSION(request);
3003 	refcount_release(&cs->cs_outstanding_ctl_pdus);
3004 
3005 	switch (request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) {
3006 	case ISCSI_BHS_OPCODE_SCSI_COMMAND:
3007 		cfiscsi_scsi_command_done(io);
3008 		break;
3009 	case ISCSI_BHS_OPCODE_TASK_REQUEST:
3010 		cfiscsi_task_management_done(io);
3011 		break;
3012 	default:
3013 		panic("cfiscsi_done called with wrong opcode 0x%x",
3014 		    request->ip_bhs->bhs_opcode);
3015 	}
3016 }
3017