Home | History | Annotate | Download | only in mpathadm
      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 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * mpathadm.c : MP API CLI program
     28  *
     29  */
     30 
     31 #include <libintl.h>
     32 
     33 #include <mpapi.h>
     34 #include "cmdparse.h"
     35 #include "mpathadm_text.h"
     36 #include "mpathadm.h"
     37 
     38 #include <sys/types.h>
     39 #include <sys/stat.h>
     40 #include <unistd.h>
     41 #include <stdlib.h>
     42 #include <devid.h>
     43 #include <fcntl.h>
     44 
     45 /* helper functions */
     46 static char *getExecBasename(char *);
     47 
     48 /* object functions per subcommand */
     49 static int listFunc(int, char **, int, cmdOptions_t *, void *);
     50 static int showFunc(int, char **, int, cmdOptions_t *, void *);
     51 static int modifyFunc(int, char **, int, cmdOptions_t *, void *);
     52 static int enableFunc(int, char **, int, cmdOptions_t *, void *);
     53 static int disableFunc(int, char **, int, cmdOptions_t *, void *);
     54 static int failoverFunc(int, char **, int, cmdOptions_t *, void *);
     55 static int overrideFunc(int, char **, int, cmdOptions_t *, void *);
     56 
     57 #define	VERSION_STRING_MAX_LEN	10
     58 
     59 #define	OPTIONSTRING_NAME	"name"
     60 #define	OPTIONSTRING_TPNAME	"target-port name"
     61 #define	OPTIONSTRING_ONOFF	"on/off"
     62 #define	OPTIONSTRING_LBTYPE	"loadbalance type"
     63 #define	OPTIONSTRING_IPORT	"initiator-port name"
     64 #define	OPTIONSTRING_LUNIT	"logical-unit name"
     65 #define	OPTIONSTRING_CANCEL	"cancel"
     66 #define	OPTIONSTRING_VALUE	"value"
     67 
     68 /*
     69  * Version number: (copied from iscsiadm)
     70  *  MAJOR - This should only change when there is an incompatible change made
     71  *  to the interfaces or the output.
     72  *
     73  *  MINOR - This should change whenever there is a new command or new feature
     74  *  with no incompatible change.
     75  */
     76 #define	VERSION_STRING_MAJOR	    "1"
     77 #define	VERSION_STRING_MINOR	    "0"
     78 
     79 
     80 /* globals */
     81 static char *cmdName;
     82 
     83 
     84 /*
     85  * ****************************************************************************
     86  *
     87  * getExecBasename - copied from iscsiadm code
     88  *
     89  * input:
     90  *  execFullName - exec name of program (argv[0])
     91  *
     92  * Returns:
     93  *  command name portion of execFullName
     94  *
     95  * ****************************************************************************
     96  */
     97 static char *
     98 getExecBasename(char *execFullname)
     99 {
    100 	char 				*lastSlash, *execBasename;
    101 
    102 	/* guard against '/' at end of command invocation */
    103 	for (;;) {
    104 		lastSlash = strrchr(execFullname, '/');
    105 		if (lastSlash == NULL) {
    106 			execBasename = execFullname;
    107 			break;
    108 		} else {
    109 			execBasename = lastSlash + 1;
    110 			if (*execBasename == '\0') {
    111 				*lastSlash = '\0';
    112 				continue;
    113 			}
    114 			break;
    115 		}
    116 	}
    117 	return (execBasename);
    118 }
    119 
    120 
    121 /*
    122  * Add new options here
    123  */
    124 
    125 /* tables set up based on cmdparse instructions */
    126 optionTbl_t longOptions[] = {
    127 	{"inqname", required_arg, 'n', OPTIONSTRING_NAME},
    128 	{"target-port", required_arg, 't', OPTIONSTRING_TPNAME},
    129 	{"autofailback", required_arg, 'a', OPTIONSTRING_ONOFF},
    130 	{"autoprobe", required_arg, 'p', OPTIONSTRING_ONOFF},
    131 	{"loadbalance", required_arg, 'b', OPTIONSTRING_LBTYPE},
    132 	{"initiator-port", required_arg, 'i', OPTIONSTRING_IPORT},
    133 	{"logical-unit", required_arg, 'l', OPTIONSTRING_LUNIT},
    134 	{"cancel", no_arg, 'c', OPTIONSTRING_CANCEL},
    135 	{"vendor-id", required_arg, 'd', OPTIONSTRING_VALUE},
    136 	{NULL, 0, 0, 0}
    137 };
    138 
    139 
    140 /*
    141  * Add new subcommands here
    142  */
    143 subcommand_t subcommands[] = {
    144 	{"list", LIST, listFunc},
    145 	{"show", SHOW, showFunc},
    146 	{"modify", MODIFY, modifyFunc},
    147 	{"enable", ENABLE, enableFunc},
    148 	{"disable", DISABLE, disableFunc},
    149 	{"failover", FAILOVER, failoverFunc},
    150 	{"override", OVERRIDE, overrideFunc},
    151 	{NULL, 0, NULL}
    152 };
    153 
    154 /*
    155  * Add objects here
    156  */
    157 object_t objects[] = {
    158 	{"mpath-support", MPATH_SUPPORT},
    159 	{"logical-unit", LOGICAL_UNIT},
    160 	{"LU", LOGICAL_UNIT},
    161 	{"initiator-port", INITIATOR_PORT},
    162 	{"path", PATH},
    163 	{NULL, 0}
    164 };
    165 
    166 /*
    167  * Rules for subcommands and objects
    168  *
    169  * command
    170  *
    171  * reqOpCmd -> subcommands that must have an operand
    172  * optOpCmd -> subcommands that may have an operand
    173  * noOpCmd -> subcommands that will have no operand
    174  * invCmd -> subcommands that are invalid
    175  * multOpCmd -> subcommands that can accept multiple operands
    176  * operandDefinition -> Usage definition for the operand of this object
    177  */
    178 objectRules_t objectRules[] = {
    179 	{MPATH_SUPPORT, SHOW|MODIFY|ADD, LIST|REMOVE, 0,
    180 	    ENABLE|DISABLE|FAILOVER|OVERRIDE, LIST|SHOW|MODIFY,
    181 	    "mpath-support name"},
    182 	{INITIATOR_PORT, SHOW, LIST, 0,
    183 	    MODIFY|ENABLE|DISABLE|FAILOVER|OVERRIDE|ADD|REMOVE, LIST|SHOW,
    184 	    "initiator-port name"},
    185 	{LOGICAL_UNIT, SHOW|MODIFY|FAILOVER, LIST, 0,
    186 	    ENABLE|DISABLE|OVERRIDE|ADD|REMOVE, LIST|SHOW|MODIFY,
    187 	    "logical-unit name"},
    188 	{PATH, 0, 0, ENABLE|DISABLE|OVERRIDE,
    189 	    SHOW|LIST|MODIFY|FAILOVER|ADD|REMOVE, 0,
    190 	    "initiator-port name"},
    191 	{0, 0, 0, 0, 0, NULL}
    192 };
    193 
    194 /*
    195  * list of objects, subcommands, valid short options, required flag and
    196  * exclusive option string
    197  *
    198  * If it's not here, there are no options for that object.
    199  */
    200 optionRules_t optionRules[] = {
    201 	{LOGICAL_UNIT, LIST, "nt", B_FALSE, NULL},
    202 	{LOGICAL_UNIT, MODIFY, "apb", B_TRUE, NULL},
    203 	{MPATH_SUPPORT, MODIFY, "apb", B_TRUE, NULL},
    204 	{MPATH_SUPPORT, ADD, "d", B_TRUE, NULL},
    205 	{MPATH_SUPPORT, REMOVE, "d", B_TRUE, NULL},
    206 	{PATH, ENABLE, "itl", B_TRUE, NULL},
    207 	{PATH, DISABLE, "itl", B_TRUE, NULL},
    208 	{PATH, OVERRIDE, "itlc", B_TRUE, NULL},
    209 	{0, 0, 0, 0, 0}
    210 };
    211 
    212 
    213 /*
    214  * ****************************************************************************
    215  *
    216  * listMpathSupport - mpathadm list mpath-support
    217  *
    218  * operandLen	- number of operands user passed into the cli
    219  * operand	- pointer to operand list from user
    220  *
    221  * ****************************************************************************
    222  */
    223 int
    224 listMpathSupport(int operandLen, char *operand[])
    225 {
    226 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
    227 	MP_PLUGIN_PROPERTIES			pluginProps;
    228 	MP_OID_LIST				*pPluginOidList;
    229 	boolean_t				shown = B_FALSE;
    230 	/* number of plugins listed */
    231 	int					i, op;
    232 
    233 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
    234 	    != MP_STATUS_SUCCESS) {
    235 		(void) fprintf(stderr, "%s: %s\n", cmdName,
    236 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    237 		return (mpstatus);
    238 	}
    239 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
    240 		(void) fprintf(stderr, "%s: %s\n", cmdName,
    241 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    242 		return (ERROR_CLI_FAILED);
    243 	}
    244 
    245 
    246 	/* loop through operands first */
    247 	for (op = 0; (op < operandLen) |
    248 	    ((0 == operandLen) && (B_FALSE == shown)); op++) {
    249 		shown = B_TRUE;
    250 		for (i = 0; i < pPluginOidList->oidCount; i++) {
    251 
    252 			(void) memset(&pluginProps, 0,
    253 			    sizeof (MP_PLUGIN_PROPERTIES));
    254 			mpstatus =
    255 			    MP_GetPluginProperties(pPluginOidList->oids[i],
    256 			    &pluginProps);
    257 			if (mpstatus != MP_STATUS_SUCCESS) {
    258 				(void) fprintf(stderr, "%s:  %s\n",
    259 				    cmdName, getTextString(ERR_NO_PROPERTIES));
    260 			} else {
    261 				if (0 == operandLen) {
    262 					/* if no operands, list them all */
    263 					(void) printf("%s  %s\n",
    264 					    getTextString(
    265 					    TEXT_LB_MPATH_SUPPORT),
    266 					    pluginProps.fileName);
    267 				} else {
    268 					/* if there is an operand... */
    269 					/* ... compare and display if match */
    270 					if (0 ==
    271 					    strcmp(operand[op],
    272 					    pluginProps.fileName)) {
    273 						(void) printf("%s  %s\n",
    274 						    getTextString(
    275 						    TEXT_LB_MPATH_SUPPORT),
    276 						    pluginProps.fileName);
    277 					} else {
    278 				/* begin back-up indentation */
    279 				/* LINTED E_SEC_PRINTF_VAR_FMT */
    280 				(void) fprintf(stderr, getTextString(
    281 				    ERR_CANT_FIND_MPATH_SUPPORT_WITH_NAME),
    282 				    operand[op]);
    283 				/* end back-up indentation */
    284 						(void) printf("\n");
    285 					}
    286 				}
    287 			}
    288 		}
    289 	}
    290 
    291 	return (mpstatus);
    292 }
    293 
    294 
    295 /*
    296  * ****************************************************************************
    297  *
    298  * showMpathSupport - mpathadm show mpath-support <mpath-support name>, ...
    299  *
    300  * operandLen	- number of operands user passed into the cli
    301  * operand	- pointer to operand list from user
    302  *
    303  * ****************************************************************************
    304  */
    305 int
    306 showMpathSupport(int operandLen, char *operand[])
    307 {
    308 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
    309 	MP_PLUGIN_PROPERTIES			pluginProps;
    310 	MP_OID_LIST				*pPluginOidList;
    311 	MP_OID_LIST				*deviceOidListArray;
    312 	MP_DEVICE_PRODUCT_PROPERTIES		devProps;
    313 	boolean_t				bListIt = B_FALSE;
    314 	int					op, i, j;
    315 	MP_LOAD_BALANCE_TYPE 			lb;
    316 
    317 
    318 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList)) !=
    319 	    MP_STATUS_SUCCESS) {
    320 		(void) fprintf(stderr, "%s:  %s\n",
    321 		    cmdName, getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    322 		return (mpstatus);
    323 	}
    324 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
    325 		(void) fprintf(stderr, "%s:  %s\n",
    326 		    cmdName, getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    327 		return (ERROR_CLI_FAILED);
    328 	}
    329 
    330 	for (op = 0; op < operandLen; op++) {
    331 		bListIt = B_FALSE;
    332 
    333 		for (i = 0; i < pPluginOidList->oidCount; i++) {
    334 
    335 			(void) memset(&pluginProps, 0,
    336 			    sizeof (MP_PLUGIN_PROPERTIES));
    337 			mpstatus =
    338 			    MP_GetPluginProperties(pPluginOidList->oids[i],
    339 			    &pluginProps);
    340 			if (MP_STATUS_SUCCESS != mpstatus) {
    341 				(void) fprintf(stderr, "%s: %s\n",
    342 				    cmdName, getTextString(ERR_NO_PROPERTIES));
    343 				return (mpstatus);
    344 				}
    345 
    346 				if (0 == operandLen) {
    347 					/* if no operand, list it */
    348 					bListIt = B_TRUE;
    349 				} else {
    350 					/* ... compare and display if match */
    351 					if (0 ==
    352 					    strcmp(operand[op],
    353 					    pluginProps.fileName)) {
    354 						bListIt = B_TRUE;
    355 				}
    356 			}
    357 
    358 			if (B_TRUE != bListIt) {
    359 				break;
    360 			}
    361 
    362 			(void) printf("%s  %s\n",
    363 			    getTextString(TEXT_LB_MPATH_SUPPORT),
    364 			    pluginProps.fileName);
    365 
    366 			/* display the info for this plugin */
    367 			(void) printf("\t%s  ", getTextString(TEXT_LB_VENDOR));
    368 			displayWideArray(pluginProps.vendor,
    369 			    sizeof (pluginProps.vendor));
    370 			(void) printf("\n\t%s  ",
    371 			    getTextString(TEXT_LB_DRIVER_NAME));
    372 			displayArray(pluginProps.driverName,
    373 			    sizeof (pluginProps.driverName));
    374 			(void) printf("\n\t%s  ",
    375 			    getTextString(TEXT_LB_DEFAULT_LB));
    376 			/* don't ignore load balance type none. */
    377 			if (pluginProps.defaultloadBalanceType == 0) {
    378 				(void) printf("%s",
    379 				    getTextString(TEXT_LBTYPE_NONE));
    380 			} else {
    381 				displayLoadBalanceString(
    382 				    pluginProps.defaultloadBalanceType);
    383 			}
    384 			(void) printf("\n");
    385 
    386 
    387 			(void) printf("\t%s  \n",
    388 			    getTextString(TEXT_LB_SUPPORTED_LB));
    389 			/* check each bit, display string if found set */
    390 			if (pluginProps.supportedLoadBalanceTypes == 0) {
    391 				(void) printf("\t\t%s\n",
    392 				    getTextString(TEXT_LBTYPE_NONE));
    393 			} else {
    394 				lb = 1;
    395 				do {
    396 					if (0 != (lb & pluginProps.
    397 					    supportedLoadBalanceTypes)) {
    398 						(void) printf("\t\t");
    399 						displayLoadBalanceString(lb &
    400 						    pluginProps.
    401 						    supportedLoadBalanceTypes);
    402 						(void) printf("\n");
    403 					}
    404 					lb = lb<<1;
    405 				} while (lb < 0x80000000);
    406 			}
    407 
    408 			(void) printf("\t%s  %s\n",
    409 			    getTextString(TEXT_LB_ALLOWS_ACT_TPG),
    410 			    (MP_TRUE == pluginProps.canSetTPGAccess)?
    411 			    getTextString(TEXT_YES):getTextString(TEXT_NO));
    412 			(void) printf("\t%s  %s\n",
    413 			    getTextString(TEXT_LB_ALLOWS_PATH_OV),
    414 			    (MP_TRUE == pluginProps.canOverridePaths)?
    415 			    getTextString(TEXT_YES):getTextString(TEXT_NO));
    416 			(void) printf("\t%s  %d\n",
    417 			    getTextString(TEXT_LB_SUPP_AUTO_FB),
    418 			    pluginProps.autoFailbackSupport);
    419 			if ((MP_AUTOFAILBACK_SUPPORT_PLUGIN  ==
    420 			    pluginProps.autoFailbackSupport) |
    421 			    (MP_AUTOFAILBACK_SUPPORT_PLUGINANDMPLU
    422 			    == pluginProps.autoFailbackSupport)) {
    423 				(void) printf("\t%s  %s\n",
    424 				    getTextString(TEXT_LB_AUTO_FB),
    425 				    pluginProps.pluginAutoFailbackEnabled?\
    426 				    getTextString(TEXT_ON):
    427 				    getTextString(TEXT_OFF));
    428 				(void) printf("\t%s  %d/%d\n",
    429 				    getTextString(TEXT_LB_FB_POLLING_RATE),
    430 				    pluginProps.currentFailbackPollingRate,
    431 				    pluginProps.failbackPollingRateMax);
    432 			} else {
    433 				(void) printf("\t%s  %s\n",
    434 				    getTextString(TEXT_LB_AUTO_FB),
    435 				    getTextString(TEXT_NA));
    436 				(void) printf("\t%s  %s/%s\n",
    437 				    getTextString(TEXT_LB_FB_POLLING_RATE),
    438 				    getTextString(TEXT_NA),
    439 				    getTextString(TEXT_NA));
    440 			}
    441 			(void) printf("\t%s  %d\n",
    442 			    getTextString(TEXT_LB_SUPP_AUTO_P),
    443 			    pluginProps.autoProbingSupport);
    444 			if ((MP_AUTOPROBING_SUPPORT_PLUGIN  ==
    445 			    pluginProps.autoProbingSupport) |
    446 			    (MP_AUTOPROBING_SUPPORT_PLUGIN ==
    447 			    pluginProps.autoProbingSupport)) {
    448 				(void) printf("\t%s  %s\n",
    449 				    getTextString(TEXT_LB_AUTO_PROB),
    450 				    (MP_TRUE ==
    451 				    pluginProps.pluginAutoProbingEnabled)?\
    452 				    getTextString(TEXT_YES):
    453 				    getTextString(TEXT_NO));
    454 				(void) printf("\t%s  %d/%d\n",
    455 				    getTextString(TEXT_LB_PR_POLLING_RATE),
    456 				    pluginProps.currentProbingPollingRate,
    457 				    pluginProps.probingPollingRateMax);
    458 			} else {
    459 				(void) printf("\t%s  %s\n",
    460 				    getTextString(TEXT_LB_AUTO_PROB),
    461 				    getTextString(TEXT_NA));
    462 				(void) printf("\t%s  %s/%s\n",
    463 				    getTextString(TEXT_LB_PR_POLLING_RATE),
    464 				    getTextString(TEXT_NA),
    465 				    getTextString(TEXT_NA));
    466 			}
    467 
    468 
    469 			(void) printf("\t%s\n",
    470 			    getTextString(TEXT_LB_SUPP_DEVICES));
    471 
    472 
    473 			if (MP_TRUE !=
    474 			    pluginProps.onlySupportsSpecifiedProducts) {
    475 				/* LINTED E_SEC_PRINTF_VAR_FMT */
    476 				(void) printf(getTextString(TEXT_ANY_DEVICE));
    477 			} else {
    478 				/* if only supports specific products, */
    479 				/* get device product properties supported */
    480 
    481 				mpstatus = MP_GetDeviceProductOidList(\
    482 				    pPluginOidList->oids[i],
    483 				    &deviceOidListArray);
    484 				if (mpstatus != MP_STATUS_SUCCESS) {
    485 					(void) fprintf(stderr, "%s:  %s\n",
    486 					    cmdName, getTextString(
    487 					    ERR_NO_SUPP_DEVICE_INFO));
    488 					/* can't get any more info, */
    489 					/* so we're done with this one */
    490 					break;
    491 				}
    492 
    493 				for (j = 0; j < deviceOidListArray->oidCount;
    494 				    j++) {
    495 				/* begin backup indentation */
    496 				(void) memset(&devProps, 0,
    497 				    sizeof (MP_DEVICE_PRODUCT_PROPERTIES));
    498 				/* end backup indentation */
    499 					if ((mpstatus =
    500 					    MP_GetDeviceProductProperties(\
    501 					    deviceOidListArray->oids[j],
    502 					    &devProps)) == MP_STATUS_SUCCESS) {
    503 
    504 						(void) printf("\t\t%s  ",
    505 						    getTextString(
    506 						    TEXT_LB_VENDOR));
    507 						displayArray(devProps.vendor,
    508 						    sizeof (devProps.vendor));
    509 						(void) printf("\n\t\t%s  ",
    510 						    getTextString(
    511 						    TEXT_LB_PRODUCT));
    512 						displayArray(devProps.product,
    513 						    sizeof (devProps.product));
    514 						(void) printf("\n\t\t%s  ",
    515 						    getTextString(
    516 						    TEXT_LB_REVISION));
    517 						displayArray(devProps.revision,
    518 						    sizeof (devProps.revision));
    519 
    520 						(void) printf("\n\t\t%s\n",
    521 						    getTextString(
    522 						    TEXT_LB_SUPPORTED_LB));
    523 		/* begin back-up indentation */
    524 		if (devProps.supportedLoadBalanceTypes == 0) {
    525 			(void) printf("\t\t\t%s\n",
    526 			    getTextString(TEXT_LBTYPE_NONE));
    527 		} else {
    528 			lb = 1;
    529 			do {
    530 				if (0 != (lb &
    531 				    devProps.supportedLoadBalanceTypes)) {
    532 					(void) printf("\t\t\t");
    533 					displayLoadBalanceString(lb &
    534 					    devProps.supportedLoadBalanceTypes);
    535 					(void) printf("\n");
    536 				}
    537 				lb = lb<<1;
    538 			} while (lb < 0x80000000);
    539 		}
    540 		/* end back-up indentation */
    541 						(void) printf("\n");
    542 
    543 					} else {
    544 						(void) fprintf(stderr,
    545 						    "%s:  %s\n", cmdName,
    546 						    getTextString(
    547 						    ERR_NO_SUPP_DEVICE_INFO));
    548 					}
    549 				} /* for j */
    550 			} /* if only supports specified devices */
    551 
    552 		} /* for each plugin */
    553 
    554 		if (B_FALSE == bListIt) {
    555 			/* LINTED E_SEC_PRINTF_VAR_FMT */
    556 			(void) fprintf(stderr, getTextString(
    557 			    ERR_CANT_FIND_MPATH_SUPPORT_WITH_NAME),
    558 			    operand[op]);
    559 			(void) printf("\n");
    560 
    561 		}
    562 
    563 	} /* for each operand */
    564 
    565 
    566 	return (mpstatus);
    567 }
    568 
    569 
    570 /*
    571  * ****************************************************************************
    572  *
    573  * modifyMpathSupport -
    574  * 	mpathadm modify mpath-support [options] <mpath-support name>, ...
    575  *
    576  * operandLen	- number of operands user passed into the cli
    577  * operand	- pointer to operand list from user
    578  * options	- pointer to option list from user
    579  *
    580  * ****************************************************************************
    581  */
    582 int
    583 modifyMpathSupport(int operandLen, char *operand[], cmdOptions_t *options)
    584 {
    585 	MP_STATUS		mpstatus = MP_STATUS_SUCCESS;
    586 	MP_PLUGIN_PROPERTIES	pluginProps;
    587 	MP_OID_LIST		*pPluginOidList;
    588 	boolean_t		bFoundIt = B_FALSE;
    589 	MP_OID			pluginOid;
    590 	cmdOptions_t 		*optionList = options;
    591 	char			*cmdStr = getTextString(TEXT_UNKNOWN);
    592 	int			op, i, lbValue;
    593 
    594 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
    595 	    != MP_STATUS_SUCCESS) {
    596 		(void) fprintf(stderr, "%s: %s\n", cmdName,
    597 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    598 		return (mpstatus);
    599 	}
    600 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
    601 		(void) fprintf(stderr, "%s: %s\n", cmdName,
    602 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    603 		return (ERROR_CLI_FAILED);
    604 	}
    605 
    606 	for (op = 0; op < operandLen; op++) {
    607 		bFoundIt = B_FALSE;
    608 		for (i = 0;
    609 		    (i < pPluginOidList->oidCount) && (B_TRUE != bFoundIt);
    610 		    i++) {
    611 
    612 			(void) memset(&pluginProps, 0,
    613 			    sizeof (MP_PLUGIN_PROPERTIES));
    614 			if ((mpstatus =
    615 			    MP_GetPluginProperties(pPluginOidList->oids[i],
    616 			    &pluginProps)) == MP_STATUS_SUCCESS) {
    617 
    618 				if (0 == strcmp(operand[op],
    619 				    pluginProps.fileName)) {
    620 					bFoundIt = B_TRUE;
    621 					pluginOid = pPluginOidList->oids[i];
    622 				}
    623 			} else {
    624 				(void) fprintf(stderr, "%s:  %s\n",
    625 				    cmdName, getTextString(ERR_NO_PROPERTIES));
    626 			}
    627 
    628 			if (B_FALSE == bFoundIt) {
    629 				break;
    630 			}
    631 
    632 /* begin back-up indentation */
    633 	/* we found the plugin oid */
    634 	/* now change the options requested */
    635 	switch (optionList->optval) {
    636 		case 'a':
    637 			/* modify autofailback */
    638 			cmdStr = getTextString(TEXT_AUTO_FAILBACK);
    639 			if (0 == strcasecmp(optionList->optarg,
    640 			    getTextString(TEXT_ON))) {
    641 				mpstatus =
    642 				    MP_EnableAutoFailback(pluginOid);
    643 			} else if (0 ==
    644 			    strcasecmp(optionList->optarg,
    645 			    getTextString(TEXT_OFF))) {
    646 				mpstatus =
    647 				    MP_DisableAutoFailback(pluginOid);
    648 			} else {
    649 				/* LINTED E_SEC_PRINTF_VAR_FMT */
    650 				(void) fprintf(stderr, getTextString(
    651 				    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
    652 				    cmdStr,
    653 				    getTextString(TEXT_ILLEGAL_ARGUMENT));
    654 				(void) printf("\n");
    655 				return (ERROR_CLI_FAILED);
    656 			}
    657 			break;
    658 		case 'p':
    659 			/* modify autoprobing */
    660 			cmdStr = getTextString(TEXT_AUTO_PROBING);
    661 			if (0 == strcasecmp(optionList->optarg,
    662 			    getTextString(TEXT_ON))) {
    663 				mpstatus =
    664 				    MP_EnableAutoProbing(pluginOid);
    665 			} else if (0 ==
    666 			    strcasecmp(optionList->optarg,
    667 			    getTextString(TEXT_OFF))) {
    668 				mpstatus =
    669 				    MP_DisableAutoProbing(pluginOid);
    670 			} else {
    671 				/* LINTED E_SEC_PRINTF_VAR_FMT */
    672 				(void) fprintf(stderr, getTextString(
    673 				    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
    674 				    cmdStr,
    675 				    getTextString(TEXT_ILLEGAL_ARGUMENT));
    676 				(void) printf("\n");
    677 				return (ERROR_CLI_FAILED);
    678 			}
    679 			break;
    680 		case 'b':
    681 			/* modify loadbalance type */
    682 			cmdStr = getTextString(TEXT_LOAD_BALANCE);
    683 			/* user of the cli sends text string, we need the int */
    684 			/* value to pass to the mpapi */
    685 			lbValue = getLbValueFromString(optionList->optarg);
    686 			mpstatus =
    687 			    MP_SetPluginLoadBalanceType(pluginOid,
    688 			    lbValue);
    689 			break;
    690 
    691 		} /* switch */
    692 		if (MP_STATUS_SUCCESS != mpstatus) {
    693 			/* LINTED E_SEC_PRINTF_VAR_FMT */
    694 			(void) fprintf(stderr,
    695 			    getTextString(
    696 			    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
    697 			    cmdStr, getMpStatusStr(mpstatus));
    698 			(void) printf("\n");
    699 			return (mpstatus);
    700 		}
    701 /* end back-up indentation */
    702 
    703 		} /* for each plugin */
    704 
    705 		if (B_FALSE == bFoundIt) {
    706 			/* LINTED E_SEC_PRINTF_VAR_FMT */
    707 			(void) fprintf(stderr,
    708 			    getTextString(
    709 			    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
    710 			    cmdStr,
    711 			    getTextString(TEXT_MPATH_SUPPORT_NOT_FOUND));
    712 			(void) printf("\n");
    713 			return (ERROR_CLI_FAILED);
    714 		}
    715 
    716 	} /* for each operand */
    717 
    718 	return (mpstatus);
    719 }
    720 
    721 
    722 /*
    723  * ****************************************************************************
    724  *
    725  * listLogicalUnit -
    726  * 	mpathadm list {logical-unit | LU} [options] [<logical-unit name>, ...]
    727  *
    728  * operandLen	- number of operands user passed into the cli
    729  * operand	- pointer to operand list from user
    730  * options	- pointer to option list from user
    731  *
    732  * ****************************************************************************
    733  */
    734 int
    735 listLogicalUnit(int operandLen, char *operand[], cmdOptions_t *options)
    736 {
    737 	MP_STATUS mpstatus = MP_STATUS_SUCCESS;
    738 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES luProps;
    739 	MP_PLUGIN_PROPERTIES pluginProps;
    740 	MP_TARGET_PORT_PROPERTIES tportProps;
    741 	MP_OID_LIST *pPluginOidList, *pLogicalUnitOidList,
    742 	    *pTpgOidListArray, *pTportOidListArray;
    743 	boolean_t bListIt = B_FALSE, bFoundOperand = B_FALSE,
    744 	    *bFoundOption, bContinue = B_FALSE;
    745 	MP_OID luOid;
    746 	cmdOptions_t *optionList = options;
    747 	int opListCount = 0, i = 0, lu = 0, tpg = 0, opoffset = 0, j = 0,
    748 	    opStart = 0, opEnd = 0, opIndex;
    749 
    750 	/* count number of options */
    751 	for (; optionList->optval; optionList++) {
    752 		opListCount++;
    753 	}
    754 
    755 	bFoundOption = malloc((sizeof (boolean_t)) * opListCount);
    756 	if (NULL == bFoundOption) {
    757 		(void) fprintf(stdout, "%s\n",
    758 		    getTextString(ERR_MEMORY_ALLOCATION));
    759 		return (ERROR_CLI_FAILED);
    760 	}
    761 
    762 	/* list to keep track of multiple options */
    763 	optionList = options;
    764 	for (opIndex = 0; opIndex < opListCount; opIndex++) {
    765 		bFoundOption[opIndex] = B_FALSE;
    766 	}
    767 
    768 	optionList = options;
    769 
    770 	/* if no operands or options, list everything we find */
    771 	if ((0 == operandLen) && (0 == opListCount)) {
    772 		if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
    773 		    != MP_STATUS_SUCCESS) {
    774 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    775 			    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    776 			return (mpstatus);
    777 		}
    778 		if ((NULL == pPluginOidList) ||
    779 		    (pPluginOidList->oidCount < 1)) {
    780 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    781 			    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    782 			return (ERROR_CLI_FAILED);
    783 		}
    784 
    785 		for (i = 0; i < pPluginOidList->oidCount; i++) {
    786 			/* get properties so we can list the name */
    787 			(void) memset(&pluginProps, 0,
    788 			    sizeof (MP_PLUGIN_PROPERTIES));
    789 			if ((mpstatus =
    790 			    MP_GetPluginProperties(pPluginOidList->oids[i],
    791 			    &pluginProps)) != MP_STATUS_SUCCESS) {
    792 				(void) fprintf(stderr, "%s:  %s\n",
    793 				    cmdName, getTextString(ERR_NO_PROPERTIES));
    794 				return (mpstatus);
    795 			}
    796 
    797 			/* attempt to find this logical unit */
    798 			mpstatus = MP_GetMultipathLus(pPluginOidList->oids[i],
    799 			    &pLogicalUnitOidList);
    800 			if (mpstatus != MP_STATUS_SUCCESS) {
    801 				(void) fprintf(stderr, "%s:  %s\n",
    802 				    cmdName, getTextString(ERR_NO_LU_LIST));
    803 				return (mpstatus);
    804 			}
    805 
    806 			for (lu = 0; lu < pLogicalUnitOidList->oidCount; lu++) {
    807 			/* begin backup indentation */
    808 			/* get lu properties so we can check the name */
    809 			(void) memset(&luProps, 0,
    810 			    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
    811 			/* end backup indentation */
    812 				mpstatus =
    813 				    MP_GetMPLogicalUnitProperties(
    814 				    pLogicalUnitOidList->oids[lu],
    815 				    &luProps);
    816 				if (mpstatus != MP_STATUS_SUCCESS) {
    817 					(void) fprintf(stderr, "%s:  %s\n",
    818 					    cmdName,
    819 					    getTextString(ERR_NO_PROPERTIES));
    820 					return (mpstatus);
    821 				}
    822 
    823 				luOid = pLogicalUnitOidList->oids[lu];
    824 				if (listIndividualLogicalUnit(luOid, luProps)
    825 				    != 0) {
    826 					return (ERROR_CLI_FAILED);
    827 				}
    828 			} /* for each LU */
    829 		} /* for each plugin */
    830 	} else { /* we have operands and/or options */
    831 
    832 		/* check if we have operands */
    833 		if (0 == operandLen) {
    834 			/* no operands */
    835 			opStart = -1;
    836 			opEnd = 0;
    837 		} else {
    838 			/* operands */
    839 			opStart = 0;
    840 			opEnd = operandLen;
    841 		}
    842 
    843 		if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
    844 		    != MP_STATUS_SUCCESS) {
    845 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    846 			    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    847 			return (mpstatus);
    848 		}
    849 		if ((NULL == pPluginOidList) ||
    850 		    (pPluginOidList->oidCount < 1)) {
    851 			(void) fprintf(stderr, "%s: %s\n", cmdName,
    852 			    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
    853 			return (ERROR_CLI_FAILED);
    854 		}
    855 
    856 		for (opoffset = opStart; opoffset < opEnd; opoffset++) {
    857 			/* loop through operands */
    858 			bFoundOperand = B_FALSE;
    859 
    860 			for (i = 0; i < pPluginOidList->oidCount; i++) {
    861 
    862 				/*
    863 				 * loop through plugin, and get properties
    864 				 * so we can list the name
    865 				 */
    866 				(void) memset(&pluginProps, 0,
    867 				    sizeof (MP_PLUGIN_PROPERTIES));
    868 				if ((mpstatus =
    869 				    MP_GetPluginProperties(
    870 				    pPluginOidList->oids[i], &pluginProps))
    871 				    != MP_STATUS_SUCCESS) {
    872 					(void) fprintf(stderr, "%s:  %s\n",
    873 					    cmdName,
    874 					    getTextString(ERR_NO_PROPERTIES));
    875 					return (mpstatus);
    876 				}
    877 
    878 				/* attempt to find this logical unit */
    879 				mpstatus =
    880 				    MP_GetMultipathLus(pPluginOidList->oids[i],
    881 				    &pLogicalUnitOidList);
    882 				if (mpstatus != MP_STATUS_SUCCESS) {
    883 					(void) fprintf(stderr, "%s:  %s\n",
    884 					    cmdName,
    885 					    getTextString(ERR_NO_LU_LIST));
    886 					return (mpstatus);
    887 				}
    888 
    889 				for (lu = 0;
    890 				    (lu < pLogicalUnitOidList->oidCount);
    891 				    lu++) {
    892 					bListIt = B_FALSE;
    893 			/* begin backup indentation */
    894 			/* get lu props & check the name */
    895 			(void) memset(&luProps, 0,
    896 			    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
    897 			/* end backup indentation */
    898 					mpstatus =
    899 					    MP_GetMPLogicalUnitProperties(
    900 					    pLogicalUnitOidList->oids[lu],
    901 					    &luProps);
    902 					if (mpstatus != MP_STATUS_SUCCESS) {
    903 						(void) fprintf(stderr,
    904 						    "%s:  %s\n", cmdName,
    905 						    getTextString(
    906 						    ERR_NO_PROPERTIES));
    907 						return (mpstatus);
    908 					}
    909 
    910 					/*
    911 					 * compare operand - is it a match?
    912 					 * If so, continue
    913 					 */
    914 
    915 					bContinue = B_TRUE;
    916 					if (operandLen > 0) {
    917 						bContinue =
    918 						    compareLUName(
    919 						    operand[opoffset],
    920 						    luProps.deviceFileName);
    921 					}
    922 
    923 					if (B_TRUE == bContinue) {
    924 
    925 						if (0 != opListCount) {
    926 							/* check options */
    927 
    928 
    929 /* begin backup indentation */
    930 optionList = options;
    931 
    932 for (opIndex = 0; optionList->optval; optionList++, opIndex++) {
    933 switch (optionList->optval) {
    934 	case 'n':
    935 		if (B_TRUE ==
    936 		    compareLUName(optionList->optarg, luProps.name)) {
    937 			bListIt = B_TRUE;
    938 			bFoundOperand = B_TRUE;
    939 			bFoundOption[opIndex] = B_TRUE;
    940 		}
    941 		break;
    942 	case 't':
    943 		/* get TPG list */
    944 		mpstatus =
    945 		    MP_GetAssociatedTPGOidList(pLogicalUnitOidList->oids[lu],
    946 		    &pTpgOidListArray);
    947 		if (mpstatus !=  MP_STATUS_SUCCESS) {
    948 			(void) fprintf(stderr,  "%s:  %s\n", cmdName,
    949 			    getTextString(ERR_NO_ASSOC_TPGS));
    950 			return (mpstatus);
    951 		}
    952 
    953 		/* get target ports */
    954 		for (tpg = 0;
    955 		    (NULL != pTpgOidListArray) &&
    956 		    (tpg < pTpgOidListArray->oidCount) &&
    957 		    (B_FALSE == bListIt); tpg++) {
    958 			mpstatus =
    959 			    MP_GetTargetPortOidList(pTpgOidListArray->oids[tpg],
    960 			    &pTportOidListArray);
    961 			if (mpstatus != MP_STATUS_SUCCESS) {
    962 				(void) fprintf(stderr, "%s:  %s\n",
    963 				    cmdName,
    964 				    getTextString(ERR_NO_ASSOC_TPORTS));
    965 				return (mpstatus);
    966 			}
    967 
    968 			/* get target port properties for the name */
    969 			for (j = 0; (NULL != pTportOidListArray) &&
    970 			    (j < pTportOidListArray->oidCount) &&
    971 			    (B_FALSE == bListIt); j++) {
    972 				(void) memset(&tportProps, 0,
    973 				    sizeof (MP_TARGET_PORT_PROPERTIES));
    974 				mpstatus =
    975 				    MP_GetTargetPortProperties(
    976 				    pTportOidListArray->oids[j], &tportProps);
    977 				if (mpstatus != MP_STATUS_SUCCESS) {
    978 					(void) fprintf(stderr, "%s:  %s\n",
    979 					    cmdName,
    980 					    getTextString(ERR_NO_PROPERTIES));
    981 					return (mpstatus);
    982 				}
    983 
    984 
    985 				/* check the name */
    986 				if (0 == strcmp(optionList->optarg,
    987 				    tportProps.portID)) {
    988 					bListIt = B_TRUE;
    989 					bFoundOperand = B_TRUE;
    990 					bFoundOption[opIndex] = B_TRUE;
    991 				}
    992 			} /* for each target port */
    993 		} /* for each tpg */
    994 	} /* end switch */
    995 } /* loop through options */
    996 /* end back-up indentation */
    997 
    998 						} else {
    999 							/*
   1000 							 * if no options,
   1001 							 * listit
   1002 							 */
   1003 							bListIt = B_TRUE;
   1004 							bFoundOperand = B_TRUE;
   1005 						}
   1006 					} /* end bContinue check */
   1007 
   1008 		if (bListIt) {
   1009 			(void) printf("%s  %s\n",
   1010 			    getTextString(TEXT_LB_MPATH_SUPPORT),
   1011 			    pluginProps.fileName);
   1012 			luOid = pLogicalUnitOidList->oids[lu];
   1013 			if (listIndividualLogicalUnit(luOid, luProps)
   1014 			    != 0) {
   1015 				return (ERROR_CLI_FAILED);
   1016 			}
   1017 
   1018 		}
   1019 
   1020 				} /* end LU loop */
   1021 			} /* end plugin loop */
   1022 			if ((0 == opListCount) && (0 != operandLen)) {
   1023 				if (B_FALSE == bFoundOperand) {
   1024 					/* option/operand combo not found */
   1025 					/* LINTED E_SEC_PRINTF_VAR_FMT */
   1026 					(void) fprintf(stderr,
   1027 					    getTextString(
   1028 				    ERR_LU_NOT_FOUND_WITH_MISSING_LU_STR),
   1029 					    operand[opoffset]);
   1030 					(void) fprintf(stderr, "\n");
   1031 				}
   1032 			}
   1033 
   1034 			optionList = options;
   1035 			for (opIndex = 0; optionList->optval; optionList++,
   1036 			    opIndex++) {
   1037 				if (B_FALSE == bFoundOption[opIndex]) {
   1038 					/* LINTED E_SEC_PRINTF_VAR_FMT */
   1039 					(void) fprintf(stderr,
   1040 					    getTextString(
   1041 				    ERR_LU_NOT_FOUND_WITH_MISSING_LU_STR),
   1042 					    optionList->optarg);
   1043 					(void) fprintf(stderr, "\n");
   1044 				}
   1045 			}
   1046 
   1047 
   1048 
   1049 		} /* end loop through operands */
   1050 	} /* we have operands and/or options */
   1051 
   1052 
   1053 	return (mpstatus);
   1054 }
   1055 
   1056 
   1057 /*
   1058  * ****************************************************************************
   1059  *
   1060  * compareLUName -
   1061  * 	compare names directly and via devid if no match directly
   1062  *
   1063  * cmpString		- first string to compare
   1064  * deviceProperty	- string from properties
   1065  * sizeToCompare	- size of deviceProperty
   1066  *
   1067  * returns 	B_TRUE if the strings match either directly or via devid
   1068  *		B_FALSE otherwise
   1069  *
   1070  * ****************************************************************************
   1071  */
   1072 boolean_t
   1073 compareLUName(MP_CHAR *cmpString, MP_CHAR *deviceProperty)
   1074 {
   1075 
   1076 	boolean_t				isSame = B_FALSE;
   1077 	int 					fd1, fd2;
   1078 	ddi_devid_t				devid1 = NULL, devid2 = NULL;
   1079 
   1080 	if (0 == strcmp(cmpString, deviceProperty)) {
   1081 		isSame = B_TRUE;
   1082 	} else {
   1083 		/* user input didn't match, try via devid */
   1084 		/*
   1085 		 * I don't see a reason to print the error for
   1086 		 * any of these since they'll get the error at
   1087 		 * the end anyway
   1088 		 */
   1089 
   1090 		fd1 = fd2 = -1;
   1091 		if (((fd1 = open(cmpString, O_RDONLY|O_NDELAY)) >= 0) &&
   1092 		    ((fd2 = open(deviceProperty, O_RDONLY|O_NDELAY)) >= 0) &&
   1093 		    (devid_get(fd1, &devid1) == 0) &&
   1094 		    (devid_get(fd2, &devid2) == 0) &&
   1095 		    ((NULL != devid1) && (NULL != devid2))) {
   1096 			if (0 ==
   1097 			    (devid_compare(devid1, devid2))) {
   1098 				isSame = B_TRUE;
   1099 			}
   1100 		}
   1101 
   1102 		if (NULL != devid1) {
   1103 			devid_free(devid1);
   1104 		}
   1105 		if (NULL != devid2) {
   1106 			devid_free(devid2);
   1107 		}
   1108 
   1109 		if (fd1 >= 0) {
   1110 			(void) close(fd1);
   1111 		}
   1112 		if (fd2 >= 0) {
   1113 			(void) close(fd2);
   1114 		}
   1115 	} /* compare */
   1116 
   1117 	return (isSame);
   1118 }
   1119 
   1120 
   1121 /*
   1122  * ****************************************************************************
   1123  *
   1124  * listIndivudualLogicalUnit -
   1125  * 	Used by list logical unit cli.
   1126  *	Displays info about an LU
   1127  *
   1128  * luOid	- LU to list
   1129  * luProps	- properties of he LU to list
   1130  *
   1131  * ****************************************************************************
   1132  */
   1133 int
   1134 listIndividualLogicalUnit(MP_OID luOid,
   1135 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES luProps)
   1136 {
   1137 	MP_PATH_LOGICAL_UNIT_PROPERTIES		pathProps;
   1138 	MP_OID_LIST				*pPathOidListArray;
   1139 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   1140 	int					numOperationalPaths, pa;
   1141 
   1142 	(void) printf("\t");
   1143 	displayArray(luProps.deviceFileName, sizeof (luProps.deviceFileName));
   1144 	(void) printf("\n");
   1145 
   1146 	mpstatus = MP_GetAssociatedPathOidList(luOid,
   1147 	    &pPathOidListArray);
   1148 	if (mpstatus != MP_STATUS_SUCCESS) {
   1149 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   1150 		(void) fprintf(stderr,
   1151 		    getTextString(ERR_NO_LU_PATH_INFO_WITH_MISSING_LU_STR),
   1152 		    getStringArray(luProps.deviceFileName,
   1153 		    sizeof (luProps.deviceFileName)));
   1154 		(void) fprintf(stderr, "\n");
   1155 		return (mpstatus);
   1156 	}
   1157 	(void) printf("\t\t%s %d\n",
   1158 	    getTextString(TEXT_LB_PATH_COUNT), pPathOidListArray->oidCount);
   1159 
   1160 	numOperationalPaths = 0;
   1161 	for (pa = 0; pa < pPathOidListArray->oidCount; pa++) {
   1162 		(void) memset(&pathProps, 0,
   1163 		    sizeof (MP_PATH_LOGICAL_UNIT_PROPERTIES));
   1164 		mpstatus =
   1165 		    MP_GetPathLogicalUnitProperties(
   1166 		    pPathOidListArray->oids[pa], &pathProps);
   1167 		if (mpstatus != MP_STATUS_SUCCESS) {
   1168 			(void) fprintf(stderr, "%s:  %s\n",
   1169 			    cmdName, getTextString(ERR_NO_PROPERTIES));
   1170 			return (mpstatus);
   1171 		}
   1172 
   1173 		/* cycle through and check status of each for */
   1174 		/* operation path count */
   1175 		if (MP_PATH_STATE_OKAY == pathProps.pathState) {
   1176 			numOperationalPaths++;
   1177 		}
   1178 	}
   1179 
   1180 	(void) printf("\t\t%s %d\n",
   1181 	    getTextString(TEXT_LB_OP_PATH_COUNT), numOperationalPaths);
   1182 
   1183 	return (mpstatus);
   1184 }
   1185 
   1186 
   1187 /*
   1188  * ****************************************************************************
   1189  *
   1190  * showLogicalUnit -
   1191  * 	mpathadm show {logical-unit | LU} <logical-unit name>, ...
   1192  *
   1193  * operandLen	- number of operands user passed into the cli
   1194  * operand	- pointer to operand list from user
   1195  *
   1196  * ****************************************************************************
   1197  */
   1198 int
   1199 showLogicalUnit(int operandLen, char *operand[])
   1200 {
   1201 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   1202 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES	luProps;
   1203 	MP_PLUGIN_PROPERTIES			pluginProps;
   1204 	MP_OID					luOid, pluginOid;
   1205 
   1206 	int					op;
   1207 
   1208 	for (op = 0; op < operandLen; op++) {
   1209 		if (op > 0) {
   1210 			(void) printf("\n");
   1211 		}
   1212 		if (B_TRUE == getLogicalUnitOid(operand[op], &luOid)) {
   1213 			(void) memset(&luProps, 0,
   1214 			    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
   1215 			mpstatus =
   1216 			    MP_GetMPLogicalUnitProperties(
   1217 			    luOid, &luProps);
   1218 			if (mpstatus != MP_STATUS_SUCCESS) {
   1219 				(void) fprintf(stderr, "%s:  %s\n",
   1220 				    cmdName, getTextString(ERR_NO_PROPERTIES));
   1221 				return (mpstatus);
   1222 			}
   1223 
   1224 			mpstatus =
   1225 			    MP_GetAssociatedPluginOid(luOid, &pluginOid);
   1226 			if (mpstatus != MP_STATUS_SUCCESS) {
   1227 				(void) fprintf(stderr, "%s:  %s\n",
   1228 				    cmdName,
   1229 				    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   1230 				return (mpstatus);
   1231 			}
   1232 
   1233 			mpstatus =
   1234 			    MP_GetPluginProperties(pluginOid, &pluginProps);
   1235 			if (mpstatus != MP_STATUS_SUCCESS) {
   1236 				(void) fprintf(stderr, "%s:  %s\n",
   1237 				    cmdName, getTextString(ERR_NO_PROPERTIES));
   1238 				return (mpstatus);
   1239 			}
   1240 
   1241 			if (showIndividualLogicalUnit(luOid, luProps,
   1242 			    pluginProps) != 0) {
   1243 				return (ERROR_CLI_FAILED);
   1244 			}
   1245 
   1246 		} else {
   1247 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   1248 			(void) fprintf(stderr, getTextString(
   1249 			    ERR_LU_NOT_FOUND_WITH_MISSING_LU_STR),
   1250 			    operand[op]);
   1251 			(void) printf("\n");
   1252 		}
   1253 
   1254 	} /* for each operand */
   1255 
   1256 	return (mpstatus);
   1257 }
   1258 
   1259 
   1260 /*
   1261  * ****************************************************************************
   1262  *
   1263  * showIndivudualLogicalUnit -
   1264  * 	Used by show logical unit cli.
   1265  *	Displays info about an LU
   1266  *
   1267  * luOid	- LU to show
   1268  * luProps	- properties of he LU to show
   1269  * pluginProps	- propertis of the plugin this LU belongs to
   1270  *
   1271  * ****************************************************************************
   1272  */
   1273 int
   1274 showIndividualLogicalUnit(MP_OID luOid,
   1275 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES luProps,
   1276 	MP_PLUGIN_PROPERTIES pluginProps)
   1277 {
   1278 	MP_PATH_LOGICAL_UNIT_PROPERTIES		pathProps;
   1279 	MP_TARGET_PORT_GROUP_PROPERTIES		tpgProps;
   1280 	MP_TARGET_PORT_PROPERTIES 		tportProps;
   1281 	MP_INITIATOR_PORT_PROPERTIES 		initProps;
   1282 	MP_OID_LIST	*pPathOidListArray, *pTPGOidListArray,
   1283 	    *pTportOidListArray;
   1284 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   1285 	boolean_t				showTportLabel = B_TRUE;
   1286 
   1287 	int					pa, tpg, tport;
   1288 
   1289 	(void) printf("%s  ", getTextString(TEXT_LB_LOGICAL_UNIT));
   1290 	displayArray(luProps.deviceFileName, sizeof (luProps.deviceFileName));
   1291 	(void) printf("\n");
   1292 	(void) printf("\t%s  %s\n", getTextString(TEXT_LB_MPATH_SUPPORT),
   1293 	    pluginProps.fileName);
   1294 
   1295 	(void) printf("\t%s  ", getTextString(TEXT_LB_VENDOR));
   1296 	displayArray(luProps.vendor,
   1297 	    sizeof (luProps.vendor));
   1298 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_PRODUCT));
   1299 	displayArray(luProps.product,
   1300 	    sizeof (luProps.product));
   1301 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_REVISION));
   1302 	displayArray(luProps.revision,
   1303 	    sizeof (luProps.revision));
   1304 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_INQUIRY_NAME_TYPE));
   1305 	displayLogicalUnitNameTypeString(luProps.nameType);
   1306 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_INQUIRY_NAME));
   1307 	displayArray(luProps.name, sizeof (luProps.name));
   1308 	(void) printf("\n\t%s  %s\n", getTextString(TEXT_LB_ASYMMETRIC),
   1309 	    (MP_TRUE == luProps.asymmetric)?
   1310 	    getTextString(TEXT_YES):getTextString(TEXT_NO));
   1311 
   1312 	(void) printf("\t%s  ", getTextString(TEXT_LB_CURR_LOAD_BALANCE));
   1313 	/* don't ignore load balance type none. */
   1314 	if (luProps.currentLoadBalanceType == 0) {
   1315 		(void) printf("%s", getTextString(TEXT_LBTYPE_NONE));
   1316 	} else {
   1317 		displayLoadBalanceString(luProps.currentLoadBalanceType);
   1318 	}
   1319 	(void) printf("\n");
   1320 
   1321 	(void) printf("\t%s  ", getTextString(TEXT_LB_LU_GROUP_ID));
   1322 	if (0xffffffff == luProps.logicalUnitGroupID) {
   1323 		(void) printf("%s\n", getTextString(TEXT_NA));
   1324 	} else {
   1325 		(void) printf("0x%x\n", luProps.logicalUnitGroupID);
   1326 	}
   1327 
   1328 	(void) printf("\t%s  ", getTextString(TEXT_LB_AUTO_FB));
   1329 	if (MP_FALSE == pluginProps.autoFailbackSupport) {
   1330 		(void) printf("%s\n", getTextString(TEXT_NA));
   1331 	} else {
   1332 		(void) printf("%s\n", (MP_TRUE == luProps.autoFailbackEnabled)?
   1333 		    getTextString(TEXT_ON):getTextString(TEXT_OFF));
   1334 	}
   1335 
   1336 	(void) printf("\t%s  ", getTextString(TEXT_LB_AUTO_PROB));
   1337 	if (MP_FALSE == pluginProps.autoProbingSupport) {
   1338 		(void) printf("%s\n", getTextString(TEXT_NA));
   1339 	} else {
   1340 		(void) printf("%s\n", (MP_TRUE == luProps.autoProbingEnabled)?
   1341 		    getTextString(TEXT_ON):getTextString(TEXT_OFF));
   1342 	}
   1343 
   1344 
   1345 	/* get path info */
   1346 	mpstatus = MP_GetAssociatedPathOidList(luOid, &pPathOidListArray);
   1347 	if (mpstatus != MP_STATUS_SUCCESS) {
   1348 		(void) fprintf(stderr, "%s:  %s", cmdName,
   1349 		    getTextString(ERR_NO_LU_PATH_INFO));
   1350 		displayArray(luProps.deviceFileName,
   1351 		    sizeof (luProps.deviceFileName));
   1352 		(void) fprintf(stderr, "\n");
   1353 		return (mpstatus);
   1354 	}
   1355 
   1356 	(void) printf("\n\t%s  \n", getTextString(TEXT_LB_PATH_INFO));
   1357 
   1358 	for (pa = 0; pa < pPathOidListArray->oidCount; pa++) {
   1359 		(void) memset(&pathProps, 0,
   1360 		    sizeof (MP_PATH_LOGICAL_UNIT_PROPERTIES));
   1361 		mpstatus = MP_GetPathLogicalUnitProperties(
   1362 		    pPathOidListArray->oids[pa], &pathProps);
   1363 		if (mpstatus != MP_STATUS_SUCCESS) {
   1364 			(void) fprintf(stderr, "%s:  %s\n",
   1365 			    cmdName, getTextString(ERR_NO_PROPERTIES));
   1366 			return (mpstatus);
   1367 		}
   1368 
   1369 		(void) printf("\t\t%s  ",
   1370 		    getTextString(TEXT_LB_INIT_PORT_NAME));
   1371 		if ((mpstatus =
   1372 		    MP_GetInitiatorPortProperties(pathProps.initiatorPortOid,
   1373 		    &initProps)) != MP_STATUS_SUCCESS) {
   1374 			(void) printf("%s\n", getTextString(TEXT_UNKNOWN));
   1375 		} else {
   1376 			displayArray(initProps.portID,
   1377 			    sizeof (initProps.portID));
   1378 			(void) printf("\n");
   1379 		}
   1380 
   1381 		(void) printf("\t\t%s  ",
   1382 		    getTextString(TEXT_LB_TARGET_PORT_NAME));
   1383 		if ((mpstatus =
   1384 		    MP_GetTargetPortProperties(pathProps.targetPortOid,
   1385 		    &tportProps)) != MP_STATUS_SUCCESS) {
   1386 			(void) printf("%s\n", getTextString(TEXT_UNKNOWN));
   1387 		} else {
   1388 			displayArray(tportProps.portID,
   1389 			    sizeof (tportProps.portID));
   1390 			(void) printf("\n");
   1391 		}
   1392 
   1393 		(void) printf("\t\t%s  ", getTextString(TEXT_LB_OVERRIDE_PATH));
   1394 		if (MP_FALSE == pluginProps.canOverridePaths) {
   1395 			(void) printf("%s\n", getTextString(TEXT_NA));
   1396 		} else if (luProps.overridePath.objectSequenceNumber ==
   1397 		    pPathOidListArray->oids[pa].objectSequenceNumber) {
   1398 			(void) printf("%s\n", getTextString(TEXT_YES));
   1399 		} else {
   1400 			(void) printf("%s\n", getTextString(TEXT_NO));
   1401 		}
   1402 
   1403 		(void) printf("\t\t%s  %s\n", getTextString(TEXT_LB_PATH_STATE),
   1404 		    getPathStateStr(pathProps.pathState));
   1405 
   1406 		(void) printf("\t\t%s  %s\n\n", getTextString(TEXT_LB_DISABLED),
   1407 		    pathProps.disabled?getTextString(TEXT_YES):
   1408 		    getTextString(TEXT_NO));
   1409 
   1410 	}
   1411 
   1412 	/* get tpg info */
   1413 	mpstatus = MP_GetAssociatedTPGOidList(luOid, &pTPGOidListArray);
   1414 	if (mpstatus != MP_STATUS_SUCCESS) {
   1415 		(void) fprintf(stderr, "%s:  %s", cmdName,
   1416 		    getTextString(ERR_NO_ASSOC_TPGS));
   1417 	} else {
   1418 
   1419 	/* display tpg info only if is assymetric */
   1420 	if (MP_TRUE == luProps.asymmetric) {
   1421 		(void) printf("\t%s  \n", getTextString(TEXT_LB_TPG_INFO));
   1422 	}
   1423 
   1424 		for (tpg = 0; tpg < pTPGOidListArray->oidCount; tpg++) {
   1425 			(void) memset(&tpgProps, 0,
   1426 			    sizeof (MP_TARGET_PORT_GROUP_PROPERTIES));
   1427 			mpstatus = MP_GetTargetPortGroupProperties(
   1428 			    pTPGOidListArray->oids[tpg], &tpgProps);
   1429 			if (mpstatus != MP_STATUS_SUCCESS) {
   1430 				(void) fprintf(stderr, "%s:  %s",
   1431 				    cmdName, getTextString(ERR_NO_PROPERTIES));
   1432 			} else {
   1433 				/* display tpg info only if is assymetric */
   1434 				if (tpg > 0) {
   1435 					(void) printf("\n");
   1436 				}
   1437 				if (MP_TRUE == luProps.asymmetric) {
   1438 					(void) printf("\t\t%s  %d\n",
   1439 					    getTextString(TEXT_LB_ID),
   1440 					    tpgProps.tpgID);
   1441 					(void) printf("\t\t%s  %s\n",
   1442 					    getTextString(
   1443 					    TEXT_LB_EXPLICIT_FAILOVER),
   1444 					    (MP_TRUE ==
   1445 					    tpgProps.explicitFailover)?
   1446 					    getTextString(TEXT_YES):
   1447 					    getTextString(TEXT_NO));
   1448 					(void) printf("\t\t%s  %s\n",
   1449 					    getTextString(
   1450 					    TEXT_LB_ACCESS_STATE),
   1451 					    getAccessStateStr(
   1452 					    tpgProps.accessState));
   1453 					    /* display label for each tpg. */
   1454 					(void) printf("\t\t%s\n",
   1455 					    getTextString(TEXT_TPORT_LIST));
   1456 				} else {
   1457 					/* display label once for symmetric. */
   1458 					if (B_TRUE == showTportLabel) {
   1459 					/* begin back-up indentation */
   1460 					(void) printf("\t%s\n",
   1461 					    getTextString(TEXT_TPORT_LIST));
   1462 					showTportLabel = B_FALSE;
   1463 					/* end back-up indentation */
   1464 					}
   1465 				}
   1466 
   1467 				/* get target port info */
   1468 				mpstatus = MP_GetTargetPortOidList(
   1469 				    pTPGOidListArray->oids[tpg],
   1470 				    &pTportOidListArray);
   1471 				if (mpstatus != MP_STATUS_SUCCESS) {
   1472 					(void) fprintf(stderr, "%s:  %s",
   1473 					    cmdName,
   1474 					    getTextString(ERR_NO_ASSOC_TPORTS));
   1475 				} else {
   1476 
   1477 /* begin back-up indentation */
   1478 	for (tport = 0; tport < pTportOidListArray->oidCount; tport++) {
   1479 		(void) memset(&tportProps, 0,
   1480 		    sizeof (MP_TARGET_PORT_PROPERTIES));
   1481 		if ((mpstatus =
   1482 		    MP_GetTargetPortProperties(pTportOidListArray->oids[tport],
   1483 		    &tportProps)) != MP_STATUS_SUCCESS) {
   1484 			(void) fprintf(stderr, "%s:  %s",
   1485 			    cmdName, getTextString(ERR_NO_PROPERTIES));
   1486 		} else {
   1487 			if (MP_TRUE == luProps.asymmetric) {
   1488 				(void) printf("\t\t\t%s  ",
   1489 				    getTextString(TEXT_LB_NAME));
   1490 				displayArray(tportProps.portID,
   1491 				    sizeof (tportProps.portID));
   1492 				(void) printf("\n\t\t\t%s  %d\n",
   1493 				    getTextString(TEXT_LB_RELATIVE_ID),
   1494 				    tportProps.relativePortID);
   1495 			} else {
   1496 				(void) printf("\t\t%s  ",
   1497 				    getTextString(TEXT_LB_NAME));
   1498 				displayArray(tportProps.portID,
   1499 				    sizeof (tportProps.portID));
   1500 				(void) printf("\n\t\t%s  %d\n",
   1501 				    getTextString(TEXT_LB_RELATIVE_ID),
   1502 				    tportProps.relativePortID);
   1503 			}
   1504 			/* insert blank line if not the last target port. */
   1505 			if (!(tport == (pTportOidListArray->oidCount - 1))) {
   1506 				(void) printf("\n");
   1507 			}
   1508 		}
   1509 	} /* for each target port */
   1510 /* end back-up indentation */
   1511 
   1512 				} /* else got target port props */
   1513 			} /* else got TPG props */
   1514 		} /* for each TPG */
   1515 	} /* else got tpg list */
   1516 
   1517 
   1518 	return (mpstatus);
   1519 }
   1520 
   1521 
   1522 /*
   1523  * ****************************************************************************
   1524  *
   1525  * modifyLogicalUnit -
   1526  * 	mpathadm modify {logical-unit | LU} [options] <logical-unit name>, ...
   1527  *
   1528  * operandLen	- number of operands user passed into the cli
   1529  * operand	- pointer to operand list from user
   1530  * options	- pointer to option list from user
   1531  *
   1532  * ****************************************************************************
   1533  */
   1534 int
   1535 modifyLogicalUnit(int operandLen, char *operand[], cmdOptions_t *options)
   1536 {
   1537 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   1538 	MP_OID					luOid;
   1539 	cmdOptions_t 				*optionList = options;
   1540 	char	*cmdStr = getTextString(TEXT_UNKNOWN);
   1541 	int					op;
   1542 
   1543 	for (op = 0; op < operandLen; op++) {
   1544 		if (B_TRUE != getLogicalUnitOid(operand[op], &luOid)) {
   1545 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   1546 			(void) fprintf(stderr,
   1547 			    getTextString(ERR_LU_NOT_FOUND_WITH_MISSING_LU_STR),
   1548 			    operand[op]);
   1549 			(void) printf("\n");
   1550 			return (ERROR_CLI_FAILED);
   1551 		}
   1552 
   1553 		/* we found the lu oid, now change the options requested */
   1554 		switch (optionList->optval) {
   1555 			case 'a':
   1556 				/* modify autofailback */
   1557 				cmdStr = getTextString(TEXT_AUTO_FAILBACK);
   1558 				if (0 == strcasecmp(optionList->optarg,
   1559 				    getTextString(TEXT_ON))) {
   1560 					mpstatus =
   1561 					    MP_EnableAutoFailback(luOid);
   1562 				} else if (0 == strcasecmp(optionList->optarg,
   1563 				    getTextString(TEXT_OFF))) {
   1564 					mpstatus =
   1565 					    MP_DisableAutoFailback(luOid);
   1566 				} else {
   1567 				/* begin back-up indentation */
   1568 				/* LINTED E_SEC_PRINTF_VAR_FMT */
   1569 				(void) fprintf(stderr, getTextString(
   1570 				    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
   1571 				    cmdStr, getTextString(
   1572 				    TEXT_ILLEGAL_ARGUMENT));
   1573 				(void) printf("\n");
   1574 				return (ERROR_CLI_FAILED);
   1575 				/* start back-up indentation */
   1576 				}
   1577 				break;
   1578 			case 'p':
   1579 				/* modify autoprobing */
   1580 				cmdStr = getTextString(TEXT_AUTO_PROBING);
   1581 				if (0 == strcasecmp(optionList->optarg,
   1582 				    getTextString(TEXT_ON))) {
   1583 					mpstatus =
   1584 					    MP_EnableAutoProbing(luOid);
   1585 				} else if (0 == strcasecmp(optionList->optarg,
   1586 				    getTextString(TEXT_OFF))) {
   1587 					mpstatus =
   1588 					    MP_DisableAutoProbing(luOid);
   1589 				} else {
   1590 				/* begin back-up indentation */
   1591 				/* LINTED E_SEC_PRINTF_VAR_FMT */
   1592 				(void) fprintf(stderr, getTextString(
   1593 				    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
   1594 				    cmdStr, getTextString(
   1595 				    TEXT_ILLEGAL_ARGUMENT));
   1596 				(void) printf("\n");
   1597 				return (ERROR_CLI_FAILED);
   1598 				/* end back-up indentation */
   1599 				}
   1600 				break;
   1601 			case 'b':
   1602 				/* modify loadbalance type */
   1603 				cmdStr = getTextString(TEXT_LOAD_BALANCE);
   1604 				mpstatus =
   1605 				    MP_SetLogicalUnitLoadBalanceType(luOid,
   1606 				    getLbValueFromString(optionList->optarg));
   1607 				break;
   1608 
   1609 		} /* switch */
   1610 		if (MP_STATUS_SUCCESS != mpstatus) {
   1611 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   1612 			(void) fprintf(stderr,
   1613 			    getTextString(
   1614 			    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
   1615 			    cmdStr, getMpStatusStr(mpstatus));
   1616 			(void) printf("\n");
   1617 			return (ERROR_CLI_FAILED);
   1618 		}
   1619 	} /* for each operand */
   1620 	return (mpstatus);
   1621 }
   1622 
   1623 
   1624 /*
   1625  * ****************************************************************************
   1626  *
   1627  * failoverLogicalUnit -
   1628  * 	mpathadm failover {logical-unit | LU} <logical-unit name>, ...
   1629  *
   1630  * operand	- pointer to operand list from user
   1631  *
   1632  * ****************************************************************************
   1633  */
   1634 int
   1635 failoverLogicalUnit(char *operand[])
   1636 {
   1637 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   1638 	MP_OID					luOid;
   1639 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES	luProps;
   1640 	MP_TARGET_PORT_GROUP_PROPERTIES		tpgProps;
   1641 	MP_OID_LIST				*pTpgOidListArray;
   1642 	boolean_t				bFoundIt = B_FALSE;
   1643 	MP_TPG_STATE_PAIR			tpgStatePair;
   1644 
   1645 	int					tpg;
   1646 
   1647 	if (B_TRUE != getLogicalUnitOid(operand[0], &luOid)) {
   1648 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   1649 		(void) fprintf(stderr, getTextString(
   1650 		    ERR_LU_NOT_FOUND_WITH_MISSING_LU_STR),
   1651 		    operand[0]);
   1652 		(void) printf("\n");
   1653 		return (ERROR_CLI_FAILED);
   1654 	}
   1655 
   1656 	/* get LUN properties and check to be sure it's asymmetric */
   1657 	(void) memset(&luProps, 0,
   1658 	    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
   1659 	mpstatus =
   1660 	    MP_GetMPLogicalUnitProperties(luOid, &luProps);
   1661 	if (mpstatus != MP_STATUS_SUCCESS) {
   1662 		(void) fprintf(stderr, "%s:  %s\n",
   1663 		    cmdName, getTextString(ERR_NO_PROPERTIES));
   1664 		return (mpstatus);
   1665 	}
   1666 
   1667 	if (MP_TRUE != luProps.asymmetric) {
   1668 		(void) fprintf(stderr, "%s:  %s\n",
   1669 		    cmdName, getTextString(ERR_LU_NOT_ASYMMETRIC));
   1670 		return (ERROR_CLI_FAILED);
   1671 	}
   1672 
   1673 	/* get TPGs for this LUN */
   1674 	mpstatus =
   1675 	    MP_GetAssociatedTPGOidList(luOid, &pTpgOidListArray);
   1676 	if (mpstatus != MP_STATUS_SUCCESS) {
   1677 		(void) fprintf(stderr, "%s:  %s\n",
   1678 		    cmdName, getTextString(ERR_NO_ASSOC_TPGS));
   1679 		return (mpstatus);
   1680 	}
   1681 
   1682 	/* pick a TPG whose state is active or standby, and change it */
   1683 	/* to opposite via MP_SetTPGAccessState */
   1684 	bFoundIt = B_FALSE;
   1685 	for (tpg = 0; tpg < pTpgOidListArray->oidCount; tpg++) {
   1686 		(void) memset(&tpgProps, 0,
   1687 		    sizeof (MP_TARGET_PORT_GROUP_PROPERTIES));
   1688 		mpstatus =
   1689 		    MP_GetTargetPortGroupProperties(
   1690 		    pTpgOidListArray->oids[tpg], &tpgProps);
   1691 		if (mpstatus != MP_STATUS_SUCCESS) {
   1692 			(void) fprintf(stderr, "%s:  %s\n",
   1693 			    cmdName, getTextString(ERR_NO_PROPERTIES));
   1694 			return (ERROR_CLI_FAILED);
   1695 		}
   1696 		if (MP_FALSE == tpgProps.explicitFailover) {
   1697 			(void) fprintf(stderr, "%s:  %s\n",
   1698 			    cmdName, getTextString(ERR_NO_FAILOVER_ALLOWED));
   1699 			return (ERROR_CLI_FAILED);
   1700 		}
   1701 
   1702 		/* find one that is standby */
   1703 		if ((MP_ACCESS_STATE_STANDBY ==
   1704 		    tpgProps.accessState) && (B_FALSE == bFoundIt)) {
   1705 
   1706 			bFoundIt = B_TRUE;
   1707 
   1708 			tpgStatePair.tpgOid =
   1709 			    pTpgOidListArray->oids[tpg];
   1710 			tpgStatePair.desiredState =
   1711 			    MP_ACCESS_STATE_ACTIVE;
   1712 			mpstatus =
   1713 			    MP_SetTPGAccess(luOid, 1, &tpgStatePair);
   1714 			if (MP_STATUS_SUCCESS != mpstatus) {
   1715 			/* begin back-up indentation */
   1716 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   1717 			(void) fprintf(stderr, getTextString(
   1718 			    ERR_FAILED_TO_FAILOVER_WITH_REASON),
   1719 			    getMpStatusStr(mpstatus));
   1720 			(void) printf("\n");
   1721 			return (mpstatus);
   1722 			/* end back-up indentation */
   1723 			}
   1724 		}
   1725 
   1726 
   1727 	} /* for each tpg */
   1728 
   1729 	if (B_FALSE == bFoundIt) {
   1730 		(void) fprintf(stderr, "%s:  %s\n",
   1731 		    cmdName, getTextString(ERR_LU_ACCESS_STATE_UNCHANGED));
   1732 		return (ERROR_CLI_FAILED);
   1733 	}
   1734 
   1735 	return (mpstatus);
   1736 }
   1737 
   1738 
   1739 /*
   1740  * ****************************************************************************
   1741  *
   1742  * getLogicalUnitOid -
   1743  *	Search through all plugins and get the OID for specified logical unit
   1744  *
   1745  * luFileName	- file name of LU (specified by the user) to find
   1746  * pLuOid	- OID to return
   1747  *
   1748  * ****************************************************************************
   1749  */
   1750 boolean_t
   1751 getLogicalUnitOid(MP_CHAR *luFileName, MP_OID *pluOid)
   1752 {
   1753 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   1754 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES	luProps;
   1755 	MP_PLUGIN_PROPERTIES			pluginProps;
   1756 	MP_OID_LIST	*pPluginOidList, *pLogicalUnitOidList;
   1757 	boolean_t				foundIt = B_FALSE;
   1758 
   1759 	int					i, lu;
   1760 
   1761 	int 					fd1, fd2;
   1762 	ddi_devid_t				devid1, devid2;
   1763 
   1764 	if (NULL == pluOid) {
   1765 		/* print some kind of error msg here - should never happen */
   1766 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   1767 		(void) fprintf(stderr, getTextString(ERR_MEMORY_ALLOCATION));
   1768 		(void) printf("\n");
   1769 		return (B_FALSE);
   1770 	}
   1771 
   1772 	pluOid->objectSequenceNumber = 0;
   1773 	pluOid->objectType = 0;
   1774 	pluOid->ownerId = 0;
   1775 
   1776 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
   1777 	    != MP_STATUS_SUCCESS) {
   1778 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   1779 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   1780 		return (B_FALSE);
   1781 	}
   1782 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
   1783 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   1784 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   1785 		return (ERROR_CLI_FAILED);
   1786 	}
   1787 	for (i = 0; i < pPluginOidList->oidCount; i++) {
   1788 
   1789 		/* get properties so we can list the name */
   1790 		(void) memset(&pluginProps, 0, sizeof (MP_PLUGIN_PROPERTIES));
   1791 		if ((mpstatus =
   1792 		    MP_GetPluginProperties(pPluginOidList->oids[i],
   1793 		    &pluginProps)) != MP_STATUS_SUCCESS) {
   1794 			(void) fprintf(stderr, "%s:  %s\n",
   1795 			    cmdName, getTextString(ERR_NO_PROPERTIES));
   1796 			return (B_FALSE);
   1797 		}
   1798 
   1799 		/* attempt to find this logical unit */
   1800 		mpstatus = MP_GetMultipathLus(pPluginOidList->oids[i],
   1801 		    &pLogicalUnitOidList);
   1802 		if (mpstatus != MP_STATUS_SUCCESS) {
   1803 			(void) fprintf(stderr, "%s:  %s\n",
   1804 			    cmdName, getTextString(ERR_NO_LU_LIST));
   1805 			return (B_FALSE);
   1806 		}
   1807 
   1808 		for (lu = 0; (lu < pLogicalUnitOidList->oidCount) &&
   1809 		    (B_FALSE == foundIt); lu++) {
   1810 
   1811 			/* get lu properties so we can check the name */
   1812 			(void) memset(&luProps, 0,
   1813 			    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
   1814 			mpstatus =
   1815 			    MP_GetMPLogicalUnitProperties(
   1816 			    pLogicalUnitOidList->oids[lu], &luProps);
   1817 			if (mpstatus != MP_STATUS_SUCCESS) {
   1818 				(void) fprintf(stderr, "%s:  %s\n",
   1819 				    cmdName, getTextString(ERR_NO_PROPERTIES));
   1820 				return (B_FALSE);
   1821 			}
   1822 
   1823 			if (compareLUName(luFileName, luProps.deviceFileName)
   1824 			    == B_TRUE) {
   1825 				foundIt = B_TRUE;
   1826 			} else {
   1827 				/* user input didn't match, try via devid */
   1828 				/*
   1829 				 * I don't see a reason to print the error for
   1830 				 * any of these since they'll get the error at
   1831 				 * the end anyway
   1832 				 */
   1833 
   1834 				fd1 = fd2 = -1;
   1835 				devid1 = devid2 = NULL;
   1836 				if (((fd1 = open(luFileName,
   1837 				    O_RDONLY|O_NDELAY)) >= 0) &&
   1838 				    ((fd2 = open(luProps.deviceFileName,
   1839 				    O_RDONLY|O_NDELAY)) >= 0) &&
   1840 				    (devid_get(fd1, &devid1) == 0) &&
   1841 				    (devid_get(fd2, &devid2) == 0) &&
   1842 				    ((NULL != devid1) && (NULL != devid2))) {
   1843 					if (0 ==
   1844 					    (devid_compare(devid1, devid2))) {
   1845 						foundIt = B_TRUE;
   1846 					}
   1847 				}
   1848 
   1849 				if (NULL != devid1) {
   1850 					devid_free(devid1);
   1851 				}
   1852 				if (NULL != devid2) {
   1853 					devid_free(devid2);
   1854 				}
   1855 
   1856 				if (fd1 >= 0) {
   1857 					(void) close(fd1);
   1858 				}
   1859 				if (fd2 >= 0) {
   1860 					(void) close(fd2);
   1861 				}
   1862 			}
   1863 			if (B_TRUE == foundIt) {
   1864 				pluOid->objectSequenceNumber =
   1865 				    pLogicalUnitOidList->
   1866 				    oids[lu].objectSequenceNumber;
   1867 				pluOid->objectType =
   1868 				    pLogicalUnitOidList->
   1869 				    oids[lu].objectType;
   1870 				pluOid->ownerId =
   1871 				    pLogicalUnitOidList->oids[lu].ownerId;
   1872 			}
   1873 		}
   1874 	}
   1875 
   1876 	return (foundIt);
   1877 }
   1878 
   1879 
   1880 /*
   1881  * ****************************************************************************
   1882  *
   1883  * listInitiatorPort -
   1884  * 	mpathadm list initiator-port [<initiator-port name>, ...]
   1885  *
   1886  * operandLen	- number of operands user passed into the cli
   1887  * operand	- pointer to operand list from user
   1888  *
   1889  * ****************************************************************************
   1890  */
   1891 int
   1892 listInitiatorPort(int operandLen, char *operand[])
   1893 {
   1894 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   1895 	MP_INITIATOR_PORT_PROPERTIES 		initProps;
   1896 	MP_OID_LIST	*pPluginOidList, *pInitOidList;
   1897 	boolean_t				bListIt = B_FALSE;
   1898 	boolean_t				*foundOp;
   1899 
   1900 	int		ol, i, iport;
   1901 
   1902 	foundOp = malloc((sizeof (boolean_t)) * operandLen);
   1903 	if (NULL == foundOp) {
   1904 		(void) fprintf(stdout, "%s\n",
   1905 		    getTextString(ERR_MEMORY_ALLOCATION));
   1906 		return (ERROR_CLI_FAILED);
   1907 	}
   1908 
   1909 	for (ol = 0; ol < operandLen; ol++) {
   1910 		foundOp[ol] = B_FALSE;
   1911 	}
   1912 
   1913 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
   1914 	    != MP_STATUS_SUCCESS) {
   1915 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   1916 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   1917 		return (mpstatus);
   1918 	}
   1919 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
   1920 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   1921 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   1922 		return (ERROR_CLI_FAILED);
   1923 	}
   1924 
   1925 	for (i = 0; i < pPluginOidList->oidCount; i++) {
   1926 		mpstatus =
   1927 		    MP_GetInitiatorPortOidList(pPluginOidList->oids[i],
   1928 		    &pInitOidList);
   1929 		if (mpstatus != MP_STATUS_SUCCESS) {
   1930 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   1931 			(void) fprintf(stderr,
   1932 			    getTextString(ERR_NO_INIT_PORT_LIST_WITH_REASON),
   1933 			    getMpStatusStr(mpstatus));
   1934 			(void) printf("\n");
   1935 		} else if ((NULL == pInitOidList) ||
   1936 		    (pInitOidList->oidCount < 1)) {
   1937 			(void) fprintf(stderr, "%s: %s\n", cmdName,
   1938 			    getTextString(ERR_NO_INIT_PORTS));
   1939 		} else {
   1940 			for (iport = 0;
   1941 			    iport < pInitOidList->oidCount; iport ++) {
   1942 				bListIt = B_FALSE;
   1943 				if ((mpstatus =
   1944 				    MP_GetInitiatorPortProperties(
   1945 				    pInitOidList->oids[iport],
   1946 				    &initProps)) != MP_STATUS_SUCCESS) {
   1947 					(void) fprintf(stderr,
   1948 					    "%s: %s\n", cmdName,
   1949 					    getTextString(ERR_NO_PROPERTIES));
   1950 				} else {
   1951 					/* if no operands listed, */
   1952 					/* list all we find */
   1953 					if (0 == operandLen) {
   1954 						bListIt = B_TRUE;
   1955 					} else {
   1956 
   1957 						/* check each operand */
   1958 						/* Is it */
   1959 						/* the one we want to list? */
   1960 						for (ol = 0;
   1961 						    ol < operandLen; ol++) {
   1962 							if (0 ==
   1963 							    strcmp(operand[ol],
   1964 							    initProps.
   1965 							    portID)) {
   1966 								bListIt =
   1967 								    B_TRUE;
   1968 								foundOp[ol] =
   1969 								    B_TRUE;
   1970 							}
   1971 						}
   1972 					}
   1973 				}
   1974 
   1975 				if (B_TRUE == bListIt) {
   1976 
   1977 					if (listIndividualInitiatorPort(
   1978 					    initProps) != 0) {
   1979 						return (ERROR_CLI_FAILED);
   1980 					}
   1981 
   1982 				} /* list It */
   1983 
   1984 			} /* for each initiator port */
   1985 		} /* else found an init port */
   1986 
   1987 	} /* for each plugin */
   1988 
   1989 	for (ol = 0; ol < operandLen; ol++) {
   1990 		if (B_FALSE == foundOp[ol]) {
   1991 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   1992 			(void) fprintf(stderr, getTextString(
   1993 			    ERR_INIT_PORT_NOT_FOUND_WITH_MISSING_LU_STR),
   1994 			    operand[ol]);
   1995 			(void) printf("\n");
   1996 		}
   1997 	}
   1998 
   1999 	return (mpstatus);
   2000 }
   2001 
   2002 
   2003 /*
   2004  * ****************************************************************************
   2005  *
   2006  * listIndividualInitiatorPort -
   2007  * 	used by listInitiatorPort to list info for one init port
   2008  *
   2009  * initProps	- properties of initiator port to list
   2010  *
   2011  * ****************************************************************************
   2012  */
   2013 int
   2014 listIndividualInitiatorPort(MP_INITIATOR_PORT_PROPERTIES initProps)
   2015 {
   2016 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   2017 
   2018 	(void) printf("%s  ", getTextString(TEXT_LB_INITATOR_PORT));
   2019 	displayArray(initProps.portID,
   2020 	    sizeof (initProps.portID));
   2021 	(void) printf("\n");
   2022 
   2023 	return (mpstatus);
   2024 
   2025 }
   2026 
   2027 
   2028 /*
   2029  * ****************************************************************************
   2030  *
   2031  * showInitiatorPort -
   2032  * 	mpathadm show initiator-port <initiator-port name>, ...
   2033  *
   2034  * operandLen	- number of operands user passed into the cli
   2035  * operand	- pointer to operand list from user
   2036  *
   2037  * ****************************************************************************
   2038  */
   2039 int
   2040 showInitiatorPort(int operandLen, char *operand[])
   2041 {
   2042 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   2043 	MP_INITIATOR_PORT_PROPERTIES 		initProps;
   2044 	MP_OID_LIST	*pPluginOidList, *pInitOidList;
   2045 	boolean_t	bListIt = B_FALSE, bFoundIt = B_FALSE;
   2046 	int		op, i, iport;
   2047 
   2048 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
   2049 	    != MP_STATUS_SUCCESS) {
   2050 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   2051 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   2052 		return (mpstatus);
   2053 	}
   2054 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
   2055 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   2056 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   2057 		return (ERROR_CLI_FAILED);
   2058 	}
   2059 
   2060 	for (op = 0; op < operandLen; op++) {
   2061 	bFoundIt = B_FALSE;
   2062 
   2063 		for (i = 0; i < pPluginOidList->oidCount; i++) {
   2064 
   2065 			mpstatus =
   2066 			    MP_GetInitiatorPortOidList(pPluginOidList->oids[i],
   2067 			    &pInitOidList);
   2068 			if (mpstatus != MP_STATUS_SUCCESS) {
   2069 				/* LINTED E_SEC_PRINTF_VAR_FMT */
   2070 				(void) fprintf(stderr,
   2071 				    getTextString(
   2072 				    ERR_NO_INIT_PORT_LIST_WITH_REASON),
   2073 				    getMpStatusStr(mpstatus));
   2074 				(void) printf("\n");
   2075 			} else if ((NULL == pInitOidList) ||
   2076 			    (pInitOidList->oidCount < 1)) {
   2077 				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2078 				    getTextString(ERR_NO_INIT_PORTS));
   2079 			} else {
   2080 
   2081 				for (iport = 0;
   2082 				    iport < pInitOidList->oidCount;
   2083 				    iport ++) {
   2084 					bListIt = B_FALSE;
   2085 
   2086 					if ((mpstatus =
   2087 					    MP_GetInitiatorPortProperties(
   2088 					    pInitOidList->oids[iport],
   2089 					    &initProps))
   2090 					    != MP_STATUS_SUCCESS) {
   2091 					/* begin back-up indentation */
   2092 					(void) fprintf(stderr,
   2093 					    "%s: %s\n", cmdName,
   2094 					    getTextString(ERR_NO_PROPERTIES));
   2095 					/* end back-up indentation */
   2096 					} else {
   2097 						if (0 == strcmp(operand[op],
   2098 						    initProps.portID)) {
   2099 							bListIt = B_TRUE;
   2100 							bFoundIt = B_TRUE;
   2101 						}
   2102 					}
   2103 
   2104 					if (B_TRUE == bListIt) {
   2105 						mpstatus =
   2106 						    showIndividualInitiatorPort(
   2107 						    initProps);
   2108 						if (0 != mpstatus) {
   2109 							return (mpstatus);
   2110 						}
   2111 
   2112 					} /* list It */
   2113 
   2114 				} /* for each initiator port */
   2115 			} /* else found an init port */
   2116 
   2117 		} /* for each plugin */
   2118 
   2119 		if (B_FALSE == bFoundIt) {
   2120 			/* need temp string here since we need to fill in a */
   2121 			/* name in the error string */
   2122 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   2123 			(void) fprintf(stderr, getTextString(
   2124 			    ERR_INIT_PORT_NOT_FOUND_WITH_MISSING_LU_STR),
   2125 			    operand[op]);
   2126 			(void) printf("\n");
   2127 		}
   2128 
   2129 	} /* for each operand */
   2130 
   2131 	return (mpstatus);
   2132 }
   2133 
   2134 
   2135 /*
   2136  * ****************************************************************************
   2137  *
   2138  * showIndividualInitiatorPort -
   2139  * 	used by showInitiatorPort to show info for one init port
   2140  *
   2141  * initProps	- properties of initiator port to show
   2142  *
   2143  * ****************************************************************************
   2144  */
   2145 int
   2146 showIndividualInitiatorPort(MP_INITIATOR_PORT_PROPERTIES initProps)
   2147 {
   2148 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   2149 
   2150 	(void) printf("%s  ", getTextString(TEXT_LB_INITATOR_PORT));
   2151 	displayArray(initProps.portID,
   2152 	    sizeof (initProps.portID));
   2153 
   2154 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_TRANSPORT_TYPE));
   2155 	displayTransportTypeString(initProps.portType);
   2156 	(void) printf("\n");
   2157 
   2158 	(void) printf("\t%s  ", getTextString(TEXT_LB_OS_DEVICE_FILE));
   2159 	displayArray(initProps.osDeviceFile,
   2160 	    sizeof (initProps.osDeviceFile));
   2161 	(void) printf("\n");
   2162 
   2163 	return (mpstatus);
   2164 }
   2165 
   2166 
   2167 /*
   2168  * ****************************************************************************
   2169  *
   2170  * enablePath -
   2171  * 	mpathadm enable path -i <initiator-port>
   2172  *		-t <target-port name> -l <logical-unit name>
   2173  *
   2174  * options	- pointer to option list from user
   2175  *
   2176  * ****************************************************************************
   2177  */
   2178 int
   2179 enablePath(cmdOptions_t *options)
   2180 {
   2181 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   2182 	MP_OID					pathOid;
   2183 
   2184 	cmdOptions_t 				*optionList = options;
   2185 	boolean_t   bHaveInit = B_FALSE, bHaveTarg = B_FALSE, bHaveLu = B_FALSE;
   2186 
   2187 	for (; optionList->optval; optionList++) {
   2188 		switch (optionList->optval) {
   2189 			case 'i':
   2190 				/* have init port name */
   2191 				bHaveInit = B_TRUE;
   2192 				break;
   2193 			case 't':
   2194 				/* have target port id */
   2195 				bHaveTarg = B_TRUE;
   2196 				break;
   2197 			case 'l':
   2198 				/* have LU name */
   2199 				bHaveLu = B_TRUE;
   2200 				break;
   2201 		}
   2202 	}
   2203 	if (B_FALSE == bHaveInit) {
   2204 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2205 		(void) fprintf(stderr,
   2206 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
   2207 		    getTextString(MISSING_INIT_PORT_NAME));
   2208 		(void) printf("\n");
   2209 		return (ERROR_CLI_FAILED);
   2210 	} else if (B_FALSE == bHaveTarg) {
   2211 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2212 		(void) fprintf(stderr,
   2213 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
   2214 		    getTextString(MISSING_TARGET_PORT_NAME));
   2215 		(void) printf("\n");
   2216 		return (ERROR_CLI_FAILED);
   2217 	} else if (B_FALSE == bHaveLu) {
   2218 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2219 		(void) fprintf(stderr,
   2220 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
   2221 		    getTextString(MISSING_LU_NAME));
   2222 		(void) printf("\n");
   2223 		return (ERROR_CLI_FAILED);
   2224 	}
   2225 
   2226 	if (B_FALSE == getPathOid(options, &pathOid)) {
   2227 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2228 		(void) fprintf(stderr,
   2229 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
   2230 		    getTextString(FAILED_TO_FIND_PATH));
   2231 		(void) printf("\n");
   2232 		return (ERROR_CLI_FAILED);
   2233 	}
   2234 
   2235 	/* found the path, attempt to enable it */
   2236 	mpstatus =  MP_EnablePath(pathOid);
   2237 	if (mpstatus != MP_STATUS_SUCCESS) {
   2238 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2239 		(void) fprintf(stderr,
   2240 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
   2241 		    getMpStatusStr(mpstatus));
   2242 		(void) printf("\n");
   2243 		return (mpstatus);
   2244 	}
   2245 
   2246 	return (mpstatus);
   2247 }
   2248 
   2249 
   2250 /*
   2251  * ****************************************************************************
   2252  *
   2253  * disablePath -
   2254  * 	mpathadm disable path -i <initiator-port>
   2255  *		-t <target-port name> -l <logical-unit name>
   2256  *
   2257  * options	- pointer to option list from user
   2258  *
   2259  * ****************************************************************************
   2260  */
   2261 int
   2262 disablePath(cmdOptions_t *options)
   2263 {
   2264 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   2265 	MP_OID					pathOid;
   2266 
   2267 	cmdOptions_t 				*optionList = options;
   2268 	boolean_t	bHaveInit = B_FALSE, bHaveTarg = B_FALSE,
   2269 	    bHaveLu = B_FALSE;
   2270 
   2271 	for (; optionList->optval; optionList++) {
   2272 		switch (optionList->optval) {
   2273 			case 'i':
   2274 				/* have init port name */
   2275 				bHaveInit = B_TRUE;
   2276 				break;
   2277 			case 't':
   2278 				/* have target port id */
   2279 				bHaveTarg = B_TRUE;
   2280 				break;
   2281 			case 'l':
   2282 				/* have LU name */
   2283 				bHaveLu = B_TRUE;
   2284 				break;
   2285 		}
   2286 	}
   2287 	if (B_FALSE == bHaveInit) {
   2288 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2289 		(void) fprintf(stderr,
   2290 		    getTextString(ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
   2291 		    getTextString(MISSING_INIT_PORT_NAME));
   2292 		(void) printf("\n");
   2293 		return (ERROR_CLI_FAILED);
   2294 	} else if (B_FALSE == bHaveTarg) {
   2295 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2296 		(void) fprintf(stderr,
   2297 		    getTextString(ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
   2298 		    getTextString(MISSING_TARGET_PORT_NAME));
   2299 		(void) printf("\n");
   2300 		return (ERROR_CLI_FAILED);
   2301 	} else if (B_FALSE == bHaveLu) {
   2302 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2303 		(void) fprintf(stderr,
   2304 		    getTextString(ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
   2305 		    getTextString(MISSING_LU_NAME));
   2306 		(void) printf("\n");
   2307 		return (ERROR_CLI_FAILED);
   2308 	}
   2309 
   2310 	if (B_FALSE == getPathOid(options, &pathOid)) {
   2311 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2312 		(void) fprintf(stderr,
   2313 		    getTextString(ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
   2314 		    getTextString(FAILED_TO_FIND_PATH));
   2315 		(void) printf("\n");
   2316 		return (ERROR_CLI_FAILED);
   2317 	}
   2318 
   2319 	/* found the path, attempt to enable it */
   2320 	mpstatus =  MP_DisablePath(pathOid);
   2321 	if (MP_STATUS_SUCCESS != mpstatus) {
   2322 		/* LINTED E_SEC_PRINTF_VAR_FMT */
   2323 		(void) fprintf(stderr, getTextString(
   2324 		    ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
   2325 		    getMpStatusStr(mpstatus));
   2326 		(void) printf("\n");
   2327 		return (mpstatus);
   2328 	}
   2329 
   2330 
   2331 	return (mpstatus);
   2332 }
   2333 
   2334 
   2335 /*
   2336  * ****************************************************************************
   2337  *
   2338  * overridePath -
   2339  * 	mpathadm override path {-i <initiator-port>
   2340  *		-t <target-port name> | -c} <logical-unit name>
   2341  *
   2342  * options	- pointer to option list from user
   2343  *
   2344  * ****************************************************************************
   2345  */
   2346 int
   2347 overridePath(cmdOptions_t *options)
   2348 {
   2349 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   2350 	MP_OID					pathOid, luOid;
   2351 	boolean_t				bCancelOverride = B_FALSE;
   2352 	MP_CHAR					pLuDeviceFileName[256];
   2353 	cmdOptions_t 				*optionList = options;
   2354 
   2355 	/* First check to see if we have the cancel option, */
   2356 	/* May as well save off the lun while we're at it */
   2357 	for (; optionList->optval; optionList++) {
   2358 		switch (optionList->optval) {
   2359 			case 'c':
   2360 				/* we have a cancel */
   2361 				bCancelOverride = B_TRUE;
   2362 				break;
   2363 			case 'l':
   2364 				/* we have a lun- save it while we're here */
   2365 				(void) memcpy(pLuDeviceFileName,
   2366 				    optionList->optarg, 256);
   2367 				break;
   2368 		}
   2369 	}
   2370 
   2371 	if (B_TRUE == bCancelOverride) {
   2372 		/* if we have the cancel option, */
   2373 		if (getLogicalUnitOid(pLuDeviceFileName, &luOid) == B_FALSE) {
   2374 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   2375 			(void) fprintf(stderr,
   2376 			    getTextString(
   2377 			    ERR_FAILED_TO_CANCEL_OVERRIDE_PATH_WITH_REASON),
   2378 			    getTextString(LU_NOT_FOUND));
   2379 			(void) printf("\n");
   2380 			return (ERROR_CLI_FAILED);
   2381 		}
   2382 
   2383 		/* cancel the override path for the specified LU */
   2384 		mpstatus = MP_CancelOverridePath(luOid);
   2385 		if (MP_STATUS_SUCCESS != mpstatus) {
   2386 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   2387 			(void) fprintf(stderr,
   2388 			    getTextString(
   2389 			    ERR_FAILED_TO_CANCEL_OVERRIDE_PATH_WITH_REASON),
   2390 			    getMpStatusStr(mpstatus));
   2391 			(void) printf("\n");
   2392 			return (mpstatus);
   2393 		}
   2394 	} else {
   2395 		/* must be wanting to override the path */
   2396 		if (getLogicalUnitOid(pLuDeviceFileName, &luOid) == B_FALSE) {
   2397 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   2398 			(void) fprintf(stderr,
   2399 			    getTextString(
   2400 			    ERR_FAILED_TO_OVERRIDE_PATH_WITH_REASON),
   2401 			    getTextString(LU_NOT_FOUND));
   2402 			(void) printf("\n");
   2403 			return (ERROR_CLI_FAILED);
   2404 		}
   2405 
   2406 		if (B_FALSE == getPathOid(options, &pathOid)) {
   2407 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   2408 			(void) fprintf(stderr,
   2409 			    getTextString(
   2410 			    ERR_FAILED_TO_OVERRIDE_PATH_WITH_REASON),
   2411 			    getTextString(FAILED_TO_FIND_PATH));
   2412 
   2413 			(void) printf("\n");
   2414 			return (ERROR_CLI_FAILED);
   2415 		}
   2416 
   2417 		/* attempt to set the override path */
   2418 		mpstatus =  MP_SetOverridePath(luOid, pathOid);
   2419 		if (mpstatus != MP_STATUS_SUCCESS) {
   2420 			/* LINTED E_SEC_PRINTF_VAR_FMT */
   2421 			(void) fprintf(stderr,
   2422 			    getTextString(
   2423 			    ERR_FAILED_TO_OVERRIDE_PATH_WITH_REASON),
   2424 			    getMpStatusStr(mpstatus));
   2425 			(void) printf("\n");
   2426 			return (mpstatus);
   2427 		}
   2428 	}
   2429 
   2430 	return (mpstatus);
   2431 }
   2432 
   2433 
   2434 /*
   2435  * ****************************************************************************
   2436  *
   2437  * getPathOid -
   2438  *	Search through all plugins and get the OID for specified path
   2439  *
   2440  * operand	- pointer to operand list from user
   2441  * options	- pointer to option list from user
   2442  *
   2443  * ****************************************************************************
   2444  */
   2445 boolean_t
   2446 getPathOid(cmdOptions_t *options, MP_OID *pPathOid)
   2447 {
   2448 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
   2449 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES 	luProps;
   2450 	MP_PATH_LOGICAL_UNIT_PROPERTIES		pathProps;
   2451 	MP_INITIATOR_PORT_PROPERTIES		initProps;
   2452 	MP_TARGET_PORT_PROPERTIES		targProps;
   2453 
   2454 	MP_OID_LIST	*pPluginOidList, *pLogicalUnitOidList,
   2455 	    *pathOidListArray;
   2456 
   2457 	boolean_t				bFoundIt = B_FALSE;
   2458 	MP_CHAR					initPortID[256];
   2459 	MP_CHAR					targetPortID[256];
   2460 	MP_CHAR					luDeviceFileName[256];
   2461 	boolean_t	bHaveTarg = B_FALSE, bHaveLu = B_FALSE,
   2462 	    bHaveInit = B_FALSE;
   2463 	cmdOptions_t 				*optionList = options;
   2464 
   2465 	int					i, lu, pa;
   2466 	if (NULL == pPathOid) {
   2467 		return (B_FALSE);
   2468 	}
   2469 
   2470 	for (; optionList->optval; optionList++) {
   2471 		switch (optionList->optval) {
   2472 			case 'i':
   2473 				/* save init port name */
   2474 				(void) memcpy(initPortID,
   2475 				    optionList->optarg, 256);
   2476 				bHaveInit = B_TRUE;
   2477 				break;
   2478 			case 't':
   2479 				/* save target port id */
   2480 				(void) memcpy(targetPortID,
   2481 				    optionList->optarg, 256);
   2482 				bHaveTarg = B_TRUE;
   2483 				break;
   2484 			case 'l':
   2485 				/* save LU name */
   2486 				(void) memcpy(luDeviceFileName,
   2487 				    optionList->optarg, 256);
   2488 				bHaveLu = B_TRUE;
   2489 				break;
   2490 		}
   2491 	}
   2492 
   2493 
   2494 	if ((B_FALSE == bHaveInit) ||
   2495 	    (B_FALSE == bHaveTarg) ||
   2496 	    (B_FALSE == bHaveLu)) {
   2497 		/* if we don't have all three pieces, we can't find the path */
   2498 
   2499 		return (B_FALSE);
   2500 	}
   2501 
   2502 	/* get the plugin ist */
   2503 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
   2504 	    != MP_STATUS_SUCCESS) {
   2505 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   2506 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   2507 		return (B_FALSE);
   2508 	}
   2509 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
   2510 		(void) fprintf(stderr, "%s: %s\n", cmdName,
   2511 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
   2512 		return (B_FALSE);
   2513 	}
   2514 
   2515 	for (i = 0; i < pPluginOidList->oidCount; i++) {
   2516 
   2517 		/* get Logical Unit list */
   2518 		mpstatus = MP_GetMultipathLus(pPluginOidList->oids[i],
   2519 		    &pLogicalUnitOidList);
   2520 		if (mpstatus != MP_STATUS_SUCCESS) {
   2521 			(void) fprintf(stderr, "%s:  %s\n",
   2522 			    cmdName, getTextString(ERR_NO_LU_LIST));
   2523 			return (B_FALSE);
   2524 		}
   2525 
   2526 		for (lu = 0; (lu < pLogicalUnitOidList->oidCount) &&
   2527 		    (B_FALSE == bFoundIt); lu++) {
   2528 
   2529 			/* get lu properties so we can check the name */
   2530 			(void) memset(&luProps, 0,
   2531 			    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
   2532 			mpstatus =
   2533 			    MP_GetMPLogicalUnitProperties(
   2534 			    pLogicalUnitOidList->oids[lu], &luProps);
   2535 			if (mpstatus != MP_STATUS_SUCCESS) {
   2536 				(void) fprintf(stderr, "%s:  %s\n",
   2537 				    cmdName, getTextString(ERR_NO_PROPERTIES));
   2538 				return (B_FALSE);
   2539 			}
   2540 			if (compareLUName(luDeviceFileName,
   2541 			    luProps.deviceFileName) == B_TRUE) {
   2542 				/* get paths for this LU and search from here */
   2543 				mpstatus =
   2544 				    MP_GetAssociatedPathOidList(
   2545 				    pLogicalUnitOidList->oids[lu],
   2546 				    &pathOidListArray);
   2547 				if (mpstatus != MP_STATUS_SUCCESS) {
   2548 					/* LINTED E_SEC_PRINTF_VAR_FMT */
   2549 					(void) fprintf(stderr,
   2550 					    getTextString(
   2551 					    ERR_FAILED_TO_FIND_PATH));
   2552 					(void) printf("\n");
   2553 					return (B_FALSE);
   2554 				}
   2555 
   2556 				for (pa = 0;
   2557 				    (pa < pathOidListArray->oidCount) &&
   2558 				    (B_FALSE == bFoundIt); pa++) {
   2559 					mpstatus =
   2560 					    MP_GetPathLogicalUnitProperties
   2561 					    (pathOidListArray->oids[pa],
   2562 					    &pathProps);
   2563 					if (mpstatus != MP_STATUS_SUCCESS) {
   2564 						(void) fprintf(stderr,
   2565 						    "%s:  %s\n", cmdName,
   2566 						    getTextString(
   2567 						    ERR_NO_PROPERTIES));
   2568 						return (B_FALSE);
   2569 					}
   2570 
   2571 					/*
   2572 					 * get properties of iniator port and
   2573 					 * target port to see if we have the
   2574 					 * right path
   2575 					 */
   2576 					mpstatus =
   2577 					    MP_GetInitiatorPortProperties(
   2578 					    pathProps.initiatorPortOid,
   2579 					    &initProps);
   2580 
   2581 					if (mpstatus != MP_STATUS_SUCCESS) {
   2582 						(void) fprintf(stderr,
   2583 						    "%s:  %s\n", cmdName,
   2584 						    getTextString(
   2585 						    ERR_NO_PROPERTIES));
   2586 						return (B_FALSE);
   2587 					}
   2588 	if (0 == strcmp(initPortID, initProps.portID)) {
   2589 		/* lu and init port matches, check target port */
   2590 		mpstatus = MP_GetTargetPortProperties(pathProps.targetPortOid,
   2591 		    &targProps);
   2592 		if (mpstatus != MP_STATUS_SUCCESS) {
   2593 			(void) fprintf(stderr, "%s:  %s\n", cmdName,
   2594 			    getTextString(ERR_NO_PROPERTIES));
   2595 			return (B_FALSE);
   2596 		}
   2597 
   2598 		if (0 == strcmp(targetPortID, targProps.portID)) {
   2599 			/* we found our path */
   2600 			pPathOid->objectSequenceNumber =
   2601 			    pathOidListArray->oids[pa].objectSequenceNumber;
   2602 			pPathOid->objectType =
   2603 			    pathOidListArray->oids[pa].objectType;
   2604 			pPathOid->ownerId = pathOidListArray->oids[pa].ownerId;
   2605 			bFoundIt = B_TRUE;
   2606 		}
   2607 	} /* init port matched */
   2608 
   2609 				} /* for each path associated with this lu */
   2610 
   2611 			} /* lu matched */
   2612 
   2613 		} /* for each lu */
   2614 
   2615 	} /* for each plugin */
   2616 
   2617 	return (bFoundIt);
   2618 }
   2619 
   2620 
   2621 /*
   2622  * ****************************************************************************
   2623  *
   2624  * getLbValueFromString
   2625  * 	Gets the MP_LOAD_BALANCE_TYPE specified load balance type string
   2626  *
   2627  * lbStr	- load balance string defined in the .h file
   2628  *		This is what users will be required to feed into the
   2629  *		modify lu command.
   2630  *
   2631  * ****************************************************************************
   2632  */
   2633 MP_LOAD_BALANCE_TYPE
   2634 getLbValueFromString(char *lbStr)
   2635 {
   2636 	MP_LOAD_BALANCE_TYPE		lbVal = MP_LOAD_BALANCE_TYPE_UNKNOWN;
   2637 
   2638 	if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_ROUNDROBIN))) {
   2639 		lbVal = MP_LOAD_BALANCE_TYPE_ROUNDROBIN;
   2640 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_LEASTBLOCKS))) {
   2641 		lbVal = MP_LOAD_BALANCE_TYPE_LEASTBLOCKS;
   2642 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_LEASTIO))) {
   2643 		lbVal = MP_LOAD_BALANCE_TYPE_LEASTIO;
   2644 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_DEVICEPROD))) {
   2645 		lbVal = MP_LOAD_BALANCE_TYPE_DEVICE_PRODUCT;
   2646 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_LBAREGION))) {
   2647 		lbVal = MP_LOAD_BALANCE_TYPE_LBA_REGION;
   2648 	} else if (0 == strcmp(lbStr,
   2649 	    getTextString(TEXT_LBTYPE_FAILOVER_ONLY))) {
   2650 		lbVal = MP_LOAD_BALANCE_TYPE_FAILOVER_ONLY;
   2651 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_UNKNOWN))) {
   2652 		lbVal = MP_LOAD_BALANCE_TYPE_UNKNOWN;
   2653 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_NONE))) {
   2654 		lbVal = 0;
   2655 	} else if (0 == strcmp(lbStr,
   2656 	    getTextString(TEXT_LBTYPE_PROPRIETARY1))) {
   2657 		lbVal = ((MP_UINT32)0x00000001)<<16;
   2658 	} else if (0 == strcmp(lbStr,
   2659 	    getTextString(TEXT_LBTYPE_PROPRIETARY2))) {
   2660 		lbVal = ((MP_UINT32)0x00000001)<<17;
   2661 	} else if (0 == strcmp(lbStr,
   2662 	    getTextString(TEXT_LBTYPE_PROPRIETARY3))) {
   2663 		lbVal = ((MP_UINT32)0x00000001)<<18;
   2664 	} else if (0 == strcmp(lbStr,
   2665 	    getTextString(TEXT_LBTYPE_PROPRIETARY4))) {
   2666 		lbVal = ((MP_UINT32)0x00000001)<<19;
   2667 	} else if (0 == strcmp(lbStr,
   2668 	    getTextString(TEXT_LBTYPE_PROPRIETARY5))) {
   2669 		lbVal = ((MP_UINT32)0x00000001)<<20;
   2670 	} else if (0 == strcmp(lbStr,
   2671 	    getTextString(TEXT_LBTYPE_PROPRIETARY6))) {
   2672 		lbVal = ((MP_UINT32)0x00000001)<<21;
   2673 	} else if (0 == strcmp(lbStr,
   2674 	    getTextString(TEXT_LBTYPE_PROPRIETARY7))) {
   2675 		lbVal = ((MP_UINT32)0x00000001)<<22;
   2676 	} else if (0 == strcmp(lbStr,
   2677 	    getTextString(TEXT_LBTYPE_PROPRIETARY8))) {
   2678 		lbVal = ((MP_UINT32)0x00000001)<<23;
   2679 	} else if (0 == strcmp(lbStr,
   2680 	    getTextString(TEXT_LBTYPE_PROPRIETARY9))) {
   2681 		lbVal = ((MP_UINT32)0x00000001)<<24;
   2682 	} else if (0 == strcmp(lbStr,
   2683 	    getTextString(TEXT_LBTYPE_PROPRIETARY10))) {
   2684 		lbVal = ((MP_UINT32)0x00000001)<<25;
   2685 	} else if (0 == strcmp(lbStr,
   2686 	    getTextString(TEXT_LBTYPE_PROPRIETARY11))) {
   2687 		lbVal = ((MP_UINT32)0x00000001)<<26;
   2688 	} else if (0 == strcmp(lbStr,
   2689 	    getTextString(TEXT_LBTYPE_PROPRIETARY12))) {
   2690 		lbVal = ((MP_UINT32)0x00000001)<<27;
   2691 	} else if (0 == strcmp(lbStr,
   2692 	    getTextString(TEXT_LBTYPE_PROPRIETARY13))) {
   2693 		lbVal = ((MP_UINT32)0x00000001)<<28;
   2694 	} else if (0 == strcmp(lbStr,
   2695 	    getTextString(TEXT_LBTYPE_PROPRIETARY14))) {
   2696 		lbVal = ((MP_UINT32)0x00000001)<<29;
   2697 	} else if (0 == strcmp(lbStr,
   2698 	    getTextString(TEXT_LBTYPE_PROPRIETARY15))) {
   2699 		lbVal = ((MP_UINT32)0x00000001)<<30;
   2700 	} else if (0 == strcmp(lbStr,
   2701 	    getTextString(TEXT_LBTYPE_PROPRIETARY16))) {
   2702 		lbVal = ((MP_UINT32)0x00000001)<<31;
   2703 	}
   2704 
   2705 	return (lbVal);
   2706 
   2707 
   2708 } /* end getLbValueFromString */
   2709 
   2710 
   2711 /*
   2712  * ****************************************************************************
   2713  *
   2714  * displayLogicalUnitNameTypeString
   2715  * 	Displays the text equivalent string for the MP_LOGICAL_UNIT_NAME_TYPE
   2716  *	specified load balance type
   2717  *
   2718  * typeVal	- load balance type defined in the MPAPI spec
   2719  *
   2720  * ****************************************************************************
   2721  */
   2722 void
   2723 displayLogicalUnitNameTypeString(MP_LOGICAL_UNIT_NAME_TYPE typeVal)
   2724 {
   2725 
   2726 	char					*typeString;
   2727 
   2728 	switch (typeVal) {
   2729 
   2730 		case MP_LU_NAME_TYPE_UNKNOWN:
   2731 			typeString = getTextString(TEXT_NAME_TYPE_UNKNOWN);
   2732 			break;
   2733 		case MP_LU_NAME_TYPE_VPD83_TYPE1:
   2734 			typeString = getTextString(TEXT_NAME_TYPE_VPD83_TYPE1);
   2735 			break;
   2736 		case MP_LU_NAME_TYPE_VPD83_TYPE2:
   2737 			typeString = getTextString(TEXT_NAME_TYPE_VPD83_TYPE2);
   2738 			break;
   2739 		case MP_LU_NAME_TYPE_VPD83_TYPE3:
   2740 			typeString = getTextString(TEXT_NAME_TYPE_VPD83_TYPE3);
   2741 			break;
   2742 		case MP_LU_NAME_TYPE_DEVICE_SPECIFIC:
   2743 			typeString =
   2744 			    getTextString(TEXT_NAME_TYPE_DEVICE_SPECIFIC);
   2745 			break;
   2746 		default:
   2747 			typeString = getTextString(TEXT_UNKNOWN);
   2748 			break;
   2749 	}
   2750 
   2751 	(void) printf("%s", typeString);
   2752 
   2753 
   2754 } /* end displayLogicalUnitNameTypeString */
   2755 
   2756 /*
   2757  * ****************************************************************************
   2758  *
   2759  * displayLoadBalanceString
   2760  * 	Displays the text equivalent string for the MP_LOAD_BALANCE_TYPE
   2761  *	specified load balance type
   2762  *
   2763  * lbVal	- load balance type defined in the MPAPI spec
   2764  *
   2765  * ****************************************************************************
   2766  */
   2767 void
   2768 displayLoadBalanceString(MP_LOAD_BALANCE_TYPE lbVal)
   2769 {
   2770 
   2771 	char					*lbString;
   2772 
   2773 	switch (lbVal) {
   2774 
   2775 		case MP_LOAD_BALANCE_TYPE_UNKNOWN:
   2776 			lbString = getTextString(TEXT_LBTYPE_UNKNOWN);
   2777 			break;
   2778 		case MP_LOAD_BALANCE_TYPE_ROUNDROBIN:
   2779 			lbString = getTextString(TEXT_LBTYPE_ROUNDROBIN);
   2780 			break;
   2781 		case MP_LOAD_BALANCE_TYPE_LEASTBLOCKS:
   2782 			lbString = getTextString(TEXT_LBTYPE_LEASTBLOCKS);
   2783 			break;
   2784 		case MP_LOAD_BALANCE_TYPE_LEASTIO:
   2785 			lbString = getTextString(TEXT_LBTYPE_LEASTIO);
   2786 			break;
   2787 		case MP_LOAD_BALANCE_TYPE_DEVICE_PRODUCT:
   2788 			lbString = getTextString(TEXT_LBTYPE_DEVICEPROD);
   2789 			break;
   2790 		case MP_LOAD_BALANCE_TYPE_LBA_REGION:
   2791 			lbString = getTextString(TEXT_LBTYPE_LBAREGION);
   2792 			break;
   2793 		case MP_LOAD_BALANCE_TYPE_FAILOVER_ONLY:
   2794 			lbString = getTextString(TEXT_LBTYPE_FAILOVER_ONLY);
   2795 			break;
   2796 		case (((MP_UINT32)0x00000001)<<16):
   2797 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY1);
   2798 			break;
   2799 		case (((MP_UINT32)0x00000001)<<17):
   2800 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY2);
   2801 			break;
   2802 		case (((MP_UINT32)0x00000001)<<18):
   2803 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY3);
   2804 			break;
   2805 		case (((MP_UINT32)0x00000001)<<19):
   2806 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY4);
   2807 			break;
   2808 		case (((MP_UINT32)0x00000001)<<20):
   2809 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY5);
   2810 			break;
   2811 		case (((MP_UINT32)0x00000001)<<21):
   2812 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY6);
   2813 			break;
   2814 		case (((MP_UINT32)0x00000001)<<22):
   2815 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY7);
   2816 			break;
   2817 		case (((MP_UINT32)0x00000001)<<23):
   2818 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY8);
   2819 			break;
   2820 		case (((MP_UINT32)0x00000001)<<24):
   2821 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY9);
   2822 			break;
   2823 		case (((MP_UINT32)0x00000001)<<25):
   2824 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY10);
   2825 			break;
   2826 		case (((MP_UINT32)0x00000001)<<26):
   2827 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY11);
   2828 			break;
   2829 		case (((MP_UINT32)0x00000001)<<27):
   2830 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY12);
   2831 			break;
   2832 		case (((MP_UINT32)0x00000001)<<28):
   2833 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY13);
   2834 			break;
   2835 		case (((MP_UINT32)0x00000001)<<29):
   2836 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY14);
   2837 			break;
   2838 		case (((MP_UINT32)0x00000001)<<30):
   2839 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY15);
   2840 			break;
   2841 		case (((MP_UINT32)0x00000001)<<31):
   2842 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY16);
   2843 			break;
   2844 		default:
   2845 			lbString = getTextString(TEXT_UNKNOWN);
   2846 			break;
   2847 	}
   2848 
   2849 	(void) printf("%s", lbString);
   2850 
   2851 
   2852 } /* end displayLoadBalanceString */
   2853 
   2854 /*
   2855  * ****************************************************************************
   2856  *
   2857  * displayTransportTypeString
   2858  * 	Displays the text equivalent string for the MP_PORT_TRANSPORT_TYPE
   2859  *	specified load balance type
   2860  *
   2861  * transportTypeVal	- transport type defined in the MPAPI spec
   2862  *
   2863  * ****************************************************************************
   2864  */
   2865 void
   2866 displayTransportTypeString(MP_PORT_TRANSPORT_TYPE transportTypeVal)
   2867 {
   2868 
   2869 	char					*ttypeString;
   2870 	switch (transportTypeVal) {
   2871 
   2872 		case MP_PORT_TRANSPORT_TYPE_MPNODE:
   2873 			ttypeString =
   2874 			    getTextString(TEXT_TRANS_PORT_TYPE_MPNODE);
   2875 			break;
   2876 		case MP_PORT_TRANSPORT_TYPE_FC:
   2877 			ttypeString = getTextString(TEXT_TRANS_PORT_TYPE_FC);
   2878 			break;
   2879 		case MP_PORT_TRANSPORT_TYPE_SPI:
   2880 			ttypeString = getTextString(TEXT_TRANS_PORT_TYPE_SPI);
   2881 			break;
   2882 		case MP_PORT_TRANSPORT_TYPE_ISCSI:
   2883 			ttypeString = getTextString(TEXT_TRANS_PORT_TYPE_ISCSI);
   2884 			break;
   2885 		case MP_PORT_TRANSPORT_TYPE_IFB:
   2886 			ttypeString = getTextString(TEXT_TRANS_PORT_TYPE_IFB);
   2887 			break;
   2888 		default:
   2889 			ttypeString = getTextString(TEXT_UNKNOWN);
   2890 			break;
   2891 	}
   2892 
   2893 	(void) printf("%s", ttypeString);
   2894 
   2895 } /* end displayTransportTypeString */
   2896 
   2897 
   2898 /*
   2899  * ****************************************************************************
   2900  *
   2901  * getMpStatusStr
   2902  * 	Gets the string description for the specified load balance type value
   2903  *
   2904  * mpstatus	- MP_STATUS value
   2905  *
   2906  * ****************************************************************************
   2907  */
   2908 char *
   2909 getMpStatusStr(MP_STATUS mpstatus)
   2910 {
   2911 	char					*statString;
   2912 
   2913 	switch (mpstatus) {
   2914 		case MP_STATUS_SUCCESS:
   2915 			statString = getTextString(TEXT_MPSTATUS_SUCCESS);
   2916 			break;
   2917 		case MP_STATUS_INVALID_PARAMETER:
   2918 			statString = getTextString(TEXT_MPSTATUS_INV_PARAMETER);
   2919 			break;
   2920 		case MP_STATUS_UNKNOWN_FN:
   2921 			statString = getTextString(TEXT_MPSTATUS_UNKNOWN_FN);
   2922 			break;
   2923 		case MP_STATUS_FAILED:
   2924 			statString = getTextString(TEXT_MPSTATUS_FAILED);
   2925 			break;
   2926 		case MP_STATUS_INSUFFICIENT_MEMORY:
   2927 			statString = getTextString(TEXT_MPSTATUS_INSUFF_MEMORY);
   2928 			break;
   2929 		case MP_STATUS_INVALID_OBJECT_TYPE:
   2930 			statString = getTextString(TEXT_MPSTATUS_INV_OBJ_TYPE);
   2931 			break;
   2932 		case MP_STATUS_UNSUPPORTED:
   2933 			statString = getTextString(TEXT_MPSTATUS_UNSUPPORTED);
   2934 			break;
   2935 		case MP_STATUS_OBJECT_NOT_FOUND:
   2936 			statString = getTextString(TEXT_MPSTATUS_OBJ_NOT_FOUND);
   2937 			break;
   2938 		case MP_STATUS_ACCESS_STATE_INVALID:
   2939 			statString = getTextString(TEXT_MPSTATUS_UNSUPPORTED);
   2940 			break;
   2941 		case MP_STATUS_FN_REPLACED:
   2942 			statString = getTextString(TEXT_MPSTATUS_FN_REPLACED);
   2943 			break;
   2944 		case MP_STATUS_PATH_NONOPERATIONAL:
   2945 			statString = getTextString(TEXT_MPSTATUS_PATH_NONOP);
   2946 			break;
   2947 		case MP_STATUS_TRY_AGAIN:
   2948 			statString = getTextString(TEXT_MPSTATUS_TRY_AGAIN);
   2949 			break;
   2950 		case MP_STATUS_NOT_PERMITTED:
   2951 			statString = getTextString(TEXT_MPSTATUS_NOT_PERMITTED);
   2952 			break;
   2953 		default:
   2954 			statString = getTextString(TEXT_UNKNOWN);
   2955 			break;
   2956 	}
   2957 
   2958 	return (statString);
   2959 } /* end getMpStatusStr */
   2960 
   2961 
   2962 /*
   2963  * ****************************************************************************
   2964  *
   2965  * GetPathStateStr
   2966  * 	Gets the string description for the specified path state type value
   2967  *
   2968  * pathState	- MP_PATH_STATE values
   2969  *
   2970  * ****************************************************************************
   2971  */
   2972 char *
   2973 getPathStateStr(MP_PATH_STATE pathState)
   2974 {
   2975 	char					*pathString;
   2976 
   2977 	switch (pathState) {
   2978 		case MP_PATH_STATE_OKAY:
   2979 			pathString = getTextString(TEXT_PATH_STATE_OKAY);
   2980 			break;
   2981 		case MP_PATH_STATE_PATH_ERR:
   2982 			pathString = getTextString(TEXT_PATH_STATE_PATH_ERR);
   2983 			break;
   2984 		case MP_PATH_STATE_LU_ERR:
   2985 			pathString = getTextString(TEXT_PATH_STATE_LU_ERR);
   2986 			break;
   2987 		case MP_PATH_STATE_RESERVED:
   2988 			pathString = getTextString(TEXT_PATH_STATE_RESERVED);
   2989 			break;
   2990 		case MP_PATH_STATE_REMOVED:
   2991 			pathString = getTextString(TEXT_PATH_STATE_REMOVED);
   2992 			break;
   2993 		case MP_PATH_STATE_TRANSITIONING:
   2994 			pathString =
   2995 			    getTextString(TEXT_PATH_STATE_TRANSITIONING);
   2996 			break;
   2997 		case MP_PATH_STATE_OPERATIONAL_CLOSED:
   2998 			pathString =
   2999 			    getTextString(TEXT_PATH_STATE_OPERATIONAL_CLOSED);
   3000 			break;
   3001 		case MP_PATH_STATE_INVALID_CLOSED:
   3002 			pathString =
   3003 			    getTextString(TEXT_PATH_STATE_INVALID_CLOSED);
   3004 			break;
   3005 		case MP_PATH_STATE_OFFLINE_CLOSED:
   3006 			pathString =
   3007 			    getTextString(TEXT_PATH_STATE_OFFLINE_CLOSED);
   3008 			break;
   3009 		default:
   3010 			pathString = getTextString(TEXT_UNKNOWN);
   3011 			break;
   3012 	}
   3013 
   3014 	return (pathString);
   3015 } /* end getPathStateStr */
   3016 
   3017 
   3018 
   3019 /*
   3020  * ****************************************************************************
   3021  *
   3022  * getAccessStateStr
   3023  * 	Gets the string description for the specified access state type value
   3024  *
   3025  * accessState	- MP_ACCESS_STATE_TYPE values
   3026  *
   3027  * ****************************************************************************
   3028  */
   3029 char *
   3030 getAccessStateStr(MP_ACCESS_STATE_TYPE accessState)
   3031 {
   3032 	char					*accessString;
   3033 
   3034 	switch (accessState) {
   3035 		case MP_ACCESS_STATE_ACTIVE_OPTIMIZED:
   3036 			accessString =
   3037 			    getTextString(TEXT_ACCESS_STATE_ACTIVE_OPTIMIZED);
   3038 			break;
   3039 		case MP_ACCESS_STATE_ACTIVE_NONOPTIMIZED:
   3040 			accessString =
   3041 			    getTextString(
   3042 			    TEXT_ACCESS_STATE_ACTIVE_NONOPTIMIZED);
   3043 			break;
   3044 		case MP_ACCESS_STATE_STANDBY:
   3045 			accessString =
   3046 			    getTextString(TEXT_ACCESS_STATE_STANDBY);
   3047 			break;
   3048 		case MP_ACCESS_STATE_UNAVAILABLE:
   3049 			accessString =
   3050 			    getTextString(TEXT_ACCESS_STATE_UNAVAILABLE);
   3051 			break;
   3052 		case MP_ACCESS_STATE_TRANSITIONING:
   3053 			accessString =
   3054 			    getTextString(TEXT_ACCESS_STATE_TRANSITIONING);
   3055 			break;
   3056 		case MP_ACCESS_STATE_ACTIVE:
   3057 			accessString = getTextString(TEXT_ACCESS_STATE_ACTIVE);
   3058 			break;
   3059 		default:
   3060 			accessString = getTextString(TEXT_UNKNOWN);
   3061 			break;
   3062 	}
   3063 	return (accessString);
   3064 } /* end getAccessStateStr */
   3065 
   3066 
   3067 /*
   3068  * ****************************************************************************
   3069  *
   3070  * displayArray
   3071  * 	Print out the specified array.
   3072  *
   3073  * arrayToDisplay	- array to display
   3074  * arraySize		- size of array to display
   3075  *
   3076  * ****************************************************************************
   3077  */
   3078 void
   3079 displayArray(MP_CHAR *arrayToDisplay, int arraySize)
   3080 {
   3081 	int					i;
   3082 
   3083 	for (i = 0; i < arraySize; i++) {
   3084 		if ('\0' != arrayToDisplay[i]) {
   3085 			(void) fprintf(stdout, "%c", arrayToDisplay[i]);
   3086 		}
   3087 	}
   3088 
   3089 }
   3090 
   3091 
   3092 /*
   3093  * ****************************************************************************
   3094  *
   3095  * getStringArray
   3096  * 	Return a null terminated array for the specified array as a string,
   3097  *	This is used for inputting into the %s in formatted strings.
   3098  *
   3099  * arrayToDisplay	- array to display
   3100  * arraySize		- size of array to display
   3101  *
   3102  * ****************************************************************************
   3103  */
   3104 MP_CHAR *
   3105 getStringArray(MP_CHAR *arrayToDisplay, int arraySize)
   3106 {
   3107 	MP_CHAR					*newStr;
   3108 
   3109 	int					i;
   3110 
   3111 	newStr = malloc(((sizeof (MP_CHAR)) * arraySize) + 1);
   3112 	if (NULL == newStr) {
   3113 		(void) fprintf(stdout, "%s\n",
   3114 		    getTextString(ERR_MEMORY_ALLOCATION));
   3115 	} else {
   3116 
   3117 		for (i = 0; i < arraySize; i++) {
   3118 			newStr[i] = arrayToDisplay[i];
   3119 		}
   3120 		newStr[arraySize] = '\0';
   3121 	}
   3122 
   3123 	return (newStr);
   3124 }
   3125 
   3126 
   3127 /*
   3128  * ****************************************************************************
   3129  *
   3130  * displayWideArray
   3131  * 	Print out the specified wide character array as a string,
   3132  * 	adding the null termination
   3133  *
   3134  * arrayToDisplay	- array to display
   3135  * arraySize		- size of array to display
   3136  *
   3137  * ****************************************************************************
   3138  */
   3139 void
   3140 displayWideArray(MP_WCHAR *arrayToDisplay, int arraySize)
   3141 {
   3142 	int					i;
   3143 	int					numChars = arraySize/4;
   3144 
   3145 	for (i = 0; i < numChars; i++) {
   3146 		if (L'\0' != arrayToDisplay[i]) {
   3147 			(void) fprintf(stdout, "%wc", arrayToDisplay[i]);
   3148 		}
   3149 	}
   3150 }
   3151 
   3152 
   3153 /*
   3154  * ****************************************************************************
   3155  *
   3156  * listfunc
   3157  * 	Used by cmdparse for list clis
   3158  *
   3159  * ****************************************************************************
   3160  */
   3161 /*ARGSUSED*/
   3162 static int
   3163 listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
   3164     void *addArgs)
   3165 {
   3166 	int 					ret = 0;
   3167 
   3168 	switch (object) {
   3169 		case MPATH_SUPPORT:
   3170 			ret = listMpathSupport(operandLen, operand);
   3171 			break;
   3172 		case LOGICAL_UNIT:
   3173 			ret = listLogicalUnit(operandLen, operand, options);
   3174 			break;
   3175 		case INITIATOR_PORT:
   3176 			ret = listInitiatorPort(operandLen, operand);
   3177 			break;
   3178 		default:
   3179 			(void) fprintf(stderr, "%s: %s\n",
   3180 			    cmdName, getTextString(TEXT_UNKNOWN_OBJECT));
   3181 			ret = 1;
   3182 			break;
   3183 	}
   3184 
   3185 	return (ret);
   3186 }
   3187 
   3188 
   3189 /*
   3190  * ****************************************************************************
   3191  *
   3192  * showFunc
   3193  * 	used bycmdparse for show clis
   3194  *
   3195  * ****************************************************************************
   3196  */
   3197 /*ARGSUSED*/
   3198 static int
   3199 showFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
   3200     void *addArgs)
   3201 {
   3202 	int 					ret = 0;
   3203 
   3204 	switch (object) {
   3205 		case MPATH_SUPPORT:
   3206 			ret = showMpathSupport(operandLen, operand);
   3207 			break;
   3208 		case LOGICAL_UNIT:
   3209 			ret = showLogicalUnit(operandLen, operand);
   3210 			break;
   3211 		case INITIATOR_PORT:
   3212 			ret = showInitiatorPort(operandLen, operand);
   3213 			break;
   3214 		default:
   3215 			ret = 1;
   3216 			break;
   3217 	}
   3218 
   3219 	return (ret);
   3220 }
   3221 
   3222 
   3223 /*
   3224  * ****************************************************************************
   3225  *
   3226  * modifyFunc
   3227  * 	Used by cmdparse for midify clis
   3228  *
   3229  *
   3230  * ****************************************************************************
   3231  */
   3232 /*ARGSUSED*/
   3233 static int
   3234 modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
   3235     void *addArgs)
   3236 {
   3237 	int 					ret = 0;
   3238 
   3239 	switch (object) {
   3240 		case MPATH_SUPPORT:
   3241 			ret = modifyMpathSupport(operandLen, operand, options);
   3242 			break;
   3243 		case LOGICAL_UNIT:
   3244 			ret = modifyLogicalUnit(operandLen, operand, options);
   3245 			break;
   3246 		default:
   3247 			ret = 1;
   3248 			break;
   3249 	}
   3250 
   3251 
   3252 	return (ret);
   3253 }
   3254 
   3255 
   3256 /*
   3257  * ****************************************************************************
   3258  *
   3259  * enableFunc
   3260  * 	Used by cmdpars for enable clis
   3261  *
   3262  * ****************************************************************************
   3263  */
   3264 /*ARGSUSED*/
   3265 static int
   3266 enableFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
   3267     void *addArgs)
   3268 {
   3269 	int 					ret = 0;
   3270 
   3271 	switch (object) {
   3272 		case PATH:
   3273 			ret = enablePath(options);
   3274 			break;
   3275 		default:
   3276 			ret = 1;
   3277 			break;
   3278 	}
   3279 
   3280 	return (ret);
   3281 }
   3282 
   3283 
   3284 /*
   3285  * ****************************************************************************
   3286  *
   3287  * disableFunc
   3288  * 	Used by cmdpars for disable clis
   3289  *
   3290  * ****************************************************************************
   3291  */
   3292 /*ARGSUSED*/
   3293 static int
   3294 disableFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
   3295     void *addArgs)
   3296 {
   3297 	int 					ret = 0;
   3298 
   3299 	switch (object) {
   3300 		case PATH:
   3301 			ret = disablePath(options);
   3302 			break;
   3303 		default:
   3304 			ret = 1;
   3305 			break;
   3306 	}
   3307 
   3308 	return (ret);
   3309 }
   3310 
   3311 
   3312 /*
   3313  * ****************************************************************************
   3314  *
   3315  * failoverFunc
   3316  * 	Used by cmdpars for failover clis
   3317  *
   3318  * ****************************************************************************
   3319  */
   3320 /*ARGSUSED*/
   3321 static int
   3322 failoverFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
   3323     void *addArgs)
   3324 {
   3325 	int 					ret = 0;
   3326 
   3327 	switch (object) {
   3328 		case LOGICAL_UNIT:
   3329 			ret = failoverLogicalUnit(operand);
   3330 			break;
   3331 		default:
   3332 			ret = 1;
   3333 			break;
   3334 	}
   3335 
   3336 	return (ret);
   3337 }
   3338 
   3339 
   3340 /*
   3341  * ****************************************************************************
   3342  *
   3343  * overrideFunc
   3344  * 	Used by cmdpars for override clis
   3345  *
   3346  * ****************************************************************************
   3347  */
   3348 /*ARGSUSED*/
   3349 static int
   3350 overrideFunc(int operandLen, char *operand[],
   3351 	int object, cmdOptions_t *options,
   3352     void *addArgs)
   3353 {
   3354 	int 					ret = 0;
   3355 
   3356 	switch (object) {
   3357 		case PATH:
   3358 			ret = overridePath(options);
   3359 			break;
   3360 		default:
   3361 			ret = 1;
   3362 			break;
   3363 	}
   3364 
   3365 
   3366 	return (ret);
   3367 }
   3368 
   3369 
   3370 /*
   3371  * *************************************************************************
   3372  *
   3373  * main
   3374  *
   3375  * *************************************************************************
   3376  */
   3377 int
   3378 main(int argc, char *argv[])
   3379 {
   3380 	synTables_t 			synTables;
   3381 	char 				versionString[VERSION_STRING_MAX_LEN];
   3382 	int 				ret;
   3383 	int 				funcRet;
   3384 	void 				*subcommandArgs = NULL;
   3385 
   3386 	/* set global command name */
   3387 	cmdName = getExecBasename(argv[0]);
   3388 
   3389 	(void) sprintf(versionString, "%2s.%2s",
   3390 	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
   3391 	synTables.versionString = versionString;
   3392 	synTables.longOptionTbl = &longOptions[0];
   3393 	synTables.subcommandTbl = &subcommands[0];
   3394 	synTables.objectTbl = &objects[0];
   3395 	synTables.objectRulesTbl = &objectRules[0];
   3396 	synTables.optionRulesTbl = &optionRules[0];
   3397 
   3398 	ret = cmdParse(argc, argv, /* SUB_COMMAND_ISSUED, */ synTables,
   3399 	    subcommandArgs, &funcRet);
   3400 	if (ret == 1) {
   3401 		(void) fprintf(stdout, "%s %s(1M)\n",
   3402 		    getTextString(TEXT_MORE_INFO), cmdName);
   3403 		return (ERROR_CLI_FAILED);
   3404 	} else if (ret == -1) {
   3405 		perror(argv[0]);
   3406 		return (1);
   3407 	}
   3408 
   3409 	if (funcRet != 0) {
   3410 		(void) fprintf(stderr, "%s: %s\n",
   3411 		    argv[0], getTextString(TEXT_UNABLE_TO_COMPLETE));
   3412 		return (1);
   3413 	}
   3414 	return (0);
   3415 
   3416 } /* end main */
   3417