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