xref: /onnv-gate/usr/src/lib/cfgadm_plugins/fp/common/cfga_fp.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM 
27*7836SJohn.Forte@Sun.COM 
28*7836SJohn.Forte@Sun.COM 
29*7836SJohn.Forte@Sun.COM #include "cfga_fp.h"
30*7836SJohn.Forte@Sun.COM 
31*7836SJohn.Forte@Sun.COM /*
32*7836SJohn.Forte@Sun.COM  * This file contains the entry points to the plug-in as defined in the
33*7836SJohn.Forte@Sun.COM  * config_admin(3X) man page.
34*7836SJohn.Forte@Sun.COM  */
35*7836SJohn.Forte@Sun.COM 
36*7836SJohn.Forte@Sun.COM /*
37*7836SJohn.Forte@Sun.COM  * Set the version number
38*7836SJohn.Forte@Sun.COM  */
39*7836SJohn.Forte@Sun.COM int cfga_version = CFGA_HSL_V2;
40*7836SJohn.Forte@Sun.COM 
41*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
42*7836SJohn.Forte@Sun.COM cfga_err_t
cfga_change_state(cfga_cmd_t state_change_cmd,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)43*7836SJohn.Forte@Sun.COM cfga_change_state(
44*7836SJohn.Forte@Sun.COM 	cfga_cmd_t state_change_cmd,
45*7836SJohn.Forte@Sun.COM 	const char *ap_id,
46*7836SJohn.Forte@Sun.COM 	const char *options,
47*7836SJohn.Forte@Sun.COM 	struct cfga_confirm *confp,
48*7836SJohn.Forte@Sun.COM 	struct cfga_msg *msgp,
49*7836SJohn.Forte@Sun.COM 	char **errstring,
50*7836SJohn.Forte@Sun.COM 	cfga_flags_t flags)
51*7836SJohn.Forte@Sun.COM {
52*7836SJohn.Forte@Sun.COM 	apid_t		apidt = {NULL};
53*7836SJohn.Forte@Sun.COM 	fpcfga_ret_t	ret;
54*7836SJohn.Forte@Sun.COM 	la_wwn_t	pwwn;
55*7836SJohn.Forte@Sun.COM 	char *value, *hw_option, *hw_option_p;
56*7836SJohn.Forte@Sun.COM 	char *fp_cs_hw_opts[] = {"disable_rcm", "force_update",
57*7836SJohn.Forte@Sun.COM 		"no_update", "unusable_SCSI_LUN", "unusable_FCP_dev", NULL};
58*7836SJohn.Forte@Sun.COM 	HBA_HANDLE	handle;
59*7836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES	portAttrs;
60*7836SJohn.Forte@Sun.COM 	int			portIndex;
61*7836SJohn.Forte@Sun.COM 
62*7836SJohn.Forte@Sun.COM 	if (errstring != NULL) {
63*7836SJohn.Forte@Sun.COM 		*errstring = NULL;
64*7836SJohn.Forte@Sun.COM 	}
65*7836SJohn.Forte@Sun.COM 
66*7836SJohn.Forte@Sun.COM 	/* Check for super user priveleges */
67*7836SJohn.Forte@Sun.COM 	if (geteuid() != 0) {
68*7836SJohn.Forte@Sun.COM 		return (CFGA_PRIV);
69*7836SJohn.Forte@Sun.COM 	}
70*7836SJohn.Forte@Sun.COM 
71*7836SJohn.Forte@Sun.COM 	/* Only configure and unconfigure operations are supported */
72*7836SJohn.Forte@Sun.COM 	if (state_change_cmd != CFGA_CMD_CONFIGURE &&
73*7836SJohn.Forte@Sun.COM 				state_change_cmd != CFGA_CMD_UNCONFIGURE) {
74*7836SJohn.Forte@Sun.COM 		return (CFGA_OPNOTSUPP);
75*7836SJohn.Forte@Sun.COM 	}
76*7836SJohn.Forte@Sun.COM 
77*7836SJohn.Forte@Sun.COM 	if ((ret = apidt_create(ap_id, &apidt, errstring)) != CFGA_OK) {
78*7836SJohn.Forte@Sun.COM 		return (err_cvt(ret));
79*7836SJohn.Forte@Sun.COM 	}
80*7836SJohn.Forte@Sun.COM 
81*7836SJohn.Forte@Sun.COM 	if (options != NULL) {
82*7836SJohn.Forte@Sun.COM 		hw_option = calloc(1, strlen(options) + 1);
83*7836SJohn.Forte@Sun.COM 		(void) snprintf(hw_option, strlen(options) + 1, "%s", options);
84*7836SJohn.Forte@Sun.COM 		hw_option_p = hw_option;
85*7836SJohn.Forte@Sun.COM 		/* Use getsubopt() if more options get added */
86*7836SJohn.Forte@Sun.COM 		while (*hw_option_p != '\0') {
87*7836SJohn.Forte@Sun.COM 		    switch (getsubopt(&hw_option_p, fp_cs_hw_opts, &value)) {
88*7836SJohn.Forte@Sun.COM 			case OPT_DISABLE_RCM :
89*7836SJohn.Forte@Sun.COM 				apidt.flags |= FLAG_DISABLE_RCM;
90*7836SJohn.Forte@Sun.COM 				break;
91*7836SJohn.Forte@Sun.COM 			case OPT_FORCE_UPDATE_REP :
92*7836SJohn.Forte@Sun.COM 				apidt.flags |= FLAG_FORCE_UPDATE_REP;
93*7836SJohn.Forte@Sun.COM 				break;
94*7836SJohn.Forte@Sun.COM 			case OPT_NO_UPDATE_REP :
95*7836SJohn.Forte@Sun.COM 				apidt.flags |= FLAG_NO_UPDATE_REP;
96*7836SJohn.Forte@Sun.COM 				break;
97*7836SJohn.Forte@Sun.COM 			case OPT_REMOVE_UNUSABLE_FCP_DEV :
98*7836SJohn.Forte@Sun.COM 			case OPT_REMOVE_UNUSABLE_SCSI_LUN:
99*7836SJohn.Forte@Sun.COM 				if (state_change_cmd != CFGA_CMD_UNCONFIGURE) {
100*7836SJohn.Forte@Sun.COM 					cfga_err(errstring, 0, ERRARG_OPT_INVAL,
101*7836SJohn.Forte@Sun.COM 						options, 0);
102*7836SJohn.Forte@Sun.COM 					S_FREE(hw_option);
103*7836SJohn.Forte@Sun.COM 					apidt_free(&apidt);
104*7836SJohn.Forte@Sun.COM 					return (CFGA_ERROR);
105*7836SJohn.Forte@Sun.COM 				}
106*7836SJohn.Forte@Sun.COM 				apidt.flags |= FLAG_REMOVE_UNUSABLE_FCP_DEV;
107*7836SJohn.Forte@Sun.COM 				break;
108*7836SJohn.Forte@Sun.COM 			default :
109*7836SJohn.Forte@Sun.COM 				/* process unknonw option. */
110*7836SJohn.Forte@Sun.COM 				cfga_err(errstring, 0, ERRARG_OPT_INVAL,
111*7836SJohn.Forte@Sun.COM 					options, 0);
112*7836SJohn.Forte@Sun.COM 				S_FREE(hw_option);
113*7836SJohn.Forte@Sun.COM 				apidt_free(&apidt);
114*7836SJohn.Forte@Sun.COM 				return (CFGA_ERROR);
115*7836SJohn.Forte@Sun.COM 		    }
116*7836SJohn.Forte@Sun.COM 		}
117*7836SJohn.Forte@Sun.COM 		S_FREE(hw_option);
118*7836SJohn.Forte@Sun.COM 	}
119*7836SJohn.Forte@Sun.COM 
120*7836SJohn.Forte@Sun.COM 	if (options != NULL && apidt.flags == 0) {
121*7836SJohn.Forte@Sun.COM 		/* invalid option specified. */
122*7836SJohn.Forte@Sun.COM 		cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
123*7836SJohn.Forte@Sun.COM 		apidt_free(&apidt);
124*7836SJohn.Forte@Sun.COM 		return (CFGA_ERROR);
125*7836SJohn.Forte@Sun.COM 	}
126*7836SJohn.Forte@Sun.COM 
127*7836SJohn.Forte@Sun.COM 	if (apidt.dyncomp != NULL) {	/* Was there a port WWN passed ? */
128*7836SJohn.Forte@Sun.COM 		/*
129*7836SJohn.Forte@Sun.COM 		 * Yes - so change state of the particular device
130*7836SJohn.Forte@Sun.COM 		 *
131*7836SJohn.Forte@Sun.COM 		 * First Get the WWN in la_wwn_t form
132*7836SJohn.Forte@Sun.COM 		 */
133*7836SJohn.Forte@Sun.COM 		if (cvt_dyncomp_to_lawwn(apidt.dyncomp, &pwwn)) {
134*7836SJohn.Forte@Sun.COM 			cfga_err(errstring, 0, ERR_APID_INVAL, 0);
135*7836SJohn.Forte@Sun.COM 			return (err_cvt(FPCFGA_LIB_ERR));
136*7836SJohn.Forte@Sun.COM 		}
137*7836SJohn.Forte@Sun.COM 
138*7836SJohn.Forte@Sun.COM 		if ((ret = findMatchingAdapterPort(apidt.xport_phys,
139*7836SJohn.Forte@Sun.COM 		    &handle, &portIndex, &portAttrs, errstring)) ==
140*7836SJohn.Forte@Sun.COM 		    FPCFGA_OK) {
141*7836SJohn.Forte@Sun.COM 		    ret = dev_change_state(state_change_cmd, &apidt, &pwwn,
142*7836SJohn.Forte@Sun.COM 				flags, errstring, handle, portAttrs);
143*7836SJohn.Forte@Sun.COM 		    HBA_CloseAdapter(handle);
144*7836SJohn.Forte@Sun.COM 		    HBA_FreeLibrary();
145*7836SJohn.Forte@Sun.COM 		}
146*7836SJohn.Forte@Sun.COM 	} else {
147*7836SJohn.Forte@Sun.COM 		/* Change state of all devices on FCA and the FCA itself */
148*7836SJohn.Forte@Sun.COM 		ret = fca_change_state(state_change_cmd, &apidt,
149*7836SJohn.Forte@Sun.COM 							flags, errstring);
150*7836SJohn.Forte@Sun.COM 	}
151*7836SJohn.Forte@Sun.COM 
152*7836SJohn.Forte@Sun.COM 	apidt_free(&apidt);
153*7836SJohn.Forte@Sun.COM 	return (err_cvt(ret));
154*7836SJohn.Forte@Sun.COM }
155*7836SJohn.Forte@Sun.COM 
156*7836SJohn.Forte@Sun.COM 
157*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
158*7836SJohn.Forte@Sun.COM cfga_err_t
cfga_private_func(const char * func,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)159*7836SJohn.Forte@Sun.COM cfga_private_func(
160*7836SJohn.Forte@Sun.COM 	const char *func,
161*7836SJohn.Forte@Sun.COM 	const char *ap_id,
162*7836SJohn.Forte@Sun.COM 	const char *options,
163*7836SJohn.Forte@Sun.COM 	struct cfga_confirm *confp,
164*7836SJohn.Forte@Sun.COM 	struct cfga_msg *msgp,
165*7836SJohn.Forte@Sun.COM 	char **errstring,
166*7836SJohn.Forte@Sun.COM 	cfga_flags_t flags)
167*7836SJohn.Forte@Sun.COM {
168*7836SJohn.Forte@Sun.COM 	if (errstring != NULL) {
169*7836SJohn.Forte@Sun.COM 		*errstring = NULL;
170*7836SJohn.Forte@Sun.COM 	}
171*7836SJohn.Forte@Sun.COM 
172*7836SJohn.Forte@Sun.COM 	if (geteuid() != 0) {
173*7836SJohn.Forte@Sun.COM 		return (CFGA_PRIV);
174*7836SJohn.Forte@Sun.COM 	}
175*7836SJohn.Forte@Sun.COM 
176*7836SJohn.Forte@Sun.COM 	return (CFGA_OPNOTSUPP);
177*7836SJohn.Forte@Sun.COM }
178*7836SJohn.Forte@Sun.COM 
179*7836SJohn.Forte@Sun.COM 
180*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
181*7836SJohn.Forte@Sun.COM cfga_err_t
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)182*7836SJohn.Forte@Sun.COM cfga_test(
183*7836SJohn.Forte@Sun.COM 	const char *ap_id,
184*7836SJohn.Forte@Sun.COM 	const char *options,
185*7836SJohn.Forte@Sun.COM 	struct cfga_msg *msgp,
186*7836SJohn.Forte@Sun.COM 	char **errstring,
187*7836SJohn.Forte@Sun.COM 	cfga_flags_t flags)
188*7836SJohn.Forte@Sun.COM {
189*7836SJohn.Forte@Sun.COM 	if (errstring != NULL) {
190*7836SJohn.Forte@Sun.COM 		*errstring = NULL;
191*7836SJohn.Forte@Sun.COM 	}
192*7836SJohn.Forte@Sun.COM 
193*7836SJohn.Forte@Sun.COM 	if (geteuid() != 0) {
194*7836SJohn.Forte@Sun.COM 		return (CFGA_PRIV);
195*7836SJohn.Forte@Sun.COM 	}
196*7836SJohn.Forte@Sun.COM 
197*7836SJohn.Forte@Sun.COM 	return (CFGA_OPNOTSUPP);
198*7836SJohn.Forte@Sun.COM }
199*7836SJohn.Forte@Sun.COM 
200*7836SJohn.Forte@Sun.COM 
201*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
202*7836SJohn.Forte@Sun.COM cfga_err_t
cfga_list_ext(const char * ap_id,cfga_list_data_t ** ap_id_list,int * nlistp,const char * options,const char * listopts,char ** errstring,cfga_flags_t flags)203*7836SJohn.Forte@Sun.COM cfga_list_ext(
204*7836SJohn.Forte@Sun.COM 	const char *ap_id,
205*7836SJohn.Forte@Sun.COM 	cfga_list_data_t **ap_id_list,
206*7836SJohn.Forte@Sun.COM 	int *nlistp,
207*7836SJohn.Forte@Sun.COM 	const char *options,
208*7836SJohn.Forte@Sun.COM 	const char *listopts,
209*7836SJohn.Forte@Sun.COM 	char **errstring,
210*7836SJohn.Forte@Sun.COM 	cfga_flags_t flags)
211*7836SJohn.Forte@Sun.COM {
212*7836SJohn.Forte@Sun.COM 	int fca, expand, nelem;
213*7836SJohn.Forte@Sun.COM 	ldata_list_t *ldatalistp = NULL;
214*7836SJohn.Forte@Sun.COM 	apid_t apidt = {NULL};
215*7836SJohn.Forte@Sun.COM 	fpcfga_cmd_t cmd;
216*7836SJohn.Forte@Sun.COM 	fpcfga_ret_t ret;
217*7836SJohn.Forte@Sun.COM 	char *value, *hw_option, *hw_option_p;
218*7836SJohn.Forte@Sun.COM 	uint_t fp_flags = 0;
219*7836SJohn.Forte@Sun.COM 	char *fp_list_hw_opts[] = {"devinfo_force", "show_SCSI_LUN",
220*7836SJohn.Forte@Sun.COM 		"show_FCP_dev", NULL};
221*7836SJohn.Forte@Sun.COM 
222*7836SJohn.Forte@Sun.COM 	if (errstring != NULL) {
223*7836SJohn.Forte@Sun.COM 		*errstring = NULL;
224*7836SJohn.Forte@Sun.COM 	}
225*7836SJohn.Forte@Sun.COM 
226*7836SJohn.Forte@Sun.COM 	/* Check for super user privileges */
227*7836SJohn.Forte@Sun.COM 	if (geteuid() != 0) {
228*7836SJohn.Forte@Sun.COM 		return (CFGA_PRIV);
229*7836SJohn.Forte@Sun.COM 	}
230*7836SJohn.Forte@Sun.COM 
231*7836SJohn.Forte@Sun.COM 	if (ap_id_list == NULL || nlistp == NULL) {
232*7836SJohn.Forte@Sun.COM 		return (CFGA_ERROR);
233*7836SJohn.Forte@Sun.COM 	}
234*7836SJohn.Forte@Sun.COM 
235*7836SJohn.Forte@Sun.COM 	*ap_id_list = NULL;
236*7836SJohn.Forte@Sun.COM 	*nlistp = 0;
237*7836SJohn.Forte@Sun.COM 
238*7836SJohn.Forte@Sun.COM 	if (options != NULL) {
239*7836SJohn.Forte@Sun.COM 		hw_option = calloc(1, strlen(options) + 1);
240*7836SJohn.Forte@Sun.COM 		(void) snprintf(hw_option, strlen(options) + 1, "%s", options);
241*7836SJohn.Forte@Sun.COM 		hw_option_p = hw_option;
242*7836SJohn.Forte@Sun.COM 		/* Use getsubopt() if more options get added */
243*7836SJohn.Forte@Sun.COM 		while (*hw_option_p != '\0') {
244*7836SJohn.Forte@Sun.COM 		    switch (getsubopt(&hw_option_p, fp_list_hw_opts, &value)) {
245*7836SJohn.Forte@Sun.COM 			case OPT_DEVINFO_FORCE :
246*7836SJohn.Forte@Sun.COM 				fp_flags |= FLAG_DEVINFO_FORCE;
247*7836SJohn.Forte@Sun.COM 				break;
248*7836SJohn.Forte@Sun.COM 			case OPT_FCP_DEV :
249*7836SJohn.Forte@Sun.COM 			case OPT_SHOW_SCSI_LUN:
250*7836SJohn.Forte@Sun.COM 				fp_flags |= FLAG_FCP_DEV;
251*7836SJohn.Forte@Sun.COM 				break;
252*7836SJohn.Forte@Sun.COM 			default :
253*7836SJohn.Forte@Sun.COM 				/* process unknonw option. */
254*7836SJohn.Forte@Sun.COM 				cfga_err(errstring, 0, ERRARG_OPT_INVAL,
255*7836SJohn.Forte@Sun.COM 					options, 0);
256*7836SJohn.Forte@Sun.COM 				S_FREE(hw_option);
257*7836SJohn.Forte@Sun.COM 			return (CFGA_ERROR);
258*7836SJohn.Forte@Sun.COM 		    }
259*7836SJohn.Forte@Sun.COM 		}
260*7836SJohn.Forte@Sun.COM 		S_FREE(hw_option);
261*7836SJohn.Forte@Sun.COM 	}
262*7836SJohn.Forte@Sun.COM 
263*7836SJohn.Forte@Sun.COM 	/* if force_devinfo is specified check uid = 0 or not. */
264*7836SJohn.Forte@Sun.COM 	if (((fp_flags & FLAG_DEVINFO_FORCE) == FLAG_DEVINFO_FORCE) &&
265*7836SJohn.Forte@Sun.COM 			(geteuid() != 0)) {
266*7836SJohn.Forte@Sun.COM 		return (CFGA_PRIV);
267*7836SJohn.Forte@Sun.COM 	}
268*7836SJohn.Forte@Sun.COM 
269*7836SJohn.Forte@Sun.COM 	fca = 0;
270*7836SJohn.Forte@Sun.COM 	if (GET_DYN(ap_id) == NULL) {
271*7836SJohn.Forte@Sun.COM 		fca = 1;
272*7836SJohn.Forte@Sun.COM 	}
273*7836SJohn.Forte@Sun.COM 
274*7836SJohn.Forte@Sun.COM 	expand = 0;
275*7836SJohn.Forte@Sun.COM 	if ((flags & CFGA_FLAG_LIST_ALL) == CFGA_FLAG_LIST_ALL) {
276*7836SJohn.Forte@Sun.COM 		expand = 1;
277*7836SJohn.Forte@Sun.COM 	}
278*7836SJohn.Forte@Sun.COM 
279*7836SJohn.Forte@Sun.COM 	/*
280*7836SJohn.Forte@Sun.COM 	 * We expand published attachment points but not
281*7836SJohn.Forte@Sun.COM 	 * dynamic attachment points
282*7836SJohn.Forte@Sun.COM 	 */
283*7836SJohn.Forte@Sun.COM 
284*7836SJohn.Forte@Sun.COM 	if (!fca) { /* Stat a single device - no expansion for devices */
285*7836SJohn.Forte@Sun.COM 		cmd = FPCFGA_STAT_FC_DEV;
286*7836SJohn.Forte@Sun.COM 	} else if (!expand) { /* Stat only the HBA */
287*7836SJohn.Forte@Sun.COM 		cmd = FPCFGA_STAT_FCA_PORT;
288*7836SJohn.Forte@Sun.COM 	} else { /* Expand HBA attachment point */
289*7836SJohn.Forte@Sun.COM 		cmd = FPCFGA_STAT_ALL;
290*7836SJohn.Forte@Sun.COM 	}
291*7836SJohn.Forte@Sun.COM 
292*7836SJohn.Forte@Sun.COM 	ldatalistp = NULL;
293*7836SJohn.Forte@Sun.COM 	nelem = 0;
294*7836SJohn.Forte@Sun.COM 
295*7836SJohn.Forte@Sun.COM 	if ((fp_flags & FLAG_FCP_DEV) == FLAG_FCP_DEV) {
296*7836SJohn.Forte@Sun.COM 		ret = do_list_FCP_dev(ap_id, fp_flags, cmd, &ldatalistp, &nelem,
297*7836SJohn.Forte@Sun.COM 			errstring);
298*7836SJohn.Forte@Sun.COM 		if (ret != FPCFGA_OK) {
299*7836SJohn.Forte@Sun.COM 			list_free(&ldatalistp);
300*7836SJohn.Forte@Sun.COM 			return (err_cvt(ret));
301*7836SJohn.Forte@Sun.COM 		}
302*7836SJohn.Forte@Sun.COM 	} else {
303*7836SJohn.Forte@Sun.COM 		if ((ret = apidt_create(ap_id, &apidt, errstring))
304*7836SJohn.Forte@Sun.COM 				!= FPCFGA_OK) {
305*7836SJohn.Forte@Sun.COM 			return (err_cvt(ret));
306*7836SJohn.Forte@Sun.COM 		}
307*7836SJohn.Forte@Sun.COM 
308*7836SJohn.Forte@Sun.COM 		if (options != NULL) {
309*7836SJohn.Forte@Sun.COM 			apidt.flags |= fp_flags;
310*7836SJohn.Forte@Sun.COM 		}
311*7836SJohn.Forte@Sun.COM 
312*7836SJohn.Forte@Sun.COM 		ret = do_list(&apidt, cmd, &ldatalistp, &nelem, errstring);
313*7836SJohn.Forte@Sun.COM 		if (ret != FPCFGA_OK) {
314*7836SJohn.Forte@Sun.COM 			list_free(&ldatalistp);
315*7836SJohn.Forte@Sun.COM 			apidt_free(&apidt);
316*7836SJohn.Forte@Sun.COM 			return (err_cvt(ret));
317*7836SJohn.Forte@Sun.COM 		}
318*7836SJohn.Forte@Sun.COM 		apidt_free(&apidt);
319*7836SJohn.Forte@Sun.COM 	}
320*7836SJohn.Forte@Sun.COM 
321*7836SJohn.Forte@Sun.COM 	assert(ldatalistp != NULL);
322*7836SJohn.Forte@Sun.COM 
323*7836SJohn.Forte@Sun.COM 	if (list_ext_postprocess(&ldatalistp, nelem, ap_id_list, nlistp,
324*7836SJohn.Forte@Sun.COM 	    errstring) != FPCFGA_OK) {
325*7836SJohn.Forte@Sun.COM 		assert(*ap_id_list == NULL && *nlistp == 0);
326*7836SJohn.Forte@Sun.COM 		ret = FPCFGA_LIB_ERR;
327*7836SJohn.Forte@Sun.COM 	} else {
328*7836SJohn.Forte@Sun.COM 		assert(*ap_id_list != NULL && *nlistp == nelem);
329*7836SJohn.Forte@Sun.COM 		ret = FPCFGA_OK;
330*7836SJohn.Forte@Sun.COM 	}
331*7836SJohn.Forte@Sun.COM 
332*7836SJohn.Forte@Sun.COM 	list_free(&ldatalistp);
333*7836SJohn.Forte@Sun.COM 	return (err_cvt(ret));
334*7836SJohn.Forte@Sun.COM }
335*7836SJohn.Forte@Sun.COM 
336*7836SJohn.Forte@Sun.COM 
337*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
338*7836SJohn.Forte@Sun.COM cfga_err_t
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)339*7836SJohn.Forte@Sun.COM cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
340*7836SJohn.Forte@Sun.COM {
341*7836SJohn.Forte@Sun.COM 	cfga_msg(msgp, MSG_HELP_HDR, MSG_HELP_USAGE, 0);
342*7836SJohn.Forte@Sun.COM 
343*7836SJohn.Forte@Sun.COM 	return (CFGA_OK);
344*7836SJohn.Forte@Sun.COM 
345*7836SJohn.Forte@Sun.COM }
346*7836SJohn.Forte@Sun.COM 
347*7836SJohn.Forte@Sun.COM /*ARGSUSED*/
348*7836SJohn.Forte@Sun.COM int
cfga_ap_id_cmp(const char * ap_id1,const char * ap_id2)349*7836SJohn.Forte@Sun.COM cfga_ap_id_cmp(const char *ap_id1, const char *ap_id2)
350*7836SJohn.Forte@Sun.COM {
351*7836SJohn.Forte@Sun.COM 	int i = 0;
352*7836SJohn.Forte@Sun.COM 	long long ret;
353*7836SJohn.Forte@Sun.COM 
354*7836SJohn.Forte@Sun.COM 	if (ap_id1 == ap_id2) {
355*7836SJohn.Forte@Sun.COM 		return (0);
356*7836SJohn.Forte@Sun.COM 	}
357*7836SJohn.Forte@Sun.COM 
358*7836SJohn.Forte@Sun.COM 	if (ap_id1 == NULL || ap_id2 == NULL) {
359*7836SJohn.Forte@Sun.COM 		if (ap_id1 == NULL) {
360*7836SJohn.Forte@Sun.COM 			/* Return a negative value */
361*7836SJohn.Forte@Sun.COM 			return (0 - (uchar_t)ap_id2[0]);
362*7836SJohn.Forte@Sun.COM 		} else {
363*7836SJohn.Forte@Sun.COM 			return ((uchar_t)ap_id1[0]);
364*7836SJohn.Forte@Sun.COM 		}
365*7836SJohn.Forte@Sun.COM 	}
366*7836SJohn.Forte@Sun.COM 
367*7836SJohn.Forte@Sun.COM 	/*
368*7836SJohn.Forte@Sun.COM 	 * Search for first different char
369*7836SJohn.Forte@Sun.COM 	 */
370*7836SJohn.Forte@Sun.COM 	while (ap_id1[i] == ap_id2[i] && ap_id1[i] != '\0')
371*7836SJohn.Forte@Sun.COM 		i++;
372*7836SJohn.Forte@Sun.COM 
373*7836SJohn.Forte@Sun.COM 	if ((ap_id1[i] == '\0') &&
374*7836SJohn.Forte@Sun.COM 		!(strncmp(&ap_id2[i], LUN_COMP_SEP, strlen(LUN_COMP_SEP)))) {
375*7836SJohn.Forte@Sun.COM 		return (0);
376*7836SJohn.Forte@Sun.COM 	} else if ((ap_id2[i] == '\0') &&
377*7836SJohn.Forte@Sun.COM 		!(strncmp(&ap_id1[i], LUN_COMP_SEP, strlen(LUN_COMP_SEP)))) {
378*7836SJohn.Forte@Sun.COM 		return (0);
379*7836SJohn.Forte@Sun.COM 	}
380*7836SJohn.Forte@Sun.COM 
381*7836SJohn.Forte@Sun.COM 	/*
382*7836SJohn.Forte@Sun.COM 	 * If one of the char is a digit, back up to where the
383*7836SJohn.Forte@Sun.COM 	 * number started, compare the number.
384*7836SJohn.Forte@Sun.COM 	 */
385*7836SJohn.Forte@Sun.COM 	if (isxdigit(ap_id1[i]) || isxdigit(ap_id2[i])) {
386*7836SJohn.Forte@Sun.COM 		while ((i > 0) && isxdigit(ap_id1[i - 1]))
387*7836SJohn.Forte@Sun.COM 			i--;
388*7836SJohn.Forte@Sun.COM 
389*7836SJohn.Forte@Sun.COM 		if (isxdigit(ap_id1[i]) && isxdigit(ap_id2[i])) {
390*7836SJohn.Forte@Sun.COM 			ret = (strtoll((ap_id1 + i), NULL, 16)) -
391*7836SJohn.Forte@Sun.COM 				(strtoll((ap_id2 + i), NULL, 16));
392*7836SJohn.Forte@Sun.COM 			if (ret > 0) {
393*7836SJohn.Forte@Sun.COM 				return (1);
394*7836SJohn.Forte@Sun.COM 			} else if (ret < 0) {
395*7836SJohn.Forte@Sun.COM 				return (-1);
396*7836SJohn.Forte@Sun.COM 			} else {
397*7836SJohn.Forte@Sun.COM 				return (0);
398*7836SJohn.Forte@Sun.COM 			}
399*7836SJohn.Forte@Sun.COM 		}
400*7836SJohn.Forte@Sun.COM 	}
401*7836SJohn.Forte@Sun.COM 
402*7836SJohn.Forte@Sun.COM 	/* One of them isn't a number, compare the char */
403*7836SJohn.Forte@Sun.COM 	return (ap_id1[i] - ap_id2[i]);
404*7836SJohn.Forte@Sun.COM }
405