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