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