1*1303Swesolows /* 2*1303Swesolows * CDDL HEADER START 3*1303Swesolows * 4*1303Swesolows * The contents of this file are subject to the terms of the 5*1303Swesolows * Common Development and Distribution License (the "License"). 6*1303Swesolows * You may not use this file except in compliance with the License. 7*1303Swesolows * 8*1303Swesolows * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1303Swesolows * or http://www.opensolaris.org/os/licensing. 10*1303Swesolows * See the License for the specific language governing permissions 11*1303Swesolows * and limitations under the License. 12*1303Swesolows * 13*1303Swesolows * When distributing Covered Code, include this CDDL HEADER in each 14*1303Swesolows * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1303Swesolows * If applicable, add the following below this CDDL HEADER, with the 16*1303Swesolows * fields enclosed by brackets "[]" replaced with your own identifying 17*1303Swesolows * information: Portions Copyright [yyyy] [name of copyright owner] 18*1303Swesolows * 19*1303Swesolows * CDDL HEADER END 20*1303Swesolows */ 21*1303Swesolows 22*1303Swesolows /* 23*1303Swesolows * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*1303Swesolows * Use is subject to license terms. 25*1303Swesolows */ 26*1303Swesolows 27*1303Swesolows #pragma ident "%Z%%M% %I% %E% SMI" 28*1303Swesolows 29*1303Swesolows #include <sys/fm/protocol.h> 30*1303Swesolows #include <sys/types.h> 31*1303Swesolows #include <sys/systeminfo.h> 32*1303Swesolows #include <fm/fmd_snmp.h> 33*1303Swesolows #include <net-snmp/net-snmp-config.h> 34*1303Swesolows #include <net-snmp/net-snmp-includes.h> 35*1303Swesolows #include <net-snmp/agent/net-snmp-agent-includes.h> 36*1303Swesolows #include <libnvpair.h> 37*1303Swesolows #include <limits.h> 38*1303Swesolows #include <strings.h> 39*1303Swesolows #include <stddef.h> 40*1303Swesolows #include <unistd.h> 41*1303Swesolows #include <dlfcn.h> 42*1303Swesolows #include <errno.h> 43*1303Swesolows 44*1303Swesolows #define SCHEMEDIR_BASE "/usr/lib/fm/fmd/schemes" 45*1303Swesolows 46*1303Swesolows #if defined(__sparcv9) 47*1303Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/sparcv9" 48*1303Swesolows #elif defined(__amd64) 49*1303Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/amd64" 50*1303Swesolows #else 51*1303Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE 52*1303Swesolows #endif 53*1303Swesolows 54*1303Swesolows typedef struct fmd_scheme_ops { 55*1303Swesolows int (*sop_init)(void); 56*1303Swesolows void (*sop_fini)(void); 57*1303Swesolows ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t); 58*1303Swesolows } fmd_scheme_ops_t; 59*1303Swesolows 60*1303Swesolows typedef struct fmd_scheme_opd { 61*1303Swesolows const char *opd_name; /* symbol name of scheme function */ 62*1303Swesolows size_t opd_off; /* offset within fmd_scheme_ops_t */ 63*1303Swesolows } fmd_scheme_opd_t; 64*1303Swesolows 65*1303Swesolows typedef struct fmd_scheme { 66*1303Swesolows struct fmd_scheme *sch_next; /* next scheme on list of schemes */ 67*1303Swesolows char *sch_name; /* name of this scheme (fmri prefix) */ 68*1303Swesolows void *sch_dlp; /* libdl(3DL) shared library handle */ 69*1303Swesolows int sch_err; /* if negative entry, errno to return */ 70*1303Swesolows fmd_scheme_ops_t sch_ops; /* scheme function pointers */ 71*1303Swesolows } fmd_scheme_t; 72*1303Swesolows 73*1303Swesolows static fmd_scheme_t *sch_list; /* list of cached schemes */ 74*1303Swesolows static char *g_root; /* fmd root dir */ 75*1303Swesolows 76*1303Swesolows static long 77*1303Swesolows fmd_scheme_notsup(void) 78*1303Swesolows { 79*1303Swesolows errno = ENOTSUP; 80*1303Swesolows return (-1); 81*1303Swesolows } 82*1303Swesolows 83*1303Swesolows static int 84*1303Swesolows fmd_scheme_nop(void) 85*1303Swesolows { 86*1303Swesolows return (0); 87*1303Swesolows } 88*1303Swesolows 89*1303Swesolows /* 90*1303Swesolows * Default values for the scheme ops. If a scheme function is not defined in 91*1303Swesolows * the module, then this operation is implemented using the default function. 92*1303Swesolows */ 93*1303Swesolows static const fmd_scheme_ops_t _fmd_scheme_default_ops = { 94*1303Swesolows (int (*)())fmd_scheme_nop, /* sop_init */ 95*1303Swesolows (void (*)())fmd_scheme_nop, /* sop_fini */ 96*1303Swesolows (ssize_t (*)())fmd_scheme_notsup, /* sop_nvl2str */ 97*1303Swesolows }; 98*1303Swesolows 99*1303Swesolows /* 100*1303Swesolows * Scheme ops descriptions. These names and offsets are used by the function 101*1303Swesolows * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t. 102*1303Swesolows */ 103*1303Swesolows static const fmd_scheme_opd_t _fmd_scheme_ops[] = { 104*1303Swesolows { "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) }, 105*1303Swesolows { "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) }, 106*1303Swesolows { "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) }, 107*1303Swesolows { NULL, 0 } 108*1303Swesolows }; 109*1303Swesolows 110*1303Swesolows static fmd_scheme_t * 111*1303Swesolows fmd_scheme_create(const char *name) 112*1303Swesolows { 113*1303Swesolows fmd_scheme_t *sp; 114*1303Swesolows 115*1303Swesolows if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL || 116*1303Swesolows (sp->sch_name = strdup(name)) == NULL) { 117*1303Swesolows free(sp); 118*1303Swesolows return (NULL); 119*1303Swesolows } 120*1303Swesolows 121*1303Swesolows sp->sch_next = sch_list; 122*1303Swesolows sp->sch_dlp = NULL; 123*1303Swesolows sp->sch_err = 0; 124*1303Swesolows sp->sch_ops = _fmd_scheme_default_ops; 125*1303Swesolows 126*1303Swesolows sch_list = sp; 127*1303Swesolows return (sp); 128*1303Swesolows } 129*1303Swesolows 130*1303Swesolows static int 131*1303Swesolows fmd_scheme_rtld_init(fmd_scheme_t *sp) 132*1303Swesolows { 133*1303Swesolows const fmd_scheme_opd_t *opd; 134*1303Swesolows void *p; 135*1303Swesolows 136*1303Swesolows for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) { 137*1303Swesolows if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL) 138*1303Swesolows *(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p; 139*1303Swesolows } 140*1303Swesolows 141*1303Swesolows return (sp->sch_ops.sop_init()); 142*1303Swesolows } 143*1303Swesolows 144*1303Swesolows static fmd_scheme_t * 145*1303Swesolows fmd_scheme_lookup(const char *dir, const char *name) 146*1303Swesolows { 147*1303Swesolows fmd_scheme_t *sp; 148*1303Swesolows char path[PATH_MAX]; 149*1303Swesolows 150*1303Swesolows for (sp = sch_list; sp != NULL; sp = sp->sch_next) { 151*1303Swesolows if (strcmp(name, sp->sch_name) == 0) 152*1303Swesolows return (sp); 153*1303Swesolows } 154*1303Swesolows 155*1303Swesolows if ((sp = fmd_scheme_create(name)) == NULL) 156*1303Swesolows return (NULL); /* errno is set for us */ 157*1303Swesolows 158*1303Swesolows (void) snprintf(path, sizeof (path), "%s%s/%s.so", 159*1303Swesolows g_root ? g_root : "", dir, name); 160*1303Swesolows 161*1303Swesolows if (access(path, F_OK) != 0) { 162*1303Swesolows sp->sch_err = errno; 163*1303Swesolows return (sp); 164*1303Swesolows } 165*1303Swesolows 166*1303Swesolows if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) == 167*1303Swesolows NULL) { 168*1303Swesolows sp->sch_err = ELIBACC; 169*1303Swesolows return (sp); 170*1303Swesolows } 171*1303Swesolows 172*1303Swesolows if (fmd_scheme_rtld_init(sp) != 0) { 173*1303Swesolows sp->sch_err = errno; 174*1303Swesolows (void) dlclose(sp->sch_dlp); 175*1303Swesolows sp->sch_dlp = NULL; 176*1303Swesolows } 177*1303Swesolows 178*1303Swesolows return (sp); 179*1303Swesolows } 180*1303Swesolows 181*1303Swesolows char * 182*1303Swesolows sunFm_nvl2str(nvlist_t *nvl) 183*1303Swesolows { 184*1303Swesolows fmd_scheme_t *sp; 185*1303Swesolows char c, *name, *s = NULL; 186*1303Swesolows ssize_t len; 187*1303Swesolows 188*1303Swesolows if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) { 189*1303Swesolows DEBUGMSGTL((MODNAME_STR, "fmri does not contain required " 190*1303Swesolows "'%s' nvpair\n", FM_FMRI_SCHEME)); 191*1303Swesolows return (NULL); 192*1303Swesolows } 193*1303Swesolows 194*1303Swesolows if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL || 195*1303Swesolows sp->sch_dlp == NULL || sp->sch_err != 0) { 196*1303Swesolows const char *msg = 197*1303Swesolows sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err); 198*1303Swesolows DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to " 199*1303Swesolows "format fmri: %s\n", name, msg ? msg : "unknown error")); 200*1303Swesolows return (NULL); 201*1303Swesolows } 202*1303Swesolows 203*1303Swesolows if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 || 204*1303Swesolows (s = malloc(len + 1)) == NULL || 205*1303Swesolows sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) { 206*1303Swesolows DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'", 207*1303Swesolows name)); 208*1303Swesolows free(s); 209*1303Swesolows return (NULL); 210*1303Swesolows } 211*1303Swesolows 212*1303Swesolows return (s); 213*1303Swesolows } 214*1303Swesolows 215*1303Swesolows void * 216*1303Swesolows fmd_fmri_alloc(size_t size) 217*1303Swesolows { 218*1303Swesolows return (malloc(size)); 219*1303Swesolows } 220*1303Swesolows 221*1303Swesolows void * 222*1303Swesolows fmd_fmri_zalloc(size_t size) 223*1303Swesolows { 224*1303Swesolows void *data; 225*1303Swesolows 226*1303Swesolows if ((data = malloc(size)) != NULL) 227*1303Swesolows bzero(data, size); 228*1303Swesolows 229*1303Swesolows return (data); 230*1303Swesolows } 231*1303Swesolows 232*1303Swesolows /*ARGSUSED*/ 233*1303Swesolows void 234*1303Swesolows fmd_fmri_free(void *data, size_t size) 235*1303Swesolows { 236*1303Swesolows free(data); 237*1303Swesolows } 238*1303Swesolows 239*1303Swesolows int 240*1303Swesolows fmd_fmri_error(int err) 241*1303Swesolows { 242*1303Swesolows errno = err; 243*1303Swesolows return (-1); 244*1303Swesolows } 245*1303Swesolows 246*1303Swesolows char * 247*1303Swesolows fmd_fmri_strescape(const char *s) 248*1303Swesolows { 249*1303Swesolows return (strdup(s)); 250*1303Swesolows } 251*1303Swesolows 252*1303Swesolows char * 253*1303Swesolows fmd_fmri_strdup(const char *s) 254*1303Swesolows { 255*1303Swesolows return (strdup(s)); 256*1303Swesolows } 257*1303Swesolows 258*1303Swesolows void 259*1303Swesolows fmd_fmri_strfree(char *s) 260*1303Swesolows { 261*1303Swesolows free(s); 262*1303Swesolows } 263*1303Swesolows 264*1303Swesolows const char * 265*1303Swesolows fmd_fmri_get_rootdir(void) 266*1303Swesolows { 267*1303Swesolows return (g_root ? g_root : ""); 268*1303Swesolows } 269*1303Swesolows 270*1303Swesolows const char * 271*1303Swesolows fmd_fmri_get_platform(void) 272*1303Swesolows { 273*1303Swesolows static char platform[MAXNAMELEN]; 274*1303Swesolows 275*1303Swesolows if (platform[0] == '\0') 276*1303Swesolows (void) sysinfo(SI_PLATFORM, platform, sizeof (platform)); 277*1303Swesolows 278*1303Swesolows return (platform); 279*1303Swesolows } 280*1303Swesolows 281*1303Swesolows uint64_t 282*1303Swesolows fmd_fmri_get_drgen(void) 283*1303Swesolows { 284*1303Swesolows return (0); 285*1303Swesolows } 286*1303Swesolows 287*1303Swesolows int 288*1303Swesolows fmd_fmri_set_errno(int err) 289*1303Swesolows { 290*1303Swesolows errno = err; 291*1303Swesolows return (-1); 292*1303Swesolows } 293*1303Swesolows 294*1303Swesolows void 295*1303Swesolows fmd_fmri_warn(const char *format, ...) 296*1303Swesolows { 297*1303Swesolows } 298