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