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