xref: /onnv-gate/usr/src/lib/fm/libfmd_snmp/common/scheme.c (revision 1303:6e5751a0b831)
1*1303Swesolows /*
2*1303Swesolows  * CDDL HEADER START
3*1303Swesolows  *
4*1303Swesolows  * The contents of this file are subject to the terms of the
5*1303Swesolows  * Common Development and Distribution License (the "License").
6*1303Swesolows  * You may not use this file except in compliance with the License.
7*1303Swesolows  *
8*1303Swesolows  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1303Swesolows  * or http://www.opensolaris.org/os/licensing.
10*1303Swesolows  * See the License for the specific language governing permissions
11*1303Swesolows  * and limitations under the License.
12*1303Swesolows  *
13*1303Swesolows  * When distributing Covered Code, include this CDDL HEADER in each
14*1303Swesolows  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1303Swesolows  * If applicable, add the following below this CDDL HEADER, with the
16*1303Swesolows  * fields enclosed by brackets "[]" replaced with your own identifying
17*1303Swesolows  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1303Swesolows  *
19*1303Swesolows  * CDDL HEADER END
20*1303Swesolows  */
21*1303Swesolows 
22*1303Swesolows /*
23*1303Swesolows  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*1303Swesolows  * Use is subject to license terms.
25*1303Swesolows  */
26*1303Swesolows 
27*1303Swesolows #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*1303Swesolows 
29*1303Swesolows #include <sys/fm/protocol.h>
30*1303Swesolows #include <sys/types.h>
31*1303Swesolows #include <sys/systeminfo.h>
32*1303Swesolows #include <fm/fmd_snmp.h>
33*1303Swesolows #include <net-snmp/net-snmp-config.h>
34*1303Swesolows #include <net-snmp/net-snmp-includes.h>
35*1303Swesolows #include <net-snmp/agent/net-snmp-agent-includes.h>
36*1303Swesolows #include <libnvpair.h>
37*1303Swesolows #include <limits.h>
38*1303Swesolows #include <strings.h>
39*1303Swesolows #include <stddef.h>
40*1303Swesolows #include <unistd.h>
41*1303Swesolows #include <dlfcn.h>
42*1303Swesolows #include <errno.h>
43*1303Swesolows 
44*1303Swesolows #define	SCHEMEDIR_BASE	"/usr/lib/fm/fmd/schemes"
45*1303Swesolows 
46*1303Swesolows #if defined(__sparcv9)
47*1303Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE "/sparcv9"
48*1303Swesolows #elif defined(__amd64)
49*1303Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE "/amd64"
50*1303Swesolows #else
51*1303Swesolows #define	DEFAULTSCHEMEDIR	SCHEMEDIR_BASE
52*1303Swesolows #endif
53*1303Swesolows 
54*1303Swesolows typedef struct fmd_scheme_ops {
55*1303Swesolows 	int (*sop_init)(void);
56*1303Swesolows 	void (*sop_fini)(void);
57*1303Swesolows 	ssize_t (*sop_nvl2str)(nvlist_t *, char *, size_t);
58*1303Swesolows } fmd_scheme_ops_t;
59*1303Swesolows 
60*1303Swesolows typedef struct fmd_scheme_opd {
61*1303Swesolows 	const char *opd_name;		/* symbol name of scheme function */
62*1303Swesolows 	size_t opd_off;			/* offset within fmd_scheme_ops_t */
63*1303Swesolows } fmd_scheme_opd_t;
64*1303Swesolows 
65*1303Swesolows typedef struct fmd_scheme {
66*1303Swesolows 	struct fmd_scheme *sch_next;    /* next scheme on list of schemes */
67*1303Swesolows 	char *sch_name;			/* name of this scheme (fmri prefix) */
68*1303Swesolows 	void *sch_dlp;			/* libdl(3DL) shared library handle */
69*1303Swesolows 	int sch_err;			/* if negative entry, errno to return */
70*1303Swesolows 	fmd_scheme_ops_t sch_ops;	/* scheme function pointers */
71*1303Swesolows } fmd_scheme_t;
72*1303Swesolows 
73*1303Swesolows static fmd_scheme_t *sch_list;		/* list of cached schemes */
74*1303Swesolows static char *g_root;			/* fmd root dir */
75*1303Swesolows 
76*1303Swesolows static long
77*1303Swesolows fmd_scheme_notsup(void)
78*1303Swesolows {
79*1303Swesolows 	errno = ENOTSUP;
80*1303Swesolows 	return (-1);
81*1303Swesolows }
82*1303Swesolows 
83*1303Swesolows static int
84*1303Swesolows fmd_scheme_nop(void)
85*1303Swesolows {
86*1303Swesolows 	return (0);
87*1303Swesolows }
88*1303Swesolows 
89*1303Swesolows /*
90*1303Swesolows  * Default values for the scheme ops.  If a scheme function is not defined in
91*1303Swesolows  * the module, then this operation is implemented using the default function.
92*1303Swesolows  */
93*1303Swesolows static const fmd_scheme_ops_t _fmd_scheme_default_ops = {
94*1303Swesolows 	(int (*)())fmd_scheme_nop,		/* sop_init */
95*1303Swesolows 	(void (*)())fmd_scheme_nop,		/* sop_fini */
96*1303Swesolows 	(ssize_t (*)())fmd_scheme_notsup,	/* sop_nvl2str */
97*1303Swesolows };
98*1303Swesolows 
99*1303Swesolows /*
100*1303Swesolows  * Scheme ops descriptions.  These names and offsets are used by the function
101*1303Swesolows  * fmd_scheme_rtld_init(), defined below, to load up a fmd_scheme_ops_t.
102*1303Swesolows  */
103*1303Swesolows static const fmd_scheme_opd_t _fmd_scheme_ops[] = {
104*1303Swesolows 	{ "fmd_fmri_init", offsetof(fmd_scheme_ops_t, sop_init) },
105*1303Swesolows 	{ "fmd_fmri_fini", offsetof(fmd_scheme_ops_t, sop_fini) },
106*1303Swesolows 	{ "fmd_fmri_nvl2str", offsetof(fmd_scheme_ops_t, sop_nvl2str) },
107*1303Swesolows 	{ NULL, 0 }
108*1303Swesolows };
109*1303Swesolows 
110*1303Swesolows static fmd_scheme_t *
111*1303Swesolows fmd_scheme_create(const char *name)
112*1303Swesolows {
113*1303Swesolows 	fmd_scheme_t *sp;
114*1303Swesolows 
115*1303Swesolows 	if ((sp = malloc(sizeof (fmd_scheme_t))) == NULL ||
116*1303Swesolows 	    (sp->sch_name = strdup(name)) == NULL) {
117*1303Swesolows 		free(sp);
118*1303Swesolows 		return (NULL);
119*1303Swesolows 	}
120*1303Swesolows 
121*1303Swesolows 	sp->sch_next = sch_list;
122*1303Swesolows 	sp->sch_dlp = NULL;
123*1303Swesolows 	sp->sch_err = 0;
124*1303Swesolows 	sp->sch_ops = _fmd_scheme_default_ops;
125*1303Swesolows 
126*1303Swesolows 	sch_list = sp;
127*1303Swesolows 	return (sp);
128*1303Swesolows }
129*1303Swesolows 
130*1303Swesolows static int
131*1303Swesolows fmd_scheme_rtld_init(fmd_scheme_t *sp)
132*1303Swesolows {
133*1303Swesolows 	const fmd_scheme_opd_t *opd;
134*1303Swesolows 	void *p;
135*1303Swesolows 
136*1303Swesolows 	for (opd = _fmd_scheme_ops; opd->opd_name != NULL; opd++) {
137*1303Swesolows 		if ((p = dlsym(sp->sch_dlp, opd->opd_name)) != NULL)
138*1303Swesolows 			*(void **)((uintptr_t)&sp->sch_ops + opd->opd_off) = p;
139*1303Swesolows 	}
140*1303Swesolows 
141*1303Swesolows 	return (sp->sch_ops.sop_init());
142*1303Swesolows }
143*1303Swesolows 
144*1303Swesolows static fmd_scheme_t *
145*1303Swesolows fmd_scheme_lookup(const char *dir, const char *name)
146*1303Swesolows {
147*1303Swesolows 	fmd_scheme_t *sp;
148*1303Swesolows 	char path[PATH_MAX];
149*1303Swesolows 
150*1303Swesolows 	for (sp = sch_list; sp != NULL; sp = sp->sch_next) {
151*1303Swesolows 		if (strcmp(name, sp->sch_name) == 0)
152*1303Swesolows 			return (sp);
153*1303Swesolows 	}
154*1303Swesolows 
155*1303Swesolows 	if ((sp = fmd_scheme_create(name)) == NULL)
156*1303Swesolows 		return (NULL); /* errno is set for us */
157*1303Swesolows 
158*1303Swesolows 	(void) snprintf(path, sizeof (path), "%s%s/%s.so",
159*1303Swesolows 	    g_root ? g_root : "", dir, name);
160*1303Swesolows 
161*1303Swesolows 	if (access(path, F_OK) != 0) {
162*1303Swesolows 		sp->sch_err = errno;
163*1303Swesolows 		return (sp);
164*1303Swesolows 	}
165*1303Swesolows 
166*1303Swesolows 	if ((sp->sch_dlp = dlopen(path, RTLD_LOCAL | RTLD_NOW | RTLD_PARENT)) ==
167*1303Swesolows 	    NULL) {
168*1303Swesolows 		sp->sch_err = ELIBACC;
169*1303Swesolows 		return (sp);
170*1303Swesolows 	}
171*1303Swesolows 
172*1303Swesolows 	if (fmd_scheme_rtld_init(sp) != 0) {
173*1303Swesolows 		sp->sch_err = errno;
174*1303Swesolows 		(void) dlclose(sp->sch_dlp);
175*1303Swesolows 		sp->sch_dlp = NULL;
176*1303Swesolows 	}
177*1303Swesolows 
178*1303Swesolows 	return (sp);
179*1303Swesolows }
180*1303Swesolows 
181*1303Swesolows char *
182*1303Swesolows sunFm_nvl2str(nvlist_t *nvl)
183*1303Swesolows {
184*1303Swesolows 	fmd_scheme_t *sp;
185*1303Swesolows 	char c, *name, *s = NULL;
186*1303Swesolows 	ssize_t len;
187*1303Swesolows 
188*1303Swesolows 	if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) {
189*1303Swesolows 		DEBUGMSGTL((MODNAME_STR, "fmri does not contain required "
190*1303Swesolows 		    "'%s' nvpair\n", FM_FMRI_SCHEME));
191*1303Swesolows 		return (NULL);
192*1303Swesolows 	}
193*1303Swesolows 
194*1303Swesolows 	if ((sp = fmd_scheme_lookup(DEFAULTSCHEMEDIR, name)) == NULL ||
195*1303Swesolows 	    sp->sch_dlp == NULL || sp->sch_err != 0) {
196*1303Swesolows 		const char *msg =
197*1303Swesolows 		    sp->sch_err == ELIBACC ? dlerror() : strerror(sp->sch_err);
198*1303Swesolows 		DEBUGMSGTL((MODNAME_STR, "cannot init '%s' scheme library to "
199*1303Swesolows 		    "format fmri: %s\n", name, msg ? msg : "unknown error"));
200*1303Swesolows 		return (NULL);
201*1303Swesolows 	}
202*1303Swesolows 
203*1303Swesolows 	if ((len = sp->sch_ops.sop_nvl2str(nvl, &c, sizeof (c))) == -1 ||
204*1303Swesolows 	    (s = malloc(len + 1)) == NULL ||
205*1303Swesolows 	    sp->sch_ops.sop_nvl2str(nvl, s, len + 1) == -1) {
206*1303Swesolows 		DEBUGMSGTL((MODNAME_STR, "cannot format fmri using scheme '%s'",
207*1303Swesolows 		    name));
208*1303Swesolows 		free(s);
209*1303Swesolows 		return (NULL);
210*1303Swesolows 	}
211*1303Swesolows 
212*1303Swesolows 	return (s);
213*1303Swesolows }
214*1303Swesolows 
215*1303Swesolows void *
216*1303Swesolows fmd_fmri_alloc(size_t size)
217*1303Swesolows {
218*1303Swesolows 	return (malloc(size));
219*1303Swesolows }
220*1303Swesolows 
221*1303Swesolows void *
222*1303Swesolows fmd_fmri_zalloc(size_t size)
223*1303Swesolows {
224*1303Swesolows 	void *data;
225*1303Swesolows 
226*1303Swesolows 	if ((data = malloc(size)) != NULL)
227*1303Swesolows 		bzero(data, size);
228*1303Swesolows 
229*1303Swesolows 	return (data);
230*1303Swesolows }
231*1303Swesolows 
232*1303Swesolows /*ARGSUSED*/
233*1303Swesolows void
234*1303Swesolows fmd_fmri_free(void *data, size_t size)
235*1303Swesolows {
236*1303Swesolows 	free(data);
237*1303Swesolows }
238*1303Swesolows 
239*1303Swesolows int
240*1303Swesolows fmd_fmri_error(int err)
241*1303Swesolows {
242*1303Swesolows 	errno = err;
243*1303Swesolows 	return (-1);
244*1303Swesolows }
245*1303Swesolows 
246*1303Swesolows char *
247*1303Swesolows fmd_fmri_strescape(const char *s)
248*1303Swesolows {
249*1303Swesolows 	return (strdup(s));
250*1303Swesolows }
251*1303Swesolows 
252*1303Swesolows char *
253*1303Swesolows fmd_fmri_strdup(const char *s)
254*1303Swesolows {
255*1303Swesolows 	return (strdup(s));
256*1303Swesolows }
257*1303Swesolows 
258*1303Swesolows void
259*1303Swesolows fmd_fmri_strfree(char *s)
260*1303Swesolows {
261*1303Swesolows 	free(s);
262*1303Swesolows }
263*1303Swesolows 
264*1303Swesolows const char *
265*1303Swesolows fmd_fmri_get_rootdir(void)
266*1303Swesolows {
267*1303Swesolows 	return (g_root ? g_root : "");
268*1303Swesolows }
269*1303Swesolows 
270*1303Swesolows const char *
271*1303Swesolows fmd_fmri_get_platform(void)
272*1303Swesolows {
273*1303Swesolows 	static char platform[MAXNAMELEN];
274*1303Swesolows 
275*1303Swesolows 	if (platform[0] == '\0')
276*1303Swesolows 		(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
277*1303Swesolows 
278*1303Swesolows 	return (platform);
279*1303Swesolows }
280*1303Swesolows 
281*1303Swesolows uint64_t
282*1303Swesolows fmd_fmri_get_drgen(void)
283*1303Swesolows {
284*1303Swesolows 	return (0);
285*1303Swesolows }
286*1303Swesolows 
287*1303Swesolows int
288*1303Swesolows fmd_fmri_set_errno(int err)
289*1303Swesolows {
290*1303Swesolows 	errno = err;
291*1303Swesolows 	return (-1);
292*1303Swesolows }
293*1303Swesolows 
294*1303Swesolows void
295*1303Swesolows fmd_fmri_warn(const char *format, ...)
296*1303Swesolows {
297*1303Swesolows }
298