xref: /titanic_50/usr/src/common/iscsit/iscsit_common.c (revision 4f1fc35da1d29699488fd1c9472dbeb042b2b9d0)
1a6d42e7dSPeter Dunlap /*
2a6d42e7dSPeter Dunlap  * CDDL HEADER START
3a6d42e7dSPeter Dunlap  *
4a6d42e7dSPeter Dunlap  * The contents of this file are subject to the terms of the
5a6d42e7dSPeter Dunlap  * Common Development and Distribution License (the "License").
6a6d42e7dSPeter Dunlap  * You may not use this file except in compliance with the License.
7a6d42e7dSPeter Dunlap  *
8a6d42e7dSPeter Dunlap  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a6d42e7dSPeter Dunlap  * or http://www.opensolaris.org/os/licensing.
10a6d42e7dSPeter Dunlap  * See the License for the specific language governing permissions
11a6d42e7dSPeter Dunlap  * and limitations under the License.
12a6d42e7dSPeter Dunlap  *
13a6d42e7dSPeter Dunlap  * When distributing Covered Code, include this CDDL HEADER in each
14a6d42e7dSPeter Dunlap  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a6d42e7dSPeter Dunlap  * If applicable, add the following below this CDDL HEADER, with the
16a6d42e7dSPeter Dunlap  * fields enclosed by brackets "[]" replaced with your own identifying
17a6d42e7dSPeter Dunlap  * information: Portions Copyright [yyyy] [name of copyright owner]
18a6d42e7dSPeter Dunlap  *
19a6d42e7dSPeter Dunlap  * CDDL HEADER END
20a6d42e7dSPeter Dunlap  */
21a6d42e7dSPeter Dunlap /*
22*4f1fc35dSsrivijitha dugganapalli  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23a6d42e7dSPeter Dunlap  * Use is subject to license terms.
24a6d42e7dSPeter Dunlap  */
25a6d42e7dSPeter Dunlap 
26a6d42e7dSPeter Dunlap #include <sys/time.h>
27a6d42e7dSPeter Dunlap 
28a6d42e7dSPeter Dunlap #if defined(_KERNEL)
29a6d42e7dSPeter Dunlap #include <sys/ddi.h>
30a6d42e7dSPeter Dunlap #include <sys/types.h>
31a6d42e7dSPeter Dunlap #include <sys/sunddi.h>
32a6d42e7dSPeter Dunlap #include <sys/socket.h>
33a6d42e7dSPeter Dunlap #include <inet/tcp.h>
34a6d42e7dSPeter Dunlap #else
35a6d42e7dSPeter Dunlap #include <stdio.h>
36a6d42e7dSPeter Dunlap #include <strings.h>
37a6d42e7dSPeter Dunlap #include <stdlib.h>
38a6d42e7dSPeter Dunlap #include <errno.h>
39a6d42e7dSPeter Dunlap #include <sys/types.h>
40a6d42e7dSPeter Dunlap #include <sys/socket.h>
41a6d42e7dSPeter Dunlap #include <netinet/in.h>
42a6d42e7dSPeter Dunlap #include <arpa/inet.h>
43a6d42e7dSPeter Dunlap #endif
44a6d42e7dSPeter Dunlap 
45a6d42e7dSPeter Dunlap #include <sys/iscsit/iscsit_common.h>
46a6d42e7dSPeter Dunlap #include <sys/iscsi_protocol.h>
47a6d42e7dSPeter Dunlap #include <sys/iscsit/isns_protocol.h>
48a6d42e7dSPeter Dunlap 
49a6d42e7dSPeter Dunlap void *
50a6d42e7dSPeter Dunlap iscsit_zalloc(size_t size)
51a6d42e7dSPeter Dunlap {
52a6d42e7dSPeter Dunlap #if defined(_KERNEL)
53a6d42e7dSPeter Dunlap 	return (kmem_zalloc(size, KM_SLEEP));
54a6d42e7dSPeter Dunlap #else
55a6d42e7dSPeter Dunlap 	return (calloc(1, size));
56a6d42e7dSPeter Dunlap #endif
57a6d42e7dSPeter Dunlap }
58a6d42e7dSPeter Dunlap 
59a6d42e7dSPeter Dunlap void
60a6d42e7dSPeter Dunlap iscsit_free(void *buf, size_t size)	/* ARGSUSED */
61a6d42e7dSPeter Dunlap {
62a6d42e7dSPeter Dunlap #if defined(_KERNEL)
63a6d42e7dSPeter Dunlap 	kmem_free(buf, size);
64a6d42e7dSPeter Dunlap #else
65a6d42e7dSPeter Dunlap 	free(buf);
66a6d42e7dSPeter Dunlap #endif
67a6d42e7dSPeter Dunlap }
68a6d42e7dSPeter Dunlap 
69a6d42e7dSPeter Dunlap /*
70a6d42e7dSPeter Dunlap  * default_port should be the port to be used, if not specified
71a6d42e7dSPeter Dunlap  * as part of the supplied string 'arg'.
72a6d42e7dSPeter Dunlap  */
73a6d42e7dSPeter Dunlap 
74a6d42e7dSPeter Dunlap #define	NI_MAXHOST	1025
75a6d42e7dSPeter Dunlap #define	NI_MAXSERV	32
76a6d42e7dSPeter Dunlap 
77a6d42e7dSPeter Dunlap 
78a6d42e7dSPeter Dunlap struct sockaddr_storage *
79a6d42e7dSPeter Dunlap it_common_convert_sa(char *arg, struct sockaddr_storage *buf,
80a6d42e7dSPeter Dunlap     uint32_t default_port)
81a6d42e7dSPeter Dunlap {
82a6d42e7dSPeter Dunlap 	/* Why does addrbuf need to be this big!??! XXX */
83a6d42e7dSPeter Dunlap 	char		addrbuf[NI_MAXHOST + NI_MAXSERV + 1];
84a6d42e7dSPeter Dunlap 	char		*addr_str;
85a6d42e7dSPeter Dunlap 	char		*port_str;
86a6d42e7dSPeter Dunlap #ifndef _KERNEL
87a6d42e7dSPeter Dunlap 	char		*errchr;
88a6d42e7dSPeter Dunlap #endif
89a6d42e7dSPeter Dunlap 	long		tmp_port = 0;
90a6d42e7dSPeter Dunlap 	sa_family_t	af;
91a6d42e7dSPeter Dunlap 
92a6d42e7dSPeter Dunlap 	struct sockaddr_in	*sin;
93a6d42e7dSPeter Dunlap 	struct sockaddr_in6	*sin6;
94a6d42e7dSPeter Dunlap 	struct sockaddr_storage	*sa = buf;
95a6d42e7dSPeter Dunlap 
96a6d42e7dSPeter Dunlap 	if (!arg || !buf) {
97a6d42e7dSPeter Dunlap 		return (NULL);
98a6d42e7dSPeter Dunlap 	}
99a6d42e7dSPeter Dunlap 
100a6d42e7dSPeter Dunlap 	bzero(buf, sizeof (struct sockaddr_storage));
101a6d42e7dSPeter Dunlap 
102a6d42e7dSPeter Dunlap 	/* don't modify the passed-in string */
103a6d42e7dSPeter Dunlap 	(void) strlcpy(addrbuf, arg, sizeof (addrbuf));
104a6d42e7dSPeter Dunlap 
105a6d42e7dSPeter Dunlap 	addr_str = addrbuf;
106a6d42e7dSPeter Dunlap 
107a6d42e7dSPeter Dunlap 	if (*addr_str == '[') {
108a6d42e7dSPeter Dunlap 		/*
109a6d42e7dSPeter Dunlap 		 * An IPv6 address must be inside square brackets
110a6d42e7dSPeter Dunlap 		 */
111a6d42e7dSPeter Dunlap 		port_str = strchr(addr_str, ']');
112a6d42e7dSPeter Dunlap 		if (!port_str) {
113a6d42e7dSPeter Dunlap 			/* No closing bracket */
114a6d42e7dSPeter Dunlap 			return (NULL);
115a6d42e7dSPeter Dunlap 		}
116a6d42e7dSPeter Dunlap 
117a6d42e7dSPeter Dunlap 		/* strip off the square brackets so we can convert */
118a6d42e7dSPeter Dunlap 		addr_str++;
119a6d42e7dSPeter Dunlap 		*port_str = '\0';
120a6d42e7dSPeter Dunlap 		port_str++;
121a6d42e7dSPeter Dunlap 
122a6d42e7dSPeter Dunlap 		if (*port_str == ':') {
123a6d42e7dSPeter Dunlap 			/* TCP port to follow */
124a6d42e7dSPeter Dunlap 			port_str++;
125a6d42e7dSPeter Dunlap 		} else if (*port_str == '\0') {
126a6d42e7dSPeter Dunlap 			/* No port specified */
127a6d42e7dSPeter Dunlap 			port_str = NULL;
128a6d42e7dSPeter Dunlap 		} else {
129a6d42e7dSPeter Dunlap 			/* malformed */
130a6d42e7dSPeter Dunlap 			return (NULL);
131a6d42e7dSPeter Dunlap 		}
132a6d42e7dSPeter Dunlap 		af = AF_INET6;
133a6d42e7dSPeter Dunlap 	} else {
134a6d42e7dSPeter Dunlap 		port_str = strchr(addr_str, ':');
135a6d42e7dSPeter Dunlap 		if (port_str) {
136a6d42e7dSPeter Dunlap 			*port_str = '\0';
137a6d42e7dSPeter Dunlap 			port_str++;
138a6d42e7dSPeter Dunlap 		}
139a6d42e7dSPeter Dunlap 		af = AF_INET;
140a6d42e7dSPeter Dunlap 	}
141a6d42e7dSPeter Dunlap 
142a6d42e7dSPeter Dunlap 	if (port_str) {
143a6d42e7dSPeter Dunlap #if defined(_KERNEL)
144a6d42e7dSPeter Dunlap 		if (ddi_strtol(port_str, NULL, 10, &tmp_port) != 0) {
145a6d42e7dSPeter Dunlap 			return (NULL);
146a6d42e7dSPeter Dunlap 		}
147a6d42e7dSPeter Dunlap #else
148a6d42e7dSPeter Dunlap 		tmp_port = strtol(port_str, &errchr, 10);
149a6d42e7dSPeter Dunlap #endif
150a6d42e7dSPeter Dunlap 		if (tmp_port < 0 || tmp_port > 65535) {
151a6d42e7dSPeter Dunlap 			return (NULL);
152a6d42e7dSPeter Dunlap 		}
153a6d42e7dSPeter Dunlap 	} else {
154a6d42e7dSPeter Dunlap 		tmp_port = default_port;
155a6d42e7dSPeter Dunlap 	}
156a6d42e7dSPeter Dunlap 
157a6d42e7dSPeter Dunlap 	sa->ss_family = af;
158a6d42e7dSPeter Dunlap 
159a6d42e7dSPeter Dunlap 	sin = (struct sockaddr_in *)sa;
160a6d42e7dSPeter Dunlap 	if (af == AF_INET) {
161a6d42e7dSPeter Dunlap 		if (inet_pton(af, addr_str,
162a6d42e7dSPeter Dunlap 		    (void *)&(sin->sin_addr.s_addr)) != 1) {
163a6d42e7dSPeter Dunlap 			return (NULL);
164a6d42e7dSPeter Dunlap 		}
165a6d42e7dSPeter Dunlap 		/*
166a6d42e7dSPeter Dunlap 		 * intet_pton does not seem to convert to network
167a6d42e7dSPeter Dunlap 		 * order in kernel. This is a workaround until the
168a6d42e7dSPeter Dunlap 		 * inet_pton works or we have our own inet_pton function.
169a6d42e7dSPeter Dunlap 		 */
170a6d42e7dSPeter Dunlap #ifdef _KERNEL
171a6d42e7dSPeter Dunlap 		sin->sin_addr.s_addr = ntohl((uint32_t)sin->sin_addr.s_addr);
172a6d42e7dSPeter Dunlap #endif
173a6d42e7dSPeter Dunlap 		sin->sin_port = htons(tmp_port);
174a6d42e7dSPeter Dunlap 	} else {
175a6d42e7dSPeter Dunlap 		sin6 = (struct sockaddr_in6 *)sa;
176a6d42e7dSPeter Dunlap 		if (inet_pton(af, addr_str,
177a6d42e7dSPeter Dunlap 		    (void *)&(sin6->sin6_addr.s6_addr)) != 1) {
178a6d42e7dSPeter Dunlap 			return (NULL);
179a6d42e7dSPeter Dunlap 		}
180a6d42e7dSPeter Dunlap 		sin6->sin6_port = htons(tmp_port);
181a6d42e7dSPeter Dunlap 	}
182a6d42e7dSPeter Dunlap 
183a6d42e7dSPeter Dunlap 	/* successful */
184a6d42e7dSPeter Dunlap 	return (sa);
185a6d42e7dSPeter Dunlap }
186a6d42e7dSPeter Dunlap 
187a6d42e7dSPeter Dunlap 
188a6d42e7dSPeter Dunlap /*  Functions to convert iSCSI target structures to/from nvlists. */
189a6d42e7dSPeter Dunlap 
190a6d42e7dSPeter Dunlap #ifndef _KERNEL
191a6d42e7dSPeter Dunlap int
192a6d42e7dSPeter Dunlap it_config_to_nv(it_config_t *cfg, nvlist_t **nvl)
193a6d42e7dSPeter Dunlap {
194a6d42e7dSPeter Dunlap 	int		ret;
195a6d42e7dSPeter Dunlap 	nvlist_t	*nv;
196a6d42e7dSPeter Dunlap 	nvlist_t	*lnv = NULL;
197a6d42e7dSPeter Dunlap 
198a6d42e7dSPeter Dunlap 	if (!nvl) {
199a6d42e7dSPeter Dunlap 		return (EINVAL);
200a6d42e7dSPeter Dunlap 	}
201a6d42e7dSPeter Dunlap 
202a6d42e7dSPeter Dunlap 	*nvl = NULL;
203a6d42e7dSPeter Dunlap 
204a6d42e7dSPeter Dunlap 	ret = nvlist_alloc(&nv, NV_UNIQUE_NAME_TYPE, 0);
205a6d42e7dSPeter Dunlap 	if (ret != 0) {
206a6d42e7dSPeter Dunlap 		return (ret);
207a6d42e7dSPeter Dunlap 	}
208a6d42e7dSPeter Dunlap 
209a6d42e7dSPeter Dunlap 	/* if there's no config, store an empty list */
210a6d42e7dSPeter Dunlap 	if (!cfg) {
211a6d42e7dSPeter Dunlap 		*nvl = nv;
212a6d42e7dSPeter Dunlap 		return (0);
213a6d42e7dSPeter Dunlap 	}
214a6d42e7dSPeter Dunlap 
215a6d42e7dSPeter Dunlap 	ret = nvlist_add_uint32(nv, "cfgVersion", cfg->config_version);
216a6d42e7dSPeter Dunlap 	if (ret == 0) {
217a6d42e7dSPeter Dunlap 		ret = it_tgtlist_to_nv(cfg->config_tgt_list, &lnv);
218a6d42e7dSPeter Dunlap 	}
219a6d42e7dSPeter Dunlap 
220a6d42e7dSPeter Dunlap 	if ((ret == 0) && (lnv != NULL)) {
221a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(nv, "targetList", lnv);
222a6d42e7dSPeter Dunlap 		nvlist_free(lnv);
223a6d42e7dSPeter Dunlap 		lnv = NULL;
224a6d42e7dSPeter Dunlap 	}
225a6d42e7dSPeter Dunlap 
226a6d42e7dSPeter Dunlap 	if (ret == 0) {
227a6d42e7dSPeter Dunlap 		ret = it_tpglist_to_nv(cfg->config_tpg_list, &lnv);
228a6d42e7dSPeter Dunlap 	}
229a6d42e7dSPeter Dunlap 
230a6d42e7dSPeter Dunlap 	if ((ret == 0) && (lnv != NULL)) {
231a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(nv, "tpgList", lnv);
232a6d42e7dSPeter Dunlap 		nvlist_free(lnv);
233a6d42e7dSPeter Dunlap 		lnv = NULL;
234a6d42e7dSPeter Dunlap 	}
235a6d42e7dSPeter Dunlap 
236a6d42e7dSPeter Dunlap 	if (ret == 0) {
237a6d42e7dSPeter Dunlap 		ret = it_inilist_to_nv(cfg->config_ini_list, &lnv);
238a6d42e7dSPeter Dunlap 	}
239a6d42e7dSPeter Dunlap 
240a6d42e7dSPeter Dunlap 	if ((ret == 0) && (lnv != NULL)) {
241a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(nv, "iniList", lnv);
242a6d42e7dSPeter Dunlap 		nvlist_free(lnv);
243a6d42e7dSPeter Dunlap 		lnv = NULL;
244a6d42e7dSPeter Dunlap 	}
245a6d42e7dSPeter Dunlap 
246a6d42e7dSPeter Dunlap 	if (ret == 0) {
247a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(nv, "globalProperties",
248a6d42e7dSPeter Dunlap 		    cfg->config_global_properties);
249a6d42e7dSPeter Dunlap 	}
250a6d42e7dSPeter Dunlap 
251a6d42e7dSPeter Dunlap 	if (ret == 0) {
252a6d42e7dSPeter Dunlap 		*nvl = nv;
253a6d42e7dSPeter Dunlap 	} else {
254a6d42e7dSPeter Dunlap 		nvlist_free(nv);
255a6d42e7dSPeter Dunlap 	}
256a6d42e7dSPeter Dunlap 
257a6d42e7dSPeter Dunlap 	return (ret);
258a6d42e7dSPeter Dunlap }
259a6d42e7dSPeter Dunlap #endif /* !_KERNEL */
260a6d42e7dSPeter Dunlap 
261a6d42e7dSPeter Dunlap /*
262a6d42e7dSPeter Dunlap  * nvlist version of config is 3 list-of-list, + 1 proplist.  arrays
263a6d42e7dSPeter Dunlap  * are interesting, but lists-of-lists are more useful when doing
264a6d42e7dSPeter Dunlap  * individual lookups when we later add support for it.  Also, no
265a6d42e7dSPeter Dunlap  * need to store name in individual struct representation.
266a6d42e7dSPeter Dunlap  */
267a6d42e7dSPeter Dunlap int
268a6d42e7dSPeter Dunlap it_nv_to_config(nvlist_t *nvl, it_config_t **cfg)
269a6d42e7dSPeter Dunlap {
270a6d42e7dSPeter Dunlap 	int		ret;
271a6d42e7dSPeter Dunlap 	uint32_t	intval;
272a6d42e7dSPeter Dunlap 	nvlist_t	*listval;
273a6d42e7dSPeter Dunlap 	it_config_t	*tmpcfg;
274a6d42e7dSPeter Dunlap 
275a6d42e7dSPeter Dunlap 	if (!cfg) {
276a6d42e7dSPeter Dunlap 		return (EINVAL);
277a6d42e7dSPeter Dunlap 	}
278a6d42e7dSPeter Dunlap 
279a6d42e7dSPeter Dunlap 	/* initialize output */
280a6d42e7dSPeter Dunlap 	*cfg = NULL;
281a6d42e7dSPeter Dunlap 
282a6d42e7dSPeter Dunlap 	tmpcfg = iscsit_zalloc(sizeof (it_config_t));
283a6d42e7dSPeter Dunlap 	if (tmpcfg == NULL) {
284a6d42e7dSPeter Dunlap 		return (ENOMEM);
285a6d42e7dSPeter Dunlap 	}
286a6d42e7dSPeter Dunlap 
287a6d42e7dSPeter Dunlap 	if (!nvl) {
288a6d42e7dSPeter Dunlap 		/* nothing to decode, but return the empty cfg struct */
289a6d42e7dSPeter Dunlap 		ret = nvlist_alloc(&tmpcfg->config_global_properties,
290a6d42e7dSPeter Dunlap 		    NV_UNIQUE_NAME, 0);
291a6d42e7dSPeter Dunlap 		if (ret != 0) {
292a6d42e7dSPeter Dunlap 			iscsit_free(tmpcfg, sizeof (it_config_t));
293a6d42e7dSPeter Dunlap 			return (ret);
294a6d42e7dSPeter Dunlap 		}
295a6d42e7dSPeter Dunlap 		*cfg = tmpcfg;
296a6d42e7dSPeter Dunlap 		return (0);
297a6d42e7dSPeter Dunlap 	}
298a6d42e7dSPeter Dunlap 
299a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_uint32(nvl, "cfgVersion", &intval);
300a6d42e7dSPeter Dunlap 	if (ret != 0) {
301a6d42e7dSPeter Dunlap 		iscsit_free(tmpcfg, sizeof (it_config_t));
302a6d42e7dSPeter Dunlap 		return (ret);
303a6d42e7dSPeter Dunlap 	}
304a6d42e7dSPeter Dunlap 
305a6d42e7dSPeter Dunlap 	tmpcfg->config_version = intval;
306a6d42e7dSPeter Dunlap 
307a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_nvlist(nvl, "targetList", &listval);
308a6d42e7dSPeter Dunlap 	if (ret == 0) {
309a6d42e7dSPeter Dunlap 		/* decode list of it_tgt_t */
310a6d42e7dSPeter Dunlap 		ret = it_nv_to_tgtlist(listval, &(tmpcfg->config_tgt_count),
311a6d42e7dSPeter Dunlap 		    &(tmpcfg->config_tgt_list));
312a6d42e7dSPeter Dunlap 	}
313a6d42e7dSPeter Dunlap 
314a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_nvlist(nvl, "tpgList", &listval);
315a6d42e7dSPeter Dunlap 	if (ret == 0) {
316a6d42e7dSPeter Dunlap 		/* decode list of it_tpg_t */
317a6d42e7dSPeter Dunlap 		ret = it_nv_to_tpglist(listval, &(tmpcfg->config_tpg_count),
318a6d42e7dSPeter Dunlap 		    &(tmpcfg->config_tpg_list));
319a6d42e7dSPeter Dunlap 	}
320a6d42e7dSPeter Dunlap 
321a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_nvlist(nvl, "iniList", &listval);
322a6d42e7dSPeter Dunlap 	if (ret == 0) {
323a6d42e7dSPeter Dunlap 		/* decode list of initiators */
324a6d42e7dSPeter Dunlap 		ret = it_nv_to_inilist(listval, &(tmpcfg->config_ini_count),
325a6d42e7dSPeter Dunlap 		    &(tmpcfg->config_ini_list));
326a6d42e7dSPeter Dunlap 	}
327a6d42e7dSPeter Dunlap 
328a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_nvlist(nvl, "globalProperties", &listval);
329a6d42e7dSPeter Dunlap 	if (ret == 0) {
330a6d42e7dSPeter Dunlap 		/*
331a6d42e7dSPeter Dunlap 		 * don't depend on the original nvlist staying in-scope,
332a6d42e7dSPeter Dunlap 		 * duplicate the nvlist
333a6d42e7dSPeter Dunlap 		 */
334a6d42e7dSPeter Dunlap 		ret = nvlist_dup(listval, &(tmpcfg->config_global_properties),
335a6d42e7dSPeter Dunlap 		    0);
336a6d42e7dSPeter Dunlap 	} else if (ret == ENOENT) {
337a6d42e7dSPeter Dunlap 		/*
338a6d42e7dSPeter Dunlap 		 * No global properties defined, make an empty list
339a6d42e7dSPeter Dunlap 		 */
340a6d42e7dSPeter Dunlap 		ret = nvlist_alloc(&tmpcfg->config_global_properties,
341a6d42e7dSPeter Dunlap 		    NV_UNIQUE_NAME, 0);
342a6d42e7dSPeter Dunlap 	}
343a6d42e7dSPeter Dunlap 
344a6d42e7dSPeter Dunlap 	if (ret == 0) {
345a6d42e7dSPeter Dunlap 		char		**isnsArray = NULL;
346a6d42e7dSPeter Dunlap 		uint32_t	numisns = 0;
347a6d42e7dSPeter Dunlap 
348a6d42e7dSPeter Dunlap 		/*
349a6d42e7dSPeter Dunlap 		 * decode the list of iSNS server information to make
350a6d42e7dSPeter Dunlap 		 * references from the kernel simpler.
351a6d42e7dSPeter Dunlap 		 */
352a6d42e7dSPeter Dunlap 		if (tmpcfg->config_global_properties) {
353a6d42e7dSPeter Dunlap 			ret = nvlist_lookup_string_array(
354a6d42e7dSPeter Dunlap 			    tmpcfg->config_global_properties,
355a6d42e7dSPeter Dunlap 			    PROP_ISNS_SERVER,
356a6d42e7dSPeter Dunlap 			    &isnsArray, &numisns);
357a6d42e7dSPeter Dunlap 			if (ret == 0) {
358a6d42e7dSPeter Dunlap 				ret = it_array_to_portallist(isnsArray,
359a6d42e7dSPeter Dunlap 				    numisns, ISNS_DEFAULT_SERVER_PORT,
360a6d42e7dSPeter Dunlap 				    &tmpcfg->config_isns_svr_list,
361a6d42e7dSPeter Dunlap 				    &tmpcfg->config_isns_svr_count);
362a6d42e7dSPeter Dunlap 			} else if (ret == ENOENT) {
363a6d42e7dSPeter Dunlap 				/* It's OK if we don't have any iSNS servers */
364a6d42e7dSPeter Dunlap 				ret = 0;
365a6d42e7dSPeter Dunlap 			}
366a6d42e7dSPeter Dunlap 		}
367a6d42e7dSPeter Dunlap 	}
368a6d42e7dSPeter Dunlap 
369a6d42e7dSPeter Dunlap 	if (ret == 0) {
370a6d42e7dSPeter Dunlap 		*cfg = tmpcfg;
371a6d42e7dSPeter Dunlap 	} else {
372a6d42e7dSPeter Dunlap 		it_config_free_cmn(tmpcfg);
373a6d42e7dSPeter Dunlap 	}
374a6d42e7dSPeter Dunlap 
375a6d42e7dSPeter Dunlap 	return (ret);
376a6d42e7dSPeter Dunlap }
377a6d42e7dSPeter Dunlap 
378a6d42e7dSPeter Dunlap it_tgt_t *
379a6d42e7dSPeter Dunlap it_tgt_lookup(it_config_t *cfg, char *tgt_name)
380a6d42e7dSPeter Dunlap {
381a6d42e7dSPeter Dunlap 	it_tgt_t *cfg_tgt = NULL;
382a6d42e7dSPeter Dunlap 
383a6d42e7dSPeter Dunlap 	for (cfg_tgt = cfg->config_tgt_list;
384a6d42e7dSPeter Dunlap 	    cfg_tgt != NULL;
385a6d42e7dSPeter Dunlap 	    cfg_tgt = cfg_tgt->tgt_next) {
386a6d42e7dSPeter Dunlap 		if (strncmp(cfg_tgt->tgt_name, tgt_name,
387a6d42e7dSPeter Dunlap 		    MAX_ISCSI_NODENAMELEN) == 0) {
388a6d42e7dSPeter Dunlap 			return (cfg_tgt);
389a6d42e7dSPeter Dunlap 		}
390a6d42e7dSPeter Dunlap 	}
391a6d42e7dSPeter Dunlap 
392a6d42e7dSPeter Dunlap 	return (NULL);
393a6d42e7dSPeter Dunlap }
394a6d42e7dSPeter Dunlap 
395a6d42e7dSPeter Dunlap int
396a6d42e7dSPeter Dunlap it_nv_to_tgtlist(nvlist_t *nvl, uint32_t *count, it_tgt_t **tgtlist)
397a6d42e7dSPeter Dunlap {
398a6d42e7dSPeter Dunlap 	int		ret = 0;
399a6d42e7dSPeter Dunlap 	it_tgt_t	*tgt;
400a6d42e7dSPeter Dunlap 	it_tgt_t	*prev = NULL;
401a6d42e7dSPeter Dunlap 	nvpair_t	*nvp = NULL;
402a6d42e7dSPeter Dunlap 	nvlist_t	*nvt;
403a6d42e7dSPeter Dunlap 	char		*name;
404a6d42e7dSPeter Dunlap 
405a6d42e7dSPeter Dunlap 	if (!tgtlist || !count) {
406a6d42e7dSPeter Dunlap 		return (EINVAL);
407a6d42e7dSPeter Dunlap 	}
408a6d42e7dSPeter Dunlap 
409a6d42e7dSPeter Dunlap 	*tgtlist = NULL;
410a6d42e7dSPeter Dunlap 	*count = 0;
411a6d42e7dSPeter Dunlap 
412a6d42e7dSPeter Dunlap 	if (!nvl) {
413a6d42e7dSPeter Dunlap 		/* nothing to do */
414a6d42e7dSPeter Dunlap 		return (0);
415a6d42e7dSPeter Dunlap 	}
416a6d42e7dSPeter Dunlap 
417a6d42e7dSPeter Dunlap 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
418a6d42e7dSPeter Dunlap 		name = nvpair_name(nvp);
419a6d42e7dSPeter Dunlap 
420a6d42e7dSPeter Dunlap 		ret = nvpair_value_nvlist(nvp, &nvt);
421a6d42e7dSPeter Dunlap 		if (ret != 0) {
422a6d42e7dSPeter Dunlap 			/* invalid entry? */
423a6d42e7dSPeter Dunlap 			continue;
424a6d42e7dSPeter Dunlap 		}
425a6d42e7dSPeter Dunlap 
426a6d42e7dSPeter Dunlap 		ret = it_nv_to_tgt(nvt, name, &tgt);
427a6d42e7dSPeter Dunlap 		if (ret != 0) {
428a6d42e7dSPeter Dunlap 			break;
429a6d42e7dSPeter Dunlap 		}
430a6d42e7dSPeter Dunlap 
431a6d42e7dSPeter Dunlap 		(*count)++;
432a6d42e7dSPeter Dunlap 
433a6d42e7dSPeter Dunlap 		if (*tgtlist == NULL) {
434a6d42e7dSPeter Dunlap 			*tgtlist = tgt;
435a6d42e7dSPeter Dunlap 		} else {
436a6d42e7dSPeter Dunlap 			prev->tgt_next = tgt;
437a6d42e7dSPeter Dunlap 		}
438a6d42e7dSPeter Dunlap 		prev = tgt;
439a6d42e7dSPeter Dunlap 	}
440a6d42e7dSPeter Dunlap 
441a6d42e7dSPeter Dunlap 	if (ret != 0) {
442a6d42e7dSPeter Dunlap 		it_tgt_free_cmn(*tgtlist);
443a6d42e7dSPeter Dunlap 		*tgtlist = NULL;
444a6d42e7dSPeter Dunlap 	}
445a6d42e7dSPeter Dunlap 
446a6d42e7dSPeter Dunlap 	return (ret);
447a6d42e7dSPeter Dunlap }
448a6d42e7dSPeter Dunlap 
449a6d42e7dSPeter Dunlap int
450a6d42e7dSPeter Dunlap it_tgtlist_to_nv(it_tgt_t *tgtlist, nvlist_t **nvl)
451a6d42e7dSPeter Dunlap {
452a6d42e7dSPeter Dunlap 	int		ret;
453a6d42e7dSPeter Dunlap 	it_tgt_t	*tgtp = tgtlist;
454a6d42e7dSPeter Dunlap 	nvlist_t	*pnv = NULL;
455a6d42e7dSPeter Dunlap 	nvlist_t	*tnv;
456a6d42e7dSPeter Dunlap 
457a6d42e7dSPeter Dunlap 	if (!nvl) {
458a6d42e7dSPeter Dunlap 		return (EINVAL);
459a6d42e7dSPeter Dunlap 	}
460a6d42e7dSPeter Dunlap 
461a6d42e7dSPeter Dunlap 	if (!tgtlist) {
462a6d42e7dSPeter Dunlap 		/* nothing to do */
463a6d42e7dSPeter Dunlap 		return (0);
464a6d42e7dSPeter Dunlap 	}
465a6d42e7dSPeter Dunlap 
466a6d42e7dSPeter Dunlap 	/* create the target list if required */
467a6d42e7dSPeter Dunlap 	if (*nvl == NULL) {
468a6d42e7dSPeter Dunlap 		ret = nvlist_alloc(&pnv, NV_UNIQUE_NAME, 0);
469a6d42e7dSPeter Dunlap 		if (ret != 0) {
470a6d42e7dSPeter Dunlap 			return (ret);
471a6d42e7dSPeter Dunlap 		}
472a6d42e7dSPeter Dunlap 		*nvl = pnv;
473a6d42e7dSPeter Dunlap 	}
474a6d42e7dSPeter Dunlap 
475a6d42e7dSPeter Dunlap 	while (tgtp) {
476a6d42e7dSPeter Dunlap 		ret = it_tgt_to_nv(tgtp, &tnv);
477a6d42e7dSPeter Dunlap 
478a6d42e7dSPeter Dunlap 		if (ret != 0) {
479a6d42e7dSPeter Dunlap 			break;
480a6d42e7dSPeter Dunlap 		}
481a6d42e7dSPeter Dunlap 
482a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(*nvl, tgtp->tgt_name, tnv);
483a6d42e7dSPeter Dunlap 
484a6d42e7dSPeter Dunlap 		if (ret != 0) {
485a6d42e7dSPeter Dunlap 			break;
486a6d42e7dSPeter Dunlap 		}
487a6d42e7dSPeter Dunlap 
488a6d42e7dSPeter Dunlap 		nvlist_free(tnv);
489a6d42e7dSPeter Dunlap 
490a6d42e7dSPeter Dunlap 		tgtp = tgtp->tgt_next;
491a6d42e7dSPeter Dunlap 	}
492a6d42e7dSPeter Dunlap 
493a6d42e7dSPeter Dunlap 	if (ret != 0) {
494a6d42e7dSPeter Dunlap 		if (pnv) {
495a6d42e7dSPeter Dunlap 			nvlist_free(pnv);
496a6d42e7dSPeter Dunlap 			*nvl = NULL;
497a6d42e7dSPeter Dunlap 		}
498a6d42e7dSPeter Dunlap 	}
499a6d42e7dSPeter Dunlap 
500a6d42e7dSPeter Dunlap 	return (ret);
501a6d42e7dSPeter Dunlap }
502a6d42e7dSPeter Dunlap 
503a6d42e7dSPeter Dunlap int
504a6d42e7dSPeter Dunlap it_tgt_to_nv(it_tgt_t *tgt, nvlist_t **nvl)
505a6d42e7dSPeter Dunlap {
506a6d42e7dSPeter Dunlap 	int		ret;
507a6d42e7dSPeter Dunlap 	nvlist_t	*tnv = NULL;
508a6d42e7dSPeter Dunlap 
509a6d42e7dSPeter Dunlap 	if (!nvl) {
510a6d42e7dSPeter Dunlap 		return (EINVAL);
511a6d42e7dSPeter Dunlap 	}
512a6d42e7dSPeter Dunlap 
513a6d42e7dSPeter Dunlap 	if (!tgt) {
514a6d42e7dSPeter Dunlap 		/* nothing to do */
515a6d42e7dSPeter Dunlap 		return (0);
516a6d42e7dSPeter Dunlap 	}
517a6d42e7dSPeter Dunlap 
518a6d42e7dSPeter Dunlap 	ret = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0);
519a6d42e7dSPeter Dunlap 	if (ret != 0) {
520a6d42e7dSPeter Dunlap 		return (ret);
521a6d42e7dSPeter Dunlap 	}
522a6d42e7dSPeter Dunlap 
523a6d42e7dSPeter Dunlap 	if (tgt->tgt_properties) {
524a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(*nvl, "properties",
525a6d42e7dSPeter Dunlap 		    tgt->tgt_properties);
526a6d42e7dSPeter Dunlap 	}
527a6d42e7dSPeter Dunlap 
528a6d42e7dSPeter Dunlap 	if (ret == 0) {
529a6d42e7dSPeter Dunlap 		ret = nvlist_add_uint64(*nvl, "generation",
530a6d42e7dSPeter Dunlap 		    tgt->tgt_generation);
531a6d42e7dSPeter Dunlap 	}
532a6d42e7dSPeter Dunlap 
533a6d42e7dSPeter Dunlap 	if (ret == 0) {
534a6d42e7dSPeter Dunlap 		ret = it_tpgtlist_to_nv(tgt->tgt_tpgt_list, &tnv);
535a6d42e7dSPeter Dunlap 	}
536a6d42e7dSPeter Dunlap 
537a6d42e7dSPeter Dunlap 	if ((ret == 0) && tnv) {
538a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(*nvl, "tpgtList", tnv);
539a6d42e7dSPeter Dunlap 		nvlist_free(tnv);
540a6d42e7dSPeter Dunlap 	}
541a6d42e7dSPeter Dunlap 
542a6d42e7dSPeter Dunlap 	if (ret != 0) {
543a6d42e7dSPeter Dunlap 		nvlist_free(*nvl);
544a6d42e7dSPeter Dunlap 		*nvl = NULL;
545a6d42e7dSPeter Dunlap 	}
546a6d42e7dSPeter Dunlap 
547a6d42e7dSPeter Dunlap 	return (ret);
548a6d42e7dSPeter Dunlap }
549a6d42e7dSPeter Dunlap 
550a6d42e7dSPeter Dunlap int
551a6d42e7dSPeter Dunlap it_nv_to_tgt(nvlist_t *nvl, char *name, it_tgt_t **tgt)
552a6d42e7dSPeter Dunlap {
553a6d42e7dSPeter Dunlap 	int		ret;
554a6d42e7dSPeter Dunlap 	it_tgt_t	*ttgt;
555a6d42e7dSPeter Dunlap 	nvlist_t	*listval;
556a6d42e7dSPeter Dunlap 	uint32_t	intval;
557a6d42e7dSPeter Dunlap 
558a6d42e7dSPeter Dunlap 	if (!nvl || !tgt || !name) {
559a6d42e7dSPeter Dunlap 		return (EINVAL);
560a6d42e7dSPeter Dunlap 	}
561a6d42e7dSPeter Dunlap 
562a6d42e7dSPeter Dunlap 	*tgt = NULL;
563a6d42e7dSPeter Dunlap 
564a6d42e7dSPeter Dunlap 	ttgt = iscsit_zalloc(sizeof (it_tgt_t));
565a6d42e7dSPeter Dunlap 	if (!ttgt) {
566a6d42e7dSPeter Dunlap 		return (ENOMEM);
567a6d42e7dSPeter Dunlap 	}
568a6d42e7dSPeter Dunlap 
569a6d42e7dSPeter Dunlap 	(void) strlcpy(ttgt->tgt_name, name, sizeof (ttgt->tgt_name));
570a6d42e7dSPeter Dunlap 
571a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_nvlist(nvl, "properties", &listval);
572a6d42e7dSPeter Dunlap 	if (ret == 0) {
573a6d42e7dSPeter Dunlap 		/* duplicate list so it does not go out of context */
574a6d42e7dSPeter Dunlap 		ret = nvlist_dup(listval, &(ttgt->tgt_properties), 0);
575a6d42e7dSPeter Dunlap 	} else if (ret == ENOENT) {
576a6d42e7dSPeter Dunlap 		ret = 0;
577a6d42e7dSPeter Dunlap 	}
578a6d42e7dSPeter Dunlap 
579a6d42e7dSPeter Dunlap 	if (ret == 0) {
580a6d42e7dSPeter Dunlap 		ret = nvlist_lookup_uint64(nvl, "generation",
581a6d42e7dSPeter Dunlap 		    &(ttgt->tgt_generation));
582a6d42e7dSPeter Dunlap 	} else if (ret == ENOENT) {
583a6d42e7dSPeter Dunlap 		ret = 0;
584a6d42e7dSPeter Dunlap 	}
585a6d42e7dSPeter Dunlap 
586a6d42e7dSPeter Dunlap 	if (ret == 0) {
587a6d42e7dSPeter Dunlap 		ret = nvlist_lookup_nvlist(nvl, "tpgtList", &listval);
588a6d42e7dSPeter Dunlap 	}
589a6d42e7dSPeter Dunlap 
590a6d42e7dSPeter Dunlap 	if (ret == 0) {
591a6d42e7dSPeter Dunlap 		ret = it_nv_to_tpgtlist(listval, &intval,
592a6d42e7dSPeter Dunlap 		    &(ttgt->tgt_tpgt_list));
593a6d42e7dSPeter Dunlap 		ttgt->tgt_tpgt_count = intval;
594a6d42e7dSPeter Dunlap 	} else if (ret == ENOENT) {
595a6d42e7dSPeter Dunlap 		ret = 0;
596a6d42e7dSPeter Dunlap 	}
597a6d42e7dSPeter Dunlap 
598a6d42e7dSPeter Dunlap 	if (ret == 0) {
599a6d42e7dSPeter Dunlap 		*tgt = ttgt;
600a6d42e7dSPeter Dunlap 	} else {
601a6d42e7dSPeter Dunlap 		it_tgt_free_cmn(ttgt);
602a6d42e7dSPeter Dunlap 	}
603a6d42e7dSPeter Dunlap 
604a6d42e7dSPeter Dunlap 	return (ret);
605a6d42e7dSPeter Dunlap }
606a6d42e7dSPeter Dunlap 
607a6d42e7dSPeter Dunlap int
608a6d42e7dSPeter Dunlap it_tpgt_to_nv(it_tpgt_t *tpgt, nvlist_t **nvl)
609a6d42e7dSPeter Dunlap {
610a6d42e7dSPeter Dunlap 	int		ret;
611a6d42e7dSPeter Dunlap 
612a6d42e7dSPeter Dunlap 	if (!nvl) {
613a6d42e7dSPeter Dunlap 		return (EINVAL);
614a6d42e7dSPeter Dunlap 	}
615a6d42e7dSPeter Dunlap 
616a6d42e7dSPeter Dunlap 	if (!tpgt) {
617a6d42e7dSPeter Dunlap 		/* nothing to do */
618a6d42e7dSPeter Dunlap 		return (0);
619a6d42e7dSPeter Dunlap 	}
620a6d42e7dSPeter Dunlap 
621a6d42e7dSPeter Dunlap 	ret = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0);
622a6d42e7dSPeter Dunlap 	if (ret != 0) {
623a6d42e7dSPeter Dunlap 		return (ret);
624a6d42e7dSPeter Dunlap 	}
625a6d42e7dSPeter Dunlap 
626a6d42e7dSPeter Dunlap 	ret = nvlist_add_uint16(*nvl, "tag", tpgt->tpgt_tag);
627a6d42e7dSPeter Dunlap 	if (ret == 0) {
628a6d42e7dSPeter Dunlap 		ret = nvlist_add_uint64(*nvl, "generation",
629a6d42e7dSPeter Dunlap 		    tpgt->tpgt_generation);
630a6d42e7dSPeter Dunlap 	}
631a6d42e7dSPeter Dunlap 
632a6d42e7dSPeter Dunlap 	if (ret != 0) {
633a6d42e7dSPeter Dunlap 		nvlist_free(*nvl);
634a6d42e7dSPeter Dunlap 		*nvl = NULL;
635a6d42e7dSPeter Dunlap 	}
636a6d42e7dSPeter Dunlap 
637a6d42e7dSPeter Dunlap 	return (ret);
638a6d42e7dSPeter Dunlap }
639a6d42e7dSPeter Dunlap 
640a6d42e7dSPeter Dunlap int
641a6d42e7dSPeter Dunlap it_nv_to_tpgt(nvlist_t *nvl, char *name, it_tpgt_t **tpgt)
642a6d42e7dSPeter Dunlap {
643a6d42e7dSPeter Dunlap 	int		ret;
644a6d42e7dSPeter Dunlap 	it_tpgt_t	*ptr;
645a6d42e7dSPeter Dunlap 
646a6d42e7dSPeter Dunlap 	if (!tpgt || !name) {
647a6d42e7dSPeter Dunlap 		return (EINVAL);
648a6d42e7dSPeter Dunlap 	}
649a6d42e7dSPeter Dunlap 
650a6d42e7dSPeter Dunlap 	*tpgt = NULL;
651a6d42e7dSPeter Dunlap 
652a6d42e7dSPeter Dunlap 	if (!nvl) {
653a6d42e7dSPeter Dunlap 		return (0);
654a6d42e7dSPeter Dunlap 	}
655a6d42e7dSPeter Dunlap 
656a6d42e7dSPeter Dunlap 	ptr = iscsit_zalloc(sizeof (it_tpgt_t));
657a6d42e7dSPeter Dunlap 	if (!ptr) {
658a6d42e7dSPeter Dunlap 		return (ENOMEM);
659a6d42e7dSPeter Dunlap 	}
660a6d42e7dSPeter Dunlap 
661a6d42e7dSPeter Dunlap 	(void) strlcpy(ptr->tpgt_tpg_name, name, sizeof (ptr->tpgt_tpg_name));
662a6d42e7dSPeter Dunlap 
663a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_uint16(nvl, "tag", &(ptr->tpgt_tag));
664a6d42e7dSPeter Dunlap 	if (ret == 0) {
665a6d42e7dSPeter Dunlap 		ret = nvlist_lookup_uint64(nvl, "generation",
666a6d42e7dSPeter Dunlap 		    &(ptr->tpgt_generation));
667a6d42e7dSPeter Dunlap 	}
668a6d42e7dSPeter Dunlap 
669a6d42e7dSPeter Dunlap 	if (ret == 0) {
670a6d42e7dSPeter Dunlap 		*tpgt = ptr;
671a6d42e7dSPeter Dunlap 	} else {
672a6d42e7dSPeter Dunlap 		iscsit_free(ptr, sizeof (it_tpgt_t));
673a6d42e7dSPeter Dunlap 	}
674a6d42e7dSPeter Dunlap 
675a6d42e7dSPeter Dunlap 	return (ret);
676a6d42e7dSPeter Dunlap }
677a6d42e7dSPeter Dunlap 
678a6d42e7dSPeter Dunlap int
679a6d42e7dSPeter Dunlap it_tpgtlist_to_nv(it_tpgt_t *tpgtlist, nvlist_t **nvl)
680a6d42e7dSPeter Dunlap {
681a6d42e7dSPeter Dunlap 	int		ret;
682a6d42e7dSPeter Dunlap 	nvlist_t	*pnv = NULL;
683a6d42e7dSPeter Dunlap 	nvlist_t	*tnv;
684a6d42e7dSPeter Dunlap 	it_tpgt_t	*ptr = tpgtlist;
685a6d42e7dSPeter Dunlap 
686a6d42e7dSPeter Dunlap 	if (!nvl) {
687a6d42e7dSPeter Dunlap 		return (EINVAL);
688a6d42e7dSPeter Dunlap 	}
689a6d42e7dSPeter Dunlap 
690a6d42e7dSPeter Dunlap 	if (!tpgtlist) {
691a6d42e7dSPeter Dunlap 		/* nothing to do */
692a6d42e7dSPeter Dunlap 		return (0);
693a6d42e7dSPeter Dunlap 	}
694a6d42e7dSPeter Dunlap 
695a6d42e7dSPeter Dunlap 	/* create the target list if required */
696a6d42e7dSPeter Dunlap 	if (*nvl == NULL) {
697a6d42e7dSPeter Dunlap 		ret = nvlist_alloc(&pnv, NV_UNIQUE_NAME, 0);
698a6d42e7dSPeter Dunlap 		if (ret != 0) {
699a6d42e7dSPeter Dunlap 			return (ret);
700a6d42e7dSPeter Dunlap 		}
701a6d42e7dSPeter Dunlap 		*nvl = pnv;
702a6d42e7dSPeter Dunlap 	}
703a6d42e7dSPeter Dunlap 
704a6d42e7dSPeter Dunlap 	while (ptr) {
705a6d42e7dSPeter Dunlap 		ret = it_tpgt_to_nv(ptr, &tnv);
706a6d42e7dSPeter Dunlap 
707a6d42e7dSPeter Dunlap 		if (ret != 0) {
708a6d42e7dSPeter Dunlap 			break;
709a6d42e7dSPeter Dunlap 		}
710a6d42e7dSPeter Dunlap 
711a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(*nvl, ptr->tpgt_tpg_name, tnv);
712a6d42e7dSPeter Dunlap 
713a6d42e7dSPeter Dunlap 		if (ret != 0) {
714a6d42e7dSPeter Dunlap 			break;
715a6d42e7dSPeter Dunlap 		}
716a6d42e7dSPeter Dunlap 
717a6d42e7dSPeter Dunlap 		nvlist_free(tnv);
718a6d42e7dSPeter Dunlap 
719a6d42e7dSPeter Dunlap 		ptr = ptr->tpgt_next;
720a6d42e7dSPeter Dunlap 	}
721a6d42e7dSPeter Dunlap 
722a6d42e7dSPeter Dunlap 	if (ret != 0) {
723a6d42e7dSPeter Dunlap 		if (pnv) {
724a6d42e7dSPeter Dunlap 			nvlist_free(pnv);
725a6d42e7dSPeter Dunlap 			*nvl = NULL;
726a6d42e7dSPeter Dunlap 		}
727a6d42e7dSPeter Dunlap 	}
728a6d42e7dSPeter Dunlap 
729a6d42e7dSPeter Dunlap 	return (ret);
730a6d42e7dSPeter Dunlap }
731a6d42e7dSPeter Dunlap 
732a6d42e7dSPeter Dunlap int
733a6d42e7dSPeter Dunlap it_nv_to_tpgtlist(nvlist_t *nvl, uint32_t *count, it_tpgt_t **tpgtlist)
734a6d42e7dSPeter Dunlap {
735a6d42e7dSPeter Dunlap 	int		ret = 0;
736a6d42e7dSPeter Dunlap 	it_tpgt_t	*tpgt;
737a6d42e7dSPeter Dunlap 	it_tpgt_t	*prev = NULL;
738a6d42e7dSPeter Dunlap 	nvpair_t	*nvp = NULL;
739a6d42e7dSPeter Dunlap 	nvlist_t	*nvt;
740a6d42e7dSPeter Dunlap 	char		*name;
741a6d42e7dSPeter Dunlap 
742a6d42e7dSPeter Dunlap 	if (!tpgtlist || !count) {
743a6d42e7dSPeter Dunlap 		return (EINVAL);
744a6d42e7dSPeter Dunlap 	}
745a6d42e7dSPeter Dunlap 
746a6d42e7dSPeter Dunlap 	*tpgtlist = NULL;
747a6d42e7dSPeter Dunlap 	*count = 0;
748a6d42e7dSPeter Dunlap 
749a6d42e7dSPeter Dunlap 	if (!nvl) {
750a6d42e7dSPeter Dunlap 		/* nothing to do */
751a6d42e7dSPeter Dunlap 		return (0);
752a6d42e7dSPeter Dunlap 	}
753a6d42e7dSPeter Dunlap 
754a6d42e7dSPeter Dunlap 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
755a6d42e7dSPeter Dunlap 		name = nvpair_name(nvp);
756a6d42e7dSPeter Dunlap 
757a6d42e7dSPeter Dunlap 		ret = nvpair_value_nvlist(nvp, &nvt);
758a6d42e7dSPeter Dunlap 		if (ret != 0) {
759a6d42e7dSPeter Dunlap 			/* invalid entry? */
760a6d42e7dSPeter Dunlap 			continue;
761a6d42e7dSPeter Dunlap 		}
762a6d42e7dSPeter Dunlap 
763a6d42e7dSPeter Dunlap 		ret = it_nv_to_tpgt(nvt, name, &tpgt);
764a6d42e7dSPeter Dunlap 		if (ret != 0) {
765a6d42e7dSPeter Dunlap 			break;
766a6d42e7dSPeter Dunlap 		}
767a6d42e7dSPeter Dunlap 
768a6d42e7dSPeter Dunlap 		(*count)++;
769a6d42e7dSPeter Dunlap 
770a6d42e7dSPeter Dunlap 		if (*tpgtlist == NULL) {
771a6d42e7dSPeter Dunlap 			*tpgtlist = tpgt;
772a6d42e7dSPeter Dunlap 		} else {
773a6d42e7dSPeter Dunlap 			prev->tpgt_next = tpgt;
774a6d42e7dSPeter Dunlap 		}
775a6d42e7dSPeter Dunlap 
776a6d42e7dSPeter Dunlap 		prev = tpgt;
777a6d42e7dSPeter Dunlap 	}
778a6d42e7dSPeter Dunlap 
779a6d42e7dSPeter Dunlap 	if (ret != 0) {
780a6d42e7dSPeter Dunlap 		it_tpgt_free_cmn(*tpgtlist);
781a6d42e7dSPeter Dunlap 		*tpgtlist = NULL;
782a6d42e7dSPeter Dunlap 	}
783a6d42e7dSPeter Dunlap 
784a6d42e7dSPeter Dunlap 	return (ret);
785a6d42e7dSPeter Dunlap }
786a6d42e7dSPeter Dunlap 
787a6d42e7dSPeter Dunlap #ifndef _KERNEL
788a6d42e7dSPeter Dunlap int
789a6d42e7dSPeter Dunlap it_tpg_to_nv(it_tpg_t *tpg, nvlist_t **nvl)
790a6d42e7dSPeter Dunlap {
791a6d42e7dSPeter Dunlap 	int		ret;
792a6d42e7dSPeter Dunlap 	char		**portalArray = NULL;
793a6d42e7dSPeter Dunlap 	int		i;
794a6d42e7dSPeter Dunlap 	it_portal_t	*ptr;
795a6d42e7dSPeter Dunlap 
796a6d42e7dSPeter Dunlap 	if (!nvl) {
797a6d42e7dSPeter Dunlap 		return (EINVAL);
798a6d42e7dSPeter Dunlap 	}
799a6d42e7dSPeter Dunlap 
800a6d42e7dSPeter Dunlap 	if (!tpg) {
801a6d42e7dSPeter Dunlap 		/* nothing to do */
802a6d42e7dSPeter Dunlap 		return (0);
803a6d42e7dSPeter Dunlap 	}
804a6d42e7dSPeter Dunlap 
805a6d42e7dSPeter Dunlap 	ret = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0);
806a6d42e7dSPeter Dunlap 	if (ret != 0) {
807a6d42e7dSPeter Dunlap 		return (ret);
808a6d42e7dSPeter Dunlap 	}
809a6d42e7dSPeter Dunlap 
810a6d42e7dSPeter Dunlap 	ret = nvlist_add_uint64(*nvl, "generation", tpg->tpg_generation);
811a6d42e7dSPeter Dunlap 
812a6d42e7dSPeter Dunlap 	if ((ret == 0) && tpg->tpg_portal_list) {
813a6d42e7dSPeter Dunlap 		/* add the portals */
814a6d42e7dSPeter Dunlap 		portalArray = iscsit_zalloc(tpg->tpg_portal_count *
815a6d42e7dSPeter Dunlap 		    sizeof (it_portal_t));
816a6d42e7dSPeter Dunlap 		if (portalArray == NULL) {
817a6d42e7dSPeter Dunlap 			nvlist_free(*nvl);
818a6d42e7dSPeter Dunlap 			*nvl = NULL;
819a6d42e7dSPeter Dunlap 			return (ENOMEM);
820a6d42e7dSPeter Dunlap 		}
821a6d42e7dSPeter Dunlap 
822a6d42e7dSPeter Dunlap 		i = 0;
823a6d42e7dSPeter Dunlap 		ptr = tpg->tpg_portal_list;
824a6d42e7dSPeter Dunlap 
825a6d42e7dSPeter Dunlap 		while (ptr && (i < tpg->tpg_portal_count)) {
826a6d42e7dSPeter Dunlap 			ret = sockaddr_to_str(&(ptr->portal_addr),
827a6d42e7dSPeter Dunlap 			    &(portalArray[i]));
828a6d42e7dSPeter Dunlap 			if (ret != 0) {
829a6d42e7dSPeter Dunlap 				break;
830a6d42e7dSPeter Dunlap 			}
831a6d42e7dSPeter Dunlap 			ptr = ptr->next;
832a6d42e7dSPeter Dunlap 			i++;
833a6d42e7dSPeter Dunlap 		}
834a6d42e7dSPeter Dunlap 	}
835a6d42e7dSPeter Dunlap 
836a6d42e7dSPeter Dunlap 	if ((ret == 0) && portalArray) {
837a6d42e7dSPeter Dunlap 		ret = nvlist_add_string_array(*nvl, "portalList",
838a6d42e7dSPeter Dunlap 		    portalArray, i);
839a6d42e7dSPeter Dunlap 	}
840a6d42e7dSPeter Dunlap 
841a6d42e7dSPeter Dunlap 
842a6d42e7dSPeter Dunlap 	if (portalArray) {
843*4f1fc35dSsrivijitha dugganapalli 		while (--i >= 0) {
844a6d42e7dSPeter Dunlap 			if (portalArray[i]) {
845a6d42e7dSPeter Dunlap 				iscsit_free(portalArray[i],
846a6d42e7dSPeter Dunlap 				    strlen(portalArray[i] + 1));
847a6d42e7dSPeter Dunlap 			}
848a6d42e7dSPeter Dunlap 		}
849a6d42e7dSPeter Dunlap 		iscsit_free(portalArray,
850a6d42e7dSPeter Dunlap 		    tpg->tpg_portal_count * sizeof (it_portal_t));
851a6d42e7dSPeter Dunlap 	}
852a6d42e7dSPeter Dunlap 
853a6d42e7dSPeter Dunlap 	if (ret != 0) {
854a6d42e7dSPeter Dunlap 		nvlist_free(*nvl);
855a6d42e7dSPeter Dunlap 		*nvl = NULL;
856a6d42e7dSPeter Dunlap 	}
857a6d42e7dSPeter Dunlap 
858a6d42e7dSPeter Dunlap 	return (ret);
859a6d42e7dSPeter Dunlap }
860a6d42e7dSPeter Dunlap #endif /* !_KERNEL */
861a6d42e7dSPeter Dunlap 
862a6d42e7dSPeter Dunlap int
863a6d42e7dSPeter Dunlap it_nv_to_tpg(nvlist_t *nvl, char *name, it_tpg_t **tpg)
864a6d42e7dSPeter Dunlap {
865a6d42e7dSPeter Dunlap 	int		ret;
866a6d42e7dSPeter Dunlap 	it_tpg_t	*ptpg;
867a6d42e7dSPeter Dunlap 	char		**portalArray = NULL;
868a6d42e7dSPeter Dunlap 	uint32_t	count = 0;
869a6d42e7dSPeter Dunlap 
870a6d42e7dSPeter Dunlap 	if (!name || !tpg) {
871a6d42e7dSPeter Dunlap 		return (EINVAL);
872a6d42e7dSPeter Dunlap 	}
873a6d42e7dSPeter Dunlap 
874a6d42e7dSPeter Dunlap 	*tpg = NULL;
875a6d42e7dSPeter Dunlap 
876a6d42e7dSPeter Dunlap 	ptpg = iscsit_zalloc(sizeof (it_tpg_t));
877a6d42e7dSPeter Dunlap 	if (ptpg == NULL) {
878a6d42e7dSPeter Dunlap 		return (ENOMEM);
879a6d42e7dSPeter Dunlap 	}
880a6d42e7dSPeter Dunlap 
881a6d42e7dSPeter Dunlap 	(void) strlcpy(ptpg->tpg_name, name, sizeof (ptpg->tpg_name));
882a6d42e7dSPeter Dunlap 
883a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_uint64(nvl, "generation",
884a6d42e7dSPeter Dunlap 	    &(ptpg->tpg_generation));
885a6d42e7dSPeter Dunlap 
886a6d42e7dSPeter Dunlap 	if (ret == 0) {
887a6d42e7dSPeter Dunlap 		ret = nvlist_lookup_string_array(nvl, "portalList",
888a6d42e7dSPeter Dunlap 		    &portalArray, &count);
889a6d42e7dSPeter Dunlap 	}
890a6d42e7dSPeter Dunlap 
891a6d42e7dSPeter Dunlap 	if (ret == 0) {
892a6d42e7dSPeter Dunlap 		/* set the portals */
893a6d42e7dSPeter Dunlap 		ret = it_array_to_portallist(portalArray, count,
894a6d42e7dSPeter Dunlap 		    ISCSI_LISTEN_PORT, &ptpg->tpg_portal_list,
895a6d42e7dSPeter Dunlap 		    &ptpg->tpg_portal_count);
896a6d42e7dSPeter Dunlap 	} else if (ret == ENOENT) {
897a6d42e7dSPeter Dunlap 		ret = 0;
898a6d42e7dSPeter Dunlap 	}
899a6d42e7dSPeter Dunlap 
900a6d42e7dSPeter Dunlap 	if (ret == 0) {
901a6d42e7dSPeter Dunlap 		*tpg = ptpg;
902a6d42e7dSPeter Dunlap 	} else {
903a6d42e7dSPeter Dunlap 		it_tpg_free_cmn(ptpg);
904a6d42e7dSPeter Dunlap 	}
905a6d42e7dSPeter Dunlap 
906a6d42e7dSPeter Dunlap 	return (ret);
907a6d42e7dSPeter Dunlap }
908a6d42e7dSPeter Dunlap 
909a6d42e7dSPeter Dunlap 
910a6d42e7dSPeter Dunlap 
911a6d42e7dSPeter Dunlap 
912a6d42e7dSPeter Dunlap #ifndef _KERNEL
913a6d42e7dSPeter Dunlap int
914a6d42e7dSPeter Dunlap it_tpglist_to_nv(it_tpg_t *tpglist, nvlist_t **nvl)
915a6d42e7dSPeter Dunlap {
916a6d42e7dSPeter Dunlap 	int		ret;
917a6d42e7dSPeter Dunlap 	nvlist_t	*pnv = NULL;
918a6d42e7dSPeter Dunlap 	nvlist_t	*tnv;
919a6d42e7dSPeter Dunlap 	it_tpg_t	*ptr = tpglist;
920a6d42e7dSPeter Dunlap 
921a6d42e7dSPeter Dunlap 	if (!nvl) {
922a6d42e7dSPeter Dunlap 		return (EINVAL);
923a6d42e7dSPeter Dunlap 	}
924a6d42e7dSPeter Dunlap 
925a6d42e7dSPeter Dunlap 	if (!tpglist) {
926a6d42e7dSPeter Dunlap 		/* nothing to do */
927a6d42e7dSPeter Dunlap 		return (0);
928a6d42e7dSPeter Dunlap 	}
929a6d42e7dSPeter Dunlap 
930a6d42e7dSPeter Dunlap 	/* create the target portal group list if required */
931a6d42e7dSPeter Dunlap 	if (*nvl == NULL) {
932a6d42e7dSPeter Dunlap 		ret = nvlist_alloc(&pnv, NV_UNIQUE_NAME, 0);
933a6d42e7dSPeter Dunlap 		if (ret != 0) {
934a6d42e7dSPeter Dunlap 			return (ret);
935a6d42e7dSPeter Dunlap 		}
936a6d42e7dSPeter Dunlap 		*nvl = pnv;
937a6d42e7dSPeter Dunlap 	}
938a6d42e7dSPeter Dunlap 
939a6d42e7dSPeter Dunlap 	while (ptr) {
940a6d42e7dSPeter Dunlap 		ret = it_tpg_to_nv(ptr, &tnv);
941a6d42e7dSPeter Dunlap 
942a6d42e7dSPeter Dunlap 		if (ret != 0) {
943a6d42e7dSPeter Dunlap 			break;
944a6d42e7dSPeter Dunlap 		}
945a6d42e7dSPeter Dunlap 
946a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(*nvl, ptr->tpg_name, tnv);
947a6d42e7dSPeter Dunlap 
948a6d42e7dSPeter Dunlap 		if (ret != 0) {
949a6d42e7dSPeter Dunlap 			break;
950a6d42e7dSPeter Dunlap 		}
951a6d42e7dSPeter Dunlap 
952a6d42e7dSPeter Dunlap 		nvlist_free(tnv);
953a6d42e7dSPeter Dunlap 
954a6d42e7dSPeter Dunlap 		ptr = ptr->tpg_next;
955a6d42e7dSPeter Dunlap 	}
956a6d42e7dSPeter Dunlap 
957a6d42e7dSPeter Dunlap 	if (ret != 0) {
958a6d42e7dSPeter Dunlap 		if (pnv) {
959a6d42e7dSPeter Dunlap 			nvlist_free(pnv);
960a6d42e7dSPeter Dunlap 			*nvl = NULL;
961a6d42e7dSPeter Dunlap 		}
962a6d42e7dSPeter Dunlap 	}
963a6d42e7dSPeter Dunlap 
964a6d42e7dSPeter Dunlap 	return (ret);
965a6d42e7dSPeter Dunlap }
966a6d42e7dSPeter Dunlap #endif /* !_KERNEL */
967a6d42e7dSPeter Dunlap 
968a6d42e7dSPeter Dunlap it_tpg_t *
969a6d42e7dSPeter Dunlap it_tpg_lookup(it_config_t *cfg, char *tpg_name)
970a6d42e7dSPeter Dunlap {
971a6d42e7dSPeter Dunlap 	it_tpg_t *cfg_tpg = NULL;
972a6d42e7dSPeter Dunlap 
973a6d42e7dSPeter Dunlap 	for (cfg_tpg = cfg->config_tpg_list;
974a6d42e7dSPeter Dunlap 	    cfg_tpg != NULL;
975a6d42e7dSPeter Dunlap 	    cfg_tpg = cfg_tpg->tpg_next) {
976a6d42e7dSPeter Dunlap 		if (strncmp(&cfg_tpg->tpg_name[0], tpg_name,
977a6d42e7dSPeter Dunlap 		    MAX_TPG_NAMELEN) == 0) {
978a6d42e7dSPeter Dunlap 			return (cfg_tpg);
979a6d42e7dSPeter Dunlap 		}
980a6d42e7dSPeter Dunlap 	}
981a6d42e7dSPeter Dunlap 
982a6d42e7dSPeter Dunlap 	return (NULL);
983a6d42e7dSPeter Dunlap }
984a6d42e7dSPeter Dunlap 
985a6d42e7dSPeter Dunlap int
986a6d42e7dSPeter Dunlap it_sa_compare(struct sockaddr_storage *sa1, struct sockaddr_storage *sa2)
987a6d42e7dSPeter Dunlap {
988a6d42e7dSPeter Dunlap 	struct sockaddr_in	*sin1, *sin2;
989a6d42e7dSPeter Dunlap 	struct sockaddr_in6	*sin6_1, *sin6_2;
990a6d42e7dSPeter Dunlap 
991a6d42e7dSPeter Dunlap 	/*
992a6d42e7dSPeter Dunlap 	 * XXX - should we check here for IPv4 addrs mapped to v6?
993a6d42e7dSPeter Dunlap 	 * see also iscsit_is_v4_mapped in iscsit_login.c
994a6d42e7dSPeter Dunlap 	 */
995a6d42e7dSPeter Dunlap 
996a6d42e7dSPeter Dunlap 	if (sa1->ss_family != sa2->ss_family) {
997a6d42e7dSPeter Dunlap 		return (1);
998a6d42e7dSPeter Dunlap 	}
999a6d42e7dSPeter Dunlap 
1000a6d42e7dSPeter Dunlap 	/*
1001a6d42e7dSPeter Dunlap 	 * sockaddr_in has padding which may not be initialized.
1002a6d42e7dSPeter Dunlap 	 * be more specific in the comparison, and don't trust the
1003a6d42e7dSPeter Dunlap 	 * caller has fully initialized the structure.
1004a6d42e7dSPeter Dunlap 	 */
1005a6d42e7dSPeter Dunlap 	if (sa1->ss_family == AF_INET) {
1006a6d42e7dSPeter Dunlap 		sin1 = (struct sockaddr_in *)sa1;
1007a6d42e7dSPeter Dunlap 		sin2 = (struct sockaddr_in *)sa2;
1008a6d42e7dSPeter Dunlap 		if ((bcmp(&sin1->sin_addr, &sin2->sin_addr,
1009a6d42e7dSPeter Dunlap 		    sizeof (struct in_addr)) == 0) &&
1010a6d42e7dSPeter Dunlap 		    (sin1->sin_port == sin2->sin_port)) {
1011a6d42e7dSPeter Dunlap 			return (0);
1012a6d42e7dSPeter Dunlap 		}
1013a6d42e7dSPeter Dunlap 	} else if (sa1->ss_family == AF_INET6) {
1014a6d42e7dSPeter Dunlap 		sin6_1 = (struct sockaddr_in6 *)sa1;
1015a6d42e7dSPeter Dunlap 		sin6_2 = (struct sockaddr_in6 *)sa2;
1016a6d42e7dSPeter Dunlap 		if (bcmp(sin6_1, sin6_2, sizeof (struct sockaddr_in6)) == 0) {
1017a6d42e7dSPeter Dunlap 			return (0);
1018a6d42e7dSPeter Dunlap 		}
1019a6d42e7dSPeter Dunlap 	}
1020a6d42e7dSPeter Dunlap 
1021a6d42e7dSPeter Dunlap 	return (1);
1022a6d42e7dSPeter Dunlap }
1023a6d42e7dSPeter Dunlap 
1024a6d42e7dSPeter Dunlap it_portal_t *
1025a6d42e7dSPeter Dunlap it_portal_lookup(it_tpg_t *tpg, struct sockaddr_storage *sa)
1026a6d42e7dSPeter Dunlap {
1027a6d42e7dSPeter Dunlap 	it_portal_t *cfg_portal;
1028a6d42e7dSPeter Dunlap 
1029a6d42e7dSPeter Dunlap 	for (cfg_portal = tpg->tpg_portal_list;
1030a6d42e7dSPeter Dunlap 	    cfg_portal != NULL;
1031a6d42e7dSPeter Dunlap 	    cfg_portal = cfg_portal->next) {
1032a6d42e7dSPeter Dunlap 		if (it_sa_compare(sa, &cfg_portal->portal_addr) == 0)
1033a6d42e7dSPeter Dunlap 			return (cfg_portal);
1034a6d42e7dSPeter Dunlap 	}
1035a6d42e7dSPeter Dunlap 
1036a6d42e7dSPeter Dunlap 	return (NULL);
1037a6d42e7dSPeter Dunlap }
1038a6d42e7dSPeter Dunlap 
1039a6d42e7dSPeter Dunlap it_portal_t *
1040a6d42e7dSPeter Dunlap it_sns_svr_lookup(it_config_t *cfg, struct sockaddr_storage *sa)
1041a6d42e7dSPeter Dunlap {
1042a6d42e7dSPeter Dunlap 	it_portal_t *cfg_portal;
1043a6d42e7dSPeter Dunlap 
1044a6d42e7dSPeter Dunlap 	for (cfg_portal = cfg->config_isns_svr_list;
1045a6d42e7dSPeter Dunlap 	    cfg_portal != NULL;
1046a6d42e7dSPeter Dunlap 	    cfg_portal = cfg_portal->next) {
1047a6d42e7dSPeter Dunlap 		if (it_sa_compare(sa, &cfg_portal->portal_addr) == 0)
1048a6d42e7dSPeter Dunlap 			return (cfg_portal);
1049a6d42e7dSPeter Dunlap 	}
1050a6d42e7dSPeter Dunlap 
1051a6d42e7dSPeter Dunlap 	return (NULL);
1052a6d42e7dSPeter Dunlap }
1053a6d42e7dSPeter Dunlap 
1054a6d42e7dSPeter Dunlap int
1055a6d42e7dSPeter Dunlap it_nv_to_tpglist(nvlist_t *nvl, uint32_t *count, it_tpg_t **tpglist)
1056a6d42e7dSPeter Dunlap {
1057a6d42e7dSPeter Dunlap 	int		ret = 0;
1058a6d42e7dSPeter Dunlap 	it_tpg_t	*tpg;
1059a6d42e7dSPeter Dunlap 	it_tpg_t	*prev = NULL;
1060a6d42e7dSPeter Dunlap 	nvpair_t	*nvp = NULL;
1061a6d42e7dSPeter Dunlap 	nvlist_t	*nvt;
1062a6d42e7dSPeter Dunlap 	char		*name;
1063a6d42e7dSPeter Dunlap 
1064a6d42e7dSPeter Dunlap 	if (!tpglist || !count) {
1065a6d42e7dSPeter Dunlap 		return (EINVAL);
1066a6d42e7dSPeter Dunlap 	}
1067a6d42e7dSPeter Dunlap 
1068a6d42e7dSPeter Dunlap 	*tpglist = NULL;
1069a6d42e7dSPeter Dunlap 	*count = 0;
1070a6d42e7dSPeter Dunlap 
1071a6d42e7dSPeter Dunlap 	if (!nvl) {
1072a6d42e7dSPeter Dunlap 		/* nothing to do */
1073a6d42e7dSPeter Dunlap 		return (0);
1074a6d42e7dSPeter Dunlap 	}
1075a6d42e7dSPeter Dunlap 
1076a6d42e7dSPeter Dunlap 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
1077a6d42e7dSPeter Dunlap 		name = nvpair_name(nvp);
1078a6d42e7dSPeter Dunlap 
1079a6d42e7dSPeter Dunlap 		ret = nvpair_value_nvlist(nvp, &nvt);
1080a6d42e7dSPeter Dunlap 		if (ret != 0) {
1081a6d42e7dSPeter Dunlap 			/* invalid entry? */
1082a6d42e7dSPeter Dunlap 			continue;
1083a6d42e7dSPeter Dunlap 		}
1084a6d42e7dSPeter Dunlap 
1085a6d42e7dSPeter Dunlap 		ret = it_nv_to_tpg(nvt, name, &tpg);
1086a6d42e7dSPeter Dunlap 		if (ret != 0) {
1087a6d42e7dSPeter Dunlap 			break;
1088a6d42e7dSPeter Dunlap 		}
1089a6d42e7dSPeter Dunlap 
1090a6d42e7dSPeter Dunlap 		(*count)++;
1091a6d42e7dSPeter Dunlap 
1092a6d42e7dSPeter Dunlap 		if (*tpglist == NULL) {
1093a6d42e7dSPeter Dunlap 			*tpglist = tpg;
1094a6d42e7dSPeter Dunlap 		} else {
1095a6d42e7dSPeter Dunlap 			prev->tpg_next = tpg;
1096a6d42e7dSPeter Dunlap 		}
1097a6d42e7dSPeter Dunlap 		prev = tpg;
1098a6d42e7dSPeter Dunlap 	}
1099a6d42e7dSPeter Dunlap 
1100a6d42e7dSPeter Dunlap 	if (ret != 0) {
1101a6d42e7dSPeter Dunlap 		it_tpg_free_cmn(*tpglist);
1102a6d42e7dSPeter Dunlap 		*tpglist = NULL;
1103a6d42e7dSPeter Dunlap 	}
1104a6d42e7dSPeter Dunlap 
1105a6d42e7dSPeter Dunlap 	return (ret);
1106a6d42e7dSPeter Dunlap }
1107a6d42e7dSPeter Dunlap 
1108a6d42e7dSPeter Dunlap int
1109a6d42e7dSPeter Dunlap it_ini_to_nv(it_ini_t *ini, nvlist_t **nvl)
1110a6d42e7dSPeter Dunlap {
1111a6d42e7dSPeter Dunlap 	int		ret;
1112a6d42e7dSPeter Dunlap 
1113a6d42e7dSPeter Dunlap 	if (!nvl) {
1114a6d42e7dSPeter Dunlap 		return (EINVAL);
1115a6d42e7dSPeter Dunlap 	}
1116a6d42e7dSPeter Dunlap 
1117a6d42e7dSPeter Dunlap 	if (!ini) {
1118a6d42e7dSPeter Dunlap 		return (0);
1119a6d42e7dSPeter Dunlap 	}
1120a6d42e7dSPeter Dunlap 
1121a6d42e7dSPeter Dunlap 	ret = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0);
1122a6d42e7dSPeter Dunlap 	if (ret != 0) {
1123a6d42e7dSPeter Dunlap 		return (ret);
1124a6d42e7dSPeter Dunlap 	}
1125a6d42e7dSPeter Dunlap 
1126a6d42e7dSPeter Dunlap 	if (ini->ini_properties) {
1127a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(*nvl, "properties",
1128a6d42e7dSPeter Dunlap 		    ini->ini_properties);
1129a6d42e7dSPeter Dunlap 	}
1130a6d42e7dSPeter Dunlap 
1131a6d42e7dSPeter Dunlap 	if (ret == 0) {
1132a6d42e7dSPeter Dunlap 		ret = nvlist_add_uint64(*nvl, "generation",
1133a6d42e7dSPeter Dunlap 		    ini->ini_generation);
1134a6d42e7dSPeter Dunlap 	} else if (ret == ENOENT) {
1135a6d42e7dSPeter Dunlap 		ret = 0;
1136a6d42e7dSPeter Dunlap 	}
1137a6d42e7dSPeter Dunlap 
1138a6d42e7dSPeter Dunlap 	if (ret != 0) {
1139a6d42e7dSPeter Dunlap 		nvlist_free(*nvl);
1140a6d42e7dSPeter Dunlap 		*nvl = NULL;
1141a6d42e7dSPeter Dunlap 	}
1142a6d42e7dSPeter Dunlap 
1143a6d42e7dSPeter Dunlap 	return (ret);
1144a6d42e7dSPeter Dunlap }
1145a6d42e7dSPeter Dunlap 
1146a6d42e7dSPeter Dunlap int
1147a6d42e7dSPeter Dunlap it_nv_to_ini(nvlist_t *nvl, char *name, it_ini_t **ini)
1148a6d42e7dSPeter Dunlap {
1149a6d42e7dSPeter Dunlap 	int		ret;
1150a6d42e7dSPeter Dunlap 	it_ini_t	*inip;
1151a6d42e7dSPeter Dunlap 	nvlist_t	*listval;
1152a6d42e7dSPeter Dunlap 
1153a6d42e7dSPeter Dunlap 	if (!name || !ini) {
1154a6d42e7dSPeter Dunlap 		return (EINVAL);
1155a6d42e7dSPeter Dunlap 	}
1156a6d42e7dSPeter Dunlap 
1157a6d42e7dSPeter Dunlap 	*ini = NULL;
1158a6d42e7dSPeter Dunlap 
1159a6d42e7dSPeter Dunlap 	if (!nvl) {
1160a6d42e7dSPeter Dunlap 		return (0);
1161a6d42e7dSPeter Dunlap 	}
1162a6d42e7dSPeter Dunlap 
1163a6d42e7dSPeter Dunlap 	inip = iscsit_zalloc(sizeof (it_ini_t));
1164a6d42e7dSPeter Dunlap 	if (!inip) {
1165a6d42e7dSPeter Dunlap 		return (ENOMEM);
1166a6d42e7dSPeter Dunlap 	}
1167a6d42e7dSPeter Dunlap 
1168a6d42e7dSPeter Dunlap 	(void) strlcpy(inip->ini_name, name, sizeof (inip->ini_name));
1169a6d42e7dSPeter Dunlap 
1170a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_nvlist(nvl, "properties", &listval);
1171a6d42e7dSPeter Dunlap 	if (ret == 0) {
1172a6d42e7dSPeter Dunlap 		ret = nvlist_dup(listval, &(inip->ini_properties), 0);
1173a6d42e7dSPeter Dunlap 	} else if (ret == ENOENT) {
1174a6d42e7dSPeter Dunlap 		ret = 0;
1175a6d42e7dSPeter Dunlap 	}
1176a6d42e7dSPeter Dunlap 
1177a6d42e7dSPeter Dunlap 	if (ret == 0) {
1178a6d42e7dSPeter Dunlap 		ret = nvlist_lookup_uint64(nvl, "generation",
1179a6d42e7dSPeter Dunlap 		    &(inip->ini_generation));
1180a6d42e7dSPeter Dunlap 	}
1181a6d42e7dSPeter Dunlap 
1182a6d42e7dSPeter Dunlap 	if (ret == 0) {
1183a6d42e7dSPeter Dunlap 		*ini = inip;
1184a6d42e7dSPeter Dunlap 	} else {
1185a6d42e7dSPeter Dunlap 		it_ini_free_cmn(inip);
1186a6d42e7dSPeter Dunlap 	}
1187a6d42e7dSPeter Dunlap 
1188a6d42e7dSPeter Dunlap 	return (ret);
1189a6d42e7dSPeter Dunlap }
1190a6d42e7dSPeter Dunlap 
1191a6d42e7dSPeter Dunlap int
1192a6d42e7dSPeter Dunlap it_inilist_to_nv(it_ini_t *inilist, nvlist_t **nvl)
1193a6d42e7dSPeter Dunlap {
1194a6d42e7dSPeter Dunlap 	int		ret;
1195a6d42e7dSPeter Dunlap 	nvlist_t	*pnv = NULL;
1196a6d42e7dSPeter Dunlap 	nvlist_t	*tnv;
1197a6d42e7dSPeter Dunlap 	it_ini_t	*ptr = inilist;
1198a6d42e7dSPeter Dunlap 
1199a6d42e7dSPeter Dunlap 	if (!nvl) {
1200a6d42e7dSPeter Dunlap 		return (EINVAL);
1201a6d42e7dSPeter Dunlap 	}
1202a6d42e7dSPeter Dunlap 
1203a6d42e7dSPeter Dunlap 	if (!inilist) {
1204a6d42e7dSPeter Dunlap 		return (0);
1205a6d42e7dSPeter Dunlap 	}
1206a6d42e7dSPeter Dunlap 
1207a6d42e7dSPeter Dunlap 	/* create the target list if required */
1208a6d42e7dSPeter Dunlap 	if (*nvl == NULL) {
1209a6d42e7dSPeter Dunlap 		ret = nvlist_alloc(&pnv, NV_UNIQUE_NAME, 0);
1210a6d42e7dSPeter Dunlap 		if (ret != 0) {
1211a6d42e7dSPeter Dunlap 			return (ret);
1212a6d42e7dSPeter Dunlap 		}
1213a6d42e7dSPeter Dunlap 		*nvl = pnv;
1214a6d42e7dSPeter Dunlap 	}
1215a6d42e7dSPeter Dunlap 
1216a6d42e7dSPeter Dunlap 	while (ptr) {
1217a6d42e7dSPeter Dunlap 		ret = it_ini_to_nv(ptr, &tnv);
1218a6d42e7dSPeter Dunlap 
1219a6d42e7dSPeter Dunlap 		if (ret != 0) {
1220a6d42e7dSPeter Dunlap 			break;
1221a6d42e7dSPeter Dunlap 		}
1222a6d42e7dSPeter Dunlap 
1223a6d42e7dSPeter Dunlap 		ret = nvlist_add_nvlist(*nvl, ptr->ini_name, tnv);
1224a6d42e7dSPeter Dunlap 
1225a6d42e7dSPeter Dunlap 		if (ret != 0) {
1226a6d42e7dSPeter Dunlap 			break;
1227a6d42e7dSPeter Dunlap 		}
1228a6d42e7dSPeter Dunlap 
1229a6d42e7dSPeter Dunlap 		nvlist_free(tnv);
1230a6d42e7dSPeter Dunlap 
1231a6d42e7dSPeter Dunlap 		ptr = ptr->ini_next;
1232a6d42e7dSPeter Dunlap 	}
1233a6d42e7dSPeter Dunlap 
1234a6d42e7dSPeter Dunlap 	if (ret != 0) {
1235a6d42e7dSPeter Dunlap 		if (pnv) {
1236a6d42e7dSPeter Dunlap 			nvlist_free(pnv);
1237a6d42e7dSPeter Dunlap 			*nvl = NULL;
1238a6d42e7dSPeter Dunlap 		}
1239a6d42e7dSPeter Dunlap 	}
1240a6d42e7dSPeter Dunlap 
1241a6d42e7dSPeter Dunlap 	return (ret);
1242a6d42e7dSPeter Dunlap }
1243a6d42e7dSPeter Dunlap 
1244a6d42e7dSPeter Dunlap int
1245a6d42e7dSPeter Dunlap it_nv_to_inilist(nvlist_t *nvl, uint32_t *count, it_ini_t **inilist)
1246a6d42e7dSPeter Dunlap {
1247a6d42e7dSPeter Dunlap 	int		ret = 0;
1248a6d42e7dSPeter Dunlap 	it_ini_t	*inip;
1249a6d42e7dSPeter Dunlap 	it_ini_t	*prev = NULL;
1250a6d42e7dSPeter Dunlap 	nvpair_t	*nvp = NULL;
1251a6d42e7dSPeter Dunlap 	nvlist_t	*nvt;
1252a6d42e7dSPeter Dunlap 	char		*name;
1253a6d42e7dSPeter Dunlap 
1254a6d42e7dSPeter Dunlap 	if (!inilist || !count) {
1255a6d42e7dSPeter Dunlap 		return (EINVAL);
1256a6d42e7dSPeter Dunlap 	}
1257a6d42e7dSPeter Dunlap 
1258a6d42e7dSPeter Dunlap 	*inilist = NULL;
1259a6d42e7dSPeter Dunlap 	*count = 0;
1260a6d42e7dSPeter Dunlap 
1261a6d42e7dSPeter Dunlap 	if (!nvl) {
1262a6d42e7dSPeter Dunlap 		/* nothing to do */
1263a6d42e7dSPeter Dunlap 		return (0);
1264a6d42e7dSPeter Dunlap 	}
1265a6d42e7dSPeter Dunlap 
1266a6d42e7dSPeter Dunlap 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
1267a6d42e7dSPeter Dunlap 		name = nvpair_name(nvp);
1268a6d42e7dSPeter Dunlap 
1269a6d42e7dSPeter Dunlap 		ret = nvpair_value_nvlist(nvp, &nvt);
1270a6d42e7dSPeter Dunlap 		if (ret != 0) {
1271a6d42e7dSPeter Dunlap 			/* invalid entry? */
1272a6d42e7dSPeter Dunlap 			continue;
1273a6d42e7dSPeter Dunlap 		}
1274a6d42e7dSPeter Dunlap 
1275a6d42e7dSPeter Dunlap 		ret = it_nv_to_ini(nvt, name, &inip);
1276a6d42e7dSPeter Dunlap 		if (ret != 0) {
1277a6d42e7dSPeter Dunlap 			break;
1278a6d42e7dSPeter Dunlap 		}
1279a6d42e7dSPeter Dunlap 
1280a6d42e7dSPeter Dunlap 		(*count)++;
1281a6d42e7dSPeter Dunlap 
1282a6d42e7dSPeter Dunlap 		if (*inilist == NULL) {
1283a6d42e7dSPeter Dunlap 			*inilist = inip;
1284a6d42e7dSPeter Dunlap 		} else {
1285a6d42e7dSPeter Dunlap 			prev->ini_next = inip;
1286a6d42e7dSPeter Dunlap 		}
1287a6d42e7dSPeter Dunlap 		prev = inip;
1288a6d42e7dSPeter Dunlap 	}
1289a6d42e7dSPeter Dunlap 
1290a6d42e7dSPeter Dunlap 	if (ret != 0) {
1291a6d42e7dSPeter Dunlap 		it_ini_free_cmn(*inilist);
1292a6d42e7dSPeter Dunlap 		*inilist = NULL;
1293a6d42e7dSPeter Dunlap 	}
1294a6d42e7dSPeter Dunlap 
1295a6d42e7dSPeter Dunlap 	return (ret);
1296a6d42e7dSPeter Dunlap }
1297a6d42e7dSPeter Dunlap 
1298a6d42e7dSPeter Dunlap /*
1299a6d42e7dSPeter Dunlap  * Convert a sockaddr to the string representation, suitable for
1300a6d42e7dSPeter Dunlap  * storing in an nvlist or printing out in a list.
1301a6d42e7dSPeter Dunlap  */
1302a6d42e7dSPeter Dunlap #ifndef _KERNEL
1303a6d42e7dSPeter Dunlap int
1304a6d42e7dSPeter Dunlap sockaddr_to_str(struct sockaddr_storage *sa, char **addr)
1305a6d42e7dSPeter Dunlap {
1306a6d42e7dSPeter Dunlap 	int			ret;
1307a6d42e7dSPeter Dunlap 	char			buf[INET6_ADDRSTRLEN + 7]; /* addr : port */
1308a6d42e7dSPeter Dunlap 	char			pbuf[7];
1309a6d42e7dSPeter Dunlap 	const char		*bufp;
1310a6d42e7dSPeter Dunlap 	struct sockaddr_in	*sin;
1311a6d42e7dSPeter Dunlap 	struct sockaddr_in6	*sin6;
1312a6d42e7dSPeter Dunlap 	uint16_t		port;
1313a6d42e7dSPeter Dunlap 
1314a6d42e7dSPeter Dunlap 	if (!sa || !addr) {
1315a6d42e7dSPeter Dunlap 		return (EINVAL);
1316a6d42e7dSPeter Dunlap 	}
1317a6d42e7dSPeter Dunlap 
1318a6d42e7dSPeter Dunlap 	buf[0] = '\0';
1319a6d42e7dSPeter Dunlap 
1320a6d42e7dSPeter Dunlap 	if (sa->ss_family == AF_INET) {
1321a6d42e7dSPeter Dunlap 		sin = (struct sockaddr_in *)sa;
1322a6d42e7dSPeter Dunlap 		bufp = inet_ntop(AF_INET,
1323a6d42e7dSPeter Dunlap 		    (const void *)&(sin->sin_addr.s_addr),
1324a6d42e7dSPeter Dunlap 		    buf, sizeof (buf));
1325a6d42e7dSPeter Dunlap 		if (bufp == NULL) {
1326a6d42e7dSPeter Dunlap 			ret = errno;
1327a6d42e7dSPeter Dunlap 			return (ret);
1328a6d42e7dSPeter Dunlap 		}
1329a6d42e7dSPeter Dunlap 		port = ntohs(sin->sin_port);
1330a6d42e7dSPeter Dunlap 	} else if (sa->ss_family == AF_INET6) {
1331a6d42e7dSPeter Dunlap 		(void) strlcat(buf, "[", sizeof (buf));
1332a6d42e7dSPeter Dunlap 		sin6 = (struct sockaddr_in6 *)sa;
1333a6d42e7dSPeter Dunlap 		bufp = inet_ntop(AF_INET6,
1334a6d42e7dSPeter Dunlap 		    (const void *)&sin6->sin6_addr.s6_addr,
1335a6d42e7dSPeter Dunlap 		    &buf[1], (sizeof (buf) - 1));
1336a6d42e7dSPeter Dunlap 		if (bufp == NULL) {
1337a6d42e7dSPeter Dunlap 			ret = errno;
1338a6d42e7dSPeter Dunlap 			return (ret);
1339a6d42e7dSPeter Dunlap 		}
1340a6d42e7dSPeter Dunlap 		(void) strlcat(buf, "]", sizeof (buf));
1341a6d42e7dSPeter Dunlap 		port = ntohs(sin6->sin6_port);
1342a6d42e7dSPeter Dunlap 	} else {
1343a6d42e7dSPeter Dunlap 		return (EINVAL);
1344a6d42e7dSPeter Dunlap 	}
1345a6d42e7dSPeter Dunlap 
1346a6d42e7dSPeter Dunlap 
1347a6d42e7dSPeter Dunlap 	(void) snprintf(pbuf, sizeof (pbuf), ":%u", port);
1348a6d42e7dSPeter Dunlap 	(void) strlcat(buf, pbuf, sizeof (buf));
1349a6d42e7dSPeter Dunlap 
1350a6d42e7dSPeter Dunlap 	*addr = strdup(buf);
1351a6d42e7dSPeter Dunlap 	if (*addr == NULL) {
1352a6d42e7dSPeter Dunlap 		return (ENOMEM);
1353a6d42e7dSPeter Dunlap 	}
1354a6d42e7dSPeter Dunlap 
1355a6d42e7dSPeter Dunlap 	return (0);
1356a6d42e7dSPeter Dunlap }
1357a6d42e7dSPeter Dunlap #endif /* !_KERNEL */
1358a6d42e7dSPeter Dunlap 
1359a6d42e7dSPeter Dunlap int
1360a6d42e7dSPeter Dunlap it_array_to_portallist(char **arr, uint32_t count, uint32_t default_port,
1361a6d42e7dSPeter Dunlap     it_portal_t **portallist, uint32_t *list_count)
1362a6d42e7dSPeter Dunlap {
1363a6d42e7dSPeter Dunlap 	int		ret = 0;
1364a6d42e7dSPeter Dunlap 	int		i;
1365a6d42e7dSPeter Dunlap 	it_portal_t	*portal;
1366a6d42e7dSPeter Dunlap 	it_portal_t	*prev = NULL;
1367a6d42e7dSPeter Dunlap 	it_portal_t	*tmp;
1368a6d42e7dSPeter Dunlap 
1369a6d42e7dSPeter Dunlap 	if (!arr || !portallist || !list_count) {
1370a6d42e7dSPeter Dunlap 		return (EINVAL);
1371a6d42e7dSPeter Dunlap 	}
1372a6d42e7dSPeter Dunlap 
1373a6d42e7dSPeter Dunlap 	*list_count = 0;
1374a6d42e7dSPeter Dunlap 	*portallist = NULL;
1375a6d42e7dSPeter Dunlap 
1376a6d42e7dSPeter Dunlap 	for (i = 0; i < count; i++) {
1377a6d42e7dSPeter Dunlap 		if (!arr[i]) {
1378a6d42e7dSPeter Dunlap 			/* should never happen */
1379a6d42e7dSPeter Dunlap 			continue;
1380a6d42e7dSPeter Dunlap 		}
1381a6d42e7dSPeter Dunlap 		portal = iscsit_zalloc(sizeof (it_portal_t));
1382a6d42e7dSPeter Dunlap 		if (!portal) {
1383a6d42e7dSPeter Dunlap 			ret = ENOMEM;
1384a6d42e7dSPeter Dunlap 			break;
1385a6d42e7dSPeter Dunlap 		}
1386a6d42e7dSPeter Dunlap 		if (it_common_convert_sa(arr[i],
1387a6d42e7dSPeter Dunlap 		    &(portal->portal_addr), default_port) == NULL) {
1388a6d42e7dSPeter Dunlap 			iscsit_free(portal, sizeof (it_portal_t));
1389a6d42e7dSPeter Dunlap 			ret = EINVAL;
1390a6d42e7dSPeter Dunlap 			break;
1391a6d42e7dSPeter Dunlap 		}
1392a6d42e7dSPeter Dunlap 
1393a6d42e7dSPeter Dunlap 		/* make sure no duplicates */
1394a6d42e7dSPeter Dunlap 		tmp = *portallist;
1395a6d42e7dSPeter Dunlap 		while (tmp) {
1396a6d42e7dSPeter Dunlap 			if (it_sa_compare(&(tmp->portal_addr),
1397a6d42e7dSPeter Dunlap 			    &(portal->portal_addr)) == 0) {
1398a6d42e7dSPeter Dunlap 				iscsit_free(portal, sizeof (it_portal_t));
1399a6d42e7dSPeter Dunlap 				portal = NULL;
1400a6d42e7dSPeter Dunlap 				break;
1401a6d42e7dSPeter Dunlap 			}
1402a6d42e7dSPeter Dunlap 			tmp = tmp->next;
1403a6d42e7dSPeter Dunlap 		}
1404a6d42e7dSPeter Dunlap 
1405a6d42e7dSPeter Dunlap 		if (!portal) {
1406a6d42e7dSPeter Dunlap 			continue;
1407a6d42e7dSPeter Dunlap 		}
1408a6d42e7dSPeter Dunlap 
1409a6d42e7dSPeter Dunlap 		/*
1410a6d42e7dSPeter Dunlap 		 * The first time through the loop, *portallist == NULL
1411a6d42e7dSPeter Dunlap 		 * because we assigned it to NULL above.  Subsequently
1412a6d42e7dSPeter Dunlap 		 * prev will have been set.  Therefor it's OK to put
1413a6d42e7dSPeter Dunlap 		 * lint override before prev->next assignment.
1414a6d42e7dSPeter Dunlap 		 */
1415a6d42e7dSPeter Dunlap 		if (*portallist == NULL) {
1416a6d42e7dSPeter Dunlap 			*portallist = portal;
1417a6d42e7dSPeter Dunlap 		} else {
1418a6d42e7dSPeter Dunlap 			prev->next = portal;
1419a6d42e7dSPeter Dunlap 		}
1420a6d42e7dSPeter Dunlap 
1421a6d42e7dSPeter Dunlap 		prev = portal;
1422a6d42e7dSPeter Dunlap 		(*list_count)++;
1423a6d42e7dSPeter Dunlap 	}
1424a6d42e7dSPeter Dunlap 
1425a6d42e7dSPeter Dunlap 	return (ret);
1426a6d42e7dSPeter Dunlap }
1427a6d42e7dSPeter Dunlap 
1428a6d42e7dSPeter Dunlap /*
1429a6d42e7dSPeter Dunlap  * Function:  it_config_free_cmn()
1430a6d42e7dSPeter Dunlap  *
1431a6d42e7dSPeter Dunlap  * Free any resources associated with the it_config_t structure.
1432a6d42e7dSPeter Dunlap  *
1433a6d42e7dSPeter Dunlap  * Parameters:
1434a6d42e7dSPeter Dunlap  *    cfg       A C representation of the current iSCSI configuration
1435a6d42e7dSPeter Dunlap  */
1436a6d42e7dSPeter Dunlap void
1437a6d42e7dSPeter Dunlap it_config_free_cmn(it_config_t *cfg)
1438a6d42e7dSPeter Dunlap {
1439a6d42e7dSPeter Dunlap 	if (!cfg) {
1440a6d42e7dSPeter Dunlap 		return;
1441a6d42e7dSPeter Dunlap 	}
1442a6d42e7dSPeter Dunlap 
1443a6d42e7dSPeter Dunlap 	if (cfg->config_tgt_list) {
1444a6d42e7dSPeter Dunlap 		it_tgt_free_cmn(cfg->config_tgt_list);
1445a6d42e7dSPeter Dunlap 	}
1446a6d42e7dSPeter Dunlap 
1447a6d42e7dSPeter Dunlap 	if (cfg->config_tpg_list) {
1448a6d42e7dSPeter Dunlap 		it_tpg_free_cmn(cfg->config_tpg_list);
1449a6d42e7dSPeter Dunlap 	}
1450a6d42e7dSPeter Dunlap 
1451a6d42e7dSPeter Dunlap 	if (cfg->config_ini_list) {
1452a6d42e7dSPeter Dunlap 		it_ini_free_cmn(cfg->config_ini_list);
1453a6d42e7dSPeter Dunlap 	}
1454a6d42e7dSPeter Dunlap 
1455a6d42e7dSPeter Dunlap 	if (cfg->config_global_properties) {
1456a6d42e7dSPeter Dunlap 		nvlist_free(cfg->config_global_properties);
1457a6d42e7dSPeter Dunlap 	}
1458a6d42e7dSPeter Dunlap 
1459a6d42e7dSPeter Dunlap 	if (cfg->config_isns_svr_list) {
1460a6d42e7dSPeter Dunlap 		it_portal_t	*pp = cfg->config_isns_svr_list;
1461a6d42e7dSPeter Dunlap 		it_portal_t	*pp_next;
1462a6d42e7dSPeter Dunlap 
1463a6d42e7dSPeter Dunlap 		while (pp) {
1464a6d42e7dSPeter Dunlap 			pp_next = pp->next;
1465a6d42e7dSPeter Dunlap 			iscsit_free(pp, sizeof (it_portal_t));
1466a6d42e7dSPeter Dunlap 			pp = pp_next;
1467a6d42e7dSPeter Dunlap 		}
1468a6d42e7dSPeter Dunlap 	}
1469a6d42e7dSPeter Dunlap 
1470a6d42e7dSPeter Dunlap 	iscsit_free(cfg, sizeof (it_config_t));
1471a6d42e7dSPeter Dunlap }
1472a6d42e7dSPeter Dunlap 
1473a6d42e7dSPeter Dunlap /*
1474a6d42e7dSPeter Dunlap  * Function:  it_tgt_free_cmn()
1475a6d42e7dSPeter Dunlap  *
1476a6d42e7dSPeter Dunlap  * Frees an it_tgt_t structure.  If tgt_next is not NULL, frees
1477a6d42e7dSPeter Dunlap  * all structures in the list.
1478a6d42e7dSPeter Dunlap  */
1479a6d42e7dSPeter Dunlap void
1480a6d42e7dSPeter Dunlap it_tgt_free_cmn(it_tgt_t *tgt)
1481a6d42e7dSPeter Dunlap {
1482a6d42e7dSPeter Dunlap 	it_tgt_t	*tgtp = tgt;
1483a6d42e7dSPeter Dunlap 	it_tgt_t	*next;
1484a6d42e7dSPeter Dunlap 
1485a6d42e7dSPeter Dunlap 	if (!tgt) {
1486a6d42e7dSPeter Dunlap 		return;
1487a6d42e7dSPeter Dunlap 	}
1488a6d42e7dSPeter Dunlap 
1489a6d42e7dSPeter Dunlap 	while (tgtp) {
1490a6d42e7dSPeter Dunlap 		next = tgtp->tgt_next;
1491a6d42e7dSPeter Dunlap 
1492a6d42e7dSPeter Dunlap 		if (tgtp->tgt_tpgt_list) {
1493a6d42e7dSPeter Dunlap 			it_tpgt_free_cmn(tgtp->tgt_tpgt_list);
1494a6d42e7dSPeter Dunlap 		}
1495a6d42e7dSPeter Dunlap 
1496a6d42e7dSPeter Dunlap 		if (tgtp->tgt_properties) {
1497a6d42e7dSPeter Dunlap 			nvlist_free(tgtp->tgt_properties);
1498a6d42e7dSPeter Dunlap 		}
1499a6d42e7dSPeter Dunlap 
1500a6d42e7dSPeter Dunlap 		iscsit_free(tgtp, sizeof (it_tgt_t));
1501a6d42e7dSPeter Dunlap 
1502a6d42e7dSPeter Dunlap 		tgtp = next;
1503a6d42e7dSPeter Dunlap 	}
1504a6d42e7dSPeter Dunlap }
1505a6d42e7dSPeter Dunlap 
1506a6d42e7dSPeter Dunlap /*
1507a6d42e7dSPeter Dunlap  * Function:  it_tpgt_free_cmn()
1508a6d42e7dSPeter Dunlap  *
1509a6d42e7dSPeter Dunlap  * Deallocates resources of an it_tpgt_t structure.  If tpgt->next
1510a6d42e7dSPeter Dunlap  * is not NULL, frees all members of the list.
1511a6d42e7dSPeter Dunlap  */
1512a6d42e7dSPeter Dunlap void
1513a6d42e7dSPeter Dunlap it_tpgt_free_cmn(it_tpgt_t *tpgt)
1514a6d42e7dSPeter Dunlap {
1515a6d42e7dSPeter Dunlap 	it_tpgt_t	*tpgtp = tpgt;
1516a6d42e7dSPeter Dunlap 	it_tpgt_t	*next;
1517a6d42e7dSPeter Dunlap 
1518a6d42e7dSPeter Dunlap 	if (!tpgt) {
1519a6d42e7dSPeter Dunlap 		return;
1520a6d42e7dSPeter Dunlap 	}
1521a6d42e7dSPeter Dunlap 
1522a6d42e7dSPeter Dunlap 	while (tpgtp) {
1523a6d42e7dSPeter Dunlap 		next = tpgtp->tpgt_next;
1524a6d42e7dSPeter Dunlap 
1525a6d42e7dSPeter Dunlap 		iscsit_free(tpgtp, sizeof (it_tpgt_t));
1526a6d42e7dSPeter Dunlap 
1527a6d42e7dSPeter Dunlap 		tpgtp = next;
1528a6d42e7dSPeter Dunlap 	}
1529a6d42e7dSPeter Dunlap }
1530a6d42e7dSPeter Dunlap 
1531a6d42e7dSPeter Dunlap /*
1532a6d42e7dSPeter Dunlap  * Function:  it_tpg_free_cmn()
1533a6d42e7dSPeter Dunlap  *
1534a6d42e7dSPeter Dunlap  * Deallocates resources associated with an it_tpg_t structure.
1535a6d42e7dSPeter Dunlap  * If tpg->next is not NULL, frees all members of the list.
1536a6d42e7dSPeter Dunlap  */
1537a6d42e7dSPeter Dunlap void
1538a6d42e7dSPeter Dunlap it_tpg_free_cmn(it_tpg_t *tpg)
1539a6d42e7dSPeter Dunlap {
1540a6d42e7dSPeter Dunlap 	it_tpg_t	*tpgp = tpg;
1541a6d42e7dSPeter Dunlap 	it_tpg_t	*next;
1542a6d42e7dSPeter Dunlap 	it_portal_t	*portalp;
1543a6d42e7dSPeter Dunlap 	it_portal_t	*pnext;
1544a6d42e7dSPeter Dunlap 
1545a6d42e7dSPeter Dunlap 	while (tpgp) {
1546a6d42e7dSPeter Dunlap 		next = tpgp->tpg_next;
1547a6d42e7dSPeter Dunlap 
1548a6d42e7dSPeter Dunlap 		portalp = tpgp->tpg_portal_list;
1549a6d42e7dSPeter Dunlap 
1550a6d42e7dSPeter Dunlap 		while (portalp) {
1551a6d42e7dSPeter Dunlap 			pnext = portalp->next;
1552a6d42e7dSPeter Dunlap 			iscsit_free(portalp, sizeof (it_portal_t));
1553a6d42e7dSPeter Dunlap 			portalp = pnext;
1554a6d42e7dSPeter Dunlap 		}
1555a6d42e7dSPeter Dunlap 
1556a6d42e7dSPeter Dunlap 		iscsit_free(tpgp, sizeof (it_tpg_t));
1557a6d42e7dSPeter Dunlap 
1558a6d42e7dSPeter Dunlap 		tpgp = next;
1559a6d42e7dSPeter Dunlap 	}
1560a6d42e7dSPeter Dunlap }
1561a6d42e7dSPeter Dunlap 
1562a6d42e7dSPeter Dunlap /*
1563a6d42e7dSPeter Dunlap  * Function:  it_ini_free_cmn()
1564a6d42e7dSPeter Dunlap  *
1565a6d42e7dSPeter Dunlap  * Deallocates resources of an it_ini_t structure. If ini->next is
1566a6d42e7dSPeter Dunlap  * not NULL, frees all members of the list.
1567a6d42e7dSPeter Dunlap  */
1568a6d42e7dSPeter Dunlap void
1569a6d42e7dSPeter Dunlap it_ini_free_cmn(it_ini_t *ini)
1570a6d42e7dSPeter Dunlap {
1571a6d42e7dSPeter Dunlap 	it_ini_t	*inip = ini;
1572a6d42e7dSPeter Dunlap 	it_ini_t	*next;
1573a6d42e7dSPeter Dunlap 
1574a6d42e7dSPeter Dunlap 	if (!ini) {
1575a6d42e7dSPeter Dunlap 		return;
1576a6d42e7dSPeter Dunlap 	}
1577a6d42e7dSPeter Dunlap 
1578a6d42e7dSPeter Dunlap 	while (inip) {
1579a6d42e7dSPeter Dunlap 		next = inip->ini_next;
1580a6d42e7dSPeter Dunlap 
1581a6d42e7dSPeter Dunlap 		if (inip->ini_properties) {
1582a6d42e7dSPeter Dunlap 			nvlist_free(inip->ini_properties);
1583a6d42e7dSPeter Dunlap 		}
1584a6d42e7dSPeter Dunlap 
1585a6d42e7dSPeter Dunlap 		iscsit_free(inip, sizeof (it_ini_t));
1586a6d42e7dSPeter Dunlap 
1587a6d42e7dSPeter Dunlap 		inip = next;
1588a6d42e7dSPeter Dunlap 	}
1589a6d42e7dSPeter Dunlap }
1590