xref: /onnv-gate/usr/src/lib/fm/libfmd_snmp/common/scheme.c (revision 2134:60ffbfe58fef)
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