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