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