1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2019 Joshua M. Clulow <josh@sysmgr.org> 24 */ 25 26 /* 27 * ISCSID -- 28 * 29 * Discovery of targets and access to the persistent storage starts here. 30 */ 31 32 #include <sys/thread.h> 33 #include <sys/types.h> 34 #include <sys/proc.h> /* declares: p0 */ 35 #include <sys/cmn_err.h> 36 #include <sys/scsi/adapters/iscsi_if.h> 37 #include <netinet/in.h> 38 #include "iscsi_targetparam.h" 39 #include "isns_client.h" 40 #include "isns_protocol.h" 41 #include "persistent.h" 42 #include "iscsi.h" 43 #include <sys/ethernet.h> 44 #include <sys/bootprops.h> 45 46 /* 47 * local function prototypes 48 */ 49 static boolean_t iscsid_init_config(iscsi_hba_t *ihp); 50 static boolean_t iscsid_init_targets(iscsi_hba_t *ihp); 51 static void iscsid_thread_static(iscsi_thread_t *thread, void *p); 52 static void iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p); 53 static void iscsid_thread_isns(iscsi_thread_t *thread, void *p); 54 static void iscsid_thread_slp(iscsi_thread_t *thread, void *p); 55 static void iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p); 56 static void iscsid_threads_create(iscsi_hba_t *ihp); 57 static void iscsid_threads_destroy(void); 58 static int iscsid_copyto_param_set(uint32_t param_id, 59 iscsi_login_params_t *params, iscsi_param_set_t *ipsp); 60 static void iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp, 61 isns_portal_group_list_t *pg_list); 62 static void iscsid_remove_target_param(char *name); 63 static boolean_t iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method, 64 struct sockaddr *addr_dsc, char *target_name, int tpgt, 65 struct sockaddr *addr_tgt); 66 static void iscsi_discovery_event(iscsi_hba_t *ihp, 67 iSCSIDiscoveryMethod_t m, boolean_t start); 68 static boolean_t iscsid_boot_init_config(iscsi_hba_t *ihp); 69 static iscsi_sess_t *iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid); 70 static boolean_t iscsid_make_entry(ib_boot_prop_t *boot_prop_entry, 71 entry_t *entry); 72 static boolean_t iscsid_check_active_boot_conn(iscsi_hba_t *ihp); 73 74 extern int modrootloaded; 75 int iscsi_configroot_retry = 20; 76 static boolean_t iscsi_configroot_printed = FALSE; 77 static int iscsi_net_up = 0; 78 extern ib_boot_prop_t *iscsiboot_prop; 79 80 #define ISCSI_CONFIGROOT_DELAY 1 81 82 /* 83 * iSCSI target discovery thread table 84 */ 85 typedef struct iscsid_thr_table { 86 void (*func_start)(iscsi_thread_t *, void *); 87 iscsi_thread_t *thr_id; 88 iSCSIDiscoveryMethod_t method; 89 char *name; 90 } iscsid_thr_table; 91 92 static iscsid_thr_table iscsid_thr[] = { 93 { iscsid_thread_static, NULL, 94 iSCSIDiscoveryMethodStatic, 95 "Static" }, 96 { iscsid_thread_sendtgts, NULL, 97 iSCSIDiscoveryMethodSendTargets, 98 "SendTarget" }, 99 { iscsid_thread_slp, NULL, 100 iSCSIDiscoveryMethodSLP, 101 "SLP" }, 102 { iscsid_thread_isns, NULL, 103 iSCSIDiscoveryMethodISNS, 104 "iSNS" }, 105 { NULL, NULL, 106 iSCSIDiscoveryMethodUnknown, 107 NULL } 108 }; 109 110 /* 111 * discovery method event table 112 */ 113 iSCSIDiscoveryMethod_t for_failure[] = { 114 iSCSIDiscoveryMethodStatic, 115 iSCSIDiscoveryMethodSLP, 116 iSCSIDiscoveryMethodISNS, 117 iSCSIDiscoveryMethodSendTargets, 118 iSCSIDiscoveryMethodUnknown /* terminating value */ 119 }; 120 121 /* 122 * The following private tunable, set in /etc/system, e.g., 123 * set iscsi:iscsi_boot_max_delay = 360 124 * , provides with customer a max wait time in 125 * seconds to wait for boot lun online during iscsi boot. 126 * Defaults to 180s. 127 */ 128 int iscsi_boot_max_delay = ISCSI_BOOT_DEFAULT_MAX_DELAY; 129 130 /* 131 * discovery configuration semaphore 132 */ 133 ksema_t iscsid_config_semaphore; 134 135 static iscsi_thread_t *iscsi_boot_wd_handle = NULL; 136 137 #define CHECK_METHOD(v) ((dm & v) ? B_TRUE : B_FALSE) 138 139 /* 140 * Check if IP is valid 141 */ 142 static boolean_t 143 iscsid_ip_check(char *ip) 144 { 145 int i = 0; 146 147 if (!ip) 148 return (B_FALSE); 149 for (; (ip[i] == 0) && (i < IB_IP_BUFLEN); i++) {} 150 if (i == IB_IP_BUFLEN) { 151 /* invalid IP address */ 152 return (B_FALSE); 153 } 154 return (B_TRUE); 155 } 156 157 /* 158 * Make an entry for the boot target. 159 * return B_TRUE upon success 160 * B_FALSE if fail 161 */ 162 static boolean_t 163 iscsid_make_entry(ib_boot_prop_t *boot_prop_entry, entry_t *entry) 164 { 165 if (entry == NULL || boot_prop_entry == NULL) { 166 return (B_FALSE); 167 } 168 169 if (!iscsid_ip_check( 170 (char *)&boot_prop_entry->boot_tgt.tgt_ip_u)) 171 return (B_FALSE); 172 173 if (boot_prop_entry->boot_tgt.sin_family != AF_INET && 174 boot_prop_entry->boot_tgt.sin_family != AF_INET6) 175 return (B_FALSE); 176 177 entry->e_vers = ISCSI_INTERFACE_VERSION; 178 179 mutex_enter(&iscsi_oid_mutex); 180 entry->e_oid = iscsi_oid++; 181 mutex_exit(&iscsi_oid_mutex); 182 183 entry->e_tpgt = ISCSI_DEFAULT_TPGT; 184 185 if (boot_prop_entry->boot_tgt.sin_family == AF_INET) { 186 entry->e_u.u_in4.s_addr = 187 boot_prop_entry->boot_tgt.tgt_ip_u.u_in4.s_addr; 188 entry->e_insize = sizeof (struct in_addr); 189 } else { 190 (void) bcopy( 191 &boot_prop_entry->boot_tgt.tgt_ip_u.u_in6.s6_addr, 192 entry->e_u.u_in6.s6_addr, 16); 193 entry->e_insize = sizeof (struct in6_addr); 194 } 195 196 entry->e_port = boot_prop_entry->boot_tgt.tgt_port; 197 entry->e_boot = B_TRUE; 198 return (B_TRUE); 199 } 200 201 /* 202 * Create the boot session 203 */ 204 static void 205 iscsi_boot_session_create(iscsi_hba_t *ihp, 206 ib_boot_prop_t *boot_prop_table) 207 { 208 iSCSIDiscoveryMethod_t dm; 209 entry_t e; 210 iscsi_sockaddr_t addr_dsc; 211 212 if (ihp == NULL || boot_prop_table == NULL) { 213 return; 214 } 215 216 if (!iscsid_ip_check( 217 (char *)&boot_prop_table->boot_tgt.tgt_ip_u)) { 218 return; 219 } 220 221 if (boot_prop_table->boot_tgt.tgt_name != NULL) { 222 dm = iSCSIDiscoveryMethodStatic | 223 iSCSIDiscoveryMethodBoot; 224 if (!iscsid_make_entry(boot_prop_table, &e)) 225 return; 226 iscsid_addr_to_sockaddr(e.e_insize, &e.e_u, 227 e.e_port, &addr_dsc.sin); 228 229 (void) iscsid_add(ihp, dm, &addr_dsc.sin, 230 (char *)boot_prop_table->boot_tgt.tgt_name, 231 e.e_tpgt, &addr_dsc.sin); 232 } else { 233 dm = iSCSIDiscoveryMethodSendTargets | 234 iSCSIDiscoveryMethodBoot; 235 if (!iscsid_make_entry(boot_prop_table, &e)) 236 return; 237 iscsid_addr_to_sockaddr(e.e_insize, &e.e_u, 238 e.e_port, &addr_dsc.sin); 239 iscsid_do_sendtgts(&e); 240 (void) iscsid_login_tgt(ihp, NULL, dm, 241 &addr_dsc.sin); 242 } 243 } 244 245 /* 246 * iscsid_init -- to initialize stuffs related to iscsi daemon, 247 * and to create boot session if needed 248 */ 249 boolean_t 250 iscsid_init(iscsi_hba_t *ihp) 251 { 252 boolean_t rval = B_TRUE; 253 254 sema_init(&iscsid_config_semaphore, 1, NULL, 255 SEMA_DRIVER, NULL); 256 persistent_init(); 257 iscsid_threads_create(ihp); 258 259 if (modrootloaded) { 260 /* 261 * The root file system is available so we can load the 262 * persistent store. 263 */ 264 if (persistent_load() == B_TRUE) { 265 ihp->hba_persistent_loaded = B_TRUE; 266 } else { 267 return (B_FALSE); 268 } 269 } else { 270 /* 271 * If the root file system is not yet mounted then we _must_ be 272 * booting from an iSCSI device. If not, we want to fail to 273 * attach so that we can try again after the VFS root is 274 * available. 275 */ 276 if (iscsiboot_prop == NULL) { 277 return (B_FALSE); 278 } 279 280 if (!iscsid_boot_init_config(ihp)) { 281 rval = B_FALSE; 282 } else { 283 iscsi_boot_session_create(ihp, iscsiboot_prop); 284 iscsi_boot_wd_handle = 285 iscsi_thread_create(ihp->hba_dip, 286 "BootWD", iscsid_thread_boot_wd, ihp); 287 if (iscsi_boot_wd_handle != NULL) { 288 rval = iscsi_thread_start( 289 iscsi_boot_wd_handle); 290 } else { 291 rval = B_FALSE; 292 } 293 } 294 if (rval == B_FALSE) { 295 cmn_err(CE_NOTE, "Initializaton of iscsi boot session" 296 " partially failed"); 297 } 298 } 299 300 return (rval); 301 } 302 303 /* 304 * iscsid_start -- start the iscsi initiator daemon, actually this code 305 * is just to enable discovery methods which are set enabled in 306 * persistent store, as an economic way to present the 'daemon' funtionality 307 */ 308 boolean_t 309 iscsid_start(iscsi_hba_t *ihp) 310 { 311 boolean_t rval = B_FALSE; 312 iSCSIDiscoveryMethod_t dm; 313 iSCSIDiscoveryMethod_t *fdm; 314 315 rval = iscsid_init_config(ihp); 316 if (rval == B_TRUE) { 317 rval = iscsid_init_targets(ihp); 318 } 319 320 if (rval == B_TRUE) { 321 dm = persistent_disc_meth_get(); 322 rval = iscsid_enable_discovery(ihp, dm, B_TRUE); 323 if (rval == B_TRUE) { 324 iscsid_poke_discovery(ihp, 325 iSCSIDiscoveryMethodUnknown); 326 (void) iscsid_login_tgt(ihp, NULL, 327 iSCSIDiscoveryMethodUnknown, NULL); 328 } 329 } 330 331 if (rval == B_FALSE) { 332 /* 333 * In case of failure the events still need to be sent 334 * because the door daemon will pause until all these 335 * events have occurred. 336 */ 337 for (fdm = &for_failure[0]; *fdm != 338 iSCSIDiscoveryMethodUnknown; fdm++) { 339 /* ---- Send both start and end events ---- */ 340 iscsi_discovery_event(ihp, *fdm, B_TRUE); 341 iscsi_discovery_event(ihp, *fdm, B_FALSE); 342 } 343 } 344 345 return (rval); 346 } 347 348 /* 349 * iscsid_stop -- stop the iscsi initiator daemon, by disabling 350 * all the discovery methods first, and then try to stop all 351 * related threads. This is a try-best effort, leave any 'busy' device 352 * (and therefore session) there and just return. 353 */ 354 boolean_t 355 iscsid_stop(iscsi_hba_t *ihp) 356 { 357 boolean_t rval = B_FALSE; 358 iscsi_sess_t *isp = NULL; 359 360 (void) iscsid_disable_discovery(ihp, ISCSI_ALL_DISCOVERY_METHODS); 361 362 /* final check */ 363 rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 364 if (ihp->hba_sess_list == NULL) { 365 rval = B_TRUE; 366 } else { 367 /* 368 * If only boot session is left, that is OK. 369 * Otherwise, we should report that some sessions are left. 370 */ 371 rval = B_TRUE; 372 for (isp = ihp->hba_sess_list; isp != NULL; 373 isp = isp->sess_next) { 374 if (isp->sess_boot == B_FALSE) { 375 rval = B_FALSE; 376 break; 377 } 378 } 379 } 380 rw_exit(&ihp->hba_sess_list_rwlock); 381 382 return (rval); 383 } 384 385 /* 386 * iscsid_fini -- do whatever is required to clean up 387 */ 388 /* ARGSUSED */ 389 void 390 iscsid_fini() 391 { 392 if (iscsi_boot_wd_handle != NULL) { 393 iscsi_thread_destroy(iscsi_boot_wd_handle); 394 iscsi_boot_wd_handle = NULL; 395 } 396 iscsid_threads_destroy(); 397 persistent_fini(); 398 sema_destroy(&iscsid_config_semaphore); 399 } 400 401 /* 402 * iscsid_props -- returns discovery thread information, used by ioctl code 403 */ 404 void 405 iscsid_props(iSCSIDiscoveryProperties_t *props) 406 { 407 iSCSIDiscoveryMethod_t dm; 408 409 dm = persistent_disc_meth_get(); 410 411 props->vers = ISCSI_INTERFACE_VERSION; 412 413 /* ---- change once thread is implemented ---- */ 414 props->iSNSDiscoverySettable = B_FALSE; 415 props->SLPDiscoverySettable = B_FALSE; 416 props->StaticDiscoverySettable = B_TRUE; 417 props->SendTargetsDiscoverySettable = B_TRUE; 418 props->iSNSDiscoveryMethod = iSNSDiscoveryMethodStatic; 419 420 props->iSNSDiscoveryEnabled = CHECK_METHOD(iSCSIDiscoveryMethodISNS); 421 props->StaticDiscoveryEnabled = 422 CHECK_METHOD(iSCSIDiscoveryMethodStatic); 423 props->SendTargetsDiscoveryEnabled = 424 CHECK_METHOD(iSCSIDiscoveryMethodSendTargets); 425 props->SLPDiscoveryEnabled = CHECK_METHOD(iSCSIDiscoveryMethodSLP); 426 } 427 428 /* 429 * iscsid_enable_discovery - start specified discovery methods 430 */ 431 /* ARGSUSED */ 432 boolean_t 433 iscsid_enable_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t idm, 434 boolean_t poke) 435 { 436 boolean_t rval = B_TRUE; 437 iscsid_thr_table *dt; 438 439 /* 440 * start the specified discovery method(s) 441 */ 442 for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown; 443 dt++) { 444 if (idm & dt->method) { 445 if (dt->thr_id != NULL) { 446 rval = iscsi_thread_start(dt->thr_id); 447 if (rval == B_FALSE) { 448 break; 449 } 450 if (poke == B_TRUE) { 451 (void) iscsi_thread_send_wakeup( 452 dt->thr_id); 453 } 454 } else { 455 /* 456 * unexpected condition. The threads for each 457 * discovery method should have started at 458 * initialization 459 */ 460 ASSERT(B_FALSE); 461 } 462 } 463 } /* END for() */ 464 465 return (rval); 466 } 467 468 469 /* 470 * iscsid_disable_discovery - stop specified discovery methods 471 */ 472 boolean_t 473 iscsid_disable_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t idm) 474 { 475 boolean_t rval = B_TRUE; 476 iscsid_thr_table *dt; 477 478 /* 479 * stop the specified discovery method(s) 480 */ 481 for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown; 482 dt++) { 483 if (idm & dt->method) { 484 485 /* signal discovery event change - begin */ 486 iscsi_discovery_event(ihp, dt->method, B_TRUE); 487 488 /* Attempt to logout of all associated targets */ 489 rval = iscsid_del(ihp, NULL, dt->method, NULL); 490 if (rval == B_TRUE) { 491 /* Successfully logged out of targets */ 492 if (dt->thr_id != NULL) { 493 rval = iscsi_thread_stop(dt->thr_id); 494 if (rval == B_FALSE) { 495 /* 496 * signal discovery 497 * event change - end 498 */ 499 iscsi_discovery_event(ihp, 500 dt->method, B_FALSE); 501 break; 502 } 503 504 } else { 505 /* 506 * unexpected condition. The threads 507 * for each discovery method should 508 * have started at initialization 509 */ 510 ASSERT(B_FALSE); 511 } 512 } 513 514 /* signal discovery event change - end */ 515 iscsi_discovery_event(ihp, dt->method, B_FALSE); 516 517 } 518 } /* END for() */ 519 520 return (rval); 521 } 522 523 /* 524 * iscsid_poke_discovery - wakeup discovery methods to find any new targets 525 * and wait for all discovery processes to complete. 526 */ 527 void 528 iscsid_poke_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method) 529 { 530 #define ISCSI_DISCOVERY_DELAY 1 531 532 iSCSIDiscoveryMethod_t dm; 533 iscsid_thr_table *dt; 534 boolean_t send_wakeup; 535 536 ASSERT(ihp != NULL); 537 538 /* reset discovery flags */ 539 mutex_enter(&ihp->hba_discovery_events_mutex); 540 ihp->hba_discovery_in_progress = B_TRUE; 541 ihp->hba_discovery_events = iSCSIDiscoveryMethodUnknown; 542 mutex_exit(&ihp->hba_discovery_events_mutex); 543 544 /* start all enabled discovery methods */ 545 dm = persistent_disc_meth_get(); 546 for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown; 547 dt++) { 548 send_wakeup = B_FALSE; 549 550 if ((method == iSCSIDiscoveryMethodUnknown) || 551 (method == dt->method)) { 552 if ((dm & dt->method) && (dt->thr_id != NULL)) { 553 if (iscsi_thread_send_wakeup(dt->thr_id) == 554 B_TRUE) { 555 send_wakeup = B_TRUE; 556 } 557 } 558 } 559 560 if (send_wakeup == B_FALSE) { 561 iscsi_discovery_event(ihp, dt->method, B_TRUE); 562 iscsi_discovery_event(ihp, dt->method, B_FALSE); 563 } 564 } 565 566 mutex_enter(&ihp->hba_discovery_events_mutex); 567 while (ihp->hba_discovery_events != ISCSI_ALL_DISCOVERY_METHODS) { 568 mutex_exit(&ihp->hba_discovery_events_mutex); 569 delay(SEC_TO_TICK(ISCSI_DISCOVERY_DELAY)); 570 mutex_enter(&ihp->hba_discovery_events_mutex); 571 } 572 ihp->hba_discovery_in_progress = B_FALSE; 573 mutex_exit(&ihp->hba_discovery_events_mutex); 574 575 } 576 577 /* 578 * iscsid_do_sendtgts - issue send targets command to the given discovery 579 * address and then add the discovered targets to the discovery queue 580 */ 581 void 582 iscsid_do_sendtgts(entry_t *disc_addr) 583 { 584 585 #define SENDTGTS_DEFAULT_NUM_TARGETS 10 586 587 int stl_sz; 588 int stl_num_tgts = SENDTGTS_DEFAULT_NUM_TARGETS; 589 iscsi_sendtgts_list_t *stl_hdr = NULL; 590 boolean_t retry = B_TRUE; 591 char inp_buf[INET6_ADDRSTRLEN]; 592 const char *ip; 593 int ctr; 594 int rc; 595 iscsi_hba_t *ihp; 596 iSCSIDiscoveryMethod_t dm = iSCSIDiscoveryMethodSendTargets; 597 598 /* allocate and initialize sendtargets list header */ 599 stl_sz = sizeof (*stl_hdr) + ((stl_num_tgts - 1) * 600 sizeof (iscsi_sendtgts_entry_t)); 601 stl_hdr = kmem_zalloc(stl_sz, KM_SLEEP); 602 603 retry_sendtgts: 604 stl_hdr->stl_in_cnt = stl_num_tgts; 605 bcopy(disc_addr, &(stl_hdr->stl_entry), 606 sizeof (stl_hdr->stl_entry)); 607 stl_hdr->stl_entry.e_vers = ISCSI_INTERFACE_VERSION; 608 609 /* lock interface so only one SendTargets operation occurs */ 610 if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) { 611 cmn_err(CE_NOTE, "!iscsi discovery failure - SendTargets. " 612 "failure to get soft state"); 613 kmem_free(stl_hdr, stl_sz); 614 return; 615 } 616 sema_p(&ihp->hba_sendtgts_semaphore); 617 rc = iscsi_ioctl_sendtgts_get(ihp, stl_hdr); 618 sema_v(&ihp->hba_sendtgts_semaphore); 619 if (rc) { 620 ip = inet_ntop((disc_addr->e_insize == 621 sizeof (struct in_addr) ? AF_INET : AF_INET6), 622 &disc_addr->e_u, inp_buf, sizeof (inp_buf)); 623 cmn_err(CE_NOTE, 624 "iscsi discovery failure - SendTargets (%s)\n", ip); 625 kmem_free(stl_hdr, stl_sz); 626 return; 627 } 628 629 /* check if all targets received */ 630 if (stl_hdr->stl_in_cnt < stl_hdr->stl_out_cnt) { 631 if (retry == B_TRUE) { 632 stl_num_tgts = stl_hdr->stl_out_cnt; 633 kmem_free(stl_hdr, stl_sz); 634 stl_sz = sizeof (*stl_hdr) + 635 ((stl_num_tgts - 1) * 636 sizeof (iscsi_sendtgts_entry_t)); 637 stl_hdr = kmem_zalloc(stl_sz, KM_SLEEP); 638 retry = B_FALSE; 639 goto retry_sendtgts; 640 } else { 641 ip = inet_ntop((disc_addr->e_insize == 642 sizeof (struct in_addr) ? 643 AF_INET : AF_INET6), &disc_addr->e_u, 644 inp_buf, sizeof (inp_buf)); 645 cmn_err(CE_NOTE, "iscsi discovery failure - " 646 "SendTargets overflow (%s)\n", ip); 647 kmem_free(stl_hdr, stl_sz); 648 return; 649 } 650 } 651 652 for (ctr = 0; ctr < stl_hdr->stl_out_cnt; ctr++) { 653 iscsi_sockaddr_t addr_dsc; 654 iscsi_sockaddr_t addr_tgt; 655 656 iscsid_addr_to_sockaddr(disc_addr->e_insize, 657 &disc_addr->e_u, disc_addr->e_port, &addr_dsc.sin); 658 iscsid_addr_to_sockaddr( 659 stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize, 660 &(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr), 661 stl_hdr->stl_list[ctr].ste_ipaddr.a_port, 662 &addr_tgt.sin); 663 if (disc_addr->e_boot == B_TRUE) { 664 dm = dm | iSCSIDiscoveryMethodBoot; 665 } 666 (void) iscsid_add(ihp, dm, 667 &addr_dsc.sin, (char *)stl_hdr->stl_list[ctr].ste_name, 668 stl_hdr->stl_list[ctr].ste_tpgt, 669 &addr_tgt.sin); 670 } 671 kmem_free(stl_hdr, stl_sz); 672 } 673 674 void 675 iscsid_do_isns_query_one_server(iscsi_hba_t *ihp, entry_t *isns_server) 676 { 677 int pg_sz, query_status; 678 iscsi_addr_t *ap; 679 isns_portal_group_list_t *pg_list; 680 681 ap = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP); 682 ap->a_port = isns_server->e_port; 683 ap->a_addr.i_insize = isns_server->e_insize; 684 685 if (isns_server->e_insize == sizeof (struct in_addr)) { 686 ap->a_addr.i_addr.in4.s_addr = (isns_server->e_u.u_in4.s_addr); 687 } else if (isns_server->e_insize == sizeof (struct in6_addr)) { 688 bcopy(&(isns_server->e_u.u_in6.s6_addr), 689 ap->a_addr.i_addr.in6.s6_addr, 16); 690 } else { 691 kmem_free(ap, sizeof (iscsi_addr_t)); 692 return; 693 } 694 695 pg_list = NULL; 696 query_status = isns_query_one_server( 697 ap, ihp->hba_isid, 698 ihp->hba_name, ihp->hba_alias, 699 ISNS_INITIATOR_NODE_TYPE, &pg_list); 700 kmem_free(ap, sizeof (iscsi_addr_t)); 701 if (query_status != isns_ok || pg_list == NULL) { 702 DTRACE_PROBE1(iscsid_do_isns_query_one_server_status, 703 int, query_status); 704 return; 705 } 706 707 iscsid_add_pg_list_to_cache(ihp, pg_list); 708 pg_sz = sizeof (isns_portal_group_list_t); 709 if (pg_list->pg_out_cnt > 0) { 710 pg_sz += (pg_list->pg_out_cnt - 1) * 711 sizeof (isns_portal_group_t); 712 } 713 kmem_free(pg_list, pg_sz); 714 } 715 716 void 717 iscsid_do_isns_query(iscsi_hba_t *ihp) 718 { 719 int pg_sz, query_status; 720 isns_portal_group_list_t *pg_list; 721 722 pg_list = NULL; 723 query_status = isns_query(ihp->hba_isid, 724 ihp->hba_name, 725 ihp->hba_alias, 726 ISNS_INITIATOR_NODE_TYPE, 727 &pg_list); 728 729 if (pg_list == NULL) { 730 DTRACE_PROBE1(iscsid_do_isns_query_status, 731 int, query_status); 732 return; 733 } 734 735 if ((query_status != isns_ok && 736 query_status != isns_op_partially_failed)) { 737 DTRACE_PROBE1(iscsid_do_isns_query_status, 738 int, query_status); 739 pg_sz = sizeof (isns_portal_group_list_t); 740 if (pg_list->pg_out_cnt > 0) { 741 pg_sz += (pg_list->pg_out_cnt - 1) * 742 sizeof (isns_portal_group_t); 743 } 744 kmem_free(pg_list, pg_sz); 745 return; 746 } 747 748 iscsid_add_pg_list_to_cache(ihp, pg_list); 749 750 pg_sz = sizeof (isns_portal_group_list_t); 751 if (pg_list->pg_out_cnt > 0) { 752 pg_sz += (pg_list->pg_out_cnt - 1) * 753 sizeof (isns_portal_group_t); 754 } 755 kmem_free(pg_list, pg_sz); 756 } 757 758 /* 759 * iscsid_config_one - for the given target name, attempt 760 * to login to all targets associated with name. If target 761 * name is not found in discovery queue, reset the discovery 762 * queue, kick the discovery processes, and then retry. 763 * 764 * NOTE: The caller of this function must hold the 765 * iscsid_config_semaphore across this call. 766 */ 767 void 768 iscsid_config_one(iscsi_hba_t *ihp, char *name, boolean_t protect) 769 { 770 boolean_t rc = B_FALSE; 771 int retry = 0; 772 int lun_online = 0; 773 int cur_sec = 0; 774 775 if (!modrootloaded && (iscsiboot_prop != NULL)) { 776 if (!iscsi_configroot_printed) { 777 cmn_err(CE_NOTE, "Configuring" 778 " iSCSI boot session..."); 779 iscsi_configroot_printed = B_TRUE; 780 } 781 if (iscsi_net_up == 0) { 782 if (iscsi_net_interface(B_FALSE) == 783 ISCSI_STATUS_SUCCESS) { 784 iscsi_net_up = 1; 785 } else { 786 cmn_err(CE_WARN, "Failed to configure interface" 787 " for iSCSI boot session"); 788 return; 789 } 790 } 791 while (rc == B_FALSE && retry < 792 iscsi_configroot_retry) { 793 rc = iscsid_login_tgt(ihp, name, 794 iSCSIDiscoveryMethodBoot, NULL); 795 if (rc == B_FALSE) { 796 /* 797 * create boot session 798 */ 799 iscsi_boot_session_create(ihp, 800 iscsiboot_prop); 801 retry++; 802 continue; 803 } 804 rc = iscsid_check_active_boot_conn(ihp); 805 if (rc == B_FALSE) { 806 /* 807 * no active connection for the boot 808 * session, retry the login until 809 * one is found or the retry count 810 * is exceeded 811 */ 812 delay(SEC_TO_TICK(ISCSI_CONFIGROOT_DELAY)); 813 retry++; 814 continue; 815 } 816 /* 817 * The boot session has been created with active 818 * connection. If the target lun has not been online, 819 * we should wait here for a while 820 */ 821 do { 822 lun_online = 823 iscsiboot_prop->boot_tgt.lun_online; 824 if (lun_online == 0) { 825 delay(SEC_TO_TICK( 826 ISCSI_CONFIGROOT_DELAY)); 827 cur_sec++; 828 } 829 } while ((lun_online == 0) && 830 (cur_sec < iscsi_boot_max_delay)); 831 retry++; 832 } 833 if (!rc) { 834 cmn_err(CE_WARN, "Failed to configure iSCSI" 835 " boot session"); 836 } 837 } else { 838 rc = iscsid_login_tgt(ihp, name, iSCSIDiscoveryMethodUnknown, 839 NULL); 840 /* 841 * If we didn't login to the device we might have 842 * to update our discovery information and attempt 843 * the login again. 844 */ 845 if (rc == B_FALSE) { 846 /* 847 * Stale /dev links can cause us to get floods 848 * of config requests. Prevent these repeated 849 * requests from causing unneeded discovery updates 850 * if ISCSI_CONFIG_STORM_PROTECT is set. 851 */ 852 if ((protect == B_FALSE) || 853 (ddi_get_lbolt() > ihp->hba_config_lbolt + 854 SEC_TO_TICK(ihp->hba_config_storm_delay))) { 855 ihp->hba_config_lbolt = ddi_get_lbolt(); 856 iscsid_poke_discovery(ihp, 857 iSCSIDiscoveryMethodUnknown); 858 (void) iscsid_login_tgt(ihp, name, 859 iSCSIDiscoveryMethodUnknown, NULL); 860 } 861 } 862 } 863 } 864 865 /* 866 * iscsid_config_all - reset the discovery queue, kick the 867 * discovery processes, and login to all targets found 868 * 869 * NOTE: The caller of this function must hold the 870 * iscsid_config_semaphore across this call. 871 */ 872 void 873 iscsid_config_all(iscsi_hba_t *ihp, boolean_t protect) 874 { 875 boolean_t rc = B_FALSE; 876 int retry = 0; 877 int lun_online = 0; 878 int cur_sec = 0; 879 880 if (!modrootloaded && iscsiboot_prop != NULL) { 881 if (!iscsi_configroot_printed) { 882 cmn_err(CE_NOTE, "Configuring" 883 " iSCSI boot session..."); 884 iscsi_configroot_printed = B_TRUE; 885 } 886 if (iscsi_net_up == 0) { 887 if (iscsi_net_interface(B_FALSE) == 888 ISCSI_STATUS_SUCCESS) { 889 iscsi_net_up = 1; 890 } 891 } 892 while (rc == B_FALSE && retry < 893 iscsi_configroot_retry) { 894 rc = iscsid_login_tgt(ihp, NULL, 895 iSCSIDiscoveryMethodBoot, NULL); 896 if (rc == B_FALSE) { 897 /* 898 * No boot session has been created. 899 * We would like to create the boot 900 * Session first. 901 */ 902 iscsi_boot_session_create(ihp, 903 iscsiboot_prop); 904 retry++; 905 continue; 906 } 907 rc = iscsid_check_active_boot_conn(ihp); 908 if (rc == B_FALSE) { 909 /* 910 * no active connection for the boot 911 * session, retry the login until 912 * one is found or the retry count 913 * is exceeded 914 */ 915 delay(SEC_TO_TICK(ISCSI_CONFIGROOT_DELAY)); 916 retry++; 917 continue; 918 } 919 /* 920 * The boot session has been created with active 921 * connection. If the target lun has not been online, 922 * we should wait here for a while 923 */ 924 do { 925 lun_online = 926 iscsiboot_prop->boot_tgt.lun_online; 927 if (lun_online == 0) { 928 delay(SEC_TO_TICK( 929 ISCSI_CONFIGROOT_DELAY)); 930 cur_sec++; 931 } 932 } while ((lun_online == 0) && 933 (cur_sec < iscsi_boot_max_delay)); 934 retry++; 935 } 936 if (!rc) { 937 cmn_err(CE_WARN, "Failed to configure" 938 " boot session"); 939 } 940 } else { 941 /* 942 * Stale /dev links can cause us to get floods 943 * of config requests. Prevent these repeated 944 * requests from causing unneeded discovery updates 945 * if ISCSI_CONFIG_STORM_PROTECT is set. 946 */ 947 if ((protect == B_FALSE) || 948 (ddi_get_lbolt() > ihp->hba_config_lbolt + 949 SEC_TO_TICK(ihp->hba_config_storm_delay))) { 950 ihp->hba_config_lbolt = ddi_get_lbolt(); 951 iscsid_poke_discovery(ihp, 952 iSCSIDiscoveryMethodUnknown); 953 } 954 (void) iscsid_login_tgt(ihp, NULL, 955 iSCSIDiscoveryMethodUnknown, NULL); 956 } 957 } 958 959 /* 960 * isns_scn_callback - iSNS client received an SCN 961 * 962 * This code processes the iSNS client SCN events. These 963 * could relate to the addition, removal, or update of a 964 * logical unit. 965 */ 966 void 967 isns_scn_callback(void *arg) 968 { 969 int i, pg_sz; 970 int qry_status; 971 isns_portal_group_list_t *pg_list; 972 uint32_t scn_type; 973 iscsi_hba_t *ihp; 974 975 if (arg == NULL) { 976 /* No argument */ 977 return; 978 } 979 980 if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) { 981 kmem_free(arg, sizeof (isns_scn_callback_arg_t)); 982 return; 983 } 984 985 /* 986 * All isns callbacks are from a standalone taskq 987 * therefore the blocking here doesn't affect the enable/disable 988 * of isns discovery method 989 */ 990 if (iscsi_client_request_service(ihp) == B_FALSE) { 991 kmem_free(arg, sizeof (isns_scn_callback_arg_t)); 992 return; 993 } 994 995 scn_type = ((isns_scn_callback_arg_t *)arg)->scn_type; 996 DTRACE_PROBE1(isns_scn_callback_scn_type, int, scn_type); 997 switch (scn_type) { 998 /* 999 * ISNS_OBJ_ADDED - An object has been added. 1000 */ 1001 case ISNS_OBJ_ADDED: 1002 /* Query iSNS server for contact information */ 1003 pg_list = NULL; 1004 qry_status = isns_query_one_node( 1005 ((isns_scn_callback_arg_t *)arg)->source_key_attr, 1006 ihp->hba_isid, 1007 ihp->hba_name, 1008 (uint8_t *)"", 1009 ISNS_INITIATOR_NODE_TYPE, 1010 &pg_list); 1011 1012 /* Verify portal group is found */ 1013 if ((qry_status != isns_ok && 1014 qry_status != isns_op_partially_failed) || 1015 pg_list == NULL) { 1016 break; 1017 } 1018 1019 DTRACE_PROBE1(pg_list, 1020 isns_portal_group_list_t *, pg_list); 1021 1022 /* Add all portals for logical unit to discovery cache */ 1023 for (i = 0; i < pg_list->pg_out_cnt; i++) { 1024 iscsi_sockaddr_t addr_dsc; 1025 iscsi_sockaddr_t addr_tgt; 1026 1027 iscsid_addr_to_sockaddr( 1028 pg_list->pg_list[i].isns_server_ip.i_insize, 1029 &pg_list->pg_list[i].isns_server_ip.i_addr, 1030 pg_list->pg_list[i].isns_server_port, 1031 &addr_dsc.sin); 1032 iscsid_addr_to_sockaddr(pg_list->pg_list[i].insize, 1033 &pg_list->pg_list[i].pg_ip_addr, 1034 pg_list->pg_list[i].pg_port, &addr_tgt.sin); 1035 1036 (void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS, 1037 &addr_dsc.sin, (char *)pg_list->pg_list[i]. 1038 pg_iscsi_name, pg_list->pg_list[i].pg_tag, 1039 &addr_tgt.sin); 1040 1041 /* Force target to login */ 1042 (void) iscsid_login_tgt(ihp, (char *)pg_list-> 1043 pg_list[i].pg_iscsi_name, iSCSIDiscoveryMethodISNS, 1044 NULL); 1045 } 1046 1047 if (pg_list != NULL) { 1048 pg_sz = sizeof (isns_portal_group_list_t); 1049 if (pg_list->pg_out_cnt > 0) { 1050 pg_sz += (pg_list->pg_out_cnt - 1) * 1051 sizeof (isns_portal_group_t); 1052 } 1053 kmem_free(pg_list, pg_sz); 1054 } 1055 break; 1056 1057 /* 1058 * ISNS_OBJ_REMOVED - logical unit has been removed 1059 */ 1060 case ISNS_OBJ_REMOVED: 1061 if (iscsid_del(ihp, 1062 (char *)((isns_scn_callback_arg_t *)arg)-> 1063 source_key_attr, iSCSIDiscoveryMethodISNS, NULL) != 1064 B_TRUE) { 1065 cmn_err(CE_NOTE, "iscsi initiator - " 1066 "isns remove scn failed for target %s\n", 1067 (char *)((isns_scn_callback_arg_t *)arg)-> 1068 source_key_attr); 1069 1070 } 1071 break; 1072 1073 /* 1074 * ISNS_OBJ_UPDATED - logical unit has changed 1075 */ 1076 case ISNS_OBJ_UPDATED: 1077 cmn_err(CE_NOTE, "iscsi initiator - " 1078 "received iSNS update SCN for %s\n", 1079 (char *)((isns_scn_callback_arg_t *)arg)-> 1080 source_key_attr); 1081 break; 1082 1083 /* 1084 * ISNS_OBJ_UNKNOWN - 1085 */ 1086 default: 1087 cmn_err(CE_NOTE, "iscsi initiator - " 1088 "received unknown iSNS SCN type 0x%x\n", scn_type); 1089 break; 1090 } 1091 1092 iscsi_client_release_service(ihp); 1093 kmem_free(arg, sizeof (isns_scn_callback_arg_t)); 1094 } 1095 1096 1097 /* 1098 * iscsid_add - Creates discovered session and connection 1099 */ 1100 static boolean_t 1101 iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method, 1102 struct sockaddr *addr_dsc, char *target_name, int tpgt, 1103 struct sockaddr *addr_tgt) 1104 { 1105 boolean_t rtn = B_TRUE; 1106 iscsi_sess_t *isp; 1107 iscsi_conn_t *icp; 1108 uint_t oid; 1109 int idx; 1110 int isid; 1111 iscsi_config_sess_t *ics; 1112 int size; 1113 char *tmp; 1114 1115 ASSERT(ihp != NULL); 1116 ASSERT(addr_dsc != NULL); 1117 ASSERT(target_name != NULL); 1118 ASSERT(addr_tgt != NULL); 1119 1120 /* setup initial buffer for configured session information */ 1121 size = sizeof (*ics); 1122 ics = kmem_zalloc(size, KM_SLEEP); 1123 ics->ics_in = 1; 1124 1125 /* get configured sessions information */ 1126 tmp = target_name; 1127 if (persistent_get_config_session(tmp, ics) == B_FALSE) { 1128 /* 1129 * No target information available check for 1130 * initiator information. 1131 */ 1132 tmp = (char *)ihp->hba_name; 1133 if (persistent_get_config_session(tmp, ics) == B_FALSE) { 1134 /* 1135 * No hba information is 1136 * found. So assume default 1137 * one session unbound behavior. 1138 */ 1139 ics->ics_out = 1; 1140 ics->ics_bound = B_TRUE; 1141 } 1142 } 1143 1144 if (iscsiboot_prop && (ics->ics_out > 1) && 1145 !iscsi_chk_bootlun_mpxio(ihp)) { 1146 /* 1147 * iscsi boot with mpxio disabled 1148 * no need to search configured boot session 1149 */ 1150 1151 if (iscsi_cmp_boot_ini_name(tmp) || 1152 iscsi_cmp_boot_tgt_name(tmp)) { 1153 ics->ics_out = 1; 1154 ics->ics_bound = B_FALSE; 1155 } 1156 } 1157 /* Check to see if we need to get more information */ 1158 if (ics->ics_out > 1) { 1159 /* record new size and free last buffer */ 1160 idx = ics->ics_out; 1161 size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out); 1162 kmem_free(ics, sizeof (*ics)); 1163 1164 /* allocate new buffer */ 1165 ics = kmem_zalloc(size, KM_SLEEP); 1166 ics->ics_in = idx; 1167 1168 /* get configured sessions information */ 1169 if (persistent_get_config_session(tmp, ics) != B_TRUE) { 1170 cmn_err(CE_NOTE, "iscsi session(%s) - " 1171 "unable to get configured session information\n", 1172 target_name); 1173 kmem_free(ics, size); 1174 return (B_FALSE); 1175 } 1176 } 1177 1178 /* loop for all configured sessions */ 1179 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 1180 for (isid = 0; isid < ics->ics_out; isid++) { 1181 /* create or find matching session */ 1182 isp = iscsi_sess_create(ihp, method, addr_dsc, target_name, 1183 tpgt, isid, ISCSI_SESS_TYPE_NORMAL, &oid); 1184 if (isp == NULL) { 1185 rtn = B_FALSE; 1186 break; 1187 } 1188 1189 /* create or find matching connection */ 1190 if (!ISCSI_SUCCESS(iscsi_conn_create(addr_tgt, isp, &icp))) { 1191 /* 1192 * Teardown the session we just created. It can't 1193 * have any luns or connections associated with it 1194 * so this should always succeed (luckily since what 1195 * would we do if it failed?) 1196 */ 1197 (void) iscsi_sess_destroy(isp); 1198 rtn = B_FALSE; 1199 break; 1200 } 1201 } 1202 rw_exit(&ihp->hba_sess_list_rwlock); 1203 kmem_free(ics, size); 1204 return (rtn); 1205 } 1206 1207 /* 1208 * iscsid_del - Attempts to delete all associated sessions 1209 */ 1210 boolean_t 1211 iscsid_del(iscsi_hba_t *ihp, char *target_name, 1212 iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc) 1213 { 1214 boolean_t rtn = B_TRUE; 1215 iscsi_status_t status; 1216 iscsi_sess_t *isp; 1217 char name[ISCSI_MAX_NAME_LEN]; 1218 1219 ASSERT(ihp != NULL); 1220 /* target name can be NULL or !NULL */ 1221 /* addr_dsc can be NULL or !NULL */ 1222 1223 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 1224 isp = ihp->hba_sess_list; 1225 while (isp != NULL) { 1226 /* 1227 * If no target_name is listed (meaning all targets) 1228 * or this specific target was listed. And the same 1229 * discovery method discovered this target then 1230 * continue evaulation. Otherwise fail. 1231 */ 1232 if (((target_name == NULL) || 1233 (strcmp((char *)isp->sess_name, target_name) == 0)) && 1234 (isp->sess_discovered_by == method)) { 1235 boolean_t try_destroy; 1236 1237 /* 1238 * If iSNS, SendTargets, or Static then special 1239 * handling for disc_addr. 1240 */ 1241 if ((method == iSCSIDiscoveryMethodISNS) || 1242 (method == iSCSIDiscoveryMethodSendTargets)) { 1243 /* 1244 * If NULL addr_dsc (meaning all disc_addr) 1245 * or matching discovered addr. 1246 */ 1247 if ((addr_dsc == NULL) || 1248 (bcmp(addr_dsc, &isp->sess_discovered_addr, 1249 SIZEOF_SOCKADDR( 1250 &isp->sess_discovered_addr.sin)) == 0)) { 1251 try_destroy = B_TRUE; 1252 } else { 1253 try_destroy = B_FALSE; 1254 } 1255 } else if (method == iSCSIDiscoveryMethodStatic) { 1256 /* 1257 * If NULL addr_dsc (meaning all disc_addr) 1258 * or matching active connection. 1259 */ 1260 if ((addr_dsc == NULL) || 1261 ((isp->sess_conn_act != NULL) && 1262 (bcmp(addr_dsc, 1263 &isp->sess_conn_act->conn_base_addr.sin, 1264 SIZEOF_SOCKADDR( 1265 &isp->sess_conn_act->conn_base_addr.sin)) 1266 == 0))) { 1267 try_destroy = B_TRUE; 1268 } else { 1269 try_destroy = B_FALSE; 1270 } 1271 } else { 1272 /* Unknown discovery specified */ 1273 try_destroy = B_TRUE; 1274 } 1275 1276 if (try_destroy == B_TRUE && 1277 isp->sess_boot == B_FALSE) { 1278 (void) strcpy(name, (char *)isp->sess_name); 1279 status = iscsi_sess_destroy(isp); 1280 if (ISCSI_SUCCESS(status)) { 1281 iscsid_remove_target_param(name); 1282 isp = ihp->hba_sess_list; 1283 } else if (status == ISCSI_STATUS_BUSY) { 1284 /* 1285 * The most likely destroy failure 1286 * is that ndi/mdi offline failed. 1287 * This means that the resource is 1288 * in_use/busy. 1289 */ 1290 cmn_err(CE_NOTE, "iscsi session(%d) - " 1291 "resource is in use\n", 1292 isp->sess_oid); 1293 isp = isp->sess_next; 1294 rtn = B_FALSE; 1295 } else { 1296 cmn_err(CE_NOTE, "iscsi session(%d) - " 1297 "session logout failed (%d)\n", 1298 isp->sess_oid, status); 1299 isp = isp->sess_next; 1300 rtn = B_FALSE; 1301 } 1302 } else { 1303 isp = isp->sess_next; 1304 } 1305 } else { 1306 isp = isp->sess_next; 1307 } 1308 } 1309 rw_exit(&ihp->hba_sess_list_rwlock); 1310 return (rtn); 1311 } 1312 1313 1314 /* 1315 * iscsid_login_tgt - request target(s) to login 1316 */ 1317 boolean_t 1318 iscsid_login_tgt(iscsi_hba_t *ihp, char *target_name, 1319 iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc) 1320 { 1321 boolean_t rtn = B_FALSE; 1322 iscsi_sess_t *isp = NULL; 1323 iscsi_sess_list_t *isp_list = NULL; 1324 iscsi_sess_list_t *last_sess = NULL; 1325 iscsi_sess_list_t *cur_sess = NULL; 1326 int total = 0; 1327 ddi_taskq_t *login_taskq = NULL; 1328 char taskq_name[ISCSI_TH_MAX_NAME_LEN] = {0}; 1329 time_t time_stamp; 1330 1331 ASSERT(ihp != NULL); 1332 1333 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 1334 /* Loop thru sessions */ 1335 isp = ihp->hba_sess_list; 1336 while (isp != NULL) { 1337 boolean_t try_online; 1338 if (!(method & iSCSIDiscoveryMethodBoot)) { 1339 if (target_name == NULL) { 1340 if (method == iSCSIDiscoveryMethodUnknown) { 1341 /* unknown method mean login to all */ 1342 try_online = B_TRUE; 1343 } else if (isp->sess_discovered_by & method) { 1344 if ((method == 1345 iSCSIDiscoveryMethodISNS) || 1346 (method == 1347 iSCSIDiscoveryMethodSendTargets)) { 1348 #define SESS_DISC_ADDR isp->sess_discovered_addr.sin 1349 if ((addr_dsc == NULL) || 1350 (bcmp( 1351 &isp->sess_discovered_addr, 1352 addr_dsc, SIZEOF_SOCKADDR( 1353 &SESS_DISC_ADDR)) 1354 == 0)) { 1355 /* 1356 * iSNS or sendtarget 1357 * discovery and 1358 * discovery address 1359 * is NULL or match 1360 */ 1361 try_online = B_TRUE; 1362 } else { 1363 /* addr_dsc not a match */ 1364 try_online = B_FALSE; 1365 } 1366 #undef SESS_DISC_ADDR 1367 } else { 1368 /* static configuration */ 1369 try_online = B_TRUE; 1370 } 1371 } else { 1372 /* method not a match */ 1373 try_online = B_FALSE; 1374 } 1375 } else if (strcmp(target_name, 1376 (char *)isp->sess_name) == 0) { 1377 /* target_name match */ 1378 try_online = B_TRUE; 1379 } else { 1380 /* target_name not a match */ 1381 try_online = B_FALSE; 1382 } 1383 } else { 1384 /* 1385 * online the boot session. 1386 */ 1387 if (isp->sess_boot == B_TRUE) { 1388 try_online = B_TRUE; 1389 } 1390 } 1391 1392 if (try_online == B_TRUE && 1393 isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 1394 total++; 1395 /* Copy these sessions to the list. */ 1396 if (isp_list == NULL) { 1397 isp_list = 1398 (iscsi_sess_list_t *)kmem_zalloc( 1399 sizeof (iscsi_sess_list_t), KM_SLEEP); 1400 last_sess = isp_list; 1401 last_sess->session = isp; 1402 last_sess->next = NULL; 1403 } else { 1404 last_sess->next = 1405 (iscsi_sess_list_t *)kmem_zalloc( 1406 sizeof (iscsi_sess_list_t), KM_SLEEP); 1407 last_sess->next->session = isp; 1408 last_sess->next->next = NULL; 1409 last_sess = last_sess->next; 1410 } 1411 rtn = B_TRUE; 1412 } 1413 1414 isp = isp->sess_next; 1415 } 1416 1417 if (total > 0) { 1418 time_stamp = ddi_get_time(); 1419 (void) snprintf(taskq_name, (ISCSI_TH_MAX_NAME_LEN - 1), 1420 "login_queue.%lx", time_stamp); 1421 1422 login_taskq = ddi_taskq_create(ihp->hba_dip, 1423 taskq_name, total, TASKQ_DEFAULTPRI, 0); 1424 if (login_taskq == NULL) { 1425 while (isp_list != NULL) { 1426 cur_sess = isp_list; 1427 isp_list = isp_list->next; 1428 kmem_free(cur_sess, sizeof (iscsi_sess_list_t)); 1429 } 1430 rtn = B_FALSE; 1431 rw_exit(&ihp->hba_sess_list_rwlock); 1432 return (rtn); 1433 } 1434 1435 for (cur_sess = isp_list; cur_sess != NULL; 1436 cur_sess = cur_sess->next) { 1437 if (ddi_taskq_dispatch(login_taskq, 1438 iscsi_sess_online, (void *)cur_sess->session, 1439 DDI_SLEEP) != DDI_SUCCESS) { 1440 cmn_err(CE_NOTE, "Can't dispatch the task " 1441 "for login to the target: %s", 1442 cur_sess->session->sess_name); 1443 } 1444 } 1445 1446 ddi_taskq_wait(login_taskq); 1447 ddi_taskq_destroy(login_taskq); 1448 while (isp_list != NULL) { 1449 cur_sess = isp_list; 1450 isp_list = isp_list->next; 1451 kmem_free(cur_sess, sizeof (iscsi_sess_list_t)); 1452 } 1453 1454 } 1455 1456 rw_exit(&ihp->hba_sess_list_rwlock); 1457 return (rtn); 1458 } 1459 1460 /* 1461 * +--------------------------------------------------------------------+ 1462 * | Local Helper Functions | 1463 * +--------------------------------------------------------------------+ 1464 */ 1465 1466 /* 1467 * iscsid_init_config -- initialize configuration parameters of iSCSI initiator 1468 */ 1469 static boolean_t 1470 iscsid_init_config(iscsi_hba_t *ihp) 1471 { 1472 iscsi_param_set_t ips; 1473 void *v = NULL; 1474 char *name; 1475 char *initiatorName; 1476 persistent_param_t pp; 1477 persistent_tunable_param_t pparam; 1478 uint32_t param_id; 1479 int rc; 1480 1481 /* allocate memory to hold initiator names */ 1482 initiatorName = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1483 1484 /* 1485 * initialize iSCSI initiator name 1486 */ 1487 bzero(&ips, sizeof (ips)); 1488 if (persistent_initiator_name_get(initiatorName, 1489 ISCSI_MAX_NAME_LEN) == B_TRUE) { 1490 ips.s_vers = ISCSI_INTERFACE_VERSION; 1491 ips.s_param = ISCSI_LOGIN_PARAM_INITIATOR_NAME; 1492 1493 if (iscsiboot_prop && !iscsi_cmp_boot_ini_name(initiatorName)) { 1494 (void) strncpy(initiatorName, 1495 (const char *)iscsiboot_prop->boot_init.ini_name, 1496 ISCSI_MAX_NAME_LEN); 1497 (void) strncpy((char *)ips.s_value.v_name, 1498 (const char *)iscsiboot_prop->boot_init.ini_name, 1499 sizeof (ips.s_value.v_name)); 1500 (void) iscsi_set_params(&ips, ihp, B_TRUE); 1501 /* use default tunable value */ 1502 ihp->hba_tunable_params.recv_login_rsp_timeout = 1503 ISCSI_DEFAULT_RX_TIMEOUT_VALUE; 1504 ihp->hba_tunable_params.polling_login_delay = 1505 ISCSI_DEFAULT_LOGIN_POLLING_DELAY; 1506 ihp->hba_tunable_params.conn_login_max = 1507 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX; 1508 cmn_err(CE_NOTE, "Set initiator's name" 1509 " from firmware"); 1510 } else { 1511 (void) strncpy((char *)ips.s_value.v_name, 1512 initiatorName, sizeof (ips.s_value.v_name)); 1513 1514 (void) iscsi_set_params(&ips, ihp, B_FALSE); 1515 if (persistent_get_tunable_param(initiatorName, 1516 &pparam) == B_FALSE) { 1517 /* use default value */ 1518 pparam.p_params.recv_login_rsp_timeout = 1519 ISCSI_DEFAULT_RX_TIMEOUT_VALUE; 1520 pparam.p_params.polling_login_delay = 1521 ISCSI_DEFAULT_LOGIN_POLLING_DELAY; 1522 pparam.p_params.conn_login_max = 1523 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX; 1524 } 1525 bcopy(&pparam.p_params, &ihp->hba_tunable_params, 1526 sizeof (iscsi_tunable_params_t)); 1527 } 1528 } else { 1529 /* 1530 * if no initiator-node name available it is most 1531 * likely due to a fresh install, or the persistent 1532 * store is not working correctly. Set 1533 * a default initiator name so that the initiator can 1534 * be brought up properly. 1535 */ 1536 iscsid_set_default_initiator_node_settings(ihp, B_FALSE); 1537 (void) strncpy(initiatorName, (const char *)ihp->hba_name, 1538 ISCSI_MAX_NAME_LEN); 1539 } 1540 1541 /* 1542 * initialize iSCSI initiator alias (if any) 1543 */ 1544 bzero(&ips, sizeof (ips)); 1545 if (persistent_alias_name_get((char *)ips.s_value.v_name, 1546 sizeof (ips.s_value.v_name)) == B_TRUE) { 1547 ips.s_param = ISCSI_LOGIN_PARAM_INITIATOR_ALIAS; 1548 (void) iscsi_set_params(&ips, ihp, B_FALSE); 1549 } else { 1550 /* EMPTY */ 1551 /* No alias defined - not a problem. */ 1552 } 1553 1554 /* 1555 * load up the overriden iSCSI initiator parameters 1556 */ 1557 name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1558 persistent_param_lock(); 1559 v = NULL; 1560 while (persistent_param_next(&v, name, &pp) == B_TRUE) { 1561 if (strncmp(name, initiatorName, ISCSI_MAX_NAME_LEN) == 0) { 1562 ips.s_oid = ihp->hba_oid; 1563 ips.s_vers = ISCSI_INTERFACE_VERSION; 1564 for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM; 1565 param_id++) { 1566 if (pp.p_bitmap & (1 << param_id)) { 1567 rc = iscsid_copyto_param_set(param_id, 1568 &pp.p_params, &ips); 1569 if (rc == 0) { 1570 rc = iscsi_set_params(&ips, 1571 ihp, B_FALSE); 1572 } 1573 if (rc != 0) { 1574 /* note error but continue */ 1575 cmn_err(CE_NOTE, 1576 "Failed to set " 1577 "param %d for OID %d", 1578 ips.s_param, ips.s_oid); 1579 } 1580 } 1581 } /* END for() */ 1582 if (iscsiboot_prop && 1583 iscsi_chk_bootlun_mpxio(ihp)) { 1584 (void) iscsi_reconfig_boot_sess(ihp); 1585 } 1586 break; 1587 } 1588 } /* END while() */ 1589 persistent_param_unlock(); 1590 1591 kmem_free(initiatorName, ISCSI_MAX_NAME_LEN); 1592 kmem_free(name, ISCSI_MAX_NAME_LEN); 1593 return (B_TRUE); 1594 } 1595 1596 1597 /* 1598 * iscsid_init_targets -- Load up the driver with known static targets and 1599 * targets whose parameters have been modified. 1600 * 1601 * This is done so that the CLI can find a list of targets the driver 1602 * currently knows about. 1603 * 1604 * The driver doesn't need to log into these targets. Log in is done based 1605 * upon the enabled discovery methods. 1606 */ 1607 static boolean_t 1608 iscsid_init_targets(iscsi_hba_t *ihp) 1609 { 1610 void *v = NULL; 1611 char *name; 1612 iscsi_param_set_t ips; 1613 persistent_param_t pp; 1614 char *iname; 1615 uint32_t param_id; 1616 int rc; 1617 1618 ASSERT(ihp != NULL); 1619 1620 /* allocate memory to hold target names */ 1621 name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1622 1623 /* 1624 * load up targets whose parameters have been overriden 1625 */ 1626 1627 /* ---- only need to be set once ---- */ 1628 bzero(&ips, sizeof (ips)); 1629 ips.s_vers = ISCSI_INTERFACE_VERSION; 1630 1631 /* allocate memory to hold initiator name */ 1632 iname = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1633 (void) persistent_initiator_name_get(iname, ISCSI_MAX_NAME_LEN); 1634 1635 persistent_param_lock(); 1636 v = NULL; 1637 while (persistent_param_next(&v, name, &pp) == B_TRUE) { 1638 1639 if (strncmp(iname, name, ISCSI_MAX_NAME_LEN) == 0) { 1640 /* 1641 * target name matched initiator's name so, 1642 * continue to next target. Initiator's 1643 * parmeters have already been set. 1644 */ 1645 continue; 1646 } 1647 1648 if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) && 1649 !iscsi_chk_bootlun_mpxio(ihp)) { 1650 /* 1651 * boot target is not mpxio enabled 1652 * simply ignore these overriden parameters 1653 */ 1654 continue; 1655 } 1656 1657 ips.s_oid = iscsi_targetparam_get_oid((unsigned char *)name); 1658 1659 for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM; 1660 param_id++) { 1661 if (pp.p_bitmap & (1 << param_id)) { 1662 rc = iscsid_copyto_param_set(param_id, 1663 &pp.p_params, &ips); 1664 if (rc == 0) { 1665 rc = iscsi_set_params(&ips, 1666 ihp, B_FALSE); 1667 } 1668 if (rc != 0) { 1669 /* note error but continue ---- */ 1670 cmn_err(CE_NOTE, "Failed to set " 1671 "param %d for OID %d", 1672 ips.s_param, ips.s_oid); 1673 } 1674 } 1675 } /* END for() */ 1676 if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) && 1677 iscsi_chk_bootlun_mpxio(ihp)) { 1678 (void) iscsi_reconfig_boot_sess(ihp); 1679 } 1680 } /* END while() */ 1681 persistent_param_unlock(); 1682 1683 kmem_free(iname, ISCSI_MAX_NAME_LEN); 1684 kmem_free(name, ISCSI_MAX_NAME_LEN); 1685 1686 return (B_TRUE); 1687 } 1688 1689 1690 /* 1691 * iscsid_thread_static -- If static discovery is enabled, this routine obtains 1692 * all statically configured targets from the peristent store and issues a 1693 * login request to the driver. 1694 */ 1695 /* ARGSUSED */ 1696 static void 1697 iscsid_thread_static(iscsi_thread_t *thread, void *p) 1698 { 1699 iSCSIDiscoveryMethod_t dm; 1700 entry_t entry; 1701 char name[ISCSI_MAX_NAME_LEN]; 1702 void *v = NULL; 1703 iscsi_hba_t *ihp = (iscsi_hba_t *)p; 1704 1705 while (iscsi_thread_wait(thread, -1) != 0) { 1706 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_TRUE); 1707 1708 /* ---- ensure static target discovery is enabled ---- */ 1709 dm = persistent_disc_meth_get(); 1710 if ((dm & iSCSIDiscoveryMethodStatic) == 0) { 1711 cmn_err(CE_NOTE, 1712 "iscsi discovery failure - " 1713 "StaticTargets method is not enabled"); 1714 iscsi_discovery_event(ihp, 1715 iSCSIDiscoveryMethodStatic, B_FALSE); 1716 continue; 1717 } 1718 1719 /* 1720 * walk list of the statically configured targets from the 1721 * persistent store 1722 */ 1723 v = NULL; 1724 persistent_static_addr_lock(); 1725 while (persistent_static_addr_next(&v, name, &entry) == 1726 B_TRUE) { 1727 iscsi_sockaddr_t addr; 1728 1729 iscsid_addr_to_sockaddr(entry.e_insize, 1730 &(entry.e_u), entry.e_port, &addr.sin); 1731 1732 (void) iscsid_add(ihp, iSCSIDiscoveryMethodStatic, 1733 &addr.sin, name, entry.e_tpgt, &addr.sin); 1734 } 1735 persistent_static_addr_unlock(); 1736 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_FALSE); 1737 } 1738 } 1739 1740 1741 /* 1742 * iscsid_thread_sendtgts -- If SendTargets discovery is enabled, this routine 1743 * obtains all target discovery addresses configured from the peristent store 1744 * and probe the IP/port addresses for possible targets. It will then issue 1745 * a login request to the driver for all discoveryed targets. 1746 */ 1747 static void 1748 iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p) 1749 { 1750 iscsi_hba_t *ihp = (iscsi_hba_t *)p; 1751 iSCSIDiscoveryMethod_t dm; 1752 entry_t entry; 1753 void *v = NULL; 1754 1755 while (iscsi_thread_wait(thread, -1) != 0) { 1756 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets, 1757 B_TRUE); 1758 1759 /* ---- ensure SendTargets discovery is enabled ---- */ 1760 dm = persistent_disc_meth_get(); 1761 if ((dm & iSCSIDiscoveryMethodSendTargets) == 0) { 1762 cmn_err(CE_NOTE, 1763 "iscsi discovery failure - " 1764 "SendTargets method is not enabled"); 1765 iscsi_discovery_event(ihp, 1766 iSCSIDiscoveryMethodSendTargets, B_FALSE); 1767 continue; 1768 } 1769 /* 1770 * walk list of the SendTarget discovery addresses from the 1771 * persistent store 1772 */ 1773 v = NULL; 1774 persistent_disc_addr_lock(); 1775 while (persistent_disc_addr_next(&v, &entry) == B_TRUE) { 1776 iscsid_do_sendtgts(&entry); 1777 } 1778 persistent_disc_addr_unlock(); 1779 1780 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets, 1781 B_FALSE); 1782 } 1783 } 1784 1785 /* 1786 * iscsid_thread_slp -- If SLP discovery is enabled, this routine provides 1787 * the SLP discovery service. 1788 */ 1789 static void 1790 iscsid_thread_slp(iscsi_thread_t *thread, void *p) 1791 { 1792 iscsi_hba_t *ihp = (iscsi_hba_t *)p; 1793 1794 do { 1795 /* 1796 * Even though we don't have support for SLP at this point 1797 * we'll send the events if someone has enabled this thread. 1798 * If this is not done the daemon waiting for discovery to 1799 * complete will pause forever holding up the boot process. 1800 */ 1801 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_TRUE); 1802 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_FALSE); 1803 } while (iscsi_thread_wait(thread, -1) != 0); 1804 } 1805 1806 /* 1807 * iscsid_thread_isns -- 1808 */ 1809 static void 1810 iscsid_thread_isns(iscsi_thread_t *thread, void *ptr) 1811 { 1812 iscsi_hba_t *ihp = (iscsi_hba_t *)ptr; 1813 iSCSIDiscoveryMethod_t dm; 1814 1815 while (iscsi_thread_wait(thread, -1) != 0) { 1816 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_TRUE); 1817 1818 /* ---- ensure iSNS discovery is enabled ---- */ 1819 dm = persistent_disc_meth_get(); 1820 if ((dm & iSCSIDiscoveryMethodISNS) == 0) { 1821 cmn_err(CE_NOTE, 1822 "iscsi discovery failure - " 1823 "iSNS method is not enabled"); 1824 iscsi_discovery_event(ihp, 1825 iSCSIDiscoveryMethodISNS, B_FALSE); 1826 continue; 1827 } 1828 1829 (void) isns_reg(ihp->hba_isid, 1830 ihp->hba_name, 1831 ISCSI_MAX_NAME_LEN, 1832 ihp->hba_alias, 1833 ISCSI_MAX_NAME_LEN, 1834 ISNS_INITIATOR_NODE_TYPE, 1835 isns_scn_callback); 1836 iscsid_do_isns_query(ihp); 1837 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_FALSE); 1838 } 1839 1840 /* Thread stopped. Deregister from iSNS servers(s). */ 1841 (void) isns_dereg(ihp->hba_isid, ihp->hba_name); 1842 } 1843 1844 1845 /* 1846 * iscsid_threads_create -- Creates all the discovery threads. 1847 */ 1848 static void 1849 iscsid_threads_create(iscsi_hba_t *ihp) 1850 { 1851 iscsid_thr_table *t; 1852 1853 /* 1854 * start a thread for each discovery method 1855 */ 1856 for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown; 1857 t++) { 1858 if (t->thr_id == NULL) { 1859 t->thr_id = iscsi_thread_create(ihp->hba_dip, t->name, 1860 t->func_start, ihp); 1861 } 1862 } 1863 } 1864 1865 /* 1866 * iscsid_threads_destroy -- Destroys all the discovery threads. 1867 */ 1868 static void 1869 iscsid_threads_destroy(void) 1870 { 1871 iscsid_thr_table *t; 1872 1873 for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown; 1874 t++) { 1875 if (t->thr_id != NULL) { 1876 iscsi_thread_destroy(t->thr_id); 1877 t->thr_id = NULL; 1878 } 1879 } 1880 } 1881 1882 /* 1883 * iscsid_copyto_param_set - helper function for iscsid_init_params. 1884 */ 1885 static int 1886 iscsid_copyto_param_set(uint32_t param_id, iscsi_login_params_t *params, 1887 iscsi_param_set_t *ipsp) 1888 { 1889 int rtn = 0; 1890 1891 if (param_id >= ISCSI_NUM_LOGIN_PARAM) { 1892 return (EINVAL); 1893 } 1894 1895 switch (param_id) { 1896 1897 /* 1898 * Boolean parameters 1899 */ 1900 case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER: 1901 ipsp->s_value.v_bool = params->data_pdu_in_order; 1902 break; 1903 case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA: 1904 ipsp->s_value.v_bool = params->immediate_data; 1905 break; 1906 case ISCSI_LOGIN_PARAM_INITIAL_R2T: 1907 ipsp->s_value.v_bool = params->initial_r2t; 1908 break; 1909 case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER: 1910 ipsp->s_value.v_bool = params->data_pdu_in_order; 1911 break; 1912 1913 /* 1914 * Integer parameters 1915 */ 1916 case ISCSI_LOGIN_PARAM_HEADER_DIGEST: 1917 ipsp->s_value.v_integer = params->header_digest; 1918 break; 1919 case ISCSI_LOGIN_PARAM_DATA_DIGEST: 1920 ipsp->s_value.v_integer = params->data_digest; 1921 break; 1922 case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN: 1923 ipsp->s_value.v_integer = params->default_time_to_retain; 1924 break; 1925 case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT: 1926 ipsp->s_value.v_integer = params->default_time_to_wait; 1927 break; 1928 case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH: 1929 ipsp->s_value.v_integer = params->max_recv_data_seg_len; 1930 break; 1931 case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH: 1932 ipsp->s_value.v_integer = params->first_burst_length; 1933 break; 1934 case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH: 1935 ipsp->s_value.v_integer = params->max_burst_length; 1936 break; 1937 1938 /* 1939 * Integer parameters which currently are unsettable 1940 */ 1941 case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS: 1942 case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T: 1943 case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL: 1944 /* ---- drop through to default case ---- */ 1945 default: 1946 rtn = EINVAL; 1947 break; 1948 } 1949 1950 /* if all is well, set the parameter identifier */ 1951 if (rtn == 0) { 1952 ipsp->s_param = param_id; 1953 } 1954 1955 return (rtn); 1956 } 1957 1958 /* 1959 * iscsid_add_pg_list_to_cache - Add portal groups in the list to the 1960 * discovery cache. 1961 */ 1962 static void 1963 iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp, 1964 isns_portal_group_list_t *pg_list) 1965 { 1966 int i; 1967 1968 for (i = 0; i < pg_list->pg_out_cnt; i++) { 1969 iscsi_sockaddr_t addr_dsc; 1970 iscsi_sockaddr_t addr_tgt; 1971 1972 iscsid_addr_to_sockaddr( 1973 pg_list->pg_list[i].isns_server_ip.i_insize, 1974 &pg_list->pg_list[i].isns_server_ip.i_addr, 1975 pg_list->pg_list[i].isns_server_port, 1976 &addr_dsc.sin); 1977 iscsid_addr_to_sockaddr( 1978 pg_list->pg_list[i].insize, 1979 &pg_list->pg_list[i].pg_ip_addr, 1980 pg_list->pg_list[i].pg_port, 1981 &addr_tgt.sin); 1982 1983 (void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS, &addr_dsc.sin, 1984 (char *)pg_list->pg_list[i].pg_iscsi_name, 1985 pg_list->pg_list[i].pg_tag, &addr_tgt.sin); 1986 } 1987 } 1988 1989 /* 1990 * set_initiator_name - set default initiator name and alias. 1991 * 1992 * This sets the default initiator name and alias. The 1993 * initiator name is composed of sun's reverse domain name 1994 * and registration followed and a unique classifier. This 1995 * classifier is the mac address of the first NIC in the 1996 * host and a timestamp to make sure the classifier is 1997 * unique if the NIC is moved between hosts. The alias 1998 * is just the hostname. 1999 */ 2000 void 2001 iscsid_set_default_initiator_node_settings(iscsi_hba_t *ihp, boolean_t minimal) 2002 { 2003 int i; 2004 time_t x; 2005 struct ether_addr eaddr; 2006 char val[10]; 2007 iscsi_chap_props_t *chap = NULL; 2008 2009 /* Set default initiator-node name */ 2010 if (iscsiboot_prop && iscsiboot_prop->boot_init.ini_name != NULL) { 2011 (void) strncpy((char *)ihp->hba_name, 2012 (const char *)iscsiboot_prop->boot_init.ini_name, 2013 ISCSI_MAX_NAME_LEN); 2014 } else { 2015 (void) snprintf((char *)ihp->hba_name, 2016 ISCSI_MAX_NAME_LEN, 2017 "iqn.1986-03.com.sun:01:"); 2018 2019 (void) localetheraddr(NULL, &eaddr); 2020 for (i = 0; i < ETHERADDRL; i++) { 2021 (void) snprintf(val, sizeof (val), "%02x", 2022 eaddr.ether_addr_octet[i]); 2023 (void) strncat((char *)ihp->hba_name, val, 2024 ISCSI_MAX_NAME_LEN); 2025 } 2026 2027 /* Set default initiator-node alias */ 2028 x = ddi_get_time(); 2029 (void) snprintf(val, sizeof (val), ".%lx", x); 2030 (void) strncat((char *)ihp->hba_name, val, ISCSI_MAX_NAME_LEN); 2031 2032 if (ihp->hba_alias[0] == '\0') { 2033 (void) strncpy((char *)ihp->hba_alias, 2034 utsname.nodename, ISCSI_MAX_NAME_LEN); 2035 ihp->hba_alias_length = strlen((char *)ihp->hba_alias); 2036 if (minimal == B_FALSE) { 2037 (void) persistent_alias_name_set( 2038 (char *)ihp->hba_alias); 2039 } 2040 } 2041 } 2042 2043 if (minimal == B_TRUE) { 2044 return; 2045 } 2046 2047 (void) persistent_initiator_name_set((char *)ihp->hba_name); 2048 2049 /* Set default initiator-node CHAP settings */ 2050 if (persistent_initiator_name_get((char *)ihp->hba_name, 2051 ISCSI_MAX_NAME_LEN) == B_TRUE) { 2052 chap = (iscsi_chap_props_t *)kmem_zalloc(sizeof (*chap), 2053 KM_SLEEP); 2054 if (persistent_chap_get((char *)ihp->hba_name, chap) == 2055 B_FALSE) { 2056 bcopy((char *)ihp->hba_name, chap->c_user, 2057 strlen((char *)ihp->hba_name)); 2058 chap->c_user_len = strlen((char *)ihp->hba_name); 2059 (void) persistent_chap_set((char *)ihp->hba_name, chap); 2060 } 2061 kmem_free(chap, sizeof (*chap)); 2062 } 2063 } 2064 2065 static void 2066 iscsid_remove_target_param(char *name) 2067 { 2068 persistent_param_t *pparam; 2069 uint32_t t_oid; 2070 iscsi_config_sess_t *ics; 2071 2072 ASSERT(name != NULL); 2073 2074 /* 2075 * Remove target-param <-> target mapping. 2076 * Only remove if there is not any overridden 2077 * parameters in the persistent store 2078 */ 2079 pparam = (persistent_param_t *)kmem_zalloc(sizeof (*pparam), KM_SLEEP); 2080 2081 /* 2082 * setup initial buffer for configured session 2083 * information 2084 */ 2085 ics = (iscsi_config_sess_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP); 2086 ics->ics_in = 1; 2087 2088 if ((persistent_param_get(name, pparam) == B_FALSE) && 2089 (persistent_get_config_session(name, ics) == B_FALSE)) { 2090 t_oid = iscsi_targetparam_get_oid((uchar_t *)name); 2091 (void) iscsi_targetparam_remove_target(t_oid); 2092 } 2093 2094 kmem_free(pparam, sizeof (*pparam)); 2095 pparam = NULL; 2096 kmem_free(ics, sizeof (*ics)); 2097 ics = NULL; 2098 } 2099 2100 /* 2101 * iscsid_addr_to_sockaddr - convert other types to struct sockaddr 2102 */ 2103 void 2104 iscsid_addr_to_sockaddr(int src_insize, void *src_addr, int src_port, 2105 struct sockaddr *dst_addr) 2106 { 2107 ASSERT((src_insize == sizeof (struct in_addr)) || 2108 (src_insize == sizeof (struct in6_addr))); 2109 ASSERT(src_addr != NULL); 2110 ASSERT(dst_addr != NULL); 2111 2112 bzero(dst_addr, sizeof (*dst_addr)); 2113 2114 /* translate discovery information */ 2115 if (src_insize == sizeof (struct in_addr)) { 2116 struct sockaddr_in *addr_in = 2117 (struct sockaddr_in *)dst_addr; 2118 addr_in->sin_family = AF_INET; 2119 bcopy(src_addr, &addr_in->sin_addr.s_addr, 2120 sizeof (struct in_addr)); 2121 addr_in->sin_port = htons(src_port); 2122 } else { 2123 struct sockaddr_in6 *addr_in6 = 2124 (struct sockaddr_in6 *)dst_addr; 2125 addr_in6->sin6_family = AF_INET6; 2126 bcopy(src_addr, &addr_in6->sin6_addr.s6_addr, 2127 sizeof (struct in6_addr)); 2128 addr_in6->sin6_port = htons(src_port); 2129 } 2130 } 2131 2132 /* 2133 * iscsi_discovery_event -- send event associated with discovery operations 2134 * 2135 * Each discovery event has a start and end event. Which is sent is based 2136 * on the boolean argument start with the obvious results. 2137 */ 2138 static void 2139 iscsi_discovery_event(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t m, 2140 boolean_t start) 2141 { 2142 char *subclass = NULL; 2143 2144 mutex_enter(&ihp->hba_discovery_events_mutex); 2145 switch (m) { 2146 case iSCSIDiscoveryMethodStatic: 2147 if (start == B_TRUE) { 2148 subclass = ESC_ISCSI_STATIC_START; 2149 } else { 2150 ihp->hba_discovery_events |= iSCSIDiscoveryMethodStatic; 2151 subclass = ESC_ISCSI_STATIC_END; 2152 } 2153 break; 2154 2155 case iSCSIDiscoveryMethodSendTargets: 2156 if (start == B_TRUE) { 2157 subclass = ESC_ISCSI_SEND_TARGETS_START; 2158 } else { 2159 ihp->hba_discovery_events |= 2160 iSCSIDiscoveryMethodSendTargets; 2161 subclass = ESC_ISCSI_SEND_TARGETS_END; 2162 } 2163 break; 2164 2165 case iSCSIDiscoveryMethodSLP: 2166 if (start == B_TRUE) { 2167 subclass = ESC_ISCSI_SLP_START; 2168 } else { 2169 ihp->hba_discovery_events |= iSCSIDiscoveryMethodSLP; 2170 subclass = ESC_ISCSI_SLP_END; 2171 } 2172 break; 2173 2174 case iSCSIDiscoveryMethodISNS: 2175 if (start == B_TRUE) { 2176 subclass = ESC_ISCSI_ISNS_START; 2177 } else { 2178 ihp->hba_discovery_events |= iSCSIDiscoveryMethodISNS; 2179 subclass = ESC_ISCSI_ISNS_END; 2180 } 2181 break; 2182 } 2183 mutex_exit(&ihp->hba_discovery_events_mutex); 2184 iscsi_send_sysevent(ihp, EC_ISCSI, subclass, NULL); 2185 } 2186 2187 /* 2188 * iscsi_send_sysevent -- send sysevent using specified class 2189 */ 2190 void 2191 iscsi_send_sysevent( 2192 iscsi_hba_t *ihp, 2193 char *eventclass, 2194 char *subclass, 2195 nvlist_t *np) 2196 { 2197 (void) ddi_log_sysevent(ihp->hba_dip, DDI_VENDOR_SUNW, eventclass, 2198 subclass, np, NULL, DDI_SLEEP); 2199 } 2200 2201 static boolean_t 2202 iscsid_boot_init_config(iscsi_hba_t *ihp) 2203 { 2204 if (strlen((const char *)iscsiboot_prop->boot_init.ini_name) != 0) { 2205 bcopy(iscsiboot_prop->boot_init.ini_name, 2206 ihp->hba_name, 2207 strlen((const char *)iscsiboot_prop->boot_init.ini_name)); 2208 } 2209 /* or using default login param for boot session */ 2210 return (B_TRUE); 2211 } 2212 2213 boolean_t 2214 iscsi_reconfig_boot_sess(iscsi_hba_t *ihp) 2215 { 2216 iscsi_config_sess_t *ics; 2217 int idx; 2218 iscsi_sess_t *isp, *t_isp; 2219 int isid, size; 2220 char *name; 2221 boolean_t rtn = B_TRUE; 2222 uint32_t event_count; 2223 2224 if (iscsiboot_prop == NULL) { 2225 return (B_FALSE); 2226 } 2227 size = sizeof (*ics); 2228 ics = kmem_zalloc(size, KM_SLEEP); 2229 ics->ics_in = 1; 2230 2231 /* get information of number of sessions to be configured */ 2232 name = (char *)iscsiboot_prop->boot_tgt.tgt_name; 2233 if (persistent_get_config_session(name, ics) == B_FALSE) { 2234 /* 2235 * No target information available to check 2236 * initiator information. Assume one session 2237 * by default. 2238 */ 2239 name = (char *)iscsiboot_prop->boot_init.ini_name; 2240 if (persistent_get_config_session(name, ics) == B_FALSE) { 2241 ics->ics_out = 1; 2242 ics->ics_bound = B_TRUE; 2243 } 2244 } 2245 2246 /* get necessary information */ 2247 if (ics->ics_out > 1) { 2248 idx = ics->ics_out; 2249 size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out); 2250 kmem_free(ics, sizeof (*ics)); 2251 2252 ics = kmem_zalloc(size, KM_SLEEP); 2253 ics->ics_in = idx; 2254 2255 /* get configured sessions information */ 2256 if (persistent_get_config_session((char *)name, 2257 ics) != B_TRUE) { 2258 cmn_err(CE_NOTE, "session(%s) - " 2259 "failed to setup multiple sessions", 2260 name); 2261 kmem_free(ics, size); 2262 return (B_FALSE); 2263 } 2264 } 2265 2266 /* create a temporary session to keep boot session connective */ 2267 t_isp = iscsi_add_boot_sess(ihp, ISCSI_MAX_CONFIG_SESSIONS); 2268 if (t_isp == NULL) { 2269 cmn_err(CE_NOTE, "session(%s) - " 2270 "failed to setup multiple sessions", name); 2271 rw_exit(&ihp->hba_sess_list_rwlock); 2272 kmem_free(ics, size); 2273 return (B_FALSE); 2274 } 2275 2276 /* destroy all old boot sessions */ 2277 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 2278 isp = ihp->hba_sess_list; 2279 while (isp != NULL) { 2280 if (iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) { 2281 if (isp->sess_isid[5] != ISCSI_MAX_CONFIG_SESSIONS) { 2282 /* 2283 * destroy all stale sessions 2284 * except temporary boot session 2285 */ 2286 if (ISCSI_SUCCESS(iscsi_sess_destroy( 2287 isp))) { 2288 isp = ihp->hba_sess_list; 2289 } else { 2290 /* 2291 * couldn't destroy stale sessions 2292 * at least poke it to disconnect 2293 */ 2294 event_count = atomic_inc_32_nv( 2295 &isp->sess_state_event_count); 2296 iscsi_sess_enter_state_zone(isp); 2297 iscsi_sess_state_machine(isp, 2298 ISCSI_SESS_EVENT_N7, event_count); 2299 iscsi_sess_exit_state_zone(isp); 2300 2301 isp = isp->sess_next; 2302 cmn_err(CE_NOTE, "session(%s) - " 2303 "failed to setup multiple" 2304 " sessions", name); 2305 } 2306 } else { 2307 isp = isp->sess_next; 2308 } 2309 } else { 2310 isp = isp->sess_next; 2311 } 2312 } 2313 rw_exit(&ihp->hba_sess_list_rwlock); 2314 2315 for (isid = 0; isid < ics->ics_out; isid++) { 2316 isp = iscsi_add_boot_sess(ihp, isid); 2317 if (isp == NULL) { 2318 cmn_err(CE_NOTE, "session(%s) - failed to setup" 2319 " multiple sessions", name); 2320 rtn = B_FALSE; 2321 break; 2322 } 2323 } 2324 if (!rtn && (isid == 0)) { 2325 /* 2326 * fail to create any new boot session 2327 * so only the temporary session is alive 2328 * quit without destroying it 2329 */ 2330 kmem_free(ics, size); 2331 return (rtn); 2332 } 2333 2334 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 2335 if (!ISCSI_SUCCESS(iscsi_sess_destroy(t_isp))) { 2336 /* couldn't destroy temp boot session */ 2337 cmn_err(CE_NOTE, "session(%s) - " 2338 "failed to setup multiple sessions", name); 2339 rw_exit(&ihp->hba_sess_list_rwlock); 2340 rtn = B_FALSE; 2341 } 2342 rw_exit(&ihp->hba_sess_list_rwlock); 2343 2344 kmem_free(ics, size); 2345 return (rtn); 2346 } 2347 2348 static iscsi_sess_t * 2349 iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid) 2350 { 2351 iscsi_sess_t *isp; 2352 iscsi_conn_t *icp; 2353 uint_t oid; 2354 2355 iscsi_sockaddr_t addr_dst; 2356 2357 addr_dst.sin.sa_family = iscsiboot_prop->boot_tgt.sin_family; 2358 if (addr_dst.sin.sa_family == AF_INET) { 2359 bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in4.s_addr, 2360 &addr_dst.sin4.sin_addr.s_addr, sizeof (struct in_addr)); 2361 addr_dst.sin4.sin_port = 2362 htons(iscsiboot_prop->boot_tgt.tgt_port); 2363 } else { 2364 bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in6.s6_addr, 2365 &addr_dst.sin6.sin6_addr.s6_addr, 2366 sizeof (struct in6_addr)); 2367 addr_dst.sin6.sin6_port = 2368 htons(iscsiboot_prop->boot_tgt.tgt_port); 2369 } 2370 2371 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 2372 isp = iscsi_sess_create(ihp, 2373 iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic, 2374 (struct sockaddr *)&addr_dst, 2375 (char *)iscsiboot_prop->boot_tgt.tgt_name, 2376 ISCSI_DEFAULT_TPGT, isid, ISCSI_SESS_TYPE_NORMAL, &oid); 2377 if (isp == NULL) { 2378 /* create temp booting session failed */ 2379 rw_exit(&ihp->hba_sess_list_rwlock); 2380 return (NULL); 2381 } 2382 isp->sess_boot = B_TRUE; 2383 2384 if (!ISCSI_SUCCESS(iscsi_conn_create((struct sockaddr *)&addr_dst, 2385 isp, &icp))) { 2386 rw_exit(&ihp->hba_sess_list_rwlock); 2387 return (NULL); 2388 } 2389 2390 rw_exit(&ihp->hba_sess_list_rwlock); 2391 /* now online created session */ 2392 if (iscsid_login_tgt(ihp, (char *)iscsiboot_prop->boot_tgt.tgt_name, 2393 iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic, 2394 (struct sockaddr *)&addr_dst) == B_FALSE) { 2395 return (NULL); 2396 } 2397 2398 return (isp); 2399 } 2400 2401 static void 2402 iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p) 2403 { 2404 int rc = 1; 2405 iscsi_hba_t *ihp = (iscsi_hba_t *)p; 2406 boolean_t reconfigured = B_FALSE; 2407 2408 while (rc != 0) { 2409 if (iscsiboot_prop && (modrootloaded == 1)) { 2410 if (ihp->hba_persistent_loaded == B_FALSE) { 2411 if (persistent_load() == B_TRUE) { 2412 ihp->hba_persistent_loaded = B_TRUE; 2413 } 2414 } 2415 if ((ihp->hba_persistent_loaded == B_TRUE) && 2416 (reconfigured == B_FALSE)) { 2417 if (iscsi_chk_bootlun_mpxio(ihp) == B_TRUE) { 2418 (void) iscsi_reconfig_boot_sess(ihp); 2419 iscsid_poke_discovery(ihp, 2420 iSCSIDiscoveryMethodUnknown); 2421 (void) iscsid_login_tgt(ihp, NULL, 2422 iSCSIDiscoveryMethodUnknown, NULL); 2423 } 2424 reconfigured = B_TRUE; 2425 } 2426 break; 2427 } 2428 rc = iscsi_thread_wait(thread, SEC_TO_TICK(1)); 2429 } 2430 } 2431 2432 boolean_t 2433 iscsi_cmp_boot_tgt_name(char *name) 2434 { 2435 if (iscsiboot_prop && (strncmp((const char *)name, 2436 (const char *)iscsiboot_prop->boot_tgt.tgt_name, 2437 ISCSI_MAX_NAME_LEN) == 0)) { 2438 return (B_TRUE); 2439 } else { 2440 return (B_FALSE); 2441 } 2442 } 2443 2444 boolean_t 2445 iscsi_cmp_boot_ini_name(char *name) 2446 { 2447 if (iscsiboot_prop && (strncmp((const char *)name, 2448 (const char *)iscsiboot_prop->boot_init.ini_name, 2449 ISCSI_MAX_NAME_LEN) == 0)) { 2450 return (B_TRUE); 2451 } else { 2452 return (B_FALSE); 2453 } 2454 } 2455 2456 boolean_t 2457 iscsi_chk_bootlun_mpxio(iscsi_hba_t *ihp) 2458 { 2459 iscsi_sess_t *isp; 2460 iscsi_lun_t *ilp; 2461 isp = ihp->hba_sess_list; 2462 boolean_t tgt_mpxio_enabled = B_FALSE; 2463 boolean_t bootlun_found = B_FALSE; 2464 uint16_t lun_num; 2465 2466 if (iscsiboot_prop == NULL) { 2467 return (B_FALSE); 2468 } 2469 2470 if (!ihp->hba_mpxio_enabled) { 2471 return (B_FALSE); 2472 } 2473 2474 lun_num = *((uint64_t *)(iscsiboot_prop->boot_tgt.tgt_boot_lun)); 2475 2476 while (isp != NULL) { 2477 if ((strncmp((char *)isp->sess_name, 2478 (const char *)iscsiboot_prop->boot_tgt.tgt_name, 2479 ISCSI_MAX_NAME_LEN) == 0) && 2480 (isp->sess_boot == B_TRUE)) { 2481 /* 2482 * found boot session. 2483 * check its mdi path info is null or not 2484 */ 2485 ilp = isp->sess_lun_list; 2486 while (ilp != NULL) { 2487 if (lun_num == ilp->lun_num) { 2488 if (ilp->lun_pip) { 2489 tgt_mpxio_enabled = B_TRUE; 2490 } 2491 bootlun_found = B_TRUE; 2492 } 2493 ilp = ilp->lun_next; 2494 } 2495 } 2496 isp = isp->sess_next; 2497 } 2498 if (bootlun_found) { 2499 return (tgt_mpxio_enabled); 2500 } else { 2501 /* 2502 * iscsiboot_prop not NULL while no boot lun found 2503 * in most cases this is none iscsi boot while iscsiboot_prop 2504 * is not NULL, in this scenario return iscsi HBA's mpxio config 2505 */ 2506 return (ihp->hba_mpxio_enabled); 2507 } 2508 } 2509 2510 static boolean_t 2511 iscsid_check_active_boot_conn(iscsi_hba_t *ihp) 2512 { 2513 iscsi_sess_t *isp = NULL; 2514 iscsi_conn_t *icp = NULL; 2515 2516 rw_enter(&ihp->hba_sess_list_rwlock, RW_READER); 2517 isp = ihp->hba_sess_list; 2518 while (isp != NULL) { 2519 if (isp->sess_boot == B_TRUE) { 2520 rw_enter(&isp->sess_conn_list_rwlock, RW_READER); 2521 icp = isp->sess_conn_list; 2522 while (icp != NULL) { 2523 if (icp->conn_state == 2524 ISCSI_CONN_STATE_LOGGED_IN) { 2525 rw_exit(&isp->sess_conn_list_rwlock); 2526 rw_exit(&ihp->hba_sess_list_rwlock); 2527 return (B_TRUE); 2528 } 2529 icp = icp->conn_next; 2530 } 2531 rw_exit(&isp->sess_conn_list_rwlock); 2532 } 2533 isp = isp->sess_next; 2534 } 2535 rw_exit(&ihp->hba_sess_list_rwlock); 2536 2537 return (B_FALSE); 2538 } 2539