xref: /illumos-gate/usr/src/lib/fm/libfmd_snmp/common/scheme.c (revision 1743a90d9abccc6cd1e57ef89729c674b859fc6e)
1749f21d3Swesolows /*
2749f21d3Swesolows  * CDDL HEADER START
3749f21d3Swesolows  *
4749f21d3Swesolows  * The contents of this file are subject to the terms of the
5749f21d3Swesolows  * Common Development and Distribution License (the "License").
6749f21d3Swesolows  * You may not use this file except in compliance with the License.
7749f21d3Swesolows  *
8749f21d3Swesolows  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9749f21d3Swesolows  * or http://www.opensolaris.org/os/licensing.
10749f21d3Swesolows  * See the License for the specific language governing permissions
11749f21d3Swesolows  * and limitations under the License.
12749f21d3Swesolows  *
13749f21d3Swesolows  * When distributing Covered Code, include this CDDL HEADER in each
14749f21d3Swesolows  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15749f21d3Swesolows  * If applicable, add the following below this CDDL HEADER, with the
16749f21d3Swesolows  * fields enclosed by brackets "[]" replaced with your own identifying
17749f21d3Swesolows  * information: Portions Copyright [yyyy] [name of copyright owner]
18749f21d3Swesolows  *
19749f21d3Swesolows  * CDDL HEADER END
20749f21d3Swesolows  */
21749f21d3Swesolows 
22749f21d3Swesolows /*
231fe76c0bSwesolows  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24749f21d3Swesolows  * Use is subject to license terms.
25749f21d3Swesolows  */
26749f21d3Swesolows 
27749f21d3Swesolows #include <sys/fm/protocol.h>
28749f21d3Swesolows #include <sys/types.h>
29749f21d3Swesolows #include <sys/systeminfo.h>
30749f21d3Swesolows #include <fm/fmd_snmp.h>
311fe76c0bSwesolows #include <fm/libtopo.h>
32749f21d3Swesolows #include <net-snmp/net-snmp-config.h>
33749f21d3Swesolows #include <net-snmp/net-snmp-includes.h>
34749f21d3Swesolows #include <net-snmp/agent/net-snmp-agent-includes.h>
35749f21d3Swesolows #include <libnvpair.h>
36749f21d3Swesolows #include <limits.h>
37749f21d3Swesolows #include <strings.h>
38749f21d3Swesolows #include <stddef.h>
39749f21d3Swesolows #include <unistd.h>
40749f21d3Swesolows #include <dlfcn.h>
41749f21d3Swesolows #include <errno.h>
42749f21d3Swesolows 
43749f21d3Swesolows #define	SCHEMEDIR_BASE	"/usr/lib/fm/fmd/schemes"
44749f21d3Swesolows 
45749f21d3Swesolows #if defined(__sparcv9)
46749f21d3Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE "/sparcv9"
47749f21d3Swesolows #elif defined(__amd64)
48749f21d3Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE "/amd64"
49749f21d3Swesolows #else
50749f21d3Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE
51749f21d3Swesolows #endif
52749f21d3Swesolows 
53749f21d3Swesolows typedef struct fmd_scheme_ops {
54749f21d3Swesolows 	int (*sop_init)(void);
55749f21d3Swesolows 	void (*sop_fini)(void);
56749f21d3Swesolows 	ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t);
57749f21d3Swesolows } fmd_scheme_ops_t;
58749f21d3Swesolows 
59749f21d3Swesolows typedef struct fmd_scheme_opd {
60749f21d3Swesolows 	const char *opd_name;		/* symbol name of scheme function */
61749f21d3Swesolows 	size_t opd_off;			/* offset within fmd_scheme_ops_t */
62749f21d3Swesolows } fmd_scheme_opd_t;
63749f21d3Swesolows 
64749f21d3Swesolows typedef struct fmd_scheme {
65749f21d3Swesolows 	struct fmd_scheme *sch_next;    /* next scheme on list of schemes */
66749f21d3Swesolows 	char *sch_name;			/* name of this scheme (fmri prefix) */
67749f21d3Swesolows 	void *sch_dlp;			/* libdl(3DL) shared library handle */
68749f21d3Swesolows 	int sch_err;			/* if negative entry, errno to return */
69749f21d3Swesolows 	fmd_scheme_ops_t sch_ops;	/* scheme function pointers */
70749f21d3Swesolows } fmd_scheme_t;
71749f21d3Swesolows 
72749f21d3Swesolows static fmd_scheme_t *sch_list;		/* list of cached schemes */
73749f21d3Swesolows static char *g_root;			/* fmd root dir */
741fe76c0bSwesolows static struct topo_hdl *g_thp;
75749f21d3Swesolows 
76*1743a90dSToomas Soome static ssize_t
fmd_scheme_notsup(nvlist_t * nv __unused,char * arg1 __unused,size_t arg2 __unused)77*1743a90dSToomas Soome fmd_scheme_notsup(nvlist_t *nv __unused, char *arg1 __unused,
78*1743a90dSToomas Soome     size_t arg2 __unused)
79749f21d3Swesolows {
80749f21d3Swesolows 	errno = ENOTSUP;
81749f21d3Swesolows 	return (-1);
82749f21d3Swesolows }
83749f21d3Swesolows 
84*1743a90dSToomas Soome static void
fmd_scheme_vnop(void)85*1743a90dSToomas Soome fmd_scheme_vnop(void)
86*1743a90dSToomas Soome {
87*1743a90dSToomas Soome }
88*1743a90dSToomas Soome 
89749f21d3Swesolows static int
fmd_scheme_nop(void)90749f21d3Swesolows fmd_scheme_nop(void)
91749f21d3Swesolows {
92749f21d3Swesolows 	return (0);
93749f21d3Swesolows }
94749f21d3Swesolows 
95749f21d3Swesolows /*
96749f21d3Swesolows  * Default values for the scheme ops.  If a scheme function is not defined in
97749f21d3Swesolows  * the module, then this operation is implemented using the default function.
98749f21d3Swesolows  */
99749f21d3Swesolows static const fmd_scheme_ops_t _fmd_scheme_default_ops = {
100*1743a90dSToomas Soome 	.sop_init = fmd_scheme_nop,		/* sop_init */
101*1743a90dSToomas Soome 	.sop_fini = fmd_scheme_vnop,		/* sop_fini */
102*1743a90dSToomas Soome 	.sop_nvl2str = fmd_scheme_notsup	/* sop_nvl2str */
103749f21d3Swesolows };
104749f21d3Swesolows 
105749f21d3Swesolows /*
106749f21d3Swesolows  * Scheme ops descriptions.  These names and offsets are used by the function
107749f21d3Swesolows  * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t.
108749f21d3Swesolows  */
109749f21d3Swesolows static const fmd_scheme_opd_t _fmd_scheme_ops[] = {
110749f21d3Swesolows 	{ "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) },
111749f21d3Swesolows 	{ "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) },
112749f21d3Swesolows 	{ "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) },
113749f21d3Swesolows 	{ NULL, 0 }
114749f21d3Swesolows };
115749f21d3Swesolows 
116749f21d3Swesolows static fmd_scheme_t *
fmd_scheme_create(const char * name)117749f21d3Swesolows fmd_scheme_create(const char *name)
118749f21d3Swesolows {
119749f21d3Swesolows 	fmd_scheme_t *sp;
120749f21d3Swesolows 
121749f21d3Swesolows 	if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL ||
122749f21d3Swesolows 	    (sp->sch_name = strdup(name)) == NULL) {
123749f21d3Swesolows 		free(sp);
124749f21d3Swesolows 		return (NULL);
125749f21d3Swesolows 	}
126749f21d3Swesolows 
127749f21d3Swesolows 	sp->sch_next = sch_list;
128749f21d3Swesolows 	sp->sch_dlp = NULL;
129749f21d3Swesolows 	sp->sch_err = 0;
130749f21d3Swesolows 	sp->sch_ops = _fmd_scheme_default_ops;
131749f21d3Swesolows 
132749f21d3Swesolows 	sch_list = sp;
133749f21d3Swesolows 	return (sp);
134749f21d3Swesolows }
135749f21d3Swesolows 
136749f21d3Swesolows static int
fmd_scheme_rtld_init(fmd_scheme_t * sp)137749f21d3Swesolows fmd_scheme_rtld_init(fmd_scheme_t *sp)
138749f21d3Swesolows {
139749f21d3Swesolows 	const fmd_scheme_opd_t *opd;
140749f21d3Swesolows 	void *p;
141749f21d3Swesolows 
142749f21d3Swesolows 	for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) {
143749f21d3Swesolows 		if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL)
144749f21d3Swesolows 			*(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p;
145749f21d3Swesolows 	}
146749f21d3Swesolows 
147749f21d3Swesolows 	return (sp->sch_ops.sop_init());
148749f21d3Swesolows }
149749f21d3Swesolows 
150749f21d3Swesolows static fmd_scheme_t *
fmd_scheme_lookup(const char * dir,const char * name)151749f21d3Swesolows fmd_scheme_lookup(const char *dir, const char *name)
152749f21d3Swesolows {
153749f21d3Swesolows 	fmd_scheme_t *sp;
154749f21d3Swesolows 	char path[PATH_MAX];
155749f21d3Swesolows 
156749f21d3Swesolows 	for (sp = sch_list; sp != NULL; sp = sp->sch_next) {
157749f21d3Swesolows 		if (strcmp(name, sp->sch_name) == 0)
158749f21d3Swesolows 			return (sp);
159749f21d3Swesolows 	}
160749f21d3Swesolows 
161749f21d3Swesolows 	if ((sp = fmd_scheme_create(name)) == NULL)
162749f21d3Swesolows 		return (NULL); /* errno is set for us */
163749f21d3Swesolows 
164749f21d3Swesolows 	(void) snprintf(path, sizeof (path), "%s%s/%s.so",
165749f21d3Swesolows 	    g_root ? g_root : "", dir, name);
166749f21d3Swesolows 
167749f21d3Swesolows 	if (access(path, F_OK) != 0) {
168749f21d3Swesolows 		sp->sch_err = errno;
169749f21d3Swesolows 		return (sp);
170749f21d3Swesolows 	}
171749f21d3Swesolows 
172749f21d3Swesolows 	if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) ==
173749f21d3Swesolows 	    NULL) {
174749f21d3Swesolows 		sp->sch_err = ELIBACC;
175749f21d3Swesolows 		return (sp);
176749f21d3Swesolows 	}
177749f21d3Swesolows 
178749f21d3Swesolows 	if (fmd_scheme_rtld_init(sp) != 0) {
179749f21d3Swesolows 		sp->sch_err = errno;
180749f21d3Swesolows 		(void) dlclose(sp->sch_dlp);
181749f21d3Swesolows 		sp->sch_dlp = NULL;
182749f21d3Swesolows 	}
183749f21d3Swesolows 
184749f21d3Swesolows 	return (sp);
185749f21d3Swesolows }
186749f21d3Swesolows 
187749f21d3Swesolows char *
sunFm_nvl2str(nvlist_t * nvl)188749f21d3Swesolows sunFm_nvl2str(nvlist_t *nvl)
189749f21d3Swesolows {
190749f21d3Swesolows 	fmd_scheme_t *sp;
191749f21d3Swesolows 	char c, *name, *s = NULL;
192749f21d3Swesolows 	ssize_t len;
193749f21d3Swesolows 
194749f21d3Swesolows 	if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) {
195749f21d3Swesolows 		DEBUGMSGTL((MODNAME_STR, "fmri does not contain required "
196749f21d3Swesolows 		    "'%s' nvpair\n", FM_FMRI_SCHEME));
197749f21d3Swesolows 		return (NULL);
198749f21d3Swesolows 	}
199749f21d3Swesolows 
200749f21d3Swesolows 	if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL ||
201749f21d3Swesolows 	    sp->sch_dlp == NULL || sp->sch_err != 0) {
202749f21d3Swesolows 		const char *msg =
203749f21d3Swesolows 		    sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err);
204749f21d3Swesolows 		DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to "
205749f21d3Swesolows 		    "format fmri: %s\n", name, msg ? msg : "unknown error"));
206749f21d3Swesolows 		return (NULL);
207749f21d3Swesolows 	}
208749f21d3Swesolows 
209749f21d3Swesolows 	if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 ||
210749f21d3Swesolows 	    (s = malloc(len + 1)) == NULL ||
211749f21d3Swesolows 	    sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) {
212749f21d3Swesolows 		DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'",
213749f21d3Swesolows 		    name));
214749f21d3Swesolows 		free(s);
215749f21d3Swesolows 		return (NULL);
216749f21d3Swesolows 	}
217749f21d3Swesolows 
218749f21d3Swesolows 	return (s);
219749f21d3Swesolows }
220749f21d3Swesolows 
221749f21d3Swesolows void *
fmd_fmri_alloc(size_t size)222749f21d3Swesolows fmd_fmri_alloc(size_t size)
223749f21d3Swesolows {
224749f21d3Swesolows 	return (malloc(size));
225749f21d3Swesolows }
226749f21d3Swesolows 
227749f21d3Swesolows void *
fmd_fmri_zalloc(size_t size)228749f21d3Swesolows fmd_fmri_zalloc(size_t size)
229749f21d3Swesolows {
230749f21d3Swesolows 	void *data;
231749f21d3Swesolows 
232749f21d3Swesolows 	if ((data = malloc(size)) != NULL)
233749f21d3Swesolows 		bzero(data, size);
234749f21d3Swesolows 
235749f21d3Swesolows 	return (data);
236749f21d3Swesolows }
237749f21d3Swesolows 
238749f21d3Swesolows /*ARGSUSED*/
239749f21d3Swesolows void
fmd_fmri_free(void * data,size_t size)240749f21d3Swesolows fmd_fmri_free(void *data, size_t size)
241749f21d3Swesolows {
242749f21d3Swesolows 	free(data);
243749f21d3Swesolows }
244749f21d3Swesolows 
245749f21d3Swesolows int
fmd_fmri_error(int err)246749f21d3Swesolows fmd_fmri_error(int err)
247749f21d3Swesolows {
248749f21d3Swesolows 	errno = err;
249749f21d3Swesolows 	return (-1);
250749f21d3Swesolows }
251749f21d3Swesolows 
252749f21d3Swesolows char *
fmd_fmri_strescape(const char * s)253749f21d3Swesolows fmd_fmri_strescape(const char *s)
254749f21d3Swesolows {
255749f21d3Swesolows 	return (strdup(s));
256749f21d3Swesolows }
257749f21d3Swesolows 
258749f21d3Swesolows char *
fmd_fmri_strdup(const char * s)259749f21d3Swesolows fmd_fmri_strdup(const char *s)
260749f21d3Swesolows {
261749f21d3Swesolows 	return (strdup(s));
262749f21d3Swesolows }
263749f21d3Swesolows 
264749f21d3Swesolows void
fmd_fmri_strfree(char * s)265749f21d3Swesolows fmd_fmri_strfree(char *s)
266749f21d3Swesolows {
267749f21d3Swesolows 	free(s);
268749f21d3Swesolows }
269749f21d3Swesolows 
270749f21d3Swesolows const char *
fmd_fmri_get_rootdir(void)271749f21d3Swesolows fmd_fmri_get_rootdir(void)
272749f21d3Swesolows {
273749f21d3Swesolows 	return (g_root ? g_root : "");
274749f21d3Swesolows }
275749f21d3Swesolows 
276749f21d3Swesolows const char *
fmd_fmri_get_platform(void)277749f21d3Swesolows fmd_fmri_get_platform(void)
278749f21d3Swesolows {
279749f21d3Swesolows 	static char platform[MAXNAMELEN];
280749f21d3Swesolows 
281749f21d3Swesolows 	if (platform[0] == '\0')
282749f21d3Swesolows 		(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
283749f21d3Swesolows 
284749f21d3Swesolows 	return (platform);
285749f21d3Swesolows }
286749f21d3Swesolows 
287749f21d3Swesolows uint64_t
fmd_fmri_get_drgen(void)288749f21d3Swesolows fmd_fmri_get_drgen(void)
289749f21d3Swesolows {
290749f21d3Swesolows 	return (0);
291749f21d3Swesolows }
292749f21d3Swesolows 
293749f21d3Swesolows int
fmd_fmri_set_errno(int err)294749f21d3Swesolows fmd_fmri_set_errno(int err)
295749f21d3Swesolows {
296749f21d3Swesolows 	errno = err;
297749f21d3Swesolows 	return (-1);
298749f21d3Swesolows }
299749f21d3Swesolows 
30030698f33Swesolows /*ARGSUSED*/
301749f21d3Swesolows void
fmd_fmri_warn(const char * format,...)302749f21d3Swesolows fmd_fmri_warn(const char *format, ...)
303749f21d3Swesolows {
304749f21d3Swesolows }
3051fe76c0bSwesolows 
3061fe76c0bSwesolows struct topo_hdl *
fmd_fmri_topo_hold(int version)30724db4641Seschrock fmd_fmri_topo_hold(int version)
3081fe76c0bSwesolows {
3091fe76c0bSwesolows 	int err;
3101fe76c0bSwesolows 
31124db4641Seschrock 	if (version != TOPO_VERSION)
31224db4641Seschrock 		return (NULL);
31324db4641Seschrock 
3141fe76c0bSwesolows 	if (g_thp == NULL) {
3151fe76c0bSwesolows 		if ((g_thp = topo_open(TOPO_VERSION, "/", &err)) == NULL) {
3161fe76c0bSwesolows 			DEBUGMSGTL((MODNAME_STR, "topo_open failed: %s\n",
3171fe76c0bSwesolows 			    topo_strerror(err)));
3181fe76c0bSwesolows 			return (NULL);
3191fe76c0bSwesolows 		}
3201fe76c0bSwesolows 	}
3211fe76c0bSwesolows 
3221fe76c0bSwesolows 	return (g_thp);
3231fe76c0bSwesolows }
32424db4641Seschrock 
32524db4641Seschrock /*ARGSUSED*/
32624db4641Seschrock void
fmd_fmri_topo_rele(struct topo_hdl * thp)32724db4641Seschrock fmd_fmri_topo_rele(struct topo_hdl *thp)
32824db4641Seschrock {
32924db4641Seschrock 	/* nothing to do */
33024db4641Seschrock }
331