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