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