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