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