11303Swesolows /* 21303Swesolows * CDDL HEADER START 31303Swesolows * 41303Swesolows * The contents of this file are subject to the terms of the 51303Swesolows * Common Development and Distribution License (the "License"). 61303Swesolows * You may not use this file except in compliance with the License. 71303Swesolows * 81303Swesolows * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91303Swesolows * or http://www.opensolaris.org/os/licensing. 101303Swesolows * See the License for the specific language governing permissions 111303Swesolows * and limitations under the License. 121303Swesolows * 131303Swesolows * When distributing Covered Code, include this CDDL HEADER in each 141303Swesolows * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151303Swesolows * If applicable, add the following below this CDDL HEADER, with the 161303Swesolows * fields enclosed by brackets "[]" replaced with your own identifying 171303Swesolows * information: Portions Copyright [yyyy] [name of copyright owner] 181303Swesolows * 191303Swesolows * CDDL HEADER END 201303Swesolows */ 211303Swesolows 221303Swesolows /* 231303Swesolows * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 241303Swesolows * Use is subject to license terms. 251303Swesolows */ 261303Swesolows 271303Swesolows #pragma ident "%Z%%M% %I% %E% SMI" 281303Swesolows 291303Swesolows #include <sys/fm/protocol.h> 301303Swesolows #include <sys/types.h> 311303Swesolows #include <sys/systeminfo.h> 321303Swesolows #include <fm/fmd_snmp.h> 331303Swesolows #include <net-snmp/net-snmp-config.h> 341303Swesolows #include <net-snmp/net-snmp-includes.h> 351303Swesolows #include <net-snmp/agent/net-snmp-agent-includes.h> 361303Swesolows #include <libnvpair.h> 371303Swesolows #include <limits.h> 381303Swesolows #include <strings.h> 391303Swesolows #include <stddef.h> 401303Swesolows #include <unistd.h> 411303Swesolows #include <dlfcn.h> 421303Swesolows #include <errno.h> 431303Swesolows 441303Swesolows #define SCHEMEDIR_BASE "/usr/lib/fm/fmd/schemes" 451303Swesolows 461303Swesolows #if defined(__sparcv9) 471303Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/sparcv9" 481303Swesolows #elif defined(__amd64) 491303Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/amd64" 501303Swesolows #else 511303Swesolows #define DEFAULTSCHEMEDIR SCHEMEDIR_BASE 521303Swesolows #endif 531303Swesolows 541303Swesolows typedef struct fmd_scheme_ops { 551303Swesolows int (*sop_init)(void); 561303Swesolows void (*sop_fini)(void); 571303Swesolows ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t); 581303Swesolows } fmd_scheme_ops_t; 591303Swesolows 601303Swesolows typedef struct fmd_scheme_opd { 611303Swesolows const char *opd_name; /* symbol name of scheme function */ 621303Swesolows size_t opd_off; /* offset within fmd_scheme_ops_t */ 631303Swesolows } fmd_scheme_opd_t; 641303Swesolows 651303Swesolows typedef struct fmd_scheme { 661303Swesolows struct fmd_scheme *sch_next; /* next scheme on list of schemes */ 671303Swesolows char *sch_name; /* name of this scheme (fmri prefix) */ 681303Swesolows void *sch_dlp; /* libdl(3DL) shared library handle */ 691303Swesolows int sch_err; /* if negative entry, errno to return */ 701303Swesolows fmd_scheme_ops_t sch_ops; /* scheme function pointers */ 711303Swesolows } fmd_scheme_t; 721303Swesolows 731303Swesolows static fmd_scheme_t *sch_list; /* list of cached schemes */ 741303Swesolows static char *g_root; /* fmd root dir */ 751303Swesolows 761303Swesolows static long 771303Swesolows fmd_scheme_notsup(void) 781303Swesolows { 791303Swesolows errno = ENOTSUP; 801303Swesolows return (-1); 811303Swesolows } 821303Swesolows 831303Swesolows static int 841303Swesolows fmd_scheme_nop(void) 851303Swesolows { 861303Swesolows return (0); 871303Swesolows } 881303Swesolows 891303Swesolows /* 901303Swesolows * Default values for the scheme ops. If a scheme function is not defined in 911303Swesolows * the module, then this operation is implemented using the default function. 921303Swesolows */ 931303Swesolows static const fmd_scheme_ops_t _fmd_scheme_default_ops = { 941303Swesolows (int (*)())fmd_scheme_nop, /* sop_init */ 951303Swesolows (void (*)())fmd_scheme_nop, /* sop_fini */ 961303Swesolows (ssize_t (*)())fmd_scheme_notsup, /* sop_nvl2str */ 971303Swesolows }; 981303Swesolows 991303Swesolows /* 1001303Swesolows * Scheme ops descriptions. These names and offsets are used by the function 1011303Swesolows * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t. 1021303Swesolows */ 1031303Swesolows static const fmd_scheme_opd_t _fmd_scheme_ops[] = { 1041303Swesolows { "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) }, 1051303Swesolows { "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) }, 1061303Swesolows { "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) }, 1071303Swesolows { NULL, 0 } 1081303Swesolows }; 1091303Swesolows 1101303Swesolows static fmd_scheme_t * 1111303Swesolows fmd_scheme_create(const char *name) 1121303Swesolows { 1131303Swesolows fmd_scheme_t *sp; 1141303Swesolows 1151303Swesolows if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL || 1161303Swesolows (sp->sch_name = strdup(name)) == NULL) { 1171303Swesolows free(sp); 1181303Swesolows return (NULL); 1191303Swesolows } 1201303Swesolows 1211303Swesolows sp->sch_next = sch_list; 1221303Swesolows sp->sch_dlp = NULL; 1231303Swesolows sp->sch_err = 0; 1241303Swesolows sp->sch_ops = _fmd_scheme_default_ops; 1251303Swesolows 1261303Swesolows sch_list = sp; 1271303Swesolows return (sp); 1281303Swesolows } 1291303Swesolows 1301303Swesolows static int 1311303Swesolows fmd_scheme_rtld_init(fmd_scheme_t *sp) 1321303Swesolows { 1331303Swesolows const fmd_scheme_opd_t *opd; 1341303Swesolows void *p; 1351303Swesolows 1361303Swesolows for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) { 1371303Swesolows if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL) 1381303Swesolows *(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p; 1391303Swesolows } 1401303Swesolows 1411303Swesolows return (sp->sch_ops.sop_init()); 1421303Swesolows } 1431303Swesolows 1441303Swesolows static fmd_scheme_t * 1451303Swesolows fmd_scheme_lookup(const char *dir, const char *name) 1461303Swesolows { 1471303Swesolows fmd_scheme_t *sp; 1481303Swesolows char path[PATH_MAX]; 1491303Swesolows 1501303Swesolows for (sp = sch_list; sp != NULL; sp = sp->sch_next) { 1511303Swesolows if (strcmp(name, sp->sch_name) == 0) 1521303Swesolows return (sp); 1531303Swesolows } 1541303Swesolows 1551303Swesolows if ((sp = fmd_scheme_create(name)) == NULL) 1561303Swesolows return (NULL); /* errno is set for us */ 1571303Swesolows 1581303Swesolows (void) snprintf(path, sizeof (path), "%s%s/%s.so", 1591303Swesolows g_root ? g_root : "", dir, name); 1601303Swesolows 1611303Swesolows if (access(path, F_OK) != 0) { 1621303Swesolows sp->sch_err = errno; 1631303Swesolows return (sp); 1641303Swesolows } 1651303Swesolows 1661303Swesolows if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) == 1671303Swesolows NULL) { 1681303Swesolows sp->sch_err = ELIBACC; 1691303Swesolows return (sp); 1701303Swesolows } 1711303Swesolows 1721303Swesolows if (fmd_scheme_rtld_init(sp) != 0) { 1731303Swesolows sp->sch_err = errno; 1741303Swesolows (void) dlclose(sp->sch_dlp); 1751303Swesolows sp->sch_dlp = NULL; 1761303Swesolows } 1771303Swesolows 1781303Swesolows return (sp); 1791303Swesolows } 1801303Swesolows 1811303Swesolows char * 1821303Swesolows sunFm_nvl2str(nvlist_t *nvl) 1831303Swesolows { 1841303Swesolows fmd_scheme_t *sp; 1851303Swesolows char c, *name, *s = NULL; 1861303Swesolows ssize_t len; 1871303Swesolows 1881303Swesolows if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) { 1891303Swesolows DEBUGMSGTL((MODNAME_STR, "fmri does not contain required " 1901303Swesolows "'%s' nvpair\n", FM_FMRI_SCHEME)); 1911303Swesolows return (NULL); 1921303Swesolows } 1931303Swesolows 1941303Swesolows if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL || 1951303Swesolows sp->sch_dlp == NULL || sp->sch_err != 0) { 1961303Swesolows const char *msg = 1971303Swesolows sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err); 1981303Swesolows DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to " 1991303Swesolows "format fmri: %s\n", name, msg ? msg : "unknown error")); 2001303Swesolows return (NULL); 2011303Swesolows } 2021303Swesolows 2031303Swesolows if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 || 2041303Swesolows (s = malloc(len + 1)) == NULL || 2051303Swesolows sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) { 2061303Swesolows DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'", 2071303Swesolows name)); 2081303Swesolows free(s); 2091303Swesolows return (NULL); 2101303Swesolows } 2111303Swesolows 2121303Swesolows return (s); 2131303Swesolows } 2141303Swesolows 2151303Swesolows void * 2161303Swesolows fmd_fmri_alloc(size_t size) 2171303Swesolows { 2181303Swesolows return (malloc(size)); 2191303Swesolows } 2201303Swesolows 2211303Swesolows void * 2221303Swesolows fmd_fmri_zalloc(size_t size) 2231303Swesolows { 2241303Swesolows void *data; 2251303Swesolows 2261303Swesolows if ((data = malloc(size)) != NULL) 2271303Swesolows bzero(data, size); 2281303Swesolows 2291303Swesolows return (data); 2301303Swesolows } 2311303Swesolows 2321303Swesolows /*ARGSUSED*/ 2331303Swesolows void 2341303Swesolows fmd_fmri_free(void *data, size_t size) 2351303Swesolows { 2361303Swesolows free(data); 2371303Swesolows } 2381303Swesolows 2391303Swesolows int 2401303Swesolows fmd_fmri_error(int err) 2411303Swesolows { 2421303Swesolows errno = err; 2431303Swesolows return (-1); 2441303Swesolows } 2451303Swesolows 2461303Swesolows char * 2471303Swesolows fmd_fmri_strescape(const char *s) 2481303Swesolows { 2491303Swesolows return (strdup(s)); 2501303Swesolows } 2511303Swesolows 2521303Swesolows char * 2531303Swesolows fmd_fmri_strdup(const char *s) 2541303Swesolows { 2551303Swesolows return (strdup(s)); 2561303Swesolows } 2571303Swesolows 2581303Swesolows void 2591303Swesolows fmd_fmri_strfree(char *s) 2601303Swesolows { 2611303Swesolows free(s); 2621303Swesolows } 2631303Swesolows 2641303Swesolows const char * 2651303Swesolows fmd_fmri_get_rootdir(void) 2661303Swesolows { 2671303Swesolows return (g_root ? g_root : ""); 2681303Swesolows } 2691303Swesolows 2701303Swesolows const char * 2711303Swesolows fmd_fmri_get_platform(void) 2721303Swesolows { 2731303Swesolows static char platform[MAXNAMELEN]; 2741303Swesolows 2751303Swesolows if (platform[0] == '\0') 2761303Swesolows (void) sysinfo(SI_PLATFORM, platform, sizeof (platform)); 2771303Swesolows 2781303Swesolows return (platform); 2791303Swesolows } 2801303Swesolows 2811303Swesolows uint64_t 2821303Swesolows fmd_fmri_get_drgen(void) 2831303Swesolows { 2841303Swesolows return (0); 2851303Swesolows } 2861303Swesolows 2871303Swesolows int 2881303Swesolows fmd_fmri_set_errno(int err) 2891303Swesolows { 2901303Swesolows errno = err; 2911303Swesolows return (-1); 2921303Swesolows } 2931303Swesolows 294*2134Swesolows /*ARGSUSED*/ 2951303Swesolows void 2961303Swesolows fmd_fmri_warn(const char *format, ...) 2971303Swesolows { 2981303Swesolows } 299