summaryrefslogtreecommitdiff
path: root/usr/src/lib/fm/libfmd_snmp/common/scheme.c
diff options
context:
space:
mode:
authorwesolows <none@none>2006-01-20 16:06:55 -0800
committerwesolows <none@none>2006-01-20 16:06:55 -0800
commit749f21d359d8fbd020c974a1a5227316221bfc9c (patch)
tree41bfaf56a9f0c31430c9dd2e35fedffd5d69b220 /usr/src/lib/fm/libfmd_snmp/common/scheme.c
parent1f017db093f7568e41a3d8c6429e13daf5424ff8 (diff)
downloadillumos-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.c297
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, ...)
+{
+}