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 #include "iscsi.h" 27 #include "nvfile.h" 28 #include "persistent.h" 29 #include <sys/scsi/adapters/iscsi_if.h> 30 #include <netinet/in.h> 31 32 /* 33 * MAX_KEY_SIZE needs to be the same size of the ISCSI_MAX_NAME_LEN 34 * plus space for a ',' and a string form of tpgt (5 bytes). 35 */ 36 #define MAX_KEY_SIZE (ISCSI_MAX_NAME_LEN + 5) 37 38 /* 39 * Name identifiers for the various types of data 40 */ 41 #define DISCOVERY_METHOD_ID "DiscMethod" 42 #define NODE_NAME_ID "NodeName" 43 #define NODE_ALIAS_ID "NodeAlias" 44 #define STATIC_ADDR_ID "StaticAddr" 45 #define STATIC_ADDR2_ID "StaticAddr2" 46 #define DISCOVERY_ADDR_ID "DiscAddr" 47 #define ISNS_SERVER_ADDR_ID "ISNSAddr" 48 #define LOGIN_PARAMS_ID "Login" 49 #define CHAP_PARAMS_ID "Chap" 50 #define RADIUS_PARAMS_ID "Radius" 51 #define BIDIR_AUTH_PARAMS_ID "BidirAuth" 52 #define SESSION_PARAMS_ID "Session" 53 #define TUNABLE_PARAMS_ID "Tunable" 54 55 /* 56 * Local Global Variables 57 */ 58 static kmutex_t static_addr_data_lock; 59 static kmutex_t disc_addr_data_lock; 60 static kmutex_t isns_addr_data_lock; 61 static kmutex_t param_data_lock; 62 static kmutex_t chap_data_lock; 63 static kmutex_t auth_data_lock; 64 static kmutex_t tunable_data_lock; 65 /* 66 * Local Function Prototypes 67 */ 68 static boolean_t persistent_disc_meth_common(iSCSIDiscoveryMethod_t method, 69 boolean_t do_clear); 70 static void persistent_static_addr_upgrade_to_v2(); 71 72 /* 73 * persistent_init_disc_addr_oids - Oid is stored with discovery address 74 * however oids are not persisted and the discovery address oids need to 75 * be regenerated during initialization. 76 */ 77 static void persistent_init_disc_addr_oids() 78 { 79 uint32_t addr_count = 0; 80 void *void_p = NULL; 81 entry_t e; 82 uint32_t i, curr_count; 83 84 /* 85 * Using two loops here as as addresses are updated and readded we get 86 * into an infinite loop while doing persistent_disc_addr_next if we 87 * update the entry as we go. The first loop will get the number of 88 * addresses that need to be updated and the second will update that 89 * many addresses. 90 */ 91 persistent_disc_addr_lock(); 92 while (persistent_disc_addr_next(&void_p, &e) == B_TRUE) { 93 addr_count++; 94 } 95 persistent_disc_addr_unlock(); 96 97 for (i = 0; i < addr_count; i++) { 98 curr_count = 0; 99 100 void_p = NULL; 101 persistent_disc_addr_lock(); 102 103 /* Use curr_count to skip previously updated addresses */ 104 while (persistent_disc_addr_next(&void_p, &e) == 105 B_TRUE && i < curr_count) { 106 curr_count++; 107 } 108 persistent_disc_addr_unlock(); 109 110 mutex_enter(&iscsi_oid_mutex); 111 e.e_oid = iscsi_oid++; 112 mutex_exit(&iscsi_oid_mutex); 113 114 if (persistent_disc_addr_set(&e) == B_FALSE) { 115 break; 116 } 117 } 118 } 119 120 /* 121 * persistent_init_static_addr_oids - Oid is stored with static address 122 * however oids are not persisted and the static address oids need to 123 * be regenerated during initialization. 124 */ 125 static void persistent_init_static_addr_oids() 126 { 127 uint32_t addr_count = 0; 128 void *void_p = NULL; 129 entry_t e; 130 uint32_t i, curr_count; 131 char *target_name; 132 133 /* 134 * Solaris 10 Update 1/2 initially had a database 135 * that didn't support the multiple static-config 136 * entries to the same target. The below call 137 * will check if the database is still of that 138 * old structure and upgrade it. It will leave 139 * the old records incase a down grade of the 140 * software is required. 141 */ 142 persistent_static_addr_upgrade_to_v2(); 143 144 /* 145 * Using two loops here as as addresses are updated and readded we get 146 * into an infinite loop while doing persistent_disc_addr_next if we 147 * update the entry as we go. The first loop will get the number of 148 * addresses that need to be updated and the second will update that 149 * many addresses. 150 */ 151 target_name = kmem_alloc(MAX_KEY_SIZE, KM_SLEEP); 152 persistent_static_addr_lock(); 153 while (persistent_static_addr_next(&void_p, target_name, &e) == 154 B_TRUE) { 155 addr_count++; 156 } 157 158 for (i = 0; i < addr_count; i++) { 159 curr_count = 0; 160 161 void_p = NULL; 162 163 /* Use curr_count to skip previously updated addresses */ 164 while ((persistent_static_addr_next( 165 &void_p, target_name, &e) == B_TRUE) && 166 (i < curr_count)) { 167 curr_count++; 168 } 169 170 /* Skip the target whose address size length is 0 */ 171 if (e.e_insize == 0) { 172 continue; 173 } 174 175 mutex_enter(&iscsi_oid_mutex); 176 e.e_oid = iscsi_oid++; 177 mutex_exit(&iscsi_oid_mutex); 178 179 if (persistent_static_addr_set(target_name, &e) == B_FALSE) { 180 break; 181 } 182 } 183 persistent_static_addr_unlock(); 184 kmem_free(target_name, MAX_KEY_SIZE); 185 } 186 187 /* 188 * persistent_static_addr_upgrade_to_v2 - checks to see if the 189 * STATIC_ADDR2_ID exists in the persistent store tree. If not 190 * found then it converts the STATIC_ADDR_ID data into the 191 * STATIC_ADDR2_ID format and saves the branch. 192 */ 193 static void 194 persistent_static_addr_upgrade_to_v2() 195 { 196 entry_t e; 197 char *target_name; 198 char *c_end; 199 void *void_p = NULL; 200 201 /* 202 * Check is version 2 of STATIC_ADDR list exists. 203 */ 204 target_name = kmem_zalloc(MAX_KEY_SIZE, KM_SLEEP); 205 persistent_static_addr_lock(); 206 if (nvf_list_check(STATIC_ADDR2_ID) == B_FALSE) { 207 /* 208 * We need to upgrade any existing 209 * STATIC_ADDR data to version 2. Loop 210 * thru all old entries and set new version 211 * values. 212 */ 213 while (nvf_data_next(STATIC_ADDR_ID, &void_p, 214 target_name, (void *)&e, sizeof (e)) == B_TRUE) { 215 /* Convert STATIC_ADDR to STATIC_ADDR2 */ 216 c_end = strchr(target_name, ','); 217 if (c_end == NULL) { 218 continue; 219 } 220 *c_end = '\0'; 221 /* Skip the target whose address size length is 0 */ 222 if (e.e_insize == 0) { 223 continue; 224 } 225 /* Add updated record */ 226 (void) persistent_static_addr_set(target_name, &e); 227 } 228 } 229 persistent_static_addr_unlock(); 230 kmem_free(target_name, MAX_KEY_SIZE); 231 } 232 233 /* 234 * persistent_init -- initialize use of the persistent store 235 */ 236 void 237 persistent_init() 238 { 239 nvf_init(); 240 mutex_init(&static_addr_data_lock, NULL, MUTEX_DRIVER, NULL); 241 mutex_init(&disc_addr_data_lock, NULL, MUTEX_DRIVER, NULL); 242 mutex_init(&isns_addr_data_lock, NULL, MUTEX_DRIVER, NULL); 243 mutex_init(¶m_data_lock, NULL, MUTEX_DRIVER, NULL); 244 mutex_init(&chap_data_lock, NULL, MUTEX_DRIVER, NULL); 245 mutex_init(&auth_data_lock, NULL, MUTEX_DRIVER, NULL); 246 mutex_init(&tunable_data_lock, NULL, MUTEX_DRIVER, NULL); 247 } 248 249 /* 250 * persistent_load -- load the persistent store 251 */ 252 boolean_t 253 persistent_load() 254 { 255 boolean_t rval = B_FALSE; 256 257 rval = nvf_load(); 258 if (rval == B_TRUE) { 259 persistent_init_disc_addr_oids(); 260 persistent_init_static_addr_oids(); 261 } 262 263 return (rval); 264 } 265 266 /* 267 * persistent_fini -- finish using the persistent store 268 */ 269 void 270 persistent_fini(void) 271 { 272 nvf_fini(); 273 274 mutex_destroy(&static_addr_data_lock); 275 mutex_destroy(&disc_addr_data_lock); 276 mutex_destroy(¶m_data_lock); 277 mutex_destroy(&chap_data_lock); 278 mutex_destroy(&auth_data_lock); 279 mutex_destroy(&tunable_data_lock); 280 } 281 282 283 /* 284 * +--------------------------------------------------------------------+ 285 * | Discovery Method Interfaces | 286 * +--------------------------------------------------------------------+ 287 */ 288 289 /* 290 * persistent_disc_meth_set -- enable a specific discovery method 291 */ 292 boolean_t 293 persistent_disc_meth_set(iSCSIDiscoveryMethod_t method) 294 { 295 return (persistent_disc_meth_common(method, B_FALSE)); 296 } 297 298 /* 299 * persistent_disc_meth_get -- return the status of all discovery methods as 300 * found in the persistent store 301 */ 302 iSCSIDiscoveryMethod_t 303 persistent_disc_meth_get(void) 304 { 305 boolean_t rval; 306 iSCSIDiscoveryMethod_t methods; 307 308 rval = nvf_node_value_get(DISCOVERY_METHOD_ID, (uint32_t *)&methods); 309 if (rval == B_FALSE) { 310 methods = iSCSIDiscoveryMethodUnknown; 311 } 312 313 return (methods); 314 } 315 316 /* 317 * persistent_disc_meth_clear -- disable a specific discovery method 318 */ 319 boolean_t 320 persistent_disc_meth_clear(iSCSIDiscoveryMethod_t method) 321 { 322 return (persistent_disc_meth_common(method, B_TRUE)); 323 } 324 325 326 327 /* 328 * persistent_disc_meth_common - common function used to set or clear the 329 * status of a discovery method in the persistent store. 330 */ 331 static boolean_t 332 persistent_disc_meth_common(iSCSIDiscoveryMethod_t method, boolean_t do_clear) 333 { 334 boolean_t rval; 335 iSCSIDiscoveryMethod_t discovery_types = iSCSIDiscoveryMethodUnknown; 336 337 (void) nvf_node_value_get(DISCOVERY_METHOD_ID, 338 (uint32_t *)&discovery_types); 339 if (do_clear) { 340 discovery_types &= ~method; 341 } else { 342 discovery_types |= method; 343 } 344 345 rval = nvf_node_value_set(DISCOVERY_METHOD_ID, discovery_types); 346 347 return (rval); 348 } 349 350 351 352 /* 353 * +--------------------------------------------------------------------+ 354 * | Node/Initiator Name Interfaces | 355 * +--------------------------------------------------------------------+ 356 */ 357 358 /* 359 * persistent_initiator_name_set -- sets the node's initiator name 360 */ 361 boolean_t 362 persistent_initiator_name_set(char *p) 363 { 364 return (nvf_node_name_set(NODE_NAME_ID, p)); 365 } 366 367 /* 368 * persistent_initiator_name_get -- returns the node's initiator name 369 */ 370 boolean_t 371 persistent_initiator_name_get(char *p, int size) 372 { 373 return (nvf_node_name_get(NODE_NAME_ID, p, size)); 374 } 375 376 377 /* 378 * +--------------------------------------------------------------------+ 379 * | Node/Initiator Alias Interfaces | 380 * +--------------------------------------------------------------------+ 381 */ 382 383 /* 384 * persistent_alias_name_set -- sets the node's initiator name alias 385 */ 386 boolean_t 387 persistent_alias_name_set(char *p) 388 { 389 return (nvf_node_name_set(NODE_ALIAS_ID, p)); 390 } 391 392 /* 393 * persistent_initiator_name_get -- returns the node's initiator name alias 394 */ 395 boolean_t 396 persistent_alias_name_get(char *p, int size) 397 { 398 return (nvf_node_name_get(NODE_ALIAS_ID, p, size)); 399 } 400 401 402 /* 403 * +--------------------------------------------------------------------+ 404 * | Static Target Address Interfaces | 405 * +--------------------------------------------------------------------+ 406 */ 407 408 /* 409 * persistent_static_addr_set -- store hostname, IP address, and port 410 * information for a specific target. 411 */ 412 boolean_t 413 persistent_static_addr_set(char *target_name, entry_t *e) 414 { 415 boolean_t rval; 416 char *key; 417 char *ip_str; 418 419 ASSERT(target_name != NULL); 420 ASSERT(e != NULL); 421 ASSERT(mutex_owned(&static_addr_data_lock)); 422 423 key = kmem_zalloc(MAX_KEY_SIZE, KM_SLEEP); 424 ip_str = kmem_zalloc(INET6_ADDRSTRLEN, KM_SLEEP); 425 if (e->e_insize == sizeof (struct in_addr)) { 426 (void) inet_ntop(AF_INET, &e->e_u.u_in4, 427 ip_str, INET6_ADDRSTRLEN); 428 } else { 429 (void) inet_ntop(AF_INET6, &e->e_u.u_in6, 430 ip_str, INET6_ADDRSTRLEN); 431 } 432 433 if (snprintf(key, MAX_KEY_SIZE - 1, "%s,%s:%d,%d", 434 target_name, ip_str, e->e_port, e->e_tpgt) >= MAX_KEY_SIZE) { 435 kmem_free(key, MAX_KEY_SIZE); 436 kmem_free(ip_str, INET6_ADDRSTRLEN); 437 return (B_FALSE); 438 } 439 440 rval = nvf_data_set(STATIC_ADDR2_ID, key, (void *)e, 441 sizeof (entry_t)); 442 443 kmem_free(key, MAX_KEY_SIZE); 444 kmem_free(ip_str, INET6_ADDRSTRLEN); 445 return (rval); 446 } 447 448 /* 449 * persistent_static_addr_next -- get the next target's hostname, IP address, 450 * and port information. 451 * 452 * The first time this function is called, the argument (void **v) 453 * should be a pointer to a value of NULL which causes this function to obtain 454 * the first static target element. 455 * 456 * This function assumes the associated static address lock is held. 457 * 458 * Returns B_TRUE when data is valid. B_FALSE returned when data is 459 * not available (end of configured targets has been reached). 460 * 461 */ 462 boolean_t 463 persistent_static_addr_next(void **v, char *target_name, entry_t *e) 464 { 465 boolean_t rval; 466 char *c_end, *key; 467 468 ASSERT(v != NULL); 469 ASSERT(target_name != NULL); 470 ASSERT(e != NULL); 471 ASSERT(mutex_owned(&static_addr_data_lock)); 472 473 key = kmem_zalloc(MAX_KEY_SIZE, KM_SLEEP); 474 rval = nvf_data_next(STATIC_ADDR2_ID, v, key, 475 (void *)e, sizeof (*e)); 476 477 /* extract target_name */ 478 c_end = strchr(key, ','); 479 if (c_end == NULL) { 480 kmem_free(key, MAX_KEY_SIZE); 481 return (B_FALSE); 482 } 483 *c_end = '\0'; 484 /* copy target name */ 485 (void) strcpy(target_name, key); 486 487 kmem_free(key, MAX_KEY_SIZE); 488 489 return (rval); 490 } 491 492 /* 493 * persistent_static_addr_clear -- remove the next hostname, IP address, and 494 * port information for a specific target from the configured static targets. 495 */ 496 boolean_t 497 persistent_static_addr_clear(uint32_t oid) 498 { 499 boolean_t rval = B_FALSE; 500 void *void_p = NULL; 501 entry_t e; 502 char *key; 503 char *target_name; 504 char *ip_str; 505 506 /* Find the entry based on oid then record the name and tpgt */ 507 target_name = kmem_zalloc(MAX_KEY_SIZE, KM_SLEEP); 508 persistent_static_addr_lock(); 509 while (persistent_static_addr_next( 510 &void_p, target_name, &e) == B_TRUE) { 511 if (e.e_oid == oid) { 512 break; 513 } 514 } 515 516 /* If we found a match clear the entry */ 517 if (e.e_oid == oid) { 518 ip_str = kmem_zalloc(INET6_ADDRSTRLEN, KM_SLEEP); 519 key = kmem_zalloc(MAX_KEY_SIZE, KM_SLEEP); 520 if (e.e_insize == sizeof (struct in_addr)) { 521 (void) inet_ntop(AF_INET, &e.e_u.u_in4, 522 ip_str, INET6_ADDRSTRLEN); 523 } else { 524 (void) inet_ntop(AF_INET6, &e.e_u.u_in6, 525 ip_str, INET6_ADDRSTRLEN); 526 } 527 528 if (snprintf(key, MAX_KEY_SIZE - 1, "%s,%s:%d,%d", 529 target_name, ip_str, e.e_port, e.e_tpgt) >= MAX_KEY_SIZE) { 530 persistent_static_addr_unlock(); 531 kmem_free(key, MAX_KEY_SIZE); 532 kmem_free(ip_str, INET6_ADDRSTRLEN); 533 kmem_free(target_name, MAX_KEY_SIZE); 534 return (B_FALSE); 535 } 536 537 rval = nvf_data_clear(STATIC_ADDR2_ID, key); 538 kmem_free(key, MAX_KEY_SIZE); 539 kmem_free(ip_str, INET6_ADDRSTRLEN); 540 } 541 persistent_static_addr_unlock(); 542 kmem_free(target_name, MAX_KEY_SIZE); 543 544 return (rval); 545 } 546 547 548 /* 549 * persistent_static_addr_lock -- lock access to static targets. This 550 * ensures static targets are unchanged while the lock is held. The 551 * lock should be grabbed while walking through the static targets. 552 */ 553 void 554 persistent_static_addr_lock(void) 555 { 556 mutex_enter(&static_addr_data_lock); 557 } 558 559 /* 560 * persistent_static_addr_unlock -- unlock access to the configured of static 561 * targets. 562 */ 563 void 564 persistent_static_addr_unlock(void) 565 { 566 mutex_exit(&static_addr_data_lock); 567 } 568 569 570 /* 571 * +--------------------------------------------------------------------+ 572 * | ISNS Server Address Interfaces | 573 * +--------------------------------------------------------------------+ 574 */ 575 576 /* 577 * persistent_addr_set -- store entry address information 578 */ 579 boolean_t 580 persistent_isns_addr_set(entry_t *e) 581 { 582 char name[INET6_ADDRSTRLEN]; 583 boolean_t rval; 584 585 /* 586 * Create name from given discovery address - SendTargets discovery 587 * nodes do not have an associated node name. A name is manufactured 588 * from the IP address given. 589 */ 590 if (e->e_insize == sizeof (struct in_addr)) { 591 (void) inet_ntop(AF_INET, &e->e_u.u_in4, name, sizeof (name)); 592 } else { 593 (void) inet_ntop(AF_INET6, &e->e_u.u_in6, name, sizeof (name)); 594 } 595 596 mutex_enter(&isns_addr_data_lock); 597 rval = nvf_data_set(ISNS_SERVER_ADDR_ID, name, 598 (void *)e, sizeof (entry_t)); 599 mutex_exit(&isns_addr_data_lock); 600 601 return (rval); 602 } 603 604 /* 605 * persistent_disc_addr_next -- get the next iSCSI discovery node's address 606 * and port information. 607 * 608 * The first time this function is called, the argument (void **v) 609 * should be a pointer to a value of NULL which causes this function to obtain 610 * the first discovery address element. 611 * 612 * This function assumes the associated disccovery address lock is held. 613 * 614 * Returns B_TRUE when data is valid. B_FALSE returned when data is 615 * not available (end of configured discovery addresses has been reached). 616 * 617 */ 618 boolean_t 619 persistent_isns_addr_next(void **v, entry_t *e) 620 { 621 char name[INET6_ADDRSTRLEN]; 622 623 ASSERT(mutex_owned(&isns_addr_data_lock)); 624 625 return (nvf_data_next(ISNS_SERVER_ADDR_ID, v, name, 626 (void *)e, sizeof (*e))); 627 } 628 629 /* 630 * persistent_disc_addr_clear -- remove IP address and port information from 631 * the configured SendTargets discovery nodes. 632 */ 633 boolean_t 634 persistent_isns_addr_clear(entry_t *e) 635 { 636 char name[INET6_ADDRSTRLEN]; 637 boolean_t rval; 638 639 /* 640 * Create name from given discovery address - SendTargets discovery 641 * nodes do not have an associated node name. A name is manufactured 642 * from the IP address given. 643 */ 644 if (e->e_insize == sizeof (struct in_addr)) { 645 (void) inet_ntop(AF_INET, &e->e_u.u_in4, name, sizeof (name)); 646 } else { 647 (void) inet_ntop(AF_INET6, &e->e_u.u_in6, name, sizeof (name)); 648 } 649 650 mutex_enter(&static_addr_data_lock); 651 rval = nvf_data_clear(ISNS_SERVER_ADDR_ID, name); 652 mutex_exit(&static_addr_data_lock); 653 654 return (rval); 655 } 656 657 658 /* 659 * persistent_disc_addr_lock -- lock access to the SendTargets discovery 660 * addresses. This ensures discovery addresses are unchanged while the lock 661 * is held. The lock should be grabbed while walking through the discovery 662 * addresses 663 */ 664 void 665 persistent_isns_addr_lock(void) 666 { 667 mutex_enter(&isns_addr_data_lock); 668 } 669 670 /* 671 * persistent_disc_addr_unlock -- unlock access to discovery addresses. 672 */ 673 void 674 persistent_isns_addr_unlock(void) 675 { 676 mutex_exit(&isns_addr_data_lock); 677 } 678 679 /* 680 * +--------------------------------------------------------------------+ 681 * | Discovery Address Interfaces | 682 * +--------------------------------------------------------------------+ 683 */ 684 685 /* 686 * persistent_disc_addr_set -- store IP address, and port information for 687 * for an iSCSI discovery node that provides target information via a 688 * SendTargets response. 689 */ 690 boolean_t 691 persistent_disc_addr_set(entry_t *e) 692 { 693 char name[INET6_ADDRSTRLEN]; 694 boolean_t rval; 695 696 /* 697 * Create name from given discovery address - SendTargets discovery 698 * nodes do not have an associated node name. A name is manufactured 699 * from the IP address given. 700 */ 701 if (e->e_insize == sizeof (struct in_addr)) { 702 (void) inet_ntop(AF_INET, &e->e_u.u_in4, name, sizeof (name)); 703 } else { 704 (void) inet_ntop(AF_INET6, &e->e_u.u_in6, name, sizeof (name)); 705 } 706 707 mutex_enter(&disc_addr_data_lock); 708 rval = nvf_data_set(DISCOVERY_ADDR_ID, name, 709 (void *)e, sizeof (entry_t)); 710 mutex_exit(&disc_addr_data_lock); 711 712 return (rval); 713 } 714 715 /* 716 * persistent_disc_addr_next -- get the next iSCSI discovery node's address 717 * and port information. 718 * 719 * The first time this function is called, the argument (void **v) 720 * should be a pointer to a value of NULL which causes this function to obtain 721 * the first discovery address element. 722 * 723 * This function assumes the associated disccovery address lock is held. 724 * 725 * Returns B_TRUE when data is valid. B_FALSE returned when data is 726 * not available (end of configured discovery addresses has been reached). 727 * 728 */ 729 boolean_t 730 persistent_disc_addr_next(void **v, entry_t *e) 731 { 732 char name[INET6_ADDRSTRLEN]; 733 734 ASSERT(mutex_owned(&disc_addr_data_lock)); 735 736 return (nvf_data_next(DISCOVERY_ADDR_ID, v, name, 737 (void *)e, sizeof (*e))); 738 } 739 740 /* 741 * persistent_disc_addr_clear -- remove IP address and port information from 742 * the configured SendTargets discovery nodes. 743 */ 744 boolean_t 745 persistent_disc_addr_clear(entry_t *e) 746 { 747 char name[INET6_ADDRSTRLEN]; 748 boolean_t rval; 749 750 /* 751 * Create name from given discovery address - SendTargets discovery 752 * nodes do not have an associated node name. A name is manufactured 753 * from the IP address given. 754 */ 755 if (e->e_insize == sizeof (struct in_addr)) { 756 (void) inet_ntop(AF_INET, &e->e_u.u_in4, name, sizeof (name)); 757 } else { 758 (void) inet_ntop(AF_INET6, &e->e_u.u_in6, name, sizeof (name)); 759 } 760 761 mutex_enter(&static_addr_data_lock); 762 rval = nvf_data_clear(DISCOVERY_ADDR_ID, name); 763 mutex_exit(&static_addr_data_lock); 764 765 return (rval); 766 } 767 768 769 /* 770 * persistent_disc_addr_lock -- lock access to the SendTargets discovery 771 * addresses. This ensures discovery addresses are unchanged while the lock 772 * is held. The lock should be grabbed while walking through the discovery 773 * addresses 774 */ 775 void 776 persistent_disc_addr_lock(void) 777 { 778 mutex_enter(&disc_addr_data_lock); 779 } 780 781 /* 782 * persistent_disc_addr_unlock -- unlock access to discovery addresses. 783 */ 784 void 785 persistent_disc_addr_unlock(void) 786 { 787 mutex_exit(&disc_addr_data_lock); 788 } 789 790 791 /* 792 * +--------------------------------------------------------------------+ 793 * | Login Parameter Interfaces | 794 * +--------------------------------------------------------------------+ 795 */ 796 797 /* 798 * persistent_param_set -- store login parameters for a specific target 799 */ 800 boolean_t 801 persistent_param_set(char *node, persistent_param_t *param) 802 { 803 boolean_t rval; 804 805 mutex_enter(¶m_data_lock); 806 rval = nvf_data_set(LOGIN_PARAMS_ID, node, 807 (void *)param, sizeof (persistent_param_t)); 808 mutex_exit(¶m_data_lock); 809 810 return (rval); 811 } 812 813 /* 814 * persistent_param_get -- obtain login parameters for a specific target 815 */ 816 boolean_t 817 persistent_param_get(char *node, persistent_param_t *param) 818 { 819 return (nvf_data_get(LOGIN_PARAMS_ID, node, 820 (void *)param, sizeof (*param))); 821 } 822 823 /* 824 * persistent_param_next -- get the next target's login parameters. 825 * 826 * The first time this function is called, the argument (void **v) 827 * should be a pointer to a value of NULL which causes this function to obtain 828 * the first target's login parameters. 829 * 830 * This function assumes the associated login parameter lock is held. 831 * 832 * Returns B_TRUE when data in *param is valid. B_FALSE returned when no 833 * more data is available (end of configured target login parameters). 834 */ 835 boolean_t 836 persistent_param_next(void **v, char *node, persistent_param_t *param) 837 { 838 ASSERT(mutex_owned(¶m_data_lock)); 839 840 return (nvf_data_next(LOGIN_PARAMS_ID, v, node, 841 (void *)param, sizeof (*param))); 842 } 843 844 /* 845 * persistent_param_clear -- remove login parameters for a specific target 846 */ 847 boolean_t 848 persistent_param_clear(char *node) 849 { 850 boolean_t rval1, rval2, rval3; 851 852 mutex_enter(¶m_data_lock); 853 rval1 = nvf_data_clear(LOGIN_PARAMS_ID, node); 854 rval2 = nvf_data_clear(SESSION_PARAMS_ID, node); 855 rval3 = nvf_data_clear(TUNABLE_PARAMS_ID, node); 856 mutex_exit(¶m_data_lock); 857 858 return (((rval1 == B_TRUE) || (rval2 == B_TRUE) || (rval3 == B_TRUE)) 859 ? B_TRUE : B_FALSE); 860 } 861 862 /* 863 * persistent_param_lock -- lock access to login parameters. This 864 * ensures the login parameters will be unchanged while the lock is held. 865 * The lock should be grabbed while walking through the login parameters. 866 */ 867 void 868 persistent_param_lock(void) 869 { 870 mutex_enter(¶m_data_lock); 871 } 872 873 /* 874 * persistent_param_unlock -- unlock access to login parameters. 875 */ 876 void 877 persistent_param_unlock(void) 878 { 879 mutex_exit(¶m_data_lock); 880 } 881 882 /* 883 * +--------------------------------------------------------------------+ 884 * | Session Config Interfaces | 885 * +--------------------------------------------------------------------+ 886 */ 887 888 889 /* 890 * persistent_set_config_session -- store configured sessions 891 * for a specific target 892 */ 893 boolean_t 894 persistent_set_config_session(char *node, iscsi_config_sess_t *ics) 895 { 896 boolean_t rval; 897 int size; 898 899 /* 900 * Make ics_out match ics_in. Since when someone gets 901 * this information the in value becomes the out. 902 */ 903 ics->ics_out = ics->ics_in; 904 905 /* calculate size */ 906 size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_in); 907 908 mutex_enter(¶m_data_lock); 909 rval = nvf_data_set(SESSION_PARAMS_ID, node, (void *)ics, size); 910 mutex_exit(¶m_data_lock); 911 912 return (rval); 913 } 914 915 /* 916 * persistent_get_config_session -- obtain configured sessions 917 * for a specific target 918 */ 919 boolean_t 920 persistent_get_config_session(char *node, iscsi_config_sess_t *ics) 921 { 922 boolean_t status; 923 int in; 924 int size; 925 926 ASSERT(ics->ics_in >= 1); 927 928 /* record caller buffer size */ 929 in = ics->ics_in; 930 931 /* Get base config_sess information */ 932 size = ISCSI_SESSION_CONFIG_SIZE(in); 933 status = nvf_data_get(SESSION_PARAMS_ID, node, 934 (void *)ics, size); 935 936 /* reset the in size */ 937 ics->ics_in = in; 938 939 return (status); 940 } 941 942 /* 943 * persistent_get_tunable_param -- obtain tunable parameters 944 * for a specific target 945 */ 946 boolean_t 947 persistent_get_tunable_param(char *node, persistent_tunable_param_t *tpsg) 948 { 949 return (nvf_data_get(TUNABLE_PARAMS_ID, node, 950 (void *)tpsg, sizeof (persistent_tunable_param_t))); 951 } 952 953 /* 954 * persistent_set_tunable_param -- store tunable parameters 955 * for a specific target 956 */ 957 boolean_t 958 persistent_set_tunable_param(char *node, persistent_tunable_param_t *tpss) 959 { 960 boolean_t rval; 961 mutex_enter(&tunable_data_lock); 962 rval = nvf_data_set(TUNABLE_PARAMS_ID, node, 963 (void *)tpss, sizeof (persistent_tunable_param_t)); 964 mutex_exit(&tunable_data_lock); 965 return (rval); 966 } 967 968 /* 969 * +--------------------------------------------------------------------+ 970 * | CHAP Parameter Interfaces | 971 * +--------------------------------------------------------------------+ 972 */ 973 974 /* 975 * persistent_chap_set -- store CHAP parameters for a specific target 976 */ 977 boolean_t 978 persistent_chap_set(char *node, iscsi_chap_props_t *chap) 979 { 980 boolean_t rval; 981 982 mutex_enter(&chap_data_lock); 983 rval = nvf_data_set(CHAP_PARAMS_ID, node, 984 (void *)chap, sizeof (iscsi_chap_props_t)); 985 mutex_exit(&chap_data_lock); 986 987 return (rval); 988 } 989 990 /* 991 * persistent_chap_get -- obtain CHAP parameters for a specific target 992 */ 993 boolean_t 994 persistent_chap_get(char *node, iscsi_chap_props_t *chap) 995 { 996 return (nvf_data_get(CHAP_PARAMS_ID, node, 997 (void *)chap, sizeof (*chap))); 998 } 999 1000 /* 1001 * persistent_chap_next -- copy the next target's chap parameters. 1002 * 1003 * The first time this function is called, the argument (void **v) 1004 * should be a pointer to a value of NULL which causes this function to obtain 1005 * the first target's login parameters. 1006 * 1007 * This function assumes the associated chap parameter lock is held. 1008 * 1009 * Returns B_TRUE when data in *param is valid. B_FALSE returned when no 1010 * more data is available. 1011 */ 1012 boolean_t 1013 persistent_chap_next(void **v, char *node, iscsi_chap_props_t *chap) 1014 { 1015 ASSERT(mutex_owned(&chap_data_lock)); 1016 1017 return (nvf_data_next(CHAP_PARAMS_ID, v, node, 1018 (void *)chap, sizeof (*chap))); 1019 } 1020 1021 /* 1022 * persistent_chap_clear -- remove CHAP parameters for a specific target 1023 */ 1024 boolean_t 1025 persistent_chap_clear(char *node) 1026 { 1027 boolean_t rval; 1028 1029 mutex_enter(&chap_data_lock); 1030 rval = nvf_data_clear(CHAP_PARAMS_ID, node); 1031 mutex_exit(&chap_data_lock); 1032 1033 return (rval); 1034 } 1035 1036 /* 1037 * persistent_chap_lock -- lock access to chap parameters. This 1038 * ensures the chap parameters will be unchanged while the lock is held. 1039 * The lock should be grabbed while walking through the chap parameters. 1040 */ 1041 void 1042 persistent_chap_lock(void) 1043 { 1044 mutex_enter(&chap_data_lock); 1045 } 1046 1047 /* 1048 * persistent_chap_unlock -- unlock access to chap parameters. 1049 */ 1050 void 1051 persistent_chap_unlock(void) 1052 { 1053 mutex_exit(&chap_data_lock); 1054 } 1055 1056 1057 /* 1058 * +--------------------------------------------------------------------+ 1059 * | RADIUS Configuration Interfaces | 1060 * +--------------------------------------------------------------------+ 1061 */ 1062 1063 /* 1064 * persistent_radius_set -- stores the RADIUS configuration info 1065 */ 1066 boolean_t 1067 persistent_radius_set(iscsi_radius_props_t *radius) 1068 { 1069 return (nvf_node_data_set(RADIUS_PARAMS_ID, (void *)radius, 1070 sizeof (iscsi_radius_props_t))); 1071 } 1072 1073 /* 1074 * persistent_radius_get -- obtain the RADIUS configuration info 1075 */ 1076 iscsi_nvfile_status_t 1077 persistent_radius_get(iscsi_radius_props_t *radius) 1078 { 1079 return (nvf_node_data_get(RADIUS_PARAMS_ID, 1080 (void *)radius, sizeof (*radius))); 1081 } 1082 1083 1084 /* 1085 * +--------------------------------------------------------------------+ 1086 * | Authentication Configuration Interface | 1087 * +--------------------------------------------------------------------+ 1088 */ 1089 1090 /* 1091 * persistent_auth_set -- stores the bidirectional authentication settings 1092 * for a specific target 1093 */ 1094 boolean_t 1095 persistent_auth_set(char *node, iscsi_auth_props_t *auth) 1096 { 1097 boolean_t rval; 1098 1099 mutex_enter(&auth_data_lock); 1100 rval = nvf_data_set(BIDIR_AUTH_PARAMS_ID, node, 1101 (void *)auth, sizeof (iscsi_auth_props_t)); 1102 mutex_exit(&auth_data_lock); 1103 1104 return (rval); 1105 } 1106 1107 /* 1108 * persistent_auth_get -- gets the bidirectional authentication settings 1109 * for a specific target 1110 */ 1111 boolean_t 1112 persistent_auth_get(char *node, iscsi_auth_props_t *auth) 1113 { 1114 return (nvf_data_get(BIDIR_AUTH_PARAMS_ID, node, 1115 (void *)auth, sizeof (*auth))); 1116 } 1117 1118 /* 1119 * persistent_auth_next -- get the next target's bidirectional authentication 1120 * parameters. 1121 * 1122 * The first time this function is called, the argument (void **v) 1123 * should be a pointer to a value of NULL which causes this function to obtain 1124 * the first target's login parameters. 1125 * 1126 * This function assumes the associated bidirectional authentication lock is 1127 * held. 1128 * 1129 * Returns B_TRUE when data in *param is valid. B_FALSE returned when no 1130 * more data is available. 1131 */ 1132 boolean_t 1133 persistent_auth_next(void **v, char *node, iscsi_auth_props_t *auth) 1134 { 1135 ASSERT(mutex_owned(&auth_data_lock)); 1136 1137 return (nvf_data_next(BIDIR_AUTH_PARAMS_ID, v, node, 1138 (void *)auth, sizeof (*auth))); 1139 } 1140 1141 /* 1142 * persistent_auth_clear -- remove bidirectional authentication parameters for 1143 * a specific target 1144 */ 1145 boolean_t 1146 persistent_auth_clear(char *node) 1147 { 1148 boolean_t rval; 1149 1150 mutex_enter(&auth_data_lock); 1151 rval = nvf_data_clear(BIDIR_AUTH_PARAMS_ID, node); 1152 mutex_exit(&auth_data_lock); 1153 1154 return (rval); 1155 } 1156 1157 /* 1158 * persistent_auth_lock -- lock access to bidirectional authentication 1159 * parameters. This ensures the authentication parameters will be unchanged 1160 * while the lock is held. The lock should be grabbed while walking through 1161 * the authentication parameters. 1162 */ 1163 void 1164 persistent_auth_lock(void) 1165 { 1166 mutex_enter(&auth_data_lock); 1167 } 1168 1169 /* 1170 * persistent_auth_unlock -- unlock access to bidirectional authentication 1171 * parameters. 1172 */ 1173 void 1174 persistent_auth_unlock(void) 1175 { 1176 mutex_exit(&auth_data_lock); 1177 } 1178 1179 1180 /* 1181 * +--------------------------------------------------------------------+ 1182 * | Debug Functions | 1183 * +--------------------------------------------------------------------+ 1184 */ 1185 1186 #define BITBUF_LEN 128 1187 1188 /* 1189 * persistent_dump_data -- dump contents of persistent store 1190 */ 1191 void 1192 persistent_dump_data(void) 1193 { 1194 boolean_t rval; 1195 char *name; 1196 iSCSIDiscoveryMethod_t methods; 1197 char *bitbuf; 1198 iscsi_radius_props_t *radius; 1199 entry_t *entry; 1200 void *v; 1201 char *addr_buf; 1202 persistent_param_t *param; 1203 uint32_t param_id; 1204 char *param_name; 1205 iscsi_chap_props_t *chap; 1206 iscsi_auth_props_t *auth; 1207 1208 name = (char *)kmem_alloc(ISCSI_MAX_NAME_LEN, KM_SLEEP); 1209 addr_buf = (char *)kmem_alloc(INET6_ADDRSTRLEN, KM_SLEEP); 1210 bitbuf = (char *)kmem_alloc(BITBUF_LEN, KM_SLEEP); 1211 1212 rval = persistent_initiator_name_get(name, ISCSI_MAX_NAME_LEN); 1213 if (rval == B_TRUE) { 1214 cmn_err(CE_CONT, " Node Name: %s\n", name); 1215 } 1216 1217 rval = persistent_alias_name_get(name, ISCSI_MAX_NAME_LEN); 1218 if (rval == B_TRUE) { 1219 cmn_err(CE_CONT, " Node Alias: %s\n", name); 1220 } 1221 1222 methods = persistent_disc_meth_get(); 1223 if (methods != iSCSIDiscoveryMethodUnknown) { 1224 cmn_err(CE_CONT, " Methods: <%s>\n", 1225 prt_bitmap(methods, 1226 "\003SendTarget\002iSNS\001SLP\000Static", 1227 bitbuf, BITBUF_LEN)); 1228 } 1229 1230 radius = (iscsi_radius_props_t *)kmem_alloc(sizeof (*radius), 1231 KM_SLEEP); 1232 if (persistent_radius_get(radius) == ISCSI_NVFILE_SUCCESS) { 1233 cmn_err(CE_CONT, " <------ RADIUS Configuration ------>\n"); 1234 if (radius->r_insize == sizeof (struct in_addr)) { 1235 (void) inet_ntop(AF_INET, &radius->r_addr.u_in4, 1236 addr_buf, INET6_ADDRSTRLEN); 1237 } else { 1238 (void) inet_ntop(AF_INET6, &radius->r_addr.u_in6, 1239 addr_buf, INET6_ADDRSTRLEN); 1240 } 1241 cmn_err(CE_CONT, " IP: %s, port %d\n", addr_buf, 1242 radius->r_port); 1243 } 1244 kmem_free(radius, sizeof (*radius)); 1245 1246 entry = (entry_t *)kmem_alloc(sizeof (*entry), KM_SLEEP); 1247 v = NULL; 1248 cmn_err(CE_CONT, 1249 " <------ Static Target Discovery Addresses ------>\n"); 1250 persistent_static_addr_lock(); 1251 while (persistent_static_addr_next(&v, name, entry) == B_TRUE) { 1252 cmn_err(CE_CONT, " Target Name: %s TPGT: %d\n", 1253 name, entry->e_tpgt); 1254 if (entry->e_insize == sizeof (struct in_addr)) { 1255 (void) inet_ntop(AF_INET, &entry->e_u.u_in4, 1256 addr_buf, INET6_ADDRSTRLEN); 1257 } else { 1258 (void) inet_ntop(AF_INET6, &entry->e_u.u_in6, 1259 addr_buf, INET6_ADDRSTRLEN); 1260 } 1261 cmn_err(CE_CONT, 1262 " IP: %s, port %d\n", addr_buf, entry->e_port); 1263 } 1264 persistent_static_addr_unlock(); 1265 1266 v = NULL; 1267 cmn_err(CE_CONT, 1268 " <------ SendTargets Discovery Addresses ------>\n"); 1269 persistent_disc_addr_lock(); 1270 while (persistent_disc_addr_next(&v, entry) == B_TRUE) { 1271 if (entry->e_insize == sizeof (struct in_addr)) { 1272 (void) inet_ntop(AF_INET, &entry->e_u.u_in4, 1273 addr_buf, INET6_ADDRSTRLEN); 1274 } else { 1275 (void) inet_ntop(AF_INET6, &entry->e_u.u_in6, 1276 addr_buf, INET6_ADDRSTRLEN); 1277 } 1278 cmn_err(CE_CONT, 1279 " IP: %s, port %d\n", addr_buf, entry->e_port); 1280 } 1281 persistent_disc_addr_unlock(); 1282 1283 v = NULL; 1284 cmn_err(CE_CONT, 1285 " <------ ISNS Server Discovery Addresses ------>\n"); 1286 persistent_isns_addr_lock(); 1287 while (persistent_isns_addr_next(&v, entry) == B_TRUE) { 1288 if (entry->e_insize == sizeof (struct in_addr)) { 1289 (void) inet_ntop(AF_INET, &entry->e_u.u_in4, 1290 addr_buf, INET6_ADDRSTRLEN); 1291 } else { 1292 (void) inet_ntop(AF_INET6, &entry->e_u.u_in6, 1293 addr_buf, INET6_ADDRSTRLEN); 1294 } 1295 cmn_err(CE_CONT, 1296 " IP: %s, port %d\n", addr_buf, entry->e_port); 1297 } 1298 persistent_isns_addr_unlock(); 1299 kmem_free(entry, sizeof (*entry)); 1300 1301 param = (persistent_param_t *)kmem_alloc(sizeof (*param), KM_SLEEP); 1302 v = NULL; 1303 cmn_err(CE_CONT, " <------ Overriden Login Parameters ------>\n"); 1304 persistent_param_lock(); 1305 while (persistent_param_next(&v, name, param) == B_TRUE) { 1306 cmn_err(CE_CONT, " Host: %s\n", name); 1307 cmn_err(CE_CONT, " Bitmap: <%s>\n", 1308 prt_bitmap(param->p_bitmap, 1309 "\015DDIG\014HDIG\013SEGLEN\012OUT_R2T\011" 1310 "DATAPDU\010MAXCONN\007BURST\006R2T\005" 1311 "IMMDATA\004FIRSTBURST\003LEVEL\002T2WAIT" 1312 "\001T2RETAIN\000SEQIN", bitbuf, BITBUF_LEN)); 1313 for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM; 1314 param_id++) { 1315 if (param->p_bitmap & (1 << param_id)) { 1316 param_name = utils_map_param(param_id); 1317 if (param_name == NULL) { 1318 param_name = "Param_Not_Found"; 1319 } 1320 switch (param_id) { 1321 case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER: 1322 cmn_err(CE_CONT, " %s = %s", 1323 param_name, (param->p_params. 1324 data_sequence_in_order == B_TRUE) ? 1325 "True" : "False"); 1326 break; 1327 case ISCSI_LOGIN_PARAM_INITIAL_R2T: 1328 cmn_err(CE_CONT, " %s = %s", 1329 param_name, (param->p_params. 1330 initial_r2t == B_TRUE) ? 1331 "True" : "False"); 1332 break; 1333 case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER: 1334 cmn_err(CE_CONT, " %s = %s", 1335 param_name, (param->p_params. 1336 data_pdu_in_order == B_TRUE) ? 1337 "True" : "False"); 1338 break; 1339 case ISCSI_LOGIN_PARAM_HEADER_DIGEST: 1340 cmn_err(CE_CONT, " %s = %d", 1341 param_name, param->p_params. 1342 header_digest); 1343 break; 1344 case ISCSI_LOGIN_PARAM_DATA_DIGEST: 1345 cmn_err(CE_CONT, " %s = %d", 1346 param_name, param->p_params. 1347 data_digest); 1348 break; 1349 case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN: 1350 cmn_err(CE_CONT, " %s = %d", 1351 param_name, param->p_params. 1352 default_time_to_retain); 1353 break; 1354 case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT: 1355 cmn_err(CE_CONT, " %s = %d", 1356 param_name, param->p_params. 1357 default_time_to_wait); 1358 break; 1359 case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH: 1360 cmn_err(CE_CONT, " %s = %d", 1361 param_name, param->p_params. 1362 max_recv_data_seg_len); 1363 break; 1364 case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH: 1365 cmn_err(CE_CONT, " %s = %d", 1366 param_name, param->p_params. 1367 first_burst_length); 1368 break; 1369 case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH: 1370 cmn_err(CE_CONT, " %s = %d", 1371 param_name, param->p_params. 1372 max_burst_length); 1373 break; 1374 case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS: 1375 cmn_err(CE_CONT, " %s = %d", 1376 param_name, param->p_params. 1377 max_connections); 1378 break; 1379 case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T: 1380 cmn_err(CE_CONT, " %s = %d", 1381 param_name, param->p_params. 1382 max_outstanding_r2t); 1383 break; 1384 case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL: 1385 cmn_err(CE_CONT, " %s = %d", 1386 param_name, param->p_params. 1387 error_recovery_level); 1388 break; 1389 default: 1390 break; 1391 } 1392 } 1393 } 1394 } 1395 persistent_param_unlock(); 1396 kmem_free(param, sizeof (*param)); 1397 1398 chap = (iscsi_chap_props_t *)kmem_alloc(sizeof (*chap), KM_SLEEP); 1399 v = NULL; 1400 cmn_err(CE_CONT, " <------ Chap Parameters ------>\n"); 1401 persistent_chap_lock(); 1402 while (persistent_chap_next(&v, name, chap) == B_TRUE) { 1403 cmn_err(CE_CONT, " Host: %s\n", name); 1404 cmn_err(CE_CONT, " User: %s Secret: %s\n", 1405 chap->c_user, chap->c_secret); 1406 } 1407 persistent_chap_unlock(); 1408 kmem_free(chap, sizeof (*chap)); 1409 1410 auth = (iscsi_auth_props_t *)kmem_alloc(sizeof (*auth), KM_SLEEP); 1411 v = NULL; 1412 cmn_err(CE_CONT, " <------ Bidirectional Authentication ------>\n"); 1413 persistent_auth_lock(); 1414 while (persistent_auth_next(&v, name, auth) == B_TRUE) { 1415 cmn_err(CE_CONT, " Host: %s\n", name); 1416 cmn_err(CE_CONT, " Bidir Auth = %s\n", 1417 (auth->a_bi_auth == B_TRUE) ? "True" : "False"); 1418 } 1419 persistent_auth_unlock(); 1420 kmem_free(auth, sizeof (*auth)); 1421 1422 1423 kmem_free(bitbuf, BITBUF_LEN); 1424 kmem_free(addr_buf, INET6_ADDRSTRLEN); 1425 kmem_free(name, ISCSI_MAX_NAME_LEN); 1426 } 1427