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