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