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