1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <errno.h> 30*0Sstevel@tonic-gate #include <stdio.h> 31*0Sstevel@tonic-gate #include <stdlib.h> 32*0Sstevel@tonic-gate #include <string.h> 33*0Sstevel@tonic-gate #include <locale.h> 34*0Sstevel@tonic-gate #include <langinfo.h> 35*0Sstevel@tonic-gate #include <time.h> 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #if !defined(DEBUG) 38*0Sstevel@tonic-gate #define NDEBUG 1 39*0Sstevel@tonic-gate #else 40*0Sstevel@tonic-gate #undef NDEBUG 41*0Sstevel@tonic-gate #endif 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #include <assert.h> 44*0Sstevel@tonic-gate #include <sys/types.h> 45*0Sstevel@tonic-gate #include <sys/stat.h> 46*0Sstevel@tonic-gate #include <sys/param.h> 47*0Sstevel@tonic-gate #include <dlfcn.h> 48*0Sstevel@tonic-gate #include <synch.h> 49*0Sstevel@tonic-gate #include <sys/systeminfo.h> 50*0Sstevel@tonic-gate #include <sys/sunddi.h> 51*0Sstevel@tonic-gate #include <libdevinfo.h> 52*0Sstevel@tonic-gate #include <unistd.h> 53*0Sstevel@tonic-gate #include <stdarg.h> 54*0Sstevel@tonic-gate #include <limits.h> 55*0Sstevel@tonic-gate #include <ftw.h> 56*0Sstevel@tonic-gate #include <ctype.h> 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate #define CFGA_PLUGIN_LIB 59*0Sstevel@tonic-gate #include <config_admin.h> 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate /* Limit size of sysinfo return */ 62*0Sstevel@tonic-gate #define SYSINFO_LENGTH 256 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate /* 65*0Sstevel@tonic-gate * Attachment point specifier types. 66*0Sstevel@tonic-gate */ 67*0Sstevel@tonic-gate typedef enum { 68*0Sstevel@tonic-gate UNKNOWN_AP, 69*0Sstevel@tonic-gate LOGICAL_LINK_AP, 70*0Sstevel@tonic-gate LOGICAL_DRV_AP, 71*0Sstevel@tonic-gate PHYSICAL_AP, 72*0Sstevel@tonic-gate AP_TYPE 73*0Sstevel@tonic-gate } cfga_ap_types_t; 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate static char *listopt_array[] = { 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate #define LISTOPT_CLASS 0 78*0Sstevel@tonic-gate "class", 79*0Sstevel@tonic-gate NULL 80*0Sstevel@tonic-gate }; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate typedef struct { 83*0Sstevel@tonic-gate int v_min; /* Min acceptable version */ 84*0Sstevel@tonic-gate int v_max; /* Max acceptable version */ 85*0Sstevel@tonic-gate } vers_req_t; 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate #define INVALID_VERSION -1 88*0Sstevel@tonic-gate #define VALID_HSL_VERS(v) (((v) >= CFGA_HSL_V1) && \ 89*0Sstevel@tonic-gate ((v) <= CFGA_HSL_VERS)) 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate /* 92*0Sstevel@tonic-gate * Incomplete definition 93*0Sstevel@tonic-gate */ 94*0Sstevel@tonic-gate struct cfga_vers_ops; 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate /* 97*0Sstevel@tonic-gate * Structure that contains plugin library information. 98*0Sstevel@tonic-gate */ 99*0Sstevel@tonic-gate typedef struct plugin_lib { 100*0Sstevel@tonic-gate struct plugin_lib *next; /* pointer to next */ 101*0Sstevel@tonic-gate mutex_t lock; /* protects refcnt */ 102*0Sstevel@tonic-gate int refcnt; /* reference count */ 103*0Sstevel@tonic-gate void *handle; /* handle from dlopen */ 104*0Sstevel@tonic-gate cfga_err_t (*cfga_change_state_p)(); 105*0Sstevel@tonic-gate cfga_err_t (*cfga_private_func_p)(); 106*0Sstevel@tonic-gate cfga_err_t (*cfga_test_p)(); 107*0Sstevel@tonic-gate cfga_err_t (*cfga_stat_p)(); 108*0Sstevel@tonic-gate cfga_err_t (*cfga_list_p)(); 109*0Sstevel@tonic-gate cfga_err_t (*cfga_help_p)(); 110*0Sstevel@tonic-gate int (*cfga_ap_id_cmp_p)(); 111*0Sstevel@tonic-gate cfga_err_t (*cfga_list_ext_p)(); /* For V2 plug-ins only */ 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate int plugin_vers; /* actual plugin version */ 114*0Sstevel@tonic-gate struct cfga_vers_ops *vers_ops; /* version dependant routines */ 115*0Sstevel@tonic-gate char libpath[MAXPATHLEN]; /* full pathname to lib */ 116*0Sstevel@tonic-gate } plugin_lib_t; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate static plugin_lib_t plugin_list; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate typedef struct lib_cache { 121*0Sstevel@tonic-gate struct lib_cache *lc_next; 122*0Sstevel@tonic-gate plugin_lib_t *lc_libp; 123*0Sstevel@tonic-gate char *lc_ap_id; 124*0Sstevel@tonic-gate char *lc_ap_physical; /* physical ap_id */ 125*0Sstevel@tonic-gate char *lc_ap_logical; /* logical ap_id */ 126*0Sstevel@tonic-gate } lib_cache_t; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate static lib_cache_t *lib_cache; 129*0Sstevel@tonic-gate static mutex_t lib_cache_lock; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate /* 132*0Sstevel@tonic-gate * Library locator data struct - used to pass down through the device 133*0Sstevel@tonic-gate * tree walking code. 134*0Sstevel@tonic-gate */ 135*0Sstevel@tonic-gate typedef struct lib_locator { 136*0Sstevel@tonic-gate char ap_base[MAXPATHLEN]; 137*0Sstevel@tonic-gate char ap_logical[CFGA_LOG_EXT_LEN]; 138*0Sstevel@tonic-gate char ap_physical[CFGA_PHYS_EXT_LEN]; 139*0Sstevel@tonic-gate char ap_class[CFGA_CLASS_LEN]; 140*0Sstevel@tonic-gate char pathname[MAXPATHLEN]; 141*0Sstevel@tonic-gate plugin_lib_t *libp; 142*0Sstevel@tonic-gate cfga_err_t status; 143*0Sstevel@tonic-gate vers_req_t vers_req; /* plug-in version required */ 144*0Sstevel@tonic-gate } lib_loc_t; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate /* 147*0Sstevel@tonic-gate * linked list of cfga_stat_data structs - used for 148*0Sstevel@tonic-gate * config_list 149*0Sstevel@tonic-gate */ 150*0Sstevel@tonic-gate typedef struct stat_data_list { 151*0Sstevel@tonic-gate struct stat_data_list *next; 152*0Sstevel@tonic-gate cfga_stat_data_t stat_data; 153*0Sstevel@tonic-gate } stat_data_list_t; 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate /* 156*0Sstevel@tonic-gate * linked list of arrays. Each array represents a bunch 157*0Sstevel@tonic-gate * of list_data_t structures returned by a single call 158*0Sstevel@tonic-gate * to a plugin's cfga_list_ext() routine. 159*0Sstevel@tonic-gate */ 160*0Sstevel@tonic-gate typedef struct array_list { 161*0Sstevel@tonic-gate struct array_list *next; 162*0Sstevel@tonic-gate cfga_list_data_t *array; 163*0Sstevel@tonic-gate int nelem; 164*0Sstevel@tonic-gate } array_list_t; 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* 167*0Sstevel@tonic-gate * encapsulate config_list args to get them through the tree 168*0Sstevel@tonic-gate * walking code 169*0Sstevel@tonic-gate */ 170*0Sstevel@tonic-gate typedef struct list_stat { 171*0Sstevel@tonic-gate const char *opts; /* Hardware specific options */ 172*0Sstevel@tonic-gate char **errstr; 173*0Sstevel@tonic-gate cfga_flags_t flags; 174*0Sstevel@tonic-gate int *countp; /* Total number of list and stat structures */ 175*0Sstevel@tonic-gate stat_data_list_t *sdl; /* Linked list of stat structures */ 176*0Sstevel@tonic-gate array_list_t *al; /* Linked list of arrays of list structures */ 177*0Sstevel@tonic-gate vers_req_t use_vers; /* plugin versions to be stat'ed */ 178*0Sstevel@tonic-gate } list_stat_t; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* 181*0Sstevel@tonic-gate * Internal operations for libcfgadm which are version dependant 182*0Sstevel@tonic-gate */ 183*0Sstevel@tonic-gate struct cfga_vers_ops { 184*0Sstevel@tonic-gate cfga_err_t (*resolve_lib)(plugin_lib_t *libp); 185*0Sstevel@tonic-gate cfga_err_t (*stat_plugin)(list_stat_t *, lib_loc_t *, char **errstring); 186*0Sstevel@tonic-gate cfga_err_t (*mklog)(di_node_t, di_minor_t, plugin_lib_t *, 187*0Sstevel@tonic-gate lib_loc_t *liblocp); 188*0Sstevel@tonic-gate cfga_err_t (*get_cond)(lib_loc_t *, cfga_cond_t *, char **); 189*0Sstevel@tonic-gate }; 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate /* 193*0Sstevel@tonic-gate * Lock to protect list of libraries 194*0Sstevel@tonic-gate */ 195*0Sstevel@tonic-gate static mutex_t plugin_list_lock; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* 198*0Sstevel@tonic-gate * Forward declarations 199*0Sstevel@tonic-gate */ 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate static const char *__config_strerror(cfga_err_t); 202*0Sstevel@tonic-gate static void *config_calloc_check(size_t, size_t, char **); 203*0Sstevel@tonic-gate static cfga_err_t resolve_lib_ref(plugin_lib_t *, lib_loc_t *); 204*0Sstevel@tonic-gate static cfga_err_t config_get_lib(const char *, lib_loc_t *, char **); 205*0Sstevel@tonic-gate static int check_ap(di_node_t, di_minor_t, void *); 206*0Sstevel@tonic-gate static int check_ap_phys(di_node_t, di_minor_t, void *); 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate static cfga_err_t find_ap_common(lib_loc_t *libloc_p, const char *rootpath, 209*0Sstevel@tonic-gate int (*fcn)(di_node_t node, di_minor_t minor, void *arg), char **errstring); 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate static plugin_lib_t *lib_in_list(char *); 212*0Sstevel@tonic-gate static cfga_err_t load_lib(di_node_t, di_minor_t, lib_loc_t *); 213*0Sstevel@tonic-gate extern void bcopy(const void *, void *, size_t); 214*0Sstevel@tonic-gate static void config_err(int, int, char **); 215*0Sstevel@tonic-gate static void hold_lib(plugin_lib_t *); 216*0Sstevel@tonic-gate static void rele_lib(plugin_lib_t *); 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate static cfga_err_t parse_listopt(char *listopts, char **classpp, 219*0Sstevel@tonic-gate char **errstring); 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate static cfga_err_t list_common(list_stat_t *lstatp, const char *class); 222*0Sstevel@tonic-gate static int do_list_common(di_node_t node, di_minor_t minor, void *arg); 223*0Sstevel@tonic-gate static cfga_err_t stat_common(int num_ap_ids, char *const *ap_ids, 224*0Sstevel@tonic-gate const char *class, list_stat_t *lstatp); 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate static cfga_err_t null_resolve(plugin_lib_t *libp); 227*0Sstevel@tonic-gate static cfga_err_t resolve_v1(plugin_lib_t *libp); 228*0Sstevel@tonic-gate static cfga_err_t resolve_v2(plugin_lib_t *libp); 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate static cfga_err_t mklog_common(di_node_t node, di_minor_t minor, 231*0Sstevel@tonic-gate lib_loc_t *liblocp, size_t len); 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate static cfga_err_t null_mklog(di_node_t node, di_minor_t minor, 234*0Sstevel@tonic-gate plugin_lib_t *libp, lib_loc_t *liblocp); 235*0Sstevel@tonic-gate static cfga_err_t mklog_v1(di_node_t node, di_minor_t minor, 236*0Sstevel@tonic-gate plugin_lib_t *libp, lib_loc_t *liblocp); 237*0Sstevel@tonic-gate static cfga_err_t mklog_v2(di_node_t node, di_minor_t minor, 238*0Sstevel@tonic-gate plugin_lib_t *libp, lib_loc_t *liblocp); 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate static cfga_err_t null_stat_plugin(list_stat_t *lstatp, lib_loc_t *libloc_p, 241*0Sstevel@tonic-gate char **errstring); 242*0Sstevel@tonic-gate static cfga_err_t stat_plugin_v2(list_stat_t *lstat, lib_loc_t *libloc_p, 243*0Sstevel@tonic-gate char **errstring); 244*0Sstevel@tonic-gate static cfga_err_t stat_plugin_v1(list_stat_t *lstat, lib_loc_t *libloc_p, 245*0Sstevel@tonic-gate char **errstring); 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate static cfga_err_t null_get_cond(lib_loc_t *liblocp, cfga_cond_t *condp, 248*0Sstevel@tonic-gate char **errstring); 249*0Sstevel@tonic-gate static cfga_err_t get_cond_v1(lib_loc_t *liblocp, cfga_cond_t *condp, 250*0Sstevel@tonic-gate char **errstring); 251*0Sstevel@tonic-gate static cfga_err_t get_cond_v2(lib_loc_t *liblocp, cfga_cond_t *condp, 252*0Sstevel@tonic-gate char **errstring); 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate static cfga_err_t realloc_data(cfga_stat_data_t **ap_id_list, 255*0Sstevel@tonic-gate int *nlistp, list_stat_t *lstatp); 256*0Sstevel@tonic-gate static cfga_err_t realloc_data_ext(cfga_list_data_t **ap_id_list, 257*0Sstevel@tonic-gate int *nlistp, list_stat_t *lstatp); 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate static void stat_to_list(cfga_list_data_t *lp, cfga_stat_data_t *statp); 260*0Sstevel@tonic-gate static void lstat_free(list_stat_t *lstatp); 261*0Sstevel@tonic-gate static cfga_ap_types_t find_arg_type(const char *ap_id); 262*0Sstevel@tonic-gate static int compat_plugin(vers_req_t *reqp, int plugin_vers); 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate static cfga_err_t check_flags(cfga_flags_t flags, cfga_flags_t mask, 265*0Sstevel@tonic-gate char **errstring); 266*0Sstevel@tonic-gate static cfga_err_t check_apids(int num_ap_ids, char *const *ap_ids, 267*0Sstevel@tonic-gate char **errstring); 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate static char *get_class(di_minor_t minor); 270*0Sstevel@tonic-gate static cfga_err_t split_apid(char *ap_id, char **dyncompp, char **errstring); 271*0Sstevel@tonic-gate static void append_dyn(char *buf, const char *dyncomp, size_t blen); 272*0Sstevel@tonic-gate static int default_ap_id_cmp(const char *ap_id1, const char *ap_id2); 273*0Sstevel@tonic-gate static void destroy_cache(); 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* 276*0Sstevel@tonic-gate * Plugin library search path helpers 277*0Sstevel@tonic-gate */ 278*0Sstevel@tonic-gate #define LIB_PATH_BASE1 "/usr/platform/" 279*0Sstevel@tonic-gate #define LIB_PATH_BASE2 "/usr" 280*0Sstevel@tonic-gate #ifdef __sparcv9 281*0Sstevel@tonic-gate #define LIB_PATH_MIDDLE "/lib/cfgadm/sparcv9/" 282*0Sstevel@tonic-gate #else 283*0Sstevel@tonic-gate #define LIB_PATH_MIDDLE "/lib/cfgadm/" 284*0Sstevel@tonic-gate #endif 285*0Sstevel@tonic-gate #define LIB_PATH_TAIL ".so.1" 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 289*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 290*0Sstevel@tonic-gate #endif 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate /* 293*0Sstevel@tonic-gate * Defined constants 294*0Sstevel@tonic-gate */ 295*0Sstevel@tonic-gate #define DEVICES_DIR "/devices" 296*0Sstevel@tonic-gate #define DOT_DOT_DEVICES "../devices" 297*0Sstevel@tonic-gate #define CFGA_DEV_DIR "/dev/cfg" 298*0Sstevel@tonic-gate #define SLASH "/" 299*0Sstevel@tonic-gate #define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0) 300*0Sstevel@tonic-gate #define GET_DYN(a) (strstr((a), CFGA_DYN_SEP)) 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate #define CFGA_NO_CLASS "none" 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate /* 305*0Sstevel@tonic-gate * Error strings 306*0Sstevel@tonic-gate */ 307*0Sstevel@tonic-gate #define DI_INIT_FAILED 1 308*0Sstevel@tonic-gate #define ALLOC_FAILED 2 309*0Sstevel@tonic-gate #define INVALID_ARGS 3 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate static char * 312*0Sstevel@tonic-gate err_strings[] = { 313*0Sstevel@tonic-gate NULL, 314*0Sstevel@tonic-gate "Device library initialize failed", 315*0Sstevel@tonic-gate "Memory allocation failed", 316*0Sstevel@tonic-gate "Invalid argument(s)" 317*0Sstevel@tonic-gate }; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate static const char err_sep[] = ": "; 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate /* 323*0Sstevel@tonic-gate * Table of version dependant routines 324*0Sstevel@tonic-gate */ 325*0Sstevel@tonic-gate static struct cfga_vers_ops cfga_vers_ops[CFGA_HSL_VERS + 1] = { 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate {null_resolve, null_stat_plugin, null_mklog, null_get_cond }, 328*0Sstevel@tonic-gate {resolve_v1, stat_plugin_v1, mklog_v1, get_cond_v1 }, 329*0Sstevel@tonic-gate {resolve_v2, stat_plugin_v2, mklog_v2, get_cond_v2 } 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate }; 332*0Sstevel@tonic-gate #define VERS_ARRAY_SZ (sizeof (cfga_vers_ops)/sizeof (cfga_vers_ops[0])) 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* 336*0Sstevel@tonic-gate * Public interfaces for libcfgadm, as documented in config_admin.3x 337*0Sstevel@tonic-gate */ 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate /* 340*0Sstevel@tonic-gate * config_change_state 341*0Sstevel@tonic-gate */ 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate cfga_err_t 344*0Sstevel@tonic-gate config_change_state( 345*0Sstevel@tonic-gate cfga_cmd_t state_change_cmd, 346*0Sstevel@tonic-gate int num_ap_ids, 347*0Sstevel@tonic-gate char *const *ap_id, 348*0Sstevel@tonic-gate const char *options, 349*0Sstevel@tonic-gate struct cfga_confirm *confp, 350*0Sstevel@tonic-gate struct cfga_msg *msgp, 351*0Sstevel@tonic-gate char **errstring, 352*0Sstevel@tonic-gate cfga_flags_t flags) 353*0Sstevel@tonic-gate { 354*0Sstevel@tonic-gate /* 355*0Sstevel@tonic-gate * for each arg - 356*0Sstevel@tonic-gate * load hs library, 357*0Sstevel@tonic-gate * if force 358*0Sstevel@tonic-gate * call cfga_state_change_func 359*0Sstevel@tonic-gate * return status 360*0Sstevel@tonic-gate * else 361*0Sstevel@tonic-gate * call it's cfga_stat 362*0Sstevel@tonic-gate * check condition 363*0Sstevel@tonic-gate * call cfga_state_change_func 364*0Sstevel@tonic-gate * return status 365*0Sstevel@tonic-gate */ 366*0Sstevel@tonic-gate int i; 367*0Sstevel@tonic-gate lib_loc_t libloc; 368*0Sstevel@tonic-gate plugin_lib_t *libp; 369*0Sstevel@tonic-gate cfga_cond_t cond; 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate cfga_err_t retval = CFGA_OK; 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* Sanity checks */ 374*0Sstevel@tonic-gate if (state_change_cmd == CFGA_CMD_NONE) 375*0Sstevel@tonic-gate return (retval); 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate if ((state_change_cmd < CFGA_CMD_NONE) || 378*0Sstevel@tonic-gate (state_change_cmd > CFGA_CMD_UNCONFIGURE)) 379*0Sstevel@tonic-gate return (CFGA_INVAL); 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate if (errstring != NULL) { 382*0Sstevel@tonic-gate *errstring = NULL; 383*0Sstevel@tonic-gate } 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate if (check_flags(flags, CFGA_FLAG_FORCE | CFGA_FLAG_VERBOSE, errstring) 386*0Sstevel@tonic-gate != CFGA_OK) { 387*0Sstevel@tonic-gate return (CFGA_ERROR); 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate if (check_apids(num_ap_ids, ap_id, errstring) != CFGA_OK) { 391*0Sstevel@tonic-gate return (CFGA_ERROR); 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate /* 395*0Sstevel@tonic-gate * operate on each ap_id 396*0Sstevel@tonic-gate */ 397*0Sstevel@tonic-gate for (i = 0; (i < num_ap_ids) && (retval == CFGA_OK); i++) { 398*0Sstevel@tonic-gate libloc.libp = NULL; 399*0Sstevel@tonic-gate if ((retval = config_get_lib(ap_id[i], &libloc, errstring)) != 400*0Sstevel@tonic-gate CFGA_OK) { 401*0Sstevel@tonic-gate break; 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate libp = libloc.libp; 405*0Sstevel@tonic-gate if ((flags & CFGA_FLAG_FORCE) || 406*0Sstevel@tonic-gate (state_change_cmd == CFGA_CMD_UNLOAD) || 407*0Sstevel@tonic-gate (state_change_cmd == CFGA_CMD_DISCONNECT) || 408*0Sstevel@tonic-gate (state_change_cmd == CFGA_CMD_UNCONFIGURE)) { 409*0Sstevel@tonic-gate errno = 0; 410*0Sstevel@tonic-gate retval = (*libp->cfga_change_state_p) 411*0Sstevel@tonic-gate (state_change_cmd, libloc.ap_physical, options, 412*0Sstevel@tonic-gate confp, msgp, errstring, flags); 413*0Sstevel@tonic-gate } else { 414*0Sstevel@tonic-gate /* 415*0Sstevel@tonic-gate * Need to check condition before proceeding in 416*0Sstevel@tonic-gate * the "configure direction" 417*0Sstevel@tonic-gate */ 418*0Sstevel@tonic-gate if ((retval = libp->vers_ops->get_cond(&libloc, &cond, 419*0Sstevel@tonic-gate errstring)) != CFGA_OK) { 420*0Sstevel@tonic-gate break; 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate if (cond == CFGA_COND_OK || cond == CFGA_COND_UNKNOWN) { 424*0Sstevel@tonic-gate errno = 0; 425*0Sstevel@tonic-gate retval = 426*0Sstevel@tonic-gate (*libp->cfga_change_state_p)( 427*0Sstevel@tonic-gate state_change_cmd, 428*0Sstevel@tonic-gate libloc.ap_physical, options, 429*0Sstevel@tonic-gate confp, msgp, errstring, 430*0Sstevel@tonic-gate flags); 431*0Sstevel@tonic-gate } else { 432*0Sstevel@tonic-gate retval = CFGA_INSUFFICENT_CONDITION; 433*0Sstevel@tonic-gate } 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate rele_lib(libp); 436*0Sstevel@tonic-gate } 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate return (retval); 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate /* 442*0Sstevel@tonic-gate * config_private_func 443*0Sstevel@tonic-gate */ 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate cfga_err_t 446*0Sstevel@tonic-gate config_private_func( 447*0Sstevel@tonic-gate const char *function, 448*0Sstevel@tonic-gate int num_ap_ids, 449*0Sstevel@tonic-gate char *const *ap_ids, 450*0Sstevel@tonic-gate const char *options, 451*0Sstevel@tonic-gate struct cfga_confirm *confp, 452*0Sstevel@tonic-gate struct cfga_msg *msgp, 453*0Sstevel@tonic-gate char **errstring, 454*0Sstevel@tonic-gate cfga_flags_t flags) 455*0Sstevel@tonic-gate { 456*0Sstevel@tonic-gate int i; 457*0Sstevel@tonic-gate lib_loc_t libloc; 458*0Sstevel@tonic-gate cfga_err_t retval = CFGA_OK; 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate if (errstring != NULL) { 462*0Sstevel@tonic-gate *errstring = NULL; 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate if (check_flags(flags, CFGA_FLAG_FORCE | CFGA_FLAG_VERBOSE, errstring) 466*0Sstevel@tonic-gate != CFGA_OK) { 467*0Sstevel@tonic-gate return (CFGA_ERROR); 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate if (check_apids(num_ap_ids, ap_ids, errstring) != CFGA_OK) { 471*0Sstevel@tonic-gate return (CFGA_ERROR); 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate /* 475*0Sstevel@tonic-gate * operate on each ap_id 476*0Sstevel@tonic-gate */ 477*0Sstevel@tonic-gate for (i = 0; (i < num_ap_ids) && (retval == CFGA_OK); i++) { 478*0Sstevel@tonic-gate libloc.libp = NULL; 479*0Sstevel@tonic-gate if ((retval = config_get_lib(ap_ids[i], &libloc, errstring)) != 480*0Sstevel@tonic-gate CFGA_OK) { 481*0Sstevel@tonic-gate return (retval); 482*0Sstevel@tonic-gate } 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate errno = 0; 485*0Sstevel@tonic-gate retval = (*libloc.libp->cfga_private_func_p)(function, 486*0Sstevel@tonic-gate libloc.ap_physical, options, confp, msgp, errstring, 487*0Sstevel@tonic-gate flags); 488*0Sstevel@tonic-gate rele_lib(libloc.libp); 489*0Sstevel@tonic-gate } 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate return (retval); 492*0Sstevel@tonic-gate } 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate /* 496*0Sstevel@tonic-gate * config_test 497*0Sstevel@tonic-gate */ 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate cfga_err_t 500*0Sstevel@tonic-gate config_test( 501*0Sstevel@tonic-gate int num_ap_ids, 502*0Sstevel@tonic-gate char *const *ap_ids, 503*0Sstevel@tonic-gate const char *options, 504*0Sstevel@tonic-gate struct cfga_msg *msgp, 505*0Sstevel@tonic-gate char **errstring, 506*0Sstevel@tonic-gate cfga_flags_t flags) 507*0Sstevel@tonic-gate { 508*0Sstevel@tonic-gate int i; 509*0Sstevel@tonic-gate lib_loc_t libloc; 510*0Sstevel@tonic-gate cfga_err_t retval = CFGA_OK; 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate if (errstring != NULL) { 513*0Sstevel@tonic-gate *errstring = NULL; 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate if (check_flags(flags, CFGA_FLAG_FORCE | CFGA_FLAG_VERBOSE, errstring) 517*0Sstevel@tonic-gate != CFGA_OK) { 518*0Sstevel@tonic-gate return (CFGA_ERROR); 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate if (check_apids(num_ap_ids, ap_ids, errstring) != CFGA_OK) { 522*0Sstevel@tonic-gate return (CFGA_ERROR); 523*0Sstevel@tonic-gate } 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate /* 526*0Sstevel@tonic-gate * operate on each ap_id 527*0Sstevel@tonic-gate */ 528*0Sstevel@tonic-gate for (i = 0; (i < num_ap_ids) && (retval == CFGA_OK); i++) { 529*0Sstevel@tonic-gate libloc.libp = NULL; 530*0Sstevel@tonic-gate if ((retval = config_get_lib(ap_ids[i], &libloc, errstring)) != 531*0Sstevel@tonic-gate CFGA_OK) { 532*0Sstevel@tonic-gate return (retval); 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate errno = 0; 536*0Sstevel@tonic-gate retval = (*libloc.libp->cfga_test_p)(libloc.ap_physical, 537*0Sstevel@tonic-gate options, msgp, errstring, flags); 538*0Sstevel@tonic-gate rele_lib(libloc.libp); 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate return (retval); 542*0Sstevel@tonic-gate } 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate cfga_err_t 545*0Sstevel@tonic-gate config_stat( 546*0Sstevel@tonic-gate int num_ap_ids, 547*0Sstevel@tonic-gate char *const *ap_ids, 548*0Sstevel@tonic-gate struct cfga_stat_data *buf, 549*0Sstevel@tonic-gate const char *options, 550*0Sstevel@tonic-gate char **errstring) 551*0Sstevel@tonic-gate { 552*0Sstevel@tonic-gate int nstat, n, i; 553*0Sstevel@tonic-gate list_stat_t lstat = {NULL}; 554*0Sstevel@tonic-gate cfga_err_t rc = CFGA_OK; 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate if (check_apids(num_ap_ids, ap_ids, errstring) != CFGA_OK) { 557*0Sstevel@tonic-gate return (CFGA_ERROR); 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate /* 561*0Sstevel@tonic-gate * V1 entry points don't support dynamic attachment points 562*0Sstevel@tonic-gate */ 563*0Sstevel@tonic-gate for (i = 0; i < num_ap_ids; i++) { 564*0Sstevel@tonic-gate if (GET_DYN(ap_ids[i]) != NULL) { 565*0Sstevel@tonic-gate return (CFGA_APID_NOEXIST); 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate nstat = n = 0; 571*0Sstevel@tonic-gate lstat.countp = &nstat; 572*0Sstevel@tonic-gate lstat.opts = options; 573*0Sstevel@tonic-gate lstat.errstr = errstring; 574*0Sstevel@tonic-gate /* 575*0Sstevel@tonic-gate * This is a V1 interface which can use only V1 plugins 576*0Sstevel@tonic-gate */ 577*0Sstevel@tonic-gate lstat.use_vers.v_max = lstat.use_vers.v_min = CFGA_HSL_V1; 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate rc = stat_common(num_ap_ids, ap_ids, NULL, &lstat); 580*0Sstevel@tonic-gate if (rc == CFGA_OK) { 581*0Sstevel@tonic-gate assert(*lstat.countp == num_ap_ids); 582*0Sstevel@tonic-gate rc = realloc_data(&buf, &n, &lstat); 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate return (rc); 586*0Sstevel@tonic-gate } 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate /* 589*0Sstevel@tonic-gate * config_list 590*0Sstevel@tonic-gate */ 591*0Sstevel@tonic-gate cfga_err_t 592*0Sstevel@tonic-gate config_list( 593*0Sstevel@tonic-gate struct cfga_stat_data **ap_id_list, 594*0Sstevel@tonic-gate int *nlistp, 595*0Sstevel@tonic-gate const char *options, 596*0Sstevel@tonic-gate char **errstring) 597*0Sstevel@tonic-gate { 598*0Sstevel@tonic-gate int nstat; 599*0Sstevel@tonic-gate list_stat_t lstat = {NULL}; 600*0Sstevel@tonic-gate cfga_err_t retval = CFGA_ERROR; 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate if (errstring != NULL) { 603*0Sstevel@tonic-gate *errstring = NULL; 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate nstat = 0; 607*0Sstevel@tonic-gate lstat.countp = &nstat; 608*0Sstevel@tonic-gate lstat.opts = options; 609*0Sstevel@tonic-gate lstat.errstr = errstring; 610*0Sstevel@tonic-gate /* 611*0Sstevel@tonic-gate * This is a V1 interface which can use only V1 plugins 612*0Sstevel@tonic-gate */ 613*0Sstevel@tonic-gate lstat.use_vers.v_max = lstat.use_vers.v_min = CFGA_HSL_V1; 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate *ap_id_list = NULL; 617*0Sstevel@tonic-gate *nlistp = 0; 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate /* 620*0Sstevel@tonic-gate * V1 interfaces don't support prefiltering, no class 621*0Sstevel@tonic-gate * specified. 622*0Sstevel@tonic-gate */ 623*0Sstevel@tonic-gate retval = list_common(&lstat, NULL); 624*0Sstevel@tonic-gate if (retval == CFGA_OK) { 625*0Sstevel@tonic-gate retval = realloc_data(ap_id_list, nlistp, &lstat); 626*0Sstevel@tonic-gate } 627*0Sstevel@tonic-gate 628*0Sstevel@tonic-gate assert((ap_id_list != NULL && *nlistp != 0) || 629*0Sstevel@tonic-gate (ap_id_list == NULL && *nlistp == 0)); 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate if (retval == CFGA_OK && *nlistp == 0) { 632*0Sstevel@tonic-gate return (CFGA_NOTSUPP); 633*0Sstevel@tonic-gate } else { 634*0Sstevel@tonic-gate return (retval); 635*0Sstevel@tonic-gate } 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate /* 640*0Sstevel@tonic-gate * config_list_ext 641*0Sstevel@tonic-gate */ 642*0Sstevel@tonic-gate cfga_err_t 643*0Sstevel@tonic-gate config_list_ext( 644*0Sstevel@tonic-gate int num_ap_ids, 645*0Sstevel@tonic-gate char *const *ap_ids, 646*0Sstevel@tonic-gate struct cfga_list_data **ap_id_list, 647*0Sstevel@tonic-gate int *nlistp, 648*0Sstevel@tonic-gate const char *options, 649*0Sstevel@tonic-gate const char *listopts, 650*0Sstevel@tonic-gate char **errstring, 651*0Sstevel@tonic-gate cfga_flags_t flags) 652*0Sstevel@tonic-gate { 653*0Sstevel@tonic-gate int nstat, list, prefilter; 654*0Sstevel@tonic-gate list_stat_t lstat = {NULL}; 655*0Sstevel@tonic-gate char *class; 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate cfga_err_t rc = CFGA_ERROR; 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate *nlistp = 0; 660*0Sstevel@tonic-gate *ap_id_list = NULL; 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate if (errstring != NULL) { 663*0Sstevel@tonic-gate *errstring = NULL; 664*0Sstevel@tonic-gate } 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate if (check_flags(flags, CFGA_FLAG_LIST_ALL, errstring) != CFGA_OK) { 667*0Sstevel@tonic-gate return (CFGA_ERROR); 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate class = NULL; 671*0Sstevel@tonic-gate if ((rc = parse_listopt((char *)listopts, &class, errstring)) 672*0Sstevel@tonic-gate != CFGA_OK) { 673*0Sstevel@tonic-gate return (rc); 674*0Sstevel@tonic-gate } 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate prefilter = (class == NULL) ? 0 : 1; 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate nstat = 0; 679*0Sstevel@tonic-gate lstat.countp = &nstat; 680*0Sstevel@tonic-gate lstat.opts = options; 681*0Sstevel@tonic-gate lstat.errstr = errstring; 682*0Sstevel@tonic-gate lstat.flags = flags; 683*0Sstevel@tonic-gate /* 684*0Sstevel@tonic-gate * We support both V1 and V2 plugins through this entry 685*0Sstevel@tonic-gate * point. 686*0Sstevel@tonic-gate */ 687*0Sstevel@tonic-gate lstat.use_vers.v_min = CFGA_HSL_V1; 688*0Sstevel@tonic-gate lstat.use_vers.v_max = CFGA_HSL_V2; 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate list = 0; 691*0Sstevel@tonic-gate if (num_ap_ids == 0 && ap_ids == NULL) { 692*0Sstevel@tonic-gate /* 693*0Sstevel@tonic-gate * discover and stat all attachment points 694*0Sstevel@tonic-gate */ 695*0Sstevel@tonic-gate list = 1; 696*0Sstevel@tonic-gate rc = list_common(&lstat, class); 697*0Sstevel@tonic-gate } else if (num_ap_ids > 0 && ap_ids != NULL) { 698*0Sstevel@tonic-gate /* 699*0Sstevel@tonic-gate * Stat specified attachment points. With dynamic expansion 700*0Sstevel@tonic-gate * more data may be returned than was specified by user. 701*0Sstevel@tonic-gate */ 702*0Sstevel@tonic-gate rc = stat_common(num_ap_ids, ap_ids, class, &lstat); 703*0Sstevel@tonic-gate } else { 704*0Sstevel@tonic-gate rc = CFGA_ERROR; 705*0Sstevel@tonic-gate } 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate S_FREE(class); 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate if (rc != CFGA_OK) { 710*0Sstevel@tonic-gate return (rc); 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate rc = realloc_data_ext(ap_id_list, nlistp, &lstat); 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate assert((ap_id_list != NULL && *nlistp != 0) || 716*0Sstevel@tonic-gate (ap_id_list == NULL && *nlistp == 0)); 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate /* 719*0Sstevel@tonic-gate * For the list command notify user if no attachment 720*0Sstevel@tonic-gate * point is found in the system. 721*0Sstevel@tonic-gate * 722*0Sstevel@tonic-gate */ 723*0Sstevel@tonic-gate if (list && rc == CFGA_OK && *nlistp == 0) { 724*0Sstevel@tonic-gate /* 725*0Sstevel@tonic-gate * If attachment points are being prefiltered, absence of data 726*0Sstevel@tonic-gate * does not imply that config. admin. is not 727*0Sstevel@tonic-gate * supported by the system. 728*0Sstevel@tonic-gate */ 729*0Sstevel@tonic-gate if (prefilter) { 730*0Sstevel@tonic-gate /* 731*0Sstevel@tonic-gate * Prefiltering: requested class is absent 732*0Sstevel@tonic-gate */ 733*0Sstevel@tonic-gate return (CFGA_APID_NOEXIST); 734*0Sstevel@tonic-gate } else { 735*0Sstevel@tonic-gate /* 736*0Sstevel@tonic-gate * No attachment points in system 737*0Sstevel@tonic-gate */ 738*0Sstevel@tonic-gate return (CFGA_NOTSUPP); 739*0Sstevel@tonic-gate } 740*0Sstevel@tonic-gate } else { 741*0Sstevel@tonic-gate return (rc); 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate } 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate /* 747*0Sstevel@tonic-gate * config_unload_libs 748*0Sstevel@tonic-gate * 749*0Sstevel@tonic-gate * Attempts to remove all libs on the plugin list. 750*0Sstevel@tonic-gate */ 751*0Sstevel@tonic-gate void 752*0Sstevel@tonic-gate config_unload_libs() 753*0Sstevel@tonic-gate { 754*0Sstevel@tonic-gate plugin_lib_t *libp, *prev = &plugin_list, *next = NULL; 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate /* destroy cache entries to remove refcnt agains plugins */ 757*0Sstevel@tonic-gate destroy_cache(); 758*0Sstevel@tonic-gate 759*0Sstevel@tonic-gate (void) mutex_lock(&plugin_list_lock); 760*0Sstevel@tonic-gate for (libp = plugin_list.next; libp != NULL; libp = next) { 761*0Sstevel@tonic-gate next = libp->next; 762*0Sstevel@tonic-gate (void) mutex_lock(&libp->lock); 763*0Sstevel@tonic-gate if (libp->refcnt) { 764*0Sstevel@tonic-gate (void) mutex_unlock(&libp->lock); 765*0Sstevel@tonic-gate prev = libp; 766*0Sstevel@tonic-gate continue; 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate (void) mutex_unlock(&libp->lock); 769*0Sstevel@tonic-gate prev->next = next; 770*0Sstevel@tonic-gate (void) dlclose(libp->handle); 771*0Sstevel@tonic-gate (void) mutex_destroy(&libp->lock); 772*0Sstevel@tonic-gate free(libp); 773*0Sstevel@tonic-gate } 774*0Sstevel@tonic-gate (void) mutex_unlock(&plugin_list_lock); 775*0Sstevel@tonic-gate } 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate /* 778*0Sstevel@tonic-gate * config_ap_id_cmp 779*0Sstevel@tonic-gate */ 780*0Sstevel@tonic-gate int 781*0Sstevel@tonic-gate config_ap_id_cmp( 782*0Sstevel@tonic-gate const cfga_ap_log_id_t ap1, 783*0Sstevel@tonic-gate const cfga_ap_log_id_t ap2) 784*0Sstevel@tonic-gate { 785*0Sstevel@tonic-gate int ret; 786*0Sstevel@tonic-gate lib_loc_t libloc; 787*0Sstevel@tonic-gate char apstat1[CFGA_PHYS_EXT_LEN]; 788*0Sstevel@tonic-gate char apstat2[CFGA_PHYS_EXT_LEN]; 789*0Sstevel@tonic-gate char *sep1, *sep2; 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate /* 792*0Sstevel@tonic-gate * Extract static ap_ids 793*0Sstevel@tonic-gate */ 794*0Sstevel@tonic-gate (void) strlcpy(apstat1, ap1, sizeof (apstat1)); 795*0Sstevel@tonic-gate (void) strlcpy(apstat2, ap2, sizeof (apstat2)); 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate sep1 = GET_DYN(apstat1); 798*0Sstevel@tonic-gate sep2 = GET_DYN(apstat2); 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate if (sep1) 801*0Sstevel@tonic-gate *sep1 = '\0'; 802*0Sstevel@tonic-gate if (sep2) 803*0Sstevel@tonic-gate *sep2 = '\0'; 804*0Sstevel@tonic-gate 805*0Sstevel@tonic-gate /* 806*0Sstevel@tonic-gate * Use the default comparator for static ap_ids 807*0Sstevel@tonic-gate */ 808*0Sstevel@tonic-gate ret = default_ap_id_cmp(apstat1, apstat2); 809*0Sstevel@tonic-gate if (ret) 810*0Sstevel@tonic-gate return (ret); 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate /* 813*0Sstevel@tonic-gate * static components match. They belong to 814*0Sstevel@tonic-gate * the same static ap_id. Check if both are dynamic 815*0Sstevel@tonic-gate * If not, static < dynamic. 816*0Sstevel@tonic-gate */ 817*0Sstevel@tonic-gate if ((sep1 == NULL) ^ (sep2 == NULL)) 818*0Sstevel@tonic-gate return (sep1 ? 1 : -1); 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate /* 821*0Sstevel@tonic-gate * If both are static, then ap1 = ap2 822*0Sstevel@tonic-gate */ 823*0Sstevel@tonic-gate if (sep1 == NULL) 824*0Sstevel@tonic-gate return (0); 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate /* 827*0Sstevel@tonic-gate * Both are dynamic and belong to same static ap_id. 828*0Sstevel@tonic-gate * Use the plugin comparator 829*0Sstevel@tonic-gate */ 830*0Sstevel@tonic-gate libloc.libp = NULL; 831*0Sstevel@tonic-gate if (config_get_lib(ap1, &libloc, NULL) != CFGA_OK) { 832*0Sstevel@tonic-gate return (strncmp(sep1, sep2, CFGA_PHYS_EXT_LEN)); 833*0Sstevel@tonic-gate } 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate ret = (*libloc.libp->cfga_ap_id_cmp_p)(ap1, ap2); 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate rele_lib(libloc.libp); 838*0Sstevel@tonic-gate 839*0Sstevel@tonic-gate return (ret); 840*0Sstevel@tonic-gate } 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate /* 843*0Sstevel@tonic-gate * config_strerror 844*0Sstevel@tonic-gate */ 845*0Sstevel@tonic-gate 846*0Sstevel@tonic-gate const char * 847*0Sstevel@tonic-gate config_strerror(cfga_err_t cfgerrnum) 848*0Sstevel@tonic-gate { 849*0Sstevel@tonic-gate const char *ep = NULL; 850*0Sstevel@tonic-gate 851*0Sstevel@tonic-gate if ((cfgerrnum < CFGA_OK) || (cfgerrnum > CFGA_ATTR_INVAL)) 852*0Sstevel@tonic-gate return (NULL); 853*0Sstevel@tonic-gate 854*0Sstevel@tonic-gate ep = __config_strerror(cfgerrnum); 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate return ((ep != NULL) ? dgettext(TEXT_DOMAIN, ep) : NULL); 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate /* 860*0Sstevel@tonic-gate * config_help 861*0Sstevel@tonic-gate */ 862*0Sstevel@tonic-gate cfga_err_t 863*0Sstevel@tonic-gate config_help( 864*0Sstevel@tonic-gate int num_ap_ids, 865*0Sstevel@tonic-gate char *const *ap_ids, 866*0Sstevel@tonic-gate struct cfga_msg *msgp, 867*0Sstevel@tonic-gate const char *options, 868*0Sstevel@tonic-gate cfga_flags_t flags) 869*0Sstevel@tonic-gate { 870*0Sstevel@tonic-gate int i; 871*0Sstevel@tonic-gate lib_loc_t libloc; 872*0Sstevel@tonic-gate cfga_err_t retval = CFGA_OK; 873*0Sstevel@tonic-gate 874*0Sstevel@tonic-gate if (check_flags(flags, CFGA_FLAG_FORCE | CFGA_FLAG_VERBOSE, NULL) 875*0Sstevel@tonic-gate != CFGA_OK) { 876*0Sstevel@tonic-gate return (CFGA_ERROR); 877*0Sstevel@tonic-gate } 878*0Sstevel@tonic-gate 879*0Sstevel@tonic-gate if (num_ap_ids < 0) { 880*0Sstevel@tonic-gate return (CFGA_ERROR); 881*0Sstevel@tonic-gate } 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate if (num_ap_ids > 0 && ap_ids == NULL) { 884*0Sstevel@tonic-gate return (CFGA_ERROR); 885*0Sstevel@tonic-gate } 886*0Sstevel@tonic-gate 887*0Sstevel@tonic-gate /* 888*0Sstevel@tonic-gate * operate on each ap_id 889*0Sstevel@tonic-gate */ 890*0Sstevel@tonic-gate for (i = 0; (i < num_ap_ids) && (retval == CFGA_OK); i++) { 891*0Sstevel@tonic-gate libloc.libp = NULL; 892*0Sstevel@tonic-gate if ((retval = config_get_lib(ap_ids[i], &libloc, 893*0Sstevel@tonic-gate NULL)) != CFGA_OK) { 894*0Sstevel@tonic-gate return (retval); 895*0Sstevel@tonic-gate } 896*0Sstevel@tonic-gate 897*0Sstevel@tonic-gate errno = 0; 898*0Sstevel@tonic-gate retval = (*libloc.libp->cfga_help_p)(msgp, options, flags); 899*0Sstevel@tonic-gate rele_lib(libloc.libp); 900*0Sstevel@tonic-gate } 901*0Sstevel@tonic-gate return (retval); 902*0Sstevel@tonic-gate } 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate /* 905*0Sstevel@tonic-gate * Private support routines for the public interfaces 906*0Sstevel@tonic-gate */ 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate static const char * 909*0Sstevel@tonic-gate __config_strerror(cfga_err_t cfgerrnum) 910*0Sstevel@tonic-gate { 911*0Sstevel@tonic-gate const char *ep = NULL; 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate switch (cfgerrnum) { 914*0Sstevel@tonic-gate case CFGA_OK: 915*0Sstevel@tonic-gate ep = "Configuration operation succeeded"; 916*0Sstevel@tonic-gate break; 917*0Sstevel@tonic-gate case CFGA_NACK: 918*0Sstevel@tonic-gate ep = "Configuration operation cancelled"; 919*0Sstevel@tonic-gate break; 920*0Sstevel@tonic-gate case CFGA_INVAL: 921*0Sstevel@tonic-gate ep = "Configuration operation invalid"; 922*0Sstevel@tonic-gate break; 923*0Sstevel@tonic-gate case CFGA_NOTSUPP: 924*0Sstevel@tonic-gate ep = "Configuration administration not supported"; 925*0Sstevel@tonic-gate break; 926*0Sstevel@tonic-gate case CFGA_OPNOTSUPP: 927*0Sstevel@tonic-gate ep = "Configuration operation not supported"; 928*0Sstevel@tonic-gate break; 929*0Sstevel@tonic-gate case CFGA_PRIV: 930*0Sstevel@tonic-gate ep = "Insufficient privileges"; 931*0Sstevel@tonic-gate break; 932*0Sstevel@tonic-gate case CFGA_BUSY: 933*0Sstevel@tonic-gate ep = "Component system is busy, try again"; 934*0Sstevel@tonic-gate break; 935*0Sstevel@tonic-gate case CFGA_SYSTEM_BUSY: 936*0Sstevel@tonic-gate ep = "System is busy, try again"; 937*0Sstevel@tonic-gate break; 938*0Sstevel@tonic-gate case CFGA_DATA_ERROR: 939*0Sstevel@tonic-gate ep = "Data error"; 940*0Sstevel@tonic-gate break; 941*0Sstevel@tonic-gate case CFGA_LIB_ERROR: 942*0Sstevel@tonic-gate ep = "Library error"; 943*0Sstevel@tonic-gate break; 944*0Sstevel@tonic-gate case CFGA_NO_LIB: 945*0Sstevel@tonic-gate ep = "No Library found"; 946*0Sstevel@tonic-gate break; 947*0Sstevel@tonic-gate case CFGA_INSUFFICENT_CONDITION: 948*0Sstevel@tonic-gate ep = "Insufficient condition"; 949*0Sstevel@tonic-gate break; 950*0Sstevel@tonic-gate case CFGA_ERROR: 951*0Sstevel@tonic-gate ep = "Hardware specific failure"; 952*0Sstevel@tonic-gate break; 953*0Sstevel@tonic-gate case CFGA_APID_NOEXIST: 954*0Sstevel@tonic-gate ep = "Attachment point not found"; 955*0Sstevel@tonic-gate break; 956*0Sstevel@tonic-gate case CFGA_ATTR_INVAL: 957*0Sstevel@tonic-gate ep = "No attachment point with specified attributes found"; 958*0Sstevel@tonic-gate break; 959*0Sstevel@tonic-gate default: 960*0Sstevel@tonic-gate ep = NULL; 961*0Sstevel@tonic-gate break; 962*0Sstevel@tonic-gate } 963*0Sstevel@tonic-gate return (ep); 964*0Sstevel@tonic-gate } 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate /* 967*0Sstevel@tonic-gate * listopts is a string in the getsubopt(3C) style: 968*0Sstevel@tonic-gate * name1=value1,name2=value2, 969*0Sstevel@tonic-gate */ 970*0Sstevel@tonic-gate static cfga_err_t 971*0Sstevel@tonic-gate parse_listopt(char *listopts, char **classpp, char **errstring) 972*0Sstevel@tonic-gate { 973*0Sstevel@tonic-gate char *bufp, *optp, *val = NULL; 974*0Sstevel@tonic-gate cfga_err_t rc = CFGA_ERROR; 975*0Sstevel@tonic-gate 976*0Sstevel@tonic-gate *classpp = NULL; 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gate /* 979*0Sstevel@tonic-gate * NULL is a legal value for listopts 980*0Sstevel@tonic-gate */ 981*0Sstevel@tonic-gate if (listopts == NULL) { 982*0Sstevel@tonic-gate return (CFGA_OK); 983*0Sstevel@tonic-gate } 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate if ((bufp = config_calloc_check(1, strlen(listopts) + 1, errstring)) 986*0Sstevel@tonic-gate == NULL) { 987*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 988*0Sstevel@tonic-gate } 989*0Sstevel@tonic-gate (void) strcpy(bufp, listopts); 990*0Sstevel@tonic-gate 991*0Sstevel@tonic-gate optp = bufp; /* getsubopt() modifies its argument */ 992*0Sstevel@tonic-gate while (*optp != '\0') { 993*0Sstevel@tonic-gate switch (getsubopt(&optp, listopt_array, &val)) { 994*0Sstevel@tonic-gate case LISTOPT_CLASS: 995*0Sstevel@tonic-gate if (val == NULL || *classpp != NULL) { 996*0Sstevel@tonic-gate rc = CFGA_ERROR; 997*0Sstevel@tonic-gate goto out; 998*0Sstevel@tonic-gate } 999*0Sstevel@tonic-gate if ((*classpp = config_calloc_check(1, strlen(val) + 1, 1000*0Sstevel@tonic-gate errstring)) == NULL) { 1001*0Sstevel@tonic-gate rc = CFGA_LIB_ERROR; 1002*0Sstevel@tonic-gate goto out; 1003*0Sstevel@tonic-gate } 1004*0Sstevel@tonic-gate (void) strcpy(*classpp, val); 1005*0Sstevel@tonic-gate break; 1006*0Sstevel@tonic-gate default: 1007*0Sstevel@tonic-gate rc = CFGA_ERROR; 1008*0Sstevel@tonic-gate goto out; 1009*0Sstevel@tonic-gate } 1010*0Sstevel@tonic-gate } 1011*0Sstevel@tonic-gate 1012*0Sstevel@tonic-gate rc = CFGA_OK; 1013*0Sstevel@tonic-gate /*FALLTHRU*/ 1014*0Sstevel@tonic-gate out: 1015*0Sstevel@tonic-gate S_FREE(bufp); 1016*0Sstevel@tonic-gate if (rc != CFGA_OK) { 1017*0Sstevel@tonic-gate S_FREE(*classpp); 1018*0Sstevel@tonic-gate } 1019*0Sstevel@tonic-gate return (rc); 1020*0Sstevel@tonic-gate } 1021*0Sstevel@tonic-gate 1022*0Sstevel@tonic-gate /*ARGSUSED*/ 1023*0Sstevel@tonic-gate static cfga_err_t 1024*0Sstevel@tonic-gate null_mklog( 1025*0Sstevel@tonic-gate di_node_t node, 1026*0Sstevel@tonic-gate di_minor_t minor, 1027*0Sstevel@tonic-gate plugin_lib_t *libp, 1028*0Sstevel@tonic-gate lib_loc_t *liblocp) 1029*0Sstevel@tonic-gate { 1030*0Sstevel@tonic-gate return (CFGA_OK); 1031*0Sstevel@tonic-gate } 1032*0Sstevel@tonic-gate 1033*0Sstevel@tonic-gate static cfga_err_t 1034*0Sstevel@tonic-gate mklog_v1( 1035*0Sstevel@tonic-gate di_node_t node, 1036*0Sstevel@tonic-gate di_minor_t minor, 1037*0Sstevel@tonic-gate plugin_lib_t *libp, 1038*0Sstevel@tonic-gate lib_loc_t *liblocp) 1039*0Sstevel@tonic-gate { 1040*0Sstevel@tonic-gate const size_t len = CFGA_AP_LOG_ID_LEN; 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate assert(len <= sizeof (liblocp->ap_logical)); 1043*0Sstevel@tonic-gate 1044*0Sstevel@tonic-gate if (libp->plugin_vers != CFGA_HSL_V1) { 1045*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1046*0Sstevel@tonic-gate } 1047*0Sstevel@tonic-gate 1048*0Sstevel@tonic-gate return (mklog_common(node, minor, liblocp, len)); 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate /* 1053*0Sstevel@tonic-gate * Obtain the devlink from a /devices path 1054*0Sstevel@tonic-gate */ 1055*0Sstevel@tonic-gate static int 1056*0Sstevel@tonic-gate get_link(di_devlink_t devlink, void *arg) 1057*0Sstevel@tonic-gate { 1058*0Sstevel@tonic-gate char *linkp = (char *)arg; 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate (void) snprintf(linkp, CFGA_LOG_EXT_LEN, "%s", 1061*0Sstevel@tonic-gate di_devlink_path(devlink)); 1062*0Sstevel@tonic-gate return (DI_WALK_TERMINATE); 1063*0Sstevel@tonic-gate } 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate static cfga_err_t 1066*0Sstevel@tonic-gate mklog_v2( 1067*0Sstevel@tonic-gate di_node_t node, 1068*0Sstevel@tonic-gate di_minor_t minor, 1069*0Sstevel@tonic-gate plugin_lib_t *libp, 1070*0Sstevel@tonic-gate lib_loc_t *liblocp) 1071*0Sstevel@tonic-gate { 1072*0Sstevel@tonic-gate const size_t len = CFGA_LOG_EXT_LEN; 1073*0Sstevel@tonic-gate di_devlink_handle_t hdl; 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate assert(len <= sizeof (liblocp->ap_logical)); 1076*0Sstevel@tonic-gate 1077*0Sstevel@tonic-gate if (libp->plugin_vers != CFGA_HSL_V2) { 1078*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1079*0Sstevel@tonic-gate } 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate /* open devlink database */ 1082*0Sstevel@tonic-gate if ((hdl = di_devlink_init(NULL, 0)) == NULL) { 1083*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1084*0Sstevel@tonic-gate } 1085*0Sstevel@tonic-gate 1086*0Sstevel@tonic-gate liblocp->ap_logical[0] = '\0'; 1087*0Sstevel@tonic-gate (void) di_devlink_walk(hdl, NULL, 1088*0Sstevel@tonic-gate liblocp->ap_physical + strlen(DEVICES_DIR), 1089*0Sstevel@tonic-gate DI_PRIMARY_LINK, (void *)liblocp->ap_logical, get_link); 1090*0Sstevel@tonic-gate 1091*0Sstevel@tonic-gate (void) di_devlink_fini(&hdl); 1092*0Sstevel@tonic-gate 1093*0Sstevel@tonic-gate if (liblocp->ap_logical[0] != '\0') 1094*0Sstevel@tonic-gate return (CFGA_OK); 1095*0Sstevel@tonic-gate return (mklog_common(node, minor, liblocp, len)); 1096*0Sstevel@tonic-gate } 1097*0Sstevel@tonic-gate 1098*0Sstevel@tonic-gate /* 1099*0Sstevel@tonic-gate * mklog_common - make a logical name from the driver and instance 1100*0Sstevel@tonic-gate */ 1101*0Sstevel@tonic-gate static cfga_err_t 1102*0Sstevel@tonic-gate mklog_common( 1103*0Sstevel@tonic-gate di_node_t node, 1104*0Sstevel@tonic-gate di_minor_t minor, 1105*0Sstevel@tonic-gate lib_loc_t *libloc_p, 1106*0Sstevel@tonic-gate size_t len) 1107*0Sstevel@tonic-gate { 1108*0Sstevel@tonic-gate int inst; 1109*0Sstevel@tonic-gate char *drv, *minor_name; 1110*0Sstevel@tonic-gate 1111*0Sstevel@tonic-gate drv = di_driver_name(node); 1112*0Sstevel@tonic-gate inst = di_instance(node); 1113*0Sstevel@tonic-gate minor_name = di_minor_name(minor); 1114*0Sstevel@tonic-gate 1115*0Sstevel@tonic-gate errno = 0; 1116*0Sstevel@tonic-gate if (drv != NULL && inst != -1 && minor_name != NULL && 1117*0Sstevel@tonic-gate snprintf(libloc_p->ap_logical, len, "%s%d:%s", drv, inst, 1118*0Sstevel@tonic-gate minor_name) < len) { /* snprintf returns strlen */ 1119*0Sstevel@tonic-gate return (CFGA_OK); 1120*0Sstevel@tonic-gate } 1121*0Sstevel@tonic-gate 1122*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1123*0Sstevel@tonic-gate } 1124*0Sstevel@tonic-gate 1125*0Sstevel@tonic-gate /* 1126*0Sstevel@tonic-gate * resolve_lib_ref - relocate to use plugin lib 1127*0Sstevel@tonic-gate */ 1128*0Sstevel@tonic-gate static cfga_err_t 1129*0Sstevel@tonic-gate resolve_lib_ref( 1130*0Sstevel@tonic-gate plugin_lib_t *libp, 1131*0Sstevel@tonic-gate lib_loc_t *libloc_p) 1132*0Sstevel@tonic-gate { 1133*0Sstevel@tonic-gate void *sym; 1134*0Sstevel@tonic-gate void *libhdlp = libp->handle; 1135*0Sstevel@tonic-gate int plug_vers; 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate if ((sym = dlsym(libhdlp, "cfga_version")) == NULL) { 1138*0Sstevel@tonic-gate /* 1139*0Sstevel@tonic-gate * Version symbol not defined, must be the first version 1140*0Sstevel@tonic-gate */ 1141*0Sstevel@tonic-gate plug_vers = CFGA_HSL_V1; 1142*0Sstevel@tonic-gate } else { 1143*0Sstevel@tonic-gate plug_vers = *((int *)sym); 1144*0Sstevel@tonic-gate } 1145*0Sstevel@tonic-gate 1146*0Sstevel@tonic-gate /* 1147*0Sstevel@tonic-gate * Check if plugin version matches request. 1148*0Sstevel@tonic-gate */ 1149*0Sstevel@tonic-gate if (!compat_plugin(&libloc_p->vers_req, plug_vers)) { 1150*0Sstevel@tonic-gate return (CFGA_NO_LIB); 1151*0Sstevel@tonic-gate } 1152*0Sstevel@tonic-gate 1153*0Sstevel@tonic-gate /* 1154*0Sstevel@tonic-gate * Record the plugin version and setup version dependant routines 1155*0Sstevel@tonic-gate */ 1156*0Sstevel@tonic-gate assert(plug_vers < VERS_ARRAY_SZ); 1157*0Sstevel@tonic-gate libp->plugin_vers = plug_vers; 1158*0Sstevel@tonic-gate libp->vers_ops = &cfga_vers_ops[plug_vers]; 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate /* resolve symbols common to all versions */ 1161*0Sstevel@tonic-gate if ((sym = dlsym(libhdlp, "cfga_change_state")) == NULL) { 1162*0Sstevel@tonic-gate perror("dlsym: cfga_change_state"); 1163*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1164*0Sstevel@tonic-gate } else 1165*0Sstevel@tonic-gate libp->cfga_change_state_p = (cfga_err_t (*)(cfga_cmd_t, 1166*0Sstevel@tonic-gate const char *, const char *, struct cfga_confirm *, 1167*0Sstevel@tonic-gate struct cfga_msg *, char **, cfga_flags_t)) sym; 1168*0Sstevel@tonic-gate 1169*0Sstevel@tonic-gate if ((sym = dlsym(libhdlp, "cfga_private_func")) == NULL) { 1170*0Sstevel@tonic-gate perror("dlsym: cfga_private_func"); 1171*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1172*0Sstevel@tonic-gate } else 1173*0Sstevel@tonic-gate libp->cfga_private_func_p = (cfga_err_t (*)(const char *, 1174*0Sstevel@tonic-gate const char *, const char *, struct cfga_confirm *, 1175*0Sstevel@tonic-gate struct cfga_msg *, char **, cfga_flags_t))sym; 1176*0Sstevel@tonic-gate 1177*0Sstevel@tonic-gate if ((sym = dlsym(libhdlp, "cfga_test")) == NULL) { 1178*0Sstevel@tonic-gate perror("dlsym: cfga_test"); 1179*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1180*0Sstevel@tonic-gate } else 1181*0Sstevel@tonic-gate libp->cfga_test_p = (cfga_err_t (*)(const char *, const char *, 1182*0Sstevel@tonic-gate struct cfga_msg *, char **, cfga_flags_t))sym; 1183*0Sstevel@tonic-gate 1184*0Sstevel@tonic-gate if ((sym = dlsym(libhdlp, "cfga_help")) == NULL) { 1185*0Sstevel@tonic-gate perror("dlsym: cfga_help"); 1186*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1187*0Sstevel@tonic-gate } else 1188*0Sstevel@tonic-gate libp->cfga_help_p = (cfga_err_t (*)(struct cfga_msg *, 1189*0Sstevel@tonic-gate const char *, cfga_flags_t))sym; 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate if ((sym = dlsym(libhdlp, "cfga_ap_id_cmp")) == NULL) { 1192*0Sstevel@tonic-gate libp->cfga_ap_id_cmp_p = default_ap_id_cmp; 1193*0Sstevel@tonic-gate } else 1194*0Sstevel@tonic-gate libp->cfga_ap_id_cmp_p = (int (*)(const 1195*0Sstevel@tonic-gate cfga_ap_log_id_t, const cfga_ap_log_id_t))sym; 1196*0Sstevel@tonic-gate 1197*0Sstevel@tonic-gate /* Resolve version specific symbols */ 1198*0Sstevel@tonic-gate return (libp->vers_ops->resolve_lib(libp)); 1199*0Sstevel@tonic-gate } 1200*0Sstevel@tonic-gate 1201*0Sstevel@tonic-gate /*ARGSUSED*/ 1202*0Sstevel@tonic-gate static cfga_err_t 1203*0Sstevel@tonic-gate null_resolve(plugin_lib_t *libp) 1204*0Sstevel@tonic-gate { 1205*0Sstevel@tonic-gate return (CFGA_OK); 1206*0Sstevel@tonic-gate } 1207*0Sstevel@tonic-gate 1208*0Sstevel@tonic-gate static cfga_err_t 1209*0Sstevel@tonic-gate resolve_v1(plugin_lib_t *libp) 1210*0Sstevel@tonic-gate { 1211*0Sstevel@tonic-gate void *sym, *libhdlp = libp->handle; 1212*0Sstevel@tonic-gate 1213*0Sstevel@tonic-gate 1214*0Sstevel@tonic-gate if (libp->plugin_vers != CFGA_HSL_V1) { 1215*0Sstevel@tonic-gate return (CFGA_NO_LIB); 1216*0Sstevel@tonic-gate } 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gate if ((sym = dlsym(libhdlp, "cfga_stat")) == NULL) { 1219*0Sstevel@tonic-gate perror("dlsym: cfga_stat"); 1220*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1221*0Sstevel@tonic-gate } else 1222*0Sstevel@tonic-gate libp->cfga_stat_p = (cfga_err_t (*)(const char *, 1223*0Sstevel@tonic-gate struct cfga_stat_data *, const char *, 1224*0Sstevel@tonic-gate char **))sym; 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate if ((sym = dlsym(libhdlp, "cfga_list")) == NULL) { 1227*0Sstevel@tonic-gate perror("dlsym: cfga_list"); 1228*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1229*0Sstevel@tonic-gate } else 1230*0Sstevel@tonic-gate libp->cfga_list_p = (cfga_err_t (*)(struct cfga_stat_data **, 1231*0Sstevel@tonic-gate int *, const char *, char **))sym; 1232*0Sstevel@tonic-gate 1233*0Sstevel@tonic-gate return (CFGA_OK); 1234*0Sstevel@tonic-gate } 1235*0Sstevel@tonic-gate 1236*0Sstevel@tonic-gate static cfga_err_t 1237*0Sstevel@tonic-gate resolve_v2(plugin_lib_t *libp) 1238*0Sstevel@tonic-gate { 1239*0Sstevel@tonic-gate void *sym; 1240*0Sstevel@tonic-gate 1241*0Sstevel@tonic-gate 1242*0Sstevel@tonic-gate if (libp->plugin_vers != CFGA_HSL_V2) { 1243*0Sstevel@tonic-gate return (CFGA_NO_LIB); 1244*0Sstevel@tonic-gate } 1245*0Sstevel@tonic-gate 1246*0Sstevel@tonic-gate if ((sym = dlsym(libp->handle, "cfga_list_ext")) == NULL) { 1247*0Sstevel@tonic-gate perror("dlsym: cfga_list_ext"); 1248*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1249*0Sstevel@tonic-gate } else { 1250*0Sstevel@tonic-gate libp->cfga_list_ext_p = (cfga_err_t (*)(const char *, 1251*0Sstevel@tonic-gate struct cfga_list_data **, int *, const char *, 1252*0Sstevel@tonic-gate const char *, char **, cfga_flags_t))sym; 1253*0Sstevel@tonic-gate return (CFGA_OK); 1254*0Sstevel@tonic-gate } 1255*0Sstevel@tonic-gate } 1256*0Sstevel@tonic-gate 1257*0Sstevel@tonic-gate /* 1258*0Sstevel@tonic-gate * config_calloc_check - perform allocation, check result and 1259*0Sstevel@tonic-gate * set error string 1260*0Sstevel@tonic-gate */ 1261*0Sstevel@tonic-gate static void * 1262*0Sstevel@tonic-gate config_calloc_check( 1263*0Sstevel@tonic-gate size_t nelem, 1264*0Sstevel@tonic-gate size_t elsize, 1265*0Sstevel@tonic-gate char **errstring) 1266*0Sstevel@tonic-gate { 1267*0Sstevel@tonic-gate void *p; 1268*0Sstevel@tonic-gate 1269*0Sstevel@tonic-gate p = calloc(nelem, elsize); 1270*0Sstevel@tonic-gate if (p == NULL) { 1271*0Sstevel@tonic-gate config_err(0, ALLOC_FAILED, errstring); 1272*0Sstevel@tonic-gate } 1273*0Sstevel@tonic-gate 1274*0Sstevel@tonic-gate return (p); 1275*0Sstevel@tonic-gate } 1276*0Sstevel@tonic-gate 1277*0Sstevel@tonic-gate 1278*0Sstevel@tonic-gate /* 1279*0Sstevel@tonic-gate * config_get_lib - given an ap_id find the library name 1280*0Sstevel@tonic-gate * If successful, the plugin library is held. 1281*0Sstevel@tonic-gate */ 1282*0Sstevel@tonic-gate static cfga_err_t 1283*0Sstevel@tonic-gate config_get_lib( 1284*0Sstevel@tonic-gate const char *ap_id, 1285*0Sstevel@tonic-gate lib_loc_t *lib_loc_p, 1286*0Sstevel@tonic-gate char **errstring) 1287*0Sstevel@tonic-gate { 1288*0Sstevel@tonic-gate char *dyncomp, path[PATH_MAX]; 1289*0Sstevel@tonic-gate char *apdup; 1290*0Sstevel@tonic-gate cfga_ap_types_t type = UNKNOWN_AP; 1291*0Sstevel@tonic-gate cfga_err_t ret = CFGA_ERROR; 1292*0Sstevel@tonic-gate 1293*0Sstevel@tonic-gate if (ap_id == NULL) { 1294*0Sstevel@tonic-gate config_err(0, INVALID_ARGS, errstring); 1295*0Sstevel@tonic-gate return (ret); 1296*0Sstevel@tonic-gate } 1297*0Sstevel@tonic-gate 1298*0Sstevel@tonic-gate lib_loc_p->libp = NULL; 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate if ((apdup = config_calloc_check(1, strlen(ap_id) + 1, errstring)) 1301*0Sstevel@tonic-gate == NULL) { 1302*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1303*0Sstevel@tonic-gate } 1304*0Sstevel@tonic-gate (void) strcpy(apdup, ap_id); 1305*0Sstevel@tonic-gate 1306*0Sstevel@tonic-gate /* 1307*0Sstevel@tonic-gate * Separate into base and dynamic components 1308*0Sstevel@tonic-gate */ 1309*0Sstevel@tonic-gate if ((ret = split_apid(apdup, &dyncomp, errstring)) != CFGA_OK) { 1310*0Sstevel@tonic-gate goto out; 1311*0Sstevel@tonic-gate } 1312*0Sstevel@tonic-gate 1313*0Sstevel@tonic-gate /* 1314*0Sstevel@tonic-gate * No upper limit on version 1315*0Sstevel@tonic-gate */ 1316*0Sstevel@tonic-gate lib_loc_p->vers_req.v_max = CFGA_HSL_VERS; 1317*0Sstevel@tonic-gate if (dyncomp != NULL) { 1318*0Sstevel@tonic-gate /* 1319*0Sstevel@tonic-gate * We need atleast version 2 of the plug-in library 1320*0Sstevel@tonic-gate * interface since the ap_id has a dynamic component. 1321*0Sstevel@tonic-gate */ 1322*0Sstevel@tonic-gate 1323*0Sstevel@tonic-gate lib_loc_p->vers_req.v_min = CFGA_HSL_V2; 1324*0Sstevel@tonic-gate } else { 1325*0Sstevel@tonic-gate lib_loc_p->vers_req.v_min = CFGA_HSL_V1; 1326*0Sstevel@tonic-gate } 1327*0Sstevel@tonic-gate 1328*0Sstevel@tonic-gate /* 1329*0Sstevel@tonic-gate * If the ap_id is a devlink in CFGA_DEV_DIR, follow link 1330*0Sstevel@tonic-gate * to get the physical ap_id. 1331*0Sstevel@tonic-gate */ 1332*0Sstevel@tonic-gate if ((type = find_arg_type(apdup)) == LOGICAL_LINK_AP) { 1333*0Sstevel@tonic-gate (void) snprintf(lib_loc_p->ap_base, sizeof (lib_loc_p->ap_base), 1334*0Sstevel@tonic-gate "%s%s", CFGA_DEV_DIR SLASH, apdup); 1335*0Sstevel@tonic-gate } 1336*0Sstevel@tonic-gate 1337*0Sstevel@tonic-gate path[sizeof (path) - 1] = '\0'; 1338*0Sstevel@tonic-gate if (type == LOGICAL_LINK_AP && realpath(lib_loc_p->ap_base, path) 1339*0Sstevel@tonic-gate != NULL) { 1340*0Sstevel@tonic-gate (void) snprintf(lib_loc_p->ap_base, sizeof (lib_loc_p->ap_base), 1341*0Sstevel@tonic-gate "%s", path); 1342*0Sstevel@tonic-gate } else { 1343*0Sstevel@tonic-gate (void) snprintf(lib_loc_p->ap_base, sizeof (lib_loc_p->ap_base), 1344*0Sstevel@tonic-gate "%s", apdup); 1345*0Sstevel@tonic-gate } 1346*0Sstevel@tonic-gate 1347*0Sstevel@tonic-gate 1348*0Sstevel@tonic-gate /* 1349*0Sstevel@tonic-gate * find and load the library 1350*0Sstevel@tonic-gate * The base component of the ap_id is used to locate the plug-in 1351*0Sstevel@tonic-gate */ 1352*0Sstevel@tonic-gate if ((type = find_arg_type(lib_loc_p->ap_base)) == PHYSICAL_AP) { 1353*0Sstevel@tonic-gate /* 1354*0Sstevel@tonic-gate * physical ap_id: Use ap_base as root for tree walk 1355*0Sstevel@tonic-gate * A link based apid (logical) will resolve to a physical 1356*0Sstevel@tonic-gate * ap_id. 1357*0Sstevel@tonic-gate */ 1358*0Sstevel@tonic-gate ret = find_ap_common(lib_loc_p, lib_loc_p->ap_base, 1359*0Sstevel@tonic-gate check_ap_phys, errstring); 1360*0Sstevel@tonic-gate } else if ((type == LOGICAL_DRV_AP) || 1361*0Sstevel@tonic-gate (type == AP_TYPE && dyncomp == NULL)) { 1362*0Sstevel@tonic-gate /* 1363*0Sstevel@tonic-gate * logical ap_id or ap_type: Use "/" as root for tree walk 1364*0Sstevel@tonic-gate * Note: an aptype cannot have a dynamic component 1365*0Sstevel@tonic-gate */ 1366*0Sstevel@tonic-gate ret = find_ap_common(lib_loc_p, "/", check_ap, errstring); 1367*0Sstevel@tonic-gate } else { 1368*0Sstevel@tonic-gate ret = CFGA_APID_NOEXIST; 1369*0Sstevel@tonic-gate } 1370*0Sstevel@tonic-gate 1371*0Sstevel@tonic-gate if (ret == CFGA_OK) { 1372*0Sstevel@tonic-gate #ifndef NDEBUG 1373*0Sstevel@tonic-gate /* 1374*0Sstevel@tonic-gate * variables used by assert() only which is disabled 1375*0Sstevel@tonic-gate * by defining NDEBUG (see top of this file) 1376*0Sstevel@tonic-gate */ 1377*0Sstevel@tonic-gate plugin_lib_t *libp; 1378*0Sstevel@tonic-gate 1379*0Sstevel@tonic-gate libp = lib_loc_p->libp; 1380*0Sstevel@tonic-gate #endif /* NDEBUG */ 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate assert(strcmp(libp->libpath, lib_loc_p->pathname) == 0); 1383*0Sstevel@tonic-gate assert(VALID_HSL_VERS(libp->plugin_vers)); 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate /* 1386*0Sstevel@tonic-gate * If a dynamic component was present, v1 plug-ins are not 1387*0Sstevel@tonic-gate * acceptable. 1388*0Sstevel@tonic-gate */ 1389*0Sstevel@tonic-gate assert(dyncomp == NULL || libp->plugin_vers >= CFGA_HSL_V2); 1390*0Sstevel@tonic-gate 1391*0Sstevel@tonic-gate /* 1392*0Sstevel@tonic-gate * ap_physical is passed to plugins as their ap_id argument. 1393*0Sstevel@tonic-gate * Append dynamic component if any. 1394*0Sstevel@tonic-gate */ 1395*0Sstevel@tonic-gate append_dyn(lib_loc_p->ap_physical, dyncomp, 1396*0Sstevel@tonic-gate sizeof (lib_loc_p->ap_physical)); 1397*0Sstevel@tonic-gate } 1398*0Sstevel@tonic-gate 1399*0Sstevel@tonic-gate /* cleanup */ 1400*0Sstevel@tonic-gate lib_loc_p->vers_req.v_min = INVALID_VERSION; 1401*0Sstevel@tonic-gate lib_loc_p->vers_req.v_max = INVALID_VERSION; 1402*0Sstevel@tonic-gate *lib_loc_p->ap_base = '\0'; 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate /*FALLTHRU*/ 1405*0Sstevel@tonic-gate out: 1406*0Sstevel@tonic-gate S_FREE(apdup); 1407*0Sstevel@tonic-gate S_FREE(dyncomp); 1408*0Sstevel@tonic-gate if (ret != CFGA_OK) { 1409*0Sstevel@tonic-gate lib_loc_p->libp = NULL; 1410*0Sstevel@tonic-gate } 1411*0Sstevel@tonic-gate 1412*0Sstevel@tonic-gate assert(ret != CFGA_OK || lib_loc_p->libp != NULL); 1413*0Sstevel@tonic-gate 1414*0Sstevel@tonic-gate return (ret); 1415*0Sstevel@tonic-gate } 1416*0Sstevel@tonic-gate 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate /* 1419*0Sstevel@tonic-gate * load_lib - Given a library pathname, create a entry for it 1420*0Sstevel@tonic-gate * in the library list, if one does not already exist, and read 1421*0Sstevel@tonic-gate * lock it to keep it there. 1422*0Sstevel@tonic-gate */ 1423*0Sstevel@tonic-gate static cfga_err_t 1424*0Sstevel@tonic-gate load_lib( 1425*0Sstevel@tonic-gate di_node_t node, 1426*0Sstevel@tonic-gate di_minor_t minor, 1427*0Sstevel@tonic-gate lib_loc_t *libloc_p) 1428*0Sstevel@tonic-gate { 1429*0Sstevel@tonic-gate plugin_lib_t *libp, *list_libp; 1430*0Sstevel@tonic-gate char *devfs_path; 1431*0Sstevel@tonic-gate 1432*0Sstevel@tonic-gate /* 1433*0Sstevel@tonic-gate * lock the library list 1434*0Sstevel@tonic-gate */ 1435*0Sstevel@tonic-gate (void) mutex_lock(&plugin_list_lock); 1436*0Sstevel@tonic-gate 1437*0Sstevel@tonic-gate /* 1438*0Sstevel@tonic-gate * see if lib exist in list, if not, allocate a new one 1439*0Sstevel@tonic-gate */ 1440*0Sstevel@tonic-gate list_libp = lib_in_list(libloc_p->pathname); 1441*0Sstevel@tonic-gate if (list_libp != NULL) { 1442*0Sstevel@tonic-gate hold_lib(list_libp); 1443*0Sstevel@tonic-gate (void) mutex_unlock(&plugin_list_lock); 1444*0Sstevel@tonic-gate 1445*0Sstevel@tonic-gate /* fill in logical and physical name in libloc_p */ 1446*0Sstevel@tonic-gate libloc_p->libp = libp = list_libp; 1447*0Sstevel@tonic-gate if (libp->vers_ops->mklog(node, minor, libp, libloc_p) 1448*0Sstevel@tonic-gate != CFGA_OK) { 1449*0Sstevel@tonic-gate rele_lib(list_libp); 1450*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1451*0Sstevel@tonic-gate } 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate devfs_path = di_devfs_path(node); 1454*0Sstevel@tonic-gate (void) snprintf(libloc_p->ap_physical, MAXPATHLEN, "%s%s:%s", 1455*0Sstevel@tonic-gate DEVICES_DIR, devfs_path, di_minor_name(minor)); 1456*0Sstevel@tonic-gate di_devfs_path_free(devfs_path); 1457*0Sstevel@tonic-gate 1458*0Sstevel@tonic-gate return (CFGA_OK); 1459*0Sstevel@tonic-gate } 1460*0Sstevel@tonic-gate 1461*0Sstevel@tonic-gate /* allocate a new plugin_lib_t structure */ 1462*0Sstevel@tonic-gate libp = config_calloc_check(1, sizeof (plugin_lib_t), NULL); 1463*0Sstevel@tonic-gate if (libp == NULL) { 1464*0Sstevel@tonic-gate (void) mutex_unlock(&plugin_list_lock); 1465*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1466*0Sstevel@tonic-gate } 1467*0Sstevel@tonic-gate 1468*0Sstevel@tonic-gate (void) snprintf(libp->libpath, sizeof (libp->libpath), "%s", 1469*0Sstevel@tonic-gate libloc_p->pathname); 1470*0Sstevel@tonic-gate 1471*0Sstevel@tonic-gate /* 1472*0Sstevel@tonic-gate * ensure that the lib is open and linked in 1473*0Sstevel@tonic-gate */ 1474*0Sstevel@tonic-gate libp->handle = dlopen(libp->libpath, RTLD_NOW); 1475*0Sstevel@tonic-gate if (libp->handle == NULL) { 1476*0Sstevel@tonic-gate (void) mutex_unlock(&plugin_list_lock); 1477*0Sstevel@tonic-gate free(libp); 1478*0Sstevel@tonic-gate return (CFGA_NO_LIB); 1479*0Sstevel@tonic-gate } 1480*0Sstevel@tonic-gate 1481*0Sstevel@tonic-gate if (resolve_lib_ref(libp, libloc_p) != CFGA_OK || 1482*0Sstevel@tonic-gate libp->vers_ops->mklog(node, minor, libp, libloc_p) != CFGA_OK) { 1483*0Sstevel@tonic-gate (void) mutex_unlock(&plugin_list_lock); 1484*0Sstevel@tonic-gate (void) dlclose(libp->handle); 1485*0Sstevel@tonic-gate free(libp); 1486*0Sstevel@tonic-gate return (CFGA_NO_LIB); 1487*0Sstevel@tonic-gate } 1488*0Sstevel@tonic-gate 1489*0Sstevel@tonic-gate /* 1490*0Sstevel@tonic-gate * link in new entry to the end of list 1491*0Sstevel@tonic-gate */ 1492*0Sstevel@tonic-gate list_libp = &plugin_list; 1493*0Sstevel@tonic-gate while (list_libp->next != NULL) 1494*0Sstevel@tonic-gate list_libp = list_libp->next; 1495*0Sstevel@tonic-gate libp->next = list_libp->next; 1496*0Sstevel@tonic-gate list_libp->next = libp; 1497*0Sstevel@tonic-gate 1498*0Sstevel@tonic-gate /* Initialize refcnt to 1 */ 1499*0Sstevel@tonic-gate libp->refcnt = 1; 1500*0Sstevel@tonic-gate (void) mutex_init(&libp->lock, USYNC_THREAD, NULL); 1501*0Sstevel@tonic-gate 1502*0Sstevel@tonic-gate (void) mutex_unlock(&plugin_list_lock); 1503*0Sstevel@tonic-gate 1504*0Sstevel@tonic-gate /* 1505*0Sstevel@tonic-gate * record libp and physical node name in the libloc struct 1506*0Sstevel@tonic-gate */ 1507*0Sstevel@tonic-gate libloc_p->libp = libp; 1508*0Sstevel@tonic-gate devfs_path = di_devfs_path(node); 1509*0Sstevel@tonic-gate (void) snprintf(libloc_p->ap_physical, MAXPATHLEN, "%s%s:%s", 1510*0Sstevel@tonic-gate DEVICES_DIR, devfs_path, di_minor_name(minor)); 1511*0Sstevel@tonic-gate di_devfs_path_free(devfs_path); 1512*0Sstevel@tonic-gate 1513*0Sstevel@tonic-gate return (CFGA_OK); 1514*0Sstevel@tonic-gate } 1515*0Sstevel@tonic-gate 1516*0Sstevel@tonic-gate 1517*0Sstevel@tonic-gate #define NUM_LIB_NAMES 2 1518*0Sstevel@tonic-gate 1519*0Sstevel@tonic-gate /* 1520*0Sstevel@tonic-gate * find_lib - Given an attachment point node find it's library 1521*0Sstevel@tonic-gate * 1522*0Sstevel@tonic-gate */ 1523*0Sstevel@tonic-gate static cfga_err_t 1524*0Sstevel@tonic-gate find_lib( 1525*0Sstevel@tonic-gate di_node_t node, 1526*0Sstevel@tonic-gate di_minor_t minor, 1527*0Sstevel@tonic-gate lib_loc_t *libloc_p) 1528*0Sstevel@tonic-gate { 1529*0Sstevel@tonic-gate char lib[MAXPATHLEN]; 1530*0Sstevel@tonic-gate char name[NUM_LIB_NAMES][MAXPATHLEN]; 1531*0Sstevel@tonic-gate struct stat lib_stat; 1532*0Sstevel@tonic-gate void *dlhandle = NULL; 1533*0Sstevel@tonic-gate static char machine_name[SYSINFO_LENGTH]; 1534*0Sstevel@tonic-gate static char arch_name[SYSINFO_LENGTH]; 1535*0Sstevel@tonic-gate int i = 0; 1536*0Sstevel@tonic-gate char *class = NULL, *drv = NULL; 1537*0Sstevel@tonic-gate 1538*0Sstevel@tonic-gate 1539*0Sstevel@tonic-gate /* Make sure pathname and class is null if we fail */ 1540*0Sstevel@tonic-gate *libloc_p->ap_class = *libloc_p->pathname = *lib = '\0'; 1541*0Sstevel@tonic-gate 1542*0Sstevel@tonic-gate /* 1543*0Sstevel@tonic-gate * Initialize machine name and arch name 1544*0Sstevel@tonic-gate */ 1545*0Sstevel@tonic-gate if (strncmp("", machine_name, MAXPATHLEN) == 0) { 1546*0Sstevel@tonic-gate if (sysinfo(SI_MACHINE, machine_name, SYSINFO_LENGTH) == -1) { 1547*0Sstevel@tonic-gate return (CFGA_ERROR); 1548*0Sstevel@tonic-gate } 1549*0Sstevel@tonic-gate if (sysinfo(SI_ARCHITECTURE, arch_name, SYSINFO_LENGTH) == -1) { 1550*0Sstevel@tonic-gate return (CFGA_ERROR); 1551*0Sstevel@tonic-gate } 1552*0Sstevel@tonic-gate } 1553*0Sstevel@tonic-gate 1554*0Sstevel@tonic-gate /* 1555*0Sstevel@tonic-gate * Initialize possible library tags. 1556*0Sstevel@tonic-gate */ 1557*0Sstevel@tonic-gate 1558*0Sstevel@tonic-gate drv = di_driver_name(node); 1559*0Sstevel@tonic-gate class = get_class(minor); 1560*0Sstevel@tonic-gate 1561*0Sstevel@tonic-gate if (drv == NULL || class == NULL) { 1562*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1563*0Sstevel@tonic-gate } 1564*0Sstevel@tonic-gate 1565*0Sstevel@tonic-gate i = 0; 1566*0Sstevel@tonic-gate (void) snprintf(&name[i++][0], sizeof (name[0]), "%s", drv); 1567*0Sstevel@tonic-gate (void) snprintf(&name[i++][0], sizeof (name[0]), "%s", class); 1568*0Sstevel@tonic-gate 1569*0Sstevel@tonic-gate /* 1570*0Sstevel@tonic-gate * Cycle through the array of names to find the library. 1571*0Sstevel@tonic-gate */ 1572*0Sstevel@tonic-gate for (i = 0; i < NUM_LIB_NAMES; i++) { 1573*0Sstevel@tonic-gate 1574*0Sstevel@tonic-gate /* Attachment points may not have a class (i.e. are generic) */ 1575*0Sstevel@tonic-gate if (name[i][0] == '\0') { 1576*0Sstevel@tonic-gate continue; 1577*0Sstevel@tonic-gate } 1578*0Sstevel@tonic-gate 1579*0Sstevel@tonic-gate /* 1580*0Sstevel@tonic-gate * Try path based upon machine name 1581*0Sstevel@tonic-gate */ 1582*0Sstevel@tonic-gate (void) snprintf(lib, sizeof (lib), "%s%s%s%s%s", 1583*0Sstevel@tonic-gate LIB_PATH_BASE1, machine_name, LIB_PATH_MIDDLE, 1584*0Sstevel@tonic-gate name[i], LIB_PATH_TAIL); 1585*0Sstevel@tonic-gate 1586*0Sstevel@tonic-gate 1587*0Sstevel@tonic-gate if (stat(lib, &lib_stat) == 0) { 1588*0Sstevel@tonic-gate /* file exists, is it a lib */ 1589*0Sstevel@tonic-gate dlhandle = dlopen(lib, RTLD_LAZY); 1590*0Sstevel@tonic-gate if (dlhandle != NULL) { 1591*0Sstevel@tonic-gate goto found; 1592*0Sstevel@tonic-gate } 1593*0Sstevel@tonic-gate } 1594*0Sstevel@tonic-gate 1595*0Sstevel@tonic-gate /* 1596*0Sstevel@tonic-gate * Try path based upon arch name 1597*0Sstevel@tonic-gate */ 1598*0Sstevel@tonic-gate (void) snprintf(lib, sizeof (lib), "%s%s%s%s%s", 1599*0Sstevel@tonic-gate LIB_PATH_BASE1, arch_name, LIB_PATH_MIDDLE, 1600*0Sstevel@tonic-gate name[i], LIB_PATH_TAIL); 1601*0Sstevel@tonic-gate 1602*0Sstevel@tonic-gate if (stat(lib, &lib_stat) == 0) { 1603*0Sstevel@tonic-gate /* file exists, is it a lib */ 1604*0Sstevel@tonic-gate dlhandle = dlopen(lib, RTLD_LAZY); 1605*0Sstevel@tonic-gate if (dlhandle != NULL) { 1606*0Sstevel@tonic-gate goto found; 1607*0Sstevel@tonic-gate } 1608*0Sstevel@tonic-gate 1609*0Sstevel@tonic-gate } 1610*0Sstevel@tonic-gate 1611*0Sstevel@tonic-gate /* 1612*0Sstevel@tonic-gate * Try generic location 1613*0Sstevel@tonic-gate */ 1614*0Sstevel@tonic-gate (void) snprintf(lib, sizeof (lib), "%s%s%s%s", 1615*0Sstevel@tonic-gate LIB_PATH_BASE2, LIB_PATH_MIDDLE, name[i], LIB_PATH_TAIL); 1616*0Sstevel@tonic-gate 1617*0Sstevel@tonic-gate 1618*0Sstevel@tonic-gate 1619*0Sstevel@tonic-gate if (stat(lib, &lib_stat) == 0) { 1620*0Sstevel@tonic-gate /* file exists, is it a lib */ 1621*0Sstevel@tonic-gate dlhandle = dlopen(lib, RTLD_LAZY); 1622*0Sstevel@tonic-gate if (dlhandle != NULL) { 1623*0Sstevel@tonic-gate goto found; 1624*0Sstevel@tonic-gate } 1625*0Sstevel@tonic-gate 1626*0Sstevel@tonic-gate } 1627*0Sstevel@tonic-gate } 1628*0Sstevel@tonic-gate 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gate return (CFGA_NO_LIB); 1631*0Sstevel@tonic-gate 1632*0Sstevel@tonic-gate found: 1633*0Sstevel@tonic-gate /* we got one! */ 1634*0Sstevel@tonic-gate (void) snprintf(libloc_p->pathname, sizeof (libloc_p->pathname), "%s", 1635*0Sstevel@tonic-gate lib); 1636*0Sstevel@tonic-gate 1637*0Sstevel@tonic-gate (void) dlclose(dlhandle); 1638*0Sstevel@tonic-gate 1639*0Sstevel@tonic-gate /* Record class name (if any) */ 1640*0Sstevel@tonic-gate (void) snprintf(libloc_p->ap_class, sizeof (libloc_p->ap_class), "%s", 1641*0Sstevel@tonic-gate class); 1642*0Sstevel@tonic-gate 1643*0Sstevel@tonic-gate return (CFGA_OK); 1644*0Sstevel@tonic-gate } 1645*0Sstevel@tonic-gate 1646*0Sstevel@tonic-gate static cfga_err_t 1647*0Sstevel@tonic-gate lookup_cache(lib_loc_t *libloc_p) 1648*0Sstevel@tonic-gate { 1649*0Sstevel@tonic-gate lib_cache_t *entry; 1650*0Sstevel@tonic-gate (void) mutex_lock(&lib_cache_lock); 1651*0Sstevel@tonic-gate entry = lib_cache; 1652*0Sstevel@tonic-gate while (entry) { 1653*0Sstevel@tonic-gate if (strcmp(entry->lc_ap_id, libloc_p->ap_base) == 0) { 1654*0Sstevel@tonic-gate plugin_lib_t *libp = entry->lc_libp; 1655*0Sstevel@tonic-gate libloc_p->libp = libp; 1656*0Sstevel@tonic-gate hold_lib(libp); 1657*0Sstevel@tonic-gate (void) strcpy(libloc_p->pathname, libp->libpath); 1658*0Sstevel@tonic-gate (void) strcpy(libloc_p->ap_physical, 1659*0Sstevel@tonic-gate entry->lc_ap_physical); 1660*0Sstevel@tonic-gate (void) strcpy(libloc_p->ap_logical, 1661*0Sstevel@tonic-gate entry->lc_ap_logical); 1662*0Sstevel@tonic-gate (void) mutex_unlock(&lib_cache_lock); 1663*0Sstevel@tonic-gate return (CFGA_OK); 1664*0Sstevel@tonic-gate } 1665*0Sstevel@tonic-gate entry = entry->lc_next; 1666*0Sstevel@tonic-gate } 1667*0Sstevel@tonic-gate (void) mutex_unlock(&lib_cache_lock); 1668*0Sstevel@tonic-gate 1669*0Sstevel@tonic-gate return (CFGA_ERROR); 1670*0Sstevel@tonic-gate } 1671*0Sstevel@tonic-gate 1672*0Sstevel@tonic-gate static void 1673*0Sstevel@tonic-gate update_cache(lib_loc_t *libloc_p) 1674*0Sstevel@tonic-gate { 1675*0Sstevel@tonic-gate lib_cache_t *entry; 1676*0Sstevel@tonic-gate entry = config_calloc_check(1, sizeof (lib_cache_t), NULL); 1677*0Sstevel@tonic-gate if (entry == NULL) 1678*0Sstevel@tonic-gate return; 1679*0Sstevel@tonic-gate 1680*0Sstevel@tonic-gate entry->lc_ap_id = strdup(libloc_p->ap_base); 1681*0Sstevel@tonic-gate entry->lc_ap_physical = strdup(libloc_p->ap_physical); 1682*0Sstevel@tonic-gate entry->lc_ap_logical = strdup(libloc_p->ap_logical); 1683*0Sstevel@tonic-gate if ((entry->lc_ap_id == NULL) || (entry->lc_ap_physical == NULL) || 1684*0Sstevel@tonic-gate (entry->lc_ap_logical == NULL)) { 1685*0Sstevel@tonic-gate free(entry->lc_ap_id); 1686*0Sstevel@tonic-gate free(entry->lc_ap_physical); 1687*0Sstevel@tonic-gate free(entry->lc_ap_logical); 1688*0Sstevel@tonic-gate free(entry); 1689*0Sstevel@tonic-gate return; 1690*0Sstevel@tonic-gate } 1691*0Sstevel@tonic-gate 1692*0Sstevel@tonic-gate (void) mutex_lock(&lib_cache_lock); 1693*0Sstevel@tonic-gate entry->lc_libp = libloc_p->libp; 1694*0Sstevel@tonic-gate entry->lc_next = lib_cache; 1695*0Sstevel@tonic-gate lib_cache = entry; 1696*0Sstevel@tonic-gate hold_lib(entry->lc_libp); /* prevent stale cache */ 1697*0Sstevel@tonic-gate (void) mutex_unlock(&lib_cache_lock); 1698*0Sstevel@tonic-gate } 1699*0Sstevel@tonic-gate 1700*0Sstevel@tonic-gate static void 1701*0Sstevel@tonic-gate destroy_cache() 1702*0Sstevel@tonic-gate { 1703*0Sstevel@tonic-gate lib_cache_t *entry, *next; 1704*0Sstevel@tonic-gate (void) mutex_lock(&lib_cache_lock); 1705*0Sstevel@tonic-gate entry = lib_cache; 1706*0Sstevel@tonic-gate while (entry) { 1707*0Sstevel@tonic-gate next = entry->lc_next; 1708*0Sstevel@tonic-gate rele_lib(entry->lc_libp); 1709*0Sstevel@tonic-gate free(entry->lc_ap_id); 1710*0Sstevel@tonic-gate free(entry->lc_ap_physical); 1711*0Sstevel@tonic-gate free(entry->lc_ap_logical); 1712*0Sstevel@tonic-gate free(entry); 1713*0Sstevel@tonic-gate entry = next; 1714*0Sstevel@tonic-gate } 1715*0Sstevel@tonic-gate (void) mutex_unlock(&lib_cache_lock); 1716*0Sstevel@tonic-gate } 1717*0Sstevel@tonic-gate 1718*0Sstevel@tonic-gate /* 1719*0Sstevel@tonic-gate * find_ap_common - locate a particular attachment point 1720*0Sstevel@tonic-gate */ 1721*0Sstevel@tonic-gate static cfga_err_t 1722*0Sstevel@tonic-gate find_ap_common( 1723*0Sstevel@tonic-gate lib_loc_t *libloc_p, 1724*0Sstevel@tonic-gate const char *physpath, 1725*0Sstevel@tonic-gate int (*fcn)(di_node_t node, di_minor_t minor, void *arg), 1726*0Sstevel@tonic-gate char **errstring) 1727*0Sstevel@tonic-gate { 1728*0Sstevel@tonic-gate di_node_t rnode; 1729*0Sstevel@tonic-gate char *cp, *rpath; 1730*0Sstevel@tonic-gate size_t len; 1731*0Sstevel@tonic-gate 1732*0Sstevel@tonic-gate if (lookup_cache(libloc_p) == CFGA_OK) 1733*0Sstevel@tonic-gate return (CFGA_OK); 1734*0Sstevel@tonic-gate 1735*0Sstevel@tonic-gate if ((rpath = config_calloc_check(1, strlen(physpath) + 1, 1736*0Sstevel@tonic-gate errstring)) == NULL) { 1737*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate 1740*0Sstevel@tonic-gate (void) strcpy(rpath, physpath); 1741*0Sstevel@tonic-gate 1742*0Sstevel@tonic-gate /* Remove devices prefix (if any) */ 1743*0Sstevel@tonic-gate len = strlen(DEVICES_DIR); 1744*0Sstevel@tonic-gate if (strncmp(rpath, DEVICES_DIR SLASH, len + strlen(SLASH)) == 0) { 1745*0Sstevel@tonic-gate (void) memmove(rpath, rpath + len, 1746*0Sstevel@tonic-gate strlen(rpath + len) + 1); 1747*0Sstevel@tonic-gate } 1748*0Sstevel@tonic-gate 1749*0Sstevel@tonic-gate /* Remove dynamic component if any */ 1750*0Sstevel@tonic-gate if ((cp = GET_DYN(rpath)) != NULL) { 1751*0Sstevel@tonic-gate *cp = '\0'; 1752*0Sstevel@tonic-gate } 1753*0Sstevel@tonic-gate 1754*0Sstevel@tonic-gate /* Remove minor name (if any) */ 1755*0Sstevel@tonic-gate if ((cp = strrchr(rpath, ':')) != NULL) { 1756*0Sstevel@tonic-gate *cp = '\0'; 1757*0Sstevel@tonic-gate } 1758*0Sstevel@tonic-gate 1759*0Sstevel@tonic-gate /* 1760*0Sstevel@tonic-gate * begin walk of device tree 1761*0Sstevel@tonic-gate */ 1762*0Sstevel@tonic-gate rnode = di_init(rpath, DINFOCPYALL); 1763*0Sstevel@tonic-gate S_FREE(rpath); 1764*0Sstevel@tonic-gate 1765*0Sstevel@tonic-gate if (rnode == DI_NODE_NIL) { 1766*0Sstevel@tonic-gate /* 1767*0Sstevel@tonic-gate * di_init() may fail because the ap_id does not exist 1768*0Sstevel@tonic-gate */ 1769*0Sstevel@tonic-gate if (errno == EINVAL || errno == ENXIO) { 1770*0Sstevel@tonic-gate return (CFGA_APID_NOEXIST); 1771*0Sstevel@tonic-gate } else { 1772*0Sstevel@tonic-gate config_err(errno, DI_INIT_FAILED, errstring); 1773*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 1774*0Sstevel@tonic-gate } 1775*0Sstevel@tonic-gate } 1776*0Sstevel@tonic-gate 1777*0Sstevel@tonic-gate libloc_p->libp = NULL; 1778*0Sstevel@tonic-gate libloc_p->status = CFGA_APID_NOEXIST; 1779*0Sstevel@tonic-gate 1780*0Sstevel@tonic-gate (void) di_walk_minor(rnode, "ddi_ctl:attachment_point", 1781*0Sstevel@tonic-gate DI_CHECK_ALIAS|DI_CHECK_INTERNAL_PATH, 1782*0Sstevel@tonic-gate libloc_p, fcn); 1783*0Sstevel@tonic-gate 1784*0Sstevel@tonic-gate di_fini(rnode); 1785*0Sstevel@tonic-gate 1786*0Sstevel@tonic-gate if (libloc_p->libp != NULL) { 1787*0Sstevel@tonic-gate update_cache(libloc_p); 1788*0Sstevel@tonic-gate return (CFGA_OK); 1789*0Sstevel@tonic-gate } else { 1790*0Sstevel@tonic-gate return (libloc_p->status); 1791*0Sstevel@tonic-gate } 1792*0Sstevel@tonic-gate } 1793*0Sstevel@tonic-gate 1794*0Sstevel@tonic-gate /* 1795*0Sstevel@tonic-gate * check_ap - called for each attachment point found 1796*0Sstevel@tonic-gate * 1797*0Sstevel@tonic-gate * This is used in cases where a particular attachment point 1798*0Sstevel@tonic-gate * or type of attachment point is specified via a logical name or ap_type. 1799*0Sstevel@tonic-gate * Not used for physical names or in the list case with no 1800*0Sstevel@tonic-gate * ap's specified. 1801*0Sstevel@tonic-gate */ 1802*0Sstevel@tonic-gate 1803*0Sstevel@tonic-gate static int 1804*0Sstevel@tonic-gate check_ap( 1805*0Sstevel@tonic-gate di_node_t node, 1806*0Sstevel@tonic-gate di_minor_t minor, 1807*0Sstevel@tonic-gate void *arg) 1808*0Sstevel@tonic-gate { 1809*0Sstevel@tonic-gate char *cp = NULL; 1810*0Sstevel@tonic-gate char aptype[MAXPATHLEN]; 1811*0Sstevel@tonic-gate char *recep_id = NULL; 1812*0Sstevel@tonic-gate char *node_minor; 1813*0Sstevel@tonic-gate char *drv_name; 1814*0Sstevel@tonic-gate char inst[MAXPATHLEN]; 1815*0Sstevel@tonic-gate char inst2[MAXPATHLEN]; 1816*0Sstevel@tonic-gate lib_loc_t *libloc_p; 1817*0Sstevel@tonic-gate int comparison_test; 1818*0Sstevel@tonic-gate int instance; 1819*0Sstevel@tonic-gate cfga_ap_types_t type; 1820*0Sstevel@tonic-gate 1821*0Sstevel@tonic-gate 1822*0Sstevel@tonic-gate libloc_p = (lib_loc_t *)arg; 1823*0Sstevel@tonic-gate 1824*0Sstevel@tonic-gate (void) snprintf(aptype, sizeof (aptype), "%s", libloc_p->ap_base); 1825*0Sstevel@tonic-gate 1826*0Sstevel@tonic-gate /* 1827*0Sstevel@tonic-gate * This routime handles only aptypes and driver based logical apids. 1828*0Sstevel@tonic-gate */ 1829*0Sstevel@tonic-gate type = find_arg_type(aptype); 1830*0Sstevel@tonic-gate if (type == LOGICAL_DRV_AP) { 1831*0Sstevel@tonic-gate cp = strchr(aptype, ':'); 1832*0Sstevel@tonic-gate *cp = '\0'; 1833*0Sstevel@tonic-gate recep_id = cp+1; 1834*0Sstevel@tonic-gate cp--; 1835*0Sstevel@tonic-gate while (isdigit(*cp) && cp != aptype) 1836*0Sstevel@tonic-gate cp--; 1837*0Sstevel@tonic-gate cp++; 1838*0Sstevel@tonic-gate 1839*0Sstevel@tonic-gate (void) snprintf(inst, sizeof (inst), "%s", cp); 1840*0Sstevel@tonic-gate 1841*0Sstevel@tonic-gate *cp = '\0'; 1842*0Sstevel@tonic-gate } else if (type != AP_TYPE) { 1843*0Sstevel@tonic-gate libloc_p->status = CFGA_APID_NOEXIST; 1844*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1845*0Sstevel@tonic-gate } 1846*0Sstevel@tonic-gate 1847*0Sstevel@tonic-gate node_minor = di_minor_name(minor); 1848*0Sstevel@tonic-gate drv_name = di_driver_name(node); 1849*0Sstevel@tonic-gate instance = di_instance(node); 1850*0Sstevel@tonic-gate 1851*0Sstevel@tonic-gate if (node_minor == NULL || drv_name == NULL || instance == -1) { 1852*0Sstevel@tonic-gate libloc_p->status = CFGA_APID_NOEXIST; 1853*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1854*0Sstevel@tonic-gate } 1855*0Sstevel@tonic-gate 1856*0Sstevel@tonic-gate (void) sprintf(inst2, "%d", instance); 1857*0Sstevel@tonic-gate 1858*0Sstevel@tonic-gate /* 1859*0Sstevel@tonic-gate * If the base matches driver and instance try and find a lib for it, 1860*0Sstevel@tonic-gate * then load it. On any failure we continue the walk. 1861*0Sstevel@tonic-gate * 1862*0Sstevel@tonic-gate * driver based logical ap_ids are derived from driver name + instance. 1863*0Sstevel@tonic-gate * Ap_types are just partial driver names. 1864*0Sstevel@tonic-gate * 1865*0Sstevel@tonic-gate */ 1866*0Sstevel@tonic-gate 1867*0Sstevel@tonic-gate comparison_test = 0; 1868*0Sstevel@tonic-gate if (type == AP_TYPE) { 1869*0Sstevel@tonic-gate if (strncmp(aptype, drv_name, strlen(aptype)) == 0) { 1870*0Sstevel@tonic-gate comparison_test = 1; 1871*0Sstevel@tonic-gate } 1872*0Sstevel@tonic-gate } else { 1873*0Sstevel@tonic-gate if (strcmp(aptype, drv_name) == 0 && 1874*0Sstevel@tonic-gate strcmp(recep_id, node_minor) == 0 && 1875*0Sstevel@tonic-gate strcmp(inst, inst2) == 0) { 1876*0Sstevel@tonic-gate comparison_test = 1; 1877*0Sstevel@tonic-gate } 1878*0Sstevel@tonic-gate } 1879*0Sstevel@tonic-gate 1880*0Sstevel@tonic-gate if (comparison_test) { 1881*0Sstevel@tonic-gate /* 1882*0Sstevel@tonic-gate * save the correct type of error so user does not get confused 1883*0Sstevel@tonic-gate */ 1884*0Sstevel@tonic-gate if (find_lib(node, minor, libloc_p) != CFGA_OK) { 1885*0Sstevel@tonic-gate libloc_p->status = CFGA_NO_LIB; 1886*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1887*0Sstevel@tonic-gate } 1888*0Sstevel@tonic-gate if (load_lib(node, minor, libloc_p) != CFGA_OK) { 1889*0Sstevel@tonic-gate libloc_p->status = CFGA_LIB_ERROR; 1890*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1891*0Sstevel@tonic-gate } 1892*0Sstevel@tonic-gate libloc_p->status = CFGA_OK; 1893*0Sstevel@tonic-gate return (DI_WALK_TERMINATE); 1894*0Sstevel@tonic-gate } else { 1895*0Sstevel@tonic-gate libloc_p->status = CFGA_APID_NOEXIST; 1896*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1897*0Sstevel@tonic-gate } 1898*0Sstevel@tonic-gate } 1899*0Sstevel@tonic-gate 1900*0Sstevel@tonic-gate 1901*0Sstevel@tonic-gate /* 1902*0Sstevel@tonic-gate * check_ap_phys - called for each attachment point found 1903*0Sstevel@tonic-gate * 1904*0Sstevel@tonic-gate * This is used in cases where a particular attachment point 1905*0Sstevel@tonic-gate * is specified via a physical name. If the name matches then 1906*0Sstevel@tonic-gate * we try and find and load the library for it. 1907*0Sstevel@tonic-gate */ 1908*0Sstevel@tonic-gate 1909*0Sstevel@tonic-gate static int 1910*0Sstevel@tonic-gate check_ap_phys( 1911*0Sstevel@tonic-gate di_node_t node, 1912*0Sstevel@tonic-gate di_minor_t minor, 1913*0Sstevel@tonic-gate void *arg) 1914*0Sstevel@tonic-gate { 1915*0Sstevel@tonic-gate lib_loc_t *libloc_p; 1916*0Sstevel@tonic-gate char phys_name[MAXPATHLEN]; 1917*0Sstevel@tonic-gate char *devfs_path; 1918*0Sstevel@tonic-gate char *minor_name; 1919*0Sstevel@tonic-gate 1920*0Sstevel@tonic-gate libloc_p = (lib_loc_t *)arg; 1921*0Sstevel@tonic-gate devfs_path = di_devfs_path(node); 1922*0Sstevel@tonic-gate minor_name = di_minor_name(minor); 1923*0Sstevel@tonic-gate 1924*0Sstevel@tonic-gate if (devfs_path == NULL || minor_name == NULL) { 1925*0Sstevel@tonic-gate libloc_p->status = CFGA_APID_NOEXIST; 1926*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1927*0Sstevel@tonic-gate } 1928*0Sstevel@tonic-gate 1929*0Sstevel@tonic-gate (void) snprintf(phys_name, sizeof (phys_name), "%s%s:%s", 1930*0Sstevel@tonic-gate DEVICES_DIR, devfs_path, minor_name); 1931*0Sstevel@tonic-gate 1932*0Sstevel@tonic-gate di_devfs_path_free(devfs_path); 1933*0Sstevel@tonic-gate 1934*0Sstevel@tonic-gate if (strcmp(phys_name, libloc_p->ap_base) == 0) { 1935*0Sstevel@tonic-gate if (find_lib(node, minor, libloc_p) != CFGA_OK) { 1936*0Sstevel@tonic-gate libloc_p->status = CFGA_NO_LIB; 1937*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1938*0Sstevel@tonic-gate } 1939*0Sstevel@tonic-gate if (load_lib(node, minor, libloc_p) != CFGA_OK) { 1940*0Sstevel@tonic-gate libloc_p->status = CFGA_LIB_ERROR; 1941*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1942*0Sstevel@tonic-gate } 1943*0Sstevel@tonic-gate libloc_p->status = CFGA_OK; 1944*0Sstevel@tonic-gate return (DI_WALK_TERMINATE); 1945*0Sstevel@tonic-gate } else { 1946*0Sstevel@tonic-gate libloc_p->status = CFGA_APID_NOEXIST; 1947*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1948*0Sstevel@tonic-gate } 1949*0Sstevel@tonic-gate } 1950*0Sstevel@tonic-gate 1951*0Sstevel@tonic-gate /* 1952*0Sstevel@tonic-gate * lib_in_list 1953*0Sstevel@tonic-gate * 1954*0Sstevel@tonic-gate * See if library, as specified by the full pathname and controller 1955*0Sstevel@tonic-gate * instance number is already represented in the plugin library list. 1956*0Sstevel@tonic-gate * If the instance number is -1 it is ignored. 1957*0Sstevel@tonic-gate */ 1958*0Sstevel@tonic-gate static plugin_lib_t * 1959*0Sstevel@tonic-gate lib_in_list(char *libpath) 1960*0Sstevel@tonic-gate { 1961*0Sstevel@tonic-gate plugin_lib_t *libp = NULL; 1962*0Sstevel@tonic-gate 1963*0Sstevel@tonic-gate for (libp = plugin_list.next; libp != NULL; libp = libp->next) { 1964*0Sstevel@tonic-gate if (strncmp(libpath, libp->libpath, MAXPATHLEN) == 0) { 1965*0Sstevel@tonic-gate return (libp); 1966*0Sstevel@tonic-gate } 1967*0Sstevel@tonic-gate } 1968*0Sstevel@tonic-gate return (NULL); 1969*0Sstevel@tonic-gate } 1970*0Sstevel@tonic-gate 1971*0Sstevel@tonic-gate 1972*0Sstevel@tonic-gate 1973*0Sstevel@tonic-gate 1974*0Sstevel@tonic-gate /* 1975*0Sstevel@tonic-gate * Coalesce stat and list data into single array 1976*0Sstevel@tonic-gate */ 1977*0Sstevel@tonic-gate static cfga_err_t 1978*0Sstevel@tonic-gate realloc_data_ext( 1979*0Sstevel@tonic-gate cfga_list_data_t **ap_id_list, 1980*0Sstevel@tonic-gate int *nlistp, 1981*0Sstevel@tonic-gate list_stat_t *lstatp) 1982*0Sstevel@tonic-gate { 1983*0Sstevel@tonic-gate int i, j; 1984*0Sstevel@tonic-gate stat_data_list_t *slp; 1985*0Sstevel@tonic-gate cfga_list_data_t *cldp; 1986*0Sstevel@tonic-gate array_list_t *alp; 1987*0Sstevel@tonic-gate cfga_err_t rc = CFGA_OK; 1988*0Sstevel@tonic-gate 1989*0Sstevel@tonic-gate 1990*0Sstevel@tonic-gate assert(*lstatp->countp >= 0); 1991*0Sstevel@tonic-gate 1992*0Sstevel@tonic-gate if (*lstatp->countp == 0) { 1993*0Sstevel@tonic-gate *ap_id_list = NULL; 1994*0Sstevel@tonic-gate *nlistp = 0; 1995*0Sstevel@tonic-gate return (CFGA_OK); 1996*0Sstevel@tonic-gate } 1997*0Sstevel@tonic-gate 1998*0Sstevel@tonic-gate /* 1999*0Sstevel@tonic-gate * allocate the array 2000*0Sstevel@tonic-gate */ 2001*0Sstevel@tonic-gate if ((cldp = config_calloc_check(*lstatp->countp, 2002*0Sstevel@tonic-gate sizeof (cfga_list_data_t), lstatp->errstr)) == NULL) { 2003*0Sstevel@tonic-gate rc = CFGA_LIB_ERROR; 2004*0Sstevel@tonic-gate goto out; 2005*0Sstevel@tonic-gate } 2006*0Sstevel@tonic-gate 2007*0Sstevel@tonic-gate /* 2008*0Sstevel@tonic-gate * copy all the stat elements (if any) into the array 2009*0Sstevel@tonic-gate */ 2010*0Sstevel@tonic-gate slp = lstatp->sdl; 2011*0Sstevel@tonic-gate for (i = 0; slp != NULL; i++) { 2012*0Sstevel@tonic-gate if (i >= *lstatp->countp) { 2013*0Sstevel@tonic-gate rc = CFGA_LIB_ERROR; 2014*0Sstevel@tonic-gate goto out; 2015*0Sstevel@tonic-gate } 2016*0Sstevel@tonic-gate stat_to_list(&cldp[i], &slp->stat_data); 2017*0Sstevel@tonic-gate slp = slp->next; 2018*0Sstevel@tonic-gate } 2019*0Sstevel@tonic-gate 2020*0Sstevel@tonic-gate /* 2021*0Sstevel@tonic-gate * copy all the list elements (if any) into the array 2022*0Sstevel@tonic-gate */ 2023*0Sstevel@tonic-gate alp = lstatp->al; 2024*0Sstevel@tonic-gate for (; alp != NULL; ) { 2025*0Sstevel@tonic-gate if (i + alp->nelem > *lstatp->countp) { 2026*0Sstevel@tonic-gate rc = CFGA_LIB_ERROR; 2027*0Sstevel@tonic-gate goto out; 2028*0Sstevel@tonic-gate } 2029*0Sstevel@tonic-gate 2030*0Sstevel@tonic-gate for (j = 0; j < alp->nelem; i++, j++) { 2031*0Sstevel@tonic-gate cldp[i] = alp->array[j]; 2032*0Sstevel@tonic-gate } 2033*0Sstevel@tonic-gate alp = alp->next; 2034*0Sstevel@tonic-gate } 2035*0Sstevel@tonic-gate 2036*0Sstevel@tonic-gate if (i != *lstatp->countp) { 2037*0Sstevel@tonic-gate rc = CFGA_LIB_ERROR; 2038*0Sstevel@tonic-gate } else { 2039*0Sstevel@tonic-gate rc = CFGA_OK; 2040*0Sstevel@tonic-gate } 2041*0Sstevel@tonic-gate 2042*0Sstevel@tonic-gate /*FALLTHRU*/ 2043*0Sstevel@tonic-gate 2044*0Sstevel@tonic-gate out: 2045*0Sstevel@tonic-gate /* clean up */ 2046*0Sstevel@tonic-gate lstat_free(lstatp); 2047*0Sstevel@tonic-gate 2048*0Sstevel@tonic-gate if (rc == CFGA_OK) { 2049*0Sstevel@tonic-gate *ap_id_list = cldp; 2050*0Sstevel@tonic-gate *nlistp = *lstatp->countp; 2051*0Sstevel@tonic-gate } else { 2052*0Sstevel@tonic-gate S_FREE(cldp); 2053*0Sstevel@tonic-gate *ap_id_list = NULL; 2054*0Sstevel@tonic-gate *nlistp = 0; 2055*0Sstevel@tonic-gate } 2056*0Sstevel@tonic-gate return (rc); 2057*0Sstevel@tonic-gate } 2058*0Sstevel@tonic-gate 2059*0Sstevel@tonic-gate /* 2060*0Sstevel@tonic-gate * The caller of this routine may supply a buffer through 2061*0Sstevel@tonic-gate * ap_id_list for returning data. Otherwise, this routine allocates the 2062*0Sstevel@tonic-gate * buffer. 2063*0Sstevel@tonic-gate */ 2064*0Sstevel@tonic-gate static cfga_err_t 2065*0Sstevel@tonic-gate realloc_data(cfga_stat_data_t **ap_id_list, int *nlistp, list_stat_t *lstatp) 2066*0Sstevel@tonic-gate { 2067*0Sstevel@tonic-gate int i; 2068*0Sstevel@tonic-gate stat_data_list_t *slp; 2069*0Sstevel@tonic-gate cfga_stat_data_t *csdp, *buf; 2070*0Sstevel@tonic-gate cfga_err_t rc; 2071*0Sstevel@tonic-gate 2072*0Sstevel@tonic-gate 2073*0Sstevel@tonic-gate assert(*lstatp->countp >= 0); 2074*0Sstevel@tonic-gate 2075*0Sstevel@tonic-gate if (*lstatp->countp == 0) { 2076*0Sstevel@tonic-gate *nlistp = 0; 2077*0Sstevel@tonic-gate return (CFGA_OK); 2078*0Sstevel@tonic-gate } 2079*0Sstevel@tonic-gate 2080*0Sstevel@tonic-gate 2081*0Sstevel@tonic-gate /* 2082*0Sstevel@tonic-gate * allocate the array if caller does not supply one. 2083*0Sstevel@tonic-gate */ 2084*0Sstevel@tonic-gate if (*ap_id_list == NULL) { 2085*0Sstevel@tonic-gate if ((buf = config_calloc_check(*lstatp->countp, 2086*0Sstevel@tonic-gate sizeof (cfga_stat_data_t), lstatp->errstr)) == NULL) { 2087*0Sstevel@tonic-gate rc = CFGA_LIB_ERROR; 2088*0Sstevel@tonic-gate goto out; 2089*0Sstevel@tonic-gate } 2090*0Sstevel@tonic-gate } else { 2091*0Sstevel@tonic-gate buf = *ap_id_list; 2092*0Sstevel@tonic-gate } 2093*0Sstevel@tonic-gate 2094*0Sstevel@tonic-gate /* 2095*0Sstevel@tonic-gate * copy the stat elements into the array 2096*0Sstevel@tonic-gate */ 2097*0Sstevel@tonic-gate csdp = buf; 2098*0Sstevel@tonic-gate slp = lstatp->sdl; 2099*0Sstevel@tonic-gate for (i = 0; slp != NULL; i++) { 2100*0Sstevel@tonic-gate if (i >= *lstatp->countp) { 2101*0Sstevel@tonic-gate rc = CFGA_LIB_ERROR; 2102*0Sstevel@tonic-gate goto out; 2103*0Sstevel@tonic-gate } 2104*0Sstevel@tonic-gate *csdp++ = slp->stat_data; 2105*0Sstevel@tonic-gate slp = slp->next; 2106*0Sstevel@tonic-gate } 2107*0Sstevel@tonic-gate 2108*0Sstevel@tonic-gate rc = CFGA_OK; 2109*0Sstevel@tonic-gate 2110*0Sstevel@tonic-gate out: 2111*0Sstevel@tonic-gate if (rc == CFGA_OK) { 2112*0Sstevel@tonic-gate *nlistp = *lstatp->countp; 2113*0Sstevel@tonic-gate *ap_id_list = buf; 2114*0Sstevel@tonic-gate } else { 2115*0Sstevel@tonic-gate /* 2116*0Sstevel@tonic-gate * Free buffer only if we allocated it. 2117*0Sstevel@tonic-gate */ 2118*0Sstevel@tonic-gate if (*ap_id_list == NULL) { 2119*0Sstevel@tonic-gate free(buf); 2120*0Sstevel@tonic-gate } 2121*0Sstevel@tonic-gate *nlistp = 0; 2122*0Sstevel@tonic-gate } 2123*0Sstevel@tonic-gate 2124*0Sstevel@tonic-gate assert(lstatp->al == NULL); 2125*0Sstevel@tonic-gate lstat_free(lstatp); 2126*0Sstevel@tonic-gate 2127*0Sstevel@tonic-gate return (rc); 2128*0Sstevel@tonic-gate } 2129*0Sstevel@tonic-gate 2130*0Sstevel@tonic-gate 2131*0Sstevel@tonic-gate /* 2132*0Sstevel@tonic-gate * list_common - walk the device tree and stat all attachment points. 2133*0Sstevel@tonic-gate */ 2134*0Sstevel@tonic-gate static cfga_err_t 2135*0Sstevel@tonic-gate list_common(list_stat_t *lstatp, const char *class) 2136*0Sstevel@tonic-gate { 2137*0Sstevel@tonic-gate di_node_t rnode; 2138*0Sstevel@tonic-gate char nodetype[MAXPATHLEN]; 2139*0Sstevel@tonic-gate const char *l_class, *l_sep; 2140*0Sstevel@tonic-gate 2141*0Sstevel@tonic-gate 2142*0Sstevel@tonic-gate /* 2143*0Sstevel@tonic-gate * begin walk of device tree 2144*0Sstevel@tonic-gate */ 2145*0Sstevel@tonic-gate if ((rnode = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 2146*0Sstevel@tonic-gate config_err(errno, DI_INIT_FAILED, lstatp->errstr); 2147*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 2148*0Sstevel@tonic-gate } 2149*0Sstevel@tonic-gate 2150*0Sstevel@tonic-gate /* 2151*0Sstevel@tonic-gate * May walk a subset of all attachment points in the device tree if 2152*0Sstevel@tonic-gate * a class is specified 2153*0Sstevel@tonic-gate */ 2154*0Sstevel@tonic-gate if (class != NULL) { 2155*0Sstevel@tonic-gate l_sep = ":"; 2156*0Sstevel@tonic-gate l_class = class; 2157*0Sstevel@tonic-gate } else { 2158*0Sstevel@tonic-gate l_sep = l_class = ""; 2159*0Sstevel@tonic-gate } 2160*0Sstevel@tonic-gate 2161*0Sstevel@tonic-gate (void) snprintf(nodetype, sizeof (nodetype), "%s%s%s", 2162*0Sstevel@tonic-gate DDI_NT_ATTACHMENT_POINT, l_sep, l_class); 2163*0Sstevel@tonic-gate 2164*0Sstevel@tonic-gate (void) di_walk_minor(rnode, nodetype, 2165*0Sstevel@tonic-gate DI_CHECK_ALIAS|DI_CHECK_INTERNAL_PATH, lstatp, do_list_common); 2166*0Sstevel@tonic-gate di_fini(rnode); 2167*0Sstevel@tonic-gate 2168*0Sstevel@tonic-gate return (CFGA_OK); 2169*0Sstevel@tonic-gate } 2170*0Sstevel@tonic-gate 2171*0Sstevel@tonic-gate static void 2172*0Sstevel@tonic-gate config_err(int errnum, int err_type, char **errstring) 2173*0Sstevel@tonic-gate { 2174*0Sstevel@tonic-gate char *p = NULL, *q = NULL; 2175*0Sstevel@tonic-gate char *syserr = NULL; 2176*0Sstevel@tonic-gate char syserr_num[20]; 2177*0Sstevel@tonic-gate int len = 0; 2178*0Sstevel@tonic-gate 2179*0Sstevel@tonic-gate /* 2180*0Sstevel@tonic-gate * If errstring is null it means user in not interested in getting 2181*0Sstevel@tonic-gate * error status. So we don't do all the work 2182*0Sstevel@tonic-gate */ 2183*0Sstevel@tonic-gate if (errstring == NULL) { 2184*0Sstevel@tonic-gate return; 2185*0Sstevel@tonic-gate } 2186*0Sstevel@tonic-gate 2187*0Sstevel@tonic-gate if (errnum != 0) { 2188*0Sstevel@tonic-gate syserr = strerror(errnum); 2189*0Sstevel@tonic-gate if (syserr == NULL) { 2190*0Sstevel@tonic-gate (void) sprintf(syserr_num, "errno=%d", errnum); 2191*0Sstevel@tonic-gate syserr = syserr_num; 2192*0Sstevel@tonic-gate } 2193*0Sstevel@tonic-gate } else 2194*0Sstevel@tonic-gate syserr = NULL; 2195*0Sstevel@tonic-gate 2196*0Sstevel@tonic-gate q = dgettext(TEXT_DOMAIN, err_strings[err_type]); 2197*0Sstevel@tonic-gate 2198*0Sstevel@tonic-gate len = strlen(q); 2199*0Sstevel@tonic-gate if (syserr != NULL) { 2200*0Sstevel@tonic-gate len += strlen(err_sep) + strlen(syserr); 2201*0Sstevel@tonic-gate } 2202*0Sstevel@tonic-gate 2203*0Sstevel@tonic-gate p = malloc(len + 1); 2204*0Sstevel@tonic-gate if (p == NULL) { 2205*0Sstevel@tonic-gate *errstring = NULL; 2206*0Sstevel@tonic-gate return; 2207*0Sstevel@tonic-gate } 2208*0Sstevel@tonic-gate 2209*0Sstevel@tonic-gate (void) strcpy(p, q); 2210*0Sstevel@tonic-gate if (syserr != NULL) { 2211*0Sstevel@tonic-gate (void) strcat(p, err_sep); 2212*0Sstevel@tonic-gate (void) strcat(p, syserr); 2213*0Sstevel@tonic-gate } 2214*0Sstevel@tonic-gate 2215*0Sstevel@tonic-gate *errstring = p; 2216*0Sstevel@tonic-gate } 2217*0Sstevel@tonic-gate 2218*0Sstevel@tonic-gate /* 2219*0Sstevel@tonic-gate * do_list_common - Routine to list attachment point as part of 2220*0Sstevel@tonic-gate * a config_list opertion. Used by both v1 and v2 interfaces. 2221*0Sstevel@tonic-gate * This is somewhat similar to config_get_lib() and its helper routines 2222*0Sstevel@tonic-gate * except that the ap_ids are always physical and don't have dynamic 2223*0Sstevel@tonic-gate * components. 2224*0Sstevel@tonic-gate */ 2225*0Sstevel@tonic-gate static int 2226*0Sstevel@tonic-gate do_list_common( 2227*0Sstevel@tonic-gate di_node_t node, 2228*0Sstevel@tonic-gate di_minor_t minor, 2229*0Sstevel@tonic-gate void *arg) 2230*0Sstevel@tonic-gate { 2231*0Sstevel@tonic-gate lib_loc_t lib_loc; 2232*0Sstevel@tonic-gate plugin_lib_t *libp; 2233*0Sstevel@tonic-gate list_stat_t *lstatp = NULL; 2234*0Sstevel@tonic-gate cfga_err_t ret = CFGA_ERROR; 2235*0Sstevel@tonic-gate 2236*0Sstevel@tonic-gate 2237*0Sstevel@tonic-gate lstatp = (list_stat_t *)arg; 2238*0Sstevel@tonic-gate 2239*0Sstevel@tonic-gate lib_loc.libp = NULL; 2240*0Sstevel@tonic-gate /* 2241*0Sstevel@tonic-gate * try and find a lib for this node 2242*0Sstevel@tonic-gate */ 2243*0Sstevel@tonic-gate if (find_lib(node, minor, &lib_loc) != CFGA_OK) { 2244*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 2245*0Sstevel@tonic-gate } 2246*0Sstevel@tonic-gate 2247*0Sstevel@tonic-gate /* 2248*0Sstevel@tonic-gate * Load all plugins. We will check compatibility later in this 2249*0Sstevel@tonic-gate * routine. 2250*0Sstevel@tonic-gate */ 2251*0Sstevel@tonic-gate lib_loc.vers_req.v_min = CFGA_HSL_V1; 2252*0Sstevel@tonic-gate lib_loc.vers_req.v_max = CFGA_HSL_VERS; 2253*0Sstevel@tonic-gate 2254*0Sstevel@tonic-gate ret = load_lib(node, minor, &lib_loc); 2255*0Sstevel@tonic-gate if (ret != CFGA_OK) { 2256*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 2257*0Sstevel@tonic-gate } 2258*0Sstevel@tonic-gate 2259*0Sstevel@tonic-gate libp = lib_loc.libp; 2260*0Sstevel@tonic-gate assert(libp != NULL); 2261*0Sstevel@tonic-gate 2262*0Sstevel@tonic-gate /* 2263*0Sstevel@tonic-gate * Note: For list type routines (list all attachment points in 2264*0Sstevel@tonic-gate * device tree) we don't pass errstring to the plugin, nor do we 2265*0Sstevel@tonic-gate * stop the walk if an error occurs in the plugin. 2266*0Sstevel@tonic-gate */ 2267*0Sstevel@tonic-gate if (compat_plugin(&lstatp->use_vers, libp->plugin_vers)) { 2268*0Sstevel@tonic-gate (void) libp->vers_ops->stat_plugin(lstatp, &lib_loc, NULL); 2269*0Sstevel@tonic-gate } 2270*0Sstevel@tonic-gate rele_lib(libp); 2271*0Sstevel@tonic-gate 2272*0Sstevel@tonic-gate return (DI_WALK_CONTINUE); 2273*0Sstevel@tonic-gate } 2274*0Sstevel@tonic-gate 2275*0Sstevel@tonic-gate /* 2276*0Sstevel@tonic-gate * stat_common - stat a user specified set of attachment points. 2277*0Sstevel@tonic-gate */ 2278*0Sstevel@tonic-gate static cfga_err_t 2279*0Sstevel@tonic-gate stat_common( 2280*0Sstevel@tonic-gate int num_ap_ids, 2281*0Sstevel@tonic-gate char *const *ap_ids, 2282*0Sstevel@tonic-gate const char *class, 2283*0Sstevel@tonic-gate list_stat_t *lstatp) 2284*0Sstevel@tonic-gate { 2285*0Sstevel@tonic-gate int i; 2286*0Sstevel@tonic-gate lib_loc_t libloc; 2287*0Sstevel@tonic-gate plugin_lib_t *libp; 2288*0Sstevel@tonic-gate cfga_err_t rc = CFGA_OK; 2289*0Sstevel@tonic-gate 2290*0Sstevel@tonic-gate 2291*0Sstevel@tonic-gate /* 2292*0Sstevel@tonic-gate * operate on each ap_id 2293*0Sstevel@tonic-gate */ 2294*0Sstevel@tonic-gate for (i = 0; i < num_ap_ids; i++) { 2295*0Sstevel@tonic-gate libloc.libp = NULL; 2296*0Sstevel@tonic-gate if ((rc = config_get_lib(ap_ids[i], &libloc, 2297*0Sstevel@tonic-gate lstatp->errstr)) != CFGA_OK) { 2298*0Sstevel@tonic-gate break; 2299*0Sstevel@tonic-gate } 2300*0Sstevel@tonic-gate assert(libloc.libp != NULL); 2301*0Sstevel@tonic-gate libp = libloc.libp; 2302*0Sstevel@tonic-gate 2303*0Sstevel@tonic-gate /* 2304*0Sstevel@tonic-gate * do pre-filtering if requested 2305*0Sstevel@tonic-gate */ 2306*0Sstevel@tonic-gate if (class != NULL && strcmp(libloc.ap_class, class)) { 2307*0Sstevel@tonic-gate rele_lib(libp); 2308*0Sstevel@tonic-gate continue; 2309*0Sstevel@tonic-gate } 2310*0Sstevel@tonic-gate 2311*0Sstevel@tonic-gate /* 2312*0Sstevel@tonic-gate * Unlike list type routines, while stat'ing specific 2313*0Sstevel@tonic-gate * attachment points we pass errstring to the plugins 2314*0Sstevel@tonic-gate * and halt if an error occurs in the plugin. 2315*0Sstevel@tonic-gate */ 2316*0Sstevel@tonic-gate rc = libp->vers_ops->stat_plugin(lstatp, &libloc, 2317*0Sstevel@tonic-gate lstatp->errstr); 2318*0Sstevel@tonic-gate rele_lib(libp); 2319*0Sstevel@tonic-gate if (rc != CFGA_OK) { 2320*0Sstevel@tonic-gate break; 2321*0Sstevel@tonic-gate } 2322*0Sstevel@tonic-gate } 2323*0Sstevel@tonic-gate 2324*0Sstevel@tonic-gate if (rc != CFGA_OK) { 2325*0Sstevel@tonic-gate lstat_free(lstatp); 2326*0Sstevel@tonic-gate } 2327*0Sstevel@tonic-gate return (rc); 2328*0Sstevel@tonic-gate } 2329*0Sstevel@tonic-gate 2330*0Sstevel@tonic-gate /*ARGSUSED*/ 2331*0Sstevel@tonic-gate static cfga_err_t 2332*0Sstevel@tonic-gate null_stat_plugin(list_stat_t *lstatp, lib_loc_t *libloc_p, char **errstring) 2333*0Sstevel@tonic-gate { 2334*0Sstevel@tonic-gate return (CFGA_OK); 2335*0Sstevel@tonic-gate } 2336*0Sstevel@tonic-gate 2337*0Sstevel@tonic-gate /* 2338*0Sstevel@tonic-gate * Pass errstring as a separate argument. Some higher level routines need 2339*0Sstevel@tonic-gate * it to be NULL. 2340*0Sstevel@tonic-gate */ 2341*0Sstevel@tonic-gate static cfga_err_t 2342*0Sstevel@tonic-gate stat_plugin_v1(list_stat_t *lstatp, lib_loc_t *libloc_p, char **errstring) 2343*0Sstevel@tonic-gate { 2344*0Sstevel@tonic-gate stat_data_list_t *slp, *slp2 = NULL; 2345*0Sstevel@tonic-gate cfga_err_t rc; 2346*0Sstevel@tonic-gate 2347*0Sstevel@tonic-gate /* 2348*0Sstevel@tonic-gate * allocate stat data buffer and list element 2349*0Sstevel@tonic-gate */ 2350*0Sstevel@tonic-gate if ((slp = config_calloc_check(1, sizeof (stat_data_list_t), 2351*0Sstevel@tonic-gate errstring)) == NULL) { 2352*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 2353*0Sstevel@tonic-gate } 2354*0Sstevel@tonic-gate 2355*0Sstevel@tonic-gate /* 2356*0Sstevel@tonic-gate * Do the stat 2357*0Sstevel@tonic-gate */ 2358*0Sstevel@tonic-gate errno = 0; 2359*0Sstevel@tonic-gate if ((rc = (*(libloc_p->libp->cfga_stat_p))(libloc_p->ap_physical, 2360*0Sstevel@tonic-gate &slp->stat_data, lstatp->opts, errstring)) != CFGA_OK) { 2361*0Sstevel@tonic-gate S_FREE(slp); 2362*0Sstevel@tonic-gate return (rc); 2363*0Sstevel@tonic-gate } 2364*0Sstevel@tonic-gate slp->next = NULL; 2365*0Sstevel@tonic-gate 2366*0Sstevel@tonic-gate /* 2367*0Sstevel@tonic-gate * Set up the logical and physical id's. 2368*0Sstevel@tonic-gate * For v1 interfaces, the generic library (libcfgadm) creates the 2369*0Sstevel@tonic-gate * ap_ids. mklog() is assumed to have been called in 2370*0Sstevel@tonic-gate * the caller of this routine. 2371*0Sstevel@tonic-gate */ 2372*0Sstevel@tonic-gate (void) snprintf(slp->stat_data.ap_log_id, CFGA_AP_LOG_ID_LEN, "%s", 2373*0Sstevel@tonic-gate libloc_p->ap_logical); 2374*0Sstevel@tonic-gate 2375*0Sstevel@tonic-gate (void) snprintf(slp->stat_data.ap_phys_id, CFGA_AP_PHYS_ID_LEN, "%s", 2376*0Sstevel@tonic-gate libloc_p->ap_physical); 2377*0Sstevel@tonic-gate 2378*0Sstevel@tonic-gate /* 2379*0Sstevel@tonic-gate * link it in 2380*0Sstevel@tonic-gate */ 2381*0Sstevel@tonic-gate if ((slp2 = lstatp->sdl) == NULL) { 2382*0Sstevel@tonic-gate lstatp->sdl = slp; 2383*0Sstevel@tonic-gate } else { 2384*0Sstevel@tonic-gate while (slp2->next != NULL) 2385*0Sstevel@tonic-gate slp2 = slp2->next; 2386*0Sstevel@tonic-gate slp2->next = slp; 2387*0Sstevel@tonic-gate } 2388*0Sstevel@tonic-gate 2389*0Sstevel@tonic-gate /* keep count */ 2390*0Sstevel@tonic-gate (*lstatp->countp)++; 2391*0Sstevel@tonic-gate 2392*0Sstevel@tonic-gate return (CFGA_OK); 2393*0Sstevel@tonic-gate } 2394*0Sstevel@tonic-gate 2395*0Sstevel@tonic-gate static cfga_err_t 2396*0Sstevel@tonic-gate stat_plugin_v2(list_stat_t *lstatp, lib_loc_t *libloc_p, char **errstring) 2397*0Sstevel@tonic-gate { 2398*0Sstevel@tonic-gate int i; 2399*0Sstevel@tonic-gate array_list_t *alp, *alp2 = NULL; 2400*0Sstevel@tonic-gate cfga_err_t rc; 2401*0Sstevel@tonic-gate char *class; 2402*0Sstevel@tonic-gate 2403*0Sstevel@tonic-gate /* 2404*0Sstevel@tonic-gate * allocate array list 2405*0Sstevel@tonic-gate */ 2406*0Sstevel@tonic-gate if ((alp = config_calloc_check(1, sizeof (array_list_t), 2407*0Sstevel@tonic-gate errstring)) == NULL) { 2408*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 2409*0Sstevel@tonic-gate } 2410*0Sstevel@tonic-gate 2411*0Sstevel@tonic-gate alp->array = NULL; 2412*0Sstevel@tonic-gate alp->nelem = 0; 2413*0Sstevel@tonic-gate 2414*0Sstevel@tonic-gate /* 2415*0Sstevel@tonic-gate * The listopts argument is currently unused. Use NULL 2416*0Sstevel@tonic-gate */ 2417*0Sstevel@tonic-gate errno = 0; 2418*0Sstevel@tonic-gate if ((rc = (*(libloc_p->libp->cfga_list_ext_p))( 2419*0Sstevel@tonic-gate libloc_p->ap_physical, &alp->array, &alp->nelem, lstatp->opts, NULL, 2420*0Sstevel@tonic-gate errstring, lstatp->flags)) != CFGA_OK || alp->nelem <= 0) { 2421*0Sstevel@tonic-gate S_FREE(alp); 2422*0Sstevel@tonic-gate return (rc); 2423*0Sstevel@tonic-gate } 2424*0Sstevel@tonic-gate alp->next = NULL; 2425*0Sstevel@tonic-gate 2426*0Sstevel@tonic-gate /* 2427*0Sstevel@tonic-gate * Set up the logical and physical id's if necessary. 2428*0Sstevel@tonic-gate * For v2 interfaces, the generic library (libcfgadm) creates the 2429*0Sstevel@tonic-gate * ap_ids only if there are no dynamic attachment points and the 2430*0Sstevel@tonic-gate * plug-in does not create the name itself. mklog() is 2431*0Sstevel@tonic-gate * assumed to have been called in the caller of this routine. 2432*0Sstevel@tonic-gate */ 2433*0Sstevel@tonic-gate if (alp->nelem == 1) { 2434*0Sstevel@tonic-gate char cphys, clog; 2435*0Sstevel@tonic-gate 2436*0Sstevel@tonic-gate clog = (alp->array[0]).ap_log_id[0]; 2437*0Sstevel@tonic-gate cphys = (alp->array[0]).ap_phys_id[0]; 2438*0Sstevel@tonic-gate 2439*0Sstevel@tonic-gate if (clog == '\0') { 2440*0Sstevel@tonic-gate (void) snprintf((alp->array[0]).ap_log_id, 2441*0Sstevel@tonic-gate sizeof ((alp->array[0]).ap_log_id), "%s", 2442*0Sstevel@tonic-gate libloc_p->ap_logical); 2443*0Sstevel@tonic-gate } 2444*0Sstevel@tonic-gate 2445*0Sstevel@tonic-gate if (cphys == '\0') { 2446*0Sstevel@tonic-gate (void) snprintf((alp->array[0]).ap_phys_id, 2447*0Sstevel@tonic-gate sizeof ((alp->array[0]).ap_phys_id), "%s", 2448*0Sstevel@tonic-gate libloc_p->ap_physical); 2449*0Sstevel@tonic-gate } 2450*0Sstevel@tonic-gate } 2451*0Sstevel@tonic-gate 2452*0Sstevel@tonic-gate if (libloc_p->ap_class[0] == '\0') { 2453*0Sstevel@tonic-gate class = CFGA_NO_CLASS; 2454*0Sstevel@tonic-gate } else { 2455*0Sstevel@tonic-gate class = libloc_p->ap_class; 2456*0Sstevel@tonic-gate } 2457*0Sstevel@tonic-gate 2458*0Sstevel@tonic-gate /* Fill in the class information for all list elements */ 2459*0Sstevel@tonic-gate for (i = 0; i < alp->nelem; i++) { 2460*0Sstevel@tonic-gate (void) snprintf((alp->array[i]).ap_class, 2461*0Sstevel@tonic-gate sizeof ((alp->array[i]).ap_class), "%s", class); 2462*0Sstevel@tonic-gate } 2463*0Sstevel@tonic-gate 2464*0Sstevel@tonic-gate /* 2465*0Sstevel@tonic-gate * link it in 2466*0Sstevel@tonic-gate */ 2467*0Sstevel@tonic-gate if ((alp2 = lstatp->al) == NULL) { 2468*0Sstevel@tonic-gate lstatp->al = alp; 2469*0Sstevel@tonic-gate } else { 2470*0Sstevel@tonic-gate while (alp2->next != NULL) 2471*0Sstevel@tonic-gate alp2 = alp2->next; 2472*0Sstevel@tonic-gate alp2->next = alp; 2473*0Sstevel@tonic-gate } 2474*0Sstevel@tonic-gate 2475*0Sstevel@tonic-gate /* keep count */ 2476*0Sstevel@tonic-gate (*lstatp->countp) += alp->nelem; 2477*0Sstevel@tonic-gate 2478*0Sstevel@tonic-gate return (CFGA_OK); 2479*0Sstevel@tonic-gate } 2480*0Sstevel@tonic-gate 2481*0Sstevel@tonic-gate /* 2482*0Sstevel@tonic-gate * Check if a plugin version is within requested limits. 2483*0Sstevel@tonic-gate */ 2484*0Sstevel@tonic-gate static int 2485*0Sstevel@tonic-gate compat_plugin(vers_req_t *reqp, int plugin_vers) 2486*0Sstevel@tonic-gate { 2487*0Sstevel@tonic-gate 2488*0Sstevel@tonic-gate if (!VALID_HSL_VERS(reqp->v_min) || !VALID_HSL_VERS(reqp->v_max) || 2489*0Sstevel@tonic-gate !VALID_HSL_VERS(plugin_vers)) { 2490*0Sstevel@tonic-gate return (0); 2491*0Sstevel@tonic-gate } 2492*0Sstevel@tonic-gate 2493*0Sstevel@tonic-gate if (plugin_vers < reqp->v_min || plugin_vers > reqp->v_max) { 2494*0Sstevel@tonic-gate return (0); 2495*0Sstevel@tonic-gate } 2496*0Sstevel@tonic-gate 2497*0Sstevel@tonic-gate 2498*0Sstevel@tonic-gate return (1); 2499*0Sstevel@tonic-gate } 2500*0Sstevel@tonic-gate 2501*0Sstevel@tonic-gate /* 2502*0Sstevel@tonic-gate * find_arg_type - determine if an argument is an ap_id or an ap_type. 2503*0Sstevel@tonic-gate * Adapted from cfgadm.c 2504*0Sstevel@tonic-gate */ 2505*0Sstevel@tonic-gate static cfga_ap_types_t 2506*0Sstevel@tonic-gate find_arg_type(const char *ap_id) 2507*0Sstevel@tonic-gate { 2508*0Sstevel@tonic-gate struct stat sbuf; 2509*0Sstevel@tonic-gate cfga_ap_types_t type = UNKNOWN_AP; 2510*0Sstevel@tonic-gate char *mkr = NULL; 2511*0Sstevel@tonic-gate size_t len; 2512*0Sstevel@tonic-gate int size_ap = 0, size_mkr = 0, digit = 0, i = 0; 2513*0Sstevel@tonic-gate char *cp, path[MAXPATHLEN], ap_base[MAXPATHLEN]; 2514*0Sstevel@tonic-gate 2515*0Sstevel@tonic-gate 2516*0Sstevel@tonic-gate /* 2517*0Sstevel@tonic-gate * sanity checks 2518*0Sstevel@tonic-gate */ 2519*0Sstevel@tonic-gate if (ap_id == NULL || *ap_id == '\0') { 2520*0Sstevel@tonic-gate 2521*0Sstevel@tonic-gate return (UNKNOWN_AP); 2522*0Sstevel@tonic-gate } 2523*0Sstevel@tonic-gate 2524*0Sstevel@tonic-gate /* 2525*0Sstevel@tonic-gate * Extract the base component 2526*0Sstevel@tonic-gate */ 2527*0Sstevel@tonic-gate if ((cp = GET_DYN(ap_id)) != NULL) { 2528*0Sstevel@tonic-gate len = cp - ap_id; 2529*0Sstevel@tonic-gate } else { 2530*0Sstevel@tonic-gate len = strlen(ap_id); 2531*0Sstevel@tonic-gate } 2532*0Sstevel@tonic-gate 2533*0Sstevel@tonic-gate if (len >= sizeof (ap_base)) { 2534*0Sstevel@tonic-gate return (UNKNOWN_AP); 2535*0Sstevel@tonic-gate } 2536*0Sstevel@tonic-gate 2537*0Sstevel@tonic-gate /* Copy only the first "len" chars */ 2538*0Sstevel@tonic-gate (void) strncpy(ap_base, ap_id, len); 2539*0Sstevel@tonic-gate ap_base[len] = '\0'; 2540*0Sstevel@tonic-gate 2541*0Sstevel@tonic-gate /* 2542*0Sstevel@tonic-gate * If it starts with a slash and is stat-able its a physical. 2543*0Sstevel@tonic-gate */ 2544*0Sstevel@tonic-gate if (*ap_base == '/' && stat(ap_base, &sbuf) == 0) { 2545*0Sstevel@tonic-gate return (PHYSICAL_AP); 2546*0Sstevel@tonic-gate } 2547*0Sstevel@tonic-gate 2548*0Sstevel@tonic-gate /* 2549*0Sstevel@tonic-gate * Is this a symlink in CFGA_DEV_DIR ? 2550*0Sstevel@tonic-gate */ 2551*0Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s%s", 2552*0Sstevel@tonic-gate CFGA_DEV_DIR SLASH, ap_base); 2553*0Sstevel@tonic-gate 2554*0Sstevel@tonic-gate if (lstat(path, &sbuf) == 0 && S_ISLNK(sbuf.st_mode) && 2555*0Sstevel@tonic-gate stat(path, &sbuf) == 0) { 2556*0Sstevel@tonic-gate return (LOGICAL_LINK_AP); 2557*0Sstevel@tonic-gate } 2558*0Sstevel@tonic-gate 2559*0Sstevel@tonic-gate /* 2560*0Sstevel@tonic-gate * Check for ":" which is always present in an ap_id 2561*0Sstevel@tonic-gate * but not in an ap_type. 2562*0Sstevel@tonic-gate * we need to check that the characters right before the : are digits 2563*0Sstevel@tonic-gate * since an ap_id is of the form <name><instance>:<specific ap name> 2564*0Sstevel@tonic-gate */ 2565*0Sstevel@tonic-gate if ((mkr = strchr(ap_base, ':')) == NULL) { 2566*0Sstevel@tonic-gate type = AP_TYPE; 2567*0Sstevel@tonic-gate } else { 2568*0Sstevel@tonic-gate size_ap = strlen(ap_base); 2569*0Sstevel@tonic-gate size_mkr = strlen(mkr); 2570*0Sstevel@tonic-gate mkr = ap_base; 2571*0Sstevel@tonic-gate 2572*0Sstevel@tonic-gate digit = 0; 2573*0Sstevel@tonic-gate for (i = size_ap - size_mkr - 1; i > 0; i--) { 2574*0Sstevel@tonic-gate if ((int)isdigit(mkr[i])) { 2575*0Sstevel@tonic-gate digit++; 2576*0Sstevel@tonic-gate break; 2577*0Sstevel@tonic-gate } 2578*0Sstevel@tonic-gate } 2579*0Sstevel@tonic-gate if (digit == 0) { 2580*0Sstevel@tonic-gate type = AP_TYPE; 2581*0Sstevel@tonic-gate } else { 2582*0Sstevel@tonic-gate type = LOGICAL_DRV_AP; 2583*0Sstevel@tonic-gate } 2584*0Sstevel@tonic-gate } 2585*0Sstevel@tonic-gate 2586*0Sstevel@tonic-gate return (type); 2587*0Sstevel@tonic-gate } 2588*0Sstevel@tonic-gate 2589*0Sstevel@tonic-gate /*ARGSUSED*/ 2590*0Sstevel@tonic-gate static cfga_err_t 2591*0Sstevel@tonic-gate null_get_cond(lib_loc_t *liblocp, cfga_cond_t *condp, char **errstring) 2592*0Sstevel@tonic-gate { 2593*0Sstevel@tonic-gate return (CFGA_OK); 2594*0Sstevel@tonic-gate } 2595*0Sstevel@tonic-gate 2596*0Sstevel@tonic-gate static cfga_err_t 2597*0Sstevel@tonic-gate get_cond_v1(lib_loc_t *liblocp, cfga_cond_t *condp, char **errstring) 2598*0Sstevel@tonic-gate { 2599*0Sstevel@tonic-gate plugin_lib_t *libp; 2600*0Sstevel@tonic-gate cfga_stat_data_t sdbuf; 2601*0Sstevel@tonic-gate cfga_err_t rc; 2602*0Sstevel@tonic-gate 2603*0Sstevel@tonic-gate 2604*0Sstevel@tonic-gate libp = liblocp->libp; 2605*0Sstevel@tonic-gate if (libp->plugin_vers != CFGA_HSL_V1) { 2606*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 2607*0Sstevel@tonic-gate } 2608*0Sstevel@tonic-gate 2609*0Sstevel@tonic-gate errno = 0; 2610*0Sstevel@tonic-gate if ((rc = (*liblocp->libp->cfga_stat_p)( 2611*0Sstevel@tonic-gate liblocp->ap_physical, &sdbuf, NULL, errstring)) 2612*0Sstevel@tonic-gate == CFGA_OK) { 2613*0Sstevel@tonic-gate *condp = sdbuf.ap_cond; 2614*0Sstevel@tonic-gate } else { 2615*0Sstevel@tonic-gate *condp = CFGA_COND_UNKNOWN; 2616*0Sstevel@tonic-gate } 2617*0Sstevel@tonic-gate 2618*0Sstevel@tonic-gate return (rc); 2619*0Sstevel@tonic-gate } 2620*0Sstevel@tonic-gate 2621*0Sstevel@tonic-gate static cfga_err_t 2622*0Sstevel@tonic-gate get_cond_v2(lib_loc_t *liblocp, cfga_cond_t *condp, char **errstring) 2623*0Sstevel@tonic-gate { 2624*0Sstevel@tonic-gate int nelem; 2625*0Sstevel@tonic-gate plugin_lib_t *libp; 2626*0Sstevel@tonic-gate cfga_list_data_t *ldbufp; 2627*0Sstevel@tonic-gate cfga_err_t rc; 2628*0Sstevel@tonic-gate 2629*0Sstevel@tonic-gate 2630*0Sstevel@tonic-gate libp = liblocp->libp; 2631*0Sstevel@tonic-gate if (libp->plugin_vers != CFGA_HSL_V2) { 2632*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 2633*0Sstevel@tonic-gate } 2634*0Sstevel@tonic-gate 2635*0Sstevel@tonic-gate errno = 0; 2636*0Sstevel@tonic-gate nelem = 0; 2637*0Sstevel@tonic-gate ldbufp = NULL; 2638*0Sstevel@tonic-gate if ((rc = (*liblocp->libp->cfga_list_ext_p)( 2639*0Sstevel@tonic-gate liblocp->ap_physical, &ldbufp, &nelem, NULL, NULL, 2640*0Sstevel@tonic-gate errstring, 0)) == CFGA_OK) { 2641*0Sstevel@tonic-gate assert(nelem == 1 && ldbufp != NULL); 2642*0Sstevel@tonic-gate 2643*0Sstevel@tonic-gate *condp = ldbufp->ap_cond; 2644*0Sstevel@tonic-gate S_FREE(ldbufp); 2645*0Sstevel@tonic-gate } else { 2646*0Sstevel@tonic-gate *condp = CFGA_COND_UNKNOWN; 2647*0Sstevel@tonic-gate } 2648*0Sstevel@tonic-gate 2649*0Sstevel@tonic-gate return (rc); 2650*0Sstevel@tonic-gate } 2651*0Sstevel@tonic-gate 2652*0Sstevel@tonic-gate /* mask represents the flags accepted */ 2653*0Sstevel@tonic-gate static cfga_err_t 2654*0Sstevel@tonic-gate check_flags(cfga_flags_t flags, cfga_flags_t mask, char **errstring) 2655*0Sstevel@tonic-gate { 2656*0Sstevel@tonic-gate if ((flags & ~mask) != 0) { 2657*0Sstevel@tonic-gate config_err(0, INVALID_ARGS, errstring); 2658*0Sstevel@tonic-gate return (CFGA_ERROR); 2659*0Sstevel@tonic-gate } else { 2660*0Sstevel@tonic-gate return (CFGA_OK); 2661*0Sstevel@tonic-gate } 2662*0Sstevel@tonic-gate } 2663*0Sstevel@tonic-gate 2664*0Sstevel@tonic-gate static cfga_err_t 2665*0Sstevel@tonic-gate check_apids(int num_ap_ids, char *const *ap_ids, char **errstring) 2666*0Sstevel@tonic-gate { 2667*0Sstevel@tonic-gate if (num_ap_ids <= 0 || ap_ids == NULL) { 2668*0Sstevel@tonic-gate config_err(0, INVALID_ARGS, errstring); 2669*0Sstevel@tonic-gate return (CFGA_ERROR); 2670*0Sstevel@tonic-gate } else { 2671*0Sstevel@tonic-gate return (CFGA_OK); 2672*0Sstevel@tonic-gate } 2673*0Sstevel@tonic-gate } 2674*0Sstevel@tonic-gate 2675*0Sstevel@tonic-gate /* 2676*0Sstevel@tonic-gate * Returns the class or the empty string if attacment point has 2677*0Sstevel@tonic-gate * no class. 2678*0Sstevel@tonic-gate */ 2679*0Sstevel@tonic-gate static char * 2680*0Sstevel@tonic-gate get_class(di_minor_t minor) 2681*0Sstevel@tonic-gate { 2682*0Sstevel@tonic-gate char *cp, c; 2683*0Sstevel@tonic-gate size_t len; 2684*0Sstevel@tonic-gate 2685*0Sstevel@tonic-gate 2686*0Sstevel@tonic-gate if (minor == DI_MINOR_NIL) { 2687*0Sstevel@tonic-gate return (NULL); 2688*0Sstevel@tonic-gate } 2689*0Sstevel@tonic-gate 2690*0Sstevel@tonic-gate cp = di_minor_nodetype(minor); 2691*0Sstevel@tonic-gate if (cp == NULL) { 2692*0Sstevel@tonic-gate return (NULL); 2693*0Sstevel@tonic-gate } 2694*0Sstevel@tonic-gate 2695*0Sstevel@tonic-gate len = strlen(DDI_NT_ATTACHMENT_POINT); 2696*0Sstevel@tonic-gate if (strncmp(cp, DDI_NT_ATTACHMENT_POINT, len)) { 2697*0Sstevel@tonic-gate return (NULL); 2698*0Sstevel@tonic-gate } 2699*0Sstevel@tonic-gate 2700*0Sstevel@tonic-gate cp += len; 2701*0Sstevel@tonic-gate 2702*0Sstevel@tonic-gate c = *cp; 2703*0Sstevel@tonic-gate if (c != '\0' && c != ':') { 2704*0Sstevel@tonic-gate return (NULL); 2705*0Sstevel@tonic-gate } 2706*0Sstevel@tonic-gate 2707*0Sstevel@tonic-gate if (c == ':') { 2708*0Sstevel@tonic-gate cp++; 2709*0Sstevel@tonic-gate } 2710*0Sstevel@tonic-gate 2711*0Sstevel@tonic-gate return (cp); 2712*0Sstevel@tonic-gate 2713*0Sstevel@tonic-gate } 2714*0Sstevel@tonic-gate 2715*0Sstevel@tonic-gate /* 2716*0Sstevel@tonic-gate * Transform stat data to list data 2717*0Sstevel@tonic-gate */ 2718*0Sstevel@tonic-gate static void 2719*0Sstevel@tonic-gate stat_to_list(cfga_list_data_t *lp, cfga_stat_data_t *statp) 2720*0Sstevel@tonic-gate { 2721*0Sstevel@tonic-gate 2722*0Sstevel@tonic-gate (void) snprintf(lp->ap_log_id, sizeof (lp->ap_log_id), "%s", 2723*0Sstevel@tonic-gate statp->ap_log_id); 2724*0Sstevel@tonic-gate 2725*0Sstevel@tonic-gate (void) snprintf(lp->ap_phys_id, sizeof (lp->ap_phys_id), "%s", 2726*0Sstevel@tonic-gate statp->ap_phys_id); 2727*0Sstevel@tonic-gate 2728*0Sstevel@tonic-gate (void) snprintf(lp->ap_class, sizeof (lp->ap_class), "%s", 2729*0Sstevel@tonic-gate CFGA_NO_CLASS); 2730*0Sstevel@tonic-gate 2731*0Sstevel@tonic-gate lp->ap_r_state = statp->ap_r_state; 2732*0Sstevel@tonic-gate lp->ap_o_state = statp->ap_o_state; 2733*0Sstevel@tonic-gate lp->ap_cond = statp->ap_cond; 2734*0Sstevel@tonic-gate lp->ap_busy = statp->ap_busy; 2735*0Sstevel@tonic-gate lp->ap_status_time = statp->ap_status_time; 2736*0Sstevel@tonic-gate 2737*0Sstevel@tonic-gate (void) snprintf(lp->ap_info, sizeof (lp->ap_info), "%s", 2738*0Sstevel@tonic-gate statp->ap_info); 2739*0Sstevel@tonic-gate (void) snprintf(lp->ap_type, sizeof (lp->ap_type), "%s", 2740*0Sstevel@tonic-gate statp->ap_type); 2741*0Sstevel@tonic-gate } 2742*0Sstevel@tonic-gate 2743*0Sstevel@tonic-gate static void 2744*0Sstevel@tonic-gate lstat_free(list_stat_t *lstatp) 2745*0Sstevel@tonic-gate { 2746*0Sstevel@tonic-gate stat_data_list_t *slp, *slp2; 2747*0Sstevel@tonic-gate array_list_t *ap, *ap2; 2748*0Sstevel@tonic-gate 2749*0Sstevel@tonic-gate slp = lstatp->sdl; 2750*0Sstevel@tonic-gate while (slp != NULL) { 2751*0Sstevel@tonic-gate slp2 = slp->next; 2752*0Sstevel@tonic-gate S_FREE(slp); 2753*0Sstevel@tonic-gate slp = slp2; 2754*0Sstevel@tonic-gate } 2755*0Sstevel@tonic-gate 2756*0Sstevel@tonic-gate lstatp->sdl = NULL; 2757*0Sstevel@tonic-gate 2758*0Sstevel@tonic-gate ap = lstatp->al; 2759*0Sstevel@tonic-gate while (ap != NULL) { 2760*0Sstevel@tonic-gate ap2 = ap->next; 2761*0Sstevel@tonic-gate S_FREE(ap->array); 2762*0Sstevel@tonic-gate S_FREE(ap); 2763*0Sstevel@tonic-gate ap = ap2; 2764*0Sstevel@tonic-gate } 2765*0Sstevel@tonic-gate 2766*0Sstevel@tonic-gate lstatp->al = NULL; 2767*0Sstevel@tonic-gate } 2768*0Sstevel@tonic-gate 2769*0Sstevel@tonic-gate static cfga_err_t 2770*0Sstevel@tonic-gate split_apid(char *ap_id, char **dyncompp, char **errstring) 2771*0Sstevel@tonic-gate { 2772*0Sstevel@tonic-gate char *cp; 2773*0Sstevel@tonic-gate 2774*0Sstevel@tonic-gate *dyncompp = NULL; 2775*0Sstevel@tonic-gate 2776*0Sstevel@tonic-gate if (ap_id == NULL) { 2777*0Sstevel@tonic-gate return (CFGA_ERROR); 2778*0Sstevel@tonic-gate } 2779*0Sstevel@tonic-gate 2780*0Sstevel@tonic-gate if ((cp = strstr(ap_id, CFGA_DYN_SEP)) == NULL) { 2781*0Sstevel@tonic-gate return (CFGA_OK); 2782*0Sstevel@tonic-gate } 2783*0Sstevel@tonic-gate 2784*0Sstevel@tonic-gate *cp = '\0'; 2785*0Sstevel@tonic-gate cp += strlen(CFGA_DYN_SEP); 2786*0Sstevel@tonic-gate if ((*dyncompp = config_calloc_check(1, strlen(cp) + 1, 2787*0Sstevel@tonic-gate errstring)) == NULL) { 2788*0Sstevel@tonic-gate return (CFGA_LIB_ERROR); 2789*0Sstevel@tonic-gate } 2790*0Sstevel@tonic-gate (void) strcpy(*dyncompp, cp); 2791*0Sstevel@tonic-gate 2792*0Sstevel@tonic-gate return (CFGA_OK); 2793*0Sstevel@tonic-gate } 2794*0Sstevel@tonic-gate 2795*0Sstevel@tonic-gate static void 2796*0Sstevel@tonic-gate append_dyn(char *buf, const char *dyncomp, size_t blen) 2797*0Sstevel@tonic-gate { 2798*0Sstevel@tonic-gate if (dyncomp != NULL) { 2799*0Sstevel@tonic-gate char *cp = buf + strlen(buf); 2800*0Sstevel@tonic-gate size_t len = blen - strlen(buf); 2801*0Sstevel@tonic-gate 2802*0Sstevel@tonic-gate (void) snprintf(cp, len, "%s%s", CFGA_DYN_SEP, 2803*0Sstevel@tonic-gate dyncomp); 2804*0Sstevel@tonic-gate } 2805*0Sstevel@tonic-gate } 2806*0Sstevel@tonic-gate 2807*0Sstevel@tonic-gate /* 2808*0Sstevel@tonic-gate * Default implementation of cfga_ap_id_cmp. Works for most cases 2809*0Sstevel@tonic-gate * except for long hex number sequences like world-wide-name. 2810*0Sstevel@tonic-gate * 2811*0Sstevel@tonic-gate * This function compares the ap's in a generic way. It does so by 2812*0Sstevel@tonic-gate * determining the place of difference between the 2 aps. If the first 2813*0Sstevel@tonic-gate * difference is a digit, it attempts to obtain the numbers and compare them 2814*0Sstevel@tonic-gate * Otherwise it just compares the aps as strings 2815*0Sstevel@tonic-gate */ 2816*0Sstevel@tonic-gate static int 2817*0Sstevel@tonic-gate default_ap_id_cmp(const char *ap_id1, const char *ap_id2) 2818*0Sstevel@tonic-gate { 2819*0Sstevel@tonic-gate int i = 0; 2820*0Sstevel@tonic-gate 2821*0Sstevel@tonic-gate /* 2822*0Sstevel@tonic-gate * Search for first different char 2823*0Sstevel@tonic-gate */ 2824*0Sstevel@tonic-gate while (ap_id1[i] == ap_id2[i] && ap_id1[i] != '\0') 2825*0Sstevel@tonic-gate i++; 2826*0Sstevel@tonic-gate 2827*0Sstevel@tonic-gate /* 2828*0Sstevel@tonic-gate * If one of the char is a digit, back up to where the 2829*0Sstevel@tonic-gate * number started, compare the number. 2830*0Sstevel@tonic-gate */ 2831*0Sstevel@tonic-gate if (isdigit(ap_id1[i]) || isdigit(ap_id2[i])) { 2832*0Sstevel@tonic-gate while ((i > 0) && isdigit(ap_id1[i - 1])) 2833*0Sstevel@tonic-gate i--; 2834*0Sstevel@tonic-gate 2835*0Sstevel@tonic-gate if (isdigit(ap_id1[i]) && isdigit(ap_id2[i])) 2836*0Sstevel@tonic-gate return (atoi(ap_id1 + i) - atoi(ap_id2 + i)); 2837*0Sstevel@tonic-gate } 2838*0Sstevel@tonic-gate 2839*0Sstevel@tonic-gate /* One of them isn't a number, compare the char */ 2840*0Sstevel@tonic-gate return (ap_id1[i] - ap_id2[i]); 2841*0Sstevel@tonic-gate } 2842*0Sstevel@tonic-gate 2843*0Sstevel@tonic-gate static void 2844*0Sstevel@tonic-gate hold_lib(plugin_lib_t *libp) 2845*0Sstevel@tonic-gate { 2846*0Sstevel@tonic-gate assert(libp->refcnt >= 0); 2847*0Sstevel@tonic-gate (void) mutex_lock(&libp->lock); 2848*0Sstevel@tonic-gate libp->refcnt++; 2849*0Sstevel@tonic-gate (void) mutex_unlock(&libp->lock); 2850*0Sstevel@tonic-gate } 2851*0Sstevel@tonic-gate 2852*0Sstevel@tonic-gate static void 2853*0Sstevel@tonic-gate rele_lib(plugin_lib_t *libp) 2854*0Sstevel@tonic-gate { 2855*0Sstevel@tonic-gate assert(libp->refcnt > 0); 2856*0Sstevel@tonic-gate (void) mutex_lock(&libp->lock); 2857*0Sstevel@tonic-gate libp->refcnt--; 2858*0Sstevel@tonic-gate (void) mutex_unlock(&libp->lock); 2859*0Sstevel@tonic-gate } 2860