xref: /freebsd/sys/dev/iscsi/iscsi.c (revision 3ae0125a99dc29a8f8ca9ba933825e2447b54c6b)
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 #include <sys/param.h>
33 #include <sys/condvar.h>
34 #include <sys/conf.h>
35 #include <sys/endian.h>
36 #include <sys/eventhandler.h>
37 #include <sys/file.h>
38 #include <sys/kernel.h>
39 #include <sys/kthread.h>
40 #include <sys/lock.h>
41 #include <sys/malloc.h>
42 #include <sys/mutex.h>
43 #include <sys/module.h>
44 #include <sys/sysctl.h>
45 #include <sys/systm.h>
46 #include <sys/sx.h>
47 #include <vm/uma.h>
48 
49 #include <cam/cam.h>
50 #include <cam/cam_ccb.h>
51 #include <cam/cam_xpt.h>
52 #include <cam/cam_debug.h>
53 #include <cam/cam_sim.h>
54 #include <cam/cam_xpt_sim.h>
55 #include <cam/cam_xpt_periph.h>
56 #include <cam/cam_periph.h>
57 #include <cam/scsi/scsi_all.h>
58 #include <cam/scsi/scsi_message.h>
59 
60 #include "iscsi_ioctl.h"
61 #include "iscsi.h"
62 #include "icl.h"
63 #include "iscsi_proto.h"
64 
65 #ifdef ICL_KERNEL_PROXY
66 #include <sys/socketvar.h>
67 #endif
68 
69 /*
70  * XXX: This is global so the iscsi_unload() can access it.
71  * 	Think about how to do this properly.
72  */
73 static struct iscsi_softc	*sc;
74 
75 SYSCTL_NODE(_kern, OID_AUTO, iscsi, CTLFLAG_RD, 0, "iSCSI initiator");
76 static int debug = 1;
77 TUNABLE_INT("kern.iscsi.debug", &debug);
78 SYSCTL_INT(_kern_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN,
79     &debug, 0, "Enable debug messages");
80 static int ping_timeout = 5;
81 TUNABLE_INT("kern.iscsi.ping_timeout", &ping_timeout);
82 SYSCTL_INT(_kern_iscsi, OID_AUTO, ping_timeout, CTLFLAG_RWTUN, &ping_timeout,
83     0, "Timeout for ping (NOP-Out) requests, in seconds");
84 static int iscsid_timeout = 60;
85 TUNABLE_INT("kern.iscsi.iscsid_timeout", &iscsid_timeout);
86 SYSCTL_INT(_kern_iscsi, OID_AUTO, iscsid_timeout, CTLFLAG_RWTUN, &iscsid_timeout,
87     0, "Time to wait for iscsid(8) to handle reconnection, in seconds");
88 static int login_timeout = 60;
89 TUNABLE_INT("kern.iscsi.login_timeout", &login_timeout);
90 SYSCTL_INT(_kern_iscsi, OID_AUTO, login_timeout, CTLFLAG_RWTUN, &login_timeout,
91     0, "Time to wait for iscsid(8) to finish Login Phase, in seconds");
92 static int maxtags = 255;
93 TUNABLE_INT("kern.iscsi.maxtags", &maxtags);
94 SYSCTL_INT(_kern_iscsi, OID_AUTO, maxtags, CTLFLAG_RWTUN, &maxtags,
95     0, "Max number of IO requests queued");
96 
97 static MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI initiator");
98 static uma_zone_t iscsi_outstanding_zone;
99 
100 #define	CONN_SESSION(X)	((struct iscsi_session *)X->ic_prv0)
101 #define	PDU_SESSION(X)	(CONN_SESSION(X->ip_conn))
102 
103 #define	ISCSI_DEBUG(X, ...)						\
104 	do {								\
105 		if (debug > 1) 						\
106 			printf("%s: " X "\n", __func__, ## __VA_ARGS__);\
107 	} while (0)
108 
109 #define	ISCSI_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	ISCSI_SESSION_DEBUG(S, X, ...)					\
118 	do {								\
119 		if (debug > 1) {					\
120 			printf("%s: %s (%s): " X "\n",			\
121 			    __func__, S->is_conf.isc_target_addr,	\
122 			    S->is_conf.isc_target, ## __VA_ARGS__);	\
123 		}							\
124 	} while (0)
125 
126 #define	ISCSI_SESSION_WARN(S, X, ...)					\
127 	do {								\
128 		if (debug > 0) {					\
129 			printf("WARNING: %s (%s): " X "\n",		\
130 			    S->is_conf.isc_target_addr,			\
131 			    S->is_conf.isc_target, ## __VA_ARGS__);	\
132 		}							\
133 	} while (0)
134 
135 #define ISCSI_SESSION_LOCK(X)		mtx_lock(&X->is_lock)
136 #define ISCSI_SESSION_UNLOCK(X)		mtx_unlock(&X->is_lock)
137 #define ISCSI_SESSION_LOCK_ASSERT(X)	mtx_assert(&X->is_lock, MA_OWNED)
138 
139 static int	iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg,
140 		    int mode, struct thread *td);
141 
142 static struct cdevsw iscsi_cdevsw = {
143      .d_version = D_VERSION,
144      .d_ioctl   = iscsi_ioctl,
145      .d_name    = "iscsi",
146 };
147 
148 static void	iscsi_pdu_queue_locked(struct icl_pdu *request);
149 static void	iscsi_pdu_queue(struct icl_pdu *request);
150 static void	iscsi_pdu_update_statsn(const struct icl_pdu *response);
151 static void	iscsi_pdu_handle_nop_in(struct icl_pdu *response);
152 static void	iscsi_pdu_handle_scsi_response(struct icl_pdu *response);
153 static void	iscsi_pdu_handle_data_in(struct icl_pdu *response);
154 static void	iscsi_pdu_handle_logout_response(struct icl_pdu *response);
155 static void	iscsi_pdu_handle_r2t(struct icl_pdu *response);
156 static void	iscsi_pdu_handle_async_message(struct icl_pdu *response);
157 static void	iscsi_pdu_handle_reject(struct icl_pdu *response);
158 static void	iscsi_session_reconnect(struct iscsi_session *is);
159 static void	iscsi_session_terminate(struct iscsi_session *is);
160 static void	iscsi_action(struct cam_sim *sim, union ccb *ccb);
161 static void	iscsi_poll(struct cam_sim *sim);
162 static struct iscsi_outstanding	*iscsi_outstanding_find(struct iscsi_session *is,
163 		    uint32_t initiator_task_tag);
164 static int	iscsi_outstanding_add(struct iscsi_session *is,
165 		    uint32_t initiator_task_tag, union ccb *ccb);
166 static void	iscsi_outstanding_remove(struct iscsi_session *is,
167 		    struct iscsi_outstanding *io);
168 
169 static bool
170 iscsi_pdu_prepare(struct icl_pdu *request)
171 {
172 	struct iscsi_session *is;
173 	struct iscsi_bhs_scsi_command *bhssc;
174 
175 	is = PDU_SESSION(request);
176 
177 	ISCSI_SESSION_LOCK_ASSERT(is);
178 
179 	/*
180 	 * We're only using fields common for all the request
181 	 * (initiator -> target) PDUs.
182 	 */
183 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
184 
185 	/*
186 	 * Data-Out PDU does not contain CmdSN.
187 	 */
188 	if (bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_OUT) {
189 		if (is->is_cmdsn > is->is_maxcmdsn &&
190 		    (bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) {
191 			/*
192 			 * Current MaxCmdSN prevents us from sending any more
193 			 * SCSI Command PDUs to the target; postpone the PDU.
194 			 * It will get resent by either iscsi_pdu_queue(),
195 			 * or by maintenance thread.
196 			 */
197 #if 0
198 			ISCSI_SESSION_DEBUG(is, "postponing send, CmdSN %d, ExpCmdSN %d, MaxCmdSN %d, opcode 0x%x",
199 			    is->is_cmdsn, is->is_expcmdsn, is->is_maxcmdsn, bhssc->bhssc_opcode);
200 #endif
201 			return (true);
202 		}
203 		bhssc->bhssc_cmdsn = htonl(is->is_cmdsn);
204 		if ((bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0)
205 			is->is_cmdsn++;
206 	}
207 	bhssc->bhssc_expstatsn = htonl(is->is_statsn + 1);
208 
209 	return (false);
210 }
211 
212 static void
213 iscsi_session_send_postponed(struct iscsi_session *is)
214 {
215 	struct icl_pdu *request;
216 	bool postpone;
217 
218 	ISCSI_SESSION_LOCK_ASSERT(is);
219 
220 	while (!STAILQ_EMPTY(&is->is_postponed)) {
221 		request = STAILQ_FIRST(&is->is_postponed);
222 		postpone = iscsi_pdu_prepare(request);
223 		if (postpone)
224 			break;
225 		STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next);
226 		icl_pdu_queue(request);
227 	}
228 }
229 
230 static void
231 iscsi_pdu_queue_locked(struct icl_pdu *request)
232 {
233 	struct iscsi_session *is;
234 	bool postpone;
235 
236 	is = PDU_SESSION(request);
237 	ISCSI_SESSION_LOCK_ASSERT(is);
238 	iscsi_session_send_postponed(is);
239 	postpone = iscsi_pdu_prepare(request);
240 	if (postpone) {
241 		STAILQ_INSERT_TAIL(&is->is_postponed, request, ip_next);
242 		return;
243 	}
244 	icl_pdu_queue(request);
245 }
246 
247 static void
248 iscsi_pdu_queue(struct icl_pdu *request)
249 {
250 	struct iscsi_session *is;
251 
252 	is = PDU_SESSION(request);
253 	ISCSI_SESSION_LOCK(is);
254 	iscsi_pdu_queue_locked(request);
255 	ISCSI_SESSION_UNLOCK(is);
256 }
257 
258 static void
259 iscsi_session_logout(struct iscsi_session *is)
260 {
261 	struct icl_pdu *request;
262 	struct iscsi_bhs_logout_request *bhslr;
263 
264 	request = icl_pdu_new_bhs(is->is_conn, M_NOWAIT);
265 	if (request == NULL)
266 		return;
267 
268 	bhslr = (struct iscsi_bhs_logout_request *)request->ip_bhs;
269 	bhslr->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_REQUEST;
270 	bhslr->bhslr_reason = BHSLR_REASON_CLOSE_SESSION;
271 	iscsi_pdu_queue_locked(request);
272 }
273 
274 static void
275 iscsi_session_terminate_tasks(struct iscsi_session *is, bool requeue)
276 {
277 	struct iscsi_outstanding *io, *tmp;
278 
279 	ISCSI_SESSION_LOCK_ASSERT(is);
280 
281 	TAILQ_FOREACH_SAFE(io, &is->is_outstanding, io_next, tmp) {
282 		if (requeue) {
283 			io->io_ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
284 			io->io_ccb->ccb_h.status |= CAM_REQUEUE_REQ;
285 		} else {
286 			io->io_ccb->ccb_h.status = CAM_REQ_ABORTED;
287 		}
288 
289 		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
290 			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
291 			ISCSI_SESSION_DEBUG(is, "freezing devq");
292 		}
293 		io->io_ccb->ccb_h.status |= CAM_DEV_QFRZN;
294 		xpt_done(io->io_ccb);
295 		iscsi_outstanding_remove(is, io);
296 	}
297 }
298 
299 static void
300 iscsi_maintenance_thread_reconnect(struct iscsi_session *is)
301 {
302 	struct icl_pdu *pdu;
303 
304 	icl_conn_shutdown(is->is_conn);
305 	icl_conn_close(is->is_conn);
306 
307 	ISCSI_SESSION_LOCK(is);
308 
309 #ifdef ICL_KERNEL_PROXY
310 	if (is->is_login_pdu != NULL) {
311 		icl_pdu_free(is->is_login_pdu);
312 		is->is_login_pdu = NULL;
313 	}
314 	cv_signal(&is->is_login_cv);
315 #endif
316 
317 	/*
318 	 * Don't queue any new PDUs.
319 	 */
320 	if (is->is_sim != NULL && is->is_simq_frozen == false) {
321 		ISCSI_SESSION_DEBUG(is, "freezing");
322 		xpt_freeze_simq(is->is_sim, 1);
323 		is->is_simq_frozen = true;
324 	}
325 
326 	/*
327 	 * Remove postponed PDUs.
328 	 */
329 	while (!STAILQ_EMPTY(&is->is_postponed)) {
330 		pdu = STAILQ_FIRST(&is->is_postponed);
331 		STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next);
332 		icl_pdu_free(pdu);
333 	}
334 
335 	/*
336 	 * Terminate SCSI tasks, asking CAM to requeue them.
337 	 */
338 	//ISCSI_SESSION_DEBUG(is, "terminating tasks");
339 	iscsi_session_terminate_tasks(is, true);
340 
341 	KASSERT(TAILQ_EMPTY(&is->is_outstanding),
342 	    ("destroying session with active tasks"));
343 	KASSERT(STAILQ_EMPTY(&is->is_postponed),
344 	    ("destroying session with postponed PDUs"));
345 
346 	/*
347 	 * Request immediate reconnection from iscsid(8).
348 	 */
349 	//ISCSI_SESSION_DEBUG(is, "waking up iscsid(8)");
350 	is->is_connected = false;
351 	is->is_reconnecting = false;
352 	is->is_login_phase = false;
353 	is->is_waiting_for_iscsid = true;
354 	strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
355 	is->is_timeout = 0;
356 	ISCSI_SESSION_UNLOCK(is);
357 	cv_signal(&is->is_softc->sc_cv);
358 }
359 
360 static void
361 iscsi_maintenance_thread_terminate(struct iscsi_session *is)
362 {
363 	struct iscsi_softc *sc;
364 	struct icl_pdu *pdu;
365 
366 	sc = is->is_softc;
367 	sx_xlock(&sc->sc_lock);
368 	TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
369 	sx_xunlock(&sc->sc_lock);
370 
371 	icl_conn_close(is->is_conn);
372 
373 	ISCSI_SESSION_LOCK(is);
374 
375 	KASSERT(is->is_terminating, ("is_terminating == false"));
376 
377 #ifdef ICL_KERNEL_PROXY
378 	if (is->is_login_pdu != NULL) {
379 		icl_pdu_free(is->is_login_pdu);
380 		is->is_login_pdu = NULL;
381 	}
382 	cv_signal(&is->is_login_cv);
383 #endif
384 
385 	/*
386 	 * Don't queue any new PDUs.
387 	 */
388 	callout_drain(&is->is_callout);
389 	if (is->is_sim != NULL && is->is_simq_frozen == false) {
390 		ISCSI_SESSION_DEBUG(is, "freezing");
391 		xpt_freeze_simq(is->is_sim, 1);
392 		is->is_simq_frozen = true;
393 	}
394 
395 	/*
396 	 * Remove postponed PDUs.
397 	 */
398 	while (!STAILQ_EMPTY(&is->is_postponed)) {
399 		pdu = STAILQ_FIRST(&is->is_postponed);
400 		STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next);
401 		icl_pdu_free(pdu);
402 	}
403 
404 	/*
405 	 * Forcibly terminate SCSI tasks.
406 	 */
407 	ISCSI_SESSION_DEBUG(is, "terminating tasks");
408 	iscsi_session_terminate_tasks(is, false);
409 
410 	/*
411 	 * Deregister CAM.
412 	 */
413 	if (is->is_sim != NULL) {
414 		ISCSI_SESSION_DEBUG(is, "deregistering SIM");
415 		xpt_async(AC_LOST_DEVICE, is->is_path, NULL);
416 
417 		if (is->is_simq_frozen) {
418 			xpt_release_simq(is->is_sim, 1);
419 			is->is_simq_frozen = false;
420 		}
421 
422 		xpt_free_path(is->is_path);
423 		xpt_bus_deregister(cam_sim_path(is->is_sim));
424 		cam_sim_free(is->is_sim, TRUE /*free_devq*/);
425 		is->is_sim = NULL;
426 	}
427 
428 	KASSERT(TAILQ_EMPTY(&is->is_outstanding),
429 	    ("destroying session with active tasks"));
430 	KASSERT(STAILQ_EMPTY(&is->is_postponed),
431 	    ("destroying session with postponed PDUs"));
432 
433 	ISCSI_SESSION_UNLOCK(is);
434 
435 	icl_conn_free(is->is_conn);
436 	mtx_destroy(&is->is_lock);
437 	cv_destroy(&is->is_maintenance_cv);
438 #ifdef ICL_KERNEL_PROXY
439 	cv_destroy(&is->is_login_cv);
440 #endif
441 	ISCSI_SESSION_DEBUG(is, "terminated");
442 	free(is, M_ISCSI);
443 
444 	/*
445 	 * The iscsi_unload() routine might be waiting.
446 	 */
447 	cv_signal(&sc->sc_cv);
448 }
449 
450 static void
451 iscsi_maintenance_thread(void *arg)
452 {
453 	struct iscsi_session *is;
454 
455 	is = arg;
456 
457 	for (;;) {
458 		ISCSI_SESSION_LOCK(is);
459 		if (is->is_reconnecting == false &&
460 		    is->is_terminating == false &&
461 		    STAILQ_EMPTY(&is->is_postponed))
462 			cv_wait(&is->is_maintenance_cv, &is->is_lock);
463 
464 		if (is->is_reconnecting) {
465 			ISCSI_SESSION_UNLOCK(is);
466 			iscsi_maintenance_thread_reconnect(is);
467 			continue;
468 		}
469 
470 		if (is->is_terminating) {
471 			ISCSI_SESSION_UNLOCK(is);
472 			iscsi_maintenance_thread_terminate(is);
473 			kthread_exit();
474 			return;
475 		}
476 
477 		iscsi_session_send_postponed(is);
478 		ISCSI_SESSION_UNLOCK(is);
479 	}
480 }
481 
482 static void
483 iscsi_session_reconnect(struct iscsi_session *is)
484 {
485 
486 	/*
487 	 * XXX: We can't use locking here, because
488 	 * 	it's being called from various contexts.
489 	 * 	Hope it doesn't break anything.
490 	 */
491 	if (is->is_reconnecting)
492 		return;
493 
494 	is->is_reconnecting = true;
495 	cv_signal(&is->is_maintenance_cv);
496 }
497 
498 static void
499 iscsi_session_terminate(struct iscsi_session *is)
500 {
501 	if (is->is_terminating)
502 		return;
503 
504 	is->is_terminating = true;
505 
506 #if 0
507 	iscsi_session_logout(is);
508 #endif
509 	cv_signal(&is->is_maintenance_cv);
510 }
511 
512 static void
513 iscsi_callout(void *context)
514 {
515 	struct icl_pdu *request;
516 	struct iscsi_bhs_nop_out *bhsno;
517 	struct iscsi_session *is;
518 	bool reconnect_needed = false;
519 
520 	is = context;
521 
522 	if (is->is_terminating)
523 		return;
524 
525 	callout_schedule(&is->is_callout, 1 * hz);
526 
527 	ISCSI_SESSION_LOCK(is);
528 	is->is_timeout++;
529 
530 	if (is->is_waiting_for_iscsid) {
531 		if (is->is_timeout > iscsid_timeout) {
532 			ISCSI_SESSION_WARN(is, "timed out waiting for iscsid(8) "
533 			    "for %d seconds; reconnecting",
534 			    is->is_timeout);
535 			reconnect_needed = true;
536 		}
537 		goto out;
538 	}
539 
540 	if (is->is_login_phase) {
541 		if (is->is_timeout > login_timeout) {
542 			ISCSI_SESSION_WARN(is, "login timed out after %d seconds; "
543 			    "reconnecting", is->is_timeout);
544 			reconnect_needed = true;
545 		}
546 		goto out;
547 	}
548 
549 	if (is->is_timeout >= ping_timeout) {
550 		ISCSI_SESSION_WARN(is, "no ping reply (NOP-In) after %d seconds; "
551 		    "reconnecting", ping_timeout);
552 		reconnect_needed = true;
553 		goto out;
554 	}
555 
556 	ISCSI_SESSION_UNLOCK(is);
557 
558 	/*
559 	 * If the ping was reset less than one second ago - which means
560 	 * that we've received some PDU during the last second - assume
561 	 * the traffic flows correctly and don't bother sending a NOP-Out.
562 	 *
563 	 * (It's 2 - one for one second, and one for incrementing is_timeout
564 	 * earlier in this routine.)
565 	 */
566 	if (is->is_timeout < 2)
567 		return;
568 
569 	request = icl_pdu_new_bhs(is->is_conn, M_NOWAIT);
570 	if (request == NULL) {
571 		ISCSI_SESSION_WARN(is, "failed to allocate PDU");
572 		return;
573 	}
574 	bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
575 	bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT |
576 	    ISCSI_BHS_OPCODE_IMMEDIATE;
577 	bhsno->bhsno_flags = 0x80;
578 	bhsno->bhsno_target_transfer_tag = 0xffffffff;
579 	iscsi_pdu_queue(request);
580 	return;
581 
582 out:
583 	ISCSI_SESSION_UNLOCK(is);
584 
585 	if (reconnect_needed)
586 		iscsi_session_reconnect(is);
587 }
588 
589 static void
590 iscsi_pdu_update_statsn(const struct icl_pdu *response)
591 {
592 	const struct iscsi_bhs_data_in *bhsdi;
593 	struct iscsi_session *is;
594 	uint32_t expcmdsn, maxcmdsn;
595 
596 	is = PDU_SESSION(response);
597 
598 	ISCSI_SESSION_LOCK_ASSERT(is);
599 
600 	/*
601 	 * We're only using fields common for all the response
602 	 * (target -> initiator) PDUs.
603 	 */
604 	bhsdi = (const struct iscsi_bhs_data_in *)response->ip_bhs;
605 	/*
606 	 * Ok, I lied.  In case of Data-In, "The fields StatSN, Status,
607 	 * and Residual Count only have meaningful content if the S bit
608 	 * is set to 1", so we also need to check the bit specific for
609 	 * Data-In PDU.
610 	 */
611 	if (bhsdi->bhsdi_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN ||
612 	    (bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0) {
613 		if (ntohl(bhsdi->bhsdi_statsn) < is->is_statsn) {
614 			ISCSI_SESSION_WARN(is,
615 			    "PDU StatSN %d >= session StatSN %d, opcode 0x%x",
616 			    is->is_statsn, ntohl(bhsdi->bhsdi_statsn),
617 			    bhsdi->bhsdi_opcode);
618 		}
619 		is->is_statsn = ntohl(bhsdi->bhsdi_statsn);
620 	}
621 
622 	expcmdsn = ntohl(bhsdi->bhsdi_expcmdsn);
623 	maxcmdsn = ntohl(bhsdi->bhsdi_maxcmdsn);
624 
625 	/*
626 	 * XXX: Compare using Serial Arithmetic Sense.
627 	 */
628 	if (maxcmdsn + 1 < expcmdsn) {
629 		ISCSI_SESSION_DEBUG(is, "PDU MaxCmdSN %d + 1 < PDU ExpCmdSN %d; ignoring",
630 		    maxcmdsn, expcmdsn);
631 	} else {
632 		if (maxcmdsn > is->is_maxcmdsn) {
633 			is->is_maxcmdsn = maxcmdsn;
634 
635 			/*
636 			 * Command window increased; kick the maintanance thread
637 			 * to send out postponed commands.
638 			 */
639 			if (!STAILQ_EMPTY(&is->is_postponed))
640 				cv_signal(&is->is_maintenance_cv);
641 		} else if (maxcmdsn < is->is_maxcmdsn) {
642 			ISCSI_SESSION_DEBUG(is, "PDU MaxCmdSN %d < session MaxCmdSN %d; ignoring",
643 			    maxcmdsn, is->is_maxcmdsn);
644 		}
645 
646 		if (expcmdsn > is->is_expcmdsn) {
647 			is->is_expcmdsn = expcmdsn;
648 		} else if (expcmdsn < is->is_expcmdsn) {
649 			ISCSI_SESSION_DEBUG(is, "PDU ExpCmdSN %d < session ExpCmdSN %d; ignoring",
650 			    expcmdsn, is->is_expcmdsn);
651 		}
652 	}
653 
654 	/*
655 	 * Every incoming PDU - not just NOP-In - resets the ping timer.
656 	 * The purpose of the timeout is to reset the connection when it stalls;
657 	 * we don't want this to happen when NOP-In or NOP-Out ends up delayed
658 	 * in some queue.
659 	 */
660 	is->is_timeout = 0;
661 }
662 
663 static void
664 iscsi_receive_callback(struct icl_pdu *response)
665 {
666 	struct iscsi_session *is;
667 
668 	is = PDU_SESSION(response);
669 
670 	ISCSI_SESSION_LOCK(is);
671 
672 #ifdef ICL_KERNEL_PROXY
673 	if (is->is_login_phase) {
674 		if (is->is_login_pdu == NULL)
675 			is->is_login_pdu = response;
676 		else
677 			icl_pdu_free(response);
678 		ISCSI_SESSION_UNLOCK(is);
679 		cv_signal(&is->is_login_cv);
680 		return;
681 	}
682 #endif
683 
684 	iscsi_pdu_update_statsn(response);
685 
686 	/*
687 	 * The handling routine is responsible for freeing the PDU
688 	 * when it's no longer needed.
689 	 */
690 	switch (response->ip_bhs->bhs_opcode) {
691 	case ISCSI_BHS_OPCODE_NOP_IN:
692 		iscsi_pdu_handle_nop_in(response);
693 		break;
694 	case ISCSI_BHS_OPCODE_SCSI_RESPONSE:
695 		iscsi_pdu_handle_scsi_response(response);
696 		break;
697 	case ISCSI_BHS_OPCODE_SCSI_DATA_IN:
698 		iscsi_pdu_handle_data_in(response);
699 		break;
700 	case ISCSI_BHS_OPCODE_LOGOUT_RESPONSE:
701 		iscsi_pdu_handle_logout_response(response);
702 		break;
703 	case ISCSI_BHS_OPCODE_R2T:
704 		iscsi_pdu_handle_r2t(response);
705 		break;
706 	case ISCSI_BHS_OPCODE_ASYNC_MESSAGE:
707 		iscsi_pdu_handle_async_message(response);
708 		break;
709 	case ISCSI_BHS_OPCODE_REJECT:
710 		iscsi_pdu_handle_reject(response);
711 		break;
712 	default:
713 		ISCSI_SESSION_WARN(is, "received PDU with unsupported "
714 		    "opcode 0x%x; reconnecting",
715 		    response->ip_bhs->bhs_opcode);
716 		iscsi_session_reconnect(is);
717 		icl_pdu_free(response);
718 	}
719 
720 	ISCSI_SESSION_UNLOCK(is);
721 }
722 
723 static void
724 iscsi_error_callback(struct icl_conn *ic)
725 {
726 	struct iscsi_session *is;
727 
728 	is = CONN_SESSION(ic);
729 
730 	ISCSI_SESSION_WARN(is, "connection error; reconnecting");
731 	iscsi_session_reconnect(is);
732 }
733 
734 static void
735 iscsi_pdu_handle_nop_in(struct icl_pdu *response)
736 {
737 	struct iscsi_session *is;
738 	struct iscsi_bhs_nop_out *bhsno;
739 	struct iscsi_bhs_nop_in *bhsni;
740 	struct icl_pdu *request;
741 	void *data = NULL;
742 	size_t datasize;
743 	int error;
744 
745 	is = PDU_SESSION(response);
746 	bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs;
747 
748 	if (bhsni->bhsni_target_transfer_tag == 0xffffffff) {
749 		/*
750 		 * Nothing to do; iscsi_pdu_update_statsn() already
751 		 * zeroed the timeout.
752 		 */
753 		icl_pdu_free(response);
754 		return;
755 	}
756 
757 	datasize = icl_pdu_data_segment_length(response);
758 	if (datasize > 0) {
759 		data = malloc(datasize, M_ISCSI, M_NOWAIT | M_ZERO);
760 		if (data == NULL) {
761 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
762 			    "reconnecting");
763 			icl_pdu_free(response);
764 			iscsi_session_reconnect(is);
765 			return;
766 		}
767 		icl_pdu_get_data(response, 0, data, datasize);
768 	}
769 
770 	request = icl_pdu_new_bhs(response->ip_conn, M_NOWAIT);
771 	if (request == NULL) {
772 		ISCSI_SESSION_WARN(is, "failed to allocate memory; "
773 		    "reconnecting");
774 		free(data, M_ISCSI);
775 		icl_pdu_free(response);
776 		iscsi_session_reconnect(is);
777 		return;
778 	}
779 	bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
780 	bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT |
781 	    ISCSI_BHS_OPCODE_IMMEDIATE;
782 	bhsno->bhsno_flags = 0x80;
783 	bhsno->bhsno_initiator_task_tag = 0xffffffff;
784 	bhsno->bhsno_target_transfer_tag = bhsni->bhsni_target_transfer_tag;
785 	if (datasize > 0) {
786 		error = icl_pdu_append_data(request, data, datasize, M_NOWAIT);
787 		if (error != 0) {
788 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
789 			    "reconnecting");
790 			free(data, M_ISCSI);
791 			icl_pdu_free(request);
792 			icl_pdu_free(response);
793 			iscsi_session_reconnect(is);
794 			return;
795 		}
796 		free(data, M_ISCSI);
797 	}
798 
799 	icl_pdu_free(response);
800 	iscsi_pdu_queue_locked(request);
801 }
802 
803 static void
804 iscsi_pdu_handle_scsi_response(struct icl_pdu *response)
805 {
806 	struct iscsi_bhs_scsi_response *bhssr;
807 	struct iscsi_outstanding *io;
808 	struct iscsi_session *is;
809 	struct ccb_scsiio *csio;
810 	size_t data_segment_len;
811 	uint16_t sense_len;
812 
813 	is = PDU_SESSION(response);
814 
815 	bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs;
816 	io = iscsi_outstanding_find(is, bhssr->bhssr_initiator_task_tag);
817 	if (io == NULL) {
818 		ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhssr->bhssr_initiator_task_tag);
819 		icl_pdu_free(response);
820 		iscsi_session_reconnect(is);
821 		return;
822 	}
823 
824 	if (bhssr->bhssr_response != BHSSR_RESPONSE_COMMAND_COMPLETED) {
825 		ISCSI_SESSION_WARN(is, "service response 0x%x", bhssr->bhssr_response);
826  		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
827  			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
828 			ISCSI_SESSION_DEBUG(is, "freezing devq");
829 		}
830  		io->io_ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
831 	} else if (bhssr->bhssr_status == 0) {
832 		io->io_ccb->ccb_h.status = CAM_REQ_CMP;
833 	} else {
834  		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
835  			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
836 			ISCSI_SESSION_DEBUG(is, "freezing devq");
837 		}
838  		io->io_ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN;
839 		io->io_ccb->csio.scsi_status = bhssr->bhssr_status;
840 	}
841 
842 	if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_OVERFLOW) {
843 		ISCSI_SESSION_WARN(is, "target indicated residual overflow");
844 		icl_pdu_free(response);
845 		iscsi_session_reconnect(is);
846 		return;
847 	}
848 
849 	csio = &io->io_ccb->csio;
850 
851 	data_segment_len = icl_pdu_data_segment_length(response);
852 	if (data_segment_len > 0) {
853 		if (data_segment_len < sizeof(sense_len)) {
854 			ISCSI_SESSION_WARN(is, "truncated data segment (%zd bytes)",
855 			    data_segment_len);
856 			if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
857 				xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
858 				ISCSI_SESSION_DEBUG(is, "freezing devq");
859 			}
860 			io->io_ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
861 			goto out;
862 		}
863 		icl_pdu_get_data(response, 0, &sense_len, sizeof(sense_len));
864 		sense_len = ntohs(sense_len);
865 #if 0
866 		ISCSI_SESSION_DEBUG(is, "sense_len %d, data len %zd",
867 		    sense_len, data_segment_len);
868 #endif
869 		if (sizeof(sense_len) + sense_len > data_segment_len) {
870 			ISCSI_SESSION_WARN(is, "truncated data segment "
871 			    "(%zd bytes, should be %zd)",
872 			    data_segment_len, sizeof(sense_len) + sense_len);
873 			if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
874 				xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
875 				ISCSI_SESSION_DEBUG(is, "freezing devq");
876 			}
877 			io->io_ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
878 			goto out;
879 		} else if (sizeof(sense_len) + sense_len < data_segment_len)
880 			ISCSI_SESSION_WARN(is, "oversize data segment "
881 			    "(%zd bytes, should be %zd)",
882 			    data_segment_len, sizeof(sense_len) + sense_len);
883 		if (sense_len > csio->sense_len) {
884 			ISCSI_SESSION_DEBUG(is, "truncating sense from %d to %d",
885 			    sense_len, csio->sense_len);
886 			sense_len = csio->sense_len;
887 		}
888 		icl_pdu_get_data(response, sizeof(sense_len), &csio->sense_data, sense_len);
889 		csio->sense_resid = csio->sense_len - sense_len;
890 		io->io_ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
891 	}
892 
893 out:
894 	if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_UNDERFLOW)
895 		csio->resid = ntohl(bhssr->bhssr_residual_count);
896 
897 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
898 		KASSERT(io->io_received <= csio->dxfer_len,
899 		    ("io->io_received > csio->dxfer_len"));
900 		if (io->io_received < csio->dxfer_len) {
901 			if (csio->resid != csio->dxfer_len - io->io_received) {
902 				ISCSI_SESSION_WARN(is, "underflow mismatch: "
903 				    "target indicates %d, we calculated %zd",
904 				    csio->resid,
905 				    csio->dxfer_len - io->io_received);
906 			}
907 			csio->resid = csio->dxfer_len - io->io_received;
908 		}
909 	}
910 
911 	xpt_done(io->io_ccb);
912 	iscsi_outstanding_remove(is, io);
913 	icl_pdu_free(response);
914 }
915 
916 static void
917 iscsi_pdu_handle_data_in(struct icl_pdu *response)
918 {
919 	struct iscsi_bhs_data_in *bhsdi;
920 	struct iscsi_outstanding *io;
921 	struct iscsi_session *is;
922 	struct ccb_scsiio *csio;
923 	size_t data_segment_len;
924 
925 	is = PDU_SESSION(response);
926 	bhsdi = (struct iscsi_bhs_data_in *)response->ip_bhs;
927 	io = iscsi_outstanding_find(is, bhsdi->bhsdi_initiator_task_tag);
928 	if (io == NULL) {
929 		ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhsdi->bhsdi_initiator_task_tag);
930 		icl_pdu_free(response);
931 		iscsi_session_reconnect(is);
932 		return;
933 	}
934 
935 	data_segment_len = icl_pdu_data_segment_length(response);
936 	if (data_segment_len == 0) {
937 		/*
938 		 * "The sending of 0 length data segments should be avoided,
939 		 * but initiators and targets MUST be able to properly receive
940 		 * 0 length data segments."
941 		 */
942 		icl_pdu_free(response);
943 		return;
944 	}
945 
946 	/*
947 	 * We need to track this for security reasons - without it, malicious target
948 	 * could respond to SCSI READ without sending Data-In PDUs, which would result
949 	 * in read operation on the initiator side returning random kernel data.
950 	 */
951 	if (ntohl(bhsdi->bhsdi_buffer_offset) != io->io_received) {
952 		ISCSI_SESSION_WARN(is, "data out of order; expected offset %zd, got %zd",
953 		    io->io_received, (size_t)ntohl(bhsdi->bhsdi_buffer_offset));
954 		icl_pdu_free(response);
955 		iscsi_session_reconnect(is);
956 		return;
957 	}
958 
959 	csio = &io->io_ccb->csio;
960 
961 	if (io->io_received + data_segment_len > csio->dxfer_len) {
962 		ISCSI_SESSION_WARN(is, "oversize data segment (%zd bytes "
963 		    "at offset %zd, buffer is %d)",
964 		    data_segment_len, io->io_received, csio->dxfer_len);
965 		icl_pdu_free(response);
966 		iscsi_session_reconnect(is);
967 		return;
968 	}
969 
970 	icl_pdu_get_data(response, 0, csio->data_ptr + io->io_received, data_segment_len);
971 	io->io_received += data_segment_len;
972 
973 	/*
974 	 * XXX: Check DataSN.
975 	 * XXX: Check F.
976 	 */
977 	if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) == 0) {
978 		/*
979 		 * Nothing more to do.
980 		 */
981 		icl_pdu_free(response);
982 		return;
983 	}
984 
985 	//ISCSI_SESSION_DEBUG(is, "got S flag; status 0x%x", bhsdi->bhsdi_status);
986 	if (bhsdi->bhsdi_status == 0) {
987 		io->io_ccb->ccb_h.status = CAM_REQ_CMP;
988 	} else {
989 		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
990 			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
991 			ISCSI_SESSION_DEBUG(is, "freezing devq");
992 		}
993 		io->io_ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN;
994 		csio->scsi_status = bhsdi->bhsdi_status;
995 	}
996 
997 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
998 		KASSERT(io->io_received <= csio->dxfer_len,
999 		    ("io->io_received > csio->dxfer_len"));
1000 		if (io->io_received < csio->dxfer_len) {
1001 			csio->resid = ntohl(bhsdi->bhsdi_residual_count);
1002 			if (csio->resid != csio->dxfer_len - io->io_received) {
1003 				ISCSI_SESSION_WARN(is, "underflow mismatch: "
1004 				    "target indicates %d, we calculated %zd",
1005 				    csio->resid,
1006 				    csio->dxfer_len - io->io_received);
1007 			}
1008 			csio->resid = csio->dxfer_len - io->io_received;
1009 		}
1010 	}
1011 
1012 	xpt_done(io->io_ccb);
1013 	iscsi_outstanding_remove(is, io);
1014 	icl_pdu_free(response);
1015 }
1016 
1017 static void
1018 iscsi_pdu_handle_logout_response(struct icl_pdu *response)
1019 {
1020 
1021 	ISCSI_SESSION_DEBUG(PDU_SESSION(response), "logout response");
1022 	icl_pdu_free(response);
1023 }
1024 
1025 static void
1026 iscsi_pdu_handle_r2t(struct icl_pdu *response)
1027 {
1028 	struct icl_pdu *request;
1029 	struct iscsi_session *is;
1030 	struct iscsi_bhs_r2t *bhsr2t;
1031 	struct iscsi_bhs_data_out *bhsdo;
1032 	struct iscsi_outstanding *io;
1033 	struct ccb_scsiio *csio;
1034 	size_t off, len, total_len;
1035 	int error;
1036 
1037 	is = PDU_SESSION(response);
1038 
1039 	bhsr2t = (struct iscsi_bhs_r2t *)response->ip_bhs;
1040 	io = iscsi_outstanding_find(is, bhsr2t->bhsr2t_initiator_task_tag);
1041 	if (io == NULL) {
1042 		ISCSI_SESSION_WARN(is, "bad itt 0x%x; reconnecting",
1043 		    bhsr2t->bhsr2t_initiator_task_tag);
1044 		icl_pdu_free(response);
1045 		iscsi_session_reconnect(is);
1046 		return;
1047 	}
1048 
1049 	csio = &io->io_ccb->csio;
1050 
1051 	if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_OUT) {
1052 		ISCSI_SESSION_WARN(is, "received R2T for read command; reconnecting");
1053 		icl_pdu_free(response);
1054 		iscsi_session_reconnect(is);
1055 		return;
1056 	}
1057 
1058 	/*
1059 	 * XXX: Verify R2TSN.
1060 	 */
1061 
1062 	io->io_datasn = 0;
1063 
1064 	off = ntohl(bhsr2t->bhsr2t_buffer_offset);
1065 	if (off > csio->dxfer_len) {
1066 		ISCSI_SESSION_WARN(is, "target requested invalid offset "
1067 		    "%zd, buffer is is %d; reconnecting", off, csio->dxfer_len);
1068 		icl_pdu_free(response);
1069 		iscsi_session_reconnect(is);
1070 		return;
1071 	}
1072 
1073 	total_len = ntohl(bhsr2t->bhsr2t_desired_data_transfer_length);
1074 	if (total_len == 0 || total_len > csio->dxfer_len) {
1075 		ISCSI_SESSION_WARN(is, "target requested invalid length "
1076 		    "%zd, buffer is %d; reconnecting", total_len, csio->dxfer_len);
1077 		icl_pdu_free(response);
1078 		iscsi_session_reconnect(is);
1079 		return;
1080 	}
1081 
1082 	//ISCSI_SESSION_DEBUG(is, "r2t; off %zd, len %zd", off, total_len);
1083 
1084 	for (;;) {
1085 		len = total_len;
1086 
1087 		if (len > is->is_max_data_segment_length)
1088 			len = is->is_max_data_segment_length;
1089 
1090 		if (off + len > csio->dxfer_len) {
1091 			ISCSI_SESSION_WARN(is, "target requested invalid "
1092 			    "length/offset %zd, buffer is %d; reconnecting",
1093 			    off + len, csio->dxfer_len);
1094 			icl_pdu_free(response);
1095 			iscsi_session_reconnect(is);
1096 			return;
1097 		}
1098 
1099 		request = icl_pdu_new_bhs(response->ip_conn, M_NOWAIT);
1100 		if (request == NULL) {
1101 			icl_pdu_free(response);
1102 			iscsi_session_reconnect(is);
1103 			return;
1104 		}
1105 
1106 		bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs;
1107 		bhsdo->bhsdo_opcode = ISCSI_BHS_OPCODE_SCSI_DATA_OUT;
1108 		bhsdo->bhsdo_lun = bhsr2t->bhsr2t_lun;
1109 		bhsdo->bhsdo_initiator_task_tag =
1110 		    bhsr2t->bhsr2t_initiator_task_tag;
1111 		bhsdo->bhsdo_target_transfer_tag =
1112 		    bhsr2t->bhsr2t_target_transfer_tag;
1113 		bhsdo->bhsdo_datasn = htonl(io->io_datasn++);
1114 		bhsdo->bhsdo_buffer_offset = htonl(off);
1115 		error = icl_pdu_append_data(request, csio->data_ptr + off, len,
1116 		    M_NOWAIT);
1117 		if (error != 0) {
1118 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
1119 			    "reconnecting");
1120 			icl_pdu_free(request);
1121 			icl_pdu_free(response);
1122 			iscsi_session_reconnect(is);
1123 			return;
1124 		}
1125 
1126 		off += len;
1127 		total_len -= len;
1128 
1129 		if (total_len == 0) {
1130 			bhsdo->bhsdo_flags |= BHSDO_FLAGS_F;
1131 			//ISCSI_SESSION_DEBUG(is, "setting F, off %zd", off);
1132 		} else {
1133 			//ISCSI_SESSION_DEBUG(is, "not finished, off %zd", off);
1134 		}
1135 
1136 		iscsi_pdu_queue_locked(request);
1137 
1138 		if (total_len == 0)
1139 			break;
1140 	}
1141 
1142 	icl_pdu_free(response);
1143 }
1144 
1145 static void
1146 iscsi_pdu_handle_async_message(struct icl_pdu *response)
1147 {
1148 	struct iscsi_bhs_asynchronous_message *bhsam;
1149 	struct iscsi_session *is;
1150 
1151 	is = PDU_SESSION(response);
1152 	bhsam = (struct iscsi_bhs_asynchronous_message *)response->ip_bhs;
1153 	switch (bhsam->bhsam_async_event) {
1154 	case BHSAM_EVENT_TARGET_REQUESTS_LOGOUT:
1155 		ISCSI_SESSION_WARN(is, "target requests logout; removing session");
1156 		iscsi_session_logout(is);
1157 		iscsi_session_terminate(is);
1158 		break;
1159 	case BHSAM_EVENT_TARGET_TERMINATES_CONNECTION:
1160 		ISCSI_SESSION_WARN(is, "target indicates it will drop drop the connection");
1161 		break;
1162 	case BHSAM_EVENT_TARGET_TERMINATES_SESSION:
1163 		ISCSI_SESSION_WARN(is, "target indicates it will drop drop the session");
1164 		break;
1165 	default:
1166 		/*
1167 		 * XXX: Technically, we're obligated to also handle
1168 		 * 	parameter renegotiation.
1169 		 */
1170 		ISCSI_SESSION_WARN(is, "ignoring AsyncEvent %d", bhsam->bhsam_async_event);
1171 		break;
1172 	}
1173 
1174 	icl_pdu_free(response);
1175 }
1176 
1177 static void
1178 iscsi_pdu_handle_reject(struct icl_pdu *response)
1179 {
1180 	struct iscsi_bhs_reject *bhsr;
1181 	struct iscsi_session *is;
1182 
1183 	is = PDU_SESSION(response);
1184 	bhsr = (struct iscsi_bhs_reject *)response->ip_bhs;
1185 	ISCSI_SESSION_WARN(is, "received Reject PDU, reason 0x%x; protocol error?",
1186 	    bhsr->bhsr_reason);
1187 
1188 	icl_pdu_free(response);
1189 }
1190 
1191 static int
1192 iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
1193     struct iscsi_daemon_request *request)
1194 {
1195 	struct iscsi_session *is;
1196 	int error;
1197 
1198 	sx_slock(&sc->sc_lock);
1199 	for (;;) {
1200 		TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1201 			if (is->is_waiting_for_iscsid)
1202 				break;
1203 		}
1204 
1205 		if (is == NULL) {
1206 			/*
1207 			 * No session requires attention from iscsid(8); wait.
1208 			 */
1209 			error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
1210 			if (error != 0) {
1211 				sx_sunlock(&sc->sc_lock);
1212 				return (error);
1213 			}
1214 			continue;
1215 		}
1216 
1217 		ISCSI_SESSION_LOCK(is);
1218 		is->is_waiting_for_iscsid = false;
1219 		is->is_login_phase = true;
1220 		is->is_reason[0] = '\0';
1221 		ISCSI_SESSION_UNLOCK(is);
1222 
1223 		request->idr_session_id = is->is_id;
1224 		memcpy(&request->idr_conf, &is->is_conf,
1225 		    sizeof(request->idr_conf));
1226 
1227 		sx_sunlock(&sc->sc_lock);
1228 		return (0);
1229 	}
1230 }
1231 
1232 static int
1233 iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc,
1234     struct iscsi_daemon_handoff *handoff)
1235 {
1236 	struct iscsi_session *is;
1237 	int error;
1238 
1239 	sx_slock(&sc->sc_lock);
1240 
1241 	/*
1242 	 * Find the session to hand off socket to.
1243 	 */
1244 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1245 		if (is->is_id == handoff->idh_session_id)
1246 			break;
1247 	}
1248 	if (is == NULL) {
1249 		sx_sunlock(&sc->sc_lock);
1250 		return (ESRCH);
1251 	}
1252 	ISCSI_SESSION_LOCK(is);
1253 	if (is->is_conf.isc_discovery || is->is_terminating) {
1254 		ISCSI_SESSION_UNLOCK(is);
1255 		sx_sunlock(&sc->sc_lock);
1256 		return (EINVAL);
1257 	}
1258 	if (is->is_connected) {
1259 		/*
1260 		 * This might have happened because another iscsid(8)
1261 		 * instance handed off the connection in the meantime.
1262 		 * Just return.
1263 		 */
1264 		ISCSI_SESSION_WARN(is, "handoff on already connected "
1265 		    "session");
1266 		ISCSI_SESSION_UNLOCK(is);
1267 		sx_sunlock(&sc->sc_lock);
1268 		return (EBUSY);
1269 	}
1270 
1271 	strlcpy(is->is_target_alias, handoff->idh_target_alias,
1272 	    sizeof(is->is_target_alias));
1273 	memcpy(is->is_isid, handoff->idh_isid, sizeof(is->is_isid));
1274 	is->is_statsn = handoff->idh_statsn;
1275 	is->is_initial_r2t = handoff->idh_initial_r2t;
1276 	is->is_immediate_data = handoff->idh_immediate_data;
1277 	is->is_max_data_segment_length = handoff->idh_max_data_segment_length;
1278 	is->is_max_burst_length = handoff->idh_max_burst_length;
1279 	is->is_first_burst_length = handoff->idh_first_burst_length;
1280 
1281 	if (handoff->idh_header_digest == ISCSI_DIGEST_CRC32C)
1282 		is->is_conn->ic_header_crc32c = true;
1283 	else
1284 		is->is_conn->ic_header_crc32c = false;
1285 	if (handoff->idh_data_digest == ISCSI_DIGEST_CRC32C)
1286 		is->is_conn->ic_data_crc32c = true;
1287 	else
1288 		is->is_conn->ic_data_crc32c = false;
1289 
1290 	is->is_cmdsn = 0;
1291 	is->is_expcmdsn = 0;
1292 	is->is_maxcmdsn = 0;
1293 	is->is_waiting_for_iscsid = false;
1294 	is->is_login_phase = false;
1295 	is->is_timeout = 0;
1296 	is->is_connected = true;
1297 	is->is_reason[0] = '\0';
1298 
1299 	ISCSI_SESSION_UNLOCK(is);
1300 
1301 #ifndef ICL_KERNEL_PROXY
1302 	error = icl_conn_handoff(is->is_conn, handoff->idh_socket);
1303 	if (error != 0) {
1304 		sx_sunlock(&sc->sc_lock);
1305 		iscsi_session_terminate(is);
1306 		return (error);
1307 	}
1308 #endif
1309 
1310 	sx_sunlock(&sc->sc_lock);
1311 
1312 	if (is->is_sim != NULL) {
1313 		/*
1314 		 * When reconnecting, there already is SIM allocated for the session.
1315 		 */
1316 		KASSERT(is->is_simq_frozen, ("reconnect without frozen simq"));
1317 		ISCSI_SESSION_LOCK(is);
1318 		ISCSI_SESSION_DEBUG(is, "releasing");
1319 		xpt_release_simq(is->is_sim, 1);
1320 		is->is_simq_frozen = false;
1321 		ISCSI_SESSION_UNLOCK(is);
1322 
1323 	} else {
1324 		ISCSI_SESSION_LOCK(is);
1325 		is->is_devq = cam_simq_alloc(maxtags);
1326 		if (is->is_devq == NULL) {
1327 			ISCSI_SESSION_WARN(is, "failed to allocate simq");
1328 			iscsi_session_terminate(is);
1329 			return (ENOMEM);
1330 		}
1331 
1332 		is->is_sim = cam_sim_alloc(iscsi_action, iscsi_poll, "iscsi",
1333 		    is, is->is_id /* unit */, &is->is_lock,
1334 		    maxtags, maxtags, is->is_devq);
1335 		if (is->is_sim == NULL) {
1336 			ISCSI_SESSION_UNLOCK(is);
1337 			ISCSI_SESSION_WARN(is, "failed to allocate SIM");
1338 			cam_simq_free(is->is_devq);
1339 			iscsi_session_terminate(is);
1340 			return (ENOMEM);
1341 		}
1342 
1343 		error = xpt_bus_register(is->is_sim, NULL, 0);
1344 		if (error != 0) {
1345 			ISCSI_SESSION_UNLOCK(is);
1346 			ISCSI_SESSION_WARN(is, "failed to register bus");
1347 			iscsi_session_terminate(is);
1348 			return (ENOMEM);
1349 		}
1350 
1351 		error = xpt_create_path(&is->is_path, /*periph*/NULL,
1352 		    cam_sim_path(is->is_sim), CAM_TARGET_WILDCARD,
1353 		    CAM_LUN_WILDCARD);
1354 		if (error != CAM_REQ_CMP) {
1355 			ISCSI_SESSION_UNLOCK(is);
1356 			ISCSI_SESSION_WARN(is, "failed to create path");
1357 			iscsi_session_terminate(is);
1358 			return (ENOMEM);
1359 		}
1360 		ISCSI_SESSION_UNLOCK(is);
1361 	}
1362 
1363 	return (0);
1364 }
1365 
1366 static int
1367 iscsi_ioctl_daemon_fail(struct iscsi_softc *sc,
1368     struct iscsi_daemon_fail *fail)
1369 {
1370 	struct iscsi_session *is;
1371 
1372 	sx_slock(&sc->sc_lock);
1373 
1374 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1375 		if (is->is_id == fail->idf_session_id)
1376 			break;
1377 	}
1378 	if (is == NULL) {
1379 		sx_sunlock(&sc->sc_lock);
1380 		return (ESRCH);
1381 	}
1382 	ISCSI_SESSION_LOCK(is);
1383 	ISCSI_SESSION_DEBUG(is, "iscsid(8) failed: %s",
1384 	    fail->idf_reason);
1385 	strlcpy(is->is_reason, fail->idf_reason, sizeof(is->is_reason));
1386 	//is->is_waiting_for_iscsid = false;
1387 	//is->is_login_phase = true;
1388 	//iscsi_session_reconnect(is);
1389 	ISCSI_SESSION_UNLOCK(is);
1390 	sx_sunlock(&sc->sc_lock);
1391 
1392 	return (0);
1393 }
1394 
1395 #ifdef ICL_KERNEL_PROXY
1396 static int
1397 iscsi_ioctl_daemon_connect(struct iscsi_softc *sc,
1398     struct iscsi_daemon_connect *idc)
1399 {
1400 	struct iscsi_session *is;
1401 	struct sockaddr *from_sa, *to_sa;
1402 	int error;
1403 
1404 	sx_slock(&sc->sc_lock);
1405 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1406 		if (is->is_id == idc->idc_session_id)
1407 			break;
1408 	}
1409 	if (is == NULL) {
1410 		sx_sunlock(&sc->sc_lock);
1411 		return (ESRCH);
1412 	}
1413 	sx_sunlock(&sc->sc_lock);
1414 
1415 	if (idc->idc_from_addrlen > 0) {
1416 		error = getsockaddr(&from_sa, (void *)idc->idc_from_addr, idc->idc_from_addrlen);
1417 		if (error != 0)
1418 			return (error);
1419 	} else {
1420 		from_sa = NULL;
1421 	}
1422 	error = getsockaddr(&to_sa, (void *)idc->idc_to_addr, idc->idc_to_addrlen);
1423 	if (error != 0) {
1424 		free(from_sa, M_SONAME);
1425 		return (error);
1426 	}
1427 
1428 	ISCSI_SESSION_LOCK(is);
1429 	is->is_waiting_for_iscsid = false;
1430 	is->is_login_phase = true;
1431 	is->is_timeout = 0;
1432 	ISCSI_SESSION_UNLOCK(is);
1433 
1434 	error = icl_conn_connect(is->is_conn, idc->idc_iser, idc->idc_domain,
1435 	    idc->idc_socktype, idc->idc_protocol, from_sa, to_sa);
1436 	free(from_sa, M_SONAME);
1437 	free(to_sa, M_SONAME);
1438 
1439 	/*
1440 	 * Digests are always disabled during login phase.
1441 	 */
1442 	is->is_conn->ic_header_crc32c = false;
1443 	is->is_conn->ic_data_crc32c = false;
1444 
1445 	return (error);
1446 }
1447 
1448 static int
1449 iscsi_ioctl_daemon_send(struct iscsi_softc *sc,
1450     struct iscsi_daemon_send *ids)
1451 {
1452 	struct iscsi_session *is;
1453 	struct icl_pdu *ip;
1454 	size_t datalen;
1455 	void *data;
1456 	int error;
1457 
1458 	sx_slock(&sc->sc_lock);
1459 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1460 		if (is->is_id == ids->ids_session_id)
1461 			break;
1462 	}
1463 	if (is == NULL) {
1464 		sx_sunlock(&sc->sc_lock);
1465 		return (ESRCH);
1466 	}
1467 	sx_sunlock(&sc->sc_lock);
1468 
1469 	if (is->is_login_phase == false)
1470 		return (EBUSY);
1471 
1472 	if (is->is_terminating || is->is_reconnecting)
1473 		return (EIO);
1474 
1475 	datalen = ids->ids_data_segment_len;
1476 	if (datalen > ISCSI_MAX_DATA_SEGMENT_LENGTH)
1477 		return (EINVAL);
1478 	if (datalen > 0) {
1479 		data = malloc(datalen, M_ISCSI, M_WAITOK);
1480 		error = copyin(ids->ids_data_segment, data, datalen);
1481 		if (error != 0) {
1482 			free(data, M_ISCSI);
1483 			return (error);
1484 		}
1485 	}
1486 
1487 	ip = icl_pdu_new_bhs(is->is_conn, M_WAITOK);
1488 	memcpy(ip->ip_bhs, ids->ids_bhs, sizeof(*ip->ip_bhs));
1489 	if (datalen > 0) {
1490 		error = icl_pdu_append_data(ip, data, datalen, M_WAITOK);
1491 		KASSERT(error == 0, ("icl_pdu_append_data(..., M_WAITOK) failed"));
1492 		free(data, M_ISCSI);
1493 	}
1494 	icl_pdu_queue(ip);
1495 
1496 	return (0);
1497 }
1498 
1499 static int
1500 iscsi_ioctl_daemon_receive(struct iscsi_softc *sc,
1501     struct iscsi_daemon_receive *idr)
1502 {
1503 	struct iscsi_session *is;
1504 	struct icl_pdu *ip;
1505 	void *data;
1506 
1507 	sx_slock(&sc->sc_lock);
1508 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1509 		if (is->is_id == idr->idr_session_id)
1510 			break;
1511 	}
1512 	if (is == NULL) {
1513 		sx_sunlock(&sc->sc_lock);
1514 		return (ESRCH);
1515 	}
1516 	sx_sunlock(&sc->sc_lock);
1517 
1518 	if (is->is_login_phase == false)
1519 		return (EBUSY);
1520 
1521 	ISCSI_SESSION_LOCK(is);
1522 	while (is->is_login_pdu == NULL &&
1523 	    is->is_terminating == false &&
1524 	    is->is_reconnecting == false)
1525 		cv_wait(&is->is_login_cv, &is->is_lock);
1526 	if (is->is_terminating || is->is_reconnecting) {
1527 		ISCSI_SESSION_UNLOCK(is);
1528 		return (EIO);
1529 	}
1530 	ip = is->is_login_pdu;
1531 	is->is_login_pdu = NULL;
1532 	ISCSI_SESSION_UNLOCK(is);
1533 
1534 	if (ip->ip_data_len > idr->idr_data_segment_len) {
1535 		icl_pdu_free(ip);
1536 		return (EMSGSIZE);
1537 	}
1538 
1539 	copyout(ip->ip_bhs, idr->idr_bhs, sizeof(*ip->ip_bhs));
1540 	if (ip->ip_data_len > 0) {
1541 		data = malloc(ip->ip_data_len, M_ISCSI, M_WAITOK);
1542 		icl_pdu_get_data(ip, 0, data, ip->ip_data_len);
1543 		copyout(data, idr->idr_data_segment, ip->ip_data_len);
1544 		free(data, M_ISCSI);
1545 	}
1546 
1547 	icl_pdu_free(ip);
1548 
1549 	return (0);
1550 }
1551 
1552 static int
1553 iscsi_ioctl_daemon_close(struct iscsi_softc *sc,
1554     struct iscsi_daemon_close *idc)
1555 {
1556 	struct iscsi_session *is;
1557 
1558 	sx_slock(&sc->sc_lock);
1559 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1560 		if (is->is_id == idc->idc_session_id)
1561 			break;
1562 	}
1563 	if (is == NULL) {
1564 		sx_sunlock(&sc->sc_lock);
1565 		return (ESRCH);
1566 	}
1567 	sx_sunlock(&sc->sc_lock);
1568 
1569 	iscsi_session_reconnect(is);
1570 
1571 	return (0);
1572 }
1573 #endif /* ICL_KERNEL_PROXY */
1574 
1575 static void
1576 iscsi_sanitize_session_conf(struct iscsi_session_conf *isc)
1577 {
1578 	/*
1579 	 * Just make sure all the fields are null-terminated.
1580 	 *
1581 	 * XXX: This is not particularly secure.  We should
1582 	 * 	create our own conf and then copy in relevant
1583 	 * 	fields.
1584 	 */
1585 	isc->isc_initiator[ISCSI_NAME_LEN - 1] = '\0';
1586 	isc->isc_initiator_addr[ISCSI_ADDR_LEN - 1] = '\0';
1587 	isc->isc_initiator_alias[ISCSI_ALIAS_LEN - 1] = '\0';
1588 	isc->isc_target[ISCSI_NAME_LEN - 1] = '\0';
1589 	isc->isc_target_addr[ISCSI_ADDR_LEN - 1] = '\0';
1590 	isc->isc_user[ISCSI_NAME_LEN - 1] = '\0';
1591 	isc->isc_secret[ISCSI_SECRET_LEN - 1] = '\0';
1592 	isc->isc_mutual_user[ISCSI_NAME_LEN - 1] = '\0';
1593 	isc->isc_mutual_secret[ISCSI_SECRET_LEN - 1] = '\0';
1594 }
1595 
1596 static int
1597 iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
1598 {
1599 	struct iscsi_session *is;
1600 	const struct iscsi_session *is2;
1601 	int error;
1602 
1603 	iscsi_sanitize_session_conf(&isa->isa_conf);
1604 
1605 	is = malloc(sizeof(*is), M_ISCSI, M_ZERO | M_WAITOK);
1606 	memcpy(&is->is_conf, &isa->isa_conf, sizeof(is->is_conf));
1607 
1608 	if (is->is_conf.isc_initiator[0] == '\0' ||
1609 	    is->is_conf.isc_target_addr[0] == '\0') {
1610 		free(is, M_ISCSI);
1611 		return (EINVAL);
1612 	}
1613 
1614 	if ((is->is_conf.isc_discovery != 0 && is->is_conf.isc_target[0] != 0) ||
1615 	    (is->is_conf.isc_discovery == 0 && is->is_conf.isc_target[0] == 0)) {
1616 		free(is, M_ISCSI);
1617 		return (EINVAL);
1618 	}
1619 
1620 	sx_xlock(&sc->sc_lock);
1621 
1622 	/*
1623 	 * Prevent duplicates.
1624 	 */
1625 	TAILQ_FOREACH(is2, &sc->sc_sessions, is_next) {
1626 		if (!!is->is_conf.isc_discovery !=
1627 		    !!is2->is_conf.isc_discovery)
1628 			continue;
1629 
1630 		if (strcmp(is->is_conf.isc_target_addr,
1631 		    is2->is_conf.isc_target_addr) != 0)
1632 			continue;
1633 
1634 		if (is->is_conf.isc_discovery == 0 &&
1635 		    strcmp(is->is_conf.isc_target,
1636 		    is2->is_conf.isc_target) != 0)
1637 			continue;
1638 
1639 		sx_xunlock(&sc->sc_lock);
1640 		free(is, M_ISCSI);
1641 		return (EBUSY);
1642 	}
1643 
1644 	is->is_conn = icl_conn_new("iscsi", &is->is_lock);
1645 	is->is_conn->ic_receive = iscsi_receive_callback;
1646 	is->is_conn->ic_error = iscsi_error_callback;
1647 	is->is_conn->ic_prv0 = is;
1648 	TAILQ_INIT(&is->is_outstanding);
1649 	STAILQ_INIT(&is->is_postponed);
1650 	mtx_init(&is->is_lock, "iscsi_lock", NULL, MTX_DEF);
1651 	cv_init(&is->is_maintenance_cv, "iscsi_mt");
1652 #ifdef ICL_KERNEL_PROXY
1653 	cv_init(&is->is_login_cv, "iscsi_login");
1654 #endif
1655 
1656 	is->is_softc = sc;
1657 	sc->sc_last_session_id++;
1658 	is->is_id = sc->sc_last_session_id;
1659 	callout_init(&is->is_callout, 1);
1660 	callout_reset(&is->is_callout, 1 * hz, iscsi_callout, is);
1661 	TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next);
1662 
1663 	error = kthread_add(iscsi_maintenance_thread, is, NULL, NULL, 0, 0, "iscsimt");
1664 	if (error != 0) {
1665 		ISCSI_SESSION_WARN(is, "kthread_add(9) failed with error %d", error);
1666 		return (error);
1667 	}
1668 
1669 	/*
1670 	 * Trigger immediate reconnection.
1671 	 */
1672 	is->is_waiting_for_iscsid = true;
1673 	strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
1674 	cv_signal(&sc->sc_cv);
1675 
1676 	sx_xunlock(&sc->sc_lock);
1677 
1678 	return (0);
1679 }
1680 
1681 static bool
1682 iscsi_session_conf_matches(unsigned int id1, const struct iscsi_session_conf *c1,
1683     unsigned int id2, const struct iscsi_session_conf *c2)
1684 {
1685 	if (id2 == 0 && c2->isc_target[0] == '\0' &&
1686 	    c2->isc_target_addr[0] == '\0')
1687 		return (true);
1688 	if (id2 != 0 && id2 == id1)
1689 		return (true);
1690 	if (c2->isc_target[0] != '\0' &&
1691 	    strcmp(c1->isc_target, c2->isc_target) == 0)
1692 		return (true);
1693 	if (c2->isc_target_addr[0] != '\0' &&
1694 	    strcmp(c1->isc_target_addr, c2->isc_target_addr) == 0)
1695 		return (true);
1696 	return (false);
1697 }
1698 
1699 static int
1700 iscsi_ioctl_session_remove(struct iscsi_softc *sc,
1701     struct iscsi_session_remove *isr)
1702 {
1703 	struct iscsi_session *is, *tmp;
1704 	bool found = false;
1705 
1706 	iscsi_sanitize_session_conf(&isr->isr_conf);
1707 
1708 	sx_xlock(&sc->sc_lock);
1709 	TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp) {
1710 		ISCSI_SESSION_LOCK(is);
1711 		if (iscsi_session_conf_matches(is->is_id, &is->is_conf,
1712 		    isr->isr_session_id, &isr->isr_conf)) {
1713 			found = true;
1714 			iscsi_session_logout(is);
1715 			iscsi_session_terminate(is);
1716 		}
1717 		ISCSI_SESSION_UNLOCK(is);
1718 	}
1719 	sx_xunlock(&sc->sc_lock);
1720 
1721 	if (!found)
1722 		return (ESRCH);
1723 
1724 	return (0);
1725 }
1726 
1727 static int
1728 iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl)
1729 {
1730 	int error;
1731 	unsigned int i = 0;
1732 	struct iscsi_session *is;
1733 	struct iscsi_session_state iss;
1734 
1735 	sx_slock(&sc->sc_lock);
1736 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1737 		if (i >= isl->isl_nentries) {
1738 			sx_sunlock(&sc->sc_lock);
1739 			return (EMSGSIZE);
1740 		}
1741 		memset(&iss, 0, sizeof(iss));
1742 		memcpy(&iss.iss_conf, &is->is_conf, sizeof(iss.iss_conf));
1743 		iss.iss_id = is->is_id;
1744 		strlcpy(iss.iss_target_alias, is->is_target_alias, sizeof(iss.iss_target_alias));
1745 		strlcpy(iss.iss_reason, is->is_reason, sizeof(iss.iss_reason));
1746 
1747 		if (is->is_conn->ic_header_crc32c)
1748 			iss.iss_header_digest = ISCSI_DIGEST_CRC32C;
1749 		else
1750 			iss.iss_header_digest = ISCSI_DIGEST_NONE;
1751 
1752 		if (is->is_conn->ic_data_crc32c)
1753 			iss.iss_data_digest = ISCSI_DIGEST_CRC32C;
1754 		else
1755 			iss.iss_data_digest = ISCSI_DIGEST_NONE;
1756 
1757 		iss.iss_max_data_segment_length = is->is_max_data_segment_length;
1758 		iss.iss_immediate_data = is->is_immediate_data;
1759 		iss.iss_connected = is->is_connected;
1760 
1761 		error = copyout(&iss, isl->isl_pstates + i, sizeof(iss));
1762 		if (error != 0) {
1763 			sx_sunlock(&sc->sc_lock);
1764 			return (error);
1765 		}
1766 		i++;
1767 	}
1768 	sx_sunlock(&sc->sc_lock);
1769 
1770 	isl->isl_nentries = i;
1771 
1772 	return (0);
1773 }
1774 
1775 static int
1776 iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
1777     struct thread *td)
1778 {
1779 	struct iscsi_softc *sc;
1780 
1781 	sc = dev->si_drv1;
1782 
1783 	switch (cmd) {
1784 	case ISCSIDWAIT:
1785 		return (iscsi_ioctl_daemon_wait(sc,
1786 		    (struct iscsi_daemon_request *)arg));
1787 	case ISCSIDHANDOFF:
1788 		return (iscsi_ioctl_daemon_handoff(sc,
1789 		    (struct iscsi_daemon_handoff *)arg));
1790 	case ISCSIDFAIL:
1791 		return (iscsi_ioctl_daemon_fail(sc,
1792 		    (struct iscsi_daemon_fail *)arg));
1793 #ifdef ICL_KERNEL_PROXY
1794 	case ISCSIDCONNECT:
1795 		return (iscsi_ioctl_daemon_connect(sc,
1796 		    (struct iscsi_daemon_connect *)arg));
1797 	case ISCSIDSEND:
1798 		return (iscsi_ioctl_daemon_send(sc,
1799 		    (struct iscsi_daemon_send *)arg));
1800 	case ISCSIDRECEIVE:
1801 		return (iscsi_ioctl_daemon_receive(sc,
1802 		    (struct iscsi_daemon_receive *)arg));
1803 	case ISCSIDCLOSE:
1804 		return (iscsi_ioctl_daemon_close(sc,
1805 		    (struct iscsi_daemon_close *)arg));
1806 #endif /* ICL_KERNEL_PROXY */
1807 	case ISCSISADD:
1808 		return (iscsi_ioctl_session_add(sc,
1809 		    (struct iscsi_session_add *)arg));
1810 	case ISCSISREMOVE:
1811 		return (iscsi_ioctl_session_remove(sc,
1812 		    (struct iscsi_session_remove *)arg));
1813 	case ISCSISLIST:
1814 		return (iscsi_ioctl_session_list(sc,
1815 		    (struct iscsi_session_list *)arg));
1816 	default:
1817 		return (EINVAL);
1818 	}
1819 }
1820 
1821 static struct iscsi_outstanding *
1822 iscsi_outstanding_find(struct iscsi_session *is, uint32_t initiator_task_tag)
1823 {
1824 	struct iscsi_outstanding *io;
1825 
1826 	ISCSI_SESSION_LOCK_ASSERT(is);
1827 
1828 	TAILQ_FOREACH(io, &is->is_outstanding, io_next) {
1829 		if (io->io_initiator_task_tag == initiator_task_tag)
1830 			return (io);
1831 	}
1832 	return (NULL);
1833 }
1834 
1835 static int
1836 iscsi_outstanding_add(struct iscsi_session *is,
1837     uint32_t initiator_task_tag, union ccb *ccb)
1838 {
1839 	struct iscsi_outstanding *io;
1840 
1841 	ISCSI_SESSION_LOCK_ASSERT(is);
1842 
1843 	KASSERT(iscsi_outstanding_find(is, initiator_task_tag) == NULL,
1844 	    ("initiator_task_tag 0x%x already added", initiator_task_tag));
1845 
1846 	io = uma_zalloc(iscsi_outstanding_zone, M_NOWAIT | M_ZERO);
1847 	if (io == NULL) {
1848 		ISCSI_SESSION_WARN(is, "failed to allocate %zd bytes", sizeof(*io));
1849 		return (ENOMEM);
1850 	}
1851 	io->io_initiator_task_tag = initiator_task_tag;
1852 	io->io_ccb = ccb;
1853 	TAILQ_INSERT_TAIL(&is->is_outstanding, io, io_next);
1854 	return (0);
1855 }
1856 
1857 static void
1858 iscsi_outstanding_remove(struct iscsi_session *is, struct iscsi_outstanding *io)
1859 {
1860 
1861 	ISCSI_SESSION_LOCK_ASSERT(is);
1862 
1863 	TAILQ_REMOVE(&is->is_outstanding, io, io_next);
1864 	uma_zfree(iscsi_outstanding_zone, io);
1865 }
1866 
1867 static void
1868 iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
1869 {
1870 	struct icl_pdu *request;
1871 	struct iscsi_bhs_scsi_command *bhssc;
1872 	struct ccb_scsiio *csio;
1873 	size_t len;
1874 	int error;
1875 
1876 	ISCSI_SESSION_LOCK_ASSERT(is);
1877 
1878 #if 0
1879 	KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__));
1880 #else
1881 	if (is->is_login_phase) {
1882 		ISCSI_SESSION_DEBUG(is, "called during login phase");
1883 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1884 			xpt_freeze_devq(ccb->ccb_h.path, 1);
1885 			ISCSI_SESSION_DEBUG(is, "freezing devq");
1886 		}
1887 		ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_DEV_QFRZN;
1888 		xpt_done(ccb);
1889 		return;
1890 	}
1891 #endif
1892 
1893 	request = icl_pdu_new_bhs(is->is_conn, M_NOWAIT);
1894 	if (request == NULL) {
1895 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1896 			xpt_freeze_devq(ccb->ccb_h.path, 1);
1897 			ISCSI_SESSION_DEBUG(is, "freezing devq");
1898 		}
1899 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
1900 		xpt_done(ccb);
1901 		return;
1902 	}
1903 
1904 	csio = &ccb->csio;
1905 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
1906 	bhssc->bhssc_opcode = ISCSI_BHS_OPCODE_SCSI_COMMAND;
1907 	bhssc->bhssc_flags |= BHSSC_FLAGS_F;
1908 	switch (csio->ccb_h.flags & CAM_DIR_MASK) {
1909 	case CAM_DIR_IN:
1910 		bhssc->bhssc_flags |= BHSSC_FLAGS_R;
1911 		break;
1912 	case CAM_DIR_OUT:
1913 		bhssc->bhssc_flags |= BHSSC_FLAGS_W;
1914 		break;
1915 	}
1916 
1917         switch (csio->tag_action) {
1918         case MSG_HEAD_OF_Q_TAG:
1919 		bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_HOQ;
1920 		break;
1921                 break;
1922         case MSG_ORDERED_Q_TAG:
1923 		bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ORDERED;
1924                 break;
1925         case MSG_ACA_TASK:
1926 		bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ACA;
1927                 break;
1928         case CAM_TAG_ACTION_NONE:
1929         case MSG_SIMPLE_Q_TAG:
1930         default:
1931 		bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_SIMPLE;
1932                 break;
1933         }
1934 
1935 	bhssc->bhssc_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
1936 	bhssc->bhssc_initiator_task_tag = is->is_initiator_task_tag;
1937 	is->is_initiator_task_tag++;
1938 	bhssc->bhssc_expected_data_transfer_length = htonl(csio->dxfer_len);
1939 	KASSERT(csio->cdb_len <= sizeof(bhssc->bhssc_cdb),
1940 	    ("unsupported CDB size %zd", (size_t)csio->cdb_len));
1941 
1942 	if (csio->ccb_h.flags & CAM_CDB_POINTER)
1943 		memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_ptr, csio->cdb_len);
1944 	else
1945 		memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_bytes, csio->cdb_len);
1946 
1947 	error = iscsi_outstanding_add(is, bhssc->bhssc_initiator_task_tag, ccb);
1948 	if (error != 0) {
1949 		icl_pdu_free(request);
1950 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1951 			xpt_freeze_devq(ccb->ccb_h.path, 1);
1952 			ISCSI_SESSION_DEBUG(is, "freezing devq");
1953 		}
1954 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
1955 		xpt_done(ccb);
1956 		return;
1957 	}
1958 
1959 	if (is->is_immediate_data &&
1960 	    (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
1961 		len = csio->dxfer_len;
1962 		//ISCSI_SESSION_DEBUG(is, "adding %zd of immediate data", len);
1963 		if (len > is->is_first_burst_length) {
1964 			ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_first_burst_length);
1965 			len = is->is_first_burst_length;
1966 		}
1967 
1968 		error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT);
1969 		if (error != 0) {
1970 			icl_pdu_free(request);
1971 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1972 				xpt_freeze_devq(ccb->ccb_h.path, 1);
1973 				ISCSI_SESSION_DEBUG(is, "freezing devq");
1974 			}
1975 			ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
1976 			xpt_done(ccb);
1977 			return;
1978 		}
1979 	}
1980 	iscsi_pdu_queue_locked(request);
1981 }
1982 
1983 static void
1984 iscsi_action(struct cam_sim *sim, union ccb *ccb)
1985 {
1986 	struct iscsi_session *is;
1987 
1988 	is = cam_sim_softc(sim);
1989 
1990 	ISCSI_SESSION_LOCK_ASSERT(is);
1991 
1992 	if (is->is_terminating) {
1993 		ISCSI_SESSION_DEBUG(is, "called during termination");
1994 		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
1995 		xpt_done(ccb);
1996 		return;
1997 	}
1998 
1999 	switch (ccb->ccb_h.func_code) {
2000 	case XPT_PATH_INQ:
2001 	{
2002 		struct ccb_pathinq *cpi = &ccb->cpi;
2003 
2004 		cpi->version_num = 1;
2005 		cpi->hba_inquiry = PI_TAG_ABLE;
2006 		cpi->target_sprt = 0;
2007 		cpi->hba_misc = PIM_EXTLUNS;
2008 		cpi->hba_eng_cnt = 0;
2009 		cpi->max_target = 0;
2010 		cpi->max_lun = 0;
2011 		cpi->initiator_id = ~0;
2012 		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2013 		strlcpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
2014 		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2015 		cpi->unit_number = cam_sim_unit(sim);
2016 		cpi->bus_id = cam_sim_bus(sim);
2017 		cpi->base_transfer_speed = 150000; /* XXX */
2018 		cpi->transport = XPORT_ISCSI;
2019 		cpi->transport_version = 0;
2020 		cpi->protocol = PROTO_SCSI;
2021 		cpi->protocol_version = SCSI_REV_SPC3;
2022 		cpi->maxio = MAXPHYS;
2023 		cpi->ccb_h.status = CAM_REQ_CMP;
2024 		break;
2025 	}
2026 	case XPT_CALC_GEOMETRY:
2027 		cam_calc_geometry(&ccb->ccg, /*extended*/1);
2028 		ccb->ccb_h.status = CAM_REQ_CMP;
2029 		break;
2030 #if 0
2031 	/*
2032 	 * XXX: What's the point?
2033 	 */
2034 	case XPT_RESET_BUS:
2035 	case XPT_ABORT:
2036 	case XPT_TERM_IO:
2037 		ISCSI_SESSION_DEBUG(is, "faking success for reset, abort, or term_io");
2038 		ccb->ccb_h.status = CAM_REQ_CMP;
2039 		break;
2040 #endif
2041 	case XPT_SCSI_IO:
2042 		iscsi_action_scsiio(is, ccb);
2043 		return;
2044 	default:
2045 #if 0
2046 		ISCSI_SESSION_DEBUG(is, "got unsupported code 0x%x", ccb->ccb_h.func_code);
2047 #endif
2048 		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2049 		break;
2050 	}
2051 	xpt_done(ccb);
2052 }
2053 
2054 static void
2055 iscsi_poll(struct cam_sim *sim)
2056 {
2057 
2058 	KASSERT(0, ("%s: you're not supposed to be here", __func__));
2059 }
2060 
2061 static void
2062 iscsi_shutdown(struct iscsi_softc *sc)
2063 {
2064 	struct iscsi_session *is;
2065 
2066 	ISCSI_DEBUG("removing all sessions due to shutdown");
2067 
2068 	sx_slock(&sc->sc_lock);
2069 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next)
2070 		iscsi_session_terminate(is);
2071 	sx_sunlock(&sc->sc_lock);
2072 }
2073 
2074 static int
2075 iscsi_load(void)
2076 {
2077 	int error;
2078 
2079 	sc = malloc(sizeof(*sc), M_ISCSI, M_ZERO | M_WAITOK);
2080 	sx_init(&sc->sc_lock, "iscsi");
2081 	TAILQ_INIT(&sc->sc_sessions);
2082 	cv_init(&sc->sc_cv, "iscsi_cv");
2083 
2084 	iscsi_outstanding_zone = uma_zcreate("iscsi_outstanding",
2085 	    sizeof(struct iscsi_outstanding), NULL, NULL, NULL, NULL,
2086 	    UMA_ALIGN_PTR, 0);
2087 
2088 	error = make_dev_p(MAKEDEV_CHECKNAME, &sc->sc_cdev, &iscsi_cdevsw,
2089 	    NULL, UID_ROOT, GID_WHEEL, 0600, "iscsi");
2090 	if (error != 0) {
2091 		ISCSI_WARN("failed to create device node, error %d", error);
2092 		return (error);
2093 	}
2094 	sc->sc_cdev->si_drv1 = sc;
2095 
2096 	/*
2097 	 * Note that this needs to get run before dashutdown().  Otherwise,
2098 	 * when rebooting with iSCSI session with outstanding requests,
2099 	 * but disconnected, dashutdown() will hang on cam_periph_runccb().
2100 	 */
2101 	sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
2102 	    iscsi_shutdown, sc, SHUTDOWN_PRI_FIRST);
2103 
2104 	return (0);
2105 }
2106 
2107 static int
2108 iscsi_unload(void)
2109 {
2110 	struct iscsi_session *is, *tmp;
2111 
2112 	if (sc->sc_cdev != NULL) {
2113 		ISCSI_DEBUG("removing device node");
2114 		destroy_dev(sc->sc_cdev);
2115 		ISCSI_DEBUG("device node removed");
2116 	}
2117 
2118 	if (sc->sc_shutdown_eh != NULL)
2119 		EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_eh);
2120 
2121 	sx_slock(&sc->sc_lock);
2122 	TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp)
2123 		iscsi_session_terminate(is);
2124 	while(!TAILQ_EMPTY(&sc->sc_sessions)) {
2125 		ISCSI_DEBUG("waiting for sessions to terminate");
2126 		cv_wait(&sc->sc_cv, &sc->sc_lock);
2127 	}
2128 	ISCSI_DEBUG("all sessions terminated");
2129 	sx_sunlock(&sc->sc_lock);
2130 
2131 	uma_zdestroy(iscsi_outstanding_zone);
2132 	sx_destroy(&sc->sc_lock);
2133 	cv_destroy(&sc->sc_cv);
2134 	free(sc, M_ISCSI);
2135 	return (0);
2136 }
2137 
2138 static int
2139 iscsi_quiesce(void)
2140 {
2141 	sx_slock(&sc->sc_lock);
2142 	if (!TAILQ_EMPTY(&sc->sc_sessions)) {
2143 		sx_sunlock(&sc->sc_lock);
2144 		return (EBUSY);
2145 	}
2146 	sx_sunlock(&sc->sc_lock);
2147 	return (0);
2148 }
2149 
2150 static int
2151 iscsi_modevent(module_t mod, int what, void *arg)
2152 {
2153 	int error;
2154 
2155 	switch (what) {
2156 	case MOD_LOAD:
2157 		error = iscsi_load();
2158 		break;
2159 	case MOD_UNLOAD:
2160 		error = iscsi_unload();
2161 		break;
2162 	case MOD_QUIESCE:
2163 		error = iscsi_quiesce();
2164 		break;
2165 	default:
2166 		error = EINVAL;
2167 		break;
2168 	}
2169 	return (error);
2170 }
2171 
2172 moduledata_t iscsi_data = {
2173 	"iscsi",
2174 	iscsi_modevent,
2175 	0
2176 };
2177 
2178 DECLARE_MODULE(iscsi, iscsi_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
2179 MODULE_DEPEND(iscsi, cam, 1, 1, 1);
2180 MODULE_DEPEND(iscsi, icl, 1, 1, 1);
2181