xref: /titanic_44/usr/src/cmd/itadm/itadm.c (revision a4f92191582c96753b047f1055fe49937a714272)
1a6d42e7dSPeter Dunlap /*
2a6d42e7dSPeter Dunlap  * CDDL HEADER START
3a6d42e7dSPeter Dunlap  *
4a6d42e7dSPeter Dunlap  * The contents of this file are subject to the terms of the
5a6d42e7dSPeter Dunlap  * Common Development and Distribution License (the "License").
6a6d42e7dSPeter Dunlap  * You may not use this file except in compliance with the License.
7a6d42e7dSPeter Dunlap  *
8a6d42e7dSPeter Dunlap  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a6d42e7dSPeter Dunlap  * or http://www.opensolaris.org/os/licensing.
10a6d42e7dSPeter Dunlap  * See the License for the specific language governing permissions
11a6d42e7dSPeter Dunlap  * and limitations under the License.
12a6d42e7dSPeter Dunlap  *
13a6d42e7dSPeter Dunlap  * When distributing Covered Code, include this CDDL HEADER in each
14a6d42e7dSPeter Dunlap  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a6d42e7dSPeter Dunlap  * If applicable, add the following below this CDDL HEADER, with the
16a6d42e7dSPeter Dunlap  * fields enclosed by brackets "[]" replaced with your own identifying
17a6d42e7dSPeter Dunlap  * information: Portions Copyright [yyyy] [name of copyright owner]
18a6d42e7dSPeter Dunlap  *
19a6d42e7dSPeter Dunlap  * CDDL HEADER END
20a6d42e7dSPeter Dunlap  */
21a6d42e7dSPeter Dunlap /*
22836fc322SSam Cramer  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23a6d42e7dSPeter Dunlap  * Use is subject to license terms.
24a6d42e7dSPeter Dunlap  */
25a6d42e7dSPeter Dunlap #include <stdlib.h>
26a6d42e7dSPeter Dunlap #include <stdio.h>
27a6d42e7dSPeter Dunlap #include <sys/types.h>
28a6d42e7dSPeter Dunlap #include <sys/stat.h>
29a6d42e7dSPeter Dunlap #include <fcntl.h>
30a6d42e7dSPeter Dunlap #include <unistd.h>
31a6d42e7dSPeter Dunlap #include <errno.h>
32a6d42e7dSPeter Dunlap #include <string.h>
33a6d42e7dSPeter Dunlap #include <getopt.h>
34a6d42e7dSPeter Dunlap #include <strings.h>
35a6d42e7dSPeter Dunlap #include <ctype.h>
36a6d42e7dSPeter Dunlap #include <libnvpair.h>
37a6d42e7dSPeter Dunlap #include <libintl.h>
38a6d42e7dSPeter Dunlap #include <libgen.h>
39a6d42e7dSPeter Dunlap #include <pwd.h>
40a6d42e7dSPeter Dunlap #include <auth_attr.h>
41a6d42e7dSPeter Dunlap #include <secdb.h>
42a6d42e7dSPeter Dunlap #include <libscf.h>
43a6d42e7dSPeter Dunlap #include <limits.h>
44a6d42e7dSPeter Dunlap #include <locale.h>
45a6d42e7dSPeter Dunlap 
46a6d42e7dSPeter Dunlap #include <libstmf.h>
47a6d42e7dSPeter Dunlap #include <libiscsit.h>
48a6d42e7dSPeter Dunlap 
49a6d42e7dSPeter Dunlap /* what's this used for?? */
50a6d42e7dSPeter Dunlap #define	ITADM_VERSION	"1.0"
51a6d42e7dSPeter Dunlap 
52a6d42e7dSPeter Dunlap /* SMF service info */
53a6d42e7dSPeter Dunlap #define	ISCSIT_SVC	"svc:/network/iscsi/target:default"
54a6d42e7dSPeter Dunlap 
55a6d42e7dSPeter Dunlap #define	STMF_STALE(ret) {\
56a6d42e7dSPeter Dunlap 	if (ret == STMF_ERROR_PROV_DATA_STALE) {\
57a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",\
58a6d42e7dSPeter Dunlap 		    gettext("Configuration changed during processing.  "\
59a6d42e7dSPeter Dunlap 		    "Check the configuration, then retry this command "\
60a6d42e7dSPeter Dunlap 		    "if appropriate."));\
61a6d42e7dSPeter Dunlap 	}\
62a6d42e7dSPeter Dunlap }
63a6d42e7dSPeter Dunlap 
64a6d42e7dSPeter Dunlap #define	ITADM_CHKAUTH(sec) {\
65a6d42e7dSPeter Dunlap 	if (!chkauthattr(sec, itadm_uname)) {\
66a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,\
67a6d42e7dSPeter Dunlap 		    gettext("Error, operation requires authorization %s"),\
68a6d42e7dSPeter Dunlap 		    sec);\
69a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");\
70a6d42e7dSPeter Dunlap 		return (1);\
71a6d42e7dSPeter Dunlap 	}\
72a6d42e7dSPeter Dunlap }
73a6d42e7dSPeter Dunlap 
74*a4f92191SSam Cramer #define	IS_IQN_NAME(s) (strncmp((s), "iqn.", 4) == 0)
75*a4f92191SSam Cramer 
76*a4f92191SSam Cramer 
77a6d42e7dSPeter Dunlap static struct option itadm_long[] = {
78a6d42e7dSPeter Dunlap 	{"alias",		required_argument,	NULL, 'l'},
79a6d42e7dSPeter Dunlap 	{"auth-method",		required_argument,	NULL, 'a'},
80a6d42e7dSPeter Dunlap 	{"chap-secret",		no_argument,		NULL, 's'},
81a6d42e7dSPeter Dunlap 	{"chap-secret-file",	required_argument,	NULL, 'S'},
82a6d42e7dSPeter Dunlap 	{"chap-user",		required_argument,	NULL, 'u'},
83a6d42e7dSPeter Dunlap 	{"force",		no_argument,		NULL, 'f'},
84a6d42e7dSPeter Dunlap 	{"help",		no_argument,		NULL, 'h'},
85a6d42e7dSPeter Dunlap 	{"help",		no_argument,		NULL, '?'},
86a6d42e7dSPeter Dunlap 	{"isns",		required_argument,	NULL, 'i'},
87a6d42e7dSPeter Dunlap 	{"isns-server",		required_argument,	NULL, 'I'},
88a6d42e7dSPeter Dunlap 	{"node-name",		required_argument,	NULL, 'n'},
89a6d42e7dSPeter Dunlap 	{"radius-secret",	no_argument,		NULL, 'd'},
90a6d42e7dSPeter Dunlap 	{"radius-secret-file",	required_argument,	NULL, 'D'},
91a6d42e7dSPeter Dunlap 	{"radius-server",	required_argument,	NULL, 'r'},
92a6d42e7dSPeter Dunlap 	{"tpg-tag",		required_argument,	NULL, 't'},
93a6d42e7dSPeter Dunlap 	{"verbose",		no_argument,		NULL, 'v'},
94a6d42e7dSPeter Dunlap 	{"version",		no_argument,		NULL, 'V'},
95a6d42e7dSPeter Dunlap 	{NULL, 0, NULL, 0}
96a6d42e7dSPeter Dunlap };
97a6d42e7dSPeter Dunlap 
98a6d42e7dSPeter Dunlap char c_tgt[] = "itadm create-target [-a radius|chap|none|default] [-s] \
99a6d42e7dSPeter Dunlap [-S chap-secret-path] [-u chap-username] [-n target-node-name] \
100a6d42e7dSPeter Dunlap [-l alias] [-t tpg-name[,tpg-name,...]]";
101a6d42e7dSPeter Dunlap 
102a6d42e7dSPeter Dunlap static char m_tgt[] = "itadm modify-target [-a radius|chap|none|default] [-s] \
103a6d42e7dSPeter Dunlap [-S chap-secret-path] [-u chap-username] [-n new-target-node-name] \
104a6d42e7dSPeter Dunlap [-l alias] [-t tpg-name[,tpg-name,...]] target-node-name";
105a6d42e7dSPeter Dunlap 
106a6d42e7dSPeter Dunlap static char d_tgt[] = "itadm delete-target [-f] target-node-name";
107a6d42e7dSPeter Dunlap 
108a6d42e7dSPeter Dunlap static char l_tgt[] = "itadm list-target [-v] [target-node-name";
109a6d42e7dSPeter Dunlap 
110a6d42e7dSPeter Dunlap static char c_tpg[] = "itadm create-tpg tpg-name IP-address[:port] \
111a6d42e7dSPeter Dunlap [IP-address[:port]] [...]";
112a6d42e7dSPeter Dunlap 
113a6d42e7dSPeter Dunlap static char l_tpg[] = "itadm list-tpg [-v] [tpg-name]";
114a6d42e7dSPeter Dunlap 
115a6d42e7dSPeter Dunlap static char d_tpg[] = "itadm delete-tpg [-f] tpg-name";
116a6d42e7dSPeter Dunlap 
117a6d42e7dSPeter Dunlap static char c_ini[] = "itadm create-initiator [-s] [-S chap-secret-path] \
118a6d42e7dSPeter Dunlap [-u chap-username] initiator-node-name";
119a6d42e7dSPeter Dunlap 
120a6d42e7dSPeter Dunlap static char m_ini[] = "itadm modify-initiator [-s] [-S chap-secret-path] \
121a6d42e7dSPeter Dunlap [-u chap-username] initiator-node-name";
122a6d42e7dSPeter Dunlap 
123a6d42e7dSPeter Dunlap static char l_ini[] = "itadm list-initiator [-v] initiator-node-name";
124a6d42e7dSPeter Dunlap 
125a6d42e7dSPeter Dunlap static char d_ini[] = "itadm delete-inititator initiator-node-name";
126a6d42e7dSPeter Dunlap 
127a6d42e7dSPeter Dunlap static char m_def[] = "itadm modify-defaults [-a radius|chap|none] \
128a6d42e7dSPeter Dunlap [-r IP-address[:port]] [-d] [-D radius-secret-path] [-i enable|disable] \
129a6d42e7dSPeter Dunlap [-I IP-address[:port][,IP-adddress[:port]]]";
130a6d42e7dSPeter Dunlap 
131a6d42e7dSPeter Dunlap static char l_def[] = "itadm list-defaults";
132a6d42e7dSPeter Dunlap 
133a6d42e7dSPeter Dunlap 
134a6d42e7dSPeter Dunlap /* keep the order of this enum in the same order as the 'subcmds' struct */
135a6d42e7dSPeter Dunlap typedef enum {
136a6d42e7dSPeter Dunlap 	CREATE_TGT,
137a6d42e7dSPeter Dunlap 	MODIFY_TGT,
138a6d42e7dSPeter Dunlap 	DELETE_TGT,
139a6d42e7dSPeter Dunlap 	LIST_TGT,
140a6d42e7dSPeter Dunlap 	CREATE_TPG,
141a6d42e7dSPeter Dunlap 	DELETE_TPG,
142a6d42e7dSPeter Dunlap 	LIST_TPG,
143a6d42e7dSPeter Dunlap 	CREATE_INI,
144a6d42e7dSPeter Dunlap 	MODIFY_INI,
145a6d42e7dSPeter Dunlap 	LIST_INI,
146a6d42e7dSPeter Dunlap 	DELETE_INI,
147a6d42e7dSPeter Dunlap 	MODIFY_DEF,
148a6d42e7dSPeter Dunlap 	LIST_DEF,
149a6d42e7dSPeter Dunlap 	NULL_SUBCMD	/* must always be last! */
150a6d42e7dSPeter Dunlap } itadm_sub_t;
151a6d42e7dSPeter Dunlap 
152a6d42e7dSPeter Dunlap typedef struct {
153a6d42e7dSPeter Dunlap 	char		*name;
154a6d42e7dSPeter Dunlap 	char		*shortopts;
155a6d42e7dSPeter Dunlap 	char		*usemsg;
156a6d42e7dSPeter Dunlap } itadm_subcmds_t;
157a6d42e7dSPeter Dunlap 
158a6d42e7dSPeter Dunlap static itadm_subcmds_t	subcmds[] = {
159a6d42e7dSPeter Dunlap 	{"create-target", ":a:sS:u:n:l:t:h?", c_tgt},
160a6d42e7dSPeter Dunlap 	{"modify-target", ":a:sS:u:n:l:t:h?", m_tgt},
161a6d42e7dSPeter Dunlap 	{"delete-target", ":fh?", d_tgt},
162a6d42e7dSPeter Dunlap 	{"list-target", ":vh?", l_tgt},
163a6d42e7dSPeter Dunlap 	{"create-tpg", ":h?", c_tpg},
164a6d42e7dSPeter Dunlap 	{"delete-tpg", ":fh?", d_tpg},
165a6d42e7dSPeter Dunlap 	{"list-tpg", ":vh?", l_tpg},
166a6d42e7dSPeter Dunlap 	{"create-initiator", ":sS:u:h?", c_ini},
167a6d42e7dSPeter Dunlap 	{"modify-initiator", ":sS:u:h?", m_ini},
168a6d42e7dSPeter Dunlap 	{"list-initiator", ":vh?", l_ini},
169a6d42e7dSPeter Dunlap 	{"delete-initiator", ":h?", d_ini},
170a6d42e7dSPeter Dunlap 	{"modify-defaults", ":a:r:dD:i:I:h?", m_def},
171a6d42e7dSPeter Dunlap 	{"list-defaults", ":h?", l_def},
172a6d42e7dSPeter Dunlap 	{NULL, ":h?", NULL},
173a6d42e7dSPeter Dunlap };
174a6d42e7dSPeter Dunlap 
175a6d42e7dSPeter Dunlap /* used for checking if user is authorized */
176a6d42e7dSPeter Dunlap static char *itadm_uname = NULL;
177a6d42e7dSPeter Dunlap 
178a6d42e7dSPeter Dunlap /* prototypes */
179a6d42e7dSPeter Dunlap static int
180a6d42e7dSPeter Dunlap itadm_get_password(nvlist_t *nvl, char *key, char *passfile,
181a6d42e7dSPeter Dunlap     char *phrase);
182a6d42e7dSPeter Dunlap 
183a6d42e7dSPeter Dunlap static int
184a6d42e7dSPeter Dunlap itadm_opt_to_arr(nvlist_t *nvl, char *key, char *opt, uint32_t *num);
185a6d42e7dSPeter Dunlap 
186a6d42e7dSPeter Dunlap static int
187a6d42e7dSPeter Dunlap create_target(char *tgt, nvlist_t *proplist);
188a6d42e7dSPeter Dunlap 
189a6d42e7dSPeter Dunlap static int
190a6d42e7dSPeter Dunlap modify_target(char *tgt, char *new, nvlist_t *proplist);
191a6d42e7dSPeter Dunlap 
192a6d42e7dSPeter Dunlap static int
193a6d42e7dSPeter Dunlap delete_target(char *tgt, boolean_t force);
194a6d42e7dSPeter Dunlap 
195a6d42e7dSPeter Dunlap static int
196a6d42e7dSPeter Dunlap list_target(char *tgt, boolean_t verbose, boolean_t script);
197a6d42e7dSPeter Dunlap 
198a6d42e7dSPeter Dunlap static int
199a6d42e7dSPeter Dunlap create_tpg(char *tpg, int addrc, char **addrs);
200a6d42e7dSPeter Dunlap 
201a6d42e7dSPeter Dunlap static int
202a6d42e7dSPeter Dunlap list_tpg(char *tpg, boolean_t verbose, boolean_t script);
203a6d42e7dSPeter Dunlap 
204a6d42e7dSPeter Dunlap static int
205a6d42e7dSPeter Dunlap delete_tpg(char *tpg, boolean_t force);
206a6d42e7dSPeter Dunlap 
207a6d42e7dSPeter Dunlap static int
208a6d42e7dSPeter Dunlap modify_initiator(char *ini, nvlist_t *proplist, boolean_t create);
209a6d42e7dSPeter Dunlap 
210a6d42e7dSPeter Dunlap static int
211a6d42e7dSPeter Dunlap list_initiator(char *ini, boolean_t verbose, boolean_t script);
212a6d42e7dSPeter Dunlap 
213a6d42e7dSPeter Dunlap static int
214a6d42e7dSPeter Dunlap delete_initiator(char *ini);
215a6d42e7dSPeter Dunlap 
216a6d42e7dSPeter Dunlap static int
217a6d42e7dSPeter Dunlap modify_defaults(nvlist_t *proplist);
218a6d42e7dSPeter Dunlap 
219a6d42e7dSPeter Dunlap static int
220a6d42e7dSPeter Dunlap list_defaults(boolean_t script);
221a6d42e7dSPeter Dunlap 
222a6d42e7dSPeter Dunlap static void
223a6d42e7dSPeter Dunlap tag_name_to_num(char *tagname, uint16_t *tagnum);
224a6d42e7dSPeter Dunlap 
225*a4f92191SSam Cramer static char *
226*a4f92191SSam Cramer canonical_target_name(char *tgt);
227*a4f92191SSam Cramer 
228*a4f92191SSam Cramer static char *
229*a4f92191SSam Cramer strduplc(char *s);
230*a4f92191SSam Cramer 
231a6d42e7dSPeter Dunlap /* prototype from iscsit_common.h */
232a6d42e7dSPeter Dunlap extern int
233a6d42e7dSPeter Dunlap sockaddr_to_str(struct sockaddr_storage *sa, char **addr);
234a6d42e7dSPeter Dunlap 
235a6d42e7dSPeter Dunlap int
236a6d42e7dSPeter Dunlap main(int argc, char *argv[])
237a6d42e7dSPeter Dunlap {
238a6d42e7dSPeter Dunlap 	int		ret = 0;
239a6d42e7dSPeter Dunlap 	int		idx = NULL_SUBCMD;
240a6d42e7dSPeter Dunlap 	char		c;
241a6d42e7dSPeter Dunlap 	int		newargc = argc;
242a6d42e7dSPeter Dunlap 	char		**newargv = NULL;
243a6d42e7dSPeter Dunlap 	char		*objp;
244a6d42e7dSPeter Dunlap 	int		itind = 0;
245a6d42e7dSPeter Dunlap 	nvlist_t	*proplist = NULL;
246a6d42e7dSPeter Dunlap 	boolean_t	verbose = B_FALSE;
247a6d42e7dSPeter Dunlap 	boolean_t	scripting = B_FALSE;
248a6d42e7dSPeter Dunlap 	boolean_t	tbool;
249a6d42e7dSPeter Dunlap 	char		*targetname = NULL;
250a6d42e7dSPeter Dunlap 	char		*propname;
251a6d42e7dSPeter Dunlap 	boolean_t	force = B_FALSE;
252a6d42e7dSPeter Dunlap 	struct passwd	*pwd = NULL;
253a6d42e7dSPeter Dunlap 	uint32_t	count = 0;
254a6d42e7dSPeter Dunlap 	char		*smfstate = NULL;
255a6d42e7dSPeter Dunlap 
256a6d42e7dSPeter Dunlap 	(void) setlocale(LC_ALL, "");
257a6d42e7dSPeter Dunlap 	(void) textdomain(TEXT_DOMAIN);
258a6d42e7dSPeter Dunlap 
259a6d42e7dSPeter Dunlap 	if (argc < 2) {
260a6d42e7dSPeter Dunlap 		ret = 1;
261a6d42e7dSPeter Dunlap 		goto usage_error;
262a6d42e7dSPeter Dunlap 	}
263a6d42e7dSPeter Dunlap 
264a6d42e7dSPeter Dunlap 	for (idx = 0; subcmds[idx].name != NULL; idx++) {
265a6d42e7dSPeter Dunlap 		if (strcmp(argv[1], subcmds[idx].name) == 0) {
266a6d42e7dSPeter Dunlap 			break;
267a6d42e7dSPeter Dunlap 		}
268a6d42e7dSPeter Dunlap 	}
269a6d42e7dSPeter Dunlap 
270a6d42e7dSPeter Dunlap 
271a6d42e7dSPeter Dunlap 	/* get the caller's user name for subsequent chkauthattr() calls */
272a6d42e7dSPeter Dunlap 	pwd = getpwuid(getuid());
273a6d42e7dSPeter Dunlap 	if (pwd == NULL) {
274a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
275a6d42e7dSPeter Dunlap 		    gettext("Could not determine callers user name."));
276a6d42e7dSPeter Dunlap 		return (1);
277a6d42e7dSPeter Dunlap 	}
278a6d42e7dSPeter Dunlap 
279a6d42e7dSPeter Dunlap 	itadm_uname = strdup(pwd->pw_name);
280a6d42e7dSPeter Dunlap 
281a6d42e7dSPeter Dunlap 	/* increment past command & subcommand */
282a6d42e7dSPeter Dunlap 	newargc--;
283a6d42e7dSPeter Dunlap 	newargv = &(argv[1]);
284a6d42e7dSPeter Dunlap 
285a6d42e7dSPeter Dunlap 	ret = nvlist_alloc(&proplist, NV_UNIQUE_NAME, 0);
286a6d42e7dSPeter Dunlap 	if (ret != 0) {
287a6d42e7dSPeter Dunlap 		ret = errno;
288a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
289a6d42e7dSPeter Dunlap 		    gettext("Could not allocate nvlist, errno = %d"),
290a6d42e7dSPeter Dunlap 		    ret);
291a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
292a6d42e7dSPeter Dunlap 		ret = 1;
293a6d42e7dSPeter Dunlap 		goto usage_error;
294a6d42e7dSPeter Dunlap 	}
295a6d42e7dSPeter Dunlap 
296a6d42e7dSPeter Dunlap 	while ((ret == 0) && (newargv)) {
297a6d42e7dSPeter Dunlap 		c = getopt_long(newargc, newargv, subcmds[idx].shortopts,
298a6d42e7dSPeter Dunlap 		    itadm_long, &itind);
299a6d42e7dSPeter Dunlap 		if (c == -1) {
300a6d42e7dSPeter Dunlap 			break;
301a6d42e7dSPeter Dunlap 		}
302a6d42e7dSPeter Dunlap 
303a6d42e7dSPeter Dunlap 		switch (c) {
304a6d42e7dSPeter Dunlap 			case 0:
305a6d42e7dSPeter Dunlap 				/* flag set by getopt */
306a6d42e7dSPeter Dunlap 				break;
307a6d42e7dSPeter Dunlap 			case 'a':
308a6d42e7dSPeter Dunlap 				ret = nvlist_add_string(proplist,
309a6d42e7dSPeter Dunlap 				    "auth", optarg);
310a6d42e7dSPeter Dunlap 				break;
311a6d42e7dSPeter Dunlap 			case 'd':
312a6d42e7dSPeter Dunlap 				ret = itadm_get_password(proplist,
313a6d42e7dSPeter Dunlap 				    "radiussecret", NULL,
314a6d42e7dSPeter Dunlap 				    gettext("Enter RADIUS secret: "));
315a6d42e7dSPeter Dunlap 				break;
316a6d42e7dSPeter Dunlap 			case 'D':
317a6d42e7dSPeter Dunlap 				ret = itadm_get_password(proplist,
318a6d42e7dSPeter Dunlap 				    "radiussecret", optarg, NULL);
319a6d42e7dSPeter Dunlap 				break;
320a6d42e7dSPeter Dunlap 			case 'f':
321a6d42e7dSPeter Dunlap 				force = B_TRUE;
322a6d42e7dSPeter Dunlap 				break;
323a6d42e7dSPeter Dunlap 			case '?':
324a6d42e7dSPeter Dunlap 				/*
325a6d42e7dSPeter Dunlap 				 * '?' is returned for both unrecognized
326a6d42e7dSPeter Dunlap 				 * options and if explicitly provided on
327a6d42e7dSPeter Dunlap 				 * the command line.  The latter should
328a6d42e7dSPeter Dunlap 				 * be handled the same as -h.
329a6d42e7dSPeter Dunlap 				 */
330a6d42e7dSPeter Dunlap 				if (strcmp(newargv[optind-1], "-?") != 0) {
331a6d42e7dSPeter Dunlap 					(void) fprintf(stderr,
332a6d42e7dSPeter Dunlap 					    gettext("Unrecognized option %s"),
333a6d42e7dSPeter Dunlap 					    newargv[optind-1]);
334a6d42e7dSPeter Dunlap 					(void) fprintf(stderr, "\n");
335a6d42e7dSPeter Dunlap 					ret = 1;
336a6d42e7dSPeter Dunlap 				}
337a6d42e7dSPeter Dunlap 				goto usage_error;
338a6d42e7dSPeter Dunlap 			case 'h':
339a6d42e7dSPeter Dunlap 				goto usage_error;
340a6d42e7dSPeter Dunlap 			case 'i':
341a6d42e7dSPeter Dunlap 				if (strncmp(optarg, "enable", strlen(optarg))
342a6d42e7dSPeter Dunlap 				    == 0) {
343a6d42e7dSPeter Dunlap 					tbool = B_TRUE;
344a6d42e7dSPeter Dunlap 				} else if (strncmp(optarg, "disable",
345a6d42e7dSPeter Dunlap 				    strlen(optarg)) == 0) {
346a6d42e7dSPeter Dunlap 					tbool = B_FALSE;
347a6d42e7dSPeter Dunlap 				} else {
348a6d42e7dSPeter Dunlap 					(void) fprintf(stderr, "%s\n",
349a6d42e7dSPeter Dunlap 					    gettext("invalid value for -i"));
350a6d42e7dSPeter Dunlap 					ret = 1;
351a6d42e7dSPeter Dunlap 					break;
352a6d42e7dSPeter Dunlap 				}
353a6d42e7dSPeter Dunlap 				ret = nvlist_add_boolean_value(proplist,
354a6d42e7dSPeter Dunlap 				    "isns", tbool);
355a6d42e7dSPeter Dunlap 				break;
356a6d42e7dSPeter Dunlap 			case 'I':
357a6d42e7dSPeter Dunlap 				/* possibly multi-valued */
358a6d42e7dSPeter Dunlap 				ret = itadm_opt_to_arr(proplist,
359a6d42e7dSPeter Dunlap 				    "isnsserver", optarg, &count);
360a6d42e7dSPeter Dunlap 				if ((ret == 0) && (count > 8)) {
361a6d42e7dSPeter Dunlap 					(void) fprintf(stderr, "%s\n",
362a6d42e7dSPeter Dunlap 					    gettext(
363a6d42e7dSPeter Dunlap 					    "Too many iSNS servers specified, "
364a6d42e7dSPeter Dunlap 					    "maximum of 8 allowed"));
365a6d42e7dSPeter Dunlap 					ret = 1;
366a6d42e7dSPeter Dunlap 				}
367a6d42e7dSPeter Dunlap 				break;
368a6d42e7dSPeter Dunlap 			case 'l':
369a6d42e7dSPeter Dunlap 				ret = nvlist_add_string(proplist,
370a6d42e7dSPeter Dunlap 				    "alias", optarg);
371a6d42e7dSPeter Dunlap 				break;
372a6d42e7dSPeter Dunlap 			case 'n':
373a6d42e7dSPeter Dunlap 				targetname = strdup(optarg);
374a6d42e7dSPeter Dunlap 				if (targetname == NULL) {
375a6d42e7dSPeter Dunlap 					ret = ENOMEM;
376a6d42e7dSPeter Dunlap 				}
377a6d42e7dSPeter Dunlap 				break;
378a6d42e7dSPeter Dunlap 			case 'r':
379a6d42e7dSPeter Dunlap 				ret = nvlist_add_string(proplist,
380a6d42e7dSPeter Dunlap 				    "radiusserver", optarg);
381a6d42e7dSPeter Dunlap 				break;
382a6d42e7dSPeter Dunlap 			case 's':
383a6d42e7dSPeter Dunlap 				if ((idx == CREATE_TGT) ||
384a6d42e7dSPeter Dunlap 				    (idx == MODIFY_TGT)) {
385a6d42e7dSPeter Dunlap 					propname = "targetchapsecret";
386a6d42e7dSPeter Dunlap 				} else {
387a6d42e7dSPeter Dunlap 					propname = "chapsecret";
388a6d42e7dSPeter Dunlap 				}
389a6d42e7dSPeter Dunlap 				ret = itadm_get_password(proplist,
390a6d42e7dSPeter Dunlap 				    propname, NULL,
391a6d42e7dSPeter Dunlap 				    gettext("Enter CHAP secret: "));
392a6d42e7dSPeter Dunlap 				break;
393a6d42e7dSPeter Dunlap 			case 'S':
394a6d42e7dSPeter Dunlap 				if ((idx == CREATE_TGT) ||
395a6d42e7dSPeter Dunlap 				    (idx == MODIFY_TGT)) {
396a6d42e7dSPeter Dunlap 					propname = "targetchapsecret";
397a6d42e7dSPeter Dunlap 				} else {
398a6d42e7dSPeter Dunlap 					propname = "chapsecret";
399a6d42e7dSPeter Dunlap 				}
400a6d42e7dSPeter Dunlap 				ret = itadm_get_password(proplist,
401a6d42e7dSPeter Dunlap 				    propname, optarg, NULL);
402a6d42e7dSPeter Dunlap 				break;
403a6d42e7dSPeter Dunlap 			case 't':
404a6d42e7dSPeter Dunlap 				/* possibly multi-valued */
405a6d42e7dSPeter Dunlap 				ret = itadm_opt_to_arr(proplist,
406a6d42e7dSPeter Dunlap 				    "tpg-tag", optarg, NULL);
407a6d42e7dSPeter Dunlap 				break;
408a6d42e7dSPeter Dunlap 			case 'u':
409a6d42e7dSPeter Dunlap 				if ((idx == CREATE_TGT) ||
410a6d42e7dSPeter Dunlap 				    (idx == MODIFY_TGT)) {
411a6d42e7dSPeter Dunlap 					propname = "targetchapuser";
412a6d42e7dSPeter Dunlap 				} else {
413a6d42e7dSPeter Dunlap 					propname = "chapuser";
414a6d42e7dSPeter Dunlap 				}
415a6d42e7dSPeter Dunlap 				ret = nvlist_add_string(proplist,
416a6d42e7dSPeter Dunlap 				    propname, optarg);
417a6d42e7dSPeter Dunlap 				break;
418a6d42e7dSPeter Dunlap 			case 'v':
419a6d42e7dSPeter Dunlap 				verbose = B_TRUE;
420a6d42e7dSPeter Dunlap 				break;
421a6d42e7dSPeter Dunlap 			case ':':
422a6d42e7dSPeter Dunlap 				(void) fprintf(stderr,
423a6d42e7dSPeter Dunlap 				    gettext("Option %s requires an operand."),
424a6d42e7dSPeter Dunlap 				    newargv[optind-1]);
425a6d42e7dSPeter Dunlap 				(void) fprintf(stderr, "\n");
426a6d42e7dSPeter Dunlap 
427a6d42e7dSPeter Dunlap 				/* fall through to default */
428a6d42e7dSPeter Dunlap 			default:
429a6d42e7dSPeter Dunlap 				ret = 1;
430a6d42e7dSPeter Dunlap 				break;
431a6d42e7dSPeter Dunlap 		}
432a6d42e7dSPeter Dunlap 	}
433a6d42e7dSPeter Dunlap 
434a6d42e7dSPeter Dunlap 	if (ret != 0) {
435a6d42e7dSPeter Dunlap 		goto usage_error;
436a6d42e7dSPeter Dunlap 	}
437a6d42e7dSPeter Dunlap 
438a6d42e7dSPeter Dunlap 	/* after getopt() to allow handling of -h option */
439a6d42e7dSPeter Dunlap 	if ((itadm_sub_t)idx == NULL_SUBCMD) {
440a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
441a6d42e7dSPeter Dunlap 		    gettext("Error, no subcommand specified"));
442a6d42e7dSPeter Dunlap 		ret = 1;
443a6d42e7dSPeter Dunlap 		goto usage_error;
444a6d42e7dSPeter Dunlap 	}
445a6d42e7dSPeter Dunlap 
446a6d42e7dSPeter Dunlap 	/*
447a6d42e7dSPeter Dunlap 	 * some subcommands take multiple operands, so adjust now that
448a6d42e7dSPeter Dunlap 	 * getopt is complete
449a6d42e7dSPeter Dunlap 	 */
450a6d42e7dSPeter Dunlap 	newargc -= optind;
451a6d42e7dSPeter Dunlap 	if (newargc == 0) {
452a6d42e7dSPeter Dunlap 		newargv = NULL;
453a6d42e7dSPeter Dunlap 		objp = NULL;
454a6d42e7dSPeter Dunlap 	} else {
455a6d42e7dSPeter Dunlap 		newargv = &(newargv[optind]);
456a6d42e7dSPeter Dunlap 		objp = newargv[0];
457a6d42e7dSPeter Dunlap 	}
458a6d42e7dSPeter Dunlap 
459a6d42e7dSPeter Dunlap 	if (objp == NULL) {
460a6d42e7dSPeter Dunlap 		switch ((itadm_sub_t)idx) {
461a6d42e7dSPeter Dunlap 		case MODIFY_TGT:
462a6d42e7dSPeter Dunlap 		case DELETE_TGT:
463a6d42e7dSPeter Dunlap 		case CREATE_TPG:
464a6d42e7dSPeter Dunlap 		case DELETE_TPG:
465a6d42e7dSPeter Dunlap 		case CREATE_INI:
466a6d42e7dSPeter Dunlap 		case MODIFY_INI:
467a6d42e7dSPeter Dunlap 		case DELETE_INI:
468a6d42e7dSPeter Dunlap 			/* These subcommands need operands */
469a6d42e7dSPeter Dunlap 			ret = 1;
470a6d42e7dSPeter Dunlap 			goto usage_error;
471a6d42e7dSPeter Dunlap 		default:
472a6d42e7dSPeter Dunlap 			break;
473a6d42e7dSPeter Dunlap 		}
474a6d42e7dSPeter Dunlap 	}
475a6d42e7dSPeter Dunlap 
476836fc322SSam Cramer 	if (newargc > 1) {
477836fc322SSam Cramer 		switch ((itadm_sub_t)idx) {
478836fc322SSam Cramer 		case MODIFY_TGT:
479836fc322SSam Cramer 		case DELETE_TGT:
480836fc322SSam Cramer 		case LIST_TGT:
481836fc322SSam Cramer 		case DELETE_TPG:
482836fc322SSam Cramer 		case LIST_TPG:
483836fc322SSam Cramer 		case CREATE_INI:
484836fc322SSam Cramer 		case MODIFY_INI:
485836fc322SSam Cramer 		case LIST_INI:
486836fc322SSam Cramer 		case DELETE_INI:
487836fc322SSam Cramer 			/* These subcommands should have at most one operand */
488836fc322SSam Cramer 			ret = 1;
489836fc322SSam Cramer 			goto usage_error;
490836fc322SSam Cramer 
491836fc322SSam Cramer 		default:
492836fc322SSam Cramer 			break;
493836fc322SSam Cramer 		}
494836fc322SSam Cramer 	}
495836fc322SSam Cramer 
496a6d42e7dSPeter Dunlap 	/*
497a6d42e7dSPeter Dunlap 	 * XXX - this should probably get pushed down to the library
498a6d42e7dSPeter Dunlap 	 * depending on the decision to allow/disallow configuratoin
499a6d42e7dSPeter Dunlap 	 * without the service running.
500a6d42e7dSPeter Dunlap 	 */
501a6d42e7dSPeter Dunlap 	/*
502a6d42e7dSPeter Dunlap 	 * Make sure iSCSI target service is enabled before
503a6d42e7dSPeter Dunlap 	 * proceeding.
504a6d42e7dSPeter Dunlap 	 */
505a6d42e7dSPeter Dunlap 	smfstate = smf_get_state(ISCSIT_SVC);
506a6d42e7dSPeter Dunlap 	if (!smfstate ||
507a6d42e7dSPeter Dunlap 	    (strcmp(smfstate, SCF_STATE_STRING_ONLINE) != 0)) {
508a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
509a6d42e7dSPeter Dunlap 		    gettext("The iSCSI target service must be online "
510a6d42e7dSPeter Dunlap 		    "before running this command."));
511a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
512a6d42e7dSPeter Dunlap 		    gettext("Use 'svcadm enable -r %s'"), ISCSIT_SVC);
513a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
514a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
515a6d42e7dSPeter Dunlap 		    gettext("to enable the service and its prerequisite "
516a6d42e7dSPeter Dunlap 		    "services and/or"));
517a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
518a6d42e7dSPeter Dunlap 		    gettext("'svcs -x %s' to determine why it is not online."),
519a6d42e7dSPeter Dunlap 		    ISCSIT_SVC);
520a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
521a6d42e7dSPeter Dunlap 
522a6d42e7dSPeter Dunlap 		return (1);
523a6d42e7dSPeter Dunlap 	}
524a6d42e7dSPeter Dunlap 
525a6d42e7dSPeter Dunlap 	switch ((itadm_sub_t)idx) {
526a6d42e7dSPeter Dunlap 		case CREATE_TGT:
527a6d42e7dSPeter Dunlap 			if (targetname) {
528a6d42e7dSPeter Dunlap 				ret = create_target(targetname, proplist);
529a6d42e7dSPeter Dunlap 			} else {
530a6d42e7dSPeter Dunlap 				/*
531a6d42e7dSPeter Dunlap 				 * OK for objp to be NULL here.  If the
532a6d42e7dSPeter Dunlap 				 * user did not specify a target name,
533a6d42e7dSPeter Dunlap 				 * one will be generated.
534a6d42e7dSPeter Dunlap 				 */
535a6d42e7dSPeter Dunlap 				ret = create_target(objp, proplist);
536a6d42e7dSPeter Dunlap 			}
537a6d42e7dSPeter Dunlap 			break;
538a6d42e7dSPeter Dunlap 		case MODIFY_TGT:
539a6d42e7dSPeter Dunlap 			ret = modify_target(objp, targetname, proplist);
540a6d42e7dSPeter Dunlap 			break;
541a6d42e7dSPeter Dunlap 		case DELETE_TGT:
542a6d42e7dSPeter Dunlap 			ret = delete_target(objp, force);
543a6d42e7dSPeter Dunlap 			break;
544a6d42e7dSPeter Dunlap 		case LIST_TGT:
545a6d42e7dSPeter Dunlap 			ret = list_target(objp, verbose, scripting);
546a6d42e7dSPeter Dunlap 			break;
547a6d42e7dSPeter Dunlap 		case CREATE_TPG:
548a6d42e7dSPeter Dunlap 			ret = create_tpg(objp, newargc - 1, &(newargv[1]));
549a6d42e7dSPeter Dunlap 			break;
550a6d42e7dSPeter Dunlap 		case DELETE_TPG:
551a6d42e7dSPeter Dunlap 			ret = delete_tpg(objp, force);
552a6d42e7dSPeter Dunlap 			break;
553a6d42e7dSPeter Dunlap 		case LIST_TPG:
554a6d42e7dSPeter Dunlap 			ret = list_tpg(objp, verbose, scripting);
555a6d42e7dSPeter Dunlap 			break;
556a6d42e7dSPeter Dunlap 		case CREATE_INI:
557a6d42e7dSPeter Dunlap 			ret = modify_initiator(objp, proplist, B_TRUE);
558a6d42e7dSPeter Dunlap 			break;
559a6d42e7dSPeter Dunlap 		case MODIFY_INI:
560a6d42e7dSPeter Dunlap 			ret = modify_initiator(objp, proplist, B_FALSE);
561a6d42e7dSPeter Dunlap 			break;
562a6d42e7dSPeter Dunlap 		case LIST_INI:
563a6d42e7dSPeter Dunlap 			ret = list_initiator(objp, verbose, scripting);
564a6d42e7dSPeter Dunlap 			break;
565a6d42e7dSPeter Dunlap 		case DELETE_INI:
566a6d42e7dSPeter Dunlap 			ret = delete_initiator(objp);
567a6d42e7dSPeter Dunlap 			break;
568a6d42e7dSPeter Dunlap 		case MODIFY_DEF:
569a6d42e7dSPeter Dunlap 			ret = modify_defaults(proplist);
570a6d42e7dSPeter Dunlap 			break;
571a6d42e7dSPeter Dunlap 		case LIST_DEF:
572a6d42e7dSPeter Dunlap 			ret = list_defaults(scripting);
573a6d42e7dSPeter Dunlap 			break;
574a6d42e7dSPeter Dunlap 		default:
575a6d42e7dSPeter Dunlap 			ret = 1;
576a6d42e7dSPeter Dunlap 			goto usage_error;
577a6d42e7dSPeter Dunlap 	}
578a6d42e7dSPeter Dunlap 
579a6d42e7dSPeter Dunlap 	if (ret != 0) {
580a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
581a6d42e7dSPeter Dunlap 		    gettext("itadm %s failed with error %d"),
582a6d42e7dSPeter Dunlap 		    subcmds[idx].name, ret);
583a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
584a6d42e7dSPeter Dunlap 	}
585a6d42e7dSPeter Dunlap 	return (ret);
586a6d42e7dSPeter Dunlap 
587a6d42e7dSPeter Dunlap usage_error:
588a6d42e7dSPeter Dunlap 	if (subcmds[idx].name) {
589a6d42e7dSPeter Dunlap 		(void) printf("%s\n", gettext(subcmds[idx].usemsg));
590a6d42e7dSPeter Dunlap 	} else {
591a6d42e7dSPeter Dunlap 		/* overall usage */
592a6d42e7dSPeter Dunlap 		(void) printf("%s\n\n", gettext("itadm usage:"));
593a6d42e7dSPeter Dunlap 		for (idx = 0; subcmds[idx].name != NULL; idx++) {
594a6d42e7dSPeter Dunlap 			if (!subcmds[idx].usemsg) {
595a6d42e7dSPeter Dunlap 				continue;
596a6d42e7dSPeter Dunlap 			}
597a6d42e7dSPeter Dunlap 			(void) printf("\t%s\n", gettext(subcmds[idx].usemsg));
598a6d42e7dSPeter Dunlap 		}
599a6d42e7dSPeter Dunlap 	}
600a6d42e7dSPeter Dunlap 
601a6d42e7dSPeter Dunlap 	return (ret);
602a6d42e7dSPeter Dunlap }
603a6d42e7dSPeter Dunlap 
604a6d42e7dSPeter Dunlap static int
605a6d42e7dSPeter Dunlap create_target(char *tgt, nvlist_t *proplist)
606a6d42e7dSPeter Dunlap {
607a6d42e7dSPeter Dunlap 	int		ret;
608a6d42e7dSPeter Dunlap 	it_config_t	*cfg = NULL;
609a6d42e7dSPeter Dunlap 	it_tgt_t	*tgtp;
610a6d42e7dSPeter Dunlap 	char		**tags = NULL;
611a6d42e7dSPeter Dunlap 	uint32_t	count = 0;
612a6d42e7dSPeter Dunlap 	nvlist_t	*errlist = NULL;
613a6d42e7dSPeter Dunlap 	int		i;
614a6d42e7dSPeter Dunlap 	it_tpg_t	*tpg = NULL;
615a6d42e7dSPeter Dunlap 	uint16_t	tagid = 0;
616a6d42e7dSPeter Dunlap 	it_tpgt_t	*tpgt;
617a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.modify.stmf";
618*a4f92191SSam Cramer 	char		*canonical_tgt = NULL;
619*a4f92191SSam Cramer 	boolean_t	did_it_config_load = B_FALSE;
620a6d42e7dSPeter Dunlap 
621a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
622a6d42e7dSPeter Dunlap 
623a6d42e7dSPeter Dunlap 	if (tgt) {
624a6d42e7dSPeter Dunlap 		/*
625*a4f92191SSam Cramer 		 * Validate target name.
626a6d42e7dSPeter Dunlap 		 */
627a6d42e7dSPeter Dunlap 		if ((strncmp(tgt, "eui.", 4) != 0) &&
628a6d42e7dSPeter Dunlap 		    (strncmp(tgt, "iqn.", 4) != 0)) {
629a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, gettext("Invalid name %s"),
630a6d42e7dSPeter Dunlap 			    tgt);
631a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
632a6d42e7dSPeter Dunlap 			return (EINVAL);
633a6d42e7dSPeter Dunlap 		}
634*a4f92191SSam Cramer 
635*a4f92191SSam Cramer 		canonical_tgt = canonical_target_name(tgt);
636a6d42e7dSPeter Dunlap 	}
637a6d42e7dSPeter Dunlap 
638a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
639a6d42e7dSPeter Dunlap 	if (ret != 0) {
640a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
641a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
642a6d42e7dSPeter Dunlap 		    ret);
643a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
644*a4f92191SSam Cramer 		goto done;
645a6d42e7dSPeter Dunlap 	}
646a6d42e7dSPeter Dunlap 
647*a4f92191SSam Cramer 	did_it_config_load = B_TRUE;
648*a4f92191SSam Cramer 
649*a4f92191SSam Cramer 	ret = it_tgt_create(cfg, &tgtp, canonical_tgt);
650a6d42e7dSPeter Dunlap 	if (ret != 0) {
651a6d42e7dSPeter Dunlap 		if (ret == EFAULT) {
652a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
653a6d42e7dSPeter Dunlap 			    gettext("Invalid iSCSI name %s"), tgt);
654a6d42e7dSPeter Dunlap 		} else if (ret == EEXIST) {
655a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
656a6d42e7dSPeter Dunlap 			    gettext("iSCSI target %s already configured"),
657a6d42e7dSPeter Dunlap 			    tgt);
658836fc322SSam Cramer 		} else if (ret == E2BIG) {
659836fc322SSam Cramer 			(void) fprintf(stderr,
660836fc322SSam Cramer 			    gettext("Maximum of %d iSCSI targets"),
661836fc322SSam Cramer 			    MAX_TARGETS);
662a6d42e7dSPeter Dunlap 		} else {
663a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
664a6d42e7dSPeter Dunlap 			    gettext("Error creating target: %d"), ret);
665a6d42e7dSPeter Dunlap 		}
666a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
667a6d42e7dSPeter Dunlap 		goto done;
668a6d42e7dSPeter Dunlap 	}
669a6d42e7dSPeter Dunlap 
670a6d42e7dSPeter Dunlap 	/* set the target portal group tags */
671a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_string_array(proplist, "tpg-tag", &tags,
672a6d42e7dSPeter Dunlap 	    &count);
673a6d42e7dSPeter Dunlap 
674a6d42e7dSPeter Dunlap 	if (ret == ENOENT) {
675a6d42e7dSPeter Dunlap 		/* none specified.  is this ok? */
676a6d42e7dSPeter Dunlap 		ret = 0;
677a6d42e7dSPeter Dunlap 	} else if (ret != 0) {
678a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
679a6d42e7dSPeter Dunlap 		    gettext("internal error: %d"), ret);
680a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
681a6d42e7dSPeter Dunlap 		goto done;
682a6d42e7dSPeter Dunlap 	}
683a6d42e7dSPeter Dunlap 
684a6d42e7dSPeter Dunlap 	/* special case, don't set any TPGs */
685a6d42e7dSPeter Dunlap 	if (tags && (strcmp("default", tags[0]) == 0)) {
686a6d42e7dSPeter Dunlap 		count = 0;
687a6d42e7dSPeter Dunlap 	}
688a6d42e7dSPeter Dunlap 
689a6d42e7dSPeter Dunlap 	for (i = 0; i < count; i++) {
690a6d42e7dSPeter Dunlap 		if (!tags[i]) {
691a6d42e7dSPeter Dunlap 			continue;
692a6d42e7dSPeter Dunlap 		}
693a6d42e7dSPeter Dunlap 
694a6d42e7dSPeter Dunlap 		/* see that all referenced groups are already defined */
695a6d42e7dSPeter Dunlap 		tpg = cfg->config_tpg_list;
696a6d42e7dSPeter Dunlap 		while (tpg != NULL) {
697a6d42e7dSPeter Dunlap 			if (strcmp(tags[i], tpg->tpg_name) == 0) {
698a6d42e7dSPeter Dunlap 				break;
699a6d42e7dSPeter Dunlap 			}
700a6d42e7dSPeter Dunlap 
701a6d42e7dSPeter Dunlap 			tpg = tpg->tpg_next;
702a6d42e7dSPeter Dunlap 		}
703a6d42e7dSPeter Dunlap 		if (tpg == NULL) {
704a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
705a6d42e7dSPeter Dunlap 			    gettext("Invalid tpg-tag %s, tag not defined"),
706a6d42e7dSPeter Dunlap 			    tags[i]);
707a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
708a6d42e7dSPeter Dunlap 			ret = 1;
709a6d42e7dSPeter Dunlap 			goto done;
710a6d42e7dSPeter Dunlap 		}
711a6d42e7dSPeter Dunlap 
712a6d42e7dSPeter Dunlap 		/* generate the tag number to use */
713a6d42e7dSPeter Dunlap 		tag_name_to_num(tags[i], &tagid);
714a6d42e7dSPeter Dunlap 
715a6d42e7dSPeter Dunlap 		ret = it_tpgt_create(cfg, tgtp, &tpgt, tags[i], tagid);
716a6d42e7dSPeter Dunlap 		if (ret != 0) {
717a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
718a6d42e7dSPeter Dunlap 			    gettext("Could not add target portal group"
719a6d42e7dSPeter Dunlap 			    "tag %s, error %d"), tags[i], ret);
720a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
721a6d42e7dSPeter Dunlap 			goto done;
722a6d42e7dSPeter Dunlap 		}
723a6d42e7dSPeter Dunlap 		tagid++;
724a6d42e7dSPeter Dunlap 	}
725a6d42e7dSPeter Dunlap 
726a6d42e7dSPeter Dunlap 	/* remove the tags from the proplist before continuing */
727a6d42e7dSPeter Dunlap 	if (tags) {
728a6d42e7dSPeter Dunlap 		(void) nvlist_remove_all(proplist, "tpg-tag");
729a6d42e7dSPeter Dunlap 	}
730a6d42e7dSPeter Dunlap 
731a6d42e7dSPeter Dunlap 	ret = it_tgt_setprop(cfg, tgtp, proplist, &errlist);
732a6d42e7dSPeter Dunlap 	if (ret != 0) {
733a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
734a6d42e7dSPeter Dunlap 		    gettext("Error setting target properties, %d"), ret);
735a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
736a6d42e7dSPeter Dunlap 		if (errlist) {
737a6d42e7dSPeter Dunlap 			nvpair_t	*nvp = NULL;
738a6d42e7dSPeter Dunlap 			char		*nn;
739a6d42e7dSPeter Dunlap 			char		*nv;
740a6d42e7dSPeter Dunlap 
741a6d42e7dSPeter Dunlap 			while ((nvp = nvlist_next_nvpair(errlist, nvp))
742a6d42e7dSPeter Dunlap 			    != NULL) {
743a6d42e7dSPeter Dunlap 				nv = NULL;
744a6d42e7dSPeter Dunlap 
745a6d42e7dSPeter Dunlap 				nn = nvpair_name(nvp);
746a6d42e7dSPeter Dunlap 				(void) nvpair_value_string(nvp, &nv);
747a6d42e7dSPeter Dunlap 
748a6d42e7dSPeter Dunlap 				if (nv != NULL) {
749a6d42e7dSPeter Dunlap 					(void) fprintf(stderr, "\t%s: %s\n",
750a6d42e7dSPeter Dunlap 					    nn, nv);
751a6d42e7dSPeter Dunlap 				}
752a6d42e7dSPeter Dunlap 			}
753a6d42e7dSPeter Dunlap 
754a6d42e7dSPeter Dunlap 			nvlist_free(errlist);
755a6d42e7dSPeter Dunlap 		}
756a6d42e7dSPeter Dunlap 		goto done;
757a6d42e7dSPeter Dunlap 	}
758a6d42e7dSPeter Dunlap 
759a6d42e7dSPeter Dunlap 	if (ret == 0) {
760a6d42e7dSPeter Dunlap 		ret = it_config_commit(cfg);
761a6d42e7dSPeter Dunlap 		STMF_STALE(ret);
762a6d42e7dSPeter Dunlap 	}
763a6d42e7dSPeter Dunlap 
764a6d42e7dSPeter Dunlap done:
765a6d42e7dSPeter Dunlap 	if (ret == 0) {
766a6d42e7dSPeter Dunlap 		(void) printf(gettext("Target %s successfully created"),
767a6d42e7dSPeter Dunlap 		    tgtp->tgt_name);
768a6d42e7dSPeter Dunlap 		(void) printf("\n");
769a6d42e7dSPeter Dunlap 	}
770a6d42e7dSPeter Dunlap 
771*a4f92191SSam Cramer 	if (did_it_config_load)
772a6d42e7dSPeter Dunlap 		it_config_free(cfg);
773a6d42e7dSPeter Dunlap 
774*a4f92191SSam Cramer 	if (canonical_tgt != NULL)
775*a4f92191SSam Cramer 		free(canonical_tgt);
776*a4f92191SSam Cramer 
777a6d42e7dSPeter Dunlap 	return (ret);
778a6d42e7dSPeter Dunlap }
779a6d42e7dSPeter Dunlap 
780a6d42e7dSPeter Dunlap int
781a6d42e7dSPeter Dunlap list_target(char *tgt, boolean_t verbose, boolean_t script)
782a6d42e7dSPeter Dunlap {
783a6d42e7dSPeter Dunlap 	int		ret;
784a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
785a6d42e7dSPeter Dunlap 	it_tgt_t	*ptr;
786a6d42e7dSPeter Dunlap 	boolean_t	found = B_FALSE;
787a6d42e7dSPeter Dunlap 	boolean_t	first = B_TRUE;
788a6d42e7dSPeter Dunlap 	boolean_t	first_tag = B_TRUE;
789a6d42e7dSPeter Dunlap 	char		*gauth = "none";
790a6d42e7dSPeter Dunlap 	char		*galias = "-";
791a6d42e7dSPeter Dunlap 	char		*auth;
792a6d42e7dSPeter Dunlap 	char		*alias;
793a6d42e7dSPeter Dunlap 	char		*chapu;
794a6d42e7dSPeter Dunlap 	char		*chaps;
795a6d42e7dSPeter Dunlap 	it_tpgt_t	*tagp;
796a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.read.stmf";
797a6d42e7dSPeter Dunlap 	stmfDevid	devid;
798a6d42e7dSPeter Dunlap 	stmfSessionList	*sess = NULL;
799a6d42e7dSPeter Dunlap 	stmfTargetProperties	props;
800a6d42e7dSPeter Dunlap 	char		*state;
801a6d42e7dSPeter Dunlap 	int		num_sessions;
802a6d42e7dSPeter Dunlap 
803a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
804a6d42e7dSPeter Dunlap 
805a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
806a6d42e7dSPeter Dunlap 	if (ret != 0) {
807a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
808a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
809a6d42e7dSPeter Dunlap 		    ret);
810a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
811a6d42e7dSPeter Dunlap 		return (ret);
812a6d42e7dSPeter Dunlap 	}
813a6d42e7dSPeter Dunlap 
814a6d42e7dSPeter Dunlap 	ptr = cfg->config_tgt_list;
815a6d42e7dSPeter Dunlap 
816a6d42e7dSPeter Dunlap 	/* grab global defaults for auth, alias */
817a6d42e7dSPeter Dunlap 	if (cfg->config_global_properties) {
818a6d42e7dSPeter Dunlap 		(void) nvlist_lookup_string(cfg->config_global_properties,
819a6d42e7dSPeter Dunlap 		    "alias", &galias);
820a6d42e7dSPeter Dunlap 		(void) nvlist_lookup_string(cfg->config_global_properties,
821a6d42e7dSPeter Dunlap 		    "auth", &gauth);
822a6d42e7dSPeter Dunlap 	}
823a6d42e7dSPeter Dunlap 
824a6d42e7dSPeter Dunlap 	for (; ptr != NULL; ptr = ptr->tgt_next) {
825a6d42e7dSPeter Dunlap 		if (found) {
826a6d42e7dSPeter Dunlap 			break;
827a6d42e7dSPeter Dunlap 		}
828a6d42e7dSPeter Dunlap 
829a6d42e7dSPeter Dunlap 		if (tgt) {
830*a4f92191SSam Cramer 			/*
831*a4f92191SSam Cramer 			 * We do a case-insensitive match in case
832*a4f92191SSam Cramer 			 * a non-lower case value got stored.
833*a4f92191SSam Cramer 			 */
834*a4f92191SSam Cramer 			if (strcasecmp(tgt, ptr->tgt_name) != 0) {
835a6d42e7dSPeter Dunlap 				continue;
836a6d42e7dSPeter Dunlap 			} else {
837a6d42e7dSPeter Dunlap 				found = B_TRUE;
838a6d42e7dSPeter Dunlap 			}
839a6d42e7dSPeter Dunlap 		}
840a6d42e7dSPeter Dunlap 
841a6d42e7dSPeter Dunlap 		state = "-";
842a6d42e7dSPeter Dunlap 		num_sessions = 0;
843a6d42e7dSPeter Dunlap 		sess = NULL;
844a6d42e7dSPeter Dunlap 
845a6d42e7dSPeter Dunlap 		/*
846a6d42e7dSPeter Dunlap 		 * make a best effort to retrieve target status and
847a6d42e7dSPeter Dunlap 		 * number of active sessions from STMF.
848a6d42e7dSPeter Dunlap 		 */
849a6d42e7dSPeter Dunlap 		ret = stmfDevidFromIscsiName(ptr->tgt_name, &devid);
850a6d42e7dSPeter Dunlap 		if (ret == STMF_STATUS_SUCCESS) {
851a6d42e7dSPeter Dunlap 			ret = stmfGetTargetProperties(&devid, &props);
852a6d42e7dSPeter Dunlap 			if (ret == STMF_STATUS_SUCCESS) {
853a6d42e7dSPeter Dunlap 				if (props.status == STMF_TARGET_PORT_ONLINE) {
854a6d42e7dSPeter Dunlap 					state = "online";
855a6d42e7dSPeter Dunlap 				} else {
856a6d42e7dSPeter Dunlap 					state = "offline";
857a6d42e7dSPeter Dunlap 				}
858a6d42e7dSPeter Dunlap 			}
859a6d42e7dSPeter Dunlap 		}
860a6d42e7dSPeter Dunlap 		if (ret == STMF_STATUS_SUCCESS) {
861a6d42e7dSPeter Dunlap 			ret = stmfGetSessionList(&devid, &sess);
862a6d42e7dSPeter Dunlap 			if (ret == STMF_STATUS_SUCCESS) {
863a6d42e7dSPeter Dunlap 				num_sessions = sess->cnt;
864a6d42e7dSPeter Dunlap 				free(sess);
865a6d42e7dSPeter Dunlap 			}
866a6d42e7dSPeter Dunlap 		}
867a6d42e7dSPeter Dunlap 
868a6d42e7dSPeter Dunlap 		/* reset ret so we don't return an error */
869a6d42e7dSPeter Dunlap 		ret = 0;
870a6d42e7dSPeter Dunlap 
871a6d42e7dSPeter Dunlap 		if (!script && first) {
872a6d42e7dSPeter Dunlap 			(void) printf("%-61s%-9s%-9s\n", "TARGET NAME",
873a6d42e7dSPeter Dunlap 			    "STATE", "SESSIONS");
874a6d42e7dSPeter Dunlap 			first = B_FALSE;
875a6d42e7dSPeter Dunlap 		}
876a6d42e7dSPeter Dunlap 
877a6d42e7dSPeter Dunlap 		if (!script) {
878a6d42e7dSPeter Dunlap 			/*
879a6d42e7dSPeter Dunlap 			 * try not to let columns run into each other.
880a6d42e7dSPeter Dunlap 			 * Stick a tab after too-long fields.
881a6d42e7dSPeter Dunlap 			 * Lengths chosen are for the 'common' cases.
882a6d42e7dSPeter Dunlap 			 */
883a6d42e7dSPeter Dunlap 			(void) printf("%-61s", ptr->tgt_name);
884a6d42e7dSPeter Dunlap 			if (strlen(ptr->tgt_name) > 60) {
885a6d42e7dSPeter Dunlap 				(void) printf("\t");
886a6d42e7dSPeter Dunlap 			}
887a6d42e7dSPeter Dunlap 			(void) printf("%-9s%-9d", state, num_sessions);
888a6d42e7dSPeter Dunlap 		} else {
889a6d42e7dSPeter Dunlap 			(void) printf("%s\t%s\t%d", ptr->tgt_name,
890a6d42e7dSPeter Dunlap 			    state, num_sessions);
891a6d42e7dSPeter Dunlap 		}
892a6d42e7dSPeter Dunlap 
893a6d42e7dSPeter Dunlap 		if (!verbose) {
894a6d42e7dSPeter Dunlap 			(void) printf("\n");
895a6d42e7dSPeter Dunlap 			continue;
896a6d42e7dSPeter Dunlap 		}
897a6d42e7dSPeter Dunlap 
898a6d42e7dSPeter Dunlap 		auth = gauth;
899a6d42e7dSPeter Dunlap 		alias = galias;
900a6d42e7dSPeter Dunlap 		chapu = "-";
901a6d42e7dSPeter Dunlap 		chaps = "unset";
902a6d42e7dSPeter Dunlap 
903a6d42e7dSPeter Dunlap 		if (ptr->tgt_properties) {
904a6d42e7dSPeter Dunlap 			(void) nvlist_lookup_string(ptr->tgt_properties,
905a6d42e7dSPeter Dunlap 			    "auth", &auth);
906a6d42e7dSPeter Dunlap 			(void) nvlist_lookup_string(ptr->tgt_properties,
907a6d42e7dSPeter Dunlap 			    "alias", &alias);
908a6d42e7dSPeter Dunlap 			if (nvlist_exists(ptr->tgt_properties,
909a6d42e7dSPeter Dunlap 			    "targetchapsecret")) {
910a6d42e7dSPeter Dunlap 				chaps = "set";
911a6d42e7dSPeter Dunlap 			}
912a6d42e7dSPeter Dunlap 			(void) nvlist_lookup_string(ptr->tgt_properties,
913a6d42e7dSPeter Dunlap 			    "targetchapuser", &chapu);
914a6d42e7dSPeter Dunlap 		}
915a6d42e7dSPeter Dunlap 
916a6d42e7dSPeter Dunlap 		if (!script) {
917263f58aaSPriya Krishnan 			(void) printf("\n\t%-20s\t%s\n\t%-20s\t%s %s\n"
918a6d42e7dSPeter Dunlap 			    "\t%-20s\t%s\n\t%-20s\t%s\n\t%-20s\t",
919263f58aaSPriya Krishnan 			    "alias:", alias, "auth:", auth,
920263f58aaSPriya Krishnan 			    ((auth == gauth) ? "(defaults)" : ""),
921263f58aaSPriya Krishnan 			    "targetchapuser:",
922a6d42e7dSPeter Dunlap 			    chapu, "targetchapsecret:", chaps, "tpg-tags:");
923a6d42e7dSPeter Dunlap 		} else {
924263f58aaSPriya Krishnan 			(void) printf("\t%s\t%s %s\t%s\t%s\t",
925263f58aaSPriya Krishnan 			    alias, auth,
926263f58aaSPriya Krishnan 			    ((auth == gauth) ? "(defaults)" : ""),
927263f58aaSPriya Krishnan 			    chapu, chaps);
928a6d42e7dSPeter Dunlap 		}
929a6d42e7dSPeter Dunlap 
930a6d42e7dSPeter Dunlap 		first_tag = B_TRUE;
931a6d42e7dSPeter Dunlap 		tagp = ptr->tgt_tpgt_list;
932a6d42e7dSPeter Dunlap 		for (; tagp != NULL; tagp = tagp->tpgt_next) {
933a6d42e7dSPeter Dunlap 			if (!first_tag) {
934a6d42e7dSPeter Dunlap 				(void) printf(",");
935a6d42e7dSPeter Dunlap 			} else {
936a6d42e7dSPeter Dunlap 				first_tag = B_FALSE;
937a6d42e7dSPeter Dunlap 			}
938263f58aaSPriya Krishnan 			(void) printf("%s = %d",
939263f58aaSPriya Krishnan 			    tagp->tpgt_tpg_name, tagp->tpgt_tag);
940a6d42e7dSPeter Dunlap 		}
941a6d42e7dSPeter Dunlap 
942a6d42e7dSPeter Dunlap 		if (first_tag) {
943a6d42e7dSPeter Dunlap 			/* didn't find any */
944a6d42e7dSPeter Dunlap 			(void) printf("default");
945a6d42e7dSPeter Dunlap 		}
946a6d42e7dSPeter Dunlap 
947a6d42e7dSPeter Dunlap 		(void) printf("\n");
948a6d42e7dSPeter Dunlap 	}
949a6d42e7dSPeter Dunlap 
950a6d42e7dSPeter Dunlap 	if (tgt && (!found)) {
951a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
952a6d42e7dSPeter Dunlap 		    gettext("Target %s not found!\n"), tgt);
953a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
954a6d42e7dSPeter Dunlap 		ret = 1;
955a6d42e7dSPeter Dunlap 	}
956a6d42e7dSPeter Dunlap 
957a6d42e7dSPeter Dunlap 	it_config_free(cfg);
958a6d42e7dSPeter Dunlap 
959a6d42e7dSPeter Dunlap 	return (ret);
960a6d42e7dSPeter Dunlap }
961a6d42e7dSPeter Dunlap 
962a6d42e7dSPeter Dunlap int
963a6d42e7dSPeter Dunlap delete_target(char *tgt, boolean_t force)
964a6d42e7dSPeter Dunlap {
965a6d42e7dSPeter Dunlap 	int		ret;
966a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
967a6d42e7dSPeter Dunlap 	it_tgt_t	*ptr;
968a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.modify.stmf";
969a6d42e7dSPeter Dunlap 
970a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
971a6d42e7dSPeter Dunlap 
972a6d42e7dSPeter Dunlap 	if (!tgt) {
973a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
974a6d42e7dSPeter Dunlap 		    gettext("Error, no target specified"));
975a6d42e7dSPeter Dunlap 		return (EINVAL);
976a6d42e7dSPeter Dunlap 	}
977a6d42e7dSPeter Dunlap 
978a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
979a6d42e7dSPeter Dunlap 	if (ret != 0) {
980a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
981a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
982a6d42e7dSPeter Dunlap 		    ret);
983a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
984a6d42e7dSPeter Dunlap 		return (ret);
985a6d42e7dSPeter Dunlap 	}
986a6d42e7dSPeter Dunlap 
987a6d42e7dSPeter Dunlap 	ptr = cfg->config_tgt_list;
988a6d42e7dSPeter Dunlap 	while (ptr) {
989*a4f92191SSam Cramer 		/*
990*a4f92191SSam Cramer 		 * We do a case-insensitive match in case
991*a4f92191SSam Cramer 		 * a non-lower case value got stored.
992*a4f92191SSam Cramer 		 */
993*a4f92191SSam Cramer 		if (strcasecmp(ptr->tgt_name, tgt) == 0) {
994a6d42e7dSPeter Dunlap 			break;
995a6d42e7dSPeter Dunlap 		}
996a6d42e7dSPeter Dunlap 
997a6d42e7dSPeter Dunlap 		ptr = ptr->tgt_next;
998a6d42e7dSPeter Dunlap 	}
999a6d42e7dSPeter Dunlap 
1000a6d42e7dSPeter Dunlap 	if (ptr) {
1001a6d42e7dSPeter Dunlap 		ret = it_tgt_delete(cfg, ptr, force);
1002a6d42e7dSPeter Dunlap 
1003a6d42e7dSPeter Dunlap 		if (ret != 0) {
1004a6d42e7dSPeter Dunlap 			if (ret == EBUSY) {
1005a6d42e7dSPeter Dunlap 				(void) fprintf(stderr,
1006a6d42e7dSPeter Dunlap 				    gettext("The target is online or busy. "
1007a6d42e7dSPeter Dunlap 				    "Use the -f (force) option, or "
1008a6d42e7dSPeter Dunlap 				    "'stmfadm offline-target %s'"), tgt);
1009a6d42e7dSPeter Dunlap 				(void) fprintf(stderr, "\n");
1010a6d42e7dSPeter Dunlap 			}
1011a6d42e7dSPeter Dunlap 		}
1012a6d42e7dSPeter Dunlap 
1013a6d42e7dSPeter Dunlap 		if (ret == 0) {
1014a6d42e7dSPeter Dunlap 			ret = it_config_commit(cfg);
1015a6d42e7dSPeter Dunlap 			STMF_STALE(ret);
1016a6d42e7dSPeter Dunlap 		}
1017a6d42e7dSPeter Dunlap 	} else {
1018a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1019a6d42e7dSPeter Dunlap 		    gettext("Target %s not found"), tgt);
1020a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1021a6d42e7dSPeter Dunlap 		ret = 1;
1022a6d42e7dSPeter Dunlap 	}
1023a6d42e7dSPeter Dunlap 
1024a6d42e7dSPeter Dunlap 	it_config_free(cfg);
1025a6d42e7dSPeter Dunlap 
1026a6d42e7dSPeter Dunlap 	return (ret);
1027a6d42e7dSPeter Dunlap }
1028a6d42e7dSPeter Dunlap 
1029a6d42e7dSPeter Dunlap static int
1030a6d42e7dSPeter Dunlap modify_target(char *tgt, char *newname, nvlist_t *proplist)
1031a6d42e7dSPeter Dunlap {
1032a6d42e7dSPeter Dunlap 	int		ret;
1033a6d42e7dSPeter Dunlap 	it_config_t	*cfg = NULL;
1034a6d42e7dSPeter Dunlap 	it_tgt_t	*ptr = NULL;
1035836fc322SSam Cramer 	it_tgt_t	*tgtp = NULL;
1036a6d42e7dSPeter Dunlap 	char		**tags = NULL;
1037a6d42e7dSPeter Dunlap 	uint32_t	count = 0;
1038a6d42e7dSPeter Dunlap 	nvlist_t	*errlist = NULL;
1039a6d42e7dSPeter Dunlap 	int		i;
1040a6d42e7dSPeter Dunlap 	it_tpg_t	*tpg = NULL;
1041a6d42e7dSPeter Dunlap 	uint16_t	tagid;
1042836fc322SSam Cramer 	it_tpgt_t	*tpgt = NULL;
1043a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.modify.stmf";
1044*a4f92191SSam Cramer 	char 		*canonical_newname = NULL;
1045*a4f92191SSam Cramer 	boolean_t	did_it_config_load = B_FALSE;
1046a6d42e7dSPeter Dunlap 
1047a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1048a6d42e7dSPeter Dunlap 
1049a6d42e7dSPeter Dunlap 	/* XXX:  Do we need to offline anything here too? */
1050a6d42e7dSPeter Dunlap 
1051a6d42e7dSPeter Dunlap 	if (!tgt) {
1052a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
1053a6d42e7dSPeter Dunlap 		    gettext("Error, no target specified"));
1054*a4f92191SSam Cramer 		ret = EINVAL;
1055*a4f92191SSam Cramer 		goto done;
1056a6d42e7dSPeter Dunlap 	}
1057a6d42e7dSPeter Dunlap 
1058a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1059a6d42e7dSPeter Dunlap 	if (ret != 0) {
1060a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1061a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1062a6d42e7dSPeter Dunlap 		    ret);
1063a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1064*a4f92191SSam Cramer 		goto done;
1065a6d42e7dSPeter Dunlap 	}
1066a6d42e7dSPeter Dunlap 
1067*a4f92191SSam Cramer 	did_it_config_load = B_TRUE;
1068*a4f92191SSam Cramer 
1069a6d42e7dSPeter Dunlap 	/*
1070*a4f92191SSam Cramer 	 * If newname is specified, ensure it is a valid name,
1071*a4f92191SSam Cramer 	 * and generate its canonical form.
1072a6d42e7dSPeter Dunlap 	 */
1073a6d42e7dSPeter Dunlap 	if (newname) {
1074a6d42e7dSPeter Dunlap 		if (!validate_iscsi_name(newname)) {
1075a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
1076a6d42e7dSPeter Dunlap 			    gettext("Invalid iSCSI name %s"), newname);
1077a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
1078*a4f92191SSam Cramer 			ret = 1;
1079*a4f92191SSam Cramer 			goto done;
1080a6d42e7dSPeter Dunlap 		}
1081*a4f92191SSam Cramer 
1082*a4f92191SSam Cramer 		canonical_newname = canonical_target_name(newname);
1083a6d42e7dSPeter Dunlap 	}
1084a6d42e7dSPeter Dunlap 
1085a6d42e7dSPeter Dunlap 	/*
1086a6d42e7dSPeter Dunlap 	 * Loop through to verify that the target to be modified truly
1087a6d42e7dSPeter Dunlap 	 * exists.  If this target is to be renamed, ensure the new
1088a6d42e7dSPeter Dunlap 	 * name is not already in use.
1089a6d42e7dSPeter Dunlap 	 */
1090a6d42e7dSPeter Dunlap 	ptr = cfg->config_tgt_list;
1091a6d42e7dSPeter Dunlap 	while (ptr) {
1092*a4f92191SSam Cramer 		/*
1093*a4f92191SSam Cramer 		 * Does a target with the new name already exist?
1094*a4f92191SSam Cramer 		 */
1095*a4f92191SSam Cramer 		if (newname &&
1096*a4f92191SSam Cramer 		    (strcmp(canonical_newname, ptr->tgt_name) == 0)) {
1097a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
1098a6d42e7dSPeter Dunlap 			    gettext("A target with name %s already exists"),
1099a6d42e7dSPeter Dunlap 			    newname);
1100a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
1101a6d42e7dSPeter Dunlap 			ret = 1;
1102a6d42e7dSPeter Dunlap 			goto done;
1103a6d42e7dSPeter Dunlap 		}
1104a6d42e7dSPeter Dunlap 
1105*a4f92191SSam Cramer 		if (strcasecmp(ptr->tgt_name, tgt) == 0) {
1106a6d42e7dSPeter Dunlap 			tgtp = ptr;
1107a6d42e7dSPeter Dunlap 		}
1108a6d42e7dSPeter Dunlap 
1109a6d42e7dSPeter Dunlap 		ptr = ptr ->tgt_next;
1110a6d42e7dSPeter Dunlap 	}
1111a6d42e7dSPeter Dunlap 
1112a6d42e7dSPeter Dunlap 	if (!tgtp) {
1113a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1114a6d42e7dSPeter Dunlap 		    gettext("Target %s not found"), tgt);
1115a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1116*a4f92191SSam Cramer 		ret = EINVAL;
1117*a4f92191SSam Cramer 		goto done;
1118a6d42e7dSPeter Dunlap 	}
1119a6d42e7dSPeter Dunlap 
1120a6d42e7dSPeter Dunlap 	/* set the target portal group tags */
1121a6d42e7dSPeter Dunlap 	ret = nvlist_lookup_string_array(proplist, "tpg-tag", &tags,
1122a6d42e7dSPeter Dunlap 	    &count);
1123a6d42e7dSPeter Dunlap 
1124a6d42e7dSPeter Dunlap 	if (ret == ENOENT) {
1125a6d42e7dSPeter Dunlap 		/* none specified.  is this ok? */
1126a6d42e7dSPeter Dunlap 		ret = 0;
1127a6d42e7dSPeter Dunlap 	} else if (ret != 0) {
1128a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1129a6d42e7dSPeter Dunlap 		    gettext("internal error: %d"), ret);
1130a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1131a6d42e7dSPeter Dunlap 		goto done;
1132a6d42e7dSPeter Dunlap 	}
1133a6d42e7dSPeter Dunlap 
1134a6d42e7dSPeter Dunlap 	/* special case, remove all explicit TPGs, and don't add any */
1135a6d42e7dSPeter Dunlap 	if (tags && (strcmp("default", tags[0]) == 0)) {
1136a6d42e7dSPeter Dunlap 		count = 0;
1137a6d42e7dSPeter Dunlap 	}
1138a6d42e7dSPeter Dunlap 
1139a6d42e7dSPeter Dunlap 	for (i = 0; i < count; i++) {
1140*a4f92191SSam Cramer 		if (!tags || !tags[i]) {
1141a6d42e7dSPeter Dunlap 			continue;
1142a6d42e7dSPeter Dunlap 		}
1143a6d42e7dSPeter Dunlap 
1144a6d42e7dSPeter Dunlap 		/* see that all referenced groups are already defined */
1145a6d42e7dSPeter Dunlap 		tpg = cfg->config_tpg_list;
1146a6d42e7dSPeter Dunlap 		while (tpg != NULL) {
1147a6d42e7dSPeter Dunlap 			if (strcmp(tags[i], tpg->tpg_name) == 0) {
1148a6d42e7dSPeter Dunlap 				break;
1149a6d42e7dSPeter Dunlap 			}
1150a6d42e7dSPeter Dunlap 			tpg = tpg->tpg_next;
1151a6d42e7dSPeter Dunlap 		}
1152a6d42e7dSPeter Dunlap 		if (tpg == NULL) {
1153a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
1154a6d42e7dSPeter Dunlap 			    gettext("Invalid tpg-name %s: not defined"),
1155a6d42e7dSPeter Dunlap 			    tags[i]);
1156a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
1157a6d42e7dSPeter Dunlap 			ret = 1;
1158a6d42e7dSPeter Dunlap 			goto done;
1159a6d42e7dSPeter Dunlap 		}
1160a6d42e7dSPeter Dunlap 	}
1161a6d42e7dSPeter Dunlap 
1162a6d42e7dSPeter Dunlap 	/*
1163a6d42e7dSPeter Dunlap 	 * don't recreate tags that are already associated,
1164a6d42e7dSPeter Dunlap 	 * remove tags not requested.
1165a6d42e7dSPeter Dunlap 	 */
1166a6d42e7dSPeter Dunlap 	if (tags) {
1167a6d42e7dSPeter Dunlap 		tpgt = tgtp->tgt_tpgt_list;
1168a6d42e7dSPeter Dunlap 		while (tpgt) {
1169a6d42e7dSPeter Dunlap 			for (i = 0; i < count; i++) {
1170a6d42e7dSPeter Dunlap 				if (!tags[i]) {
1171a6d42e7dSPeter Dunlap 					continue;
1172a6d42e7dSPeter Dunlap 				}
1173a6d42e7dSPeter Dunlap 
1174a6d42e7dSPeter Dunlap 				if (strcmp(tpgt->tpgt_tpg_name, tags[i])
1175a6d42e7dSPeter Dunlap 				    == 0) {
1176a6d42e7dSPeter Dunlap 					/* non-null tags will be created */
1177a6d42e7dSPeter Dunlap 					tags[i] = NULL;
1178a6d42e7dSPeter Dunlap 					break;
1179a6d42e7dSPeter Dunlap 				}
1180a6d42e7dSPeter Dunlap 			}
1181a6d42e7dSPeter Dunlap 			if (i == count) {
1182a6d42e7dSPeter Dunlap 				/* one to remove */
1183a6d42e7dSPeter Dunlap 				it_tpgt_t	*ptr = tpgt;
1184a6d42e7dSPeter Dunlap 
1185a6d42e7dSPeter Dunlap 				tpgt = ptr->tpgt_next;
1186a6d42e7dSPeter Dunlap 				it_tpgt_delete(cfg, tgtp, ptr);
1187a6d42e7dSPeter Dunlap 			} else {
1188a6d42e7dSPeter Dunlap 				tpgt = tpgt->tpgt_next;
1189a6d42e7dSPeter Dunlap 			}
1190a6d42e7dSPeter Dunlap 		}
1191a6d42e7dSPeter Dunlap 	}
1192a6d42e7dSPeter Dunlap 
1193a6d42e7dSPeter Dunlap 	/* see if there are any left to add */
1194a6d42e7dSPeter Dunlap 	for (i = 0; i < count; i++) {
1195*a4f92191SSam Cramer 		if (!tags || !tags[i]) {
1196a6d42e7dSPeter Dunlap 			continue;
1197a6d42e7dSPeter Dunlap 		}
1198a6d42e7dSPeter Dunlap 
1199a6d42e7dSPeter Dunlap 		/* generate the tag number to use */
1200a6d42e7dSPeter Dunlap 		tag_name_to_num(tags[i], &tagid);
1201a6d42e7dSPeter Dunlap 
1202a6d42e7dSPeter Dunlap 		ret = it_tpgt_create(cfg, tgtp, &tpgt, tags[i], tagid);
1203a6d42e7dSPeter Dunlap 		if (ret != 0) {
1204a6d42e7dSPeter Dunlap 			if (ret == E2BIG) {
1205a6d42e7dSPeter Dunlap 				(void) fprintf(stderr, "%s\n",
1206a6d42e7dSPeter Dunlap 				    gettext("Error, no portal tag available"));
1207a6d42e7dSPeter Dunlap 			} else {
1208a6d42e7dSPeter Dunlap 				(void) fprintf(stderr, gettext(
1209a6d42e7dSPeter Dunlap 				    "Could not add target portal group"
1210a6d42e7dSPeter Dunlap 				    " tag %s, error %d"), tags[i], ret);
1211a6d42e7dSPeter Dunlap 				(void) fprintf(stderr, "\n");
1212a6d42e7dSPeter Dunlap 			}
1213a6d42e7dSPeter Dunlap 			goto done;
1214a6d42e7dSPeter Dunlap 		}
1215a6d42e7dSPeter Dunlap 	}
1216a6d42e7dSPeter Dunlap 
1217a6d42e7dSPeter Dunlap 	/* remove the tags from the proplist before continuing */
1218a6d42e7dSPeter Dunlap 	(void) nvlist_remove_all(proplist, "tpg-tag");
1219a6d42e7dSPeter Dunlap 
1220a6d42e7dSPeter Dunlap 	/*
1221a6d42e7dSPeter Dunlap 	 * Rename this target, if requested.  Save the old name in
1222a6d42e7dSPeter Dunlap 	 * the property list, so the kernel knows this is a renamed
1223a6d42e7dSPeter Dunlap 	 * target, and not a new one.
1224a6d42e7dSPeter Dunlap 	 */
1225a6d42e7dSPeter Dunlap 	if (newname && (strlen(newname) > 0)) {
1226a6d42e7dSPeter Dunlap 		ret = nvlist_add_string(proplist, "oldtargetname",
1227a6d42e7dSPeter Dunlap 		    tgtp->tgt_name);
1228a6d42e7dSPeter Dunlap 		if (ret != 0) {
1229a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "%s\n",
1230a6d42e7dSPeter Dunlap 			    gettext("Error renaming target."));
1231a6d42e7dSPeter Dunlap 			goto done;
1232a6d42e7dSPeter Dunlap 		}
1233*a4f92191SSam Cramer 		(void) strlcpy(tgtp->tgt_name, canonical_newname,
1234a6d42e7dSPeter Dunlap 		    sizeof (tgtp->tgt_name));
1235a6d42e7dSPeter Dunlap 	}
1236a6d42e7dSPeter Dunlap 
1237a6d42e7dSPeter Dunlap 	ret = it_tgt_setprop(cfg, tgtp, proplist, &errlist);
1238a6d42e7dSPeter Dunlap 	if (ret != 0) {
1239a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1240a6d42e7dSPeter Dunlap 		    gettext("Error setting target properties: %d"), ret);
1241a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1242a6d42e7dSPeter Dunlap 		if (errlist) {
1243a6d42e7dSPeter Dunlap 			nvpair_t	*nvp = NULL;
1244a6d42e7dSPeter Dunlap 			char		*nn;
1245a6d42e7dSPeter Dunlap 			char		*nv;
1246a6d42e7dSPeter Dunlap 
1247a6d42e7dSPeter Dunlap 			while ((nvp = nvlist_next_nvpair(errlist, nvp))
1248a6d42e7dSPeter Dunlap 			    != NULL) {
1249a6d42e7dSPeter Dunlap 				nv = NULL;
1250a6d42e7dSPeter Dunlap 
1251a6d42e7dSPeter Dunlap 				nn = nvpair_name(nvp);
1252a6d42e7dSPeter Dunlap 				(void) nvpair_value_string(nvp, &nv);
1253a6d42e7dSPeter Dunlap 
1254a6d42e7dSPeter Dunlap 				if (nv != NULL) {
1255a6d42e7dSPeter Dunlap 					(void) fprintf(stderr, "\t%s: %s\n",
1256a6d42e7dSPeter Dunlap 					    nn, nv);
1257a6d42e7dSPeter Dunlap 				}
1258a6d42e7dSPeter Dunlap 			}
1259a6d42e7dSPeter Dunlap 
1260a6d42e7dSPeter Dunlap 			nvlist_free(errlist);
1261a6d42e7dSPeter Dunlap 		}
1262a6d42e7dSPeter Dunlap 		goto done;
1263a6d42e7dSPeter Dunlap 	}
1264a6d42e7dSPeter Dunlap 
1265a6d42e7dSPeter Dunlap 	if (ret == 0) {
1266a6d42e7dSPeter Dunlap 		ret = it_config_commit(cfg);
1267a6d42e7dSPeter Dunlap 		STMF_STALE(ret);
1268a6d42e7dSPeter Dunlap 	}
1269a6d42e7dSPeter Dunlap 
1270a6d42e7dSPeter Dunlap done:
1271a6d42e7dSPeter Dunlap 	if (ret == 0) {
1272a6d42e7dSPeter Dunlap 		(void) printf(gettext("Target %s successfully modified"),
1273a6d42e7dSPeter Dunlap 		    tgtp->tgt_name);
1274a6d42e7dSPeter Dunlap 		(void) printf("\n");
1275a6d42e7dSPeter Dunlap 	}
1276a6d42e7dSPeter Dunlap 
1277*a4f92191SSam Cramer 	if (did_it_config_load)
1278a6d42e7dSPeter Dunlap 		it_config_free(cfg);
1279a6d42e7dSPeter Dunlap 
1280*a4f92191SSam Cramer 	if (canonical_newname != NULL)
1281*a4f92191SSam Cramer 		free(canonical_newname);
1282*a4f92191SSam Cramer 
1283a6d42e7dSPeter Dunlap 	return (ret);
1284a6d42e7dSPeter Dunlap }
1285a6d42e7dSPeter Dunlap 
1286a6d42e7dSPeter Dunlap int
1287a6d42e7dSPeter Dunlap create_tpg(char *tpg, int addrc, char **addrs)
1288a6d42e7dSPeter Dunlap {
1289a6d42e7dSPeter Dunlap 	int		ret;
1290a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
1291a6d42e7dSPeter Dunlap 	it_tpg_t	*tpgp;
1292a6d42e7dSPeter Dunlap 	int		count = 0;
1293a6d42e7dSPeter Dunlap 	it_portal_t	*ptl;
1294a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.modify.stmf";
1295836fc322SSam Cramer 	int 		i = 0;
1296a6d42e7dSPeter Dunlap 
1297a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1298a6d42e7dSPeter Dunlap 
1299a6d42e7dSPeter Dunlap 	if (!tpg) {
1300a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
1301a6d42e7dSPeter Dunlap 		    gettext("Error, no target portal group specified"));
1302a6d42e7dSPeter Dunlap 		return (EINVAL);
1303a6d42e7dSPeter Dunlap 	}
1304a6d42e7dSPeter Dunlap 
1305a6d42e7dSPeter Dunlap 	if (strlen(tpg) > (MAX_TPG_NAMELEN - 1)) {
1306a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1307a6d42e7dSPeter Dunlap 		    gettext("Target Portal Group name must be no longer "
1308a6d42e7dSPeter Dunlap 		    "than %d characters."), (MAX_TPG_NAMELEN - 1));
1309a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1310a6d42e7dSPeter Dunlap 		return (EINVAL);
1311a6d42e7dSPeter Dunlap 	}
1312a6d42e7dSPeter Dunlap 
1313a6d42e7dSPeter Dunlap 	if (!addrs || (addrc <= 0)) {
1314a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
1315a6d42e7dSPeter Dunlap 		    gettext("Error, no portal addresses specified"));
1316a6d42e7dSPeter Dunlap 		return (EINVAL);
1317a6d42e7dSPeter Dunlap 	}
1318a6d42e7dSPeter Dunlap 
1319a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1320a6d42e7dSPeter Dunlap 	if (ret != 0) {
1321a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1322a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1323a6d42e7dSPeter Dunlap 		    ret);
1324a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1325a6d42e7dSPeter Dunlap 		return (ret);
1326a6d42e7dSPeter Dunlap 	}
1327a6d42e7dSPeter Dunlap 
1328a6d42e7dSPeter Dunlap 	tpgp = cfg->config_tpg_list;
1329a6d42e7dSPeter Dunlap 	while (tpgp != NULL) {
1330a6d42e7dSPeter Dunlap 		if (strcmp(tpgp->tpg_name, tpg) == 0) {
1331a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
1332a6d42e7dSPeter Dunlap 			    gettext("Target Portal Group %s already exists"),
1333a6d42e7dSPeter Dunlap 			    tpg);
1334a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
1335a6d42e7dSPeter Dunlap 			it_config_free(cfg);
1336a6d42e7dSPeter Dunlap 			return (1);
1337a6d42e7dSPeter Dunlap 		}
1338a6d42e7dSPeter Dunlap 		tpgp = tpgp->tpg_next;
1339a6d42e7dSPeter Dunlap 	}
1340a6d42e7dSPeter Dunlap 
1341a6d42e7dSPeter Dunlap 	/*
1342836fc322SSam Cramer 	 * Ensure that the addrs don't contain commas.
1343836fc322SSam Cramer 	 */
1344836fc322SSam Cramer 	for (i = 0; i < addrc; i++) {
1345836fc322SSam Cramer 		if (strchr(addrs[i], ',')) {
1346836fc322SSam Cramer 			(void) fprintf(stderr,
1347836fc322SSam Cramer 			    gettext("Bad portal name %s"),
1348836fc322SSam Cramer 			    addrs[i]);
1349836fc322SSam Cramer 			(void) fprintf(stderr, "\n");
1350836fc322SSam Cramer 
1351836fc322SSam Cramer 			it_config_free(cfg);
1352836fc322SSam Cramer 			return (EINVAL);
1353836fc322SSam Cramer 		}
1354836fc322SSam Cramer 	}
1355836fc322SSam Cramer 
1356836fc322SSam Cramer 	/*
1357a6d42e7dSPeter Dunlap 	 * Create the portal group and first portal
1358a6d42e7dSPeter Dunlap 	 */
1359a6d42e7dSPeter Dunlap 	ret = it_tpg_create(cfg, &tpgp, tpg, addrs[count]);
1360a6d42e7dSPeter Dunlap 	if (ret != 0) {
1361a6d42e7dSPeter Dunlap 		if (ret == EEXIST) {
1362a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
1363a6d42e7dSPeter Dunlap 			    gettext("Portal %s already in use"),
1364a6d42e7dSPeter Dunlap 			    addrs[count]);
1365a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
1366a6d42e7dSPeter Dunlap 		}
1367a6d42e7dSPeter Dunlap 		it_config_free(cfg);
1368a6d42e7dSPeter Dunlap 		return (ret);
1369a6d42e7dSPeter Dunlap 	}
1370a6d42e7dSPeter Dunlap 
1371a6d42e7dSPeter Dunlap 	/*
1372a6d42e7dSPeter Dunlap 	 * Add the remaining portals
1373a6d42e7dSPeter Dunlap 	 */
1374a6d42e7dSPeter Dunlap 	for (count = 1; count < addrc; count++) {
1375a6d42e7dSPeter Dunlap 		if (!addrs[count]) {
1376a6d42e7dSPeter Dunlap 			continue;
1377a6d42e7dSPeter Dunlap 		}
1378a6d42e7dSPeter Dunlap 
1379a6d42e7dSPeter Dunlap 		ret = it_portal_create(cfg, tpgp, &ptl, addrs[count]);
1380a6d42e7dSPeter Dunlap 		if (ret != 0) {
1381a6d42e7dSPeter Dunlap 			if (ret == EEXIST) {
1382a6d42e7dSPeter Dunlap 				(void) fprintf(stderr,
1383a6d42e7dSPeter Dunlap 				    gettext("Portal %s already in use"),
1384a6d42e7dSPeter Dunlap 				    addrs[count]);
1385a6d42e7dSPeter Dunlap 				(void) fprintf(stderr, "\n");
1386a6d42e7dSPeter Dunlap 			} else {
1387a6d42e7dSPeter Dunlap 				(void) fprintf(stderr,
1388a6d42e7dSPeter Dunlap 				    gettext("Error adding portal %s: %d"),
1389a6d42e7dSPeter Dunlap 				    addrs[count], ret);
1390a6d42e7dSPeter Dunlap 				(void) fprintf(stderr, "\n");
1391a6d42e7dSPeter Dunlap 				break;
1392a6d42e7dSPeter Dunlap 			}
1393a6d42e7dSPeter Dunlap 		}
1394a6d42e7dSPeter Dunlap 	}
1395a6d42e7dSPeter Dunlap 
1396a6d42e7dSPeter Dunlap 	if (ret == 0) {
1397a6d42e7dSPeter Dunlap 		ret = it_config_commit(cfg);
1398a6d42e7dSPeter Dunlap 		STMF_STALE(ret);
1399a6d42e7dSPeter Dunlap 	}
1400a6d42e7dSPeter Dunlap 
1401a6d42e7dSPeter Dunlap 	it_config_free(cfg);
1402a6d42e7dSPeter Dunlap 
1403a6d42e7dSPeter Dunlap 	return (ret);
1404a6d42e7dSPeter Dunlap }
1405a6d42e7dSPeter Dunlap 
1406a6d42e7dSPeter Dunlap static int
1407a6d42e7dSPeter Dunlap list_tpg(char *tpg, boolean_t verbose, boolean_t script)
1408a6d42e7dSPeter Dunlap {
1409a6d42e7dSPeter Dunlap 	int		ret;
1410a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
1411a6d42e7dSPeter Dunlap 	it_tpg_t	*ptr;
1412a6d42e7dSPeter Dunlap 	boolean_t	found = B_FALSE;
1413a6d42e7dSPeter Dunlap 	it_portal_t	*portal;
1414a6d42e7dSPeter Dunlap 	boolean_t	first = B_TRUE;
1415a6d42e7dSPeter Dunlap 	boolean_t	first_portal;
1416a6d42e7dSPeter Dunlap 	char		*pstr;
1417a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.read.stmf";
1418a6d42e7dSPeter Dunlap 
1419a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1420a6d42e7dSPeter Dunlap 
1421a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1422a6d42e7dSPeter Dunlap 	if (ret != 0) {
1423a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1424a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1425a6d42e7dSPeter Dunlap 		    ret);
1426a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1427a6d42e7dSPeter Dunlap 		return (ret);
1428a6d42e7dSPeter Dunlap 	}
1429a6d42e7dSPeter Dunlap 
1430a6d42e7dSPeter Dunlap 	ptr = cfg->config_tpg_list;
1431a6d42e7dSPeter Dunlap 
1432a6d42e7dSPeter Dunlap 	for (; ptr != NULL; ptr = ptr->tpg_next) {
1433a6d42e7dSPeter Dunlap 		if (found) {
1434a6d42e7dSPeter Dunlap 			break;
1435a6d42e7dSPeter Dunlap 		}
1436a6d42e7dSPeter Dunlap 
1437a6d42e7dSPeter Dunlap 		if (tpg) {
1438a6d42e7dSPeter Dunlap 			if (strcmp(tpg, ptr->tpg_name) != 0) {
1439a6d42e7dSPeter Dunlap 				continue;
1440a6d42e7dSPeter Dunlap 			} else {
1441a6d42e7dSPeter Dunlap 				found = B_TRUE;
1442a6d42e7dSPeter Dunlap 			}
1443a6d42e7dSPeter Dunlap 		}
1444a6d42e7dSPeter Dunlap 
1445a6d42e7dSPeter Dunlap 		if (!script && first) {
1446a6d42e7dSPeter Dunlap 			(void) printf("%-30s%-9s\n", "TARGET PORTAL GROUP",
1447a6d42e7dSPeter Dunlap 			    "PORTAL COUNT");
1448a6d42e7dSPeter Dunlap 			first = B_FALSE;
1449a6d42e7dSPeter Dunlap 		}
1450a6d42e7dSPeter Dunlap 
1451a6d42e7dSPeter Dunlap 		if (!script) {
1452a6d42e7dSPeter Dunlap 			(void) printf("%-30s", ptr->tpg_name);
1453a6d42e7dSPeter Dunlap 			if (strlen(ptr->tpg_name) > 30) {
1454a6d42e7dSPeter Dunlap 				(void) printf("\t");
1455a6d42e7dSPeter Dunlap 			}
1456a6d42e7dSPeter Dunlap 			(void) printf("%-9d", ptr->tpg_portal_count);
1457a6d42e7dSPeter Dunlap 		} else {
1458a6d42e7dSPeter Dunlap 			(void) printf("%s\t%d", ptr->tpg_name,
1459a6d42e7dSPeter Dunlap 			    ptr->tpg_portal_count);
1460a6d42e7dSPeter Dunlap 		}
1461a6d42e7dSPeter Dunlap 
1462a6d42e7dSPeter Dunlap 		if (!verbose) {
1463a6d42e7dSPeter Dunlap 			(void) printf("\n");
1464a6d42e7dSPeter Dunlap 			continue;
1465a6d42e7dSPeter Dunlap 		}
1466a6d42e7dSPeter Dunlap 
1467a6d42e7dSPeter Dunlap 		if (!script) {
1468a6d42e7dSPeter Dunlap 			(void) printf("\n    portals:");
1469a6d42e7dSPeter Dunlap 		}
1470a6d42e7dSPeter Dunlap 
1471a6d42e7dSPeter Dunlap 		first_portal = B_TRUE;
1472a6d42e7dSPeter Dunlap 
1473a6d42e7dSPeter Dunlap 		portal = ptr->tpg_portal_list;
1474a6d42e7dSPeter Dunlap 		for (; portal != NULL; portal = portal->next) {
1475a6d42e7dSPeter Dunlap 			ret = sockaddr_to_str(&(portal->portal_addr), &pstr);
1476a6d42e7dSPeter Dunlap 			if (ret != 0) {
1477a6d42e7dSPeter Dunlap 				/* invalid addr? */
1478a6d42e7dSPeter Dunlap 				continue;
1479a6d42e7dSPeter Dunlap 			}
1480a6d42e7dSPeter Dunlap 			if (!first_portal) {
1481a6d42e7dSPeter Dunlap 				(void) printf(",");
1482a6d42e7dSPeter Dunlap 			} else {
1483a6d42e7dSPeter Dunlap 				(void) printf("\t");
1484a6d42e7dSPeter Dunlap 				first_portal = B_FALSE;
1485a6d42e7dSPeter Dunlap 			}
1486a6d42e7dSPeter Dunlap 
1487a6d42e7dSPeter Dunlap 			(void) printf("%s", pstr);
1488a6d42e7dSPeter Dunlap 			free(pstr);
1489a6d42e7dSPeter Dunlap 		}
1490a6d42e7dSPeter Dunlap 
1491a6d42e7dSPeter Dunlap 		if (first_portal) {
1492a6d42e7dSPeter Dunlap 			/* none found */
1493a6d42e7dSPeter Dunlap 			(void) printf("\t<none>");
1494a6d42e7dSPeter Dunlap 		}
1495a6d42e7dSPeter Dunlap 
1496a6d42e7dSPeter Dunlap 		(void) printf("\n");
1497a6d42e7dSPeter Dunlap 	}
1498a6d42e7dSPeter Dunlap 
1499a6d42e7dSPeter Dunlap 	if (tpg && (!found)) {
1500a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1501a6d42e7dSPeter Dunlap 		    gettext("Target Portal Group %s not found!\n"), tpg);
1502a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1503a6d42e7dSPeter Dunlap 		ret = 1;
1504a6d42e7dSPeter Dunlap 	}
1505a6d42e7dSPeter Dunlap 
1506a6d42e7dSPeter Dunlap 	it_config_free(cfg);
1507a6d42e7dSPeter Dunlap 
1508a6d42e7dSPeter Dunlap 	return (ret);
1509a6d42e7dSPeter Dunlap }
1510a6d42e7dSPeter Dunlap 
1511a6d42e7dSPeter Dunlap static int
1512a6d42e7dSPeter Dunlap delete_tpg(char *tpg, boolean_t force)
1513a6d42e7dSPeter Dunlap {
1514a6d42e7dSPeter Dunlap 	int		ret;
1515a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
1516a6d42e7dSPeter Dunlap 	it_tpg_t	*ptpg = NULL;
1517a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.modify.stmf";
1518a6d42e7dSPeter Dunlap 
1519a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1520a6d42e7dSPeter Dunlap 
1521a6d42e7dSPeter Dunlap 	if (!tpg) {
1522a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
1523a6d42e7dSPeter Dunlap 		    gettext("Error, no target portal group specified"));
1524a6d42e7dSPeter Dunlap 		return (EINVAL);
1525a6d42e7dSPeter Dunlap 	}
1526a6d42e7dSPeter Dunlap 
1527a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1528a6d42e7dSPeter Dunlap 	if (ret != 0) {
1529a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1530a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1531a6d42e7dSPeter Dunlap 		    ret);
1532a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1533a6d42e7dSPeter Dunlap 		return (ret);
1534a6d42e7dSPeter Dunlap 	}
1535a6d42e7dSPeter Dunlap 
1536a6d42e7dSPeter Dunlap 	ptpg = cfg->config_tpg_list;
1537a6d42e7dSPeter Dunlap 	for (; ptpg != NULL; ptpg = ptpg->tpg_next) {
1538a6d42e7dSPeter Dunlap 		if (strcmp(tpg, ptpg->tpg_name) == 0) {
1539a6d42e7dSPeter Dunlap 			break;
1540a6d42e7dSPeter Dunlap 		}
1541a6d42e7dSPeter Dunlap 	}
1542a6d42e7dSPeter Dunlap 
1543a6d42e7dSPeter Dunlap 	if (!ptpg) {
1544a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1545a6d42e7dSPeter Dunlap 		    gettext("Target portal group %s does not exist."),
1546a6d42e7dSPeter Dunlap 		    tpg);
1547a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1548a6d42e7dSPeter Dunlap 		ret = 1;
1549a6d42e7dSPeter Dunlap 	} else {
1550a6d42e7dSPeter Dunlap 		ret = it_tpg_delete(cfg, ptpg, force);
1551a6d42e7dSPeter Dunlap 		if (ret == EBUSY) {
1552a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "%s\n",
1553a6d42e7dSPeter Dunlap 			    gettext(
1554a6d42e7dSPeter Dunlap 			    "Target portal group associated with one or more "
1555a6d42e7dSPeter Dunlap 			    "targets.  Cannot delete."));
1556a6d42e7dSPeter Dunlap 		}
1557a6d42e7dSPeter Dunlap 
1558a6d42e7dSPeter Dunlap 		if (ret == 0) {
1559a6d42e7dSPeter Dunlap 			ret = it_config_commit(cfg);
1560a6d42e7dSPeter Dunlap 			STMF_STALE(ret);
1561a6d42e7dSPeter Dunlap 		}
1562a6d42e7dSPeter Dunlap 	}
1563a6d42e7dSPeter Dunlap 
1564a6d42e7dSPeter Dunlap 	it_config_free(cfg);
1565a6d42e7dSPeter Dunlap 
1566a6d42e7dSPeter Dunlap 	return (ret);
1567a6d42e7dSPeter Dunlap }
1568a6d42e7dSPeter Dunlap 
1569a6d42e7dSPeter Dunlap static int
1570a6d42e7dSPeter Dunlap modify_initiator(char *ini, nvlist_t *proplist, boolean_t create)
1571a6d42e7dSPeter Dunlap {
1572a6d42e7dSPeter Dunlap 	int		ret;
1573a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
1574a6d42e7dSPeter Dunlap 	it_ini_t	*inip;
1575a6d42e7dSPeter Dunlap 	nvlist_t	*errlist = NULL;
1576a6d42e7dSPeter Dunlap 	nvpair_t	*nvp = NULL;
1577a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.modify.stmf";
1578a6d42e7dSPeter Dunlap 	boolean_t	changed = B_TRUE;
1579a6d42e7dSPeter Dunlap 
1580a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1581a6d42e7dSPeter Dunlap 
1582a6d42e7dSPeter Dunlap 	if (!ini) {
1583a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
1584a6d42e7dSPeter Dunlap 		    gettext("Error, no initiator specified"));
1585a6d42e7dSPeter Dunlap 		return (EINVAL);
1586a6d42e7dSPeter Dunlap 	} else if (create) {
1587a6d42e7dSPeter Dunlap 		/*
1588a6d42e7dSPeter Dunlap 		 * validate input name - what are the rules for EUI
1589a6d42e7dSPeter Dunlap 		 * and IQN values?
1590a6d42e7dSPeter Dunlap 		 */
1591a6d42e7dSPeter Dunlap 		if ((strncmp(ini, "eui.", 4) != 0) &&
1592a6d42e7dSPeter Dunlap 		    (strncmp(ini, "iqn.", 4) != 0)) {
1593a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, gettext("Invalid name %s"),
1594a6d42e7dSPeter Dunlap 			    ini);
1595a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
1596a6d42e7dSPeter Dunlap 			return (EINVAL);
1597a6d42e7dSPeter Dunlap 		}
1598a6d42e7dSPeter Dunlap 	}
1599a6d42e7dSPeter Dunlap 
1600a6d42e7dSPeter Dunlap 	/*
1601a6d42e7dSPeter Dunlap 	 * See if any properties were actually specified.
1602a6d42e7dSPeter Dunlap 	 */
1603a6d42e7dSPeter Dunlap 	if (proplist) {
1604a6d42e7dSPeter Dunlap 		nvp = nvlist_next_nvpair(proplist, nvp);
1605a6d42e7dSPeter Dunlap 	}
1606a6d42e7dSPeter Dunlap 
1607a6d42e7dSPeter Dunlap 	if ((nvp == NULL) && !create) {
1608a6d42e7dSPeter Dunlap 		changed = B_FALSE;
1609a6d42e7dSPeter Dunlap 	}
1610a6d42e7dSPeter Dunlap 
1611a6d42e7dSPeter Dunlap 	/*
1612a6d42e7dSPeter Dunlap 	 * If no properties, and this is really a modify op, verify
1613a6d42e7dSPeter Dunlap 	 * that the requested initiator exists, but then don't do anything.
1614a6d42e7dSPeter Dunlap 	 * Modifying non-existent is an error; doing nothing to a defined
1615a6d42e7dSPeter Dunlap 	 * initiator is not.
1616a6d42e7dSPeter Dunlap 	 */
1617a6d42e7dSPeter Dunlap 
1618a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1619a6d42e7dSPeter Dunlap 	if (ret != 0) {
1620a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1621a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1622a6d42e7dSPeter Dunlap 		    ret);
1623a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1624a6d42e7dSPeter Dunlap 		return (ret);
1625a6d42e7dSPeter Dunlap 	}
1626a6d42e7dSPeter Dunlap 
1627a6d42e7dSPeter Dunlap 	inip = cfg->config_ini_list;
1628a6d42e7dSPeter Dunlap 	while (inip) {
1629a6d42e7dSPeter Dunlap 		if (strcmp(inip->ini_name, ini) == 0) {
1630a6d42e7dSPeter Dunlap 			break;
1631a6d42e7dSPeter Dunlap 		}
1632a6d42e7dSPeter Dunlap 
1633a6d42e7dSPeter Dunlap 		inip = inip->ini_next;
1634a6d42e7dSPeter Dunlap 	}
1635a6d42e7dSPeter Dunlap 
1636a6d42e7dSPeter Dunlap 	if (create) {
1637a6d42e7dSPeter Dunlap 		if (inip) {
1638a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
1639a6d42e7dSPeter Dunlap 			    gettext("Initiator %s already exists"),
1640a6d42e7dSPeter Dunlap 			    inip->ini_name);
1641a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
1642a6d42e7dSPeter Dunlap 			ret = EINVAL;
1643a6d42e7dSPeter Dunlap 		} else {
1644a6d42e7dSPeter Dunlap 			ret = it_ini_create(cfg, &inip, ini);
1645a6d42e7dSPeter Dunlap 			if (ret != 0) {
1646a6d42e7dSPeter Dunlap 				if (ret == EFAULT) {
1647a6d42e7dSPeter Dunlap 					(void) fprintf(stderr,
1648a6d42e7dSPeter Dunlap 					    gettext("Invalid iSCSI name %s"),
1649a6d42e7dSPeter Dunlap 					    ini);
1650a6d42e7dSPeter Dunlap 				} else {
1651a6d42e7dSPeter Dunlap 					(void) fprintf(stderr,
1652a6d42e7dSPeter Dunlap 					    gettext(
1653a6d42e7dSPeter Dunlap 					    "Error creating initiator: %d"),
1654a6d42e7dSPeter Dunlap 					    ret);
1655a6d42e7dSPeter Dunlap 				}
1656a6d42e7dSPeter Dunlap 				(void) fprintf(stderr, "\n");
1657a6d42e7dSPeter Dunlap 			}
1658a6d42e7dSPeter Dunlap 		}
1659a6d42e7dSPeter Dunlap 	} else if (!inip) {
1660a6d42e7dSPeter Dunlap 		ret = ENOENT;
1661a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1662a6d42e7dSPeter Dunlap 		    gettext("Error, initiator %s not found."),
1663a6d42e7dSPeter Dunlap 		    ini);
1664a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1665a6d42e7dSPeter Dunlap 	}
1666a6d42e7dSPeter Dunlap 
1667a6d42e7dSPeter Dunlap 	if ((ret == 0) && nvp) {
1668a6d42e7dSPeter Dunlap 		ret = it_ini_setprop(inip, proplist, &errlist);
1669a6d42e7dSPeter Dunlap 
1670a6d42e7dSPeter Dunlap 		if (ret != 0) {
1671a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
1672a6d42e7dSPeter Dunlap 			    gettext("Error setting initiator properties: %d"),
1673a6d42e7dSPeter Dunlap 			    ret);
1674a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
1675a6d42e7dSPeter Dunlap 			if (errlist) {
1676a6d42e7dSPeter Dunlap 				nvpair_t	*nvp = NULL;
1677a6d42e7dSPeter Dunlap 				char		*nn;
1678a6d42e7dSPeter Dunlap 				char		*nv;
1679a6d42e7dSPeter Dunlap 
1680a6d42e7dSPeter Dunlap 				while ((nvp = nvlist_next_nvpair(errlist, nvp))
1681a6d42e7dSPeter Dunlap 				    != NULL) {
1682a6d42e7dSPeter Dunlap 					nv = NULL;
1683a6d42e7dSPeter Dunlap 
1684a6d42e7dSPeter Dunlap 					nn = nvpair_name(nvp);
1685a6d42e7dSPeter Dunlap 					(void) nvpair_value_string(nvp, &nv);
1686a6d42e7dSPeter Dunlap 
1687a6d42e7dSPeter Dunlap 					if (nv != NULL) {
1688a6d42e7dSPeter Dunlap 						(void) fprintf(stderr,
1689a6d42e7dSPeter Dunlap 						    "\t%s: %s\n", nn, nv);
1690a6d42e7dSPeter Dunlap 					}
1691a6d42e7dSPeter Dunlap 				}
1692a6d42e7dSPeter Dunlap 
1693a6d42e7dSPeter Dunlap 				nvlist_free(errlist);
1694a6d42e7dSPeter Dunlap 			}
1695a6d42e7dSPeter Dunlap 		}
1696a6d42e7dSPeter Dunlap 	}
1697a6d42e7dSPeter Dunlap 
1698a6d42e7dSPeter Dunlap 	if ((ret == 0) && changed) {
1699a6d42e7dSPeter Dunlap 		ret = it_config_commit(cfg);
1700a6d42e7dSPeter Dunlap 		STMF_STALE(ret);
1701a6d42e7dSPeter Dunlap 	}
1702a6d42e7dSPeter Dunlap 
1703a6d42e7dSPeter Dunlap 	it_config_free(cfg);
1704a6d42e7dSPeter Dunlap 
1705a6d42e7dSPeter Dunlap 	return (ret);
1706a6d42e7dSPeter Dunlap }
1707a6d42e7dSPeter Dunlap 
1708a6d42e7dSPeter Dunlap static int
1709a6d42e7dSPeter Dunlap list_initiator(char *ini, boolean_t verbose, boolean_t script) /* ARGSUSED */
1710a6d42e7dSPeter Dunlap {
1711a6d42e7dSPeter Dunlap 	int		ret;
1712a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
1713a6d42e7dSPeter Dunlap 	it_ini_t	*ptr;
1714a6d42e7dSPeter Dunlap 	boolean_t	found = B_FALSE;
1715a6d42e7dSPeter Dunlap 	boolean_t	first = B_TRUE;
1716a6d42e7dSPeter Dunlap 	char		*isecret;
1717a6d42e7dSPeter Dunlap 	char		*iuser;
1718a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.read.stmf";
1719a6d42e7dSPeter Dunlap 
1720a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1721a6d42e7dSPeter Dunlap 
1722a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1723a6d42e7dSPeter Dunlap 	if (ret != 0) {
1724a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1725a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1726a6d42e7dSPeter Dunlap 		    ret);
1727a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1728a6d42e7dSPeter Dunlap 		return (ret);
1729a6d42e7dSPeter Dunlap 	}
1730a6d42e7dSPeter Dunlap 
1731a6d42e7dSPeter Dunlap 	ptr = cfg->config_ini_list;
1732a6d42e7dSPeter Dunlap 
1733a6d42e7dSPeter Dunlap 	for (; ptr != NULL; ptr = ptr->ini_next) {
1734a6d42e7dSPeter Dunlap 		isecret = "unset";
1735a6d42e7dSPeter Dunlap 		iuser = "<none>";
1736a6d42e7dSPeter Dunlap 
1737a6d42e7dSPeter Dunlap 		if (found) {
1738a6d42e7dSPeter Dunlap 			break;
1739a6d42e7dSPeter Dunlap 		}
1740a6d42e7dSPeter Dunlap 
1741a6d42e7dSPeter Dunlap 		if (ini) {
1742a6d42e7dSPeter Dunlap 			if (strcmp(ini, ptr->ini_name) != 0) {
1743a6d42e7dSPeter Dunlap 				continue;
1744a6d42e7dSPeter Dunlap 			} else {
1745a6d42e7dSPeter Dunlap 				found = B_TRUE;
1746a6d42e7dSPeter Dunlap 			}
1747a6d42e7dSPeter Dunlap 		}
1748a6d42e7dSPeter Dunlap 
1749a6d42e7dSPeter Dunlap 		if (ptr->ini_properties) {
1750a6d42e7dSPeter Dunlap 			if (nvlist_exists(ptr->ini_properties, "chapsecret")) {
1751a6d42e7dSPeter Dunlap 				isecret = "set";
1752a6d42e7dSPeter Dunlap 			}
1753a6d42e7dSPeter Dunlap 			(void) nvlist_lookup_string(ptr->ini_properties,
1754a6d42e7dSPeter Dunlap 			    "chapuser", &iuser);
1755a6d42e7dSPeter Dunlap 
1756a6d42e7dSPeter Dunlap 		}
1757a6d42e7dSPeter Dunlap 
1758a6d42e7dSPeter Dunlap 		/* there's nothing to print for verbose yet */
1759a6d42e7dSPeter Dunlap 		if (!script && first) {
1760a6d42e7dSPeter Dunlap 			(void) printf("%-61s%-10s%-7s\n", "INITIATOR NAME",
1761a6d42e7dSPeter Dunlap 			    "CHAPUSER", "SECRET");
1762a6d42e7dSPeter Dunlap 			first = B_FALSE;
1763a6d42e7dSPeter Dunlap 		}
1764a6d42e7dSPeter Dunlap 
1765a6d42e7dSPeter Dunlap 		if (!script) {
1766a6d42e7dSPeter Dunlap 			/*
1767a6d42e7dSPeter Dunlap 			 * try not to let columns run into each other.
1768a6d42e7dSPeter Dunlap 			 * Stick a tab after too-long fields.
1769a6d42e7dSPeter Dunlap 			 * Lengths chosen are for the 'common' cases.
1770a6d42e7dSPeter Dunlap 			 */
1771a6d42e7dSPeter Dunlap 			(void) printf("%-61s", ptr->ini_name);
1772a6d42e7dSPeter Dunlap 
1773a6d42e7dSPeter Dunlap 			if (strlen(ptr->ini_name) > 60) {
1774a6d42e7dSPeter Dunlap 				(void) printf("\t");
1775a6d42e7dSPeter Dunlap 			}
1776a6d42e7dSPeter Dunlap 
1777a6d42e7dSPeter Dunlap 			(void) printf("%-15s", iuser);
1778a6d42e7dSPeter Dunlap 			if (strlen(iuser) >= 15) {
1779a6d42e7dSPeter Dunlap 				(void) printf("\t");
1780a6d42e7dSPeter Dunlap 			}
1781a6d42e7dSPeter Dunlap 
1782a6d42e7dSPeter Dunlap 			(void) printf("%-4s", isecret);
1783a6d42e7dSPeter Dunlap 		} else {
1784a6d42e7dSPeter Dunlap 			(void) printf("%s\t%s\t%s", ptr->ini_name,
1785a6d42e7dSPeter Dunlap 			    iuser, isecret);
1786a6d42e7dSPeter Dunlap 		}
1787a6d42e7dSPeter Dunlap 
1788a6d42e7dSPeter Dunlap 		(void) printf("\n");
1789a6d42e7dSPeter Dunlap 	}
1790a6d42e7dSPeter Dunlap 
1791a6d42e7dSPeter Dunlap 	if (ini && (!found)) {
1792a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1793a6d42e7dSPeter Dunlap 		    gettext("Initiator %s not found!"), ini);
1794a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1795a6d42e7dSPeter Dunlap 		ret = 1;
1796a6d42e7dSPeter Dunlap 	}
1797a6d42e7dSPeter Dunlap 
1798a6d42e7dSPeter Dunlap 	it_config_free(cfg);
1799a6d42e7dSPeter Dunlap 
1800a6d42e7dSPeter Dunlap 	return (ret);
1801a6d42e7dSPeter Dunlap }
1802a6d42e7dSPeter Dunlap 
1803a6d42e7dSPeter Dunlap int
1804a6d42e7dSPeter Dunlap delete_initiator(char *ini)
1805a6d42e7dSPeter Dunlap {
1806a6d42e7dSPeter Dunlap 	int		ret;
1807a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
1808a6d42e7dSPeter Dunlap 	it_ini_t	*ptr;
1809a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.modify.stmf";
1810a6d42e7dSPeter Dunlap 
1811a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1812a6d42e7dSPeter Dunlap 
1813a6d42e7dSPeter Dunlap 	if (!ini) {
1814a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
1815a6d42e7dSPeter Dunlap 		    gettext("Error, no initiator specified"));
1816a6d42e7dSPeter Dunlap 		return (EINVAL);
1817a6d42e7dSPeter Dunlap 	}
1818a6d42e7dSPeter Dunlap 
1819a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1820a6d42e7dSPeter Dunlap 	if (ret != 0) {
1821a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1822a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1823a6d42e7dSPeter Dunlap 		    ret);
1824a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1825a6d42e7dSPeter Dunlap 		return (ret);
1826a6d42e7dSPeter Dunlap 	}
1827a6d42e7dSPeter Dunlap 
1828a6d42e7dSPeter Dunlap 	ptr = cfg->config_ini_list;
1829a6d42e7dSPeter Dunlap 	while (ptr) {
1830a6d42e7dSPeter Dunlap 		if (strcmp(ptr->ini_name, ini) == 0) {
1831a6d42e7dSPeter Dunlap 			break;
1832a6d42e7dSPeter Dunlap 		}
1833a6d42e7dSPeter Dunlap 
1834a6d42e7dSPeter Dunlap 		ptr = ptr->ini_next;
1835a6d42e7dSPeter Dunlap 	}
1836a6d42e7dSPeter Dunlap 
1837a6d42e7dSPeter Dunlap 	if (ptr) {
1838a6d42e7dSPeter Dunlap 		it_ini_delete(cfg, ptr);
1839a6d42e7dSPeter Dunlap 
1840a6d42e7dSPeter Dunlap 		ret = it_config_commit(cfg);
1841a6d42e7dSPeter Dunlap 		STMF_STALE(ret);
1842a6d42e7dSPeter Dunlap 	} else {
1843a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1844a6d42e7dSPeter Dunlap 		    gettext("Initiator %s not found"), ini);
1845a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1846a6d42e7dSPeter Dunlap 		ret = 1;
1847a6d42e7dSPeter Dunlap 	}
1848a6d42e7dSPeter Dunlap 
1849a6d42e7dSPeter Dunlap 	return (ret);
1850a6d42e7dSPeter Dunlap }
1851a6d42e7dSPeter Dunlap 
1852a6d42e7dSPeter Dunlap static int
1853a6d42e7dSPeter Dunlap modify_defaults(nvlist_t *proplist)
1854a6d42e7dSPeter Dunlap {
1855a6d42e7dSPeter Dunlap 	int		ret;
1856a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
1857a6d42e7dSPeter Dunlap 	nvlist_t	*errlist = NULL;
1858a6d42e7dSPeter Dunlap 	nvpair_t	*nvp = NULL;
1859a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.modify.stmf";
1860a6d42e7dSPeter Dunlap 
1861a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1862a6d42e7dSPeter Dunlap 
1863a6d42e7dSPeter Dunlap 	if (proplist) {
1864a6d42e7dSPeter Dunlap 		/* make sure at least one property is specified */
1865a6d42e7dSPeter Dunlap 		nvp = nvlist_next_nvpair(proplist, nvp);
1866a6d42e7dSPeter Dunlap 	}
1867a6d42e7dSPeter Dunlap 
1868a6d42e7dSPeter Dunlap 	if (nvp == NULL) {
1869a6d42e7dSPeter Dunlap 		/* empty list */
1870a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "%s\n",
1871a6d42e7dSPeter Dunlap 		    gettext("Error, no properties specified"));
1872a6d42e7dSPeter Dunlap 		return (EINVAL);
1873a6d42e7dSPeter Dunlap 	}
1874a6d42e7dSPeter Dunlap 
1875a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1876a6d42e7dSPeter Dunlap 	if (ret != 0) {
1877a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1878a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1879a6d42e7dSPeter Dunlap 		    ret);
1880a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1881a6d42e7dSPeter Dunlap 		return (ret);
1882a6d42e7dSPeter Dunlap 	}
1883a6d42e7dSPeter Dunlap 
1884a6d42e7dSPeter Dunlap 	ret = it_config_setprop(cfg, proplist, &errlist);
1885a6d42e7dSPeter Dunlap 	if (ret != 0) {
1886a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1887a6d42e7dSPeter Dunlap 		    gettext("Error setting global properties: %d"),
1888a6d42e7dSPeter Dunlap 		    ret);
1889a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1890a6d42e7dSPeter Dunlap 		if (errlist) {
1891a6d42e7dSPeter Dunlap 			nvpair_t	*nvp = NULL;
1892a6d42e7dSPeter Dunlap 			char		*nn;
1893a6d42e7dSPeter Dunlap 			char		*nv;
1894a6d42e7dSPeter Dunlap 
1895a6d42e7dSPeter Dunlap 			while ((nvp = nvlist_next_nvpair(errlist, nvp))
1896a6d42e7dSPeter Dunlap 			    != NULL) {
1897a6d42e7dSPeter Dunlap 				nv = NULL;
1898a6d42e7dSPeter Dunlap 
1899a6d42e7dSPeter Dunlap 				nn = nvpair_name(nvp);
1900a6d42e7dSPeter Dunlap 				(void) nvpair_value_string(nvp, &nv);
1901a6d42e7dSPeter Dunlap 
1902a6d42e7dSPeter Dunlap 				if (nv != NULL) {
1903a6d42e7dSPeter Dunlap 					(void) fprintf(stderr, "\t%s: %s\n",
1904a6d42e7dSPeter Dunlap 					    nn, nv);
1905a6d42e7dSPeter Dunlap 				}
1906a6d42e7dSPeter Dunlap 			}
1907a6d42e7dSPeter Dunlap 
1908a6d42e7dSPeter Dunlap 			nvlist_free(errlist);
1909a6d42e7dSPeter Dunlap 		}
1910a6d42e7dSPeter Dunlap 	}
1911a6d42e7dSPeter Dunlap 
1912a6d42e7dSPeter Dunlap 	if (ret == 0) {
1913a6d42e7dSPeter Dunlap 		ret = it_config_commit(cfg);
1914a6d42e7dSPeter Dunlap 		STMF_STALE(ret);
1915a6d42e7dSPeter Dunlap 	}
1916a6d42e7dSPeter Dunlap 
1917a6d42e7dSPeter Dunlap 	it_config_free(cfg);
1918a6d42e7dSPeter Dunlap 
1919a6d42e7dSPeter Dunlap 	return (ret);
1920a6d42e7dSPeter Dunlap }
1921a6d42e7dSPeter Dunlap 
1922a6d42e7dSPeter Dunlap static int
1923a6d42e7dSPeter Dunlap list_defaults(boolean_t script)
1924a6d42e7dSPeter Dunlap {
1925a6d42e7dSPeter Dunlap 	int		ret;
1926a6d42e7dSPeter Dunlap 	it_config_t	*cfg;
1927a6d42e7dSPeter Dunlap 	nvlist_t	*nvl;
1928a6d42e7dSPeter Dunlap 	char		*alias = "<none>";
1929a6d42e7dSPeter Dunlap 	char		*auth = "<none>";
1930a6d42e7dSPeter Dunlap 	char		*isns = "disabled";
1931a6d42e7dSPeter Dunlap 	char		**isvrs = NULL;
1932a6d42e7dSPeter Dunlap 	uint32_t	scount = 0;
1933a6d42e7dSPeter Dunlap 	char		*rsvr = "<none>";
1934a6d42e7dSPeter Dunlap 	char		*rsecret = "unset";
1935a6d42e7dSPeter Dunlap 	boolean_t	val = B_FALSE;
1936a6d42e7dSPeter Dunlap 	int		i;
1937a6d42e7dSPeter Dunlap 	char		*sec = "solaris.smf.read.stmf";
1938a6d42e7dSPeter Dunlap 
1939a6d42e7dSPeter Dunlap 	ITADM_CHKAUTH(sec);
1940a6d42e7dSPeter Dunlap 
1941a6d42e7dSPeter Dunlap 	ret = it_config_load(&cfg);
1942a6d42e7dSPeter Dunlap 	if (ret != 0) {
1943a6d42e7dSPeter Dunlap 		(void) fprintf(stderr,
1944a6d42e7dSPeter Dunlap 		    gettext("Error retrieving iSCSI target configuration: %d"),
1945a6d42e7dSPeter Dunlap 		    ret);
1946a6d42e7dSPeter Dunlap 		(void) fprintf(stderr, "\n");
1947a6d42e7dSPeter Dunlap 		return (ret);
1948a6d42e7dSPeter Dunlap 	}
1949a6d42e7dSPeter Dunlap 
1950a6d42e7dSPeter Dunlap 	nvl = cfg->config_global_properties;
1951a6d42e7dSPeter Dunlap 
1952a6d42e7dSPeter Dunlap 	/* look up all possible options */
1953a6d42e7dSPeter Dunlap 	(void) nvlist_lookup_string(nvl, "alias", &alias);
1954a6d42e7dSPeter Dunlap 	(void) nvlist_lookup_string(nvl, "auth", &auth);
1955a6d42e7dSPeter Dunlap 	(void) nvlist_lookup_boolean_value(nvl, "isns", &val);
1956a6d42e7dSPeter Dunlap 	if (val == B_TRUE) {
1957a6d42e7dSPeter Dunlap 		isns = "enabled";
1958a6d42e7dSPeter Dunlap 	}
1959a6d42e7dSPeter Dunlap 	(void) nvlist_lookup_string_array(nvl, "isnsserver", &isvrs,
1960a6d42e7dSPeter Dunlap 	    &scount);
1961a6d42e7dSPeter Dunlap 	(void) nvlist_lookup_string(nvl, "radiusserver", &rsvr);
1962a6d42e7dSPeter Dunlap 	if (nvlist_exists(nvl, "radiussecret")) {
1963a6d42e7dSPeter Dunlap 		rsecret = "set";
1964a6d42e7dSPeter Dunlap 	}
1965a6d42e7dSPeter Dunlap 
1966a6d42e7dSPeter Dunlap 	if (!script) {
1967a6d42e7dSPeter Dunlap 		(void) printf("%s:\n\n",
1968a6d42e7dSPeter Dunlap 		    gettext("iSCSI Target Default Properties"));
1969a6d42e7dSPeter Dunlap 	}
1970a6d42e7dSPeter Dunlap 
1971a6d42e7dSPeter Dunlap 	if (script) {
1972a6d42e7dSPeter Dunlap 		(void) printf("%s\t%s\t%s\t%s\t%s\t",
1973a6d42e7dSPeter Dunlap 		    alias, auth, rsvr, rsecret, isns);
1974a6d42e7dSPeter Dunlap 	} else {
1975a6d42e7dSPeter Dunlap 		(void) printf("%-15s\t%s\n%-15s\t%s\n%-15s\t%s\n%-15s\t%s\n"
1976a6d42e7dSPeter Dunlap 		    "%-15s\t%s\n%-15s\t",
1977a6d42e7dSPeter Dunlap 		    "alias:", alias, "auth:", auth, "radiusserver:",
1978a6d42e7dSPeter Dunlap 		    rsvr, "radiussecret:", rsecret, "isns:", isns,
1979a6d42e7dSPeter Dunlap 		    "isnsserver:");
1980a6d42e7dSPeter Dunlap 	}
1981a6d42e7dSPeter Dunlap 
1982a6d42e7dSPeter Dunlap 	for (i = 0; i < scount; i++) {
1983a6d42e7dSPeter Dunlap 		if (!isvrs || !isvrs[i]) {
1984a6d42e7dSPeter Dunlap 			break;
1985a6d42e7dSPeter Dunlap 		}
1986a6d42e7dSPeter Dunlap 		if (i > 0) {
1987a6d42e7dSPeter Dunlap 			(void) printf(",");
1988a6d42e7dSPeter Dunlap 		}
1989a6d42e7dSPeter Dunlap 		(void) printf("%s", isvrs[i]);
1990a6d42e7dSPeter Dunlap 	}
1991a6d42e7dSPeter Dunlap 
1992a6d42e7dSPeter Dunlap 	if (i == 0) {
1993a6d42e7dSPeter Dunlap 		(void) printf("%s", "<none>");
1994a6d42e7dSPeter Dunlap 	}
1995a6d42e7dSPeter Dunlap 
1996a6d42e7dSPeter Dunlap 	(void) printf("\n");
1997a6d42e7dSPeter Dunlap 
1998a6d42e7dSPeter Dunlap 	it_config_free(cfg);
1999a6d42e7dSPeter Dunlap 
2000a6d42e7dSPeter Dunlap 	return (0);
2001a6d42e7dSPeter Dunlap }
2002a6d42e7dSPeter Dunlap 
2003a6d42e7dSPeter Dunlap static int
2004a6d42e7dSPeter Dunlap itadm_get_password(nvlist_t *nvl, char *key, char *passfile,
2005a6d42e7dSPeter Dunlap     char *phrase)
2006a6d42e7dSPeter Dunlap {
2007a6d42e7dSPeter Dunlap 	int		ret = 0;
2008a6d42e7dSPeter Dunlap 	char		*pass;
2009a6d42e7dSPeter Dunlap 	char		buf[1024];
2010a6d42e7dSPeter Dunlap 	int		fd;
2011a6d42e7dSPeter Dunlap 	struct stat64	sbuf;
2012a6d42e7dSPeter Dunlap 	size_t		rd;
2013a6d42e7dSPeter Dunlap 
2014a6d42e7dSPeter Dunlap 	if (!nvl || !key) {
2015a6d42e7dSPeter Dunlap 		return (EINVAL);
2016a6d42e7dSPeter Dunlap 	}
2017a6d42e7dSPeter Dunlap 
2018a6d42e7dSPeter Dunlap 	if (passfile) {
2019a6d42e7dSPeter Dunlap 		ret = stat64(passfile, &sbuf);
2020a6d42e7dSPeter Dunlap 		if ((ret != 0) || (!S_ISREG(sbuf.st_mode))) {
2021a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
2022a6d42e7dSPeter Dunlap 			    gettext("Invalid secret file %s"),
2023a6d42e7dSPeter Dunlap 			    passfile);
2024a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
2025a6d42e7dSPeter Dunlap 			return (EBADF);
2026a6d42e7dSPeter Dunlap 		}
2027a6d42e7dSPeter Dunlap 
2028a6d42e7dSPeter Dunlap 		fd = open64(passfile, O_RDONLY);
2029a6d42e7dSPeter Dunlap 		if (fd == -1) {
2030a6d42e7dSPeter Dunlap 			ret = errno;
2031a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
2032a6d42e7dSPeter Dunlap 			    gettext("Could not open secret file %s, %d"),
2033a6d42e7dSPeter Dunlap 			    passfile, ret);
2034a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
2035a6d42e7dSPeter Dunlap 			return (ret);
2036a6d42e7dSPeter Dunlap 		}
2037a6d42e7dSPeter Dunlap 
2038a6d42e7dSPeter Dunlap 		rd = read(fd, buf, sbuf.st_size);
2039a6d42e7dSPeter Dunlap 		(void) close(fd);
2040a6d42e7dSPeter Dunlap 
2041a6d42e7dSPeter Dunlap 		if (rd != sbuf.st_size) {
2042a6d42e7dSPeter Dunlap 			ret = EIO;
2043a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
2044a6d42e7dSPeter Dunlap 			    gettext("Could not read secret file %s, %d"),
2045a6d42e7dSPeter Dunlap 			    passfile, ret);
2046a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
2047a6d42e7dSPeter Dunlap 			return (ret);
2048a6d42e7dSPeter Dunlap 		}
2049a6d42e7dSPeter Dunlap 
2050a6d42e7dSPeter Dunlap 		/* ensure buf is properly terminated */
2051a6d42e7dSPeter Dunlap 		buf[rd] = '\0';
2052a6d42e7dSPeter Dunlap 
2053a6d42e7dSPeter Dunlap 		/* if last char is a newline, strip it off */
2054a6d42e7dSPeter Dunlap 		if (buf[rd - 1] == '\n') {
2055a6d42e7dSPeter Dunlap 			buf[rd - 1] = '\0';
2056a6d42e7dSPeter Dunlap 		}
2057a6d42e7dSPeter Dunlap 
2058a6d42e7dSPeter Dunlap 		/* validate length */
2059a6d42e7dSPeter Dunlap 		if ((strlen(buf) > 255) || (strlen(buf) < 12)) {
2060a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "%s\n",
2061a6d42e7dSPeter Dunlap 			    gettext(
2062a6d42e7dSPeter Dunlap 			    "Secret must be between 12 and 255 characters"));
2063a6d42e7dSPeter Dunlap 			return (EINVAL);
2064a6d42e7dSPeter Dunlap 		}
2065a6d42e7dSPeter Dunlap 	} else {
2066a6d42e7dSPeter Dunlap 		/* prompt for secret */
2067a6d42e7dSPeter Dunlap 		if (!phrase) {
2068a6d42e7dSPeter Dunlap 			return (EINVAL);
2069a6d42e7dSPeter Dunlap 		}
2070a6d42e7dSPeter Dunlap 
2071a6d42e7dSPeter Dunlap 		pass = getpassphrase(phrase);
2072a6d42e7dSPeter Dunlap 		if (!pass) {
2073a6d42e7dSPeter Dunlap 			ret = errno;
2074a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
2075a6d42e7dSPeter Dunlap 			    gettext("Could not read secret, %d"),
2076a6d42e7dSPeter Dunlap 			    ret);
2077a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
2078a6d42e7dSPeter Dunlap 			return (ret);
2079a6d42e7dSPeter Dunlap 		}
2080a6d42e7dSPeter Dunlap 
2081a6d42e7dSPeter Dunlap 		/* validate length */
2082a6d42e7dSPeter Dunlap 		if ((strlen(pass) > 255) || (strlen(pass) < 12)) {
2083a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "%s\n",
2084a6d42e7dSPeter Dunlap 			    gettext(
2085a6d42e7dSPeter Dunlap 			    "Secret must be between 12 and 255 characters"));
2086a6d42e7dSPeter Dunlap 			return (EINVAL);
2087a6d42e7dSPeter Dunlap 		}
2088a6d42e7dSPeter Dunlap 
2089a6d42e7dSPeter Dunlap 		(void) strlcpy(buf, pass, sizeof (buf));
2090a6d42e7dSPeter Dunlap 
2091a6d42e7dSPeter Dunlap 		/* confirm entered secret */
2092a6d42e7dSPeter Dunlap 		pass = getpassphrase(gettext("Re-enter secret: "));
2093a6d42e7dSPeter Dunlap 		if (!pass) {
2094a6d42e7dSPeter Dunlap 			ret = errno;
2095a6d42e7dSPeter Dunlap 			(void) fprintf(stderr,
2096a6d42e7dSPeter Dunlap 			    gettext("Could not read secret, %d"),
2097a6d42e7dSPeter Dunlap 			    ret);
2098a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "\n");
2099a6d42e7dSPeter Dunlap 			return (ret);
2100a6d42e7dSPeter Dunlap 		}
2101a6d42e7dSPeter Dunlap 
2102a6d42e7dSPeter Dunlap 		if (strcmp(buf, pass) != 0) {
2103a6d42e7dSPeter Dunlap 			ret = EINVAL;
2104a6d42e7dSPeter Dunlap 			(void) fprintf(stderr, "%s\n",
2105a6d42e7dSPeter Dunlap 			    gettext("Secret validation failed"));
2106a6d42e7dSPeter Dunlap 			return (ret);
2107a6d42e7dSPeter Dunlap 		}
2108a6d42e7dSPeter Dunlap 
2109a6d42e7dSPeter Dunlap 	}
2110a6d42e7dSPeter Dunlap 
2111a6d42e7dSPeter Dunlap 	ret = nvlist_add_string(nvl, key, buf);
2112a6d42e7dSPeter Dunlap 
2113a6d42e7dSPeter Dunlap 	return (ret);
2114a6d42e7dSPeter Dunlap }
2115a6d42e7dSPeter Dunlap 
2116a6d42e7dSPeter Dunlap static int
2117a6d42e7dSPeter Dunlap itadm_opt_to_arr(nvlist_t *nvl, char *key, char *opt, uint32_t *num)
2118a6d42e7dSPeter Dunlap {
2119a6d42e7dSPeter Dunlap 	int		count;
2120a6d42e7dSPeter Dunlap 	char		*bufp;
2121a6d42e7dSPeter Dunlap 	char		**arr;
2122a6d42e7dSPeter Dunlap 
2123a6d42e7dSPeter Dunlap 	if (!opt || !key || !nvl) {
2124a6d42e7dSPeter Dunlap 		return (EINVAL);
2125a6d42e7dSPeter Dunlap 	}
2126a6d42e7dSPeter Dunlap 
2127a6d42e7dSPeter Dunlap 	bufp = opt;
2128a6d42e7dSPeter Dunlap 	count = 1;
2129a6d42e7dSPeter Dunlap 
2130a6d42e7dSPeter Dunlap 	for (;;) {
2131a6d42e7dSPeter Dunlap 		bufp = strchr(bufp, ',');
2132a6d42e7dSPeter Dunlap 		if (!bufp) {
2133a6d42e7dSPeter Dunlap 			break;
2134a6d42e7dSPeter Dunlap 		}
2135a6d42e7dSPeter Dunlap 		bufp++;
2136a6d42e7dSPeter Dunlap 		count++;
2137a6d42e7dSPeter Dunlap 	}
2138a6d42e7dSPeter Dunlap 
2139a6d42e7dSPeter Dunlap 	arr = calloc(count, sizeof (char *));
2140a6d42e7dSPeter Dunlap 	if (!arr) {
2141a6d42e7dSPeter Dunlap 		return (ENOMEM);
2142a6d42e7dSPeter Dunlap 	}
2143a6d42e7dSPeter Dunlap 
2144a6d42e7dSPeter Dunlap 	bufp = opt;
2145a6d42e7dSPeter Dunlap 	/* set delimiter to comma */
2146a6d42e7dSPeter Dunlap 	(void) bufsplit(",", 0, NULL);
2147a6d42e7dSPeter Dunlap 
2148a6d42e7dSPeter Dunlap 	/* split up that buf! */
2149a6d42e7dSPeter Dunlap 	(void) bufsplit(bufp, count, arr);
2150a6d42e7dSPeter Dunlap 
2151a6d42e7dSPeter Dunlap 	/* if requested, return the number of array members found */
2152a6d42e7dSPeter Dunlap 	if (num) {
2153a6d42e7dSPeter Dunlap 		*num = count;
2154a6d42e7dSPeter Dunlap 	}
2155a6d42e7dSPeter Dunlap 
2156a6d42e7dSPeter Dunlap 	return (nvlist_add_string_array(nvl, key, arr, count));
2157a6d42e7dSPeter Dunlap }
2158a6d42e7dSPeter Dunlap 
2159a6d42e7dSPeter Dunlap static void
2160a6d42e7dSPeter Dunlap tag_name_to_num(char *tagname, uint16_t *tagnum)
2161a6d42e7dSPeter Dunlap {
2162a6d42e7dSPeter Dunlap 	ulong_t		id;
2163a6d42e7dSPeter Dunlap 	char		*ptr = NULL;
2164a6d42e7dSPeter Dunlap 
2165a6d42e7dSPeter Dunlap 	if (!tagname || !tagnum) {
2166a6d42e7dSPeter Dunlap 		return;
2167a6d42e7dSPeter Dunlap 	}
2168a6d42e7dSPeter Dunlap 
2169a6d42e7dSPeter Dunlap 	*tagnum = 0;
2170a6d42e7dSPeter Dunlap 
2171a6d42e7dSPeter Dunlap 	id = strtoul(tagname, &ptr, 10);
2172a6d42e7dSPeter Dunlap 
2173a6d42e7dSPeter Dunlap 	/* Must be entirely numeric and in-range */
2174a6d42e7dSPeter Dunlap 	if (ptr && (*ptr != '\0')) {
2175a6d42e7dSPeter Dunlap 		return;
2176a6d42e7dSPeter Dunlap 	}
2177a6d42e7dSPeter Dunlap 
2178a6d42e7dSPeter Dunlap 	if ((id <= UINT16_MAX) && (id > 1)) {
2179a6d42e7dSPeter Dunlap 		*tagnum = (uint16_t)id;
2180a6d42e7dSPeter Dunlap 	}
2181a6d42e7dSPeter Dunlap }
2182*a4f92191SSam Cramer 
2183*a4f92191SSam Cramer /*
2184*a4f92191SSam Cramer  * Return a new string containing the canonical (lower-case)
2185*a4f92191SSam Cramer  * form of the target name.
2186*a4f92191SSam Cramer  */
2187*a4f92191SSam Cramer static char *
2188*a4f92191SSam Cramer canonical_target_name(char *tgt)
2189*a4f92191SSam Cramer {
2190*a4f92191SSam Cramer 	if (IS_IQN_NAME(tgt)) {
2191*a4f92191SSam Cramer 		/* lowercase iqn names */
2192*a4f92191SSam Cramer 		return (strduplc(tgt));
2193*a4f92191SSam Cramer 	} else {
2194*a4f92191SSam Cramer 		return (strdup(tgt));
2195*a4f92191SSam Cramer 	}
2196*a4f92191SSam Cramer }
2197*a4f92191SSam Cramer 
2198*a4f92191SSam Cramer /*
2199*a4f92191SSam Cramer  * Duplicate a string, converting it to lower case in the process.
2200*a4f92191SSam Cramer  * Returns NULL if no memory.
2201*a4f92191SSam Cramer  */
2202*a4f92191SSam Cramer static char *
2203*a4f92191SSam Cramer strduplc(char *s)
2204*a4f92191SSam Cramer {
2205*a4f92191SSam Cramer 	char *lc = strdup(s);
2206*a4f92191SSam Cramer 
2207*a4f92191SSam Cramer 	if (lc != NULL) {
2208*a4f92191SSam Cramer 		char *l = lc;
2209*a4f92191SSam Cramer 		while (*s) {
2210*a4f92191SSam Cramer 			*l = tolower(*s);
2211*a4f92191SSam Cramer 			s++; l++;
2212*a4f92191SSam Cramer 		}
2213*a4f92191SSam Cramer 	}
2214*a4f92191SSam Cramer 
2215*a4f92191SSam Cramer 	return (lc);
2216*a4f92191SSam Cramer }
2217