1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include "cfga_scsi.h"
27
28 /*
29 * This file contains the entry points to the plug-in as defined in the
30 * config_admin(3CFGADM) man page.
31 */
32
33 /*
34 * Set the version number
35 */
36 int cfga_version = CFGA_HSL_V2;
37
38 /*
39 * For debugging - higher values increase verbosity
40 */
41 int _scfga_debug = 0;
42
43 #pragma init(_cfgadm_scsi_init)
44
45 static void
_cfgadm_scsi_init()46 _cfgadm_scsi_init()
47 {
48 char *tstr;
49
50 if (tstr = getenv("SCFGA_DEBUG")) {
51 _scfga_debug = atoi(tstr);
52 }
53 }
54
55 /*ARGSUSED*/
56 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)57 cfga_change_state(
58 cfga_cmd_t state_change_cmd,
59 const char *ap_id,
60 const char *options,
61 struct cfga_confirm *confp,
62 struct cfga_msg *msgp,
63 char **errstring,
64 cfga_flags_t flags)
65 {
66 apid_t apidt = {NULL};
67 scfga_ret_t ret;
68
69 if (errstring != NULL) {
70 *errstring = NULL;
71 }
72
73 /*
74 * All sub-commands which can change state of device require
75 * root privileges.
76 */
77 if (geteuid() != 0) {
78 return (CFGA_PRIV);
79 }
80
81 if (options != NULL && strcmp(options, OPT_DISABLE_RCM) != 0) {
82 cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
83 return (CFGA_ERROR);
84 }
85
86 if ((ret = apidt_create(ap_id, &apidt, errstring)) != SCFGA_OK) {
87 return (err_cvt(ret));
88 }
89
90 if (options != NULL)
91 apidt.flags |= FLAG_DISABLE_RCM;
92
93 /* A dynamic component indicates a device, else it is the bus */
94 if (apidt.dyncomp != NULL) {
95 ret = dev_change_state(state_change_cmd, &apidt, flags,
96 errstring);
97 } else {
98 ret = bus_change_state(state_change_cmd, &apidt, confp, flags,
99 errstring);
100 }
101
102 apidt_free(&apidt);
103 return (err_cvt(ret));
104 }
105
106 /*ARGSUSED*/
107 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)108 cfga_private_func(
109 const char *func,
110 const char *ap_id,
111 const char *options,
112 struct cfga_confirm *confp,
113 struct cfga_msg *msgp,
114 char **errstring,
115 cfga_flags_t flags)
116 {
117 apid_t apidt = {NULL};
118 prompt_t args = {NULL};
119 scfga_ret_t ret;
120
121 if (errstring != NULL)
122 *errstring = NULL;
123
124 if (geteuid() != 0) {
125 return (CFGA_PRIV);
126 }
127
128 if (func == NULL) {
129 return (CFGA_ERROR);
130 }
131
132 if (options != NULL && strcmp(options, OPT_DISABLE_RCM) != 0) {
133 cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
134 return (CFGA_ERROR);
135 }
136
137 if ((ret = apidt_create(ap_id, &apidt, errstring)) != SCFGA_OK) {
138 return (err_cvt(ret));
139 }
140
141 if (apidt.dyntype == PATH_APID) {
142 return (CFGA_OPNOTSUPP);
143 }
144
145 if (options != NULL)
146 apidt.flags |= FLAG_DISABLE_RCM;
147
148 args.confp = confp;
149 args.msgp = msgp;
150
151 /*
152 * Process command
153 */
154 ret = invoke_cmd(func, &apidt, &args, flags, errstring);
155
156 apidt_free(&apidt);
157 return (err_cvt(ret));
158 }
159
160 /*ARGSUSED*/
161 cfga_err_t
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)162 cfga_test(
163 const char *ap_id,
164 const char *options,
165 struct cfga_msg *msgp,
166 char **errstring,
167 cfga_flags_t flags)
168 {
169 if (errstring != NULL) {
170 *errstring = NULL;
171 }
172
173 if (geteuid() != 0) {
174 return (CFGA_PRIV);
175 }
176
177 return (CFGA_OPNOTSUPP);
178 }
179
180 /*ARGSUSED*/
181 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)182 cfga_list_ext(
183 const char *ap_id,
184 cfga_list_data_t **ap_id_list,
185 int *nlistp,
186 const char *options,
187 const char *listopts,
188 char **errstring,
189 cfga_flags_t flags)
190 {
191 int hba, expand, nelem;
192 ldata_list_t *llp = NULL;
193 apid_t apidt = {NULL};
194 scfga_cmd_t cmd;
195 scfga_ret_t ret;
196
197 if (errstring != NULL) {
198 *errstring = NULL;
199 }
200
201 if (ap_id_list == NULL || nlistp == NULL) {
202 return (CFGA_ERROR);
203 }
204
205 *ap_id_list = NULL;
206 *nlistp = 0;
207
208 /*
209 * There is no RCM involvement in "list" operations.
210 * The only supported option is OPT_USE_DIFORCE.
211 */
212 if (options != NULL && strcmp(options, OPT_USE_DIFORCE) != 0) {
213 cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
214 return (CFGA_ERROR);
215 }
216
217 hba = 0;
218 if (GET_DYN(ap_id) == NULL) {
219 hba = 1;
220 }
221
222 expand = 0;
223 if ((flags & CFGA_FLAG_LIST_ALL) == CFGA_FLAG_LIST_ALL) {
224 expand = 1;
225 }
226
227 /*
228 * We expand published attachment points but not
229 * dynamic attachment points
230 */
231
232 if (!hba) { /* Stat a single device - no expansion for devices */
233 cmd = SCFGA_STAT_DEV;
234 } else if (!expand) { /* Stat only the HBA */
235 cmd = SCFGA_STAT_BUS;
236 } else { /* Expand HBA attachment point */
237 cmd = SCFGA_STAT_ALL;
238 }
239
240 if ((ret = apidt_create(ap_id, &apidt, errstring)) != SCFGA_OK) {
241 return (err_cvt(ret));
242 }
243
244 /*
245 * Currently only 1 option supported
246 */
247 if (options)
248 apidt.flags |= FLAG_USE_DIFORCE;
249
250 llp = NULL;
251 nelem = 0;
252
253 ret = do_list(&apidt, cmd, &llp, &nelem, errstring);
254 if (ret != SCFGA_OK) {
255 goto out;
256 }
257
258 assert(llp != NULL);
259
260 if (list_ext_postprocess(&llp, nelem, ap_id_list, nlistp,
261 errstring) != SCFGA_OK) {
262 assert(*ap_id_list == NULL && *nlistp == 0);
263 ret = SCFGA_LIB_ERR;
264 } else {
265 assert(*ap_id_list != NULL && *nlistp == nelem);
266 ret = SCFGA_OK;
267 }
268
269 /* FALLTHROUGH */
270 out:
271 list_free(&llp);
272 apidt_free(&apidt);
273 return (err_cvt(ret));
274 }
275
276
277 /*ARGSUSED*/
278 cfga_err_t
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)279 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
280 {
281 cfga_msg(msgp, MSG_HELP_HDR, MSG_HELP_USAGE, 0);
282
283 return (CFGA_OK);
284 }
285
286 /*
287 * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm
288 */
289