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 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 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 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 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 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 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