xref: /freebsd/sys/dev/iscsi/iscsi.c (revision c03c5b1c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2012 The FreeBSD Foundation
5  *
6  * This software was developed by Edward Tomasz Napierala under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 
35 #include <sys/param.h>
36 #include <sys/condvar.h>
37 #include <sys/conf.h>
38 #include <sys/endian.h>
39 #include <sys/eventhandler.h>
40 #include <sys/file.h>
41 #include <sys/kernel.h>
42 #include <sys/kthread.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mbuf.h>
46 #include <sys/mutex.h>
47 #include <sys/module.h>
48 #include <sys/socket.h>
49 #include <sys/sockopt.h>
50 #include <sys/sysctl.h>
51 #include <sys/systm.h>
52 #include <sys/sx.h>
53 #include <vm/uma.h>
54 
55 #include <cam/cam.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/cam_xpt.h>
58 #include <cam/cam_debug.h>
59 #include <cam/cam_sim.h>
60 #include <cam/cam_xpt_sim.h>
61 #include <cam/cam_xpt_periph.h>
62 #include <cam/cam_periph.h>
63 #include <cam/scsi/scsi_all.h>
64 #include <cam/scsi/scsi_message.h>
65 
66 #include <dev/iscsi/icl.h>
67 #include <dev/iscsi/icl_wrappers.h>
68 #include <dev/iscsi/iscsi_ioctl.h>
69 #include <dev/iscsi/iscsi_proto.h>
70 #include <dev/iscsi/iscsi.h>
71 
72 #ifdef ICL_KERNEL_PROXY
73 #include <sys/socketvar.h>
74 #endif
75 
76 #ifdef ICL_KERNEL_PROXY
77 FEATURE(iscsi_kernel_proxy, "iSCSI initiator built with ICL_KERNEL_PROXY");
78 #endif
79 
80 /*
81  * XXX: This is global so the iscsi_unload() can access it.
82  * 	Think about how to do this properly.
83  */
84 static struct iscsi_softc	*sc;
85 
86 SYSCTL_NODE(_kern, OID_AUTO, iscsi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
87     "iSCSI initiator");
88 static int debug = 1;
89 SYSCTL_INT(_kern_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN,
90     &debug, 0, "Enable debug messages");
91 
92 static int ping_timeout = 5;
93 SYSCTL_INT(_kern_iscsi, OID_AUTO, ping_timeout, CTLFLAG_RWTUN, &ping_timeout,
94     0, "Timeout for ping (NOP-Out) requests, in seconds");
95 static int iscsid_timeout = 60;
96 SYSCTL_INT(_kern_iscsi, OID_AUTO, iscsid_timeout, CTLFLAG_RWTUN, &iscsid_timeout,
97     0, "Time to wait for iscsid(8) to handle reconnection, in seconds");
98 static int login_timeout = 60;
99 SYSCTL_INT(_kern_iscsi, OID_AUTO, login_timeout, CTLFLAG_RWTUN, &login_timeout,
100     0, "Time to wait for iscsid(8) to finish Login Phase, in seconds");
101 static int maxtags = 255;
102 SYSCTL_INT(_kern_iscsi, OID_AUTO, maxtags, CTLFLAG_RWTUN, &maxtags,
103     0, "Max number of IO requests queued");
104 static int fail_on_disconnection = 0;
105 SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_disconnection, CTLFLAG_RWTUN,
106     &fail_on_disconnection, 0, "Destroy CAM SIM on connection failure");
107 static int fail_on_shutdown = 1;
108 SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_shutdown, CTLFLAG_RWTUN,
109     &fail_on_shutdown, 0, "Fail disconnected sessions on shutdown");
110 
111 static MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI initiator");
112 static uma_zone_t iscsi_outstanding_zone;
113 
114 #define	CONN_SESSION(X)	((struct iscsi_session *)X->ic_prv0)
115 #define	PDU_SESSION(X)	(CONN_SESSION(X->ip_conn))
116 
117 #define	ISCSI_DEBUG(X, ...)						\
118 	do {								\
119 		if (debug > 1) 						\
120 			printf("%s: " X "\n", __func__, ## __VA_ARGS__);\
121 	} while (0)
122 
123 #define	ISCSI_WARN(X, ...)						\
124 	do {								\
125 		if (debug > 0) {					\
126 			printf("WARNING: %s: " X "\n",			\
127 			    __func__, ## __VA_ARGS__);			\
128 		}							\
129 	} while (0)
130 
131 #define	ISCSI_SESSION_DEBUG(S, X, ...)					\
132 	do {								\
133 		if (debug > 1) {					\
134 			printf("%s: %s (%s): " X "\n",			\
135 			    __func__, S->is_conf.isc_target_addr,	\
136 			    S->is_conf.isc_target, ## __VA_ARGS__);	\
137 		}							\
138 	} while (0)
139 
140 #define	ISCSI_SESSION_WARN(S, X, ...)					\
141 	do {								\
142 		if (debug > 0) {					\
143 			printf("WARNING: %s (%s): " X "\n",		\
144 			    S->is_conf.isc_target_addr,			\
145 			    S->is_conf.isc_target, ## __VA_ARGS__);	\
146 		}							\
147 	} while (0)
148 
149 #define ISCSI_SESSION_LOCK(X)		mtx_lock(&X->is_lock)
150 #define ISCSI_SESSION_UNLOCK(X)		mtx_unlock(&X->is_lock)
151 #define ISCSI_SESSION_LOCK_ASSERT(X)	mtx_assert(&X->is_lock, MA_OWNED)
152 #define ISCSI_SESSION_LOCK_ASSERT_NOT(X) mtx_assert(&X->is_lock, MA_NOTOWNED)
153 
154 static int	iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg,
155 		    int mode, struct thread *td);
156 
157 static struct cdevsw iscsi_cdevsw = {
158      .d_version = D_VERSION,
159      .d_ioctl   = iscsi_ioctl,
160      .d_name    = "iscsi",
161 };
162 
163 static void	iscsi_pdu_queue_locked(struct icl_pdu *request);
164 static void	iscsi_pdu_queue(struct icl_pdu *request);
165 static void	iscsi_pdu_update_statsn(const struct icl_pdu *response);
166 static void	iscsi_pdu_handle_nop_in(struct icl_pdu *response);
167 static void	iscsi_pdu_handle_scsi_response(struct icl_pdu *response);
168 static void	iscsi_pdu_handle_task_response(struct icl_pdu *response);
169 static void	iscsi_pdu_handle_data_in(struct icl_pdu *response);
170 static void	iscsi_pdu_handle_logout_response(struct icl_pdu *response);
171 static void	iscsi_pdu_handle_r2t(struct icl_pdu *response);
172 static void	iscsi_pdu_handle_async_message(struct icl_pdu *response);
173 static void	iscsi_pdu_handle_reject(struct icl_pdu *response);
174 static void	iscsi_session_reconnect(struct iscsi_session *is);
175 static void	iscsi_session_terminate(struct iscsi_session *is);
176 static void	iscsi_action(struct cam_sim *sim, union ccb *ccb);
177 static struct iscsi_outstanding	*iscsi_outstanding_find(struct iscsi_session *is,
178 		    uint32_t initiator_task_tag);
179 static struct iscsi_outstanding	*iscsi_outstanding_add(struct iscsi_session *is,
180 		    struct icl_pdu *request, union ccb *ccb,
181 		    uint32_t *initiator_task_tagp);
182 static void	iscsi_outstanding_remove(struct iscsi_session *is,
183 		    struct iscsi_outstanding *io);
184 
185 static bool
186 iscsi_pdu_prepare(struct icl_pdu *request)
187 {
188 	struct iscsi_session *is;
189 	struct iscsi_bhs_scsi_command *bhssc;
190 
191 	is = PDU_SESSION(request);
192 
193 	ISCSI_SESSION_LOCK_ASSERT(is);
194 
195 	/*
196 	 * We're only using fields common for all the request
197 	 * (initiator -> target) PDUs.
198 	 */
199 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
200 
201 	/*
202 	 * Data-Out PDU does not contain CmdSN.
203 	 */
204 	if (bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_OUT) {
205 		if (ISCSI_SNGT(is->is_cmdsn, is->is_maxcmdsn) &&
206 		    (bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) {
207 			/*
208 			 * Current MaxCmdSN prevents us from sending any more
209 			 * SCSI Command PDUs to the target; postpone the PDU.
210 			 * It will get resent by either iscsi_pdu_queue(),
211 			 * or by maintenance thread.
212 			 */
213 #if 0
214 			ISCSI_SESSION_DEBUG(is, "postponing send, CmdSN %u, "
215 			    "ExpCmdSN %u, MaxCmdSN %u, opcode 0x%x",
216 			    is->is_cmdsn, is->is_expcmdsn, is->is_maxcmdsn,
217 			    bhssc->bhssc_opcode);
218 #endif
219 			return (true);
220 		}
221 		bhssc->bhssc_cmdsn = htonl(is->is_cmdsn);
222 		if ((bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0)
223 			is->is_cmdsn++;
224 	}
225 	bhssc->bhssc_expstatsn = htonl(is->is_statsn + 1);
226 
227 	return (false);
228 }
229 
230 static void
231 iscsi_session_send_postponed(struct iscsi_session *is)
232 {
233 	struct icl_pdu *request;
234 	bool postpone;
235 
236 	ISCSI_SESSION_LOCK_ASSERT(is);
237 
238 	if (STAILQ_EMPTY(&is->is_postponed))
239 		return;
240 	while ((request = STAILQ_FIRST(&is->is_postponed)) != NULL) {
241 		postpone = iscsi_pdu_prepare(request);
242 		if (postpone)
243 			return;
244 		STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next);
245 		icl_pdu_queue(request);
246 	}
247 	xpt_release_simq(is->is_sim, 1);
248 }
249 
250 static void
251 iscsi_pdu_queue_locked(struct icl_pdu *request)
252 {
253 	struct iscsi_session *is;
254 	bool postpone;
255 
256 	is = PDU_SESSION(request);
257 	ISCSI_SESSION_LOCK_ASSERT(is);
258 	iscsi_session_send_postponed(is);
259 	postpone = iscsi_pdu_prepare(request);
260 	if (postpone) {
261 		if (STAILQ_EMPTY(&is->is_postponed))
262 			xpt_freeze_simq(is->is_sim, 1);
263 		STAILQ_INSERT_TAIL(&is->is_postponed, request, ip_next);
264 		return;
265 	}
266 	icl_pdu_queue(request);
267 }
268 
269 static void
270 iscsi_pdu_queue(struct icl_pdu *request)
271 {
272 	struct iscsi_session *is;
273 
274 	is = PDU_SESSION(request);
275 	ISCSI_SESSION_LOCK(is);
276 	iscsi_pdu_queue_locked(request);
277 	ISCSI_SESSION_UNLOCK(is);
278 }
279 
280 static void
281 iscsi_session_logout(struct iscsi_session *is)
282 {
283 	struct icl_pdu *request;
284 	struct iscsi_bhs_logout_request *bhslr;
285 
286 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
287 	if (request == NULL)
288 		return;
289 
290 	bhslr = (struct iscsi_bhs_logout_request *)request->ip_bhs;
291 	bhslr->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_REQUEST;
292 	bhslr->bhslr_reason = BHSLR_REASON_CLOSE_SESSION;
293 	iscsi_pdu_queue_locked(request);
294 }
295 
296 static void
297 iscsi_session_terminate_task(struct iscsi_session *is,
298     struct iscsi_outstanding *io, cam_status status)
299 {
300 
301 	ISCSI_SESSION_LOCK_ASSERT(is);
302 
303 	if (io->io_ccb != NULL) {
304 		io->io_ccb->ccb_h.status &= ~(CAM_SIM_QUEUED | CAM_STATUS_MASK);
305 		io->io_ccb->ccb_h.status |= status;
306 		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
307 			io->io_ccb->ccb_h.status |= CAM_DEV_QFRZN;
308 			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
309 			ISCSI_SESSION_DEBUG(is, "freezing devq");
310 		}
311 		xpt_done(io->io_ccb);
312 	}
313 	iscsi_outstanding_remove(is, io);
314 }
315 
316 static void
317 iscsi_session_terminate_tasks(struct iscsi_session *is, cam_status status)
318 {
319 	struct iscsi_outstanding *io, *tmp;
320 
321 	ISCSI_SESSION_LOCK_ASSERT(is);
322 
323 	TAILQ_FOREACH_SAFE(io, &is->is_outstanding, io_next, tmp) {
324 		iscsi_session_terminate_task(is, io, status);
325 	}
326 }
327 
328 static void
329 iscsi_session_cleanup(struct iscsi_session *is, bool destroy_sim)
330 {
331 	struct icl_pdu *pdu;
332 
333 	ISCSI_SESSION_LOCK_ASSERT(is);
334 
335 	/*
336 	 * Don't queue any new PDUs.
337 	 */
338 	if (is->is_sim != NULL && is->is_simq_frozen == false) {
339 		ISCSI_SESSION_DEBUG(is, "freezing");
340 		xpt_freeze_simq(is->is_sim, 1);
341 		is->is_simq_frozen = true;
342 	}
343 
344 	/*
345 	 * Remove postponed PDUs.
346 	 */
347 	if (!STAILQ_EMPTY(&is->is_postponed))
348 		xpt_release_simq(is->is_sim, 1);
349 	while ((pdu = STAILQ_FIRST(&is->is_postponed)) != NULL) {
350 		STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next);
351 		icl_pdu_free(pdu);
352 	}
353 
354 	if (destroy_sim == false) {
355 		/*
356 		 * Terminate SCSI tasks, asking CAM to requeue them.
357 		 */
358 		iscsi_session_terminate_tasks(is, CAM_REQUEUE_REQ);
359 		return;
360 	}
361 
362 	iscsi_session_terminate_tasks(is, CAM_DEV_NOT_THERE);
363 
364 	if (is->is_sim == NULL)
365 		return;
366 
367 	ISCSI_SESSION_DEBUG(is, "deregistering SIM");
368 	xpt_async(AC_LOST_DEVICE, is->is_path, NULL);
369 
370 	if (is->is_simq_frozen) {
371 		is->is_simq_frozen = false;
372 		xpt_release_simq(is->is_sim, 1);
373 	}
374 
375 	xpt_free_path(is->is_path);
376 	is->is_path = NULL;
377 	xpt_bus_deregister(cam_sim_path(is->is_sim));
378 	cam_sim_free(is->is_sim, TRUE /*free_devq*/);
379 	is->is_sim = NULL;
380 	is->is_devq = NULL;
381 }
382 
383 static void
384 iscsi_maintenance_thread_reconnect(struct iscsi_session *is)
385 {
386 	/*
387 	 * As we will be reconnecting shortly,
388 	 * discard outstanding data immediately on
389 	 * close(), also notify peer via RST if
390 	 * any packets come in.
391 	 */
392 	struct socket *so;
393 	so = is->is_conn->ic_socket;
394 	if (so != NULL) {
395 		struct sockopt sopt;
396 		struct linger sl;
397 		sopt.sopt_dir     = SOPT_SET;
398 		sopt.sopt_level   = SOL_SOCKET;
399 		sopt.sopt_name    = SO_LINGER;
400 		sopt.sopt_val     = &sl;
401 		sopt.sopt_valsize = sizeof(sl);
402 		sl.l_onoff        = 1;	/* non-zero value enables linger option in kernel */
403 		sl.l_linger       = 0;	/* timeout interval in seconds */
404 		sosetopt(is->is_conn->ic_socket, &sopt);
405 	}
406 
407 	icl_conn_close(is->is_conn);
408 
409 	ISCSI_SESSION_LOCK(is);
410 
411 	is->is_connected = false;
412 	is->is_reconnecting = false;
413 	is->is_login_phase = false;
414 
415 #ifdef ICL_KERNEL_PROXY
416 	if (is->is_login_pdu != NULL) {
417 		icl_pdu_free(is->is_login_pdu);
418 		is->is_login_pdu = NULL;
419 	}
420 	cv_signal(&is->is_login_cv);
421 #endif
422 
423 	if (fail_on_disconnection) {
424 		ISCSI_SESSION_DEBUG(is, "connection failed, destroying devices");
425 		iscsi_session_cleanup(is, true);
426 	} else {
427 		iscsi_session_cleanup(is, false);
428 	}
429 
430 	KASSERT(TAILQ_EMPTY(&is->is_outstanding),
431 	    ("destroying session with active tasks"));
432 	KASSERT(STAILQ_EMPTY(&is->is_postponed),
433 	    ("destroying session with postponed PDUs"));
434 
435 	if (is->is_conf.isc_enable == 0 && is->is_conf.isc_discovery == 0) {
436 		ISCSI_SESSION_UNLOCK(is);
437 		return;
438 	}
439 
440 	/*
441 	 * Request immediate reconnection from iscsid(8).
442 	 */
443 	//ISCSI_SESSION_DEBUG(is, "waking up iscsid(8)");
444 	is->is_waiting_for_iscsid = true;
445 	strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
446 	is->is_timeout = 0;
447 	ISCSI_SESSION_UNLOCK(is);
448 	cv_signal(&is->is_softc->sc_cv);
449 }
450 
451 static void
452 iscsi_maintenance_thread_terminate(struct iscsi_session *is)
453 {
454 	struct iscsi_softc *sc;
455 
456 	sc = is->is_softc;
457 	sx_xlock(&sc->sc_lock);
458 	TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
459 	sx_xunlock(&sc->sc_lock);
460 
461 	icl_conn_close(is->is_conn);
462 	callout_drain(&is->is_callout);
463 
464 	ISCSI_SESSION_LOCK(is);
465 
466 	KASSERT(is->is_terminating, ("is_terminating == false"));
467 
468 #ifdef ICL_KERNEL_PROXY
469 	if (is->is_login_pdu != NULL) {
470 		icl_pdu_free(is->is_login_pdu);
471 		is->is_login_pdu = NULL;
472 	}
473 	cv_signal(&is->is_login_cv);
474 #endif
475 
476 	iscsi_session_cleanup(is, true);
477 
478 	KASSERT(TAILQ_EMPTY(&is->is_outstanding),
479 	    ("destroying session with active tasks"));
480 	KASSERT(STAILQ_EMPTY(&is->is_postponed),
481 	    ("destroying session with postponed PDUs"));
482 
483 	ISCSI_SESSION_UNLOCK(is);
484 
485 	icl_conn_free(is->is_conn);
486 	mtx_destroy(&is->is_lock);
487 	cv_destroy(&is->is_maintenance_cv);
488 #ifdef ICL_KERNEL_PROXY
489 	cv_destroy(&is->is_login_cv);
490 #endif
491 
492 	ISCSI_SESSION_DEBUG(is, "terminated");
493 	free(is, M_ISCSI);
494 
495 	/*
496 	 * The iscsi_unload() routine might be waiting.
497 	 */
498 	cv_signal(&sc->sc_cv);
499 }
500 
501 static void
502 iscsi_maintenance_thread(void *arg)
503 {
504 	struct iscsi_session *is = arg;
505 
506 	ISCSI_SESSION_LOCK(is);
507 	for (;;) {
508 		if (is->is_reconnecting == false &&
509 		    is->is_terminating == false &&
510 		    (STAILQ_EMPTY(&is->is_postponed) ||
511 		     ISCSI_SNGT(is->is_cmdsn, is->is_maxcmdsn)))
512 			cv_wait(&is->is_maintenance_cv, &is->is_lock);
513 
514 		/* Terminate supersedes reconnect. */
515 		if (is->is_terminating) {
516 			ISCSI_SESSION_UNLOCK(is);
517 			iscsi_maintenance_thread_terminate(is);
518 			kthread_exit();
519 			return;
520 		}
521 
522 		if (is->is_reconnecting) {
523 			ISCSI_SESSION_UNLOCK(is);
524 			iscsi_maintenance_thread_reconnect(is);
525 			ISCSI_SESSION_LOCK(is);
526 			continue;
527 		}
528 
529 		iscsi_session_send_postponed(is);
530 	}
531 	ISCSI_SESSION_UNLOCK(is);
532 }
533 
534 static void
535 iscsi_session_reconnect(struct iscsi_session *is)
536 {
537 
538 	/*
539 	 * XXX: We can't use locking here, because
540 	 * 	it's being called from various contexts.
541 	 * 	Hope it doesn't break anything.
542 	 */
543 	if (is->is_reconnecting)
544 		return;
545 
546 	is->is_reconnecting = true;
547 	cv_signal(&is->is_maintenance_cv);
548 }
549 
550 static void
551 iscsi_session_terminate(struct iscsi_session *is)
552 {
553 
554 	if (is->is_terminating)
555 		return;
556 
557 	is->is_terminating = true;
558 
559 #if 0
560 	iscsi_session_logout(is);
561 #endif
562 	cv_signal(&is->is_maintenance_cv);
563 }
564 
565 static void
566 iscsi_callout(void *context)
567 {
568 	struct icl_pdu *request;
569 	struct iscsi_bhs_nop_out *bhsno;
570 	struct iscsi_session *is;
571 	bool reconnect_needed = false;
572 	sbintime_t sbt, pr;
573 
574 	is = context;
575 
576 	ISCSI_SESSION_LOCK(is);
577 	if (is->is_terminating) {
578 		ISCSI_SESSION_UNLOCK(is);
579 		return;
580 	}
581 
582 	sbt = mstosbt(995);
583 	pr  = mstosbt(10);
584 	callout_schedule_sbt(&is->is_callout, sbt, pr, 0);
585 
586 	if (is->is_conf.isc_enable == 0)
587 		goto out;
588 
589 	is->is_timeout++;
590 
591 	if (is->is_waiting_for_iscsid) {
592 		if (iscsid_timeout > 0 && is->is_timeout > iscsid_timeout) {
593 			ISCSI_SESSION_WARN(is, "timed out waiting for iscsid(8) "
594 			    "for %d seconds; reconnecting",
595 			    is->is_timeout);
596 			reconnect_needed = true;
597 		}
598 		goto out;
599 	}
600 
601 	if (is->is_login_phase) {
602 		if (is->is_login_timeout > 0 && is->is_timeout > is->is_login_timeout) {
603 			ISCSI_SESSION_WARN(is, "login timed out after %d seconds; "
604 			    "reconnecting", is->is_timeout);
605 			reconnect_needed = true;
606 		}
607 		goto out;
608 	}
609 
610 	if (is->is_ping_timeout <= 0) {
611 		/*
612 		 * Pings are disabled.  Don't send NOP-Out in this case.
613 		 * Reset the timeout, to avoid triggering reconnection,
614 		 * should the user decide to reenable them.
615 		 */
616 		is->is_timeout = 0;
617 		goto out;
618 	}
619 
620 	if (is->is_timeout >= is->is_ping_timeout) {
621 		ISCSI_SESSION_WARN(is, "no ping reply (NOP-In) after %d seconds; "
622 		    "reconnecting", is->is_ping_timeout);
623 		reconnect_needed = true;
624 		goto out;
625 	}
626 
627 	ISCSI_SESSION_UNLOCK(is);
628 
629 	/*
630 	 * If the ping was reset less than one second ago - which means
631 	 * that we've received some PDU during the last second - assume
632 	 * the traffic flows correctly and don't bother sending a NOP-Out.
633 	 *
634 	 * (It's 2 - one for one second, and one for incrementing is_timeout
635 	 * earlier in this routine.)
636 	 */
637 	if (is->is_timeout < 2)
638 		return;
639 
640 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
641 	if (request == NULL) {
642 		ISCSI_SESSION_WARN(is, "failed to allocate PDU");
643 		return;
644 	}
645 	bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
646 	bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT |
647 	    ISCSI_BHS_OPCODE_IMMEDIATE;
648 	bhsno->bhsno_flags = 0x80;
649 	bhsno->bhsno_target_transfer_tag = 0xffffffff;
650 	iscsi_pdu_queue(request);
651 	return;
652 
653 out:
654 	if (is->is_terminating) {
655 		ISCSI_SESSION_UNLOCK(is);
656 		return;
657 	}
658 
659 	ISCSI_SESSION_UNLOCK(is);
660 
661 	if (reconnect_needed)
662 		iscsi_session_reconnect(is);
663 }
664 
665 static void
666 iscsi_pdu_update_statsn(const struct icl_pdu *response)
667 {
668 	const struct iscsi_bhs_data_in *bhsdi;
669 	struct iscsi_session *is;
670 	uint32_t expcmdsn, maxcmdsn, statsn;
671 
672 	is = PDU_SESSION(response);
673 
674 	ISCSI_SESSION_LOCK_ASSERT(is);
675 
676 	/*
677 	 * We're only using fields common for all the response
678 	 * (target -> initiator) PDUs.
679 	 */
680 	bhsdi = (const struct iscsi_bhs_data_in *)response->ip_bhs;
681 	/*
682 	 * Ok, I lied.  In case of Data-In, "The fields StatSN, Status,
683 	 * and Residual Count only have meaningful content if the S bit
684 	 * is set to 1", so we also need to check the bit specific for
685 	 * Data-In PDU.
686 	 */
687 	if (bhsdi->bhsdi_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN ||
688 	    (bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0) {
689 		statsn = ntohl(bhsdi->bhsdi_statsn);
690 		if (statsn != is->is_statsn && statsn != (is->is_statsn + 1)) {
691 			/* XXX: This is normal situation for MCS */
692 			ISCSI_SESSION_WARN(is, "PDU 0x%x StatSN %u != "
693 			    "session ExpStatSN %u (or + 1); reconnecting",
694 			    bhsdi->bhsdi_opcode, statsn, is->is_statsn);
695 			iscsi_session_reconnect(is);
696 		}
697 		if (ISCSI_SNGT(statsn, is->is_statsn))
698 			is->is_statsn = statsn;
699 	}
700 
701 	expcmdsn = ntohl(bhsdi->bhsdi_expcmdsn);
702 	maxcmdsn = ntohl(bhsdi->bhsdi_maxcmdsn);
703 
704 	if (ISCSI_SNLT(maxcmdsn + 1, expcmdsn)) {
705 		ISCSI_SESSION_DEBUG(is,
706 		    "PDU MaxCmdSN %u + 1 < PDU ExpCmdSN %u; ignoring",
707 		    maxcmdsn, expcmdsn);
708 	} else {
709 		if (ISCSI_SNGT(maxcmdsn, is->is_maxcmdsn)) {
710 			is->is_maxcmdsn = maxcmdsn;
711 
712 			/*
713 			 * Command window increased; kick the maintanance thread
714 			 * to send out postponed commands.
715 			 */
716 			if (!STAILQ_EMPTY(&is->is_postponed))
717 				cv_signal(&is->is_maintenance_cv);
718 		} else if (ISCSI_SNLT(maxcmdsn, is->is_maxcmdsn)) {
719 			/* XXX: This is normal situation for MCS */
720 			ISCSI_SESSION_DEBUG(is,
721 			    "PDU MaxCmdSN %u < session MaxCmdSN %u; ignoring",
722 			    maxcmdsn, is->is_maxcmdsn);
723 		}
724 
725 		if (ISCSI_SNGT(expcmdsn, is->is_expcmdsn)) {
726 			is->is_expcmdsn = expcmdsn;
727 		} else if (ISCSI_SNLT(expcmdsn, is->is_expcmdsn)) {
728 			/* XXX: This is normal situation for MCS */
729 			ISCSI_SESSION_DEBUG(is,
730 			    "PDU ExpCmdSN %u < session ExpCmdSN %u; ignoring",
731 			    expcmdsn, is->is_expcmdsn);
732 		}
733 	}
734 
735 	/*
736 	 * Every incoming PDU - not just NOP-In - resets the ping timer.
737 	 * The purpose of the timeout is to reset the connection when it stalls;
738 	 * we don't want this to happen when NOP-In or NOP-Out ends up delayed
739 	 * in some queue.
740 	 */
741 	is->is_timeout = 0;
742 }
743 
744 static void
745 iscsi_receive_callback(struct icl_pdu *response)
746 {
747 	struct iscsi_session *is;
748 
749 	is = PDU_SESSION(response);
750 
751 	ISCSI_SESSION_LOCK(is);
752 
753 	iscsi_pdu_update_statsn(response);
754 
755 #ifdef ICL_KERNEL_PROXY
756 	if (is->is_login_phase) {
757 		if (is->is_login_pdu == NULL)
758 			is->is_login_pdu = response;
759 		else
760 			icl_pdu_free(response);
761 		ISCSI_SESSION_UNLOCK(is);
762 		cv_signal(&is->is_login_cv);
763 		return;
764 	}
765 #endif
766 
767 	/*
768 	 * The handling routine is responsible for freeing the PDU
769 	 * when it's no longer needed.
770 	 */
771 	switch (response->ip_bhs->bhs_opcode) {
772 	case ISCSI_BHS_OPCODE_NOP_IN:
773 		iscsi_pdu_handle_nop_in(response);
774 		ISCSI_SESSION_UNLOCK(is);
775 		break;
776 	case ISCSI_BHS_OPCODE_SCSI_RESPONSE:
777 		iscsi_pdu_handle_scsi_response(response);
778 		/* Session lock dropped inside. */
779 		ISCSI_SESSION_LOCK_ASSERT_NOT(is);
780 		break;
781 	case ISCSI_BHS_OPCODE_TASK_RESPONSE:
782 		iscsi_pdu_handle_task_response(response);
783 		ISCSI_SESSION_UNLOCK(is);
784 		break;
785 	case ISCSI_BHS_OPCODE_SCSI_DATA_IN:
786 		iscsi_pdu_handle_data_in(response);
787 		/* Session lock dropped inside. */
788 		ISCSI_SESSION_LOCK_ASSERT_NOT(is);
789 		break;
790 	case ISCSI_BHS_OPCODE_LOGOUT_RESPONSE:
791 		iscsi_pdu_handle_logout_response(response);
792 		ISCSI_SESSION_UNLOCK(is);
793 		break;
794 	case ISCSI_BHS_OPCODE_R2T:
795 		iscsi_pdu_handle_r2t(response);
796 		ISCSI_SESSION_UNLOCK(is);
797 		break;
798 	case ISCSI_BHS_OPCODE_ASYNC_MESSAGE:
799 		iscsi_pdu_handle_async_message(response);
800 		ISCSI_SESSION_UNLOCK(is);
801 		break;
802 	case ISCSI_BHS_OPCODE_REJECT:
803 		iscsi_pdu_handle_reject(response);
804 		ISCSI_SESSION_UNLOCK(is);
805 		break;
806 	default:
807 		ISCSI_SESSION_WARN(is, "received PDU with unsupported "
808 		    "opcode 0x%x; reconnecting",
809 		    response->ip_bhs->bhs_opcode);
810 		iscsi_session_reconnect(is);
811 		ISCSI_SESSION_UNLOCK(is);
812 		icl_pdu_free(response);
813 	}
814 }
815 
816 static void
817 iscsi_error_callback(struct icl_conn *ic)
818 {
819 	struct iscsi_session *is;
820 
821 	is = CONN_SESSION(ic);
822 
823 	ISCSI_SESSION_WARN(is, "connection error; reconnecting");
824 	iscsi_session_reconnect(is);
825 }
826 
827 static void
828 iscsi_pdu_handle_nop_in(struct icl_pdu *response)
829 {
830 	struct iscsi_session *is;
831 	struct iscsi_bhs_nop_out *bhsno;
832 	struct iscsi_bhs_nop_in *bhsni;
833 	struct icl_pdu *request;
834 	void *data = NULL;
835 	size_t datasize;
836 	int error;
837 
838 	is = PDU_SESSION(response);
839 	bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs;
840 
841 	if (bhsni->bhsni_target_transfer_tag == 0xffffffff) {
842 		/*
843 		 * Nothing to do; iscsi_pdu_update_statsn() already
844 		 * zeroed the timeout.
845 		 */
846 		icl_pdu_free(response);
847 		return;
848 	}
849 
850 	datasize = icl_pdu_data_segment_length(response);
851 	if (datasize > 0) {
852 		data = malloc(datasize, M_ISCSI, M_NOWAIT | M_ZERO);
853 		if (data == NULL) {
854 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
855 			    "reconnecting");
856 			icl_pdu_free(response);
857 			iscsi_session_reconnect(is);
858 			return;
859 		}
860 		icl_pdu_get_data(response, 0, data, datasize);
861 	}
862 
863 	request = icl_pdu_new(response->ip_conn, M_NOWAIT);
864 	if (request == NULL) {
865 		ISCSI_SESSION_WARN(is, "failed to allocate memory; "
866 		    "reconnecting");
867 		free(data, M_ISCSI);
868 		icl_pdu_free(response);
869 		iscsi_session_reconnect(is);
870 		return;
871 	}
872 	bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
873 	bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT |
874 	    ISCSI_BHS_OPCODE_IMMEDIATE;
875 	bhsno->bhsno_flags = 0x80;
876 	bhsno->bhsno_initiator_task_tag = 0xffffffff;
877 	bhsno->bhsno_target_transfer_tag = bhsni->bhsni_target_transfer_tag;
878 	if (datasize > 0) {
879 		error = icl_pdu_append_data(request, data, datasize, M_NOWAIT);
880 		if (error != 0) {
881 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
882 			    "reconnecting");
883 			free(data, M_ISCSI);
884 			icl_pdu_free(request);
885 			icl_pdu_free(response);
886 			iscsi_session_reconnect(is);
887 			return;
888 		}
889 		free(data, M_ISCSI);
890 	}
891 
892 	icl_pdu_free(response);
893 	iscsi_pdu_queue_locked(request);
894 }
895 
896 static void
897 iscsi_pdu_handle_scsi_response(struct icl_pdu *response)
898 {
899 	struct iscsi_bhs_scsi_response *bhssr;
900 	struct iscsi_outstanding *io;
901 	struct iscsi_session *is;
902 	union ccb *ccb;
903 	struct ccb_scsiio *csio;
904 	size_t data_segment_len, received;
905 	uint16_t sense_len;
906 	uint32_t resid;
907 
908 	is = PDU_SESSION(response);
909 
910 	bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs;
911 	io = iscsi_outstanding_find(is, bhssr->bhssr_initiator_task_tag);
912 	if (io == NULL || io->io_ccb == NULL) {
913 		ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhssr->bhssr_initiator_task_tag);
914 		icl_pdu_free(response);
915 		iscsi_session_reconnect(is);
916 		ISCSI_SESSION_UNLOCK(is);
917 		return;
918 	}
919 
920 	ccb = io->io_ccb;
921 	if (bhssr->bhssr_response == BHSSR_RESPONSE_COMMAND_COMPLETED) {
922 		if (ntohl(bhssr->bhssr_expdatasn) != io->io_datasn) {
923 			ISCSI_SESSION_WARN(is,
924 			    "ExpDataSN mismatch in SCSI Response (%u vs %u)",
925 			    ntohl(bhssr->bhssr_expdatasn), io->io_datasn);
926 
927 			/*
928 			 * XXX: Permit an ExpDataSN of zero for errors.
929 			 *
930 			 * This doesn't conform to RFC 7143, but some
931 			 * targets seem to do this.
932 			 */
933 			if (bhssr->bhssr_status != 0 &&
934 			    bhssr->bhssr_expdatasn == htonl(0))
935 				goto skip_expdatasn;
936 
937 			icl_pdu_free(response);
938 			iscsi_session_reconnect(is);
939 			ISCSI_SESSION_UNLOCK(is);
940 			return;
941 		}
942 	} else {
943 		if (bhssr->bhssr_expdatasn != htonl(0)) {
944 			ISCSI_SESSION_WARN(is,
945 			    "ExpDataSN mismatch in SCSI Response (%u vs 0)",
946 			    ntohl(bhssr->bhssr_expdatasn));
947 			icl_pdu_free(response);
948 			iscsi_session_reconnect(is);
949 			ISCSI_SESSION_UNLOCK(is);
950 			return;
951 		}
952 	}
953 skip_expdatasn:
954 
955 	/*
956 	 * With iSER, after getting good response we can be sure
957 	 * that all the data has been successfully transferred.
958 	 */
959 	if (is->is_conn->ic_iser) {
960 		resid = ntohl(bhssr->bhssr_residual_count);
961 		if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_UNDERFLOW) {
962 			io->io_received = ccb->csio.dxfer_len - resid;
963 		} else if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_OVERFLOW) {
964 			ISCSI_SESSION_WARN(is, "overflow: target indicates %d", resid);
965 		} else {
966 			io->io_received = ccb->csio.dxfer_len;
967 		}
968 	}
969 
970 	received = io->io_received;
971 	iscsi_outstanding_remove(is, io);
972 	ISCSI_SESSION_UNLOCK(is);
973 
974 	if (bhssr->bhssr_response != BHSSR_RESPONSE_COMMAND_COMPLETED) {
975 		ISCSI_SESSION_WARN(is, "service response 0x%x", bhssr->bhssr_response);
976  		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
977  			xpt_freeze_devq(ccb->ccb_h.path, 1);
978 			ISCSI_SESSION_DEBUG(is, "freezing devq");
979 		}
980  		ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
981 	} else if (bhssr->bhssr_status == 0) {
982 		ccb->ccb_h.status = CAM_REQ_CMP;
983 	} else {
984  		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
985  			xpt_freeze_devq(ccb->ccb_h.path, 1);
986 			ISCSI_SESSION_DEBUG(is, "freezing devq");
987 		}
988  		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN;
989 		ccb->csio.scsi_status = bhssr->bhssr_status;
990 	}
991 
992 	csio = &ccb->csio;
993 	data_segment_len = icl_pdu_data_segment_length(response);
994 	if (data_segment_len > 0) {
995 		if (data_segment_len < sizeof(sense_len)) {
996 			ISCSI_SESSION_WARN(is, "truncated data segment (%zd bytes)",
997 			    data_segment_len);
998 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
999 				xpt_freeze_devq(ccb->ccb_h.path, 1);
1000 				ISCSI_SESSION_DEBUG(is, "freezing devq");
1001 			}
1002 			ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
1003 			goto out;
1004 		}
1005 		icl_pdu_get_data(response, 0, &sense_len, sizeof(sense_len));
1006 		sense_len = ntohs(sense_len);
1007 #if 0
1008 		ISCSI_SESSION_DEBUG(is, "sense_len %d, data len %zd",
1009 		    sense_len, data_segment_len);
1010 #endif
1011 		if (sizeof(sense_len) + sense_len > data_segment_len) {
1012 			ISCSI_SESSION_WARN(is, "truncated data segment "
1013 			    "(%zd bytes, should be %zd)",
1014 			    data_segment_len, sizeof(sense_len) + sense_len);
1015 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1016 				xpt_freeze_devq(ccb->ccb_h.path, 1);
1017 				ISCSI_SESSION_DEBUG(is, "freezing devq");
1018 			}
1019 			ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
1020 			goto out;
1021 		} else if (sizeof(sense_len) + sense_len < data_segment_len)
1022 			ISCSI_SESSION_WARN(is, "oversize data segment "
1023 			    "(%zd bytes, should be %zd)",
1024 			    data_segment_len, sizeof(sense_len) + sense_len);
1025 		if (sense_len > csio->sense_len) {
1026 			ISCSI_SESSION_DEBUG(is, "truncating sense from %d to %d",
1027 			    sense_len, csio->sense_len);
1028 			sense_len = csio->sense_len;
1029 		}
1030 		icl_pdu_get_data(response, sizeof(sense_len), &csio->sense_data, sense_len);
1031 		csio->sense_resid = csio->sense_len - sense_len;
1032 		ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
1033 	}
1034 
1035 out:
1036 	if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_UNDERFLOW)
1037 		csio->resid = ntohl(bhssr->bhssr_residual_count);
1038 
1039 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1040 		KASSERT(received <= csio->dxfer_len,
1041 		    ("received > csio->dxfer_len"));
1042 		if (received < csio->dxfer_len) {
1043 			if (csio->resid != csio->dxfer_len - received) {
1044 				ISCSI_SESSION_WARN(is, "underflow mismatch: "
1045 				    "target indicates %d, we calculated %zd",
1046 				    csio->resid, csio->dxfer_len - received);
1047 			}
1048 			csio->resid = csio->dxfer_len - received;
1049 		}
1050 	}
1051 
1052 	xpt_done(ccb);
1053 	icl_pdu_free(response);
1054 }
1055 
1056 static void
1057 iscsi_pdu_handle_task_response(struct icl_pdu *response)
1058 {
1059 	struct iscsi_bhs_task_management_response *bhstmr;
1060 	struct iscsi_outstanding *io, *aio;
1061 	struct iscsi_session *is;
1062 
1063 	is = PDU_SESSION(response);
1064 
1065 	bhstmr = (struct iscsi_bhs_task_management_response *)response->ip_bhs;
1066 	io = iscsi_outstanding_find(is, bhstmr->bhstmr_initiator_task_tag);
1067 	if (io == NULL || io->io_ccb != NULL) {
1068 		ISCSI_SESSION_WARN(is, "bad itt 0x%x",
1069 		    bhstmr->bhstmr_initiator_task_tag);
1070 		icl_pdu_free(response);
1071 		iscsi_session_reconnect(is);
1072 		return;
1073 	}
1074 
1075 	if (bhstmr->bhstmr_response != BHSTMR_RESPONSE_FUNCTION_COMPLETE) {
1076 		ISCSI_SESSION_WARN(is, "task response 0x%x",
1077 		    bhstmr->bhstmr_response);
1078 	} else {
1079 		aio = iscsi_outstanding_find(is, io->io_referenced_task_tag);
1080 		if (aio != NULL && aio->io_ccb != NULL)
1081 			iscsi_session_terminate_task(is, aio, CAM_REQ_ABORTED);
1082 	}
1083 
1084 	iscsi_outstanding_remove(is, io);
1085 	icl_pdu_free(response);
1086 }
1087 
1088 static void
1089 iscsi_pdu_handle_data_in(struct icl_pdu *response)
1090 {
1091 	struct iscsi_bhs_data_in *bhsdi;
1092 	struct iscsi_outstanding *io;
1093 	struct iscsi_session *is;
1094 	union ccb *ccb;
1095 	struct ccb_scsiio *csio;
1096 	size_t data_segment_len, received, oreceived;
1097 
1098 	is = PDU_SESSION(response);
1099 	bhsdi = (struct iscsi_bhs_data_in *)response->ip_bhs;
1100 	io = iscsi_outstanding_find(is, bhsdi->bhsdi_initiator_task_tag);
1101 	if (io == NULL || io->io_ccb == NULL) {
1102 		ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhsdi->bhsdi_initiator_task_tag);
1103 		icl_pdu_free(response);
1104 		iscsi_session_reconnect(is);
1105 		ISCSI_SESSION_UNLOCK(is);
1106 		return;
1107 	}
1108 
1109 	if (io->io_datasn != ntohl(bhsdi->bhsdi_datasn)) {
1110 		ISCSI_SESSION_WARN(is, "received Data-In PDU with "
1111 		    "DataSN %u, while expected %u; dropping connection",
1112 		    ntohl(bhsdi->bhsdi_datasn), io->io_datasn);
1113 		icl_pdu_free(response);
1114 		iscsi_session_reconnect(is);
1115 		ISCSI_SESSION_UNLOCK(is);
1116 		return;
1117 	}
1118 	io->io_datasn += response->ip_additional_pdus + 1;
1119 
1120 	data_segment_len = icl_pdu_data_segment_length(response);
1121 	if (data_segment_len == 0) {
1122 		/*
1123 		 * "The sending of 0 length data segments should be avoided,
1124 		 * but initiators and targets MUST be able to properly receive
1125 		 * 0 length data segments."
1126 		 */
1127 		ISCSI_SESSION_UNLOCK(is);
1128 		icl_pdu_free(response);
1129 		return;
1130 	}
1131 
1132 	/*
1133 	 * We need to track this for security reasons - without it, malicious target
1134 	 * could respond to SCSI READ without sending Data-In PDUs, which would result
1135 	 * in read operation on the initiator side returning random kernel data.
1136 	 */
1137 	if (ntohl(bhsdi->bhsdi_buffer_offset) != io->io_received) {
1138 		ISCSI_SESSION_WARN(is, "data out of order; expected offset %zd, got %zd",
1139 		    io->io_received, (size_t)ntohl(bhsdi->bhsdi_buffer_offset));
1140 		icl_pdu_free(response);
1141 		iscsi_session_reconnect(is);
1142 		ISCSI_SESSION_UNLOCK(is);
1143 		return;
1144 	}
1145 
1146 	ccb = io->io_ccb;
1147 	csio = &ccb->csio;
1148 
1149 	if (io->io_received + data_segment_len > csio->dxfer_len) {
1150 		ISCSI_SESSION_WARN(is, "oversize data segment (%zd bytes "
1151 		    "at offset %zd, buffer is %d)",
1152 		    data_segment_len, io->io_received, csio->dxfer_len);
1153 		icl_pdu_free(response);
1154 		iscsi_session_reconnect(is);
1155 		ISCSI_SESSION_UNLOCK(is);
1156 		return;
1157 	}
1158 
1159 	oreceived = io->io_received;
1160 	io->io_received += data_segment_len;
1161 	received = io->io_received;
1162 	if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0)
1163 		iscsi_outstanding_remove(is, io);
1164 	ISCSI_SESSION_UNLOCK(is);
1165 
1166 	icl_pdu_get_data(response, 0, csio->data_ptr + oreceived, data_segment_len);
1167 
1168 	/*
1169 	 * XXX: Check F.
1170 	 */
1171 	if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) == 0) {
1172 		/*
1173 		 * Nothing more to do.
1174 		 */
1175 		icl_pdu_free(response);
1176 		return;
1177 	}
1178 
1179 	//ISCSI_SESSION_DEBUG(is, "got S flag; status 0x%x", bhsdi->bhsdi_status);
1180 	if (bhsdi->bhsdi_status == 0) {
1181 		ccb->ccb_h.status = CAM_REQ_CMP;
1182 	} else {
1183 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1184 			xpt_freeze_devq(ccb->ccb_h.path, 1);
1185 			ISCSI_SESSION_DEBUG(is, "freezing devq");
1186 		}
1187 		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN;
1188 		csio->scsi_status = bhsdi->bhsdi_status;
1189 	}
1190 
1191 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1192 		KASSERT(received <= csio->dxfer_len,
1193 		    ("received > csio->dxfer_len"));
1194 		if (received < csio->dxfer_len) {
1195 			csio->resid = ntohl(bhsdi->bhsdi_residual_count);
1196 			if (csio->resid != csio->dxfer_len - received) {
1197 				ISCSI_SESSION_WARN(is, "underflow mismatch: "
1198 				    "target indicates %d, we calculated %zd",
1199 				    csio->resid, csio->dxfer_len - received);
1200 			}
1201 			csio->resid = csio->dxfer_len - received;
1202 		}
1203 	}
1204 
1205 	xpt_done(ccb);
1206 	icl_pdu_free(response);
1207 }
1208 
1209 static void
1210 iscsi_pdu_handle_logout_response(struct icl_pdu *response)
1211 {
1212 
1213 	ISCSI_SESSION_DEBUG(PDU_SESSION(response), "logout response");
1214 	icl_pdu_free(response);
1215 }
1216 
1217 static void
1218 iscsi_pdu_handle_r2t(struct icl_pdu *response)
1219 {
1220 	struct icl_pdu *request;
1221 	struct iscsi_session *is;
1222 	struct iscsi_bhs_r2t *bhsr2t;
1223 	struct iscsi_bhs_data_out *bhsdo;
1224 	struct iscsi_outstanding *io;
1225 	struct ccb_scsiio *csio;
1226 	size_t off, len, max_send_data_segment_length, total_len;
1227 	int error;
1228 	uint32_t datasn = 0;
1229 
1230 	is = PDU_SESSION(response);
1231 
1232 	bhsr2t = (struct iscsi_bhs_r2t *)response->ip_bhs;
1233 	io = iscsi_outstanding_find(is, bhsr2t->bhsr2t_initiator_task_tag);
1234 	if (io == NULL || io->io_ccb == NULL) {
1235 		ISCSI_SESSION_WARN(is, "bad itt 0x%x; reconnecting",
1236 		    bhsr2t->bhsr2t_initiator_task_tag);
1237 		icl_pdu_free(response);
1238 		iscsi_session_reconnect(is);
1239 		return;
1240 	}
1241 
1242 	csio = &io->io_ccb->csio;
1243 
1244 	if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_OUT) {
1245 		ISCSI_SESSION_WARN(is, "received R2T for read command; reconnecting");
1246 		icl_pdu_free(response);
1247 		iscsi_session_reconnect(is);
1248 		return;
1249 	}
1250 
1251 	/*
1252 	 * XXX: Verify R2TSN.
1253 	 */
1254 
1255 	off = ntohl(bhsr2t->bhsr2t_buffer_offset);
1256 	if (off > csio->dxfer_len) {
1257 		ISCSI_SESSION_WARN(is, "target requested invalid offset "
1258 		    "%zd, buffer is is %d; reconnecting", off, csio->dxfer_len);
1259 		icl_pdu_free(response);
1260 		iscsi_session_reconnect(is);
1261 		return;
1262 	}
1263 
1264 	total_len = ntohl(bhsr2t->bhsr2t_desired_data_transfer_length);
1265 	if (total_len == 0 || total_len > csio->dxfer_len) {
1266 		ISCSI_SESSION_WARN(is, "target requested invalid length "
1267 		    "%zd, buffer is %d; reconnecting", total_len, csio->dxfer_len);
1268 		icl_pdu_free(response);
1269 		iscsi_session_reconnect(is);
1270 		return;
1271 	}
1272 
1273 	//ISCSI_SESSION_DEBUG(is, "r2t; off %zd, len %zd", off, total_len);
1274 
1275 	if (is->is_conn->ic_hw_isomax != 0)
1276 		max_send_data_segment_length = is->is_conn->ic_hw_isomax;
1277 	else
1278 		max_send_data_segment_length =
1279 		    is->is_conn->ic_max_send_data_segment_length;
1280 	for (;;) {
1281 		len = total_len;
1282 
1283 		if (len > max_send_data_segment_length)
1284 			len = max_send_data_segment_length;
1285 
1286 		if (off + len > csio->dxfer_len) {
1287 			ISCSI_SESSION_WARN(is, "target requested invalid "
1288 			    "length/offset %zd, buffer is %d; reconnecting",
1289 			    off + len, csio->dxfer_len);
1290 			icl_pdu_free(response);
1291 			iscsi_session_reconnect(is);
1292 			return;
1293 		}
1294 
1295 		request = icl_pdu_new(response->ip_conn, M_NOWAIT);
1296 		if (request == NULL) {
1297 			icl_pdu_free(response);
1298 			iscsi_session_reconnect(is);
1299 			return;
1300 		}
1301 
1302 		bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs;
1303 		bhsdo->bhsdo_opcode = ISCSI_BHS_OPCODE_SCSI_DATA_OUT;
1304 		bhsdo->bhsdo_lun = bhsr2t->bhsr2t_lun;
1305 		bhsdo->bhsdo_initiator_task_tag =
1306 		    bhsr2t->bhsr2t_initiator_task_tag;
1307 		bhsdo->bhsdo_target_transfer_tag =
1308 		    bhsr2t->bhsr2t_target_transfer_tag;
1309 		bhsdo->bhsdo_datasn = htonl(datasn);
1310 		bhsdo->bhsdo_buffer_offset = htonl(off);
1311 		error = icl_pdu_append_data(request, csio->data_ptr + off, len,
1312 		    M_NOWAIT);
1313 		if (error != 0) {
1314 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
1315 			    "reconnecting");
1316 			icl_pdu_free(request);
1317 			icl_pdu_free(response);
1318 			iscsi_session_reconnect(is);
1319 			return;
1320 		}
1321 
1322 		datasn += howmany(len,
1323 		    is->is_conn->ic_max_send_data_segment_length);
1324 		off += len;
1325 		total_len -= len;
1326 
1327 		if (total_len == 0) {
1328 			bhsdo->bhsdo_flags |= BHSDO_FLAGS_F;
1329 			//ISCSI_SESSION_DEBUG(is, "setting F, off %zd", off);
1330 		} else {
1331 			//ISCSI_SESSION_DEBUG(is, "not finished, off %zd", off);
1332 		}
1333 
1334 		iscsi_pdu_queue_locked(request);
1335 
1336 		if (total_len == 0)
1337 			break;
1338 	}
1339 
1340 	icl_pdu_free(response);
1341 }
1342 
1343 static void
1344 iscsi_pdu_handle_async_message(struct icl_pdu *response)
1345 {
1346 	struct iscsi_bhs_asynchronous_message *bhsam;
1347 	struct iscsi_session *is;
1348 
1349 	is = PDU_SESSION(response);
1350 	bhsam = (struct iscsi_bhs_asynchronous_message *)response->ip_bhs;
1351 	switch (bhsam->bhsam_async_event) {
1352 	case BHSAM_EVENT_TARGET_REQUESTS_LOGOUT:
1353 		ISCSI_SESSION_WARN(is, "target requests logout; removing session");
1354 		iscsi_session_logout(is);
1355 		iscsi_session_terminate(is);
1356 		break;
1357 	case BHSAM_EVENT_TARGET_TERMINATES_CONNECTION:
1358 		ISCSI_SESSION_WARN(is, "target indicates it will drop the connection");
1359 		break;
1360 	case BHSAM_EVENT_TARGET_TERMINATES_SESSION:
1361 		ISCSI_SESSION_WARN(is, "target indicates it will drop the session");
1362 		break;
1363 	default:
1364 		/*
1365 		 * XXX: Technically, we're obligated to also handle
1366 		 * 	parameter renegotiation.
1367 		 */
1368 		ISCSI_SESSION_WARN(is, "ignoring AsyncEvent %d", bhsam->bhsam_async_event);
1369 		break;
1370 	}
1371 
1372 	icl_pdu_free(response);
1373 }
1374 
1375 static void
1376 iscsi_pdu_handle_reject(struct icl_pdu *response)
1377 {
1378 	struct iscsi_bhs_reject *bhsr;
1379 	struct iscsi_session *is;
1380 
1381 	is = PDU_SESSION(response);
1382 	bhsr = (struct iscsi_bhs_reject *)response->ip_bhs;
1383 	ISCSI_SESSION_WARN(is, "received Reject PDU, reason 0x%x; protocol error?",
1384 	    bhsr->bhsr_reason);
1385 
1386 	icl_pdu_free(response);
1387 }
1388 
1389 static int
1390 iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
1391     struct iscsi_daemon_request *request)
1392 {
1393 	struct iscsi_session *is;
1394 	struct icl_drv_limits idl;
1395 	int error;
1396 
1397 	sx_slock(&sc->sc_lock);
1398 	for (;;) {
1399 		TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1400 			ISCSI_SESSION_LOCK(is);
1401 			if (is->is_conf.isc_enable == 0 &&
1402 			    is->is_conf.isc_discovery == 0) {
1403 				ISCSI_SESSION_UNLOCK(is);
1404 				continue;
1405 			}
1406 			if (is->is_waiting_for_iscsid)
1407 				break;
1408 			ISCSI_SESSION_UNLOCK(is);
1409 		}
1410 
1411 		if (is == NULL) {
1412 			if (sc->sc_unloading) {
1413 				sx_sunlock(&sc->sc_lock);
1414 				return (ENXIO);
1415 			}
1416 
1417 			/*
1418 			 * No session requires attention from iscsid(8); wait.
1419 			 */
1420 			error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
1421 			if (error != 0) {
1422 				sx_sunlock(&sc->sc_lock);
1423 				return (error);
1424 			}
1425 			continue;
1426 		}
1427 
1428 		is->is_waiting_for_iscsid = false;
1429 		is->is_login_phase = true;
1430 		is->is_reason[0] = '\0';
1431 		ISCSI_SESSION_UNLOCK(is);
1432 
1433 		request->idr_session_id = is->is_id;
1434 		memcpy(&request->idr_isid, &is->is_isid,
1435 		    sizeof(request->idr_isid));
1436 		request->idr_tsih = 0;	/* New or reinstated session. */
1437 		memcpy(&request->idr_conf, &is->is_conf,
1438 		    sizeof(request->idr_conf));
1439 
1440 		error = icl_limits(is->is_conf.isc_offload,
1441 		    is->is_conf.isc_iser, &idl);
1442 		if (error != 0) {
1443 			ISCSI_SESSION_WARN(is, "icl_limits for offload \"%s\" "
1444 			    "failed with error %d", is->is_conf.isc_offload,
1445 			    error);
1446 			sx_sunlock(&sc->sc_lock);
1447 			return (error);
1448 		}
1449 		request->idr_limits.isl_max_recv_data_segment_length =
1450 		    idl.idl_max_recv_data_segment_length;
1451 		request->idr_limits.isl_max_send_data_segment_length =
1452 		    idl.idl_max_send_data_segment_length;
1453 		request->idr_limits.isl_max_burst_length =
1454 		    idl.idl_max_burst_length;
1455 		request->idr_limits.isl_first_burst_length =
1456 		    idl.idl_first_burst_length;
1457 
1458 		sx_sunlock(&sc->sc_lock);
1459 		return (0);
1460 	}
1461 }
1462 
1463 static int
1464 iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc,
1465     struct iscsi_daemon_handoff *handoff)
1466 {
1467 	struct iscsi_session *is;
1468 	struct icl_conn *ic;
1469 	int error;
1470 
1471 	sx_slock(&sc->sc_lock);
1472 
1473 	/*
1474 	 * Find the session to hand off socket to.
1475 	 */
1476 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1477 		if (is->is_id == handoff->idh_session_id)
1478 			break;
1479 	}
1480 	if (is == NULL) {
1481 		sx_sunlock(&sc->sc_lock);
1482 		return (ESRCH);
1483 	}
1484 	ISCSI_SESSION_LOCK(is);
1485 	ic = is->is_conn;
1486 	if (is->is_conf.isc_discovery || is->is_terminating) {
1487 		ISCSI_SESSION_UNLOCK(is);
1488 		sx_sunlock(&sc->sc_lock);
1489 		return (EINVAL);
1490 	}
1491 	if (is->is_connected) {
1492 		/*
1493 		 * This might have happened because another iscsid(8)
1494 		 * instance handed off the connection in the meantime.
1495 		 * Just return.
1496 		 */
1497 		ISCSI_SESSION_WARN(is, "handoff on already connected "
1498 		    "session");
1499 		ISCSI_SESSION_UNLOCK(is);
1500 		sx_sunlock(&sc->sc_lock);
1501 		return (EBUSY);
1502 	}
1503 
1504 	strlcpy(is->is_target_alias, handoff->idh_target_alias,
1505 	    sizeof(is->is_target_alias));
1506 	is->is_tsih = handoff->idh_tsih;
1507 	is->is_statsn = handoff->idh_statsn;
1508 	is->is_protocol_level = handoff->idh_protocol_level;
1509 	is->is_initial_r2t = handoff->idh_initial_r2t;
1510 	is->is_immediate_data = handoff->idh_immediate_data;
1511 
1512 	ic->ic_max_recv_data_segment_length =
1513 	    handoff->idh_max_recv_data_segment_length;
1514 	ic->ic_max_send_data_segment_length =
1515 	    handoff->idh_max_send_data_segment_length;
1516 	is->is_max_burst_length = handoff->idh_max_burst_length;
1517 	is->is_first_burst_length = handoff->idh_first_burst_length;
1518 
1519 	if (handoff->idh_header_digest == ISCSI_DIGEST_CRC32C)
1520 		ic->ic_header_crc32c = true;
1521 	else
1522 		ic->ic_header_crc32c = false;
1523 	if (handoff->idh_data_digest == ISCSI_DIGEST_CRC32C)
1524 		ic->ic_data_crc32c = true;
1525 	else
1526 		ic->ic_data_crc32c = false;
1527 	ic->ic_maxtags = maxtags;
1528 
1529 	is->is_cmdsn = 0;
1530 	is->is_expcmdsn = 0;
1531 	is->is_maxcmdsn = 0;
1532 	is->is_waiting_for_iscsid = false;
1533 	is->is_login_phase = false;
1534 	is->is_timeout = 0;
1535 	is->is_ping_timeout = is->is_conf.isc_ping_timeout;
1536 	if (is->is_ping_timeout < 0)
1537 		is->is_ping_timeout = ping_timeout;
1538 	is->is_login_timeout = is->is_conf.isc_login_timeout;
1539 	if (is->is_login_timeout < 0)
1540 		is->is_login_timeout = login_timeout;
1541 	is->is_connected = true;
1542 	is->is_reason[0] = '\0';
1543 
1544 	ISCSI_SESSION_UNLOCK(is);
1545 
1546 	/*
1547 	 * If we're going through the proxy, the idh_socket will be 0,
1548 	 * and the ICL module can simply ignore this call.  It can also
1549 	 * use it to determine it's no longer in the Login phase.
1550 	 */
1551 	error = icl_conn_handoff(ic, handoff->idh_socket);
1552 	if (error != 0) {
1553 		sx_sunlock(&sc->sc_lock);
1554 		iscsi_session_terminate(is);
1555 		return (error);
1556 	}
1557 
1558 	sx_sunlock(&sc->sc_lock);
1559 
1560 	if (is->is_sim != NULL) {
1561 		/*
1562 		 * When reconnecting, there already is SIM allocated for the session.
1563 		 */
1564 		KASSERT(is->is_simq_frozen, ("reconnect without frozen simq"));
1565 		ISCSI_SESSION_LOCK(is);
1566 		ISCSI_SESSION_DEBUG(is, "releasing");
1567 		is->is_simq_frozen = false;
1568 		xpt_release_simq(is->is_sim, 1);
1569 		ISCSI_SESSION_UNLOCK(is);
1570 
1571 	} else {
1572 		ISCSI_SESSION_LOCK(is);
1573 		is->is_devq = cam_simq_alloc(ic->ic_maxtags);
1574 		if (is->is_devq == NULL) {
1575 			ISCSI_SESSION_UNLOCK(is);
1576 			ISCSI_SESSION_WARN(is, "failed to allocate simq");
1577 			iscsi_session_terminate(is);
1578 			return (ENOMEM);
1579 		}
1580 
1581 		is->is_sim = cam_sim_alloc(iscsi_action, NULL, "iscsi",
1582 		    is, is->is_id /* unit */, &is->is_lock,
1583 		    1, ic->ic_maxtags, is->is_devq);
1584 		if (is->is_sim == NULL) {
1585 			ISCSI_SESSION_UNLOCK(is);
1586 			ISCSI_SESSION_WARN(is, "failed to allocate SIM");
1587 			cam_simq_free(is->is_devq);
1588 			iscsi_session_terminate(is);
1589 			return (ENOMEM);
1590 		}
1591 
1592 		if (xpt_bus_register(is->is_sim, NULL, 0) != 0) {
1593 			ISCSI_SESSION_UNLOCK(is);
1594 			ISCSI_SESSION_WARN(is, "failed to register bus");
1595 			iscsi_session_terminate(is);
1596 			return (ENOMEM);
1597 		}
1598 
1599 		error = xpt_create_path(&is->is_path, /*periph*/NULL,
1600 		    cam_sim_path(is->is_sim), CAM_TARGET_WILDCARD,
1601 		    CAM_LUN_WILDCARD);
1602 		if (error != CAM_REQ_CMP) {
1603 			ISCSI_SESSION_UNLOCK(is);
1604 			ISCSI_SESSION_WARN(is, "failed to create path");
1605 			iscsi_session_terminate(is);
1606 			return (ENOMEM);
1607 		}
1608 		ISCSI_SESSION_UNLOCK(is);
1609 	}
1610 
1611 	return (0);
1612 }
1613 
1614 static int
1615 iscsi_ioctl_daemon_fail(struct iscsi_softc *sc,
1616     struct iscsi_daemon_fail *fail)
1617 {
1618 	struct iscsi_session *is;
1619 
1620 	sx_slock(&sc->sc_lock);
1621 
1622 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1623 		if (is->is_id == fail->idf_session_id)
1624 			break;
1625 	}
1626 	if (is == NULL) {
1627 		sx_sunlock(&sc->sc_lock);
1628 		return (ESRCH);
1629 	}
1630 	ISCSI_SESSION_LOCK(is);
1631 	ISCSI_SESSION_DEBUG(is, "iscsid(8) failed: %s",
1632 	    fail->idf_reason);
1633 	strlcpy(is->is_reason, fail->idf_reason, sizeof(is->is_reason));
1634 	//is->is_waiting_for_iscsid = false;
1635 	//is->is_login_phase = true;
1636 	//iscsi_session_reconnect(is);
1637 	ISCSI_SESSION_UNLOCK(is);
1638 	sx_sunlock(&sc->sc_lock);
1639 
1640 	return (0);
1641 }
1642 
1643 #ifdef ICL_KERNEL_PROXY
1644 static int
1645 iscsi_ioctl_daemon_connect(struct iscsi_softc *sc,
1646     struct iscsi_daemon_connect *idc)
1647 {
1648 	struct iscsi_session *is;
1649 	struct sockaddr *from_sa, *to_sa;
1650 	int error;
1651 
1652 	sx_slock(&sc->sc_lock);
1653 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1654 		if (is->is_id == idc->idc_session_id)
1655 			break;
1656 	}
1657 	if (is == NULL) {
1658 		sx_sunlock(&sc->sc_lock);
1659 		return (ESRCH);
1660 	}
1661 	sx_sunlock(&sc->sc_lock);
1662 
1663 	if (idc->idc_from_addrlen > 0) {
1664 		error = getsockaddr(&from_sa, (void *)idc->idc_from_addr, idc->idc_from_addrlen);
1665 		if (error != 0) {
1666 			ISCSI_SESSION_WARN(is,
1667 			    "getsockaddr failed with error %d", error);
1668 			return (error);
1669 		}
1670 	} else {
1671 		from_sa = NULL;
1672 	}
1673 	error = getsockaddr(&to_sa, (void *)idc->idc_to_addr, idc->idc_to_addrlen);
1674 	if (error != 0) {
1675 		ISCSI_SESSION_WARN(is, "getsockaddr failed with error %d",
1676 		    error);
1677 		free(from_sa, M_SONAME);
1678 		return (error);
1679 	}
1680 
1681 	ISCSI_SESSION_LOCK(is);
1682 	is->is_statsn = 0;
1683 	is->is_cmdsn = 0;
1684 	is->is_expcmdsn = 0;
1685 	is->is_maxcmdsn = 0;
1686 	is->is_waiting_for_iscsid = false;
1687 	is->is_login_phase = true;
1688 	is->is_timeout = 0;
1689 	ISCSI_SESSION_UNLOCK(is);
1690 
1691 	error = icl_conn_connect(is->is_conn, idc->idc_domain,
1692 	    idc->idc_socktype, idc->idc_protocol, from_sa, to_sa);
1693 	free(from_sa, M_SONAME);
1694 	free(to_sa, M_SONAME);
1695 
1696 	/*
1697 	 * Digests are always disabled during login phase.
1698 	 */
1699 	is->is_conn->ic_header_crc32c = false;
1700 	is->is_conn->ic_data_crc32c = false;
1701 
1702 	return (error);
1703 }
1704 
1705 static int
1706 iscsi_ioctl_daemon_send(struct iscsi_softc *sc,
1707     struct iscsi_daemon_send *ids)
1708 {
1709 	struct iscsi_session *is;
1710 	struct icl_pdu *ip;
1711 	size_t datalen;
1712 	void *data;
1713 	int error;
1714 
1715 	sx_slock(&sc->sc_lock);
1716 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1717 		if (is->is_id == ids->ids_session_id)
1718 			break;
1719 	}
1720 	if (is == NULL) {
1721 		sx_sunlock(&sc->sc_lock);
1722 		return (ESRCH);
1723 	}
1724 	sx_sunlock(&sc->sc_lock);
1725 
1726 	if (is->is_login_phase == false)
1727 		return (EBUSY);
1728 
1729 	if (is->is_terminating || is->is_reconnecting)
1730 		return (EIO);
1731 
1732 	datalen = ids->ids_data_segment_len;
1733 	if (datalen > is->is_conn->ic_max_send_data_segment_length)
1734 		return (EINVAL);
1735 	if (datalen > 0) {
1736 		data = malloc(datalen, M_ISCSI, M_WAITOK);
1737 		error = copyin(ids->ids_data_segment, data, datalen);
1738 		if (error != 0) {
1739 			free(data, M_ISCSI);
1740 			return (error);
1741 		}
1742 	}
1743 
1744 	ip = icl_pdu_new(is->is_conn, M_WAITOK);
1745 	memcpy(ip->ip_bhs, ids->ids_bhs, sizeof(*ip->ip_bhs));
1746 	if (datalen > 0) {
1747 		error = icl_pdu_append_data(ip, data, datalen, M_WAITOK);
1748 		KASSERT(error == 0, ("icl_pdu_append_data(..., M_WAITOK) failed"));
1749 		free(data, M_ISCSI);
1750 	}
1751 	iscsi_pdu_queue(ip);
1752 
1753 	return (0);
1754 }
1755 
1756 static int
1757 iscsi_ioctl_daemon_receive(struct iscsi_softc *sc,
1758     struct iscsi_daemon_receive *idr)
1759 {
1760 	struct iscsi_session *is;
1761 	struct icl_pdu *ip;
1762 	void *data;
1763 	int error;
1764 
1765 	sx_slock(&sc->sc_lock);
1766 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1767 		if (is->is_id == idr->idr_session_id)
1768 			break;
1769 	}
1770 	if (is == NULL) {
1771 		sx_sunlock(&sc->sc_lock);
1772 		return (ESRCH);
1773 	}
1774 	sx_sunlock(&sc->sc_lock);
1775 
1776 	if (is->is_login_phase == false)
1777 		return (EBUSY);
1778 
1779 	ISCSI_SESSION_LOCK(is);
1780 	while (is->is_login_pdu == NULL &&
1781 	    is->is_terminating == false &&
1782 	    is->is_reconnecting == false) {
1783 		error = cv_wait_sig(&is->is_login_cv, &is->is_lock);
1784 		if (error != 0) {
1785 			ISCSI_SESSION_UNLOCK(is);
1786 			return (error);
1787 		}
1788 	}
1789 	if (is->is_terminating || is->is_reconnecting) {
1790 		ISCSI_SESSION_UNLOCK(is);
1791 		return (EIO);
1792 	}
1793 	ip = is->is_login_pdu;
1794 	is->is_login_pdu = NULL;
1795 	ISCSI_SESSION_UNLOCK(is);
1796 
1797 	if (ip->ip_data_len > idr->idr_data_segment_len) {
1798 		icl_pdu_free(ip);
1799 		return (EMSGSIZE);
1800 	}
1801 
1802 	copyout(ip->ip_bhs, idr->idr_bhs, sizeof(*ip->ip_bhs));
1803 	if (ip->ip_data_len > 0) {
1804 		data = malloc(ip->ip_data_len, M_ISCSI, M_WAITOK);
1805 		icl_pdu_get_data(ip, 0, data, ip->ip_data_len);
1806 		copyout(data, idr->idr_data_segment, ip->ip_data_len);
1807 		free(data, M_ISCSI);
1808 	}
1809 
1810 	icl_pdu_free(ip);
1811 
1812 	return (0);
1813 }
1814 #endif /* ICL_KERNEL_PROXY */
1815 
1816 static void
1817 iscsi_sanitize_session_conf(struct iscsi_session_conf *isc)
1818 {
1819 	/*
1820 	 * Just make sure all the fields are null-terminated.
1821 	 *
1822 	 * XXX: This is not particularly secure.  We should
1823 	 * 	create our own conf and then copy in relevant
1824 	 * 	fields.
1825 	 */
1826 	isc->isc_initiator[ISCSI_NAME_LEN - 1] = '\0';
1827 	isc->isc_initiator_addr[ISCSI_ADDR_LEN - 1] = '\0';
1828 	isc->isc_initiator_alias[ISCSI_ALIAS_LEN - 1] = '\0';
1829 	isc->isc_target[ISCSI_NAME_LEN - 1] = '\0';
1830 	isc->isc_target_addr[ISCSI_ADDR_LEN - 1] = '\0';
1831 	isc->isc_user[ISCSI_NAME_LEN - 1] = '\0';
1832 	isc->isc_secret[ISCSI_SECRET_LEN - 1] = '\0';
1833 	isc->isc_mutual_user[ISCSI_NAME_LEN - 1] = '\0';
1834 	isc->isc_mutual_secret[ISCSI_SECRET_LEN - 1] = '\0';
1835 }
1836 
1837 static bool
1838 iscsi_valid_session_conf(const struct iscsi_session_conf *isc)
1839 {
1840 
1841 	if (isc->isc_initiator[0] == '\0') {
1842 		ISCSI_DEBUG("empty isc_initiator");
1843 		return (false);
1844 	}
1845 
1846 	if (isc->isc_target_addr[0] == '\0') {
1847 		ISCSI_DEBUG("empty isc_target_addr");
1848 		return (false);
1849 	}
1850 
1851 	if (isc->isc_discovery != 0 && isc->isc_target[0] != 0) {
1852 		ISCSI_DEBUG("non-empty isc_target for discovery session");
1853 		return (false);
1854 	}
1855 
1856 	if (isc->isc_discovery == 0 && isc->isc_target[0] == 0) {
1857 		ISCSI_DEBUG("empty isc_target for non-discovery session");
1858 		return (false);
1859 	}
1860 
1861 	return (true);
1862 }
1863 
1864 static int
1865 iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
1866 {
1867 	struct iscsi_session *is;
1868 	const struct iscsi_session *is2;
1869 	int error;
1870 	sbintime_t sbt, pr;
1871 
1872 	iscsi_sanitize_session_conf(&isa->isa_conf);
1873 	if (iscsi_valid_session_conf(&isa->isa_conf) == false)
1874 		return (EINVAL);
1875 
1876 	is = malloc(sizeof(*is), M_ISCSI, M_ZERO | M_WAITOK);
1877 	memcpy(&is->is_conf, &isa->isa_conf, sizeof(is->is_conf));
1878 
1879 	sx_xlock(&sc->sc_lock);
1880 
1881 	/*
1882 	 * Prevent duplicates.
1883 	 */
1884 	TAILQ_FOREACH(is2, &sc->sc_sessions, is_next) {
1885 		if (!!is->is_conf.isc_discovery !=
1886 		    !!is2->is_conf.isc_discovery)
1887 			continue;
1888 
1889 		if (strcmp(is->is_conf.isc_target_addr,
1890 		    is2->is_conf.isc_target_addr) != 0)
1891 			continue;
1892 
1893 		if (is->is_conf.isc_discovery == 0 &&
1894 		    strcmp(is->is_conf.isc_target,
1895 		    is2->is_conf.isc_target) != 0)
1896 			continue;
1897 
1898 		sx_xunlock(&sc->sc_lock);
1899 		free(is, M_ISCSI);
1900 		return (EBUSY);
1901 	}
1902 
1903 	is->is_conn = icl_new_conn(is->is_conf.isc_offload,
1904 	    is->is_conf.isc_iser, "iscsi", &is->is_lock);
1905 	if (is->is_conn == NULL) {
1906 		sx_xunlock(&sc->sc_lock);
1907 		free(is, M_ISCSI);
1908 		return (EINVAL);
1909 	}
1910 	is->is_conn->ic_receive = iscsi_receive_callback;
1911 	is->is_conn->ic_error = iscsi_error_callback;
1912 	is->is_conn->ic_prv0 = is;
1913 	TAILQ_INIT(&is->is_outstanding);
1914 	STAILQ_INIT(&is->is_postponed);
1915 	mtx_init(&is->is_lock, "iscsi_lock", NULL, MTX_DEF);
1916 	cv_init(&is->is_maintenance_cv, "iscsi_mt");
1917 #ifdef ICL_KERNEL_PROXY
1918 	cv_init(&is->is_login_cv, "iscsi_login");
1919 #endif
1920 
1921 	/*
1922 	 * Set some default values, from RFC 3720, section 12.
1923 	 *
1924 	 * These values are updated by the handoff IOCTL, but are
1925 	 * needed prior to the handoff to support sending the ISER
1926 	 * login PDU.
1927 	 */
1928 	is->is_conn->ic_max_recv_data_segment_length = 8192;
1929 	is->is_conn->ic_max_send_data_segment_length = 8192;
1930 	is->is_max_burst_length = 262144;
1931 	is->is_first_burst_length = 65536;
1932 
1933 	is->is_softc = sc;
1934 	sc->sc_last_session_id++;
1935 	is->is_id = sc->sc_last_session_id;
1936 	is->is_isid[0] = 0x80; /* RFC 3720, 10.12.5: 10b, "Random" ISID. */
1937 	arc4rand(&is->is_isid[1], 5, 0);
1938 	is->is_tsih = 0;
1939 	callout_init(&is->is_callout, 1);
1940 
1941 	error = kthread_add(iscsi_maintenance_thread, is, NULL, NULL, 0, 0, "iscsimt");
1942 	if (error != 0) {
1943 		ISCSI_SESSION_WARN(is, "kthread_add(9) failed with error %d", error);
1944 		sx_xunlock(&sc->sc_lock);
1945 		return (error);
1946 	}
1947 	is->is_ping_timeout = is->is_conf.isc_ping_timeout;
1948 	if (is->is_ping_timeout < 0)
1949 		is->is_ping_timeout = ping_timeout;
1950 	is->is_login_timeout = is->is_conf.isc_login_timeout;
1951 	if (is->is_login_timeout < 0)
1952 		is->is_login_timeout = login_timeout;
1953 
1954 	sbt = mstosbt(995);
1955 	pr = mstosbt(10);
1956 	callout_reset_sbt(&is->is_callout, sbt, pr, iscsi_callout, is, 0);
1957 	TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next);
1958 
1959 	ISCSI_SESSION_LOCK(is);
1960 	/*
1961 	 * Don't notify iscsid(8) if the session is disabled and it's not
1962 	 * a discovery session,
1963 	 */
1964 	if (is->is_conf.isc_enable == 0 && is->is_conf.isc_discovery == 0) {
1965 		ISCSI_SESSION_UNLOCK(is);
1966 		sx_xunlock(&sc->sc_lock);
1967 		return (0);
1968 	}
1969 
1970 	is->is_waiting_for_iscsid = true;
1971 	strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
1972 	ISCSI_SESSION_UNLOCK(is);
1973 	cv_signal(&sc->sc_cv);
1974 	sx_xunlock(&sc->sc_lock);
1975 	return (0);
1976 }
1977 
1978 static bool
1979 iscsi_session_conf_matches(unsigned int id1, const struct iscsi_session_conf *c1,
1980     unsigned int id2, const struct iscsi_session_conf *c2)
1981 {
1982 
1983 	if (id2 != 0 && id2 != id1)
1984 		return (false);
1985 	if (c2->isc_target[0] != '\0' &&
1986 	    strcmp(c1->isc_target, c2->isc_target) != 0)
1987 		return (false);
1988 	if (c2->isc_target_addr[0] != '\0' &&
1989 	    strcmp(c1->isc_target_addr, c2->isc_target_addr) != 0)
1990 		return (false);
1991 	return (true);
1992 }
1993 
1994 static int
1995 iscsi_ioctl_session_remove(struct iscsi_softc *sc,
1996     struct iscsi_session_remove *isr)
1997 {
1998 	struct iscsi_session *is, *tmp;
1999 	bool found = false;
2000 
2001 	iscsi_sanitize_session_conf(&isr->isr_conf);
2002 
2003 	sx_xlock(&sc->sc_lock);
2004 	TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp) {
2005 		ISCSI_SESSION_LOCK(is);
2006 		if (iscsi_session_conf_matches(is->is_id, &is->is_conf,
2007 		    isr->isr_session_id, &isr->isr_conf)) {
2008 			found = true;
2009 			iscsi_session_logout(is);
2010 			iscsi_session_terminate(is);
2011 		}
2012 		ISCSI_SESSION_UNLOCK(is);
2013 	}
2014 	sx_xunlock(&sc->sc_lock);
2015 
2016 	if (!found)
2017 		return (ESRCH);
2018 
2019 	return (0);
2020 }
2021 
2022 static int
2023 iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl)
2024 {
2025 	int error;
2026 	unsigned int i = 0;
2027 	struct iscsi_session *is;
2028 	struct iscsi_session_state iss;
2029 
2030 	sx_slock(&sc->sc_lock);
2031 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
2032 		if (i >= isl->isl_nentries) {
2033 			sx_sunlock(&sc->sc_lock);
2034 			return (EMSGSIZE);
2035 		}
2036 		memset(&iss, 0, sizeof(iss));
2037 		memcpy(&iss.iss_conf, &is->is_conf, sizeof(iss.iss_conf));
2038 		iss.iss_id = is->is_id;
2039 		strlcpy(iss.iss_target_alias, is->is_target_alias, sizeof(iss.iss_target_alias));
2040 		strlcpy(iss.iss_reason, is->is_reason, sizeof(iss.iss_reason));
2041 		strlcpy(iss.iss_offload, is->is_conn->ic_offload, sizeof(iss.iss_offload));
2042 
2043 		if (is->is_conn->ic_header_crc32c)
2044 			iss.iss_header_digest = ISCSI_DIGEST_CRC32C;
2045 		else
2046 			iss.iss_header_digest = ISCSI_DIGEST_NONE;
2047 
2048 		if (is->is_conn->ic_data_crc32c)
2049 			iss.iss_data_digest = ISCSI_DIGEST_CRC32C;
2050 		else
2051 			iss.iss_data_digest = ISCSI_DIGEST_NONE;
2052 
2053 		iss.iss_max_send_data_segment_length =
2054 		    is->is_conn->ic_max_send_data_segment_length;
2055 		iss.iss_max_recv_data_segment_length =
2056 		    is->is_conn->ic_max_recv_data_segment_length;
2057 		iss.iss_max_burst_length = is->is_max_burst_length;
2058 		iss.iss_first_burst_length = is->is_first_burst_length;
2059 		iss.iss_immediate_data = is->is_immediate_data;
2060 		iss.iss_connected = is->is_connected;
2061 
2062 		error = copyout(&iss, isl->isl_pstates + i, sizeof(iss));
2063 		if (error != 0) {
2064 			sx_sunlock(&sc->sc_lock);
2065 			return (error);
2066 		}
2067 		i++;
2068 	}
2069 	sx_sunlock(&sc->sc_lock);
2070 
2071 	isl->isl_nentries = i;
2072 
2073 	return (0);
2074 }
2075 
2076 static int
2077 iscsi_ioctl_session_modify(struct iscsi_softc *sc,
2078     struct iscsi_session_modify *ism)
2079 {
2080 	struct iscsi_session *is;
2081 	const struct iscsi_session *is2;
2082 
2083 	iscsi_sanitize_session_conf(&ism->ism_conf);
2084 	if (iscsi_valid_session_conf(&ism->ism_conf) == false)
2085 		return (EINVAL);
2086 
2087 	sx_xlock(&sc->sc_lock);
2088 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
2089 		ISCSI_SESSION_LOCK(is);
2090 		if (is->is_id == ism->ism_session_id) {
2091 			/* Note that the session remains locked. */
2092 			break;
2093 		}
2094 		ISCSI_SESSION_UNLOCK(is);
2095 	}
2096 	if (is == NULL) {
2097 		sx_xunlock(&sc->sc_lock);
2098 		return (ESRCH);
2099 	}
2100 
2101 	/*
2102 	 * Prevent duplicates.
2103 	 */
2104 	TAILQ_FOREACH(is2, &sc->sc_sessions, is_next) {
2105 		if (is == is2)
2106 			continue;
2107 
2108 		if (!!ism->ism_conf.isc_discovery !=
2109 		    !!is2->is_conf.isc_discovery)
2110 			continue;
2111 
2112 		if (strcmp(ism->ism_conf.isc_target_addr,
2113 		    is2->is_conf.isc_target_addr) != 0)
2114 			continue;
2115 
2116 		if (ism->ism_conf.isc_discovery == 0 &&
2117 		    strcmp(ism->ism_conf.isc_target,
2118 		    is2->is_conf.isc_target) != 0)
2119 			continue;
2120 
2121 		ISCSI_SESSION_UNLOCK(is);
2122 		sx_xunlock(&sc->sc_lock);
2123 		return (EBUSY);
2124 	}
2125 
2126 	sx_xunlock(&sc->sc_lock);
2127 
2128 	memcpy(&is->is_conf, &ism->ism_conf, sizeof(is->is_conf));
2129 	ISCSI_SESSION_UNLOCK(is);
2130 
2131 	iscsi_session_reconnect(is);
2132 
2133 	return (0);
2134 }
2135 
2136 static int
2137 iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
2138     struct thread *td)
2139 {
2140 	struct iscsi_softc *sc;
2141 
2142 	sc = dev->si_drv1;
2143 
2144 	switch (cmd) {
2145 	case ISCSIDWAIT:
2146 		return (iscsi_ioctl_daemon_wait(sc,
2147 		    (struct iscsi_daemon_request *)arg));
2148 	case ISCSIDHANDOFF:
2149 		return (iscsi_ioctl_daemon_handoff(sc,
2150 		    (struct iscsi_daemon_handoff *)arg));
2151 	case ISCSIDFAIL:
2152 		return (iscsi_ioctl_daemon_fail(sc,
2153 		    (struct iscsi_daemon_fail *)arg));
2154 #ifdef ICL_KERNEL_PROXY
2155 	case ISCSIDCONNECT:
2156 		return (iscsi_ioctl_daemon_connect(sc,
2157 		    (struct iscsi_daemon_connect *)arg));
2158 	case ISCSIDSEND:
2159 		return (iscsi_ioctl_daemon_send(sc,
2160 		    (struct iscsi_daemon_send *)arg));
2161 	case ISCSIDRECEIVE:
2162 		return (iscsi_ioctl_daemon_receive(sc,
2163 		    (struct iscsi_daemon_receive *)arg));
2164 #endif /* ICL_KERNEL_PROXY */
2165 	case ISCSISADD:
2166 		return (iscsi_ioctl_session_add(sc,
2167 		    (struct iscsi_session_add *)arg));
2168 	case ISCSISREMOVE:
2169 		return (iscsi_ioctl_session_remove(sc,
2170 		    (struct iscsi_session_remove *)arg));
2171 	case ISCSISLIST:
2172 		return (iscsi_ioctl_session_list(sc,
2173 		    (struct iscsi_session_list *)arg));
2174 	case ISCSISMODIFY:
2175 		return (iscsi_ioctl_session_modify(sc,
2176 		    (struct iscsi_session_modify *)arg));
2177 	default:
2178 		return (EINVAL);
2179 	}
2180 }
2181 
2182 static struct iscsi_outstanding *
2183 iscsi_outstanding_find(struct iscsi_session *is, uint32_t initiator_task_tag)
2184 {
2185 	struct iscsi_outstanding *io;
2186 
2187 	ISCSI_SESSION_LOCK_ASSERT(is);
2188 
2189 	TAILQ_FOREACH(io, &is->is_outstanding, io_next) {
2190 		if (io->io_initiator_task_tag == initiator_task_tag)
2191 			return (io);
2192 	}
2193 	return (NULL);
2194 }
2195 
2196 static struct iscsi_outstanding *
2197 iscsi_outstanding_find_ccb(struct iscsi_session *is, union ccb *ccb)
2198 {
2199 	struct iscsi_outstanding *io;
2200 
2201 	ISCSI_SESSION_LOCK_ASSERT(is);
2202 
2203 	TAILQ_FOREACH(io, &is->is_outstanding, io_next) {
2204 		if (io->io_ccb == ccb)
2205 			return (io);
2206 	}
2207 	return (NULL);
2208 }
2209 
2210 static struct iscsi_outstanding *
2211 iscsi_outstanding_add(struct iscsi_session *is, struct icl_pdu *request,
2212     union ccb *ccb, uint32_t *initiator_task_tagp)
2213 {
2214 	struct iscsi_outstanding *io;
2215 	int error;
2216 
2217 	ISCSI_SESSION_LOCK_ASSERT(is);
2218 
2219 	io = uma_zalloc(iscsi_outstanding_zone, M_NOWAIT | M_ZERO);
2220 	if (io == NULL) {
2221 		ISCSI_SESSION_WARN(is, "failed to allocate %zd bytes",
2222 		    sizeof(*io));
2223 		return (NULL);
2224 	}
2225 
2226 	error = icl_conn_task_setup(is->is_conn, request, &ccb->csio,
2227 	    initiator_task_tagp, &io->io_icl_prv);
2228 	if (error != 0) {
2229 		ISCSI_SESSION_WARN(is,
2230 		    "icl_conn_task_setup() failed with error %d", error);
2231 		uma_zfree(iscsi_outstanding_zone, io);
2232 		return (NULL);
2233 	}
2234 
2235 	KASSERT(iscsi_outstanding_find(is, *initiator_task_tagp) == NULL,
2236 	    ("initiator_task_tag 0x%x already added", *initiator_task_tagp));
2237 
2238 	io->io_initiator_task_tag = *initiator_task_tagp;
2239 	io->io_ccb = ccb;
2240 	TAILQ_INSERT_TAIL(&is->is_outstanding, io, io_next);
2241 	return (io);
2242 }
2243 
2244 static void
2245 iscsi_outstanding_remove(struct iscsi_session *is, struct iscsi_outstanding *io)
2246 {
2247 
2248 	ISCSI_SESSION_LOCK_ASSERT(is);
2249 
2250 	icl_conn_task_done(is->is_conn, io->io_icl_prv);
2251 	TAILQ_REMOVE(&is->is_outstanding, io, io_next);
2252 	uma_zfree(iscsi_outstanding_zone, io);
2253 }
2254 
2255 static void
2256 iscsi_action_abort(struct iscsi_session *is, union ccb *ccb)
2257 {
2258 	struct icl_pdu *request;
2259 	struct iscsi_bhs_task_management_request *bhstmr;
2260 	struct ccb_abort *cab = &ccb->cab;
2261 	struct iscsi_outstanding *io, *aio;
2262 	uint32_t initiator_task_tag;
2263 
2264 	ISCSI_SESSION_LOCK_ASSERT(is);
2265 
2266 #if 0
2267 	KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__));
2268 #else
2269 	if (is->is_login_phase) {
2270 		ccb->ccb_h.status = CAM_REQ_ABORTED;
2271 		xpt_done(ccb);
2272 		return;
2273 	}
2274 #endif
2275 
2276 	aio = iscsi_outstanding_find_ccb(is, cab->abort_ccb);
2277 	if (aio == NULL) {
2278 		ccb->ccb_h.status = CAM_REQ_CMP;
2279 		xpt_done(ccb);
2280 		return;
2281 	}
2282 
2283 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
2284 	if (request == NULL) {
2285 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2286 		xpt_done(ccb);
2287 		return;
2288 	}
2289 
2290 	initiator_task_tag = is->is_initiator_task_tag++;
2291 	if (initiator_task_tag == 0xffffffff)
2292 		initiator_task_tag = is->is_initiator_task_tag++;
2293 
2294 	io = iscsi_outstanding_add(is, request, NULL, &initiator_task_tag);
2295 	if (io == NULL) {
2296 		icl_pdu_free(request);
2297 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2298 		xpt_done(ccb);
2299 		return;
2300 	}
2301 	io->io_referenced_task_tag = aio->io_initiator_task_tag;
2302 
2303 	bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs;
2304 	bhstmr->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_REQUEST;
2305 	bhstmr->bhstmr_function = 0x80 | BHSTMR_FUNCTION_ABORT_TASK;
2306 	bhstmr->bhstmr_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
2307 	bhstmr->bhstmr_initiator_task_tag = initiator_task_tag;
2308 	bhstmr->bhstmr_referenced_task_tag = aio->io_initiator_task_tag;
2309 
2310 	iscsi_pdu_queue_locked(request);
2311 }
2312 
2313 static void
2314 iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
2315 {
2316 	struct icl_pdu *request;
2317 	struct iscsi_bhs_scsi_command *bhssc;
2318 	struct ccb_scsiio *csio;
2319 	struct iscsi_outstanding *io;
2320 	size_t len;
2321 	uint32_t initiator_task_tag;
2322 	int error;
2323 
2324 	ISCSI_SESSION_LOCK_ASSERT(is);
2325 
2326 #if 0
2327 	KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__));
2328 #else
2329 	if (is->is_login_phase) {
2330 		ISCSI_SESSION_DEBUG(is, "called during login phase");
2331 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2332 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2333 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2334 		}
2335 		ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_DEV_QFRZN;
2336 		xpt_done(ccb);
2337 		return;
2338 	}
2339 #endif
2340 
2341 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
2342 	if (request == NULL) {
2343 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2344 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2345 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2346 		}
2347 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2348 		xpt_done(ccb);
2349 		return;
2350 	}
2351 
2352 	initiator_task_tag = is->is_initiator_task_tag++;
2353 	if (initiator_task_tag == 0xffffffff)
2354 		initiator_task_tag = is->is_initiator_task_tag++;
2355 
2356 	io = iscsi_outstanding_add(is, request, ccb, &initiator_task_tag);
2357 	if (io == NULL) {
2358 		icl_pdu_free(request);
2359 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2360 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2361 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2362 		}
2363 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2364 		xpt_done(ccb);
2365 		return;
2366 	}
2367 
2368 	csio = &ccb->csio;
2369 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
2370 	bhssc->bhssc_opcode = ISCSI_BHS_OPCODE_SCSI_COMMAND;
2371 	bhssc->bhssc_flags |= BHSSC_FLAGS_F;
2372 	switch (csio->ccb_h.flags & CAM_DIR_MASK) {
2373 	case CAM_DIR_IN:
2374 		bhssc->bhssc_flags |= BHSSC_FLAGS_R;
2375 		break;
2376 	case CAM_DIR_OUT:
2377 		bhssc->bhssc_flags |= BHSSC_FLAGS_W;
2378 		break;
2379 	}
2380 
2381 	if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
2382 		switch (csio->tag_action) {
2383 		case MSG_HEAD_OF_Q_TAG:
2384 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_HOQ;
2385 			break;
2386 		case MSG_ORDERED_Q_TAG:
2387 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ORDERED;
2388 			break;
2389 		case MSG_ACA_TASK:
2390 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ACA;
2391 			break;
2392 		case MSG_SIMPLE_Q_TAG:
2393 		default:
2394 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_SIMPLE;
2395 			break;
2396 		}
2397 	} else
2398 		bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_UNTAGGED;
2399 
2400 	if (is->is_protocol_level >= 2) {
2401 		bhssc->bhssc_pri = (csio->priority << BHSSC_PRI_SHIFT) &
2402 		    BHSSC_PRI_MASK;
2403 	}
2404 
2405 	bhssc->bhssc_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
2406 	bhssc->bhssc_initiator_task_tag = initiator_task_tag;
2407 	bhssc->bhssc_expected_data_transfer_length = htonl(csio->dxfer_len);
2408 	KASSERT(csio->cdb_len <= sizeof(bhssc->bhssc_cdb),
2409 	    ("unsupported CDB size %zd", (size_t)csio->cdb_len));
2410 
2411 	if (csio->ccb_h.flags & CAM_CDB_POINTER)
2412 		memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_ptr, csio->cdb_len);
2413 	else
2414 		memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_bytes, csio->cdb_len);
2415 
2416 	if (is->is_immediate_data &&
2417 	    (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
2418 		len = csio->dxfer_len;
2419 		//ISCSI_SESSION_DEBUG(is, "adding %zd of immediate data", len);
2420 		if (len > is->is_first_burst_length) {
2421 			ISCSI_SESSION_DEBUG(is, "len %zd -> %d", len, is->is_first_burst_length);
2422 			len = is->is_first_burst_length;
2423 		}
2424 		if (len > is->is_conn->ic_max_send_data_segment_length) {
2425 			ISCSI_SESSION_DEBUG(is, "len %zd -> %d", len,
2426 			    is->is_conn->ic_max_send_data_segment_length);
2427 			len = is->is_conn->ic_max_send_data_segment_length;
2428 		}
2429 
2430 		error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT);
2431 		if (error != 0) {
2432 			iscsi_outstanding_remove(is, io);
2433 			icl_pdu_free(request);
2434 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2435 				xpt_freeze_devq(ccb->ccb_h.path, 1);
2436 				ISCSI_SESSION_DEBUG(is, "freezing devq");
2437 			}
2438 			ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2439 			xpt_done(ccb);
2440 			return;
2441 		}
2442 	}
2443 	iscsi_pdu_queue_locked(request);
2444 }
2445 
2446 static void
2447 iscsi_action(struct cam_sim *sim, union ccb *ccb)
2448 {
2449 	struct iscsi_session *is;
2450 
2451 	is = cam_sim_softc(sim);
2452 
2453 	ISCSI_SESSION_LOCK_ASSERT(is);
2454 
2455 	if (is->is_terminating ||
2456 	    (is->is_connected == false && fail_on_disconnection)) {
2457 		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2458 		xpt_done(ccb);
2459 		return;
2460 	}
2461 
2462 	/*
2463 	 * Make sure CAM doesn't sneak in a CCB just after freezing the queue.
2464 	 */
2465 	if (is->is_simq_frozen == true) {
2466 		ccb->ccb_h.status &= ~(CAM_SIM_QUEUED | CAM_STATUS_MASK);
2467 		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
2468 		/* Don't freeze the devq - the SIM queue is already frozen. */
2469 		xpt_done(ccb);
2470 		return;
2471 	}
2472 
2473 	switch (ccb->ccb_h.func_code) {
2474 	case XPT_PATH_INQ:
2475 	{
2476 		struct ccb_pathinq *cpi = &ccb->cpi;
2477 
2478 		cpi->version_num = 1;
2479 		cpi->hba_inquiry = PI_TAG_ABLE;
2480 		cpi->target_sprt = 0;
2481 		cpi->hba_misc = PIM_EXTLUNS;
2482 		/*
2483 		 * XXX: It shouldn't ever be NULL; this could be turned
2484 		 *      into a KASSERT eventually.
2485 		 */
2486 		if (is->is_conn == NULL)
2487 			ISCSI_WARN("NULL conn");
2488 		else if (is->is_conn->ic_unmapped)
2489 			cpi->hba_misc |= PIM_UNMAPPED;
2490 		cpi->hba_eng_cnt = 0;
2491 		cpi->max_target = 0;
2492 		/*
2493 		 * Note that the variable below is only relevant for targets
2494 		 * that don't claim compliance with anything above SPC2, which
2495 		 * means they don't support REPORT_LUNS.
2496 		 */
2497 		cpi->max_lun = 255;
2498 		cpi->initiator_id = ~0;
2499 		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2500 		strlcpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
2501 		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2502 		cpi->unit_number = cam_sim_unit(sim);
2503 		cpi->bus_id = cam_sim_bus(sim);
2504 		cpi->base_transfer_speed = 150000; /* XXX */
2505 		cpi->transport = XPORT_ISCSI;
2506 		cpi->transport_version = 0;
2507 		cpi->protocol = PROTO_SCSI;
2508 		cpi->protocol_version = SCSI_REV_SPC3;
2509 		cpi->maxio = maxphys;
2510 		cpi->ccb_h.status = CAM_REQ_CMP;
2511 		break;
2512 	}
2513 	case XPT_GET_TRAN_SETTINGS:
2514 	{
2515 		struct ccb_trans_settings	*cts;
2516 		struct ccb_trans_settings_scsi	*scsi;
2517 
2518 		cts = &ccb->cts;
2519 		scsi = &cts->proto_specific.scsi;
2520 
2521 		cts->protocol = PROTO_SCSI;
2522 		cts->protocol_version = SCSI_REV_SPC3;
2523 		cts->transport = XPORT_ISCSI;
2524 		cts->transport_version = 0;
2525 		scsi->valid = CTS_SCSI_VALID_TQ;
2526 		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
2527 		cts->ccb_h.status = CAM_REQ_CMP;
2528 		break;
2529 	}
2530 	case XPT_CALC_GEOMETRY:
2531 		cam_calc_geometry(&ccb->ccg, /*extended*/1);
2532 		ccb->ccb_h.status = CAM_REQ_CMP;
2533 		break;
2534 #if 0
2535 	/*
2536 	 * XXX: What's the point?
2537 	 */
2538 	case XPT_RESET_BUS:
2539 	case XPT_TERM_IO:
2540 		ISCSI_SESSION_DEBUG(is, "faking success for reset, abort, or term_io");
2541 		ccb->ccb_h.status = CAM_REQ_CMP;
2542 		break;
2543 #endif
2544 	case XPT_ABORT:
2545 		iscsi_action_abort(is, ccb);
2546 		return;
2547 	case XPT_SCSI_IO:
2548 		iscsi_action_scsiio(is, ccb);
2549 		return;
2550 	default:
2551 #if 0
2552 		ISCSI_SESSION_DEBUG(is, "got unsupported code 0x%x", ccb->ccb_h.func_code);
2553 #endif
2554 		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2555 		break;
2556 	}
2557 	xpt_done(ccb);
2558 }
2559 
2560 static void
2561 iscsi_terminate_sessions(struct iscsi_softc *sc)
2562 {
2563 	struct iscsi_session *is;
2564 
2565 	sx_slock(&sc->sc_lock);
2566 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next)
2567 		iscsi_session_terminate(is);
2568 	while(!TAILQ_EMPTY(&sc->sc_sessions)) {
2569 		ISCSI_DEBUG("waiting for sessions to terminate");
2570 		cv_wait(&sc->sc_cv, &sc->sc_lock);
2571 	}
2572 	ISCSI_DEBUG("all sessions terminated");
2573 	sx_sunlock(&sc->sc_lock);
2574 }
2575 
2576 static void
2577 iscsi_shutdown_pre(struct iscsi_softc *sc)
2578 {
2579 	struct iscsi_session *is;
2580 
2581 	if (!fail_on_shutdown)
2582 		return;
2583 
2584 	/*
2585 	 * If we have any sessions waiting for reconnection, request
2586 	 * maintenance thread to fail them immediately instead of waiting
2587 	 * for reconnect timeout.
2588 	 *
2589 	 * This prevents LUNs with mounted filesystems that are supported
2590 	 * by disconnected iSCSI sessions from hanging, however it will
2591 	 * fail all queued BIOs.
2592 	 */
2593 	ISCSI_DEBUG("forcing failing all disconnected sessions due to shutdown");
2594 
2595 	fail_on_disconnection = 1;
2596 
2597 	sx_slock(&sc->sc_lock);
2598 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
2599 		ISCSI_SESSION_LOCK(is);
2600 		if (!is->is_connected) {
2601 			ISCSI_SESSION_DEBUG(is, "force failing disconnected session early");
2602 			iscsi_session_reconnect(is);
2603 		}
2604 		ISCSI_SESSION_UNLOCK(is);
2605 	}
2606 	sx_sunlock(&sc->sc_lock);
2607 }
2608 
2609 static void
2610 iscsi_shutdown_post(struct iscsi_softc *sc)
2611 {
2612 
2613 	if (!KERNEL_PANICKED()) {
2614 		ISCSI_DEBUG("removing all sessions due to shutdown");
2615 		iscsi_terminate_sessions(sc);
2616 	}
2617 }
2618 
2619 static int
2620 iscsi_load(void)
2621 {
2622 	int error;
2623 
2624 	sc = malloc(sizeof(*sc), M_ISCSI, M_ZERO | M_WAITOK);
2625 	sx_init(&sc->sc_lock, "iscsi");
2626 	TAILQ_INIT(&sc->sc_sessions);
2627 	cv_init(&sc->sc_cv, "iscsi_cv");
2628 
2629 	iscsi_outstanding_zone = uma_zcreate("iscsi_outstanding",
2630 	    sizeof(struct iscsi_outstanding), NULL, NULL, NULL, NULL,
2631 	    UMA_ALIGN_PTR, 0);
2632 
2633 	error = make_dev_p(MAKEDEV_CHECKNAME, &sc->sc_cdev, &iscsi_cdevsw,
2634 	    NULL, UID_ROOT, GID_WHEEL, 0600, "iscsi");
2635 	if (error != 0) {
2636 		ISCSI_WARN("failed to create device node, error %d", error);
2637 		return (error);
2638 	}
2639 	sc->sc_cdev->si_drv1 = sc;
2640 
2641 	sc->sc_shutdown_pre_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync,
2642 	    iscsi_shutdown_pre, sc, SHUTDOWN_PRI_FIRST);
2643 	/*
2644 	 * shutdown_post_sync needs to run after filesystem shutdown and before
2645 	 * CAM shutdown - otherwise when rebooting with an iSCSI session that is
2646 	 * disconnected but has outstanding requests, dashutdown() will hang on
2647 	 * cam_periph_runccb().
2648 	 */
2649 	sc->sc_shutdown_post_eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
2650 	    iscsi_shutdown_post, sc, SHUTDOWN_PRI_DEFAULT - 1);
2651 
2652 	return (0);
2653 }
2654 
2655 static int
2656 iscsi_unload(void)
2657 {
2658 
2659 	/* Awaken any threads asleep in iscsi_ioctl(). */
2660 	sx_xlock(&sc->sc_lock);
2661 	sc->sc_unloading = true;
2662 	cv_signal(&sc->sc_cv);
2663 	sx_xunlock(&sc->sc_lock);
2664 
2665 	if (sc->sc_cdev != NULL) {
2666 		ISCSI_DEBUG("removing device node");
2667 		destroy_dev(sc->sc_cdev);
2668 		ISCSI_DEBUG("device node removed");
2669 	}
2670 
2671 	if (sc->sc_shutdown_pre_eh != NULL)
2672 		EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_pre_eh);
2673 	if (sc->sc_shutdown_post_eh != NULL)
2674 		EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_post_eh);
2675 
2676 	iscsi_terminate_sessions(sc);
2677 
2678 	uma_zdestroy(iscsi_outstanding_zone);
2679 	sx_destroy(&sc->sc_lock);
2680 	cv_destroy(&sc->sc_cv);
2681 	free(sc, M_ISCSI);
2682 	return (0);
2683 }
2684 
2685 static int
2686 iscsi_quiesce(void)
2687 {
2688 	sx_slock(&sc->sc_lock);
2689 	if (!TAILQ_EMPTY(&sc->sc_sessions)) {
2690 		sx_sunlock(&sc->sc_lock);
2691 		return (EBUSY);
2692 	}
2693 	sx_sunlock(&sc->sc_lock);
2694 	return (0);
2695 }
2696 
2697 static int
2698 iscsi_modevent(module_t mod, int what, void *arg)
2699 {
2700 	int error;
2701 
2702 	switch (what) {
2703 	case MOD_LOAD:
2704 		error = iscsi_load();
2705 		break;
2706 	case MOD_UNLOAD:
2707 		error = iscsi_unload();
2708 		break;
2709 	case MOD_QUIESCE:
2710 		error = iscsi_quiesce();
2711 		break;
2712 	default:
2713 		error = EINVAL;
2714 		break;
2715 	}
2716 	return (error);
2717 }
2718 
2719 moduledata_t iscsi_data = {
2720 	"iscsi",
2721 	iscsi_modevent,
2722 	0
2723 };
2724 
2725 DECLARE_MODULE(iscsi, iscsi_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
2726 MODULE_DEPEND(iscsi, cam, 1, 1, 1);
2727 MODULE_DEPEND(iscsi, icl, 1, 1, 1);
2728