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