1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <stdlib.h>
  27 #include <stdio.h>
  28 #include <strings.h>
  29 #include <sys/types.h>
  30 #include <unistd.h>
  31 #include <wchar.h>
  32 #include <libintl.h>
  33 #include <errno.h>
  34 #include <time.h>
  35 #include <string.h>
  36 #include <assert.h>
  37 #include <getopt.h>
  38 #include <cmdparse.h>
  39 #include <stmfadm.h>
  40 #include <libstmf.h>
  41 #include <signal.h>
  42 #include <pthread.h>
  43 #include <locale.h>
  44 
  45 static int addHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
  46 static int addTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
  47 static int addViewFunc(int, char **, cmdOptions_t *, void *);
  48 static int createHostGroupFunc(int, char **, cmdOptions_t *, void *);
  49 static int createLuFunc(int, char **, cmdOptions_t *, void *);
  50 static int modifyLuFunc(int, char **, cmdOptions_t *, void *);
  51 static int importLuFunc(int, char **, cmdOptions_t *, void *);
  52 static int deleteLuFunc(int, char **, cmdOptions_t *, void *);
  53 static int createTargetGroupFunc(int, char **, cmdOptions_t *, void *);
  54 static int deleteHostGroupFunc(int, char **, cmdOptions_t *, void *);
  55 static int deleteTargetGroupFunc(int, char **, cmdOptions_t *, void *);
  56 static int listLuFunc(int, char **, cmdOptions_t *, void *);
  57 static int listTargetFunc(int, char **, cmdOptions_t *, void *);
  58 static int listViewFunc(int, char **, cmdOptions_t *, void *);
  59 static int listHostGroupFunc(int, char **, cmdOptions_t *, void *);
  60 static int listStateFunc(int, char **, cmdOptions_t *, void *);
  61 static int listTargetGroupFunc(int, char **, cmdOptions_t *, void *);
  62 static int offlineTargetFunc(int, char **, cmdOptions_t *, void *);
  63 static int offlineLuFunc(int, char **, cmdOptions_t *, void *);
  64 static int onlineTargetFunc(int, char **, cmdOptions_t *, void *);
  65 static int onlineLuFunc(int, char **, cmdOptions_t *, void *);
  66 static int onlineOfflineTarget(char *, int);
  67 static int onlineOfflineLu(char *, int);
  68 static int removeHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
  69 static int removeTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
  70 static int callModify(char *, stmfGuid *, uint32_t, const char *, const char *);
  71 static int removeViewFunc(int, char **, cmdOptions_t *, void *);
  72 static char *getExecBasename(char *);
  73 static int parseDevid(char *input, stmfDevid *devid);
  74 static void printGroupProps(stmfGroupProperties *groupProps);
  75 static int checkScsiNameString(wchar_t *, stmfDevid *);
  76 static int checkHexUpper(char *);
  77 static int checkIscsiName(wchar_t *);
  78 static void printLuProps(stmfLogicalUnitProperties *luProps);
  79 static int printExtLuProps(stmfGuid *guid);
  80 static void printGuid(stmfGuid *guid, FILE *printWhere);
  81 static void printTargetProps(stmfTargetProperties *);
  82 static void printSessionProps(stmfSessionList *);
  83 static int setLuPropFromInput(luResource, char *);
  84 static int convertCharToPropId(char *, uint32_t *);
  85 
  86 
  87 
  88 /*
  89  *  MAJOR - This should only change when there is an incompatible change made
  90  *  to the interfaces or the output.
  91  *
  92  *  MINOR - This should change whenever there is a new command or new feature
  93  *  with no incompatible change.
  94  */
  95 #define VERSION_STRING_MAJOR        "1"
  96 #define VERSION_STRING_MINOR        "0"
  97 #define MAX_DEVID_INPUT             256
  98 #define GUID_INPUT                  32
  99 #define MAX_LU_NBR                  16383
 100 #define ONLINE_LU                   0
 101 #define OFFLINE_LU                  1
 102 #define ONLINE_TARGET               2
 103 #define OFFLINE_TARGET              3
 104 #define PROPS_FORMAT                "    %-18s: "
 105 #define VIEW_FORMAT                 "    %-13s: "
 106 #define LVL3_FORMAT                 "        %s"
 107 #define LVL4_FORMAT                 "            %s"
 108 #define DELAYED_EXEC_WAIT_INTERVAL  300 * 1000 * 1000   /* in nano sec */
 109 #define DELAYED_EXEC_WAIT_MAX       30  /* Maximum number of interval times */
 110 
 111 /* SCSI Name String length definitions */
 112 #define SNS_EUI_16                  16
 113 #define SNS_EUI_24                  24
 114 #define SNS_EUI_32                  32
 115 #define SNS_NAA_16                  16
 116 #define SNS_NAA_32                  32
 117 #define SNS_WWN_16                  16
 118 #define SNS_IQN_223                 223
 119 
 120 /* LU Property strings */
 121 #define GUID                        "GUID"
 122 #define ALIAS                       "ALIAS"
 123 #define VID                         "VID"
 124 #define PID                         "PID"
 125 #define META_FILE                   "META"
 126 #define WRITE_PROTECT               "WP"
 127 #define WRITEBACK_CACHE_DISABLE     "WCD"
 128 #define COMPANY_ID                  "OUI"
 129 #define BLOCK_SIZE                  "BLK"
 130 #define SERIAL_NUMBER               "SERIAL"
 131 #define MGMT_URL                    "MGMT-URL"
 132 #define HOST_ID                     "HOST-ID"
 133 
 134 #define STMFADM_SUCCESS             0
 135 #define STMFADM_FAILURE             1
 136 
 137 #define MODIFY_HELP "\n"\
 138 "Description: Modify properties of a logical unit. \n" \
 139 "Valid properties for -p, --lu-prop are: \n" \
 140 "     alias    - alias for logical unit (up to 255 chars)\n" \
 141 "     mgmt-url - Management URL address\n" \
 142 "     wcd      - write cache disabled (true, false)\n" \
 143 "     wp       - write protect (true, false)\n\n" \
 144 "-f alters the meaning of the operand to be a file name\n" \
 145 "rather than a LU name. This allows for modification\n" \
 146 "of a logical unit that is not yet imported into stmf\n"
 147 
 148 #define CREATE_HELP "\n"\
 149 "Description: Create a logical unit. \n" \
 150 "Valid properties for -p, --lu-prop are: \n" \
 151 "     alias    - alias for logical unit (up to 255 chars)\n" \
 152 "     blk      - block size in bytes in 2^n\n" \
 153 "     guid     - 32 ascii hex characters in NAA format \n" \
 154 "     host-id  - host identifier to be used for GUID generation \n" \
 155 "                8 ascii hex characters\n" \
 156 "     meta     - separate meta data file name\n" \
 157 "     mgmt-url - Management URL address\n" \
 158 "     oui      - organizational unique identifier\n" \
 159 "                6 ascii hex characters of valid format\n" \
 160 "     pid      - product identifier (up to 16 chars)\n" \
 161 "     serial   - serial number (up to 252 chars)\n" \
 162 "     vid      - vendor identifier (up to 8 chars)\n" \
 163 "     wcd      - write cache disabled (true, false)\n" \
 164 "     wp       - write protect (true, false)\n"
 165 #define ADD_VIEW_HELP "\n"\
 166 "Description: Add a view entry to a logical unit. \n" \
 167 "A view entry is comprised of three elements; the \n" \
 168 "logical unit number, the target group name and the\n" \
 169 "host group name. These three elements combine together\n" \
 170 "to form a view for a given COMSTAR logical unit.\n" \
 171 "This view is realized by a client, a SCSI initiator,\n" \
 172 "via a REPORT LUNS command. \n"
 173 
 174 
 175 
 176 /* tables set up based on cmdparse instructions */
 177 
 178 /* add new options here */
 179 optionTbl_t longOptions[] = {
 180         {"all", no_arg, 'a', NULL},
 181         {"group-name", required_arg, 'g', "group-name"},
 182         {"keep-views", no_arg, 'k', NULL},
 183         {"lu-name", required_arg, 'l', "LU-Name"},
 184         {"lun", required_arg, 'n', "logical-unit-number"},
 185         {"lu-prop", required_arg, 'p', "logical-unit-property=value"},
 186         {"file", no_arg, 'f', "filename"},
 187         {"size", required_arg, 's', "size K/M/G/T/P"},
 188         {"target-group", required_arg, 't', "group-name"},
 189         {"host-group", required_arg, 'h', "group-name"},
 190         {"verbose", no_arg, 'v', NULL},
 191         {NULL, 0, 0, 0}
 192 };
 193 
 194 /*
 195  * Add new subcommands here
 196  */
 197 subCommandProps_t subcommands[] = {
 198         {"add-hg-member", addHostGroupMemberFunc, "g", "g", NULL,
 199                 OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
 200         {"add-tg-member", addTargetGroupMemberFunc, "g", "g", NULL,
 201                 OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
 202         {"add-view", addViewFunc, "nth", NULL, NULL,
 203                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, ADD_VIEW_HELP},
 204         {"create-hg", createHostGroupFunc, NULL, NULL, NULL,
 205                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
 206         {"create-tg", createTargetGroupFunc, NULL, NULL, NULL,
 207                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
 208         {"create-lu", createLuFunc, "ps", NULL, NULL, OPERAND_MANDATORY_SINGLE,
 209                 "lu file", CREATE_HELP},
 210         {"delete-hg", deleteHostGroupFunc, NULL, NULL, NULL,
 211                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
 212         {"modify-lu", modifyLuFunc, "psf", NULL, NULL, OPERAND_MANDATORY_SINGLE,
 213                 OPERANDSTRING_LU, MODIFY_HELP},
 214         {"delete-lu", deleteLuFunc, "k", NULL, NULL,
 215                 OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_LU, NULL},
 216         {"delete-tg", deleteTargetGroupFunc, NULL, NULL, NULL,
 217                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
 218         {"import-lu", importLuFunc, NULL, NULL, NULL,
 219                 OPERAND_MANDATORY_SINGLE, "file name", NULL},
 220         {"list-hg", listHostGroupFunc, "v", NULL, NULL,
 221                 OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
 222         {"list-lu", listLuFunc, "v", NULL, NULL, OPERAND_OPTIONAL_MULTIPLE,
 223                 OPERANDSTRING_LU, NULL},
 224         {"list-state", listStateFunc, NULL, NULL, NULL, OPERAND_NONE, NULL},
 225         {"list-target", listTargetFunc, "v", NULL, NULL,
 226                 OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_TARGET, NULL},
 227         {"list-tg", listTargetGroupFunc, "v", NULL, NULL,
 228                 OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
 229         {"list-view", listViewFunc, "l", "l", NULL,
 230                 OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
 231         {"online-lu", onlineLuFunc, NULL, NULL, NULL,
 232                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
 233         {"offline-lu", offlineLuFunc, NULL, NULL, NULL,
 234                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
 235         {"online-target", onlineTargetFunc, NULL, NULL, NULL,
 236                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
 237         {"offline-target", offlineTargetFunc, NULL, NULL, NULL,
 238                 OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
 239         {"remove-hg-member", removeHostGroupMemberFunc, "g", "g", NULL,
 240                 OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
 241         {"remove-tg-member", removeTargetGroupMemberFunc, "g", "g", NULL,
 242                 OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
 243         {"remove-view", removeViewFunc, "la", "l", NULL,
 244                 OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
 245         {NULL, 0, NULL, NULL, 0, NULL, 0, NULL, NULL}
 246 };
 247 
 248 /* globals */
 249 char *cmdName;
 250 
 251 /*
 252  * addHostGroupMemberFunc
 253  *
 254  * Add members to a host group
 255  *
 256  */
 257 /*ARGSUSED*/
 258 static int
 259 addHostGroupMemberFunc(int operandLen, char *operands[], cmdOptions_t *options,
 260     void *args)
 261 {
 262         int i;
 263         int ret = 0;
 264         int stmfRet;
 265         stmfGroupName groupName = {0};
 266         wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
 267         stmfDevid devid;
 268 
 269         for (; options->optval; options++) {
 270                 switch (options->optval) {
 271                         /* host group name */
 272                         case 'g':
 273                                 (void) mbstowcs(groupNamePrint, options->optarg,
 274                                     sizeof (stmfGroupName) - 1);
 275                                 bcopy(options->optarg, groupName,
 276                                     strlen(options->optarg));
 277                                 break;
 278                         default:
 279                                 (void) fprintf(stderr, "%s: %c: %s\n",
 280                                     cmdName, options->optval,
 281                                     gettext("unknown option"));
 282                                 return (1);
 283                 }
 284         }
 285 
 286         for (i = 0; i < operandLen; i++) {
 287                 if (parseDevid(operands[i], &devid) != 0) {
 288                         (void) fprintf(stderr, "%s: %s: %s\n",
 289                             cmdName, operands[i],
 290                             gettext("unrecognized device id"));
 291                         ret++;
 292                         continue;
 293                 }
 294                 stmfRet = stmfAddToHostGroup(&groupName, &devid);
 295                 switch (stmfRet) {
 296                         case STMF_STATUS_SUCCESS:
 297                                 break;
 298                         case STMF_ERROR_EXISTS:
 299                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 300                                     operands[i], gettext("already exists"));
 301                                 ret++;
 302                                 break;
 303                         case STMF_ERROR_GROUP_NOT_FOUND:
 304                                 (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
 305                                     groupNamePrint, gettext("not found"));
 306                                 ret++;
 307                                 break;
 308                         case STMF_ERROR_PERM:
 309                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
 310                                     gettext("permission denied"));
 311                                 ret++;
 312                                 break;
 313                         case STMF_ERROR_BUSY:
 314                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 315                                     operands[i], gettext("resource busy"));
 316                                 ret++;
 317                                 break;
 318                         case STMF_ERROR_SERVICE_NOT_FOUND:
 319                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
 320                                     gettext("STMF service not found"));
 321                                 ret++;
 322                                 break;
 323                         case STMF_ERROR_SERVICE_DATA_VERSION:
 324                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
 325                                     gettext("STMF service version incorrect"));
 326                                 ret++;
 327                                 break;
 328                         default:
 329                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 330                                     operands[i], gettext("unknown error"));
 331                                 ret++;
 332                                 break;
 333                 }
 334         }
 335 
 336         return (ret);
 337 }
 338 
 339 /*
 340  * addTargetGroupMemberFunc
 341  *
 342  * Add members to a target group
 343  *
 344  */
 345 /*ARGSUSED*/
 346 static int
 347 addTargetGroupMemberFunc(int operandLen, char *operands[],
 348     cmdOptions_t *options, void *args)
 349 {
 350         int i;
 351         int ret = 0;
 352         int stmfRet;
 353         stmfGroupName groupName = {0};
 354         wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
 355         stmfDevid devid;
 356 
 357         for (; options->optval; options++) {
 358                 switch (options->optval) {
 359                         /* target group name */
 360                         case 'g':
 361                                 (void) mbstowcs(groupNamePrint, options->optarg,
 362                                     sizeof (stmfGroupName) - 1);
 363                                 bcopy(options->optarg, groupName,
 364                                     strlen(options->optarg));
 365                                 break;
 366                         default:
 367                                 (void) fprintf(stderr, "%s: %c: %s\n",
 368                                     cmdName, options->optval,
 369                                     gettext("unknown option"));
 370                                 return (1);
 371                 }
 372         }
 373 
 374         for (i = 0; i < operandLen; i++) {
 375                 if (parseDevid(operands[i], &devid) != 0) {
 376                         (void) fprintf(stderr, "%s: %s: %s\n",
 377                             cmdName, operands[i],
 378                             gettext("unrecognized device id"));
 379                         ret++;
 380                         continue;
 381                 }
 382                 stmfRet = stmfAddToTargetGroup(&groupName, &devid);
 383                 switch (stmfRet) {
 384                         case STMF_STATUS_SUCCESS:
 385                                 break;
 386                         case STMF_ERROR_EXISTS:
 387                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 388                                     operands[i], gettext("already exists"));
 389                                 ret++;
 390                                 break;
 391                         case STMF_ERROR_GROUP_NOT_FOUND:
 392                                 (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
 393                                     groupNamePrint, gettext("not found"));
 394                                 ret++;
 395                                 break;
 396                         case STMF_ERROR_PERM:
 397                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
 398                                     gettext("permission denied"));
 399                                 ret++;
 400                                 break;
 401                         case STMF_ERROR_BUSY:
 402                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 403                                     operands[i], gettext("resource busy"));
 404                                 ret++;
 405                                 break;
 406                         case STMF_ERROR_SERVICE_NOT_FOUND:
 407                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
 408                                     gettext("STMF service not found"));
 409                                 ret++;
 410                                 break;
 411                         case STMF_ERROR_SERVICE_ONLINE:
 412                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
 413                                     gettext("STMF service must be offline"));
 414                                 ret++;
 415                                 break;
 416                         case STMF_ERROR_SERVICE_DATA_VERSION:
 417                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
 418                                     gettext("STMF service version incorrect"));
 419                                 ret++;
 420                                 break;
 421                         case STMF_ERROR_TG_ONLINE:
 422                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
 423                                     gettext("STMF target must be offline"));
 424                                 ret++;
 425                                 break;
 426                         default:
 427                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 428                                     operands[i], gettext("unknown error"));
 429                                 ret++;
 430                                 break;
 431                 }
 432         }
 433 
 434         return (ret);
 435 }
 436 
 437 /*
 438  * parseDevid
 439  *
 440  * Converts char * input to a stmfDevid
 441  *
 442  * input - this should be in the following format with either a
 443  * wwn. iqn. or eui. representation.
 444  * A name string of the format:
 445  *      wwn.<WWN> (FC/SAS address)
 446  *      iqn.<iSCSI name> (iSCSI iqn)
 447  *      eui.<WWN> (iSCSI eui name)
 448  *
 449  * devid - pointer to stmfDevid structure allocated by the caller.
 450  *
 451  * Returns:
 452  *  0 on success
 453  *  non-zero on failure
 454  */
 455 static int
 456 parseDevid(char *input, stmfDevid *devid)
 457 {
 458         wchar_t inputWc[MAX_DEVID_INPUT + 1] = {0};
 459 
 460         /* convert to wcs */
 461         (void) mbstowcs(inputWc, input, MAX_DEVID_INPUT);
 462 
 463         /*
 464          * Check for known scsi name string formats
 465          * If one is found, we're done
 466          * If not, then it's a failure to parse
 467          */
 468         if (checkScsiNameString(inputWc, devid) == 0) {
 469                 return (0);
 470         }
 471 
 472         return (-1);
 473 }
 474 
 475 /*
 476  * checkScsiNameString
 477  *
 478  * Validates known SCSI name string formats and converts to stmfDevid
 479  * format
 480  *
 481  * input - input SCSI name string
 482  * devid - pointer to stmfDevid structure allocated by the caller
 483  *         on successful return, contains the devid based on input
 484  *
 485  * returns:
 486  *         0 on success
 487  *         -1 on failure
 488  */
 489 static int
 490 checkScsiNameString(wchar_t *input, stmfDevid *devid)
 491 {
 492         char *mbString = NULL;
 493         int mbStringLen;
 494         int len;
 495         int i;
 496 
 497         /*
 498          * Convert to multi-byte string
 499          *
 500          * This is used for either eui or naa formats
 501          */
 502         mbString = calloc(1, (mbStringLen = wcstombs(mbString, input, 0)) + 1);
 503         if (mbString == NULL) {
 504                 (void) fprintf(stderr, "%s: %s\n",
 505                     cmdName, "Insufficient memory\n");
 506                 return (-1);
 507         }
 508         if (wcstombs(mbString, input, mbStringLen) == (size_t)-1) {
 509                 return (-1);
 510         }
 511 
 512         /*
 513          * check for iqn format
 514          */
 515         if (strncmp(mbString, "iqn.", 4) == 0) {
 516                 if ((len = strlen(mbString)) > (SNS_IQN_223)) {
 517                         return (-1);
 518                 }
 519                 for (i = 0; i < len; i++) {
 520                         mbString[i] = tolower(mbString[i]);
 521                 }
 522                 if (checkIscsiName(input + 4) != 0) {
 523                         return (-1);
 524                 }
 525         } else if (strncmp(mbString, "wwn.", 4) == 0) {
 526                 if ((len = strlen(mbString + 4)) != SNS_WWN_16) {
 527                         return (-1);
 528                 } else if (checkHexUpper(mbString + 4) != 0) {
 529                         return (-1);
 530                 }
 531         } else if (strncmp(mbString, "eui.", 4) == 0) {
 532                 if ((len = strlen(mbString + 4)) != SNS_EUI_16) {
 533                         return (-1);
 534                 } else if (checkHexUpper(mbString + 4) != 0) {
 535                         return (-1);
 536                 }
 537         } else {
 538                 return (-1);
 539         }
 540 
 541         /*
 542          * We have a validated name string.
 543          * Go ahead and set the length and copy it.
 544          */
 545         devid->identLength = strlen(mbString);
 546         bzero(devid->ident, STMF_IDENT_LENGTH);
 547         bcopy(mbString, devid->ident, devid->identLength);
 548 
 549         return (0);
 550 }
 551 
 552 
 553 /*
 554  * Checks whether the entire string is in hex and converts to upper
 555  */
 556 static int
 557 checkHexUpper(char *input)
 558 {
 559         int i;
 560 
 561         for (i = 0; i < strlen(input); i++) {
 562                 if (isxdigit(input[i])) {
 563                         input[i] = toupper(input[i]);
 564                         continue;
 565                 }
 566                 return (-1);
 567         }
 568 
 569         return (0);
 570 }
 571 
 572 /*
 573  * checkIscsiName
 574  *
 575  * Purpose: Basic string checking on name
 576  */
 577 static int
 578 checkIscsiName(wchar_t *input)
 579 {
 580         int i;
 581 
 582         for (i = 0; input[i] != 0; i++) {
 583                 if (!iswalnum(input[i]) && input[i] != '-' &&
 584                     input[i] != '.' && input[i] != ':') {
 585                         return (-1);
 586                 }
 587         }
 588 
 589         return (0);
 590 }
 591 
 592 
 593 /*
 594  * addViewFunc
 595  *
 596  * Adds a view entry to a logical unit
 597  *
 598  */
 599 /*ARGSUSED*/
 600 static int
 601 addViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
 602     void *args)
 603 {
 604         stmfViewEntry viewEntry;
 605         stmfGuid inGuid;
 606         unsigned int guid[sizeof (stmfGuid)];
 607         uint16_t inputLuNbr;
 608         int ret = 0;
 609         int stmfRet;
 610         int i;
 611         char sGuid[GUID_INPUT + 1];
 612 
 613         bzero(&viewEntry, sizeof (viewEntry));
 614         /* init view entry structure */
 615         viewEntry.allHosts = B_TRUE;
 616         viewEntry.allTargets = B_TRUE;
 617         viewEntry.luNbrValid = B_FALSE;
 618 
 619         /* check input length */
 620         if (strlen(operands[0]) != GUID_INPUT) {
 621                 (void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
 622                     gettext("must be "), GUID_INPUT,
 623                     gettext(" hexadecimal digits"));
 624                 return (1);
 625         }
 626 
 627         for (; options->optval; options++) {
 628                 switch (options->optval) {
 629                         /* logical unit number */
 630                         case 'n':
 631                                 viewEntry.luNbrValid = B_TRUE;
 632                                 inputLuNbr = atoi(options->optarg);
 633                                 if (inputLuNbr > MAX_LU_NBR) {
 634                                         (void) fprintf(stderr, "%s: %d: %s\n",
 635                                             cmdName, inputLuNbr,
 636                                             gettext("Logical unit number"
 637                                             " must be less than 16384"));
 638                                         return (1);
 639                                 }
 640                                 viewEntry.luNbr[0] = inputLuNbr >> 8;
 641                                 viewEntry.luNbr[1] = inputLuNbr & 0xff;
 642                                 break;
 643                         /* host group */
 644                         case 'h':
 645                                 viewEntry.allHosts = B_FALSE;
 646                                 bcopy(options->optarg, viewEntry.hostGroup,
 647                                     strlen(options->optarg));
 648                                 break;
 649                         /* target group */
 650                         case 't':
 651                                 viewEntry.allTargets = B_FALSE;
 652                                 bcopy(options->optarg, viewEntry.targetGroup,
 653                                     strlen(options->optarg));
 654                                 break;
 655                         default:
 656                                 (void) fprintf(stderr, "%s: %c: %s\n",
 657                                     cmdName, options->optval,
 658                                     gettext("unknown option"));
 659                                 return (1);
 660                 }
 661         }
 662 
 663         /* convert to lower case for scan */
 664         for (i = 0; i < 32; i++)
 665                 sGuid[i] = tolower(operands[0][i]);
 666         sGuid[i] = 0;
 667 
 668         (void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
 669             &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
 670             &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
 671             &guid[12], &guid[13], &guid[14], &guid[15]);
 672 
 673         for (i = 0; i < sizeof (stmfGuid); i++) {
 674                 inGuid.guid[i] = guid[i];
 675         }
 676 
 677         /* add the view entry */
 678         stmfRet = stmfAddViewEntry(&inGuid, &viewEntry);
 679         switch (stmfRet) {
 680                 case STMF_STATUS_SUCCESS:
 681                         break;
 682                 case STMF_ERROR_EXISTS:
 683                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 684                             operands[0], gettext("already exists"));
 685                         ret++;
 686                         break;
 687                 case STMF_ERROR_BUSY:
 688                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 689                             operands[0], gettext("resource busy"));
 690                         ret++;
 691                         break;
 692                 case STMF_ERROR_SERVICE_NOT_FOUND:
 693                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 694                             gettext("STMF service not found"));
 695                         ret++;
 696                         break;
 697                 case STMF_ERROR_PERM:
 698                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 699                             gettext("permission denied"));
 700                         ret++;
 701                         break;
 702                 case STMF_ERROR_LUN_IN_USE:
 703                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 704                             gettext("LUN already in use"));
 705                         ret++;
 706                         break;
 707                 case STMF_ERROR_VE_CONFLICT:
 708                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 709                             gettext("view entry exists"));
 710                         ret++;
 711                         break;
 712                 case STMF_ERROR_CONFIG_NONE:
 713                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 714                             gettext("STMF service is not initialized"));
 715                         ret++;
 716                         break;
 717                 case STMF_ERROR_SERVICE_DATA_VERSION:
 718                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 719                             gettext("STMF service version incorrect"));
 720                         ret++;
 721                         break;
 722                 case STMF_ERROR_INVALID_HG:
 723                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 724                             gettext("invalid host group"));
 725                         ret++;
 726                         break;
 727                 case STMF_ERROR_INVALID_TG:
 728                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 729                             gettext("invalid target group"));
 730                         ret++;
 731                         break;
 732                 default:
 733                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 734                             operands[0], gettext("unknown error"));
 735                         ret++;
 736                         break;
 737         }
 738 
 739         return (ret);
 740 }
 741 
 742 /*
 743  * createHostGroupFunc
 744  *
 745  * Create a host group
 746  *
 747  */
 748 /*ARGSUSED*/
 749 static int
 750 createHostGroupFunc(int operandLen, char *operands[],
 751     cmdOptions_t *options, void *args)
 752 {
 753         int ret = 0;
 754         int stmfRet;
 755         wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
 756         stmfGroupName groupName = {0};
 757 
 758         (void) strlcpy(groupName, operands[0], sizeof (groupName));
 759         (void) mbstowcs(groupNamePrint, (char *)groupName,
 760             sizeof (stmfGroupName) - 1);
 761         /* call create group */
 762         stmfRet = stmfCreateHostGroup(&groupName);
 763         switch (stmfRet) {
 764                 case STMF_STATUS_SUCCESS:
 765                         break;
 766                 case STMF_ERROR_EXISTS:
 767                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 768                             operands[0], gettext("already exists"));
 769                         ret++;
 770                         break;
 771                 case STMF_ERROR_BUSY:
 772                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
 773                             operands[0], gettext("resource busy"));
 774                         ret++;
 775                         break;
 776                 case STMF_ERROR_SERVICE_NOT_FOUND:
 777                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 778                             gettext("STMF service not found"));
 779                         ret++;
 780                         break;
 781                 case STMF_ERROR_PERM:
 782                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 783                             gettext("permission denied"));
 784                         ret++;
 785                         break;
 786                 case STMF_ERROR_SERVICE_DATA_VERSION:
 787                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 788                             gettext("STMF service version incorrect"));
 789                         ret++;
 790                         break;
 791                 default:
 792                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
 793                             operands[0], gettext("unknown error"));
 794                         ret++;
 795                         break;
 796         }
 797 
 798         return (ret);
 799 }
 800 
 801 /*
 802  * createLuFunc
 803  *
 804  * Create a logical unit
 805  *
 806  */
 807 /*ARGSUSED*/
 808 static int
 809 createLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
 810     void *args)
 811 {
 812         luResource hdl = NULL;
 813         int ret = 0;
 814         int stmfRet = 0;
 815         char guidAsciiBuf[33];
 816         stmfGuid createdGuid;
 817 
 818         stmfRet = stmfCreateLuResource(STMF_DISK, &hdl);
 819 
 820         if (stmfRet != STMF_STATUS_SUCCESS) {
 821                 (void) fprintf(stderr, "%s: %s\n",
 822                     cmdName, gettext("Failure to create lu resource\n"));
 823                 return (1);
 824         }
 825 
 826         for (; options->optval; options++) {
 827                 switch (options->optval) {
 828                         case 'p':
 829                                 ret = setLuPropFromInput(hdl, options->optarg);
 830                                 if (ret != 0) {
 831                                         (void) stmfFreeLuResource(hdl);
 832                                         return (1);
 833                                 }
 834                                 break;
 835                         case 's':
 836                                 stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_SIZE,
 837                                     options->optarg);
 838                                 if (stmfRet != STMF_STATUS_SUCCESS) {
 839                                         (void) fprintf(stderr, "%s: %c: %s\n",
 840                                             cmdName, options->optval,
 841                                             gettext("size param invalid"));
 842                                         (void) stmfFreeLuResource(hdl);
 843                                         return (1);
 844                                 }
 845                                 break;
 846                         default:
 847                                 (void) fprintf(stderr, "%s: %c: %s\n",
 848                                     cmdName, options->optval,
 849                                     gettext("unknown option"));
 850                                 return (1);
 851                 }
 852         }
 853 
 854         stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_FILENAME, operands[0]);
 855 
 856         if (stmfRet != STMF_STATUS_SUCCESS) {
 857                 (void) fprintf(stderr, "%s: %s\n",
 858                     cmdName, gettext("could not set filename"));
 859                 return (1);
 860         }
 861 
 862         stmfRet = stmfCreateLu(hdl, &createdGuid);
 863         switch (stmfRet) {
 864                 case STMF_STATUS_SUCCESS:
 865                         break;
 866                 case STMF_ERROR_BUSY:
 867                 case STMF_ERROR_LU_BUSY:
 868                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 869                             gettext("resource busy"));
 870                         ret++;
 871                         break;
 872                 case STMF_ERROR_PERM:
 873                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 874                             gettext("permission denied"));
 875                         ret++;
 876                         break;
 877                 case STMF_ERROR_FILE_IN_USE:
 878                         (void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
 879                             operands[0], gettext("in use"));
 880                         ret++;
 881                         break;
 882                 case STMF_ERROR_INVALID_BLKSIZE:
 883                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 884                             gettext("invalid block size"));
 885                         ret++;
 886                         break;
 887                 case STMF_ERROR_GUID_IN_USE:
 888                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 889                             gettext("guid in use"));
 890                         ret++;
 891                         break;
 892                 case STMF_ERROR_META_FILE_NAME:
 893                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 894                             gettext("meta file error"));
 895                         ret++;
 896                         break;
 897                 case STMF_ERROR_DATA_FILE_NAME:
 898                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 899                             gettext("data file error"));
 900                         ret++;
 901                         break;
 902                 case STMF_ERROR_FILE_SIZE_INVALID:
 903                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 904                             gettext("file size invalid"));
 905                         ret++;
 906                         break;
 907                 case STMF_ERROR_SIZE_OUT_OF_RANGE:
 908                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 909                             gettext("invalid size"));
 910                         ret++;
 911                         break;
 912                 case STMF_ERROR_META_CREATION:
 913                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 914                             gettext("could not create meta file"));
 915                         ret++;
 916                         break;
 917                 case STMF_ERROR_WRITE_CACHE_SET:
 918                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 919                             gettext("could not set write cache"));
 920                         ret++;
 921                         break;
 922                 default:
 923                         (void) fprintf(stderr, "%s: %s\n", cmdName,
 924                             gettext("unknown error"));
 925                         ret++;
 926                         break;
 927         }
 928 
 929         if (ret != 0) {
 930                 goto done;
 931         }
 932 
 933         (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
 934             "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
 935             "%02X%02X%02X%02X%02X%02X",
 936             createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
 937             createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
 938             createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
 939             createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
 940             createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
 941             createdGuid.guid[15]);
 942         (void) printf("Logical unit created: %s\n", guidAsciiBuf);
 943 
 944 done:
 945         (void) stmfFreeLuResource(hdl);
 946         return (ret);
 947 }
 948 
 949 /*
 950  * createLuFunc
 951  *
 952  * Create a logical unit
 953  *
 954  */
 955 /*ARGSUSED*/
 956 static int
 957 modifyLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
 958     void *args)
 959 {
 960         stmfGuid inGuid;
 961         unsigned int guid[sizeof (stmfGuid)];
 962         int ret = 0;
 963         int i;
 964         char *fname = NULL;
 965         char *lasts = NULL;
 966         char sGuid[GUID_INPUT + 1];
 967         char *prop = NULL;
 968         char *propVal = NULL;
 969         boolean_t fnameUsed = B_FALSE;
 970         uint32_t propId;
 971         cmdOptions_t *optionStart = options;
 972 
 973 
 974         for (; options->optval; options++) {
 975                 switch (options->optval) {
 976                         case 'f':
 977                                 fnameUsed = B_TRUE;
 978                                 fname = operands[0];
 979                                 break;
 980                 }
 981         }
 982         options = optionStart;
 983 
 984         /* check input length */
 985         if (!fnameUsed && strlen(operands[0]) != GUID_INPUT) {
 986                 (void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
 987                     gettext("must be "), GUID_INPUT,
 988                     gettext(" hexadecimal digits"));
 989                 return (1);
 990         }
 991 
 992         if (!fnameUsed) {
 993                 /* convert to lower case for scan */
 994                 for (i = 0; i < 32; i++)
 995                         sGuid[i] = tolower(operands[0][i]);
 996                 sGuid[i] = 0;
 997                 (void) sscanf(sGuid,
 998                     "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
 999                     &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
1000                     &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
1001                     &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
1002 
1003                 for (i = 0; i < sizeof (stmfGuid); i++) {
1004                         inGuid.guid[i] = guid[i];
1005                 }
1006         }
1007 
1008         for (; options->optval; options++) {
1009                 switch (options->optval) {
1010                         case 'p':
1011                                 prop = strtok_r(options->optarg, "=", &lasts);
1012                                 propVal = strtok_r(NULL, "=", &lasts);
1013                                 ret = convertCharToPropId(prop, &propId);
1014                                 if (ret != 0) {
1015                                         (void) fprintf(stderr, "%s: %s: %s\n",
1016                                             cmdName,
1017                                         gettext("invalid property specified"),
1018                                             prop);
1019                                         return (1);
1020                                 }
1021                                 if (propVal ==  NULL &&
1022                                     propId != STMF_LU_PROP_MGMT_URL) {
1023                                         (void) fprintf(stderr, "%s: %s: %s\n",
1024                                             cmdName, options->optarg,
1025                                             gettext("invalid property specifier"
1026                                             "- prop=val\n"));
1027                                         return (1);
1028                                 }
1029                                 if (propVal ==  NULL) {
1030                                         ret = callModify(fname, &inGuid, propId,
1031                                             "", prop);
1032                                 } else {
1033                                         ret = callModify(fname, &inGuid, propId,
1034                                             propVal, prop);
1035                                 }
1036                                 if (ret != 0) {
1037                                         return (1);
1038                                 }
1039                                 break;
1040                         case 's':
1041                                 if (callModify(fname, &inGuid,
1042                                     STMF_LU_PROP_SIZE, options->optarg,
1043                                     "size") != 0) {
1044                                         return (1);
1045                                 }
1046                                 break;
1047                         case 'f':
1048                                 break;
1049                         default:
1050                                 (void) fprintf(stderr, "%s: %c: %s\n",
1051                                     cmdName, options->optval,
1052                                     gettext("unknown option"));
1053                                 return (1);
1054                 }
1055         }
1056         return (ret);
1057 }
1058 
1059 static int
1060 callModify(char *fname, stmfGuid *luGuid, uint32_t prop, const char *propVal,
1061     const char *propString)
1062 {
1063         int ret = 0;
1064         int stmfRet = 0;
1065 
1066         if (!fname) {
1067                 stmfRet = stmfModifyLu(luGuid, prop, propVal);
1068         } else {
1069                 stmfRet = stmfModifyLuByFname(STMF_DISK, fname, prop,
1070                     propVal);
1071         }
1072         switch (stmfRet) {
1073                 case STMF_STATUS_SUCCESS:
1074                         break;
1075                 case STMF_ERROR_BUSY:
1076                 case STMF_ERROR_LU_BUSY:
1077                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1078                             gettext("resource busy"));
1079                         ret++;
1080                         break;
1081                 case STMF_ERROR_PERM:
1082                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1083                             gettext("permission denied"));
1084                         ret++;
1085                         break;
1086                 case STMF_ERROR_INVALID_BLKSIZE:
1087                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1088                             gettext("invalid block size"));
1089                         ret++;
1090                         break;
1091                 case STMF_ERROR_GUID_IN_USE:
1092                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1093                             gettext("guid in use"));
1094                         ret++;
1095                         break;
1096                 case STMF_ERROR_META_FILE_NAME:
1097                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1098                             gettext("meta file error"));
1099                         ret++;
1100                         break;
1101                 case STMF_ERROR_DATA_FILE_NAME:
1102                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1103                             gettext("data file error"));
1104                         ret++;
1105                         break;
1106                 case STMF_ERROR_FILE_SIZE_INVALID:
1107                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1108                             gettext("file size invalid"));
1109                         ret++;
1110                         break;
1111                 case STMF_ERROR_SIZE_OUT_OF_RANGE:
1112                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1113                             gettext("invalid size"));
1114                         ret++;
1115                         break;
1116                 case STMF_ERROR_META_CREATION:
1117                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1118                             gettext("could not create meta file"));
1119                         ret++;
1120                         break;
1121                 case STMF_ERROR_INVALID_PROP:
1122                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1123                             gettext("invalid property for modify"));
1124                         ret++;
1125                         break;
1126                 case STMF_ERROR_WRITE_CACHE_SET:
1127                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1128                             gettext("could not set write cache"));
1129                         ret++;
1130                         break;
1131                 case STMF_ERROR_ACCESS_STATE_SET:
1132                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1133                             gettext("cannot modify while in standby mode"));
1134                         ret++;
1135                         break;
1136                 default:
1137                         (void) fprintf(stderr, "%s: %s: %s: %d\n", cmdName,
1138                             gettext("could not set property"), propString,
1139                             stmfRet);
1140                         ret++;
1141                         break;
1142         }
1143 
1144         return (ret);
1145 }
1146 
1147 
1148 /*
1149  * importLuFunc
1150  *
1151  * Create a logical unit
1152  *
1153  */
1154 /*ARGSUSED*/
1155 static int
1156 importLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
1157     void *args)
1158 {
1159         int stmfRet = 0;
1160         int ret = 0;
1161         char guidAsciiBuf[33];
1162         stmfGuid createdGuid;
1163 
1164         stmfRet = stmfImportLu(STMF_DISK, operands[0], &createdGuid);
1165         switch (stmfRet) {
1166                 case STMF_STATUS_SUCCESS:
1167                         break;
1168                 case STMF_ERROR_BUSY:
1169                 case STMF_ERROR_LU_BUSY:
1170                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1171                             gettext("resource busy"));
1172                         ret++;
1173                         break;
1174                 case STMF_ERROR_PERM:
1175                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1176                             gettext("permission denied"));
1177                         ret++;
1178                         break;
1179                 case STMF_ERROR_FILE_IN_USE:
1180                         (void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
1181                             operands[0], gettext("in use"));
1182                         ret++;
1183                         break;
1184                 case STMF_ERROR_GUID_IN_USE:
1185                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1186                             gettext("guid in use"));
1187                         ret++;
1188                         break;
1189                 case STMF_ERROR_META_FILE_NAME:
1190                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1191                             gettext("meta file error"));
1192                         ret++;
1193                         break;
1194                 case STMF_ERROR_DATA_FILE_NAME:
1195                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1196                             gettext("data file error"));
1197                         ret++;
1198                         break;
1199                 case STMF_ERROR_META_CREATION:
1200                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1201                             gettext("could not create meta file"));
1202                         ret++;
1203                         break;
1204                 case STMF_ERROR_WRITE_CACHE_SET:
1205                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1206                             gettext("could not set write cache"));
1207                         ret++;
1208                         break;
1209                 default:
1210                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1211                             gettext("unknown error"));
1212                         ret++;
1213                         break;
1214         }
1215 
1216         if (ret != STMF_STATUS_SUCCESS) {
1217                 goto done;
1218         }
1219 
1220         (void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
1221             "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
1222             "%02X%02X%02X%02X%02X%02X",
1223             createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
1224             createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
1225             createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
1226             createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
1227             createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
1228             createdGuid.guid[15]);
1229         (void) printf("Logical unit imported: %s\n", guidAsciiBuf);
1230 
1231 done:
1232         return (ret);
1233 }
1234 
1235 static int
1236 setLuPropFromInput(luResource hdl, char *optarg)
1237 {
1238         char *prop = NULL;
1239         char *propVal = NULL;
1240         char *lasts = NULL;
1241         uint32_t propId;
1242         int ret = 0;
1243 
1244         prop = strtok_r(optarg, "=", &lasts);
1245         if ((propVal = strtok_r(NULL, "=", &lasts)) == NULL) {
1246                 (void) fprintf(stderr, "%s: %s: %s\n",
1247                     cmdName, optarg,
1248                     gettext("invalid property specifier - prop=val\n"));
1249                 return (1);
1250         }
1251 
1252         ret = convertCharToPropId(prop, &propId);
1253         if (ret != 0) {
1254                 (void) fprintf(stderr, "%s: %s: %s\n",
1255                     cmdName, gettext("invalid property specified"), prop);
1256                 return (1);
1257         }
1258 
1259         ret = stmfSetLuProp(hdl, propId, propVal);
1260         if (ret != STMF_STATUS_SUCCESS) {
1261                 (void) fprintf(stderr, "%s: %s %s: ",
1262                     cmdName, gettext("unable to set"), prop);
1263                 switch (ret) {
1264                         case STMF_ERROR_INVALID_PROPSIZE:
1265                                 (void) fprintf(stderr, "invalid length\n");
1266                                 break;
1267                         case STMF_ERROR_INVALID_ARG:
1268                                 (void) fprintf(stderr, "bad format\n");
1269                                 break;
1270                         default:
1271                                 (void) fprintf(stderr, "\n");
1272                                 break;
1273                 }
1274                 return (1);
1275         }
1276 
1277         return (0);
1278 }
1279 
1280 static int
1281 convertCharToPropId(char *prop, uint32_t *propId)
1282 {
1283         if (strcasecmp(prop, GUID) == 0) {
1284                 *propId = STMF_LU_PROP_GUID;
1285         } else if (strcasecmp(prop, ALIAS) == 0) {
1286                 *propId = STMF_LU_PROP_ALIAS;
1287         } else if (strcasecmp(prop, VID) == 0) {
1288                 *propId = STMF_LU_PROP_VID;
1289         } else if (strcasecmp(prop, PID) == 0) {
1290                 *propId = STMF_LU_PROP_PID;
1291         } else if (strcasecmp(prop, WRITE_PROTECT) == 0) {
1292                 *propId = STMF_LU_PROP_WRITE_PROTECT;
1293         } else if (strcasecmp(prop, WRITEBACK_CACHE_DISABLE) == 0) {
1294                 *propId = STMF_LU_PROP_WRITE_CACHE_DISABLE;
1295         } else if (strcasecmp(prop, BLOCK_SIZE) == 0) {
1296                 *propId = STMF_LU_PROP_BLOCK_SIZE;
1297         } else if (strcasecmp(prop, SERIAL_NUMBER) == 0) {
1298                 *propId = STMF_LU_PROP_SERIAL_NUM;
1299         } else if (strcasecmp(prop, COMPANY_ID) == 0) {
1300                 *propId = STMF_LU_PROP_COMPANY_ID;
1301         } else if (strcasecmp(prop, META_FILE) == 0) {
1302                 *propId = STMF_LU_PROP_META_FILENAME;
1303         } else if (strcasecmp(prop, MGMT_URL) == 0) {
1304                 *propId = STMF_LU_PROP_MGMT_URL;
1305         } else if (strcasecmp(prop, HOST_ID) == 0) {
1306                 *propId = STMF_LU_PROP_HOST_ID;
1307         } else {
1308                 return (1);
1309         }
1310         return (0);
1311 }
1312 
1313 /*
1314  * deleteLuFunc
1315  *
1316  * Delete a logical unit
1317  *
1318  */
1319 /*ARGSUSED*/
1320 static int
1321 deleteLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
1322     void *args)
1323 {
1324         int i, j;
1325         int ret = 0;
1326         int stmfRet;
1327         unsigned int inGuid[sizeof (stmfGuid)];
1328         stmfGuid delGuid;
1329         boolean_t keepViews = B_FALSE;
1330         boolean_t viewEntriesRemoved = B_FALSE;
1331         boolean_t noLunFound = B_FALSE;
1332         boolean_t views = B_FALSE;
1333         boolean_t notValidHexNumber = B_FALSE;
1334         char sGuid[GUID_INPUT + 1];
1335         stmfViewEntryList *viewEntryList = NULL;
1336 
1337         for (; options->optval; options++) {
1338                 switch (options->optval) {
1339                         /* Keep views for logical unit */
1340                         case 'k':
1341                                 keepViews = B_TRUE;
1342                                 break;
1343                         default:
1344                                 (void) fprintf(stderr, "%s: %c: %s\n",
1345                                     cmdName, options->optval,
1346                                     gettext("unknown option"));
1347                                 return (1);
1348                 }
1349         }
1350 
1351 
1352         for (i = 0; i < operandLen; i++) {
1353                 for (j = 0; j < GUID_INPUT; j++) {
1354                         if (!isxdigit(operands[i][j])) {
1355                                 notValidHexNumber = B_TRUE;
1356                                 break;
1357                         }
1358                         sGuid[j] = tolower(operands[i][j]);
1359                 }
1360                 if ((notValidHexNumber == B_TRUE) ||
1361                     (strlen(operands[i]) != GUID_INPUT)) {
1362                         (void) fprintf(stderr, "%s: %s: %s%d%s\n",
1363                             cmdName, operands[i], gettext("must be "),
1364                             GUID_INPUT,
1365                             gettext(" hexadecimal digits long"));
1366                         notValidHexNumber = B_FALSE;
1367                         ret++;
1368                         continue;
1369                 }
1370 
1371                 sGuid[j] = 0;
1372 
1373                 (void) sscanf(sGuid,
1374                     "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1375                     &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
1376                     &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
1377                     &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
1378                     &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
1379 
1380                 for (j = 0; j < sizeof (stmfGuid); j++) {
1381                         delGuid.guid[j] = inGuid[j];
1382                 }
1383 
1384                 stmfRet = stmfDeleteLu(&delGuid);
1385                 switch (stmfRet) {
1386                         case STMF_STATUS_SUCCESS:
1387                                 break;
1388                         case STMF_ERROR_NOT_FOUND:
1389                                 noLunFound = B_TRUE;
1390                                 break;
1391                         case STMF_ERROR_BUSY:
1392                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1393                                     gettext("resource busy"));
1394                                 ret++;
1395                                 break;
1396                         case STMF_ERROR_PERM:
1397                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1398                                     gettext("permission denied"));
1399                                 ret++;
1400                                 break;
1401                         default:
1402                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1403                                     gettext("unknown error"));
1404                                 ret++;
1405                                 break;
1406                 }
1407 
1408                 if (!keepViews) {
1409                         stmfRet = stmfGetViewEntryList(&delGuid,
1410                             &viewEntryList);
1411                         if (stmfRet == STMF_STATUS_SUCCESS) {
1412                                 for (j = 0; j < viewEntryList->cnt; j++) {
1413                                         (void) stmfRemoveViewEntry(&delGuid,
1414                                             viewEntryList->ve[j].veIndex);
1415                                 }
1416                                 /* check if viewEntryList is empty */
1417                                 if (viewEntryList->cnt != 0)
1418                                         viewEntriesRemoved = B_TRUE;
1419                                 stmfFreeMemory(viewEntryList);
1420                         } else {
1421                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1422                                     gettext("unable to remove view entries\n"));
1423                                 ret++;
1424                         }
1425 
1426                 }
1427                 if (keepViews) {
1428                         stmfRet = stmfGetViewEntryList(&delGuid,
1429                             &viewEntryList);
1430                         if (stmfRet == STMF_STATUS_SUCCESS) {
1431                                 views = B_TRUE;
1432                                 stmfFreeMemory(viewEntryList);
1433                         }
1434                 }
1435 
1436                 if ((!viewEntriesRemoved && noLunFound && !views) ||
1437                     (!views && keepViews && noLunFound)) {
1438                         (void) fprintf(stderr, "%s: %s: %s\n",
1439                             cmdName, sGuid,
1440                             gettext("not found"));
1441                         ret++;
1442                 }
1443                 noLunFound = viewEntriesRemoved = views = B_FALSE;
1444         }
1445         return (ret);
1446 }
1447 
1448 
1449 /*
1450  * createTargetGroupFunc
1451  *
1452  * Create a target group
1453  *
1454  */
1455 /*ARGSUSED*/
1456 static int
1457 createTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1458     void *args)
1459 {
1460         int ret = 0;
1461         int stmfRet;
1462         wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1463         stmfGroupName groupName = {0};
1464 
1465         (void) strlcpy(groupName, operands[0], sizeof (groupName));
1466         (void) mbstowcs(groupNamePrint, (char *)groupName,
1467             sizeof (stmfGroupName) - 1);
1468         /* call create group */
1469         stmfRet = stmfCreateTargetGroup(&groupName);
1470         switch (stmfRet) {
1471                 case STMF_STATUS_SUCCESS:
1472                         break;
1473                 case STMF_ERROR_EXISTS:
1474                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1475                             groupNamePrint, gettext("already exists"));
1476                         ret++;
1477                         break;
1478                 case STMF_ERROR_BUSY:
1479                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1480                             groupNamePrint, gettext("resource busy"));
1481                         ret++;
1482                         break;
1483                 case STMF_ERROR_PERM:
1484                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1485                             gettext("permission denied"));
1486                         ret++;
1487                         break;
1488                 case STMF_ERROR_SERVICE_NOT_FOUND:
1489                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1490                             gettext("STMF service not found"));
1491                         ret++;
1492                         break;
1493                 case STMF_ERROR_SERVICE_DATA_VERSION:
1494                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1495                             gettext("STMF service version incorrect"));
1496                         ret++;
1497                         break;
1498                 default:
1499                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1500                             groupNamePrint, gettext("unknown error"));
1501                         ret++;
1502                         break;
1503         }
1504 
1505         return (ret);
1506 }
1507 
1508 /*
1509  * deleteHostGroupFunc
1510  *
1511  * Delete a host group
1512  *
1513  */
1514 /*ARGSUSED*/
1515 static int
1516 deleteHostGroupFunc(int operandLen, char *operands[],
1517     cmdOptions_t *options, void *args)
1518 {
1519         int ret = 0;
1520         int stmfRet;
1521         wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1522         stmfGroupName groupName = {0};
1523 
1524         (void) strlcpy(groupName, operands[0], sizeof (groupName));
1525         (void) mbstowcs(groupNamePrint, (char *)groupName,
1526             sizeof (stmfGroupName) - 1);
1527         /* call delete group */
1528         stmfRet = stmfDeleteHostGroup(&groupName);
1529         switch (stmfRet) {
1530                 case STMF_STATUS_SUCCESS:
1531                         break;
1532                 case STMF_ERROR_NOT_FOUND:
1533                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1534                             groupNamePrint, gettext("not found"));
1535                         ret++;
1536                         break;
1537                 case STMF_ERROR_BUSY:
1538                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1539                             groupNamePrint, gettext("resource busy"));
1540                         ret++;
1541                         break;
1542                 case STMF_ERROR_SERVICE_NOT_FOUND:
1543                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1544                             gettext("STMF service not found"));
1545                         ret++;
1546                         break;
1547                 case STMF_ERROR_PERM:
1548                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1549                             gettext("permission denied"));
1550                         ret++;
1551                         break;
1552                 case STMF_ERROR_GROUP_IN_USE:
1553                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1554                             groupNamePrint,
1555                             gettext("group is in use by existing view entry"));
1556                         ret++;
1557                         break;
1558                 case STMF_ERROR_SERVICE_DATA_VERSION:
1559                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1560                             gettext("STMF service version incorrect"));
1561                         ret++;
1562                         break;
1563                 default:
1564                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1565                             groupNamePrint, gettext("unknown error"));
1566                         ret++;
1567                         break;
1568         }
1569 
1570         return (ret);
1571 }
1572 
1573 /*
1574  * deleteTargetGroupFunc
1575  *
1576  * Delete a target group
1577  *
1578  */
1579 /*ARGSUSED*/
1580 static int
1581 deleteTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1582     void *args)
1583 {
1584         int ret = 0;
1585         int stmfRet;
1586         wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
1587         stmfGroupName groupName = {0};
1588 
1589         (void) strlcpy(groupName, operands[0], sizeof (groupName));
1590         (void) mbstowcs(groupNamePrint, (char *)groupName,
1591             sizeof (stmfGroupName) - 1);
1592         /* call delete group */
1593         stmfRet = stmfDeleteTargetGroup(&groupName);
1594         switch (stmfRet) {
1595                 case STMF_STATUS_SUCCESS:
1596                         break;
1597                 case STMF_ERROR_NOT_FOUND:
1598                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1599                             groupNamePrint, gettext("not found"));
1600                         ret++;
1601                         break;
1602                 case STMF_ERROR_BUSY:
1603                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1604                             groupNamePrint, gettext("resource busy"));
1605                         ret++;
1606                         break;
1607                 case STMF_ERROR_SERVICE_NOT_FOUND:
1608                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1609                             gettext("STMF service not found"));
1610                         ret++;
1611                         break;
1612                 case STMF_ERROR_PERM:
1613                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1614                             gettext("permission denied"));
1615                         ret++;
1616                         break;
1617                 case STMF_ERROR_GROUP_IN_USE:
1618                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1619                             groupNamePrint,
1620                             gettext("group is in use by existing view entry"));
1621                         ret++;
1622                         break;
1623                 case STMF_ERROR_SERVICE_DATA_VERSION:
1624                         (void) fprintf(stderr, "%s: %s\n", cmdName,
1625                             gettext("STMF service version incorrect"));
1626                         ret++;
1627                         break;
1628                 default:
1629                         (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
1630                             groupNamePrint, gettext("unknown error"));
1631                         ret++;
1632                         break;
1633         }
1634 
1635         return (ret);
1636 }
1637 
1638 /*
1639  * listHostGroupFunc
1640  *
1641  * Lists the specified host groups or all if none are specified
1642  *
1643  */
1644 /*ARGSUSED*/
1645 static int
1646 listHostGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1647     void *args)
1648 {
1649         int ret = 0;
1650         int stmfRet;
1651         int i, j, outerLoop;
1652         boolean_t verbose = B_FALSE;
1653         boolean_t found = B_TRUE;
1654         boolean_t operandEntered;
1655         stmfGroupList *groupList;
1656         stmfGroupProperties *groupProps;
1657         wchar_t operandName[sizeof (stmfGroupName)];
1658         wchar_t groupNamePrint[sizeof (stmfGroupName)];
1659 
1660         for (; options->optval; options++) {
1661                 switch (options->optval) {
1662                         case 'v':
1663                                 verbose = B_TRUE;
1664                                 break;
1665                         default:
1666                                 (void) fprintf(stderr, "%s: %c: %s\n",
1667                                     cmdName, options->optval,
1668                                     gettext("unknown option"));
1669                                 return (1);
1670                 }
1671         }
1672 
1673         if (operandLen > 0) {
1674                 outerLoop = operandLen;
1675                 operandEntered = B_TRUE;
1676         } else {
1677                 outerLoop = 1;
1678                 operandEntered = B_FALSE;
1679         }
1680 
1681         stmfRet = stmfGetHostGroupList(&groupList);
1682         if (stmfRet != STMF_STATUS_SUCCESS) {
1683                 switch (stmfRet) {
1684                         case STMF_ERROR_BUSY:
1685                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1686                                     gettext("resource busy"));
1687                                 break;
1688                         case STMF_ERROR_SERVICE_NOT_FOUND:
1689                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1690                                     gettext("STMF service not found"));
1691                                 break;
1692                         case STMF_ERROR_PERM:
1693                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1694                                     gettext("permission denied"));
1695                                 break;
1696                         case STMF_ERROR_SERVICE_DATA_VERSION:
1697                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1698                                     gettext("STMF service version incorrect"));
1699                                 break;
1700                         default:
1701                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1702                                     gettext("unknown error"));
1703                                 break;
1704                 }
1705                 return (1);
1706         }
1707 
1708         for (i = 0; i < outerLoop; i++) {
1709                 for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
1710                         (void) mbstowcs(groupNamePrint,
1711                             (char *)groupList->name[j],
1712                             sizeof (stmfGroupName) - 1);
1713                         groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
1714                         if (operandEntered) {
1715                                 (void) mbstowcs(operandName, operands[i],
1716                                     sizeof (stmfGroupName) - 1);
1717                                 operandName[sizeof (stmfGroupName) - 1] = 0;
1718                                 if (wcscmp(operandName, groupNamePrint)
1719                                     == 0) {
1720                                         found = B_TRUE;
1721                                 }
1722                         }
1723                         if ((found && operandEntered) || !operandEntered) {
1724                                 (void) printf("Host Group: %ws\n",
1725                                     groupNamePrint);
1726                                 if (verbose) {
1727                                         stmfRet = stmfGetHostGroupMembers(
1728                                             &(groupList->name[j]), &groupProps);
1729                                         if (stmfRet != STMF_STATUS_SUCCESS) {
1730                                                 return (1);
1731                                         }
1732                                         printGroupProps(groupProps);
1733                                 }
1734                                 if (found && operandEntered) {
1735                                         break;
1736                                 }
1737                         }
1738 
1739                 }
1740                 if (operandEntered && !found) {
1741                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1742                             operands[i], gettext("not found"));
1743                         ret = 1;
1744                 }
1745         }
1746         return (ret);
1747 }
1748 
1749 /*
1750  * printGroupProps
1751  *
1752  * Prints group members for target or host groups
1753  *
1754  */
1755 static void
1756 printGroupProps(stmfGroupProperties *groupProps)
1757 {
1758         int i;
1759         wchar_t memberIdent[sizeof (groupProps->name[0].ident) + 1] = {0};
1760 
1761 
1762         for (i = 0; i < groupProps->cnt; i++) {
1763                 (void) mbstowcs(memberIdent, (char *)groupProps->name[i].ident,
1764                     sizeof (groupProps->name[0].ident));
1765                 (void) printf("\tMember: %ws\n", memberIdent);
1766         }
1767 }
1768 
1769 /*
1770  * listTargetGroupFunc
1771  *
1772  * Lists the specified target groups or all if none are specified
1773  *
1774  */
1775 /*ARGSUSED*/
1776 static int
1777 listTargetGroupFunc(int operandLen, char *operands[], cmdOptions_t *options,
1778     void *args)
1779 {
1780         int ret = 0;
1781         int stmfRet;
1782         int i, j, outerLoop;
1783         boolean_t verbose = B_FALSE;
1784         boolean_t found = B_TRUE;
1785         boolean_t operandEntered;
1786         stmfGroupList *groupList;
1787         stmfGroupProperties *groupProps;
1788         wchar_t operandName[sizeof (stmfGroupName)];
1789         wchar_t groupNamePrint[sizeof (stmfGroupName)];
1790 
1791         for (; options->optval; options++) {
1792                 switch (options->optval) {
1793                         case 'v':
1794                                 verbose = B_TRUE;
1795                                 break;
1796                         default:
1797                                 (void) fprintf(stderr, "%s: %c: %s\n",
1798                                     cmdName, options->optval,
1799                                     gettext("unknown option"));
1800                                 return (1);
1801                 }
1802         }
1803 
1804         if (operandLen > 0) {
1805                 outerLoop = operandLen;
1806                 operandEntered = B_TRUE;
1807         } else {
1808                 outerLoop = 1;
1809                 operandEntered = B_FALSE;
1810         }
1811 
1812         stmfRet = stmfGetTargetGroupList(&groupList);
1813         if (stmfRet != STMF_STATUS_SUCCESS) {
1814                 switch (stmfRet) {
1815                         case STMF_ERROR_BUSY:
1816                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1817                                     gettext("resource busy"));
1818                                 break;
1819                         case STMF_ERROR_SERVICE_NOT_FOUND:
1820                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1821                                     gettext("STMF service not found"));
1822                                 break;
1823                         case STMF_ERROR_SERVICE_DATA_VERSION:
1824                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1825                                     gettext("STMF service version incorrect"));
1826                                 break;
1827                         case STMF_ERROR_PERM:
1828                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1829                                     gettext("permission denied"));
1830                                 break;
1831                         default:
1832                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1833                                     gettext("unknown error"));
1834                                 break;
1835                 }
1836                 return (1);
1837         }
1838 
1839         for (i = 0; i < outerLoop; i++) {
1840                 for (found = B_FALSE, j = 0; j < groupList->cnt; j++) {
1841                         (void) mbstowcs(groupNamePrint,
1842                             (char *)groupList->name[j],
1843                             sizeof (stmfGroupName) - 1);
1844                         groupNamePrint[sizeof (stmfGroupName) - 1] = 0;
1845                         if (operandEntered) {
1846                                 (void) mbstowcs(operandName, operands[i],
1847                                     sizeof (stmfGroupName) - 1);
1848                                 operandName[sizeof (stmfGroupName) - 1] = 0;
1849                                 if (wcscmp(operandName, groupNamePrint)
1850                                     == 0) {
1851                                         found = B_TRUE;
1852                                 }
1853                         }
1854                         if ((found && operandEntered) || !operandEntered) {
1855                                 (void) printf("Target Group: %ws\n",
1856                                     groupNamePrint);
1857                                 if (verbose) {
1858                                         stmfRet = stmfGetTargetGroupMembers(
1859                                             &(groupList->name[j]), &groupProps);
1860                                         if (stmfRet != STMF_STATUS_SUCCESS) {
1861                                                 return (1);
1862                                         }
1863                                         printGroupProps(groupProps);
1864                                 }
1865                                 if (found && operandEntered) {
1866                                         break;
1867                                 }
1868                         }
1869 
1870                 }
1871                 if (operandEntered && !found) {
1872                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1873                             operands[i], gettext("not found"));
1874                         ret = 1;
1875                 }
1876         }
1877         return (ret);
1878 }
1879 
1880 /*
1881  * listLuFunc
1882  *
1883  * List the logical units and optionally the properties
1884  *
1885  */
1886 /*ARGSUSED*/
1887 static int
1888 listLuFunc(int operandLen, char *operands[], cmdOptions_t *options, void *args)
1889 {
1890         cmdOptions_t *optionList = options;
1891         boolean_t operandEntered;
1892         int i, j;
1893         int ret = 0;
1894         int stmfRet;
1895         int outerLoop;
1896         unsigned int inGuid[sizeof (stmfGuid)];
1897         stmfGuid cmpGuid;
1898         boolean_t verbose = B_FALSE;
1899         boolean_t found;
1900         char sGuid[GUID_INPUT + 1];
1901         stmfGuidList *luList;
1902         stmfLogicalUnitProperties luProps;
1903         boolean_t invalidInput = B_FALSE;
1904         stmfViewEntryList *viewEntryList;
1905 
1906         for (; optionList->optval; optionList++) {
1907                 switch (optionList->optval) {
1908                         case 'v':
1909                                 verbose = B_TRUE;
1910                                 break;
1911                 }
1912         }
1913 
1914         if ((stmfRet = stmfGetLogicalUnitList(&luList))
1915             != STMF_STATUS_SUCCESS) {
1916                 switch (stmfRet) {
1917                         case STMF_ERROR_SERVICE_NOT_FOUND:
1918                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1919                                     gettext("STMF service not found"));
1920                                 break;
1921                         case STMF_ERROR_BUSY:
1922                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1923                                     gettext("resource busy"));
1924                                 break;
1925                         case STMF_ERROR_PERM:
1926                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1927                                     gettext("permission denied"));
1928                                 break;
1929                         case STMF_ERROR_SERVICE_DATA_VERSION:
1930                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1931                                     gettext("STMF service version incorrect"));
1932                                 break;
1933                         default:
1934                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
1935                                     gettext("list failed"));
1936                                 break;
1937                 }
1938                 return (1);
1939         }
1940 
1941         if (operandLen > 0) {
1942                 operandEntered = B_TRUE;
1943                 outerLoop = operandLen;
1944         } else {
1945                 operandEntered = B_FALSE;
1946                 outerLoop = 1;
1947         }
1948 
1949 
1950         for (invalidInput = B_FALSE, i = 0; i < outerLoop; i++) {
1951                 if (operandEntered) {
1952                         if (strlen(operands[i]) != GUID_INPUT) {
1953                                 invalidInput = B_TRUE;
1954                         } else {
1955                                 for (j = 0; j < GUID_INPUT; j++) {
1956                                         if (!isxdigit(operands[i][j])) {
1957                                                 invalidInput = B_TRUE;
1958                                                 break;
1959                                         }
1960                                 }
1961                         }
1962                         if (invalidInput) {
1963                                 (void) fprintf(stderr, "%s: %s: %s%d%s\n",
1964                                     cmdName, operands[i], gettext("must be "),
1965                                     GUID_INPUT,
1966                                     gettext(" hexadecimal digits long"));
1967                                 invalidInput = B_FALSE;
1968                                 continue;
1969                         }
1970 
1971                         for (j = 0; j < GUID_INPUT; j++) {
1972                                 sGuid[j] = tolower(operands[i][j]);
1973                         }
1974                         sGuid[j] = 0;
1975 
1976                         (void) sscanf(sGuid,
1977                             "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1978                             &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
1979                             &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
1980                             &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
1981                             &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
1982 
1983                         for (j = 0; j < sizeof (stmfGuid); j++) {
1984                                 cmpGuid.guid[j] = inGuid[j];
1985                         }
1986                 }
1987 
1988                 for (found = B_FALSE, j = 0; j < luList->cnt; j++) {
1989                         if (operandEntered) {
1990                                 if (bcmp(luList->guid[j].guid, cmpGuid.guid,
1991                                     sizeof (stmfGuid)) == 0) {
1992                                         found = B_TRUE;
1993                                 }
1994                         }
1995                         if ((found && operandEntered) || !operandEntered) {
1996                                 (void) printf("LU Name: ");
1997                                 printGuid(&luList->guid[j], stdout);
1998                                 (void) printf("\n");
1999 
2000                                 if (verbose) {
2001                                         stmfRet = stmfGetLogicalUnitProperties(
2002                                             &(luList->guid[j]), &luProps);
2003                                         if (stmfRet == STMF_STATUS_SUCCESS) {
2004                                                 printLuProps(&luProps);
2005                                         } else {
2006                                                 (void) fprintf(stderr, "%s:",
2007                                                     cmdName);
2008                                                 printGuid(&luList->guid[j],
2009                                                     stderr);
2010                                                 (void) fprintf(stderr, "%s\n",
2011                                                     gettext(" get properties "
2012                                                     "failed"));
2013                                         }
2014                                         stmfRet = stmfGetViewEntryList(
2015                                             &(luList->guid[j]),
2016                                             &viewEntryList);
2017                                         (void) printf(PROPS_FORMAT,
2018                                             "View Entry Count");
2019                                         if (stmfRet == STMF_STATUS_SUCCESS) {
2020                                                 (void) printf("%d",
2021                                                     viewEntryList->cnt);
2022                                         } else {
2023                                                 (void) printf("unknown");
2024                                         }
2025                                         (void) printf("\n");
2026                                         ret = printExtLuProps(
2027                                             &(luList->guid[j]));
2028                                 }
2029                                 if (found && operandEntered) {
2030                                         break;
2031                                 }
2032                         }
2033 
2034                 }
2035                 if (operandEntered && !found) {
2036                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2037                             operands[i], gettext("not found"));
2038                         ret = 1;
2039                 }
2040         }
2041 
2042         return (ret);
2043 }
2044 
2045 static void
2046 printGuid(stmfGuid *guid, FILE *stream)
2047 {
2048         int i;
2049         for (i = 0; i < 16; i++) {
2050                 (void) fprintf(stream, "%02X", guid->guid[i]);
2051         }
2052 }
2053 
2054 static int
2055 printExtLuProps(stmfGuid *guid)
2056 {
2057         int stmfRet;
2058         luResource hdl = NULL;
2059         int ret = 0;
2060         char propVal[MAXNAMELEN];
2061         size_t propValSize = sizeof (propVal);
2062 
2063         if ((stmfRet = stmfGetLuResource(guid, &hdl))
2064             != STMF_STATUS_SUCCESS) {
2065                 switch (stmfRet) {
2066                         case STMF_ERROR_BUSY:
2067                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2068                                     gettext("resource busy"));
2069                                 break;
2070                         case STMF_ERROR_PERM:
2071                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2072                                     gettext("permission denied"));
2073                                 break;
2074                         case STMF_ERROR_NOT_FOUND:
2075                                 /* No error here */
2076                                 return (0);
2077                                 break;
2078                         default:
2079                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2080                                     gettext("get extended properties failed"));
2081                                 break;
2082                 }
2083                 return (1);
2084         }
2085 
2086         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_FILENAME, propVal,
2087             &propValSize);
2088         (void) printf(PROPS_FORMAT, "Data File");
2089         if (stmfRet == STMF_STATUS_SUCCESS) {
2090                 (void) printf("%s\n", propVal);
2091         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2092                 (void) printf("not set\n");
2093         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2094                 (void) printf("prop unavailable in standby\n");
2095         } else {
2096                 (void) printf("<error retrieving property>\n");
2097                 ret++;
2098         }
2099 
2100         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_META_FILENAME, propVal,
2101             &propValSize);
2102         (void) printf(PROPS_FORMAT, "Meta File");
2103         if (stmfRet == STMF_STATUS_SUCCESS) {
2104                 (void) printf("%s\n", propVal);
2105         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2106                 (void) printf("not set\n");
2107         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2108                 (void) printf("prop unavailable in standby\n");
2109         } else {
2110                 (void) printf("<error retrieving property>\n");
2111                 ret++;
2112         }
2113 
2114         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SIZE, propVal,
2115             &propValSize);
2116         (void) printf(PROPS_FORMAT, "Size");
2117         if (stmfRet == STMF_STATUS_SUCCESS) {
2118                 (void) printf("%s\n", propVal);
2119         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2120                 (void) printf("not set\n");
2121         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2122                 (void) printf("prop unavailable in standby\n");
2123         } else {
2124                 (void) printf("<error retrieving property>\n");
2125                 ret++;
2126         }
2127 
2128         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_BLOCK_SIZE, propVal,
2129             &propValSize);
2130         (void) printf(PROPS_FORMAT, "Block Size");
2131         if (stmfRet == STMF_STATUS_SUCCESS) {
2132                 (void) printf("%s\n", propVal);
2133         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2134                 (void) printf("not set\n");
2135         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2136                 (void) printf("prop unavailable in standby\n");
2137         } else {
2138                 (void) printf("<error retrieving property>\n");
2139                 ret++;
2140         }
2141 
2142         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_MGMT_URL, propVal,
2143             &propValSize);
2144         (void) printf(PROPS_FORMAT, "Management URL");
2145         if (stmfRet == STMF_STATUS_SUCCESS) {
2146                 (void) printf("%s\n", propVal);
2147         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2148                 (void) printf("not set\n");
2149         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2150                 (void) printf("prop unavailable in standby\n");
2151         } else {
2152                 (void) printf("<error retrieving property>\n");
2153                 ret++;
2154         }
2155 
2156         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_VID, propVal,
2157             &propValSize);
2158         (void) printf(PROPS_FORMAT, "Vendor ID");
2159         if (stmfRet == STMF_STATUS_SUCCESS) {
2160                 (void) printf("%s\n", propVal);
2161         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2162                 (void) printf("not set\n");
2163         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2164                 (void) printf("prop unavailable in standby\n");
2165         } else {
2166                 (void) printf("<error retrieving property>\n");
2167                 ret++;
2168         }
2169 
2170         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_PID, propVal,
2171             &propValSize);
2172         (void) printf(PROPS_FORMAT, "Product ID");
2173         if (stmfRet == STMF_STATUS_SUCCESS) {
2174                 (void) printf("%s\n", propVal);
2175         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2176                 (void) printf("not set\n");
2177         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2178                 (void) printf("prop unavailable in standby\n");
2179         } else {
2180                 (void) printf("<error retrieving property>\n");
2181                 ret++;
2182         }
2183 
2184         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SERIAL_NUM, propVal,
2185             &propValSize);
2186         (void) printf(PROPS_FORMAT, "Serial Num");
2187         if (stmfRet == STMF_STATUS_SUCCESS) {
2188                 (void) printf("%s\n", propVal);
2189         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2190                 (void) printf("not set\n");
2191         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2192                 (void) printf("prop unavailable in standby\n");
2193         } else {
2194                 (void) printf("<error retrieving property>\n");
2195                 ret++;
2196         }
2197 
2198         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_PROTECT, propVal,
2199             &propValSize);
2200         (void) printf(PROPS_FORMAT, "Write Protect");
2201         if (stmfRet == STMF_STATUS_SUCCESS) {
2202                 (void) printf("%s\n",
2203                     strcasecmp(propVal, "true") ? "Disabled" : "Enabled");
2204         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2205                 (void) printf("not set\n");
2206         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2207                 (void) printf("prop unavailable in standby\n");
2208         } else {
2209                 (void) printf("<error retrieving property>\n");
2210                 ret++;
2211         }
2212 
2213         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_CACHE_DISABLE, propVal,
2214             &propValSize);
2215         (void) printf(PROPS_FORMAT, "Writeback Cache");
2216         if (stmfRet == STMF_STATUS_SUCCESS) {
2217                 (void) printf("%s\n",
2218                     strcasecmp(propVal, "true") ? "Enabled" : "Disabled");
2219         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2220                 (void) printf("not set\n");
2221         } else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
2222                 (void) printf("prop unavailable in standby\n");
2223         } else {
2224                 (void) printf("<error retrieving property>\n");
2225                 ret++;
2226         }
2227 
2228         stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
2229             &propValSize);
2230         (void) printf(PROPS_FORMAT, "Access State");
2231         if (stmfRet == STMF_STATUS_SUCCESS) {
2232                 if (strcmp(propVal, STMF_ACCESS_ACTIVE) == 0) {
2233                         (void) printf("%s\n", "Active");
2234                 } else if (strcmp(propVal,
2235                     STMF_ACCESS_ACTIVE_TO_STANDBY) == 0) {
2236                         (void) printf("%s\n", "Active->Standby");
2237                 } else if (strcmp(propVal, STMF_ACCESS_STANDBY) == 0) {
2238                         (void) printf("%s\n", "Standby");
2239                 } else if (strcmp(propVal,
2240                     STMF_ACCESS_STANDBY_TO_ACTIVE) == 0) {
2241                         (void) printf("%s\n", "Standby->Active");
2242                 } else {
2243                         (void) printf("%s\n", "Unknown");
2244                 }
2245         } else if (stmfRet == STMF_ERROR_NO_PROP) {
2246                 (void) printf("not set\n");
2247         } else {
2248                 (void) printf("<error retrieving property>\n");
2249                 ret++;
2250         }
2251 
2252 done:
2253         (void) stmfFreeLuResource(hdl);
2254         return (ret);
2255 
2256 }
2257 
2258 
2259 /*
2260  * printLuProps
2261  *
2262  * Prints the properties for a logical unit
2263  *
2264  */
2265 static void
2266 printLuProps(stmfLogicalUnitProperties *luProps)
2267 {
2268         (void) printf(PROPS_FORMAT, "Operational Status");
2269         switch (luProps->status) {
2270                 case STMF_LOGICAL_UNIT_ONLINE:
2271                         (void) printf("Online");
2272                         break;
2273                 case STMF_LOGICAL_UNIT_OFFLINE:
2274                         (void) printf("Offline");
2275                         break;
2276                 case STMF_LOGICAL_UNIT_ONLINING:
2277                         (void) printf("Onlining");
2278                         break;
2279                 case STMF_LOGICAL_UNIT_OFFLINING:
2280                         (void) printf("Offlining");
2281                         break;
2282                 case STMF_LOGICAL_UNIT_UNREGISTERED:
2283                         (void) printf("unregistered");
2284                         (void) strncpy(luProps->providerName, "unregistered",
2285                             sizeof (luProps->providerName));
2286                         break;
2287                 default:
2288                         (void) printf("unknown");
2289                         break;
2290         }
2291         (void) printf("\n");
2292         (void) printf(PROPS_FORMAT, "Provider Name");
2293         if (luProps->providerName[0] != 0) {
2294                 (void) printf("%s", luProps->providerName);
2295         } else {
2296                 (void) printf("unknown");
2297         }
2298         (void) printf("\n");
2299         (void) printf(PROPS_FORMAT, "Alias");
2300         if (luProps->alias[0] != 0) {
2301                 (void) printf("%s", luProps->alias);
2302         } else {
2303                 (void) printf("-");
2304         }
2305         (void) printf("\n");
2306 }
2307 
2308 /*
2309  * printTargetProps
2310  *
2311  * Prints the properties for a target
2312  *
2313  */
2314 static void
2315 printTargetProps(stmfTargetProperties *targetProps)
2316 {
2317         (void) printf(PROPS_FORMAT, "Operational Status");
2318         switch (targetProps->status) {
2319                 case STMF_TARGET_PORT_ONLINE:
2320                         (void) printf("Online");
2321                         break;
2322                 case STMF_TARGET_PORT_OFFLINE:
2323                         (void) printf("Offline");
2324                         break;
2325                 case STMF_TARGET_PORT_ONLINING:
2326                         (void) printf("Onlining");
2327                         break;
2328                 case STMF_TARGET_PORT_OFFLINING:
2329                         (void) printf("Offlining");
2330                         break;
2331                 default:
2332                         (void) printf("unknown");
2333                         break;
2334         }
2335         (void) printf("\n");
2336         (void) printf(PROPS_FORMAT, "Provider Name");
2337         if (targetProps->providerName[0] != 0) {
2338                 (void) printf("%s", targetProps->providerName);
2339         }
2340         (void) printf("\n");
2341         (void) printf(PROPS_FORMAT, "Alias");
2342         if (targetProps->alias[0] != 0) {
2343                 (void) printf("%s", targetProps->alias);
2344         } else {
2345                 (void) printf("-");
2346         }
2347         (void) printf("\n");
2348         (void) printf(PROPS_FORMAT, "Protocol");
2349         switch (targetProps->protocol) {
2350                 case STMF_PROTOCOL_FIBRE_CHANNEL:
2351                         (void) printf("%s", "Fibre Channel");
2352                         break;
2353                 case STMF_PROTOCOL_ISCSI:
2354                         (void) printf("%s", "iSCSI");
2355                         break;
2356                 case STMF_PROTOCOL_SRP:
2357                         (void) printf("%s", "SRP");
2358                         break;
2359                 case STMF_PROTOCOL_SAS:
2360                         (void) printf("%s", "SAS");
2361                         break;
2362                 default:
2363                         (void) printf("%s", "unknown");
2364                         break;
2365         }
2366 
2367         (void) printf("\n");
2368 }
2369 
2370 /*
2371  * printSessionProps
2372  *
2373  * Prints the session data
2374  *
2375  */
2376 static void
2377 printSessionProps(stmfSessionList *sessionList)
2378 {
2379         int i;
2380         char *cTime;
2381         wchar_t initiator[STMF_IDENT_LENGTH + 1];
2382 
2383         (void) printf(PROPS_FORMAT, "Sessions");
2384         (void) printf("%d\n", sessionList->cnt);
2385         for (i = 0; i < sessionList->cnt; i++) {
2386                 (void) mbstowcs(initiator,
2387                     (char *)sessionList->session[i].initiator.ident,
2388                     STMF_IDENT_LENGTH);
2389                 initiator[STMF_IDENT_LENGTH] = 0;
2390                 (void) printf(LVL3_FORMAT, "Initiator: ");
2391                 (void) printf("%ws\n", initiator);
2392                 (void) printf(LVL4_FORMAT, "Alias: ");
2393                 if (sessionList->session[i].alias[0] != 0) {
2394                         (void) printf("%s", sessionList->session[i].alias);
2395                 } else {
2396                         (void) printf("-");
2397                 }
2398                 (void) printf("\n");
2399                 (void) printf(LVL4_FORMAT, "Logged in since: ");
2400                 cTime = ctime(&(sessionList->session[i].creationTime));
2401                 if (cTime != NULL) {
2402                         (void) printf("%s", cTime);
2403                 } else {
2404                         (void) printf("unknown\n");
2405                 }
2406         }
2407 }
2408 
2409 static int
2410 getStmfState(stmfState *state)
2411 {
2412         int ret;
2413 
2414         ret = stmfGetState(state);
2415         switch (ret) {
2416                 case STMF_STATUS_SUCCESS:
2417                         break;
2418                 case STMF_ERROR_PERM:
2419                         (void) fprintf(stderr, "%s: %s\n", cmdName,
2420                             gettext("permission denied"));
2421                         break;
2422                 case STMF_ERROR_SERVICE_NOT_FOUND:
2423                         (void) fprintf(stderr, "%s: %s\n", cmdName,
2424                             gettext("STMF service not found"));
2425                         break;
2426                 case STMF_ERROR_BUSY:
2427                         (void) fprintf(stderr, "%s: %s\n", cmdName,
2428                             gettext("resource busy"));
2429                         break;
2430                 case STMF_ERROR_SERVICE_DATA_VERSION:
2431                         (void) fprintf(stderr, "%s: %s\n", cmdName,
2432                             gettext("STMF service version incorrect"));
2433                         break;
2434                 default:
2435                         (void) fprintf(stderr, "%s: %s: %d\n", cmdName,
2436                             gettext("unknown error"), ret);
2437                         break;
2438         }
2439         return (ret);
2440 }
2441 
2442 /*
2443  * listStateFunc
2444  *
2445  * List the operational and config state of the stmf service
2446  *
2447  */
2448 /*ARGSUSED*/
2449 static int
2450 listStateFunc(int operandLen, char *operands[], cmdOptions_t *options,
2451     void *args)
2452 {
2453         int ret;
2454         stmfState state;
2455         boolean_t aluaEnabled;
2456         uint32_t node;
2457 
2458         if ((ret = getStmfState(&state)) != STMF_STATUS_SUCCESS)
2459                 return (ret);
2460 
2461         (void) printf("%-18s: ", "Operational Status");
2462         switch (state.operationalState) {
2463                 case STMF_SERVICE_STATE_ONLINE:
2464                         (void) printf("online");
2465                         break;
2466                 case STMF_SERVICE_STATE_OFFLINE:
2467                         (void) printf("offline");
2468                         break;
2469                 case STMF_SERVICE_STATE_ONLINING:
2470                         (void) printf("onlining");
2471                         break;
2472                 case STMF_SERVICE_STATE_OFFLINING:
2473                         (void) printf("offlining");
2474                         break;
2475                 default:
2476                         (void) printf("unknown");
2477                         break;
2478         }
2479         (void) printf("\n");
2480         (void) printf("%-18s: ", "Config Status");
2481         switch (state.configState) {
2482                 case STMF_CONFIG_STATE_NONE:
2483                         (void) printf("uninitialized");
2484                         break;
2485                 case STMF_CONFIG_STATE_INIT:
2486                         (void) printf("initializing");
2487                         break;
2488                 case STMF_CONFIG_STATE_INIT_DONE:
2489                         (void) printf("initialized");
2490                         break;
2491                 default:
2492                         (void) printf("unknown");
2493                         break;
2494         }
2495         (void) printf("\n");
2496         ret = stmfGetAluaState(&aluaEnabled, &node);
2497         switch (ret) {
2498                 case STMF_STATUS_SUCCESS:
2499                         break;
2500                 case STMF_ERROR_PERM:
2501                         (void) fprintf(stderr, "%s: %s\n", cmdName,
2502                             gettext("permission denied"));
2503                         break;
2504                 case STMF_ERROR_BUSY:
2505                         (void) fprintf(stderr, "%s: %s\n", cmdName,
2506                             gettext("resource busy"));
2507                         break;
2508                 default:
2509                         (void) fprintf(stderr, "%s: %s: %d\n", cmdName,
2510                             gettext("unknown error"), ret);
2511                         break;
2512         }
2513         (void) printf("%-18s: ", "ALUA Status");
2514         if (ret == STMF_STATUS_SUCCESS) {
2515                 if (aluaEnabled == B_TRUE) {
2516                         (void) printf("enabled");
2517                 } else {
2518                         (void) printf("disabled");
2519                 }
2520         } else {
2521                 (void) printf("unknown");
2522         }
2523 
2524         (void) printf("\n");
2525         (void) printf("%-18s: ", "ALUA Node");
2526         if (ret == STMF_STATUS_SUCCESS) {
2527                 (void) printf("%d", node);
2528         } else {
2529                 (void) printf("unknown");
2530         }
2531         (void) printf("\n");
2532         return (ret);
2533 }
2534 
2535 /*
2536  * listTargetFunc
2537  *
2538  * list the targets and optionally their properties
2539  *
2540  */
2541 /*ARGSUSED*/
2542 static int
2543 listTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
2544     void *args)
2545 {
2546         cmdOptions_t *optionList = options;
2547         int ret = 0;
2548         int stmfRet;
2549         int i, j;
2550         int outerLoop;
2551         stmfSessionList *sessionList;
2552         stmfDevid devid;
2553         boolean_t operandEntered, found, verbose = B_FALSE;
2554         stmfDevidList *targetList;
2555         wchar_t targetIdent[STMF_IDENT_LENGTH + 1];
2556         stmfTargetProperties targetProps;
2557 
2558         if ((stmfRet = stmfGetTargetList(&targetList)) != STMF_STATUS_SUCCESS) {
2559                 switch (stmfRet) {
2560                         case STMF_ERROR_NOT_FOUND:
2561                                 ret = 0;
2562                                 break;
2563                         case STMF_ERROR_SERVICE_OFFLINE:
2564                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2565                                     gettext("STMF service offline"));
2566                                 break;
2567                         case STMF_ERROR_BUSY:
2568                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2569                                     gettext("resource busy"));
2570                                 break;
2571                         case STMF_ERROR_SERVICE_DATA_VERSION:
2572                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2573                                     gettext("STMF service version incorrect"));
2574                                 break;
2575                         case STMF_ERROR_PERM:
2576                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2577                                     gettext("permission denied"));
2578                                 break;
2579                         default:
2580                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2581                                     gettext("unknown error"));
2582                                 break;
2583                 }
2584                 return (1);
2585         }
2586 
2587         for (; optionList->optval; optionList++) {
2588                 switch (optionList->optval) {
2589                         case 'v':
2590                                 verbose = B_TRUE;
2591                                 break;
2592                 }
2593         }
2594 
2595         if (operandLen > 0) {
2596                 outerLoop = operandLen;
2597                 operandEntered = B_TRUE;
2598         } else {
2599                 outerLoop = 1;
2600                 operandEntered = B_FALSE;
2601         }
2602 
2603         for (i = 0; i < outerLoop; i++) {
2604                 if (operandEntered) {
2605                         bzero(&devid, sizeof (devid));
2606                         (void) parseDevid(operands[i], &devid);
2607                 }
2608                 for (found = B_FALSE, j = 0; j < targetList->cnt; j++) {
2609                         if (operandEntered) {
2610                                 if (bcmp(&devid, &(targetList->devid[j]),
2611                                     sizeof (devid)) == 0) {
2612                                         found = B_TRUE;
2613                                 }
2614                         }
2615                         if ((found && operandEntered) || !operandEntered) {
2616                                 (void) mbstowcs(targetIdent,
2617                                     (char *)targetList->devid[j].ident,
2618                                     STMF_IDENT_LENGTH);
2619                                 targetIdent[STMF_IDENT_LENGTH] = 0;
2620                                 (void) printf("Target: %ws\n", targetIdent);
2621                                 if (verbose) {
2622                                         stmfRet = stmfGetTargetProperties(
2623                                             &(targetList->devid[j]),
2624                                             &targetProps);
2625                                         if (stmfRet == STMF_STATUS_SUCCESS) {
2626                                                 printTargetProps(&targetProps);
2627                                         } else {
2628                                                 (void) fprintf(stderr, "%s:",
2629                                                     cmdName);
2630                                                 (void) fprintf(stderr, "%s\n",
2631                                                     gettext(" get properties"
2632                                                     " failed"));
2633                                         }
2634                                         stmfRet = stmfGetSessionList(
2635                                             &(targetList->devid[j]),
2636                                             &sessionList);
2637                                         if (stmfRet == STMF_STATUS_SUCCESS) {
2638                                                 printSessionProps(sessionList);
2639                                         } else {
2640                                                 (void) fprintf(stderr, "%s:",
2641                                                     cmdName);
2642                                                 (void) fprintf(stderr, "%s\n",
2643                                                     gettext(" get session info"
2644                                                     " failed"));
2645                                         }
2646                                 }
2647                                 if (found && operandEntered) {
2648                                         break;
2649                                 }
2650                         }
2651 
2652                 }
2653                 if (operandEntered && !found) {
2654                         (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2655                             operands[i], "not found");
2656                         ret = 1;
2657                 }
2658         }
2659         return (ret);
2660 }
2661 
2662 /*
2663  * listViewFunc
2664  *
2665  * list the view entries for the specified logical unit
2666  *
2667  */
2668 /*ARGSUSED*/
2669 static int
2670 listViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
2671     void *args)
2672 {
2673         stmfViewEntryList *viewEntryList;
2674         stmfGuid inGuid;
2675         unsigned int guid[sizeof (stmfGuid)];
2676         int ret = 0;
2677         int stmfRet;
2678         int i, j, outerLoop;
2679         boolean_t found = B_TRUE;
2680         boolean_t operandEntered;
2681         uint16_t outputLuNbr;
2682         wchar_t groupName[sizeof (stmfGroupName)];
2683         char sGuid[GUID_INPUT + 1];
2684 
2685 
2686         for (; options->optval; options++) {
2687                 switch (options->optval) {
2688                         case 'l':
2689                                 if (strlen(options->optarg) != GUID_INPUT) {
2690                                         (void) fprintf(stderr,
2691                                             "%s: %s: %s%d%s\n",
2692                                             cmdName, options->optarg,
2693                                             gettext("must be "), GUID_INPUT,
2694                                             gettext(" hexadecimal digits"
2695                                             " long"));
2696                                         return (1);
2697                                 }
2698                                 bcopy(options->optarg, sGuid, GUID_INPUT);
2699                                 break;
2700                         default:
2701                                 (void) fprintf(stderr, "%s: %c: %s\n",
2702                                     cmdName, options->optval,
2703                                     gettext("unknown option"));
2704                                 return (1);
2705                 }
2706         }
2707 
2708         if (operandLen > 0) {
2709                 outerLoop = operandLen;
2710                 operandEntered = B_TRUE;
2711         } else {
2712                 outerLoop = 1;
2713                 operandEntered = B_FALSE;
2714         }
2715 
2716         for (i = 0; i < 32; i++)
2717                 sGuid[i] = tolower(sGuid[i]);
2718         sGuid[i] = 0;
2719 
2720         (void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
2721             &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
2722             &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
2723             &guid[12], &guid[13], &guid[14], &guid[15]);
2724 
2725         for (i = 0; i < sizeof (stmfGuid); i++) {
2726                 inGuid.guid[i] = guid[i];
2727         }
2728 
2729         if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
2730             != STMF_STATUS_SUCCESS) {
2731 
2732                 switch (stmfRet) {
2733                         case STMF_ERROR_BUSY:
2734                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2735                                     sGuid, gettext("resource busy"));
2736                                 break;
2737                         case STMF_ERROR_SERVICE_NOT_FOUND:
2738                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2739                                     gettext("STMF service not found"));
2740                                 break;
2741                         case STMF_ERROR_SERVICE_DATA_VERSION:
2742                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2743                                     gettext("STMF service version incorrect"));
2744                                 break;
2745                         case STMF_ERROR_PERM:
2746                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2747                                     gettext("permission denied"));
2748                                 break;
2749                         default:
2750                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2751                                     sGuid, gettext("unknown error"));
2752                                 break;
2753                 }
2754                 return (1);
2755         }
2756 
2757         if (viewEntryList->cnt == 0) {
2758                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2759                     sGuid, gettext("no views found"));
2760                 return (1);
2761         }
2762 
2763         for (i = 0; i < outerLoop; i++) {
2764                 for (found = B_FALSE, j = 0; j < viewEntryList->cnt; j++) {
2765                         if (operandEntered) {
2766                                 if (atoi(operands[i]) ==
2767                                     viewEntryList->ve[j].veIndex) {
2768                                         found = B_TRUE;
2769                                 }
2770                         }
2771                         if ((found && operandEntered) || !operandEntered) {
2772                                 (void) printf("View Entry: %d\n",
2773                                     viewEntryList->ve[j].veIndex);
2774                                 (void) printf(VIEW_FORMAT, "Host group");
2775                                 if (viewEntryList->ve[j].allHosts) {
2776                                         (void) printf("All\n");
2777                                 } else {
2778                                         (void) mbstowcs(groupName,
2779                                             viewEntryList->ve[j].hostGroup,
2780                                             sizeof (stmfGroupName) - 1);
2781                                         groupName[sizeof (stmfGroupName) - 1]
2782                                             = 0;
2783                                         (void) printf("%ws\n", groupName);
2784                                 }
2785                                 (void) printf(VIEW_FORMAT, "Target group");
2786                                 if (viewEntryList->ve[j].allTargets) {
2787                                         (void) printf("All\n");
2788                                 } else {
2789                                         (void) mbstowcs(groupName,
2790                                             viewEntryList->ve[j].targetGroup,
2791                                             sizeof (stmfGroupName) - 1);
2792                                         groupName[sizeof (stmfGroupName) - 1]
2793                                             = 0;
2794                                         (void) printf("%ws\n", groupName);
2795                                 }
2796                                 outputLuNbr = ((viewEntryList->ve[j].luNbr[0] &
2797                                     0x3F) << 8) | viewEntryList->ve[j].luNbr[1];
2798                                 (void) printf(VIEW_FORMAT, "LUN");
2799                                 (void) printf("%d\n", outputLuNbr);
2800                                 if (found && operandEntered) {
2801                                         break;
2802                                 }
2803                         }
2804                 }
2805                 if (operandEntered && !found) {
2806                         (void) fprintf(stderr, "%s: %s, %s: %s\n", cmdName,
2807                             sGuid, operands[i], gettext("not found"));
2808                         ret = 1;
2809                 }
2810         }
2811 
2812         return (ret);
2813 }
2814 
2815 
2816 /*
2817  * onlineOfflineLu
2818  *
2819  * Purpose: Online or offline a logical unit
2820  *
2821  * lu - logical unit to online or offline
2822  *
2823  * state - ONLINE_LU
2824  *         OFFLINE_LU
2825  */
2826 static int
2827 onlineOfflineLu(char *lu, int state)
2828 {
2829         char sGuid[GUID_INPUT + 1];
2830         stmfGuid inGuid;
2831         unsigned int guid[sizeof (stmfGuid)];
2832         int i;
2833         int ret = 0, stmfRet;
2834         stmfLogicalUnitProperties luProps;
2835 
2836         if (strlen(lu) != GUID_INPUT) {
2837                 (void) fprintf(stderr, "%s: %s: %s %d %s\n", cmdName, lu,
2838                     gettext("must be"), GUID_INPUT,
2839                     gettext("hexadecimal digits long"));
2840                 return (1);
2841         }
2842 
2843         bcopy(lu, sGuid, GUID_INPUT);
2844 
2845         for (i = 0; i < 32; i++)
2846                 sGuid[i] = tolower(sGuid[i]);
2847         sGuid[i] = 0;
2848 
2849         (void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
2850             &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
2851             &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
2852             &guid[12], &guid[13], &guid[14], &guid[15]);
2853 
2854         for (i = 0; i < sizeof (stmfGuid); i++) {
2855                 inGuid.guid[i] = guid[i];
2856         }
2857 
2858         if (state == ONLINE_LU) {
2859                 ret = stmfOnlineLogicalUnit(&inGuid);
2860         } else if (state == OFFLINE_LU) {
2861                 ret = stmfOfflineLogicalUnit(&inGuid);
2862         } else {
2863                 return (STMFADM_FAILURE);
2864         }
2865         if (ret != STMF_STATUS_SUCCESS) {
2866                 switch (ret) {
2867                         case STMF_ERROR_PERM:
2868                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2869                                     gettext("permission denied"));
2870                                 break;
2871                         case STMF_ERROR_SERVICE_NOT_FOUND:
2872                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2873                                     gettext("STMF service not found"));
2874                                 break;
2875                         case STMF_ERROR_BUSY:
2876                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2877                                     gettext("resource busy"));
2878                                 break;
2879                         case STMF_ERROR_NOT_FOUND:
2880                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
2881                                     lu, gettext("not found"));
2882                                 break;
2883                         case STMF_ERROR_SERVICE_DATA_VERSION:
2884                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2885                                     gettext("STMF service version incorrect"));
2886                                 break;
2887                         default:
2888                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2889                                     gettext("unknown error"));
2890                                 break;
2891                 }
2892         } else {
2893                 struct timespec ts = {0};
2894                 unsigned int    count = 0;
2895                 uint32_t        ret_state;
2896 
2897                 ret_state = (state == ONLINE_LU) ?
2898                     STMF_LOGICAL_UNIT_ONLINING : STMF_LOGICAL_UNIT_OFFLINING;
2899                 ts.tv_nsec = DELAYED_EXEC_WAIT_INTERVAL;
2900 
2901                 /* CONSTCOND */
2902                 while (1) {
2903                         stmfRet = stmfGetLogicalUnitProperties(&inGuid,
2904                             &luProps);
2905                         if (stmfRet == STMF_STATUS_SUCCESS)
2906                                 ret_state = luProps.status;
2907 
2908                         if ((state == ONLINE_LU &&
2909                             ret_state == STMF_LOGICAL_UNIT_ONLINE) ||
2910                             (state == OFFLINE_LU &&
2911                             ret_state == STMF_LOGICAL_UNIT_OFFLINE))
2912                                 return (STMFADM_SUCCESS);
2913 
2914                         if ((state == ONLINE_LU &&
2915                             ret_state == STMF_LOGICAL_UNIT_OFFLINE) ||
2916                             (state == OFFLINE_LU &&
2917                             ret_state == STMF_LOGICAL_UNIT_ONLINE))
2918                                 return (STMFADM_FAILURE);
2919 
2920                         if (++count ==  DELAYED_EXEC_WAIT_MAX) {
2921                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2922                                     gettext("Logical Unit state change request "
2923                                     "submitted. Waiting for completion "
2924                                     "timed out"));
2925                                 return (STMFADM_FAILURE);
2926                         }
2927                         (void) nanosleep(&ts, NULL);
2928                 }
2929         }
2930         return (STMFADM_FAILURE);
2931 }
2932 
2933 /*
2934  * onlineLuFunc
2935  *
2936  * Purpose: Online a logical unit
2937  *
2938  */
2939 /*ARGSUSED*/
2940 static int
2941 onlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
2942     void *args)
2943 {
2944         int ret;
2945         stmfState state;
2946 
2947         ret = getStmfState(&state);
2948         if (ret != STMF_STATUS_SUCCESS)
2949                 return (ret);
2950         if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
2951             state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
2952                 (void) fprintf(stderr, "%s: %s\n", cmdName,
2953                     gettext("STMF service is offline"));
2954                 return (1);
2955         }
2956         return (onlineOfflineLu(operands[0], ONLINE_LU));
2957 }
2958 
2959 /*
2960  * offlineLuFunc
2961  *
2962  * Purpose: Offline a logical unit
2963  *
2964  */
2965 /*ARGSUSED*/
2966 static int
2967 offlineLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
2968     void *args)
2969 {
2970         return (onlineOfflineLu(operands[0], OFFLINE_LU));
2971 }
2972 
2973 /*
2974  * onlineOfflineTarget
2975  *
2976  * Purpose: Online or offline a target
2977  *
2978  * target - target to online or offline
2979  *
2980  * state - ONLINE_TARGET
2981  *         OFFLINE_TARGET
2982  */
2983 static int
2984 onlineOfflineTarget(char *target, int state)
2985 {
2986         int ret = 0, stmfRet = 0;
2987         stmfDevid devid;
2988         stmfTargetProperties targetProps;
2989 
2990         if (parseDevid(target, &devid) != 0) {
2991                 (void) fprintf(stderr, "%s: %s: %s\n",
2992                     cmdName, target, gettext("unrecognized device id"));
2993                 return (1);
2994         }
2995         if (state == ONLINE_TARGET) {
2996                 ret = stmfOnlineTarget(&devid);
2997         } else if (state == OFFLINE_TARGET) {
2998                 ret = stmfOfflineTarget(&devid);
2999         } else {
3000                 return (STMFADM_FAILURE);
3001         }
3002         if (ret != STMF_STATUS_SUCCESS) {
3003                 switch (ret) {
3004                         case STMF_ERROR_PERM:
3005                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3006                                     gettext("permission denied"));
3007                                 break;
3008                         case STMF_ERROR_SERVICE_NOT_FOUND:
3009                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3010                                     gettext("STMF service not found"));
3011                                 break;
3012                         case STMF_ERROR_BUSY:
3013                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3014                                     gettext("resource busy"));
3015                                 break;
3016                         case STMF_ERROR_NOT_FOUND:
3017                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3018                                     target, gettext("not found"));
3019                                 break;
3020                         case STMF_ERROR_SERVICE_DATA_VERSION:
3021                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3022                                     gettext("STMF service version incorrect"));
3023                                 break;
3024                         default:
3025                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3026                                     gettext("unknown error"));
3027                                 break;
3028                 }
3029         } else {
3030                 struct timespec  ts = {0};
3031                 unsigned int count = 0;
3032                 uint32_t        ret_state;
3033 
3034                 ret_state = (state == ONLINE_TARGET) ?
3035                     STMF_TARGET_PORT_ONLINING : STMF_TARGET_PORT_OFFLINING;
3036                 ts.tv_nsec = DELAYED_EXEC_WAIT_INTERVAL;
3037 
3038                 /* CONSTCOND */
3039                 while (1) {
3040                         stmfRet = stmfGetTargetProperties(&devid, &targetProps);
3041                         if (stmfRet == STMF_STATUS_SUCCESS)
3042                                 ret_state = targetProps.status;
3043 
3044                         if ((state == ONLINE_TARGET &&
3045                             ret_state == STMF_TARGET_PORT_ONLINE) ||
3046                             (state == OFFLINE_TARGET &&
3047                             ret_state == STMF_TARGET_PORT_OFFLINE)) {
3048                                 return (STMFADM_SUCCESS);
3049                         }
3050 
3051                         if ((state == ONLINE_TARGET &&
3052                             ret_state == STMF_TARGET_PORT_OFFLINE) ||
3053                             (state == OFFLINE_TARGET &&
3054                             ret_state == STMF_TARGET_PORT_ONLINE)) {
3055                                 return (STMFADM_FAILURE);
3056                         }
3057 
3058                         if (++count ==  DELAYED_EXEC_WAIT_MAX) {
3059                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3060                                     gettext("Target state change request "
3061                                     "submitted. Waiting for completion "
3062                                     "timed out."));
3063                                 return (STMFADM_FAILURE);
3064                         }
3065                         (void) nanosleep(&ts, NULL);
3066                 }
3067         }
3068         return (STMFADM_FAILURE);
3069 }
3070 
3071 /*
3072  * onlineTargetFunc
3073  *
3074  * Purpose: Online a target
3075  *
3076  */
3077 /*ARGSUSED*/
3078 static int
3079 onlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
3080     void *args)
3081 {
3082         int ret;
3083         stmfState state;
3084 
3085         ret = getStmfState(&state);
3086         if (ret != STMF_STATUS_SUCCESS)
3087                 return (ret);
3088         if (state.operationalState == STMF_SERVICE_STATE_OFFLINE ||
3089             state.operationalState == STMF_SERVICE_STATE_OFFLINING) {
3090                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3091                     gettext("STMF service is offline"));
3092                 return (1);
3093         }
3094         return (onlineOfflineTarget(operands[0], ONLINE_TARGET));
3095 }
3096 
3097 /*
3098  * offlineTargetFunc
3099  *
3100  * Purpose: Offline a target
3101  *
3102  */
3103 /*ARGSUSED*/
3104 static int
3105 offlineTargetFunc(int operandLen, char *operands[], cmdOptions_t *options,
3106     void *args)
3107 {
3108         return (onlineOfflineTarget(operands[0], OFFLINE_TARGET));
3109 }
3110 
3111 
3112 /*ARGSUSED*/
3113 static int
3114 removeHostGroupMemberFunc(int operandLen, char *operands[],
3115     cmdOptions_t *options, void *args)
3116 {
3117         int i;
3118         int ret = 0;
3119         int stmfRet;
3120         stmfGroupName groupName = {0};
3121         stmfDevid devid;
3122         wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
3123 
3124         for (; options->optval; options++) {
3125                 switch (options->optval) {
3126                         case 'g':
3127                                 (void) mbstowcs(groupNamePrint, options->optarg,
3128                                     sizeof (stmfGroupName) - 1);
3129                                 bcopy(options->optarg, groupName,
3130                                     strlen(options->optarg));
3131                                 break;
3132                         default:
3133                                 (void) fprintf(stderr, "%s: %c: %s\n",
3134                                     cmdName, options->optval,
3135                                     gettext("unknown option"));
3136                                 return (1);
3137                 }
3138         }
3139 
3140         for (i = 0; i < operandLen; i++) {
3141                 if (parseDevid(operands[i], &devid) != 0) {
3142                         (void) fprintf(stderr, "%s: %s: %s\n",
3143                             cmdName, operands[i],
3144                             gettext("unrecognized device id"));
3145                         ret++;
3146                         continue;
3147                 }
3148                 stmfRet = stmfRemoveFromHostGroup(&groupName, &devid);
3149                 switch (stmfRet) {
3150                         case STMF_STATUS_SUCCESS:
3151                                 break;
3152                         case STMF_ERROR_MEMBER_NOT_FOUND:
3153                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3154                                     operands[i], gettext("not found"));
3155                                 ret++;
3156                                 break;
3157                         case STMF_ERROR_GROUP_NOT_FOUND:
3158                                 (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
3159                                     groupNamePrint, gettext("not found"));
3160                                 ret++;
3161                                 break;
3162                         case STMF_ERROR_BUSY:
3163                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3164                                     operands[i], "resource busy");
3165                                 ret++;
3166                                 break;
3167                         case STMF_ERROR_SERVICE_NOT_FOUND:
3168                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3169                                     gettext("STMF service not found"));
3170                                 ret++;
3171                                 break;
3172                         case STMF_ERROR_SERVICE_DATA_VERSION:
3173                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3174                                     gettext("STMF service version incorrect"));
3175                                 ret++;
3176                                 break;
3177                         case STMF_ERROR_PERM:
3178                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3179                                     gettext("permission denied"));
3180                                 ret++;
3181                                 break;
3182                         default:
3183                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3184                                     operands[i], gettext("unknown error"));
3185                                 ret++;
3186                                 break;
3187                 }
3188         }
3189 
3190         return (ret);
3191 }
3192 
3193 /*
3194  * removeTargetGroupMemberFunc
3195  *
3196  * Removes one or more members from a target group
3197  *
3198  */
3199 /*ARGSUSED*/
3200 static int
3201 removeTargetGroupMemberFunc(int operandLen, char *operands[],
3202     cmdOptions_t *options, void *args)
3203 {
3204         int i;
3205         int ret = 0;
3206         int stmfRet;
3207         stmfGroupName groupName = {0};
3208         stmfDevid devid;
3209         wchar_t groupNamePrint[sizeof (stmfGroupName)] = {0};
3210 
3211         for (; options->optval; options++) {
3212                 switch (options->optval) {
3213                         case 'g':
3214                                 (void) mbstowcs(groupNamePrint, options->optarg,
3215                                     sizeof (stmfGroupName) - 1);
3216                                 bcopy(options->optarg, groupName,
3217                                     strlen(options->optarg));
3218                                 break;
3219                         default:
3220                                 (void) fprintf(stderr, "%s: %c: %s\n",
3221                                     cmdName, options->optval,
3222                                     gettext("unknown option"));
3223                                 return (1);
3224                 }
3225         }
3226 
3227         for (i = 0; i < operandLen; i++) {
3228                 if (parseDevid(operands[i], &devid) != 0) {
3229                         (void) fprintf(stderr, "%s: %s: %s\n",
3230                             cmdName, operands[i],
3231                             gettext("unrecognized device id"));
3232                         ret++;
3233                         continue;
3234                 }
3235                 stmfRet = stmfRemoveFromTargetGroup(&groupName, &devid);
3236                 switch (stmfRet) {
3237                         case STMF_STATUS_SUCCESS:
3238                                 break;
3239                         case STMF_ERROR_MEMBER_NOT_FOUND:
3240                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3241                                     operands[i], gettext("not found"));
3242                                 ret++;
3243                                 break;
3244                         case STMF_ERROR_GROUP_NOT_FOUND:
3245                                 (void) fprintf(stderr, "%s: %ws: %s\n", cmdName,
3246                                     groupNamePrint, gettext("not found"));
3247                                 ret++;
3248                                 break;
3249                         case STMF_ERROR_BUSY:
3250                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3251                                     operands[i], gettext("resource busy"));
3252                                 ret++;
3253                                 break;
3254                         case STMF_ERROR_SERVICE_NOT_FOUND:
3255                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3256                                     gettext("STMF service not found"));
3257                                 ret++;
3258                                 break;
3259                         case STMF_ERROR_PERM:
3260                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3261                                     gettext("permission denied"));
3262                                 ret++;
3263                                 break;
3264                         case STMF_ERROR_SERVICE_DATA_VERSION:
3265                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3266                                     gettext("STMF service version incorrect"));
3267                                 ret++;
3268                                 break;
3269                         case STMF_ERROR_TG_ONLINE:
3270                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3271                                     gettext("STMF target must be offline"));
3272                                 ret++;
3273                                 break;
3274                         default:
3275                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3276                                     operands[i], gettext("unknown error"));
3277                                 ret++;
3278                                 break;
3279                 }
3280         }
3281 
3282         return (ret);
3283 }
3284 
3285 /*
3286  * removeViewFunc
3287  *
3288  * Removes one or more view entries from a logical unit
3289  *
3290  */
3291 /*ARGSUSED*/
3292 static int
3293 removeViewFunc(int operandLen, char *operands[], cmdOptions_t *options,
3294     void *args)
3295 {
3296         char sGuid[GUID_INPUT + 1];
3297         stmfViewEntryList *viewEntryList;
3298         stmfGuid inGuid;
3299         uint32_t count;
3300         unsigned int guid[sizeof (stmfGuid)];
3301         char *endPtr;
3302         uint32_t veNbr;
3303         int i;
3304         boolean_t all = B_FALSE;
3305         boolean_t luInput = B_FALSE;
3306         int ret = 0;
3307         int stmfRet;
3308 
3309         /* Note: 'l' is required */
3310         for (; options->optval; options++) {
3311                 switch (options->optval) {
3312                         case 'l':
3313                                 if (strlen(options->optarg) != GUID_INPUT) {
3314                                         (void) fprintf(stderr,
3315                                             "%s: %s: %s %d %s\n",
3316                                             cmdName, options->optarg,
3317                                             gettext("must be"), GUID_INPUT,
3318                                             gettext("hexadecimal digits long"));
3319                                         return (1);
3320                                 }
3321                                 bcopy(options->optarg, sGuid, GUID_INPUT);
3322                                 luInput = B_TRUE;
3323                                 break;
3324                         case 'a':
3325                                 /* removing all view entries for this GUID */
3326                                 all = B_TRUE;
3327                                 break;
3328                         default:
3329                                 (void) fprintf(stderr, "%s: %c: %s\n",
3330                                     cmdName, options->optval,
3331                                     "unknown option");
3332                                 return (1);
3333                 }
3334         }
3335 
3336         if (!all && operandLen == 0) {
3337                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3338                     gettext("no view entries specified"));
3339                 return (1);
3340         }
3341 
3342         if (!luInput) {
3343                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3344                     gettext("logical unit (-l) not specified"));
3345                 return (1);
3346         }
3347 
3348         for (i = 0; i < 32; i++)
3349                 sGuid[i] = tolower(sGuid[i]);
3350         sGuid[i] = 0;
3351 
3352         (void) sscanf(sGuid, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
3353             &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
3354             &guid[6], &guid[7], &guid[8], &guid[9], &guid[10], &guid[11],
3355             &guid[12], &guid[13], &guid[14], &guid[15]);
3356 
3357         for (i = 0; i < sizeof (stmfGuid); i++) {
3358                 inGuid.guid[i] = guid[i];
3359         }
3360 
3361         if ((stmfRet = stmfGetViewEntryList(&inGuid, &viewEntryList))
3362             != STMF_STATUS_SUCCESS) {
3363 
3364                 switch (stmfRet) {
3365                         case STMF_ERROR_BUSY:
3366                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3367                                     sGuid, gettext("resource busy"));
3368                                 break;
3369                         case STMF_ERROR_SERVICE_NOT_FOUND:
3370                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3371                                     gettext("STMF service not found"));
3372                                 break;
3373                         case STMF_ERROR_SERVICE_DATA_VERSION:
3374                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3375                                     gettext("STMF service version incorrect"));
3376                                 break;
3377                         case STMF_ERROR_PERM:
3378                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3379                                     gettext("permission denied"));
3380                                 break;
3381                         default:
3382                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3383                                     sGuid, gettext("unknown error"));
3384                                 break;
3385                 }
3386                 return (1);
3387         }
3388 
3389         if (viewEntryList->cnt == 0) {
3390                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3391                     sGuid, gettext("no views found"));
3392                 return (1);
3393         }
3394 
3395         if (all) {
3396                 count = viewEntryList->cnt;
3397         } else {
3398                 count = operandLen;
3399         }
3400 
3401         for (i = 0; i < count; i++) {
3402                 if (all) {
3403                         veNbr = viewEntryList->ve[i].veIndex;
3404                 } else {
3405                         endPtr = NULL;
3406                         veNbr = strtol(operands[i], &endPtr, 10);
3407                         if (endPtr && *endPtr != 0) {
3408                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3409                                     operands[i], gettext("invalid input"));
3410                                 continue;
3411                         }
3412                 }
3413                 stmfRet = stmfRemoveViewEntry(&inGuid, veNbr);
3414                 switch (stmfRet) {
3415                         case STMF_STATUS_SUCCESS:
3416                                 break;
3417                         case STMF_ERROR_NOT_FOUND:
3418                                 (void) fprintf(stderr, "%s: %s: %d: %s\n",
3419                                     cmdName, sGuid, veNbr,
3420                                     gettext("not found"));
3421                                 ret++;
3422                                 break;
3423                         case STMF_ERROR_BUSY:
3424                                 (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
3425                                     sGuid, gettext("resource busy"));
3426                                 ret++;
3427                                 break;
3428                         case STMF_ERROR_SERVICE_NOT_FOUND:
3429                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3430                                     gettext("STMF service not found"));
3431                                 ret++;
3432                                 break;
3433                         case STMF_ERROR_CONFIG_NONE:
3434                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3435                                     gettext("STMF service is not initialized"));
3436                                 ret++;
3437                                 break;
3438                         case STMF_ERROR_SERVICE_DATA_VERSION:
3439                                 (void) fprintf(stderr, "%s: %s\n", cmdName,
3440                                     gettext("STMF service version incorrect"));
3441                                 ret++;
3442                                 break;
3443                         default:
3444                                 (void) fprintf(stderr, "%s: %s, %d: %s",
3445                                     cmdName, sGuid, veNbr,
3446                                     gettext("unknown error"));
3447                                 ret++;
3448                                 break;
3449                 }
3450         }
3451 
3452         return (ret);
3453 }
3454 
3455 /*
3456  * input:
3457  *  execFullName - exec name of program (argv[0])
3458  *
3459  *  copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
3460  *  (changed name to lowerCamelCase to keep consistent with this file)
3461  *
3462  * Returns:
3463  *  command name portion of execFullName
3464  */
3465 static char *
3466 getExecBasename(char *execFullname)
3467 {
3468         char *lastSlash, *execBasename;
3469 
3470         /* guard against '/' at end of command invocation */
3471         for (;;) {
3472                 lastSlash = strrchr(execFullname, '/');
3473                 if (lastSlash == NULL) {
3474                         execBasename = execFullname;
3475                         break;
3476                 } else {
3477                         execBasename = lastSlash + 1;
3478                         if (*execBasename == '\0') {
3479                                 *lastSlash = '\0';
3480                                 continue;
3481                         }
3482                         break;
3483                 }
3484         }
3485         return (execBasename);
3486 }
3487 
3488 int
3489 main(int argc, char *argv[])
3490 {
3491         synTables_t synTables;
3492         char versionString[VERSION_STRING_MAX_LEN];
3493         int ret;
3494         int funcRet;
3495         void *subcommandArgs = NULL;
3496 
3497         (void) setlocale(LC_ALL, "");
3498         (void) textdomain(TEXT_DOMAIN);
3499         /* set global command name */
3500         cmdName = getExecBasename(argv[0]);
3501 
3502         (void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
3503             VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
3504         synTables.versionString = versionString;
3505         synTables.longOptionTbl = &longOptions[0];
3506         synTables.subCommandPropsTbl = &subcommands[0];
3507 
3508         ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
3509         if (ret != 0) {
3510                 return (ret);
3511         }
3512 
3513         return (funcRet);
3514 } /* end main */