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