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