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 if ((ret
== 0) && portalArray
) {
831 ret
= nvlist_add_string_array(*nvl
, "portalList",
838 if (portalArray
[i
]) {
839 iscsit_free(portalArray
[i
],
840 strlen(portalArray
[i
] + 1));
843 iscsit_free(portalArray
,
844 tpg
->tpg_portal_count
* sizeof (it_portal_t
));
854 #endif /* !_KERNEL */
857 it_nv_to_tpg(nvlist_t
*nvl
, char *name
, it_tpg_t
**tpg
)
861 char **portalArray
= NULL
;
870 ptpg
= iscsit_zalloc(sizeof (it_tpg_t
));
875 (void) strlcpy(ptpg
->tpg_name
, name
, sizeof (ptpg
->tpg_name
));
877 ret
= nvlist_lookup_uint64(nvl
, "generation",
878 &(ptpg
->tpg_generation
));
881 ret
= nvlist_lookup_string_array(nvl
, "portalList",
882 &portalArray
, &count
);
886 /* set the portals */
887 ret
= it_array_to_portallist(portalArray
, count
,
888 ISCSI_LISTEN_PORT
, &ptpg
->tpg_portal_list
,
889 &ptpg
->tpg_portal_count
);
890 } else if (ret
== ENOENT
) {
897 it_tpg_free_cmn(ptpg
);
908 it_tpglist_to_nv(it_tpg_t
*tpglist
, nvlist_t
**nvl
)
911 nvlist_t
*pnv
= NULL
;
913 it_tpg_t
*ptr
= tpglist
;
924 /* create the target portal group list if required */
926 ret
= nvlist_alloc(&pnv
, NV_UNIQUE_NAME
, 0);
934 ret
= it_tpg_to_nv(ptr
, &tnv
);
940 ret
= nvlist_add_nvlist(*nvl
, ptr
->tpg_name
, tnv
);
960 #endif /* !_KERNEL */
963 it_tpg_lookup(it_config_t
*cfg
, char *tpg_name
)
965 it_tpg_t
*cfg_tpg
= NULL
;
967 for (cfg_tpg
= cfg
->config_tpg_list
;
969 cfg_tpg
= cfg_tpg
->tpg_next
) {
970 if (strncmp(&cfg_tpg
->tpg_name
[0], tpg_name
,
971 MAX_TPG_NAMELEN
) == 0) {
980 it_sa_compare(struct sockaddr_storage
*sa1
, struct sockaddr_storage
*sa2
)
982 struct sockaddr_in
*sin1
, *sin2
;
983 struct sockaddr_in6
*sin6_1
, *sin6_2
;
986 * XXX - should we check here for IPv4 addrs mapped to v6?
987 * see also iscsit_is_v4_mapped in iscsit_login.c
990 if (sa1
->ss_family
!= sa2
->ss_family
) {
995 * sockaddr_in has padding which may not be initialized.
996 * be more specific in the comparison, and don't trust the
997 * caller has fully initialized the structure.
999 if (sa1
->ss_family
== AF_INET
) {
1000 sin1
= (struct sockaddr_in
*)sa1
;
1001 sin2
= (struct sockaddr_in
*)sa2
;
1002 if ((bcmp(&sin1
->sin_addr
, &sin2
->sin_addr
,
1003 sizeof (struct in_addr
)) == 0) &&
1004 (sin1
->sin_port
== sin2
->sin_port
)) {
1007 } else if (sa1
->ss_family
== AF_INET6
) {
1008 sin6_1
= (struct sockaddr_in6
*)sa1
;
1009 sin6_2
= (struct sockaddr_in6
*)sa2
;
1010 if (bcmp(sin6_1
, sin6_2
, sizeof (struct sockaddr_in6
)) == 0) {
1019 it_portal_lookup(it_tpg_t
*tpg
, struct sockaddr_storage
*sa
)
1021 it_portal_t
*cfg_portal
;
1023 for (cfg_portal
= tpg
->tpg_portal_list
;
1025 cfg_portal
= cfg_portal
->portal_next
) {
1026 if (it_sa_compare(sa
, &cfg_portal
->portal_addr
) == 0)
1027 return (cfg_portal
);
1034 it_sns_svr_lookup(it_config_t
*cfg
, struct sockaddr_storage
*sa
)
1036 it_portal_t
*cfg_portal
;
1038 for (cfg_portal
= cfg
->config_isns_svr_list
;
1040 cfg_portal
= cfg_portal
->portal_next
) {
1041 if (it_sa_compare(sa
, &cfg_portal
->portal_addr
) == 0)
1042 return (cfg_portal
);
1049 it_nv_to_tpglist(nvlist_t
*nvl
, uint32_t *count
, it_tpg_t
**tpglist
)
1053 it_tpg_t
*prev
= NULL
;
1054 nvpair_t
*nvp
= NULL
;
1058 if (!tpglist
|| !count
) {
1070 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
) {
1071 name
= nvpair_name(nvp
);
1073 ret
= nvpair_value_nvlist(nvp
, &nvt
);
1075 /* invalid entry? */
1079 ret
= it_nv_to_tpg(nvt
, name
, &tpg
);
1086 if (*tpglist
== NULL
) {
1089 prev
->tpg_next
= tpg
;
1095 it_tpg_free_cmn(*tpglist
);
1103 it_ini_to_nv(it_ini_t
*ini
, nvlist_t
**nvl
)
1115 ret
= nvlist_alloc(nvl
, NV_UNIQUE_NAME
, 0);
1120 if (ini
->ini_properties
) {
1121 ret
= nvlist_add_nvlist(*nvl
, "properties",
1122 ini
->ini_properties
);
1126 ret
= nvlist_add_uint64(*nvl
, "generation",
1127 ini
->ini_generation
);
1128 } else if (ret
== ENOENT
) {
1141 it_nv_to_ini(nvlist_t
*nvl
, char *name
, it_ini_t
**ini
)
1147 if (!name
|| !ini
) {
1157 inip
= iscsit_zalloc(sizeof (it_ini_t
));
1162 (void) strlcpy(inip
->ini_name
, name
, sizeof (inip
->ini_name
));
1164 ret
= nvlist_lookup_nvlist(nvl
, "properties", &listval
);
1166 ret
= nvlist_dup(listval
, &(inip
->ini_properties
), 0);
1167 } else if (ret
== ENOENT
) {
1172 ret
= nvlist_lookup_uint64(nvl
, "generation",
1173 &(inip
->ini_generation
));
1179 it_ini_free_cmn(inip
);
1186 it_inilist_to_nv(it_ini_t
*inilist
, nvlist_t
**nvl
)
1189 nvlist_t
*pnv
= NULL
;
1191 it_ini_t
*ptr
= inilist
;
1201 /* create the target list if required */
1203 ret
= nvlist_alloc(&pnv
, NV_UNIQUE_NAME
, 0);
1211 ret
= it_ini_to_nv(ptr
, &tnv
);
1217 ret
= nvlist_add_nvlist(*nvl
, ptr
->ini_name
, tnv
);
1225 ptr
= ptr
->ini_next
;
1239 it_nv_to_inilist(nvlist_t
*nvl
, uint32_t *count
, it_ini_t
**inilist
)
1243 it_ini_t
*prev
= NULL
;
1244 nvpair_t
*nvp
= NULL
;
1248 if (!inilist
|| !count
) {
1260 while ((nvp
= nvlist_next_nvpair(nvl
, nvp
)) != NULL
) {
1261 name
= nvpair_name(nvp
);
1263 ret
= nvpair_value_nvlist(nvp
, &nvt
);
1265 /* invalid entry? */
1269 ret
= it_nv_to_ini(nvt
, name
, &inip
);
1276 if (*inilist
== NULL
) {
1279 prev
->ini_next
= inip
;
1285 it_ini_free_cmn(*inilist
);
1293 * Convert a sockaddr to the string representation, suitable for
1294 * storing in an nvlist or printing out in a list.
1298 sockaddr_to_str(struct sockaddr_storage
*sa
, char **addr
)
1301 char buf
[INET6_ADDRSTRLEN
+ 7]; /* addr : port */
1304 struct sockaddr_in
*sin
;
1305 struct sockaddr_in6
*sin6
;
1314 if (sa
->ss_family
== AF_INET
) {
1315 sin
= (struct sockaddr_in
*)sa
;
1316 bufp
= inet_ntop(AF_INET
,
1317 (const void *)&(sin
->sin_addr
.s_addr
),
1323 port
= ntohs(sin
->sin_port
);
1324 } else if (sa
->ss_family
== AF_INET6
) {
1325 (void) strlcat(buf
, "[", sizeof (buf
));
1326 sin6
= (struct sockaddr_in6
*)sa
;
1327 bufp
= inet_ntop(AF_INET6
,
1328 (const void *)&sin6
->sin6_addr
.s6_addr
,
1329 &buf
[1], (sizeof (buf
) - 1));
1334 (void) strlcat(buf
, "]", sizeof (buf
));
1335 port
= ntohs(sin6
->sin6_port
);
1341 (void) snprintf(pbuf
, sizeof (pbuf
), ":%u", port
);
1342 (void) strlcat(buf
, pbuf
, sizeof (buf
));
1344 *addr
= strdup(buf
);
1345 if (*addr
== NULL
) {
1351 #endif /* !_KERNEL */
1354 it_array_to_portallist(char **arr
, uint32_t count
, uint32_t default_port
,
1355 it_portal_t
**portallist
, uint32_t *list_count
)
1359 it_portal_t
*portal
;
1360 it_portal_t
*prev
= NULL
;
1363 if (!arr
|| !portallist
|| !list_count
) {
1370 for (i
= 0; i
< count
; i
++) {
1372 /* should never happen */
1375 portal
= iscsit_zalloc(sizeof (it_portal_t
));
1380 if (it_common_convert_sa(arr
[i
],
1381 &(portal
->portal_addr
), default_port
) == NULL
) {
1382 iscsit_free(portal
, sizeof (it_portal_t
));
1387 /* make sure no duplicates */
1390 if (it_sa_compare(&(tmp
->portal_addr
),
1391 &(portal
->portal_addr
)) == 0) {
1392 iscsit_free(portal
, sizeof (it_portal_t
));
1396 tmp
= tmp
->portal_next
;
1404 * The first time through the loop, *portallist == NULL
1405 * because we assigned it to NULL above. Subsequently
1406 * prev will have been set. Therefor it's OK to put
1407 * lint override before prev->portal_next assignment.
1409 if (*portallist
== NULL
) {
1410 *portallist
= portal
;
1412 prev
->portal_next
= portal
;
1423 * Function: it_config_free_cmn()
1425 * Free any resources associated with the it_config_t structure.
1428 * cfg A C representation of the current iSCSI configuration
1431 it_config_free_cmn(it_config_t
*cfg
)
1437 if (cfg
->config_tgt_list
) {
1438 it_tgt_free_cmn(cfg
->config_tgt_list
);
1441 if (cfg
->config_tpg_list
) {
1442 it_tpg_free_cmn(cfg
->config_tpg_list
);
1445 if (cfg
->config_ini_list
) {
1446 it_ini_free_cmn(cfg
->config_ini_list
);
1449 if (cfg
->config_global_properties
) {
1450 nvlist_free(cfg
->config_global_properties
);
1453 if (cfg
->config_isns_svr_list
) {
1454 it_portal_t
*pp
= cfg
->config_isns_svr_list
;
1455 it_portal_t
*pp_next
;
1458 pp_next
= pp
->portal_next
;
1459 iscsit_free(pp
, sizeof (it_portal_t
));
1464 iscsit_free(cfg
, sizeof (it_config_t
));
1468 * Function: it_tgt_free_cmn()
1470 * Frees an it_tgt_t structure. If tgt_next is not NULL, frees
1471 * all structures in the list.
1474 it_tgt_free_cmn(it_tgt_t
*tgt
)
1476 it_tgt_t
*tgtp
= tgt
;
1484 next
= tgtp
->tgt_next
;
1486 if (tgtp
->tgt_tpgt_list
) {
1487 it_tpgt_free_cmn(tgtp
->tgt_tpgt_list
);
1490 if (tgtp
->tgt_properties
) {
1491 nvlist_free(tgtp
->tgt_properties
);
1494 iscsit_free(tgtp
, sizeof (it_tgt_t
));
1501 * Function: it_tpgt_free_cmn()
1503 * Deallocates resources of an it_tpgt_t structure. If tpgt->next
1504 * is not NULL, frees all members of the list.
1507 it_tpgt_free_cmn(it_tpgt_t
*tpgt
)
1509 it_tpgt_t
*tpgtp
= tpgt
;
1517 next
= tpgtp
->tpgt_next
;
1519 iscsit_free(tpgtp
, sizeof (it_tpgt_t
));
1526 * Function: it_tpg_free_cmn()
1528 * Deallocates resources associated with an it_tpg_t structure.
1529 * If tpg->next is not NULL, frees all members of the list.
1532 it_tpg_free_cmn(it_tpg_t
*tpg
)
1534 it_tpg_t
*tpgp
= tpg
;
1536 it_portal_t
*portalp
;
1540 next
= tpgp
->tpg_next
;
1542 portalp
= tpgp
->tpg_portal_list
;
1545 pnext
= portalp
->portal_next
;
1546 iscsit_free(portalp
, sizeof (it_portal_t
));
1550 iscsit_free(tpgp
, sizeof (it_tpg_t
));
1557 * Function: it_ini_free_cmn()
1559 * Deallocates resources of an it_ini_t structure. If ini->next is
1560 * not NULL, frees all members of the list.
1563 it_ini_free_cmn(it_ini_t
*ini
)
1565 it_ini_t
*inip
= ini
;
1573 next
= inip
->ini_next
;
1575 if (inip
->ini_properties
) {
1576 nvlist_free(inip
->ini_properties
);
1579 iscsit_free(inip
, sizeof (it_ini_t
));