4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
31 #include <sys/types.h>
32 #include <sys/sunddi.h>
33 #include <sys/socket.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
47 #include <sys/iscsit/iscsit_common.h>
48 #include <sys/iscsi_protocol.h>
49 #include <sys/iscsit/isns_protocol.h>
52 iscsit_zalloc(size_t size
)
55 return (kmem_zalloc(size
, KM_SLEEP
));
57 return (calloc(1, size
));
62 iscsit_free(void *buf
, size_t size
) /* ARGSUSED */
72 * default_port should be the port to be used, if not specified
73 * as part of the supplied string 'arg'.
76 #define NI_MAXHOST 1025
80 struct sockaddr_storage
*
81 it_common_convert_sa(char *arg
, struct sockaddr_storage
*buf
,
82 uint32_t default_port
)
84 /* Why does addrbuf need to be this big!??! XXX */
85 char addrbuf
[NI_MAXHOST
+ NI_MAXSERV
+ 1];
94 struct sockaddr_in
*sin
;
95 struct sockaddr_in6
*sin6
;
96 struct sockaddr_storage
*sa
= buf
;
102 bzero(buf
, sizeof (struct sockaddr_storage
));
104 /* don't modify the passed-in string */
105 (void) strlcpy(addrbuf
, arg
, sizeof (addrbuf
));
109 if (*addr_str
== '[') {
111 * An IPv6 address must be inside square brackets
113 port_str
= strchr(addr_str
, ']');
115 /* No closing bracket */
119 /* strip off the square brackets so we can convert */
124 if (*port_str
== ':') {
125 /* TCP port to follow */
127 } else if (*port_str
== '\0') {
128 /* No port specified */
136 port_str
= strchr(addr_str
, ':');
146 if (ddi_strtol(port_str
, NULL
, 10, &tmp_port
) != 0) {
150 tmp_port
= strtol(port_str
, &errchr
, 10);
152 if (tmp_port
< 0 || tmp_port
> 65535) {
156 tmp_port
= default_port
;
161 sin
= (struct sockaddr_in
*)sa
;
163 if (inet_pton(af
, addr_str
,
164 (void *)&(sin
->sin_addr
.s_addr
)) != 1) {
167 sin
->sin_port
= htons(tmp_port
);
169 sin6
= (struct sockaddr_in6
*)sa
;
170 if (inet_pton(af
, addr_str
,
171 (void *)&(sin6
->sin6_addr
.s6_addr
)) != 1) {
174 sin6
->sin6_port
= htons(tmp_port
);
182 /* Functions to convert iSCSI target structures to/from nvlists. */
186 it_config_to_nv(it_config_t
*cfg
, nvlist_t
**nvl
)
190 nvlist_t
*lnv
= NULL
;
198 ret
= nvlist_alloc(&nv
, NV_UNIQUE_NAME_TYPE
, 0);
203 /* if there's no config, store an empty list */
209 ret
= nvlist_add_uint32(nv
, "cfgVersion", cfg
->config_version
);
211 ret
= it_tgtlist_to_nv(cfg
->config_tgt_list
, &lnv
);
214 if ((ret
== 0) && (lnv
!= NULL
)) {
215 ret
= nvlist_add_nvlist(nv
, "targetList", lnv
);
221 ret
= it_tpglist_to_nv(cfg
->config_tpg_list
, &lnv
);
224 if ((ret
== 0) && (lnv
!= NULL
)) {
225 ret
= nvlist_add_nvlist(nv
, "tpgList", lnv
);
231 ret
= it_inilist_to_nv(cfg
->config_ini_list
, &lnv
);
234 if ((ret
== 0) && (lnv
!= NULL
)) {
235 ret
= nvlist_add_nvlist(nv
, "iniList", lnv
);
241 ret
= nvlist_add_nvlist(nv
, "globalProperties",
242 cfg
->config_global_properties
);
253 #endif /* !_KERNEL */
256 * nvlist version of config is 3 list-of-list, + 1 proplist. arrays
257 * are interesting, but lists-of-lists are more useful when doing
258 * individual lookups when we later add support for it. Also, no
259 * need to store name in individual struct representation.
262 it_nv_to_config(nvlist_t
*nvl
, it_config_t
**cfg
)
273 /* initialize output */
276 tmpcfg
= iscsit_zalloc(sizeof (it_config_t
));
277 if (tmpcfg
== NULL
) {
282 /* nothing to decode, but return the empty cfg struct */
283 ret
= nvlist_alloc(&tmpcfg
->config_global_properties
,
286 iscsit_free(tmpcfg
, sizeof (it_config_t
));
293 ret
= nvlist_lookup_uint32(nvl
, "cfgVersion", &intval
);
295 iscsit_free(tmpcfg
, sizeof (it_config_t
));
299 tmpcfg
->config_version
= intval
;
301 ret
= nvlist_lookup_nvlist(nvl
, "targetList", &listval
);
303 /* decode list of it_tgt_t */
304 ret
= it_nv_to_tgtlist(listval
, &(tmpcfg
->config_tgt_count
),
305 &(tmpcfg
->config_tgt_list
));
308 ret
= nvlist_lookup_nvlist(nvl
, "tpgList", &listval
);
310 /* decode list of it_tpg_t */
311 ret
= it_nv_to_tpglist(listval
, &(tmpcfg
->config_tpg_count
),
312 &(tmpcfg
->config_tpg_list
));
315 ret
= nvlist_lookup_nvlist(nvl
, "iniList", &listval
);
317 /* decode list of initiators */
318 ret
= it_nv_to_inilist(listval
, &(tmpcfg
->config_ini_count
),
319 &(tmpcfg
->config_ini_list
));
322 ret
= nvlist_lookup_nvlist(nvl
, "globalProperties", &listval
);
325 * don't depend on the original nvlist staying in-scope,
326 * duplicate the nvlist
328 ret
= nvlist_dup(listval
, &(tmpcfg
->config_global_properties
),
330 } else if (ret
== ENOENT
) {
332 * No global properties defined, make an empty list
334 ret
= nvlist_alloc(&tmpcfg
->config_global_properties
,
339 char **isnsArray
= NULL
;
340 uint32_t numisns
= 0;
343 * decode the list of iSNS server information to make
344 * references from the kernel simpler.
346 if (tmpcfg
->config_global_properties
) {
347 ret
= nvlist_lookup_string_array(
348 tmpcfg
->config_global_properties
,
350 &isnsArray
, &numisns
);
352 ret
= it_array_to_portallist(isnsArray
,
353 numisns
, ISNS_DEFAULT_SERVER_PORT
,
354 &tmpcfg
->config_isns_svr_list
,
355 &tmpcfg
->config_isns_svr_count
);
356 } else if (ret
== ENOENT
) {
357 /* It's OK if we don't have any iSNS servers */
366 it_config_free_cmn(tmpcfg
);
373 it_tgt_lookup(it_config_t
*cfg
, char *tgt_name
)
375 it_tgt_t
*cfg_tgt
= NULL
;
377 for (cfg_tgt
= cfg
->config_tgt_list
;
379 cfg_tgt
= cfg_tgt
->tgt_next
) {
380 if (strncmp(cfg_tgt
->tgt_name
, tgt_name
,
381 MAX_ISCSI_NODENAMELEN
) == 0) {
390 it_nv_to_tgtlist(nvlist_t
*nvl
, uint32_t *count
, it_tgt_t
**tgtlist
)
394 it_tgt_t
*prev
= NULL
;
395 nvpair_t
*nvp
= NULL
;
399 if (!tgtlist
|| !count
) {
411 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
) {
412 name
= nvpair_name(nvp
);
414 ret
= nvpair_value_nvlist(nvp
, &nvt
);
420 ret
= it_nv_to_tgt(nvt
, name
, &tgt
);
427 if (*tgtlist
== NULL
) {
430 prev
->tgt_next
= tgt
;
436 it_tgt_free_cmn(*tgtlist
);
444 it_tgtlist_to_nv(it_tgt_t
*tgtlist
, nvlist_t
**nvl
)
447 it_tgt_t
*tgtp
= tgtlist
;
448 nvlist_t
*pnv
= NULL
;
460 /* create the target list if required */
462 ret
= nvlist_alloc(&pnv
, NV_UNIQUE_NAME
, 0);
470 ret
= it_tgt_to_nv(tgtp
, &tnv
);
476 ret
= nvlist_add_nvlist(*nvl
, tgtp
->tgt_name
, tnv
);
484 tgtp
= tgtp
->tgt_next
;
498 it_tgt_to_nv(it_tgt_t
*tgt
, nvlist_t
**nvl
)
501 nvlist_t
*tnv
= NULL
;
512 ret
= nvlist_alloc(nvl
, NV_UNIQUE_NAME
, 0);
517 if (tgt
->tgt_properties
) {
518 ret
= nvlist_add_nvlist(*nvl
, "properties",
519 tgt
->tgt_properties
);
523 ret
= nvlist_add_uint64(*nvl
, "generation",
524 tgt
->tgt_generation
);
528 ret
= it_tpgtlist_to_nv(tgt
->tgt_tpgt_list
, &tnv
);
531 if ((ret
== 0) && tnv
) {
532 ret
= nvlist_add_nvlist(*nvl
, "tpgtList", tnv
);
545 it_nv_to_tgt(nvlist_t
*nvl
, char *name
, it_tgt_t
**tgt
)
552 if (!nvl
|| !tgt
|| !name
) {
558 ttgt
= iscsit_zalloc(sizeof (it_tgt_t
));
563 (void) strlcpy(ttgt
->tgt_name
, name
, sizeof (ttgt
->tgt_name
));
565 ret
= nvlist_lookup_nvlist(nvl
, "properties", &listval
);
567 /* duplicate list so it does not go out of context */
568 ret
= nvlist_dup(listval
, &(ttgt
->tgt_properties
), 0);
569 } else if (ret
== ENOENT
) {
574 ret
= nvlist_lookup_uint64(nvl
, "generation",
575 &(ttgt
->tgt_generation
));
576 } else if (ret
== ENOENT
) {
581 ret
= nvlist_lookup_nvlist(nvl
, "tpgtList", &listval
);
585 ret
= it_nv_to_tpgtlist(listval
, &intval
,
586 &(ttgt
->tgt_tpgt_list
));
587 ttgt
->tgt_tpgt_count
= intval
;
588 } else if (ret
== ENOENT
) {
595 it_tgt_free_cmn(ttgt
);
602 it_tpgt_to_nv(it_tpgt_t
*tpgt
, nvlist_t
**nvl
)
615 ret
= nvlist_alloc(nvl
, NV_UNIQUE_NAME
, 0);
620 ret
= nvlist_add_uint16(*nvl
, "tag", tpgt
->tpgt_tag
);
622 ret
= nvlist_add_uint64(*nvl
, "generation",
623 tpgt
->tpgt_generation
);
635 it_nv_to_tpgt(nvlist_t
*nvl
, char *name
, it_tpgt_t
**tpgt
)
640 if (!tpgt
|| !name
) {
650 ptr
= iscsit_zalloc(sizeof (it_tpgt_t
));
655 (void) strlcpy(ptr
->tpgt_tpg_name
, name
, sizeof (ptr
->tpgt_tpg_name
));
657 ret
= nvlist_lookup_uint16(nvl
, "tag", &(ptr
->tpgt_tag
));
659 ret
= nvlist_lookup_uint64(nvl
, "generation",
660 &(ptr
->tpgt_generation
));
666 iscsit_free(ptr
, sizeof (it_tpgt_t
));
673 it_tpgtlist_to_nv(it_tpgt_t
*tpgtlist
, nvlist_t
**nvl
)
676 nvlist_t
*pnv
= NULL
;
678 it_tpgt_t
*ptr
= tpgtlist
;
689 /* create the target list if required */
691 ret
= nvlist_alloc(&pnv
, NV_UNIQUE_NAME
, 0);
699 ret
= it_tpgt_to_nv(ptr
, &tnv
);
705 ret
= nvlist_add_nvlist(*nvl
, ptr
->tpgt_tpg_name
, tnv
);
713 ptr
= ptr
->tpgt_next
;
727 it_nv_to_tpgtlist(nvlist_t
*nvl
, uint32_t *count
, it_tpgt_t
**tpgtlist
)
731 it_tpgt_t
*prev
= NULL
;
732 nvpair_t
*nvp
= NULL
;
736 if (!tpgtlist
|| !count
) {
748 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
) {
749 name
= nvpair_name(nvp
);
751 ret
= nvpair_value_nvlist(nvp
, &nvt
);
757 ret
= it_nv_to_tpgt(nvt
, name
, &tpgt
);
764 if (*tpgtlist
== NULL
) {
767 prev
->tpgt_next
= tpgt
;
774 it_tpgt_free_cmn(*tpgtlist
);
783 it_tpg_to_nv(it_tpg_t
*tpg
, nvlist_t
**nvl
)
786 char **portalArray
= NULL
;
799 ret
= nvlist_alloc(nvl
, NV_UNIQUE_NAME
, 0);
804 ret
= nvlist_add_uint64(*nvl
, "generation", tpg
->tpg_generation
);
806 if ((ret
== 0) && tpg
->tpg_portal_list
) {
807 /* add the portals */
808 portalArray
= iscsit_zalloc(tpg
->tpg_portal_count
*
809 sizeof (it_portal_t
));
810 if (portalArray
== NULL
) {
817 ptr
= tpg
->tpg_portal_list
;
819 while (ptr
&& (i
< tpg
->tpg_portal_count
)) {
820 ret
= sockaddr_to_str(&(ptr
->portal_addr
),
825 ptr
= ptr
->portal_next
;
830 ret
= nvlist_add_string_array(*nvl
, "portalList",
836 if (portalArray
[i
]) {
837 iscsit_free(portalArray
[i
],
838 strlen(portalArray
[i
] + 1));
841 iscsit_free(portalArray
,
842 tpg
->tpg_portal_count
* sizeof (it_portal_t
));
852 #endif /* !_KERNEL */
855 it_nv_to_tpg(nvlist_t
*nvl
, char *name
, it_tpg_t
**tpg
)
859 char **portalArray
= NULL
;
868 ptpg
= iscsit_zalloc(sizeof (it_tpg_t
));
873 (void) strlcpy(ptpg
->tpg_name
, name
, sizeof (ptpg
->tpg_name
));
875 ret
= nvlist_lookup_uint64(nvl
, "generation",
876 &(ptpg
->tpg_generation
));
879 ret
= nvlist_lookup_string_array(nvl
, "portalList",
880 &portalArray
, &count
);
884 /* set the portals */
885 ret
= it_array_to_portallist(portalArray
, count
,
886 ISCSI_LISTEN_PORT
, &ptpg
->tpg_portal_list
,
887 &ptpg
->tpg_portal_count
);
888 } else if (ret
== ENOENT
) {
895 it_tpg_free_cmn(ptpg
);
906 it_tpglist_to_nv(it_tpg_t
*tpglist
, nvlist_t
**nvl
)
909 nvlist_t
*pnv
= NULL
;
911 it_tpg_t
*ptr
= tpglist
;
922 /* create the target portal group list if required */
924 ret
= nvlist_alloc(&pnv
, NV_UNIQUE_NAME
, 0);
932 ret
= it_tpg_to_nv(ptr
, &tnv
);
938 ret
= nvlist_add_nvlist(*nvl
, ptr
->tpg_name
, tnv
);
958 #endif /* !_KERNEL */
961 it_tpg_lookup(it_config_t
*cfg
, char *tpg_name
)
963 it_tpg_t
*cfg_tpg
= NULL
;
965 for (cfg_tpg
= cfg
->config_tpg_list
;
967 cfg_tpg
= cfg_tpg
->tpg_next
) {
968 if (strncmp(&cfg_tpg
->tpg_name
[0], tpg_name
,
969 MAX_TPG_NAMELEN
) == 0) {
978 it_sa_compare(struct sockaddr_storage
*sa1
, struct sockaddr_storage
*sa2
)
980 struct sockaddr_in
*sin1
, *sin2
;
981 struct sockaddr_in6
*sin6_1
, *sin6_2
;
984 * XXX - should we check here for IPv4 addrs mapped to v6?
985 * see also iscsit_is_v4_mapped in iscsit_login.c
988 if (sa1
->ss_family
!= sa2
->ss_family
) {
993 * sockaddr_in has padding which may not be initialized.
994 * be more specific in the comparison, and don't trust the
995 * caller has fully initialized the structure.
997 if (sa1
->ss_family
== AF_INET
) {
998 sin1
= (struct sockaddr_in
*)sa1
;
999 sin2
= (struct sockaddr_in
*)sa2
;
1000 if ((bcmp(&sin1
->sin_addr
, &sin2
->sin_addr
,
1001 sizeof (struct in_addr
)) == 0) &&
1002 (sin1
->sin_port
== sin2
->sin_port
)) {
1005 } else if (sa1
->ss_family
== AF_INET6
) {
1006 sin6_1
= (struct sockaddr_in6
*)sa1
;
1007 sin6_2
= (struct sockaddr_in6
*)sa2
;
1008 if (bcmp(sin6_1
, sin6_2
, sizeof (struct sockaddr_in6
)) == 0) {
1017 it_portal_lookup(it_tpg_t
*tpg
, struct sockaddr_storage
*sa
)
1019 it_portal_t
*cfg_portal
;
1021 for (cfg_portal
= tpg
->tpg_portal_list
;
1023 cfg_portal
= cfg_portal
->portal_next
) {
1024 if (it_sa_compare(sa
, &cfg_portal
->portal_addr
) == 0)
1025 return (cfg_portal
);
1032 it_sns_svr_lookup(it_config_t
*cfg
, struct sockaddr_storage
*sa
)
1034 it_portal_t
*cfg_portal
;
1036 for (cfg_portal
= cfg
->config_isns_svr_list
;
1038 cfg_portal
= cfg_portal
->portal_next
) {
1039 if (it_sa_compare(sa
, &cfg_portal
->portal_addr
) == 0)
1040 return (cfg_portal
);
1047 it_nv_to_tpglist(nvlist_t
*nvl
, uint32_t *count
, it_tpg_t
**tpglist
)
1051 it_tpg_t
*prev
= NULL
;
1052 nvpair_t
*nvp
= NULL
;
1056 if (!tpglist
|| !count
) {
1068 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
) {
1069 name
= nvpair_name(nvp
);
1071 ret
= nvpair_value_nvlist(nvp
, &nvt
);
1073 /* invalid entry? */
1077 ret
= it_nv_to_tpg(nvt
, name
, &tpg
);
1084 if (*tpglist
== NULL
) {
1087 prev
->tpg_next
= tpg
;
1093 it_tpg_free_cmn(*tpglist
);
1101 it_ini_to_nv(it_ini_t
*ini
, nvlist_t
**nvl
)
1113 ret
= nvlist_alloc(nvl
, NV_UNIQUE_NAME
, 0);
1118 if (ini
->ini_properties
) {
1119 ret
= nvlist_add_nvlist(*nvl
, "properties",
1120 ini
->ini_properties
);
1124 ret
= nvlist_add_uint64(*nvl
, "generation",
1125 ini
->ini_generation
);
1126 } else if (ret
== ENOENT
) {
1139 it_nv_to_ini(nvlist_t
*nvl
, char *name
, it_ini_t
**ini
)
1145 if (!name
|| !ini
) {
1155 inip
= iscsit_zalloc(sizeof (it_ini_t
));
1160 (void) strlcpy(inip
->ini_name
, name
, sizeof (inip
->ini_name
));
1162 ret
= nvlist_lookup_nvlist(nvl
, "properties", &listval
);
1164 ret
= nvlist_dup(listval
, &(inip
->ini_properties
), 0);
1165 } else if (ret
== ENOENT
) {
1170 ret
= nvlist_lookup_uint64(nvl
, "generation",
1171 &(inip
->ini_generation
));
1177 it_ini_free_cmn(inip
);
1184 it_inilist_to_nv(it_ini_t
*inilist
, nvlist_t
**nvl
)
1187 nvlist_t
*pnv
= NULL
;
1189 it_ini_t
*ptr
= inilist
;
1199 /* create the target list if required */
1201 ret
= nvlist_alloc(&pnv
, NV_UNIQUE_NAME
, 0);
1209 ret
= it_ini_to_nv(ptr
, &tnv
);
1215 ret
= nvlist_add_nvlist(*nvl
, ptr
->ini_name
, tnv
);
1223 ptr
= ptr
->ini_next
;
1237 it_nv_to_inilist(nvlist_t
*nvl
, uint32_t *count
, it_ini_t
**inilist
)
1241 it_ini_t
*prev
= NULL
;
1242 nvpair_t
*nvp
= NULL
;
1246 if (!inilist
|| !count
) {
1258 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
) {
1259 name
= nvpair_name(nvp
);
1261 ret
= nvpair_value_nvlist(nvp
, &nvt
);
1263 /* invalid entry? */
1267 ret
= it_nv_to_ini(nvt
, name
, &inip
);
1274 if (*inilist
== NULL
) {
1277 prev
->ini_next
= inip
;
1283 it_ini_free_cmn(*inilist
);
1291 * Convert a sockaddr to the string representation, suitable for
1292 * storing in an nvlist or printing out in a list.
1296 sockaddr_to_str(struct sockaddr_storage
*sa
, char **addr
)
1299 char buf
[INET6_ADDRSTRLEN
+ 7]; /* addr : port */
1302 struct sockaddr_in
*sin
;
1303 struct sockaddr_in6
*sin6
;
1312 if (sa
->ss_family
== AF_INET
) {
1313 sin
= (struct sockaddr_in
*)sa
;
1314 bufp
= inet_ntop(AF_INET
,
1315 (const void *)&(sin
->sin_addr
.s_addr
),
1321 port
= ntohs(sin
->sin_port
);
1322 } else if (sa
->ss_family
== AF_INET6
) {
1323 (void) strlcat(buf
, "[", sizeof (buf
));
1324 sin6
= (struct sockaddr_in6
*)sa
;
1325 bufp
= inet_ntop(AF_INET6
,
1326 (const void *)&sin6
->sin6_addr
.s6_addr
,
1327 &buf
[1], (sizeof (buf
) - 1));
1332 (void) strlcat(buf
, "]", sizeof (buf
));
1333 port
= ntohs(sin6
->sin6_port
);
1339 (void) snprintf(pbuf
, sizeof (pbuf
), ":%u", port
);
1340 (void) strlcat(buf
, pbuf
, sizeof (buf
));
1342 *addr
= strdup(buf
);
1343 if (*addr
== NULL
) {
1349 #endif /* !_KERNEL */
1352 it_array_to_portallist(char **arr
, uint32_t count
, uint32_t default_port
,
1353 it_portal_t
**portallist
, uint32_t *list_count
)
1357 it_portal_t
*portal
;
1358 it_portal_t
*prev
= NULL
;
1361 if (!arr
|| !portallist
|| !list_count
) {
1368 for (i
= 0; i
< count
; i
++) {
1370 /* should never happen */
1373 portal
= iscsit_zalloc(sizeof (it_portal_t
));
1378 if (it_common_convert_sa(arr
[i
],
1379 &(portal
->portal_addr
), default_port
) == NULL
) {
1380 iscsit_free(portal
, sizeof (it_portal_t
));
1385 /* make sure no duplicates */
1388 if (it_sa_compare(&(tmp
->portal_addr
),
1389 &(portal
->portal_addr
)) == 0) {
1390 iscsit_free(portal
, sizeof (it_portal_t
));
1394 tmp
= tmp
->portal_next
;
1402 * The first time through the loop, *portallist == NULL
1403 * because we assigned it to NULL above. Subsequently
1404 * prev will have been set. Therefor it's OK to put
1405 * lint override before prev->portal_next assignment.
1407 if (*portallist
== NULL
) {
1408 *portallist
= portal
;
1410 prev
->portal_next
= portal
;
1421 * Function: it_config_free_cmn()
1423 * Free any resources associated with the it_config_t structure.
1426 * cfg A C representation of the current iSCSI configuration
1429 it_config_free_cmn(it_config_t
*cfg
)
1435 if (cfg
->config_tgt_list
) {
1436 it_tgt_free_cmn(cfg
->config_tgt_list
);
1439 if (cfg
->config_tpg_list
) {
1440 it_tpg_free_cmn(cfg
->config_tpg_list
);
1443 if (cfg
->config_ini_list
) {
1444 it_ini_free_cmn(cfg
->config_ini_list
);
1447 nvlist_free(cfg
->config_global_properties
);
1449 if (cfg
->config_isns_svr_list
) {
1450 it_portal_t
*pp
= cfg
->config_isns_svr_list
;
1451 it_portal_t
*pp_next
;
1454 pp_next
= pp
->portal_next
;
1455 iscsit_free(pp
, sizeof (it_portal_t
));
1460 iscsit_free(cfg
, sizeof (it_config_t
));
1464 * Function: it_tgt_free_cmn()
1466 * Frees an it_tgt_t structure. If tgt_next is not NULL, frees
1467 * all structures in the list.
1470 it_tgt_free_cmn(it_tgt_t
*tgt
)
1472 it_tgt_t
*tgtp
= tgt
;
1480 next
= tgtp
->tgt_next
;
1482 if (tgtp
->tgt_tpgt_list
) {
1483 it_tpgt_free_cmn(tgtp
->tgt_tpgt_list
);
1486 nvlist_free(tgtp
->tgt_properties
);
1488 iscsit_free(tgtp
, sizeof (it_tgt_t
));
1495 * Function: it_tpgt_free_cmn()
1497 * Deallocates resources of an it_tpgt_t structure. If tpgt->next
1498 * is not NULL, frees all members of the list.
1501 it_tpgt_free_cmn(it_tpgt_t
*tpgt
)
1503 it_tpgt_t
*tpgtp
= tpgt
;
1511 next
= tpgtp
->tpgt_next
;
1513 iscsit_free(tpgtp
, sizeof (it_tpgt_t
));
1520 * Function: it_tpg_free_cmn()
1522 * Deallocates resources associated with an it_tpg_t structure.
1523 * If tpg->next is not NULL, frees all members of the list.
1526 it_tpg_free_cmn(it_tpg_t
*tpg
)
1528 it_tpg_t
*tpgp
= tpg
;
1530 it_portal_t
*portalp
;
1534 next
= tpgp
->tpg_next
;
1536 portalp
= tpgp
->tpg_portal_list
;
1539 pnext
= portalp
->portal_next
;
1540 iscsit_free(portalp
, sizeof (it_portal_t
));
1544 iscsit_free(tpgp
, sizeof (it_tpg_t
));
1551 * Function: it_ini_free_cmn()
1553 * Deallocates resources of an it_ini_t structure. If ini->next is
1554 * not NULL, frees all members of the list.
1557 it_ini_free_cmn(it_ini_t
*ini
)
1559 it_ini_t
*inip
= ini
;
1567 next
= inip
->ini_next
;
1569 nvlist_free(inip
->ini_properties
);
1571 iscsit_free(inip
, sizeof (it_ini_t
));