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 709 if (pg_list == NULL) { 710 DTRACE_PROBE1(iscsid_do_isns_query_status, 711 int, query_status); 712 return; 713 } 714 715 if ((query_status != isns_ok && 716 query_status != isns_op_partially_failed)) { 717 DTRACE_PROBE1(iscsid_do_isns_query_status, 718 int, query_status); 719 pg_sz = sizeof (isns_portal_group_list_t); 720 if (pg_list->pg_out_cnt > 0) { 721 pg_sz += (pg_list->pg_out_cnt - 1) * 722 sizeof (isns_portal_group_t); 723 } 724 kmem_free(pg_list, pg_sz); 725 return; 726 } 727 728 iscsid_add_pg_list_to_cache(ihp, pg_list); 729 730 pg_sz = sizeof (isns_portal_group_list_t); 731 if (pg_list->pg_out_cnt > 0) { 732 pg_sz += (pg_list->pg_out_cnt - 1) * 733 sizeof (isns_portal_group_t); 734 } 735 kmem_free(pg_list, pg_sz); 736 } 737 738 /* 739 * iscsid_config_one - for the given target name, attempt 740 * to login to all targets associated with name. If target 741 * name is not found in discovery queue, reset the discovery 742 * queue, kick the discovery processes, and then retry. 743 * 744 * NOTE: The caller of this function must hold the 745 * iscsid_config_semaphore across this call. 746 */ 747 void 748 iscsid_config_one(iscsi_hba_t *ihp, char *name, boolean_t protect) 749 { 750 boolean_t rc = B_FALSE; 751 int retry = 0; 752 int lun_online = 0; 753 int cur_sec = 0; 754 755 if (!modrootloaded && (iscsiboot_prop != NULL)) { 756 if (!iscsi_configroot_printed) { 757 cmn_err(CE_NOTE, "Configuring" 758 " iSCSI boot session..."); 759 iscsi_configroot_printed = B_TRUE; 760 } 761 if (iscsi_net_up == 0) { 762 if (iscsi_net_interface() == ISCSI_STATUS_SUCCESS) { 763 iscsi_net_up = 1; 764 } else { 765 cmn_err(CE_WARN, "Failed to configure interface" 766 " for iSCSI boot session"); 767 return; 768 } 769 } 770 while (rc == B_FALSE && retry < 771 iscsi_configroot_retry) { 772 rc = iscsid_login_tgt(ihp, name, 773 iSCSIDiscoveryMethodBoot, NULL); 774 if (rc == B_FALSE) { 775 /* 776 * create boot session 777 */ 778 iscsi_boot_session_create(ihp, 779 iscsiboot_prop); 780 } else { 781 /* 782 * The boot session has been created, if 783 * the target lun has not been online, 784 * we should wait here for a while 785 */ 786 do { 787 lun_online = 788 iscsiboot_prop->boot_tgt.lun_online; 789 if (lun_online == 0) { 790 delay(SEC_TO_TICK(1)); 791 cur_sec++; 792 } 793 } while ((lun_online == 0) && 794 (cur_sec < iscsi_boot_max_delay)); 795 } 796 retry++; 797 } 798 if (!rc) { 799 cmn_err(CE_WARN, "Failed to configure iSCSI" 800 " boot session"); 801 } 802 } else { 803 rc = iscsid_login_tgt(ihp, name, iSCSIDiscoveryMethodUnknown, 804 NULL); 805 /* 806 * If we didn't login to the device we might have 807 * to update our discovery information and attempt 808 * the login again. 809 */ 810 if (rc == B_FALSE) { 811 /* 812 * Stale /dev links can cause us to get floods 813 * of config requests. Prevent these repeated 814 * requests from causing unneeded discovery updates 815 * if ISCSI_CONFIG_STORM_PROTECT is set. 816 */ 817 if ((protect == B_FALSE) || 818 (ddi_get_lbolt() > ihp->hba_config_lbolt + 819 SEC_TO_TICK(ihp->hba_config_storm_delay))) { 820 ihp->hba_config_lbolt = ddi_get_lbolt(); 821 iscsid_poke_discovery(ihp, 822 iSCSIDiscoveryMethodUnknown); 823 (void) iscsid_login_tgt(ihp, name, 824 iSCSIDiscoveryMethodUnknown, NULL); 825 } 826 } 827 } 828 } 829 830 /* 831 * iscsid_config_all - reset the discovery queue, kick the 832 * discovery processes, and login to all targets found 833 * 834 * NOTE: The caller of this function must hold the 835 * iscsid_config_semaphore across this call. 836 */ 837 void 838 iscsid_config_all(iscsi_hba_t *ihp, boolean_t protect) 839 { 840 boolean_t rc = B_FALSE; 841 int retry = 0; 842 int lun_online = 0; 843 int cur_sec = 0; 844 845 if (!modrootloaded && iscsiboot_prop != NULL) { 846 if (!iscsi_configroot_printed) { 847 cmn_err(CE_NOTE, "Configuring" 848 " iSCSI boot session..."); 849 iscsi_configroot_printed = B_TRUE; 850 } 851 if (iscsi_net_up == 0) { 852 if (iscsi_net_interface() == ISCSI_STATUS_SUCCESS) { 853 iscsi_net_up = 1; 854 } 855 } 856 while (rc == B_FALSE && retry < 857 iscsi_configroot_retry) { 858 rc = iscsid_login_tgt(ihp, NULL, 859 iSCSIDiscoveryMethodBoot, NULL); 860 if (rc == B_FALSE) { 861 /* 862 * No boot session has been created. 863 * We would like to create the boot 864 * Session first. 865 */ 866 iscsi_boot_session_create(ihp, 867 iscsiboot_prop); 868 } else { 869 /* 870 * The boot session has been created, if 871 * the target lun has not been online, 872 * we should wait here for a while 873 */ 874 do { 875 lun_online = 876 iscsiboot_prop->boot_tgt.lun_online; 877 if (lun_online == 0) { 878 delay(SEC_TO_TICK(1)); 879 cur_sec++; 880 } 881 } while ((lun_online == 0) && 882 (cur_sec < iscsi_boot_max_delay)); 883 } 884 retry++; 885 } 886 if (!rc) { 887 cmn_err(CE_WARN, "Failed to configure" 888 " boot session"); 889 } 890 } else { 891 /* 892 * Stale /dev links can cause us to get floods 893 * of config requests. Prevent these repeated 894 * requests from causing unneeded discovery updates 895 * if ISCSI_CONFIG_STORM_PROTECT is set. 896 */ 897 if ((protect == B_FALSE) || 898 (ddi_get_lbolt() > ihp->hba_config_lbolt + 899 SEC_TO_TICK(ihp->hba_config_storm_delay))) { 900 ihp->hba_config_lbolt = ddi_get_lbolt(); 901 iscsid_poke_discovery(ihp, 902 iSCSIDiscoveryMethodUnknown); 903 } 904 (void) iscsid_login_tgt(ihp, NULL, 905 iSCSIDiscoveryMethodUnknown, NULL); 906 } 907 } 908 909 /* 910 * isns_scn_callback - iSNS client received an SCN 911 * 912 * This code processes the iSNS client SCN events. These 913 * could relate to the addition, removal, or update of a 914 * logical unit. 915 */ 916 void 917 isns_scn_callback(void *arg) 918 { 919 int i, pg_sz; 920 int qry_status; 921 isns_portal_group_list_t *pg_list; 922 uint32_t scn_type; 923 iscsi_hba_t *ihp; 924 925 if (arg == NULL) { 926 /* No argument */ 927 return; 928 } 929 930 if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) { 931 kmem_free(arg, sizeof (isns_scn_callback_arg_t)); 932 return; 933 } 934 935 /* 936 * All isns callbacks are from a standalone taskq 937 * therefore the blocking here doesn't affect the enable/disable 938 * of isns discovery method 939 */ 940 if (iscsi_client_request_service(ihp) == B_FALSE) { 941 kmem_free(arg, sizeof (isns_scn_callback_arg_t)); 942 return; 943 } 944 945 scn_type = ((isns_scn_callback_arg_t *)arg)->scn_type; 946 DTRACE_PROBE1(isns_scn_callback_scn_type, int, scn_type); 947 switch (scn_type) { 948 /* 949 * ISNS_OBJ_ADDED - An object has been added. 950 */ 951 case ISNS_OBJ_ADDED: 952 /* Query iSNS server for contact information */ 953 pg_list = NULL; 954 qry_status = isns_query_one_node( 955 ((isns_scn_callback_arg_t *)arg)->source_key_attr, 956 ihp->hba_isid, 957 ihp->hba_name, 958 (uint8_t *)"", 959 ISNS_INITIATOR_NODE_TYPE, 960 &pg_list); 961 962 /* Verify portal group is found */ 963 if ((qry_status != isns_ok && 964 qry_status != isns_op_partially_failed) || 965 pg_list == NULL) { 966 break; 967 } 968 969 DTRACE_PROBE1(pg_list, 970 isns_portal_group_list_t *, pg_list); 971 972 /* Add all portals for logical unit to discovery cache */ 973 for (i = 0; i < pg_list->pg_out_cnt; i++) { 974 iscsi_sockaddr_t addr_dsc; 975 iscsi_sockaddr_t addr_tgt; 976 977 iscsid_addr_to_sockaddr( 978 pg_list->pg_list[i].isns_server_ip.i_insize, 979 &pg_list->pg_list[i].isns_server_ip.i_addr, 980 pg_list->pg_list[i].isns_server_port, 981 &addr_dsc.sin); 982 iscsid_addr_to_sockaddr(pg_list->pg_list[i].insize, 983 &pg_list->pg_list[i].pg_ip_addr, 984 pg_list->pg_list[i].pg_port, &addr_tgt.sin); 985 986 (void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS, 987 &addr_dsc.sin, (char *)pg_list->pg_list[i]. 988 pg_iscsi_name, pg_list->pg_list[i].pg_tag, 989 &addr_tgt.sin); 990 991 /* Force target to login */ 992 (void) iscsid_login_tgt(ihp, (char *)pg_list-> 993 pg_list[i].pg_iscsi_name, iSCSIDiscoveryMethodISNS, 994 NULL); 995 } 996 997 if (pg_list != NULL) { 998 pg_sz = sizeof (isns_portal_group_list_t); 999 if (pg_list->pg_out_cnt > 0) { 1000 pg_sz += (pg_list->pg_out_cnt - 1) * 1001 sizeof (isns_portal_group_t); 1002 } 1003 kmem_free(pg_list, pg_sz); 1004 } 1005 break; 1006 1007 /* 1008 * ISNS_OBJ_REMOVED - logical unit has been removed 1009 */ 1010 case ISNS_OBJ_REMOVED: 1011 if (iscsid_del(ihp, 1012 (char *)((isns_scn_callback_arg_t *)arg)-> 1013 source_key_attr, iSCSIDiscoveryMethodISNS, NULL) != 1014 B_TRUE) { 1015 cmn_err(CE_NOTE, "iscsi initiator - " 1016 "isns remove scn failed for target %s\n", 1017 (char *)((isns_scn_callback_arg_t *)arg)-> 1018 source_key_attr); 1019 1020 } 1021 break; 1022 1023 /* 1024 * ISNS_OBJ_UPDATED - logical unit has changed 1025 */ 1026 case ISNS_OBJ_UPDATED: 1027 cmn_err(CE_NOTE, "iscsi initiator - " 1028 "received iSNS update SCN for %s\n", 1029 (char *)((isns_scn_callback_arg_t *)arg)-> 1030 source_key_attr); 1031 break; 1032 1033 /* 1034 * ISNS_OBJ_UNKNOWN - 1035 */ 1036 default: 1037 cmn_err(CE_NOTE, "iscsi initiator - " 1038 "received unknown iSNS SCN type 0x%x\n", scn_type); 1039 break; 1040 } 1041 1042 iscsi_client_release_service(ihp); 1043 kmem_free(arg, sizeof (isns_scn_callback_arg_t)); 1044 } 1045 1046 1047 /* 1048 * iscsid_add - Creates discovered session and connection 1049 */ 1050 static boolean_t 1051 iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method, 1052 struct sockaddr *addr_dsc, char *target_name, int tpgt, 1053 struct sockaddr *addr_tgt) 1054 { 1055 boolean_t rtn = B_TRUE; 1056 iscsi_sess_t *isp; 1057 iscsi_conn_t *icp; 1058 uint_t oid; 1059 int idx; 1060 int isid; 1061 iscsi_config_sess_t *ics; 1062 int size; 1063 char *tmp; 1064 1065 ASSERT(ihp != NULL); 1066 ASSERT(addr_dsc != NULL); 1067 ASSERT(target_name != NULL); 1068 ASSERT(addr_tgt != NULL); 1069 1070 /* setup initial buffer for configured session information */ 1071 size = sizeof (*ics); 1072 ics = kmem_zalloc(size, KM_SLEEP); 1073 ics->ics_in = 1; 1074 1075 /* get configured sessions information */ 1076 tmp = target_name; 1077 if (persistent_get_config_session(tmp, ics) == B_FALSE) { 1078 /* 1079 * No target information available check for 1080 * initiator information. 1081 */ 1082 tmp = (char *)ihp->hba_name; 1083 if (persistent_get_config_session(tmp, ics) == B_FALSE) { 1084 /* 1085 * No hba information is 1086 * found. So assume default 1087 * one session unbound behavior. 1088 */ 1089 ics->ics_out = 1; 1090 ics->ics_bound = B_TRUE; 1091 } 1092 } 1093 1094 if (iscsiboot_prop && (ics->ics_out > 1) && 1095 !iscsi_chk_bootlun_mpxio(ihp)) { 1096 /* 1097 * iscsi boot with mpxio disabled 1098 * no need to search configured boot session 1099 */ 1100 1101 if (iscsi_cmp_boot_ini_name(tmp) || 1102 iscsi_cmp_boot_tgt_name(tmp)) { 1103 ics->ics_out = 1; 1104 ics->ics_bound = B_FALSE; 1105 } 1106 } 1107 /* Check to see if we need to get more information */ 1108 if (ics->ics_out > 1) { 1109 /* record new size and free last buffer */ 1110 idx = ics->ics_out; 1111 size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out); 1112 kmem_free(ics, sizeof (*ics)); 1113 1114 /* allocate new buffer */ 1115 ics = kmem_zalloc(size, KM_SLEEP); 1116 ics->ics_in = idx; 1117 1118 /* get configured sessions information */ 1119 if (persistent_get_config_session(tmp, ics) != B_TRUE) { 1120 cmn_err(CE_NOTE, "iscsi session(%s) - " 1121 "unable to get configured session information\n", 1122 target_name); 1123 kmem_free(ics, size); 1124 return (B_FALSE); 1125 } 1126 } 1127 1128 /* loop for all configured sessions */ 1129 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 1130 for (isid = 0; isid < ics->ics_out; isid++) { 1131 /* create or find matching session */ 1132 isp = iscsi_sess_create(ihp, method, addr_dsc, target_name, 1133 tpgt, isid, ISCSI_SESS_TYPE_NORMAL, &oid); 1134 if (isp == NULL) { 1135 rtn = B_FALSE; 1136 break; 1137 } 1138 1139 /* create or find matching connection */ 1140 if (!ISCSI_SUCCESS(iscsi_conn_create(addr_tgt, isp, &icp))) { 1141 /* 1142 * Teardown the session we just created. It can't 1143 * have any luns or connections associated with it 1144 * so this should always succeed (luckily since what 1145 * would we do if it failed?) 1146 */ 1147 (void) iscsi_sess_destroy(isp); 1148 rtn = B_FALSE; 1149 break; 1150 } 1151 } 1152 rw_exit(&ihp->hba_sess_list_rwlock); 1153 kmem_free(ics, size); 1154 return (rtn); 1155 } 1156 1157 /* 1158 * iscsid_del - Attempts to delete all associated sessions 1159 */ 1160 boolean_t 1161 iscsid_del(iscsi_hba_t *ihp, char *target_name, 1162 iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc) 1163 { 1164 boolean_t rtn = B_TRUE; 1165 iscsi_status_t status; 1166 iscsi_sess_t *isp; 1167 char name[ISCSI_MAX_NAME_LEN]; 1168 1169 ASSERT(ihp != NULL); 1170 /* target name can be NULL or !NULL */ 1171 /* addr_dsc can be NULL or !NULL */ 1172 1173 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 1174 isp = ihp->hba_sess_list; 1175 while (isp != NULL) { 1176 /* 1177 * If no target_name is listed (meaning all targets) 1178 * or this specific target was listed. And the same 1179 * discovery method discovered this target then 1180 * continue evaulation. Otherwise fail. 1181 */ 1182 if (((target_name == NULL) || 1183 (strcmp((char *)isp->sess_name, target_name) == 0)) && 1184 (isp->sess_discovered_by == method)) { 1185 boolean_t try_destroy; 1186 1187 /* 1188 * If iSNS, SendTargets, or Static then special 1189 * handling for disc_addr. 1190 */ 1191 if ((method == iSCSIDiscoveryMethodISNS) || 1192 (method == iSCSIDiscoveryMethodSendTargets)) { 1193 /* 1194 * If NULL addr_dsc (meaning all disc_addr) 1195 * or matching discovered addr. 1196 */ 1197 if ((addr_dsc == NULL) || 1198 (bcmp(addr_dsc, &isp->sess_discovered_addr, 1199 SIZEOF_SOCKADDR( 1200 &isp->sess_discovered_addr.sin)) == 0)) { 1201 try_destroy = B_TRUE; 1202 } else { 1203 try_destroy = B_FALSE; 1204 } 1205 } else if (method == iSCSIDiscoveryMethodStatic) { 1206 /* 1207 * If NULL addr_dsc (meaning all disc_addr) 1208 * or matching active connection. 1209 */ 1210 if ((addr_dsc == NULL) || 1211 ((isp->sess_conn_act != NULL) && 1212 (bcmp(addr_dsc, 1213 &isp->sess_conn_act->conn_base_addr.sin, 1214 SIZEOF_SOCKADDR( 1215 &isp->sess_conn_act->conn_base_addr.sin)) 1216 == 0))) { 1217 try_destroy = B_TRUE; 1218 } else { 1219 try_destroy = B_FALSE; 1220 } 1221 } else { 1222 /* Unknown discovery specified */ 1223 try_destroy = B_TRUE; 1224 } 1225 1226 if (try_destroy == B_TRUE && 1227 isp->sess_boot == B_FALSE) { 1228 (void) strcpy(name, (char *)isp->sess_name); 1229 status = iscsi_sess_destroy(isp); 1230 if (ISCSI_SUCCESS(status)) { 1231 iscsid_remove_target_param(name); 1232 isp = ihp->hba_sess_list; 1233 } else { 1234 /* 1235 * The most likely destroy failure 1236 * is that ndi/mdi offline failed. 1237 * This means that the resource is 1238 * in_use/busy. 1239 */ 1240 cmn_err(CE_NOTE, "iscsi session(%d) - " 1241 "session logout failed (%d)\n", 1242 isp->sess_oid, status); 1243 isp = isp->sess_next; 1244 rtn = B_FALSE; 1245 } 1246 } else { 1247 isp = isp->sess_next; 1248 } 1249 } else { 1250 isp = isp->sess_next; 1251 } 1252 } 1253 rw_exit(&ihp->hba_sess_list_rwlock); 1254 return (rtn); 1255 } 1256 1257 1258 /* 1259 * iscsid_login_tgt - request target(s) to login 1260 */ 1261 boolean_t 1262 iscsid_login_tgt(iscsi_hba_t *ihp, char *target_name, 1263 iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc) 1264 { 1265 boolean_t rtn = B_FALSE; 1266 iscsi_sess_t *isp = NULL; 1267 iscsi_sess_list_t *isp_list = NULL; 1268 iscsi_sess_list_t *last_sess = NULL; 1269 iscsi_sess_list_t *cur_sess = NULL; 1270 int total = 0; 1271 ddi_taskq_t *login_taskq = NULL; 1272 char taskq_name[ISCSI_TH_MAX_NAME_LEN] = {0}; 1273 time_t time_stamp; 1274 1275 ASSERT(ihp != NULL); 1276 1277 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 1278 /* Loop thru sessions */ 1279 isp = ihp->hba_sess_list; 1280 while (isp != NULL) { 1281 boolean_t try_online; 1282 if (!(method & iSCSIDiscoveryMethodBoot)) { 1283 if (target_name == NULL) { 1284 if (method == iSCSIDiscoveryMethodUnknown) { 1285 /* unknown method mean login to all */ 1286 try_online = B_TRUE; 1287 } else if (isp->sess_discovered_by & method) { 1288 if ((method == 1289 iSCSIDiscoveryMethodISNS) || 1290 (method == 1291 iSCSIDiscoveryMethodSendTargets)) { 1292 #define SESS_DISC_ADDR isp->sess_discovered_addr.sin 1293 if ((addr_dsc == NULL) || 1294 (bcmp( 1295 &isp->sess_discovered_addr, 1296 addr_dsc, SIZEOF_SOCKADDR( 1297 &SESS_DISC_ADDR)) 1298 == 0)) { 1299 /* 1300 * iSNS or sendtarget 1301 * discovery and 1302 * discovery address 1303 * is NULL or match 1304 */ 1305 try_online = B_TRUE; 1306 } else { 1307 /* addr_dsc not a match */ 1308 try_online = B_FALSE; 1309 } 1310 #undef SESS_DISC_ADDR 1311 } else { 1312 /* static configuration */ 1313 try_online = B_TRUE; 1314 } 1315 } else { 1316 /* method not a match */ 1317 try_online = B_FALSE; 1318 } 1319 } else if (strcmp(target_name, 1320 (char *)isp->sess_name) == 0) { 1321 /* target_name match */ 1322 try_online = B_TRUE; 1323 } else { 1324 /* target_name not a match */ 1325 try_online = B_FALSE; 1326 } 1327 } else { 1328 /* 1329 * online the boot session. 1330 */ 1331 if (isp->sess_boot == B_TRUE) { 1332 try_online = B_TRUE; 1333 } 1334 } 1335 1336 if (try_online == B_TRUE && 1337 isp->sess_type == ISCSI_SESS_TYPE_NORMAL) { 1338 total++; 1339 /* Copy these sessions to the list. */ 1340 if (isp_list == NULL) { 1341 isp_list = 1342 (iscsi_sess_list_t *)kmem_zalloc( 1343 sizeof (iscsi_sess_list_t), KM_SLEEP); 1344 last_sess = isp_list; 1345 last_sess->session = isp; 1346 last_sess->next = NULL; 1347 } else { 1348 last_sess->next = 1349 (iscsi_sess_list_t *)kmem_zalloc( 1350 sizeof (iscsi_sess_list_t), KM_SLEEP); 1351 last_sess->next->session = isp; 1352 last_sess->next->next = NULL; 1353 last_sess = last_sess->next; 1354 } 1355 rtn = B_TRUE; 1356 } 1357 1358 isp = isp->sess_next; 1359 } 1360 1361 if (total > 0) { 1362 time_stamp = ddi_get_time(); 1363 (void) snprintf(taskq_name, (ISCSI_TH_MAX_NAME_LEN - 1), 1364 "login_queue.%lx", time_stamp); 1365 1366 login_taskq = ddi_taskq_create(ihp->hba_dip, 1367 taskq_name, total, TASKQ_DEFAULTPRI, 0); 1368 if (login_taskq == NULL) { 1369 while (isp_list != NULL) { 1370 cur_sess = isp_list; 1371 isp_list = isp_list->next; 1372 kmem_free(cur_sess, sizeof (iscsi_sess_list_t)); 1373 } 1374 rtn = B_FALSE; 1375 rw_exit(&ihp->hba_sess_list_rwlock); 1376 return (rtn); 1377 } 1378 1379 for (cur_sess = isp_list; cur_sess != NULL; 1380 cur_sess = cur_sess->next) { 1381 if (ddi_taskq_dispatch(login_taskq, 1382 iscsi_sess_online, (void *)cur_sess->session, 1383 DDI_SLEEP) != DDI_SUCCESS) { 1384 cmn_err(CE_NOTE, "Can't dispatch the task " 1385 "for login to the target: %s", 1386 cur_sess->session->sess_name); 1387 } 1388 } 1389 1390 ddi_taskq_wait(login_taskq); 1391 ddi_taskq_destroy(login_taskq); 1392 while (isp_list != NULL) { 1393 cur_sess = isp_list; 1394 isp_list = isp_list->next; 1395 kmem_free(cur_sess, sizeof (iscsi_sess_list_t)); 1396 } 1397 1398 } 1399 1400 rw_exit(&ihp->hba_sess_list_rwlock); 1401 return (rtn); 1402 } 1403 1404 /* 1405 * +--------------------------------------------------------------------+ 1406 * | Local Helper Functions | 1407 * +--------------------------------------------------------------------+ 1408 */ 1409 1410 /* 1411 * iscsid_init_config -- initialize configuration parameters of iSCSI initiator 1412 */ 1413 static boolean_t 1414 iscsid_init_config(iscsi_hba_t *ihp) 1415 { 1416 iscsi_param_set_t ips; 1417 void *v = NULL; 1418 char *name; 1419 char *initiatorName; 1420 persistent_param_t pp; 1421 persistent_tunable_param_t pparam; 1422 uint32_t param_id; 1423 int rc; 1424 1425 /* allocate memory to hold initiator names */ 1426 initiatorName = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1427 1428 /* 1429 * initialize iSCSI initiator name 1430 */ 1431 bzero(&ips, sizeof (ips)); 1432 if (persistent_initiator_name_get(initiatorName, 1433 ISCSI_MAX_NAME_LEN) == B_TRUE) { 1434 ips.s_vers = ISCSI_INTERFACE_VERSION; 1435 ips.s_param = ISCSI_LOGIN_PARAM_INITIATOR_NAME; 1436 1437 if (iscsiboot_prop && !iscsi_cmp_boot_ini_name(initiatorName)) { 1438 (void) strncpy(initiatorName, 1439 (const char *)iscsiboot_prop->boot_init.ini_name, 1440 ISCSI_MAX_NAME_LEN); 1441 (void) strncpy((char *)ips.s_value.v_name, 1442 (const char *)iscsiboot_prop->boot_init.ini_name, 1443 sizeof (ips.s_value.v_name)); 1444 (void) iscsi_set_params(&ips, ihp, B_TRUE); 1445 /* use default tunable value */ 1446 ihp->hba_tunable_params.recv_login_rsp_timeout = 1447 ISCSI_DEFAULT_RX_TIMEOUT_VALUE; 1448 ihp->hba_tunable_params.polling_login_delay = 1449 ISCSI_DEFAULT_LOGIN_POLLING_DELAY; 1450 ihp->hba_tunable_params.conn_login_max = 1451 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX; 1452 cmn_err(CE_NOTE, "Set initiator's name" 1453 " from firmware"); 1454 } else { 1455 (void) strncpy((char *)ips.s_value.v_name, 1456 initiatorName, sizeof (ips.s_value.v_name)); 1457 1458 (void) iscsi_set_params(&ips, ihp, B_FALSE); 1459 if (persistent_get_tunable_param(initiatorName, 1460 &pparam) == B_FALSE) { 1461 /* use default value */ 1462 pparam.p_params.recv_login_rsp_timeout = 1463 ISCSI_DEFAULT_RX_TIMEOUT_VALUE; 1464 pparam.p_params.polling_login_delay = 1465 ISCSI_DEFAULT_LOGIN_POLLING_DELAY; 1466 pparam.p_params.conn_login_max = 1467 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX; 1468 } 1469 bcopy(&pparam.p_params, &ihp->hba_tunable_params, 1470 sizeof (iscsi_tunable_params_t)); 1471 } 1472 } else { 1473 /* 1474 * if no initiator-node name available it is most 1475 * likely due to a fresh install, or the persistent 1476 * store is not working correctly. Set 1477 * a default initiator name so that the initiator can 1478 * be brought up properly. 1479 */ 1480 iscsid_set_default_initiator_node_settings(ihp, B_FALSE); 1481 (void) strncpy(initiatorName, (const char *)ihp->hba_name, 1482 ISCSI_MAX_NAME_LEN); 1483 } 1484 1485 /* 1486 * initialize iSCSI initiator alias (if any) 1487 */ 1488 bzero(&ips, sizeof (ips)); 1489 if (persistent_alias_name_get((char *)ips.s_value.v_name, 1490 sizeof (ips.s_value.v_name)) == B_TRUE) { 1491 ips.s_param = ISCSI_LOGIN_PARAM_INITIATOR_ALIAS; 1492 (void) iscsi_set_params(&ips, ihp, B_FALSE); 1493 } else { 1494 /* EMPTY */ 1495 /* No alias defined - not a problem. */ 1496 } 1497 1498 /* 1499 * load up the overriden iSCSI initiator parameters 1500 */ 1501 name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1502 persistent_param_lock(); 1503 v = NULL; 1504 while (persistent_param_next(&v, name, &pp) == B_TRUE) { 1505 if (strncmp(name, initiatorName, ISCSI_MAX_NAME_LEN) == 0) { 1506 ips.s_oid = ihp->hba_oid; 1507 ips.s_vers = ISCSI_INTERFACE_VERSION; 1508 for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM; 1509 param_id++) { 1510 if (pp.p_bitmap & (1 << param_id)) { 1511 rc = iscsid_copyto_param_set(param_id, 1512 &pp.p_params, &ips); 1513 if (rc == 0) { 1514 rc = iscsi_set_params(&ips, 1515 ihp, B_FALSE); 1516 } 1517 if (rc != 0) { 1518 /* note error but continue */ 1519 cmn_err(CE_NOTE, 1520 "Failed to set " 1521 "param %d for OID %d", 1522 ips.s_param, ips.s_oid); 1523 } 1524 } 1525 } /* END for() */ 1526 if (iscsiboot_prop && 1527 iscsi_chk_bootlun_mpxio(ihp)) { 1528 (void) iscsi_reconfig_boot_sess(ihp); 1529 } 1530 break; 1531 } 1532 } /* END while() */ 1533 persistent_param_unlock(); 1534 1535 kmem_free(initiatorName, ISCSI_MAX_NAME_LEN); 1536 kmem_free(name, ISCSI_MAX_NAME_LEN); 1537 return (B_TRUE); 1538 } 1539 1540 1541 /* 1542 * iscsid_init_targets -- Load up the driver with known static targets and 1543 * targets whose parameters have been modified. 1544 * 1545 * This is done so that the CLI can find a list of targets the driver 1546 * currently knows about. 1547 * 1548 * The driver doesn't need to log into these targets. Log in is done based 1549 * upon the enabled discovery methods. 1550 */ 1551 static boolean_t 1552 iscsid_init_targets(iscsi_hba_t *ihp) 1553 { 1554 void *v = NULL; 1555 char *name; 1556 iscsi_param_set_t ips; 1557 persistent_param_t pp; 1558 char *iname; 1559 uint32_t param_id; 1560 int rc; 1561 1562 ASSERT(ihp != NULL); 1563 1564 /* allocate memory to hold target names */ 1565 name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1566 1567 /* 1568 * load up targets whose parameters have been overriden 1569 */ 1570 1571 /* ---- only need to be set once ---- */ 1572 bzero(&ips, sizeof (ips)); 1573 ips.s_vers = ISCSI_INTERFACE_VERSION; 1574 1575 /* allocate memory to hold initiator name */ 1576 iname = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1577 (void) persistent_initiator_name_get(iname, ISCSI_MAX_NAME_LEN); 1578 1579 persistent_param_lock(); 1580 v = NULL; 1581 while (persistent_param_next(&v, name, &pp) == B_TRUE) { 1582 1583 if (strncmp(iname, name, ISCSI_MAX_NAME_LEN) == 0) { 1584 /* 1585 * target name matched initiator's name so, 1586 * continue to next target. Initiator's 1587 * parmeters have already been set. 1588 */ 1589 continue; 1590 } 1591 1592 if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) && 1593 !iscsi_chk_bootlun_mpxio(ihp)) { 1594 /* 1595 * boot target is not mpxio enabled 1596 * simply ignore these overriden parameters 1597 */ 1598 continue; 1599 } 1600 1601 ips.s_oid = iscsi_targetparam_get_oid((unsigned char *)name); 1602 1603 for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM; 1604 param_id++) { 1605 if (pp.p_bitmap & (1 << param_id)) { 1606 rc = iscsid_copyto_param_set(param_id, 1607 &pp.p_params, &ips); 1608 if (rc == 0) { 1609 rc = iscsi_set_params(&ips, 1610 ihp, B_FALSE); 1611 } 1612 if (rc != 0) { 1613 /* note error but continue ---- */ 1614 cmn_err(CE_NOTE, "Failed to set " 1615 "param %d for OID %d", 1616 ips.s_param, ips.s_oid); 1617 } 1618 } 1619 } /* END for() */ 1620 if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) && 1621 iscsi_chk_bootlun_mpxio(ihp)) { 1622 (void) iscsi_reconfig_boot_sess(ihp); 1623 } 1624 } /* END while() */ 1625 persistent_param_unlock(); 1626 1627 kmem_free(iname, ISCSI_MAX_NAME_LEN); 1628 kmem_free(name, ISCSI_MAX_NAME_LEN); 1629 1630 return (B_TRUE); 1631 } 1632 1633 1634 /* 1635 * iscsid_thread_static -- If static discovery is enabled, this routine obtains 1636 * all statically configured targets from the peristent store and issues a 1637 * login request to the driver. 1638 */ 1639 /* ARGSUSED */ 1640 static void 1641 iscsid_thread_static(iscsi_thread_t *thread, void *p) 1642 { 1643 iSCSIDiscoveryMethod_t dm; 1644 entry_t entry; 1645 char name[ISCSI_MAX_NAME_LEN]; 1646 void *v = NULL; 1647 iscsi_hba_t *ihp = (iscsi_hba_t *)p; 1648 1649 while (iscsi_thread_wait(thread, -1) != 0) { 1650 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_TRUE); 1651 1652 /* ---- ensure static target discovery is enabled ---- */ 1653 dm = persistent_disc_meth_get(); 1654 if ((dm & iSCSIDiscoveryMethodStatic) == 0) { 1655 cmn_err(CE_NOTE, 1656 "iscsi discovery failure - " 1657 "StaticTargets method is not enabled"); 1658 iscsi_discovery_event(ihp, 1659 iSCSIDiscoveryMethodStatic, B_FALSE); 1660 continue; 1661 } 1662 1663 /* 1664 * walk list of the statically configured targets from the 1665 * persistent store 1666 */ 1667 v = NULL; 1668 persistent_static_addr_lock(); 1669 while (persistent_static_addr_next(&v, name, &entry) == 1670 B_TRUE) { 1671 iscsi_sockaddr_t addr; 1672 1673 iscsid_addr_to_sockaddr(entry.e_insize, 1674 &(entry.e_u), entry.e_port, &addr.sin); 1675 1676 (void) iscsid_add(ihp, iSCSIDiscoveryMethodStatic, 1677 &addr.sin, name, entry.e_tpgt, &addr.sin); 1678 } 1679 persistent_static_addr_unlock(); 1680 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_FALSE); 1681 } 1682 } 1683 1684 1685 /* 1686 * iscsid_thread_sendtgts -- If SendTargets discovery is enabled, this routine 1687 * obtains all target discovery addresses configured from the peristent store 1688 * and probe the IP/port addresses for possible targets. It will then issue 1689 * a login request to the driver for all discoveryed targets. 1690 */ 1691 static void 1692 iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p) 1693 { 1694 iscsi_hba_t *ihp = (iscsi_hba_t *)p; 1695 iSCSIDiscoveryMethod_t dm; 1696 entry_t entry; 1697 void *v = NULL; 1698 1699 while (iscsi_thread_wait(thread, -1) != 0) { 1700 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets, 1701 B_TRUE); 1702 1703 /* ---- ensure SendTargets discovery is enabled ---- */ 1704 dm = persistent_disc_meth_get(); 1705 if ((dm & iSCSIDiscoveryMethodSendTargets) == 0) { 1706 cmn_err(CE_NOTE, 1707 "iscsi discovery failure - " 1708 "SendTargets method is not enabled"); 1709 iscsi_discovery_event(ihp, 1710 iSCSIDiscoveryMethodSendTargets, B_FALSE); 1711 continue; 1712 } 1713 /* 1714 * walk list of the SendTarget discovery addresses from the 1715 * persistent store 1716 */ 1717 v = NULL; 1718 persistent_disc_addr_lock(); 1719 while (persistent_disc_addr_next(&v, &entry) == B_TRUE) { 1720 iscsid_do_sendtgts(&entry); 1721 } 1722 persistent_disc_addr_unlock(); 1723 1724 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets, 1725 B_FALSE); 1726 } 1727 } 1728 1729 /* 1730 * iscsid_thread_slp -- If SLP discovery is enabled, this routine provides 1731 * the SLP discovery service. 1732 */ 1733 static void 1734 iscsid_thread_slp(iscsi_thread_t *thread, void *p) 1735 { 1736 iscsi_hba_t *ihp = (iscsi_hba_t *)p; 1737 1738 do { 1739 /* 1740 * Even though we don't have support for SLP at this point 1741 * we'll send the events if someone has enabled this thread. 1742 * If this is not done the daemon waiting for discovery to 1743 * complete will pause forever holding up the boot process. 1744 */ 1745 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_TRUE); 1746 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_FALSE); 1747 } while (iscsi_thread_wait(thread, -1) != 0); 1748 } 1749 1750 /* 1751 * iscsid_thread_isns -- 1752 */ 1753 static void 1754 iscsid_thread_isns(iscsi_thread_t *thread, void *ptr) 1755 { 1756 iscsi_hba_t *ihp = (iscsi_hba_t *)ptr; 1757 iSCSIDiscoveryMethod_t dm; 1758 1759 while (iscsi_thread_wait(thread, -1) != 0) { 1760 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_TRUE); 1761 1762 /* ---- ensure iSNS discovery is enabled ---- */ 1763 dm = persistent_disc_meth_get(); 1764 if ((dm & iSCSIDiscoveryMethodISNS) == 0) { 1765 cmn_err(CE_NOTE, 1766 "iscsi discovery failure - " 1767 "iSNS method is not enabled"); 1768 iscsi_discovery_event(ihp, 1769 iSCSIDiscoveryMethodISNS, B_FALSE); 1770 continue; 1771 } 1772 1773 (void) isns_reg(ihp->hba_isid, 1774 ihp->hba_name, 1775 ISCSI_MAX_NAME_LEN, 1776 ihp->hba_alias, 1777 ISCSI_MAX_NAME_LEN, 1778 ISNS_INITIATOR_NODE_TYPE, 1779 isns_scn_callback); 1780 iscsid_do_isns_query(ihp); 1781 iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_FALSE); 1782 } 1783 1784 /* Thread stopped. Deregister from iSNS servers(s). */ 1785 (void) isns_dereg(ihp->hba_isid, ihp->hba_name); 1786 } 1787 1788 1789 /* 1790 * iscsid_threads_create -- Creates all the discovery threads. 1791 */ 1792 static void 1793 iscsid_threads_create(iscsi_hba_t *ihp) 1794 { 1795 iscsid_thr_table *t; 1796 1797 /* 1798 * start a thread for each discovery method 1799 */ 1800 for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown; 1801 t++) { 1802 if (t->thr_id == NULL) { 1803 t->thr_id = iscsi_thread_create(ihp->hba_dip, t->name, 1804 t->func_start, ihp); 1805 } 1806 } 1807 } 1808 1809 /* 1810 * iscsid_threads_destroy -- Destroys all the discovery threads. 1811 */ 1812 static void 1813 iscsid_threads_destroy(void) 1814 { 1815 iscsid_thr_table *t; 1816 1817 for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown; 1818 t++) { 1819 if (t->thr_id != NULL) { 1820 iscsi_thread_destroy(t->thr_id); 1821 t->thr_id = NULL; 1822 } 1823 } 1824 } 1825 1826 /* 1827 * iscsid_copyto_param_set - helper function for iscsid_init_params. 1828 */ 1829 static int 1830 iscsid_copyto_param_set(uint32_t param_id, iscsi_login_params_t *params, 1831 iscsi_param_set_t *ipsp) 1832 { 1833 int rtn = 0; 1834 1835 if (param_id >= ISCSI_NUM_LOGIN_PARAM) { 1836 return (EINVAL); 1837 } 1838 1839 switch (param_id) { 1840 1841 /* 1842 * Boolean parameters 1843 */ 1844 case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER: 1845 ipsp->s_value.v_bool = params->data_pdu_in_order; 1846 break; 1847 case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA: 1848 ipsp->s_value.v_bool = params->immediate_data; 1849 break; 1850 case ISCSI_LOGIN_PARAM_INITIAL_R2T: 1851 ipsp->s_value.v_bool = params->initial_r2t; 1852 break; 1853 case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER: 1854 ipsp->s_value.v_bool = params->data_pdu_in_order; 1855 break; 1856 1857 /* 1858 * Integer parameters 1859 */ 1860 case ISCSI_LOGIN_PARAM_HEADER_DIGEST: 1861 ipsp->s_value.v_integer = params->header_digest; 1862 break; 1863 case ISCSI_LOGIN_PARAM_DATA_DIGEST: 1864 ipsp->s_value.v_integer = params->data_digest; 1865 break; 1866 case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN: 1867 ipsp->s_value.v_integer = params->default_time_to_retain; 1868 break; 1869 case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT: 1870 ipsp->s_value.v_integer = params->default_time_to_wait; 1871 break; 1872 case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH: 1873 ipsp->s_value.v_integer = params->max_recv_data_seg_len; 1874 break; 1875 case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH: 1876 ipsp->s_value.v_integer = params->first_burst_length; 1877 break; 1878 case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH: 1879 ipsp->s_value.v_integer = params->max_burst_length; 1880 break; 1881 1882 /* 1883 * Integer parameters which currently are unsettable 1884 */ 1885 case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS: 1886 case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T: 1887 case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL: 1888 /* ---- drop through to default case ---- */ 1889 default: 1890 rtn = EINVAL; 1891 break; 1892 } 1893 1894 /* if all is well, set the parameter identifier */ 1895 if (rtn == 0) { 1896 ipsp->s_param = param_id; 1897 } 1898 1899 return (rtn); 1900 } 1901 1902 /* 1903 * iscsid_add_pg_list_to_cache - Add portal groups in the list to the 1904 * discovery cache. 1905 */ 1906 static void 1907 iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp, 1908 isns_portal_group_list_t *pg_list) 1909 { 1910 int i; 1911 1912 for (i = 0; i < pg_list->pg_out_cnt; i++) { 1913 iscsi_sockaddr_t addr_dsc; 1914 iscsi_sockaddr_t addr_tgt; 1915 1916 iscsid_addr_to_sockaddr( 1917 pg_list->pg_list[i].isns_server_ip.i_insize, 1918 &pg_list->pg_list[i].isns_server_ip.i_addr, 1919 pg_list->pg_list[i].isns_server_port, 1920 &addr_dsc.sin); 1921 iscsid_addr_to_sockaddr( 1922 pg_list->pg_list[i].insize, 1923 &pg_list->pg_list[i].pg_ip_addr, 1924 pg_list->pg_list[i].pg_port, 1925 &addr_tgt.sin); 1926 1927 (void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS, &addr_dsc.sin, 1928 (char *)pg_list->pg_list[i].pg_iscsi_name, 1929 pg_list->pg_list[i].pg_tag, &addr_tgt.sin); 1930 } 1931 } 1932 1933 /* 1934 * set_initiator_name - set default initiator name and alias. 1935 * 1936 * This sets the default initiator name and alias. The 1937 * initiator name is composed of sun's reverse domain name 1938 * and registration followed and a unique classifier. This 1939 * classifier is the mac address of the first NIC in the 1940 * host and a timestamp to make sure the classifier is 1941 * unique if the NIC is moved between hosts. The alias 1942 * is just the hostname. 1943 */ 1944 void 1945 iscsid_set_default_initiator_node_settings(iscsi_hba_t *ihp, boolean_t minimal) 1946 { 1947 int i; 1948 time_t x; 1949 struct ether_addr eaddr; 1950 char val[10]; 1951 iscsi_chap_props_t *chap = NULL; 1952 1953 /* Set default initiator-node name */ 1954 if (iscsiboot_prop && iscsiboot_prop->boot_init.ini_name != NULL) { 1955 (void) strncpy((char *)ihp->hba_name, 1956 (const char *)iscsiboot_prop->boot_init.ini_name, 1957 ISCSI_MAX_NAME_LEN); 1958 } else { 1959 (void) snprintf((char *)ihp->hba_name, 1960 ISCSI_MAX_NAME_LEN, 1961 "iqn.1986-03.com.sun:01:"); 1962 1963 (void) localetheraddr(NULL, &eaddr); 1964 for (i = 0; i < ETHERADDRL; i++) { 1965 (void) snprintf(val, sizeof (val), "%02x", 1966 eaddr.ether_addr_octet[i]); 1967 (void) strncat((char *)ihp->hba_name, val, 1968 ISCSI_MAX_NAME_LEN); 1969 } 1970 1971 /* Set default initiator-node alias */ 1972 x = ddi_get_time(); 1973 (void) snprintf(val, sizeof (val), ".%lx", x); 1974 (void) strncat((char *)ihp->hba_name, val, ISCSI_MAX_NAME_LEN); 1975 1976 if (ihp->hba_alias[0] == '\0') { 1977 (void) strncpy((char *)ihp->hba_alias, 1978 utsname.nodename, ISCSI_MAX_NAME_LEN); 1979 ihp->hba_alias_length = strlen((char *)ihp->hba_alias); 1980 if (minimal == B_FALSE) { 1981 (void) persistent_alias_name_set( 1982 (char *)ihp->hba_alias); 1983 } 1984 } 1985 } 1986 1987 if (minimal == B_TRUE) { 1988 return; 1989 } 1990 1991 (void) persistent_initiator_name_set((char *)ihp->hba_name); 1992 1993 /* Set default initiator-node CHAP settings */ 1994 if (persistent_initiator_name_get((char *)ihp->hba_name, 1995 ISCSI_MAX_NAME_LEN) == B_TRUE) { 1996 chap = (iscsi_chap_props_t *)kmem_zalloc(sizeof (*chap), 1997 KM_SLEEP); 1998 if (persistent_chap_get((char *)ihp->hba_name, chap) == 1999 B_FALSE) { 2000 bcopy((char *)ihp->hba_name, chap->c_user, 2001 strlen((char *)ihp->hba_name)); 2002 chap->c_user_len = strlen((char *)ihp->hba_name); 2003 (void) persistent_chap_set((char *)ihp->hba_name, chap); 2004 } 2005 kmem_free(chap, sizeof (*chap)); 2006 } 2007 } 2008 2009 static void 2010 iscsid_remove_target_param(char *name) 2011 { 2012 persistent_param_t *pparam; 2013 uint32_t t_oid; 2014 iscsi_config_sess_t *ics; 2015 2016 ASSERT(name != NULL); 2017 2018 /* 2019 * Remove target-param <-> target mapping. 2020 * Only remove if there is not any overridden 2021 * parameters in the persistent store 2022 */ 2023 pparam = (persistent_param_t *)kmem_zalloc(sizeof (*pparam), KM_SLEEP); 2024 2025 /* 2026 * setup initial buffer for configured session 2027 * information 2028 */ 2029 ics = (iscsi_config_sess_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP); 2030 ics->ics_in = 1; 2031 2032 if ((persistent_param_get(name, pparam) == B_FALSE) && 2033 (persistent_get_config_session(name, ics) == B_FALSE)) { 2034 t_oid = iscsi_targetparam_get_oid((uchar_t *)name); 2035 (void) iscsi_targetparam_remove_target(t_oid); 2036 } 2037 2038 kmem_free(pparam, sizeof (*pparam)); 2039 pparam = NULL; 2040 kmem_free(ics, sizeof (*ics)); 2041 ics = NULL; 2042 } 2043 2044 /* 2045 * iscsid_addr_to_sockaddr - convert other types to struct sockaddr 2046 */ 2047 void 2048 iscsid_addr_to_sockaddr(int src_insize, void *src_addr, int src_port, 2049 struct sockaddr *dst_addr) 2050 { 2051 ASSERT((src_insize == sizeof (struct in_addr)) || 2052 (src_insize == sizeof (struct in6_addr))); 2053 ASSERT(src_addr != NULL); 2054 ASSERT(dst_addr != NULL); 2055 2056 bzero(dst_addr, sizeof (*dst_addr)); 2057 2058 /* translate discovery information */ 2059 if (src_insize == sizeof (struct in_addr)) { 2060 struct sockaddr_in *addr_in = 2061 (struct sockaddr_in *)dst_addr; 2062 addr_in->sin_family = AF_INET; 2063 bcopy(src_addr, &addr_in->sin_addr.s_addr, 2064 sizeof (struct in_addr)); 2065 addr_in->sin_port = htons(src_port); 2066 } else { 2067 struct sockaddr_in6 *addr_in6 = 2068 (struct sockaddr_in6 *)dst_addr; 2069 addr_in6->sin6_family = AF_INET6; 2070 bcopy(src_addr, &addr_in6->sin6_addr.s6_addr, 2071 sizeof (struct in6_addr)); 2072 addr_in6->sin6_port = htons(src_port); 2073 } 2074 } 2075 2076 /* 2077 * iscsi_discovery_event -- send event associated with discovery operations 2078 * 2079 * Each discovery event has a start and end event. Which is sent is based 2080 * on the boolean argument start with the obvious results. 2081 */ 2082 static void 2083 iscsi_discovery_event(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t m, 2084 boolean_t start) 2085 { 2086 char *subclass = NULL; 2087 2088 mutex_enter(&ihp->hba_discovery_events_mutex); 2089 switch (m) { 2090 case iSCSIDiscoveryMethodStatic: 2091 if (start == B_TRUE) { 2092 subclass = ESC_ISCSI_STATIC_START; 2093 } else { 2094 ihp->hba_discovery_events |= iSCSIDiscoveryMethodStatic; 2095 subclass = ESC_ISCSI_STATIC_END; 2096 } 2097 break; 2098 2099 case iSCSIDiscoveryMethodSendTargets: 2100 if (start == B_TRUE) { 2101 subclass = ESC_ISCSI_SEND_TARGETS_START; 2102 } else { 2103 ihp->hba_discovery_events |= 2104 iSCSIDiscoveryMethodSendTargets; 2105 subclass = ESC_ISCSI_SEND_TARGETS_END; 2106 } 2107 break; 2108 2109 case iSCSIDiscoveryMethodSLP: 2110 if (start == B_TRUE) { 2111 subclass = ESC_ISCSI_SLP_START; 2112 } else { 2113 ihp->hba_discovery_events |= iSCSIDiscoveryMethodSLP; 2114 subclass = ESC_ISCSI_SLP_END; 2115 } 2116 break; 2117 2118 case iSCSIDiscoveryMethodISNS: 2119 if (start == B_TRUE) { 2120 subclass = ESC_ISCSI_ISNS_START; 2121 } else { 2122 ihp->hba_discovery_events |= iSCSIDiscoveryMethodISNS; 2123 subclass = ESC_ISCSI_ISNS_END; 2124 } 2125 break; 2126 } 2127 mutex_exit(&ihp->hba_discovery_events_mutex); 2128 iscsi_send_sysevent(ihp, EC_ISCSI, subclass, NULL); 2129 } 2130 2131 /* 2132 * iscsi_send_sysevent -- send sysevent using specified class 2133 */ 2134 void 2135 iscsi_send_sysevent( 2136 iscsi_hba_t *ihp, 2137 char *eventclass, 2138 char *subclass, 2139 nvlist_t *np) 2140 { 2141 (void) ddi_log_sysevent(ihp->hba_dip, DDI_VENDOR_SUNW, eventclass, 2142 subclass, np, NULL, DDI_SLEEP); 2143 } 2144 2145 static boolean_t 2146 iscsid_boot_init_config(iscsi_hba_t *ihp) 2147 { 2148 if (strlen((const char *)iscsiboot_prop->boot_init.ini_name) != 0) { 2149 bcopy(iscsiboot_prop->boot_init.ini_name, 2150 ihp->hba_name, 2151 strlen((const char *)iscsiboot_prop->boot_init.ini_name)); 2152 } 2153 /* or using default login param for boot session */ 2154 return (B_TRUE); 2155 } 2156 2157 boolean_t 2158 iscsi_reconfig_boot_sess(iscsi_hba_t *ihp) 2159 { 2160 iscsi_config_sess_t *ics; 2161 int idx; 2162 iscsi_sess_t *isp, *t_isp; 2163 int isid, size; 2164 char *name; 2165 boolean_t rtn = B_TRUE; 2166 2167 if (iscsiboot_prop == NULL) { 2168 return (B_FALSE); 2169 } 2170 size = sizeof (*ics); 2171 ics = kmem_zalloc(size, KM_SLEEP); 2172 ics->ics_in = 1; 2173 2174 /* get information of number of sessions to be configured */ 2175 name = (char *)iscsiboot_prop->boot_tgt.tgt_name; 2176 if (persistent_get_config_session(name, ics) == B_FALSE) { 2177 /* 2178 * No target information available to check 2179 * initiator information. Assume one session 2180 * by default. 2181 */ 2182 name = (char *)iscsiboot_prop->boot_init.ini_name; 2183 if (persistent_get_config_session(name, ics) == B_FALSE) { 2184 ics->ics_out = 1; 2185 ics->ics_bound = B_TRUE; 2186 } 2187 } 2188 2189 /* get necessary information */ 2190 if (ics->ics_out > 1) { 2191 idx = ics->ics_out; 2192 size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out); 2193 kmem_free(ics, sizeof (*ics)); 2194 2195 ics = kmem_zalloc(size, KM_SLEEP); 2196 ics->ics_in = idx; 2197 2198 /* get configured sessions information */ 2199 if (persistent_get_config_session((char *)name, 2200 ics) != B_TRUE) { 2201 cmn_err(CE_NOTE, "session(%s) - " 2202 "failed to setup multiple sessions", 2203 name); 2204 kmem_free(ics, size); 2205 return (B_FALSE); 2206 } 2207 } 2208 2209 /* create a temporary session to keep boot session connective */ 2210 t_isp = iscsi_add_boot_sess(ihp, ISCSI_MAX_CONFIG_SESSIONS); 2211 if (t_isp == NULL) { 2212 cmn_err(CE_NOTE, "session(%s) - " 2213 "failed to setup multiple sessions", name); 2214 rw_exit(&ihp->hba_sess_list_rwlock); 2215 kmem_free(ics, size); 2216 return (B_FALSE); 2217 } 2218 2219 /* destroy all old boot sessions */ 2220 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 2221 isp = ihp->hba_sess_list; 2222 while (isp != NULL) { 2223 if (iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) { 2224 if (isp->sess_isid[5] != ISCSI_MAX_CONFIG_SESSIONS) { 2225 /* 2226 * destroy all stale sessions 2227 * except temporary boot session 2228 */ 2229 if (ISCSI_SUCCESS(iscsi_sess_destroy( 2230 isp))) { 2231 isp = ihp->hba_sess_list; 2232 } else { 2233 /* 2234 * couldn't destroy stale sessions 2235 * at least poke it to disconnect 2236 */ 2237 mutex_enter(&isp->sess_state_mutex); 2238 iscsi_sess_state_machine(isp, 2239 ISCSI_SESS_EVENT_N7); 2240 mutex_exit(&isp->sess_state_mutex); 2241 isp = isp->sess_next; 2242 cmn_err(CE_NOTE, "session(%s) - " 2243 "failed to setup multiple" 2244 " sessions", name); 2245 } 2246 } else { 2247 isp = isp->sess_next; 2248 } 2249 } else { 2250 isp = isp->sess_next; 2251 } 2252 } 2253 rw_exit(&ihp->hba_sess_list_rwlock); 2254 2255 for (isid = 0; isid < ics->ics_out; isid++) { 2256 isp = iscsi_add_boot_sess(ihp, isid); 2257 if (isp == NULL) { 2258 cmn_err(CE_NOTE, "session(%s) - failed to setup" 2259 " multiple sessions", name); 2260 rtn = B_FALSE; 2261 break; 2262 } 2263 } 2264 if (!rtn && (isid == 0)) { 2265 /* 2266 * fail to create any new boot session 2267 * so only the temporary session is alive 2268 * quit without destroying it 2269 */ 2270 kmem_free(ics, size); 2271 return (rtn); 2272 } 2273 2274 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 2275 if (!ISCSI_SUCCESS(iscsi_sess_destroy(t_isp))) { 2276 /* couldn't destroy temp boot session */ 2277 cmn_err(CE_NOTE, "session(%s) - " 2278 "failed to setup multiple sessions", name); 2279 rw_exit(&ihp->hba_sess_list_rwlock); 2280 rtn = B_FALSE; 2281 } 2282 rw_exit(&ihp->hba_sess_list_rwlock); 2283 2284 kmem_free(ics, size); 2285 return (rtn); 2286 } 2287 2288 static iscsi_sess_t * 2289 iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid) 2290 { 2291 iscsi_sess_t *isp; 2292 iscsi_conn_t *icp; 2293 uint_t oid; 2294 2295 iscsi_sockaddr_t addr_dst; 2296 2297 addr_dst.sin.sa_family = iscsiboot_prop->boot_tgt.sin_family; 2298 if (addr_dst.sin.sa_family == AF_INET) { 2299 bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in4.s_addr, 2300 &addr_dst.sin4.sin_addr.s_addr, sizeof (struct in_addr)); 2301 addr_dst.sin4.sin_port = 2302 htons(iscsiboot_prop->boot_tgt.tgt_port); 2303 } else { 2304 bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in6.s6_addr, 2305 &addr_dst.sin6.sin6_addr.s6_addr, 2306 sizeof (struct in6_addr)); 2307 addr_dst.sin6.sin6_port = 2308 htons(iscsiboot_prop->boot_tgt.tgt_port); 2309 } 2310 2311 rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER); 2312 isp = iscsi_sess_create(ihp, 2313 iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic, 2314 (struct sockaddr *)&addr_dst, 2315 (char *)iscsiboot_prop->boot_tgt.tgt_name, 2316 ISCSI_DEFAULT_TPGT, isid, ISCSI_SESS_TYPE_NORMAL, &oid); 2317 if (isp == NULL) { 2318 /* create temp booting session failed */ 2319 rw_exit(&ihp->hba_sess_list_rwlock); 2320 return (NULL); 2321 } 2322 isp->sess_boot = B_TRUE; 2323 2324 if (!ISCSI_SUCCESS(iscsi_conn_create((struct sockaddr *)&addr_dst, 2325 isp, &icp))) { 2326 rw_exit(&ihp->hba_sess_list_rwlock); 2327 return (NULL); 2328 } 2329 2330 rw_exit(&ihp->hba_sess_list_rwlock); 2331 /* now online created session */ 2332 if (iscsid_login_tgt(ihp, (char *)iscsiboot_prop->boot_tgt.tgt_name, 2333 iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic, 2334 (struct sockaddr *)&addr_dst) == B_FALSE) { 2335 return (NULL); 2336 } 2337 2338 return (isp); 2339 } 2340 2341 static void 2342 iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p) 2343 { 2344 int rc = 1; 2345 iscsi_hba_t *ihp = (iscsi_hba_t *)p; 2346 boolean_t reconfigured = B_FALSE; 2347 2348 while (rc != 0) { 2349 if (iscsiboot_prop && (modrootloaded == 1)) { 2350 if (ihp->hba_persistent_loaded == B_FALSE) { 2351 if (persistent_load() == B_TRUE) { 2352 ihp->hba_persistent_loaded = B_TRUE; 2353 } 2354 } 2355 if ((ihp->hba_persistent_loaded == B_TRUE) && 2356 (reconfigured == B_FALSE)) { 2357 if (iscsi_chk_bootlun_mpxio(ihp) == B_TRUE) { 2358 (void) iscsi_reconfig_boot_sess(ihp); 2359 iscsid_poke_discovery(ihp, 2360 iSCSIDiscoveryMethodUnknown); 2361 (void) iscsid_login_tgt(ihp, NULL, 2362 iSCSIDiscoveryMethodUnknown, NULL); 2363 } 2364 reconfigured = B_TRUE; 2365 } 2366 break; 2367 } 2368 rc = iscsi_thread_wait(thread, SEC_TO_TICK(1)); 2369 } 2370 } 2371 2372 boolean_t 2373 iscsi_cmp_boot_tgt_name(char *name) 2374 { 2375 if (iscsiboot_prop && (strncmp((const char *)name, 2376 (const char *)iscsiboot_prop->boot_tgt.tgt_name, 2377 ISCSI_MAX_NAME_LEN) == 0)) { 2378 return (B_TRUE); 2379 } else { 2380 return (B_FALSE); 2381 } 2382 } 2383 2384 boolean_t 2385 iscsi_cmp_boot_ini_name(char *name) 2386 { 2387 if (iscsiboot_prop && (strncmp((const char *)name, 2388 (const char *)iscsiboot_prop->boot_init.ini_name, 2389 ISCSI_MAX_NAME_LEN) == 0)) { 2390 return (B_TRUE); 2391 } else { 2392 return (B_FALSE); 2393 } 2394 } 2395 2396 boolean_t 2397 iscsi_chk_bootlun_mpxio(iscsi_hba_t *ihp) 2398 { 2399 iscsi_sess_t *isp; 2400 iscsi_lun_t *ilp; 2401 isp = ihp->hba_sess_list; 2402 boolean_t tgt_mpxio_enabled = B_FALSE; 2403 boolean_t bootlun_found = B_FALSE; 2404 uint16_t lun_num; 2405 2406 if (iscsiboot_prop == NULL) { 2407 return (B_FALSE); 2408 } 2409 2410 if (!ihp->hba_mpxio_enabled) { 2411 return (B_FALSE); 2412 } 2413 2414 lun_num = *((uint64_t *)(iscsiboot_prop->boot_tgt.tgt_boot_lun)); 2415 2416 while (isp != NULL) { 2417 if ((strncmp((char *)isp->sess_name, 2418 (const char *)iscsiboot_prop->boot_tgt.tgt_name, 2419 ISCSI_MAX_NAME_LEN) == 0) && 2420 (isp->sess_boot == B_TRUE)) { 2421 /* 2422 * found boot session. 2423 * check its mdi path info is null or not 2424 */ 2425 ilp = isp->sess_lun_list; 2426 while (ilp != NULL) { 2427 if (lun_num == ilp->lun_num) { 2428 if (ilp->lun_pip) { 2429 tgt_mpxio_enabled = B_TRUE; 2430 } 2431 bootlun_found = B_TRUE; 2432 } 2433 ilp = ilp->lun_next; 2434 } 2435 } 2436 isp = isp->sess_next; 2437 } 2438 if (bootlun_found) { 2439 return (tgt_mpxio_enabled); 2440 } else { 2441 /* 2442 * iscsiboot_prop not NULL while no boot lun found 2443 * in most cases this is none iscsi boot while iscsiboot_prop 2444 * is not NULL, in this scenario return iscsi HBA's mpxio config 2445 */ 2446 return (ihp->hba_mpxio_enabled); 2447 } 2448 } 2449