xref: /onnv-gate/usr/src/lib/fm/libfmd_snmp/common/scheme.c (revision 4198:6bdfb19526db)
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 /*
233955Swesolows  * Copyright 2007 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>
333955Swesolows #include <fm/libtopo.h>
341303Swesolows #include <net-snmp/net-snmp-config.h>
351303Swesolows #include <net-snmp/net-snmp-includes.h>
361303Swesolows #include <net-snmp/agent/net-snmp-agent-includes.h>
371303Swesolows #include <libnvpair.h>
381303Swesolows #include <limits.h>
391303Swesolows #include <strings.h>
401303Swesolows #include <stddef.h>
411303Swesolows #include <unistd.h>
421303Swesolows #include <dlfcn.h>
431303Swesolows #include <errno.h>
441303Swesolows 
451303Swesolows #define	SCHEMEDIR_BASE	"/usr/lib/fm/fmd/schemes"
461303Swesolows 
471303Swesolows #if defined(__sparcv9)
481303Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE "/sparcv9"
491303Swesolows #elif defined(__amd64)
501303Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE "/amd64"
511303Swesolows #else
521303Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE
531303Swesolows #endif
541303Swesolows 
551303Swesolows typedef struct fmd_scheme_ops {
561303Swesolows 	int (*sop_init)(void);
571303Swesolows 	void (*sop_fini)(void);
581303Swesolows 	ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t);
591303Swesolows } fmd_scheme_ops_t;
601303Swesolows 
611303Swesolows typedef struct fmd_scheme_opd {
621303Swesolows 	const char *opd_name;		/* symbol name of scheme function */
631303Swesolows 	size_t opd_off;			/* offset within fmd_scheme_ops_t */
641303Swesolows } fmd_scheme_opd_t;
651303Swesolows 
661303Swesolows typedef struct fmd_scheme {
671303Swesolows 	struct fmd_scheme *sch_next;    /* next scheme on list of schemes */
681303Swesolows 	char *sch_name;			/* name of this scheme (fmri prefix) */
691303Swesolows 	void *sch_dlp;			/* libdl(3DL) shared library handle */
701303Swesolows 	int sch_err;			/* if negative entry, errno to return */
711303Swesolows 	fmd_scheme_ops_t sch_ops;	/* scheme function pointers */
721303Swesolows } fmd_scheme_t;
731303Swesolows 
741303Swesolows static fmd_scheme_t *sch_list;		/* list of cached schemes */
751303Swesolows static char *g_root;			/* fmd root dir */
763955Swesolows static struct topo_hdl *g_thp;
771303Swesolows 
781303Swesolows static long
fmd_scheme_notsup(void)791303Swesolows fmd_scheme_notsup(void)
801303Swesolows {
811303Swesolows 	errno = ENOTSUP;
821303Swesolows 	return (-1);
831303Swesolows }
841303Swesolows 
851303Swesolows static int
fmd_scheme_nop(void)861303Swesolows fmd_scheme_nop(void)
871303Swesolows {
881303Swesolows 	return (0);
891303Swesolows }
901303Swesolows 
911303Swesolows /*
921303Swesolows  * Default values for the scheme ops.  If a scheme function is not defined in
931303Swesolows  * the module, then this operation is implemented using the default function.
941303Swesolows  */
951303Swesolows static const fmd_scheme_ops_t _fmd_scheme_default_ops = {
961303Swesolows 	(int (*)())fmd_scheme_nop,		/* sop_init */
971303Swesolows 	(void (*)())fmd_scheme_nop,		/* sop_fini */
981303Swesolows 	(ssize_t (*)())fmd_scheme_notsup,	/* sop_nvl2str */
991303Swesolows };
1001303Swesolows 
1011303Swesolows /*
1021303Swesolows  * Scheme ops descriptions.  These names and offsets are used by the function
1031303Swesolows  * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t.
1041303Swesolows  */
1051303Swesolows static const fmd_scheme_opd_t _fmd_scheme_ops[] = {
1061303Swesolows 	{ "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) },
1071303Swesolows 	{ "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) },
1081303Swesolows 	{ "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) },
1091303Swesolows 	{ NULL, 0 }
1101303Swesolows };
1111303Swesolows 
1121303Swesolows static fmd_scheme_t *
fmd_scheme_create(const char * name)1131303Swesolows fmd_scheme_create(const char *name)
1141303Swesolows {
1151303Swesolows 	fmd_scheme_t *sp;
1161303Swesolows 
1171303Swesolows 	if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL ||
1181303Swesolows 	    (sp->sch_name = strdup(name)) == NULL) {
1191303Swesolows 		free(sp);
1201303Swesolows 		return (NULL);
1211303Swesolows 	}
1221303Swesolows 
1231303Swesolows 	sp->sch_next = sch_list;
1241303Swesolows 	sp->sch_dlp = NULL;
1251303Swesolows 	sp->sch_err = 0;
1261303Swesolows 	sp->sch_ops = _fmd_scheme_default_ops;
1271303Swesolows 
1281303Swesolows 	sch_list = sp;
1291303Swesolows 	return (sp);
1301303Swesolows }
1311303Swesolows 
1321303Swesolows static int
fmd_scheme_rtld_init(fmd_scheme_t * sp)1331303Swesolows fmd_scheme_rtld_init(fmd_scheme_t *sp)
1341303Swesolows {
1351303Swesolows 	const fmd_scheme_opd_t *opd;
1361303Swesolows 	void *p;
1371303Swesolows 
1381303Swesolows 	for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) {
1391303Swesolows 		if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL)
1401303Swesolows 			*(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p;
1411303Swesolows 	}
1421303Swesolows 
1431303Swesolows 	return (sp->sch_ops.sop_init());
1441303Swesolows }
1451303Swesolows 
1461303Swesolows static fmd_scheme_t *
fmd_scheme_lookup(const char * dir,const char * name)1471303Swesolows fmd_scheme_lookup(const char *dir, const char *name)
1481303Swesolows {
1491303Swesolows 	fmd_scheme_t *sp;
1501303Swesolows 	char path[PATH_MAX];
1511303Swesolows 
1521303Swesolows 	for (sp = sch_list; sp != NULL; sp = sp->sch_next) {
1531303Swesolows 		if (strcmp(name, sp->sch_name) == 0)
1541303Swesolows 			return (sp);
1551303Swesolows 	}
1561303Swesolows 
1571303Swesolows 	if ((sp = fmd_scheme_create(name)) == NULL)
1581303Swesolows 		return (NULL); /* errno is set for us */
1591303Swesolows 
1601303Swesolows 	(void) snprintf(path, sizeof (path), "%s%s/%s.so",
1611303Swesolows 	    g_root ? g_root : "", dir, name);
1621303Swesolows 
1631303Swesolows 	if (access(path, F_OK) != 0) {
1641303Swesolows 		sp->sch_err = errno;
1651303Swesolows 		return (sp);
1661303Swesolows 	}
1671303Swesolows 
1681303Swesolows 	if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) ==
1691303Swesolows 	    NULL) {
1701303Swesolows 		sp->sch_err = ELIBACC;
1711303Swesolows 		return (sp);
1721303Swesolows 	}
1731303Swesolows 
1741303Swesolows 	if (fmd_scheme_rtld_init(sp) != 0) {
1751303Swesolows 		sp->sch_err = errno;
1761303Swesolows 		(void) dlclose(sp->sch_dlp);
1771303Swesolows 		sp->sch_dlp = NULL;
1781303Swesolows 	}
1791303Swesolows 
1801303Swesolows 	return (sp);
1811303Swesolows }
1821303Swesolows 
1831303Swesolows char *
sunFm_nvl2str(nvlist_t * nvl)1841303Swesolows sunFm_nvl2str(nvlist_t *nvl)
1851303Swesolows {
1861303Swesolows 	fmd_scheme_t *sp;
1871303Swesolows 	char c, *name, *s = NULL;
1881303Swesolows 	ssize_t len;
1891303Swesolows 
1901303Swesolows 	if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) {
1911303Swesolows 		DEBUGMSGTL((MODNAME_STR, "fmri does not contain required "
1921303Swesolows 		    "'%s' nvpair\n", FM_FMRI_SCHEME));
1931303Swesolows 		return (NULL);
1941303Swesolows 	}
1951303Swesolows 
1961303Swesolows 	if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL ||
1971303Swesolows 	    sp->sch_dlp == NULL || sp->sch_err != 0) {
1981303Swesolows 		const char *msg =
1991303Swesolows 		    sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err);
2001303Swesolows 		DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to "
2011303Swesolows 		    "format fmri: %s\n", name, msg ? msg : "unknown error"));
2021303Swesolows 		return (NULL);
2031303Swesolows 	}
2041303Swesolows 
2051303Swesolows 	if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 ||
2061303Swesolows 	    (s = malloc(len + 1)) == NULL ||
2071303Swesolows 	    sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) {
2081303Swesolows 		DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'",
2091303Swesolows 		    name));
2101303Swesolows 		free(s);
2111303Swesolows 		return (NULL);
2121303Swesolows 	}
2131303Swesolows 
2141303Swesolows 	return (s);
2151303Swesolows }
2161303Swesolows 
2171303Swesolows void *
fmd_fmri_alloc(size_t size)2181303Swesolows fmd_fmri_alloc(size_t size)
2191303Swesolows {
2201303Swesolows 	return (malloc(size));
2211303Swesolows }
2221303Swesolows 
2231303Swesolows void *
fmd_fmri_zalloc(size_t size)2241303Swesolows fmd_fmri_zalloc(size_t size)
2251303Swesolows {
2261303Swesolows 	void *data;
2271303Swesolows 
2281303Swesolows 	if ((data = malloc(size)) != NULL)
2291303Swesolows 		bzero(data, size);
2301303Swesolows 
2311303Swesolows 	return (data);
2321303Swesolows }
2331303Swesolows 
2341303Swesolows /*ARGSUSED*/
2351303Swesolows void
fmd_fmri_free(void * data,size_t size)2361303Swesolows fmd_fmri_free(void *data, size_t size)
2371303Swesolows {
2381303Swesolows 	free(data);
2391303Swesolows }
2401303Swesolows 
2411303Swesolows int
fmd_fmri_error(int err)2421303Swesolows fmd_fmri_error(int err)
2431303Swesolows {
2441303Swesolows 	errno = err;
2451303Swesolows 	return (-1);
2461303Swesolows }
2471303Swesolows 
2481303Swesolows char *
fmd_fmri_strescape(const char * s)2491303Swesolows fmd_fmri_strescape(const char *s)
2501303Swesolows {
2511303Swesolows 	return (strdup(s));
2521303Swesolows }
2531303Swesolows 
2541303Swesolows char *
fmd_fmri_strdup(const char * s)2551303Swesolows fmd_fmri_strdup(const char *s)
2561303Swesolows {
2571303Swesolows 	return (strdup(s));
2581303Swesolows }
2591303Swesolows 
2601303Swesolows void
fmd_fmri_strfree(char * s)2611303Swesolows fmd_fmri_strfree(char *s)
2621303Swesolows {
2631303Swesolows 	free(s);
2641303Swesolows }
2651303Swesolows 
2661303Swesolows const char *
fmd_fmri_get_rootdir(void)2671303Swesolows fmd_fmri_get_rootdir(void)
2681303Swesolows {
2691303Swesolows 	return (g_root ? g_root : "");
2701303Swesolows }
2711303Swesolows 
2721303Swesolows const char *
fmd_fmri_get_platform(void)2731303Swesolows fmd_fmri_get_platform(void)
2741303Swesolows {
2751303Swesolows 	static char platform[MAXNAMELEN];
2761303Swesolows 
2771303Swesolows 	if (platform[0] == '\0')
2781303Swesolows 		(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
2791303Swesolows 
2801303Swesolows 	return (platform);
2811303Swesolows }
2821303Swesolows 
2831303Swesolows uint64_t
fmd_fmri_get_drgen(void)2841303Swesolows fmd_fmri_get_drgen(void)
2851303Swesolows {
2861303Swesolows 	return (0);
2871303Swesolows }
2881303Swesolows 
2891303Swesolows int
fmd_fmri_set_errno(int err)2901303Swesolows fmd_fmri_set_errno(int err)
2911303Swesolows {
2921303Swesolows 	errno = err;
2931303Swesolows 	return (-1);
2941303Swesolows }
2951303Swesolows 
2962134Swesolows /*ARGSUSED*/
2971303Swesolows void
fmd_fmri_warn(const char * format,...)2981303Swesolows fmd_fmri_warn(const char *format, ...)
2991303Swesolows {
3001303Swesolows }
3013955Swesolows 
3023955Swesolows struct topo_hdl *
fmd_fmri_topo_hold(int version)303*4198Seschrock fmd_fmri_topo_hold(int version)
3043955Swesolows {
3053955Swesolows 	int err;
3063955Swesolows 
307*4198Seschrock 	if (version != TOPO_VERSION)
308*4198Seschrock 		return (NULL);
309*4198Seschrock 
3103955Swesolows 	if (g_thp == NULL) {
3113955Swesolows 		if ((g_thp = topo_open(TOPO_VERSION, "/", &err)) == NULL) {
3123955Swesolows 			DEBUGMSGTL((MODNAME_STR, "topo_open failed: %s\n",
3133955Swesolows 			    topo_strerror(err)));
3143955Swesolows 			return (NULL);
3153955Swesolows 		}
3163955Swesolows 	}
3173955Swesolows 
3183955Swesolows 	return (g_thp);
3193955Swesolows }
320*4198Seschrock 
321*4198Seschrock /*ARGSUSED*/
322*4198Seschrock void
fmd_fmri_topo_rele(struct topo_hdl * thp)323*4198Seschrock fmd_fmri_topo_rele(struct topo_hdl *thp)
324*4198Seschrock {
325*4198Seschrock 	/* nothing to do */
326*4198Seschrock }
327