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