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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 30 #include "cfga_scsi.h" 31 32 /* 33 * This file contains the entry points to the plug-in as defined in the 34 * config_admin(3X) man page. 35 */ 36 37 /* 38 * Set the version number 39 */ 40 int cfga_version = CFGA_HSL_V2; 41 42 /* 43 * For debugging - higher values increase verbosity 44 */ 45 int _scfga_debug = 0; 46 47 #pragma init(_cfgadm_scsi_init) 48 49 static void 50 _cfgadm_scsi_init() 51 { 52 char *tstr; 53 54 if (tstr = getenv("SCFGA_DEBUG")) { 55 _scfga_debug = atoi(tstr); 56 } 57 } 58 59 /*ARGSUSED*/ 60 cfga_err_t 61 cfga_change_state( 62 cfga_cmd_t state_change_cmd, 63 const char *ap_id, 64 const char *options, 65 struct cfga_confirm *confp, 66 struct cfga_msg *msgp, 67 char **errstring, 68 cfga_flags_t flags) 69 { 70 apid_t apidt = {NULL}; 71 scfga_ret_t ret; 72 73 if (errstring != NULL) { 74 *errstring = NULL; 75 } 76 77 /* 78 * All sub-commands which can change state of device require 79 * root privileges. 80 */ 81 if (geteuid() != 0) { 82 return (CFGA_PRIV); 83 } 84 85 if (options != NULL && strcmp(options, OPT_DISABLE_RCM) != 0) { 86 cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0); 87 return (CFGA_ERROR); 88 } 89 90 if ((ret = apidt_create(ap_id, &apidt, errstring)) != SCFGA_OK) { 91 return (err_cvt(ret)); 92 } 93 94 if (options != NULL) 95 apidt.flags |= FLAG_DISABLE_RCM; 96 97 /* A dynamic component indicates a device, else it is the bus */ 98 if (apidt.dyncomp != NULL) { 99 ret = dev_change_state(state_change_cmd, &apidt, flags, 100 errstring); 101 } else { 102 ret = bus_change_state(state_change_cmd, &apidt, confp, flags, 103 errstring); 104 } 105 106 apidt_free(&apidt); 107 return (err_cvt(ret)); 108 } 109 110 /*ARGSUSED*/ 111 cfga_err_t 112 cfga_private_func( 113 const char *func, 114 const char *ap_id, 115 const char *options, 116 struct cfga_confirm *confp, 117 struct cfga_msg *msgp, 118 char **errstring, 119 cfga_flags_t flags) 120 { 121 apid_t apidt = {NULL}; 122 prompt_t args = {NULL}; 123 scfga_ret_t ret; 124 125 if (errstring != NULL) 126 *errstring = NULL; 127 128 if (geteuid() != 0) { 129 return (CFGA_PRIV); 130 } 131 132 if (func == NULL) { 133 return (CFGA_ERROR); 134 } 135 136 if (options != NULL && strcmp(options, OPT_DISABLE_RCM) != 0) { 137 cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0); 138 return (CFGA_ERROR); 139 } 140 141 if ((ret = apidt_create(ap_id, &apidt, errstring)) != SCFGA_OK) { 142 return (err_cvt(ret)); 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