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