xref: /titanic_51/usr/src/cmd/mpathadm/mpathadm.c (revision 3221df98598173bea3b143712532cdd09f4fbd0f)
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 		if (((fd1 = open(cmpString, O_RDONLY|O_NDELAY)) >= 0) &&
1102 		    ((fd2 = open(deviceProperty, O_RDONLY|O_NDELAY)) >= 0) &&
1103 		    (devid_get(fd1, &devid1) == 0) &&
1104 		    (devid_get(fd2, &devid2) == 0) &&
1105 		    ((NULL != devid1) && (NULL != devid2))) {
1106 			if (0 ==
1107 			    (devid_compare(devid1, devid2))) {
1108 				isSame = B_TRUE;
1109 			}
1110 		}
1111 
1112 		if (NULL != devid1) {
1113 			devid_free(devid1);
1114 		}
1115 		if (NULL != devid2) {
1116 			devid_free(devid2);
1117 		}
1118 	} /* compare */
1119 
1120 	return (isSame);
1121 }
1122 
1123 
1124 /*
1125  * ****************************************************************************
1126  *
1127  * listIndivudualLogicalUnit -
1128  * 	Used by list logical unit cli.
1129  *	Displays info about an LU
1130  *
1131  * luOid	- LU to list
1132  * luProps	- properties of he LU to list
1133  *
1134  * ****************************************************************************
1135  */
1136 int
1137 listIndividualLogicalUnit(MP_OID luOid,
1138 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES luProps)
1139 {
1140 	MP_PATH_LOGICAL_UNIT_PROPERTIES		pathProps;
1141 	MP_OID_LIST				*pPathOidListArray;
1142 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
1143 	int					numOperationalPaths,
1144 						pa;
1145 
1146 	(void) printf("\t");
1147 	displayArray(luProps.deviceFileName, sizeof (luProps.deviceFileName));
1148 	(void) printf("\n");
1149 
1150 	mpstatus = MP_GetAssociatedPathOidList(luOid,
1151 	    &pPathOidListArray);
1152 	if (mpstatus != MP_STATUS_SUCCESS) {
1153 		/* LINTED E_SEC_PRINTF_VAR_FMT */
1154 		(void) fprintf(stderr,
1155 		    getTextString(ERR_NO_LU_PATH_INFO_WITH_MISSING_LU_STR),
1156 		getStringArray(luProps.deviceFileName,
1157 		    sizeof (luProps.deviceFileName)));
1158 		(void) fprintf(stderr, "\n");
1159 		return (mpstatus);
1160 	}
1161 	(void) printf("\t\t%s %d\n",
1162 	    getTextString(TEXT_LB_PATH_COUNT), pPathOidListArray->oidCount);
1163 
1164 	numOperationalPaths = 0;
1165 	for (pa = 0; pa < pPathOidListArray->oidCount; pa++) {
1166 		(void) memset(&pathProps, 0,
1167 		    sizeof (MP_PATH_LOGICAL_UNIT_PROPERTIES));
1168 		mpstatus =
1169 		    MP_GetPathLogicalUnitProperties(
1170 		    pPathOidListArray->oids[pa], &pathProps);
1171 		if (mpstatus != MP_STATUS_SUCCESS) {
1172 			(void) fprintf(stderr, "%s:  %s\n",
1173 			    cmdName, getTextString(ERR_NO_PROPERTIES));
1174 			return (mpstatus);
1175 		}
1176 
1177 		/* cycle through and check status of each for */
1178 		/* operation path count */
1179 		if (MP_PATH_STATE_OKAY == pathProps.pathState) {
1180 			numOperationalPaths++;
1181 		}
1182 	}
1183 
1184 	(void) printf("\t\t%s %d\n",
1185 	    getTextString(TEXT_LB_OP_PATH_COUNT), numOperationalPaths);
1186 
1187 	return (mpstatus);
1188 }
1189 
1190 
1191 /*
1192  * ****************************************************************************
1193  *
1194  * showLogicalUnit -
1195  * 	mpathadm show {logical-unit | LU} <logical-unit name>, ...
1196  *
1197  * operandLen	- number of operands user passed into the cli
1198  * operand	- pointer to operand list from user
1199  *
1200  * ****************************************************************************
1201  */
1202 int
1203 showLogicalUnit(int operandLen, char *operand[])
1204 {
1205 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
1206 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES	luProps;
1207 	MP_PLUGIN_PROPERTIES			pluginProps;
1208 	MP_OID					luOid,
1209 						pluginOid;
1210 
1211 	int					op;
1212 
1213 	for (op = 0; op < operandLen; op++) {
1214 		if (op > 0) {
1215 			(void) printf("\n");
1216 		}
1217 		if (B_TRUE == getLogicalUnitOid(operand[op], &luOid)) {
1218 			(void) memset(&luProps, 0,
1219 			    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
1220 			mpstatus =
1221 			    MP_GetMPLogicalUnitProperties(
1222 			    luOid, &luProps);
1223 			if (mpstatus != MP_STATUS_SUCCESS) {
1224 				(void) fprintf(stderr, "%s:  %s\n",
1225 				    cmdName, getTextString(ERR_NO_PROPERTIES));
1226 				return (mpstatus);
1227 			}
1228 
1229 			mpstatus =
1230 			    MP_GetAssociatedPluginOid(luOid, &pluginOid);
1231 			if (mpstatus != MP_STATUS_SUCCESS) {
1232 				(void) fprintf(stderr, "%s:  %s\n",
1233 				    cmdName,
1234 				    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
1235 				return (mpstatus);
1236 			}
1237 
1238 			mpstatus =
1239 			    MP_GetPluginProperties(pluginOid, &pluginProps);
1240 			if (mpstatus != MP_STATUS_SUCCESS) {
1241 				(void) fprintf(stderr, "%s:  %s\n",
1242 				    cmdName, getTextString(ERR_NO_PROPERTIES));
1243 				return (mpstatus);
1244 			}
1245 
1246 			if (showIndividualLogicalUnit(luOid, luProps,
1247 			    pluginProps) != 0) {
1248 				return (ERROR_CLI_FAILED);
1249 			}
1250 
1251 		} else {
1252 			/* LINTED E_SEC_PRINTF_VAR_FMT */
1253 			(void) fprintf(stderr, getTextString(
1254 			    ERR_LU_NOT_FOUND_WITH_MISSING_LU_STR),
1255 			    operand[op]);
1256 			(void) printf("\n");
1257 		}
1258 
1259 	} /* for each operand */
1260 
1261 	return (mpstatus);
1262 }
1263 
1264 
1265 /*
1266  * ****************************************************************************
1267  *
1268  * showIndivudualLogicalUnit -
1269  * 	Used by show logical unit cli.
1270  *	Displays info about an LU
1271  *
1272  * luOid	- LU to show
1273  * luProps	- properties of he LU to show
1274  * pluginProps	- propertis of the plugin this LU belongs to
1275  *
1276  * ****************************************************************************
1277  */
1278 int
1279 showIndividualLogicalUnit(MP_OID luOid,
1280 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES luProps,
1281 	MP_PLUGIN_PROPERTIES pluginProps)
1282 {
1283 	MP_PATH_LOGICAL_UNIT_PROPERTIES		pathProps;
1284 	MP_TARGET_PORT_GROUP_PROPERTIES		tpgProps;
1285 	MP_TARGET_PORT_PROPERTIES 		tportProps;
1286 	MP_INITIATOR_PORT_PROPERTIES 		initProps;
1287 	MP_OID_LIST				*pPathOidListArray,
1288 						*pTPGOidListArray,
1289 						*pTportOidListArray;
1290 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
1291 	boolean_t				showTportLabel = B_TRUE;
1292 
1293 	int					pa,
1294 						tpg,
1295 						tport;
1296 
1297 	(void) printf("%s  ", getTextString(TEXT_LB_LOGICAL_UNIT));
1298 	displayArray(luProps.deviceFileName, sizeof (luProps.deviceFileName));
1299 	(void) printf("\n");
1300 	(void) printf("\t%s  %s\n", getTextString(TEXT_LB_MPATH_SUPPORT),
1301 		pluginProps.fileName);
1302 
1303 	(void) printf("\t%s  ", getTextString(TEXT_LB_VENDOR));
1304 	displayArray(luProps.vendor,
1305 	    sizeof (luProps.vendor));
1306 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_PRODUCT));
1307 	displayArray(luProps.product,
1308 	    sizeof (luProps.product));
1309 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_REVISION));
1310 	displayArray(luProps.revision,
1311 	    sizeof (luProps.revision));
1312 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_INQUIRY_NAME_TYPE));
1313 	displayLogicalUnitNameTypeString(luProps.nameType);
1314 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_INQUIRY_NAME));
1315 	displayArray(luProps.name, sizeof (luProps.name));
1316 	(void) printf("\n\t%s  %s\n", getTextString(TEXT_LB_ASYMMETRIC),
1317 	    (MP_TRUE == luProps.asymmetric)?
1318 	    getTextString(TEXT_YES):getTextString(TEXT_NO));
1319 
1320 	(void) printf("\t%s  ", getTextString(TEXT_LB_CURR_LOAD_BALANCE));
1321 	/* don't ignore load balance type none. */
1322 	if (luProps.currentLoadBalanceType == 0) {
1323 		(void) printf("%s", getTextString(TEXT_LBTYPE_NONE));
1324 	} else {
1325 		displayLoadBalanceString(luProps.currentLoadBalanceType);
1326 	}
1327 	(void) printf("\n");
1328 
1329 	(void) printf("\t%s  ", getTextString(TEXT_LB_LU_GROUP_ID));
1330 	if (0xffffffff == luProps.logicalUnitGroupID) {
1331 		(void) printf("%s\n", getTextString(TEXT_NA));
1332 	} else {
1333 		(void) printf("0x%x\n", luProps.logicalUnitGroupID);
1334 	}
1335 
1336 	(void) printf("\t%s  ", getTextString(TEXT_LB_AUTO_FB));
1337 	if (MP_FALSE == pluginProps.autoFailbackSupport) {
1338 		(void) printf("%s\n", getTextString(TEXT_NA));
1339 	} else {
1340 		(void) printf("%s\n", (MP_TRUE == luProps.autoFailbackEnabled)?
1341 		    getTextString(TEXT_ON):getTextString(TEXT_OFF));
1342 	}
1343 
1344 	(void) printf("\t%s  ", getTextString(TEXT_LB_AUTO_PROB));
1345 	if (MP_FALSE == pluginProps.autoProbingSupport) {
1346 		(void) printf("%s\n", getTextString(TEXT_NA));
1347 	} else {
1348 		(void) printf("%s\n", (MP_TRUE == luProps.autoProbingEnabled)?
1349 		    getTextString(TEXT_ON):getTextString(TEXT_OFF));
1350 	}
1351 
1352 
1353 	/* get path info */
1354 	mpstatus = MP_GetAssociatedPathOidList(luOid, &pPathOidListArray);
1355 	if (mpstatus != MP_STATUS_SUCCESS) {
1356 		(void) fprintf(stderr, "%s:  %s", cmdName,
1357 		    getTextString(ERR_NO_LU_PATH_INFO));
1358 		displayArray(luProps.deviceFileName,
1359 		    sizeof (luProps.deviceFileName));
1360 		(void) fprintf(stderr, "\n");
1361 		return (mpstatus);
1362 	}
1363 
1364 	(void) printf("\n\t%s  \n", getTextString(TEXT_LB_PATH_INFO));
1365 
1366 	for (pa = 0; pa < pPathOidListArray->oidCount; pa++) {
1367 		(void) memset(&pathProps, 0,
1368 		    sizeof (MP_PATH_LOGICAL_UNIT_PROPERTIES));
1369 		mpstatus = MP_GetPathLogicalUnitProperties(
1370 		    pPathOidListArray->oids[pa], &pathProps);
1371 		if (mpstatus != MP_STATUS_SUCCESS) {
1372 			(void) fprintf(stderr, "%s:  %s\n",
1373 			    cmdName, getTextString(ERR_NO_PROPERTIES));
1374 			return (mpstatus);
1375 		}
1376 
1377 		(void) printf("\t\t%s  ",
1378 		    getTextString(TEXT_LB_INIT_PORT_NAME));
1379 		if ((mpstatus =
1380 		    MP_GetInitiatorPortProperties(pathProps.initiatorPortOid,
1381 		    &initProps)) != MP_STATUS_SUCCESS) {
1382 			(void) printf("%s\n", getTextString(TEXT_UNKNOWN));
1383 		} else {
1384 			displayArray(initProps.portID,
1385 			    sizeof (initProps.portID));
1386 			(void) printf("\n");
1387 		}
1388 
1389 		(void) printf("\t\t%s  ",
1390 		    getTextString(TEXT_LB_TARGET_PORT_NAME));
1391 		if ((mpstatus =
1392 		    MP_GetTargetPortProperties(pathProps.targetPortOid,
1393 		    &tportProps)) != MP_STATUS_SUCCESS) {
1394 			(void) printf("%s\n", getTextString(TEXT_UNKNOWN));
1395 		} else {
1396 			displayArray(tportProps.portID,
1397 			    sizeof (tportProps.portID));
1398 			(void) printf("\n");
1399 		}
1400 
1401 		(void) printf("\t\t%s  ", getTextString(TEXT_LB_OVERRIDE_PATH));
1402 		if (MP_FALSE == pluginProps.canOverridePaths) {
1403 			(void) printf("%s\n", getTextString(TEXT_NA));
1404 		} else if (luProps.overridePath.objectSequenceNumber ==
1405 		    pPathOidListArray->oids[pa].objectSequenceNumber) {
1406 			(void) printf("%s\n", getTextString(TEXT_YES));
1407 		} else {
1408 			(void) printf("%s\n", getTextString(TEXT_NO));
1409 		}
1410 
1411 		(void) printf("\t\t%s  %s\n", getTextString(TEXT_LB_PATH_STATE),
1412 		    getPathStateStr(pathProps.pathState));
1413 
1414 		(void) printf("\t\t%s  %s\n\n", getTextString(TEXT_LB_DISABLED),
1415 		    pathProps.disabled?getTextString(TEXT_YES):
1416 		    getTextString(TEXT_NO));
1417 
1418 	}
1419 
1420 	/* get tpg info */
1421 	mpstatus = MP_GetAssociatedTPGOidList(luOid, &pTPGOidListArray);
1422 	if (mpstatus != MP_STATUS_SUCCESS) {
1423 		(void) fprintf(stderr, "%s:  %s", cmdName,
1424 		    getTextString(ERR_NO_ASSOC_TPGS));
1425 	} else {
1426 
1427 	/* display tpg info only if is assymetric */
1428 	if (MP_TRUE == luProps.asymmetric) {
1429 		(void) printf("\t%s  \n", getTextString(TEXT_LB_TPG_INFO));
1430 	}
1431 
1432 		for (tpg = 0; tpg < pTPGOidListArray->oidCount; tpg++) {
1433 			(void) memset(&tpgProps, 0,
1434 			    sizeof (MP_TARGET_PORT_GROUP_PROPERTIES));
1435 			mpstatus = MP_GetTargetPortGroupProperties(
1436 			    pTPGOidListArray->oids[tpg], &tpgProps);
1437 			if (mpstatus != MP_STATUS_SUCCESS) {
1438 				(void) fprintf(stderr, "%s:  %s",
1439 				    cmdName, getTextString(ERR_NO_PROPERTIES));
1440 			} else {
1441 				/* display tpg info only if is assymetric */
1442 				if (tpg > 0) {
1443 					(void) printf("\n");
1444 				}
1445 				if (MP_TRUE == luProps.asymmetric) {
1446 					(void) printf("\t\t%s  %d\n",
1447 					    getTextString(TEXT_LB_ID),
1448 					    tpgProps.tpgID);
1449 					(void) printf("\t\t%s  %s\n",
1450 					    getTextString(
1451 					    TEXT_LB_EXPLICIT_FAILOVER),
1452 					    (MP_TRUE ==
1453 					    tpgProps.explicitFailover)?
1454 					    getTextString(TEXT_YES):
1455 					    getTextString(TEXT_NO));
1456 					(void) printf("\t\t%s  %s\n",
1457 					    getTextString(
1458 					    TEXT_LB_ACCESS_STATE),
1459 					    getAccessStateStr(
1460 					    tpgProps.accessState));
1461 					    /* display label for each tpg. */
1462 					    (void) printf("\t\t%s\n",
1463 						getTextString(TEXT_TPORT_LIST));
1464 				} else {
1465 					/* display label once for symmetric. */
1466 					if (B_TRUE == showTportLabel) {
1467 						(void) printf("\t%s\n",
1468 						getTextString(TEXT_TPORT_LIST));
1469 						showTportLabel = B_FALSE;
1470 					}
1471 				}
1472 
1473 				/* get target port info */
1474 				mpstatus = MP_GetTargetPortOidList(
1475 				    pTPGOidListArray->oids[tpg],
1476 				    &pTportOidListArray);
1477 				if (mpstatus != MP_STATUS_SUCCESS) {
1478 					(void) fprintf(stderr, "%s:  %s",
1479 					    cmdName,
1480 					    getTextString(ERR_NO_ASSOC_TPORTS));
1481 				} else {
1482 
1483 /* begin back-up indentation */
1484 	for (tport = 0; tport < pTportOidListArray->oidCount; tport++) {
1485 		(void) memset(&tportProps, 0,
1486 		    sizeof (MP_TARGET_PORT_PROPERTIES));
1487 		if ((mpstatus =
1488 		    MP_GetTargetPortProperties(pTportOidListArray->oids[tport],
1489 		    &tportProps)) != MP_STATUS_SUCCESS) {
1490 			(void) fprintf(stderr, "%s:  %s",
1491 			cmdName, getTextString(ERR_NO_PROPERTIES));
1492 		} else {
1493 			if (MP_TRUE == luProps.asymmetric) {
1494 				(void) printf("\t\t\t%s  ",
1495 				getTextString(TEXT_LB_NAME));
1496 				displayArray(tportProps.portID,
1497 					sizeof (tportProps.portID));
1498 				(void) printf("\n\t\t\t%s  %d\n",
1499 				getTextString(TEXT_LB_RELATIVE_ID),
1500 				tportProps.relativePortID);
1501 			} else {
1502 				(void) printf("\t\t%s  ",
1503 				getTextString(TEXT_LB_NAME));
1504 				displayArray(tportProps.portID,
1505 					sizeof (tportProps.portID));
1506 				(void) printf("\n\t\t%s  %d\n",
1507 				getTextString(TEXT_LB_RELATIVE_ID),
1508 				tportProps.relativePortID);
1509 			}
1510 			/* insert blank line if not the last target port. */
1511 			if (!(tport == (pTportOidListArray->oidCount - 1))) {
1512 			    (void) printf("\n");
1513 			}
1514 		}
1515 	} /* for each target port */
1516 /* end back-up indentation */
1517 
1518 				} /* else got target port props */
1519 			} /* else got TPG props */
1520 		} /* for each TPG */
1521 	} /* else got tpg list */
1522 
1523 
1524 	return (mpstatus);
1525 }
1526 
1527 
1528 /*
1529  * ****************************************************************************
1530  *
1531  * modifyLogicalUnit -
1532  * 	mpathadm modify {logical-unit | LU} [options] <logical-unit name>, ...
1533  *
1534  * operandLen	- number of operands user passed into the cli
1535  * operand	- pointer to operand list from user
1536  * options	- pointer to option list from user
1537  *
1538  * ****************************************************************************
1539  */
1540 int
1541 modifyLogicalUnit(int operandLen, char *operand[], cmdOptions_t *options)
1542 {
1543 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
1544 	MP_OID					luOid;
1545 	cmdOptions_t 				*optionList = options;
1546 	char					*cmdStr =
1547 						    getTextString(
1548 						    TEXT_UNKNOWN);
1549 	int					op;
1550 
1551 	for (op = 0; op < operandLen; op++) {
1552 		if (B_TRUE != getLogicalUnitOid(operand[op], &luOid)) {
1553 			/* LINTED E_SEC_PRINTF_VAR_FMT */
1554 			(void) fprintf(stderr,
1555 			    getTextString(ERR_LU_NOT_FOUND_WITH_MISSING_LU_STR),
1556 			    operand[op]);
1557 			(void) printf("\n");
1558 			return (ERROR_CLI_FAILED);
1559 		}
1560 
1561 		/* we found the lu oid, now change the options requested */
1562 		switch (optionList->optval) {
1563 			case 'a':
1564 				/* modify autofailback */
1565 				cmdStr = getTextString(TEXT_AUTO_FAILBACK);
1566 				if (0 == strcasecmp(optionList->optarg,
1567 				    getTextString(TEXT_ON))) {
1568 					mpstatus =
1569 					    MP_EnableAutoFailback(luOid);
1570 				} else if (0 == strcasecmp(optionList->optarg,
1571 				    getTextString(TEXT_OFF))) {
1572 					mpstatus =
1573 					    MP_DisableAutoFailback(luOid);
1574 				} else {
1575 					/* LINTED E_SEC_PRINTF_VAR_FMT */
1576 					(void) fprintf(stderr, getTextString(
1577 				    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
1578 					    cmdStr,
1579 					    getTextString(
1580 					    TEXT_ILLEGAL_ARGUMENT));
1581 					(void) printf("\n");
1582 					return (ERROR_CLI_FAILED);
1583 				}
1584 				break;
1585 			case 'p':
1586 				/* modify autoprobing */
1587 				cmdStr = getTextString(TEXT_AUTO_PROBING);
1588 				if (0 == strcasecmp(optionList->optarg,
1589 				    getTextString(TEXT_ON))) {
1590 					mpstatus =
1591 					    MP_EnableAutoProbing(luOid);
1592 				} else if (0 == strcasecmp(optionList->optarg,
1593 					getTextString(TEXT_OFF))) {
1594 					mpstatus =
1595 					    MP_DisableAutoProbing(luOid);
1596 				} else {
1597 					/* LINTED E_SEC_PRINTF_VAR_FMT */
1598 					(void) fprintf(stderr, getTextString(
1599 				    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
1600 					    cmdStr,
1601 					    getTextString(
1602 					    TEXT_ILLEGAL_ARGUMENT));
1603 					(void) printf("\n");
1604 					return (ERROR_CLI_FAILED);
1605 				}
1606 				break;
1607 			case 'b':
1608 				/* modify loadbalance type */
1609 				cmdStr = getTextString(TEXT_LOAD_BALANCE);
1610 				mpstatus =
1611 				    MP_SetLogicalUnitLoadBalanceType(luOid,
1612 				    getLbValueFromString(optionList->optarg));
1613 				break;
1614 
1615 		} /* switch */
1616 		if (MP_STATUS_SUCCESS != mpstatus) {
1617 			/* LINTED E_SEC_PRINTF_VAR_FMT */
1618 			(void) fprintf(stderr,
1619 			    getTextString(
1620 			    ERR_FAILED_TO_CHANGE_OPTION_WITH_REASON),
1621 			    cmdStr, getMpStatusStr(mpstatus));
1622 			(void) printf("\n");
1623 			return (ERROR_CLI_FAILED);
1624 		}
1625 	} /* for each operand */
1626 	return (mpstatus);
1627 }
1628 
1629 
1630 /*
1631  * ****************************************************************************
1632  *
1633  * failoverLogicalUnit -
1634  * 	mpathadm failover {logical-unit | LU} <logical-unit name>, ...
1635  *
1636  * operand	- pointer to operand list from user
1637  *
1638  * ****************************************************************************
1639  */
1640 int
1641 failoverLogicalUnit(char *operand[])
1642 {
1643 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
1644 	MP_OID					luOid;
1645 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES	luProps;
1646 	MP_TARGET_PORT_GROUP_PROPERTIES		tpgProps;
1647 	MP_OID_LIST				*pTpgOidListArray;
1648 	boolean_t				bFoundIt = B_FALSE;
1649 	MP_TPG_STATE_PAIR			tpgStatePair;
1650 
1651 	int					tpg;
1652 
1653 	if (B_TRUE != getLogicalUnitOid(operand[0], &luOid)) {
1654 		/* LINTED E_SEC_PRINTF_VAR_FMT */
1655 		(void) fprintf(stderr, getTextString(
1656 		    ERR_LU_NOT_FOUND_WITH_MISSING_LU_STR),
1657 		    operand[0]);
1658 		(void) printf("\n");
1659 		return (ERROR_CLI_FAILED);
1660 	}
1661 
1662 	/* get LUN properties and check to be sure it's asymmetric */
1663 	(void) memset(&luProps, 0,
1664 	    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
1665 	mpstatus =
1666 	    MP_GetMPLogicalUnitProperties(luOid, &luProps);
1667 	if (mpstatus != MP_STATUS_SUCCESS) {
1668 		(void) fprintf(stderr, "%s:  %s\n",
1669 		    cmdName, getTextString(ERR_NO_PROPERTIES));
1670 		return (mpstatus);
1671 	}
1672 
1673 	if (MP_TRUE != luProps.asymmetric) {
1674 		(void) fprintf(stderr, "%s:  %s\n",
1675 		    cmdName, getTextString(ERR_LU_NOT_ASYMMETRIC));
1676 		return (ERROR_CLI_FAILED);
1677 	}
1678 
1679 	/* get TPGs for this LUN */
1680 	mpstatus =
1681 	    MP_GetAssociatedTPGOidList(luOid, &pTpgOidListArray);
1682 	if (mpstatus != MP_STATUS_SUCCESS) {
1683 		(void) fprintf(stderr, "%s:  %s\n",
1684 		cmdName, getTextString(ERR_NO_ASSOC_TPGS));
1685 		return (mpstatus);
1686 	}
1687 
1688 	/* pick a TPG whose state is active or standby, and change it */
1689 	/* to opposite via MP_SetTPGAccessState */
1690 	bFoundIt = B_FALSE;
1691 	for (tpg = 0; tpg < pTpgOidListArray->oidCount; tpg++) {
1692 		(void) memset(&tpgProps, 0,
1693 		    sizeof (MP_TARGET_PORT_GROUP_PROPERTIES));
1694 		mpstatus =
1695 		    MP_GetTargetPortGroupProperties(
1696 		    pTpgOidListArray->oids[tpg], &tpgProps);
1697 		if (mpstatus != MP_STATUS_SUCCESS) {
1698 			(void) fprintf(stderr, "%s:  %s\n",
1699 			    cmdName, getTextString(ERR_NO_PROPERTIES));
1700 			return (ERROR_CLI_FAILED);
1701 		}
1702 		if (MP_FALSE == tpgProps.explicitFailover) {
1703 			(void) fprintf(stderr, "%s:  %s\n",
1704 			cmdName, getTextString(ERR_NO_FAILOVER_ALLOWED));
1705 			return (ERROR_CLI_FAILED);
1706 		}
1707 
1708 		/* find one that is standby */
1709 		if ((MP_ACCESS_STATE_STANDBY ==
1710 		    tpgProps.accessState) && (B_FALSE == bFoundIt)) {
1711 
1712 			bFoundIt = B_TRUE;
1713 
1714 			tpgStatePair.tpgOid =
1715 			    pTpgOidListArray->oids[tpg];
1716 			tpgStatePair.desiredState =
1717 			    MP_ACCESS_STATE_ACTIVE;
1718 			mpstatus =
1719 			    MP_SetTPGAccess(luOid, 1, &tpgStatePair);
1720 			if (MP_STATUS_SUCCESS != mpstatus) {
1721 				/* LINTED E_SEC_PRINTF_VAR_FMT */
1722 				(void) fprintf(stderr, getTextString(
1723 			    ERR_FAILED_TO_FAILOVER_WITH_REASON),
1724 			    getMpStatusStr(mpstatus));
1725 				(void) printf("\n");
1726 				return (mpstatus);
1727 			}
1728 		}
1729 
1730 
1731 	} /* for each tpg */
1732 
1733 	if (B_FALSE == bFoundIt) {
1734 		(void) fprintf(stderr, "%s:  %s\n",
1735 		    cmdName, getTextString(ERR_LU_ACCESS_STATE_UNCHANGED));
1736 		return (ERROR_CLI_FAILED);
1737 	}
1738 
1739 	return (mpstatus);
1740 }
1741 
1742 
1743 /*
1744  * ****************************************************************************
1745  *
1746  * getLogicalUnitOid -
1747  *	Search through all plugins and get the OID for specified logical unit
1748  *
1749  * luFileName	- file name of LU (specified by the user) to find
1750  * pLuOid	- OID to return
1751  *
1752  * ****************************************************************************
1753  */
1754 boolean_t
1755 getLogicalUnitOid(MP_CHAR *luFileName, MP_OID *pluOid)
1756 {
1757 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
1758 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES	luProps;
1759 	MP_PLUGIN_PROPERTIES			pluginProps;
1760 	MP_OID_LIST				*pPluginOidList,
1761 						*pLogicalUnitOidList;
1762 	boolean_t				foundIt = B_FALSE;
1763 
1764 	int					i,
1765 						lu;
1766 
1767 	int 					fd1, fd2;
1768 	ddi_devid_t				devid1 = NULL, devid2 = NULL;
1769 
1770 	if (NULL == pluOid) {
1771 		/* print some kind of error msg here - should never happen */
1772 		/* LINTED E_SEC_PRINTF_VAR_FMT */
1773 		(void) fprintf(stderr, getTextString(ERR_MEMORY_ALLOCATION));
1774 		(void) printf("\n");
1775 		return (B_FALSE);
1776 	}
1777 
1778 	pluOid->objectSequenceNumber = 0;
1779 	pluOid->objectType = 0;
1780 	pluOid->ownerId = 0;
1781 
1782 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
1783 		!= MP_STATUS_SUCCESS) {
1784 		(void) fprintf(stderr, "%s: %s\n", cmdName,
1785 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
1786 		return (B_FALSE);
1787 	}
1788 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
1789 		(void) fprintf(stderr, "%s: %s\n", cmdName,
1790 		getTextString(ERR_NO_MPATH_SUPPORT_LIST));
1791 		return (ERROR_CLI_FAILED);
1792 	}
1793 	for (i = 0; i < pPluginOidList->oidCount; i++) {
1794 
1795 		/* get properties so we can list the name */
1796 		(void) memset(&pluginProps, 0, sizeof (MP_PLUGIN_PROPERTIES));
1797 		if ((mpstatus =
1798 		    MP_GetPluginProperties(pPluginOidList->oids[i],
1799 		    &pluginProps)) != MP_STATUS_SUCCESS) {
1800 				(void) fprintf(stderr, "%s:  %s\n",
1801 				    cmdName, getTextString(ERR_NO_PROPERTIES));
1802 				return (B_FALSE);
1803 		}
1804 
1805 		/* attempt to find this logical unit */
1806 		mpstatus = MP_GetMultipathLus(pPluginOidList->oids[i],
1807 		    &pLogicalUnitOidList);
1808 		if (mpstatus != MP_STATUS_SUCCESS) {
1809 			(void) fprintf(stderr, "%s:  %s\n",
1810 			    cmdName, getTextString(ERR_NO_LU_LIST));
1811 			return (B_FALSE);
1812 		}
1813 
1814 		for (lu = 0; (lu < pLogicalUnitOidList->oidCount) &&
1815 		    (B_FALSE == foundIt); lu++) {
1816 
1817 			/* get lu properties so we can check the name */
1818 			(void) memset(&luProps, 0,
1819 			    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
1820 			mpstatus =
1821 			    MP_GetMPLogicalUnitProperties(
1822 			    pLogicalUnitOidList->oids[lu], &luProps);
1823 			if (mpstatus != MP_STATUS_SUCCESS) {
1824 				(void) fprintf(stderr, "%s:  %s\n",
1825 				    cmdName, getTextString(ERR_NO_PROPERTIES));
1826 				return (B_FALSE);
1827 			}
1828 
1829 			if (0 == strcmp(luFileName, luProps.deviceFileName)) {
1830 				foundIt = B_TRUE;
1831 			} else {
1832 				/* user input didn't match, try via devid */
1833 				/*
1834 				 * I don't see a reason to print the error for
1835 				 * any of these since they'll get the error at
1836 				 * the end anyway
1837 				 */
1838 
1839 
1840 				if (((fd1 = open(luFileName,
1841 					O_RDONLY|O_NDELAY)) >= 0) &&
1842 				    ((fd2 = open(luProps.deviceFileName,
1843 					O_RDONLY|O_NDELAY)) >= 0) &&
1844 				    (devid_get(fd1, &devid1) == 0) &&
1845 				    (devid_get(fd2, &devid2) == 0) &&
1846 				    ((NULL != devid1) && (NULL != devid2))) {
1847 					if (0 ==
1848 					    (devid_compare(devid1, devid2))) {
1849 						foundIt = B_TRUE;
1850 					}
1851 				}
1852 
1853 				if (NULL != devid1) {
1854 					devid_free(devid1);
1855 				}
1856 				if (NULL != devid2) {
1857 					devid_free(devid2);
1858 				}
1859 			}
1860 			if (B_TRUE == foundIt) {
1861 				pluOid->objectSequenceNumber =
1862 				    pLogicalUnitOidList->
1863 				    oids[lu].objectSequenceNumber;
1864 				pluOid->objectType =
1865 				    pLogicalUnitOidList->
1866 				    oids[lu].objectType;
1867 				pluOid->ownerId =
1868 				    pLogicalUnitOidList->oids[lu].ownerId;
1869 			}
1870 		}
1871 	}
1872 
1873 	return (foundIt);
1874 }
1875 
1876 
1877 /*
1878  * ****************************************************************************
1879  *
1880  * listInitiatorPort -
1881  * 	mpathadm list initiator-port [<initiator-port name>, ...]
1882  *
1883  * operandLen	- number of operands user passed into the cli
1884  * operand	- pointer to operand list from user
1885  *
1886  * ****************************************************************************
1887  */
1888 int
1889 listInitiatorPort(int operandLen, char *operand[])
1890 {
1891 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
1892 	MP_INITIATOR_PORT_PROPERTIES 		initProps;
1893 	MP_OID_LIST				*pPluginOidList,
1894 						*pInitOidList;
1895 	boolean_t				bListIt = B_FALSE;
1896 	boolean_t				*foundOp;
1897 
1898 	int					ol,
1899 						i,
1900 						iport;
1901 
1902 	foundOp = malloc((sizeof (boolean_t)) * operandLen);
1903 	if (NULL == foundOp) {
1904 		(void) fprintf(stdout, "%s\n",
1905 		    getTextString(ERR_MEMORY_ALLOCATION));
1906 		return (ERROR_CLI_FAILED);
1907 	}
1908 
1909 	for (ol = 0; ol < operandLen; ol++) {
1910 		foundOp[ol] = B_FALSE;
1911 	}
1912 
1913 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
1914 		!= MP_STATUS_SUCCESS) {
1915 		(void) fprintf(stderr, "%s: %s\n", cmdName,
1916 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
1917 		return (mpstatus);
1918 	}
1919 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
1920 		(void) fprintf(stderr, "%s: %s\n", cmdName,
1921 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
1922 		return (ERROR_CLI_FAILED);
1923 	}
1924 
1925 	for (i = 0; i < pPluginOidList->oidCount; i++) {
1926 		mpstatus =
1927 		    MP_GetInitiatorPortOidList(pPluginOidList->oids[i],
1928 		    &pInitOidList);
1929 		if (mpstatus != MP_STATUS_SUCCESS) {
1930 			/* LINTED E_SEC_PRINTF_VAR_FMT */
1931 			(void) fprintf(stderr,
1932 			    getTextString(ERR_NO_INIT_PORT_LIST_WITH_REASON),
1933 			    getMpStatusStr(mpstatus));
1934 			(void) printf("\n");
1935 		} else if ((NULL == pInitOidList) ||
1936 			(pInitOidList->oidCount < 1)) {
1937 			(void) fprintf(stderr, "%s: %s\n", cmdName,
1938 			    getTextString(ERR_NO_INIT_PORTS));
1939 		} else {
1940 			for (iport = 0;
1941 			    iport < pInitOidList->oidCount; iport ++) {
1942 				bListIt = B_FALSE;
1943 				if ((mpstatus =
1944 				    MP_GetInitiatorPortProperties(
1945 				    pInitOidList->oids[iport],
1946 				    &initProps)) != MP_STATUS_SUCCESS) {
1947 					(void) fprintf(stderr,
1948 					    "%s: %s\n", cmdName,
1949 					    getTextString(ERR_NO_PROPERTIES));
1950 				} else {
1951 					/* if no operands listed, */
1952 					/* list all we find */
1953 					if (0 == operandLen) {
1954 						bListIt = B_TRUE;
1955 					} else {
1956 
1957 						/* check each operand */
1958 						/* Is it */
1959 						/* the one we want to list? */
1960 						for (ol = 0;
1961 						    ol < operandLen; ol++) {
1962 							if (0 ==
1963 							    strcmp(operand[ol],
1964 							    initProps.
1965 							    portID)) {
1966 								bListIt =
1967 								    B_TRUE;
1968 								foundOp[ol] =
1969 								    B_TRUE;
1970 							}
1971 						}
1972 					}
1973 				}
1974 
1975 				if (B_TRUE == bListIt) {
1976 
1977 					if (listIndividualInitiatorPort(
1978 					    initProps) != 0) {
1979 						return (ERROR_CLI_FAILED);
1980 					}
1981 
1982 				} /* list It */
1983 
1984 			} /* for each initiator port */
1985 		} /* else found an init port */
1986 
1987 	} /* for each plugin */
1988 
1989 	for (ol = 0; ol < operandLen; ol++) {
1990 		if (B_FALSE == foundOp[ol]) {
1991 			/* LINTED E_SEC_PRINTF_VAR_FMT */
1992 			(void) fprintf(stderr, getTextString(
1993 			    ERR_INIT_PORT_NOT_FOUND_WITH_MISSING_LU_STR),
1994 			    operand[ol]);
1995 			(void) printf("\n");
1996 		}
1997 	}
1998 
1999 	return (mpstatus);
2000 }
2001 
2002 
2003 /*
2004  * ****************************************************************************
2005  *
2006  * listIndividualInitiatorPort -
2007  * 	used by listInitiatorPort to list info for one init port
2008  *
2009  * initProps	- properties of initiator port to list
2010  *
2011  * ****************************************************************************
2012  */
2013 int
2014 listIndividualInitiatorPort(MP_INITIATOR_PORT_PROPERTIES initProps)
2015 {
2016 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
2017 
2018 	(void) printf("%s  ", getTextString(TEXT_LB_INITATOR_PORT));
2019 	displayArray(initProps.portID,
2020 		sizeof (initProps.portID));
2021 	(void) printf("\n");
2022 
2023 	return (mpstatus);
2024 
2025 }
2026 
2027 
2028 /*
2029  * ****************************************************************************
2030  *
2031  * showInitiatorPort -
2032  * 	mpathadm show initiator-port <initiator-port name>, ...
2033  *
2034  * operandLen	- number of operands user passed into the cli
2035  * operand	- pointer to operand list from user
2036  *
2037  * ****************************************************************************
2038  */
2039 int
2040 showInitiatorPort(int operandLen, char *operand[])
2041 {
2042 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
2043 	MP_INITIATOR_PORT_PROPERTIES 		initProps;
2044 	MP_OID_LIST				*pPluginOidList,
2045 						*pInitOidList;
2046 	boolean_t				bListIt = B_FALSE,
2047 						bFoundIt = B_FALSE;
2048 	int					op,
2049 						i,
2050 						iport;
2051 
2052 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
2053 		!= MP_STATUS_SUCCESS) {
2054 		(void) fprintf(stderr, "%s: %s\n", cmdName,
2055 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
2056 		return (mpstatus);
2057 	}
2058 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
2059 		(void) fprintf(stderr, "%s: %s\n", cmdName,
2060 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
2061 		return (ERROR_CLI_FAILED);
2062 	}
2063 
2064 	for (op = 0; op < operandLen; op++) {
2065 	bFoundIt = B_FALSE;
2066 
2067 		for (i = 0; i < pPluginOidList->oidCount; i++) {
2068 
2069 			mpstatus =
2070 			    MP_GetInitiatorPortOidList(pPluginOidList->oids[i],
2071 			    &pInitOidList);
2072 			if (mpstatus != MP_STATUS_SUCCESS) {
2073 				/* LINTED E_SEC_PRINTF_VAR_FMT */
2074 				(void) fprintf(stderr,
2075 				    getTextString(
2076 				    ERR_NO_INIT_PORT_LIST_WITH_REASON),
2077 				    getMpStatusStr(mpstatus));
2078 				(void) printf("\n");
2079 			} else if ((NULL == pInitOidList) ||
2080 			    (pInitOidList->oidCount < 1)) {
2081 				(void) fprintf(stderr, "%s: %s\n", cmdName,
2082 				    getTextString(ERR_NO_INIT_PORTS));
2083 			} else {
2084 
2085 				for (iport = 0;
2086 				    iport < pInitOidList->oidCount;
2087 				    iport ++) {
2088 					bListIt = B_FALSE;
2089 
2090 					if ((mpstatus =
2091 					    MP_GetInitiatorPortProperties(
2092 					    pInitOidList->oids[iport],
2093 					    &initProps))
2094 					    != MP_STATUS_SUCCESS) {
2095 						(void) fprintf(stderr,
2096 						    "%s: %s\n", cmdName,
2097 					    getTextString(ERR_NO_PROPERTIES));
2098 					} else {
2099 						if (0 == strcmp(operand[op],
2100 						    initProps.portID)) {
2101 							bListIt = B_TRUE;
2102 							bFoundIt = B_TRUE;
2103 						}
2104 					}
2105 
2106 					if (B_TRUE == bListIt) {
2107 						mpstatus =
2108 						showIndividualInitiatorPort(
2109 						initProps);
2110 						if (0 != mpstatus) {
2111 							return (mpstatus);
2112 						}
2113 
2114 					} /* list It */
2115 
2116 				} /* for each initiator port */
2117 			} /* else found an init port */
2118 
2119 		} /* for each plugin */
2120 
2121 		if (B_FALSE == bFoundIt) {
2122 			/* need temp string here since we need to fill in a */
2123 			/* name in the error string */
2124 			/* LINTED E_SEC_PRINTF_VAR_FMT */
2125 			(void) fprintf(stderr, getTextString(
2126 			    ERR_INIT_PORT_NOT_FOUND_WITH_MISSING_LU_STR),
2127 			    operand[op]);
2128 			(void) printf("\n");
2129 		}
2130 
2131 	} /* for each operand */
2132 
2133 	return (mpstatus);
2134 }
2135 
2136 
2137 /*
2138  * ****************************************************************************
2139  *
2140  * showIndividualInitiatorPort -
2141  * 	used by showInitiatorPort to show info for one init port
2142  *
2143  * initProps	- properties of initiator port to show
2144  *
2145  * ****************************************************************************
2146  */
2147 int
2148 showIndividualInitiatorPort(MP_INITIATOR_PORT_PROPERTIES initProps)
2149 {
2150 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
2151 
2152 	(void) printf("%s  ", getTextString(TEXT_LB_INITATOR_PORT));
2153 	displayArray(initProps.portID,
2154 	    sizeof (initProps.portID));
2155 
2156 	(void) printf("\n\t%s  ", getTextString(TEXT_LB_TRANSPORT_TYPE));
2157 	displayTransportTypeString(initProps.portType);
2158 	(void) printf("\n");
2159 
2160 	(void) printf("\t%s  ", getTextString(TEXT_LB_OS_DEVICE_FILE));
2161 	displayArray(initProps.osDeviceFile,
2162 	    sizeof (initProps.osDeviceFile));
2163 	(void) printf("\n");
2164 
2165 	return (mpstatus);
2166 }
2167 
2168 
2169 /*
2170  * ****************************************************************************
2171  *
2172  * enablePath -
2173  * 	mpathadm enable path -i <initiator-port>
2174  *		-t <target-port name> -l <logical-unit name>
2175  *
2176  * options	- pointer to option list from user
2177  *
2178  * ****************************************************************************
2179  */
2180 int
2181 enablePath(cmdOptions_t *options)
2182 {
2183 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
2184 	MP_OID					pathOid;
2185 
2186 	cmdOptions_t 				*optionList = options;
2187 	boolean_t				bHaveInit = B_FALSE,
2188 						bHaveTarg = B_FALSE,
2189 						bHaveLu = B_FALSE;
2190 
2191 	for (; optionList->optval; optionList++) {
2192 		switch (optionList->optval) {
2193 			case 'i':
2194 				/* have init port name */
2195 				bHaveInit = B_TRUE;
2196 				break;
2197 			case 't':
2198 				/* have target port id */
2199 				bHaveTarg = B_TRUE;
2200 				break;
2201 			case 'l':
2202 				/* have LU name */
2203 				bHaveLu = B_TRUE;
2204 				break;
2205 		}
2206 	}
2207 	if (B_FALSE == bHaveInit) {
2208 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2209 		(void) fprintf(stderr,
2210 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
2211 		    getTextString(MISSING_INIT_PORT_NAME));
2212 		(void) printf("\n");
2213 		return (ERROR_CLI_FAILED);
2214 	} else if (B_FALSE == bHaveTarg) {
2215 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2216 		(void) fprintf(stderr,
2217 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
2218 		    getTextString(MISSING_TARGET_PORT_NAME));
2219 		(void) printf("\n");
2220 		return (ERROR_CLI_FAILED);
2221 	} else if (B_FALSE == bHaveLu) {
2222 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2223 		(void) fprintf(stderr,
2224 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
2225 		    getTextString(MISSING_LU_NAME));
2226 		(void) printf("\n");
2227 		return (ERROR_CLI_FAILED);
2228 	}
2229 
2230 	if (B_FALSE == getPathOid(options, &pathOid)) {
2231 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2232 		(void) fprintf(stderr,
2233 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
2234 		    getTextString(FAILED_TO_FIND_PATH));
2235 		(void) printf("\n");
2236 		return (ERROR_CLI_FAILED);
2237 	}
2238 
2239 	/* found the path, attempt to enable it */
2240 	mpstatus =  MP_EnablePath(pathOid);
2241 	if (mpstatus != MP_STATUS_SUCCESS) {
2242 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2243 		(void) fprintf(stderr,
2244 		    getTextString(ERR_FAILED_TO_ENABLE_PATH_WITH_REASON),
2245 		    getMpStatusStr(mpstatus));
2246 		(void) printf("\n");
2247 		return (mpstatus);
2248 	}
2249 
2250 	return (mpstatus);
2251 }
2252 
2253 
2254 /*
2255  * ****************************************************************************
2256  *
2257  * disablePath -
2258  * 	mpathadm disable path -i <initiator-port>
2259  *		-t <target-port name> -l <logical-unit name>
2260  *
2261  * options	- pointer to option list from user
2262  *
2263  * ****************************************************************************
2264  */
2265 int
2266 disablePath(cmdOptions_t *options)
2267 {
2268 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
2269 	MP_OID					pathOid;
2270 
2271 	cmdOptions_t 				*optionList = options;
2272 	boolean_t				bHaveInit = B_FALSE,
2273 						bHaveTarg = B_FALSE,
2274 						bHaveLu = B_FALSE;
2275 
2276 	for (; optionList->optval; optionList++) {
2277 		switch (optionList->optval) {
2278 			case 'i':
2279 				/* have init port name */
2280 				bHaveInit = B_TRUE;
2281 				break;
2282 			case 't':
2283 				/* have target port id */
2284 				bHaveTarg = B_TRUE;
2285 				break;
2286 			case 'l':
2287 				/* have LU name */
2288 				bHaveLu = B_TRUE;
2289 				break;
2290 		}
2291 	}
2292 	if (B_FALSE == bHaveInit) {
2293 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2294 		(void) fprintf(stderr,
2295 		    getTextString(ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
2296 		    getTextString(MISSING_INIT_PORT_NAME));
2297 		(void) printf("\n");
2298 		return (ERROR_CLI_FAILED);
2299 	} else if (B_FALSE == bHaveTarg) {
2300 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2301 		(void) fprintf(stderr,
2302 		    getTextString(ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
2303 		    getTextString(MISSING_TARGET_PORT_NAME));
2304 		(void) printf("\n");
2305 		return (ERROR_CLI_FAILED);
2306 	} else if (B_FALSE == bHaveLu) {
2307 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2308 		(void) fprintf(stderr,
2309 		    getTextString(ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
2310 		    getTextString(MISSING_LU_NAME));
2311 		(void) printf("\n");
2312 		return (ERROR_CLI_FAILED);
2313 	}
2314 
2315 	if (B_FALSE == getPathOid(options, &pathOid)) {
2316 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2317 		(void) fprintf(stderr,
2318 		    getTextString(ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
2319 		    getTextString(FAILED_TO_FIND_PATH));
2320 		(void) printf("\n");
2321 		return (ERROR_CLI_FAILED);
2322 	}
2323 
2324 	/* found the path, attempt to enable it */
2325 	mpstatus =  MP_DisablePath(pathOid);
2326 	if (MP_STATUS_SUCCESS != mpstatus) {
2327 		/* LINTED E_SEC_PRINTF_VAR_FMT */
2328 		(void) fprintf(stderr, getTextString(
2329 		    ERR_FAILED_TO_DISABLE_PATH_WITH_REASON),
2330 		    getMpStatusStr(mpstatus));
2331 		(void) printf("\n");
2332 		return (mpstatus);
2333 	}
2334 
2335 
2336 	return (mpstatus);
2337 }
2338 
2339 
2340 /*
2341  * ****************************************************************************
2342  *
2343  * overridePath -
2344  * 	mpathadm override path {-i <initiator-port>
2345  *		-t <target-port name> | -c} <logical-unit name>
2346  *
2347  * options	- pointer to option list from user
2348  *
2349  * ****************************************************************************
2350  */
2351 int
2352 overridePath(cmdOptions_t *options)
2353 {
2354 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
2355 	MP_OID					pathOid, luOid;
2356 	boolean_t				bCancelOverride = B_FALSE;
2357 	MP_CHAR					pLuDeviceFileName[256];
2358 	cmdOptions_t 				*optionList = options;
2359 
2360 	/* First check to see if we have the cancel option, */
2361 	/* May as well save off the lun while we're at it */
2362 	for (; optionList->optval; optionList++) {
2363 		switch (optionList->optval) {
2364 			case 'c':
2365 				/* we have a cancel */
2366 				bCancelOverride = B_TRUE;
2367 				break;
2368 			case 'l':
2369 				/* we have a lun- save it while we're here */
2370 				(void) memcpy(pLuDeviceFileName,
2371 				    optionList->optarg, 256);
2372 				break;
2373 		}
2374 	}
2375 
2376 	if (B_TRUE == bCancelOverride) {
2377 		/* if we have the cancel option, */
2378 		if (getLogicalUnitOid(pLuDeviceFileName, &luOid) == B_FALSE) {
2379 			/* LINTED E_SEC_PRINTF_VAR_FMT */
2380 			(void) fprintf(stderr,
2381 			    getTextString(
2382 			    ERR_FAILED_TO_CANCEL_OVERRIDE_PATH_WITH_REASON),
2383 			    getTextString(LU_NOT_FOUND));
2384 			(void) printf("\n");
2385 			return (ERROR_CLI_FAILED);
2386 		}
2387 
2388 		/* cancel the override path for the specified LU */
2389 		mpstatus = MP_CancelOverridePath(luOid);
2390 		if (MP_STATUS_SUCCESS != mpstatus) {
2391 			/* LINTED E_SEC_PRINTF_VAR_FMT */
2392 			(void) fprintf(stderr,
2393 			    getTextString(
2394 			    ERR_FAILED_TO_CANCEL_OVERRIDE_PATH_WITH_REASON),
2395 			    getMpStatusStr(mpstatus));
2396 			(void) printf("\n");
2397 			return (mpstatus);
2398 		}
2399 	} else {
2400 		/* must be wanting to override the path */
2401 		if (getLogicalUnitOid(pLuDeviceFileName, &luOid) == B_FALSE) {
2402 			/* LINTED E_SEC_PRINTF_VAR_FMT */
2403 			(void) fprintf(stderr,
2404 			    getTextString(
2405 			    ERR_FAILED_TO_OVERRIDE_PATH_WITH_REASON),
2406 			    getTextString(LU_NOT_FOUND));
2407 			(void) printf("\n");
2408 			return (ERROR_CLI_FAILED);
2409 		}
2410 
2411 		if (B_FALSE == getPathOid(options, &pathOid)) {
2412 			/* LINTED E_SEC_PRINTF_VAR_FMT */
2413 			(void) fprintf(stderr,
2414 			    getTextString(
2415 			    ERR_FAILED_TO_OVERRIDE_PATH_WITH_REASON),
2416 			    getTextString(FAILED_TO_FIND_PATH));
2417 
2418 			(void) printf("\n");
2419 			return (ERROR_CLI_FAILED);
2420 		}
2421 
2422 		/* attempt to set the override path */
2423 		mpstatus =  MP_SetOverridePath(luOid, pathOid);
2424 		if (mpstatus != MP_STATUS_SUCCESS) {
2425 			/* LINTED E_SEC_PRINTF_VAR_FMT */
2426 			(void) fprintf(stderr,
2427 			    getTextString(
2428 			    ERR_FAILED_TO_OVERRIDE_PATH_WITH_REASON),
2429 			    getMpStatusStr(mpstatus));
2430 			(void) printf("\n");
2431 			return (mpstatus);
2432 		}
2433 	}
2434 
2435 	return (mpstatus);
2436 }
2437 
2438 
2439 /*
2440  * ****************************************************************************
2441  *
2442  * getPathOid -
2443  *	Search through all plugins and get the OID for specified path
2444  *
2445  * operand	- pointer to operand list from user
2446  * options	- pointer to option list from user
2447  *
2448  * ****************************************************************************
2449  */
2450 boolean_t
2451 getPathOid(cmdOptions_t *options, MP_OID *pPathOid)
2452 {
2453 	MP_STATUS				mpstatus = MP_STATUS_SUCCESS;
2454 	MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES 	luProps;
2455 	MP_PATH_LOGICAL_UNIT_PROPERTIES		pathProps;
2456 	MP_INITIATOR_PORT_PROPERTIES		initProps;
2457 	MP_TARGET_PORT_PROPERTIES		targProps;
2458 
2459 	MP_OID_LIST				*pPluginOidList,
2460 						*pLogicalUnitOidList,
2461 						*pathOidListArray;
2462 
2463 	boolean_t				bFoundIt = B_FALSE;
2464 	MP_CHAR					initPortID[256];
2465 	MP_CHAR					targetPortID[256];
2466 	MP_CHAR					luDeviceFileName[256];
2467 	boolean_t				bHaveTarg = B_FALSE,
2468 						bHaveLu = B_FALSE,
2469 						bHaveInit = B_FALSE;
2470 
2471 
2472 	cmdOptions_t 				*optionList = options;
2473 
2474 	int					i,
2475 						lu,
2476 						pa;
2477 	if (NULL == pPathOid) {
2478 		return (B_FALSE);
2479 	}
2480 
2481 	for (; optionList->optval; optionList++) {
2482 		switch (optionList->optval) {
2483 			case 'i':
2484 				/* save init port name */
2485 				(void) memcpy(initPortID,
2486 				    optionList->optarg, 256);
2487 				bHaveInit = B_TRUE;
2488 				break;
2489 			case 't':
2490 				/* save target port id */
2491 				(void) memcpy(targetPortID,
2492 				    optionList->optarg, 256);
2493 				bHaveTarg = B_TRUE;
2494 				break;
2495 			case 'l':
2496 				/* save LU name */
2497 				(void) memcpy(luDeviceFileName,
2498 				    optionList->optarg, 256);
2499 				bHaveLu = B_TRUE;
2500 				break;
2501 		}
2502 	}
2503 
2504 
2505 	if ((B_FALSE == bHaveInit) ||
2506 	    (B_FALSE == bHaveTarg) ||
2507 	    (B_FALSE == bHaveLu)) {
2508 		/* if we don't have all three pieces, we can't find the path */
2509 
2510 		return (B_FALSE);
2511 	}
2512 
2513 	/* get the plugin ist */
2514 	if ((mpstatus = MP_GetPluginOidList(&pPluginOidList))
2515 	    != MP_STATUS_SUCCESS) {
2516 		(void) fprintf(stderr, "%s: %s\n", cmdName,
2517 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
2518 		return (B_FALSE);
2519 	}
2520 	if ((NULL == pPluginOidList) || (pPluginOidList->oidCount < 1)) {
2521 		(void) fprintf(stderr, "%s: %s\n", cmdName,
2522 		    getTextString(ERR_NO_MPATH_SUPPORT_LIST));
2523 		return (B_FALSE);
2524 	}
2525 
2526 	for (i = 0; i < pPluginOidList->oidCount; i++) {
2527 
2528 		/* get Logical Unit list */
2529 		mpstatus = MP_GetMultipathLus(pPluginOidList->oids[i],
2530 		    &pLogicalUnitOidList);
2531 		if (mpstatus != MP_STATUS_SUCCESS) {
2532 			(void) fprintf(stderr, "%s:  %s\n",
2533 			    cmdName, getTextString(ERR_NO_LU_LIST));
2534 			return (B_FALSE);
2535 		}
2536 
2537 		for (lu = 0; (lu < pLogicalUnitOidList->oidCount) &&
2538 			(B_FALSE == bFoundIt); lu++) {
2539 
2540 			/* get lu properties so we can check the name */
2541 			(void) memset(&luProps, 0,
2542 			    sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
2543 			mpstatus =
2544 			    MP_GetMPLogicalUnitProperties(
2545 			    pLogicalUnitOidList->oids[lu], &luProps);
2546 			if (mpstatus != MP_STATUS_SUCCESS) {
2547 				(void) fprintf(stderr, "%s:  %s\n",
2548 				    cmdName, getTextString(ERR_NO_PROPERTIES));
2549 				return (B_FALSE);
2550 			}
2551 			if (0 == strcmp(luDeviceFileName,
2552 			    luProps.deviceFileName)) {
2553 				/* get paths for this LU and search from here */
2554 				mpstatus =
2555 				    MP_GetAssociatedPathOidList(
2556 				    pLogicalUnitOidList->oids[lu],
2557 				    &pathOidListArray);
2558 				if (mpstatus != MP_STATUS_SUCCESS) {
2559 					/* LINTED E_SEC_PRINTF_VAR_FMT */
2560 					(void) fprintf(stderr,
2561 					    getTextString(
2562 					    ERR_FAILED_TO_FIND_PATH));
2563 					(void) printf("\n");
2564 					return (B_FALSE);
2565 				}
2566 
2567 				for (pa = 0;
2568 					(pa < pathOidListArray->oidCount) &&
2569 					(B_FALSE == bFoundIt); pa++) {
2570 					mpstatus =
2571 					    MP_GetPathLogicalUnitProperties
2572 					    (pathOidListArray->oids[pa],
2573 					    &pathProps);
2574 					if (mpstatus != MP_STATUS_SUCCESS) {
2575 						(void) fprintf(stderr,
2576 						    "%s:  %s\n", cmdName,
2577 						    getTextString(
2578 						    ERR_NO_PROPERTIES));
2579 						return (B_FALSE);
2580 					}
2581 
2582 					/*
2583 					 * get properties of iniator port and
2584 					 * target port to see if we have the
2585 					 * right path
2586 					 */
2587 					mpstatus =
2588 					    MP_GetInitiatorPortProperties(
2589 					    pathProps.initiatorPortOid,
2590 					    &initProps);
2591 
2592 					if (mpstatus != MP_STATUS_SUCCESS) {
2593 						(void) fprintf(stderr,
2594 						    "%s:  %s\n", cmdName,
2595 						    getTextString(
2596 						    ERR_NO_PROPERTIES));
2597 						return (B_FALSE);
2598 					}
2599 	if (0 == strcmp(initPortID, initProps.portID)) {
2600 		/* lu and init port matches, check target port */
2601 		mpstatus = MP_GetTargetPortProperties(pathProps.targetPortOid,
2602 		    &targProps);
2603 		if (mpstatus != MP_STATUS_SUCCESS) {
2604 			(void) fprintf(stderr, "%s:  %s\n", cmdName,
2605 			    getTextString(ERR_NO_PROPERTIES));
2606 			return (B_FALSE);
2607 		}
2608 
2609 		if (0 == strcmp(targetPortID, targProps.portID)) {
2610 			/* we found our path */
2611 			pPathOid->objectSequenceNumber =
2612 			    pathOidListArray->oids[pa].objectSequenceNumber;
2613 			pPathOid->objectType =
2614 			    pathOidListArray->oids[pa].objectType;
2615 			pPathOid->ownerId = pathOidListArray->oids[pa].ownerId;
2616 			bFoundIt = B_TRUE;
2617 		}
2618 	} /* init port matched */
2619 
2620 				} /* for each path associated with this lu */
2621 
2622 			} /* lu matched */
2623 
2624 		} /* for each lu */
2625 
2626 	} /* for each plugin */
2627 
2628 	return (bFoundIt);
2629 }
2630 
2631 
2632 /*
2633  * ****************************************************************************
2634  *
2635  * getLbValueFromString
2636  * 	Gets the MP_LOAD_BALANCE_TYPE specified load balance type string
2637  *
2638  * lbStr	- load balance string defined in the .h file
2639  *		This is what users will be required to feed into the
2640  *		modify lu command.
2641  *
2642  * ****************************************************************************
2643  */
2644 MP_LOAD_BALANCE_TYPE
2645 getLbValueFromString(char *lbStr)
2646 {
2647 	MP_LOAD_BALANCE_TYPE		lbVal = MP_LOAD_BALANCE_TYPE_UNKNOWN;
2648 
2649 	if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_ROUNDROBIN))) {
2650 		lbVal = MP_LOAD_BALANCE_TYPE_ROUNDROBIN;
2651 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_LEASTBLOCKS))) {
2652 		lbVal = MP_LOAD_BALANCE_TYPE_LEASTBLOCKS;
2653 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_LEASTIO))) {
2654 		lbVal = MP_LOAD_BALANCE_TYPE_LEASTIO;
2655 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_DEVICEPROD))) {
2656 		lbVal = MP_LOAD_BALANCE_TYPE_DEVICE_PRODUCT;
2657 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_LBAREGION))) {
2658 		lbVal = MP_LOAD_BALANCE_TYPE_LBA_REGION;
2659 	} else if (0 == strcmp(lbStr,
2660 	    getTextString(TEXT_LBTYPE_FAILOVER_ONLY))) {
2661 		lbVal = MP_LOAD_BALANCE_TYPE_FAILOVER_ONLY;
2662 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_UNKNOWN))) {
2663 		lbVal = MP_LOAD_BALANCE_TYPE_UNKNOWN;
2664 	} else if (0 == strcmp(lbStr, getTextString(TEXT_LBTYPE_NONE))) {
2665 		lbVal = 0;
2666 	} else if (0 == strcmp(lbStr,
2667 	    getTextString(TEXT_LBTYPE_PROPRIETARY1))) {
2668 		lbVal = ((MP_UINT32)0x00000001)<<16;
2669 	} else if (0 == strcmp(lbStr,
2670 	    getTextString(TEXT_LBTYPE_PROPRIETARY2))) {
2671 		lbVal = ((MP_UINT32)0x00000001)<<17;
2672 	} else if (0 == strcmp(lbStr,
2673 	    getTextString(TEXT_LBTYPE_PROPRIETARY3))) {
2674 		lbVal = ((MP_UINT32)0x00000001)<<18;
2675 	} else if (0 == strcmp(lbStr,
2676 	    getTextString(TEXT_LBTYPE_PROPRIETARY4))) {
2677 		lbVal = ((MP_UINT32)0x00000001)<<19;
2678 	} else if (0 == strcmp(lbStr,
2679 	    getTextString(TEXT_LBTYPE_PROPRIETARY5))) {
2680 		lbVal = ((MP_UINT32)0x00000001)<<20;
2681 	} else if (0 == strcmp(lbStr,
2682 	    getTextString(TEXT_LBTYPE_PROPRIETARY6))) {
2683 		lbVal = ((MP_UINT32)0x00000001)<<21;
2684 	} else if (0 == strcmp(lbStr,
2685 	    getTextString(TEXT_LBTYPE_PROPRIETARY7))) {
2686 		lbVal = ((MP_UINT32)0x00000001)<<22;
2687 	} else if (0 == strcmp(lbStr,
2688 	    getTextString(TEXT_LBTYPE_PROPRIETARY8))) {
2689 		lbVal = ((MP_UINT32)0x00000001)<<23;
2690 	} else if (0 == strcmp(lbStr,
2691 	    getTextString(TEXT_LBTYPE_PROPRIETARY9))) {
2692 		lbVal = ((MP_UINT32)0x00000001)<<24;
2693 	} else if (0 == strcmp(lbStr,
2694 	    getTextString(TEXT_LBTYPE_PROPRIETARY10))) {
2695 		lbVal = ((MP_UINT32)0x00000001)<<25;
2696 	} else if (0 == strcmp(lbStr,
2697 	    getTextString(TEXT_LBTYPE_PROPRIETARY11))) {
2698 		lbVal = ((MP_UINT32)0x00000001)<<26;
2699 	} else if (0 == strcmp(lbStr,
2700 	    getTextString(TEXT_LBTYPE_PROPRIETARY12))) {
2701 		lbVal = ((MP_UINT32)0x00000001)<<27;
2702 	} else if (0 == strcmp(lbStr,
2703 	    getTextString(TEXT_LBTYPE_PROPRIETARY13))) {
2704 		lbVal = ((MP_UINT32)0x00000001)<<28;
2705 	} else if (0 == strcmp(lbStr,
2706 	    getTextString(TEXT_LBTYPE_PROPRIETARY14))) {
2707 		lbVal = ((MP_UINT32)0x00000001)<<29;
2708 	} else if (0 == strcmp(lbStr,
2709 	    getTextString(TEXT_LBTYPE_PROPRIETARY15))) {
2710 		lbVal = ((MP_UINT32)0x00000001)<<30;
2711 	} else if (0 == strcmp(lbStr,
2712 	    getTextString(TEXT_LBTYPE_PROPRIETARY16))) {
2713 		lbVal = ((MP_UINT32)0x00000001)<<31;
2714 	}
2715 
2716 	return (lbVal);
2717 
2718 
2719 } /* end getLbValueFromString */
2720 
2721 
2722 /*
2723  * ****************************************************************************
2724  *
2725  * displayLogicalUnitNameTypeString
2726  * 	Displays the text equivalent string for the MP_LOGICAL_UNIT_NAME_TYPE
2727  *	specified load balance type
2728  *
2729  * typeVal	- load balance type defined in the MPAPI spec
2730  *
2731  * ****************************************************************************
2732  */
2733 void
2734 displayLogicalUnitNameTypeString(MP_LOGICAL_UNIT_NAME_TYPE typeVal)
2735 {
2736 
2737 	char					*typeString;
2738 
2739 	switch (typeVal) {
2740 
2741 		case MP_LU_NAME_TYPE_UNKNOWN:
2742 			typeString = getTextString(TEXT_NAME_TYPE_UNKNOWN);
2743 			break;
2744 		case MP_LU_NAME_TYPE_VPD83_TYPE1:
2745 			typeString = getTextString(TEXT_NAME_TYPE_VPD83_TYPE1);
2746 			break;
2747 		case MP_LU_NAME_TYPE_VPD83_TYPE2:
2748 			typeString = getTextString(TEXT_NAME_TYPE_VPD83_TYPE2);
2749 			break;
2750 		case MP_LU_NAME_TYPE_VPD83_TYPE3:
2751 			typeString = getTextString(TEXT_NAME_TYPE_VPD83_TYPE3);
2752 			break;
2753 		case MP_LU_NAME_TYPE_DEVICE_SPECIFIC:
2754 			typeString =
2755 			getTextString(TEXT_NAME_TYPE_DEVICE_SPECIFIC);
2756 			break;
2757 		default:
2758 			typeString = getTextString(TEXT_UNKNOWN);
2759 			break;
2760 	}
2761 
2762 	(void) printf("%s", typeString);
2763 
2764 
2765 } /* end displayLogicalUnitNameTypeString */
2766 
2767 /*
2768  * ****************************************************************************
2769  *
2770  * displayLoadBalanceString
2771  * 	Displays the text equivalent string for the MP_LOAD_BALANCE_TYPE
2772  *	specified load balance type
2773  *
2774  * lbVal	- load balance type defined in the MPAPI spec
2775  *
2776  * ****************************************************************************
2777  */
2778 void
2779 displayLoadBalanceString(MP_LOAD_BALANCE_TYPE lbVal)
2780 {
2781 
2782 	char					*lbString;
2783 
2784 	switch (lbVal) {
2785 
2786 		case MP_LOAD_BALANCE_TYPE_UNKNOWN:
2787 			lbString = getTextString(TEXT_LBTYPE_UNKNOWN);
2788 			break;
2789 		case MP_LOAD_BALANCE_TYPE_ROUNDROBIN:
2790 			lbString = getTextString(TEXT_LBTYPE_ROUNDROBIN);
2791 			break;
2792 		case MP_LOAD_BALANCE_TYPE_LEASTBLOCKS:
2793 			lbString = getTextString(TEXT_LBTYPE_LEASTBLOCKS);
2794 			break;
2795 		case MP_LOAD_BALANCE_TYPE_LEASTIO:
2796 			lbString = getTextString(TEXT_LBTYPE_LEASTIO);
2797 			break;
2798 		case MP_LOAD_BALANCE_TYPE_DEVICE_PRODUCT:
2799 			lbString = getTextString(TEXT_LBTYPE_DEVICEPROD);
2800 			break;
2801 		case MP_LOAD_BALANCE_TYPE_LBA_REGION:
2802 			lbString = getTextString(TEXT_LBTYPE_LBAREGION);
2803 			break;
2804 		case MP_LOAD_BALANCE_TYPE_FAILOVER_ONLY:
2805 			lbString = getTextString(TEXT_LBTYPE_FAILOVER_ONLY);
2806 			break;
2807 		case (((MP_UINT32)0x00000001)<<16):
2808 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY1);
2809 			break;
2810 		case (((MP_UINT32)0x00000001)<<17):
2811 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY2);
2812 			break;
2813 		case (((MP_UINT32)0x00000001)<<18):
2814 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY3);
2815 			break;
2816 		case (((MP_UINT32)0x00000001)<<19):
2817 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY4);
2818 			break;
2819 		case (((MP_UINT32)0x00000001)<<20):
2820 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY5);
2821 			break;
2822 		case (((MP_UINT32)0x00000001)<<21):
2823 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY6);
2824 			break;
2825 		case (((MP_UINT32)0x00000001)<<22):
2826 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY7);
2827 			break;
2828 		case (((MP_UINT32)0x00000001)<<23):
2829 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY8);
2830 			break;
2831 		case (((MP_UINT32)0x00000001)<<24):
2832 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY9);
2833 			break;
2834 		case (((MP_UINT32)0x00000001)<<25):
2835 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY10);
2836 			break;
2837 		case (((MP_UINT32)0x00000001)<<26):
2838 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY11);
2839 			break;
2840 		case (((MP_UINT32)0x00000001)<<27):
2841 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY12);
2842 			break;
2843 		case (((MP_UINT32)0x00000001)<<28):
2844 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY13);
2845 			break;
2846 		case (((MP_UINT32)0x00000001)<<29):
2847 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY14);
2848 			break;
2849 		case (((MP_UINT32)0x00000001)<<30):
2850 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY15);
2851 			break;
2852 		case (((MP_UINT32)0x00000001)<<31):
2853 			lbString = getTextString(TEXT_LBTYPE_PROPRIETARY16);
2854 			break;
2855 		default:
2856 			lbString = getTextString(TEXT_UNKNOWN);
2857 			break;
2858 	}
2859 
2860 	(void) printf("%s", lbString);
2861 
2862 
2863 } /* end displayLoadBalanceString */
2864 
2865 /*
2866  * ****************************************************************************
2867  *
2868  * displayTransportTypeString
2869  * 	Displays the text equivalent string for the MP_PORT_TRANSPORT_TYPE
2870  *	specified load balance type
2871  *
2872  * transportTypeVal	- transport type defined in the MPAPI spec
2873  *
2874  * ****************************************************************************
2875  */
2876 void
2877 displayTransportTypeString(MP_PORT_TRANSPORT_TYPE transportTypeVal)
2878 {
2879 
2880 	char					*ttypeString;
2881 	switch (transportTypeVal) {
2882 
2883 		case MP_PORT_TRANSPORT_TYPE_MPNODE:
2884 			ttypeString =
2885 			    getTextString(TEXT_TRANS_PORT_TYPE_MPNODE);
2886 			break;
2887 		case MP_PORT_TRANSPORT_TYPE_FC:
2888 			ttypeString = getTextString(TEXT_TRANS_PORT_TYPE_FC);
2889 			break;
2890 		case MP_PORT_TRANSPORT_TYPE_SPI:
2891 			ttypeString = getTextString(TEXT_TRANS_PORT_TYPE_SPI);
2892 			break;
2893 		case MP_PORT_TRANSPORT_TYPE_ISCSI:
2894 			ttypeString = getTextString(TEXT_TRANS_PORT_TYPE_ISCSI);
2895 			break;
2896 		case MP_PORT_TRANSPORT_TYPE_IFB:
2897 			ttypeString = getTextString(TEXT_TRANS_PORT_TYPE_IFB);
2898 			break;
2899 		default:
2900 			ttypeString = getTextString(TEXT_UNKNOWN);
2901 			break;
2902 	}
2903 
2904 	(void) printf("%s", ttypeString);
2905 
2906 } /* end displayTransportTypeString */
2907 
2908 
2909 /*
2910  * ****************************************************************************
2911  *
2912  * getMpStatusStr
2913  * 	Gets the string description for the specified load balance type value
2914  *
2915  * mpstatus	- MP_STATUS value
2916  *
2917  * ****************************************************************************
2918  */
2919 char *
2920 getMpStatusStr(MP_STATUS mpstatus)
2921 {
2922 	char					*statString;
2923 
2924 	switch (mpstatus) {
2925 		case MP_STATUS_SUCCESS:
2926 			statString = getTextString(TEXT_MPSTATUS_SUCCESS);
2927 			break;
2928 		case MP_STATUS_INVALID_PARAMETER:
2929 			statString = getTextString(TEXT_MPSTATUS_INV_PARAMETER);
2930 			break;
2931 		case MP_STATUS_UNKNOWN_FN:
2932 			statString = getTextString(TEXT_MPSTATUS_UNKNOWN_FN);
2933 			break;
2934 		case MP_STATUS_FAILED:
2935 			statString = getTextString(TEXT_MPSTATUS_FAILED);
2936 			break;
2937 		case MP_STATUS_INSUFFICIENT_MEMORY:
2938 			statString = getTextString(TEXT_MPSTATUS_INSUFF_MEMORY);
2939 			break;
2940 		case MP_STATUS_INVALID_OBJECT_TYPE:
2941 			statString = getTextString(TEXT_MPSTATUS_INV_OBJ_TYPE);
2942 			break;
2943 		case MP_STATUS_UNSUPPORTED:
2944 			statString = getTextString(TEXT_MPSTATUS_UNSUPPORTED);
2945 			break;
2946 		case MP_STATUS_OBJECT_NOT_FOUND:
2947 			statString = getTextString(TEXT_MPSTATUS_OBJ_NOT_FOUND);
2948 			break;
2949 		case MP_STATUS_ACCESS_STATE_INVALID:
2950 			statString = getTextString(TEXT_MPSTATUS_UNSUPPORTED);
2951 			break;
2952 		case MP_STATUS_FN_REPLACED:
2953 			statString = getTextString(TEXT_MPSTATUS_FN_REPLACED);
2954 			break;
2955 		case MP_STATUS_PATH_NONOPERATIONAL:
2956 			statString = getTextString(TEXT_MPSTATUS_PATH_NONOP);
2957 			break;
2958 		case MP_STATUS_TRY_AGAIN:
2959 			statString = getTextString(TEXT_MPSTATUS_TRY_AGAIN);
2960 			break;
2961 		case MP_STATUS_NOT_PERMITTED:
2962 			statString = getTextString(TEXT_MPSTATUS_NOT_PERMITTED);
2963 			break;
2964 		default:
2965 			statString = getTextString(TEXT_UNKNOWN);
2966 			break;
2967 	}
2968 
2969 	return (statString);
2970 } /* end getMpStatusStr */
2971 
2972 
2973 /*
2974  * ****************************************************************************
2975  *
2976  * GetPathStateStr
2977  * 	Gets the string description for the specified path state type value
2978  *
2979  * pathState	- MP_PATH_STATE values
2980  *
2981  * ****************************************************************************
2982  */
2983 char *
2984 getPathStateStr(MP_PATH_STATE pathState)
2985 {
2986 	char					*pathString;
2987 
2988 	switch (pathState) {
2989 		case MP_PATH_STATE_OKAY:
2990 			pathString = getTextString(TEXT_PATH_STATE_OKAY);
2991 			break;
2992 		case MP_PATH_STATE_PATH_ERR:
2993 			pathString = getTextString(TEXT_PATH_STATE_PATH_ERR);
2994 			break;
2995 		case MP_PATH_STATE_LU_ERR:
2996 			pathString = getTextString(TEXT_PATH_STATE_LU_ERR);
2997 			break;
2998 		case MP_PATH_STATE_RESERVED:
2999 			pathString = getTextString(TEXT_PATH_STATE_RESERVED);
3000 			break;
3001 		case MP_PATH_STATE_REMOVED:
3002 			pathString = getTextString(TEXT_PATH_STATE_REMOVED);
3003 			break;
3004 		case MP_PATH_STATE_TRANSITIONING:
3005 			pathString =
3006 			    getTextString(TEXT_PATH_STATE_TRANSITIONING);
3007 			break;
3008 		case MP_PATH_STATE_OPERATIONAL_CLOSED:
3009 			pathString =
3010 			    getTextString(TEXT_PATH_STATE_OPERATIONAL_CLOSED);
3011 			break;
3012 		case MP_PATH_STATE_INVALID_CLOSED:
3013 			pathString =
3014 			    getTextString(TEXT_PATH_STATE_INVALID_CLOSED);
3015 			break;
3016 		case MP_PATH_STATE_OFFLINE_CLOSED:
3017 			pathString =
3018 			    getTextString(TEXT_PATH_STATE_OFFLINE_CLOSED);
3019 			break;
3020 		default:
3021 			pathString = getTextString(TEXT_UNKNOWN);
3022 			break;
3023 	}
3024 
3025 	return (pathString);
3026 } /* end getPathStateStr */
3027 
3028 
3029 
3030 /*
3031  * ****************************************************************************
3032  *
3033  * getAccessStateStr
3034  * 	Gets the string description for the specified access state type value
3035  *
3036  * accessState	- MP_ACCESS_STATE_TYPE values
3037  *
3038  * ****************************************************************************
3039  */
3040 char *
3041 getAccessStateStr(MP_ACCESS_STATE_TYPE accessState)
3042 {
3043 	char					*accessString;
3044 
3045 	switch (accessState) {
3046 		case MP_ACCESS_STATE_ACTIVE_OPTIMIZED:
3047 			accessString =
3048 			    getTextString(TEXT_ACCESS_STATE_ACTIVE_OPTIMIZED);
3049 			break;
3050 		case MP_ACCESS_STATE_ACTIVE_NONOPTIMIZED:
3051 			accessString =
3052 			    getTextString(
3053 			    TEXT_ACCESS_STATE_ACTIVE_NONOPTIMIZED);
3054 			break;
3055 		case MP_ACCESS_STATE_STANDBY:
3056 			accessString =
3057 			    getTextString(TEXT_ACCESS_STATE_STANDBY);
3058 			break;
3059 		case MP_ACCESS_STATE_UNAVAILABLE:
3060 			accessString =
3061 			    getTextString(TEXT_ACCESS_STATE_UNAVAILABLE);
3062 			break;
3063 		case MP_ACCESS_STATE_TRANSITIONING:
3064 			accessString =
3065 			    getTextString(TEXT_ACCESS_STATE_TRANSITIONING);
3066 			break;
3067 		case MP_ACCESS_STATE_ACTIVE:
3068 			accessString = getTextString(TEXT_ACCESS_STATE_ACTIVE);
3069 			break;
3070 		default:
3071 			accessString = getTextString(TEXT_UNKNOWN);
3072 			break;
3073 	}
3074 	return (accessString);
3075 } /* end getAccessStateStr */
3076 
3077 
3078 /*
3079  * ****************************************************************************
3080  *
3081  * displayArray
3082  * 	Print out the specified array.
3083  *
3084  * arrayToDisplay	- array to display
3085  * arraySize		- size of array to display
3086  *
3087  * ****************************************************************************
3088  */
3089 void
3090 displayArray(MP_CHAR *arrayToDisplay, int arraySize)
3091 {
3092 	int					i;
3093 
3094 	for (i = 0; i < arraySize; i++) {
3095 		if ('\0' != arrayToDisplay[i]) {
3096 			(void) fprintf(stdout, "%c", arrayToDisplay[i]);
3097 		}
3098 	}
3099 
3100 }
3101 
3102 
3103 /*
3104  * ****************************************************************************
3105  *
3106  * getStringArray
3107  * 	Return a null terminated array for the specified array as a string,
3108  *	This is used for inputting into the %s in formatted strings.
3109  *
3110  * arrayToDisplay	- array to display
3111  * arraySize		- size of array to display
3112  *
3113  * ****************************************************************************
3114  */
3115 MP_CHAR *
3116 getStringArray(MP_CHAR *arrayToDisplay, int arraySize)
3117 {
3118 	MP_CHAR					*newStr;
3119 
3120 	int					i;
3121 
3122 	newStr = malloc(((sizeof (MP_CHAR)) * arraySize) + 1);
3123 	if (NULL == newStr) {
3124 		(void) fprintf(stdout, "%s\n",
3125 		    getTextString(ERR_MEMORY_ALLOCATION));
3126 	} else {
3127 
3128 		for (i = 0; i < arraySize; i++) {
3129 			newStr[i] = arrayToDisplay[i];
3130 		}
3131 		newStr[arraySize] = '\0';
3132 	}
3133 
3134 	return (newStr);
3135 }
3136 
3137 
3138 /*
3139  * ****************************************************************************
3140  *
3141  * displayWideArray
3142  * 	Print out the specified wide character array as a string,
3143  * 	adding the null termination
3144  *
3145  * arrayToDisplay	- array to display
3146  * arraySize		- size of array to display
3147  *
3148  * ****************************************************************************
3149  */
3150 void
3151 displayWideArray(MP_WCHAR *arrayToDisplay, int arraySize)
3152 {
3153 	int					i;
3154 	int					numChars = arraySize/4;
3155 
3156 	for (i = 0; i < numChars; i++) {
3157 		if (L'\0' != arrayToDisplay[i]) {
3158 			(void) fprintf(stdout, "%wc", arrayToDisplay[i]);
3159 		}
3160 	}
3161 }
3162 
3163 
3164 /*
3165  * ****************************************************************************
3166  *
3167  * listfunc
3168  * 	Used by cmdparse for list clis
3169  *
3170  * ****************************************************************************
3171  */
3172 /*ARGSUSED*/
3173 static int
3174 listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
3175     void *addArgs)
3176 {
3177 	int 					ret = 0;
3178 
3179 	switch (object) {
3180 		case MPATH_SUPPORT:
3181 			ret = listMpathSupport(operandLen, operand);
3182 			break;
3183 		case LOGICAL_UNIT:
3184 			ret = listLogicalUnit(operandLen, operand, options);
3185 			break;
3186 		case INITIATOR_PORT:
3187 			ret = listInitiatorPort(operandLen, operand);
3188 			break;
3189 		default:
3190 			(void) fprintf(stderr, "%s: %s\n",
3191 		    cmdName, getTextString(TEXT_UNKNOWN_OBJECT));
3192 			ret = 1;
3193 			break;
3194 	}
3195 
3196 	return (ret);
3197 }
3198 
3199 
3200 /*
3201  * ****************************************************************************
3202  *
3203  * showFunc
3204  * 	used bycmdparse for show clis
3205  *
3206  * ****************************************************************************
3207  */
3208 /*ARGSUSED*/
3209 static int
3210 showFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
3211     void *addArgs)
3212 {
3213 	int 					ret = 0;
3214 
3215 	switch (object) {
3216 		case MPATH_SUPPORT:
3217 			ret = showMpathSupport(operandLen, operand);
3218 			break;
3219 		case LOGICAL_UNIT:
3220 			ret = showLogicalUnit(operandLen, operand);
3221 			break;
3222 		case INITIATOR_PORT:
3223 			ret = showInitiatorPort(operandLen, operand);
3224 			break;
3225 		default:
3226 			ret = 1;
3227 			break;
3228 	}
3229 
3230 	return (ret);
3231 }
3232 
3233 
3234 /*
3235  * ****************************************************************************
3236  *
3237  * modifyFunc
3238  * 	Used by cmdparse for midify clis
3239  *
3240  *
3241  * ****************************************************************************
3242  */
3243 /*ARGSUSED*/
3244 static int
3245 modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
3246     void *addArgs)
3247 {
3248 	int 					ret = 0;
3249 
3250 	switch (object) {
3251 		case MPATH_SUPPORT:
3252 			ret = modifyMpathSupport(operandLen, operand, options);
3253 			break;
3254 		case LOGICAL_UNIT:
3255 			ret = modifyLogicalUnit(operandLen, operand, options);
3256 			break;
3257 		default:
3258 			ret = 1;
3259 			break;
3260 	}
3261 
3262 
3263 	return (ret);
3264 }
3265 
3266 
3267 /*
3268  * ****************************************************************************
3269  *
3270  * enableFunc
3271  * 	Used by cmdpars for enable clis
3272  *
3273  * ****************************************************************************
3274  */
3275 /*ARGSUSED*/
3276 static int
3277 enableFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
3278     void *addArgs)
3279 {
3280 	int 					ret = 0;
3281 
3282 	switch (object) {
3283 		case PATH:
3284 			ret = enablePath(options);
3285 			break;
3286 		default:
3287 			ret = 1;
3288 			break;
3289 	}
3290 
3291 	return (ret);
3292 }
3293 
3294 
3295 /*
3296  * ****************************************************************************
3297  *
3298  * disableFunc
3299  * 	Used by cmdpars for disable clis
3300  *
3301  * ****************************************************************************
3302  */
3303 /*ARGSUSED*/
3304 static int
3305 disableFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
3306     void *addArgs)
3307 {
3308 	int 					ret = 0;
3309 
3310 	switch (object) {
3311 		case PATH:
3312 			ret = disablePath(options);
3313 			break;
3314 		default:
3315 			ret = 1;
3316 			break;
3317 	}
3318 
3319 	return (ret);
3320 }
3321 
3322 
3323 /*
3324  * ****************************************************************************
3325  *
3326  * failoverFunc
3327  * 	Used by cmdpars for failover clis
3328  *
3329  * ****************************************************************************
3330  */
3331 /*ARGSUSED*/
3332 static int
3333 failoverFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
3334     void *addArgs)
3335 {
3336 	int 					ret = 0;
3337 
3338 	switch (object) {
3339 		case LOGICAL_UNIT:
3340 			ret = failoverLogicalUnit(operand);
3341 			break;
3342 		default:
3343 			ret = 1;
3344 			break;
3345 	}
3346 
3347 	return (ret);
3348 }
3349 
3350 
3351 /*
3352  * ****************************************************************************
3353  *
3354  * overrideFunc
3355  * 	Used by cmdpars for override clis
3356  *
3357  * ****************************************************************************
3358  */
3359 /*ARGSUSED*/
3360 static int
3361 overrideFunc(int operandLen, char *operand[],
3362 	int object, cmdOptions_t *options,
3363     void *addArgs)
3364 {
3365 	int 					ret = 0;
3366 
3367 	switch (object) {
3368 		case PATH:
3369 			ret = overridePath(options);
3370 			break;
3371 		default:
3372 			ret = 1;
3373 			break;
3374 	}
3375 
3376 
3377 	return (ret);
3378 }
3379 
3380 
3381 /*
3382  * *************************************************************************
3383  *
3384  * main
3385  *
3386  * *************************************************************************
3387  */
3388 int
3389 main(int argc, char *argv[])
3390 {
3391 	synTables_t 			synTables;
3392 	char 				versionString[VERSION_STRING_MAX_LEN];
3393 	int 				ret;
3394 	int 				funcRet;
3395 	void 				*subcommandArgs = NULL;
3396 
3397 	/* set global command name */
3398 	cmdName = getExecBasename(argv[0]);
3399 
3400 	(void) sprintf(versionString, "%2s.%2s",
3401 	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
3402 	synTables.versionString = versionString;
3403 	synTables.longOptionTbl = &longOptions[0];
3404 	synTables.subcommandTbl = &subcommands[0];
3405 	synTables.objectTbl = &objects[0];
3406 	synTables.objectRulesTbl = &objectRules[0];
3407 	synTables.optionRulesTbl = &optionRules[0];
3408 
3409 	ret = cmdParse(argc, argv, /* SUB_COMMAND_ISSUED, */ synTables,
3410 	    subcommandArgs, &funcRet);
3411 	if (ret == 1) {
3412 		(void) fprintf(stdout, "%s %s(1M)\n",
3413 		    getTextString(TEXT_MORE_INFO), cmdName);
3414 		return (ERROR_CLI_FAILED);
3415 	} else if (ret == -1) {
3416 		perror(argv[0]);
3417 		return (1);
3418 	}
3419 
3420 	if (funcRet != 0) {
3421 		(void) fprintf(stderr, "%s: %s\n",
3422 		    argv[0], getTextString(TEXT_UNABLE_TO_COMPLETE));
3423 		return (1);
3424 	}
3425 	return (0);
3426 
3427 } /* end main */
3428