1749f21d3Swesolows /* 2749f21d3Swesolows * CDDL HEADER START 3749f21d3Swesolows * 4749f21d3Swesolows * The contents of this file are subject to the terms of the 5749f21d3Swesolows * Common Development and Distribution License (the "License"). 6749f21d3Swesolows * You may not use this file except in compliance with the License. 7749f21d3Swesolows * 8749f21d3Swesolows * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9749f21d3Swesolows * or http://www.opensolaris.org/os/licensing. 10749f21d3Swesolows * See the License for the specific language governing permissions 11749f21d3Swesolows * and limitations under the License. 12749f21d3Swesolows * 13749f21d3Swesolows * When distributing Covered Code, include this CDDL HEADER in each 14749f21d3Swesolows * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15749f21d3Swesolows * If applicable, add the following below this CDDL HEADER, with the 16749f21d3Swesolows * fields enclosed by brackets "[]" replaced with your own identifying 17749f21d3Swesolows * information: Portions Copyright [yyyy] [name of copyright owner] 18749f21d3Swesolows * 19749f21d3Swesolows * CDDL HEADER END 20749f21d3Swesolows */ 21749f21d3Swesolows 22749f21d3Swesolows /* 231fe76c0bSwesolows * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24749f21d3Swesolows * Use is subject to license terms. 25749f21d3Swesolows */ 26749f21d3Swesolows 27749f21d3Swesolows #pragma ident "%Z%%M% %I% %E% SMI" 28749f21d3Swesolows 29749f21d3Swesolows #include <sys/fm/protocol.h> 30749f21d3Swesolows #include <sys/types.h> 31749f21d3Swesolows #include <sys/systeminfo.h> 32749f21d3Swesolows #include <fm/fmd_snmp.h> 331fe76c0bSwesolows #include <fm/libtopo.h> 34749f21d3Swesolows #include <net-snmp/net-snmp-config.h> 35749f21d3Swesolows #include <net-snmp/net-snmp-includes.h> 36749f21d3Swesolows #include <net-snmp/agent/net-snmp-agent-includes.h> 37749f21d3Swesolows #include <libnvpair.h> 38749f21d3Swesolows #include <limits.h> 39749f21d3Swesolows #include <strings.h> 40749f21d3Swesolows #include <stddef.h> 41749f21d3Swesolows #include <unistd.h> 42749f21d3Swesolows #include <dlfcn.h> 43749f21d3Swesolows #include <errno.h> 44749f21d3Swesolows 45749f21d3Swesolows #define SCHEMEDIR_BASE "/usr/lib/fm/fmd/schemes" 46749f21d3Swesolows 47749f21d3Swesolows #if defined(__sparcv9) 48749f21d3Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/sparcv9" 49749f21d3Swesolows #elif defined(__amd64) 50749f21d3Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/amd64" 51749f21d3Swesolows #else 52749f21d3Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE 53749f21d3Swesolows #endif 54749f21d3Swesolows 55749f21d3Swesolows typedef struct fmd_scheme_ops { 56749f21d3Swesolows int (*sop_init)(void); 57749f21d3Swesolows void (*sop_fini)(void); 58749f21d3Swesolows ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t); 59749f21d3Swesolows } fmd_scheme_ops_t; 60749f21d3Swesolows 61749f21d3Swesolows typedef struct fmd_scheme_opd { 62749f21d3Swesolows const char *opd_name; /* symbol name of scheme function */ 63749f21d3Swesolows size_t opd_off; /* offset within fmd_scheme_ops_t */ 64749f21d3Swesolows } fmd_scheme_opd_t; 65749f21d3Swesolows 66749f21d3Swesolows typedef struct fmd_scheme { 67749f21d3Swesolows struct fmd_scheme *sch_next; /* next scheme on list of schemes */ 68749f21d3Swesolows char *sch_name; /* name of this scheme (fmri prefix) */ 69749f21d3Swesolows void *sch_dlp; /* libdl(3DL) shared library handle */ 70749f21d3Swesolows int sch_err; /* if negative entry, errno to return */ 71749f21d3Swesolows fmd_scheme_ops_t sch_ops; /* scheme function pointers */ 72749f21d3Swesolows } fmd_scheme_t; 73749f21d3Swesolows 74749f21d3Swesolows static fmd_scheme_t *sch_list; /* list of cached schemes */ 75749f21d3Swesolows static char *g_root; /* fmd root dir */ 761fe76c0bSwesolows static struct topo_hdl *g_thp; 77749f21d3Swesolows 78749f21d3Swesolows static long 79749f21d3Swesolows fmd_scheme_notsup(void) 80749f21d3Swesolows { 81749f21d3Swesolows errno = ENOTSUP; 82749f21d3Swesolows return (-1); 83749f21d3Swesolows } 84749f21d3Swesolows 85749f21d3Swesolows static int 86749f21d3Swesolows fmd_scheme_nop(void) 87749f21d3Swesolows { 88749f21d3Swesolows return (0); 89749f21d3Swesolows } 90749f21d3Swesolows 91749f21d3Swesolows /* 92749f21d3Swesolows * Default values for the scheme ops. If a scheme function is not defined in 93749f21d3Swesolows * the module, then this operation is implemented using the default function. 94749f21d3Swesolows */ 95749f21d3Swesolows static const fmd_scheme_ops_t _fmd_scheme_default_ops = { 96749f21d3Swesolows (int (*)())fmd_scheme_nop, /* sop_init */ 97749f21d3Swesolows (void (*)())fmd_scheme_nop, /* sop_fini */ 98749f21d3Swesolows (ssize_t (*)())fmd_scheme_notsup, /* sop_nvl2str */ 99749f21d3Swesolows }; 100749f21d3Swesolows 101749f21d3Swesolows /* 102749f21d3Swesolows * Scheme ops descriptions. These names and offsets are used by the function 103749f21d3Swesolows * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t. 104749f21d3Swesolows */ 105749f21d3Swesolows static const fmd_scheme_opd_t _fmd_scheme_ops[] = { 106749f21d3Swesolows { "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) }, 107749f21d3Swesolows { "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) }, 108749f21d3Swesolows { "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) }, 109749f21d3Swesolows { NULL, 0 } 110749f21d3Swesolows }; 111749f21d3Swesolows 112749f21d3Swesolows static fmd_scheme_t * 113749f21d3Swesolows fmd_scheme_create(const char *name) 114749f21d3Swesolows { 115749f21d3Swesolows fmd_scheme_t *sp; 116749f21d3Swesolows 117749f21d3Swesolows if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL || 118749f21d3Swesolows (sp->sch_name = strdup(name)) == NULL) { 119749f21d3Swesolows free(sp); 120749f21d3Swesolows return (NULL); 121749f21d3Swesolows } 122749f21d3Swesolows 123749f21d3Swesolows sp->sch_next = sch_list; 124749f21d3Swesolows sp->sch_dlp = NULL; 125749f21d3Swesolows sp->sch_err = 0; 126749f21d3Swesolows sp->sch_ops = _fmd_scheme_default_ops; 127749f21d3Swesolows 128749f21d3Swesolows sch_list = sp; 129749f21d3Swesolows return (sp); 130749f21d3Swesolows } 131749f21d3Swesolows 132749f21d3Swesolows static int 133749f21d3Swesolows fmd_scheme_rtld_init(fmd_scheme_t *sp) 134749f21d3Swesolows { 135749f21d3Swesolows const fmd_scheme_opd_t *opd; 136749f21d3Swesolows void *p; 137749f21d3Swesolows 138749f21d3Swesolows for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) { 139749f21d3Swesolows if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL) 140749f21d3Swesolows *(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p; 141749f21d3Swesolows } 142749f21d3Swesolows 143749f21d3Swesolows return (sp->sch_ops.sop_init()); 144749f21d3Swesolows } 145749f21d3Swesolows 146749f21d3Swesolows static fmd_scheme_t * 147749f21d3Swesolows fmd_scheme_lookup(const char *dir, const char *name) 148749f21d3Swesolows { 149749f21d3Swesolows fmd_scheme_t *sp; 150749f21d3Swesolows char path[PATH_MAX]; 151749f21d3Swesolows 152749f21d3Swesolows for (sp = sch_list; sp != NULL; sp = sp->sch_next) { 153749f21d3Swesolows if (strcmp(name, sp->sch_name) == 0) 154749f21d3Swesolows return (sp); 155749f21d3Swesolows } 156749f21d3Swesolows 157749f21d3Swesolows if ((sp = fmd_scheme_create(name)) == NULL) 158749f21d3Swesolows return (NULL); /* errno is set for us */ 159749f21d3Swesolows 160749f21d3Swesolows (void) snprintf(path, sizeof (path), "%s%s/%s.so", 161749f21d3Swesolows g_root ? g_root : "", dir, name); 162749f21d3Swesolows 163749f21d3Swesolows if (access(path, F_OK) != 0) { 164749f21d3Swesolows sp->sch_err = errno; 165749f21d3Swesolows return (sp); 166749f21d3Swesolows } 167749f21d3Swesolows 168749f21d3Swesolows if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) == 169749f21d3Swesolows NULL) { 170749f21d3Swesolows sp->sch_err = ELIBACC; 171749f21d3Swesolows return (sp); 172749f21d3Swesolows } 173749f21d3Swesolows 174749f21d3Swesolows if (fmd_scheme_rtld_init(sp) != 0) { 175749f21d3Swesolows sp->sch_err = errno; 176749f21d3Swesolows (void) dlclose(sp->sch_dlp); 177749f21d3Swesolows sp->sch_dlp = NULL; 178749f21d3Swesolows } 179749f21d3Swesolows 180749f21d3Swesolows return (sp); 181749f21d3Swesolows } 182749f21d3Swesolows 183749f21d3Swesolows char * 184749f21d3Swesolows sunFm_nvl2str(nvlist_t *nvl) 185749f21d3Swesolows { 186749f21d3Swesolows fmd_scheme_t *sp; 187749f21d3Swesolows char c, *name, *s = NULL; 188749f21d3Swesolows ssize_t len; 189749f21d3Swesolows 190749f21d3Swesolows if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) { 191749f21d3Swesolows DEBUGMSGTL((MODNAME_STR, "fmri does not contain required " 192749f21d3Swesolows "'%s' nvpair\n", FM_FMRI_SCHEME)); 193749f21d3Swesolows return (NULL); 194749f21d3Swesolows } 195749f21d3Swesolows 196749f21d3Swesolows if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL || 197749f21d3Swesolows sp->sch_dlp == NULL || sp->sch_err != 0) { 198749f21d3Swesolows const char *msg = 199749f21d3Swesolows sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err); 200749f21d3Swesolows DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to " 201749f21d3Swesolows "format fmri: %s\n", name, msg ? msg : "unknown error")); 202749f21d3Swesolows return (NULL); 203749f21d3Swesolows } 204749f21d3Swesolows 205749f21d3Swesolows if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 || 206749f21d3Swesolows (s = malloc(len + 1)) == NULL || 207749f21d3Swesolows sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) { 208749f21d3Swesolows DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'", 209749f21d3Swesolows name)); 210749f21d3Swesolows free(s); 211749f21d3Swesolows return (NULL); 212749f21d3Swesolows } 213749f21d3Swesolows 214749f21d3Swesolows return (s); 215749f21d3Swesolows } 216749f21d3Swesolows 217749f21d3Swesolows void * 218749f21d3Swesolows fmd_fmri_alloc(size_t size) 219749f21d3Swesolows { 220749f21d3Swesolows return (malloc(size)); 221749f21d3Swesolows } 222749f21d3Swesolows 223749f21d3Swesolows void * 224749f21d3Swesolows fmd_fmri_zalloc(size_t size) 225749f21d3Swesolows { 226749f21d3Swesolows void *data; 227749f21d3Swesolows 228749f21d3Swesolows if ((data = malloc(size)) != NULL) 229749f21d3Swesolows bzero(data, size); 230749f21d3Swesolows 231749f21d3Swesolows return (data); 232749f21d3Swesolows } 233749f21d3Swesolows 234749f21d3Swesolows /*ARGSUSED*/ 235749f21d3Swesolows void 236749f21d3Swesolows fmd_fmri_free(void *data, size_t size) 237749f21d3Swesolows { 238749f21d3Swesolows free(data); 239749f21d3Swesolows } 240749f21d3Swesolows 241749f21d3Swesolows int 242749f21d3Swesolows fmd_fmri_error(int err) 243749f21d3Swesolows { 244749f21d3Swesolows errno = err; 245749f21d3Swesolows return (-1); 246749f21d3Swesolows } 247749f21d3Swesolows 248749f21d3Swesolows char * 249749f21d3Swesolows fmd_fmri_strescape(const char *s) 250749f21d3Swesolows { 251749f21d3Swesolows return (strdup(s)); 252749f21d3Swesolows } 253749f21d3Swesolows 254749f21d3Swesolows char * 255749f21d3Swesolows fmd_fmri_strdup(const char *s) 256749f21d3Swesolows { 257749f21d3Swesolows return (strdup(s)); 258749f21d3Swesolows } 259749f21d3Swesolows 260749f21d3Swesolows void 261749f21d3Swesolows fmd_fmri_strfree(char *s) 262749f21d3Swesolows { 263749f21d3Swesolows free(s); 264749f21d3Swesolows } 265749f21d3Swesolows 266749f21d3Swesolows const char * 267749f21d3Swesolows fmd_fmri_get_rootdir(void) 268749f21d3Swesolows { 269749f21d3Swesolows return (g_root ? g_root : ""); 270749f21d3Swesolows } 271749f21d3Swesolows 272749f21d3Swesolows const char * 273749f21d3Swesolows fmd_fmri_get_platform(void) 274749f21d3Swesolows { 275749f21d3Swesolows static char platform[MAXNAMELEN]; 276749f21d3Swesolows 277749f21d3Swesolows if (platform[0] == '\0') 278749f21d3Swesolows (void) sysinfo(SI_PLATFORM, platform, sizeof (platform)); 279749f21d3Swesolows 280749f21d3Swesolows return (platform); 281749f21d3Swesolows } 282749f21d3Swesolows 283749f21d3Swesolows uint64_t 284749f21d3Swesolows fmd_fmri_get_drgen(void) 285749f21d3Swesolows { 286749f21d3Swesolows return (0); 287749f21d3Swesolows } 288749f21d3Swesolows 289749f21d3Swesolows int 290749f21d3Swesolows fmd_fmri_set_errno(int err) 291749f21d3Swesolows { 292749f21d3Swesolows errno = err; 293749f21d3Swesolows return (-1); 294749f21d3Swesolows } 295749f21d3Swesolows 29630698f33Swesolows /*ARGSUSED*/ 297749f21d3Swesolows void 298749f21d3Swesolows fmd_fmri_warn(const char *format, ...) 299749f21d3Swesolows { 300749f21d3Swesolows } 3011fe76c0bSwesolows 3021fe76c0bSwesolows struct topo_hdl * 303*24db4641Seschrock fmd_fmri_topo_hold(int version) 3041fe76c0bSwesolows { 3051fe76c0bSwesolows int err; 3061fe76c0bSwesolows 307*24db4641Seschrock if (version != TOPO_VERSION) 308*24db4641Seschrock return (NULL); 309*24db4641Seschrock 3101fe76c0bSwesolows if (g_thp == NULL) { 3111fe76c0bSwesolows if ((g_thp = topo_open(TOPO_VERSION, "/", &err)) == NULL) { 3121fe76c0bSwesolows DEBUGMSGTL((MODNAME_STR, "topo_open failed: %s\n", 3131fe76c0bSwesolows topo_strerror(err))); 3141fe76c0bSwesolows return (NULL); 3151fe76c0bSwesolows } 3161fe76c0bSwesolows } 3171fe76c0bSwesolows 3181fe76c0bSwesolows return (g_thp); 3191fe76c0bSwesolows } 320*24db4641Seschrock 321*24db4641Seschrock /*ARGSUSED*/ 322*24db4641Seschrock void 323*24db4641Seschrock fmd_fmri_topo_rele(struct topo_hdl *thp) 324*24db4641Seschrock { 325*24db4641Seschrock /* nothing to do */ 326*24db4641Seschrock } 327