dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / cfgadm_plugins / fp / common / cfga_fp.c
blob6bb74889e7f8c5d2017632c8de88abeb594174ef
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include "cfga_fp.h"
29 * This file contains the entry points to the plug-in as defined in the
30 * config_admin(3X) man page.
34 * Set the version number
36 int cfga_version = CFGA_HSL_V2;
38 /*ARGSUSED*/
39 cfga_err_t
40 cfga_change_state(
41 cfga_cmd_t state_change_cmd,
42 const char *ap_id,
43 const char *options,
44 struct cfga_confirm *confp,
45 struct cfga_msg *msgp,
46 char **errstring,
47 cfga_flags_t flags)
49 apid_t apidt = {NULL};
50 fpcfga_ret_t ret;
51 la_wwn_t pwwn;
52 char *value, *hw_option, *hw_option_p;
53 char *fp_cs_hw_opts[] = {"disable_rcm", "force_update",
54 "no_update", "unusable_SCSI_LUN", "unusable_FCP_dev", NULL};
55 HBA_HANDLE handle;
56 HBA_PORTATTRIBUTES portAttrs;
57 int portIndex;
59 if (errstring != NULL) {
60 *errstring = NULL;
63 /* Check for super user priveleges */
64 if (geteuid() != 0) {
65 return (CFGA_PRIV);
68 /* Only configure and unconfigure operations are supported */
69 if (state_change_cmd != CFGA_CMD_CONFIGURE &&
70 state_change_cmd != CFGA_CMD_UNCONFIGURE) {
71 return (CFGA_OPNOTSUPP);
74 if ((ret = apidt_create(ap_id, &apidt, errstring)) != FPCFGA_OK) {
75 return (err_cvt(ret));
78 if (options != NULL) {
79 hw_option = calloc(1, strlen(options) + 1);
80 (void) snprintf(hw_option, strlen(options) + 1, "%s", options);
81 hw_option_p = hw_option;
82 /* Use getsubopt() if more options get added */
83 while (*hw_option_p != '\0') {
84 switch (getsubopt(&hw_option_p, fp_cs_hw_opts,
85 &value)) {
86 case OPT_DISABLE_RCM :
87 apidt.flags |= FLAG_DISABLE_RCM;
88 break;
89 case OPT_FORCE_UPDATE_REP :
90 apidt.flags |= FLAG_FORCE_UPDATE_REP;
91 break;
92 case OPT_NO_UPDATE_REP :
93 apidt.flags |= FLAG_NO_UPDATE_REP;
94 break;
95 case OPT_REMOVE_UNUSABLE_FCP_DEV :
96 case OPT_REMOVE_UNUSABLE_SCSI_LUN:
97 if (state_change_cmd != CFGA_CMD_UNCONFIGURE) {
98 cfga_err(errstring, 0, ERRARG_OPT_INVAL,
99 options, 0);
100 S_FREE(hw_option);
101 apidt_free(&apidt);
102 return (CFGA_ERROR);
104 apidt.flags |= FLAG_REMOVE_UNUSABLE_FCP_DEV;
105 break;
106 default :
107 /* process unknonw option. */
108 cfga_err(errstring, 0, ERRARG_OPT_INVAL,
109 options, 0);
110 S_FREE(hw_option);
111 apidt_free(&apidt);
112 return (CFGA_ERROR);
115 S_FREE(hw_option);
118 if (options != NULL && apidt.flags == 0) {
119 /* invalid option specified. */
120 cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
121 apidt_free(&apidt);
122 return (CFGA_ERROR);
125 if (apidt.dyncomp != NULL) { /* Was there a port WWN passed ? */
127 * Yes - so change state of the particular device
129 * First Get the WWN in la_wwn_t form
131 if (cvt_dyncomp_to_lawwn(apidt.dyncomp, &pwwn)) {
132 cfga_err(errstring, 0, ERR_APID_INVAL, 0);
133 return (err_cvt(FPCFGA_LIB_ERR));
136 if ((ret = findMatchingAdapterPort(apidt.xport_phys,
137 &handle, &portIndex, &portAttrs, errstring)) ==
138 FPCFGA_OK) {
139 ret = dev_change_state(state_change_cmd, &apidt, &pwwn,
140 flags, errstring, handle, portAttrs);
141 HBA_CloseAdapter(handle);
142 HBA_FreeLibrary();
144 } else {
145 /* Change state of all devices on FCA and the FCA itself */
146 ret = fca_change_state(state_change_cmd, &apidt,
147 flags, errstring);
150 apidt_free(&apidt);
151 return (err_cvt(ret));
155 /*ARGSUSED*/
156 cfga_err_t
157 cfga_private_func(
158 const char *func,
159 const char *ap_id,
160 const char *options,
161 struct cfga_confirm *confp,
162 struct cfga_msg *msgp,
163 char **errstring,
164 cfga_flags_t flags)
166 if (errstring != NULL) {
167 *errstring = NULL;
170 if (geteuid() != 0) {
171 return (CFGA_PRIV);
174 return (CFGA_OPNOTSUPP);
178 /*ARGSUSED*/
179 cfga_err_t
180 cfga_test(
181 const char *ap_id,
182 const char *options,
183 struct cfga_msg *msgp,
184 char **errstring,
185 cfga_flags_t flags)
187 if (errstring != NULL) {
188 *errstring = NULL;
191 if (geteuid() != 0) {
192 return (CFGA_PRIV);
195 return (CFGA_OPNOTSUPP);
199 /*ARGSUSED*/
200 cfga_err_t
201 cfga_list_ext(
202 const char *ap_id,
203 cfga_list_data_t **ap_id_list,
204 int *nlistp,
205 const char *options,
206 const char *listopts,
207 char **errstring,
208 cfga_flags_t flags)
210 int fca, expand, nelem;
211 ldata_list_t *ldatalistp = NULL;
212 apid_t apidt = {NULL};
213 fpcfga_cmd_t cmd;
214 fpcfga_ret_t ret;
215 char *value, *hw_option, *hw_option_p;
216 uint_t fp_flags = 0;
217 char *fp_list_hw_opts[] = {"devinfo_force", "show_SCSI_LUN",
218 "show_FCP_dev", NULL};
220 if (errstring != NULL) {
221 *errstring = NULL;
224 /* Check for super user privileges */
225 if (geteuid() != 0) {
226 return (CFGA_PRIV);
229 if (ap_id_list == NULL || nlistp == NULL) {
230 return (CFGA_ERROR);
233 *ap_id_list = NULL;
234 *nlistp = 0;
236 if (options != NULL) {
237 hw_option = calloc(1, strlen(options) + 1);
238 (void) snprintf(hw_option, strlen(options) + 1, "%s", options);
239 hw_option_p = hw_option;
240 /* Use getsubopt() if more options get added */
241 while (*hw_option_p != '\0') {
242 switch (getsubopt(&hw_option_p, fp_list_hw_opts,
243 &value)) {
244 case OPT_DEVINFO_FORCE :
245 fp_flags |= FLAG_DEVINFO_FORCE;
246 break;
247 case OPT_FCP_DEV :
248 case OPT_SHOW_SCSI_LUN:
249 fp_flags |= FLAG_FCP_DEV;
250 break;
251 default :
252 /* process unknonw option. */
253 cfga_err(errstring, 0, ERRARG_OPT_INVAL,
254 options, 0);
255 S_FREE(hw_option);
256 return (CFGA_ERROR);
259 S_FREE(hw_option);
262 /* if force_devinfo is specified check uid = 0 or not. */
263 if (((fp_flags & FLAG_DEVINFO_FORCE) == FLAG_DEVINFO_FORCE) &&
264 (geteuid() != 0)) {
265 return (CFGA_PRIV);
268 fca = 0;
269 if (GET_DYN(ap_id) == NULL) {
270 fca = 1;
273 expand = 0;
274 if ((flags & CFGA_FLAG_LIST_ALL) == CFGA_FLAG_LIST_ALL) {
275 expand = 1;
279 * We expand published attachment points but not
280 * dynamic attachment points
283 if (!fca) { /* Stat a single device - no expansion for devices */
284 cmd = FPCFGA_STAT_FC_DEV;
285 } else if (!expand) { /* Stat only the HBA */
286 cmd = FPCFGA_STAT_FCA_PORT;
287 } else { /* Expand HBA attachment point */
288 cmd = FPCFGA_STAT_ALL;
291 ldatalistp = NULL;
292 nelem = 0;
294 if ((fp_flags & FLAG_FCP_DEV) == FLAG_FCP_DEV) {
295 ret = do_list_FCP_dev(ap_id, fp_flags, cmd, &ldatalistp, &nelem,
296 errstring);
297 if (ret != FPCFGA_OK) {
298 list_free(&ldatalistp);
299 return (err_cvt(ret));
301 } else {
302 if ((ret = apidt_create(ap_id, &apidt, errstring))
303 != FPCFGA_OK) {
304 return (err_cvt(ret));
307 if (options != NULL) {
308 apidt.flags |= fp_flags;
311 ret = do_list(&apidt, cmd, &ldatalistp, &nelem, errstring);
312 if (ret != FPCFGA_OK) {
313 list_free(&ldatalistp);
314 apidt_free(&apidt);
315 return (err_cvt(ret));
317 apidt_free(&apidt);
320 assert(ldatalistp != NULL);
322 if (list_ext_postprocess(&ldatalistp, nelem, ap_id_list, nlistp,
323 errstring) != FPCFGA_OK) {
324 assert(*ap_id_list == NULL && *nlistp == 0);
325 ret = FPCFGA_LIB_ERR;
326 } else {
327 assert(*ap_id_list != NULL && *nlistp == nelem);
328 ret = FPCFGA_OK;
331 list_free(&ldatalistp);
332 return (err_cvt(ret));
336 /*ARGSUSED*/
337 cfga_err_t
338 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
340 cfga_msg(msgp, MSG_HELP_HDR, MSG_HELP_USAGE, 0);
342 return (CFGA_OK);
346 /*ARGSUSED*/
348 cfga_ap_id_cmp(const char *ap_id1, const char *ap_id2)
350 int i = 0;
351 long long ret;
353 if (ap_id1 == ap_id2) {
354 return (0);
357 if (ap_id1 == NULL || ap_id2 == NULL) {
358 if (ap_id1 == NULL) {
359 /* Return a negative value */
360 return (0 - (uchar_t)ap_id2[0]);
361 } else {
362 return ((uchar_t)ap_id1[0]);
367 * Search for first different char
369 while (ap_id1[i] == ap_id2[i] && ap_id1[i] != '\0')
370 i++;
372 if ((ap_id1[i] == '\0') &&
373 !(strncmp(&ap_id2[i], LUN_COMP_SEP, strlen(LUN_COMP_SEP)))) {
374 return (0);
375 } else if ((ap_id2[i] == '\0') &&
376 !(strncmp(&ap_id1[i], LUN_COMP_SEP, strlen(LUN_COMP_SEP)))) {
377 return (0);
381 * If one of the char is a digit, back up to where the
382 * number started, compare the number.
384 if (isxdigit(ap_id1[i]) || isxdigit(ap_id2[i])) {
385 while ((i > 0) && isxdigit(ap_id1[i - 1]))
386 i--;
388 if (isxdigit(ap_id1[i]) && isxdigit(ap_id2[i])) {
389 ret = (strtoll((ap_id1 + i), NULL, 16)) -
390 (strtoll((ap_id2 + i), NULL, 16));
391 if (ret > 0) {
392 return (1);
393 } else if (ret < 0) {
394 return (-1);
395 } else {
396 return (0);
401 /* One of them isn't a number, compare the char */
402 return (ap_id1[i] - ap_id2[i]);