diff options
| author | wesolows <none@none> | 2006-01-20 16:06:55 -0800 |
|---|---|---|
| committer | wesolows <none@none> | 2006-01-20 16:06:55 -0800 |
| commit | 749f21d359d8fbd020c974a1a5227316221bfc9c (patch) | |
| tree | 41bfaf56a9f0c31430c9dd2e35fedffd5d69b220 /usr/src/lib/fm/libfmd_snmp/common/scheme.c | |
| parent | 1f017db093f7568e41a3d8c6429e13daf5424ff8 (diff) | |
| download | illumos-gate-749f21d359d8fbd020c974a1a5227316221bfc9c.tar.gz | |
PSARC 2005/754 FMA SNMP Agent
6365742 fault management data needs an SNMP interface
6365743 need 64-bit fmd scheme plugins
Diffstat (limited to 'usr/src/lib/fm/libfmd_snmp/common/scheme.c')
| -rw-r--r-- | usr/src/lib/fm/libfmd_snmp/common/scheme.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/usr/src/lib/fm/libfmd_snmp/common/scheme.c b/usr/src/lib/fm/libfmd_snmp/common/scheme.c new file mode 100644 index 0000000000..a357c23e71 --- /dev/null +++ b/usr/src/lib/fm/libfmd_snmp/common/scheme.c @@ -0,0 +1,297 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/fm/protocol.h> +#include <sys/types.h> +#include <sys/systeminfo.h> +#include <fm/fmd_snmp.h> +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include <libnvpair.h> +#include <limits.h> +#include <strings.h> +#include <stddef.h> +#include <unistd.h> +#include <dlfcn.h> +#include <errno.h> + +#define SCHEMEDIR_BASE "/usr/lib/fm/fmd/schemes" + +#if defined(__sparcv9) +#define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/sparcv9" +#elif defined(__amd64) +#define DEFAULTSCHEMEDIR SCHEMEDIR_BASE "/amd64" +#else +#define DEFAULTSCHEMEDIR SCHEMEDIR_BASE +#endif + +typedef struct fmd_scheme_ops { + int (*sop_init)(void); + void (*sop_fini)(void); + ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t); +} fmd_scheme_ops_t; + +typedef struct fmd_scheme_opd { + const char *opd_name; /* symbol name of scheme function */ + size_t opd_off; /* offset within fmd_scheme_ops_t */ +} fmd_scheme_opd_t; + +typedef struct fmd_scheme { + struct fmd_scheme *sch_next; /* next scheme on list of schemes */ + char *sch_name; /* name of this scheme (fmri prefix) */ + void *sch_dlp; /* libdl(3DL) shared library handle */ + int sch_err; /* if negative entry, errno to return */ + fmd_scheme_ops_t sch_ops; /* scheme function pointers */ +} fmd_scheme_t; + +static fmd_scheme_t *sch_list; /* list of cached schemes */ +static char *g_root; /* fmd root dir */ + +static long +fmd_scheme_notsup(void) +{ + errno = ENOTSUP; + return (-1); +} + +static int +fmd_scheme_nop(void) +{ + return (0); +} + +/* + * Default values for the scheme ops. If a scheme function is not defined in + * the module, then this operation is implemented using the default function. + */ +static const fmd_scheme_ops_t _fmd_scheme_default_ops = { + (int (*)())fmd_scheme_nop, /* sop_init */ + (void (*)())fmd_scheme_nop, /* sop_fini */ + (ssize_t (*)())fmd_scheme_notsup, /* sop_nvl2str */ +}; + +/* + * Scheme ops descriptions. These names and offsets are used by the function + * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t. + */ +static const fmd_scheme_opd_t _fmd_scheme_ops[] = { + { "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) }, + { "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) }, + { "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) }, + { NULL, 0 } +}; + +static fmd_scheme_t * +fmd_scheme_create(const char *name) +{ + fmd_scheme_t *sp; + + if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL || + (sp->sch_name = strdup(name)) == NULL) { + free(sp); + return (NULL); + } + + sp->sch_next = sch_list; + sp->sch_dlp = NULL; + sp->sch_err = 0; + sp->sch_ops = _fmd_scheme_default_ops; + + sch_list = sp; + return (sp); +} + +static int +fmd_scheme_rtld_init(fmd_scheme_t *sp) +{ + const fmd_scheme_opd_t *opd; + void *p; + + for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) { + if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL) + *(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p; + } + + return (sp->sch_ops.sop_init()); +} + +static fmd_scheme_t * +fmd_scheme_lookup(const char *dir, const char *name) +{ + fmd_scheme_t *sp; + char path[PATH_MAX]; + + for (sp = sch_list; sp != NULL; sp = sp->sch_next) { + if (strcmp(name, sp->sch_name) == 0) + return (sp); + } + + if ((sp = fmd_scheme_create(name)) == NULL) + return (NULL); /* errno is set for us */ + + (void) snprintf(path, sizeof (path), "%s%s/%s.so", + g_root ? g_root : "", dir, name); + + if (access(path, F_OK) != 0) { + sp->sch_err = errno; + return (sp); + } + + if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) == + NULL) { + sp->sch_err = ELIBACC; + return (sp); + } + + if (fmd_scheme_rtld_init(sp) != 0) { + sp->sch_err = errno; + (void) dlclose(sp->sch_dlp); + sp->sch_dlp = NULL; + } + + return (sp); +} + +char * +sunFm_nvl2str(nvlist_t *nvl) +{ + fmd_scheme_t *sp; + char c, *name, *s = NULL; + ssize_t len; + + if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) { + DEBUGMSGTL((MODNAME_STR, "fmri does not contain required " + "'%s' nvpair\n", FM_FMRI_SCHEME)); + return (NULL); + } + + if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL || + sp->sch_dlp == NULL || sp->sch_err != 0) { + const char *msg = + sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err); + DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to " + "format fmri: %s\n", name, msg ? msg : "unknown error")); + return (NULL); + } + + if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 || + (s = malloc(len + 1)) == NULL || + sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) { + DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'", + name)); + free(s); + return (NULL); + } + + return (s); +} + +void * +fmd_fmri_alloc(size_t size) +{ + return (malloc(size)); +} + +void * +fmd_fmri_zalloc(size_t size) +{ + void *data; + + if ((data = malloc(size)) != NULL) + bzero(data, size); + + return (data); +} + +/*ARGSUSED*/ +void +fmd_fmri_free(void *data, size_t size) +{ + free(data); +} + +int +fmd_fmri_error(int err) +{ + errno = err; + return (-1); +} + +char * +fmd_fmri_strescape(const char *s) +{ + return (strdup(s)); +} + +char * +fmd_fmri_strdup(const char *s) +{ + return (strdup(s)); +} + +void +fmd_fmri_strfree(char *s) +{ + free(s); +} + +const char * +fmd_fmri_get_rootdir(void) +{ + return (g_root ? g_root : ""); +} + +const char * +fmd_fmri_get_platform(void) +{ + static char platform[MAXNAMELEN]; + + if (platform[0] == '\0') + (void) sysinfo(SI_PLATFORM, platform, sizeof (platform)); + + return (platform); +} + +uint64_t +fmd_fmri_get_drgen(void) +{ + return (0); +} + +int +fmd_fmri_set_errno(int err) +{ + errno = err; + return (-1); +} + +void +fmd_fmri_warn(const char *format, ...) +{ +} |
