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