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