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